zaptel-1.4.11/0002755000000000000000000000000011017303255011572 5ustar rootrootzaptel-1.4.11/Makefile0000644000000000000000000004437111012353570013241 0ustar rootroot# # Makefile for Zaptel driver modules and utilities # # Copyright (C) 2001-2007 Digium, Inc. # # ifneq ($(KBUILD_EXTMOD),) # We only get in here if we're from kernel 2.6 <= 2.6.9 and going through # Kbuild. Later versions will include Kbuild instead of Makefile. include $(src)/Kbuild else CFLAGS+=-DSTANDALONE_ZAPATA -DBUILDING_TONEZONE ifeq ($(MAKELEVEL),0) PWD:=$(shell pwd) endif ifeq ($(ARCH),) ARCH:=$(shell uname -m | sed -e s/i.86/i386/) endif ifeq ($(DEB_HOST_GNU_TYPE),) UNAME_M:=$(shell uname -m) else UNAME_M:=$(DEB_HOST_GNU_TYPE) endif # If you want to build for a kernel other than the current kernel, set KVERS ifndef KVERS KVERS:=$(shell uname -r) endif ifndef KSRC ifneq (,$(wildcard /lib/modules/$(KVERS)/build)) KSRC:=/lib/modules/$(KVERS)/build else KSRC_SEARCH_PATH:=/usr/src/linux-2.4 /usr/src/linux KSRC:=$(shell for dir in $(KSRC_SEARCH_PATH); do if [ -d $$dir ]; then echo $$dir; break; fi; done) endif endif KVERS_MAJ:=$(shell echo $(KVERS) | cut -d. -f1-2) KINCLUDES:=$(KSRC)/include # We use the kernel's .config file as an indication that the KSRC # directory is indeed a valid and configured kernel source (or partial # source) directory. # # We also source it, as it has the format of Makefile variables list. # Thus we will have many CONFIG_* variables from there. KCONFIG:=$(KSRC)/.config ifneq (,$(wildcard $(KCONFIG))) HAS_KSRC=yes include $(KCONFIG) else HAS_KSRC=no endif ifeq ($(KVERS_MAJ),2.4) BUILDVER:=linux24 else BUILDVER:=linux26 endif # Set HOTPLUG_FIRMWARE=no to override automatic building with hotplug support # if it is enabled in the kernel. ifeq ($(BUILDVER),linux26) ifneq (,$(wildcard $(DESTDIR)/etc/udev/rules.d)) DYNFS=yes UDEVRULES=yes endif ifeq (yes,$(HAS_KSRC)) HOTPLUG_FIRMWARE:=$(shell if grep -q '^CONFIG_FW_LOADER=[ym]' $(KCONFIG); then echo "yes"; else echo "no"; fi) endif endif ifneq (,$(findstring $(CONFIG_DEVFS_FS),y m)) DYNFS=yes HAS_DEVFS=yes endif # If the file .zaptel.makeopts is present in your home directory, you can # include all of your favorite menuselect options so that every time you download # a new version of Asterisk, you don't have to run menuselect to set them. # The file /etc/zaptel.makeopts will also be included but can be overridden # by the file in your home directory. GLOBAL_MAKEOPTS=$(wildcard /etc/zaptel.makeopts) USER_MAKEOPTS=$(wildcard ~/.zaptel.makeopts) ifeq ($(strip $(foreach var,clean distclean dist-clean update,$(findstring $(var),$(MAKECMDGOALS)))),) ifneq ($(wildcard menuselect.makeopts),) include menuselect.makeopts endif endif ifeq ($(strip $(foreach var,clean distclean dist-clean update,$(findstring $(var),$(MAKECMDGOALS)))),) ifneq ($(wildcard makeopts),) include makeopts endif endif ifeq ($(BUILDVER),linux24) MENUSELECT_MODULES+=xpp wctc4xxp wctdm24xxp zttranscode endif ifeq ($(findstring xpp,$(MENUSELECT_MODULES)),) BUILD_XPP:=yes endif SUBDIRS_UTILS_ALL:= kernel/xpp/utils ppp SUBDIRS_UTILS := ifeq ($(BUILD_XPP),yes) SUBDIRS_UTILS += kernel/xpp/utils endif #SUBDIRS_UTILS += ppp TOPDIR_MODULES:=pciradio tor2 torisa wcfxo wct1xxp wctdm wcte11xp wcusb zaptel ztd-eth ztd-loc ztdummy ztdynamic zttranscode SUBDIR_MODULES:=wct4xxp wctc4xxp xpp wctdm24xxp wcte12xp TOPDIR_MODULES+=$(MODULES_EXTRA) SUBDIR_MODULES+=$(SUBDIRS_EXTRA) BUILD_TOPDIR_MODULES:=$(filter-out $(MENUSELECT_MODULES),$(TOPDIR_MODULES)) BUILD_SUBDIR_MODULES:=$(filter-out $(MENUSELECT_MODULES),$(SUBDIR_MODULES)) BUILD_MODULES:=$(BUILD_TOPDIR_MODULES) $(BUILD_SUBDIR_MODULES) MOD_DESTDIR:=zaptel KERN_DIR:=kernel #NOTE NOTE NOTE # # all variables set before the include of Makefile.kernel26 are needed by the 2.6 kernel module build process ifneq ($(KBUILD_EXTMOD),) obj-m:=$(BUILD_TOPDIR_MODULES:%=%.o) obj-m+=$(BUILD_SUBDIR_MODULES:%=%/) include $(src)/Makefile.kernel26 else KBUILD_OBJ_M=$(BUILD_TOPDIR_MODULES:%=%.o) $(BUILD_SUBDIR_MODULES:%=%/) ifeq ($(BUILDVER),linux24) INSTALL_MODULES:=$(BUILD_TOPDIR_MODULES:%=$(KERN_DIR)/%.o) INSTALL_MODULES+=$(foreach mod,$(BUILD_SUBDIR_MODULES),$(KERN_DIR)/$(mod)/$(mod).o) ALL_MODULES:=$(TOPDIR_MODULES:%=$(KERN_DIR)/%.o) ALL_MODULES+=$(SUBDIR_MODULES:%=$(KERN_DIR)/%/%.o) else ALL_MODULES:=$(TOPDIR_MODULES:%=%.ko) ALL_MODULES+=$(foreach mod,$(filter-out xpp,$(SUBDIR_MODULES)),$(mod)/$(mod).ko) ALL_MODULES+=$(patsubst %,xpp/%.ko,xpp_usb xpd_fxo xpd_fxs xpp) endif OPTFLAG=-O2 CFLAGS+=-I. $(OPTFLAGS) -g -fPIC -Wall -DBUILDING_TONEZONE #-DTONEZONE_DRIVER ifneq (,$(findstring ppc,$(UNAME_M))) CFLAGS_PPC:=-fsigned-char endif ifneq (,$(findstring x86_64,$(UNAME_M))) CFLAGS_x86_64:=-m64 endif CFLAGS+=$(CFLAGS_PPC) $(CFLAGS_x86_64) KFLAGS=-I$(KINCLUDES) -O6 KFLAGS+=-DMODULE -D__KERNEL__ -DEXPORT_SYMTAB -I$(KSRC)/drivers/net \ -Wall -I. -Wstrict-prototypes -fomit-frame-pointer -I$(KSRC)/drivers/net/wan -I$(KINCLUDES)/net ifneq (,$(wildcard $(KINCLUDES)/linux/modversions.h)) KFLAGS+=-DMODVERSIONS -include $(KINCLUDES)/linux/modversions.h endif ifneq (,$(findstring ppc,$(UNAME_M))) KFLAGS_PPC:=-msoft-float -fsigned-char endif KFLAGS+=$(KFLAGS_PPC) ifeq ($(KVERS_MAJ),2.4) ifneq (,$(findstring x86_64,$(UNAME_M))) KFLAGS+=-mcmodel=kernel endif endif # # Features are now configured in zconfig.h # MODULE_ALIASES=wcfxs wctdm8xxp wct2xxp KFLAGS+=-DSTANDALONE_ZAPATA CFLAGS+=-DSTANDALONE_ZAPATA ifeq ($(BUILDVER),linux24) KMAKE = $(MAKE) -C kernel HOTPLUG_FIRMWARE=no \ HOSTCC=$(HOSTCC) ARCH=$(ARCH) KSRC=$(KSRC) LD=$(LD) CC=$(CC) \ UNAME_M=$(UNAME_M) \ BUILD_TOPDIR_MODULES="$(BUILD_TOPDIR_MODULES)" BUILD_SUBDIR_MODULES="$(BUILD_SUBDIR_MODULES)" else KMAKE = $(MAKE) -C $(KSRC) ARCH=$(ARCH) SUBDIRS=$(PWD)/kernel \ HOTPLUG_FIRMWARE=$(HOTPLUG_FIRMWARE) KBUILD_OBJ_M="$(KBUILD_OBJ_M)" endif KMAKE_INST = $(KMAKE) \ INSTALL_MOD_PATH=$(DESTDIR) INSTALL_MOD_DIR=misc modules_install ROOT_PREFIX= CONFIG_FILE=/etc/zaptel.conf CFLAGS+=-DZAPTEL_CONFIG=\"$(CONFIG_FILE)\" # sample makefile "trace print" #tracedummy=$(shell echo ====== GOT HERE ===== >&2; echo >&2) CHKCONFIG := $(wildcard /sbin/chkconfig) UPDATE_RCD := $(wildcard /usr/sbin/update-rc.d) ifeq (,$(DESTDIR)) ifneq (,$(CHKCONFIG)) ADD_INITD := $(CHKCONFIG) --add zaptel else ifndef (,$(UPDATE_RCD)) ADD_INITD := $(UPDATE_RCD) zaptel defaults 15 30 endif endif endif INITRD_DIR := $(firstword $(wildcard /etc/rc.d/init.d /etc/init.d)) ifneq (,$(INITRD_DIR)) INIT_TARGET := $(DESTDIR)$(INITRD_DIR)/zaptel COPY_INITD := install -D zaptel.init $(INIT_TARGET) endif RCCONF_DIR := $(firstword $(wildcard /etc/sysconfig /etc/default)) NETSCR_DIR := $(firstword $(wildcard /etc/sysconfig/network-scripts )) ifneq (,$(NETSCR_DIR)) NETSCR_TARGET := $(DESTDIR)$(NETSCR_DIR)/ifup-hdlc COPY_NETSCR := install -D ifup-hdlc $(NETSCR_TARGET) endif ifneq ($(wildcard .version),) ZAPTELVERSION:=$(shell cat .version) else ifneq ($(wildcard .svn),) ZAPTELVERSION=SVN-$(shell build_tools/make_svn_branch_name) endif endif LTZ_A:=libtonezone.a LTZ_A_OBJS:=zonedata.o tonezone.o LTZ_SO:=libtonezone.so LTZ_SO_OBJS:=zonedata.lo tonezone.lo LTZ_SO_MAJOR_VER:=1 LTZ_SO_MINOR_VER:=0 # libdir, includedir and mandir are defined in makeopts (from # configure). # we use /sbin, rather than configure's $(sbindir) because we use /sbin # for historical reasons. BIN_DIR:=/sbin LIB_DIR:=$(libdir) INC_DIR:=$(includedir)/zaptel MAN_DIR:=$(mandir)/man8 MOD_DIR:=$(DESTDIR)/lib/modules/$(KVERS)/misc # Utilities we build with a standard build procedure: UTILS = zttool zttest ztmonitor ztspeed sethdlc-new ztcfg \ ztcfg-dude usbfxstest fxstest fxotune ztdiag torisatool \ ztscan # Makefile mentions them. Source is not included (anynore?) UTILS += fxsdump ztprovision # some tests: UTILS += patgen pattest patlooptest hdlcstress hdlctest hdlcgen \ hdlcverify timertest UTILSO = $(UTILS:%=%.o) BINS:=fxotune fxstest sethdlc-new ztcfg ztdiag ztmonitor ztspeed zttest ztscan ifeq (1,$(PBX_LIBNEWT)) BINS+=zttool endif BINS:=$(filter-out $(MENUSELECT_UTILS),$(BINS)) MAN_PAGES:=$(wildcard $(BINS:%=doc/%.8)) # All the man pages. Not just installed ones: GROFF_PAGES := $(wildcard doc/*.8 kernel/xpp/utils/*.8) GROFF_HTML := $(GROFF_PAGES:%=%.html) all: menuselect.makeopts @$(MAKE) _all _all: $(if $(BUILD_MODULES),modules) programs libs: $(LTZ_SO) $(LTZ_A) utils-subdirs: @for dir in $(SUBDIRS_UTILS); do \ $(MAKE) -C $$dir; \ done programs: libs utils utils: $(BINS) utils-subdirs modules: prereq ifeq (no,$(HAS_KSRC)) echo "You do not appear to have the sources for the $(KVERS) kernel installed." exit 1 endif $(KMAKE) modules version.h: @ZAPTELVERSION="${ZAPTELVERSION}" build_tools/make_version_h > $@.tmp @if cmp -s $@.tmp $@ ; then :; else \ mv $@.tmp $@ ; \ fi @rm -f $@.tmp tests: patgen pattest patlooptest hdlcstress hdlctest hdlcgen hdlcverify timertest zonedata.o: tonezone.h zonedata.lo: zonedata.c tonezone.h $(CC) -c $(CFLAGS) -o $@ $< tonezone.o: kernel/zaptel.h tonezone.h tonezone.lo: tonezone.c tonezone.h kernel/zaptel.h $(CC) -c $(CFLAGS) -o $@ $< prereq: config.status version.h zttool.o: kernel/zaptel.h zttool.o: CFLAGS+=$(NEWT_INCLUDE) zttool: LDLIBS+=$(NEWT_LIB) ztscan.o: kernel/zaptel.h ztprovision.o: kernel/zaptel.h ztmonitor.o: kernel/zaptel.h ztspeed: CFLAGS= sethdlc-new: CFLAGS+=-I$(KINCLUDES) $(LTZ_A): $(LTZ_A_OBJS) ar rcs $@ $^ ranlib $@ $(LTZ_SO): $(LTZ_SO_OBJS) $(CC) $(CFLAGS) -shared -Wl,-soname,$(LTZ_SO).$(LTZ_SO_MAJOR_VER).$(LTZ_SO_MINOR_VER) -o $@ $^ $(LDFLAGS) $(LDLIBS) -lm ztcfg.o: ztcfg.h kernel/zaptel.h ztcfg: ztcfg.o $(LTZ_A) ztcfg: LDLIBS+=-lm ztcfg-shared: ztcfg.o $(LTZ_SO) $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LDLIBS) -lm ztcfg-dude: ztcfg-dude.o mknotch.o complex.o $(LTZ_SO) ztcfg-dude: LDLIBS+=-lm -lstdc++ data: $(MAKE) -C datamods datamods # FIXME: we assume CC can build the C++ modules: complex.o mknotch.o: %.o: %.cc $(CC) $(CFLAGS) -o $@ -c $< usbfxstest: LDLIBS+=-lzap fxstest: $(LTZ_SO) fxstest: LDLIBS+=-lm fxotune: LDLIBS+=-lm fxsdump: LDLIBS+=-lm stackcheck: checkstack modules ./checkstack kernel/*.ko kernel/*/*.ko tonezones.txt: zonedata.c perl -ne 'next unless (/\.(country|description) = *"([^"]*)/); \ print (($$1 eq "country")? "* $$2\t":"$$2\n");' $< \ >$@ zaptel.conf.asciidoc: zaptel.conf.sample perl -n -e \ 'if (/^#($$|\s)(.*)/){ if (!$$in_doc){print "\n"}; $$in_doc=1; print "$$2\n" } else { if ($$in_doc){print "\n"}; $$in_doc=0; print " $$_" }' \ $< >$@ README.html: README zaptel.conf.asciidoc tonezones.txt $(ASCIIDOC) -n -a toc -a toclevels=3 $< kernel/xpp/README.Astribank.html: kernel/xpp/README.Astribank cd $(@D); $(ASCIIDOC) -o $(@F) -n -a toc -a toclevels=4 $($@ htmlman: $(GROFF_HTML) MISDNVERSION=1_1_7_2 MISDNUSERVERSION=1_1_7_2 b410p: @if test "$(DOWNLOAD)" = ":" ; then \ echo "**************************************************"; \ echo "*** ***"; \ echo "*** You must have either wget or fetch to be ***"; \ echo "*** able to automatically download and install ***"; \ echo "*** b410p support. ***"; \ echo "*** ***"; \ echo "*** Please install one of these. ***"; \ echo "*** ***"; \ echo "**************************************************"; \ exit 1; \ fi [ -f mISDN-$(MISDNVERSION).tar.gz ] || $(DOWNLOAD) http://downloads.digium.com/pub/zaptel/b410p/mISDN-$(MISDNVERSION).tar.gz tar -zxf mISDN-$(MISDNVERSION).tar.gz $(MAKE) -C mISDN-$(MISDNVERSION) install [ -f mISDNuser-$(MISDNUSERVERSION).tar.gz ] || $(DOWNLOAD) http://downloads.digium.com/pub/zaptel/b410p/mISDNuser-$(MISDNUSERVERSION).tar.gz tar -zxf mISDNuser-$(MISDNUSERVERSION).tar.gz $(MAKE) -C mISDNuser-$(MISDNUSERVERSION) install $(UTILS): %: %.o $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LDLIBS) $(UTILSO): %.o: %.c $(CC) $(CFLAGS) -o $@ -c $< install: all devices install-modules install-programs install-firmware @echo "###################################################" @echo "###" @echo "### Zaptel installed successfully." @echo "### If you have not done so before, install init scripts with:" @echo "###" @echo "### make config" @echo "###" @echo "###################################################" install-programs: install-utils install-libs install-include install-utils: utils install-utils-subdirs ifneq (,$(BINS)) install -d $(DESTDIR)$(BIN_DIR) install $(BINS) $(DESTDIR)$(BIN_DIR)/ install -d $(DESTDIR)$(MAN_DIR) install -m 644 $(MAN_PAGES) $(DESTDIR)$(MAN_DIR)/ endif ifeq (,$(wildcard $(DESTDIR)$(CONFIG_FILE))) $(INSTALL) -D -m 644 zaptel.conf.sample $(DESTDIR)$(CONFIG_FILE) endif # Pushing those two to a separate target that is not used by default: install-modconf: build_tools/genmodconf $(BUILDVER) "$(ROOT_PREFIX)" "$(filter-out zaptel ztdummy xpp zttranscode ztdynamic,$(BUILD_MODULES)) $(MODULE_ALIASES)" @if [ -d /etc/modutils ]; then \ /sbin/update-modules ; \ fi install-firmware: ifeq ($(HOTPLUG_FIRMWARE),yes) $(MAKE) -C firmware hotplug-install DESTDIR=$(DESTDIR) HOTPLUG_FIRMWARE=$(HOTPLUG_FIRMWARE) endif install-libs: libs $(INSTALL) -D -m 755 $(LTZ_A) $(DESTDIR)$(LIB_DIR)/$(LTZ_A) $(INSTALL) -D -m 755 $(LTZ_SO) $(DESTDIR)$(LIB_DIR)/$(LTZ_SO).$(LTZ_SO_MAJOR_VER).$(LTZ_SO_MINOR_VER) ifeq (,$(DESTDIR)) if [ `id -u` = 0 ]; then \ /sbin/ldconfig || : ;\ fi endif rm -f $(DESTDIR)$(LIB_DIR)$(LTZ_SO) $(LN) -sf $(LTZ_SO).$(LTZ_SO_MAJOR_VER).$(LTZ_SO_MINOR_VER) \ $(DESTDIR)$(LIB_DIR)/$(LTZ_SO).$(LTZ_SO_MAJOR_VER) $(LN) -sf $(LTZ_SO).$(LTZ_SO_MAJOR_VER).$(LTZ_SO_MINOR_VER) \ $(DESTDIR)$(LIB_DIR)/$(LTZ_SO) ifneq (no,$(USE_SELINUX)) ifeq (,$(DESTDIR)) /sbin/restorecon -v $(DESTDIR)$(LIB_DIR)/$(LTZ_SO) endif endif $(INSTALL) -D -m 644 tonezone.h $(DESTDIR)$(INC_DIR)/tonezone.h install-utils-subdirs: @for dir in $(SUBDIRS_UTILS); do \ $(MAKE) -C $$dir install; \ done install-include: $(INSTALL) -D -m 644 kernel/zaptel.h $(DESTDIR)$(INC_DIR)/zaptel.h devices: ifneq (yes,$(DYNFS)) mkdir -p $(DESTDIR)/dev/zap rm -f $(DESTDIR)/dev/zap/ctl rm -f $(DESTDIR)/dev/zap/channel rm -f $(DESTDIR)/dev/zap/pseudo rm -f $(DESTDIR)/dev/zap/timer rm -f $(DESTDIR)/dev/zap/transcode rm -f $(DESTDIR)/dev/zap/253 rm -f $(DESTDIR)/dev/zap/252 rm -f $(DESTDIR)/dev/zap/251 rm -f $(DESTDIR)/dev/zap/250 mknod $(DESTDIR)/dev/zap/ctl c 196 0 mknod $(DESTDIR)/dev/zap/transcode c 196 250 mknod $(DESTDIR)/dev/zap/timer c 196 253 mknod $(DESTDIR)/dev/zap/channel c 196 254 mknod $(DESTDIR)/dev/zap/pseudo c 196 255 N=1; \ while [ $$N -lt 250 ]; do \ rm -f $(DESTDIR)/dev/zap/$$N; \ mknod $(DESTDIR)/dev/zap/$$N c 196 $$N; \ N=$$[$$N+1]; \ done else # DYNFS ifneq (yes,$(UDEVRULES)) #!UDEVRULES @echo "**** Dynamic filesystem detected -- not creating device nodes" else # UDEVRULES install -d $(DESTDIR)/etc/udev/rules.d build_tools/genudevrules > $(DESTDIR)/etc/udev/rules.d/zaptel.rules endif endif install-udev: devices uninstall-hotplug: $(MAKE) -C firmware hotplug-uninstall DESTDIR=$(DESTDIR) uninstall-modules: ifneq ($(BUILDVER),linux24) @./build_tools/uninstall-modules $(DESTDIR)/lib/modules/$(KVERS) $(ALL_MODULES) endif ifeq ($(BUILDVER),linux24) install-modules: $(INSTALL_MODULES) uninstall-modules $(INSTALL) -d $(DESTDIR)$(MOD_DIR) $(INSTALL) -m 644 $(INSTALL_MODULES) $(DESTDIR)$(MOD_DIR) else install-modules: uninstall-modules $(KMAKE_INST) endif [ `id -u` = 0 ] && /sbin/depmod -a $(KVERS) || : config: ifneq (,$(COPY_INITD)) $(COPY_INITD) endif ifneq (,$(RCCONF_DIR)) ifeq (,$(wildcard $(DESTDIR)$(RCCONF_DIR)/zaptel)) $(INSTALL) -D -m 644 zaptel.sysconfig $(DESTDIR)$(RCCONF_DIR)/zaptel endif endif ifneq (,$(COPY_NETSCR)) $(COPY_NETSCR) endif ifneq (,$(ADD_INITD)) $(ADD_INITD) endif @echo "Zaptel has been configured." @echo "" @echo "If you have any zaptel hardware it is now recommended to " @echo "edit /etc/default/zaptel or /etc/sysconfig/zaptel and set there an " @echo "optimal value for the variable MODULES ." @echo "" @echo "I think that the zaptel hardware you have on your system is:" @kernel/xpp/utils/zaptel_hardware || true update: @if [ -d .svn ]; then \ echo "Updating from Subversion..." ; \ svn update | tee update.out; \ rm -f .version; \ if [ `grep -c ^C update.out` -gt 0 ]; then \ echo ; echo "The following files have conflicts:" ; \ grep ^C update.out | cut -b4- ; \ fi ; \ rm -f update.out; \ else \ echo "Not under version control"; \ fi clean: -@$(MAKE) -C menuselect clean rm -f torisatool rm -f $(BINS) rm -f *.o ztcfg tzdriver sethdlc sethdlc-new rm -f $(LTZ_SO) $(LTZ_A) *.lo ifeq (yes,$(HAS_KSRC)) $(KMAKE) clean else rm -f kernel/*.o kernel/*.ko kernel/*/*.o kernel/*/*.ko endif @for dir in $(SUBDIRS_UTILS_ALL); do \ $(MAKE) -C $$dir clean; \ done $(MAKE) -C firmware clean rm -rf .tmp_versions rm -f gendigits tones.h rm -f libtonezone* rm -f fxotune rm -f core rm -f ztcfg-shared fxstest rm -rf misdn* rm -rf mISDNuser* rm -rf $(GROFF_HTML) rm -rf README.html xpp/README.Astribank.html zaptel.conf.asciidoc distclean: dist-clean dist-clean: clean @$(MAKE) -C menuselect dist-clean @$(MAKE) -C firmware dist-clean rm -f makeopts menuselect.makeopts menuselect-tree rm -f config.log config.status config.status: configure @CFLAGS="" ./configure @echo "****" @echo "**** The configure script was just executed, so 'make' needs to be" @echo "**** restarted." @echo "****" @exit 1 menuselect.makeopts: menuselect/menuselect menuselect-tree @menuselect/menuselect --check-deps ${GLOBAL_MAKEOPTS} ${USER_MAKEOPTS} $@ menuconfig: menuselect menuselect: menuselect/menuselect menuselect-tree -@menuselect/menuselect $(GLOBAL_MAKEOPTS) $(USER_MAKEOPTS) menuselect.makeopts && echo "menuselect changes saved!" || echo "menuselect changes NOT saved!" menuselect/menuselect: menuselect/menuselect.c menuselect/menuselect_curses.c menuselect/menuselect_stub.c menuselect/menuselect.h menuselect/linkedlists.h config.status @CFLAGS="" $(MAKE) -C menuselect CC=$(HOSTCC) menuselect-tree: zaptel.xml firmware/firmware.xml @echo "Generating input for menuselect ..." @build_tools/make_tree > $@ .PHONY: menuselect distclean dist-clean clean version.h all _all install b410p devices programs modules tests devel data stackcheck install-udev config update install-programs install-modules install-include install-libs install-utils-subdirs utils-subdirs uninstall-modules endif #end of: ifneq ($(KBUILD_EXTMOD),) endif zaptel-1.4.11/README.Astribank0000644000000000000000000000020410402112617014356 0ustar rootrootSee the README.Astribank that resides in the xpp/ directory for more information regarding the Xorcom Astribank. eripheral Device). zaptel-1.4.11/torisatool.c0000644000000000000000000000360110751714440014141 0ustar rootroot/* * BSD Telephony Of Mexico "Tormenta" card LINUX driver, version 1.8 4/8/01 * * Working with the "Tormenta ISA" Card * * 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. * * Modified from original tor.c by Mark Spencer * original by Jim Dixon */ #include #include #include #include #include #include #include #include "kernel/zaptel.h" static void usage(void) { fprintf(stderr, "Usage: torisatool showerrors\n"); exit(1); } int main(int argc, char *argv[]) { int fd; struct torisa_debug td; int res; if (argc < 3) usage(); fd = open(argv[1], O_RDWR); if (fd < 0) { fprintf(stderr, "Unable to open %s: %s\n", argv[1], strerror(errno)); exit(1); } if (!strcasecmp(argv[2], "showerrors")) { res = ioctl(fd, TORISA_GETDEBUG, &td); if (res) { fprintf(stderr, "IOCTL failed: %s\n", strerror(errno)); exit(1); } printf("Recorded misses: %u\n", td.txerrors); printf("IRQ execs: %u\n", td.irqcount); printf("Tasklet Schedules: %u\n", td.taskletsched); printf("Tasklets Run: %u\n", td.taskletrun); printf("Tasklets Executed: %u\n", td.taskletexec); } else usage(); exit(0); } zaptel-1.4.11/hdlcstress.c0000644000000000000000000001301410761556530014124 0ustar rootroot#include #include #include #include #include "kernel/zaptel.h" #include #include #include #include #include #include #include "bittest.h" #define FAST_HDLC_NEED_TABLES #include "kernel/fasthdlc.h" /* #define BLOCK_SIZE 2048 */ #define BLOCK_SIZE 2041 static int hdlcmode = 0; static unsigned short fcstab[256] = { 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 }; #define PPP_INITFCS 0xffff /* Initial FCS value */ #define PPP_GOODFCS 0xf0b8 /* Good final FCS value */ #define PPP_FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff]) void print_packet(unsigned char *buf, int len) { int x; printf("{ "); for (x=0;x 7) outbuf[pos++] = fasthdlc_tx_run(&fs); } fcs ^= 0xffff; if (fasthdlc_tx_load(&fs, (fcs & 0xff))) fprintf(stderr, "Load error (fcs1)\n"); outbuf[pos++] = fasthdlc_tx_run(&fs); if (fs.bits > 7) outbuf[pos++] = fasthdlc_tx_run(&fs); if (fasthdlc_tx_load(&fs, ((fcs >> 8) & 0xff))) fprintf(stderr, "Load error (fcs2)\n"); outbuf[pos++] = fasthdlc_tx_run(&fs); if (fs.bits > 7) outbuf[pos++] = fasthdlc_tx_run(&fs); if (fasthdlc_tx_frame(&fs)) fprintf(stderr, "Frame error\n"); if (fs.bits > 7) outbuf[pos++] = fasthdlc_tx_run(&fs); if (fs.bits > 7) outbuf[pos++] = fasthdlc_tx_run(&fs); write(fd, outbuf, pos); } } int main(int argc, char *argv[]) { int res, x; ZT_PARAMS tp; ZT_BUFFERINFO bi; int bs = BLOCK_SIZE; unsigned char c=0; unsigned char outbuf[BLOCK_SIZE]; if (argc < 2) { fprintf(stderr, "Usage: markhdlctest \n"); exit(1); } fd = open(argv[1], O_RDWR, 0600); if (fd < 0) { fprintf(stderr, "Unable to open %s: %s\n", argv[1], strerror(errno)); exit(1); } if (ioctl(fd, ZT_SET_BLOCKSIZE, &bs)) { fprintf(stderr, "Unable to set block size to %d: %s\n", bs, strerror(errno)); exit(1); } if (ioctl(fd, ZT_GET_PARAMS, &tp)) { fprintf(stderr, "Unable to get channel parameters\n"); exit(1); } if ((tp.sigtype & ZT_SIG_HDLCRAW) == ZT_SIG_HDLCRAW) { printf("In HDLC mode\n"); hdlcmode = 1; } else if ((tp.sigtype & ZT_SIG_CLEAR) == ZT_SIG_CLEAR) { printf("In CLEAR mode\n"); hdlcmode = 0; } else { fprintf(stderr, "Not in a reasonable mode\n"); exit(1); } res = ioctl(fd, ZT_GET_BUFINFO, &bi); if (!res) { bi.txbufpolicy = ZT_POLICY_IMMEDIATE; bi.rxbufpolicy = ZT_POLICY_IMMEDIATE; bi.numbufs = 4; res = ioctl(fd, ZT_SET_BUFINFO, &bi); if (res < 0) { fprintf(stderr, "Unable to set buf info: %s\n", strerror(errno)); exit(1); } } else { fprintf(stderr, "Unable to get buf info: %s\n", strerror(errno)); exit(1); } ioctl(fd, ZT_GETEVENT); fasthdlc_precalc(); fasthdlc_init(&fs); #if 0 print_packet(outbuf, res); printf("FCS is %x, PPP_GOODFCS is %x\n", fcs,PPP_GOODFCS); #endif for(;;) { if (c < 1) c = 1; for (x=0;x<50;x++) { outbuf[x] = c; } send_packet(outbuf, 50); #if 0 printf("Wrote %d of %d bytes\n", res, c); #endif c = bit_next(c); #if 0 printf("(%d) Wrote %d bytes\n", packets++, res); #endif } } zaptel-1.4.11/README0000644000000000000000000006273111012635356012466 0ustar rootrootZapata Telephony Interface Driver ================================= Asterisk Development Team $Revision: 4289 $, $Date: 2008-05-14 14:18:06 -0500 (Wed, 14 May 2008) $ Zaptel is a short for ZAPata TELephony. Supported Hardware ------------------ Digital Cards ~~~~~~~~~~~~~ - wct4xxp: * Digium TE205P/TE207P/TE210P/TE212P: PCI dual-port T1/E1/J1 * Digium TE405P/TE407P/TE410P/TE412P: PCI quad-port T1/E1/J1 * Digium TE220: PCI-Express dual-port T1/E1/J1 * Digium TE420: PCI-Express quad-port T1/E1/J1 - wcte12xp: * Digium TE120P: PCI single-port T1/E1/J1 * Digium TE121: PCI-Express single-port T1/E1/J1 * Digium TE122: PCI single-port T1/E1/J1 - wcte11xp: * Digium TE110P: PCI single-port T1/E1/J1 - wct1xxp: * Digium T100P: PCI single-port T1 * Digium E100P: PCI single-port E1 - tor2: Tormenta quad-span T1/E1 card from the Zapata Telephony project - torisa: The old dual-span ISA T1 card from Zapata Telephony Analog Cards ~~~~~~~~~~~~ - wctdm24xxp: * Digium TDM2400P/AEX2400: up to 24 analog ports * Digium TDM800P/AEX800: up to 8 analog ports * Digium TDM410: up to 4 analog ports - wctdm: * Digium TDM400P: up to 4 analog ports - xpp: Xorcom Astribank: a USB connected unit of up to 32 ports (includeing the digital BRI and E1/T1 modules) - wcfxo: X100P, similar and clones. A simple single-port FXO card - wcusb: Digium S100U: A simple single-port USB FXS unit Other Drivers ~~~~~~~~~~~~~ - pciradio: Zapata Telephony PCI Quad Radio Interface - wctc4xxp: Digium hardware transcoder cards (also need zttranscode) - ztd-eth: TDM over Ethernet (TDMoE) driver. Requires ztdynamic - ztd-loc: Mirror a local span. Requires ztdynamic - ztdummy: A dummy driver that only provides a zaptel timing source. Build Requirements ------------------ You will need a matching kernel source tree and a working Linux build system. Some of the programs require some additional libraries. The script install_prereq should help you install the required packages. To see what it suggests, run: ./install_prereq test You can either copy/paste that code to a terminal to run it, or just run: ./install_prereq install Kernel Source / "Headers" ~~~~~~~~~~~~~~~~~~~~~~~~~ - Building zaptel requires a kernel build tree. - This should basically be at least a partial kernel source tree and most importantly, the exact kernel .config file used for the build as well as several files generated at kernel build time. - KERNEL_VERSION is the output of the command `uname -r` - If you build your own kernel, you need to point to the exact kernel build tree. Luckily for you, this will typically be pointed by the symbolic link /lib/modules/KERNEL_VERSION/build which is the location zaptel checks by default. - If you use a kernel from your distribution you will typically have a package with all the files required to build a kernel modules for your kernel image. * On Debian Etch and above and any Ubuntu this is +++ linux-headers-`uname -r` +++ * On Fedora, RHEL and compatibles (e.g. CentOS) this is the kernel-devel package. Or if you run kernel-smp or kernel-xen, you need kernel-smp-devel or kernel-xen-devel, respectively. * On SUSE you seem to need the package kernel-source . * In some distributions (e.g.: in RHEL/CentOS, Fedora, Ubuntu) the installation of the kernel-devel / kernel-headers package will be of a version that is newer than the one you currently run. In such a case you may need to upgrade the kernel package itself as well and reboot. - To point explicitly to a different build tree: set KSRC to the kernel source tree and KVERS to the exact kernel version: make KVERS=2.6.18.Custom KSRC=/home/tzafrir/kernels/2.6.18 Kernel Configuration ~~~~~~~~~~~~~~~~~~~~ If you build a custom kernel, note the following configuration items: - CONFIG_CRC_CCITT must be enabled ('y' or 'm'). On 2.6 kernels this can be selected These can be selected from the "Library Routines" submenu during kernel configuration via "make menuconfig". - If you don't have any zaptel hardware, you need ztdummy. ztdummy takes its timing from the kernel. It can use either of the following: * ztdummy on i386/x86_64 with kernels >= 2.6.22 can (and should) use high resolution times (CONFIG_HIGH_RES_TIMERS), and (if available, the system HPET. This shows as "source: HRTimer". This is recommended. * ztdummy on i386/x86_64 and later kernels (>= 2.6.15) can use the system's RTC (Real Time Clock). This shows as "source: RTC". * Failing that, on Linux 2.6 kernels with HZ=1000 (was the default before 2.6.13). This shows as "source: Linux26". * Alternatives to that for ztdummy are a UHCI USB controller (USB controllers made by Intel or VIA) or a kernel that has HZ=1000 (default on kernels 2.6.0-2.6.12, optional on newer kernels. Not possible on 2.4). This shows as: "source: UHCI". A Build System ~~~~~~~~~~~~~~ gcc and friends. Generally you will need to install the package gcc. There may be cases where you will need a specific version of gcc to build kernel modules. Extra Libraries ~~~~~~~~~~~~~~~ Some libraries are needed for extra utilities that are provided with Zaptel - libusb is needed for building fpga_load, needed for firmware loading of the Xorcom Astribank. - libnewt is needed to build the optional but useful utility zttool. Distribution-Specific Instructions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ==== Debian 4.0 (Etch) apt-get install linux-headers-`uname -r` build-essential libnewt-dev libusb-dev ==== Debian 3.1 (Sarge) apt-get install kernel-headers-`uname -r` build-essential libnewt-dev libusb-dev ==== RHEL4 / CentOS 4 You need the following non-kernel-related packages: yum install gcc newt-devel libusb-devel If the following command produces an error, you need to install the kernel devel package: ls /lib/modules/`uname -r`/build/.config The right one depends on your kernel version. If the following command produces output you have an SMP kernel: uname -r | grep smp and thus need to run: yum install kernel-smp kernel-smp-devel If that command produced no output, you have a non-SMP kernel: yum install kernel kernel-devel At this point you should probably reboot to get the new kernel in effect. Installation ------------ Note: If using `sudo` to build/install, you may need to add /sbin to your PATH. ---------------------------------- ./configure # optional step: select custom configuration: #make menuconfig make make install # To install init scripts and config files: #make config ---------------------------------- Build Tweaks ~~~~~~~~~~~~ Selecting Modules and Utilities ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ You can select the modules and utilities you wish to build and firmwares you wish to download by running `make menuselect` . The selection of modules that you build (or rather: not build) is saved in the file `menuselect.makeopts`. Extra Modules ^^^^^^^^^^^^^ To build extra modules / modules directory not included in the Zaptel distribution, use the optional variables MODULES_EXTRA and SUBDIRS_EXTRA: make MODULES_EXTRA="mod1 mod2" make MODULES_EXTRA="mod1 mod2" SUBDIRS_EXTRA="subdir1/ subdir1/" Note that those names are not guaranteed to continue to work on newer versions. Hopefully there will be no need for such extra configuration. Partial Build/Install ^^^^^^^^^^^^^^^^^^^^^ There are some make targets that are provided to build or install just parts of Zaptel: . Build targets: - make modules: build just the kernel modules. - make programs: Build just the Zaptel userspace programs. partial targets of it: * make 'utilname': builds 'utilname' alone (e.g: `make ztdiag`) * make utils: Build libtonezone. * make libs: Build libtonezone. . Install targets: - make install-modules: install just kernel modules. - make firmware: download and install firmwares for Digium cards - make install-programs: Userspace: Partial targets of it are: * make install-utils: install Zaptel userspace programs and and basic support files. * make install-libs: install libtonezone * make install-include: install zaptel.h - make config: should be run once to configure Building to a Subtree ^^^^^^^^^^^^^^^^^^^^^ The following may be useful when testing the package or when preparing a package for a binary distribution (such as an rpm package) installing onto a subtree rather than on th real system. make install DESTDIR=targetdir This can be useful for any partial install target of the above (e.g: install-modules or install-programs). the targetdir must be an absolute path, at least if you install the modules. To install to a relative path you can use something like: make install-modules DESTDIR=$PWD/target The 'install' target might fail if run as a user to a DESTDIR when attempting to generate device files. In that case, try: make install DESTDIR=$PWD/target DYNFS= Test Install: live_zap ^^^^^^^^^^^^^^^^^^^^^^ If you need to test a version of Zaptel without touching the version installed on your system, you can use the script live_zap . Note, however, that it may take some extra configuration to be used right. Basic usage: ./configure make ./live_zap install # instead of 'make install' ./live_zap config # instead of 'make config' ./live_zap unload # instead of '/etc/init.d/zaptel stop' ./live_zap load # instead of '/etc/init.d/zaptel start' Everything is installed under the subdirectory live/ . You will probably need to adjust MODULES . Generally you should not edit the script itself, but , rather, edit live/live.conf . Please let me know if you needed to change anything in the script beyond changing live.conf so I can include useful fixes. Testing on a different maching: ./configure make ./live_zap install # instead of 'make install' ./live_zap config # instead of 'make config' ./live_zap rsync root@remotehost ssh root@remotehost # in the remote host: cd /tmp ./live_zap unload ./live_zap load ./configure Options ^^^^^^^^^^^^^^^^^^^ The configure script various several tests and based on them generates some files ( build_tools/menuselect-deps and makeopts). You can pass it --with options and variable settings, for instance: ./configure --without-ncurses CC="gcc-4.10" If you just want to recreate the same files without a full detection run, use: ./config.status To re-run ./configure with the same parameters it was run with last time, use: ./ocnfig.status --recheck Configuration ------------- zaptel.conf ~~~~~~~~~~~ The main method to configure Zaptel devices is using the utility *ztcfg*. ztcfg reads data from the configuration file /etc/zaptel.conf , figures out what configuration to send to channels, and send it. A sample annotated zaptel.conf is included in this directory and installed by default to /etc/zaptel.conf . Edit it to suit your configuration. Alternatively use the script genzaptelconf to generate one that should work with your system. sysconfig/default ~~~~~~~~~~~~~~~~~ The configuration file of the zaptel init.d script is either /etc/default/zaptel (Debian systems) or /etc/sysconfig/zaptel (most others). That file is used to override defaults that are set at the beginning of the init.d script. For instance, to define for the init.d script to load the modules wctdm and xpp_usb (in that order) add the following line to that file: MODULES="wctdm xpp_usb" Currently that file must set "TELEPHONY=yes" for the zaptel init.d to work. Module Parameters ~~~~~~~~~~~~~~~~~ The kernel modules can be configured through module parameters. Module parameters can optionally be set at load time. They are normally set (if needed) by a line in a file under /etc/modprobe.d/ or in the file /etc/modprobe.conf (Or /etc/modules.conf in kernel 2.4). Example line: options zaptel debug=1 The module parameters can normally be modified at runtime through sysfs: pungenday:~# cat /sys/module/zaptel/parameters/debug 0 pungenday:~# echo 1 >/sys/module/zaptel/parameters/debug pungenday:~# cat /sys/module/zaptel/parameters/debug 1 Viewing and setting parameters that way is possible as of kernel 2.6 . In kernels older than 2.6.10, the sysfs "files" for the parameters reside directly under /sys/module/'module_name' . Useful module parameters: debug (most modules):: Sets debug mode / debug level. With most modules 'debug' can be either disabled (0, the default value) or enabled (any other value). + + wctdm and wcte1xp print several extra debugging messages if the value of debug is more than 1. + + Some modules have "debugging flags" bits - the value of debug is a bitmask and several messages are printed if some bits are set: - ztdummy: * 1: DEBUG_GENERAL - general error messages. * 2: DEBUG_TICKS - Show that the module is alive :-) - wctdm24xxp: * 1: DEBUG_CARD * 2: DEBUG_ECHOCAN - wct4xxp: * 1: DEBUG_MAIN * 2: DEBUG_DTMF * 4: DEBUG_REGS * 8: DEBUG_TSI * 16: DEBUG_ECHOCAN * 32: DEBUG_RBS * 64: DEBUG_FRAMER - xpp: Previously (before 1.2.26 / 1.4.11) it was called "print_dbg". See also README.Astribank: * 1: GENERAL - General debug comments. * 2: PCM - PCM-related messages. Tend to flood logs. * 4: LEDS - Anything related to the LEDs status control. The driver produces a lot of messages when the option is enabled. * 8: SYNC - Synchronization related messages. * 16: SIGNAL - Zaptel signalling related messages. * 32: PROC - Messages related to the procfs interface. * 64: REGS - Reading and writing to chip registers. Tends to flood logs. * 128: DEVICES - Device instantiation, destruction and such. * 256 - COMMANDS - Protocol commands. Tends to flood logs. deftaps (zaptel):: The default size for the echo canceller. The number is in "taps", that is "samples", 1/8 ms. The default is 64 - for a tail size of 8 ms. + + Asterisk's chan_zap tends to pass its own value anyway, with a different default size. So normally setting this doesn't change anything. To get a list of parameters supported by a module, use modinfo module_name Or, for a module you have just built: modinfo ./module_name.ko For the xpp modules this will also include the description and default value of the module. You can find a list of useful xpp module parameters in README.Astribank . Reference Configuration ----------------------- include::zaptel.conf.asciidoc[] Tonezones ~~~~~~~~~ The file zonedata.c contains the information about the tone zones used in libtonezone (and hence also in ztcfg). Here is a list of those zones: include::tonezones.txt[] Zaptel PERL modules ------------------- The directory xpp/utils has, in addition to helper utilities for the Xorcom Astribank, a collection of perl modules to provide information related to Zaptel. The perl modules themselves are under xpp/utils/zconf . In xpp/utils there are several utilities that use those modules: - xpp-specific: zt_registration, xpp_sync, xpp_blink . - General: lszaptel, zapconf, zaptel_hardware The zaptel perl modules will currently only be automatically installed if you happen to isntall the xpp module. This should be the defualt, but you can also initiate it manually by running: make -C xpp/utils install Those utilities require the perl modules to be installed, however they will also look for them in the directory zconf, and thus can be run directly from the zaptel source tree. For example: ./xpp/utils/zaptel_hardware To get usage information on a program, you can also use perldoc (sometimes provided in a package separate from perl itself). For instance: perldoc ./xpp/utils/lszaptel Some of them are specific for the Xorcom Astribank and described in its docuemntation. the others are: lszaptel:: A somewhat glorified `cat /proc/zaptel/*`. zapconf:: An currently experimental and intended to eventually replace genzaptelconf by a more maintainable code. zaptel_drivers:: A two-liner script (not installed by default) that simply returns the modules that should be modprobed on this system. zaptel_hardware:: Uses the information from sysfs and its own knowledge to show what PCI/USB Zaptel hardware is connected and if it is currently used by a driver. Shows also some more information for Astrobanks from /proc/xpp . Internals --------- Zaptel Device Files ~~~~~~~~~~~~~~~~~~~ Userspace programs will usually interact with Zaptel through device files under the /dev/zap directory (pedantically: characted device files with major number 196) . Those device files can be generated statically or dynamically through the udev system. * /dev/zap/ctl (196:0) - a general device file for various information and control operations on the zaptel channels. * /dev/zap/NNN (196:NNN) - for NNN in the range 1-249. A device file for zaptel channel NNN. It can be used to read data from the channel and write data to the channel. * /dev/zap/transcode (196:250) - Used to connect to a zaptel transcoding device. * /dev/zap/timer (196:253) - Allows setting timers. Used anywhere? * /dev/zap/channel (196:254) - Can be used to open an arbitrary zaptel channel. This is an alternative to /dev/zap/NNN that is not limited to 249 channels. * /dev/zap/pseudo (196:255) - A timing-only device. Every time you open it, a new Zaptel channel is created. That Zaptel channel is "pseudo" - Zaptel recieves no data in it, and only sends garbage data with the same timing as the Zaptel timing master device. Zaptel Timing ~~~~~~~~~~~~~ A PBX system should generally have a single clock. If you are connected to a telephony provider via a digital interface (e.g: E1, T1) you should also typically use the provider's clock (as you get through the interface). Hence one important job of Asterisk is to provide timing to the PBX. Zaptel "ticks" once per millisecond (1000 times per second). On each tick every active zaptel channel reads and 8 bytes of data. Asterisk also uses this for timing, through a zaptel pseudo channel it opens. However, not all PBX systems are connected to a telephony provider via a T1 or similar connection. With an analog connection you are not synced to the other party. And some systems don't have Zaptel hardware at all. Even a digital card may be used for other uses or is simply not connected to a provider. Zaptel cards are also capable of providing timing from a clock on card. Cheap x100P clone cards are sometimes used for that pupose. If all the above fail, you can use the module ztdummy to provide timing alone without needing any zaptel hardware. It will work with most systems and kernels. You can check the zaptel timing source with zttest, which is a small utility that is included with zaptel. It runs in cycles. In each such cycle it tries to read 8192 bytes, and sees how long it takes. If zaptel is not loaded or you don't have the device files, it will fail immedietly. If you lack a timing device it will hang forever in the first cycle. Eitherwise it will just give you in each cycle the percent of how close it was. Also try running it with the option -v for a verbose output. To check the clock source that is built into ztdummy, you can either look at title of its span in /proc/zaptel file for a "source:" in the description. Or even run: strings zaptel.ko | grep source: Spans and Channels ~~~~~~~~~~~~~~~~~~ Zaptel provides telephony *channels* to the userspace applications. Those channels are channels are incoreperated into logical units called *spans*. With digital telephony adapters (e.g: E1 or T1), a span normally represents a single port. With analog telephony a span typically represents a PCI adapter or a similar logical unit. Both channels and spans are identified by enumerating numbers (beginning with 1). The number of the channel is the lowest unused one when it is generated, and ditto for spans. PROCFS Interface: /proc/zaptel ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A simple way to get the current list of spans and channels each span contains is the files under /proc/zaptel . /proc/zaptel is generated by zaptel as it loads. As each span registers to Zaptel, a file under /proc/zaptel is created for it. The name of that file is the number of that span. Each file has a 1-line title for the span followed by an empty line and then a line for each channel of the span. The title line shows the number of the span, its name and title, and (potentially) the alarms in which it is. The title shows the span number and name, followed by any allarms the span may have: For example, here is the first span in my system (with no alarms): Span 1: XBUS-00/XPD-00 "Xorcom XPD #0/0: FXS" The channel line for each channel shows its channel number, name and the actual signalling assigned to it through ztcfg. Before being configured by ztcfg: This is Zaptel channel 2, whose name is 'XPP_FXS/0/0/1'. 2 XPP_FXS/0/0/1 After being configured by ztcfg: the signalling 'FXOLS' was added. FXS channels have FXO signalling and vice versa: 2 XPP_FXS/0/0/1 FXOLS If the channel is in use (typically opened by Asterisk) then you will see an extra '(In use)': 2 XPP_FXS/0/0/1 FXOLS (In use) ABI Compatibility ~~~~~~~~~~~~~~~~~ Like any other kernel code, Zaptel strives to maintain a stable interface to userspace programs. The API of Zaptel to userspace programs, zaptel.h, has remained backword-compatible for a long time and is expected to remain so in the future. With the ABI (the bits themselves) things are slightly trickier. Zaptel's interface to userspace is mostly ioctl(3) calls. Ioctl calls are identified by a number that stems from various things, one of which is the size of the data structure passed between the kernel and userspace. Many of the Zaptel ioctl-s use some sepcific structs to pass information between kernel and userspace. In some cases the need arose to pass a few more data members in each call. Simply adding a new member to the struct would have meant a new number for the ioctl, as its number depends on the size of the data passed. Thus we would add a new ioctl with the same base number and with the original struct. So suppose we had the following ioctl: ---------------------------------- struct zt_example { int sample; } #define ZT_EXAMPLE _IOWR (ZT_CODE, 62, struct zt_example) ---------------------------------- And we want to add the field 'int onemore', we won't just add it to the struct. We will do something that is more complex: ------------------------------------ /* The original, unchanged: */ struct zt_example_v1 { int sample; } /* The new struct: */ struct zt_example { int sample; int onemore; } #define ZT_EXAMPLE_V1 _IOWR (ZT_CODE, 62, struct zt_example_v1) #define ZT_EXAMPLE _IOWR (ZT_CODE, 62, struct zt_example) ------------------------------------ We actually have here two different ioctls: the old ZT_EXAMPLE would be 0xC0044A3E . ZT_EXAMPLE_V1 would have the same value. But the new value of ZT_EXAMPLE would be 0xC0084A3E . Programs built with the original zaptel.h (before the change) use the original ioctl, whether or not the kerenl code is actually of the newer version. Thus in most cases there are no compatibility issues. When can we have compatibility issues? if we have code built with the new zaptel.h, but the loaded kernel code (modules) are of the older version. Thus the userspace program will try to use the newer ZT_EXAMPLE (0xC0084A3E). But the kernel code has no handler for that ioctl. The result: the error 25, ENOTTY, which means "Inappropriate ioctl for device". As a by-product of that method, for each interface change a new #define is added. That definition is for the old version and thus it might appear slightly confusing in the code, but it is useful for writing code that works with both versions of Zaptel. Past Incompatibilities ^^^^^^^^^^^^^^^^^^^^^^ .Zaptel 1.4.10: * Semantics of ZT_LOADZONE. Using newer ztcfg with older modules will yield -EINVAL with the kernel message 'Invalid tone (96) defined' .Zaptel 1.4.8: * ZT_GET_PARAMS_V1 * ZT_SET_PARAMS_V1 * ZT_SPANINFO_V2 .Zaptel 1.4.6: * ZT_SPANINFO_V1 ZT_SPANINFO_V1 was originally called (up to zaptel 1.4.8) "ZT_SPANINFO_COMPAT". PPP Support ----------- Zaptel digital cards can provide data channels through ppp as point-to-point connections. This requires a plugin to the ppp daemon that is included in the ppp/ subdirectory. To install it: 1. Make sure you have the PPP source / headers installed. On Debian: apt-get install ppp-dev 2. Run 'make' on the ppp subdirectory: make -C ppp make -C ppp install 3. Make sure your kernel has support for both PPP (which is common is distribution kernels and for HDLC (much less common) - CONFIG_PPP and CONFIG_HDLC . What is the license for the zaptel driver? ------------------------------------------ libpri is distributed under the terms of the GNU General Public License, which permit its use and linking with other GPL'd software only. The GNU GPL is included in the file LICENSE in this directory. If you wish to use the zaptel drivers in an application for which the GPL is not appropriate (e.g. a proprietary embedded system), licenses under more flexible terms can be readily obtained through Digium, Inc.at reasonable cost. How do I report bugs or contribute? ----------------------------------- Please report bug and patches to the Asterisk.org bug tracker at http://bugs.digium.com in the "zaptel" category. Does anything use this library so far? -------------------------------------- Yes, the Asterisk Open Source PBX does. http://www.asterisk.org Links ----- - http://asterisk.org/[] - The Asterisk PBX - http://voip-info.org/[] - http://voip-info.org/wiki/view/Asterisk+Zaptel+Installation[] - http://www.zapatatelephony.org/[] - A historical site. - http://rapid.tzafrir.org.il/docs/README.html[Up-to-date HTML version of this file] zaptel-1.4.11/install_prereq0000755000000000000000000000626110756425115014560 0ustar rootroot#! /bin/sh # install_prereq: a script to install distribution-specific # prerequirements set -e usage() { echo "$0: a script to install distribution-specific prerequirement" echo 'Revision: $Id: install_prereq 3852 2008-02-19 01:01:01Z tzafrir $' echo "" echo "Usage: $0: Shows this message." echo "Usage: $0 test Prints commands it is about to run." echo "Usage: $0 install Really install." } PACKAGES_DEBIAN="build-essential libnewt-dev libusb-dev modemp3d" PACKAGES_RH="gcc newt-devel libusb-devel" KVERS=`uname -r` case "$1" in test) testcmd=test_cmd ;; install) testcmd='' ;; '') usage; exit 0 ;; *) usage; exit 1 ;; esac NOTHING_TO_INSTALL=true test_cmd() { NOTHING_TO_INSTALL=false echo "$@" } # Fixme: should be done by apt and not by dpkg? check_installed_debs() { dpkg-query -W --showformat '${Status} ${Package}\n' "$@" 2>/dev/null \ | awk '/ not-installed/{print $4}' } # parsing the output of yum is close to impossible. # We'll use rpm and hope for the best: check_installed_rpms() { for pack in "$@" do if ! rpm -q $pack >/dev/null 2>/dev/null then echo $pack fi done } has_kernel_source() { test -r /lib/modules/$KVERS/build/.config } in_test_mode() { test "$testcmd" != '' } handle_debian() { # echo "# Distribution is Debian or compatible" kernel_package='' extra_packs=`check_installed_debs $PACKAGES_DEBIAN` if ! has_kernel_source; then kernel_package="linux-headers-$KVERS" debian_release=`cat /etc/debian_version` case "$debian_release" in 3.1) kernel_package="kernel-headers-$KVERS";; esac echo "# Kernel source not found. Installing $kernel_package" fi if [ "$extra_packs$kernel_package" = '' ]; then return fi $testcmd apt-get install -y $extra_packs $kernel_package } handle_rh() { # echo "# Distribution is RedHat or similar." kernel_package='' extra_packs=`check_installed_rpms $PACKAGES_RH` if ! has_kernel_source; then kern_str='' # extra "kernel version" case "$KVERS" in *smp*) kern_str='-smp';; *PAE*) kern_str='-PAE';; *xen*) kern_str='-xen';; esac kernel_package="kernel$kern_str-devel-$KVERS" echo "# Kernel source not found. Installing $kernel_package" echo "# if you get an error for the following command, consider" echo "#" echo "#yum install -y kernel$kern_str kernel$kern_str-devel" echo "#" echo "# and then reboot to upgrade to the newly installed kernel." fi if [ "$extra_packs$kernel_package" = '' ]; then return fi $testcmd yum install -y $extra_packs $kernel_package } if in_test_mode; then echo "#############################################" echo "## $1: test mode." echo "## Use the commands here to install your system." echo "#############################################" fi # handle the easy case of Debians first if [ -r /etc/debian_version ]; then handle_debian elif [ -r /etc/redhat-release ]; then handle_rh fi echo "#############################################" if in_test_mode; then if $NOTHING_TO_INSTALL; then echo "## $1 completed successfully ((In test mode) " else echo "## $1: some extra packages are needed to build zaptel" exit 1 fi else echo "## $1 completed successfully" fi echo "#############################################" zaptel-1.4.11/hdlcverify.c0000644000000000000000000000433710751714440014110 0ustar rootroot#define FAST_HDLC_NEED_TABLES #include "kernel/fasthdlc.h" #include #include #include #include #include #include int myread(int fd, char *buf, int len) { int sofar; int res; sofar = 0; while(sofar < len) { res = read(fd, buf + sofar, len - sofar); if (res < 0) return res; sofar += res; } return sofar; } static inline unsigned char nextchar(int fd) { static unsigned char inbuf[2048]; static int bytes = 0; static int pos = 0; if (pos >= bytes) { pos = 0; bytes = read(fd, inbuf, sizeof(inbuf)); if (bytes < 0) { fprintf(stderr, "Unable to read more data: %s\n", strerror(errno)); exit(1); } if (bytes == 0) { fprintf(stderr, "-- END OF DATA --\n"); exit(0); } } return inbuf[pos++]; } int main(int argc, char *argv[]) { unsigned char decbuf[1024]; unsigned char actual[1024]; int res; int datain; int hdlcin; int hdlccnt; int x; struct fasthdlc_state receiver; fasthdlc_precalc(); fasthdlc_init(&receiver); hdlcin = open("random.hdlc", O_RDONLY); if (hdlcin < 0) { fprintf(stderr, "Unable to open %s: %s\n", "random.hdlc", strerror(errno)); exit(1); } datain = open("random.raw", O_RDONLY); if (datain < 0) { fprintf(stderr, "Unable to open random.raw: %s\n", strerror(errno)); exit(1); } hdlccnt = 0; for (;;) { /* Feed in some input */ if (fasthdlc_rx_load(&receiver, nextchar(hdlcin))) { fprintf(stderr, "Unable to feed receiver :(\n"); exit(1); } res = fasthdlc_rx_run(&receiver); if (res & RETURN_EMPTY_FLAG) continue; if (res & RETURN_COMPLETE_FLAG) { if (hdlccnt) { if (argc > 1) printf("Got message of length %d\n", hdlccnt); res = myread(datain, actual, hdlccnt); if (res != hdlccnt) { fprintf(stderr, "Tried to read %d bytes, but read %d instead\n", hdlccnt, res); exit(1); } for (x=0;x/dev/null | grep "^$1 "` if [ "$line" = '' ]; then return; fi # module was not loaded set -- $line # $1: the original module, $2: size, $3: refcount, $4: deps list mods=`echo $4 | tr , ' '` # xpp_usb keeps the xpds below busy if an xpp hardware is # connected. Hence must be removed before them: case "$module" in xpd_*) mods="xpp_usb $mods";; esac for mod in $mods; do # run in a subshell, so it won't step over our vars: (unload_module $mod) # TODO: the following is probably the error handling we want: # if [ $? != 0 ]; then return 1; fi done rmmod $module } # Initialize the Xorcom Astribank (xpp/) using perl utiliites: # intended to replace all the the three functions below if user has # installed the zaptel-perl utilities. xpp_startup() { # do nothing if there are no astribank devices: if ! grep -q connected /proc/xpp/xbuses 2>/dev/null; then return 0; fi echo "Waiting for Astribank devices to initialize:" cat /proc/xpp/XBUS-[0-9]*/waitfor_xpds 2>/dev/null || true # overriding locales for the above two, as perl can be noisy # when locales are missing. # No register all the devices if they didn't auto-register: LC_ALL=C zt_registration on # this one could actually be run after ztcfg: LC_ALL=C xpp_sync "$XPP_SYNC" } hpec_start() { # HPEC license found if ! echo /var/lib/digium/licenses/HPEC-*.lic | grep -v '\*' | grep -q .; then return fi # zaphpec_enable not installed in /usr/sbin if [ ! -f /usr/sbin/zaphpec_enable ]; then echo -n "Running zaphpec_enable: Failed" echo -n "." echo " The zaphpec_enable binary is not installed in /usr/sbin." return fi # zaphpec_enable not set executable if [ ! -x /usr/sbin/zaphpec_enable ]; then echo -n "Running zaphpec_enable: Failed" echo -n "." echo " /usr/sbin/zaphpec_enable is not set as executable." return fi # zaphpec_enable properly installed if [ $system = debian ]; then echo -n "Running zaphpec_enable: " /usr/sbin/zaphpec_enable 2> /dev/null elif [ $system = redhat ]; then action "Running zaphpec_enable: " /usr/sbin/zaphpec_enable fi if [ $? = 0 ]; then echo -n "done" echo "." else echo -n "Failed" echo -n "." echo " This can be caused if you had already run zaphpec_enable, or if your HPEC license is no longer valid." fi } shutdown_dynamic() { if ! grep -q ' ZTD/' /proc/* 2>/dev/null; then return; fi # we should only get here if we have dynamic spans. Right? $ZTCFG_CMD -s } # Check that telephony is up. if [ "${TELEPHONY}" != "yes" ]; then echo "No TELEPHONY found" exit 0 fi if [ ! -x "$ZTCFG" ]; then echo "ztcfg not executable" exit 0 fi if [ ! -f /etc/zaptel.conf ]; then echo "/etc/zaptel.conf not found" exit 0 fi if [ "${DEBUG}" = "yes" ]; then ARGS="debug=1" fi RETVAL=0 # See how we were called. case "$1" in start) # Load drivers rmmod wcusb 2> /dev/null rmmod wcfxsusb 2> /dev/null rmmod audio 2> /dev/null if [ $system = debian ]; then echo -n "Loading zaptel framework: " modprobe zaptel ${ARGS} 2> /dev/null && echo -n "done" echo "." elif [ $system = redhat ]; then action "Loading zaptel framework: " modprobe zaptel ${ARGS} fi echo -n "Waiting for zap to come online..." TMOUT=$ZAP_DEV_TIMEOUT # max secs to wait while [ ! -d /dev/zap ] ; do sleep 1 TMOUT=`expr $TMOUT - 1` if [ $TMOUT -eq 0 ] ; then echo "Error: missing /dev/zap!" exit 1 fi done echo "OK" echo -n "Loading zaptel hardware modules:" for x in $MODULES; do eval localARGS="\$${x}_ARGS" if modprobe ${x} ${ARGS} ${localARGS} 2> /dev/null; then echo -n " $x" echo "." fi done sleep 3 # TODO: remove it # If you have zaptel-perl, the three below can be replaced with: xpp_startup if [ ! -e /proc/zaptel/1 ]; then echo "No hardware timing source found in /proc/zaptel, loading ztdummy" modprobe ztdummy 2> /dev/null fi if [ $system = debian ]; then echo -n "Running ztcfg: " $ZTCFG_CMD 2> /dev/null && echo -n "done" echo "." elif [ $system = redhat ]; then action "Running ztcfg: " $ZTCFG_CMD fi RETVAL=$? [ $RETVAL -eq 0 ] && touch $LOCKFILE if [ -x "$FXOTUNE" ] && [ -r /etc/fxotune.conf ]; then # Allowed to fail if e.g. Asterisk already uses channels: $FXOTUNE -s || : fi hpec_start ;; stop) # Unload drivers #shutdown_dynamic # FIXME: needs test from someone with dynamic spans echo -n "Unloading zaptel hardware drivers:" unload_module zaptel RETVAL=$? echo "." [ $RETVAL -eq 0 ] && rm -f $LOCKFILE ;; unload) # We don't have zaptel helper, so let's not replicate too much code: # allow others to use the unload command. unload_module zaptel ;; restart) $0 stop $0 start ;; reload) if [ $system = debian ]; then echo -n "Reloading ztcfg: " $ZTCFG_CMD 2> /dev/null && echo -n "done" echo "." elif [ $system = redhat ]; then action "Reloading ztcfg: " $ZTCFG_CMD fi RETVAL=$? ;; *) echo "Usage: zaptel {start|stop|restart|reload}" exit 1 esac exit $RETVAL zaptel-1.4.11/pattest.c0000644000000000000000000000375710751714440013442 0ustar rootroot#include #include #include #include #include #include #include #include #include #include #include "bittest.h" #ifdef STANDALONE_ZAPATA #include "kernel/zaptel.h" #else #include #endif #define BLOCK_SIZE 2039 void print_packet(unsigned char *buf, int len) { int x; printf("{ "); for (x=0;x\n"); exit(1); } fd = open(argv[1], O_RDWR, 0600); if (fd < 0) { fprintf(stderr, "Unable to open %s: %s\n", argv[1], strerror(errno)); exit(1); } if (ioctl(fd, ZT_SET_BLOCKSIZE, &bs)) { fprintf(stderr, "Unable to set block size to %d: %s\n", bs, strerror(errno)); exit(1); } if (ioctl(fd, ZT_GET_PARAMS, &tp)) { fprintf(stderr, "Unable to get channel parameters\n"); exit(1); } ioctl(fd, ZT_GETEVENT); for(;;) { res = bs; res = read(fd, outbuf, res); if (res < bs) { int e; ZT_SPANINFO zi; res = ioctl(fd,ZT_GETEVENT,&e); if (res == -1) { perror("ZT_GETEVENT"); exit(1); } if (e == ZT_EVENT_NOALARM) printf("ALARMS CLEARED\n"); if (e == ZT_EVENT_ALARM) { zi.spanno = 0; res = ioctl(fd,ZT_SPANSTAT,&zi); if (res == -1) { perror("ZT_SPANSTAT"); exit(1); } printf("Alarm mask %x hex\n",zi.alarms); } continue; } if (!setup) { c = outbuf[0]; setup++; } for (x=0;x #include #include #include #include #include #include #include #include #ifdef STANDALONE_ZAPATA #include "kernel/zaptel.h" #else #include #endif #define BLOCK_SIZE 2039 void print_packet(unsigned char *buf, int len) { int x; printf("{ "); for (x=0;x 3 ) { fprintf(stderr, "Usage: %s [timeout]\n",argv[0]); exit(1); } fd = open(argv[1], O_RDWR, 0600); if (fd < 0) { fprintf(stderr, "Unable to open %s: %s\n", argv[1], strerror(errno)); exit(1); } if (ioctl(fd, ZT_SET_BLOCKSIZE, &bs)) { fprintf(stderr, "Unable to set block size to %d: %s\n", bs, strerror(errno)); exit(1); } if (ioctl(fd, ZT_GET_PARAMS, &tp)) { fprintf(stderr, "Unable to get channel parameters\n"); exit(1); } ioctl(fd, ZT_GETEVENT); i = ZT_FLUSH_ALL; if (ioctl(fd,ZT_FLUSH,&i) == -1) { perror("tor_flush"); exit(255); } if(argc==3){ timeout=atoi(argv[2]); start_time=time(NULL); printf("Using Timeout of %d Seconds\n",timeout); } for(;;) { res = bs; for (x=0;x 1) read(fd,inbuf,bs); skipcount--; if (!skipcount) puts("Going for it..."); continue; } res = read(fd, inbuf, bs); if (res < bs) { printf("Res is %d\n", res); exit(1); } if (!setup) { c = inbuf[0]; setup++; } for (x=0;xtimeout){ printf("Timeout achieved Ending Program\n"); return errors; } } } zaptel-1.4.11/orig.ee0000644000000000000000000000025410343120400013032 0ustar rootrootÐ ð Factory Data0µ€0µ@HHLÿÿà@ €€€0x$€ñý¶zaptel-1.4.11/ztdiag.c0000644000000000000000000000106210751714440013223 0ustar rootroot#include #include #include #include #include #ifdef STANDALONE_ZAPATA #include "kernel/zaptel.h" #else #include #endif int main(int argc, char *argv[]) { int fd; int chan; if ((argc < 2) || (sscanf(argv[1], "%d", &chan) != 1)) { fprintf(stderr, "Usage: ztdiag \n"); exit(1); } fd = open("/dev/zap/ctl", O_RDWR); if (fd < 0) { perror("open(/dev/zap/ctl"); exit(1); } if (ioctl(fd, ZT_CHANDIAG, &chan)) { perror("ioctl(ZT_CHANDIAG)"); exit(1); } exit(0); } zaptel-1.4.11/ztcfg.h0000644000000000000000000000165010374426616013074 0ustar rootroot/* * BSD Telephony Of Mexico "Tormenta" card LINUX driver, version 1.6 1/9/01 * * Working with the "Tormenta ISA" Card * * * Part of the "Zapata" Computer Telephony Technology. * * See http://www.bsdtelephony.com.mx * * * The technologies, software, hardware, designs, drawings, scheumatics, board * layouts and/or artwork, concepts, methodologies (including the use of all * of these, and that which is derived from the use of all of these), all other * intellectual properties contained herein, and all intellectual property * rights have been and shall continue to be expressly for the benefit of all * mankind, and are perpetually placed in the public domain, and may be used, * copied, and/or modified by anyone, in any manner, for any legal purpose, * without restriction. */ #ifndef _ZTCFG_H #define _ZTCFG_H #define CONFIG_FILENAME ZAPTEL_CONFIG #define MASTER_DEVICE "/dev/zap/ctl" #endif zaptel-1.4.11/tor2.ee0000644000000000000000000000025410343120400012760 0ustar rootrootÐ ð Factory Data е€0µ@HHLÿøÿø€€€0x`€ñ2±zaptel-1.4.11/zaptel.sysconfig0000644000000000000000000000446310732005243015023 0ustar rootrootTELEPHONY=yes # DEBUG: Pass debug=1 to modules you load. # May break xpp_usb. #DEBUG=yes # #Alternatively set: options zaptel debug=1 #in /etc/modprobe.d/zaptel or /etc/modprobe.conf. # # ZTCFG: The full path to ztcfg. default: /sbin/ztcfg . #ZTCFG=/usr/local/sbin/ztcfg # # ZTCFG_CMD: allow adding extra parameters to the ztcfg command. # May be handy for -v, but mostly for: #ZTCFG_CMD=/sbin/ztcfg -c /home/tzafrir/myzaptel.conf # # XPP_SYNC: Can be used to set an explicit Astribank unit as the # synchronizing Astribank. Passed to xpp_sync(8) . # Default is 'auto' and is almost always a good choice. #XPP_SYNC=01 # Un-comment as per your requirements; modules to load/unload #Module Name Hardware MODULES="$MODULES tor2" # T400P - Quad Span T1 Card # E400P - Quad Span E1 Card MODULES="$MODULES wct4xxp" # TE405P - Quad Span T1/E1 Card (5v version) # TE410P - Quad Span T1/E1 Card (3.3v version) #wct4xxp_ARGS="t1e1override=15" # Additional parameters for TE4xxP driver # or use /etc/modprobe.d/zaptel or /etc/modprobe.conf . MODULES="$MODULES wcte12xp" # TE120P - Single Span T1/E1 Card MODULES="$MODULES wct1xxp" # T100P - Single Span T1 Card # E100P - Single Span E1 Card MODULES="$MODULES wcte11xp" # TE110P - Single Span T1/E1 Card MODULES="$MODULES wctdm24xxp" # TDM2400P - Modular FXS/FXO interface (1-24 ports) MODULES="$MODULES wcfxo" # X100P - Single port FXO interface # X101P - Single port FXO interface MODULES="$MODULES wctdm" # TDM400P - Modular FXS/FXO interface (1-4 ports) MODULES="$MODULES wcusb" # S100U - Single port FXS USB Interface #MODULES="$MODULES torisa" # Old Tormenta1 ISA Card #MODULES="$MODULES ztdummy" # Zaptel Timing Only Interface MODULES="$MODULES xpp_usb" # Xorcom Astribank Device # Disables Astribank hotplug firmware loading #XPP_HOTPLUG_DISABLED=yes # # Disables Astribank udev hook called when an astribank is added and ready # or removed. #ASTRIBANK_HOOK_DISABLED=yes # # Setup the configuration for the PRI module of the Astribank. # Default: all E1,TE . See xpp/README.Astribank . #XPP_PRI_SETUP='NUM/*/XPD-01=NT,E1' # Extensions genzaptelconf are (base + channel_number) # base is by default 6000: #base_exten=6000 # # There are a host of other variables you can set to affect # genzaptelconf. See the beginning of the script. zaptel-1.4.11/README.fxotune0000644000000000000000000000222410374426616014153 0ustar rootrootQ. I have echo problems on my FXO modules and I've tried the different echo cancellation algorithms in zconfig.h, tried tweaking the gains, and still nothing works. What can I do? A. Use the fxotune utility. To use: Just run the fxotune utility with the -i option. (`fxotune -i 4`) It should discover which zap channels are FXO modules and tune them accordingly. Be warned however, it takes a significant amount of time for EACH module to test, I would say somewhere around 2-3 minutes. But you only have to initialize it once for the line. It will write a configuration file to /etc/fxotune.conf. You will need to have your system run fxotune with the -s flag (`fxotune -s`) to set the module with the previously discovered values from fxotune.conf for it to take affect, so essentially if each time you reboot the machine you need to run `fxotune -s`. You might consider putting it in your startup scripts some time after the module loads and before asterisk runs. NOTE: The digit after the -i option is the digit that will break dialtone on the line. As always, if you have any questions, you can email me at creslin@NOSPAMdigium.com Matthew Fredrickson zaptel-1.4.11/hdlcgen.c0000644000000000000000000000506210751714440013351 0ustar rootroot#define FAST_HDLC_NEED_TABLES #include "kernel/fasthdlc.h" #include #include #include #include #include #include #define RANDOM "/dev/urandom" /* Not genuinely random */ /* #define RANDOM "/dev/random" */ /* Quite genuinely random */ int myread(int fd, char *buf, int len) { int sofar; int res; sofar = 0; while(sofar < len) { res = read(fd, buf + sofar, len - sofar); if (res < 0) return res; sofar += res; } return sofar; } int main(int argc, char *argv[]) { unsigned char buf[1024]; unsigned char outbuf[2048]; int res; int randin; int randout; int hdlcout; int cnt; int hdlccnt; int x; int flags; struct fasthdlc_state transmitter; fasthdlc_precalc(); fasthdlc_init(&transmitter); randin = open(RANDOM, O_RDONLY); if (randin < 0) { fprintf(stderr, "Unable to open %s: %s\n", RANDOM, strerror(errno)); exit(1); } randout = open("random.raw", O_WRONLY|O_TRUNC|O_CREAT, 0666); if (randout < 0) { fprintf(stderr, "Unable to open random.raw: %s\n", strerror(errno)); exit(1); } hdlcout = open("random.hdlc", O_WRONLY|O_TRUNC|O_CREAT, 0666); if (hdlcout < 0) { fprintf(stderr, "Unable to open random.hdlc: %s\n", strerror(errno)); exit(1); } for (;;) { cnt = (rand() % 256) + 4; /* Read a pseudo-random amount of stuff */ res = myread(randin, buf, cnt); if (res != cnt) { fprintf(stderr, "Tried to read %d bytes, but read %d instead\n", cnt, res); exit(1); } res = write(randout, buf, cnt); if (res != cnt) { fprintf(stderr, "Tried to write %d bytes, but wrote %d instead\n", cnt, res); exit(1); } /* HDLC encode */ hdlccnt = 0; /* Start with a flag */ fasthdlc_tx_frame(&transmitter); if (transmitter.bits >= 8) outbuf[hdlccnt++] = fasthdlc_tx_run(&transmitter); for (x=0;x= 8) { outbuf[hdlccnt++] = fasthdlc_tx_run(&transmitter); } } flags = (rand() % 4); for (x=0;x 1) printf("Encoded %d byte message with %d bytes of HDLC and %d extra flags\n", cnt, hdlccnt, flags); res = write(hdlcout, outbuf, hdlccnt); if (res != hdlccnt) { fprintf(stderr, "Tried to write %d HDLC bytes, but wrote %d instead\n", cnt, res); exit(1); } } } zaptel-1.4.11/sethdlc-new.c0000644000000000000000000003523610756406320014170 0ustar rootroot/* * sethdlc.c * * Copyright (C) 1999 - 2002 Krzysztof Halasa * * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kernel/zaptel.h" #if GENERIC_HDLC_VERSION != 4 #error Generic HDLC layer version mismatch, please get correct sethdlc.c #endif #if !defined(IF_PROTO_HDLC_ETH) || !defined(IF_PROTO_FR_ETH_PVC) #warning "No kernel support for Ethernet over Frame Relay / HDLC, skipping it" #endif static struct ifreq req; /* for ioctl */ static int argc; static char **argv; int sock; static void error(const char *format, ...) __attribute__ ((noreturn)); static void error(const char *format, ...) { va_list args; va_start(args, format); fprintf(stderr, "%s: ", req.ifr_name); vfprintf(stderr, format, args); va_end(args); exit(1); } typedef struct { const char *name; const unsigned int value; } parsertab; static int checkkey(const char* name) { if (argc < 1) return -1; /* no enough parameters */ if (strcmp(name, argv[0])) return -1; argc--; argv++; return 0; } static int checktab(parsertab *tab, unsigned int *value) { int i; if (argc < 1) return -1; /* no enough parameters */ for (i = 0; tab[i].name; i++) if (!strcmp(tab[i].name, argv[0])) { argc--; argv++; *value = tab[i].value; return 0; } return -1; /* Not found */ } static const char* tabstr(unsigned int value, parsertab *tab, const char* unknown) { int i; for (i = 0; tab[i].name; i++) if (tab[i].value == value) return tab[i].name; return unknown; /* Not found */ } static unsigned int match(const char* name, unsigned int *value, unsigned int minimum, unsigned int maximum) { char test; if (argc < 1) return -1; /* no enough parameters */ if (name) { if (strcmp(name, argv[0])) return -1; argc--; argv++; } if (argc < 1) error("Missing parameter\n"); if (sscanf(argv[0], "%u%c", value, &test) != 1) error("Invalid parameter: %s\n", argv[0]); if ((*value > maximum) || (*value < minimum)) error("Parameter out of range [%u - %u]: %u\n", minimum, maximum, *value); argc--; argv++; return 0; } static parsertab ifaces[] = {{ "v35", IF_IFACE_V35 }, { "v24", IF_IFACE_V24 }, { "x21", IF_IFACE_X21 }, { "e1", IF_IFACE_E1 }, { "t1", IF_IFACE_T1 }, { NULL, 0 }}; static parsertab clocks[] = {{ "int", CLOCK_INT }, { "ext", CLOCK_EXT }, { "txint", CLOCK_TXINT }, { "txfromrx", CLOCK_TXFROMRX }, { NULL, 0 }}; static parsertab protos[] = {{ "hdlc", IF_PROTO_HDLC}, { "cisco", IF_PROTO_CISCO}, { "fr", IF_PROTO_FR}, { "ppp", IF_PROTO_PPP}, { "x25", IF_PROTO_X25}, #ifdef IF_PROTO_HDLC_ETH { "hdlc-eth", IF_PROTO_HDLC_ETH}, #endif { NULL, 0 }}; static parsertab hdlc_enc[] = {{ "nrz", ENCODING_NRZ }, { "nrzi", ENCODING_NRZI }, { "fm-mark", ENCODING_FM_MARK }, { "fm-space", ENCODING_FM_SPACE }, { "manchester", ENCODING_MANCHESTER }, { NULL, 0 }}; static parsertab hdlc_par[] = {{ "no-parity", PARITY_NONE }, { "crc16", PARITY_CRC16_PR1 }, { "crc16-pr0", PARITY_CRC16_PR0 }, { "crc16-itu", PARITY_CRC16_PR1_CCITT }, { "crc16-itu-pr0", PARITY_CRC16_PR0_CCITT }, { "crc32-itu", PARITY_CRC32_PR1_CCITT }, { NULL, 0 }}; static parsertab lmi[] = {{ "none", LMI_NONE }, { "ansi", LMI_ANSI }, { "ccitt", LMI_CCITT }, { NULL, 0 }}; static void set_iface(void) { int orig_argc = argc; te1_settings te1; memset(&te1, 0, sizeof(te1)); req.ifr_settings.type = IF_IFACE_SYNC_SERIAL; while (argc > 0) { if (req.ifr_settings.type == IF_IFACE_SYNC_SERIAL) if (!checktab(ifaces, &req.ifr_settings.type)) continue; if (!te1.clock_type) if (!checkkey("clock")) { if (!checktab(clocks, &te1.clock_type)) continue; error("Invalid clock type\n"); } if (!te1.clock_rate && (te1.clock_type == CLOCK_INT || te1.clock_type == CLOCK_TXINT)) if (!match("rate", &te1.clock_rate, 1, 0xFFFFFFFF)) continue; if (!te1.loopback) { if (!checkkey("loopback") || !checkkey("lb")) { te1.loopback = 1; continue; } } /* slotmap goes here */ if (orig_argc == argc) return; /* not an iface definition */ error("Invalid parameter: %s\n", argv[0]); } if (!te1.clock_rate && (te1.clock_type == CLOCK_INT || te1.clock_type == CLOCK_TXINT)) te1.clock_rate = 64000; /* FIXME stupid hack, will remove it later */ req.ifr_settings.ifs_ifsu.te1 = &te1; if (req.ifr_settings.type == IF_IFACE_E1 || req.ifr_settings.type == IF_IFACE_T1) req.ifr_settings.size = sizeof(te1_settings); else req.ifr_settings.size = sizeof(sync_serial_settings); if (ioctl(sock, SIOCWANDEV, &req)) error("Unable to set interface information: %s\n", strerror(errno)); exit(0); } static void set_proto_fr(void) { unsigned int lmi_type = 0; fr_proto fr; memset(&fr, 0, sizeof(fr)); while (argc > 0) { if (!lmi_type) if (!checkkey("lmi")) { if (!checktab(lmi, &lmi_type)) continue; error("Invalid LMI type: %s\n", argv[0]); } if (lmi_type && lmi_type != LMI_NONE) { if (!fr.dce) if (!checkkey("dce")) { fr.dce = 1; continue; } if (!fr.t391) if (!match("t391", &fr.t391, 1, 1000)) continue; if (!fr.t392) if (!match("t392", &fr.t392, 1, 1000)) continue; if (!fr.n391) if (!match("n391", &fr.n391, 1, 1000)) continue; if (!fr.n392) if (!match("n392", &fr.n392, 1, 1000)) continue; if (!fr.n393) if (!match("n393", &fr.n393, 1, 1000)) continue; } error("Invalid parameter: %s\n", argv[0]); } /* polling verification timer*/ if (!fr.t391) fr.t391 = 10; /* link integrity verification polling timer */ if (!fr.t392) fr.t392 = 15; /* full status polling counter*/ if (!fr.n391) fr.n391 = 6; /* error threshold */ if (!fr.n392) fr.n392 = 3; /* monitored events count */ if (!fr.n393) fr.n393 = 4; if (!lmi_type) fr.lmi = LMI_DEFAULT; else fr.lmi = lmi_type; req.ifr_settings.ifs_ifsu.fr = &fr; req.ifr_settings.size = sizeof(fr); if (ioctl(sock, SIOCWANDEV, &req)) error("Unable to set FR protocol information: %s\n", strerror(errno)); } static void set_proto_hdlc(int eth) { unsigned int enc = 0, par = 0; raw_hdlc_proto raw; memset(&raw, 0, sizeof(raw)); while (argc > 0) { if (!enc) if (!checktab(hdlc_enc, &enc)) continue; if (!par) if (!checktab(hdlc_par, &par)) continue; error("Invalid parameter: %s\n", argv[0]); } if (!enc) raw.encoding = ENCODING_DEFAULT; else raw.encoding = enc; if (!par) raw.parity = ENCODING_DEFAULT; else raw.parity = par; req.ifr_settings.ifs_ifsu.raw_hdlc = &raw; req.ifr_settings.size = sizeof(raw); if (ioctl(sock, SIOCWANDEV, &req)) error("Unable to set HDLC%s protocol information: %s\n", eth ? "-ETH" : "", strerror(errno)); } static void set_proto_cisco(void) { cisco_proto cisco; memset(&cisco, 0, sizeof(cisco)); while (argc > 0) { if (!cisco.interval) if (!match("interval", &cisco.interval, 1, 100)) continue; if (!cisco.timeout) if (!match("timeout", &cisco.timeout, 1, 100)) continue; error("Invalid parameter: %s\n", argv[0]); } if (!cisco.interval) cisco.interval = 10; if (!cisco.timeout) cisco.timeout = 25; req.ifr_settings.ifs_ifsu.cisco = &cisco; req.ifr_settings.size = sizeof(cisco); if (ioctl(sock, SIOCWANDEV, &req)) error("Unable to set Cisco HDLC protocol information: %s\n", strerror(errno)); } static void set_proto(void) { if (checktab(protos, &req.ifr_settings.type)) return; switch(req.ifr_settings.type) { case IF_PROTO_HDLC: set_proto_hdlc(0); break; #ifdef IF_PROTO_HDLC_ETH case IF_PROTO_HDLC_ETH: set_proto_hdlc(1); break; #endif case IF_PROTO_CISCO: set_proto_cisco(); break; case IF_PROTO_FR: set_proto_fr(); break; case IF_PROTO_PPP: case IF_PROTO_X25: req.ifr_settings.ifs_ifsu.sync = NULL; /* FIXME */ req.ifr_settings.size = 0; if (!ioctl(sock, SIOCWANDEV, &req)) break; error("Unable to set %s protocol information: %s\n", req.ifr_settings.type == IF_PROTO_PPP ? "PPP" : "X.25", strerror(errno)); default: error("Unknown protocol %u\n", req.ifr_settings.type); } if (argc > 0) error("Unexpected parameter: %s\n", argv[0]); close(sock); exit(0); } static void set_pvc(void) { char *op = argv[0]; parsertab ops[] = {{ "create", IF_PROTO_FR_ADD_PVC }, { "delete", IF_PROTO_FR_DEL_PVC }, { NULL, 0 }}; fr_proto_pvc pvc; memset(&pvc, 0, sizeof(pvc)); if (checktab(ops, &req.ifr_settings.type)) return; #ifdef IF_PROTO_FR_ETH_PVC if (!match("ether", &pvc.dlci, 0, 1023)) { if (req.ifr_settings.type == IF_PROTO_FR_ADD_PVC) req.ifr_settings.type = IF_PROTO_FR_ADD_ETH_PVC; else req.ifr_settings.type = IF_PROTO_FR_DEL_ETH_PVC; } else #endif if (match(NULL, &pvc.dlci, 0, 1023)) return; if (argc != 0) return; req.ifr_settings.ifs_ifsu.fr_pvc = &pvc; req.ifr_settings.size = sizeof(pvc); if (ioctl(sock, SIOCWANDEV, &req)) error("Unable to %s PVC: %s\n", op, strerror(errno)); exit(0); } static void private(void) { if (argc < 1) return; if (!strcmp(argv[0], "private")) { if (argc != 1) return; if (ioctl(sock, SIOCDEVPRIVATE, &req)) error("SIOCDEVPRIVATE: %s\n", strerror(errno)); exit(0); } } static void show_port(void) { const char *s; char buffer[128]; const te1_settings *te1 = (void*)buffer; const raw_hdlc_proto *raw = (void*)buffer; const cisco_proto *cisco = (void*)buffer; const fr_proto *fr = (void*)buffer; #ifdef IF_PROTO_FR_PVC const fr_proto_pvc_info *pvc = (void*)buffer; #endif req.ifr_settings.ifs_ifsu.sync = (void*)buffer; /* FIXME */ printf("%s: ", req.ifr_name); req.ifr_settings.size = sizeof(buffer); req.ifr_settings.type = IF_GET_IFACE; if (ioctl(sock, SIOCWANDEV, &req)) if (errno != EINVAL) { printf("unable to get interface information: %s\n", strerror(errno)); close(sock); exit(1); } /* Get and print physical interface settings */ if (req.ifr_settings.type == IF_IFACE_SYNC_SERIAL) s = ""; /* Unspecified serial interface */ else s = tabstr(req.ifr_settings.type, ifaces, NULL); if (!s) printf("unknown interface 0x%x\n", req.ifr_settings.type); else { if (*s) printf("interface %s ", s); printf("clock %s", tabstr(te1->clock_type, clocks, "type unknown")); if (te1->clock_type == CLOCK_INT || te1->clock_type == CLOCK_TXINT) printf(" rate %u", te1->clock_rate); if (te1->loopback) printf(" loopback"); if (req.ifr_settings.type == IF_IFACE_E1 || req.ifr_settings.type == IF_IFACE_T1) { unsigned int u; printf(" slotmap "); for (u = te1->slot_map; u != 0; u /= 2) printf("%u", u % 2); } printf("\n"); } /* Get and print protocol settings */ do { printf("\t"); req.ifr_settings.size = sizeof(buffer); req.ifr_settings.type = IF_GET_PROTO; if (ioctl(sock, SIOCWANDEV, &req)) { if (errno == EINVAL) printf("no protocol set\n"); else printf("unable to get protocol information: " "%s\n", strerror(errno)); break; } switch(req.ifr_settings.type) { case IF_PROTO_FR: printf("protocol fr lmi %s", tabstr(fr->lmi, lmi, "unknown")); if (fr->lmi == LMI_ANSI || fr->lmi == LMI_CCITT) printf("%s t391 %u t392 %u n391 %u n392 %u " "n393 %u\n", fr->dce ? " dce" : "", fr->t391, fr->t392, fr->n391, fr->n392, fr->n393); else putchar('\n'); break; #ifdef IF_PROTO_FR_PVC case IF_PROTO_FR_PVC: printf("Frame-Relay PVC: DLCI %u, master device %s\n", pvc->dlci, pvc->master); break; #endif #ifdef IF_PROTO_FR_ETH_PVC case IF_PROTO_FR_ETH_PVC: printf("Frame-Relay PVC (Ethernet emulation): DLCI %u," " master device %s\n", pvc->dlci, pvc->master); break; #endif case IF_PROTO_HDLC: printf("protocol hdlc %s %s\n", tabstr(raw->encoding, hdlc_enc, "unknown"), tabstr(raw->parity, hdlc_par, "unknown")); break; #ifdef IF_PROTO_HDLC_ETH case IF_PROTO_HDLC_ETH: printf("protocol hdlc-eth %s %s\n", tabstr(raw->encoding, hdlc_enc, "unknown"), tabstr(raw->parity, hdlc_par, "unknown")); break; #endif case IF_PROTO_CISCO: printf("protocol cisco interval %u timeout %u\n", cisco->interval, cisco->timeout); break; case IF_PROTO_PPP: printf("protocol ppp\n"); break; case IF_PROTO_X25: printf("protocol x25\n"); break; default: printf("unknown protocol %u\n", req.ifr_settings.type); } }while(0); close(sock); exit(0); } static void usage(void) { fprintf(stderr, "sethdlc version 1.15\n" "Copyright (C) 2000 - 2003 Krzysztof Halasa \n" "\n" "Usage: sethdlc INTERFACE [PHYSICAL] [clock CLOCK] [LOOPBACK] " "[slotmap SLOTMAP]\n" " sethdlc INTERFACE [PROTOCOL]\n" " sethdlc INTERFACE create | delete" #ifdef IF_PROTO_FR_ETH_PVC " [ether]" #endif " DLCI\n" " sethdlc INTERFACE private...\n" "\n" "PHYSICAL := v24 | v35 | x21 | e1 | t1\n" "CLOCK := int [rate RATE] | ext | txint [rate RATE] | txfromrx\n" "LOOPBACK := loopback | lb\n" "\n" "PROTOCOL := hdlc [ENCODING] [PARITY] |\n" #ifdef IF_PROTO_HDLC_ETH " hdlc-eth [ENCODING] [PARITY] |\n" #endif " cisco [interval val] [timeout val] |\n" " fr [lmi LMI] |\n" " ppp |\n" " x25\n" "\n" "ENCODING := nrz | nrzi | fm-mark | fm-space | manchester\n" "PARITY := no-parity | crc16 | crc16-pr0 | crc16-itu | crc16-itu-pr0 | crc32-itu\n" "LMI := none | ansi [LMI_SPEC] | ccitt [LMI_SPEC]\n" "LMI_SPEC := [dce] [t391 val] [t392 val] [n391 val] [n392 val] [n393 val]\n"); exit(0); } int main(int arg_c, char *arg_v[]) { argc = arg_c; argv = arg_v; if (argc <= 1) usage(); sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); if (sock < 0) error("Unable to create socket: %s\n", strerror(errno)); zap_copy_string(req.ifr_name, argv[1], sizeof(req.ifr_name)); /* Device name */ if (argc == 2) show_port(); argc -= 2; argv += 2; set_iface(); set_proto(); set_pvc(); private(); close(sock); usage(); exit(0); } zaptel-1.4.11/kernel/0002755000000000000000000000000011017303257013054 5ustar rootrootzaptel-1.4.11/kernel/ecdis.h0000644000000000000000000000732510751714440014325 0ustar rootroot/* * 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. * * 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 "biquad.h" 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; #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 > 280) { /* There is adequate energy in the channel. Is it mostly at 2100Hz? */ if (det->notch_level*6 < det->channel_level) { /* 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) { det->good_cycles++; if (det->good_cycles > 2) det->hit = TRUE; } det->tone_cycle_duration = 0; } det->tone_present = TRUE; } else { det->tone_present = FALSE; } det->tone_cycle_duration++; } else { det->tone_present = FALSE; det->tone_cycle_duration = 0; det->good_cycles = 0; } return det->hit; } /*- End of function --------------------------------------------------------*/ /*- End of file ------------------------------------------------------------*/ zaptel-1.4.11/kernel/mg2ec_const.h0000644000000000000000000000577310751714440015446 0ustar rootroot/* Important constants for tuning mg2 echo can */ #ifndef _MG2_CONST_H #define _MG2_CONST_H /* 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 #endif /* _MG2_CONST_H */ zaptel-1.4.11/kernel/wcfxo.c0000644000000000000000000007067010767263450014371 0ustar rootroot/* * Wilcard X100P FXO Interface Driver for Zapata Telephony interface * * Written by Mark Spencer * Matthew Fredrickson * * Copyright (C) 2001, Linux Support Services, 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 #ifdef STANDALONE_ZAPATA #include "zaptel.h" #else #include #endif #ifdef LINUX26 #include #endif /* Uncomment to enable tasklet handling in the FXO driver. Not recommended in general, but may improve interactive performance */ /* #define ENABLE_TASKLETS */ /* Un-comment the following for POTS line support for Japan */ /* #define JAPAN */ /* Un-comment for lines (eg from and ISDN TA) that remove */ /* phone power during ringing */ /* #define ZERO_BATT_RING */ #define WC_MAX_IFACES 128 #define WC_CNTL 0x00 #define WC_OPER 0x01 #define WC_AUXC 0x02 #define WC_AUXD 0x03 #define WC_MASK0 0x04 #define WC_MASK1 0x05 #define WC_INTSTAT 0x06 #define WC_DMAWS 0x08 #define WC_DMAWI 0x0c #define WC_DMAWE 0x10 #define WC_DMARS 0x18 #define WC_DMARI 0x1c #define WC_DMARE 0x20 #define WC_AUXFUNC 0x2b #define WC_SERCTL 0x2d #define WC_FSCDELAY 0x2f /* DAA registers */ #define WC_DAA_CTL1 1 #define WC_DAA_CTL2 2 #define WC_DAA_DCTL1 5 #define WC_DAA_DCTL2 6 #define WC_DAA_PLL1_N1 7 #define WC_DAA_PLL1_M1 8 #define WC_DAA_PLL2_N2_M2 9 #define WC_DAA_PLL_CTL 10 #define WC_DAA_CHIPA_REV 11 #define WC_DAA_LINE_STAT 12 #define WC_DAA_CHIPB_REV 13 #define WC_DAA_DAISY_CTL 14 #define WC_DAA_TXRX_GCTL 15 #define WC_DAA_INT_CTL1 16 #define WC_DAA_INT_CTL2 17 #define WC_DAA_INT_CTL3 18 #define WC_DAA_INT_CTL4 19 #define FLAG_EMPTY 0 #define FLAG_WRITE 1 #define FLAG_READ 2 #ifdef ZERO_BATT_RING /* Need to debounce Off/On hook too */ #define JAPAN #endif #define RING_DEBOUNCE 64 /* Ringer Debounce (in ms) */ #ifdef JAPAN #define BATT_DEBOUNCE 30 /* Battery debounce (in ms) */ #define OH_DEBOUNCE 350 /* Off/On hook debounce (in ms) */ #else #define BATT_DEBOUNCE 80 /* Battery debounce (in ms) */ #endif #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 wcfxo_printk(level, span, fmt, ...) \ printk(KERN_ ## level "%s-%s: %s: " fmt, #level, \ THIS_MODULE->name, (span).name, ## __VA_ARGS__) #define wcfxo_notice(span, fmt, ...) \ wcfxo_printk(NOTICE, span, fmt, ## __VA_ARGS__) #define wcfxo_dbg(span, fmt, ...) \ ((void)((debug) && wcfxo_printk(DEBUG, span, "%s: " fmt, \ __FUNCTION__, ## __VA_ARGS__) ) ) struct reg { unsigned long flags; unsigned char index; unsigned char reg; unsigned char value; }; static int wecareregs[] = { WC_DAA_DCTL1, WC_DAA_DCTL2, WC_DAA_PLL2_N2_M2, WC_DAA_CHIPA_REV, WC_DAA_LINE_STAT, WC_DAA_CHIPB_REV, WC_DAA_INT_CTL2, WC_DAA_INT_CTL4, }; struct wcfxo { struct pci_dev *dev; char *variety; struct zt_span span; struct zt_chan chan; int usecount; int dead; int pos; unsigned long flags; int freeregion; int ring; int offhook; int battery; int wregcount; int readpos; int rreadpos; unsigned int pegtimer; int pegcount; int peg; int battdebounce; int nobatttimer; int ringdebounce; #ifdef JAPAN int ohdebounce; #endif int allread; int regoffset; /* How far off our registers are from what we expect */ int alt; int ignoreread; int reset; /* Up to 6 register can be written at a time */ struct reg regs[ZT_CHUNKSIZE]; struct reg oldregs[ZT_CHUNKSIZE]; unsigned char lasttx[ZT_CHUNKSIZE]; /* Up to 32 registers of whatever we most recently read */ unsigned char readregs[32]; unsigned long ioaddr; dma_addr_t readdma; dma_addr_t writedma; volatile int *writechunk; /* Double-word aligned write memory */ volatile int *readchunk; /* Double-word aligned read memory */ #ifdef ZERO_BATT_RING int onhook; #endif #ifdef ENABLE_TASKLETS int taskletrun; int taskletsched; int taskletpending; int taskletexec; int txerrors; int ints; struct tasklet_struct wcfxo_tlet; #endif }; #define FLAG_INVERTSER (1 << 0) #define FLAG_USE_XTAL (1 << 1) #define FLAG_DOUBLE_CLOCK (1 << 2) #define FLAG_RESET_ON_AUX5 (1 << 3) #define FLAG_NO_I18N_REGS (1 << 4) /*!< Uses si3035, rather si3034 */ struct wcfxo_desc { char *name; unsigned long flags; }; static struct wcfxo_desc wcx100p = { "Wildcard X100P", FLAG_INVERTSER | FLAG_USE_XTAL | FLAG_DOUBLE_CLOCK }; static struct wcfxo_desc wcx101p = { "Wildcard X101P", FLAG_USE_XTAL | FLAG_DOUBLE_CLOCK }; static struct wcfxo_desc generic = { "Generic Clone", FLAG_USE_XTAL | FLAG_DOUBLE_CLOCK }; static struct wcfxo *ifaces[WC_MAX_IFACES]; static void wcfxo_release(struct wcfxo *wc); static int debug = 0; static int monitor = 0; static int quiet = 0; static int boost = 0; static int opermode = 0; static struct fxo_mode { char *name; int ohs; int act; int dct; int rz; int rt; int lim; int vol; } fxo_modes[] = { { "FCC", 0, 0, 2, 0, 0, 0, 0 }, /* US */ { "CTR21", 0, 0, 3, 0, 0, 3, 0 }, /* Austria, Belgium, Denmark, Finland, France, Germany, Greece, Iceland, Ireland, Italy, Luxembourg, Netherlands, Norway, Portugal, Spain, Sweden, Switzerland, and UK */ }; static inline void wcfxo_transmitprep(struct wcfxo *wc, unsigned char ints) { volatile int *writechunk; int x; int written=0; unsigned short cmd; /* if nothing to transmit, have to do the zt_transmit() anyway */ if (!(ints & 3)) { /* Calculate Transmission */ zt_transmit(&wc->span); return; } /* Remember what it was we just sent */ memcpy(wc->lasttx, wc->chan.writechunk, ZT_CHUNKSIZE); if (ints & 0x01) { /* Write is at interrupt address. Start writing from normal offset */ writechunk = wc->writechunk; } else { writechunk = wc->writechunk + ZT_CHUNKSIZE * 2; } zt_transmit(&wc->span); for (x=0;xflags & FLAG_INVERTSER) writechunk[x << 1] = cpu_to_le32( ~((unsigned short)(ZT_XLAW(wc->chan.writechunk[x], (&wc->chan)))| 0x1) << 16 ); else writechunk[x << 1] = cpu_to_le32( ((unsigned short)(ZT_XLAW(wc->chan.writechunk[x], (&wc->chan)))| 0x1) << 16 ); /* We always have a command to follow our signal */ if (!wc->regs[x].flags) { /* Fill in an empty register command with a read for a potentially useful register */ wc->regs[x].flags = FLAG_READ; wc->regs[x].reg = wecareregs[wc->readpos]; wc->regs[x].index = wc->readpos; wc->readpos++; if (wc->readpos >= (sizeof(wecareregs) / sizeof(wecareregs[0]))) { wc->allread = 1; wc->readpos = 0; } } /* Prepare the command to follow it */ switch(wc->regs[x].flags) { case FLAG_READ: cmd = (wc->regs[x].reg | 0x20) << 8; break; case FLAG_WRITE: cmd = (wc->regs[x].reg << 8) | (wc->regs[x].value & 0xff); written = 1; /* Wait at least four samples before reading */ wc->ignoreread = 4; break; default: printk("wcfxo: Huh? No read or write??\n"); cmd = 0; } /* Setup the write chunk */ if (wc->flags & FLAG_INVERTSER) writechunk[(x << 1) + 1] = cpu_to_le32(~(cmd << 16)); else writechunk[(x << 1) + 1] = cpu_to_le32(cmd << 16); } if (written) wc->readpos = 0; wc->wregcount = 0; for (x=0;xoldregs[x] = wc->regs[x]; wc->regs[x].flags = FLAG_EMPTY; } } static inline void wcfxo_receiveprep(struct wcfxo *wc, unsigned char ints) { volatile int *readchunk; int x; int realreg; int realval; int sample; if (ints & 0x04) /* Read is at interrupt address. Valid data is available at normal offset */ readchunk = wc->readchunk; else readchunk = wc->readchunk + ZT_CHUNKSIZE * 2; /* Keep track of how quickly our peg alternates */ wc->pegtimer+=ZT_CHUNKSIZE; for (x=0;xoldregs[x].flags == FLAG_READ && !wc->ignoreread) { realreg = wecareregs[(wc->regs[x].index + wc->regoffset) % (sizeof(wecareregs) / sizeof(wecareregs[0]))]; realval = (le32_to_cpu(readchunk[(x << 1) +wc->alt]) >> 16) & 0xff; if ((realval == 0x89) && (realreg != WC_DAA_PLL2_N2_M2)) { /* Some sort of slippage, correct for it */ while(realreg != WC_DAA_PLL2_N2_M2) { /* Find register 9 */ realreg = wecareregs[(wc->regs[x].index + ++wc->regoffset) % (sizeof(wecareregs) / sizeof(wecareregs[0]))]; wc->regoffset = wc->regoffset % (sizeof(wecareregs) / sizeof(wecareregs[0])); } if (debug) printk("New regoffset: %d\n", wc->regoffset); } /* Receive into the proper register */ wc->readregs[realreg] = realval; } /* Look for pegging to indicate ringing */ sample = (short)(le32_to_cpu(readchunk[(x << 1) + (1 - wc->alt)]) >> 16); if ((sample > 32000) && (wc->peg != 1)) { if ((wc->pegtimer < PEGTIME) && (wc->pegtimer > MINPEGTIME)) wc->pegcount++; wc->pegtimer = 0; wc->peg = 1; } else if ((sample < -32000) && (wc->peg != -1)) { if ((wc->pegtimer < PEGTIME) && (wc->pegtimer > MINPEGTIME)) wc->pegcount++; wc->pegtimer = 0; wc->peg = -1; } wc->chan.readchunk[x] = ZT_LIN2X((sample), (&wc->chan)); } if (wc->pegtimer > PEGTIME) { /* Reset pegcount if our timer expires */ wc->pegcount = 0; } /* Decrement debouncer if appropriate */ if (wc->ringdebounce) wc->ringdebounce--; if (!wc->offhook && !wc->ringdebounce) { if (!wc->ring && (wc->pegcount > PEGCOUNT)) { /* It's ringing */ if (debug) printk("RING!\n"); zt_hooksig(&wc->chan, ZT_RXSIG_RING); wc->ring = 1; } if (wc->ring && !wc->pegcount) { /* No more ring */ if (debug) printk("NO RING!\n"); zt_hooksig(&wc->chan, ZT_RXSIG_OFFHOOK); wc->ring = 0; } } if (wc->ignoreread) wc->ignoreread--; /* Do the echo cancellation... We are echo cancelling against what we sent two chunks ago*/ zt_ec_chunk(&wc->chan, wc->chan.readchunk, wc->lasttx); /* Receive the result */ zt_receive(&wc->span); } #ifdef ENABLE_TASKLETS static void wcfxo_tasklet(unsigned long data) { struct wcfxo *wc = (struct wcfxo *)data; wc->taskletrun++; /* Run tasklet */ if (wc->taskletpending) { wc->taskletexec++; wcfxo_receiveprep(wc, wc->ints); wcfxo_transmitprep(wc, wc->ints); } wc->taskletpending = 0; } #endif static void wcfxo_stop_dma(struct wcfxo *wc); static void wcfxo_restart_dma(struct wcfxo *wc); ZAP_IRQ_HANDLER(wcfxo_interrupt) { struct wcfxo *wc = dev_id; unsigned char ints; unsigned char b; #ifdef DEBUG_RING static int oldb = 0; static int oldcnt = 0; #endif ints = inb(wc->ioaddr + WC_INTSTAT); if (!ints) #ifdef LINUX26 return IRQ_NONE; #else return; #endif outb(ints, wc->ioaddr + WC_INTSTAT); if (ints & 0x0c) { /* if there is a rx interrupt pending */ #ifdef ENABLE_TASKLETS wc->ints = ints; if (!wc->taskletpending) { wc->taskletpending = 1; wc->taskletsched++; tasklet_hi_schedule(&wc->wcfxo_tlet); } else wc->txerrors++; #else wcfxo_receiveprep(wc, ints); /* transmitprep looks to see if there is anything to transmit and returns by itself if there is nothing */ wcfxo_transmitprep(wc, ints); #endif } if (ints & 0x10) { printk("FXO PCI Master abort\n"); /* Stop DMA andlet the watchdog start it again */ wcfxo_stop_dma(wc); #ifdef LINUX26 return IRQ_RETVAL(1); #else return; #endif } if (ints & 0x20) { printk("PCI Target abort\n"); #ifdef LINUX26 return IRQ_RETVAL(1); #else return; #endif } if (1 /* !(wc->report % 0xf) */) { /* Check for BATTERY from register and debounce for 8 ms */ b = wc->readregs[WC_DAA_LINE_STAT] & 0xf; if (!b) { wc->nobatttimer++; #if 0 if (wc->battery) printk("Battery loss: %d (%d debounce)\n", b, wc->battdebounce); #endif if (wc->battery && !wc->battdebounce) { if (debug) printk("NO BATTERY!\n"); wc->battery = 0; #ifdef JAPAN if ((!wc->ohdebounce) && wc->offhook) { zt_hooksig(&wc->chan, ZT_RXSIG_ONHOOK); if (debug) printk("Signalled On Hook\n"); #ifdef ZERO_BATT_RING wc->onhook++; #endif } #else zt_hooksig(&wc->chan, ZT_RXSIG_ONHOOK); #endif wc->battdebounce = BATT_DEBOUNCE; } else if (!wc->battery) wc->battdebounce = BATT_DEBOUNCE; if ((wc->nobatttimer > 5000) && #ifdef ZERO_BATT_RING !(wc->readregs[WC_DAA_DCTL1] & 0x04) && #endif (!wc->span.alarms)) { wc->span.alarms = ZT_ALARM_RED; zt_alarm_notify(&wc->span); } } else if (b == 0xf) { if (!wc->battery && !wc->battdebounce) { if (debug) printk("BATTERY!\n"); #ifdef ZERO_BATT_RING if (wc->onhook) { wc->onhook = 0; zt_hooksig(&wc->chan, ZT_RXSIG_OFFHOOK); if (debug) printk("Signalled Off Hook\n"); } #else zt_hooksig(&wc->chan, ZT_RXSIG_OFFHOOK); #endif wc->battery = 1; wc->nobatttimer = 0; wc->battdebounce = BATT_DEBOUNCE; if (wc->span.alarms) { wc->span.alarms = 0; zt_alarm_notify(&wc->span); } } else if (wc->battery) wc->battdebounce = BATT_DEBOUNCE; } else { /* It's something else... */ wc->battdebounce = BATT_DEBOUNCE; } if (wc->battdebounce) wc->battdebounce--; #ifdef JAPAN if (wc->ohdebounce) wc->ohdebounce--; #endif } #ifdef LINUX26 return IRQ_RETVAL(1); #endif } static int wcfxo_setreg(struct wcfxo *wc, unsigned char reg, unsigned char value) { int x; if (wc->wregcount < ZT_CHUNKSIZE) { x = wc->wregcount; wc->regs[x].reg = reg; wc->regs[x].value = value; wc->regs[x].flags = FLAG_WRITE; wc->wregcount++; return 0; } printk("wcfxo: Out of space to write register %02x with %02x\n", reg, value); return -1; } static int wcfxo_open(struct zt_chan *chan) { struct wcfxo *wc = chan->pvt; if (wc->dead) return -ENODEV; wc->usecount++; #ifndef LINUX26 MOD_INC_USE_COUNT; #endif return 0; } static int wcfxo_watchdog(struct zt_span *span, int event) { printk("FXO: Restarting DMA\n"); wcfxo_restart_dma(span->pvt); return 0; } static int wcfxo_close(struct zt_chan *chan) { struct wcfxo *wc = chan->pvt; wc->usecount--; #ifndef LINUX26 MOD_DEC_USE_COUNT; #endif /* If we're dead, release us now */ if (!wc->usecount && wc->dead) wcfxo_release(wc); return 0; } static int wcfxo_hooksig(struct zt_chan *chan, zt_txsig_t txsig) { struct wcfxo *wc = chan->pvt; int reg=0; switch(txsig) { case ZT_TXSIG_START: case ZT_TXSIG_OFFHOOK: /* Take off hook and enable normal mode reception. This must be done in two steps because of a hardware bug. */ reg = wc->readregs[WC_DAA_DCTL1] & ~0x08; wcfxo_setreg(wc, WC_DAA_DCTL1, reg); reg = reg | 0x1; wcfxo_setreg(wc, WC_DAA_DCTL1, reg); wc->offhook = 1; #ifdef JAPAN wc->battery = 1; wc->battdebounce = BATT_DEBOUNCE; wc->ohdebounce = OH_DEBOUNCE; #endif break; case ZT_TXSIG_ONHOOK: /* Put on hook and enable on hook line monitor */ reg = wc->readregs[WC_DAA_DCTL1] & 0xfe; wcfxo_setreg(wc, WC_DAA_DCTL1, reg); reg = reg | 0x08; wcfxo_setreg(wc, WC_DAA_DCTL1, reg); wc->offhook = 0; /* Don't accept a ring for another 1000 ms */ wc->ringdebounce = 1000; #ifdef JAPAN wc->ohdebounce = OH_DEBOUNCE; #endif break; default: printk("wcfxo: Can't set tx state to %d\n", txsig); } if (debug) printk("Setting hook state to %d (%02x)\n", txsig, reg); return 0; } static int wcfxo_initialize(struct wcfxo *wc) { /* Zapata stuff */ sprintf(wc->span.name, "WCFXO/%d", wc->pos); snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Board %d", wc->variety, wc->pos + 1); sprintf(wc->chan.name, "WCFXO/%d/%d", wc->pos, 0); snprintf(wc->span.location, sizeof(wc->span.location) - 1, "PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1); wc->span.manufacturer = "Digium"; zap_copy_string(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype)); wc->chan.sigcap = ZT_SIG_FXSKS | ZT_SIG_FXSLS | ZT_SIG_SF; wc->chan.chanpos = 1; wc->span.chans = &wc->chan; wc->span.channels = 1; wc->span.hooksig = wcfxo_hooksig; wc->span.irq = wc->dev->irq; wc->span.open = wcfxo_open; wc->span.close = wcfxo_close; wc->span.flags = ZT_FLAG_RBS; wc->span.deflaw = ZT_LAW_MULAW; wc->span.watchdog = wcfxo_watchdog; #ifdef ENABLE_TASKLETS tasklet_init(&wc->wcfxo_tlet, wcfxo_tasklet, (unsigned long)wc); #endif init_waitqueue_head(&wc->span.maintq); wc->span.pvt = wc; wc->chan.pvt = wc; if (zt_register(&wc->span, 0)) { printk("Unable to register span with zaptel\n"); return -1; } return 0; } static int wcfxo_hardware_init(struct wcfxo *wc) { /* Hardware stuff */ /* Reset PCI Interface chip and registers */ outb(0x0e, wc->ioaddr + WC_CNTL); if (wc->flags & FLAG_RESET_ON_AUX5) { /* Set hook state to on hook for when we switch. Make sure reset is high */ outb(0x34, wc->ioaddr + WC_AUXD); } else { /* Set hook state to on hook for when we switch */ outb(0x24, wc->ioaddr + WC_AUXD); } /* Set all to outputs except AUX 4, which is an input */ outb(0xef, wc->ioaddr + WC_AUXC); /* Back to normal, with automatic DMA wrap around */ outb(0x01, wc->ioaddr + WC_CNTL); /* Make sure serial port and DMA are out of reset */ outb(inb(wc->ioaddr + WC_CNTL) & 0xf9, wc->ioaddr + WC_CNTL); /* Configure serial port for MSB->LSB operation */ if (wc->flags & FLAG_DOUBLE_CLOCK) outb(0xc1, wc->ioaddr + WC_SERCTL); else outb(0xc0, wc->ioaddr + WC_SERCTL); if (wc->flags & FLAG_USE_XTAL) { /* Use the crystal oscillator */ outb(0x04, wc->ioaddr + WC_AUXFUNC); } /* Delay FSC by 2 so it's properly aligned */ outb(0x2, wc->ioaddr + WC_FSCDELAY); /* Setup DMA Addresses */ outl(wc->writedma, wc->ioaddr + WC_DMAWS); /* Write start */ outl(wc->writedma + ZT_CHUNKSIZE * 8 - 4, wc->ioaddr + WC_DMAWI); /* Middle (interrupt) */ outl(wc->writedma + ZT_CHUNKSIZE * 16 - 4, wc->ioaddr + WC_DMAWE); /* End */ outl(wc->readdma, wc->ioaddr + WC_DMARS); /* Read start */ outl(wc->readdma + ZT_CHUNKSIZE * 8 - 4, wc->ioaddr + WC_DMARI); /* Middle (interrupt) */ outl(wc->readdma + ZT_CHUNKSIZE * 16 - 4, wc->ioaddr + WC_DMARE); /* End */ /* Clear interrupts */ outb(0xff, wc->ioaddr + WC_INTSTAT); return 0; } static void wcfxo_enable_interrupts(struct wcfxo *wc) { /* Enable interrupts (we care about all of them) */ outb(0x3f, wc->ioaddr + WC_MASK0); /* No external interrupts */ outb(0x00, wc->ioaddr + WC_MASK1); } static void wcfxo_start_dma(struct wcfxo *wc) { /* Reset Master and TDM */ outb(0x0f, wc->ioaddr + WC_CNTL); set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1); outb(0x01, wc->ioaddr + WC_CNTL); outb(0x01, wc->ioaddr + WC_OPER); } static void wcfxo_restart_dma(struct wcfxo *wc) { /* Reset Master and TDM */ outb(0x01, wc->ioaddr + WC_CNTL); outb(0x01, wc->ioaddr + WC_OPER); } static void wcfxo_stop_dma(struct wcfxo *wc) { outb(0x00, wc->ioaddr + WC_OPER); } static void wcfxo_reset_tdm(struct wcfxo *wc) { /* Reset TDM */ outb(0x0f, wc->ioaddr + WC_CNTL); } static void wcfxo_disable_interrupts(struct wcfxo *wc) { outb(0x00, wc->ioaddr + WC_MASK0); outb(0x00, wc->ioaddr + WC_MASK1); } static void wcfxo_set_daa_mode(struct wcfxo *wc) { /* Set country specific parameters (OHS, ACT, DCT, RZ, RT, LIM, VOL) */ int reg16 = ((fxo_modes[opermode].ohs & 0x1) << 6) | ((fxo_modes[opermode].act & 0x1) << 5) | ((fxo_modes[opermode].dct & 0x3) << 2) | ((fxo_modes[opermode].rz & 0x1) << 1) | ((fxo_modes[opermode].rt & 0x1) << 0); int reg17 = ((fxo_modes[opermode].lim & 0x3) << 3); int reg18 = ((fxo_modes[opermode].vol & 0x3) << 3); if (wc->flags & FLAG_NO_I18N_REGS) { wcfxo_dbg(wc->span, "This card does not support international settings.\n"); return; } wcfxo_setreg(wc, WC_DAA_INT_CTL1, reg16); wcfxo_setreg(wc, WC_DAA_INT_CTL2, reg17); wcfxo_setreg(wc, WC_DAA_INT_CTL3, reg18); /* Wait a couple of jiffies for our writes to finish */ set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1 + (ZT_CHUNKSIZE * HZ) / 800); printk("wcfxo: DAA mode is '%s'\n", fxo_modes[opermode].name); } static int wcfxo_init_daa(struct wcfxo *wc) { /* This must not be called in an interrupt */ /* We let things settle for a bit */ unsigned char reg15; int chip_revb; // set_current_state(TASK_INTERRUPTIBLE); // schedule_timeout(10); /* Soft-reset it */ wcfxo_setreg(wc, WC_DAA_CTL1, 0x80); /* Let the reset go */ set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(1 + (ZT_CHUNKSIZE * HZ) / 800); /* We have a clock at 18.432 Mhz, so N1=1, M1=2, CGM=0 */ wcfxo_setreg(wc, WC_DAA_PLL1_N1, 0x0); /* This value is N1 - 1 */ wcfxo_setreg(wc, WC_DAA_PLL1_M1, 0x1); /* This value is M1 - 1 */ /* We want to sample at 8khz, so N2 = 9, M2 = 10 (N2-1, M2-1) */ wcfxo_setreg(wc, WC_DAA_PLL2_N2_M2, 0x89); /* Wait until the PLL's are locked. Time is between 100 uSec and 1 mSec */ set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1 + HZ/1000 + (ZT_CHUNKSIZE * HZ) / 800); /* No additional ration is applied to the PLL and faster lock times * are possible */ wcfxo_setreg(wc, WC_DAA_PLL_CTL, 0x0); /* Enable off hook pin */ wcfxo_setreg(wc, WC_DAA_DCTL1, 0x0a); if (monitor) { /* Enable ISOcap and external speaker and charge pump if present */ wcfxo_setreg(wc, WC_DAA_DCTL2, 0x80); } else { /* Enable ISOcap and charge pump if present (leave speaker disabled) */ wcfxo_setreg(wc, WC_DAA_DCTL2, 0xe0); } /* Wait a couple of jiffies for our writes to finish */ set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1 + (ZT_CHUNKSIZE * HZ) / 800); reg15 = 0x0; /* Go ahead and attenuate transmit signal by 6 db */ if (quiet) { printk("wcfxo: Attenuating transmit signal for quiet operation\n"); reg15 |= (quiet & 0x3) << 4; } if (boost) { printk("wcfxo: Boosting receive signal\n"); reg15 |= (boost & 0x3); } wcfxo_setreg(wc, WC_DAA_TXRX_GCTL, reg15); /* REVB: reg. 13, bits 5:2 */ chip_revb = (wc->readregs[WC_DAA_CHIPB_REV] >> 2) & 0xF; wcfxo_dbg(wc->span, "DAA chip REVB is %x\n", chip_revb); switch(chip_revb) { case 1: case 2: case 3: /* This is a si3034. Nothing to do */ break; case 4: case 5: case 7: /* This is 3035. Has no support for international registers */ wc->flags |= FLAG_NO_I18N_REGS; break; default: wcfxo_notice(wc->span, "Unknown DAA chip revision: REVB=%d\n", chip_revb); } /* Didn't get it right. Register 9 is still garbage */ if (wc->readregs[WC_DAA_PLL2_N2_M2] != 0x89) return -1; #if 0 { int x; int y; for (y=0;y<100;y++) { printk(" reg dump ====== %d ======\n", y); for (x=0;xreadregs[wecareregs[x]]); } set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(100); } } #endif return 0; } static int __devinit wcfxo_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { struct wcfxo *wc; struct wcfxo_desc *d = (struct wcfxo_desc *)ent->driver_data; int x; for (x=0;x= WC_MAX_IFACES) { printk(KERN_ERR "Too many interfaces: Found %d, can only handle %d.\n", x, WC_MAX_IFACES - 1); return -EIO; } if (pci_enable_device(pdev)) return -EIO; wc = kmalloc(sizeof(struct wcfxo), GFP_KERNEL); if (!wc) { printk(KERN_ERR "wcfxo: Failed initializinf card. Not enough memory."); return -ENOMEM; } ifaces[x] = wc; memset(wc, 0, sizeof(struct wcfxo)); wc->ioaddr = pci_resource_start(pdev, 0); wc->dev = pdev; wc->pos = x; wc->variety = d->name; wc->flags = d->flags; /* Keep track of whether we need to free the region */ if (request_region(wc->ioaddr, 0xff, "wcfxo")) wc->freeregion = 1; /* Allocate enough memory for two zt chunks, receive and transmit. Each sample uses 32 bits. Allocate an extra set just for control too */ wc->writechunk = (int *)pci_alloc_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, &wc->writedma); if (!wc->writechunk) { printk("wcfxo: Unable to allocate DMA-able memory\n"); if (wc->freeregion) release_region(wc->ioaddr, 0xff); return -ENOMEM; } wc->readchunk = wc->writechunk + ZT_MAX_CHUNKSIZE * 4; /* in doublewords */ wc->readdma = wc->writedma + ZT_MAX_CHUNKSIZE * 16; /* in bytes */ if (wcfxo_initialize(wc)) { printk("wcfxo: Unable to intialize modem\n"); if (wc->freeregion) release_region(wc->ioaddr, 0xff); kfree(wc); return -EIO; } /* Enable bus mastering */ pci_set_master(pdev); /* Keep track of which device we are */ pci_set_drvdata(pdev, wc); if (request_irq(pdev->irq, wcfxo_interrupt, ZAP_IRQ_SHARED, "wcfxo", wc)) { printk("wcfxo: Unable to request IRQ %d\n", pdev->irq); if (wc->freeregion) release_region(wc->ioaddr, 0xff); kfree(wc); return -EIO; } wcfxo_hardware_init(wc); /* Enable interrupts */ wcfxo_enable_interrupts(wc); /* Initialize Write/Buffers to all blank data */ memset((void *)wc->writechunk,0,ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4); /* Start DMA */ wcfxo_start_dma(wc); /* Initialize DAA (after it's started) */ if (wcfxo_init_daa(wc)) { printk("Failed to initailize DAA, giving up...\n"); wcfxo_stop_dma(wc); wcfxo_disable_interrupts(wc); zt_unregister(&wc->span); free_irq(pdev->irq, wc); /* Reset PCI chip and registers */ outb(0x0e, wc->ioaddr + WC_CNTL); if (wc->freeregion) release_region(wc->ioaddr, 0xff); kfree(wc); return -EIO; } wcfxo_set_daa_mode(wc); printk("Found a Wildcard FXO: %s\n", wc->variety); return 0; } static void wcfxo_release(struct wcfxo *wc) { zt_unregister(&wc->span); if (wc->freeregion) release_region(wc->ioaddr, 0xff); kfree(wc); printk("Freed a Wildcard\n"); } static void __devexit wcfxo_remove_one(struct pci_dev *pdev) { struct wcfxo *wc = pci_get_drvdata(pdev); if (wc) { /* Stop any DMA */ wcfxo_stop_dma(wc); wcfxo_reset_tdm(wc); /* In case hardware is still there */ wcfxo_disable_interrupts(wc); /* Immediately free resources */ pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)wc->writechunk, wc->writedma); free_irq(pdev->irq, wc); /* Reset PCI chip and registers */ outb(0x0e, wc->ioaddr + WC_CNTL); /* Release span, possibly delayed */ if (!wc->usecount) wcfxo_release(wc); else wc->dead = 1; } } static struct pci_device_id wcfxo_pci_tbl[] = { { 0xe159, 0x0001, 0x8084, PCI_ANY_ID, 0, 0, (unsigned long) &generic }, { 0xe159, 0x0001, 0x8085, PCI_ANY_ID, 0, 0, (unsigned long) &wcx101p }, { 0xe159, 0x0001, 0x8086, PCI_ANY_ID, 0, 0, (unsigned long) &generic }, { 0xe159, 0x0001, 0x8087, PCI_ANY_ID, 0, 0, (unsigned long) &generic }, { 0x1057, 0x5608, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wcx100p }, { 0 } }; MODULE_DEVICE_TABLE (pci, wcfxo_pci_tbl); static struct pci_driver wcfxo_driver = { name: "wcfxo", probe: wcfxo_init_one, #ifdef LINUX26 remove: __devexit_p(wcfxo_remove_one), #else remove: wcfxo_remove_one, #endif id_table: wcfxo_pci_tbl, }; static int __init wcfxo_init(void) { int res; int x; if ((opermode >= sizeof(fxo_modes) / sizeof(fxo_modes[0])) || (opermode < 0)) { printk("Invalid/unknown operating mode specified. Please choose one of:\n"); for (x=0;x"); #ifdef MODULE_LICENSE MODULE_LICENSE("GPL"); #endif module_init(wcfxo_init); module_exit(wcfxo_cleanup); zaptel-1.4.11/kernel/Makefile0000644000000000000000000000026610751714440014522 0ustar rootrootifneq ($(KBUILD_EXTMOD),) # 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 endif zaptel-1.4.11/kernel/zttranscode.c0000644000000000000000000002623710756340452015577 0ustar rootroot/* * Transcoder Interface for Zaptel * * Written by Mark Spencer * * Copyright (C) 2006-2007, 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 #include #include #include #include #include #ifdef CONFIG_DEVFS_FS #include #endif #ifdef STANDALONE_ZAPATA #include "zaptel.h" #else #include #endif #ifdef LINUX26 #include #endif static int debug = 0; static struct zt_transcoder *trans; static spinlock_t translock = SPIN_LOCK_UNLOCKED; EXPORT_SYMBOL(zt_transcoder_register); EXPORT_SYMBOL(zt_transcoder_unregister); EXPORT_SYMBOL(zt_transcoder_alert); EXPORT_SYMBOL(zt_transcoder_alloc); EXPORT_SYMBOL(zt_transcoder_free); struct zt_transcoder *zt_transcoder_alloc(int numchans) { struct zt_transcoder *ztc; unsigned int x; size_t size = sizeof(*ztc) + (sizeof(ztc->channels[0]) * numchans); if (!(ztc = kmalloc(size, GFP_KERNEL))) return NULL; memset(ztc, 0, size); strcpy(ztc->name, ""); ztc->numchannels = numchans; for (x=0;xnumchannels;x++) { init_waitqueue_head(&ztc->channels[x].ready); ztc->channels[x].parent = ztc; ztc->channels[x].offset = x; ztc->channels[x].chan_built = 0; ztc->channels[x].built_fmts = 0; } return ztc; } static int schluffen(wait_queue_head_t *q) { DECLARE_WAITQUEUE(wait, current); add_wait_queue(q, &wait); current->state = TASK_INTERRUPTIBLE; if (!signal_pending(current)) schedule(); current->state = TASK_RUNNING; remove_wait_queue(q, &wait); if (signal_pending(current)) return -ERESTARTSYS; return 0; } void zt_transcoder_free(struct zt_transcoder *ztc) { kfree(ztc); } /* Register a transcoder */ int zt_transcoder_register(struct zt_transcoder *tc) { struct zt_transcoder *cur; int res = -EBUSY; spin_lock(&translock); for (cur = trans; cur; cur = cur->next) { if (cur == tc) { spin_unlock(&translock); return res; } } tc->next = trans; trans = tc; printk("Registered codec translator '%s' with %d transcoders (srcs=%08x, dsts=%08x)\n", tc->name, tc->numchannels, tc->srcfmts, tc->dstfmts); res = 0; spin_unlock(&translock); return res; } /* Unregister a transcoder */ int zt_transcoder_unregister(struct zt_transcoder *tc) { struct zt_transcoder *cur, *prev; int res = -EINVAL; spin_lock(&translock); for (cur = trans, prev = NULL; cur; prev = cur, cur = cur->next) { if (cur == tc) break; } if (!cur) { spin_unlock(&translock); return res; } if (prev) prev->next = tc->next; else trans = tc->next; tc->next = NULL; printk("Unregistered codec translator '%s' with %d transcoders (srcs=%08x, dsts=%08x)\n", tc->name, tc->numchannels, tc->srcfmts, tc->dstfmts); res = 0; spin_unlock(&translock); return res; } /* Alert a transcoder */ int zt_transcoder_alert(struct zt_transcoder_channel *ztc) { if (debug) printk("ZT Transcoder Alert!\n"); if (ztc->tch) ztc->tch->status &= ~ZT_TC_FLAG_BUSY; wake_up_interruptible(&ztc->ready); return 0; } static int zt_tc_open(struct inode *inode, struct file *file) { struct zt_transcoder_channel *ztc; struct zt_transcode_header *zth; struct page *page; if (!(ztc = kmalloc(sizeof(*ztc), GFP_KERNEL))) return -ENOMEM; if (!(zth = kmalloc(sizeof(*zth), GFP_KERNEL | GFP_DMA))) { kfree(ztc); return -ENOMEM; } memset(ztc, 0, sizeof(*ztc)); memset(zth, 0, sizeof(*zth)); ztc->flags = ZT_TC_FLAG_TRANSIENT | ZT_TC_FLAG_BUSY; ztc->tch = zth; if (debug) printk("Allocated Transcoder Channel, header is at %p!\n", zth); zth->magic = ZT_TRANSCODE_MAGIC; file->private_data = ztc; for (page = virt_to_page(zth); page < virt_to_page((unsigned long) zth + sizeof(*zth)); page++) SetPageReserved(page); return 0; } static void ztc_release(struct zt_transcoder_channel *ztc) { struct zt_transcode_header *zth = ztc->tch; struct page *page; if (!ztc) return; ztc->flags &= ~(ZT_TC_FLAG_BUSY); if(ztc->tch) { for (page = virt_to_page(zth); page < virt_to_page((unsigned long) zth + sizeof(*zth)); page++) ClearPageReserved(page); kfree(ztc->tch); } ztc->tch = NULL; /* Actually reset the transcoder channel */ if (ztc->flags & ZT_TC_FLAG_TRANSIENT) kfree(ztc); if (debug) printk("Released Transcoder!\n"); } static int zt_tc_release(struct inode *inode, struct file *file) { ztc_release(file->private_data); return 0; } static int do_reset(struct zt_transcoder_channel **ztc) { struct zt_transcoder_channel *newztc = NULL, *origztc = NULL; struct zt_transcode_header *zth = (*ztc)->tch; struct zt_transcoder *tc; unsigned int x; unsigned int match = 0; if (((*ztc)->srcfmt != zth->srcfmt) || ((*ztc)->dstfmt != zth->dstfmt)) { /* Find new transcoder */ spin_lock(&translock); for (tc = trans; tc && !newztc; tc = tc->next) { if (!(tc->srcfmts & zth->srcfmt)) continue; if (!(tc->dstfmts & zth->dstfmt)) continue; match = 1; for (x = 0; x < tc->numchannels; x++) { if (tc->channels[x].flags & ZT_TC_FLAG_BUSY) continue; if ((tc->channels[x].chan_built) && ((zth->srcfmt | zth->dstfmt) != tc->channels[x].built_fmts)) continue; newztc = &tc->channels[x]; newztc->flags = ZT_TC_FLAG_BUSY; break; } } spin_unlock(&translock); if (!newztc) return match ? -EBUSY : -ENOSYS; /* Move transcoder header over */ origztc = (*ztc); (*ztc) = newztc; (*ztc)->tch = origztc->tch; origztc->tch = NULL; (*ztc)->flags |= (origztc->flags & ~(ZT_TC_FLAG_TRANSIENT)); ztc_release(origztc); } /* Actually reset the transcoder channel */ if ((*ztc)->parent && ((*ztc)->parent->operation)) return (*ztc)->parent->operation((*ztc), ZT_TCOP_ALLOCATE); return -EINVAL; } static int wait_busy(struct zt_transcoder_channel *ztc) { int ret; for (;;) { if (!(ztc->tch->status & ZT_TC_FLAG_BUSY)) return 0; if ((ret = schluffen(&ztc->ready))) return ret; } } static int zt_tc_getinfo(unsigned long data) { struct zt_transcode_info info; unsigned int x; struct zt_transcoder *tc; if (copy_from_user(&info, (struct zt_transcode_info *) data, sizeof(info))) return -EFAULT; spin_lock(&translock); for (tc = trans, x = info.tcnum; tc && x; tc = tc->next, x--); spin_unlock(&translock); if (!tc) return -ENOSYS; zap_copy_string(info.name, tc->name, sizeof(info.name)); info.numchannels = tc->numchannels; info.srcfmts = tc->srcfmts; info.dstfmts = tc->dstfmts; return copy_to_user((struct zt_transcode_info *) data, &info, sizeof(info)) ? -EFAULT : 0; } static int zt_tc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long data) { int op; int ret; struct zt_transcoder_channel *ztc = file->private_data; if (cmd != ZT_TRANSCODE_OP) return -ENOSYS; if (get_user(op, (int *) data)) return -EFAULT; if (debug) printk("ZT Transcode ioctl op = %d!\n", op); switch(op) { case ZT_TCOP_GETINFO: ret = zt_tc_getinfo(data); break; case ZT_TCOP_ALLOCATE: /* Reset transcoder, possibly changing who we point to */ ret = do_reset(&ztc); file->private_data = ztc; break; case ZT_TCOP_RELEASE: ret = ztc->parent->operation(ztc, ZT_TCOP_RELEASE); break; case ZT_TCOP_TEST: ret = ztc->parent->operation(ztc, ZT_TCOP_TEST); break; case ZT_TCOP_TRANSCODE: if (!ztc->parent->operation) return -EINVAL; ztc->tch->status |= ZT_TC_FLAG_BUSY; if (!(ret = ztc->parent->operation(ztc, ZT_TCOP_TRANSCODE))) { /* Wait for busy to go away if we're not non-blocking */ if (!(file->f_flags & O_NONBLOCK)) { if (!(ret = wait_busy(ztc))) ret = ztc->errorstatus; } } else ztc->tch->status &= ~ZT_TC_FLAG_BUSY; break; default: ret = -ENOSYS; } return ret; } static int zt_tc_mmap(struct file *file, struct vm_area_struct *vma) { struct zt_transcoder_channel *ztc = file->private_data; unsigned long physical; int res; if (!ztc) return -EINVAL; /* Do not allow an offset */ if (vma->vm_pgoff) { if (debug) printk("zttranscode: Attempted to mmap with offset!\n"); return -EINVAL; } if ((vma->vm_end - vma->vm_start) != sizeof(struct zt_transcode_header)) { if (debug) printk("zttranscode: Attempted to mmap with size %d != %zd!\n", (int) (vma->vm_end - vma->vm_start), sizeof(struct zt_transcode_header)); return -EINVAL; } physical = (unsigned long) virt_to_phys(ztc->tch); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) res = remap_pfn_range(vma, vma->vm_start, physical >> PAGE_SHIFT, sizeof(struct zt_transcode_header), PAGE_SHARED); #else #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) res = remap_page_range(vma->vm_start, physical, sizeof(struct zt_transcode_header), PAGE_SHARED); #else res = remap_page_range(vma, vma->vm_start, physical, sizeof(struct zt_transcode_header), PAGE_SHARED); #endif #endif if (res) { if (debug) printk("zttranscode: remap failed!\n"); return -EAGAIN; } if (debug) printk("zttranscode: successfully mapped transcoder!\n"); return 0; } static unsigned int zt_tc_poll(struct file *file, struct poll_table_struct *wait_table) { struct zt_transcoder_channel *ztc = file->private_data; if (!ztc) return -EINVAL; poll_wait(file, &ztc->ready, wait_table); return ztc->tch->status & ZT_TC_FLAG_BUSY ? 0 : POLLPRI; } static struct file_operations __zt_transcode_fops = { owner: THIS_MODULE, llseek: NULL, open: zt_tc_open, release: zt_tc_release, ioctl: zt_tc_ioctl, read: NULL, write: NULL, poll: zt_tc_poll, mmap: zt_tc_mmap, flush: NULL, fsync: NULL, fasync: NULL, }; static struct zt_chardev transcode_chardev = { .name = "transcode", .minor = 250, }; int zttranscode_init(void) { int res; if (zt_transcode_fops) { printk("Whoa, zt_transcode_fops already set?!\n"); return -EBUSY; } zt_transcode_fops = &__zt_transcode_fops; if ((res = zt_register_chardev(&transcode_chardev))) return res; printk("Zaptel Transcoder support loaded\n"); return 0; } void zttranscode_cleanup(void) { zt_unregister_chardev(&transcode_chardev); zt_transcode_fops = NULL; printk("Zaptel Transcoder support unloaded\n"); } #ifdef LINUX26 module_param(debug, int, S_IRUGO | S_IWUSR); #else MODULE_PARM(debug, "i"); #endif MODULE_DESCRIPTION("Zaptel Transcoder Support"); MODULE_AUTHOR("Mark Spencer "); #ifdef MODULE_LICENSE MODULE_LICENSE("GPL"); #endif module_init(zttranscode_init); module_exit(zttranscode_cleanup); zaptel-1.4.11/kernel/voicebus.c0000644000000000000000000011440310773007372015047 0ustar rootroot/* * VoiceBus(tm) Interface Library. * * Written by Shaun Ruffell * and based on previous work by Mark Spencer , * Matthew Fredrickson , and * Michael Spiceland * * Copyright (C) 2007-2008 Digium, Inc. * * All rights reserved. * * 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. * * VoiceBus is a registered trademark of Digium. * * \todo Make the client drivers back out gracefully when presented with a * signal. * \todo Modify clients to sleep with timeout when waiting for interrupt. * \todo Check on a 64-bit CPU / Kernel */ #include #include #include #include #include #include #include #include "voicebus.h" #define assert(__x__) BUG_ON(!(__x__)) #define INTERRUPT 0 /* Run the deferred processing in the ISR. */ #define TASKLET 1 /* Run in a tasklet. */ #define TIMER 2 /* Run in a system timer. */ #define WORKQUEUE 3 /* Run in a workqueue. */ #ifndef VOICEBUS_DEFERRED #define VOICEBUS_DEFERRED INTERRUPT #endif #if VOICEBUS_DEFERRED == WORKQUEUE #define VOICEBUS_ALLOC_FLAGS GFP_KERNEL #else #define VOICEBUS_ALLOC_FLAGS GFP_ATOMIC #endif #if VOICEBUS_DEFERRED == TIMER #if HZ < 1000 /* \todo Put an error message here. */ #endif #endif /*! The number of descriptors in both the tx and rx descriptor ring. */ #define DRING_SIZE (1 << 5) /* Must be a power of 2 */ #define DRING_MASK (DRING_SIZE-1) /* Interrupt status' reported in SR_CSR5 */ #define TX_COMPLETE_INTERRUPT 0x00000001 #define TX_STOPPED_INTERRUPT 0x00000002 #define TX_UNAVAILABLE_INTERRUPT 0x00000004 #define TX_JABBER_TIMEOUT_INTERRUPT 0x00000008 #define TX_UNDERFLOW_INTERRUPT 0x00000020 #define RX_COMPLETE_INTERRUPT 0x00000040 #define RX_UNAVAILABLE_INTERRUPT 0x00000080 #define RX_STOPPED_INTERRUPT 0x00000100 #define RX_WATCHDOG_TIMEOUT_INTERRUPT 0x00000200 #define TIMER_INTERRUPT 0x00000800 #define FATAL_BUS_ERROR_INTERRUPT 0x00002000 #define ABNORMAL_INTERRUPT_SUMMARY 0x00008000 #define NORMAL_INTERRUPT_SUMMARY 0x00010000 #define SR_CSR5 0x0028 #define NAR_CSR6 0x0030 #define IER_CSR7 0x0038 #define CSR7_TCIE 0x00000001 /* tx complete */ #define CSR7_TPSIE 0x00000002 /* tx processor stopped */ #define CSR7_TDUIE 0x00000004 /* tx desc unavailable */ #define CSR7_TUIE 0x00000020 /* tx underflow */ #define CSR7_RCIE 0x00000040 /* rx complete */ #define CSR7_RUIE 0x00000080 /* rx desc unavailable */ #define CSR7_RSIE 0x00000100 /* rx processor stopped */ #define CSR7_FBEIE 0x00002000 /* fatal bus error */ #define CSR7_AIE 0x00008000 /* abnormal enable */ #define CSR7_NIE 0x00010000 /* normal enable */ #define DEFAULT_INTERRUPTS ( CSR7_TCIE | CSR7_TPSIE | CSR7_TDUIE | \ CSR7_RUIE | CSR7_RSIE | CSR7_FBEIE | \ CSR7_AIE | CSR7_NIE) #define CSR9 0x0048 #define CSR9_MDC 0x00010000 #define CSR9_MDO 0x00020000 #define CSR9_MMC 0x00040000 #define CSR9_MDI 0x00080000 #define OWN_BIT (1 << 31) /* In memory structure shared by the host and the adapter. */ struct voicebus_descriptor { u32 des0; u32 des1; u32 buffer1; u32 container; /* Unused */ } __attribute__((packed)); struct voicebus_descriptor_list { /* Pointer to an array of descriptors to give to hardware. */ struct voicebus_descriptor* desc; /* Read completed buffers from the head. */ unsigned int head; /* Write ready buffers to the tail. */ unsigned int tail; /* Array to save the kernel virtual address of pending buffers. */ void * pending[DRING_SIZE]; /* PCI Bus address of the descriptor list. */ dma_addr_t desc_dma; /*! either DMA_FROM_DEVICE or DMA_TO_DEVICE */ unsigned int direction; /*! The number of buffers currently submitted to the hardware. */ atomic_t count; /*! The number of bytes to pad each descriptor for cache alignment. */ unsigned int padding; }; /*! * \brief Represents a VoiceBus interface on a Digium telephony card. */ struct voicebus { /*! Name of this card. */ const char *board_name; /*! The system pci device for this VoiceBus interface. */ struct pci_dev *pdev; /*! Protects access to card registers and this structure. You should * hold this lock before accessing most of the members of this data * structure or the card registers. */ spinlock_t lock; /*! The size of the transmit and receive buffers for this card. */ u32 framesize; /*! The number of u32s in the host system cache line. */ u8 cache_line_size; /*! Pool to allocate memory for the tx and rx descriptor rings. */ struct voicebus_descriptor_list rxd; struct voicebus_descriptor_list txd; /*! Level of debugging information. 0=None, 5=Insane. */ atomic_t debuglevel; /*! Cache of buffer objects. */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) kmem_cache_t *buffer_cache; #else struct kmem_cache *buffer_cache; #endif /*! Base address of the VoiceBus interface registers in I/O space. */ u32 iobase; /*! The IRQ line for this VoiceBus interface. */ unsigned int irq; #if VOICEBUS_DEFERRED == WORKQUEUE /*! Process buffers in the context of this workqueue. */ struct workqueue_struct *workqueue; /*! Work item to process tx / rx buffers. */ struct work_struct workitem; #elif VOICEBUS_DEFERRED == TASKLET /*! Process buffers in the context of a tasklet. */ struct tasklet_struct tasklet; #elif VOICEBUS_DEFERRED == TIMER /*! Process buffers in a timer without generating interrupts. */ struct timer_list timer; #endif /*! Callback function to board specific module to process frames. */ void (*handle_receive)(void *vbb, void *context); void (*handle_transmit)(void *vbb, void *context); /*! Data to pass to the receive and transmit callback. */ void *context; struct completion stopped_completion; /*! Flags */ unsigned long flags; /* \todo see about removing this... */ u32 sdi; /*! Number of tx buffers to queue up before enabling interrupts. */ unsigned int min_tx_buffer_count; }; /* * Use the following macros to lock the VoiceBus interface, and it won't * matter if the deferred processing is running inside the interrupt handler, * in a tasklet, or in a workqueue. */ #if VOICEBUS_DEFERRED == WORKQUEUE /* * When the deferred processing is running in a workqueue, voicebus will never * be locked from the context of the interrupt handler, and therefore we do * not need to lock interrupts. */ #define LOCKS_VOICEBUS #define LOCKS_FROM_DEFERRED #define VBLOCK(_vb_) spin_lock(&((_vb_)->lock)) #define VBUNLOCK(_vb_) spin_unlock(&((_vb_)->lock)) #define VBLOCK_FROM_DEFERRED(_vb_) spin_lock(&((_vb_)->lock)) #define VBUNLOCK_FROM_DEFERRED(_vb_) spin_lock(&((_vb_)->lock)) #else #define LOCKS_VOICEBUS unsigned long _irqflags #define LOCKS_FROM_DEFERRED #define VBLOCK(_vb_) spin_lock_irqsave(&((_vb_)->lock), _irqflags) #define VBUNLOCK(_vb_) spin_unlock_irqrestore(&((_vb_)->lock), _irqflags) #define VBLOCK_FROM_DEFERRED(_vb_) spin_lock(&((_vb_)->lock)) #define VBUNLOCK_FROM_DEFERRED(_vb_) spin_lock(&((_vb_)->lock)) #endif #define VB_PRINTK(_vb, _lvl, _fmt, _args...) \ printk(KERN_##_lvl "%s: " _fmt, (_vb)->board_name, ## _args) /* Bit definitions for struct voicebus.flags */ #define TX_UNDERRUN 1 #define RX_UNDERRUN 2 #define IN_DEFERRED_PROCESSING 3 #define STOP 4 #if VOICEBUS_DEFERRED == WORKQUEUE #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) /*! \brief Make the current task real-time. */ static void vb_setup_deferred(void *data) #else static void vb_setup_deferred(struct work_struct *work) #endif { struct sched_param param = { .sched_priority = 99 }; sched_setscheduler(current, SCHED_FIFO, ¶m); } /*! \brief Schedule a work item to make the voicebus workqueue real-time. */ static void vb_set_workqueue_priority(struct voicebus *vb) { #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) DECLARE_WORK(deferred_setup, vb_setup_deferred, NULL); #else DECLARE_WORK(deferred_setup, vb_setup_deferred); #endif queue_work(vb->workqueue, &deferred_setup); flush_workqueue(vb->workqueue); } #endif #endif #ifdef DBG static inline int assert_in_vb_deferred(struct voicebus *vb) { assert(test_bit(IN_DEFERRED_PROCESSING, &vb->flags)); } static inline void start_vb_deferred(struct voicebus *vb) { set_bit(IN_DEFERRED_PROCESSING, &vb->flags); } static inline void stop_vb_deferred(struct voicebus *vb) { clear_bit(IN_DEFERRED_PROCESSING, &vb->flags); } #else #define assert_in_vb_deferred(_x_) do {;} while(0) #define start_vb_deferred(_x_) do {;} while(0) #define stop_vb_deferred(_x_) do {;} while(0) #endif static inline struct voicebus_descriptor * vb_descriptor(struct voicebus_descriptor_list *dl, int index) { struct voicebus_descriptor *d; d = (struct voicebus_descriptor *)((u8*)dl->desc + ((sizeof(*d) + dl->padding) * index)); return d; } static int vb_initialize_descriptors(struct voicebus *vb, struct voicebus_descriptor_list *dl, u32 des1, unsigned int direction) { int i; struct voicebus_descriptor *d; const u32 END_OF_RING = 0x02000000; assert(dl); /* * Add some padding to each descriptor to ensure that they are * aligned on host system cache-line boundaries, but only for the * cache-line sizes that we support. * */ if ((0x08 == vb->cache_line_size) || (0x10 == vb->cache_line_size) || (0x20 == vb->cache_line_size)) { dl->padding = (vb->cache_line_size*sizeof(u32)) - sizeof(*d); } else { dl->padding = 0; } dl->desc = pci_alloc_consistent(vb->pdev, (sizeof(*d) + dl->padding) * DRING_SIZE, &dl->desc_dma); if (!dl->desc) { return -ENOMEM; } memset(dl->desc, 0, (sizeof(*d) + dl->padding) * DRING_SIZE); for ( i = 0; i < DRING_SIZE; ++i) { d = vb_descriptor(dl, i); d->des1 = des1; } d->des1 |= cpu_to_le32(END_OF_RING); dl->direction = direction; atomic_set(&dl->count, 0); return 0; } static int vb_initialize_tx_descriptors(struct voicebus *vb) { return vb_initialize_descriptors( vb, &vb->txd, 0xe4800000 | vb->framesize, DMA_TO_DEVICE); } static int vb_initialize_rx_descriptors(struct voicebus *vb) { return vb_initialize_descriptors( vb, &vb->rxd, vb->framesize, DMA_FROM_DEVICE); } /*! \brief Use to set the minimum number of buffers queued to the hardware * before enabling interrupts. */ int voicebus_set_minlatency(struct voicebus *vb, unsigned int ms) { LOCKS_VOICEBUS; /* * One millisecond of latency means that we have 3 buffers pending, * since two are always going to be waiting in the TX fifo on the * interface chip. * */ #define MESSAGE "%d ms is an invalid value for minumum latency. Setting to %d ms.\n" if ( DRING_SIZE < ms ) { VB_PRINTK(vb, WARNING, MESSAGE, ms, DRING_SIZE); return -EINVAL; } else if (VOICEBUS_DEFAULT_LATENCY > ms ) { VB_PRINTK(vb, WARNING, MESSAGE, ms, VOICEBUS_DEFAULT_LATENCY); return -EINVAL; } VBLOCK(vb); vb->min_tx_buffer_count = ms; VBUNLOCK(vb); return 0; } /*! \brief Returns the number of buffers currently on the transmit queue. */ int voicebus_current_latency(struct voicebus *vb) { LOCKS_VOICEBUS; int latency; VBLOCK(vb); latency = vb->min_tx_buffer_count; VBUNLOCK(vb); return latency; } /*! * \brief Read one of the hardware control registers without acquiring locks. */ static inline u32 __vb_getctl(struct voicebus *vb, u32 addr) { return le32_to_cpu(inl(vb->iobase + addr)); } /*! * \brief Read one of the hardware control registers with locks held. */ static inline u32 vb_getctl(struct voicebus *vb, u32 addr) { LOCKS_VOICEBUS; u32 val; VBLOCK(vb); val = __vb_getctl(vb, addr); VBUNLOCK(vb); return val; } /*! * \brief Returns whether or not the interface is running. * * NOTE: Running in this case means whether or not the hardware reports the * transmit processor in any state but stopped. * * \return 1 of the process is stopped, 0 if running. */ static int vb_is_stopped(struct voicebus *vb) { u32 reg; reg = vb_getctl(vb, SR_CSR5); reg = (reg >> 17)&0x38; return (0 == reg) ? 1 : 0; } static void vb_cleanup_descriptors(struct voicebus *vb, struct voicebus_descriptor_list *dl) { unsigned int i; struct voicebus_descriptor *d; assert(vb_is_stopped(vb)); for (i=0; i < DRING_SIZE; ++i) { d = vb_descriptor(dl, i); if (d->buffer1) { d->buffer1 = 0; assert(dl->pending[i]); voicebus_free(vb, dl->pending[i]); dl->pending[i] = NULL; } d->des0 &= ~OWN_BIT; } dl->head = 0; dl->tail = 0; atomic_set(&dl->count, 0); } static void vb_free_descriptors(struct voicebus *vb, struct voicebus_descriptor_list *dl) { if (NULL == dl->desc) { WARN_ON(1); return; } vb_cleanup_descriptors(vb, dl); pci_free_consistent( vb->pdev, (sizeof(struct voicebus_descriptor)+dl->padding)*DRING_SIZE, dl->desc, dl->desc_dma); } /*! * \brief Write one of the hardware control registers without acquiring locks. */ static inline void __vb_setctl(struct voicebus *vb, u32 addr, u32 val) { wmb(); outl(cpu_to_le32(val), vb->iobase + addr); } /*! * \brief Write one of the hardware control registers with locks held. */ static inline void vb_setctl(struct voicebus *vb, u32 addr, u32 val) { LOCKS_VOICEBUS; VBLOCK(vb); __vb_setctl(vb, addr, val); VBUNLOCK(vb); } static int __vb_sdi_clk(struct voicebus* vb) { unsigned int ret; vb->sdi &= ~CSR9_MDC; __vb_setctl(vb, 0x0048, vb->sdi); ret = __vb_getctl(vb, 0x0048); vb->sdi |= CSR9_MDC; __vb_setctl(vb, 0x0048, vb->sdi); return (ret & CSR9_MDI) ? 1: 0; } static void __vb_sdi_sendbits(struct voicebus *vb, u32 bits, int count) { vb->sdi &= ~CSR9_MMC; __vb_setctl(vb, 0x0048, vb->sdi); while(count--) { if (bits & (1 << count)) { vb->sdi |= CSR9_MDO; } else { vb->sdi &= ~CSR9_MDO; } __vb_sdi_clk(vb); } } #if 0 /* this function might be useful in the future for debugging. */ static unsigned int __vb_sdi_recvbits(struct voicebus *vb, int count) { unsigned int bits=0; vb->sdi |= CSR9_MMC; __vb_setctl(vb, 0x0048, vb->sdi); while(count--) { bits <<= 1; if (__vb_sdi_clk(vb)) bits |= 1; else bits &= ~1; } return bits; } #endif static void vb_setsdi(struct voicebus *vb, int addr, u16 val) { LOCKS_VOICEBUS; u32 bits; /* Send preamble */ bits = 0xffffffff; VBLOCK(vb); __vb_sdi_sendbits(vb, bits, 32); bits = (0x5 << 12) | (1 << 7) | (addr << 2) | 0x2; __vb_sdi_sendbits(vb, bits, 16); __vb_sdi_sendbits(vb, val, 16); VBUNLOCK(vb); } static void vb_enable_io_access(struct voicebus *vb) { LOCKS_VOICEBUS; u32 reg; assert(vb->pdev); VBLOCK(vb); pci_read_config_dword(vb->pdev, 0x0004, ®); reg |= 0x00000007; pci_write_config_dword(vb->pdev, 0x0004, reg); VBUNLOCK(vb); } /*! \todo Insert comments... * context: !in_interrupt() */ void* voicebus_alloc(struct voicebus *vb) { void *vbb; vbb = kmem_cache_alloc(vb->buffer_cache, VOICEBUS_ALLOC_FLAGS); return vbb; } void voicebus_setdebuglevel(struct voicebus *vb, u32 level) { atomic_set(&vb->debuglevel, level); } int voicebus_getdebuglevel(struct voicebus *vb) { return atomic_read(&vb->debuglevel); } /*! \brief Resets the voicebus hardware interface. */ static int vb_reset_interface(struct voicebus *vb) { unsigned long timeout; u32 reg; u32 pci_access; const u32 DEFAULT_PCI_ACCESS = 0xfff80002; BUG_ON(in_interrupt()); switch (vb->cache_line_size) { case 0x08: pci_access = DEFAULT_PCI_ACCESS | (0x1 << 14); break; case 0x10: pci_access = DEFAULT_PCI_ACCESS | (0x2 << 14); break; case 0x20: pci_access = DEFAULT_PCI_ACCESS | (0x3 << 14); break; default: VB_PRINTK(vb, WARNING, "Host system set a cache size "\ "of %d which is not supported. " \ "Disabling memory write line and memory read line.", vb->cache_line_size); pci_access = 0xfe584202; break; } /* The transmit and receive descriptors will have the same padding. */ pci_access |= ((vb->txd.padding / sizeof(u32)) << 2) & 0x7c; vb_setctl(vb, 0x0000, pci_access | 1); timeout = jiffies + HZ/10; /* 100ms interval */ do { reg = vb_getctl(vb, 0x0000); } while ((reg & 0x00000001) && time_before(jiffies, timeout)); if (reg & 0x00000001) { VB_PRINTK(vb, ERR, "Hardware did not come out of reset "\ "within 100ms!"); return -EIO; } vb_setctl(vb, 0x0000, pci_access); vb_cleanup_descriptors(vb, &vb->txd); vb_cleanup_descriptors(vb, &vb->rxd); /* Pass bad packets, runt packets, disable SQE function, * store-and-forward */ vb_setctl(vb, 0x0030, 0x00280048); /* ...disable jabber and the receive watchdog. */ vb_setctl(vb, 0x0078, 0x00000013); /* Tell the card where the descriptors are in host memory. */ vb_setctl(vb, 0x0020, (u32)vb->txd.desc_dma); vb_setctl(vb, 0x0018, (u32)vb->rxd.desc_dma); reg = vb_getctl(vb, 0x00fc); vb_setctl(vb, 0x00fc, (reg & ~0x7) | 0x7); vb_setsdi(vb, 0x00, 0x0100); vb_setsdi(vb, 0x16, 0x2100); reg = vb_getctl(vb, 0x00fc); vb_setctl(vb, 0x00fc, (reg & ~0x7) | 0x4); vb_setsdi(vb, 0x00, 0x0100); vb_setsdi(vb, 0x16, 0x2100); reg = vb_getctl(vb, 0x00fc); /* * The calls to setsdi above toggle the reset line of the CPLD. Wait * here to give the CPLD time to stabilize after reset. */ mdelay(1); return ((reg&0x7) == 0x4) ? 0 : -EIO; } #define OWNED(_d_) (((_d_)->des0)&OWN_BIT) #define SET_OWNED(_d_) do { wmb(); (_d_)->des0 |= OWN_BIT; wmb();} while (0) #ifdef DBG static void dump_descriptor(struct voicebus *vb, volatile struct voicebus_descriptor *d) { VB_PRINTK(vb, DEBUG, "Displaying descriptor at address %08x\n", (unsigned int)d); VB_PRINTK(vb, DEBUG, " des0: %08x\n", d->des0); VB_PRINTK(vb, DEBUG, " des1: %08x\n", d->des1); VB_PRINTK(vb, DEBUG, " buffer1: %08x\n", d->buffer1); VB_PRINTK(vb, DEBUG, " container: %08x\n", d->container); } static void show_buffer(struct voicebus *vb, void *vbb) { int x; unsigned char *c; c = vbb; printk("Packet %d\n", count); for (x = 1; x <= vb->framesize; ++x) { printk("%02x ", c[x]); if (x % 16 == 0) { printk("\n"); } } printk("\n\n"); } #endif static inline int vb_submit(struct voicebus *vb, struct voicebus_descriptor_list *dl, void *vbb) { volatile struct voicebus_descriptor *d; unsigned int tail = dl->tail; assert_in_vb_deferred(vb); d = vb_descriptor(dl, tail); if (unlikely(d->buffer1)) { /* Do not overwrite a buffer that is still in progress. */ WARN_ON(1); voicebus_free(vb, vbb); return -EBUSY; } dl->pending[tail] = vbb; dl->tail = (++tail) & DRING_MASK; d->buffer1 = dma_map_single( &vb->pdev->dev, vbb, vb->framesize, dl->direction); SET_OWNED(d); /* That's it until the hardware is done with it. */ atomic_inc(&dl->count); return 0; } static inline void* vb_retrieve(struct voicebus *vb, struct voicebus_descriptor_list *dl) { volatile struct voicebus_descriptor *d; void *vbb; unsigned int head = dl->head; assert_in_vb_deferred(vb); d = vb_descriptor(dl, head); if (!OWNED(d)) { dma_unmap_single(&vb->pdev->dev, d->buffer1, vb->framesize, dl->direction); vbb = dl->pending[head]; dl->head = (++head) & DRING_MASK; d->buffer1 = 0; atomic_dec(&dl->count); return vbb; } else { return NULL; } } /*! * \brief Give a frame to the hardware to transmit. * */ int voicebus_transmit(struct voicebus *vb, void *vbb) { return vb_submit(vb, &vb->txd, vbb); } /*! * \brief Give a frame to the hardware to use for receiving. * */ static inline int vb_submit_rxb(struct voicebus *vb, void *vbb) { return vb_submit(vb, &vb->rxd, vbb); } /*! * \brief Remove the next completed transmit buffer (txb) from the tx * descriptor ring. * * NOTE: This function doesn't need any locking because only one instance is * ever running on the deferred processing routine and it only looks at * the head pointer. The deferred routine should only ever be running * on one processor at a time (no multithreaded workqueues allowed!) * * Context: Must be called from the voicebus deferred workqueue. * * \return Pointer to buffer, or NULL if not available. */ static inline void * vb_get_completed_txb(struct voicebus *vb) { return vb_retrieve(vb, &vb->txd); } static inline void * vb_get_completed_rxb(struct voicebus *vb) { return vb_retrieve(vb, &vb->rxd); } /*! * \brief Free a buffer for reuse. * */ void voicebus_free(struct voicebus *vb, void *vbb) { kmem_cache_free(vb->buffer_cache, vbb); } /*! * \brief Instruct the hardware to check for a new tx descriptor. */ inline static void __vb_tx_demand_poll(struct voicebus *vb) { __vb_setctl(vb, 0x0008, 0x00000000); } /*! * \brief Command the hardware to check if it owns the next transmit * descriptor. */ static void vb_tx_demand_poll(struct voicebus *vb) { LOCKS_VOICEBUS; VBLOCK(vb); __vb_tx_demand_poll(vb); VBUNLOCK(vb); } /*! * \brief Command the hardware to check if it owns the next receive * descriptor. */ inline static void __vb_rx_demand_poll(struct voicebus *vb) { __vb_setctl(vb, 0x0010, 0x00000000); } static void vb_rx_demand_poll(struct voicebus *vb) { LOCKS_VOICEBUS; VBLOCK(vb); __vb_rx_demand_poll(vb); VBUNLOCK(vb); } static void __vb_enable_interrupts(struct voicebus *vb) { __vb_setctl(vb, IER_CSR7, DEFAULT_INTERRUPTS); } static void __vb_disable_interrupts(struct voicebus *vb) { __vb_setctl(vb, IER_CSR7, 0); } static void vb_disable_interrupts(struct voicebus *vb) { LOCKS_VOICEBUS; VBLOCK(vb); __vb_disable_interrupts(vb); VBUNLOCK(vb); } /*! * \brief Starts the VoiceBus interface. * * When the VoiceBus interface is started, it is actively transferring * frames to and from the backend of the card. This means the card will * generate interrupts. * * This function should only be called from process context, with interrupts * enabled, since it can sleep while running the self checks. * * \return zero on success. -EBUSY if device is already running. */ int voicebus_start(struct voicebus *vb) { LOCKS_VOICEBUS; u32 reg; int i; void *vbb; int ret; assert(!in_interrupt()); if (!vb_is_stopped(vb)) { return -EBUSY; } if ((ret=vb_reset_interface(vb))) { return ret; } /* We must set up a minimum of three buffers to start with, since two * are immediately read into the TX FIFO, and the descriptor of the * third is read as soon as the first buffer is done. */ /* * NOTE: The very first buffer after coming out of reset is used to * prime the pump and is lost. So we do not want the client driver to * prepare it, since it will never see the corresponding receive * buffer. * NOTE: handle_transmit is normally only called in the context of the * deferred processing thread. Since the deferred processing thread * is known to not be running at this point, it is safe to call the * handle transmit as if it were. */ start_vb_deferred(vb); /* Ensure that all the rx slots are ready for a buffer. */ for ( i = 0; i < DRING_SIZE; ++i) { vbb = voicebus_alloc(vb); if (unlikely(NULL == vbb)) { BUG_ON(1); /* \todo I need to make sure the driver can recover * from this condition. .... */ } else { vb_submit_rxb(vb, vbb); } } for ( i=0; i < vb->min_tx_buffer_count; ++i) { vbb = voicebus_alloc(vb); if (unlikely(NULL == vbb)) { BUG_ON(1); } else { vb->handle_transmit(vbb, vb->context); } } stop_vb_deferred(vb); VBLOCK(vb); clear_bit(STOP, &vb->flags); #if VOICEBUS_DEFERRED == TIMER vb->timer.expires = jiffies + HZ/1000; add_timer(&vb->timer); #else /* Clear the interrupt status register. */ __vb_setctl(vb, SR_CSR5, 0xffffffff); __vb_enable_interrupts(vb); #endif /* Start the transmit and receive processors. */ reg = __vb_getctl(vb, 0x0030); __vb_setctl(vb, 0x0030, reg|0x00002002); /* Tell the interface to poll the tx and rx descriptors. */ __vb_rx_demand_poll(vb); __vb_tx_demand_poll(vb); VBUNLOCK(vb); assert(!vb_is_stopped(vb)); return 0; } static void vb_clear_start_transmit_bit(struct voicebus *vb) { LOCKS_VOICEBUS; u32 reg; VBLOCK(vb); reg = __vb_getctl(vb, NAR_CSR6); reg &= ~0x00002000; __vb_setctl(vb, NAR_CSR6, reg); VBUNLOCK(vb); } static void vb_clear_start_receive_bit(struct voicebus *vb) { LOCKS_VOICEBUS; u32 reg; VBLOCK(vb); reg = __vb_getctl(vb, NAR_CSR6); reg &= ~0x00000002; __vb_setctl(vb, NAR_CSR6, reg); VBUNLOCK(vb); } unsigned long vb_wait_for_completion_timeout(struct completion *x, unsigned long timeout) { #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) /* There is a race condition here. If x->done is reset to 0 * before the call to wait_for_completion after this thread wakes. */ timeout = wait_event_timeout(x->wait, x->done, timeout); if (timeout) { wait_for_completion(x); } return timeout; #else return wait_for_completion_timeout(x, timeout); #endif } /*! * \brief Stops the VoiceBus interface. * * Stops the VoiceBus interface and waits for any outstanding DMA transactions * to complete. When this functions returns the VoiceBus interface tx and rx * states will both be suspended. * * Only call this function from process context, with interrupt enabled, * without any locks held since it sleeps. * * \return zero on success, -1 on error. */ int voicebus_stop(struct voicebus *vb) { assert(!in_interrupt()); if (vb_is_stopped(vb)) { return 0; } INIT_COMPLETION(vb->stopped_completion); set_bit(STOP, &vb->flags); vb_clear_start_transmit_bit(vb); if (vb_wait_for_completion_timeout(&vb->stopped_completion, HZ)) { #if VOICEBUS_DEFERRED == TIMER del_timer_sync(&vb->timer); #else vb_disable_interrupts(vb); #endif assert(vb_is_stopped(vb)); clear_bit(STOP, &vb->flags); } else { VB_PRINTK(vb, WARNING, "Timeout while waiting for board to "\ "stop.\n"); } return 0; } /*! * \brief Prepare the interface for module unload. * * Stop the interface and free all the resources allocated by the driver. The * caller should have returned all VoiceBus buffers to the VoiceBus layer * before calling this function. * * context: !in_interrupt() */ void voicebus_release(struct voicebus *vb) { assert(!in_interrupt()); /* quiesce the hardware */ voicebus_stop(vb); #if VOICEBUS_DEFERRED == WORKQUEUE destroy_workqueue(vb->workqueue); #elif VOICEBUS_DEFERRED == TASKLET tasklet_kill(&vb->tasklet); #endif vb_reset_interface(vb); #if VOICEBUS_DEFERRED != TIMER free_irq(vb->pdev->irq, vb); #endif /* Cleanup memory and software resources. */ vb_free_descriptors(vb, &vb->txd); vb_free_descriptors(vb, &vb->rxd); kmem_cache_destroy(vb->buffer_cache); release_region(vb->iobase, 0xff); pci_disable_device(vb->pdev); kfree(vb); } void __vb_increase_latency(struct voicebus *vb) { static int __warn_once = 1; void *vbb; int latency; assert_in_vb_deferred(vb); latency = atomic_read(&vb->txd.count); if (DRING_SIZE == latency) { if (__warn_once) { /* We must subtract two from this number since there * are always two buffers in the TX FIFO. */ VB_PRINTK(vb,ERR, "ERROR: Unable to service card within %d ms "\ "and unable to further increase latency.\n", DRING_SIZE-2); __warn_once = 0; } } else { /* Because there are 2 buffers in the transmit FIFO on the * hardware, setting 3 ms of latency means that the host needs * to be able to service the cards within 1ms. This is because * the interface will load up 2 buffers into the TX FIFO then * attempt to read the 3rd descriptor. If the OWN bit isn't * set, then the hardware will set the TX descriptor not * available interrupt. */ VB_PRINTK(vb, INFO, "Missed interrupt. " \ "Increasing latency to %d ms in order to compensate.\n", latency+1); /* Set the minimum latency in case we're restarted...we don't * want to wait for the buffer to grow to this depth again in * that case. */ voicebus_set_minlatency(vb, latency+1); vbb = voicebus_alloc(vb); if (unlikely(NULL == vbb)) { BUG_ON(1); } else { vb->handle_transmit(vbb, vb->context); } } } /*! * \brief Actually process the completed transmit and receive buffers. * * NOTE: This function may be called either from a tasklet, workqueue, or * directly in the interrupt service routine depending on * VOICEBUS_DEFERRED. */ static inline void vb_deferred(struct voicebus *vb) { void *vbb; #ifdef DBG static int count = 0; #endif int stopping = test_bit(STOP, &vb->flags); int underrun = test_bit(TX_UNDERRUN, &vb->flags); start_vb_deferred(vb); if (unlikely(stopping)) { while((vbb = vb_get_completed_txb(vb))) { voicebus_free(vb, vbb); } while((vbb = vb_get_completed_rxb(vb))) { voicebus_free(vb, vbb); } stop_vb_deferred(vb); return; } if (unlikely(underrun)) { /* When we've underrun our FIFO, for some reason we're not * able to keep enough transmit descriptors pending. This can * happen if either interrupts or this deferred processing * function is not run soon enough (within 1ms when using the * default 3 transmit buffers to start). In this case, we'll * insert an additional transmit buffer onto the descriptor * list which decreases the sensitivity to latency, but also * adds more delay to the TDM and SPI data. */ __vb_increase_latency(vb); } /* Always handle the transmit buffers first. */ while ((vbb = vb_get_completed_txb(vb))) { vb->handle_transmit(vbb, vb->context); } if (unlikely(underrun)) { vb_rx_demand_poll(vb); vb_tx_demand_poll(vb); clear_bit(TX_UNDERRUN, &vb->flags); } while ((vbb = vb_get_completed_rxb(vb))) { vb->handle_receive(vbb, vb->context); vb_submit_rxb(vb, vbb); } stop_vb_deferred(vb); } /*! * \brief Interrupt handler for VoiceBus interface. * * NOTE: This handler is optimized for the case where only a single interrupt * condition will be generated at a time. * * ALSO NOTE: Only access the interrupt status register from this function * since it doesn't employ any locking on the voicebus interface. */ static irqreturn_t #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) vb_isr(int irq, void *dev_id, struct pt_regs *regs) #else vb_isr(int irq, void *dev_id) #endif { struct voicebus *vb = dev_id; u32 int_status; int_status = __vb_getctl(vb, SR_CSR5); /* Mask out the reserved bits. */ int_status &= ~(0xfc004010); int_status &= 0x7fff; if (!int_status) { return IRQ_NONE; } if (likely(int_status & TX_COMPLETE_INTERRUPT)) { /* ******************************************************** */ /* NORMAL INTERRUPT CASE */ /* ******************************************************** */ # if VOICEBUS_DEFERRED == WORKQUEUE queue_work(vb->workqueue, &vb->workitem); # elif VOICEBUS_DEFERRED == TASKLET tasklet_schedule(&vb->tasklet); # else vb_deferred(vb); # endif __vb_setctl(vb, SR_CSR5, TX_COMPLETE_INTERRUPT); } else { /* ******************************************************** */ /* ABNORMAL / ERROR CONDITIONS */ /* ******************************************************** */ if ((int_status & TX_UNAVAILABLE_INTERRUPT) ) { /* This can happen if the host fails to service the * interrupt within the required time interval (1ms * for each buffer on the queue). Increasing the * depth of the tx queue (up to a maximum of * DRING_SIZE) can make the driver / system more * tolerant of interrupt latency under periods of * heavy system load, but also increases the general * latency that the driver adds to the voice * conversations. */ set_bit(TX_UNDERRUN, &vb->flags); # if VOICEBUS_DEFERRED == WORKQUEUE queue_work(vb->workqueue, &vb->workitem); # elif VOICEBUS_DEFERRED == TASKLET tasklet_schedule(&vb->tasklet); # else vb_deferred(vb); # endif } if (int_status & FATAL_BUS_ERROR_INTERRUPT) { VB_PRINTK(vb, ERR, "Fatal Bus Error detected!\n"); } if (int_status & TX_STOPPED_INTERRUPT) { assert(test_bit(STOP, &vb->flags)); vb_clear_start_receive_bit(vb); __vb_setctl(vb, SR_CSR5, DEFAULT_INTERRUPTS); __vb_disable_interrupts(vb); complete(&vb->stopped_completion); } if (int_status & RX_STOPPED_INTERRUPT) { assert(test_bit(STOP, &vb->flags)); if (vb_is_stopped(vb)) { complete(&vb->stopped_completion); } } /* Clear the interrupt(s) */ __vb_setctl(vb, SR_CSR5, int_status); } return IRQ_HANDLED; } #if VOICEBUS_DEFERRED == TIMER /*! \brief Called if the deferred processing is to happen in the context of * the timer. */ static void vb_timer(unsigned long data) { unsigned long start = jiffies; struct voicebus *vb = (struct voicebus *)data; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) vb_isr(0, vb, 0); #else vb_isr(0, vb); #endif if (!vb_is_stopped(vb)) { vb->timer.expires = start + HZ/1000; add_timer(&vb->timer); } } #endif #if VOICEBUS_DEFERRED == WORKQUEUE static void #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) vb_workfunc(void *data) { struct voicebus *vb = data; #else vb_workfunc(struct work_struct *work) { struct voicebus *vb = container_of(work, struct voicebus, workitem); #endif vb_deferred(vb); } #elif VOICEBUS_DEFERRED == TASKLET static void vb_tasklet(unsigned long data) { struct voicebus *vb = (struct voicebus*)data; vb_deferred(vb); } #endif /* #if VOICEBUS_DEFERRED == WORKQUEUE */ /*! * \brief Initalize the voicebus interface. * * This function must be called in process context since it may sleep. * \todo Complete this description. */ int voicebus_init(struct pci_dev *pdev, u32 framesize, const char *board_name, void (*handle_receive)(void *vbb, void *context), void (*handle_transmit)(void *vbb, void *context), void *context, struct voicebus **vbp ) { int retval = 0; struct voicebus *vb; assert(NULL != pdev); assert(NULL != board_name); assert(framesize); assert(NULL != handle_receive); assert(NULL != handle_transmit); /* ---------------------------------------------------------------- Initialize the pure software constructs. ---------------------------------------------------------------- */ *vbp = NULL; vb = kmalloc(sizeof(*vb), GFP_KERNEL); if (NULL == vb) { VB_PRINTK(vb, DEBUG, "Failed to allocate memory for voicebus "\ "interface.\n"); retval = -ENOMEM; goto cleanup; } memset(vb,0,sizeof(*vb)); /* \todo make sure there is a note that the caller needs to make sure * board_name stays in memory until voicebus_release is called. */ vb->board_name = board_name; spin_lock_init(&vb->lock); init_completion(&vb->stopped_completion); vb->pdev = pdev; set_bit(STOP, &vb->flags); clear_bit(IN_DEFERRED_PROCESSING, &vb->flags); vb->framesize = framesize; vb->min_tx_buffer_count = VOICEBUS_DEFAULT_LATENCY; #if VOICEBUS_DEFERRED == WORKQUEUE /* NOTE: This workqueue must be single threaded because locking is not * used when buffers are removed or added to the descriptor list, and * there should only be one producer / consumer (the hardware or the * deferred processing function). */ vb->workqueue = create_singlethread_workqueue(board_name); # if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) INIT_WORK(&vb->workitem, vb_workfunc, vb); # else INIT_WORK(&vb->workitem, vb_workfunc); # endif # if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) vb_set_workqueue_priority(vb); # endif #elif VOICEBUS_DEFERRED == TASKLET tasklet_init(&vb->tasklet, vb_tasklet, (unsigned long)vb); #elif VOICEBUS_DEFERRED == TIMER init_timer(&vb->timer); vb->timer.function = vb_timer; vb->timer.data = (unsigned long)vb; #endif vb->handle_receive = handle_receive; vb->handle_transmit = handle_transmit; vb->context = context; /* \todo This cache should be shared by all instances supported by * this driver. */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) vb->buffer_cache = kmem_cache_create(board_name, vb->framesize, 0, SLAB_HWCACHE_ALIGN, NULL, NULL); #else vb->buffer_cache = kmem_cache_create(board_name, vb->framesize, 0, SLAB_HWCACHE_ALIGN, NULL); #endif if (NULL == vb->buffer_cache) { VB_PRINTK(vb, ERR, "Failed to allocate buffer cache.\n"); goto cleanup; } /* ---------------------------------------------------------------- Configure the hardware / kernel module interfaces. ---------------------------------------------------------------- */ if (pci_read_config_byte(vb->pdev, 0x0c, &vb->cache_line_size)) { VB_PRINTK(vb, ERR, "Failed read of cache line " \ "size from PCI configuration space.\n"); goto cleanup; } if (pci_enable_device(pdev)) { VB_PRINTK(vb, ERR, "Failed call to pci_enable_device.\n"); retval = -EIO; goto cleanup; } /* \todo This driver should be modified to use the memory mapped I/O as opposed to IO space for portability and performance. */ if (0 == (pci_resource_flags(pdev, 0)&IORESOURCE_IO)) { VB_PRINTK(vb, ERR, "BAR0 is not IO Memory.\n"); retval = -EIO; goto cleanup; } vb->iobase = pci_resource_start(pdev, 0); if(NULL == request_region(vb->iobase, 0xff, board_name)) { VB_PRINTK(vb, ERR, "IO Registers are in use by another " \ "module.\n"); retval = -EIO; goto cleanup; } if ((retval = vb_initialize_tx_descriptors(vb))) { goto cleanup; } if ((retval = vb_initialize_rx_descriptors(vb))) { goto cleanup; } /* ---------------------------------------------------------------- Configure the hardware interface. ---------------------------------------------------------------- */ pci_set_master(pdev); vb_enable_io_access(vb); #if VOICEBUS_DEFERRED != TIMER #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) # define VB_IRQ_SHARED SA_SHIRQ #else # define VB_IRQ_SHARED IRQF_SHARED #endif if (request_irq(pdev->irq, vb_isr, VB_IRQ_SHARED, vb->board_name, vb)) { assert(0); goto cleanup; } #endif *vbp = vb; return retval; cleanup: if (NULL == vb) { return retval; } #if VOICEBUS_DEFERRED == WORKQUEUE if (vb->workqueue) { destroy_workqueue(vb->workqueue); } #elif VOICEBUS_DEFERRED == TASKLET tasklet_kill(&vb->tasklet); #endif /* Cleanup memory and software resources. */ if (vb->txd.desc) { vb_free_descriptors(vb, &vb->txd); } if (vb->rxd.desc) { vb_free_descriptors(vb, &vb->rxd); } if (vb->buffer_cache) { kmem_cache_destroy(vb->buffer_cache); } if (vb->iobase) { release_region(vb->iobase, 0xff); } if (vb->pdev) { pci_disable_device(vb->pdev); } kfree(vb); assert(0 != retval); return retval; } /*! \brief Return the pci_dev in use by this voicebus interface. */ struct pci_dev * voicebus_get_pci_dev(struct voicebus *vb) { return vb->pdev; } zaptel-1.4.11/kernel/wctdm24xxp/0002755000000000000000000000000011017303252015073 5ustar rootrootzaptel-1.4.11/kernel/wctdm24xxp/Makefile0000644000000000000000000000100610751714440016537 0ustar rootrootifneq ($(KBUILD_EXTMOD),) # 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 else all: wctdm24xxp.o %.o: %.c $(CC) $(KFLAGS) -o $@ -c $< base.o: ../zaptel.h GpakCust.h ../wctdm.h GpakCust.o: GpakCust.h ../firmware/zaptel-fw-vpmadt032.o: base.o $(MAKE) -C ../firmware zaptel-fw-vpmadt032.o wctdm24xxp.o: base.o GpakCust.o GpakApi.o ../firmware/zaptel-fw-vpmadt032.o $(LD) -r -o $@ $^ clean: rm -f *.o endif zaptel-1.4.11/kernel/wctdm24xxp/base.c0000644000000000000000000035442210775464716016210 0ustar rootroot/* * Wildcard TDM2400P TDM FXS/FXO Interface Driver for Zapata Telephony interface * * Written by Mark Spencer * Support for TDM800P and VPM150M by Matthew Fredrickson * * Copyright (C) 2005 - 2008 Digium, Inc. * All rights reserved. * * Sections for QRV cards written by Jim Dixon * Copyright (C) 2006, Jim Dixon and QRV Communications * 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. * */ /* 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 #ifdef LINUX26 #include #endif #include "zaptel.h" #include "proslic.h" #include "wctdm.h" #include "wctdm24xxp.h" #ifdef VPM150M_SUPPORT #include "adt_lec.h" #endif #include "GpakCust.h" #include "GpakApi.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; 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}, }; #ifdef FANCY_ECHOCAN static char ectab[] = { 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, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32 ,32 ,32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32 ,32 ,32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32 ,32 ,32, 32, 31, 31, 30, 29, 28, 27, 25, 23, 22, 20, 18, 16, 13, 11, 9, 8, 6, 4, 3, 2, 1, 0, 0, }; static int ectrans[4] = { 0, 1, 3, 2 }; #define EC_SIZE (sizeof(ectab)) #define EC_SIZE_Q (sizeof(ectab) / 4) #endif /* 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 { char *name; int flags; int ports; }; static struct wctdm_desc wctdm2400 = { "Wildcard TDM2400P", 0, 24 }; static struct wctdm_desc wctdm800 = { "Wildcard TDM800P", 0, 8 }; static struct wctdm_desc wctdm410 = { "Wildcard TDM410P", 0, 4 }; static struct wctdm_desc wcaex2400 = { "Wildcard AEX2400", FLAG_EXPRESS, 24 }; static struct wctdm_desc wcaex800 = { "Wildcard AEX800", FLAG_EXPRESS, 8 }; static struct wctdm_desc wcaex410 = { "Wildcard AEX410", FLAG_EXPRESS, 4 }; static int acim2tiss[16] = { 0x0, 0x1, 0x4, 0x5, 0x7, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x2, 0x0, 0x3 }; struct wctdm *ifaces[WC_MAX_IFACES]; spinlock_t ifacelock = SPIN_LOCK_UNLOCKED; 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; static int robust = 0; 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 int fxo_addrs[4] = { 0x00, 0x08, 0x04, 0x0c }; 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 fwringdetect = 0; static int latency = VOICEBUS_DEFAULT_LATENCY; #ifdef VPM_SUPPORT static int vpmsupport = 1; static int vpmdtmfsupport = 0; #define VPM_DEFAULT_DTMFTHRESHOLD 1250 static int dtmfthreshold = VPM_DEFAULT_DTMFTHRESHOLD; /* * This parameter is used to adjust the NLP type used. The options are: * 0 : None * 1 : Mute * 2 : Random Noise * 3 : Hoth Noise * 4 : Suppression NLP - In order to use this, you must set the vpmnlpmaxsupp parameter to * some value in order to give the amount of dB to suppress to the suppressor */ static int vpmnlptype = 1; /* This is the threshold (in dB) for enabling and disabling of the NLP */ static int vpmnlpthresh = 24; /* See vpmnlptype = 4 for more info */ static int vpmnlpmaxsupp = 0; #endif static int wctdm_init_proslic(struct wctdm *wc, int card, int fast , int manual, int sane); static inline int CMD_BYTE(int card, int bit, int altcs) { /* 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; } } return (((((card) & 0x3) * 3 + (bit)) * 7) \ + ((card) >> 2) + (altcs) + ((altcs) ? -21 : 0)); } /* sleep in user space until woken up. Equivilant of tsleep() in BSD */ int schluffen(wait_queue_head_t *q) { DECLARE_WAITQUEUE(wait, current); add_wait_queue(q, &wait); current->state = TASK_INTERRUPTIBLE; if (!signal_pending(current)) schedule(); current->state = TASK_RUNNING; remove_wait_queue(q, &wait); if (signal_pending(current)) return -ERESTARTSYS; return(0); } static inline int empty_slot(struct wctdm *wc, int card) { int x; for (x=0;xcmdq[card].cmds[x]) return x; } return -1; } #ifdef VPM_SUPPORT static inline void cmd_dequeue_vpm150m(struct wctdm *wc, volatile unsigned char *writechunk, int whichframe) { unsigned long flags; struct vpm150m_cmd *curcmd = NULL; struct vpm150m *vpm150m = wc->vpm150m; int x; unsigned char leds = ~((wc->intcount / 1000) % 8) & 0x7; /* Skip audio */ writechunk += 24; spin_lock_irqsave(&wc->reglock, flags); if (test_bit(VPM150M_SPIRESET, &vpm150m->control) || test_bit(VPM150M_HPIRESET, &vpm150m->control)) { if (debug & DEBUG_ECHOCAN) printk("HW Resetting VPMADT032...\n"); for (x = 24; x < 28; x++) { if (x == 24) { if (test_and_clear_bit(VPM150M_SPIRESET, &vpm150m->control)) writechunk[CMD_BYTE(x, 0, 0)] = 0x08; else if (test_and_clear_bit(VPM150M_HPIRESET, &vpm150m->control)) writechunk[CMD_BYTE(x, 0, 0)] = 0x0b; } else writechunk[CMD_BYTE(x, 0, 0)] = 0x00 | leds; writechunk[CMD_BYTE(x, 1, 0)] = 0; writechunk[CMD_BYTE(x, 2, 0)] = 0x00; } spin_unlock_irqrestore(&wc->reglock, flags); return; } /* Search for something waiting to transmit */ for (x = 0; x < VPM150M_MAX_COMMANDS; x++) { if ((vpm150m->cmdq[x].desc & (__VPM150M_RD | __VPM150M_WR)) && !(vpm150m->cmdq[x].desc & (__VPM150M_FIN | __VPM150M_TX))) { curcmd = &vpm150m->cmdq[x]; curcmd->txident = wc->txident; curcmd->desc |= __VPM150M_TX; break; } } if (curcmd) { #if 0 printk("Found command txident = %d, desc = 0x%x, addr = 0x%x, data = 0x%x\n", curcmd->txident, curcmd->desc, curcmd->addr, curcmd->data); #endif if (curcmd->desc & __VPM150M_RWPAGE) { /* Set CTRL access to page*/ writechunk[CMD_BYTE(24, 0, 0)] = (0x8 << 4); writechunk[CMD_BYTE(24, 1, 0)] = 0; writechunk[CMD_BYTE(24, 2, 0)] = 0x20; /* Do a page write */ if (curcmd->desc & __VPM150M_WR) writechunk[CMD_BYTE(25, 0, 0)] = ((0x8 | 0x4) << 4); else writechunk[CMD_BYTE(25, 0, 0)] = ((0x8 | 0x4 | 0x1) << 4); writechunk[CMD_BYTE(25, 1, 0)] = 0; if (curcmd->desc & __VPM150M_WR) writechunk[CMD_BYTE(25, 2, 0)] = curcmd->data[0] & 0xf; else writechunk[CMD_BYTE(25, 2, 0)] = 0; /* Clear XADD */ writechunk[CMD_BYTE(26, 0, 0)] = (0x8 << 4); writechunk[CMD_BYTE(26, 1, 0)] = 0; writechunk[CMD_BYTE(26, 2, 0)] = 0; /* Fill in to buffer to size */ writechunk[CMD_BYTE(27, 0, 0)] = 0; writechunk[CMD_BYTE(27, 1, 0)] = 0; writechunk[CMD_BYTE(27, 2, 0)] = 0; } else { /* Set address */ writechunk[CMD_BYTE(24, 0, 0)] = ((0x8 | 0x4) << 4); writechunk[CMD_BYTE(24, 1, 0)] = (curcmd->addr >> 8) & 0xff; writechunk[CMD_BYTE(24, 2, 0)] = curcmd->addr & 0xff; /* Send/Get our data */ if (curcmd->desc & __VPM150M_WR) { if (curcmd->datalen > 1) writechunk[CMD_BYTE(25, 0, 0)] = ((0x8 | (0x1 << 1)) << 4); else writechunk[CMD_BYTE(25, 0, 0)] = ((0x8 | (0x3 << 1)) << 4); } else if (curcmd->datalen > 1) writechunk[CMD_BYTE(25, 0, 0)] = ((0x8 | (0x1 << 1) | 0x1) << 4); else writechunk[CMD_BYTE(25, 0, 0)] = ((0x8 | (0x3 << 1) | 0x1) << 4); writechunk[CMD_BYTE(25, 1, 0)] = (curcmd->data[0] >> 8) & 0xff; writechunk[CMD_BYTE(25, 2, 0)] = curcmd->data[0] & 0xff; if (curcmd->datalen > 1) { if (curcmd->desc & __VPM150M_WR) writechunk[CMD_BYTE(26, 0, 0)] = ((0x8 | (0x1 << 1)) << 4); else writechunk[CMD_BYTE(26, 0, 0)] = ((0x8 | (0x1 << 1) | 0x1) << 4); writechunk[CMD_BYTE(26, 1, 0)] = (curcmd->data[1] >> 8) & 0xff; writechunk[CMD_BYTE(26, 2, 0)] = curcmd->data[1] & 0xff; } else { /* Fill in the rest */ writechunk[CMD_BYTE(26, 0, 0)] = 0; writechunk[CMD_BYTE(26, 1, 0)] = 0; writechunk[CMD_BYTE(26, 2, 0)] = 0; } if (curcmd->datalen > 2) { if (curcmd->desc & __VPM150M_WR) writechunk[CMD_BYTE(27, 0, 0)] = ((0x8 | (0x1 << 1)) << 4); else writechunk[CMD_BYTE(27, 0, 0)] = ((0x8 | (0x1 << 1) | 0x1) << 4); writechunk[CMD_BYTE(27, 1, 0)] = (curcmd->data[2] >> 8) & 0xff; writechunk[CMD_BYTE(27, 2, 0)] = curcmd->data[2] & 0xff; } else { /* Fill in the rest */ writechunk[CMD_BYTE(27, 0, 0)] = 0; writechunk[CMD_BYTE(27, 1, 0)] = 0; writechunk[CMD_BYTE(27, 2, 0)] = 0; } } } else if (test_and_clear_bit(VPM150M_SWRESET, &vpm150m->control)) { printk("Booting VPMADT032\n"); for (x = 24; x < 28; x++) { if (x == 24) writechunk[CMD_BYTE(x, 0, 0)] = (0x8 << 4); else writechunk[CMD_BYTE(x, 0, 0)] = 0x00; writechunk[CMD_BYTE(x, 1, 0)] = 0; if (x == 24) writechunk[CMD_BYTE(x, 2, 0)] = 0x01; else writechunk[CMD_BYTE(x, 2, 0)] = 0x00; } } else { for (x = 24; x < 28; x++) { writechunk[CMD_BYTE(x, 0, 0)] = 0x00; writechunk[CMD_BYTE(x, 1, 0)] = 0x00; writechunk[CMD_BYTE(x, 2, 0)] = 0x00; } } #ifdef VPM150M_SUPPORT /* Add our leds in */ for (x = 24; x < 28; x++) writechunk[CMD_BYTE(x, 0, 0)] |= leds; /* Now let's figure out if we need to check for DTMF */ if (test_bit(VPM150M_ACTIVE, &vpm150m->control) && !whichframe && !(wc->intcount % 100)) queue_work(vpm150m->wq, &vpm150m->work); #endif spin_unlock_irqrestore(&wc->reglock, flags); } #endif /* VPM_SUPPORT */ static inline void cmd_dequeue(struct wctdm *wc, volatile unsigned char *writechunk, int card, int pos) { unsigned long flags; unsigned int curcmd=0; int x; int subaddr = card & 0x3; #ifdef FANCY_ECHOCAN int ecval; ecval = wc->echocanpos; ecval += EC_SIZE_Q * ectrans[(card & 0x3)]; ecval = ecval % EC_SIZE; #endif /* if a QRV card, map it to its first channel */ if ((wc->modtype[card] == MOD_TYPE_QRV) && (card & 3)) { return; } if (wc->altcs[card]) subaddr = 0; /* Skip audio */ writechunk += 24; spin_lock_irqsave(&wc->reglock, flags); /* Search for something waiting to transmit */ if (pos) { for (x=0;xcmdq[card].cmds[x] & (__CMD_RD | __CMD_WR)) && !(wc->cmdq[card].cmds[x] & (__CMD_TX | __CMD_FIN))) { curcmd = wc->cmdq[card].cmds[x]; #if 0 printk("Transmitting command '%08x' in slot %d\n", wc->cmdq[card].cmds[x], wc->txident); #endif wc->cmdq[card].cmds[x] |= (wc->txident << 24) | __CMD_TX; break; } } } if (!curcmd) { /* If nothing else, use filler */ if (wc->modtype[card] == MOD_TYPE_FXS) curcmd = CMD_RD(64); else if (wc->modtype[card] == MOD_TYPE_FXO) curcmd = CMD_RD(12); else if (wc->modtype[card] == MOD_TYPE_QRV) curcmd = CMD_RD(3); else if (wc->modtype[card] == MOD_TYPE_VPM) { #ifdef FANCY_ECHOCAN if (wc->blinktimer >= 0xf) { curcmd = CMD_WR(0x1ab, 0x0f); } else if (wc->blinktimer == (ectab[ecval] >> 1)) { curcmd = CMD_WR(0x1ab, 0x00); } else #endif curcmd = CMD_RD(0x1a0); } } if (wc->modtype[card] == MOD_TYPE_FXS) { writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = (1 << (subaddr)); if (curcmd & __CMD_WR) writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = (curcmd >> 8) & 0x7f; else writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x80 | ((curcmd >> 8) & 0x7f); writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd & 0xff; } else if (wc->modtype[card] == MOD_TYPE_FXO) { if (curcmd & __CMD_WR) writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x20 | fxo_addrs[subaddr]; else writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x60 | fxo_addrs[subaddr]; writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = (curcmd >> 8) & 0xff; writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd & 0xff; } else if (wc->modtype[card] == MOD_TYPE_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. */ writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x00; writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x00; if ((card & 0x1) == 0x1) writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = 0x80; else writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = 0x00; #ifdef VPM_SUPPORT } else if (wc->modtype[card] == MOD_TYPE_VPM) { if (curcmd & __CMD_WR) writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = ((card & 0x3) << 4) | 0xc | ((curcmd >> 16) & 0x1); else writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = ((card & 0x3) << 4) | 0xa | ((curcmd >> 16) & 0x1); writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = (curcmd >> 8) & 0xff; writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd & 0xff; } else if (wc->modtype[card] == MOD_TYPE_VPM150M) { #endif } else if (wc->modtype[card] == MOD_TYPE_QRV) { writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x00; if (!curcmd) { writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x00; writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = 0x00; } else { if (curcmd & __CMD_WR) writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x40 | ((curcmd >> 8) & 0x3f); else writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0xc0 | ((curcmd >> 8) & 0x3f); writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = curcmd & 0xff; } } else if (wc->modtype[card] == MOD_TYPE_NONE) { writechunk[CMD_BYTE(card, 0, wc->altcs[card])] = 0x00; writechunk[CMD_BYTE(card, 1, wc->altcs[card])] = 0x00; writechunk[CMD_BYTE(card, 2, wc->altcs[card])] = 0x00; } #if 0 /* XXX */ if (cmddesc < 40) printk("Pass %d, card = %d (modtype=%d), pos = %d, CMD_BYTES = %d,%d,%d, (%02x,%02x,%02x) curcmd = %08x\n", cmddesc, card, wc->modtype[card], pos, CMD_BYTE(card, 0), CMD_BYTE(card, 1), CMD_BYTE(card, 2), writechunk[CMD_BYTE(card, 0)], writechunk[CMD_BYTE(card, 1)], writechunk[CMD_BYTE(card, 2)], curcmd); #endif spin_unlock_irqrestore(&wc->reglock, flags); #if 0 /* XXX */ cmddesc++; #endif } #ifdef VPM_SUPPORT static inline void cmd_decifer_vpm150m(struct wctdm *wc, volatile unsigned char *readchunk) { unsigned long flags; unsigned char ident; int x, i; /* Skip audio */ readchunk += 24; spin_lock_irqsave(&wc->reglock, flags); /* Search for any pending results */ for (x = 0; x < VPM150M_MAX_COMMANDS; x++) { if ((wc->vpm150m->cmdq[x].desc & (__VPM150M_RD | __VPM150M_WR)) && (wc->vpm150m->cmdq[x].desc & (__VPM150M_TX)) && !(wc->vpm150m->cmdq[x].desc & (__VPM150M_FIN))) { ident = wc->vpm150m->cmdq[x].txident; if (ident == wc->rxident) { /* Store result */ for (i = 0; i < wc->vpm150m->cmdq[x].datalen; i++) { wc->vpm150m->cmdq[x].data[i] = (0xff & readchunk[CMD_BYTE((25 + i), 1, 0)]) << 8; wc->vpm150m->cmdq[x].data[i] |= readchunk[CMD_BYTE((25 + i), 2, 0)]; } if (wc->vpm150m->cmdq[x].desc & __VPM150M_WR) { /* Go ahead and clear out writes since they need no acknowledgement */ wc->vpm150m->cmdq[x].desc = 0; } else wc->vpm150m->cmdq[x].desc |= __VPM150M_FIN; break; } } } spin_unlock_irqrestore(&wc->reglock, flags); } #endif /* VPM_SUPPORT */ static inline void cmd_decifer(struct wctdm *wc, volatile unsigned char *readchunk, int card) { unsigned long flags; unsigned char ident; int x; /* if a QRV card, map it to its first channel */ if ((wc->modtype[card] == MOD_TYPE_QRV) && (card & 3)) { return; } /* Skip audio */ readchunk += 24; spin_lock_irqsave(&wc->reglock, flags); /* Search for any pending results */ for (x=0;xcmdq[card].cmds[x] & (__CMD_RD | __CMD_WR)) && (wc->cmdq[card].cmds[x] & (__CMD_TX)) && !(wc->cmdq[card].cmds[x] & (__CMD_FIN))) { ident = (wc->cmdq[card].cmds[x] >> 24) & 0xff; if (ident == wc->rxident) { /* Store result */ wc->cmdq[card].cmds[x] |= readchunk[CMD_BYTE(card, 2, wc->altcs[card])]; wc->cmdq[card].cmds[x] |= __CMD_FIN; if (wc->cmdq[card].cmds[x] & __CMD_WR) { /* Go ahead and clear out writes since they need no acknowledgement */ wc->cmdq[card].cmds[x] = 0x00000000; } else if (x >= USER_COMMANDS) { /* Clear out ISR reads */ wc->cmdq[card].isrshadow[x - USER_COMMANDS] = wc->cmdq[card].cmds[x] & 0xff; wc->cmdq[card].cmds[x] = 0x00000000; } break; } } } #if 0 /* XXX */ if (!pos && (cmddesc < 256)) printk("Card %d: Command '%08x' => %02x\n",card, wc->cmdq[card].lasttx[pos], wc->cmdq[card].lastrd[pos]); #endif spin_unlock_irqrestore(&wc->reglock, flags); } static inline void cmd_checkisr(struct wctdm *wc, int card) { if (!wc->cmdq[card].cmds[USER_COMMANDS + 0]) { if (wc->sethook[card]) { wc->cmdq[card].cmds[USER_COMMANDS + 0] = wc->sethook[card]; wc->sethook[card] = 0; } else if (wc->modtype[card] == MOD_TYPE_FXS) { wc->cmdq[card].cmds[USER_COMMANDS + 0] = CMD_RD(68); /* Hook state */ } else if (wc->modtype[card] == MOD_TYPE_FXO) { wc->cmdq[card].cmds[USER_COMMANDS + 0] = CMD_RD(5); /* Hook/Ring state */ } else if (wc->modtype[card] == MOD_TYPE_QRV) { wc->cmdq[card & 0xfc].cmds[USER_COMMANDS + 0] = CMD_RD(3); /* COR/CTCSS state */ #ifdef VPM_SUPPORT } else if (wc->modtype[card] == MOD_TYPE_VPM) { wc->cmdq[card].cmds[USER_COMMANDS + 0] = CMD_RD(0xb9); /* DTMF interrupt */ #endif } } if (!wc->cmdq[card].cmds[USER_COMMANDS + 1]) { if (wc->modtype[card] == MOD_TYPE_FXS) { #ifdef PAQ_DEBUG wc->cmdq[card].cmds[USER_COMMANDS + 1] = CMD_RD(19); /* Transistor interrupts */ #else wc->cmdq[card].cmds[USER_COMMANDS + 1] = CMD_RD(64); /* Battery mode */ #endif } else if (wc->modtype[card] == MOD_TYPE_FXO) { wc->cmdq[card].cmds[USER_COMMANDS + 1] = CMD_RD(29); /* Battery */ } else if (wc->modtype[card] == MOD_TYPE_QRV) { wc->cmdq[card & 0xfc].cmds[USER_COMMANDS + 1] = CMD_RD(3); /* Battery */ #ifdef VPM_SUPPORT } else if (wc->modtype[card] == MOD_TYPE_VPM) { wc->cmdq[card].cmds[USER_COMMANDS + 1] = CMD_RD(0xbd); /* DTMF interrupt */ #endif } } } static inline void wctdm_transmitprep(struct wctdm *wc, unsigned char *writechunk) { int x,y; /* Calculate Transmission */ if (likely(wc->initialized)) { zt_transmit(&wc->span); } for (x=0;xcards;y++) { if (!x) { cmd_checkisr(wc, y); } if (likely(wc->initialized)) { if (y < wc->type) writechunk[y] = wc->chans[y].writechunk[x]; } cmd_dequeue(wc, writechunk, y, x); } #ifdef VPM_SUPPORT if (!x) wc->blinktimer++; if (wc->vpm) { for (y=24;y<28;y++) { if (!x) { cmd_checkisr(wc, y); } cmd_dequeue(wc, writechunk, y, x); } #ifdef FANCY_ECHOCAN if (wc->vpm && wc->blinktimer >= 0xf) { wc->blinktimer = -1; wc->echocanpos++; } #endif } else if (wc->vpm150m) { cmd_dequeue_vpm150m(wc, writechunk, x); } #endif if (x < ZT_CHUNKSIZE - 1) { writechunk[EFRAME_SIZE] = wc->ctlreg; writechunk[EFRAME_SIZE + 1] = wc->txident++; #if 1 if ((wc->type == 4) && ((wc->ctlreg & 0x10) || (wc->modtype[NUM_CARDS] == MOD_TYPE_NONE))) { writechunk[EFRAME_SIZE + 2] = 0; for (y = 0; y < 4; y++) { if (wc->modtype[y] == MOD_TYPE_NONE) writechunk[EFRAME_SIZE + 2] |= (1 << y); } } else writechunk[EFRAME_SIZE + 2] = 0xf; #endif } writechunk += (EFRAME_SIZE + EFRAME_GAP); } } static inline int wctdm_setreg_full(struct wctdm *wc, int card, int addr, int val, int inisr) { unsigned long flags; int hit=0; int ret; /* if a QRV card, use only its first channel */ if (wc->modtype[card] == MOD_TYPE_QRV) { if (card & 3) return(0); } do { spin_lock_irqsave(&wc->reglock, flags); hit = empty_slot(wc, card); if (hit > -1) { wc->cmdq[card].cmds[hit] = CMD_WR(addr, val); } spin_unlock_irqrestore(&wc->reglock, flags); if (inisr) break; if (hit < 0) { if ((ret = schluffen(&wc->regq))) return ret; } } while (hit < 0); return (hit > -1) ? 0 : -1; } static inline int wctdm_setreg_intr(struct wctdm *wc, int card, int addr, int val) { return wctdm_setreg_full(wc, card, addr, val, 1); } static inline int wctdm_setreg(struct wctdm *wc, int card, int addr, int val) { return wctdm_setreg_full(wc, card, addr, val, 0); } static inline int wctdm_getreg(struct wctdm *wc, int card, int addr) { unsigned long flags; int hit; int ret=0; /* if a QRV card, use only its first channel */ if (wc->modtype[card] == MOD_TYPE_QRV) { if (card & 3) return(0); } do { spin_lock_irqsave(&wc->reglock, flags); hit = empty_slot(wc, card); if (hit > -1) { wc->cmdq[card].cmds[hit] = CMD_RD(addr); } spin_unlock_irqrestore(&wc->reglock, flags); if (hit < 0) { if ((ret = schluffen(&wc->regq))) return ret; } } while (hit < 0); do { spin_lock_irqsave(&wc->reglock, flags); if (wc->cmdq[card].cmds[hit] & __CMD_FIN) { ret = wc->cmdq[card].cmds[hit] & 0xff; wc->cmdq[card].cmds[hit] = 0x00000000; hit = -1; } spin_unlock_irqrestore(&wc->reglock, flags); if (hit > -1) { if ((ret = schluffen(&wc->regq))) return ret; } } while (hit > -1); return ret; } #ifdef VPM_SUPPORT static inline unsigned char wctdm_vpm_in(struct wctdm *wc, int unit, const unsigned int addr) { return wctdm_getreg(wc, unit + NUM_CARDS, addr); } static inline void wctdm_vpm_out(struct wctdm *wc, int unit, const unsigned int addr, const unsigned char val) { wctdm_setreg(wc, unit + NUM_CARDS, addr, val); } static inline void cmd_vpm150m_retransmit(struct wctdm *wc) { unsigned long flags; int x; spin_lock_irqsave(&wc->reglock, flags); for (x = 0; x < VPM150M_MAX_COMMANDS; x++) { if (!(wc->vpm150m->cmdq[x].desc & __VPM150M_FIN)) { //printk("Retransmit!\n"); wc->vpm150m->cmdq[x].desc &= ~(__VPM150M_TX); } } spin_unlock_irqrestore(&wc->reglock, flags); } #endif static inline void cmd_retransmit(struct wctdm *wc) { int x,y; unsigned long flags; /* Force retransmissions */ spin_lock_irqsave(&wc->reglock, flags); for (x=0;xcards;y++) { if (!(wc->cmdq[y].cmds[x] & __CMD_FIN)) wc->cmdq[y].cmds[x] &= ~(__CMD_TX | (0xff << 24)); } } spin_unlock_irqrestore(&wc->reglock, flags); #ifdef VPM_SUPPORT if (wc->vpm150m) cmd_vpm150m_retransmit(wc); #endif } static inline void wctdm_receiveprep(struct wctdm *wc, unsigned char *readchunk) { int x,y; unsigned char expected; BUG_ON(NULL == readchunk); for (x=0;xrxident+1; wc->rxident = readchunk[EFRAME_SIZE + 1]; if (wc->rxident != expected) { wc->span.irqmisses++; cmd_retransmit(wc); } } for (y=0;y < wc->cards;y++) { if (likely(wc->initialized)) { if (y < wc->type) { wc->chans[y].readchunk[x] = readchunk[y]; } } cmd_decifer(wc, readchunk, y); } #ifdef VPM_SUPPORT if (wc->vpm) { for (y=NUM_CARDS;y < NUM_CARDS + NUM_EC; y++) cmd_decifer(wc, readchunk, y); } else if (wc->vpm150m) cmd_decifer_vpm150m(wc, readchunk); #endif readchunk += (EFRAME_SIZE + EFRAME_GAP); } /* XXX We're wasting 8 taps. We should get closer :( */ if (likely(wc->initialized)) { for (x=0;xtype;x++) { if (wc->cardflag & (1 << x)) zt_ec_chunk(&wc->chans[x], wc->chans[x].readchunk, wc->chans[x].writechunk); } zt_receive(&wc->span); } /* Wake up anyone sleeping to read/write a new register */ wake_up_interruptible(&wc->regq); } static int wait_access(struct wctdm *wc, int card) { unsigned char data=0; long origjiffies; int count = 0; #define MAX 10 /* attempts */ origjiffies = jiffies; /* Wait for indirect access */ while (count++ < MAX) { data = wctdm_getreg(wc, card, I_STATUS); if (!data) return 0; } if(count > (MAX-1)) printk(" ##### Loop error (%02x) #####\n", data); return 0; } static unsigned char translate_3215(unsigned char address) { int x; for (x=0;xflags[card] & FLAG_3215) { address = translate_3215(address); if (address == 255) return 0; } if(!wait_access(wc, card)) { wctdm_setreg(wc, card, IDA_LO,(unsigned char)(data & 0xFF)); wctdm_setreg(wc, card, IDA_HI,(unsigned char)((data & 0xFF00)>>8)); wctdm_setreg(wc, card, IAA,address); res = 0; }; return res; } static int wctdm_proslic_getreg_indirect(struct wctdm *wc, int card, unsigned char address) { int res = -1; char *p=NULL; /* Translate 3215 addresses */ if (wc->flags[card] & FLAG_3215) { address = translate_3215(address); if (address == 255) return 0; } if (!wait_access(wc, card)) { wctdm_setreg(wc, card, IAA, address); if (!wait_access(wc, card)) { unsigned char data1, data2; data1 = wctdm_getreg(wc, card, IDA_LO); data2 = wctdm_getreg(wc, card, IDA_HI); res = data1 | (data2 << 8); } else p = "Failed to wait inside\n"; } else p = "failed to wait\n"; if (p) printk(p); return res; } static int wctdm_proslic_init_indirect_regs(struct wctdm *wc, int card) { unsigned char i; for (i=0; iflags[card] & FLAG_3215) || (indirect_regs[i].altaddr != 255))) { printk("!!!!!!! %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) printk("Init Indirect Registers completed successfully.\n"); } else { printk(" !!!!! Init Indirect Registers UNSUCCESSFULLY.\n"); return -1; } return 0; } static inline void wctdm_proslic_recheck_sanity(struct wctdm *wc, int card) { int res; #ifdef PAQ_DEBUG res = wc->cmdq[card].isrshadow[1]; res &= ~0x3; if (res) { wc->cmdq[card].isrshadow[1]=0; wc->mods[card].fxs.palarms++; if (wc->mods[card].fxs.palarms < MAX_ALARMS) { printk("Power alarm (%02x) on module %d, resetting!\n", res, card + 1); if (wc->mods[card].fxs.lasttxhook == 4) wc->mods[card].fxs.lasttxhook = 0x11; wc->sethook[card] = CMD_WR(19, res); #if 0 wc->sethook[card] = CMD_WR(64, wc->mods[card].fxs.lasttxhook); #endif /* wctdm_setreg_intr(wc, card, 64, wc->mods[card].fxs.lasttxhook); */ /* Update shadow register to avoid extra power alarms until next read */ wc->cmdq[card].isrshadow[1] = 0; } else { if (wc->mods[card].fxs.palarms == MAX_ALARMS) printk("Too many power alarms on card %d, NOT resetting!\n", card + 1); } } #else res = wc->cmdq[card].isrshadow[1]; /* This makes sure the lasthook was put in reg 64 the linefeed reg */ if (((res & 0x0f) | 0x10) == wc->mods[card].fxs.lasttxhook) wc->mods[card].fxs.lasttxhook &= 0x0f; res = !res && /* reg 64 has to be zero at last isr read */ !(wc->mods[card].fxs.lasttxhook & 0x10 ) && /* not a transition */ wc->mods[card].fxs.lasttxhook; /* not an intended zero */ if (res) { wc->mods[card].fxs.palarms++; if (wc->mods[card].fxs.palarms < MAX_ALARMS) { printk("Power alarm on module %d, resetting!\n", card + 1); if (wc->mods[card].fxs.lasttxhook == 4) wc->mods[card].fxs.lasttxhook = 0x11; wc->mods[card].fxs.lasttxhook |= 0x10; wc->sethook[card] = CMD_WR(64, wc->mods[card].fxs.lasttxhook); /* wctdm_setreg_intr(wc, card, 64, wc->mods[card].fxs.lasttxhook); */ /* Update shadow register to avoid extra power alarms until next read */ wc->cmdq[card].isrshadow[1] = wc->mods[card].fxs.lasttxhook; } else { if (wc->mods[card].fxs.palarms == MAX_ALARMS) printk("Too many power alarms on card %d, NOT resetting!\n", card + 1); } } #endif } static inline void wctdm_qrvdri_check_hook(struct wctdm *wc, int card) { signed char b,b1; int qrvcard = card & 0xfc; if (wc->qrvdebtime[card] >= 2) wc->qrvdebtime[card]--; b = wc->cmdq[qrvcard].isrshadow[0]; /* Hook/Ring state */ b &= 0xcc; /* use bits 3-4 and 6-7 only */ if (wc->radmode[qrvcard] & RADMODE_IGNORECOR) b &= ~4; else if (!(wc->radmode[qrvcard] & RADMODE_INVERTCOR)) b ^= 4; if (wc->radmode[qrvcard + 1] | RADMODE_IGNORECOR) b &= ~0x40; else if (!(wc->radmode[qrvcard + 1] | RADMODE_INVERTCOR)) b ^= 0x40; if ((wc->radmode[qrvcard] & RADMODE_IGNORECT) || (!(wc->radmode[qrvcard] & RADMODE_EXTTONE))) b &= ~8; else if (!(wc->radmode[qrvcard] & RADMODE_EXTINVERT)) b ^= 8; if ((wc->radmode[qrvcard + 1] & RADMODE_IGNORECT) || (!(wc->radmode[qrvcard + 1] & RADMODE_EXTTONE))) b &= ~0x80; else if (!(wc->radmode[qrvcard + 1] & RADMODE_EXTINVERT)) b ^= 0x80; /* now b & MASK should be zero, if its active */ /* check for change in chan 0 */ if ((!(b & 0xc)) != wc->qrvhook[qrvcard + 2]) { wc->qrvdebtime[qrvcard] = wc->debouncetime[qrvcard]; wc->qrvhook[qrvcard + 2] = !(b & 0xc); } /* if timed-out and ready */ if (wc->qrvdebtime[qrvcard] == 1) { b1 = wc->qrvhook[qrvcard + 2]; if (debug) printk("QRV channel %d rx state changed to %d\n",qrvcard,wc->qrvhook[qrvcard + 2]); zt_hooksig(&wc->chans[qrvcard], (b1) ? ZT_RXSIG_OFFHOOK : ZT_RXSIG_ONHOOK); wc->qrvdebtime[card] = 0; } /* check for change in chan 1 */ if ((!(b & 0xc0)) != wc->qrvhook[qrvcard + 3]) { wc->qrvdebtime[qrvcard + 1] = QRV_DEBOUNCETIME; wc->qrvhook[qrvcard + 3] = !(b & 0xc0); } if (wc->qrvdebtime[qrvcard + 1] == 1) { b1 = wc->qrvhook[qrvcard + 3]; if (debug) printk("QRV channel %d rx state changed to %d\n",qrvcard + 1,wc->qrvhook[qrvcard + 3]); zt_hooksig(&wc->chans[qrvcard + 1], (b1) ? ZT_RXSIG_OFFHOOK : ZT_RXSIG_ONHOOK); wc->qrvdebtime[card] = 0; } return; } static inline void wctdm_voicedaa_check_hook(struct wctdm *wc, int card) { #define MS_PER_CHECK_HOOK 1 unsigned char res; signed char b; struct fxo *fxo = &wc->mods[card].fxo; /* Try to track issues that plague slot one FXO's */ b = wc->cmdq[card].isrshadow[0]; /* Hook/Ring state */ b &= 0x9b; if (fxo->offhook) { if (b != 0x9) wctdm_setreg_intr(wc, card, 5, 0x9); } else { if (b != 0x8) wctdm_setreg_intr(wc, card, 5, 0x8); } if (!fxo->offhook) { if (fwringdetect) { res = wc->cmdq[card].isrshadow[0] & 0x60; if (fxo->ringdebounce--) { if (res && (res != fxo->lastrdtx) && (fxo->battery == 1)) { if (!fxo->wasringing) { fxo->wasringing = 1; if (debug) printk("RING on %d/%d!\n", wc->span.spanno, card + 1); zt_hooksig(&wc->chans[card], ZT_RXSIG_RING); } fxo->lastrdtx = res; fxo->ringdebounce = 10; } else if (!res) { if ((fxo->ringdebounce == 0) && fxo->wasringing) { fxo->wasringing = 0; if (debug) printk("NO RING on %d/%d!\n", wc->span.spanno, card + 1); zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); } } } else if (res && (fxo->battery == BATTERY_PRESENT)) { fxo->lastrdtx = res; fxo->ringdebounce = 10; } } else { res = wc->cmdq[card].isrshadow[0]; if ((res & 0x60) && (fxo->battery == BATTERY_PRESENT)) { fxo->ringdebounce += (ZT_CHUNKSIZE * 16); if (fxo->ringdebounce >= ZT_CHUNKSIZE * ringdebounce) { if (!fxo->wasringing) { fxo->wasringing = 1; zt_hooksig(&wc->chans[card], ZT_RXSIG_RING); if (debug) printk("RING on %d/%d!\n", wc->span.spanno, card + 1); } fxo->ringdebounce = ZT_CHUNKSIZE * ringdebounce; } } else { fxo->ringdebounce -= ZT_CHUNKSIZE * 4; if (fxo->ringdebounce <= 0) { if (fxo->wasringing) { fxo->wasringing = 0; zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); if (debug) printk("NO RING on %d/%d!\n", wc->span.spanno, card + 1); } fxo->ringdebounce = 0; } } } } b = wc->cmdq[card].isrshadow[1]; /* Voltage */ if (fxovoltage) { if (!(wc->intcount % 100)) { printk("Port %d: Voltage: %d Debounce %d\n", card + 1, b, fxo->battdebounce); } } if (abs(b) < battthresh) { /* 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) */ if (fxo->battery == BATTERY_LOST) { if (fxo->battdebounce) { /* we were going to BATTERY_PRESENT, but battery was lost again, so clear the debounce timer */ fxo->battdebounce = 0; } } else { if (fxo->battdebounce) { /* going to BATTERY_LOST, see if we are there yet */ if (--fxo->battdebounce == 0) { fxo->battery = BATTERY_LOST; if (debug) printk("NO BATTERY on %d/%d!\n", wc->span.spanno, card + 1); #ifdef JAPAN if (!wc->ohdebounce && wc->offhook) { zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK); if (debug) printk("Signalled On Hook\n"); #ifdef ZERO_BATT_RING wc->onhook++; #endif } #else zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK); /* set the alarm timer, taking into account that part of its time period has already passed while debouncing occurred */ fxo->battalarm = (battalarm - battdebounce) / MS_PER_CHECK_HOOK; #endif } } else { /* start the debounce timer to verify that battery has been lost */ fxo->battdebounce = battdebounce / MS_PER_CHECK_HOOK; } } } else { /* possible existing states: battery lost or unknown, no debounce timer battery lost or unknown, debounce timer (going to battery present) battery present, no debounce timer battery present, debounce timer (going to battery lost) */ if (fxo->battery == BATTERY_PRESENT) { if (fxo->battdebounce) { /* we were going to BATTERY_LOST, but battery appeared again, so clear the debounce timer */ fxo->battdebounce = 0; } } else { if (fxo->battdebounce) { /* going to BATTERY_PRESENT, see if we are there yet */ if (--fxo->battdebounce == 0) { fxo->battery = BATTERY_PRESENT; if (debug) printk("BATTERY on %d/%d (%s)!\n", wc->span.spanno, card + 1, (b < 0) ? "-" : "+"); #ifdef ZERO_BATT_RING if (wc->onhook) { wc->onhook = 0; zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); if (debug) printk("Signalled Off Hook\n"); } #else zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); #endif /* set the alarm timer, taking into account that part of its time period has already passed while debouncing occurred */ fxo->battalarm = (battalarm - battdebounce) / MS_PER_CHECK_HOOK; } } else { /* start the debounce timer to verify that battery has appeared */ fxo->battdebounce = battdebounce / MS_PER_CHECK_HOOK; } } if (fxo->lastpol >= 0) { if (b < 0) { fxo->lastpol = -1; fxo->polaritydebounce = POLARITY_DEBOUNCE / MS_PER_CHECK_HOOK; } } if (fxo->lastpol <= 0) { if (b > 0) { fxo->lastpol = 1; fxo->polaritydebounce = POLARITY_DEBOUNCE / MS_PER_CHECK_HOOK; } } } if (fxo->battalarm) { if (--fxo->battalarm == 0) { /* the alarm timer has expired, so update the battery alarm state for this channel */ zt_alarm_channel(&wc->chans[card], fxo->battery ? ZT_ALARM_NONE : ZT_ALARM_RED); } } if (fxo->polaritydebounce) { fxo->polaritydebounce--; if (fxo->polaritydebounce < 1) { if (fxo->lastpol != fxo->polarity) { if (debug & DEBUG_CARD) printk("%lu Polarity reversed (%d -> %d)\n", jiffies, fxo->polarity, fxo->lastpol); if (fxo->polarity) zt_qevent_lock(&wc->chans[card], ZT_EVENT_POLARITY); fxo->polarity = fxo->lastpol; } } } #undef MS_PER_CHECK_HOOK } static inline void wctdm_proslic_check_hook(struct wctdm *wc, int card) { char res; int hook; /* For some reason we have to debounce the hook detector. */ res = wc->cmdq[card].isrshadow[0]; /* Hook state */ hook = (res & 1); if (hook != wc->mods[card].fxs.lastrxhook) { /* Reset the debounce (must be multiple of 4ms) */ wc->mods[card].fxs.debounce = 8 * (4 * 8); #if 0 printk("Resetting debounce card %d hook %d, %d\n", card, hook, wc->mods[card].fxs.debounce); #endif } else { if (wc->mods[card].fxs.debounce > 0) { wc->mods[card].fxs.debounce-= 4 * ZT_CHUNKSIZE; #if 0 printk("Sustaining hook %d, %d\n", hook, wc->mods[card].fxs.debounce); #endif if (!wc->mods[card].fxs.debounce) { #if 0 printk("Counted down debounce, newhook: %d...\n", hook); #endif wc->mods[card].fxs.debouncehook = hook; } if (!wc->mods[card].fxs.oldrxhook && wc->mods[card].fxs.debouncehook) { /* Off hook */ if (debug & DEBUG_CARD) printk("wctdm: Card %d Going off hook\n", card); zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); if (robust) wctdm_init_proslic(wc, card, 1, 0, 1); wc->mods[card].fxs.oldrxhook = 1; } else if (wc->mods[card].fxs.oldrxhook && !wc->mods[card].fxs.debouncehook) { /* On hook */ if (debug & DEBUG_CARD) printk("wctdm: Card %d Going on hook\n", card); zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK); wc->mods[card].fxs.oldrxhook = 0; } } } wc->mods[card].fxs.lastrxhook = hook; } #ifdef VPM_SUPPORT static inline void wctdm_vpm_check(struct wctdm *wc, int x) { if (wc->cmdq[x].isrshadow[0]) { if (debug & DEBUG_ECHOCAN) printk("VPM: Detected dtmf ON channel %02x on chip %d!\n", wc->cmdq[x].isrshadow[0], x - NUM_CARDS); wc->sethook[x] = CMD_WR(0xb9, wc->cmdq[x].isrshadow[0]); wc->cmdq[x].isrshadow[0] = 0; /* Cancel most recent lookup, if there is one */ wc->cmdq[x].cmds[USER_COMMANDS+0] = 0x00000000; } else if (wc->cmdq[x].isrshadow[1]) { if (debug & DEBUG_ECHOCAN) printk("VPM: Detected dtmf OFF channel %02x on chip %d!\n", wc->cmdq[x].isrshadow[1], x - NUM_CARDS); wc->sethook[x] = CMD_WR(0xbd, wc->cmdq[x].isrshadow[1]); wc->cmdq[x].isrshadow[1] = 0; /* Cancel most recent lookup, if there is one */ wc->cmdq[x].cmds[USER_COMMANDS+1] = 0x00000000; } } #include "adt_lec.c" static int wctdm_echocan_with_params(struct zt_chan *chan, struct zt_echocanparams *ecp, struct zt_echocanparam *p) { struct wctdm *wc = chan->pvt; if (wc->vpm) { int channel; int unit; channel = (chan->chanpos - 1); unit = (chan->chanpos - 1) & 0x3; if (wc->vpm < 2) channel >>= 2; if(debug & DEBUG_ECHOCAN) printk("echocan: Unit is %d, Channel is %d length %d\n", unit, channel, ecp->tap_length); if (ecp->tap_length) wctdm_vpm_out(wc,unit,channel,0x3e); else wctdm_vpm_out(wc,unit,channel,0x01); return 0; #ifdef VPM150M_SUPPORT } else if (wc->vpm150m) { struct vpm150m *vpm150m = wc->vpm150m; unsigned int ret; int channo = chan->chanpos - 1; if ((ret = adt_lec_parse_params(&vpm150m->desiredecstate[channo], ecp, p))) return ret; vpm150m->desiredecstate[channo].tap_length = ecp->tap_length; if (memcmp(&vpm150m->curecstate[channo], &vpm150m->desiredecstate[channo], sizeof(vpm150m->curecstate[channo])) && test_bit(VPM150M_ACTIVE, &vpm150m->control)) queue_work(vpm150m->wq, &vpm150m->work); return 0; #endif } else return -ENODEV; } #endif static inline void wctdm_isr_misc(struct wctdm *wc) { int x; if (unlikely(!wc->initialized)) { return; } for (x=0;xcards;x++) { if (wc->cardflag & (1 << x)) { if (wc->modtype[x] == MOD_TYPE_FXS) { if (!(wc->intcount % 10000)) { /* Accept an alarm once per 10 seconds */ if (wc->mods[x].fxs.palarms) wc->mods[x].fxs.palarms--; } wctdm_proslic_check_hook(wc, x); if (!(wc->intcount & 0xfc)) wctdm_proslic_recheck_sanity(wc, x); if (wc->mods[x].fxs.lasttxhook == 0x4) { /* RINGing, prepare for OHT */ wc->mods[x].fxs.ohttimer = OHT_TIMER << 3; wc->mods[x].fxs.idletxhookstate = 0x2; /* OHT mode when idle */ } else { if (wc->mods[x].fxs.ohttimer) { wc->mods[x].fxs.ohttimer-= ZT_CHUNKSIZE; if (!wc->mods[x].fxs.ohttimer) { wc->mods[x].fxs.idletxhookstate = 0x1; /* Switch to active */ if (wc->mods[x].fxs.lasttxhook == 0x2) { /* Apply the change if appropriate */ wc->mods[x].fxs.lasttxhook = 0x11; wc->sethook[x] = CMD_WR(64, wc->mods[x].fxs.lasttxhook); /* wctdm_setreg_intr(wc, x, 64, wc->mods[x].fxs.lasttxhook); */ } } } } } else if (wc->modtype[x] == MOD_TYPE_FXO) { wctdm_voicedaa_check_hook(wc, x); } else if (wc->modtype[x] == MOD_TYPE_QRV) { wctdm_qrvdri_check_hook(wc, x); } } } #ifdef VPM_SUPPORT if (wc->vpm > 0) { for (x=NUM_CARDS;xrxints++; wctdm_receiveprep(wc, vbb); } void handle_transmit(void* vbb, void* context) { struct wctdm *wc = context; memset(vbb, 0, SFRAME_SIZE); wc->txints++; wctdm_transmitprep(wc, vbb); wctdm_isr_misc(wc); wc->intcount++; voicebus_transmit(wc->vb, vbb); } static int wctdm_voicedaa_insane(struct wctdm *wc, int card) { int blah; blah = wctdm_getreg(wc, card, 2); if (blah != 0x3) return -2; blah = wctdm_getreg(wc, card, 11); if (debug & DEBUG_CARD) printk("VoiceDAA System: %02x\n", blah & 0xf); return 0; } static int wctdm_proslic_insane(struct wctdm *wc, int card) { int blah,insane_report; insane_report=0; blah = wctdm_getreg(wc, card, 0); if (debug & DEBUG_CARD) printk("ProSLIC on module %d, product %d, version %d\n", card, (blah & 0x30) >> 4, (blah & 0xf)); #if 0 if ((blah & 0x30) >> 4) { printk("ProSLIC on module %d is not a 3210.\n", card); return -1; } #endif if (((blah & 0xf) == 0) || ((blah & 0xf) == 0xf)) { /* SLIC not loaded */ return -1; } if ((blah & 0xf) < 2) { printk("ProSLIC 3210 version %d is too old\n", blah & 0xf); return -1; } if (wctdm_getreg(wc, card, 1) & 0x80) /* ProSLIC 3215, not a 3210 */ wc->flags[card] |= FLAG_3215; blah = wctdm_getreg(wc, card, 8); if (blah != 0x2) { printk("ProSLIC on module %d insane (1) %d should be 2\n", card, blah); return -1; } else if ( insane_report) printk("ProSLIC on module %d Reg 8 Reads %d Expected is 0x2\n",card,blah); blah = wctdm_getreg(wc, card, 64); if (blah != 0x0) { printk("ProSLIC on module %d insane (2)\n", card); return -1; } else if ( insane_report) printk("ProSLIC on module %d Reg 64 Reads %d Expected is 0x0\n",card,blah); blah = wctdm_getreg(wc, card, 11); if (blah != 0x33) { printk("ProSLIC on module %d insane (3)\n", card); return -1; } else if ( insane_report) printk("ProSLIC on module %d Reg 11 Reads %d Expected is 0x33\n",card,blah); /* Just be sure it's setup right. */ wctdm_setreg(wc, card, 30, 0); if (debug & DEBUG_CARD) printk("ProSLIC on module %d seems sane.\n", card); return 0; } static int wctdm_proslic_powerleak_test(struct wctdm *wc, int card) { unsigned long origjiffies; unsigned char vbat; /* Turn off linefeed */ wctdm_setreg(wc, card, 64, 0); /* Power down */ wctdm_setreg(wc, card, 14, 0x10); /* Wait for one second */ origjiffies = jiffies; while((vbat = wctdm_getreg(wc, card, 82)) > 0x6) { if ((jiffies - origjiffies) >= (HZ/2)) break;; } if (vbat < 0x06) { printk("Excessive leakage detected on module %d: %d volts (%02x) after %d ms\n", card, 376 * vbat / 1000, vbat, (int)((jiffies - origjiffies) * 1000 / HZ)); return -1; } else if (debug & DEBUG_CARD) { printk("Post-leakage voltage: %d volts\n", 376 * vbat / 1000); } return 0; } static int wctdm_powerup_proslic(struct wctdm *wc, int card, int fast) { unsigned char vbat; unsigned long origjiffies; int lim; /* Set period of DC-DC converter to 1/64 khz */ wctdm_setreg(wc, card, 92, 0xc0 /* was 0xff */); /* Wait for VBat to powerup */ origjiffies = jiffies; /* Disable powerdown */ wctdm_setreg(wc, card, 14, 0); /* If fast, don't bother checking anymore */ if (fast) return 0; while((vbat = wctdm_getreg(wc, card, 82)) < 0xc0) { /* Wait no more than 500ms */ if ((jiffies - origjiffies) > HZ/2) { break; } } if (vbat < 0xc0) { printk("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", card, (int)(((jiffies - origjiffies) * 1000 / HZ)), vbat * 375); return -1; } else if (debug & DEBUG_CARD) { printk("ProSLIC on module %d powered up to -%d volts (%02x) in %d ms\n", 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) printk("Loop current out of range! Setting to default 20mA!\n"); } else if (debug & DEBUG_CARD) printk("Loop current set to %dmA!\n",(lim*3)+20); wctdm_setreg(wc,card,LOOP_I_LIMIT,lim); /* Engage DC-DC converter */ wctdm_setreg(wc, card, 93, 0x19 /* was 0x19 */); #if 0 origjiffies = jiffies; while(0x80 & wctdm_getreg(wc, card, 93)) { if ((jiffies - origjiffies) > 2 * HZ) { printk("Timeout waiting for DC-DC calibration on module %d\n", card); return -1; } } #if 0 /* Wait a full two seconds */ while((jiffies - origjiffies) < 2 * HZ); /* Just check to be sure */ vbat = wctdm_getreg(wc, card, 82); printk("ProSLIC on module %d powered up to -%d volts (%02x) in %d ms\n", card, vbat * 376 / 1000, vbat, (int)(((jiffies - origjiffies) * 1000 / HZ))); #endif #endif return 0; } static int wctdm_proslic_manual_calibrate(struct wctdm *wc, int card) { unsigned long origjiffies; unsigned char i; wctdm_setreg(wc, card, 21, 0);//(0) Disable all interupts in DR21 wctdm_setreg(wc, card, 22, 0);//(0)Disable all interupts in DR21 wctdm_setreg(wc, card, 23, 0);//(0)Disable all interupts in DR21 wctdm_setreg(wc, card, 64, 0);//(0) wctdm_setreg(wc, card, 97, 0x18); //(0x18)Calibrations without the ADC and DAC offset and without common mode calibration. wctdm_setreg(wc, card, 96, 0x47); //(0x47) Calibrate common mode and differential DAC mode DAC + ILIM origjiffies=jiffies; while( wctdm_getreg(wc,card,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 *******************************************/ // Delay 10ms origjiffies=jiffies; while((jiffies-origjiffies)<1); wctdm_proslic_setreg_indirect(wc, card, 88,0); wctdm_proslic_setreg_indirect(wc,card,89,0); wctdm_proslic_setreg_indirect(wc,card,90,0); wctdm_proslic_setreg_indirect(wc,card,91,0); wctdm_proslic_setreg_indirect(wc,card,92,0); wctdm_proslic_setreg_indirect(wc,card,93,0); wctdm_setreg(wc, card, 98,0x10); // This is necessary if the calibration occurs other than at reset time wctdm_setreg(wc, card, 99,0x10); for ( i=0x1f; i>0; i--) { wctdm_setreg(wc, card, 98,i); origjiffies=jiffies; while((jiffies-origjiffies)<4); if((wctdm_getreg(wc,card,88)) == 0) break; } // for for ( i=0x1f; i>0; i--) { wctdm_setreg(wc, card, 99,i); origjiffies=jiffies; while((jiffies-origjiffies)<4); if((wctdm_getreg(wc,card,89)) == 0) break; }//for /*******************************The preceding is the manual gain mismatch calibration****************************/ /**********************************The following is the longitudinal Balance Cal***********************************/ wctdm_setreg(wc,card,64,1); while((jiffies-origjiffies)<10); // Sleep 100? wctdm_setreg(wc, card, 64, 0); wctdm_setreg(wc, card, 23, 0x4); // enable interrupt for the balance Cal wctdm_setreg(wc, card, 97, 0x1); // this is a singular calibration bit for longitudinal calibration wctdm_setreg(wc, card, 96,0x40); wctdm_getreg(wc,card,96); /* Read Reg 96 just cause */ wctdm_setreg(wc, card, 21, 0xFF); wctdm_setreg(wc, card, 22, 0xFF); wctdm_setreg(wc, card, 23, 0xFF); /**The preceding is the longitudinal Balance Cal***/ return(0); } static int wctdm_proslic_calibrate(struct wctdm *wc, int card) { unsigned long origjiffies; int x; /* Perform all calibrations */ wctdm_setreg(wc, card, 97, 0x1f); /* Begin, no speedup */ wctdm_setreg(wc, card, 96, 0x5f); /* Wait for it to finish */ origjiffies = jiffies; while(wctdm_getreg(wc, card, 96)) { if ((jiffies - origjiffies) > 2 * HZ) { printk("Timeout waiting for calibration of module %d\n", card); return -1; } } if (debug & DEBUG_CARD) { /* Print calibration parameters */ printk("Calibration Vector Regs 98 - 107: \n"); for (x=98;x<108;x++) { printk("%d: %02x\n", x, wctdm_getreg(wc, card, x)); } } return 0; } static void wait_just_a_bit(int foo) { long newjiffies; newjiffies = jiffies + foo; while(jiffies < newjiffies); } /********************************************************************* * 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, int card, __s32 gain, __u32 tx) { if (!(wc->modtype[card] == MOD_TYPE_FXO)) { printk("Cannot adjust gain. Unsupported module type!\n"); return -1; } if (tx) { if (debug) printk("setting FXO tx gain for card=%d to %d\n", card, gain); if (gain >= -150 && gain <= 0) { wctdm_setreg(wc, card, 38, 16 + (gain/-10)); wctdm_setreg(wc, card, 40, 16 + (-gain%10)); } else if (gain <= 120 && gain > 0) { wctdm_setreg(wc, card, 38, gain/10); wctdm_setreg(wc, card, 40, (gain%10)); } else { printk("FXO tx gain is out of range (%d)\n", gain); return -1; } } else { /* rx */ if (debug) printk("setting FXO rx gain for card=%d to %d\n", card, gain); if (gain >= -150 && gain <= 0) { wctdm_setreg(wc, card, 39, 16+ (gain/-10)); wctdm_setreg(wc, card, 41, 16 + (-gain%10)); } else if (gain <= 120 && gain > 0) { wctdm_setreg(wc, card, 39, gain/10); wctdm_setreg(wc, card, 41, (gain%10)); } else { printk("FXO rx gain is out of range (%d)\n", gain); return -1; } } return 0; } static int wctdm_init_voicedaa(struct wctdm *wc, int card, int fast, int manual, int sane) { unsigned char reg16=0, reg26=0, reg30=0, reg31=0; long newjiffies; if (wc->modtype[card & 0xfc] == MOD_TYPE_QRV) return -2; wc->modtype[card] = MOD_TYPE_NONE; /* Wait just a bit */ wait_just_a_bit(HZ/10); wc->modtype[card] = MOD_TYPE_FXO; wait_just_a_bit(HZ/10); if (!sane && wctdm_voicedaa_insane(wc, card)) return -2; /* Software reset */ wctdm_setreg(wc, card, 1, 0x80); /* Wait just a bit */ wait_just_a_bit(HZ/10); /* Enable PCM, ulaw */ if (alawoverride) wctdm_setreg(wc, card, 33, 0x20); else wctdm_setreg(wc, card, 33, 0x28); /* 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, card, 16, reg16); if(fwringdetect) { /* Enable ring detector full-wave rectifier mode */ wctdm_setreg(wc, card, 18, 2); wctdm_setreg(wc, card, 24, 0); } else { /* Set to the device defaults */ wctdm_setreg(wc, card, 18, 0); wctdm_setreg(wc, card, 24, 0x19); } /* Enable ring detector full-wave rectifier mode */ wctdm_setreg(wc, card, 18, 2); wctdm_setreg(wc, card, 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, card, 26, reg26); /* Set AC Impedence */ reg30 = (fxo_modes[_opermode].acim); wctdm_setreg(wc, card, 30, reg30); /* Misc. DAA parameters */ reg31 = 0xa3; reg31 |= (fxo_modes[_opermode].ohs2 << 3); wctdm_setreg(wc, card, 31, reg31); /* Set Transmit/Receive timeslot */ wctdm_setreg(wc, card, 34, (card * 8) & 0xff); wctdm_setreg(wc, card, 35, (card * 8) >> 8); wctdm_setreg(wc, card, 36, (card * 8) & 0xff); wctdm_setreg(wc, card, 37, (card * 8) >> 8); /* Enable ISO-Cap */ wctdm_setreg(wc, card, 6, 0x00); /* Wait 1000ms for ISO-cap to come up */ newjiffies = jiffies; newjiffies += 2 * HZ; while((jiffies < newjiffies) && !(wctdm_getreg(wc, card, 11) & 0xf0)) wait_just_a_bit(HZ/10); if (!(wctdm_getreg(wc, card, 11) & 0xf0)) { printk("VoiceDAA did not bring up ISO link properly!\n"); return -1; } if (debug & DEBUG_CARD) printk("ISO-Cap is now up, line side: %02x rev %02x\n", wctdm_getreg(wc, card, 11) >> 4, (wctdm_getreg(wc, card, 13) >> 2) & 0xf); /* Enable on-hook line monitor */ wctdm_setreg(wc, card, 5, 0x08); /* Take values for fxotxgain and fxorxgain and apply them to module */ wctdm_set_hwgain(wc, card, fxotxgain, 1); wctdm_set_hwgain(wc, card, fxorxgain, 0); if(debug) printk("DEBUG fxotxgain:%i.%i fxorxgain:%i.%i\n", (wctdm_getreg(wc, card, 38)/16) ? -(wctdm_getreg(wc, card, 38) - 16) : wctdm_getreg(wc, card, 38), (wctdm_getreg(wc, card, 40)/16) ? -(wctdm_getreg(wc, card, 40) - 16) : wctdm_getreg(wc, card, 40), (wctdm_getreg(wc, card, 39)/16) ? -(wctdm_getreg(wc, card, 39) - 16): wctdm_getreg(wc, card, 39), (wctdm_getreg(wc, card, 41)/16)?-(wctdm_getreg(wc, card, 41) - 16) : wctdm_getreg(wc, card, 41)); return 0; } static int wctdm_init_proslic(struct wctdm *wc, int card, int fast, int manual, int sane) { unsigned short tmp[5]; unsigned char r19,r9; int x; int fxsmode=0; if (wc->modtype[card & 0xfc] == MOD_TYPE_QRV) return -2; /* Sanity check the ProSLIC */ if (!sane && wctdm_proslic_insane(wc, card)) return -2; /* By default, don't send on hook */ wc->mods[card].fxs.idletxhookstate = 1; wc->mods[card].fxs.lasttxhook = 0x10; if (sane) { /* Make sure we turn off the DC->DC converter to prevent anything from blowing up */ wctdm_setreg(wc, card, 14, 0x10); } if (wctdm_proslic_init_indirect_regs(wc, card)) { printk(KERN_INFO "Indirect Registers failed to initialize on module %d.\n", card); return -1; } /* Clear scratch pad area */ wctdm_proslic_setreg_indirect(wc, card, 97,0); /* Clear digital loopback */ wctdm_setreg(wc, card, 8, 0); /* Revision C optimization */ wctdm_setreg(wc, card, 108, 0xeb); /* Disable automatic VBat switching for safety to prevent Q7 from accidently turning on and burning out. */ wctdm_setreg(wc, card, 67, 0x07); /* If pulse dialing has trouble at high REN loads change this to 0x17 */ /* Turn off Q7 */ wctdm_setreg(wc, card, 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, card, x + 35); wctdm_proslic_setreg_indirect(wc, card, x + 35, 0x8000); } /* Power up the DC-DC converter */ if (wctdm_powerup_proslic(wc, card, fast)) { printk("Unable to do INITIAL ProSLIC powerup on module %d\n", card); return -1; } if (!fast) { /* Check for power leaks */ if (wctdm_proslic_powerleak_test(wc, card)) { printk("ProSLIC module %d failed leakage test. Check for short circuit\n", card); } /* Power up again */ if (wctdm_powerup_proslic(wc, card, fast)) { printk("Unable to do FINAL ProSLIC powerup on module %d\n", card); return -1; } #ifndef NO_CALIBRATION /* Perform calibration */ if(manual) { if (wctdm_proslic_manual_calibrate(wc, card)) { //printk("Proslic failed on Manual Calibration\n"); if (wctdm_proslic_manual_calibrate(wc, card)) { printk("Proslic Failed on Second Attempt to Calibrate Manually. (Try -DNO_CALIBRATION in Makefile)\n"); return -1; } printk("Proslic Passed Manual Calibration on Second Attempt\n"); } } else { if(wctdm_proslic_calibrate(wc, card)) { //printk("ProSlic died on Auto Calibration.\n"); if (wctdm_proslic_calibrate(wc, card)) { printk("Proslic Failed on Second Attempt to Auto Calibrate\n"); return -1; } printk("Proslic Passed Auto Calibration on Second Attempt\n"); } } /* Perform DC-DC calibration */ wctdm_setreg(wc, card, 93, 0x99); r19 = wctdm_getreg(wc, card, 107); if ((r19 < 0x2) || (r19 > 0xd)) { printk("DC-DC cal has a surprising direct 107 of 0x%02x!\n", r19); wctdm_setreg(wc, card, 107, 0x8); } /* Save calibration vectors */ for (x=0;xmods[card].fxs.calregs.vals[x] = wctdm_getreg(wc, card, 96 + x); #endif } else { /* Restore calibration registers */ for (x=0;xmods[card].fxs.calregs.vals[x]); } /* Calibration complete, restore original values */ for (x=0;x<5;x++) { wctdm_proslic_setreg_indirect(wc, card, x + 35, tmp[x]); } if (wctdm_proslic_verify_indirect_regs(wc, card)) { printk(KERN_INFO "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 printk(KERN_INFO "ProSlic IndirectReg Died.\n"); return -1; } #endif if (alawoverride) wctdm_setreg(wc, card, 1, 0x20); else wctdm_setreg(wc, card, 1, 0x28); // U-Law 8-bit interface wctdm_setreg(wc, card, 2, (card * 8) & 0xff); // Tx Start count low byte 0 wctdm_setreg(wc, card, 3, (card * 8) >> 8); // Tx Start count high byte 0 wctdm_setreg(wc, card, 4, (card * 8) & 0xff); // Rx Start count low byte 0 wctdm_setreg(wc, card, 5, (card * 8) >> 8); // Rx Start count high byte 0 wctdm_setreg(wc, card, 18, 0xff); // clear all interrupt wctdm_setreg(wc, card, 19, 0xff); wctdm_setreg(wc, card, 20, 0xff); wctdm_setreg(wc, card, 22, 0xff); wctdm_setreg(wc, card, 73, 0x04); if (fxshonormode) { fxsmode = acim2tiss[fxo_modes[_opermode].acim]; wctdm_setreg(wc, card, 10, 0x08 | fxsmode); if (fxo_modes[_opermode].ring_osc) wctdm_proslic_setreg_indirect(wc, card, 20, fxo_modes[_opermode].ring_osc); if (fxo_modes[_opermode].ring_x) wctdm_proslic_setreg_indirect(wc, card, 21, fxo_modes[_opermode].ring_x); } if (lowpower) wctdm_setreg(wc, card, 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, card, 20, 0x7e6d); wctdm_proslic_setreg_indirect(wc, card, 21, 0x01b9); /* Beef up Ringing voltage to 89V */ if (boostringer) { wctdm_setreg(wc, card, 74, 0x3f); if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x247)) return -1; printk("Boosting fast ringer on slot %d (89V peak)\n", card + 1); } else if (lowpower) { if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x14b)) return -1; printk("Reducing fast ring power on slot %d (50V peak)\n", card + 1); } else printk("Speeding up ringer on slot %d (25Hz)\n", card + 1); } else { /* Beef up Ringing voltage to 89V */ if (boostringer) { wctdm_setreg(wc, card, 74, 0x3f); if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x1d1)) return -1; printk("Boosting ringer on slot %d (89V peak)\n", card + 1); } else if (lowpower) { if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x108)) return -1; printk("Reducing ring power on slot %d (50V peak)\n", card + 1); } } if (fxstxgain || fxsrxgain) { r9 = wctdm_getreg(wc, card, 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, card, 9, r9); } if (debug) printk("DEBUG: fxstxgain:%s fxsrxgain:%s\n",((wctdm_getreg(wc, card, 9)/8) == 1)?"3.5":(((wctdm_getreg(wc,card,9)/4) == 1)?"-3.5":"0.0"),((wctdm_getreg(wc, card, 9)/2) == 1)?"3.5":((wctdm_getreg(wc,card,9)%2)?"-3.5":"0.0")); wc->mods[card].fxs.lasttxhook = 0x11; wctdm_setreg(wc, card, 64, 0x01); return 0; } static int wctdm_init_qrvdri(struct wctdm *wc, int card) { unsigned char x,y; unsigned long endjif; /* have to set this, at least for now */ wc->modtype[card] = MOD_TYPE_QRV; if (!(card & 3)) /* if at base of card, reset and write it */ { wctdm_setreg(wc,card,0,0x80); wctdm_setreg(wc,card,0,0x55); wctdm_setreg(wc,card,1,0x69); wc->qrvhook[card] = wc->qrvhook[card + 1] = 0; wc->qrvhook[card + 2] = wc->qrvhook[card + 3] = 0xff; wc->debouncetime[card] = wc->debouncetime[card + 1] = QRV_DEBOUNCETIME; wc->qrvdebtime[card] = wc->qrvdebtime[card + 1] = 0; wc->radmode[card] = wc->radmode[card + 1] = 0; wc->txgain[card] = wc->txgain[card + 1] = 3599; wc->rxgain[card] = wc->rxgain[card + 1] = 1199; } else { /* channel is on same card as base, no need to test */ if (wc->modtype[card & 0x7c] == MOD_TYPE_QRV) { /* only lower 2 are valid */ if (!(card & 2)) return 0; } wc->modtype[card] = MOD_TYPE_NONE; return 1; } x = wctdm_getreg(wc,card,0); y = wctdm_getreg(wc,card,1); /* if not a QRV card, return as such */ if ((x != 0x55) || (y != 0x69)) { wc->modtype[card] = MOD_TYPE_NONE; return 1; } for(x = 0; x < 0x30; x++) { if ((x >= 0x1c) && (x <= 0x1e)) wctdm_setreg(wc,card,x,0xff); else wctdm_setreg(wc,card,x,0); } wctdm_setreg(wc,card,0,0x80); endjif = jiffies + (HZ/10); while(endjif > jiffies); wctdm_setreg(wc,card,0,0x10); wctdm_setreg(wc,card,0,0x10); endjif = jiffies + (HZ/10); while(endjif > jiffies); /* set up modes */ wctdm_setreg(wc,card,0,0x1c); /* set up I/O directions */ wctdm_setreg(wc,card,1,0x33); wctdm_setreg(wc,card,2,0x0f); wctdm_setreg(wc,card,5,0x0f); /* set up I/O to quiescent state */ wctdm_setreg(wc,card,3,0x11); /* D0-7 */ wctdm_setreg(wc,card,4,0xa); /* D8-11 */ wctdm_setreg(wc,card,7,0); /* CS outputs */ /* set up timeslots */ wctdm_setreg(wc,card,0x13,card + 0x80); /* codec 2 tx, ts0 */ wctdm_setreg(wc,card,0x17,card + 0x80); /* codec 0 rx, ts0 */ wctdm_setreg(wc,card,0x14,card + 0x81); /* codec 1 tx, ts1 */ wctdm_setreg(wc,card,0x18,card + 0x81); /* codec 1 rx, ts1 */ /* set up for max gains */ wctdm_setreg(wc,card,0x26,0x24); wctdm_setreg(wc,card,0x27,0x24); wctdm_setreg(wc,card,0x0b,0x01); /* "Transmit" gain codec 0 */ wctdm_setreg(wc,card,0x0c,0x01); /* "Transmit" gain codec 1 */ wctdm_setreg(wc,card,0x0f,0xff); /* "Receive" gain codec 0 */ wctdm_setreg(wc,card,0x10,0xff); /* "Receive" gain codec 1 */ return 0; } static void qrv_dosetup(struct zt_chan *chan,struct wctdm *wc) { int qrvcard; unsigned char r; long l; /* actually do something with the values */ qrvcard = (chan->chanpos - 1) & 0xfc; if (debug) printk("@@@@@ radmodes: %d,%d rxgains: %d,%d txgains: %d,%d\n", wc->radmode[qrvcard],wc->radmode[qrvcard + 1], wc->rxgain[qrvcard],wc->rxgain[qrvcard + 1], wc->txgain[qrvcard],wc->txgain[qrvcard + 1]); r = 0; if (wc->radmode[qrvcard] & RADMODE_DEEMP) r |= 4; if (wc->radmode[qrvcard + 1] & RADMODE_DEEMP) r |= 8; if (wc->rxgain[qrvcard] < 1200) r |= 1; if (wc->rxgain[qrvcard + 1] < 1200) r |= 2; wctdm_setreg(wc, qrvcard, 7, r); if (debug) printk("@@@@@ setting reg 7 to %02x hex\n",r); r = 0; if (wc->radmode[qrvcard] & RADMODE_PREEMP) r |= 3; else if (wc->txgain[qrvcard] >= 3600) r |= 1; else if (wc->txgain[qrvcard] >= 1200) r |= 2; if (wc->radmode[qrvcard + 1] & RADMODE_PREEMP) r |= 0xc; else if (wc->txgain[qrvcard + 1] >= 3600) r |= 4; else if (wc->txgain[qrvcard + 1] >= 1200) r |= 8; wctdm_setreg(wc, qrvcard, 4, r); if (debug) printk("@@@@@ setting reg 4 to %02x hex\n",r); r = 0; if (wc->rxgain[qrvcard] >= 2400) r |= 1; if (wc->rxgain[qrvcard + 1] >= 2400) r |= 2; wctdm_setreg(wc, qrvcard, 0x25, r); if (debug) printk("@@@@@ setting reg 0x25 to %02x hex\n",r); r = 0; if (wc->txgain[qrvcard] < 2400) r |= 1; else r |= 4; if (wc->txgain[qrvcard + 1] < 2400) r |= 8; else r |= 0x20; wctdm_setreg(wc, qrvcard, 0x26, r); if (debug) printk("@@@@@ setting reg 0x26 to %02x hex\n",r); l = ((long)(wc->rxgain[qrvcard] % 1200) * 10000) / 46875; if (l == 0) l = 1; if (wc->rxgain[qrvcard] >= 2400) l += 181; wctdm_setreg(wc, qrvcard, 0x0b, (unsigned char)l); if (debug) printk("@@@@@ setting reg 0x0b to %02x hex\n",(unsigned char)l); l = ((long)(wc->rxgain[qrvcard + 1] % 1200) * 10000) / 46875; if (l == 0) l = 1; if (wc->rxgain[qrvcard + 1] >= 2400) l += 181; wctdm_setreg(wc, qrvcard, 0x0c, (unsigned char)l); if (debug) printk("@@@@@ setting reg 0x0c to %02x hex\n",(unsigned char)l); l = ((long)(wc->txgain[qrvcard] % 1200) * 10000) / 46875; if (l == 0) l = 1; wctdm_setreg(wc, qrvcard, 0x0f, (unsigned char)l); if (debug) printk("@@@@@ setting reg 0x0f to %02x hex\n", (unsigned char)l); l = ((long)(wc->txgain[qrvcard + 1] % 1200) * 10000) / 46875; if (l == 0) l = 1; wctdm_setreg(wc, qrvcard, 0x10,(unsigned char)l); if (debug) printk("@@@@@ setting reg 0x10 to %02x hex\n",(unsigned char)l); return; } static int wctdm_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data) { struct wctdm_stats stats; struct wctdm_regs regs; struct wctdm_regop regop; struct wctdm_echo_coefs echoregs; struct zt_hwgain hwgain; struct wctdm *wc = chan->pvt; int x; union { struct zt_radio_stat s; struct zt_radio_param p; } stack; switch (cmd) { case ZT_ONHOOKTRANSFER: if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) return -EINVAL; if (get_user(x, (int *)data)) return -EFAULT; wc->mods[chan->chanpos - 1].fxs.ohttimer = x << 3; wc->mods[chan->chanpos - 1].fxs.idletxhookstate = 0x2; /* OHT mode when idle */ if (wc->mods[chan->chanpos - 1].fxs.lasttxhook == 0x1) { /* Apply the change if appropriate */ wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x12; wc->sethook[chan->chanpos - 1] = CMD_WR(64, wc->mods[chan->chanpos - 1].fxs.lasttxhook); /* wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mods[chan->chanpos - 1].fxs.lasttxhook); */ } break; case WCTDM_GET_STATS: if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) { stats.tipvolt = wctdm_getreg(wc, chan->chanpos - 1, 80) * -376; stats.ringvolt = wctdm_getreg(wc, chan->chanpos - 1, 81) * -376; stats.batvolt = wctdm_getreg(wc, chan->chanpos - 1, 82) * -376; } else if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) { stats.tipvolt = (signed char)wctdm_getreg(wc, chan->chanpos - 1, 29) * 1000; stats.ringvolt = (signed char)wctdm_getreg(wc, chan->chanpos - 1, 29) * 1000; stats.batvolt = (signed char)wctdm_getreg(wc, chan->chanpos - 1, 29) * 1000; } else return -EINVAL; if (copy_to_user((struct wctdm_stats *)data, &stats, sizeof(stats))) return -EFAULT; break; case WCTDM_GET_REGS: if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) { for (x=0;xchanpos -1, x); for (x=0;xchanpos - 1, x); } else if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_QRV) { memset(®s, 0, sizeof(regs)); for (x=0;x<0x32;x++) regs.direct[x] = wctdm_getreg(wc, chan->chanpos - 1, x); } else { memset(®s, 0, sizeof(regs)); for (x=0;xchanpos - 1, x); } if (copy_to_user((struct wctdm_regs *)data, ®s, sizeof(regs))) return -EFAULT; break; case WCTDM_SET_REG: if (copy_from_user(®op, (struct wctdm_regop *)data, sizeof(regop))) return -EFAULT; if (regop.indirect) { if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) return -EINVAL; printk("Setting indirect %d to 0x%04x on %d\n", regop.reg, regop.val, chan->chanpos); wctdm_proslic_setreg_indirect(wc, chan->chanpos - 1, regop.reg, regop.val); } else { regop.val &= 0xff; if (regop.reg == 64) wc->mods[chan->chanpos-1].fxs.lasttxhook = (regop.val & 0x0f) | 0x10; printk("Setting direct %d to %04x on %d\n", regop.reg, regop.val, chan->chanpos); wctdm_setreg(wc, chan->chanpos - 1, regop.reg, regop.val); } break; case WCTDM_SET_ECHOTUNE: printk("-- Setting echo registers: \n"); if (copy_from_user(&echoregs, (struct wctdm_echo_coefs*)data, sizeof(echoregs))) return -EFAULT; if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) { /* Set the ACIM register */ wctdm_setreg(wc, chan->chanpos - 1, 30, echoregs.acim); /* Set the digital echo canceller registers */ wctdm_setreg(wc, chan->chanpos - 1, 45, echoregs.coef1); wctdm_setreg(wc, chan->chanpos - 1, 46, echoregs.coef2); wctdm_setreg(wc, chan->chanpos - 1, 47, echoregs.coef3); wctdm_setreg(wc, chan->chanpos - 1, 48, echoregs.coef4); wctdm_setreg(wc, chan->chanpos - 1, 49, echoregs.coef5); wctdm_setreg(wc, chan->chanpos - 1, 50, echoregs.coef6); wctdm_setreg(wc, chan->chanpos - 1, 51, echoregs.coef7); wctdm_setreg(wc, chan->chanpos - 1, 52, echoregs.coef8); printk("-- Set echo registers successfully\n"); break; } else { return -EINVAL; } break; case ZT_SET_HWGAIN: if (copy_from_user(&hwgain, (struct zt_hwgain*) data, sizeof(hwgain))) return -EFAULT; wctdm_set_hwgain(wc, chan->chanpos-1, hwgain.newgain, hwgain.tx); if (debug) printk("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 ZT_TONEDETECT: if (get_user(x, (int *) data)) return -EFAULT; if (!wc->vpm && !wc->vpm150m) return -ENOSYS; if ((wc->vpm || wc->vpm150m) && (x && !vpmdtmfsupport)) return -ENOSYS; if (x & ZT_TONEDETECT_ON) { set_bit(chan->chanpos - 1, &wc->dtmfmask); } else { clear_bit(chan->chanpos - 1, &wc->dtmfmask); } if (x & ZT_TONEDETECT_MUTE) { if (wc->vpm150m) { set_bit(chan->chanpos - 1, &wc->vpm150m->desireddtmfmutestate); } } else { if (wc->vpm150m) { clear_bit(chan->chanpos - 1, &wc->vpm150m->desireddtmfmutestate); } } return 0; #endif case ZT_RADIO_GETPARAM: if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_QRV) return -ENOTTY; if (copy_from_user(&stack.p,(struct zt_radio_param *)data,sizeof(struct zt_radio_param))) return -EFAULT; stack.p.data = 0; /* start with 0 value in output */ switch(stack.p.radpar) { case ZT_RADPAR_INVERTCOR: if (wc->radmode[chan->chanpos - 1] & RADMODE_INVERTCOR) stack.p.data = 1; break; case ZT_RADPAR_IGNORECOR: if (wc->radmode[chan->chanpos - 1] & RADMODE_IGNORECOR) stack.p.data = 1; break; case ZT_RADPAR_IGNORECT: if (wc->radmode[chan->chanpos - 1] & RADMODE_IGNORECT) stack.p.data = 1; break; case ZT_RADPAR_EXTRXTONE: stack.p.data = 0; if (wc->radmode[chan->chanpos - 1] & RADMODE_EXTTONE) { stack.p.data = 1; if (wc->radmode[chan->chanpos - 1] & RADMODE_EXTINVERT) { stack.p.data = 2; } } break; case ZT_RADPAR_DEBOUNCETIME: stack.p.data = wc->debouncetime[chan->chanpos - 1]; break; case ZT_RADPAR_RXGAIN: stack.p.data = wc->rxgain[chan->chanpos - 1] - 1199; break; case ZT_RADPAR_TXGAIN: stack.p.data = wc->txgain[chan->chanpos - 1] - 3599; break; case ZT_RADPAR_DEEMP: stack.p.data = 0; if (wc->radmode[chan->chanpos - 1] & RADMODE_DEEMP) { stack.p.data = 1; } break; case ZT_RADPAR_PREEMP: stack.p.data = 0; if (wc->radmode[chan->chanpos - 1] & RADMODE_PREEMP) { stack.p.data = 1; } break; default: return -EINVAL; } if (copy_to_user((struct zt_radio_param *)data,&stack.p,sizeof(struct zt_radio_param))) return -EFAULT; break; case ZT_RADIO_SETPARAM: if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_QRV) return -ENOTTY; if (copy_from_user(&stack.p,(struct zt_radio_param *)data,sizeof(struct zt_radio_param))) return -EFAULT; switch(stack.p.radpar) { case ZT_RADPAR_INVERTCOR: if (stack.p.data) wc->radmode[chan->chanpos - 1] |= RADMODE_INVERTCOR; else wc->radmode[chan->chanpos - 1] &= ~RADMODE_INVERTCOR; return 0; case ZT_RADPAR_IGNORECOR: if (stack.p.data) wc->radmode[chan->chanpos - 1] |= RADMODE_IGNORECOR; else wc->radmode[chan->chanpos - 1] &= ~RADMODE_IGNORECOR; return 0; case ZT_RADPAR_IGNORECT: if (stack.p.data) wc->radmode[chan->chanpos - 1] |= RADMODE_IGNORECT; else wc->radmode[chan->chanpos - 1] &= ~RADMODE_IGNORECT; return 0; case ZT_RADPAR_EXTRXTONE: if (stack.p.data) wc->radmode[chan->chanpos - 1] |= RADMODE_EXTTONE; else wc->radmode[chan->chanpos - 1] &= ~RADMODE_EXTTONE; if (stack.p.data > 1) wc->radmode[chan->chanpos - 1] |= RADMODE_EXTINVERT; else wc->radmode[chan->chanpos - 1] &= ~RADMODE_EXTINVERT; return 0; case ZT_RADPAR_DEBOUNCETIME: wc->debouncetime[chan->chanpos - 1] = stack.p.data; return 0; case ZT_RADPAR_RXGAIN: /* if out of range */ if ((stack.p.data <= -1200) || (stack.p.data > 1552)) { return -EINVAL; } wc->rxgain[chan->chanpos - 1] = stack.p.data + 1199; break; case ZT_RADPAR_TXGAIN: /* if out of range */ if (wc->radmode[chan->chanpos -1] & 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; } } wc->txgain[chan->chanpos - 1] = stack.p.data + 3599; break; case ZT_RADPAR_DEEMP: if (stack.p.data) wc->radmode[chan->chanpos - 1] |= RADMODE_DEEMP; else wc->radmode[chan->chanpos - 1] &= ~RADMODE_DEEMP; wc->rxgain[chan->chanpos - 1] = 1199; break; case ZT_RADPAR_PREEMP: if (stack.p.data) wc->radmode[chan->chanpos - 1] |= RADMODE_PREEMP; else wc->radmode[chan->chanpos - 1] &= ~RADMODE_PREEMP; wc->txgain[chan->chanpos - 1] = 3599; break; default: return -EINVAL; } qrv_dosetup(chan,wc); return 0; default: return -ENOTTY; } return 0; } static int wctdm_open(struct zt_chan *chan) { struct wctdm *wc = chan->pvt; if (!(wc->cardflag & (1 << (chan->chanpos - 1)))) return -ENODEV; if (wc->dead) return -ENODEV; wc->usecount++; #ifndef LINUX26 MOD_INC_USE_COUNT; #else try_module_get(THIS_MODULE); #endif return 0; } static int wctdm_watchdog(struct zt_span *span, int event) { printk("TDM: Called watchdog\n"); return 0; } static int wctdm_close(struct zt_chan *chan) { struct wctdm *wc = chan->pvt; int x; signed char reg; wc->usecount--; #ifndef LINUX26 MOD_DEC_USE_COUNT; #else module_put(THIS_MODULE); #endif for (x=0;xcards;x++) { if (wc->modtype[x] == MOD_TYPE_FXS) wc->mods[x].fxs.idletxhookstate = 1; if (wc->modtype[x] == MOD_TYPE_QRV) { int qrvcard = x & 0xfc; wc->qrvhook[x] = 0; wc->qrvhook[x + 2] = 0xff; wc->debouncetime[x] = QRV_DEBOUNCETIME; wc->qrvdebtime[x] = 0; wc->radmode[x] = 0; wc->txgain[x] = 3599; wc->rxgain[x] = 1199; reg = 0; if (!wc->qrvhook[qrvcard]) reg |= 1; if (!wc->qrvhook[qrvcard + 1]) reg |= 0x10; wc->sethook[qrvcard] = CMD_WR(3, reg); qrv_dosetup(chan,wc); } } /* If we're dead, release us now */ if (!wc->usecount && wc->dead) wctdm_release(wc); return 0; } static int wctdm_hooksig(struct zt_chan *chan, zt_txsig_t txsig) { struct wctdm *wc = chan->pvt; int reg=0,qrvcard; if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_QRV) { qrvcard = (chan->chanpos - 1) & 0xfc; switch(txsig) { case ZT_TXSIG_START: case ZT_TXSIG_OFFHOOK: wc->qrvhook[chan->chanpos - 1] = 1; break; case ZT_TXSIG_ONHOOK: wc->qrvhook[chan->chanpos - 1] = 0; break; default: printk("wctdm24xxp: Can't set tx state to %d\n", txsig); } reg = 0; if (!wc->qrvhook[qrvcard]) reg |= 1; if (!wc->qrvhook[qrvcard + 1]) reg |= 0x10; wc->sethook[qrvcard] = CMD_WR(3, reg); /* wctdm_setreg(wc, qrvcard, 3, reg); */ } else if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) { switch(txsig) { case ZT_TXSIG_START: case ZT_TXSIG_OFFHOOK: wc->mods[chan->chanpos - 1].fxo.offhook = 1; wc->sethook[chan->chanpos - 1] = CMD_WR(5, 0x9); /* wctdm_setreg(wc, chan->chanpos - 1, 5, 0x9); */ break; case ZT_TXSIG_ONHOOK: wc->mods[chan->chanpos - 1].fxo.offhook = 0; wc->sethook[chan->chanpos - 1] = CMD_WR(5, 0x8); /* wctdm_setreg(wc, chan->chanpos - 1, 5, 0x8); */ break; default: printk("wctdm24xxp: Can't set tx state to %d\n", txsig); } } else { switch(txsig) { case ZT_TXSIG_ONHOOK: switch(chan->sig) { case ZT_SIG_EM: case ZT_SIG_FXOKS: case ZT_SIG_FXOLS: wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x10 | wc->mods[chan->chanpos - 1].fxs.idletxhookstate; break; case ZT_SIG_FXOGS: wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x13; break; } break; case ZT_TXSIG_OFFHOOK: switch(chan->sig) { case ZT_SIG_EM: wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x15; break; default: wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x10 | wc->mods[chan->chanpos - 1].fxs.idletxhookstate; break; } break; case ZT_TXSIG_START: wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x14; break; case ZT_TXSIG_KEWL: wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x10; break; default: printk("wctdm24xxp: Can't set tx state to %d\n", txsig); } if (debug & DEBUG_CARD) printk("Setting FXS hook state to %d (%02x)\n", txsig, reg); wc->sethook[chan->chanpos - 1] = CMD_WR(64, wc->mods[chan->chanpos - 1].fxs.lasttxhook); /* wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mods[chan->chanpos - 1].fxs.lasttxhook); */ } return 0; } static void wctdm_dacs_connect(struct wctdm *wc, int srccard, int dstcard) { if (wc->dacssrc[dstcard] > - 1) { printk("wctdm_dacs_connect: Can't have double sourcing yet!\n"); return; } if (!((wc->modtype[srccard] == MOD_TYPE_FXS)||(wc->modtype[srccard] == MOD_TYPE_FXO))){ printk("wctdm_dacs_connect: Unsupported modtype for card %d\n", srccard); return; } if (!((wc->modtype[dstcard] == MOD_TYPE_FXS)||(wc->modtype[dstcard] == MOD_TYPE_FXO))){ printk("wctdm_dacs_connect: Unsupported modtype for card %d\n", dstcard); return; } if (debug) printk("connect %d => %d\n", srccard, dstcard); wc->dacssrc[dstcard] = srccard; /* make srccard transmit to srccard+24 on the TDM bus */ if (wc->modtype[srccard] == MOD_TYPE_FXS) { /* proslic */ wctdm_setreg(wc, srccard, PCM_XMIT_START_COUNT_LSB, ((srccard+24) * 8) & 0xff); wctdm_setreg(wc, srccard, PCM_XMIT_START_COUNT_MSB, ((srccard+24) * 8) >> 8); } else if(wc->modtype[srccard] == MOD_TYPE_FXO) { /* daa */ wctdm_setreg(wc, srccard, 34, ((srccard+24) * 8) & 0xff); /* TX */ wctdm_setreg(wc, srccard, 35, ((srccard+24) * 8) >> 8); /* TX */ } /* have dstcard receive from srccard+24 on the TDM bus */ if (wc->modtype[dstcard] == MOD_TYPE_FXS) { /* proslic */ wctdm_setreg(wc, dstcard, PCM_RCV_START_COUNT_LSB, ((srccard+24) * 8) & 0xff); wctdm_setreg(wc, dstcard, PCM_RCV_START_COUNT_MSB, ((srccard+24) * 8) >> 8); } else if(wc->modtype[dstcard] == MOD_TYPE_FXO) { /* daa */ wctdm_setreg(wc, dstcard, 36, ((srccard+24) * 8) & 0xff); /* RX */ wctdm_setreg(wc, dstcard, 37, ((srccard+24) * 8) >> 8); /* RX */ } } static void wctdm_dacs_disconnect(struct wctdm *wc, int card) { if (wc->dacssrc[card] > -1) { if (debug) printk("wctdm_dacs_disconnect: restoring TX for %d and RX for %d\n",wc->dacssrc[card], card); /* restore TX (source card) */ if(wc->modtype[wc->dacssrc[card]] == MOD_TYPE_FXS){ wctdm_setreg(wc, wc->dacssrc[card], PCM_XMIT_START_COUNT_LSB, (wc->dacssrc[card] * 8) & 0xff); wctdm_setreg(wc, wc->dacssrc[card], PCM_XMIT_START_COUNT_MSB, (wc->dacssrc[card] * 8) >> 8); } else if(wc->modtype[wc->dacssrc[card]] == MOD_TYPE_FXO){ wctdm_setreg(wc, card, 34, (card * 8) & 0xff); wctdm_setreg(wc, card, 35, (card * 8) >> 8); } else { printk("WARNING: wctdm_dacs_disconnect() called on unsupported modtype\n"); } /* restore RX (this card) */ if(wc->modtype[card] == MOD_TYPE_FXS){ wctdm_setreg(wc, card, PCM_RCV_START_COUNT_LSB, (card * 8) & 0xff); wctdm_setreg(wc, card, PCM_RCV_START_COUNT_MSB, (card * 8) >> 8); } else if(wc->modtype[card] == MOD_TYPE_FXO){ wctdm_setreg(wc, card, 36, (card * 8) & 0xff); wctdm_setreg(wc, card, 37, (card * 8) >> 8); } else { printk("WARNING: wctdm_dacs_disconnect() called on unsupported modtype\n"); } wc->dacssrc[card] = -1; } } static int wctdm_dacs(struct zt_chan *dst, struct zt_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) printk("dacs connecct: %d -> %d!\n\n", src->chanpos, dst->chanpos); } else { wctdm_dacs_disconnect(wc, dst->chanpos - 1); if (debug) printk("dacs disconnect: %d!\n", dst->chanpos); } return 0; } static int wctdm_initialize(struct wctdm *wc) { int x; struct pci_dev *pdev = voicebus_get_pci_dev(wc->vb); /* Zapata stuff */ sprintf(wc->span.name, "WCTDM/%d", wc->pos); snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Board %d", wc->variety, wc->pos + 1); snprintf(wc->span.location, sizeof(wc->span.location) - 1, "PCI%s Bus %02d Slot %02d", (wc->flags[0] & FLAG_EXPRESS) ? " Express" : "", pdev->bus->number, PCI_SLOT(pdev->devfn) + 1); wc->span.manufacturer = "Digium"; strncpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype) - 1); if (alawoverride) { printk("ALAW override parameter detected. Device will be operating in ALAW\n"); wc->span.deflaw = ZT_LAW_ALAW; } else wc->span.deflaw = ZT_LAW_MULAW; for (x=0;xcards;x++) { sprintf(wc->chans[x].name, "WCTDM/%d/%d", wc->pos, x); wc->chans[x].sigcap = ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_SF | ZT_SIG_EM | ZT_SIG_CLEAR; wc->chans[x].sigcap |= ZT_SIG_FXSKS | ZT_SIG_FXSLS | ZT_SIG_SF | ZT_SIG_CLEAR; wc->chans[x].chanpos = x+1; wc->chans[x].pvt = wc; } wc->span.chans = wc->chans; wc->span.channels = wc->type; wc->span.irq = pdev->irq; wc->span.hooksig = wctdm_hooksig; wc->span.open = wctdm_open; wc->span.close = wctdm_close; wc->span.flags = ZT_FLAG_RBS; wc->span.ioctl = wctdm_ioctl; wc->span.watchdog = wctdm_watchdog; wc->span.dacs= wctdm_dacs; #ifdef VPM_SUPPORT wc->span.echocan_with_params = wctdm_echocan_with_params; #endif init_waitqueue_head(&wc->span.maintq); wc->span.pvt = wc; return 0; } static void wctdm_post_initialize(struct wctdm *wc) { int x; /* Finalize signalling */ for (x = 0; x cards; x++) { if (wc->cardflag & (1 << x)) { if (wc->modtype[x] == MOD_TYPE_FXO) wc->chans[x].sigcap = ZT_SIG_FXSKS | ZT_SIG_FXSLS | ZT_SIG_SF | ZT_SIG_CLEAR; else if (wc->modtype[x] == MOD_TYPE_FXS) wc->chans[x].sigcap = ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_SF | ZT_SIG_EM | ZT_SIG_CLEAR; else if (wc->modtype[x] == MOD_TYPE_QRV) wc->chans[x].sigcap = ZT_SIG_SF | ZT_SIG_EM | ZT_SIG_CLEAR; } else if (!(wc->chans[x].sigcap & ZT_SIG_BROKEN)) { wc->chans[x].sigcap = 0; } } if (wc->vpm) strncat(wc->span.devicetype, " with VPM100M", sizeof(wc->span.devicetype) - 1); else if (wc->vpm150m) strncat(wc->span.devicetype, " with VPMADT032", sizeof(wc->span.devicetype) - 1); } #ifdef VPM_SUPPORT #ifdef VPM150M_SUPPORT void vpm150m_set_chanconfig_from_state(struct adt_lec_params * parms, int channum, GpakChannelConfig_t *chanconfig) { chanconfig->PcmInPortA = 3; chanconfig->PcmInSlotA = channum; chanconfig->PcmOutPortA = SerialPortNull; chanconfig->PcmOutSlotA = channum; chanconfig->PcmInPortB = 2; chanconfig->PcmInSlotB = channum; chanconfig->PcmOutPortB = 3; chanconfig->PcmOutSlotB = channum; if (vpmdtmfsupport) { chanconfig->ToneTypesA = DTMF_tone; chanconfig->MuteToneA = Enabled; chanconfig->FaxCngDetA = Enabled; } else { chanconfig->ToneTypesA = Null_tone; chanconfig->MuteToneA = Disabled; chanconfig->FaxCngDetA = Disabled; } chanconfig->ToneTypesB = Null_tone; chanconfig->EcanEnableA = Enabled; chanconfig->EcanEnableB = Disabled; chanconfig->MuteToneB = Disabled; chanconfig->FaxCngDetB = Disabled; if (alawoverride) chanconfig->SoftwareCompand = cmpPCMA; else chanconfig->SoftwareCompand = cmpPCMU; chanconfig->FrameRate = rate2ms; chanconfig->EcanParametersA.EcanTapLength = 1024; chanconfig->EcanParametersA.EcanNlpType = parms->nlp_type; chanconfig->EcanParametersA.EcanAdaptEnable = 1; chanconfig->EcanParametersA.EcanG165DetEnable = 1; chanconfig->EcanParametersA.EcanDblTalkThresh = 6; chanconfig->EcanParametersA.EcanNlpThreshold = parms->nlp_threshold; chanconfig->EcanParametersA.EcanNlpConv = 0; chanconfig->EcanParametersA.EcanNlpUnConv = 0; chanconfig->EcanParametersA.EcanNlpMaxSuppress = parms->nlp_max_suppress; chanconfig->EcanParametersA.EcanCngThreshold = 43; chanconfig->EcanParametersA.EcanAdaptLimit = 50; chanconfig->EcanParametersA.EcanCrossCorrLimit = 15; chanconfig->EcanParametersA.EcanNumFirSegments = 3; chanconfig->EcanParametersA.EcanFirSegmentLen = 64; chanconfig->EcanParametersB.EcanTapLength = 1024; chanconfig->EcanParametersB.EcanNlpType = parms->nlp_type; chanconfig->EcanParametersB.EcanAdaptEnable = 1; chanconfig->EcanParametersB.EcanG165DetEnable = 1; chanconfig->EcanParametersB.EcanDblTalkThresh = 6; chanconfig->EcanParametersB.EcanNlpThreshold = parms->nlp_threshold; chanconfig->EcanParametersB.EcanNlpConv = 0; chanconfig->EcanParametersB.EcanNlpUnConv = 0; chanconfig->EcanParametersB.EcanNlpMaxSuppress = parms->nlp_max_suppress; chanconfig->EcanParametersB.EcanCngThreshold = 43; chanconfig->EcanParametersB.EcanAdaptLimit = 50; chanconfig->EcanParametersB.EcanCrossCorrLimit = 15; chanconfig->EcanParametersB.EcanNumFirSegments = 3; chanconfig->EcanParametersB.EcanFirSegmentLen = 64; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) static void vpm150m_bh(void *data) { struct vpm150m *vpm150m = data; #else static void vpm150m_bh(struct work_struct *data) { struct vpm150m *vpm150m = container_of(data, struct vpm150m, work); #endif struct wctdm *wc = vpm150m->wc; int i; for (i = 0; i < wc->type; i++) { int enable = -1; if (test_bit(i, &vpm150m->desireddtmfmutestate)) { if (!test_bit(i, &vpm150m->curdtmfmutestate)) { enable = 1; } } else { if (test_bit(i, &vpm150m->curdtmfmutestate)) { enable = 0; } } if (enable > -1) { unsigned int start = wc->intcount; GPAK_AlgControlStat_t pstatus; int res; if (enable) { res = gpakAlgControl(vpm150m->dspid, i, EnableDTMFMuteA, &pstatus); if (debug & DEBUG_ECHOCAN) printk("DTMF mute enable took %d ms\n", wc->intcount - start); } else { res = gpakAlgControl(vpm150m->dspid, i, DisableDTMFMuteA, &pstatus); if (debug & DEBUG_ECHOCAN) printk("DTMF mute disable took %d ms\n", wc->intcount - start); } if (!res) change_bit(i, &vpm150m->curdtmfmutestate); } } if (test_bit(VPM150M_DTMFDETECT, &vpm150m->control)) { unsigned short channel; GpakAsyncEventCode_t eventcode; GpakAsyncEventData_t eventdata; gpakReadEventFIFOMessageStat_t res; unsigned int start = wc->intcount; do { res = gpakReadEventFIFOMessage(vpm150m->dspid, &channel, &eventcode, &eventdata); if (debug & DEBUG_ECHOCAN) printk("ReadEventFIFOMessage took %d ms\n", wc->intcount - start); if (res == RefInvalidEvent || res == RefDspCommFailure) { printk("VPM Comm Error\n"); continue; } if (res == RefNoEventAvail) { continue; } if (eventcode == EventToneDetect) { GpakToneCodes_t tone = eventdata.toneEvent.ToneCode; int duration = eventdata.toneEvent.ToneDuration; char zaptone = vpm150mtone_to_zaptone(tone); if (debug & DEBUG_ECHOCAN) printk("Channel %d: Detected DTMF tone %d of duration %d!!!\n", channel + 1, tone, duration); if (test_bit(channel, &wc->dtmfmask) && (eventdata.toneEvent.ToneDuration > 0)) { struct zt_chan *chan = &wc->chans[channel]; if ((tone != EndofMFDigit) && (zaptone != 0)) { vpm150m->curtone[channel] = tone; if (test_bit(channel, &vpm150m->curdtmfmutestate)) { unsigned long flags; int y; /* Mute the audio data buffers */ spin_lock_irqsave(&chan->lock, flags); for (y = 0; y < chan->numbufs; y++) { if ((chan->inreadbuf > -1) && (chan->readidx[y])) memset(chan->readbuf[chan->inreadbuf], ZT_XLAW(0, chan), chan->readidx[y]); } spin_unlock_irqrestore(&chan->lock, flags); } if (!test_bit(channel, &wc->dtmfactive)) { if (debug & DEBUG_ECHOCAN) printk("Queuing DTMFDOWN %c\n", zaptone); set_bit(channel, &wc->dtmfactive); zt_qevent_lock(chan, (ZT_EVENT_DTMFDOWN | zaptone)); } } else if ((tone == EndofMFDigit) && test_bit(channel, &wc->dtmfactive)) { if (debug & DEBUG_ECHOCAN) printk("Queuing DTMFUP %c\n", vpm150mtone_to_zaptone(vpm150m->curtone[channel])); zt_qevent_lock(chan, (ZT_EVENT_DTMFUP | vpm150mtone_to_zaptone(vpm150m->curtone[channel]))); clear_bit(channel, &wc->dtmfactive); } } } } while ((res != RefNoEventAvail) && (res != RefInvalidEvent) && (res != RefDspCommFailure)); } for (i = 0; i < wc->type; i++) { unsigned int start = wc->intcount; GPAK_AlgControlStat_t pstatus; int res = 1; if ((vpm150m->desiredecstate[i].nlp_type != vpm150m->curecstate[i].nlp_type) || (vpm150m->desiredecstate[i].nlp_threshold != vpm150m->curecstate[i].nlp_threshold) || (vpm150m->desiredecstate[i].nlp_max_suppress != vpm150m->curecstate[i].nlp_max_suppress)) { GPAK_ChannelConfigStat_t cstatus; GPAK_TearDownChanStat_t tstatus; GpakChannelConfig_t chanconfig; if (debug & DEBUG_ECHOCAN) printk("Reconfiguring chan %d for nlp %d, nlp_thresh %d, and max_supp %d\n", i + 1, vpm150m->desiredecstate[i].nlp_type, vpm150m->desiredecstate[i].nlp_threshold, vpm150m->desiredecstate[i].nlp_max_suppress); vpm150m_set_chanconfig_from_state(&vpm150m->desiredecstate[i], i, &chanconfig); if ((res = gpakTearDownChannel(vpm150m->dspid, i, &tstatus))) { goto vpm_bh_out; } if ((res = gpakConfigureChannel(vpm150m->dspid, i, tdmToTdm, &chanconfig, &cstatus))) { goto vpm_bh_out; } if (!vpm150m->desiredecstate[i].tap_length) res = gpakAlgControl(vpm150m->dspid, i, BypassEcanA, &pstatus); } else if (vpm150m->desiredecstate[i].tap_length != vpm150m->curecstate[i].tap_length) { if (vpm150m->desiredecstate[i].tap_length) { res = gpakAlgControl(vpm150m->dspid, i, EnableEcanA, &pstatus); if (debug & DEBUG_ECHOCAN) printk("Echocan enable took %d ms\n", wc->intcount - start); } else { res = gpakAlgControl(vpm150m->dspid, i, BypassEcanA, &pstatus); if (debug & DEBUG_ECHOCAN) printk("Echocan disable took %d ms\n", wc->intcount - start); } } vpm_bh_out: if (!res) vpm150m->curecstate[i] = vpm150m->desiredecstate[i]; } return; } static int vpm150m_config_hw(struct wctdm *wc) { struct vpm150m *vpm150m = wc->vpm150m; gpakConfigPortStatus_t configportstatus; GpakPortConfig_t portconfig; GPAK_PortConfigStat_t pstatus; GpakChannelConfig_t chanconfig; GPAK_ChannelConfigStat_t cstatus; GPAK_AlgControlStat_t algstatus; int res, i; memset(&portconfig, 0, sizeof(GpakPortConfig_t)); /* First Serial Port config */ portconfig.SlotsSelect1 = SlotCfgNone; portconfig.FirstBlockNum1 = 0; portconfig.FirstSlotMask1 = 0x0000; portconfig.SecBlockNum1 = 1; portconfig.SecSlotMask1 = 0x0000; portconfig.SerialWordSize1 = SerWordSize8; portconfig.CompandingMode1 = cmpNone; portconfig.TxFrameSyncPolarity1 = FrameSyncActHigh; portconfig.RxFrameSyncPolarity1 = FrameSyncActHigh; portconfig.TxClockPolarity1 = SerClockActHigh; portconfig.RxClockPolarity1 = SerClockActHigh; portconfig.TxDataDelay1 = DataDelay0; portconfig.RxDataDelay1 = DataDelay0; portconfig.DxDelay1 = Disabled; portconfig.ThirdSlotMask1 = 0x0000; portconfig.FouthSlotMask1 = 0x0000; portconfig.FifthSlotMask1 = 0x0000; portconfig.SixthSlotMask1 = 0x0000; portconfig.SevenSlotMask1 = 0x0000; portconfig.EightSlotMask1 = 0x0000; /* Second Serial Port config */ portconfig.SlotsSelect2 = SlotCfg2Groups; portconfig.FirstBlockNum2 = 0; portconfig.FirstSlotMask2 = 0xffff; portconfig.SecBlockNum2 = 1; portconfig.SecSlotMask2 = 0xffff; portconfig.SerialWordSize2 = SerWordSize8; portconfig.CompandingMode2 = cmpNone; portconfig.TxFrameSyncPolarity2 = FrameSyncActHigh; portconfig.RxFrameSyncPolarity2 = FrameSyncActHigh; portconfig.TxClockPolarity2 = SerClockActHigh; portconfig.RxClockPolarity2 = SerClockActLow; portconfig.TxDataDelay2 = DataDelay0; portconfig.RxDataDelay2 = DataDelay0; portconfig.DxDelay2 = Disabled; portconfig.ThirdSlotMask2 = 0x0000; portconfig.FouthSlotMask2 = 0x0000; portconfig.FifthSlotMask2 = 0x0000; portconfig.SixthSlotMask2 = 0x0000; portconfig.SevenSlotMask2 = 0x0000; portconfig.EightSlotMask2 = 0x0000; /* Third Serial Port Config */ portconfig.SlotsSelect3 = SlotCfg2Groups; portconfig.FirstBlockNum3 = 0; portconfig.FirstSlotMask3 = 0xffff; portconfig.SecBlockNum3 = 1; portconfig.SecSlotMask3 = 0xffff; portconfig.SerialWordSize3 = SerWordSize8; portconfig.CompandingMode3 = cmpNone; portconfig.TxFrameSyncPolarity3 = FrameSyncActHigh; portconfig.RxFrameSyncPolarity3 = FrameSyncActHigh; portconfig.TxClockPolarity3 = SerClockActHigh; portconfig.RxClockPolarity3 = SerClockActLow; portconfig.TxDataDelay3 = DataDelay0; portconfig.RxDataDelay3 = DataDelay0; portconfig.DxDelay3 = Disabled; portconfig.ThirdSlotMask3 = 0x0000; portconfig.FouthSlotMask3 = 0x0000; portconfig.FifthSlotMask3 = 0x0000; portconfig.SixthSlotMask3 = 0x0000; portconfig.SevenSlotMask3 = 0x0000; portconfig.EightSlotMask3 = 0x0000; if ((configportstatus = gpakConfigurePorts(vpm150m->dspid, &portconfig, &pstatus))) { printk("Configuration of ports failed (%d)!\n", configportstatus); return -1; } else { if (debug & DEBUG_ECHOCAN) printk("Configured McBSP ports successfully\n"); } if ((res = gpakPingDsp(vpm150m->dspid, &vpm150m->version))) { printk("Error pinging DSP (%d)\n", res); return -1; } for (i = 0; i < wc->type; i++) { vpm150m->curecstate[i].tap_length = 0; vpm150m->curecstate[i].nlp_type = vpmnlptype; vpm150m->curecstate[i].nlp_threshold = vpmnlpthresh; vpm150m->curecstate[i].nlp_max_suppress = vpmnlpmaxsupp; vpm150m->desiredecstate[i].tap_length = 0; vpm150m->desiredecstate[i].nlp_type = vpmnlptype; vpm150m->desiredecstate[i].nlp_threshold = vpmnlpthresh; vpm150m->desiredecstate[i].nlp_max_suppress = vpmnlpmaxsupp; vpm150m_set_chanconfig_from_state(&vpm150m->curecstate[i], i, &chanconfig); if ((res = gpakConfigureChannel(vpm150m->dspid, i, tdmToTdm, &chanconfig, &cstatus))) { printk("Unable to configure channel (%d)\n", res); if (res == 1) { printk("Reason %d\n", cstatus); } return -1; } if ((res = gpakAlgControl(vpm150m->dspid, i, BypassEcanA, &algstatus))) { printk("Unable to disable echo can on channel %d (reason %d:%d)\n", i + 1, res, algstatus); return -1; } if (vpmdtmfsupport) { if ((res = gpakAlgControl(vpm150m->dspid, i, DisableDTMFMuteA, &algstatus))) { printk("Unable to disable dtmf muting on channel %d (reason %d:%d)\n", i + 1, res, algstatus); return -1; } } } if ((res = gpakPingDsp(vpm150m->dspid, &vpm150m->version))) { printk("Error pinging DSP (%d)\n", res); return -1; } vpm150m->wq = create_singlethread_workqueue("wctdm24xxp"); vpm150m->wc = wc; if (!vpm150m->wq) { printk("Unable to create work queue!\n"); return -1; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) INIT_WORK(&vpm150m->work, vpm150m_bh, vpm150m); #else INIT_WORK(&vpm150m->work, vpm150m_bh); #endif /* Turn on DTMF detection */ if (vpmdtmfsupport) set_bit(VPM150M_DTMFDETECT, &vpm150m->control); set_bit(VPM150M_ACTIVE, &vpm150m->control); return 0; } #endif /* VPM150M_SUPPORT */ enum vpmadt032_init_result { VPMADT032_SUCCESS, VPMADT032_NOT_FOUND, VPMADT032_FAILED, VPMADT032_DISABLED, }; static enum vpmadt032_init_result wctdm_vpm150m_init(struct wctdm *wc) { unsigned short i; struct vpm150m *vpm150m; unsigned short reg; unsigned long flags; struct pci_dev* pdev = voicebus_get_pci_dev(wc->vb); enum vpmadt032_init_result res = VPMADT032_FAILED; #ifdef VPM150M_SUPPORT struct wctdm_firmware fw; struct firmware embedded_firmware; const struct firmware *firmware = &embedded_firmware; #if !defined(HOTPLUG_FIRMWARE) extern void _binary_zaptel_fw_vpmadt032_bin_size; extern u8 _binary_zaptel_fw_vpmadt032_bin_start[]; #else static const char vpmadt032_firmware[] = "zaptel-fw-vpmadt032.bin"; #endif gpakDownloadStatus_t downloadstatus; gpakPingDspStat_t pingstatus; #endif if (!vpmsupport) { printk("VPM: Support Disabled\n"); wc->vpm150m = NULL; return VPMADT032_DISABLED; } vpm150m = kmalloc(sizeof(struct vpm150m), GFP_KERNEL); if (!vpm150m) { printk("Unable to allocate VPM150M!\n"); return VPMADT032_FAILED; } memset(vpm150m, 0, sizeof(struct vpm150m)); /* Init our vpm150m struct */ sema_init(&vpm150m->sem, 1); vpm150m->curpage = 0x80; for (i = 0; i < WC_MAX_IFACES; i++) { if (ifaces[i] == wc) vpm150m->dspid = i; } if (debug & DEBUG_ECHOCAN) printk("Setting VPMADT032 DSP ID to %d\n", vpm150m->dspid); spin_lock_irqsave(&wc->reglock, flags); wc->vpm150m = vpm150m; spin_unlock_irqrestore(&wc->reglock, flags); for (i = 0; i < 10; i++) schluffen(&wc->regq); if (debug & DEBUG_ECHOCAN) printk("VPMADT032 Testing page access: "); for (i = 0; i < 0xf; i++) { int x; for (x = 0; x < 3; x++) { wctdm_vpm150m_setpage(wc, i); reg = wctdm_vpm150m_getpage(wc); if (reg != i) { if (debug & DEBUG_ECHOCAN) printk("Failed: Sent %x != %x VPMADT032 Failed HI page test\n", i, reg); res = VPMADT032_NOT_FOUND; goto failed_exit; } } } if (debug & DEBUG_ECHOCAN) printk("Passed\n"); /* Set us up to page 0 */ wctdm_vpm150m_setpage(wc, 0); if (debug & DEBUG_ECHOCAN) printk("VPMADT032 now doing address test: "); for (i = 0; i < 16; i++) { int x; for (x = 0; x < 2; x++) { wctdm_vpm150m_setreg(wc, 1, 0x1000, &i); wctdm_vpm150m_getreg(wc, 1, 0x1000, ®); if (reg != i) { printk("VPMADT032 Failed address test\n"); goto failed_exit; } } } if (debug & DEBUG_ECHOCAN) printk("Passed\n"); #ifndef VPM150M_SUPPORT printk("Found VPMADT032 module but it is not able to function in anything less than a version 2.6 kernel\n"); printk("Please update your kernel to a 2.6 or later kernel to enable it\n"); goto failed_exit; #else #if 0 /* Load the firmware */ set_bit(VPM150M_SPIRESET, &vpm150m->control); /* Wait for it to boot */ msleep(7000); pingstatus = gpakPingDsp(vpm150m->dspid, &version); if (pingstatus || (version != 0x106)) { #endif #if defined(HOTPLUG_FIRMWARE) if ((request_firmware(&firmware, vpmadt032_firmware, &pdev->dev) != 0) || !firmware) { printk("VPMADT032: firmware %s not available from userspace\n", vpmadt032_firmware); goto failed_exit; } #else embedded_firmware.data = _binary_zaptel_fw_vpmadt032_bin_start; embedded_firmware.size = (size_t) &_binary_zaptel_fw_vpmadt032_bin_size; #endif fw.fw = firmware; fw.offset = 0; set_bit(VPM150M_HPIRESET, &vpm150m->control); while (test_bit(VPM150M_HPIRESET, &vpm150m->control)) schluffen(&wc->regq); printk("VPMADT032 Loading firwmare... "); downloadstatus = gpakDownloadDsp(vpm150m->dspid, &fw); if (firmware != &embedded_firmware) release_firmware(firmware); if (downloadstatus != 0) { printk("Unable to download firmware to VPMADT032 with cause %d\n", downloadstatus); goto failed_exit; } else { printk("Success\n"); } set_bit(VPM150M_SWRESET, &vpm150m->control); while (test_bit(VPM150M_SWRESET, &vpm150m->control)) schluffen(&wc->regq); #if 0 } #endif pingstatus = gpakPingDsp(vpm150m->dspid, &vpm150m->version); if (!pingstatus) { if (debug & DEBUG_ECHOCAN) printk("Version of DSP is %x\n", vpm150m->version); } else { printk("VPMADT032 Failed! Unable to ping the DSP (%d)!\n", pingstatus); goto failed_exit; } if (vpm150m_config_hw(wc)) { goto failed_exit; } return VPMADT032_SUCCESS; #endif /* VPM150M_SUPPORT */ failed_exit: spin_lock_irqsave(&wc->reglock, flags); wc->vpm150m = NULL; spin_unlock_irqrestore(&wc->reglock, flags); kfree(vpm150m); return res; } static void wctdm_vpm_set_dtmf_threshold(struct wctdm *wc, unsigned int threshold) { unsigned int x; for (x = 0; x < 4; x++) { wctdm_vpm_out(wc, x, 0xC4, (threshold >> 8) & 0xFF); wctdm_vpm_out(wc, x, 0xC5, (threshold & 0xFF)); } printk("VPM: DTMF threshold set to %d\n", threshold); } static void wctdm_vpm_init(struct wctdm *wc) { unsigned char reg; unsigned int mask; unsigned int ver; unsigned char vpmver=0; unsigned int i, x, y; if (!vpmsupport) { printk("VPM: Support Disabled\n"); wc->vpm = 0; return; } for (x=0;xvpm = 0; return; } if (!x) { vpmver = wctdm_vpm_in(wc, x, 0x1a6) & 0xf; printk("VPM Revision: %02x\n", vpmver); } /* Setup GPIO's */ for (y=0;y<4;y++) { wctdm_vpm_out(wc, x, 0x1a8 + y, 0x00); /* GPIO out */ if (y == 3) wctdm_vpm_out(wc, x, 0x1ac + y, 0x00); /* GPIO dir */ else wctdm_vpm_out(wc, x, 0x1ac + y, 0xff); /* GPIO dir */ wctdm_vpm_out(wc, x, 0x1b0 + y, 0x00); /* GPIO sel */ } /* Setup TDM path - sets fsync and tdm_clk as inputs */ reg = wctdm_vpm_in(wc, x, 0x1a3); /* misc_con */ wctdm_vpm_out(wc, x, 0x1a3, reg & ~2); /* Setup Echo length (256 taps) */ wctdm_vpm_out(wc, x, 0x022, 0); /* Setup timeslots */ if (vpmver == 0x01) { wctdm_vpm_out(wc, x, 0x02f, 0x00); wctdm_vpm_out(wc, x, 0x023, 0xff); mask = 0x11111111 << x; } else { wctdm_vpm_out(wc, x, 0x02f, 0x20 | (x << 3)); wctdm_vpm_out(wc, x, 0x023, 0x3f); mask = 0x0000003f; } /* Setup the tdm channel masks for all chips*/ for (i = 0; i < 4; i++) wctdm_vpm_out(wc, x, 0x33 - i, (mask >> (i << 3)) & 0xff); /* Setup convergence rate */ reg = wctdm_vpm_in(wc,x,0x20); reg &= 0xE0; if (alawoverride) { if (!x) printk("VPM: A-law mode\n"); reg |= 0x01; } else { if (!x) printk("VPM: U-law mode\n"); reg &= ~0x01; } wctdm_vpm_out(wc,x,0x20,(reg | 0x20)); /* Initialize echo cans */ for (i = 0 ; i < MAX_TDM_CHAN; i++) { if (mask & (0x00000001 << i)) wctdm_vpm_out(wc,x,i,0x00); } for (i=0;i<30;i++) schluffen(&wc->regq); /* Put in bypass mode */ for (i = 0 ; i < MAX_TDM_CHAN ; i++) { if (mask & (0x00000001 << i)) { wctdm_vpm_out(wc,x,i,0x01); } } /* Enable bypass */ for (i = 0 ; i < MAX_TDM_CHAN ; i++) { if (mask & (0x00000001 << i)) wctdm_vpm_out(wc,x,0x78 + i,0x01); } /* Enable DTMF detectors (always DTMF detect all spans) */ for (i = 0; i < 6; i++) { if (vpmver == 0x01) wctdm_vpm_out(wc, x, 0x98 + i, 0x40 | (i << 2) | x); else wctdm_vpm_out(wc, x, 0x98 + i, 0x40 | i); } for (i = 0xB8; i < 0xC0; i++) wctdm_vpm_out(wc, x, i, 0xFF); for (i = 0xC0; i < 0xC4; i++) wctdm_vpm_out(wc, x, i, 0xff); } /* set DTMF detection threshold */ wctdm_vpm_set_dtmf_threshold(wc, dtmfthreshold); if (vpmver == 0x01) wc->vpm = 2; else wc->vpm = 1; printk("Enabling VPM100 gain adjustments on any FXO ports found\n"); for (i = 0; i < wc->type; i++) { if (wc->modtype[i] == MOD_TYPE_FXO) { /* Apply negative Tx gain of 4.5db to DAA */ wctdm_setreg(wc, i, 38, 0x14); /* 4db */ wctdm_setreg(wc, i, 40, 0x15); /* 0.5db */ /* Apply negative Rx gain of 4.5db to DAA */ wctdm_setreg(wc, i, 39, 0x14); /* 4db */ wctdm_setreg(wc, i, 41, 0x15); /* 0.5db */ } } } #endif static int wctdm_locate_modules(struct wctdm *wc) { int x; unsigned long flags; unsigned int startinglatency = voicebus_current_latency(wc->vb); wc->ctlreg = 0x00; /* Make sure all units go into daisy chain mode */ spin_lock_irqsave(&wc->reglock, flags); wc->span.irqmisses = 0; for (x=0;xcards;x++) wc->modtype[x] = MOD_TYPE_FXSINIT; #ifdef VPM_SUPPORT wc->vpm = -1; for (x = wc->cards; x < wc->cards+NUM_EC; x++) wc->modtype[x] = MOD_TYPE_VPM; #endif spin_unlock_irqrestore(&wc->reglock, flags); /* Wait just a bit */ for (x=0;x<10;x++) schluffen(&wc->regq); spin_lock_irqsave(&wc->reglock, flags); for (x=0;xcards;x++) wc->modtype[x] = MOD_TYPE_FXS; spin_unlock_irqrestore(&wc->reglock, flags); #if 0 /* XXX */ cmddesc = 0; #endif /* 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->cards = wc->type; spin_unlock_irqrestore(&wc->reglock, flags); /* Reset modules */ for (x=0;xcards;x++) { int sane=0,ret=0,readi=0; retry: if (voicebus_current_latency(wc->vb) > startinglatency) { return -EAGAIN; } /* Init with Auto Calibration */ if (!(ret = wctdm_init_proslic(wc, x, 0, 0, sane))) { wc->cardflag |= (1 << x); if (debug & DEBUG_CARD) { readi = wctdm_getreg(wc,x,LOOP_I_LIMIT); printk("Proslic module %d loop current is %dmA\n",x, ((readi*3)+20)); } printk("Port %d: Installed -- AUTO FXS/DPO\n", x + 1); } else { if(ret!=-2) { sane=1; /* Init with Manual Calibration */ if (!wctdm_init_proslic(wc, x, 0, 1, sane)) { wc->cardflag |= (1 << x); if (debug & DEBUG_CARD) { readi = wctdm_getreg(wc,x,LOOP_I_LIMIT); printk("Proslic module %d loop current is %dmA\n",x, ((readi*3)+20)); } printk("Port %d: Installed -- MANUAL FXS\n",x + 1); } else { printk("Port %d: FAILED FXS (%s)\n", x + 1, fxshonormode ? fxo_modes[_opermode].name : "FCC"); wc->chans[x].sigcap = ZT_SIG_BROKEN | __ZT_SIG_FXO; } } else if (!(ret = wctdm_init_voicedaa(wc, x, 0, 0, sane))) { wc->cardflag |= (1 << x); printk("Port %d: Installed -- AUTO FXO (%s mode)\n",x + 1, fxo_modes[_opermode].name); } else if (!wctdm_init_qrvdri(wc,x)) { wc->cardflag |= 1 << x; printk("Port %d: Installed -- QRV DRI card\n",x + 1); } else { if ((wc->type != 24) && ((x & 0x3) == 1) && !wc->altcs[x]) { spin_lock_irqsave(&wc->reglock, flags); wc->altcs[x] = 2; if (wc->type == 4) { wc->altcs[x+1] = 3; wc->altcs[x+2] = 3; } wc->modtype[x] = MOD_TYPE_FXSINIT; spin_unlock_irqrestore(&wc->reglock, flags); schluffen(&wc->regq); schluffen(&wc->regq); spin_lock_irqsave(&wc->reglock, flags); wc->modtype[x] = MOD_TYPE_FXS; spin_unlock_irqrestore(&wc->reglock, flags); if (debug & DEBUG_CARD) printk("Trying port %d with alternate chip select\n", x + 1); goto retry; } else { printk("Port %d: Not installed\n", x + 1); wc->modtype[x] = MOD_TYPE_NONE; wc->cardflag |= (1 << x); } } } } #ifdef VPM_SUPPORT wctdm_vpm_init(wc); if (wc->vpm) { printk("VPM: Present and operational (Rev %c)\n", 'A' + wc->vpm - 1); wc->ctlreg |= 0x10; } else { enum vpmadt032_init_result res; spin_lock_irqsave(&wc->reglock, flags); for (x = NUM_CARDS; x < NUM_CARDS + NUM_EC; x++) wc->modtype[x] = MOD_TYPE_NONE; spin_unlock_irqrestore(&wc->reglock, flags); res = wctdm_vpm150m_init(wc); /* In case there was an error while we were loading the VPM module. */ if (voicebus_current_latency(wc->vb) > startinglatency) { return -EAGAIN; } switch (res) { case VPMADT032_SUCCESS: printk("VPMADT032: Present and operational (Firmware version %x)\n", wc->vpm150m->version); wc->ctlreg |= 0x10; break; case VPMADT032_DISABLED: case VPMADT032_NOT_FOUND: /* nothing */ break; default: return -EIO; } } #endif /* In case there was an error while we were loading the VPM module. */ if (voicebus_current_latency(wc->vb) > startinglatency) { return -EAGAIN; } return 0; } static struct pci_driver wctdm_driver; static int __devinit wctdm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { struct wctdm *wc; struct wctdm_desc *d = (struct wctdm_desc *)ent->driver_data; int i; int y; int ret; retry: wc = kmalloc(sizeof(struct wctdm), GFP_KERNEL); if (!wc) { /* \todo Print debug message. */ return -ENOMEM; } memset(wc, 0, sizeof(*wc)); spin_lock(&ifacelock); /* \todo this is a candidate for removal... */ for (i = 0; i < WC_MAX_IFACES; ++i) { if (!ifaces[i]) { ifaces[i] = wc; break; } } spin_unlock(&ifacelock); snprintf(wc->board_name, sizeof(wc->board_name)-1, "%s%d", wctdm_driver.name, i); ret = voicebus_init(pdev, SFRAME_SIZE, wc->board_name, handle_receive, handle_transmit, wc, &wc->vb); if (ret) { kfree(wc); return ret; } BUG_ON(!wc->vb); if (VOICEBUS_DEFAULT_LATENCY != latency) { voicebus_set_minlatency(wc->vb, latency); } spin_lock_init(&wc->reglock); wc->curcard = -1; wc->cards = NUM_CARDS; wc->type = d->ports; wc->pos = i; wc->variety = d->name; wc->txident = 1; for (y=0;yflags[y] = d->flags; wc->dacssrc[y] = -1; } init_waitqueue_head(&wc->regq); if (wctdm_initialize(wc)) { voicebus_release(wc->vb); wc->vb = NULL; kfree(wc); return -EIO; } /* Keep track of which device we are */ pci_set_drvdata(pdev, wc); /* Start the hardware processing. */ if (voicebus_start(wc->vb)) { BUG_ON(1); } /* Now track down what modules are installed */ ret = wctdm_locate_modules(wc); if (-EAGAIN == ret ) { /* The voicebus library increased the latency during * initialization. There is a chance that the hardware is in * an inconsistent state, so lets increase the default latency * and start the initialization over. */ printk(KERN_NOTICE "%s: Restarting board initialization " \ "after increasing latency.\n", wc->board_name); latency = voicebus_current_latency(wc->vb); wctdm_release(wc); goto retry; } /* Final initialization */ wctdm_post_initialize(wc); /* We should be ready for zaptel to come in now. */ if (zt_register(&wc->span, 0)) { printk("Unable to register span with zaptel\n"); return -1; } wc->initialized = 1; printk("Found a Wildcard TDM: %s (%d modules)\n", wc->variety, wc->type); ret = 0; return ret; } static void wctdm_release(struct wctdm *wc) { int i; if (wc->initialized) { zt_unregister(&wc->span); } voicebus_release(wc->vb); wc->vb = NULL; spin_lock(&ifacelock); for (i = 0; i < WC_MAX_IFACES; i++) if (ifaces[i] == wc) break; ifaces[i] = NULL; spin_unlock(&ifacelock); kfree(wc); } static void __devexit wctdm_remove_one(struct pci_dev *pdev) { struct wctdm *wc = pci_get_drvdata(pdev); #ifdef VPM150M_SUPPORT unsigned long flags; struct vpm150m *vpm150m = wc->vpm150m; #endif if (wc) { #ifdef VPM150M_SUPPORT if (vpm150m) { clear_bit(VPM150M_DTMFDETECT, &vpm150m->control); clear_bit(VPM150M_ACTIVE, &vpm150m->control); flush_workqueue(vpm150m->wq); destroy_workqueue(vpm150m->wq); } #endif voicebus_stop(wc->vb); #ifdef VPM150M_SUPPORT if (vpm150m) { spin_lock_irqsave(&wc->reglock, flags); wc->vpm150m = NULL; vpm150m->wc = NULL; spin_unlock_irqrestore(&wc->reglock, flags); kfree(wc->vpm150m); } #endif /* Release span, possibly delayed */ if (!wc->usecount) { wctdm_release(wc); printk("Freed a Wildcard\n"); } else wc->dead = 1; } } static struct pci_device_id wctdm_pci_tbl[] = { { 0xd161, 0x2400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm2400 }, { 0xd161, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm800 }, { 0xd161, 0x8002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wcaex800 }, { 0xd161, 0x8003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wcaex2400 }, { 0xd161, 0x8005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm410 }, { 0xd161, 0x8006, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wcaex410 }, { 0 } }; MODULE_DEVICE_TABLE(pci, wctdm_pci_tbl); static struct pci_driver wctdm_driver = { name: "wctdm24xxp", probe: wctdm_init_one, #ifdef LINUX26 remove: __devexit_p(wctdm_remove_one), #else remove: wctdm_remove_one, #endif suspend: NULL, resume: NULL, id_table: wctdm_pci_tbl, }; static int __init wctdm_init(void) { int res; int x; for (x = 0; x < (sizeof(fxo_modes) / sizeof(fxo_modes[0])); x++) { if (!strcmp(fxo_modes[x].name, opermode)) break; } if (x < sizeof(fxo_modes) / sizeof(fxo_modes[0])) { _opermode = x; } else { printk("Invalid/unknown operating mode '%s' specified. Please choose one of:\n", opermode); for (x = 0; x < sizeof(fxo_modes) / sizeof(fxo_modes[0]); x++) printk(" %s\n", fxo_modes[x].name); printk("Note this option is CASE SENSITIVE!\n"); return -ENODEV; } if (!strcmp(opermode, "AUSTRALIA")) { boostringer = 1; fxshonormode = 1; } /* 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; } res = zap_pci_module(&wctdm_driver); if (res) return -ENODEV; return 0; } static void __exit wctdm_cleanup(void) { pci_unregister_driver(&wctdm_driver); } #ifdef LINUX26 module_param(debug, int, 0600); module_param(fxovoltage, int, 0600); module_param(loopcurrent, int, 0600); module_param(robust, int, 0600); 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(alawoverride, int, 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(fwringdetect, int, 0600); module_param(latency, int, 0600); #ifdef VPM_SUPPORT module_param(vpmsupport, int, 0600); module_param(vpmdtmfsupport, int, 0600); module_param(dtmfthreshold, int, 0600); module_param(vpmnlptype, int, 0600); module_param(vpmnlpthresh, int, 0600); module_param(vpmnlpmaxsupp, int, 0600); #endif #else MODULE_PARM(debug, "i"); MODULE_PARM(fxovoltage, "i"); MODULE_PARM(loopcurrent, "i"); MODULE_PARM(robust, "i"); MODULE_PARM(opermode, "s"); MODULE_PARM(lowpower, "i"); MODULE_PARM(boostringer, "i"); MODULE_PARM(fastringer, "i"); MODULE_PARM(fxshonormode, "i"); MODULE_PARM(battdebounce, "i"); MODULE_PARM(battalarm, "i"); MODULE_PARM(battthresh, "i"); MODULE_PARM(alawoverride, "i"); MODULE_PARM(nativebridge, "i"); MODULE_PARM(fxotxgain, "i"); MODULE_PARM(fxorxgain, "i"); MODULE_PARM(fxstxgain, "i"); MODULE_PARM(fxsrxgain, "i"); MODULE_PARM(ringdebounce, "i"); MODULE_PARM(fwringdetect, "i"); #ifdef VPM_SUPPORT MODULE_PARM(vpmsupport, "i"); MODULE_PARM(vpmdtmfsupport, "i"); MODULE_PARM(dtmfthreshold, "i"); MODULE_PARM(vpmnlptype, "i"); MODULE_PARM(vpmnlpthresh, "i"); MODULE_PARM(vpmnlpmaxsupp, "i"); #endif #endif MODULE_DESCRIPTION("Wildcard TDM2400P/TDM800P Zaptel Driver"); MODULE_AUTHOR("Mark Spencer "); #if defined(MODULE_ALIAS) MODULE_ALIAS("wctdm8xxp"); #endif #ifdef MODULE_LICENSE MODULE_LICENSE("GPL"); #endif module_init(wctdm_init); module_exit(wctdm_cleanup); zaptel-1.4.11/kernel/wctdm24xxp/GpakCust.h0000644000000000000000000001366310751714440017005 0ustar rootroot/* * 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. The standard * GPL disclaimer is given inline below for your convenience. * * 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 _GPAKCUST_H /* prevent multiple inclusion */ #define _GPAKCUST_H #include "wctdm24xxp.h" #ifdef VPM150M_SUPPORT #include #include #endif #include "gpakenum.h" struct wctdm_firmware { const struct firmware *fw; unsigned int offset; }; /* Host and DSP system dependent related definitions. */ #define MAX_DSP_CORES 128 /* maximum number of DSP cores */ //#define MAX_CONFS 1 /* maximum number of conferences */ //#define MAX_PKT_CHANNELS 8 /* maximum number of packet channels */ #define MAX_CHANNELS 32 /* maximum number of channels */ #define MAX_WAIT_LOOPS 50 /* max number of wait delay loops */ #define DSP_IFBLK_ADDRESS 0x0100 /* DSP address of I/F block pointer */ #define DOWNLOAD_BLOCK_SIZE 512 /* download block size (DSP words) */ //#define MAX_CIDPAYLOAD_BYTES 512 /* max size of a CID payload (octets) */ typedef unsigned short DSP_WORD; /* 16 bit DSP word */ typedef unsigned int DSP_ADDRESS; /* 32 bit DSP address */ typedef struct wctdm_firmware* GPAK_FILE_ID; /* G.PAK Download file identifier */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadDspMemory - Read DSP memory. * * FUNCTION * This function reads a contiguous block of words from DSP memory starting at * the specified address. * * RETURNS * nothing * */ extern void gpakReadDspMemory( unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ unsigned int NumWords, /* number of contiguous words to read */ DSP_WORD *pWordValues /* pointer to array of word values variable */ ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakWriteDspMemory - Write DSP memory. * * FUNCTION * This function writes a contiguous block of words to DSP memory starting at * the specified address. * * RETURNS * nothing * */ extern void gpakWriteDspMemory( unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ unsigned int NumWords, /* number of contiguous words to write */ DSP_WORD *pWordValues /* pointer to array of word values to write */ ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakHostDelay - Delay for a fixed time interval. * * FUNCTION * This function delays for a fixed time interval before returning. The time * interval is the Host Port Interface sampling period when polling a DSP for * replies to command messages. * * RETURNS * nothing * */ extern void gpakHostDelay(void); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakLockAccess - Lock access to the specified DSP. * * FUNCTION * This function aquires exclusive access to the specified DSP. * * RETURNS * nothing * */ extern void gpakLockAccess( unsigned short int DspId /* DSP Identifier (0 to MAX_DSP_CORES-1) */ ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakUnlockAccess - Unlock access to the specified DSP. * * FUNCTION * This function releases exclusive access to the specified DSP. * * RETURNS * nothing * */ extern void gpakUnlockAccess( unsigned short int DspId /* DSP Identifier (0 to MAX_DSP_CORES-1) */ ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadFile - Read a block of bytes from a G.PAK Download file. * * FUNCTION * This function reads a contiguous block of bytes from a G.PAK Download file * starting at the current file position. * * RETURNS * The number of bytes read from the file. * -1 indicates an error occurred. * 0 indicates all bytes have been read (end of file) * */ extern int gpakReadFile( GPAK_FILE_ID FileId, /* G.PAK Download File Identifier */ unsigned char *pBuffer, /* pointer to buffer for storing bytes */ unsigned int NumBytes /* number of bytes to read */ ); unsigned char wctdm_vpm150m_getpage(struct wctdm *wc); int wctdm_vpm150m_setpage(struct wctdm *wc, unsigned short addr); int wctdm_vpm150m_setreg(struct wctdm *wc, unsigned int len, unsigned int addr, unsigned short *data); unsigned short wctdm_vpm150m_getreg(struct wctdm *wc, unsigned int len, unsigned int addr, unsigned short *data); char vpm150mtone_to_zaptone(GpakToneCodes_t tone); #endif /* prevent multiple inclusion */ zaptel-1.4.11/kernel/wctdm24xxp/Kbuild0000644000000000000000000000111510773007372016240 0ustar rootrootobj-m += wctdm24xxp.o FIRM_DIR := ../../firmware EXTRA_CFLAGS := -I$(src)/.. -Wno-undef ifeq ($(HOTPLUG_FIRMWARE),yes) EXTRA_CFLAGS+=-DHOTPLUG_FIRMWARE endif wctdm24xxp-objs := base.o GpakCust.o GpakApi.o ../voicebus.o ifneq ($(HOTPLUG_FIRMWARE),yes) wctdm24xxp-objs += $(FIRM_DIR)/zaptel-fw-vpmadt032.o endif $(obj)/$(FIRM_DIR)/zaptel-fw-vpmadt032.o: $(obj)/base.o $(MAKE) -C $(obj)/$(FIRM_DIR) zaptel-fw-vpmadt032.o $(obj)/base.o: $(src)/GpakCust.h $(src)/wctdm24xxp.h $(obj)/base.o: $(src)/../zaptel.h $(obj)/GpakCust.o: $(src)/GpakCust.h $(obj)/GpakApi.o: $(src)/GpakApi.h zaptel-1.4.11/kernel/wctdm24xxp/GpakApi.h0000644000000000000000000006202310775452562016604 0ustar rootroot/* * Copyright (c) 2005 , Adaptive Digital Technologies, Inc. * * File Name: GpakApi.h * * Description: * This file contains the function prototypes and data types for the user * API functions that communicate with DSPs executing G.PAK software. The * file is used by application software in the host processor connected to * C55X G.PAK DSPs via a Host Port Interface. * * Version: 1.0 * * Revision History: * 06/15/05 - Initial release. * 11/15/2006 - 24 TDM-TDM Channels EC release * * This program has been released under the terms of the GPL version 2 by * permission of Adaptive Digital Technologies, Inc. The standard * GPL disclaimer is given inline below for your convenience. * * 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 _GPAKAPI_H /* prevent multiple inclusion */ #define _GPAKAPI_H #include "gpakErrs.h" #include "gpakenum.h" // Bit masks to select which algorithm's parameters to update: Or-together the // desired masks into the UpdateBits function parameter. #define DTMF_UPDATE_MASK 0x0010 // update DTMF params, MinLevel, SNRFlag and Freq #define DTMF_TWIST_UPDATE_MASK 0x0020 // update DTMF TWIST system params #define DTMF_VALID_MASK 0x0080 // update DTMF ValidMask params #define DSP_DEBUG_BUFF_SIZE 42 // units of 16-bit words /* Definition of an Asynchronous Event Data Structure */ typedef union { struct { GpakToneCodes_t ToneCode; // detected tone code unsigned short int ToneDuration; // tone duration GpakTdmDirection Direction; // detected on A r B side short int DebugToneStatus;// reserved for debug info } toneEvent; } GpakAsyncEventData_t; /* Definition of an Echo Canceller Parameters information structure. */ typedef struct { short int EcanTapLength; // Echo Can Num Taps (tail length) short int EcanNlpType; // Echo Can NLP Type short int EcanAdaptEnable; // Echo Can Adapt Enable flag short int EcanG165DetEnable; // Echo Can G165 Detect Enable flag short int EcanDblTalkThresh; // Echo Can Double Talk threshold short int EcanNlpThreshold; // Echo Can NLP threshold short int EcanNlpConv; // Dynamic NLP control, NLP limit when EC about to converged short int EcanNlpUnConv;// Dynamic NLP control, NLP limit when EC not converged yet short int EcanNlpMaxSuppress; // suppression level for NLP_SUPP mode short int EcanCngThreshold; // Echo Can CNG Noise threshold short int EcanAdaptLimit; // Echo Can Max Adapts per frame short int EcanCrossCorrLimit; // Echo Can Cross Correlation limit short int EcanNumFirSegments; // Echo Can Num FIR Segments short int EcanFirSegmentLen; // Echo Can FIR Segment Length } GpakEcanParms_t; /* Definition of a Channel Configuration information structure. */ typedef struct { GpakSerialPort_t PcmInPortA; // A side PCM Input Serial Port Id unsigned short int PcmInSlotA; // A side PCM Input Time Slot GpakSerialPort_t PcmOutPortA; // A side PCM Output Serial Port Id unsigned short int PcmOutSlotA; // A side PCM Output Time Slot GpakSerialPort_t PcmInPortB; // B side PCM Input Serial Port Id unsigned short int PcmInSlotB; // B side PCM Input Time Slot GpakSerialPort_t PcmOutPortB; // B side PCM Output Serial Port Id unsigned short int PcmOutSlotB; // B side PCM Output Time Slot GpakToneTypes ToneTypesA; // A side Tone Detect Types GpakToneTypes ToneTypesB; // B side Tone Detect Types GpakActivation EcanEnableA; // Echo Cancel A Enabled GpakActivation EcanEnableB; // Echo Cancel B Enabled GpakEcanParms_t EcanParametersA; // Echo Cancel parameters GpakEcanParms_t EcanParametersB; // Echo Cancel parameters GpakCompandModes SoftwareCompand; // software companding GpakRate_t FrameRate; // Gpak Frame Rate GpakActivation MuteToneA; // A side mute DTMF Enabled GpakActivation MuteToneB; // B side mute DTMF Enabled GpakActivation FaxCngDetA; // A side FaxCng Tone Detector Enabled GpakActivation FaxCngDetB; // B side FaxCng Tone Detector Enabled } GpakChannelConfig_t; /* Definition of a Serial Port Configuration Structure */ typedef struct { GpakSlotCfg_t SlotsSelect1; // port 1 Slot selection unsigned short int FirstBlockNum1; // port 1 first group Block Number unsigned short int FirstSlotMask1; // port 1 first group Slot Mask unsigned short int SecBlockNum1; // port 1 second group Block Number unsigned short int SecSlotMask1; // port 1 second group Slot Mask GpakSerWordSize_t SerialWordSize1; // port 1 serial word size GpakCompandModes CompandingMode1; // port 1 companding mode GpakSerFrameSyncPol_t TxFrameSyncPolarity1; // port 1 Tx Frame Sync Polarity GpakSerFrameSyncPol_t RxFrameSyncPolarity1; // port 1 Rx Frame Sync Polarity GpakSerClockPol_t TxClockPolarity1; // port 1 Tx Clock Polarity GpakSerClockPol_t RxClockPolarity1; // port 1 Rx Clock Polarity GpakSerDataDelay_t TxDataDelay1; // port 1 Tx data delay GpakSerDataDelay_t RxDataDelay1; // port 1 Rx data delay GpakActivation DxDelay1; // port 1 DX Delay unsigned short int ThirdSlotMask1; // port 1 3rd group Slot Mask unsigned short int FouthSlotMask1; // port 1 4th group Slot Mask unsigned short int FifthSlotMask1; // port 1 5th group Slot Mask unsigned short int SixthSlotMask1; // port 1 6th group Slot Mask unsigned short int SevenSlotMask1; // port 1 7th group Slot Mask unsigned short int EightSlotMask1; // port 1 8th group Slot Mask GpakSlotCfg_t SlotsSelect2; // port 2 Slot selection unsigned short int FirstBlockNum2; // port 2 first group Block Number unsigned short int FirstSlotMask2; // port 2 first group Slot Mask unsigned short int SecBlockNum2; // port 2 second group Block Number unsigned short int SecSlotMask2; // port 2 second group Slot Mask GpakSerWordSize_t SerialWordSize2; // port 2 serial word size GpakCompandModes CompandingMode2; // port 2 companding mode GpakSerFrameSyncPol_t TxFrameSyncPolarity2; // port 2 Tx Frame Sync Polarity GpakSerFrameSyncPol_t RxFrameSyncPolarity2; // port 2 Rx Frame Sync Polarity GpakSerClockPol_t TxClockPolarity2; // port 2 Tx Clock Polarity GpakSerClockPol_t RxClockPolarity2; // port 2 Rx Clock Polarity GpakSerDataDelay_t TxDataDelay2; // port 2 Tx data delay GpakSerDataDelay_t RxDataDelay2; // port 2 Rx data delay GpakActivation DxDelay2; // port 2 DX Delay unsigned short int ThirdSlotMask2; // port 2 3rd group Slot Mask unsigned short int FouthSlotMask2; // port 2 4th group Slot Mask unsigned short int FifthSlotMask2; // port 2 5th group Slot Mask unsigned short int SixthSlotMask2; // port 2 6th group Slot Mask unsigned short int SevenSlotMask2; // port 2 7th group Slot Mask unsigned short int EightSlotMask2; // port 2 8th group Slot Mask GpakSlotCfg_t SlotsSelect3; // port 3 Slot selection unsigned short int FirstBlockNum3; // port 3 first group Block Number unsigned short int FirstSlotMask3; // port 3 first group Slot Mask unsigned short int SecBlockNum3; // port 3 second group Block Number unsigned short int SecSlotMask3; // port 3 second group Slot Mask GpakSerWordSize_t SerialWordSize3; // port 3 serial word size GpakCompandModes CompandingMode3; // port 3 companding mode GpakSerFrameSyncPol_t TxFrameSyncPolarity3; // port 3 Tx Frame Sync Polarity GpakSerFrameSyncPol_t RxFrameSyncPolarity3; // port 3 Rx Frame Sync Polarity GpakSerClockPol_t TxClockPolarity3; // port 3 Tx Clock Polarity GpakSerClockPol_t RxClockPolarity3; // port 3 Rx Clock Polarity GpakSerDataDelay_t TxDataDelay3; // port 3 Tx data delay GpakSerDataDelay_t RxDataDelay3; // port 3 Rx data delay GpakActivation DxDelay3; // port 3 DX Delay unsigned short int ThirdSlotMask3; // port 3 3rd group Slot Mask unsigned short int FouthSlotMask3; // port 3 4th group Slot Mask unsigned short int FifthSlotMask3; // port 3 5th group Slot Mask unsigned short int SixthSlotMask3; // port 3 6th group Slot Mask unsigned short int SevenSlotMask3; // port 3 7th group Slot Mask unsigned short int EightSlotMask3; // port 3 8th group Slot Mask } GpakPortConfig_t; /* Definition of a Tone Generation Parameter Structure */ /* typedef struct { GpakToneGenType_t ToneType; // Tone Type unsigned short int Frequency[4]; // Frequency (Hz) short int Level[4]; // Frequency's Level (1 dBm) unsigned short int OnTime[4]; // On Times (msecs) unsigned short int OffTime[4]; // Off Times (msecs) } GpakToneGenParms_t; */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* gpakConfigureChannel return status. */ typedef enum { CcsSuccess = 0, /* Channel Configured successfully */ CcsParmError = 1, /* Channel Config Parameter error */ CcsInvalidChannel = 2, /* invalid channel */ CcsInvalidDsp = 3, /* invalid DSP */ CcsDspCommFailure = 4 /* failed to communicate with DSP */ } gpakConfigChanStatus_t; /* * gpakConfigureChannel - Configure a DSP's Channel. * * FUNCTION * This function configures a DSP's Channel. * * RETURNS * Status code indicating success or a specific error. * */ extern gpakConfigChanStatus_t gpakConfigureChannel( unsigned short int DspId, // DSP identifier unsigned short int ChannelId, // channel identifier GpakChanType ChannelType, // channel type GpakChannelConfig_t *pChanConfig, // pointer to channel config info GPAK_ChannelConfigStat_t *pStatus // pointer to Channel Config Status ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* gpakTearDownChannel return status. */ typedef enum { TdsSuccess = 0, /* Channel Tear Down successful */ TdsError = 1, /* Channel Tear Down error */ TdsInvalidChannel = 2, /* invalid channel */ TdsInvalidDsp = 3, /* invalid DSP */ TdsDspCommFailure = 4 /* failed to communicate with DSP */ } gpakTearDownStatus_t; /* * gpakTearDownChannel - Tear Down a DSP's Channel. * * FUNCTION * This function tears down a DSP's Channel. * * RETURNS * Status code indicating success or a specific error. * */ extern gpakTearDownStatus_t gpakTearDownChannel( unsigned short int DspId, // DSP identifier unsigned short int ChannelId, // channel identifier GPAK_TearDownChanStat_t *pStatus // pointer to Tear Down Status ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* gpakAlgControl return status. */ typedef enum { AcSuccess = 0, /* control successful */ AcInvalidChannel = 1, /* invalid channel identifier */ AcInvalidDsp = 2, /* invalid DSP */ AcParmError = 3, /* invalid control parameter */ AcDspCommFailure = 4 /* failed to communicate with DSP */ } gpakAlgControlStat_t; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakAlgControl - Control an Algorithm. * * FUNCTION * This function controls an Algorithm * * RETURNS * Status code indicating success or a specific error. * */ extern gpakAlgControlStat_t gpakAlgControl( unsigned short int DspId, // DSP identifier unsigned short int ChannelId, // channel identifier GpakAlgCtrl_t ControlCode, // algorithm control code GPAK_AlgControlStat_t *pStatus // pointer to return status ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* gpakConfigurePorts return status. */ typedef enum { CpsSuccess = 0, /* Serial Ports configured successfully */ CpsParmError = 1, /* Configure Ports Parameter error */ CpsInvalidDsp = 2, /* invalid DSP */ CpsDspCommFailure = 3 /* failed to communicate with DSP */ } gpakConfigPortStatus_t; /* * gpakConfigurePorts - Configure a DSP's serial ports. * * FUNCTION * This function configures a DSP's serial ports. * * RETURNS * Status code indicating success or a specific error. * */ extern gpakConfigPortStatus_t gpakConfigurePorts( unsigned short int DspId, // DSP identifier GpakPortConfig_t *pPortConfig, // pointer to Port Config info GPAK_PortConfigStat_t *pStatus // pointer to Port Config Status ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* gpakDownloadDsp return status. */ typedef enum { GdlSuccess = 0, /* DSP download successful */ GdlFileReadError = 1, /* error reading Download file */ GdlInvalidFile = 2, /* invalid Download file content */ GdlInvalidDsp = 3 /* invalid DSP */ } gpakDownloadStatus_t; /* * gpakDownloadDsp - Download a DSP's Program and initialized Data memory. * * FUNCTION * This function reads a DSP's Program and Data memory image from the * specified file and writes the image to the DSP's memory. * * RETURNS * Status code indicating success or a specific error. * */ extern gpakDownloadStatus_t gpakDownloadDsp( unsigned short int DspId, // DSP identifier GPAK_FILE_ID FileId // G.PAK download file identifier ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* gpakReadEventFIFOMessage return status */ typedef enum { RefEventAvail = 0, /* an event was successfully read from the fifo */ RefNoEventAvail = 1, /* no event was in the fifo */ RefInvalidDsp = 2, /* invalid DSP identifier */ RefInvalidEvent = 3, /* invalid event */ RefDspCommFailure = 4 /* error communicating with DSP */ } gpakReadEventFIFOMessageStat_t; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadEventFIFOMessage - read from the event fifo * * FUNCTION * This function reads a single event from the event fifo if one is available * * RETURNS * Status code indicating success or a specific error. * * Note: This function should be called in a loop until the return status * indicates that the fifo is empty. */ extern gpakReadEventFIFOMessageStat_t gpakReadEventFIFOMessage( unsigned short int DspId, // DSP identifier unsigned short int *pChannelId, // pointer to channel identifier GpakAsyncEventCode_t *pEventCode, // pointer to Event Code GpakAsyncEventData_t *pEventData // pointer to Event Data Struct ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /* gpakPingDsp return status values */ typedef enum { PngSuccess = 0, /* DSP responded successfully */ PngInvalidDsp = 1, /* invalid DSP identifier */ PngDspCommFailure = 2 /* error communicating with DSP */ } gpakPingDspStat_t; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakPingDsp - ping the DSP to see if it's alive * * FUNCTION * This function checks if the DSP is still communicating with the host * * RETURNS * Status code indicating success or a specific error. */ extern gpakPingDspStat_t gpakPingDsp( unsigned short int DspId, // DSP identifier unsigned short int *pDspSwVersion // DSP software version ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /* gpakSerialTxFixedValue return status values */ typedef enum { TfvSuccess = 0, /* operation successful */ TfvInvalidChannel = 1, /* invalid channel identifier */ TfvInvalidDsp = 2, /* invalid DSP identifier */ TfvDspCommFailure = 3 /* failed to communicate with DSP */ } gpakSerialTxFixedValueStat_t; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakSerialTxFixedValue - transmit a fixed value on a timeslot * * FUNCTION * This function controls transmission of a fixed value out onto a serial * port's timeslot. * * RETURNS * Status code indicating success or a specific error. */ extern gpakSerialTxFixedValueStat_t gpakSerialTxFixedValue( unsigned short int DspId, // DSP identifier unsigned short int ChannelId, // channel identifier GpakSerialPort_t PcmOutPort, // PCM Output Serial Port Id unsigned short int PcmOutSlot, // PCM Output Time Slot unsigned short int Value, // 16-bit value GpakActivation State // activation state ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /* gpakControlTdmLoopBack return status values */ typedef enum { ClbSuccess = 0, /* operation successful */ ClbSerPortInactive = 1, /* serial port is inactive */ ClbInvalidDsp = 2, /* invalid DSP identifier */ ClbDspCommFailure = 3 /* failed to communicate with DSP */ } gpakControlTdmLoopBackStat_t; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakControlTdmLoopBack - control a serial port's loopback state * * FUNCTION * This function enables/disables the tdm input to output looback mode on a * serial port * * RETURNS * Status code indicating success or a specific error. */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ gpakControlTdmLoopBackStat_t gpakControlTdmLoopBack( unsigned short int DspId, // DSP identifier GpakSerialPort_t SerialPort, // Serial Port Id GpakActivation LoopBackState // Loopback State ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /* gpakReadCpuUsage return status values */ typedef enum { RcuSuccess = 0, /* operation successful */ RcuInvalidDsp = 1, /* invalid DSP identifier */ RcuDspCommFailure = 2 /* communication failure */ } gpakReadCpuUsageStat_t; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadCpuUsage - read the cpu usage statistics * * FUNCTION * This function reads cpu utilization from the DSP. * * RETURNS * Status code indicating success or a specific error. */ extern gpakReadCpuUsageStat_t gpakReadCpuUsage( unsigned short int DspId, // DSP identifier unsigned short int *pPeakUsage, // pointer to peak usage variable unsigned short int *pPrev1SecPeakUsage // peak usage over previous 1 second ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /* gpakResetCpuUsageStats return status values */ typedef enum { RstcSuccess = 0, /* operation successful */ RstcInvalidDsp = 1, /* invalid DSP identifier */ RstcDspCommFailure = 2 /* communication failure */ } gpakResetCpuUsageStat_t; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakResetCpuUsageStats - reset the cpu usage statistics * * FUNCTION * This function resets the cpu utilization statistics * * RETURNS * Status code indicating success or a specific error. */ extern gpakResetCpuUsageStat_t gpakResetCpuUsageStats( unsigned short int DspId // DSP identifier ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /* gpakReadFramingStats return status values */ typedef enum { RfsSuccess = 0, /* operation successful */ RfsInvalidDsp = 1, /* invalid DSP identifier */ RfsDspCommFailure = 2 /* communication failure */ } gpakReadFramingStatsStatus_t; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadFramingStats * * FUNCTION * This function reads a DSP's framing interrupt statistics * * RETURNS * Status code indicating success or a specific error. */ extern gpakReadFramingStatsStatus_t gpakReadFramingStats( unsigned short int DspId, // DSP identifier unsigned short int *pFramingError1Count, // port 1 Framing error count unsigned short int *pFramingError2Count, // port 2 Framing error count unsigned short int *pFramingError3Count, // port 3 Framing error count unsigned short int *pDmaStopErrorCount, // DMA-stoppage error count unsigned short int *pDmaSlipStatsBuffer // DMA slips count ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /* gpakResetFramingStats return values */ typedef enum { RstfSuccess = 0, /* operation successful */ RstfInvalidDsp = 1, /* invalid DSP identifier */ RstfDspCommFailure = 2 /* communication failure */ } gpakResetFramingStatsStatus_t; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakResetFramingStats - reset a DSP's framing interrupt statistics * * FUNCTION * This function resets a DSP's framing interrupt statistics * * RETURNS * Status code indicating success or a specific error. */ extern gpakResetFramingStatsStatus_t gpakResetFramingStats( unsigned short int DspId // DSP identifier ); typedef enum { RmmSuccess =0, RmmInvalidDsp = 1, RmmSizeTooBig = 2, RmmFailure = 3, RmmInvalidAddress = 4 } gpakReadDSPMemoryStat_t; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakResetFramingStats - read a section of DSP memory * to get access DSP registers, since 0x00--0x60 not HPI-accessable * * FUNCTION * This function resets a DSP's framing interrupt statistics * * RETURNS * Status code indicating success or a specific error. */ extern gpakReadDSPMemoryStat_t gpakReadDSPMemoryMap( unsigned short int DspId, // Dsp Identifier unsigned short int *pDest, // Buffer on host to hold DSP memory map DSP_ADDRESS BufrBaseAddress, // DSP memory users want to read out unsigned short int MemoryLength_Word16 // Length of memory section read out, unit is 16-bit word ); typedef enum { GPIOSuccess =0, GPIOInvalidDsp = 1, GPIODspCommFailure = 2 }gpakAccessGPIOStat_t; extern gpakAccessGPIOStat_t gpakAccessGPIO( unsigned short int DspId, // DSP identifier GpakGPIOCotrol_t gpakControlGPIO,// select oeration, changeDIR/write/read unsigned short int *pGPIOValue // pointer for the read/write value or DIR mask ); /* gpakWriteSystemParms return status. */ typedef enum { WspSuccess = 0, /* System Parameters written successfully */ WspParmError = 1, /* Write System Parms's Parameter error */ WspInvalidDsp = 2, /* invalid DSP */ WspDspCommFailure = 3 /* failed to communicate with DSP */ } gpakWriteSysParmsStatus_t; /* Definition of a System Parameters information structure. */ typedef struct { /* DTMF Parameters */ short int MinSigLevel; /* 0 = Disabled, Min Sig Power Level for detection */ short int SNRFlag; /* 0 = Disabled, relax SNR tolerances */ short int FreqDeviation; /* 0 = Disabled, X Percent Deviation times 10 (e.g. 1.7% is entered as 17) */ short int DtmfFwdTwist; /* 0 to 8 db */ short int DtmfRevTwist; /* 0 to 8 db */ short int DtmfValidityMask; /* This flag allows users to relax the trailing conditions of the tone */ } GpakSystemParms_t; /* gpakReadSystemParms return status. */ typedef enum { RspSuccess = 0, /* System Parameters read successfully */ RspInvalidDsp = 1, /* invalid DSP */ RspDspCommFailure = 2 /* failed to communicate with DSP */ } gpakReadSysParmsStatus_t; extern gpakReadSysParmsStatus_t gpakReadSystemParms( unsigned short int DspId, // DSP identifier GpakSystemParms_t *pSysParms /* pointer to System Parms info var */ ); extern gpakWriteSysParmsStatus_t gpakWriteSystemParms( unsigned short int DspId, // DSP identifier GpakSystemParms_t *pSysParms, /* pointer to System Parms info var */ unsigned short int UpdateBits, /* input: flags indicating which parms to update */ GPAK_SysParmsStat_t *pStatus /* pointer to Write System Parms Status */ ); #endif // end multiple inclusion zaptel-1.4.11/kernel/wctdm24xxp/GpakApi.c0000644000000000000000000016602210775452562016603 0ustar rootroot/* * 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. The standard * GPL disclaimer is given inline below for your convenience. * * 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 "zaptel.h" #include "GpakHpi.h" #include "GpakCust.h" #include "GpakApi.h" #include "gpakenum.h" /* DSP to Host interface block offsets. */ #define REPLY_MSG_PNTR_OFFSET 0 /* I/F blk offset to Reply Msg Pointer */ #define CMD_MSG_PNTR_OFFSET 2 /* I/F blk offset to Command Msg Pointer */ #define EVENT_MSG_PNTR_OFFSET 4 /* I/F blk offset to Event Msg Pointer */ #define PKT_BUFR_MEM_OFFSET 6 /* I/F blk offset to Packet Buffer memory */ #define DSP_STATUS_OFFSET 8 /* I/F blk offset to DSP Status */ #define VERSION_ID_OFFSET 9 /* I/F blk offset to G.PAK Version Id */ #define MAX_CMD_MSG_LEN_OFFSET 10 /* I/F blk offset to Max Cmd Msg Length */ #define CMD_MSG_LEN_OFFSET 11 /* I/F blk offset to Command Msg Length */ #define REPLY_MSG_LEN_OFFSET 12 /* I/F blk offset to Reply Msg Length */ #define NUM_CHANNELS_OFFSET 13 /* I/F blk offset to Num Built Channels */ #define NUM_PKT_CHANNELS_OFFSET 14 /* I/F blk offset to Num Pkt Channels */ #define NUM_CONFERENCES_OFFSET 15 /* I/F blk offset to Num Conferences */ //#define CPU_USAGE_OFFSET_1MS 16 /* I/F blk offset to CPU Usage statistics */ #define CPU_USAGE_OFFSET 18 /* I/F blk offset to CPU Usage statistics */ //#define CPU_USAGE_OFFSET_10MS 20 /* I/F blk offset to CPU Usage statistics */ #define FRAMING_STATS_OFFSET 22 /* I/F blk offset to Framing statistics */ //#define GPAK_RELEASE_Rate rate10ms // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = // Macro to reconstruct a 32-bit value from two 16-bit values. // Parameter p32: 32-bit-wide destination // Parameter p16: 16-bit-wide source array of length 2 words #define RECONSTRUCT_LONGWORD(p32, p16) p32 = (DSP_ADDRESS)p16[0]<<16; \ p32 |= (unsigned long)p16[1] // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = /* DSP Status value definitions. */ #define DSP_INIT_STATUS 0x5555 /* DSP Initialized status value */ #define HOST_INIT_STATUS 0xAAAA /* Host Initialized status value */ /* Circular packet buffer information structure offsets. */ #define CB_BUFR_BASE 0 /* pointer to base of circular buffer */ #define CB_BUFR_SIZE 2 /* size of buffer (words) */ #define CB_BUFR_PUT_INDEX 3 /* offset in buffer for next write */ #define CB_BUFR_TAKE_INDEX 4 /* offset in buffer for next read */ #define CIRC_BUFFER_INFO_STRUCT_SIZE 6 /* Miscellaneous definitions. */ #define MSG_BUFFER_SIZE 100 /* size (words) of Host msg buffer */ #define WORD_BUFFER_SIZE 84 /* size of DSP Word buffer (words) */ #ifdef __TMS320C55XX__ // debug sections if not on host #pragma DATA_SECTION(pDspIfBlk,"GPAKAPIDEBUG_SECT") #pragma DATA_SECTION(MaxCmdMsgLen,"GPAKAPIDEBUG_SECT") #pragma DATA_SECTION(MaxChannels,"GPAKAPIDEBUG_SECT") #pragma DATA_SECTION(DlByteBufr,"GPAKAPIDEBUG_SECT") #pragma DATA_SECTION(DlWordBufr,"GPAKAPIDEBUG_SECT") #pragma DATA_SECTION(pEventFifoAddress,"GPAKAPIDEBUG_SECT") #endif /* Host variables related to Host to DSP interface. */ static DSP_ADDRESS pDspIfBlk[MAX_DSP_CORES]; /* DSP address of I/F block */ static DSP_WORD MaxCmdMsgLen[MAX_DSP_CORES]; /* max Cmd msg length (octets) */ static unsigned short int MaxChannels[MAX_DSP_CORES]; /* max num channels */ //static unsigned short int MaxPktChannels[MAX_DSP_CORES]; /* max num pkt channels */ //static unsigned short int MaxConfs[MAX_DSP_CORES]; /* max num conferences */ //static DSP_ADDRESS pPktInBufr[MAX_DSP_CORES][MAX_PKT_CHANNELS]; /* Pkt In buffer */ //static DSP_ADDRESS pPktOutBufr[MAX_DSP_CORES][MAX_PKT_CHANNELS]; /* Pkt Out buffer */ static DSP_ADDRESS pEventFifoAddress[MAX_DSP_CORES]; /* event fifo */ static unsigned char DlByteBufr[DOWNLOAD_BLOCK_SIZE * 2]; /* Dowload byte buf */ static DSP_WORD DlWordBufr[DOWNLOAD_BLOCK_SIZE]; /* Dowload word buffer */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * CheckDspReset - Check if the DSP was reset. * * FUNCTION * This function determines if the DSP was reset and is ready. If reset * occurred, it reads interface parameters and calculates DSP addresses. * * RETURNS * -1 = DSP is not ready. * 0 = Reset did not occur. * 1 = Reset occurred. * */ static int CheckDspReset( int DspId /* DSP Identifier (0 to MaxDSPCores-1) */ ) { DSP_ADDRESS IfBlockPntr; /* Interface Block pointer */ DSP_WORD DspStatus; /* DSP Status */ DSP_WORD DspChannels; /* number of DSP channels */ DSP_WORD Temp[2]; #if 0 DSP_WORD DspConfs; /* number of DSP conferences */ DSP_ADDRESS PktBufrMem; /* address of Packet Buffer */ unsigned short int i; /* loop index / counter */ #endif /* Read the pointer to the Interface Block. */ gpakReadDspMemory(DspId, DSP_IFBLK_ADDRESS, 2, Temp); RECONSTRUCT_LONGWORD(IfBlockPntr, Temp); /* If the pointer is zero, return with an indication the DSP is not ready. */ if (IfBlockPntr == 0) return (-1); /* Read the DSP's Status. */ gpakReadDspMemory(DspId, IfBlockPntr + DSP_STATUS_OFFSET, 1, &DspStatus); /* If status indicates the DSP was reset, read the DSP's interface parameters and calculate DSP addresses. */ if (DspStatus == DSP_INIT_STATUS || ((DspStatus == HOST_INIT_STATUS) && (pDspIfBlk[DspId] == 0))) { /* Save the address of the DSP's Interface Block. */ pDspIfBlk[DspId] = IfBlockPntr; /* Read the DSP's interface parameters. */ gpakReadDspMemory(DspId, IfBlockPntr + MAX_CMD_MSG_LEN_OFFSET, 1, &(MaxCmdMsgLen[DspId])); /* read the number of configured DSP channels */ gpakReadDspMemory(DspId, IfBlockPntr + NUM_CHANNELS_OFFSET, 1, &DspChannels); if (DspChannels > MAX_CHANNELS) MaxChannels[DspId] = MAX_CHANNELS; else MaxChannels[DspId] = (unsigned short int) DspChannels; #if 0 /* read the number of configured DSP conferences */ gpakReadDspMemory(DspId, IfBlockPntr + NUM_CONFERENCES_OFFSET, 1, &DspConfs); if (DspConfs > MAX_CONFS) MaxConfs[DspId] = MAX_CONFS; else MaxConfs[DspId] = (unsigned short int) DspConfs; /* read the number of configured DSP packet channels */ gpakReadDspMemory(DspId, IfBlockPntr + NUM_PKT_CHANNELS_OFFSET, 1, &DspChannels); if (DspChannels > MAX_PKT_CHANNELS) MaxPktChannels[DspId] = MAX_PKT_CHANNELS; else MaxPktChannels[DspId] = (unsigned short int) DspChannels; /* read the pointer to the circular buffer infor struct table */ gpakReadDspMemory(DspId, IfBlockPntr + PKT_BUFR_MEM_OFFSET, 2, Temp); RECONSTRUCT_LONGWORD(PktBufrMem, Temp); /* Determine the addresses of each channel's Packet buffers. */ for (i = 0; i < MaxPktChannels[DspId]; i++) { pPktInBufr[DspId][i] = PktBufrMem; pPktOutBufr[DspId][i] = PktBufrMem + CIRC_BUFFER_INFO_STRUCT_SIZE; PktBufrMem += (CIRC_BUFFER_INFO_STRUCT_SIZE*2); } #endif /* read the pointer to the event fifo info struct */ gpakReadDspMemory(DspId, IfBlockPntr + EVENT_MSG_PNTR_OFFSET, 2, Temp); RECONSTRUCT_LONGWORD(pEventFifoAddress[DspId], Temp); /* Set the DSP Status to indicate the host recognized the reset. */ DspStatus = HOST_INIT_STATUS; gpakWriteDspMemory(DspId, IfBlockPntr + DSP_STATUS_OFFSET, 1, &DspStatus); /* Return with an indication that a reset occurred. */ return (1); } /* If status doesn't indicate the host recognized a reset, return with an indication the DSP is not ready. */ if ((DspStatus != HOST_INIT_STATUS) || (pDspIfBlk[DspId] == 0)) return (-1); /* Return with an indication that a reset did not occur. */ return (0); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * WriteDspCmdMessage - Write a Host Command/Request message to DSP. * * FUNCTION * This function writes a Host Command/Request message into DSP memory and * informs the DSP of the presence of the message. * * RETURNS * -1 = Unable to write message (msg len or DSP Id invalid or DSP not ready) * 0 = Temporarily unable to write message (previous Cmd Msg busy) * 1 = Message written successfully * */ static int WriteDspCmdMessage( int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ DSP_WORD *pMessage, /* pointer to Command message */ DSP_WORD MsgLength /* length of message (octets) */ ) { DSP_WORD CmdMsgLength; /* current Cmd message length */ DSP_WORD Temp[2]; DSP_ADDRESS BufferPointer; /* message buffer pointer */ /* Check if the DSP was reset and is ready. */ if (CheckDspReset(DspId) == -1) return (-1); /* Make sure the message length is valid. */ if ((MsgLength < 1) || (MsgLength > MaxCmdMsgLen[DspId])) return (-1); /* Make sure a previous Command message is not in use by the DSP. */ gpakReadDspMemory(DspId, pDspIfBlk[DspId] + CMD_MSG_LEN_OFFSET, 1, &CmdMsgLength); if (CmdMsgLength != 0) return (0); /* Purge any previous Reply message that wasn't read. */ gpakWriteDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_LEN_OFFSET, 1, &CmdMsgLength); /* Copy the Command message into DSP memory. */ gpakReadDspMemory(DspId, pDspIfBlk[DspId] + CMD_MSG_PNTR_OFFSET, 2, Temp); RECONSTRUCT_LONGWORD(BufferPointer, Temp); gpakWriteDspMemory(DspId, BufferPointer, (MsgLength + 1) / 2, pMessage); /* Store the message length in DSP's Command message length (flags DSP that a Command message is ready). */ CmdMsgLength = MsgLength; gpakWriteDspMemory(DspId, pDspIfBlk[DspId] + CMD_MSG_LEN_OFFSET, 1, &CmdMsgLength); /* Return with an indication the message was written. */ return (1); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * ReadDspReplyMessage - Read a DSP Reply message from DSP. * * FUNCTION * This function reads a DSP Reply message from DSP memory. * * RETURNS * -1 = Unable to write message (msg len or DSP Id invalid or DSP not ready) * 0 = No message available (DSP Reply message empty) * 1 = Message read successfully (message and length stored in variables) * */ static int ReadDspReplyMessage( int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ DSP_WORD *pMessage, /* pointer to Reply message buffer */ DSP_WORD *pMsgLength /* pointer to msg length var (octets) */ ) { DSP_WORD MsgLength; /* message length */ DSP_ADDRESS BufferPointer; /* message buffer pointer */ DSP_WORD Temp[2]; /* Check if the DSP was reset and is ready. */ if (CheckDspReset(DspId) == -1) return (-1); /* Check if a Reply message is ready. */ gpakReadDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_LEN_OFFSET, 1, &MsgLength); if (MsgLength == 0) return (0); /* Make sure the message length is valid. */ if (MsgLength > *pMsgLength) return (-1); /* Copy the Reply message from DSP memory. */ gpakReadDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_PNTR_OFFSET, 2, Temp); RECONSTRUCT_LONGWORD(BufferPointer, Temp); gpakReadDspMemory(DspId, BufferPointer, (MsgLength + 1) / 2, pMessage); /* Store the message length in the message length variable. */ *pMsgLength = MsgLength; /* Indicate a Reply message is not ready. */ MsgLength = 0; gpakWriteDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_LEN_OFFSET, 1, &MsgLength); /* Return with an indication the message was read. */ return (1); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * ReadCircBuffer - Read from a DSP circular buffer. * * FUNCTION * This function reads a block of words from a DSP circular buffer. The Take * address is incremented by the number of words read adjusting for buffer * wrap. * * RETURNS * nothing * */ static void ReadCircBuffer( int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ DSP_ADDRESS BufrBaseAddress, /* address of base of circular buffer */ DSP_ADDRESS BufrLastAddress, /* address of last word in buffer */ DSP_ADDRESS *TakeAddress, /* pointer to address in buffer for read */ DSP_WORD *pWordBuffer, /* pointer to buffer for words read */ DSP_WORD NumWords /* number of words to read */ ) { DSP_WORD WordsTillEnd; /* number of words until end of buffer */ /* Determine the number of words from the start address until the end of the buffer. */ WordsTillEnd = BufrLastAddress - *TakeAddress + 1; /* If a buffer wrap will occur, read the first part at the end of the buffer followed by the second part at the beginning of the buffer. */ if (NumWords > WordsTillEnd) { gpakReadDspMemory(DspId, *TakeAddress, WordsTillEnd, pWordBuffer); gpakReadDspMemory(DspId, BufrBaseAddress, NumWords - WordsTillEnd, &(pWordBuffer[WordsTillEnd])); *TakeAddress = BufrBaseAddress + NumWords - WordsTillEnd; } /* If a buffer wrap will not occur, read all words starting at the current take address in the buffer. */ else { gpakReadDspMemory(DspId, *TakeAddress, NumWords, pWordBuffer); if (NumWords == WordsTillEnd) *TakeAddress = BufrBaseAddress; else *TakeAddress = *TakeAddress + NumWords; } return; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * VerifyReply - Verify the reply message is correct for the command sent. * * FUNCTION * This function verifies correct reply message content for the command that * was just sent. * * RETURNS * 0 = Incorrect * 1 = Correct * */ static int VerifyReply( DSP_WORD *pMsgBufr, /* pointer to Reply message buffer */ int CheckType, /* reply check type */ DSP_WORD CheckValue /* reply check value */ ) { /* Verify Channel or Conference Id. */ if (CheckType == 1) { if (((pMsgBufr[1] >> 8) & 0xFF) != CheckValue) return (0); } /* Verify Test Mode Id. */ else if (CheckType == 2) { if (pMsgBufr[1] != CheckValue) return (0); } /* Return with an indication of correct reply. */ return (1); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * TransactCmd - Send a command to the DSP and receive it's reply. * * FUNCTION * This function sends the specified command to the DSP and receives the DSP's * reply. * * RETURNS * Length of reply message (0 = Failure) * */ static unsigned int TransactCmd( int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ DSP_WORD *pMsgBufr, /* pointer to Cmd/Reply message buffer */ DSP_WORD CmdLength, /* length of command message (octets) */ DSP_WORD ReplyType, /* required type of reply message */ DSP_WORD ReplyLength, /* required length of reply message (octets) */ int ReplyCheckType, /* reply check type */ DSP_WORD ReplyCheckValue /* reply check value */ ) { int FuncStatus; /* function status */ int LoopCount; /* wait loop counter */ DSP_WORD RcvReplyLength; /* received Reply message length */ DSP_WORD RcvReplyType; /* received Reply message type code */ DSP_WORD RetValue; /* return value */ /* Default the return value to indicate a failure. */ RetValue = 0; /* Lock access to the DSP. */ gpakLockAccess(DspId); /* Attempt to write the command message to the DSP. */ LoopCount = 0; while ((FuncStatus = WriteDspCmdMessage(DspId, pMsgBufr, CmdLength)) != 1) { if (FuncStatus == -1) break; if (++LoopCount > MAX_WAIT_LOOPS) break; gpakHostDelay(); } /* Attempt to read the reply message from the DSP if the command message was sent successfully. */ if (FuncStatus == 1) { for (LoopCount = 0; LoopCount < MAX_WAIT_LOOPS; LoopCount++) { RcvReplyLength = MSG_BUFFER_SIZE * 2; FuncStatus = ReadDspReplyMessage(DspId, pMsgBufr, &RcvReplyLength); if (FuncStatus == 1) { RcvReplyType = (pMsgBufr[0] >> 8) & 0xFF; if ((RcvReplyLength >= ReplyLength) && (RcvReplyType == ReplyType) && VerifyReply(pMsgBufr, ReplyCheckType, ReplyCheckValue)) { RetValue = RcvReplyLength; break; } else if (RcvReplyType == MSG_NULL_REPLY) break; } else if (FuncStatus == -1) break; gpakHostDelay(); } } /* Unlock access to the DSP. */ gpakUnlockAccess(DspId); /* Return the length of the reply message (0 = failure). */ return (RetValue); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakConfigurePorts - Configure a DSP's serial ports. * * FUNCTION * This function configures a DSP's serial ports. * * RETURNS * Status code indicating success or a specific error. * */ gpakConfigPortStatus_t gpakConfigurePorts( unsigned short int DspId, /* DSP Id (0 to MaxDSPCores-1) */ GpakPortConfig_t *pPortConfig, /* pointer to Port Config info */ GPAK_PortConfigStat_t *pStatus /* pointer to Port Config Status */ ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (CpsInvalidDsp); /* Build the Configure Serial Ports message. */ MsgBuffer[0] = MSG_CONFIGURE_PORTS << 8; MsgBuffer[1] = (DSP_WORD) ((pPortConfig->SlotsSelect1 << 12) | ((pPortConfig->FirstBlockNum1 << 8) & 0x0F00) | ((pPortConfig->SecBlockNum1 << 4) & 0x00F0)); MsgBuffer[2] = (DSP_WORD) pPortConfig->FirstSlotMask1; MsgBuffer[3] = (DSP_WORD) pPortConfig->SecSlotMask1; MsgBuffer[4] = (DSP_WORD) ((pPortConfig->SlotsSelect2 << 12) | ((pPortConfig->FirstBlockNum2 << 8) & 0x0F00) | ((pPortConfig->SecBlockNum2 << 4) & 0x00F0)); MsgBuffer[5] = (DSP_WORD) pPortConfig->FirstSlotMask2; MsgBuffer[6] = (DSP_WORD) pPortConfig->SecSlotMask2; MsgBuffer[7] = (DSP_WORD) ((pPortConfig->SlotsSelect3 << 12) | ((pPortConfig->FirstBlockNum3 << 8) & 0x0F00) | ((pPortConfig->SecBlockNum3 << 4) & 0x00F0)); MsgBuffer[8] = (DSP_WORD) pPortConfig->FirstSlotMask3; MsgBuffer[9] = (DSP_WORD) pPortConfig->SecSlotMask3; MsgBuffer[10] = (DSP_WORD) (((pPortConfig->DxDelay1 << 11) & 0x0800) | ((pPortConfig->RxDataDelay1 << 9) & 0x0600) | ((pPortConfig->TxDataDelay1 << 7) & 0x0180) | ((pPortConfig->RxClockPolarity1 << 6) & 0x0040) | ((pPortConfig->TxClockPolarity1 << 5) & 0x0020) | ((pPortConfig->RxFrameSyncPolarity1 << 4) & 0x0010) | ((pPortConfig->TxFrameSyncPolarity1 << 3) & 0x0008) | ((pPortConfig->CompandingMode1 << 1) & 0x0006) | (pPortConfig->SerialWordSize1 & 0x0001)); MsgBuffer[11] = (DSP_WORD) (((pPortConfig->DxDelay2 << 11) & 0x0800) | ((pPortConfig->RxDataDelay2 << 9) & 0x0600) | ((pPortConfig->TxDataDelay2 << 7) & 0x0180) | ((pPortConfig->RxClockPolarity2 << 6) & 0x0040) | ((pPortConfig->TxClockPolarity2 << 5) & 0x0020) | ((pPortConfig->RxFrameSyncPolarity2 << 4) & 0x0010) | ((pPortConfig->TxFrameSyncPolarity2 << 3) & 0x0008) | ((pPortConfig->CompandingMode2 << 1) & 0x0006) | (pPortConfig->SerialWordSize1 & 0x0001)); MsgBuffer[12] = (DSP_WORD) (((pPortConfig->DxDelay3 << 11) & 0x0800) | ((pPortConfig->RxDataDelay3 << 9) & 0x0600) | ((pPortConfig->TxDataDelay3 << 7) & 0x0180) | ((pPortConfig->RxClockPolarity3 << 6) & 0x0040) | ((pPortConfig->TxClockPolarity3 << 5) & 0x0020) | ((pPortConfig->RxFrameSyncPolarity3 << 4) & 0x0010) | ((pPortConfig->TxFrameSyncPolarity3 << 3) & 0x0008) | ((pPortConfig->CompandingMode3 << 1) & 0x0006) | (pPortConfig->SerialWordSize3 & 0x0001)); MsgBuffer[13] = (DSP_WORD) pPortConfig->ThirdSlotMask1; MsgBuffer[14] = (DSP_WORD) pPortConfig->FouthSlotMask1; MsgBuffer[15] = (DSP_WORD) pPortConfig->FifthSlotMask1; MsgBuffer[16] = (DSP_WORD) pPortConfig->SixthSlotMask1; MsgBuffer[17] = (DSP_WORD) pPortConfig->SevenSlotMask1; MsgBuffer[18] = (DSP_WORD) pPortConfig->EightSlotMask1; MsgBuffer[19] = (DSP_WORD) pPortConfig->ThirdSlotMask2;; MsgBuffer[20] = (DSP_WORD) pPortConfig->FouthSlotMask2; MsgBuffer[21] = (DSP_WORD) pPortConfig->FifthSlotMask2;; MsgBuffer[22] = (DSP_WORD) pPortConfig->SixthSlotMask2; MsgBuffer[23] = (DSP_WORD) pPortConfig->SevenSlotMask2;; MsgBuffer[24] = (DSP_WORD) pPortConfig->EightSlotMask2; MsgBuffer[25] = (DSP_WORD) pPortConfig->ThirdSlotMask3;; MsgBuffer[26] = (DSP_WORD) pPortConfig->FouthSlotMask3; MsgBuffer[27] = (DSP_WORD) pPortConfig->FifthSlotMask3;; MsgBuffer[28] = (DSP_WORD) pPortConfig->SixthSlotMask3; MsgBuffer[29] = (DSP_WORD) pPortConfig->SevenSlotMask3;; MsgBuffer[30] = (DSP_WORD) pPortConfig->EightSlotMask3; /* Attempt to send the Configure Serial Ports message to the DSP and receive it's reply. */ if (!TransactCmd(DspId, MsgBuffer, 62, MSG_CONFIG_PORTS_REPLY, 4, 0, 0)) return (CpsDspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ *pStatus = (GPAK_PortConfigStat_t) (MsgBuffer[1] & 0xFF); if (*pStatus == Pc_Success) return (CpsSuccess); else return (CpsParmError); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakConfigureChannel - Configure a DSP's Channel. * * FUNCTION * This function configures a DSP's Channel. * * RETURNS * Status code indicating success or a specific error. * */ gpakConfigChanStatus_t gpakConfigureChannel( unsigned short int DspId, /* DSP Id (0 to MaxDSPCores-1) */ unsigned short int ChannelId, /* Channel Id (0 to MaxChannels-1) */ GpakChanType ChannelType, /* Channel Type */ GpakChannelConfig_t *pChanConfig, /* pointer to Channel Config info */ GPAK_ChannelConfigStat_t *pStatus /* pointer to Channel Config Status */ ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ DSP_WORD MsgLength; /* message length */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (CcsInvalidDsp); /* Make sure the Channel Id is valid. */ if (ChannelId >= MaxChannels[DspId]) return (CcsInvalidChannel); /* Build the Configure Channel message based on the Channel Type. */ switch (ChannelType) { /* PCM to Packet channel type. */ case tdmToTdm: MsgBuffer[2] = (DSP_WORD) ((pChanConfig->PcmInPortA << 8) | (pChanConfig->PcmInSlotA & 0xFF)); MsgBuffer[3] = (DSP_WORD) ((pChanConfig->PcmOutPortA << 8) | (pChanConfig->PcmOutSlotA & 0xFF)); MsgBuffer[4] = (DSP_WORD) ((pChanConfig->PcmInPortB << 8) | (pChanConfig->PcmInSlotB & 0xFF)); MsgBuffer[5] = (DSP_WORD) ((pChanConfig->PcmOutPortB << 8) | (pChanConfig->PcmOutSlotB & 0xFF)); MsgBuffer[6] = (DSP_WORD) ( ((pChanConfig->FaxCngDetB <<11) & 0x0800) | ((pChanConfig->FaxCngDetA <<10) & 0x0400) | ((pChanConfig->MuteToneB << 9) & 0x0200) | ((pChanConfig->MuteToneA << 8) & 0x0100) | ((pChanConfig->FrameRate << 6) & 0x00C0) | ((pChanConfig->ToneTypesB << 5) & 0x0020) | ((pChanConfig->ToneTypesA << 4) & 0x0010) | ((pChanConfig->SoftwareCompand & 3) << 2) | (pChanConfig->EcanEnableB << 1) | (pChanConfig->EcanEnableA & 1) ); MsgBuffer[7] = (DSP_WORD) pChanConfig->EcanParametersA.EcanTapLength; MsgBuffer[8] = (DSP_WORD) pChanConfig->EcanParametersA.EcanNlpType; MsgBuffer[9] = (DSP_WORD) pChanConfig->EcanParametersA.EcanAdaptEnable; MsgBuffer[10] = (DSP_WORD) pChanConfig->EcanParametersA.EcanG165DetEnable; MsgBuffer[11] = (DSP_WORD) pChanConfig->EcanParametersA.EcanDblTalkThresh; MsgBuffer[12] = (DSP_WORD) pChanConfig->EcanParametersA.EcanNlpThreshold; MsgBuffer[13] = (DSP_WORD) pChanConfig->EcanParametersA.EcanNlpConv; MsgBuffer[14] = (DSP_WORD) pChanConfig->EcanParametersA.EcanNlpUnConv; MsgBuffer[15] = (DSP_WORD) pChanConfig->EcanParametersA.EcanNlpMaxSuppress; MsgBuffer[16] = (DSP_WORD) pChanConfig->EcanParametersA.EcanCngThreshold; MsgBuffer[17] = (DSP_WORD) pChanConfig->EcanParametersA.EcanAdaptLimit; MsgBuffer[18] = (DSP_WORD) pChanConfig->EcanParametersA.EcanCrossCorrLimit; MsgBuffer[19] = (DSP_WORD) pChanConfig->EcanParametersA.EcanNumFirSegments; MsgBuffer[20] = (DSP_WORD) pChanConfig->EcanParametersA.EcanFirSegmentLen; MsgBuffer[21] = (DSP_WORD) pChanConfig->EcanParametersB.EcanTapLength; MsgBuffer[22] = (DSP_WORD) pChanConfig->EcanParametersB.EcanNlpType; MsgBuffer[23] = (DSP_WORD) pChanConfig->EcanParametersB.EcanAdaptEnable; MsgBuffer[24] = (DSP_WORD) pChanConfig->EcanParametersB.EcanG165DetEnable; MsgBuffer[25] = (DSP_WORD) pChanConfig->EcanParametersB.EcanDblTalkThresh; MsgBuffer[26] = (DSP_WORD) pChanConfig->EcanParametersB.EcanNlpThreshold; MsgBuffer[27] = (DSP_WORD) pChanConfig->EcanParametersB.EcanNlpConv; MsgBuffer[28] = (DSP_WORD) pChanConfig->EcanParametersB.EcanNlpUnConv; MsgBuffer[29] = (DSP_WORD) pChanConfig->EcanParametersB.EcanNlpMaxSuppress; MsgBuffer[30] = (DSP_WORD) pChanConfig->EcanParametersB.EcanCngThreshold; MsgBuffer[31] = (DSP_WORD) pChanConfig->EcanParametersB.EcanAdaptLimit; MsgBuffer[32] = (DSP_WORD) pChanConfig->EcanParametersB.EcanCrossCorrLimit; MsgBuffer[33] = (DSP_WORD) pChanConfig->EcanParametersB.EcanNumFirSegments; MsgBuffer[34] = (DSP_WORD) pChanConfig->EcanParametersB.EcanFirSegmentLen; MsgLength = 70; // byte number == 35*2 break; /* Unknown (invalid) channel type. */ default: *pStatus = Cc_InvalidChannelType; return (CcsParmError); } MsgBuffer[0] = MSG_CONFIGURE_CHANNEL << 8; MsgBuffer[1] = (DSP_WORD) ((ChannelId << 8) | (ChannelType & 0xFF)); /* Attempt to send the Configure Channel message to the DSP and receive it's reply. */ if (!TransactCmd(DspId, MsgBuffer, MsgLength, MSG_CONFIG_CHAN_REPLY, 4, 1, (DSP_WORD) ChannelId)) return (CcsDspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ *pStatus = (GPAK_ChannelConfigStat_t) (MsgBuffer[1] & 0xFF); if (*pStatus == Cc_Success) return (CcsSuccess); else return (CcsParmError); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakTearDownChannel - Tear Down a DSP's Channel. * * FUNCTION * This function tears down a DSP's Channel. * * RETURNS * Status code indicating success or a specific error. * */ gpakTearDownStatus_t gpakTearDownChannel( unsigned short int DspId, /* DSP Id (0 to MaxDSPCores-1) */ unsigned short int ChannelId, /* Channel Id (0 to MaxChannels-1) */ GPAK_TearDownChanStat_t *pStatus /* pointer to Tear Down Status */ ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (TdsInvalidDsp); /* Make sure the Channel Id is valid. */ if (ChannelId >= MaxChannels[DspId]) return (TdsInvalidChannel); /* Build the Tear Down Channel message. */ MsgBuffer[0] = MSG_TEAR_DOWN_CHANNEL << 8; MsgBuffer[1] = (DSP_WORD) (ChannelId << 8); /* Attempt to send the Tear Down Channel message to the DSP and receive it's reply. */ if (!TransactCmd(DspId, MsgBuffer, 3, MSG_TEAR_DOWN_REPLY, 4, 1, (DSP_WORD) ChannelId)) return (TdsDspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ *pStatus = (GPAK_TearDownChanStat_t) (MsgBuffer[1] & 0xFF); if (*pStatus == Td_Success) return (TdsSuccess); else return (TdsError); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakAlgControl - Control an Algorithm. * * FUNCTION * This function controls an Algorithm * * RETURNS * Status code indicating success or a specific error. * */ gpakAlgControlStat_t gpakAlgControl( unsigned short int DspId, // DSP identifier unsigned short int ChannelId, // channel identifier GpakAlgCtrl_t ControlCode, // algorithm control code GPAK_AlgControlStat_t *pStatus // pointer to return status ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (AcInvalidDsp); /* Make sure the Channel Id is valid. */ if (ChannelId >= MaxChannels[DspId]) return (AcInvalidChannel); MsgBuffer[0] = MSG_ALG_CONTROL << 8; MsgBuffer[1] = (DSP_WORD) ((ChannelId << 8) | (ControlCode & 0xFF)); /* Attempt to send the Tear Down Channel message to the DSP and receive it's reply. */ //need_reply_len; if (!TransactCmd(DspId, MsgBuffer, 4, MSG_ALG_CONTROL_REPLY, 4, 1, (DSP_WORD) ChannelId)) return (AcDspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ *pStatus = (GPAK_AlgControlStat_t) (MsgBuffer[1] & 0xFF); if (*pStatus == Ac_Success) return (AcSuccess); else return (AcParmError); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadEventFIFOMessage - read from the event fifo * * FUNCTION * This function reads a single event from the event fifo if one is available * * RETURNS * Status code indicating success or a specific error. * * Notes: This function should be called in a loop until the return status * indicates that the fifo is empty. * * If the event code equals "EventLoopbackTeardownComplete", then the * contents of *pChannelId hold the coderBlockId that was assigned to * the loopback coder that was torn down. */ gpakReadEventFIFOMessageStat_t gpakReadEventFIFOMessage( unsigned short int DspId, // DSP identifier unsigned short int *pChannelId, // pointer to channel identifier GpakAsyncEventCode_t *pEventCode, // pointer to Event Code GpakAsyncEventData_t *pEventData // pointer to Event Data Struct ) { DSP_WORD WordBuffer[WORD_BUFFER_SIZE]; /* DSP words buffer */ GpakAsyncEventCode_t EventCode; /* DSP's event code */ DSP_WORD EventDataLength; /* Length of event to read */ DSP_WORD ChannelId; /* DSP's channel Id */ DSP_ADDRESS EventInfoAddress; /* address of EventFIFO info structure */ DSP_ADDRESS BufrBaseAddress; /* base address of EventFIFO buffer */ DSP_ADDRESS BufrLastAddress; /* last address of EventFIFO buffer */ DSP_ADDRESS TakeAddress; /* current take address in fifo buffer */ DSP_WORD BufrSize; /* size (in words) of event FIFO buffer */ DSP_WORD PutIndex; /* event fifo put index */ DSP_WORD TakeIndex; /* event fifo take index */ DSP_WORD WordsReady; /* number words ready for read out of event fifo */ DSP_WORD EventError; /* flag indicating error with event fifo msg */ #if 0 DSP_WORD *pDebugData; /* debug data buffer pointer in event data struct */ #endif /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (RefInvalidDsp); /* Lock access to the DSP. */ gpakLockAccess(DspId); /* Check if the DSP was reset and is ready. */ if (CheckDspReset(DspId) == -1) { gpakUnlockAccess(DspId); return (RefDspCommFailure); } /* Check if an event message is ready in the DSP. */ EventInfoAddress = pEventFifoAddress[DspId]; gpakReadDspMemory(DspId, EventInfoAddress, CIRC_BUFFER_INFO_STRUCT_SIZE, WordBuffer); RECONSTRUCT_LONGWORD(BufrBaseAddress, ((DSP_WORD *)&WordBuffer[CB_BUFR_BASE])); BufrSize = WordBuffer[CB_BUFR_SIZE]; PutIndex = WordBuffer[CB_BUFR_PUT_INDEX]; TakeIndex = WordBuffer[CB_BUFR_TAKE_INDEX]; if (PutIndex >= TakeIndex) WordsReady = PutIndex - TakeIndex; else WordsReady = PutIndex + BufrSize - TakeIndex; if (WordsReady < 2) { gpakUnlockAccess(DspId); return (RefNoEventAvail); } /* Read the event header from the DSP's Event FIFO. */ TakeAddress = BufrBaseAddress + TakeIndex; BufrLastAddress = BufrBaseAddress + BufrSize - 1; ReadCircBuffer(DspId, BufrBaseAddress, BufrLastAddress, &TakeAddress, WordBuffer, 2); TakeIndex += 2; if (TakeIndex >= BufrSize) TakeIndex -= BufrSize; ChannelId = (WordBuffer[0] >> 8) & 0xFF; EventCode = (GpakAsyncEventCode_t)(WordBuffer[0] & 0xFF); EventDataLength = WordBuffer[1]; EventError = 0; switch (EventCode) { case EventToneDetect: if (EventDataLength > WORD_BUFFER_SIZE) { gpakUnlockAccess(DspId); #if 0 printk("EventDataLength > WORD_BUFFER_SIZE (%d)\n", EventDataLength); #endif return (RefInvalidEvent); } ReadCircBuffer(DspId, BufrBaseAddress, BufrLastAddress, &TakeAddress, WordBuffer, EventDataLength); pEventData->toneEvent.ToneCode = (GpakToneCodes_t) (WordBuffer[0] & 0xFF); pEventData->toneEvent.ToneDuration = WordBuffer[1]; pEventData->toneEvent.Direction = WordBuffer[2]; pEventData->toneEvent.DebugToneStatus = WordBuffer[3]; TakeIndex += EventDataLength; if (TakeIndex >= BufrSize) TakeIndex -= BufrSize; if (EventDataLength != 4) { #if 0 printk("EventDataLength != 4 it's %d\n", EventDataLength); #endif EventError = 1; } break; default: #if 0 printk("Event Code not in switch\n"); #endif EventError = 1; break; }; /* Update the Take index in the DSP's Packet Out buffer information. */ gpakWriteDspMemory(DspId, EventInfoAddress + CB_BUFR_TAKE_INDEX, 1, &TakeIndex); /* Unlock access to the DSP. */ gpakUnlockAccess(DspId); if (EventError) return(RefInvalidEvent); *pChannelId = ChannelId; *pEventCode = EventCode; return(RefEventAvail); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakPingDsp - ping the DSP to see if it's alive * * FUNCTION * This function checks if the DSP is still communicating with the host * and returns the DSP SW version * * RETURNS * Status code indicating success or a specific error. */ gpakPingDspStat_t gpakPingDsp( unsigned short int DspId, // DSP identifier unsigned short int *pDspSwVersion // DSP software version ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ DSP_WORD DspStatus; /* DSP's reply status */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (PngInvalidDsp); /* send value of 1, DSP increments it */ MsgBuffer[0] = (MSG_PING << 8); /* Attempt to send the ping message to the DSP and receive it's reply. */ if (!TransactCmd(DspId, MsgBuffer, 1, MSG_PING_REPLY, 6, 0, 0)) return (PngDspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ DspStatus = (MsgBuffer[1] & 0xFF); if (DspStatus == 0) { *pDspSwVersion = MsgBuffer[2]; return (PngSuccess); } else return (PngDspCommFailure); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakSerialTxFixedValue - transmit a fixed value on a timeslot * * FUNCTION * This function controls transmission of a fixed value out onto a serial * port's timeslot. * * RETURNS * Status code indicating success or a specific error. */ gpakSerialTxFixedValueStat_t gpakSerialTxFixedValue( unsigned short int DspId, // DSP identifier unsigned short int ChannelId, // channel identifier GpakSerialPort_t PcmOutPort, // PCM Output Serial Port Id unsigned short int PcmOutSlot, // PCM Output Time Slot unsigned short int Value, // 16-bit value GpakActivation State // activation state ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ DSP_WORD DspStatus; /* DSP's reply status */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (TfvInvalidDsp); /* Make sure the Channel Id is valid. */ if (ChannelId >= MaxChannels[DspId]) return (TfvInvalidChannel); /* Build the message. */ MsgBuffer[0] = MSG_SERIAL_TXVAL << 8; MsgBuffer[1] = (DSP_WORD) ((ChannelId << 8) | (State & 0xFF)); MsgBuffer[2] = (DSP_WORD) ((PcmOutPort << 8) | (PcmOutSlot & 0xFF)); MsgBuffer[3] = (DSP_WORD) Value; /* Attempt to send the message to the DSP and receive it's reply. */ //need_reply_len; if (!TransactCmd(DspId, MsgBuffer, 8, MSG_SERIAL_TXVAL_REPLY, 4, 1, ChannelId)) return (TfvDspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ DspStatus = (MsgBuffer[1] & 0xFF); if (DspStatus == 0) return (TfvSuccess); else return (TfvDspCommFailure); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakControlTdmLoopBack - control a serial port's loopback state * * FUNCTION * This function enables/disables the tdm input to output looback mode on a * serial port * * RETURNS * Status code indicating success or a specific error. */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ gpakControlTdmLoopBackStat_t gpakControlTdmLoopBack( unsigned short int DspId, // DSP identifier GpakSerialPort_t SerialPort, // Serial Port Id GpakActivation LoopBackState // Loopback State ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ DSP_WORD DspStatus; /* DSP's reply status */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (ClbInvalidDsp); /* Build the message. */ MsgBuffer[0] = MSG_TDM_LOOPBACK << 8; MsgBuffer[1] = (DSP_WORD) ((SerialPort << 8) | (LoopBackState & 0xFF)); /* Attempt to send the message to the DSP and receive it's reply. */ //need_reply_len; if (!TransactCmd(DspId, MsgBuffer, 4, MSG_TDM_LOOPBACK_REPLY, 4, 0, 0)) return (ClbDspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ DspStatus = (MsgBuffer[1] & 0xFF); if (DspStatus == 0) return (ClbSuccess); else return (ClbDspCommFailure); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadCpuUsage - Read CPU usage statistics from a DSP. * * FUNCTION * This function reads the CPU usage statistics from a DSP's memory. The * average CPU usage in units of .1 percent are obtained for each of the frame * rates. * * RETURNS * Status code indicating success or a specific error. * */ gpakReadCpuUsageStat_t gpakReadCpuUsage( unsigned short int DspId, // Dsp Identifier unsigned short int *pPeakUsage, // pointer to peak usage variable unsigned short int *pPrev1SecPeakUsage // peak usage over previous 1 second ) { DSP_WORD ReadBuffer[2]; /* DSP read buffer */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (RcuInvalidDsp); /* Lock access to the DSP. */ gpakLockAccess(DspId); /* Check if the DSP was reset and is ready. */ if (CheckDspReset(DspId) == -1) return (RcuDspCommFailure); /* Read the CPU Usage statistics from the DSP. */ gpakReadDspMemory(DspId, pDspIfBlk[DspId] + CPU_USAGE_OFFSET, 2, ReadBuffer); /* Unlock access to the DSP. */ gpakUnlockAccess(DspId); /* Store the usage statistics in the specified variables. */ *pPrev1SecPeakUsage = ReadBuffer[0]; *pPeakUsage = ReadBuffer[1]; /* Return with an indication the usage staistics were read successfully. */ return (RcuSuccess); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakResetCpuUsageStats - reset the cpu usage statistics * * FUNCTION * This function resets the cpu utilization statistics * * RETURNS * Status code indicating success or a specific error. */ gpakResetCpuUsageStat_t gpakResetCpuUsageStats( unsigned short int DspId // DSP identifier ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ DSP_WORD DspStatus; /* DSP's reply status */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (RstcInvalidDsp); MsgBuffer[0] = (MSG_RESET_USAGE_STATS << 8); /* Attempt to send the message to the DSP and receive it's reply. */ //need_reply_len; if (!TransactCmd(DspId, MsgBuffer, 2, MSG_RESET_USAGE_STATS_REPLY, 4, 0, 0)) return (RstcDspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ DspStatus = (MsgBuffer[1] & 0xFF); if (DspStatus == 0) return (RstcSuccess); else return (RstcDspCommFailure); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadFramingStats * * FUNCTION * This function reads a DSP's framing interrupt statistics * * RETURNS * Status code indicating success or a specific error. */ gpakReadFramingStatsStatus_t gpakReadFramingStats( unsigned short int DspId, // DSP identifier unsigned short int *pFramingError1Count, // port 1 Framing error count unsigned short int *pFramingError2Count, // port 2 Framing error count unsigned short int *pFramingError3Count, // port 3 Framing error count unsigned short int *pDmaStopErrorCount, // DMA-stoppage error count unsigned short int *pDmaSlipStatsBuffer // DMA slips count ) { DSP_WORD ReadBuffer[10]; /* DSP read buffer */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (RfsInvalidDsp); /* Lock access to the DSP. */ gpakLockAccess(DspId); /* Check if the DSP was reset and is ready. */ if (CheckDspReset(DspId) == -1) return (RfsDspCommFailure); /* Read the framing interrupt statistics from the DSP. */ gpakReadDspMemory(DspId, pDspIfBlk[DspId] + FRAMING_STATS_OFFSET, 10, ReadBuffer); /* Unlock access to the DSP. */ gpakUnlockAccess(DspId); /* Store the framing statistics in the specified variables. */ *pFramingError1Count = ReadBuffer[0]; *pFramingError2Count = ReadBuffer[1]; *pFramingError3Count = ReadBuffer[2]; *pDmaStopErrorCount = ReadBuffer[3]; if(pDmaSlipStatsBuffer != 0) // If users want to get the DMA slips count { pDmaSlipStatsBuffer[0] = ReadBuffer[4]; pDmaSlipStatsBuffer[1] = ReadBuffer[5]; pDmaSlipStatsBuffer[2] = ReadBuffer[6]; pDmaSlipStatsBuffer[3] = ReadBuffer[7]; pDmaSlipStatsBuffer[4] = ReadBuffer[8]; pDmaSlipStatsBuffer[5] = ReadBuffer[9]; } /* Return with an indication the statistics were read successfully. */ return (RfsSuccess); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakResetFramingStats - reset a DSP's framing interrupt statistics * * FUNCTION * This function resets a DSP's framing interrupt statistics * * RETURNS * Status code indicating success or a specific error. */ gpakResetFramingStatsStatus_t gpakResetFramingStats( unsigned short int DspId // DSP identifier ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ DSP_WORD DspStatus; /* DSP's reply status */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (RstfInvalidDsp); MsgBuffer[0] = (MSG_RESET_FRAME_STATS << 8); /* Attempt to send the message to the DSP and receive it's reply. */ //need_reply_len; if (!TransactCmd(DspId, MsgBuffer, 2, MSG_RESET_FRAME_STATS_REPLY, 4, 0, 0)) return (RstfDspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ DspStatus = (MsgBuffer[1] & 0xFF); if (DspStatus == 0) return (RstfSuccess); else return (RstfDspCommFailure); } /* * gpakDownloadDsp - Download a DSP's Program and initialized Data memory. * * FUNCTION * This function reads a DSP's Program and Data memory image from the * specified file and writes the image to the DSP's memory. * * RETURNS * Status code indicating success or a specific error. * */ gpakDownloadStatus_t gpakDownloadDsp( unsigned short DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ GPAK_FILE_ID FileId /* G.PAK Download File Identifier */ ) { gpakDownloadStatus_t RetStatus; /* function return status */ int NumRead; /* number of file bytes read */ DSP_ADDRESS Address; /* DSP address */ unsigned int WordCount; /* number of words in record */ unsigned int NumWords; /* number of words to read/write */ unsigned int i; /* loop index / counter */ unsigned int j; /* loop index */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (GdlInvalidDsp); /* Lock access to the DSP. */ gpakLockAccess(DspId); RetStatus = GdlSuccess; while (RetStatus == GdlSuccess) { /* Read a record header from the file. */ NumRead = gpakReadFile(FileId, DlByteBufr, 6); if (NumRead == -1) { RetStatus = GdlFileReadError; break; } if (NumRead != 6) { RetStatus = GdlInvalidFile; break; } Address = (((DSP_ADDRESS) DlByteBufr[1]) << 16) | (((DSP_ADDRESS) DlByteBufr[2]) << 8) | ((DSP_ADDRESS) DlByteBufr[3]); WordCount = (((unsigned int) DlByteBufr[4]) << 8) | ((unsigned int) DlByteBufr[5]); /* Check for the End Of File record. */ if (DlByteBufr[0] == 0xFF) break; /* Verify the record is for a valid memory type. */ if ((DlByteBufr[0] != 0x00) && (DlByteBufr[0] != 0x01)) { RetStatus = GdlInvalidFile; break; } /* Read a block of words at a time from the file and write to the DSP's memory .*/ while (WordCount != 0) { if (WordCount < DOWNLOAD_BLOCK_SIZE) NumWords = WordCount; else NumWords = DOWNLOAD_BLOCK_SIZE; WordCount -= NumWords; NumRead = gpakReadFile(FileId, DlByteBufr, NumWords * 2); if (NumRead == -1) { RetStatus = GdlFileReadError; break; } if (NumRead != (NumWords * 2)) { RetStatus = GdlInvalidFile; break; } for (i = 0, j = 0; i < NumWords; i++, j += 2) DlWordBufr[i] = (((DSP_WORD) DlByteBufr[j]) << 8) | ((DSP_WORD) DlByteBufr[j + 1]); gpakWriteDspMemory(DspId, Address, NumWords, DlWordBufr); Address += ((DSP_ADDRESS) NumWords); } } /* Unlock access to the DSP. */ gpakUnlockAccess(DspId); /* Return with an indication of success or failure. */ return (RetStatus); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadCpuUsage - Read CPU usage statistics from a DSP. * * FUNCTION * This function reads the memory map register section of DSP memory. * * RETURNS * Status code indicating success or a specific error. * */ gpakReadDSPMemoryStat_t gpakReadDSPMemoryMap( unsigned short int DspId, // Dsp Identifier unsigned short int *pDest, // Buffer on host to hold DSP memory map DSP_ADDRESS BufrBaseAddress, // DSP memory users want to read out unsigned short int MemoryLength_Word16 // Length of memory section read out, unit is 16-bit word ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ DSP_WORD DspStatus; /* DSP reply's status */ int i; /* loop index / counter */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (RmmInvalidDsp); /* Verify the message buffer is large enough */ if (MSG_BUFFER_SIZE < MemoryLength_Word16 ) return (RmmSizeTooBig); MsgBuffer[0] = MSG_READ_DSP_MEMORY << 8; MsgBuffer[1] = (DSP_WORD) ((BufrBaseAddress >> 16) & 0xFFFF); MsgBuffer[2] = (DSP_WORD) (BufrBaseAddress & 0xFFFF); MsgBuffer[3] = (DSP_WORD) MemoryLength_Word16; /* Attempt to send the Read memory section message to the DSP and receive it's reply. */ //need_reply_len; if (!TransactCmd(DspId, MsgBuffer, 8, MSG_READ_DSP_MEMORY_REPLY, (MemoryLength_Word16+2)*2, 0, 0) ) return (RmmInvalidAddress); /* Return with an indication of success or failure based on the return status in the reply message. */ DspStatus = (MsgBuffer[1] & 0xFF); if (DspStatus != 0) return (RmmFailure); for (i = 0; i < MemoryLength_Word16; i++) pDest[i] = (short int) MsgBuffer[2 + i]; return (RmmSuccess); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakAccessGPIO - change Direction/read/write the GPIO on DSP * * FUNCTION * This function read/write GPIO and change the GPIO direction * * * RETURNS * Status code indicating success or a specific error. */ gpakAccessGPIOStat_t gpakAccessGPIO( unsigned short int DspId, // DSP identifier GpakGPIOCotrol_t gpakControlGPIO,// select oeration, changeDIR/write/read unsigned short int *pGPIOValue // DSP software version ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ DSP_WORD DspStatus; /* DSP's reply status */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (GPIOInvalidDsp); /* send value of 1, DSP increments it */ MsgBuffer[0] = (MSG_ACCESSGPIO << 8); MsgBuffer[1] = (DSP_WORD) ((gpakControlGPIO << 8) | (*pGPIOValue & 0xFF) ); /* Attempt to send the ping message to the DSP and receive it's reply. */ if (!TransactCmd(DspId, MsgBuffer, 4, MSG_ACCESSGPIO_REPLY, 6, 0, 0)) return (GPIODspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ DspStatus = (MsgBuffer[1] & 0xFF); if (DspStatus == 0) { *pGPIOValue = MsgBuffer[2]; return (GPIOSuccess); } else return (GPIODspCommFailure); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakWriteSystemParms - Write a DSP's System Parameters. * * FUNCTION * This function writes a DSP's System Parameters information. * * Note: * Or-together the desired bit-mask #defines that are listed below. Only * those algorithm parameters whose bit-mask is selected in the UpdateBits * function parameter will be updated. * * RETURNS * Status code indicating success or a specific error. * */ gpakWriteSysParmsStatus_t gpakWriteSystemParms( unsigned short int DspId, // DSP identifier GpakSystemParms_t *pSysParms, /* pointer to System Parms info var */ unsigned short int UpdateBits, /* input: flags indicating which parms to update */ GPAK_SysParmsStat_t *pStatus /* pointer to Write System Parms Status */ ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ DSP_WORD DspStatus; /* DSP's reply status */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (WspInvalidDsp); /* Build the Write System Parameters message. */ MsgBuffer[0] = MSG_WRITE_SYS_PARMS << 8; if (UpdateBits & DTMF_UPDATE_MASK) { MsgBuffer[1] |= DTMF_UPDATE_MASK; MsgBuffer[8] = (DSP_WORD) pSysParms->MinSigLevel; MsgBuffer[9] = (DSP_WORD) (pSysParms->FreqDeviation & 0xff); if (pSysParms->SNRFlag) MsgBuffer[9] |= (1<<8); } MsgBuffer[10] = (DSP_WORD) 0; if (UpdateBits & DTMF_TWIST_UPDATE_MASK) { MsgBuffer[1] |= DTMF_TWIST_UPDATE_MASK; MsgBuffer[10] |= (DSP_WORD) (pSysParms->DtmfFwdTwist & 0x000f); MsgBuffer[10] |= (DSP_WORD) ((pSysParms->DtmfRevTwist << 4) & 0x00f0); } if (UpdateBits & DTMF_VALID_MASK) { MsgBuffer[1] |= DTMF_VALID_MASK; MsgBuffer[11] = (DSP_WORD) (pSysParms->DtmfValidityMask & 0x00ff); } /* Attempt to send the ping message to the DSP and receive it's reply. */ if (!TransactCmd(DspId, MsgBuffer, 24, MSG_WRITE_SYS_PARMS_REPLY, 6, 0, 0)) return (WspDspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ *pStatus = (GPAK_SysParmsStat_t) (MsgBuffer[2] ); DspStatus = (MsgBuffer[1] & 0xFF); if (DspStatus == 0) return (WspSuccess); else return (WspDspCommFailure); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadSystemParms - Read a DSP's System Parameters. * * FUNCTION * This function reads a DSP's System Parameters information. * * RETURNS * Status code indicating success or a specific error. * */ gpakReadSysParmsStatus_t gpakReadSystemParms( unsigned short int DspId, // DSP identifier GpakSystemParms_t *pSysParms /* pointer to System Parms info var */ ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (RspInvalidDsp); /* Build the Read System Parameters message. */ MsgBuffer[0] = MSG_READ_SYS_PARMS << 8; /* Attempt to send the ping message to the DSP and receive it's reply. */ if (!TransactCmd(DspId, MsgBuffer, 2, MSG_READ_SYS_PARMS_REPLY, 22, 0, 0)) return (RspDspCommFailure); /* Extract the System Parameters information from the message. */ pSysParms->DtmfValidityMask = (short int)(MsgBuffer[7]) ; pSysParms->MinSigLevel = (short int)MsgBuffer[8]; pSysParms->SNRFlag = (short int)((MsgBuffer[9]>>8) & 0x1); pSysParms->FreqDeviation = (short int)(MsgBuffer[9] & 0xff); pSysParms->DtmfFwdTwist = (short int)MsgBuffer[10] & 0x000f; pSysParms->DtmfRevTwist = (short int)(MsgBuffer[10] >> 4) & 0x000f; /* Return with an indication that System Parameters info was obtained. */ return (RspSuccess); } zaptel-1.4.11/kernel/wctdm24xxp/gpakenum.h0000644000000000000000000001376710751714440017100 0ustar rootroot/* * 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. The standard * GPL disclaimer is given inline below for your convenience. * * 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 _GPAKENUM_H /* prevent multiple inclusion */ #define _GPAKENUM_H /* G.PAK Serial Port Word Size */ typedef enum { SerWordSize8 = 0, // 8-bit seial word SerWordSize16 = 1 // 16-bit serial word } GpakSerWordSize_t; /* G.PAK Serial Port FrameSync Polarity */ typedef enum { FrameSyncActLow = 0, // active low frame sync signal FrameSyncActHigh = 1 // active high frame sync signal } GpakSerFrameSyncPol_t; /* G.PAK Serial Port Clock Polarity */ typedef enum { SerClockActLow = 0, // active low serial clock SerClockActHigh = 1 // active high serial clock } GpakSerClockPol_t; /* G.PAK Serial Port Data Delay */ typedef enum { DataDelay0 = 0, // no data delay DataDelay1 = 1, // 1-bit data delay DataDelay2 = 2 // 2-bit data delay } GpakSerDataDelay_t; /* G.PAK Serial Port Ids. */ typedef enum { SerialPortNull = 0, // null serial port SerialPort1 = 1, // first PCM serial stream port (McBSP0) SerialPort2 = 2, // second PCM serial stream port (McBSP1) SerialPort3 = 3 // third PCM serial stream port (McBSP2) } GpakSerialPort_t; /* G.PAK serial port Slot Configuration selection codes. */ typedef enum { SlotCfgNone = 0, // no time slots used SlotCfg2Groups = 2, // 2 groups of 16 time slots used, 32 Channels system SlotCfg8Groups = 8 // 8-partition mode for 128-channel system } GpakSlotCfg_t; /* G.PAK serial port Companding Mode codes. */ typedef enum { cmpPCMU=0, // u-Law cmpPCMA=1, // A-Law cmpNone=2 // none } GpakCompandModes; /* G.PAK Active/Inactive selection codes. */ typedef enum { Disabled=0, // Inactive Enabled=1 // Active } GpakActivation; /* G.PAK Channel Type codes. */ typedef enum { inactive=0, // channel inactive tdmToTdm=1 // tdmToTdm } GpakChanType; /* G.PAK Algorithm control commands */ typedef enum { EnableEcanA = 0, // Enable A side echo canceller BypassEcanA = 1, // Bypass A side echo canceller ResetEcanA = 2, // Reset A side echo canceller EnableEcanB = 3, // Enable B side echo canceller BypassEcanB = 4, // Bypass B side echo canceller ResetEcanB = 5, // Reset B side echo canceller EnableMuLawSwCompanding = 6,// Enable Mu-law Software companding EnableALawSwCompanding = 7, // Enable Mu-law Software companding BypassSwCompanding = 8, // Bypass Software companding EnableDTMFMuteA = 9, // Mute A side Dtmf digit after tone detected DisableDTMFMuteA = 10, // Do not mute A side Dtmf digit once tone detected EnableDTMFMuteB = 11, // Mute B side Dtmf digit after tone detected DisableDTMFMuteB = 12, // Do not mute B side Dtmf digit once tone detected EnableFaxCngDetectA = 13, // Enable A side Fax CNG detector, channel must be configed already DisableFaxCngDetectA = 14, // Disable A side Fax CNG detector, channel must be configed already EnableFaxCngDetectB = 15, // Enable B side Fax CNG detector, channel must be configed already DisableFaxCngDetectB = 16 // Disable B side Fax CNG detector, channel must be configed already } GpakAlgCtrl_t; /* G.PAK Tone types. */ typedef enum { Null_tone = 0, // no tone detection DTMF_tone = 1 // DTMF tone } GpakToneTypes; /* G.PAK direction. */ typedef enum { TDMAToB = 0, // A to B TDMBToA = 1 // B to A } GpakTdmDirection; typedef enum { rate1ms=0, rate2ms=1, rate10ms=2 } GpakRate_t; /* G.PAK Asynchronous Event Codes */ typedef enum { EventToneDetect = 0, // Tone detection event EventDSPDebug = 7 // DSP debug data event } GpakAsyncEventCode_t; /* G.PAK MF Tone Code Indices */ typedef enum { DtmfDigit1 = 0, // DTMF Digit 1 DtmfDigit2 = 1, // DTMF Digit 2 DtmfDigit3 = 2, // DTMF Digit 3 DtmfDigitA = 3, // DTMF Digit A DtmfDigit4 = 4, // DTMF Digit 4 DtmfDigit5 = 5, // DTMF Digit 5 DtmfDigit6 = 6, // DTMF Digit 6 DtmfDigitB = 7, // DTMF Digit B DtmfDigit7 = 8, // DTMF Digit 7 DtmfDigit8 = 9, // DTMF Digit 8 DtmfDigit9 = 10, // DTMF Digit 9 DtmfDigitC = 11, // DTMF Digit C DtmfDigitSt = 12, // DTMF Digit * DtmfDigit0 = 13, // DTMF Digit 0 DtmfDigitPnd = 14, // DTMF Digit # DtmfDigitD = 15, // DTMF Digit D FaxCngDigit = 90, // Fax Calling Tone (1100 Hz) EndofMFDigit = 100, // End of MF digit EndofCngDigit = 101 // End of Cng Digit } GpakToneCodes_t; /* GPIO control code*/ typedef enum { GPIO_READ = 0, GPIO_WRITE = 1, GPIO_DIR = 2 } GpakGPIOCotrol_t; #endif // end multiple inclusion zaptel-1.4.11/kernel/wctdm24xxp/wctdm24xxp.h0000644000000000000000000001470710773007372017313 0ustar rootroot/* * Wildcard TDM2400P TDM FXS/FXO Interface Driver for Zapata Telephony interface * * Written by Mark Spencer * Support for TDM800P and VPM150M by Matthew Fredrickson * * Copyright (C) 2005, 2006, 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. * */ #ifndef _WCTDM24XXP_H #define _WCTDM24XXP_H #include "../zaptel.h" #include "../voicebus.h" #include #define NUM_FXO_REGS 60 #define WC_MAX_IFACES 128 /*! * \brief Default ringer debounce (in ms) */ #define DEFAULT_RING_DEBOUNCE 128 #define POLARITY_DEBOUNCE 64 /* Polarity debounce (in ms) */ #define OHT_TIMER 6000 /* How long after RING to retain OHT */ #define FLAG_3215 (1 << 0) #define FLAG_EXPRESS (1 << 1) #define EFRAME_SIZE 108 #define ERING_SIZE 16 /* Maximum ring size */ #define EFRAME_GAP 20 #define SFRAME_SIZE ((EFRAME_SIZE * ZT_CHUNKSIZE) + (EFRAME_GAP * (ZT_CHUNKSIZE - 1))) #define MAX_ALARMS 10 #define MOD_TYPE_NONE 0 #define MOD_TYPE_FXS 1 #define MOD_TYPE_FXO 2 #define MOD_TYPE_FXSINIT 3 #define MOD_TYPE_VPM 4 #define MOD_TYPE_QRV 5 #define MOD_TYPE_VPM150M 6 #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 PCI_WINDOW_SIZE ((2 * 2 * 2 * SFRAME_SIZE) + (2 * ERING_SIZE * 4)) #define __CMD_RD (1 << 20) /* Read Operation */ #define __CMD_WR (1 << 21) /* Write Operation */ #define __CMD_FIN (1 << 22) /* Has finished receive */ #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_CARDS 24 #define NUM_EC 4 #define NUM_SLOTS 6 #define MAX_TDM_CHAN 31 #define NUM_CAL_REGS 12 #define USER_COMMANDS 8 #define ISR_COMMANDS 2 #define QRV_DEBOUNCETIME 20 #define MAX_COMMANDS (USER_COMMANDS + ISR_COMMANDS) #define __VPM150M_RWPAGE (1 << 4) #define __VPM150M_RD (1 << 3) #define __VPM150M_WR (1 << 2) #define __VPM150M_FIN (1 << 1) #define __VPM150M_TX (1 << 0) #define VPM150M_HPI_CONTROL 0x00 #define VPM150M_HPI_ADDRESS 0x02 #define VPM150M_HPI_DATA 0x03 #define VPM150M_MAX_COMMANDS 8 /* Some Bit ops for different operations */ #define VPM150M_SPIRESET 0 #define VPM150M_HPIRESET 1 #define VPM150M_SWRESET 2 #define VPM150M_DTMFDETECT 3 #define VPM150M_ACTIVE 4 #define VPM150M_MAX_DATA 1 #define VPM_SUPPORT #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) #define VPM150M_SUPPORT #endif #ifdef VPM_SUPPORT /* Define to get more attention-grabbing but slightly more CPU using echocan status */ #define FANCY_ECHOCAN #endif #ifdef VPM150M_SUPPORT #include "adt_lec.h" #endif struct vpm150m_cmd { unsigned int addr; unsigned char datalen; unsigned char desc; unsigned char txident; unsigned short data[VPM150M_MAX_DATA]; }; struct vpm150m { #ifdef VPM150M_SUPPORT struct workqueue_struct *wq; struct work_struct work; #endif struct wctdm *wc; int dspid; struct semaphore sem; unsigned long control; unsigned char curpage; unsigned short version; struct adt_lec_params curecstate[24]; struct adt_lec_params desiredecstate[24]; unsigned long curdtmfmutestate; unsigned long desireddtmfmutestate; struct vpm150m_cmd cmdq[VPM150M_MAX_COMMANDS]; unsigned char curtone[24]; }; struct calregs { unsigned char vals[NUM_CAL_REGS]; }; struct cmdq { unsigned int cmds[MAX_COMMANDS]; unsigned char isrshadow[ISR_COMMANDS]; }; enum battery_state { BATTERY_UNKNOWN = 0, BATTERY_PRESENT, BATTERY_LOST, }; struct wctdm { char *variety; char board_name[80]; struct zt_span span; unsigned char ios; unsigned int sdi; int usecount; unsigned int intcount; unsigned int rxints; unsigned int txints; unsigned char txident; unsigned char rxident; int dead; int pos; int flags[NUM_CARDS]; int alt; int curcard; unsigned char ctlreg; int cards; int cardflag; /* Bit-map of present cards */ int altcs[NUM_CARDS + NUM_EC]; char qrvhook[NUM_CARDS]; unsigned short qrvdebtime[NUM_CARDS]; int radmode[NUM_CARDS]; #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 unsigned short debouncetime[NUM_CARDS]; signed short rxgain[NUM_CARDS]; signed short txgain[NUM_CARDS]; spinlock_t reglock; wait_queue_head_t regq; /* FXO Stuff */ union { struct fxo { int wasringing; int lastrdtx; int ringdebounce; int offhook; int battdebounce; int battalarm; enum battery_state battery; int lastpol; int polarity; int polaritydebounce; } fxo; struct fxs { int oldrxhook; int debouncehook; int lastrxhook; int debounce; int ohttimer; int idletxhookstate; /* IDLE changing hook state */ int lasttxhook; int palarms; struct calregs calregs; } fxs; } mods[NUM_CARDS]; struct cmdq cmdq[NUM_CARDS + NUM_EC]; /* Receive hook state and debouncing */ int modtype[NUM_CARDS + NUM_EC]; /* Set hook */ int sethook[NUM_CARDS + NUM_EC]; int dacssrc[NUM_CARDS]; int type; #ifdef VPM_SUPPORT int vpm; unsigned long dtmfactive; unsigned long dtmfmask; unsigned long dtmfmutemask; short dtmfenergy[NUM_CARDS]; short dtmfdigit[NUM_CARDS]; struct vpm150m *vpm150m; #ifdef FANCY_ECHOCAN int echocanpos; int blinktimer; #endif #endif struct voicebus *vb; struct zt_chan chans[NUM_CARDS]; int initialized; }; int schluffen(wait_queue_head_t *q); extern spinlock_t ifacelock; extern struct wctdm *ifaces[WC_MAX_IFACES]; #endif zaptel-1.4.11/kernel/wctdm24xxp/gpakErrs.h0000644000000000000000000001465110751714440017040 0ustar rootroot/* * 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. The standard * GPL disclaimer is given inline below for your convenience. * * 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 _GPAKERRS_H /* prevent multiple inclusion */ #define _GPAKERRS_H /* Configure Serial Ports reply status codes. */ typedef enum { Pc_Success = 0, /* serial ports configured successfully */ Pc_ChannelsActive = 1, /* unable to configure while channels active */ Pc_TooManySlots1 = 2, /* too many slots selected for port 1 */ Pc_InvalidBlockCombo1 = 3, /* invalid combination of blocks for port 1 */ Pc_NoSlots1 = 4, /* no slots selected for port 1 */ Pc_InvalidSlots1 = 5, /* invalid slot (> max) selected for port 1 */ Pc_TooManySlots2 = 6, /* too many slots selected for port 2 */ Pc_InvalidBlockCombo2 = 7, /* invalid combination of blocks for port 2 */ Pc_NoSlots2 = 8, /* no slots selected for port 2 */ Pc_InvalidSlots2 = 9, /* invalid slot (> max) selected for port 2 */ Pc_TooManySlots3 = 10, /* too many slots selected for port 3 */ Pc_InvalidBlockCombo3 = 11, /* invalid combination of blocks for port 3 */ Pc_NoSlots3 = 12, /* no slots selected for port 3 */ Pc_InvalidSlots3 = 13 /* invalid slot (> max) selected for port 3 */ } GPAK_PortConfigStat_t; /* Configure Channel reply status codes. */ typedef enum { Cc_Success = 0, /* channel configured successfully */ Cc_InvalidChannelType = 1, /* invalid Channel Type */ Cc_InvalidChannel = 2, /* invalid Channel A Id */ Cc_ChannelActiveA = 3, /* Channel A is currently active */ Cc_InvalidInputPortA = 4, /* invalid Input A Port */ Cc_InvalidInputSlotA = 5, /* invalid Input A Slot */ Cc_BusyInputSlotA = 6, /* busy Input A Slot */ Cc_InvalidOutputPortA = 7, /* invalid Output A Port */ Cc_InvalidOutputSlotA = 8, /* invalid Output A Slot */ Cc_BusyOutputSlotA = 9, /* busy Output A Slot */ Cc_InvalidInputPortB = 10, /* invalid Input B Port */ Cc_InvalidInputSlotB = 11, /* invalid Input B Slot */ Cc_BusyInputSlotB = 12, /* busy Input B Slot */ Cc_InvalidPktInCodingA = 13, /* invalid Packet In A Coding */ Cc_InvalidPktOutCodingA = 14, /* invalid Packet Out A Coding */ Cc_InvalidPktInSizeA = 15, /* invalid Packet In A Frame Size */ Cc_InvalidPktOutSizeA = 16, /* invalid Packet Out A Frame Size */ Cc_ChanTypeNotConfigured = 21, /* channel type was not configured */ Cc_InsuffECResources = 22, /* insufficient ecan resources avail. */ Cc_InsuffTDMResources = 23, /* insufficient tdm block resources avail. */ Cc_InsuffPktBufResources = 25, /* insufficient pkt buffer resources avail. */ Cc_InsuffPcmBufResources = 26, /* insufficient pcm buffer resources avail. */ Cc_BadPcmEcNlpType = 30, /* invalid EC Nlp type */ Cc_BadPcmEcTapLength = 31, /* invalid EC tap length */ Cc_BadPcmEcDblTalkThresh = 32, /* invalid EC double-talk threshold */ Cc_BadPcmEcNlpThreshold = 33, /* invalid EC Nlp threshold */ Cc_BadPcmEcCngThreshold = 34, /* invalid EC Cng threshold */ Cc_BadPcmEcAdaptLimit = 35, /* invalid EC Adapt Limit */ Cc_BadPcmEcCrossCorrLim = 36, /* invalid EC Cross Correlation Limit */ Cc_BadPcmEcNumFirSegs = 37, /* invalid EC Number of FirSegments */ Cc_BadPcmEcFirSegLen = 38, /* invalid EC Fir Segment Length */ /*Cc_InvalidNumEcsEnabled = 48, */ /* more than 1 Ec enabled on channel */ Cc_InvalidFrameRate = 49, /* invalid gpak frame rate */ Cc_InvalidSoftCompand = 50, /* invalid softCompanding type */ Cc_InvalidMuteToneA = 51, /* invalid MuteToneA set, no detector */ Cc_InvalidMuteToneB = 52, /* invalid MuteToneB set, no detector */ Cc_InsuffFaxCngDetResources = 53 /* insufficient tdm block resources avail. */ } GPAK_ChannelConfigStat_t; /* Tear Down Channel reply status codes. */ typedef enum { Td_Success = 0, /* channel torn down successfully */ Td_InvalidChannel = 1, /* invalid Channel Id */ Td_ChannelNotActive = 2 /* channel is not active */ } GPAK_TearDownChanStat_t; typedef enum { Ac_Success = 0, /* algorithm control is successfull */ Ac_InvalidChannel = 1, /* invalid channel identifier */ Ac_InvalidCode = 2, /* invalid algorithm control code */ Ac_ECNotEnabled = 3, /* echo canceller was not allocated */ Ac_InvalidSoftComp = 4, /* invalid softcompanding, 'cause serial port not in companding mode */ Ac_InvalidDTMFMuteA = 5, /* A side invalid Mute, since no dtmf detector */ Ac_InvalidDTMFMuteB = 6, /* B side invalid Mute, since no dtmf detector */ Ac_InvalidFaxCngA = 7, /* A side FAXCNG detector not available */ Ac_InvalidFaxCngB = 8, /* B side FAXCNG detector not available */ Ac_InvalidSysConfig = 9 /* No new system parameters (DTMF config) wrriten yet */ } GPAK_AlgControlStat_t; /* Write System Parameters reply status codes. */ typedef enum { Sp_Success = 0, /* System Parameters written successfully */ Sp_BadTwistThresh = 29 /* invalid twist threshold */ } GPAK_SysParmsStat_t; #endif /* prevent multiple inclusion */ zaptel-1.4.11/kernel/wctdm24xxp/GpakCust.c0000644000000000000000000002653010751714440016775 0ustar rootroot/* * Copyright (c) 2005, Adaptive Digital Technologies, Inc. * * File Name: GpakCust.c * * Description: * This file contains host system dependent functions to support generic * G.PAK API functions. The file is integrated into the host processor * connected to C55x G.PAK DSPs via a Host Port Interface. * * Note: This file needs to be modified by the G.PAK system integrator. * * Version: 1.0 * * Revision History: * 06/15/05 - Initial release. * * This program has been released under the terms of the GPL version 2 by * permission of Adaptive Digital Technologies, Inc. The standard * GPL disclaimer is given inline below for your convenience. * * 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 "zaptel.h" #include "wctdm24xxp.h" #include "GpakCust.h" char vpm150mtone_to_zaptone(GpakToneCodes_t tone) { switch (tone) { case DtmfDigit0: return '0'; case DtmfDigit1: return '1'; case DtmfDigit2: return '2'; case DtmfDigit3: return '3'; case DtmfDigit4: return '4'; case DtmfDigit5: return '5'; case DtmfDigit6: return '6'; case DtmfDigit7: return '7'; case DtmfDigit8: return '8'; case DtmfDigit9: return '9'; case DtmfDigitPnd: return '#'; case DtmfDigitSt: return '*'; case DtmfDigitA: return 'A'; case DtmfDigitB: return 'B'; case DtmfDigitC: return 'C'; case DtmfDigitD: return 'D'; case EndofCngDigit: return 'f'; default: return 0; } } static inline struct wctdm * wc_find_iface(unsigned short dspid) { int i; struct wctdm *ret = NULL; unsigned long flags; spin_lock_irqsave(&ifacelock, flags); for (i = 0; i < WC_MAX_IFACES; i++) if (ifaces[i] && ifaces[i]->vpm150m && (ifaces[i]->vpm150m->dspid == dspid)) ret = ifaces[i]; spin_unlock_irqrestore(&ifacelock, flags); return ret; } static inline struct vpm150m_cmd * vpm150m_empty_slot(struct wctdm *wc) { int x; for (x = 0; x < VPM150M_MAX_COMMANDS; x++) if (!wc->vpm150m->cmdq[x].desc) { return &wc->vpm150m->cmdq[x]; } return NULL; } /* Wait for any outstanding commands to be completed. */ static inline int vpm150m_io_wait(struct wctdm *wc) { int x; int ret=0; for (x=0; x < VPM150M_MAX_COMMANDS;) { if (wc->vpm150m->cmdq[x].desc) { if ((ret=schluffen(&wc->regq))) { return ret; } x=0; } else { ++x; } } return ret; } int wctdm_vpm150m_getreg_full_async(struct wctdm *wc, int pagechange, unsigned int len, unsigned short addr, unsigned short *outbuf, struct vpm150m_cmd **hit_p) { int ret=0; unsigned long flags; BUG_ON(!hit_p); spin_lock_irqsave(&wc->reglock, flags); (*hit_p) = vpm150m_empty_slot(wc); if (*hit_p) { (*hit_p)->desc = __VPM150M_RD; if (pagechange) { (*hit_p)->desc |= __VPM150M_RWPAGE; } (*hit_p)->datalen = len; (*hit_p)->addr = addr; memset((*hit_p)->data, 0, len*sizeof(outbuf[0])); } else { ret = -EBUSY; } spin_unlock_irqrestore(&wc->reglock, flags); return ret; } int wctdm_vpm150m_getreg_full_return(struct wctdm *wc, int pagechange, unsigned int len, unsigned short addr, unsigned short *outbuf, struct vpm150m_cmd **hit_p) { int ret = 0; unsigned long flags; BUG_ON(!hit_p); spin_lock_irqsave(&wc->reglock, flags); do { if ((*hit_p)->desc & __VPM150M_FIN) { memcpy(outbuf, (*hit_p)->data, len*(sizeof(outbuf[0]))); (*hit_p)->desc = 0; (*hit_p) = NULL; ret = 0; } else { spin_unlock_irqrestore(&wc->reglock, flags); if ((ret=schluffen(&wc->regq))) { return ret; } spin_lock_irqsave(&wc->reglock, flags); ret = -EBUSY; } } while (-EBUSY == ret); spin_unlock_irqrestore(&wc->reglock, flags); return ret; } int wctdm_vpm150m_getreg_full(struct wctdm *wc, int pagechange, unsigned int len, unsigned short addr, unsigned short *outbuf) { struct vpm150m_cmd *hit = 0; int ret = 0; do { ret = wctdm_vpm150m_getreg_full_async(wc, pagechange, len, addr, outbuf, &hit); if (!hit) { if ( -EBUSY == ret ) { if ((ret = schluffen(&wc->regq))) return ret; } BUG_ON(0 != ret); } } while (!hit); ret = wctdm_vpm150m_getreg_full_return(wc, pagechange, len, addr, outbuf, &hit); return ret; } int wctdm_vpm150m_setreg_full(struct wctdm *wc, int pagechange, unsigned int len, unsigned int addr, unsigned short *data) { unsigned long flags; struct vpm150m_cmd *hit; int ret, i; do { spin_lock_irqsave(&wc->reglock, flags); hit = vpm150m_empty_slot(wc); if (hit) { hit->desc = __VPM150M_WR; if (pagechange) hit->desc |= __VPM150M_RWPAGE; hit->addr = addr; hit->datalen = len; for (i = 0; i < len; i++) hit->data[i] = data[i]; } spin_unlock_irqrestore(&wc->reglock, flags); if (!hit) { if ((ret = schluffen(&wc->regq))) return ret; } } while (!hit); return (hit) ? 0 : -1; } int wctdm_vpm150m_setpage(struct wctdm *wc, unsigned short addr) { addr &= 0xf; /* Let's optimize this a little bit */ if (wc->vpm150m->curpage == addr) return 0; else { wc->vpm150m->curpage = addr; } return wctdm_vpm150m_setreg_full(wc, 1, 1, 0, &addr); } unsigned char wctdm_vpm150m_getpage(struct wctdm *wc) { unsigned short res; wctdm_vpm150m_getreg_full(wc, 1, 1, 0, &res); return res; } unsigned short wctdm_vpm150m_getreg(struct wctdm *wc, unsigned int len, unsigned int addr, unsigned short *data) { unsigned short res; wctdm_vpm150m_setpage(wc, addr >> 16); if ((addr >> 16) != ((addr + len) >> 16)) printk("getreg: You found it!\n"); res = wctdm_vpm150m_getreg_full(wc, 0, len, addr & 0xffff, data); return res; } int wctdm_vpm150m_setreg(struct wctdm *wc, unsigned int len, unsigned int addr, unsigned short *data) { int res; wctdm_vpm150m_setpage(wc, addr >> 16); if ((addr >> 16) != ((addr + len) >> 16)) printk("getreg: You found it!\n"); res = wctdm_vpm150m_setreg_full(wc, 0, len, addr & 0xffff, data); return res; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadDspMemory - Read DSP memory. * * FUNCTION * This function reads a contiguous block of words from DSP memory starting at * the specified address. * * RETURNS * nothing * */ void gpakReadDspMemory( unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ unsigned int NumWords, /* number of contiguous words to read */ DSP_WORD *pWordValues /* pointer to array of word values variable */ ) { struct wctdm *wc = wc_find_iface(DspId); int i; int transcount; int ret; vpm150m_io_wait(wc); if ( NumWords < VPM150M_MAX_COMMANDS ) { struct vpm150m_cmd* cmds[VPM150M_MAX_COMMANDS] = {0}; wctdm_vpm150m_setpage(wc, DspAddress >> 16); DspAddress &= 0xffff; for (i=0; i < NumWords; ++i) { ret = wctdm_vpm150m_getreg_full_async(wc,0,1,DspAddress+i,&pWordValues[i], &cmds[i]); if (0 != ret) { return; } } for (i=NumWords-1; i >=0; --i) { ret = wctdm_vpm150m_getreg_full_return(wc,0,1,DspAddress+i,&pWordValues[i], &cmds[i]); if (0 != ret) { return; } } } else { for (i = 0; i < NumWords;) { if ((NumWords - i) > VPM150M_MAX_DATA) transcount = VPM150M_MAX_DATA; else transcount = NumWords - i; wctdm_vpm150m_getreg(wc, transcount, DspAddress + i, &pWordValues[i]); i += transcount; } } return; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakWriteDspMemory - Write DSP memory. * * FUNCTION * This function writes a contiguous block of words to DSP memory starting at * the specified address. * * RETURNS * nothing * */ void gpakWriteDspMemory( unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ unsigned int NumWords, /* number of contiguous words to write */ DSP_WORD *pWordValues /* pointer to array of word values to write */ ) { struct wctdm *wc = wc_find_iface(DspId); int i; int transcount; //printk("Writing %d words to memory\n", NumWords); if (wc && wc->vpm150m) { for (i = 0; i < NumWords;) { if ((NumWords - i) > VPM150M_MAX_DATA) transcount = VPM150M_MAX_DATA; else transcount = NumWords - i; wctdm_vpm150m_setreg(wc, transcount, DspAddress + i, &pWordValues[i]); i += transcount; } #if 0 for (i = 0; i < NumWords; i++) { if (wctdm_vpm150m_getreg(wc, DspAddress + i) != pWordValues[i]) { printk("Error in write. Address %x is not %x\n", DspAddress + i, pWordValues[i]); } } #endif } return; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakHostDelay - Delay for a fixed time interval. * * FUNCTION * This function delays for a fixed time interval before returning. The time * interval is the Host Port Interface sampling period when polling a DSP for * replies to command messages. * * RETURNS * nothing * */ void gpakHostDelay(void) { } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakLockAccess - Lock access to the specified DSP. * * FUNCTION * This function aquires exclusive access to the specified DSP. * * RETURNS * nothing * */ void gpakLockAccess(unsigned short DspId) { struct wctdm *wc; wc = wc_find_iface(DspId); if (wc) { struct vpm150m *vpm = wc->vpm150m; if (vpm) down_interruptible(&vpm->sem); } } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakUnlockAccess - Unlock access to the specified DSP. * * FUNCTION * This function releases exclusive access to the specified DSP. * * RETURNS * nothing * */ void gpakUnlockAccess(unsigned short DspId) { struct wctdm *wc; wc = wc_find_iface(DspId); if (wc) { struct vpm150m *vpm = wc->vpm150m; if (vpm) up(&vpm->sem); } } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadFile - Read a block of bytes from a G.PAK Download file. * * FUNCTION * This function reads a contiguous block of bytes from a G.PAK Download file * starting at the current file position. * * RETURNS * The number of bytes read from the file. * -1 indicates an error occurred. * 0 indicates all bytes have been read (end of file) * */ int gpakReadFile( GPAK_FILE_ID FileId, /* G.PAK Download File Identifier */ unsigned char *pBuffer, /* pointer to buffer for storing bytes */ unsigned int NumBytes /* number of bytes to read */ ) { #ifdef VPM150M_SUPPORT struct wctdm_firmware *fw = FileId; unsigned int i, count; if (!fw || !fw->fw) return -1; if (NumBytes > (fw->fw->size - fw->offset)) count = fw->fw->size - fw->offset; else count = NumBytes; for (i = 0; i < count; i++) pBuffer[i] = fw->fw->data[fw->offset + i]; fw->offset += count; return count; #endif } zaptel-1.4.11/kernel/wctdm24xxp/GpakHpi.h0000644000000000000000000000730510751714440016603 0ustar rootroot/* * 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. The standard * GPL disclaimer is given inline below for your convenience. * * 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 _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 */ zaptel-1.4.11/kernel/ztdummy.h0000644000000000000000000000710310751714440014741 0ustar rootroot/* * Dummy Zaptel Driver for Zapata Telephony interface * * Written by Robert Pleh * * Copyright (C) 2002, Hermes Softlab * * 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 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,19) #define USB2420 #endif struct ztdummy { struct zt_span span; struct zt_chan chan; #ifdef LINUX26 unsigned int counter; #ifdef USE_RTC spinlock_t rtclock; rtc_task_t rtc_task; #endif #endif }; #ifndef LINUX26 /* Uhci definitions and structures - from file usb-uhci.h */ #define TD_CTRL_IOC (1 << 24) /* Interrupt on Complete */ #define USBSTS 2 typedef enum { TD_TYPE, QH_TYPE } uhci_desc_type_t; typedef struct { __u32 link; __u32 status; __u32 info; __u32 buffer; } uhci_td_t, *puhci_td_t; typedef struct { __u32 head; __u32 element; /* Queue element pointer */ } uhci_qh_t, *puhci_qh_t; typedef struct { union { uhci_td_t td; uhci_qh_t qh; } hw; uhci_desc_type_t type; dma_addr_t dma_addr; struct list_head horizontal; struct list_head vertical; struct list_head desc_list; int last_used; } uhci_desc_t, *puhci_desc_t; typedef struct { struct list_head desc_list; // list pointer to all corresponding TDs/QHs associated with this request dma_addr_t setup_packet_dma; dma_addr_t transfer_buffer_dma; unsigned long started; #ifdef USB2420 struct urb *next_queued_urb; // next queued urb for this EP struct urb *prev_queued_urb; #else urb_t *next_queued_urb; urb_t *prev_queued_urb; #endif uhci_desc_t *bottom_qh; uhci_desc_t *next_qh; // next helper QH char use_loop; char flags; } urb_priv_t, *purb_priv_t; struct virt_root_hub { int devnum; /* Address of Root Hub endpoint */ void *urb; void *int_addr; int send; int interval; int numports; int c_p_r[8]; struct timer_list rh_int_timer; }; typedef struct uhci { int irq; unsigned int io_addr; unsigned int io_size; unsigned int maxports; int running; int apm_state; struct uhci *next; // chain of uhci device contexts struct list_head urb_list; // list of all pending urbs spinlock_t urb_list_lock; // lock to keep consistency int unlink_urb_done; atomic_t avoid_bulk; struct usb_bus *bus; // our bus __u32 *framelist; dma_addr_t framelist_dma; uhci_desc_t **iso_td; uhci_desc_t *int_chain[8]; uhci_desc_t *ls_control_chain; uhci_desc_t *control_chain; uhci_desc_t *bulk_chain; uhci_desc_t *chain_end; uhci_desc_t *td1ms; uhci_desc_t *td32ms; struct list_head free_desc; spinlock_t qh_lock; spinlock_t td_lock; struct virt_root_hub rh; //private data of the virtual root hub int loop_usage; // URBs using bandwidth reclamation struct list_head urb_unlinked; // list of all unlinked urbs long timeout_check; int timeout_urbs; struct pci_dev *uhci_pci; struct pci_pool *desc_pool; long last_error_time; // last error output in uhci_interrupt() } uhci_t, *puhci_t; #endif zaptel-1.4.11/kernel/digits.h0000644000000000000000000000263110771042441014511 0ustar rootroot/* * Zapata Telephony * * 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 _DIGITS_H #define _DIGITS_H #define DEFAULT_DTMF_LENGTH 100 * ZT_CHUNKSIZE #define DEFAULT_MFR1_LENGTH 68 * ZT_CHUNKSIZE #define DEFAULT_MFR2_LENGTH 100 * ZT_CHUNKSIZE #define PAUSE_LENGTH 500 * ZT_CHUNKSIZE /* At the end of silence, the tone stops */ static struct zt_tone dtmf_silence = { .tonesamples = DEFAULT_DTMF_LENGTH, }; /* At the end of silence, the tone stops */ static struct zt_tone mfr1_silence = { .tonesamples = DEFAULT_MFR1_LENGTH, }; /* At the end of silence, the tone stops */ static struct zt_tone mfr2_silence = { .tonesamples = DEFAULT_MFR2_LENGTH, }; /* A pause in the dialing */ static struct zt_tone tone_pause = { .tonesamples = PAUSE_LENGTH, }; #endif zaptel-1.4.11/kernel/ztdummy.c0000644000000000000000000002671610756340452014752 0ustar rootroot/* * Dummy Zaptel Driver for Zapata Telephony interface * * Required: usb-uhci module and kernel > 2.4.4 OR kernel > 2.6.0 * * Written by Robert Pleh * 2.6 version by Tony Hoyle * Unified by Mark Spencer * Converted to use RTC on i386 by Tony Mountifield * * Converted to use HighResTimers on i386 by Jeffery Palmer * * 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. * */ /* * 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 #ifndef VERSION_CODE # define VERSION_CODE(vers,rel,seq) ( ((vers)<<16) | ((rel)<<8) | (seq) ) #endif #if LINUX_VERSION_CODE < VERSION_CODE(2,4,5) # error "This kernel is too old: not supported by this file" #endif /* * NOTE: (only applies to kernel 2.6) * If using an i386 architecture without a PC real-time clock, * the #define USE_RTC should be commented out. */ #if defined(__i386__) || defined(__x86_64__) #if LINUX_VERSION_CODE >= VERSION_CODE(2,6,13) /* The symbol hrtimer_forward is only exported as of 2.6.22: */ #if defined(CONFIG_HIGH_RES_TIMERS) && LINUX_VERSION_CODE >= VERSION_CODE(2,6,22) #define USE_HIGHRESTIMER #else #define USE_RTC #endif #else #if 0 #define USE_RTC #endif #endif #endif #include #include #include #include #include #include "zaptel.h" #ifndef LINUX26 #include #include #include #endif #ifdef LINUX26 #ifdef USE_HIGHRESTIMER #include #endif #ifdef USE_RTC #include #endif #include #endif #include "ztdummy.h" static struct ztdummy *ztd; static int debug = 0; #ifdef LINUX26 #ifdef USE_HIGHRESTIMER #define CLOCK_SRC "HRtimer" struct hrtimer zaptimer; #elif defined(USE_RTC) #define CLOCK_SRC "RTC" static int rtc_rate = 0; static int current_rate = 0; static int taskletpending = 0; static struct tasklet_struct ztd_tlet; static void ztd_tasklet(unsigned long data); #else /* Linux 2.6, but no RTC or HRTIMER used */ #define CLOCK_SRC "Linux26" /* 2.6 kernel timer stuff */ static struct timer_list timer; #endif #else #if LINUX_VERSION_CODE < VERSION_CODE(2,4,5) # error "This kernel is too old: not supported by this file" #endif #define CLOCK_SRC "UHCI" /* Old UCHI stuff */ static uhci_desc_t *td; static uhci_t *s; static int monitor = 0; /* exported kernel symbols */ extern int insert_td (uhci_t *s, uhci_desc_t *qh, uhci_desc_t* new, int flags); extern int alloc_td (uhci_t *s, uhci_desc_t ** new, int flags); extern int insert_td_horizontal (uhci_t *s, uhci_desc_t *td, uhci_desc_t* new); extern int unlink_td (uhci_t *s, uhci_desc_t *element, int phys_unlink); extern void fill_td (uhci_desc_t *td, int status, int info, __u32 buffer); extern void uhci_interrupt (int irq, void *__uhci, struct pt_regs *regs); extern int delete_desc (uhci_t *s, uhci_desc_t *element); extern uhci_t **uhci_devices; #endif #define ZAPTEL_RATE 1000 /* zaptel ticks per second */ #define ZAPTEL_TIME (1000000 / ZAPTEL_RATE) /* zaptel tick time in us */ #define ZAPTEL_TIME_NS (ZAPTEL_TIME * 1000) /* zaptel tick time in ns */ /* Different bits of the debug variable: */ #define DEBUG_GENERAL (1 << 0) #define DEBUG_TICKS (1 << 1) #ifdef LINUX26 #ifdef USE_RTC static void update_rtc_rate(struct ztdummy *ztd) { if (((rtc_rate & (rtc_rate - 1)) != 0) || (rtc_rate > 8192) || (rtc_rate < 2)) { printk(KERN_NOTICE "Invalid RTC rate %d specified\n", rtc_rate); rtc_rate = current_rate; /* Set default RTC rate */ } if (!rtc_rate || (rtc_rate != current_rate)) { rtc_control(&ztd->rtc_task, RTC_IRQP_SET, current_rate = (rtc_rate ? rtc_rate : 1024)); /* 1024 Hz */ printk(KERN_INFO "ztdummy: RTC rate is %d\n", rtc_rate); ztd->counter = 0; } } static void ztd_tasklet(unsigned long data) { if (taskletpending) update_rtc_rate((struct ztdummy *)ztd); taskletpending = 0; } /* rtc_interrupt - called at 1024Hz from hook in RTC handler */ static void ztdummy_rtc_interrupt(void *private_data) { struct ztdummy *ztd = private_data; unsigned long flags; /* Is spinlock required here??? */ spin_lock_irqsave(&ztd->rtclock, flags); ztd->counter += ZAPTEL_TIME; while (ztd->counter >= current_rate) { ztd->counter -= current_rate; /* Update of RTC IRQ rate isn't possible from interrupt handler :( */ if (!taskletpending && (current_rate != rtc_rate)) { taskletpending = 1; tasklet_hi_schedule(&ztd_tlet); } zt_receive(&ztd->span); zt_transmit(&ztd->span); } spin_unlock_irqrestore(&ztd->rtclock, flags); } #elif defined(USE_HIGHRESTIMER) static enum hrtimer_restart ztdummy_hr_int(struct hrtimer *htmr) { unsigned long overrun; /* Trigger Zaptel */ zt_receive(&ztd->span); zt_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, htmr->expires, ktime_set(0, ZAPTEL_TIME_NS)); if(overrun > 1) { if(printk_ratelimit()) printk(KERN_NOTICE "ztdummy: 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 "ztdummy: 5000 ticks from hrtimer\n"); } /* Always restart the timer */ return HRTIMER_RESTART; } #else /* use kernel system tick timer if PC architecture RTC is not available */ static void ztdummy_timer(unsigned long param) { timer.expires = jiffies + 1; add_timer(&timer); ztd->counter += ZAPTEL_TIME; while (ztd->counter >= HZ) { ztd->counter -= HZ; zt_receive(&ztd->span); zt_transmit(&ztd->span); } } #endif #else static void ztdummy_interrupt(int irq, void *dev_id, struct pt_regs *regs) { unsigned short status; unsigned int io_addr = s->io_addr; status = inw (io_addr + USBSTS); if (status != 0) { /* interrupt from our USB port */ static int check_int = 0; zt_receive(&ztd->span); zt_transmit(&ztd->span); /* TODO: What's the relation between monitor and * DEBUG_TICKS */ if (monitor && check_int) { check_int = 1; printk(KERN_NOTICE "ztdummy: interrupt triggered \n"); } } return; } #endif static int ztdummy_initialize(struct ztdummy *ztd) { /* Zapata stuff */ sprintf(ztd->span.name, "ZTDUMMY/1"); snprintf(ztd->span.desc, sizeof(ztd->span.desc) - 1, "%s (source: " CLOCK_SRC ") %d", ztd->span.name, 1); sprintf(ztd->chan.name, "ZTDUMMY/%d/%d", 1, 0); zap_copy_string(ztd->span.devicetype, "Zaptel Dummy Timing Driver", sizeof(ztd->span.devicetype)); ztd->chan.chanpos = 1; ztd->span.chans = &ztd->chan; ztd->span.channels = 0; /* no channels on our span */ ztd->span.deflaw = ZT_LAW_MULAW; init_waitqueue_head(&ztd->span.maintq); ztd->span.pvt = ztd; ztd->chan.pvt = ztd; if (zt_register(&ztd->span, 0)) { return -1; } return 0; } int init_module(void) { #ifdef LINUX26 #ifdef USE_RTC int err; #endif #else int irq; #ifdef DEFINE_SPINLOCK DEFINE_SPINLOCK(mylock); #else spinlock_t mylock = SPIN_LOCK_UNLOCKED; #endif if (uhci_devices==NULL) { printk (KERN_ERR "ztdummy: Uhci_devices pointer error.\n"); return -ENODEV; } s=*uhci_devices; /* uhci device */ if (s==NULL) { printk (KERN_ERR "ztdummy: No uhci_device found.\n"); return -ENODEV; } #endif ztd = kmalloc(sizeof(struct ztdummy), GFP_KERNEL); if (ztd == NULL) { printk(KERN_ERR "ztdummy: Unable to allocate memory\n"); return -ENOMEM; } memset(ztd, 0x0, sizeof(struct ztdummy)); if (ztdummy_initialize(ztd)) { printk(KERN_ERR "ztdummy: Unable to intialize zaptel driver\n"); kfree(ztd); return -ENODEV; } #ifdef LINUX26 ztd->counter = 0; #ifdef USE_RTC ztd->rtclock = SPIN_LOCK_UNLOCKED; ztd->rtc_task.func = ztdummy_rtc_interrupt; ztd->rtc_task.private_data = ztd; err = rtc_register(&ztd->rtc_task); if (err < 0) { printk(KERN_ERR "ztdummy: Unable to register zaptel rtc driver\n"); zt_unregister(&ztd->span); kfree(ztd); return err; } /* Set default RTC interrupt rate to 1024Hz */ if (!rtc_rate) rtc_rate = 1024; update_rtc_rate(ztd); rtc_control(&ztd->rtc_task, RTC_PIE_ON, 0); tasklet_init(&ztd_tlet, ztd_tasklet, 0); #elif defined(USE_HIGHRESTIMER) printk(KERN_DEBUG "ztdummy: Trying to load High Resolution Timer\n"); hrtimer_init(&zaptimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); printk(KERN_DEBUG "ztdummy: Initialized High Resolution Timer\n"); /* Set timer callback function */ zaptimer.function = ztdummy_hr_int; printk(KERN_DEBUG "ztdummy: Starting High Resolution Timer\n"); hrtimer_start(&zaptimer, ktime_set(0, ZAPTEL_TIME_NS), HRTIMER_MODE_REL); printk(KERN_INFO "ztdummy: High Resolution Timer started, good to go\n"); #else init_timer(&timer); timer.function = ztdummy_timer; timer.expires = jiffies + 1; add_timer(&timer); #endif #else irq=s->irq; spin_lock_irq(&mylock); free_irq(s->irq, s); /* remove uhci_interrupt temporaly */ if (request_irq (irq, ztdummy_interrupt, ZAP_IRQ_SHARED, "ztdummy", ztd)) { spin_unlock_irq(&mylock); err("Our request_irq %d failed!",irq); kfree(ztd); return -EIO; } /* we add our handler first, to assure, that our handler gets called first */ if (request_irq (irq, uhci_interrupt, ZAP_IRQ_SHARED, s->uhci_pci->driver->name, s)) { spin_unlock_irq(&mylock); err("Original request_irq %d failed!",irq); } spin_unlock_irq(&mylock); /* add td to usb host controller interrupt queue */ alloc_td(s, &td, 0); fill_td(td, TD_CTRL_IOC, 0, 0); insert_td_horizontal(s, s->int_chain[0], td); /* use int_chain[0] to get 1ms interrupts */ #endif if (debug) printk(KERN_DEBUG "ztdummy: init() finished\n"); return 0; } void cleanup_module(void) { #ifdef LINUX26 #ifdef USE_RTC if (taskletpending) { tasklet_disable(&ztd_tlet); tasklet_kill(&ztd_tlet); } rtc_control(&ztd->rtc_task, RTC_PIE_OFF, 0); rtc_unregister(&ztd->rtc_task); #elif defined(USE_HIGHRESTIMER) /* Stop high resolution timer */ hrtimer_cancel(&zaptimer); #else del_timer(&timer); #endif #else free_irq(s->irq, ztd); /* disable interrupts */ #endif zt_unregister(&ztd->span); kfree(ztd); #ifndef LINUX26 unlink_td(s, td, 1); delete_desc(s, td); #endif if (debug) printk("ztdummy: cleanup() finished\n"); } #ifdef LINUX26 module_param(debug, int, 0600); #ifdef USE_RTC module_param(rtc_rate, int, 0600); #endif #else MODULE_PARM(debug, "i"); #endif #ifndef LINUX26 MODULE_PARM(monitor, "i"); #endif MODULE_DESCRIPTION("Dummy Zaptel Driver"); MODULE_AUTHOR("Robert Pleh "); #ifdef MODULE_LICENSE MODULE_LICENSE("GPL"); #endif zaptel-1.4.11/kernel/wctdm.c0000644000000000000000000021556611004147250014346 0ustar rootroot/* * Wilcard TDM400P TDM FXS/FXO Interface Driver for Zapata Telephony interface * * Written by Mark Spencer * Matthew Fredrickson * * Copyright (C) 2001, Linux Support Services, 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 #include "proslic.h" #include "wctdm.h" /* * Define for audio vs. register based ring detection * */ /* #define AUDIO_RINGCHECK */ /* 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; 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",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}, }; #include "zaptel.h" #include "fxo_modes.h" #ifdef LINUX26 #include #endif #define NUM_FXO_REGS 60 #define WC_MAX_IFACES 128 #define WC_CNTL 0x00 #define WC_OPER 0x01 #define WC_AUXC 0x02 #define WC_AUXD 0x03 #define WC_MASK0 0x04 #define WC_MASK1 0x05 #define WC_INTSTAT 0x06 #define WC_AUXR 0x07 #define WC_DMAWS 0x08 #define WC_DMAWI 0x0c #define WC_DMAWE 0x10 #define WC_DMARS 0x18 #define WC_DMARI 0x1c #define WC_DMARE 0x20 #define WC_AUXFUNC 0x2b #define WC_SERCTL 0x2d #define WC_FSCDELAY 0x2f #define WC_REGBASE 0xc0 #define WC_SYNC 0x0 #define WC_TEST 0x1 #define WC_CS 0x2 #define WC_VER 0x3 #define BIT_CS (1 << 2) #define BIT_SCLK (1 << 3) #define BIT_SDI (1 << 4) #define BIT_SDO (1 << 5) #define FLAG_EMPTY 0 #define FLAG_WRITE 1 #define FLAG_READ 2 #define DEFAULT_RING_DEBOUNCE 64 /* Ringer Debounce (64 ms) */ #define POLARITY_DEBOUNCE 64 /* Polarity debounce (64 ms) */ #define OHT_TIMER 6000 /* How long after RING to retain OHT */ #define FLAG_3215 (1 << 0) #define NUM_CARDS 4 #define MAX_ALARMS 10 #define MOD_TYPE_FXS 0 #define MOD_TYPE_FXO 1 #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 NUM_CAL_REGS 12 struct calregs { unsigned char vals[NUM_CAL_REGS]; }; enum proslic_power_warn { PROSLIC_POWER_UNKNOWN = 0, PROSLIC_POWER_ON, PROSLIC_POWER_WARNED, }; enum battery_state { BATTERY_UNKNOWN = 0, BATTERY_PRESENT, BATTERY_LOST, }; struct wctdm { struct pci_dev *dev; char *variety; struct zt_span span; unsigned char ios; int usecount; unsigned int intcount; int dead; int pos; int flags[NUM_CARDS]; int freeregion; int alt; int curcard; int cardflag; /* Bit-map of present cards */ enum proslic_power_warn proslic_power; spinlock_t lock; union { struct fxo { #ifdef AUDIO_RINGCHECK unsigned int pegtimer; int pegcount; int peg; int ring; #else int wasringing; int lastrdtx; #endif int ringdebounce; int offhook; unsigned int battdebounce; unsigned int battalarm; enum battery_state battery; int lastpol; int polarity; int polaritydebounce; } fxo; struct fxs { int oldrxhook; int debouncehook; int lastrxhook; int debounce; int ohttimer; int idletxhookstate; /* IDLE changing hook state */ int lasttxhook; int palarms; struct calregs calregs; } fxs; } mod[NUM_CARDS]; /* Receive hook state and debouncing */ int modtype[NUM_CARDS]; unsigned char reg0shadow[NUM_CARDS]; unsigned char reg1shadow[NUM_CARDS]; unsigned long ioaddr; dma_addr_t readdma; dma_addr_t writedma; volatile unsigned int *writechunk; /* Double-word aligned write memory */ volatile unsigned int *readchunk; /* Double-word aligned read memory */ struct zt_chan chans[NUM_CARDS]; }; struct wctdm_desc { char *name; int flags; }; static struct wctdm_desc wctdm = { "Wildcard S400P Prototype", 0 }; static struct wctdm_desc wctdme = { "Wildcard TDM400P REV E/F", 0 }; static struct wctdm_desc wctdmh = { "Wildcard TDM400P REV H", 0 }; static struct wctdm_desc wctdmi = { "Wildcard TDM400P REV I", 0 }; static int acim2tiss[16] = { 0x0, 0x1, 0x4, 0x5, 0x7, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x2, 0x0, 0x3 }; static struct wctdm *ifaces[WC_MAX_IFACES]; static void wctdm_release(struct wctdm *wc); static unsigned int battdebounce; static unsigned int battalarm; static unsigned int battthresh; static int ringdebounce = DEFAULT_RING_DEBOUNCE; static int fwringdetect = 0; static int debug = 0; static int robust = 0; static int timingonly = 0; 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 int fastpickup = 0; static int fxotxgain = 0; static int fxorxgain = 0; static int fxstxgain = 0; static int fxsrxgain = 0; static int wctdm_init_proslic(struct wctdm *wc, int card, int fast , int manual, int sane); static inline void wctdm_transmitprep(struct wctdm *wc, unsigned char ints) { volatile unsigned int *writechunk; int x; if (ints & 0x01) /* Write is at interrupt address. Start writing from normal offset */ writechunk = wc->writechunk; else writechunk = wc->writechunk + ZT_CHUNKSIZE; /* Calculate Transmission */ zt_transmit(&wc->span); for (x=0;xcardflag & (1 << 3)) writechunk[x] |= (wc->chans[3].writechunk[x]); if (wc->cardflag & (1 << 2)) writechunk[x] |= (wc->chans[2].writechunk[x] << 8); if (wc->cardflag & (1 << 1)) writechunk[x] |= (wc->chans[1].writechunk[x] << 16); if (wc->cardflag & (1 << 0)) writechunk[x] |= (wc->chans[0].writechunk[x] << 24); #else if (wc->cardflag & (1 << 3)) writechunk[x] |= (wc->chans[3].writechunk[x] << 24); if (wc->cardflag & (1 << 2)) writechunk[x] |= (wc->chans[2].writechunk[x] << 16); if (wc->cardflag & (1 << 1)) writechunk[x] |= (wc->chans[1].writechunk[x] << 8); if (wc->cardflag & (1 << 0)) writechunk[x] |= (wc->chans[0].writechunk[x]); #endif } } #ifdef AUDIO_RINGCHECK static inline void ring_check(struct wctdm *wc, int card) { int x; short sample; if (wc->modtype[card] != MOD_TYPE_FXO) return; wc->mod[card].fxo.pegtimer += ZT_CHUNKSIZE; for (x=0;xchans[card].readchunk[x], (&(wc->chans[card]))); if ((sample > 10000) && (wc->mod[card].fxo.peg != 1)) { if (debug > 1) printk("High peg!\n"); if ((wc->mod[card].fxo.pegtimer < PEGTIME) && (wc->mod[card].fxo.pegtimer > MINPEGTIME)) wc->mod[card].fxo.pegcount++; wc->mod[card].fxo.pegtimer = 0; wc->mod[card].fxo.peg = 1; } else if ((sample < -10000) && (wc->mod[card].fxo.peg != -1)) { if (debug > 1) printk("Low peg!\n"); if ((wc->mod[card].fxo.pegtimer < (PEGTIME >> 2)) && (wc->mod[card].fxo.pegtimer > (MINPEGTIME >> 2))) wc->mod[card].fxo.pegcount++; wc->mod[card].fxo.pegtimer = 0; wc->mod[card].fxo.peg = -1; } } if (wc->mod[card].fxo.pegtimer > PEGTIME) { /* Reset pegcount if our timer expires */ wc->mod[card].fxo.pegcount = 0; } /* Decrement debouncer if appropriate */ if (wc->mod[card].fxo.ringdebounce) wc->mod[card].fxo.ringdebounce--; if (!wc->mod[card].fxo.offhook && !wc->mod[card].fxo.ringdebounce) { if (!wc->mod[card].fxo.ring && (wc->mod[card].fxo.pegcount > PEGCOUNT)) { /* It's ringing */ if (debug) printk("RING on %d/%d!\n", wc->span.spanno, card + 1); if (!wc->mod[card].fxo.offhook) zt_hooksig(&wc->chans[card], ZT_RXSIG_RING); wc->mod[card].fxo.ring = 1; } if (wc->mod[card].fxo.ring && !wc->mod[card].fxo.pegcount) { /* No more ring */ if (debug) printk("NO RING on %d/%d!\n", wc->span.spanno, card + 1); zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); wc->mod[card].fxo.ring = 0; } } } #endif static inline void wctdm_receiveprep(struct wctdm *wc, unsigned char ints) { volatile unsigned int *readchunk; int x; if (ints & 0x08) readchunk = wc->readchunk + ZT_CHUNKSIZE; else /* Read is at interrupt address. Valid data is available at normal offset */ readchunk = wc->readchunk; for (x=0;xcardflag & (1 << 3)) wc->chans[3].readchunk[x] = (readchunk[x]) & 0xff; if (wc->cardflag & (1 << 2)) wc->chans[2].readchunk[x] = (readchunk[x] >> 8) & 0xff; if (wc->cardflag & (1 << 1)) wc->chans[1].readchunk[x] = (readchunk[x] >> 16) & 0xff; if (wc->cardflag & (1 << 0)) wc->chans[0].readchunk[x] = (readchunk[x] >> 24) & 0xff; #else if (wc->cardflag & (1 << 3)) wc->chans[3].readchunk[x] = (readchunk[x] >> 24) & 0xff; if (wc->cardflag & (1 << 2)) wc->chans[2].readchunk[x] = (readchunk[x] >> 16) & 0xff; if (wc->cardflag & (1 << 1)) wc->chans[1].readchunk[x] = (readchunk[x] >> 8) & 0xff; if (wc->cardflag & (1 << 0)) wc->chans[0].readchunk[x] = (readchunk[x]) & 0xff; #endif } #ifdef AUDIO_RINGCHECK for (x=0;xcards;x++) ring_check(wc, x); #endif /* XXX We're wasting 8 taps. We should get closer :( */ for (x = 0; x < NUM_CARDS; x++) { if (wc->cardflag & (1 << x)) zt_ec_chunk(&wc->chans[x], wc->chans[x].readchunk, wc->chans[x].writechunk); } zt_receive(&wc->span); } static void wctdm_stop_dma(struct wctdm *wc); static void wctdm_reset_tdm(struct wctdm *wc); static void wctdm_restart_dma(struct wctdm *wc); static inline void __write_8bits(struct wctdm *wc, unsigned char bits) { /* Drop chip select */ int x; wc->ios |= BIT_SCLK; outb(wc->ios, wc->ioaddr + WC_AUXD); wc->ios &= ~BIT_CS; outb(wc->ios, wc->ioaddr + WC_AUXD); for (x=0;x<8;x++) { /* Send out each bit, MSB first, drop SCLK as we do so */ if (bits & 0x80) wc->ios |= BIT_SDI; else wc->ios &= ~BIT_SDI; wc->ios &= ~BIT_SCLK; outb(wc->ios, wc->ioaddr + WC_AUXD); /* Now raise SCLK high again and repeat */ wc->ios |= BIT_SCLK; outb(wc->ios, wc->ioaddr + WC_AUXD); bits <<= 1; } /* Finally raise CS back high again */ wc->ios |= BIT_CS; outb(wc->ios, wc->ioaddr + WC_AUXD); } static inline void __reset_spi(struct wctdm *wc) { /* Drop chip select and clock once and raise and clock once */ wc->ios |= BIT_SCLK; outb(wc->ios, wc->ioaddr + WC_AUXD); wc->ios &= ~BIT_CS; outb(wc->ios, wc->ioaddr + WC_AUXD); wc->ios |= BIT_SDI; wc->ios &= ~BIT_SCLK; outb(wc->ios, wc->ioaddr + WC_AUXD); /* Now raise SCLK high again and repeat */ wc->ios |= BIT_SCLK; outb(wc->ios, wc->ioaddr + WC_AUXD); /* Finally raise CS back high again */ wc->ios |= BIT_CS; outb(wc->ios, wc->ioaddr + WC_AUXD); /* Clock again */ wc->ios &= ~BIT_SCLK; outb(wc->ios, wc->ioaddr + WC_AUXD); /* Now raise SCLK high again and repeat */ wc->ios |= BIT_SCLK; outb(wc->ios, wc->ioaddr + WC_AUXD); } static inline unsigned char __read_8bits(struct wctdm *wc) { unsigned char res=0, c; int x; wc->ios |= BIT_SCLK; outb(wc->ios, wc->ioaddr + WC_AUXD); /* Drop chip select */ wc->ios &= ~BIT_CS; outb(wc->ios, wc->ioaddr + WC_AUXD); for (x=0;x<8;x++) { res <<= 1; /* Get SCLK */ wc->ios &= ~BIT_SCLK; outb(wc->ios, wc->ioaddr + WC_AUXD); /* Read back the value */ c = inb(wc->ioaddr + WC_AUXR); if (c & BIT_SDO) res |= 1; /* Now raise SCLK high again */ wc->ios |= BIT_SCLK; outb(wc->ios, wc->ioaddr + WC_AUXD); } /* Finally raise CS back high again */ wc->ios |= BIT_CS; outb(wc->ios, wc->ioaddr + WC_AUXD); wc->ios &= ~BIT_SCLK; outb(wc->ios, wc->ioaddr + WC_AUXD); /* And return our result */ return res; } static void __wctdm_setcreg(struct wctdm *wc, unsigned char reg, unsigned char val) { outb(val, wc->ioaddr + WC_REGBASE + ((reg & 0xf) << 2)); } static unsigned char __wctdm_getcreg(struct wctdm *wc, unsigned char reg) { return inb(wc->ioaddr + WC_REGBASE + ((reg & 0xf) << 2)); } static inline void __wctdm_setcard(struct wctdm *wc, int card) { if (wc->curcard != card) { __wctdm_setcreg(wc, WC_CS, (1 << card)); wc->curcard = card; } } static void __wctdm_setreg(struct wctdm *wc, int card, unsigned char reg, unsigned char value) { __wctdm_setcard(wc, card); if (wc->modtype[card] == MOD_TYPE_FXO) { __write_8bits(wc, 0x20); __write_8bits(wc, reg & 0x7f); } else { __write_8bits(wc, reg & 0x7f); } __write_8bits(wc, value); } static void wctdm_setreg(struct wctdm *wc, int card, unsigned char reg, unsigned char value) { unsigned long flags; spin_lock_irqsave(&wc->lock, flags); __wctdm_setreg(wc, card, reg, value); spin_unlock_irqrestore(&wc->lock, flags); } static unsigned char __wctdm_getreg(struct wctdm *wc, int card, unsigned char reg) { __wctdm_setcard(wc, card); if (wc->modtype[card] == MOD_TYPE_FXO) { __write_8bits(wc, 0x60); __write_8bits(wc, reg & 0x7f); } else { __write_8bits(wc, reg | 0x80); } return __read_8bits(wc); } static inline void reset_spi(struct wctdm *wc, int card) { unsigned long flags; spin_lock_irqsave(&wc->lock, flags); __wctdm_setcard(wc, card); __reset_spi(wc); __reset_spi(wc); spin_unlock_irqrestore(&wc->lock, flags); } static unsigned char wctdm_getreg(struct wctdm *wc, int card, unsigned char reg) { unsigned long flags; unsigned char res; spin_lock_irqsave(&wc->lock, flags); res = __wctdm_getreg(wc, card, reg); spin_unlock_irqrestore(&wc->lock, flags); return res; } static int __wait_access(struct wctdm *wc, int card) { unsigned char data = 0; long origjiffies; int count = 0; #define MAX 6000 /* attempts */ origjiffies = jiffies; /* Wait for indirect access */ while (count++ < MAX) { data = __wctdm_getreg(wc, card, I_STATUS); if (!data) return 0; } if(count > (MAX-1)) printk(" ##### Loop error (%02x) #####\n", data); return 0; } static unsigned char translate_3215(unsigned char address) { int x; for (x=0;xflags[card] & FLAG_3215) { address = translate_3215(address); if (address == 255) return 0; } spin_lock_irqsave(&wc->lock, flags); if(!__wait_access(wc, card)) { __wctdm_setreg(wc, card, IDA_LO,(unsigned char)(data & 0xFF)); __wctdm_setreg(wc, card, IDA_HI,(unsigned char)((data & 0xFF00)>>8)); __wctdm_setreg(wc, card, IAA,address); res = 0; }; spin_unlock_irqrestore(&wc->lock, flags); return res; } static int wctdm_proslic_getreg_indirect(struct wctdm *wc, int card, unsigned char address) { unsigned long flags; int res = -1; char *p=NULL; /* Translate 3215 addresses */ if (wc->flags[card] & FLAG_3215) { address = translate_3215(address); if (address == 255) return 0; } spin_lock_irqsave(&wc->lock, flags); if (!__wait_access(wc, card)) { __wctdm_setreg(wc, card, IAA, address); if (!__wait_access(wc, card)) { unsigned char data1, data2; data1 = __wctdm_getreg(wc, card, IDA_LO); data2 = __wctdm_getreg(wc, card, IDA_HI); res = data1 | (data2 << 8); } else p = "Failed to wait inside\n"; } else p = "failed to wait\n"; spin_unlock_irqrestore(&wc->lock, flags); if (p) printk(p); return res; } static int wctdm_proslic_init_indirect_regs(struct wctdm *wc, int card) { unsigned char i; for (i=0; iflags[card] & FLAG_3215) || (indirect_regs[i].altaddr != 255))) { printk("!!!!!!! %s iREG %X = %X should be %X\n", indirect_regs[i].name,indirect_regs[i].address,j,initial ); passed = 0; } } if (passed) { if (debug) printk("Init Indirect Registers completed successfully.\n"); } else { printk(" !!!!! Init Indirect Registers UNSUCCESSFULLY.\n"); return -1; } return 0; } static inline void wctdm_proslic_recheck_sanity(struct wctdm *wc, int card) { int res; /* Check loopback */ res = wc->reg1shadow[card]; if (!res && (res != wc->mod[card].fxs.lasttxhook)) { res = wctdm_getreg(wc, card, 8); if (res) { printk("Ouch, part reset, quickly restoring reality (%d)\n", card); wctdm_init_proslic(wc, card, 1, 0, 1); } else { if (wc->mod[card].fxs.palarms++ < MAX_ALARMS) { printk("Power alarm on module %d, resetting!\n", card + 1); if (wc->mod[card].fxs.lasttxhook == 4) wc->mod[card].fxs.lasttxhook = 1; wctdm_setreg(wc, card, 64, wc->mod[card].fxs.lasttxhook); } else { if (wc->mod[card].fxs.palarms == MAX_ALARMS) printk("Too many power alarms on card %d, NOT resetting!\n", card + 1); } } } } static inline void wctdm_voicedaa_check_hook(struct wctdm *wc, int card) { #define MS_PER_CHECK_HOOK 16 #ifndef AUDIO_RINGCHECK unsigned char res; #endif signed char b; int poopy = 0; struct fxo *fxo = &wc->mod[card].fxo; /* Try to track issues that plague slot one FXO's */ b = wc->reg0shadow[card]; if ((b & 0x2) || !(b & 0x8)) { /* Not good -- don't look at anything else */ if (debug) printk("Poopy (%02x) on card %d!\n", b, card + 1); poopy++; } b &= 0x9b; if (fxo->offhook) { if (b != 0x9) wctdm_setreg(wc, card, 5, 0x9); } else { if (b != 0x8) wctdm_setreg(wc, card, 5, 0x8); } if (poopy) return; if (!fxo->offhook) { if (fwringdetect) { res = wc->reg0shadow[card] & 0x60; if (fxo->ringdebounce--) { if (res && (res != fxo->lastrdtx) && (fxo->battery == BATTERY_PRESENT)) { if (!fxo->wasringing) { fxo->wasringing = 1; if (debug) printk("RING on %d/%d!\n", wc->span.spanno, card + 1); zt_hooksig(&wc->chans[card], ZT_RXSIG_RING); } fxo->lastrdtx = res; fxo->ringdebounce = 10; } else if (!res) { if ((fxo->ringdebounce == 0) && fxo->wasringing) { fxo->wasringing = 0; if (debug) printk("NO RING on %d/%d!\n", wc->span.spanno, card + 1); zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); } } } else if (res && (fxo->battery == BATTERY_PRESENT)) { fxo->lastrdtx = res; fxo->ringdebounce = 10; } } else { res = wc->reg0shadow[card]; if ((res & 0x60) && (fxo->battery == BATTERY_PRESENT)) { fxo->ringdebounce += (ZT_CHUNKSIZE * 16); if (fxo->ringdebounce >= ZT_CHUNKSIZE * ringdebounce) { if (!fxo->wasringing) { fxo->wasringing = 1; zt_hooksig(&wc->chans[card], ZT_RXSIG_RING); if (debug) printk("RING on %d/%d!\n", wc->span.spanno, card + 1); } fxo->ringdebounce = ZT_CHUNKSIZE * ringdebounce; } } else { fxo->ringdebounce -= ZT_CHUNKSIZE * 4; if (fxo->ringdebounce <= 0) { if (fxo->wasringing) { fxo->wasringing = 0; zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); if (debug) printk("NO RING on %d/%d!\n", wc->span.spanno, card + 1); } fxo->ringdebounce = 0; } } } } b = wc->reg1shadow[card]; if (abs(b) < battthresh) { /* 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) */ if (fxo->battery == BATTERY_LOST) { if (fxo->battdebounce) { /* we were going to BATTERY_PRESENT, but battery was lost again, so clear the debounce timer */ fxo->battdebounce = 0; } } else { if (fxo->battdebounce) { /* going to BATTERY_LOST, see if we are there yet */ if (--fxo->battdebounce == 0) { fxo->battery = BATTERY_LOST; if (debug) printk("NO BATTERY on %d/%d!\n", wc->span.spanno, card + 1); #ifdef JAPAN if (!wc->ohdebounce && wc->offhook) { zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK); if (debug) printk("Signalled On Hook\n"); #ifdef ZERO_BATT_RING wc->onhook++; #endif } #else zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK); /* set the alarm timer, taking into account that part of its time period has already passed while debouncing occurred */ fxo->battalarm = (battalarm - battdebounce) / MS_PER_CHECK_HOOK; #endif } } else { /* start the debounce timer to verify that battery has been lost */ fxo->battdebounce = battdebounce / MS_PER_CHECK_HOOK; } } } else { /* possible existing states: battery lost or unknown, no debounce timer battery lost or unknown, debounce timer (going to battery present) battery present, no debounce timer battery present, debounce timer (going to battery lost) */ if (fxo->battery == BATTERY_PRESENT) { if (fxo->battdebounce) { /* we were going to BATTERY_LOST, but battery appeared again, so clear the debounce timer */ fxo->battdebounce = 0; } } else { if (fxo->battdebounce) { /* going to BATTERY_PRESENT, see if we are there yet */ if (--fxo->battdebounce == 0) { fxo->battery = BATTERY_PRESENT; if (debug) printk("BATTERY on %d/%d (%s)!\n", wc->span.spanno, card + 1, (b < 0) ? "-" : "+"); #ifdef ZERO_BATT_RING if (wc->onhook) { wc->onhook = 0; zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); if (debug) printk("Signalled Off Hook\n"); } #else zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); #endif /* set the alarm timer, taking into account that part of its time period has already passed while debouncing occurred */ fxo->battalarm = (battalarm - battdebounce) / MS_PER_CHECK_HOOK; } } else { /* start the debounce timer to verify that battery has appeared */ fxo->battdebounce = battdebounce / MS_PER_CHECK_HOOK; } } } if (fxo->lastpol >= 0) { if (b < 0) { fxo->lastpol = -1; fxo->polaritydebounce = POLARITY_DEBOUNCE / MS_PER_CHECK_HOOK; } } if (fxo->lastpol <= 0) { if (b > 0) { fxo->lastpol = 1; fxo->polaritydebounce = POLARITY_DEBOUNCE / MS_PER_CHECK_HOOK; } } if (fxo->battalarm) { if (--fxo->battalarm == 0) { /* the alarm timer has expired, so update the battery alarm state for this channel */ zt_alarm_channel(&wc->chans[card], fxo->battery ? ZT_ALARM_NONE : ZT_ALARM_RED); } } if (fxo->polaritydebounce) { if (--fxo->polaritydebounce == 0) { if (fxo->lastpol != fxo->polarity) { if (debug) printk("%lu Polarity reversed (%d -> %d)\n", jiffies, fxo->polarity, fxo->lastpol); if (fxo->polarity) zt_qevent_lock(&wc->chans[card], ZT_EVENT_POLARITY); fxo->polarity = fxo->lastpol; } } } #undef MS_PER_CHECK_HOOK } static inline void wctdm_proslic_check_hook(struct wctdm *wc, int card) { char res; int hook; /* For some reason we have to debounce the hook detector. */ res = wc->reg0shadow[card]; hook = (res & 1); if (hook != wc->mod[card].fxs.lastrxhook) { /* Reset the debounce (must be multiple of 4ms) */ wc->mod[card].fxs.debounce = 8 * (4 * 8); #if 0 printk("Resetting debounce card %d hook %d, %d\n", card, hook, wc->mod[card].fxs.debounce); #endif } else { if (wc->mod[card].fxs.debounce > 0) { wc->mod[card].fxs.debounce-= 16 * ZT_CHUNKSIZE; #if 0 printk("Sustaining hook %d, %d\n", hook, wc->mod[card].fxs.debounce); #endif if (!wc->mod[card].fxs.debounce) { #if 0 printk("Counted down debounce, newhook: %d...\n", hook); #endif wc->mod[card].fxs.debouncehook = hook; } if (!wc->mod[card].fxs.oldrxhook && wc->mod[card].fxs.debouncehook) { /* Off hook */ #if 1 if (debug) #endif printk("wctdm: Card %d Going off hook\n", card); zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK); if (robust) wctdm_init_proslic(wc, card, 1, 0, 1); wc->mod[card].fxs.oldrxhook = 1; } else if (wc->mod[card].fxs.oldrxhook && !wc->mod[card].fxs.debouncehook) { /* On hook */ #if 1 if (debug) #endif printk("wctdm: Card %d Going on hook\n", card); zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK); wc->mod[card].fxs.oldrxhook = 0; } } } wc->mod[card].fxs.lastrxhook = hook; } ZAP_IRQ_HANDLER(wctdm_interrupt) { struct wctdm *wc = dev_id; unsigned char ints; int x; int mode; ints = inb(wc->ioaddr + WC_INTSTAT); if (!ints) #ifdef LINUX26 return IRQ_NONE; #else return; #endif outb(ints, wc->ioaddr + WC_INTSTAT); if (ints & 0x10) { /* Stop DMA, wait for watchdog */ printk("TDM PCI Master abort\n"); wctdm_stop_dma(wc); #ifdef LINUX26 return IRQ_RETVAL(1); #else return; #endif } if (ints & 0x20) { printk("PCI Target abort\n"); #ifdef LINUX26 return IRQ_RETVAL(1); #else return; #endif } for (x=0;x<4;x++) { if (wc->cardflag & (1 << x) && (wc->modtype[x] == MOD_TYPE_FXS)) { if (wc->mod[x].fxs.lasttxhook == 0x4) { /* RINGing, prepare for OHT */ wc->mod[x].fxs.ohttimer = OHT_TIMER << 3; if (reversepolarity) wc->mod[x].fxs.idletxhookstate = 0x6; /* OHT mode when idle */ else wc->mod[x].fxs.idletxhookstate = 0x2; } else { if (wc->mod[x].fxs.ohttimer) { wc->mod[x].fxs.ohttimer-= ZT_CHUNKSIZE; if (!wc->mod[x].fxs.ohttimer) { if (reversepolarity) wc->mod[x].fxs.idletxhookstate = 0x5; /* Switch to active */ else wc->mod[x].fxs.idletxhookstate = 0x1; if ((wc->mod[x].fxs.lasttxhook == 0x2) || (wc->mod[x].fxs.lasttxhook == 0x6)) { /* Apply the change if appropriate */ if (reversepolarity) wc->mod[x].fxs.lasttxhook = 0x5; else wc->mod[x].fxs.lasttxhook = 0x1; wctdm_setreg(wc, x, 64, wc->mod[x].fxs.lasttxhook); } } } } } } if (ints & 0x0f) { wc->intcount++; x = wc->intcount & 0x3; mode = wc->intcount & 0xc; if (wc->cardflag & (1 << x)) { switch(mode) { case 0: /* Rest */ break; case 4: /* Read first shadow reg */ if (wc->modtype[x] == MOD_TYPE_FXS) wc->reg0shadow[x] = wctdm_getreg(wc, x, 68); else if (wc->modtype[x] == MOD_TYPE_FXO) wc->reg0shadow[x] = wctdm_getreg(wc, x, 5); break; case 8: /* Read second shadow reg */ if (wc->modtype[x] == MOD_TYPE_FXS) wc->reg1shadow[x] = wctdm_getreg(wc, x, 64); else if (wc->modtype[x] == MOD_TYPE_FXO) wc->reg1shadow[x] = wctdm_getreg(wc, x, 29); break; case 12: /* Perform processing */ if (wc->modtype[x] == MOD_TYPE_FXS) { wctdm_proslic_check_hook(wc, x); if (!(wc->intcount & 0xf0)) wctdm_proslic_recheck_sanity(wc, x); } else if (wc->modtype[x] == MOD_TYPE_FXO) { wctdm_voicedaa_check_hook(wc, x); } break; } } if (!(wc->intcount % 10000)) { /* Accept an alarm once per 10 seconds */ for (x=0;x<4;x++) if (wc->modtype[x] == MOD_TYPE_FXS) { if (wc->mod[x].fxs.palarms) wc->mod[x].fxs.palarms--; } } wctdm_receiveprep(wc, ints); wctdm_transmitprep(wc, ints); } #ifdef LINUX26 return IRQ_RETVAL(1); #endif } static int wctdm_voicedaa_insane(struct wctdm *wc, int card) { int blah; blah = wctdm_getreg(wc, card, 2); if (blah != 0x3) return -2; blah = wctdm_getreg(wc, card, 11); if (debug) printk("VoiceDAA System: %02x\n", blah & 0xf); return 0; } static int wctdm_proslic_insane(struct wctdm *wc, int card) { int blah,insane_report; insane_report=0; blah = wctdm_getreg(wc, card, 0); if (debug) printk("ProSLIC on module %d, product %d, version %d\n", card, (blah & 0x30) >> 4, (blah & 0xf)); #if 0 if ((blah & 0x30) >> 4) { printk("ProSLIC on module %d is not a 3210.\n", card); return -1; } #endif if (((blah & 0xf) == 0) || ((blah & 0xf) == 0xf)) { /* SLIC not loaded */ return -1; } if ((blah & 0xf) < 2) { printk("ProSLIC 3210 version %d is too old\n", blah & 0xf); return -1; } if (wctdm_getreg(wc, card, 1) & 0x80) /* ProSLIC 3215, not a 3210 */ wc->flags[card] |= FLAG_3215; blah = wctdm_getreg(wc, card, 8); if (blah != 0x2) { printk("ProSLIC on module %d insane (1) %d should be 2\n", card, blah); return -1; } else if ( insane_report) printk("ProSLIC on module %d Reg 8 Reads %d Expected is 0x2\n",card,blah); blah = wctdm_getreg(wc, card, 64); if (blah != 0x0) { printk("ProSLIC on module %d insane (2)\n", card); return -1; } else if ( insane_report) printk("ProSLIC on module %d Reg 64 Reads %d Expected is 0x0\n",card,blah); blah = wctdm_getreg(wc, card, 11); if (blah != 0x33) { printk("ProSLIC on module %d insane (3)\n", card); return -1; } else if ( insane_report) printk("ProSLIC on module %d Reg 11 Reads %d Expected is 0x33\n",card,blah); /* Just be sure it's setup right. */ wctdm_setreg(wc, card, 30, 0); if (debug) printk("ProSLIC on module %d seems sane.\n", card); return 0; } static int wctdm_proslic_powerleak_test(struct wctdm *wc, int card) { unsigned long origjiffies; unsigned char vbat; /* Turn off linefeed */ wctdm_setreg(wc, card, 64, 0); /* Power down */ wctdm_setreg(wc, card, 14, 0x10); /* Wait for one second */ origjiffies = jiffies; while((vbat = wctdm_getreg(wc, card, 82)) > 0x6) { if ((jiffies - origjiffies) >= (HZ/2)) break;; } if (vbat < 0x06) { printk("Excessive leakage detected on module %d: %d volts (%02x) after %d ms\n", card, 376 * vbat / 1000, vbat, (int)((jiffies - origjiffies) * 1000 / HZ)); return -1; } else if (debug) { printk("Post-leakage voltage: %d volts\n", 376 * vbat / 1000); } return 0; } static int wctdm_powerup_proslic(struct wctdm *wc, int card, int fast) { unsigned char vbat; unsigned long origjiffies; int lim; /* Set period of DC-DC converter to 1/64 khz */ wctdm_setreg(wc, card, 92, 0xff /* was 0xff */); /* Wait for VBat to powerup */ origjiffies = jiffies; /* Disable powerdown */ wctdm_setreg(wc, card, 14, 0); /* If fast, don't bother checking anymore */ if (fast) return 0; while((vbat = wctdm_getreg(wc, card, 82)) < 0xc0) { /* Wait no more than 500ms */ if ((jiffies - origjiffies) > HZ/2) { break; } } if (vbat < 0xc0) { if (wc->proslic_power == PROSLIC_POWER_UNKNOWN) printk("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 TDM400P??\n", card, (int)(((jiffies - origjiffies) * 1000 / HZ)), vbat * 375); wc->proslic_power = PROSLIC_POWER_WARNED; return -1; } else if (debug) { printk("ProSLIC on module %d powered up to -%d volts (%02x) in %d ms\n", card, vbat * 376 / 1000, vbat, (int)(((jiffies - origjiffies) * 1000 / HZ))); } wc->proslic_power = PROSLIC_POWER_ON; /* 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) printk("Loop current out of range! Setting to default 20mA!\n"); } else if (debug) printk("Loop current set to %dmA!\n",(lim*3)+20); wctdm_setreg(wc,card,LOOP_I_LIMIT,lim); /* Engage DC-DC converter */ wctdm_setreg(wc, card, 93, 0x19 /* was 0x19 */); #if 0 origjiffies = jiffies; while(0x80 & wctdm_getreg(wc, card, 93)) { if ((jiffies - origjiffies) > 2 * HZ) { printk("Timeout waiting for DC-DC calibration on module %d\n", card); return -1; } } #if 0 /* Wait a full two seconds */ while((jiffies - origjiffies) < 2 * HZ); /* Just check to be sure */ vbat = wctdm_getreg(wc, card, 82); printk("ProSLIC on module %d powered up to -%d volts (%02x) in %d ms\n", card, vbat * 376 / 1000, vbat, (int)(((jiffies - origjiffies) * 1000 / HZ))); #endif #endif return 0; } static int wctdm_proslic_manual_calibrate(struct wctdm *wc, int card){ unsigned long origjiffies; unsigned char i; wctdm_setreg(wc, card, 21, 0);//(0) Disable all interupts in DR21 wctdm_setreg(wc, card, 22, 0);//(0)Disable all interupts in DR21 wctdm_setreg(wc, card, 23, 0);//(0)Disable all interupts in DR21 wctdm_setreg(wc, card, 64, 0);//(0) wctdm_setreg(wc, card, 97, 0x18); //(0x18)Calibrations without the ADC and DAC offset and without common mode calibration. wctdm_setreg(wc, card, 96, 0x47); //(0x47) Calibrate common mode and differential DAC mode DAC + ILIM origjiffies=jiffies; while( wctdm_getreg(wc,card,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 *******************************************/ // Delay 10ms origjiffies=jiffies; while((jiffies-origjiffies)<1); wctdm_proslic_setreg_indirect(wc, card, 88,0); wctdm_proslic_setreg_indirect(wc,card,89,0); wctdm_proslic_setreg_indirect(wc,card,90,0); wctdm_proslic_setreg_indirect(wc,card,91,0); wctdm_proslic_setreg_indirect(wc,card,92,0); wctdm_proslic_setreg_indirect(wc,card,93,0); wctdm_setreg(wc, card, 98,0x10); // This is necessary if the calibration occurs other than at reset time wctdm_setreg(wc, card, 99,0x10); for ( i=0x1f; i>0; i--) { wctdm_setreg(wc, card, 98,i); origjiffies=jiffies; while((jiffies-origjiffies)<4); if((wctdm_getreg(wc,card,88)) == 0) break; } // for for ( i=0x1f; i>0; i--) { wctdm_setreg(wc, card, 99,i); origjiffies=jiffies; while((jiffies-origjiffies)<4); if((wctdm_getreg(wc,card,89)) == 0) break; }//for /*******************************The preceding is the manual gain mismatch calibration****************************/ /**********************************The following is the longitudinal Balance Cal***********************************/ wctdm_setreg(wc,card,64,1); while((jiffies-origjiffies)<10); // Sleep 100? wctdm_setreg(wc, card, 64, 0); wctdm_setreg(wc, card, 23, 0x4); // enable interrupt for the balance Cal wctdm_setreg(wc, card, 97, 0x1); // this is a singular calibration bit for longitudinal calibration wctdm_setreg(wc, card, 96,0x40); wctdm_getreg(wc,card,96); /* Read Reg 96 just cause */ wctdm_setreg(wc, card, 21, 0xFF); wctdm_setreg(wc, card, 22, 0xFF); wctdm_setreg(wc, card, 23, 0xFF); /**The preceding is the longitudinal Balance Cal***/ return(0); } #if 1 static int wctdm_proslic_calibrate(struct wctdm *wc, int card) { unsigned long origjiffies; int x; /* Perform all calibrations */ wctdm_setreg(wc, card, 97, 0x1f); /* Begin, no speedup */ wctdm_setreg(wc, card, 96, 0x5f); /* Wait for it to finish */ origjiffies = jiffies; while(wctdm_getreg(wc, card, 96)) { if ((jiffies - origjiffies) > 2 * HZ) { printk("Timeout waiting for calibration of module %d\n", card); return -1; } } if (debug) { /* Print calibration parameters */ printk("Calibration Vector Regs 98 - 107: \n"); for (x=98;x<108;x++) { printk("%d: %02x\n", x, wctdm_getreg(wc, card, x)); } } return 0; } #endif static void wait_just_a_bit(int foo) { long newjiffies; newjiffies = jiffies + foo; while(jiffies < newjiffies); } /********************************************************************* * 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, int card, __s32 gain, __u32 tx) { if (!(wc->modtype[card] == MOD_TYPE_FXO)) { printk("Cannot adjust gain. Unsupported module type!\n"); return -1; } if (tx) { if (debug) printk("setting FXO tx gain for card=%d to %d\n", card, gain); if (gain >= -150 && gain <= 0) { wctdm_setreg(wc, card, 38, 16 + (gain/-10)); wctdm_setreg(wc, card, 40, 16 + (-gain%10)); } else if (gain <= 120 && gain > 0) { wctdm_setreg(wc, card, 38, gain/10); wctdm_setreg(wc, card, 40, (gain%10)); } else { printk("FXO tx gain is out of range (%d)\n", gain); return -1; } } else { /* rx */ if (debug) printk("setting FXO rx gain for card=%d to %d\n", card, gain); if (gain >= -150 && gain <= 0) { wctdm_setreg(wc, card, 39, 16+ (gain/-10)); wctdm_setreg(wc, card, 41, 16 + (-gain%10)); } else if (gain <= 120 && gain > 0) { wctdm_setreg(wc, card, 39, gain/10); wctdm_setreg(wc, card, 41, (gain%10)); } else { printk("FXO rx gain is out of range (%d)\n", gain); return -1; } } return 0; } static int wctdm_init_voicedaa(struct wctdm *wc, int card, int fast, int manual, int sane) { unsigned char reg16=0, reg26=0, reg30=0, reg31=0; long newjiffies; wc->modtype[card] = MOD_TYPE_FXO; /* Sanity check the ProSLIC */ reset_spi(wc, card); if (!sane && wctdm_voicedaa_insane(wc, card)) return -2; /* Software reset */ wctdm_setreg(wc, card, 1, 0x80); /* Wait just a bit */ wait_just_a_bit(HZ/10); /* Enable PCM, ulaw */ if (alawoverride) wctdm_setreg(wc, card, 33, 0x20); else wctdm_setreg(wc, card, 33, 0x28); /* 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, card, 16, reg16); if(fwringdetect) { /* Enable ring detector full-wave rectifier mode */ wctdm_setreg(wc, card, 18, 2); wctdm_setreg(wc, card, 24, 0); } else { /* Set to the device defaults */ wctdm_setreg(wc, card, 18, 0); wctdm_setreg(wc, card, 24, 0x19); } /* 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, card, 26, reg26); /* Set AC Impedence */ reg30 = (fxo_modes[_opermode].acim); wctdm_setreg(wc, card, 30, reg30); /* Misc. DAA parameters */ if (fastpickup) reg31 = 0xb3; else reg31 = 0xa3; reg31 |= (fxo_modes[_opermode].ohs2 << 3); wctdm_setreg(wc, card, 31, reg31); /* Set Transmit/Receive timeslot */ wctdm_setreg(wc, card, 34, (3-card) * 8); wctdm_setreg(wc, card, 35, 0x00); wctdm_setreg(wc, card, 36, (3-card) * 8); wctdm_setreg(wc, card, 37, 0x00); /* Enable ISO-Cap */ wctdm_setreg(wc, card, 6, 0x00); if (fastpickup) wctdm_setreg(wc, card, 17, wctdm_getreg(wc, card, 17) | 0x20); /* Wait 1000ms for ISO-cap to come up */ newjiffies = jiffies; newjiffies += 2 * HZ; while((jiffies < newjiffies) && !(wctdm_getreg(wc, card, 11) & 0xf0)) wait_just_a_bit(HZ/10); if (!(wctdm_getreg(wc, card, 11) & 0xf0)) { printk("VoiceDAA did not bring up ISO link properly!\n"); return -1; } if (debug) printk("ISO-Cap is now up, line side: %02x rev %02x\n", wctdm_getreg(wc, card, 11) >> 4, (wctdm_getreg(wc, card, 13) >> 2) & 0xf); /* Enable on-hook line monitor */ wctdm_setreg(wc, card, 5, 0x08); /* Take values for fxotxgain and fxorxgain and apply them to module */ wctdm_set_hwgain(wc, card, fxotxgain, 1); wctdm_set_hwgain(wc, card, fxorxgain, 0); /* NZ -- crank the tx gain up by 7 dB */ if (!strcmp(fxo_modes[_opermode].name, "NEWZEALAND")) { printk("Adjusting gain\n"); wctdm_set_hwgain(wc, card, 7, 1); } if(debug) printk("DEBUG fxotxgain:%i.%i fxorxgain:%i.%i\n", (wctdm_getreg(wc, card, 38)/16)?-(wctdm_getreg(wc, card, 38) - 16) : wctdm_getreg(wc, card, 38), (wctdm_getreg(wc, card, 40)/16)? -(wctdm_getreg(wc, card, 40) - 16):wctdm_getreg(wc, card, 40), (wctdm_getreg(wc, card, 39)/16)? -(wctdm_getreg(wc, card, 39) - 16) : wctdm_getreg(wc, card, 39),(wctdm_getreg(wc, card, 41)/16)?-(wctdm_getreg(wc, card, 41) - 16):wctdm_getreg(wc, card, 41)); return 0; } static int wctdm_init_proslic(struct wctdm *wc, int card, int fast, int manual, int sane) { unsigned short tmp[5]; unsigned char r19,r9; int x; int fxsmode=0; /* Sanity check the ProSLIC */ if (!sane && wctdm_proslic_insane(wc, card)) return -2; /* By default, don't send on hook */ if (reversepolarity) wc->mod[card].fxs.idletxhookstate = 5; else wc->mod[card].fxs.idletxhookstate = 1; if (sane) { /* Make sure we turn off the DC->DC converter to prevent anything from blowing up */ wctdm_setreg(wc, card, 14, 0x10); } if (wctdm_proslic_init_indirect_regs(wc, card)) { printk(KERN_INFO "Indirect Registers failed to initialize on module %d.\n", card); return -1; } /* Clear scratch pad area */ wctdm_proslic_setreg_indirect(wc, card, 97,0); /* Clear digital loopback */ wctdm_setreg(wc, card, 8, 0); /* Revision C optimization */ wctdm_setreg(wc, card, 108, 0xeb); /* Disable automatic VBat switching for safety to prevent Q7 from accidently turning on and burning out. */ wctdm_setreg(wc, card, 67, 0x07); /* Note, if pulse dialing has problems at high REN loads change this to 0x17 */ /* Turn off Q7 */ wctdm_setreg(wc, card, 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, card, x + 35); wctdm_proslic_setreg_indirect(wc, card, x + 35, 0x8000); } /* Power up the DC-DC converter */ if (wctdm_powerup_proslic(wc, card, fast)) { printk("Unable to do INITIAL ProSLIC powerup on module %d\n", card); return -1; } if (!fast) { /* Check for power leaks */ if (wctdm_proslic_powerleak_test(wc, card)) { printk("ProSLIC module %d failed leakage test. Check for short circuit\n", card); } /* Power up again */ if (wctdm_powerup_proslic(wc, card, fast)) { printk("Unable to do FINAL ProSLIC powerup on module %d\n", card); return -1; } #ifndef NO_CALIBRATION /* Perform calibration */ if(manual) { if (wctdm_proslic_manual_calibrate(wc, card)) { //printk("Proslic failed on Manual Calibration\n"); if (wctdm_proslic_manual_calibrate(wc, card)) { printk("Proslic Failed on Second Attempt to Calibrate Manually. (Try -DNO_CALIBRATION in Makefile)\n"); return -1; } printk("Proslic Passed Manual Calibration on Second Attempt\n"); } } else { if(wctdm_proslic_calibrate(wc, card)) { //printk("ProSlic died on Auto Calibration.\n"); if (wctdm_proslic_calibrate(wc, card)) { printk("Proslic Failed on Second Attempt to Auto Calibrate\n"); return -1; } printk("Proslic Passed Auto Calibration on Second Attempt\n"); } } /* Perform DC-DC calibration */ wctdm_setreg(wc, card, 93, 0x99); r19 = wctdm_getreg(wc, card, 107); if ((r19 < 0x2) || (r19 > 0xd)) { printk("DC-DC cal has a surprising direct 107 of 0x%02x!\n", r19); wctdm_setreg(wc, card, 107, 0x8); } /* Save calibration vectors */ for (x=0;xmod[card].fxs.calregs.vals[x] = wctdm_getreg(wc, card, 96 + x); #endif } else { /* Restore calibration registers */ for (x=0;xmod[card].fxs.calregs.vals[x]); } /* Calibration complete, restore original values */ for (x=0;x<5;x++) { wctdm_proslic_setreg_indirect(wc, card, x + 35, tmp[x]); } if (wctdm_proslic_verify_indirect_regs(wc, card)) { printk(KERN_INFO "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 printk(KERN_INFO "ProSlic IndirectReg Died.\n"); return -1; } #endif if (alawoverride) wctdm_setreg(wc, card, 1, 0x20); else wctdm_setreg(wc, card, 1, 0x28); // U-Law 8-bit interface wctdm_setreg(wc, card, 2, (3-card) * 8); // Tx Start count low byte 0 wctdm_setreg(wc, card, 3, 0); // Tx Start count high byte 0 wctdm_setreg(wc, card, 4, (3-card) * 8); // Rx Start count low byte 0 wctdm_setreg(wc, card, 5, 0); // Rx Start count high byte 0 wctdm_setreg(wc, card, 18, 0xff); // clear all interrupt wctdm_setreg(wc, card, 19, 0xff); wctdm_setreg(wc, card, 20, 0xff); wctdm_setreg(wc, card, 73, 0x04); if (fxshonormode) { fxsmode = acim2tiss[fxo_modes[_opermode].acim]; wctdm_setreg(wc, card, 10, 0x08 | fxsmode); if (fxo_modes[_opermode].ring_osc) wctdm_proslic_setreg_indirect(wc, card, 20, fxo_modes[_opermode].ring_osc); if (fxo_modes[_opermode].ring_x) wctdm_proslic_setreg_indirect(wc, card, 21, fxo_modes[_opermode].ring_x); } if (lowpower) wctdm_setreg(wc, card, 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, card, 20, 0x7e6d); wctdm_proslic_setreg_indirect(wc, card, 21, 0x01b9); /* Beef up Ringing voltage to 89V */ if (boostringer) { wctdm_setreg(wc, card, 74, 0x3f); if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x247)) return -1; printk("Boosting fast ringer on slot %d (89V peak)\n", card + 1); } else if (lowpower) { if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x14b)) return -1; printk("Reducing fast ring power on slot %d (50V peak)\n", card + 1); } else printk("Speeding up ringer on slot %d (25Hz)\n", card + 1); } else { /* Beef up Ringing voltage to 89V */ if (boostringer) { wctdm_setreg(wc, card, 74, 0x3f); if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x1d1)) return -1; printk("Boosting ringer on slot %d (89V peak)\n", card + 1); } else if (lowpower) { if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x108)) return -1; printk("Reducing ring power on slot %d (50V peak)\n", card + 1); } } if(fxstxgain || fxsrxgain) { r9 = wctdm_getreg(wc, card, 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,card,9,r9); } if(debug) printk("DEBUG: fxstxgain:%s fxsrxgain:%s\n",((wctdm_getreg(wc, card, 9)/8) == 1)?"3.5":(((wctdm_getreg(wc,card,9)/4) == 1)?"-3.5":"0.0"),((wctdm_getreg(wc, card, 9)/2) == 1)?"3.5":((wctdm_getreg(wc,card,9)%2)?"-3.5":"0.0")); wctdm_setreg(wc, card, 64, 0x01); return 0; } static int wctdm_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data) { struct wctdm_stats stats; struct wctdm_regs regs; struct wctdm_regop regop; struct wctdm_echo_coefs echoregs; struct zt_hwgain hwgain; struct wctdm *wc = chan->pvt; int x; switch (cmd) { case ZT_ONHOOKTRANSFER: if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) return -EINVAL; if (get_user(x, (int *)data)) return -EFAULT; wc->mod[chan->chanpos - 1].fxs.ohttimer = x << 3; if (reversepolarity) wc->mod[chan->chanpos - 1].fxs.idletxhookstate = 0x6; /* OHT mode when idle */ else wc->mod[chan->chanpos - 1].fxs.idletxhookstate = 0x2; if (wc->mod[chan->chanpos - 1].fxs.lasttxhook == 0x1 || wc->mod[chan->chanpos - 1].fxs.lasttxhook == 0x5) { /* Apply the change if appropriate */ if (reversepolarity) wc->mod[chan->chanpos - 1].fxs.lasttxhook = 0x6; else wc->mod[chan->chanpos - 1].fxs.lasttxhook = 0x2; wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mod[chan->chanpos - 1].fxs.lasttxhook); } break; case ZT_SETPOLARITY: if (get_user(x, (int *)data)) return -EFAULT; if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) return -EINVAL; /* Can't change polarity while ringing or when open */ if ((wc->mod[chan->chanpos -1 ].fxs.lasttxhook == 0x04) || (wc->mod[chan->chanpos -1 ].fxs.lasttxhook == 0x00)) return -EINVAL; if ((x && !reversepolarity) || (!x && reversepolarity)) wc->mod[chan->chanpos - 1].fxs.lasttxhook |= 0x04; else wc->mod[chan->chanpos - 1].fxs.lasttxhook &= ~0x04; wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mod[chan->chanpos - 1].fxs.lasttxhook); break; case WCTDM_GET_STATS: if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) { stats.tipvolt = wctdm_getreg(wc, chan->chanpos - 1, 80) * -376; stats.ringvolt = wctdm_getreg(wc, chan->chanpos - 1, 81) * -376; stats.batvolt = wctdm_getreg(wc, chan->chanpos - 1, 82) * -376; } else if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) { stats.tipvolt = (signed char)wctdm_getreg(wc, chan->chanpos - 1, 29) * 1000; stats.ringvolt = (signed char)wctdm_getreg(wc, chan->chanpos - 1, 29) * 1000; stats.batvolt = (signed char)wctdm_getreg(wc, chan->chanpos - 1, 29) * 1000; } else return -EINVAL; if (copy_to_user((struct wctdm_stats *)data, &stats, sizeof(stats))) return -EFAULT; break; case WCTDM_GET_REGS: if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) { for (x=0;xchanpos -1, x); for (x=0;xchanpos - 1, x); } else { memset(®s, 0, sizeof(regs)); for (x=0;xchanpos - 1, x); } if (copy_to_user((struct wctdm_regs *)data, ®s, sizeof(regs))) return -EFAULT; break; case WCTDM_SET_REG: if (copy_from_user(®op, (struct wctdm_regop *)data, sizeof(regop))) return -EFAULT; if (regop.indirect) { if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) return -EINVAL; printk("Setting indirect %d to 0x%04x on %d\n", regop.reg, regop.val, chan->chanpos); wctdm_proslic_setreg_indirect(wc, chan->chanpos - 1, regop.reg, regop.val); } else { regop.val &= 0xff; printk("Setting direct %d to %04x on %d\n", regop.reg, regop.val, chan->chanpos); wctdm_setreg(wc, chan->chanpos - 1, regop.reg, regop.val); } break; case WCTDM_SET_ECHOTUNE: printk("-- Setting echo registers: \n"); if (copy_from_user(&echoregs, (struct wctdm_echo_coefs*)data, sizeof(echoregs))) return -EFAULT; if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) { /* Set the ACIM register */ wctdm_setreg(wc, chan->chanpos - 1, 30, echoregs.acim); /* Set the digital echo canceller registers */ wctdm_setreg(wc, chan->chanpos - 1, 45, echoregs.coef1); wctdm_setreg(wc, chan->chanpos - 1, 46, echoregs.coef2); wctdm_setreg(wc, chan->chanpos - 1, 47, echoregs.coef3); wctdm_setreg(wc, chan->chanpos - 1, 48, echoregs.coef4); wctdm_setreg(wc, chan->chanpos - 1, 49, echoregs.coef5); wctdm_setreg(wc, chan->chanpos - 1, 50, echoregs.coef6); wctdm_setreg(wc, chan->chanpos - 1, 51, echoregs.coef7); wctdm_setreg(wc, chan->chanpos - 1, 52, echoregs.coef8); printk("-- Set echo registers successfully\n"); break; } else { return -EINVAL; } break; case ZT_SET_HWGAIN: if (copy_from_user(&hwgain, (struct zt_hwgain*) data, sizeof(hwgain))) return -EFAULT; wctdm_set_hwgain(wc, chan->chanpos-1, hwgain.newgain, hwgain.tx); if (debug) printk("Setting hwgain on channel %d to %d for %s direction\n", chan->chanpos-1, hwgain.newgain, hwgain.tx ? "tx" : "rx"); break; default: return -ENOTTY; } return 0; } static int wctdm_open(struct zt_chan *chan) { struct wctdm *wc = chan->pvt; if (!(wc->cardflag & (1 << (chan->chanpos - 1)))) return -ENODEV; if (wc->dead) return -ENODEV; wc->usecount++; #ifndef LINUX26 MOD_INC_USE_COUNT; #else try_module_get(THIS_MODULE); #endif return 0; } static int wctdm_watchdog(struct zt_span *span, int event) { printk("TDM: Restarting DMA\n"); wctdm_restart_dma(span->pvt); return 0; } static int wctdm_close(struct zt_chan *chan) { struct wctdm *wc = chan->pvt; wc->usecount--; #ifndef LINUX26 MOD_DEC_USE_COUNT; #else module_put(THIS_MODULE); #endif if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) { if (reversepolarity) wc->mod[chan->chanpos - 1].fxs.idletxhookstate = 5; else wc->mod[chan->chanpos - 1].fxs.idletxhookstate = 1; } /* If we're dead, release us now */ if (!wc->usecount && wc->dead) wctdm_release(wc); return 0; } static int wctdm_hooksig(struct zt_chan *chan, zt_txsig_t txsig) { struct wctdm *wc = chan->pvt; int reg=0; if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) { /* XXX Enable hooksig for FXO XXX */ switch(txsig) { case ZT_TXSIG_START: case ZT_TXSIG_OFFHOOK: wc->mod[chan->chanpos - 1].fxo.offhook = 1; wctdm_setreg(wc, chan->chanpos - 1, 5, 0x9); break; case ZT_TXSIG_ONHOOK: wc->mod[chan->chanpos - 1].fxo.offhook = 0; wctdm_setreg(wc, chan->chanpos - 1, 5, 0x8); break; default: printk("wcfxo: Can't set tx state to %d\n", txsig); } } else { switch(txsig) { case ZT_TXSIG_ONHOOK: switch(chan->sig) { case ZT_SIG_EM: case ZT_SIG_FXOKS: case ZT_SIG_FXOLS: wc->mod[chan->chanpos-1].fxs.lasttxhook = wc->mod[chan->chanpos-1].fxs.idletxhookstate; break; case ZT_SIG_FXOGS: wc->mod[chan->chanpos-1].fxs.lasttxhook = 3; break; } break; case ZT_TXSIG_OFFHOOK: switch(chan->sig) { case ZT_SIG_EM: wc->mod[chan->chanpos-1].fxs.lasttxhook = 5; break; default: wc->mod[chan->chanpos-1].fxs.lasttxhook = wc->mod[chan->chanpos-1].fxs.idletxhookstate; break; } break; case ZT_TXSIG_START: wc->mod[chan->chanpos-1].fxs.lasttxhook = 4; break; case ZT_TXSIG_KEWL: wc->mod[chan->chanpos-1].fxs.lasttxhook = 0; break; default: printk("wctdm: Can't set tx state to %d\n", txsig); } if (debug) printk("Setting FXS hook state to %d (%02x)\n", txsig, reg); #if 1 wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mod[chan->chanpos-1].fxs.lasttxhook); #endif } return 0; } static int wctdm_initialize(struct wctdm *wc) { int x; /* Zapata stuff */ sprintf(wc->span.name, "WCTDM/%d", wc->pos); snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Board %d", wc->variety, wc->pos + 1); snprintf(wc->span.location, sizeof(wc->span.location) - 1, "PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1); wc->span.manufacturer = "Digium"; zap_copy_string(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype)); if (alawoverride) { printk("ALAW override parameter detected. Device will be operating in ALAW\n"); wc->span.deflaw = ZT_LAW_ALAW; } else wc->span.deflaw = ZT_LAW_MULAW; for (x = 0; x < NUM_CARDS; x++) { sprintf(wc->chans[x].name, "WCTDM/%d/%d", wc->pos, x); wc->chans[x].sigcap = ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_SF | ZT_SIG_EM | ZT_SIG_CLEAR; wc->chans[x].sigcap |= ZT_SIG_FXSKS | ZT_SIG_FXSLS | ZT_SIG_SF | ZT_SIG_CLEAR; wc->chans[x].chanpos = x+1; wc->chans[x].pvt = wc; } wc->span.chans = wc->chans; wc->span.channels = NUM_CARDS; wc->span.hooksig = wctdm_hooksig; wc->span.irq = wc->dev->irq; wc->span.open = wctdm_open; wc->span.close = wctdm_close; wc->span.flags = ZT_FLAG_RBS; wc->span.ioctl = wctdm_ioctl; wc->span.watchdog = wctdm_watchdog; init_waitqueue_head(&wc->span.maintq); wc->span.pvt = wc; if (zt_register(&wc->span, 0)) { printk("Unable to register span with zaptel\n"); return -1; } return 0; } static void wctdm_post_initialize(struct wctdm *wc) { int x; /* Finalize signalling */ for (x = 0; x < NUM_CARDS; x++) { if (wc->cardflag & (1 << x)) { if (wc->modtype[x] == MOD_TYPE_FXO) wc->chans[x].sigcap = ZT_SIG_FXSKS | ZT_SIG_FXSLS | ZT_SIG_SF | ZT_SIG_CLEAR; else wc->chans[x].sigcap = ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_SF | ZT_SIG_EM | ZT_SIG_CLEAR; } else if (!(wc->chans[x].sigcap & ZT_SIG_BROKEN)) { wc->chans[x].sigcap = 0; } } } static int wctdm_hardware_init(struct wctdm *wc) { /* Hardware stuff */ unsigned char ver; unsigned char x,y; int failed; /* Signal Reset */ outb(0x01, wc->ioaddr + WC_CNTL); /* Check Freshmaker chip */ x=inb(wc->ioaddr + WC_CNTL); ver = __wctdm_getcreg(wc, WC_VER); failed = 0; if (ver != 0x59) { printk("Freshmaker version: %02x\n", ver); for (x=0;x<255;x++) { /* Test registers */ if (ver >= 0x70) { __wctdm_setcreg(wc, WC_CS, x); y = __wctdm_getcreg(wc, WC_CS); } else { __wctdm_setcreg(wc, WC_TEST, x); y = __wctdm_getcreg(wc, WC_TEST); } if (x != y) { printk("%02x != %02x\n", x, y); failed++; } } if (!failed) { printk("Freshmaker passed register test\n"); } else { printk("Freshmaker failed register test\n"); return -1; } /* Go to half-duty FSYNC */ __wctdm_setcreg(wc, WC_SYNC, 0x01); y = __wctdm_getcreg(wc, WC_SYNC); } else { printk("No freshmaker chip\n"); } /* Reset PCI Interface chip and registers (and serial) */ outb(0x06, wc->ioaddr + WC_CNTL); /* Setup our proper outputs for when we switch for our "serial" port */ wc->ios = BIT_CS | BIT_SCLK | BIT_SDI; outb(wc->ios, wc->ioaddr + WC_AUXD); /* Set all to outputs except AUX 5, which is an input */ outb(0xdf, wc->ioaddr + WC_AUXC); /* Select alternate function for AUX0 */ outb(0x4, wc->ioaddr + WC_AUXFUNC); /* Wait 1/4 of a sec */ wait_just_a_bit(HZ/4); /* Back to normal, with automatic DMA wrap around */ outb(0x30 | 0x01, wc->ioaddr + WC_CNTL); /* Make sure serial port and DMA are out of reset */ outb(inb(wc->ioaddr + WC_CNTL) & 0xf9, wc->ioaddr + WC_CNTL); /* Configure serial port for MSB->LSB operation */ outb(0xc1, wc->ioaddr + WC_SERCTL); /* Delay FSC by 0 so it's properly aligned */ outb(0x0, wc->ioaddr + WC_FSCDELAY); /* Setup DMA Addresses */ outl(wc->writedma, wc->ioaddr + WC_DMAWS); /* Write start */ outl(wc->writedma + ZT_CHUNKSIZE * 4 - 4, wc->ioaddr + WC_DMAWI); /* Middle (interrupt) */ outl(wc->writedma + ZT_CHUNKSIZE * 8 - 4, wc->ioaddr + WC_DMAWE); /* End */ outl(wc->readdma, wc->ioaddr + WC_DMARS); /* Read start */ outl(wc->readdma + ZT_CHUNKSIZE * 4 - 4, wc->ioaddr + WC_DMARI); /* Middle (interrupt) */ outl(wc->readdma + ZT_CHUNKSIZE * 8 - 4, wc->ioaddr + WC_DMARE); /* End */ /* Clear interrupts */ outb(0xff, wc->ioaddr + WC_INTSTAT); /* Wait 1/4 of a second more */ wait_just_a_bit(HZ/4); for (x = 0; x < NUM_CARDS; x++) { int sane=0,ret=0,readi=0; #if 1 /* Init with Auto Calibration */ if (!(ret=wctdm_init_proslic(wc, x, 0, 0, sane))) { wc->cardflag |= (1 << x); if (debug) { readi = wctdm_getreg(wc,x,LOOP_I_LIMIT); printk("Proslic module %d loop current is %dmA\n",x, ((readi*3)+20)); } printk("Module %d: Installed -- AUTO FXS/DPO\n",x); } else { if(ret!=-2) { sane=1; /* Init with Manual Calibration */ if (!wctdm_init_proslic(wc, x, 0, 1, sane)) { wc->cardflag |= (1 << x); if (debug) { readi = wctdm_getreg(wc,x,LOOP_I_LIMIT); printk("Proslic module %d loop current is %dmA\n",x, ((readi*3)+20)); } printk("Module %d: Installed -- MANUAL FXS\n",x); } else { printk("Module %d: FAILED FXS (%s)\n", x, fxshonormode ? fxo_modes[_opermode].name : "FCC"); wc->chans[x].sigcap = __ZT_SIG_FXO | ZT_SIG_BROKEN; } } else if (!(ret = wctdm_init_voicedaa(wc, x, 0, 0, sane))) { wc->cardflag |= (1 << x); printk("Module %d: Installed -- AUTO FXO (%s mode)\n",x, fxo_modes[_opermode].name); } else printk("Module %d: Not installed\n", x); } #endif } /* Return error if nothing initialized okay. */ if (!wc->cardflag && !timingonly) return -1; __wctdm_setcreg(wc, WC_SYNC, (wc->cardflag << 1) | 0x1); return 0; } static void wctdm_enable_interrupts(struct wctdm *wc) { /* Enable interrupts (we care about all of them) */ outb(0x3f, wc->ioaddr + WC_MASK0); /* No external interrupts */ outb(0x00, wc->ioaddr + WC_MASK1); } static void wctdm_restart_dma(struct wctdm *wc) { /* Reset Master and TDM */ outb(0x01, wc->ioaddr + WC_CNTL); outb(0x01, wc->ioaddr + WC_OPER); } static void wctdm_start_dma(struct wctdm *wc) { /* Reset Master and TDM */ outb(0x0f, wc->ioaddr + WC_CNTL); set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1); outb(0x01, wc->ioaddr + WC_CNTL); outb(0x01, wc->ioaddr + WC_OPER); } static void wctdm_stop_dma(struct wctdm *wc) { outb(0x00, wc->ioaddr + WC_OPER); } static void wctdm_reset_tdm(struct wctdm *wc) { /* Reset TDM */ outb(0x0f, wc->ioaddr + WC_CNTL); } static void wctdm_disable_interrupts(struct wctdm *wc) { outb(0x00, wc->ioaddr + WC_MASK0); outb(0x00, wc->ioaddr + WC_MASK1); } static int __devinit wctdm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { int res; struct wctdm *wc; struct wctdm_desc *d = (struct wctdm_desc *)ent->driver_data; int x; int y; for (x=0;x= WC_MAX_IFACES) { printk("Too many interfaces\n"); return -EIO; } if (pci_enable_device(pdev)) { res = -EIO; } else { wc = kmalloc(sizeof(struct wctdm), GFP_KERNEL); if (wc) { int cardcount = 0; ifaces[x] = wc; memset(wc, 0, sizeof(struct wctdm)); spin_lock_init(&wc->lock); wc->curcard = -1; wc->ioaddr = pci_resource_start(pdev, 0); wc->dev = pdev; wc->pos = x; wc->variety = d->name; for (y=0;yflags[y] = d->flags; /* Keep track of whether we need to free the region */ if (request_region(wc->ioaddr, 0xff, "wctdm")) wc->freeregion = 1; /* Allocate enough memory for two zt chunks, receive and transmit. Each sample uses 32 bits. Allocate an extra set just for control too */ wc->writechunk = pci_alloc_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, &wc->writedma); if (!wc->writechunk) { printk("wctdm: Unable to allocate DMA-able memory\n"); if (wc->freeregion) release_region(wc->ioaddr, 0xff); return -ENOMEM; } wc->readchunk = wc->writechunk + ZT_MAX_CHUNKSIZE * 2; /* in doublewords */ wc->readdma = wc->writedma + ZT_MAX_CHUNKSIZE * 8; /* in bytes */ if (wctdm_initialize(wc)) { printk("wctdm: Unable to intialize FXS\n"); /* Set Reset Low */ x=inb(wc->ioaddr + WC_CNTL); outb((~0x1)&x, wc->ioaddr + WC_CNTL); /* Free Resources */ free_irq(pdev->irq, wc); if (wc->freeregion) release_region(wc->ioaddr, 0xff); pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)wc->writechunk, wc->writedma); kfree(wc); return -EIO; } /* Enable bus mastering */ pci_set_master(pdev); /* Keep track of which device we are */ pci_set_drvdata(pdev, wc); if (request_irq(pdev->irq, wctdm_interrupt, ZAP_IRQ_SHARED, "wctdm", wc)) { printk("wctdm: Unable to request IRQ %d\n", pdev->irq); if (wc->freeregion) release_region(wc->ioaddr, 0xff); pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)wc->writechunk, wc->writedma); pci_set_drvdata(pdev, NULL); kfree(wc); return -EIO; } if (wctdm_hardware_init(wc)) { unsigned char x; /* Set Reset Low */ x=inb(wc->ioaddr + WC_CNTL); outb((~0x1)&x, wc->ioaddr + WC_CNTL); /* Free Resources */ free_irq(pdev->irq, wc); if (wc->freeregion) release_region(wc->ioaddr, 0xff); pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)wc->writechunk, wc->writedma); pci_set_drvdata(pdev, NULL); zt_unregister(&wc->span); kfree(wc); return -EIO; } wctdm_post_initialize(wc); /* Enable interrupts */ wctdm_enable_interrupts(wc); /* Initialize Write/Buffers to all blank data */ memset((void *)wc->writechunk,0,ZT_MAX_CHUNKSIZE * 2 * 2 * 4); /* Start DMA */ wctdm_start_dma(wc); for (x = 0; x < NUM_CARDS; x++) { if (wc->cardflag & (1 << x)) cardcount++; } printk("Found a Wildcard TDM: %s (%d modules)\n", wc->variety, cardcount); res = 0; } else res = -ENOMEM; } return res; } static void wctdm_release(struct wctdm *wc) { zt_unregister(&wc->span); if (wc->freeregion) release_region(wc->ioaddr, 0xff); kfree(wc); printk("Freed a Wildcard\n"); } static void __devexit wctdm_remove_one(struct pci_dev *pdev) { struct wctdm *wc = pci_get_drvdata(pdev); if (wc) { /* Stop any DMA */ wctdm_stop_dma(wc); wctdm_reset_tdm(wc); /* In case hardware is still there */ wctdm_disable_interrupts(wc); /* Immediately free resources */ pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)wc->writechunk, wc->writedma); free_irq(pdev->irq, wc); /* Reset PCI chip and registers */ outb(0x0e, wc->ioaddr + WC_CNTL); /* Release span, possibly delayed */ if (!wc->usecount) wctdm_release(wc); else wc->dead = 1; } } static struct pci_device_id wctdm_pci_tbl[] = { { 0xe159, 0x0001, 0xa159, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm }, { 0xe159, 0x0001, 0xe159, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm }, { 0xe159, 0x0001, 0xb100, PCI_ANY_ID, 0, 0, (unsigned long) &wctdme }, { 0xe159, 0x0001, 0xb1d9, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmi }, { 0xe159, 0x0001, 0xb118, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmi }, { 0xe159, 0x0001, 0xb119, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmi }, { 0xe159, 0x0001, 0xa9fd, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmh }, { 0xe159, 0x0001, 0xa8fd, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmh }, { 0xe159, 0x0001, 0xa800, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmh }, { 0xe159, 0x0001, 0xa801, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmh }, { 0xe159, 0x0001, 0xa908, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmh }, { 0xe159, 0x0001, 0xa901, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmh }, #ifdef TDM_REVH_MATCHALL { 0xe159, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctdmh }, #endif { 0 } }; MODULE_DEVICE_TABLE(pci, wctdm_pci_tbl); static struct pci_driver wctdm_driver = { name: "wctdm", probe: wctdm_init_one, #ifdef LINUX26 remove: __devexit_p(wctdm_remove_one), #else remove: wctdm_remove_one, #endif suspend: NULL, resume: NULL, id_table: wctdm_pci_tbl, }; static int __init wctdm_init(void) { int res; int x; for (x = 0; x < (sizeof(fxo_modes) / sizeof(fxo_modes[0])); x++) { if (!strcmp(fxo_modes[x].name, opermode)) break; } if (x < sizeof(fxo_modes) / sizeof(fxo_modes[0])) { _opermode = x; } else { printk("Invalid/unknown operating mode '%s' specified. Please choose one of:\n", opermode); for (x = 0; x < sizeof(fxo_modes) / sizeof(fxo_modes[0]); x++) printk(" %s\n", fxo_modes[x].name); printk("Note this option is CASE SENSITIVE!\n"); return -ENODEV; } if (!strcmp(opermode, "AUSTRALIA")) { boostringer = 1; fxshonormode = 1; } /* 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; } res = zap_pci_module(&wctdm_driver); if (res) return -ENODEV; return 0; } static void __exit wctdm_cleanup(void) { pci_unregister_driver(&wctdm_driver); } #ifdef LINUX26 module_param(debug, int, 0600); module_param(loopcurrent, int, 0600); module_param(reversepolarity, int, 0600); module_param(robust, int, 0600); module_param(opermode, charp, 0600); module_param(timingonly, int, 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(ringdebounce, int, 0600); module_param(fwringdetect, int, 0600); module_param(alawoverride, int, 0600); module_param(fastpickup, int, 0600); module_param(fxotxgain, int, 0600); module_param(fxorxgain, int, 0600); module_param(fxstxgain, int, 0600); module_param(fxsrxgain, int, 0600); #else MODULE_PARM(debug, "i"); MODULE_PARM(loopcurrent, "i"); MODULE_PARM(reversepolarity, "i"); MODULE_PARM(robust, "i"); MODULE_PARM(opermode, "s"); MODULE_PARM(timingonly, "i"); MODULE_PARM(lowpower, "i"); MODULE_PARM(boostringer, "i"); MODULE_PARM(fastringer, "i"); MODULE_PARM(fxshonormode, "i"); MODULE_PARM(battdebounce, "i"); MODULE_PARM(battalarm, "i"); MODULE_PARM(battthresh, "i"); MODULE_PARM(ringdebounce, "i"); MODULE_PARM(fwringdetect, "i"); MODULE_PARM(alawoverride, "i"); MODULE_PARM(fastpickup, "i"); MODULE_PARM(fxotxgain, "i"); MODULE_PARM(fxorxgain, "i"); MODULE_PARM(fxstxgain, "i"); MODULE_PARM(fxsrxgain, "i"); #endif MODULE_DESCRIPTION("Wildcard TDM400P Zaptel Driver"); MODULE_AUTHOR("Mark Spencer "); #if defined(MODULE_ALIAS) MODULE_ALIAS("wcfxs"); #endif #ifdef MODULE_LICENSE MODULE_LICENSE("GPL"); #endif module_init(wctdm_init); module_exit(wctdm_cleanup); zaptel-1.4.11/kernel/proslic.h0000644000000000000000000001037210751714440014705 0ustar rootroot// 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 #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 zaptel-1.4.11/kernel/pciradio.c0000644000000000000000000014661311003536306015021 0ustar rootroot/* * PCI RADIO Card Zapata Telephony PCI Quad Radio Interface driver * * Written by Jim Dixon * Based on previous work by Mark Spencer * Based on previous works, designs, and archetectures conceived and * written by Jim Dixon . * * Copyright (C) 2001-2007 Jim Dixon / Zapata Telephony. * * 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. * */ /* The PCI Radio Interface card interfaces up to 4 two-way radios (either a base/mobile radio or repeater system) to Zaptel channels. The driver may work either independent of an application, or with it, through the driver;s ioctl() interface. This file gives you access to specify load-time parameters for Radio channels, so that the driver may run by itself, and just act like a generic Zaptel radio interface. */ /* Latency tests: Without driver: 308496 With driver: 303826 (1.5 %) */ #include #include #include #include #include #include #include #include #include #ifdef STANDALONE_ZAPATA #include "zaptel.h" #else #include #endif #ifdef LINUX26 #include #endif #define RAD_MAX_IFACES 128 #define NUM_CODES 15 #define SERIAL_BUFLEN 128 #define SRX_TIMEOUT 300 #define RAD_CNTL 0x00 #define RAD_OPER 0x01 #define RAD_AUXC 0x02 #define RAD_AUXD 0x03 #define XPGM 4 #define XCS 2 #define RAD_MASK0 0x04 #define RAD_MASK1 0x05 #define RAD_INTSTAT 0x06 #define RAD_AUXR 0x07 #define XINIT 8 #define XDONE 0x10 #define RAD_DMAWS 0x08 #define RAD_DMAWI 0x0c #define RAD_DMAWE 0x10 #define RAD_DMARS 0x18 #define RAD_DMARI 0x1c #define RAD_DMARE 0x20 #define RAD_AUXFUNC 0x2b #define RAD_SERCTL 0x2d #define RAD_FSCDELAY 0x2f #define RAD_REGBASE 0xc0 #define RAD_CTCSSMASK 0xf #define RAD_CTCSSOTHER 0xf #define RAD_CTCSSVALID 0x10 #define NUM_CHANS 4 #define RAD_GOTRX_DEBOUNCE_TIME 75 #define RAD_CTCSS_ACQUIRE_TIME 10 #define RAD_CTCSS_TALKOFF_TIME 1000 #define ZT_RADPAR_CTCSSACQUIRETIME 18 /* DEBUG only, this belongs in zaptel.h */ #define ZT_RADPAR_CTCSSTALKOFFTIME 19 /* DEBUG only, this belongs in zaptel.h */ /* * MX828 Commands */ #define MX828_GEN_RESET 0x01 /* W */ #define MX828_SAUDIO_CTRL 0x80 /* W */ #define MX828_SAUDIO_STATUS 0x81 /* R */ #define MX828_SAUDIO_SETUP 0x82 /* W */ #define MX828_TX_TONE 0x83 /* W16 */ #define MX828_RX_TONE 0x84 /* W16 */ #define MX828_DCS3 0x85 /* W */ #define MX828_DCS2 0x86 /* W */ #define MX828_DCS1 0x87 /* W */ #define MX828_GEN_CTRL 0x88 /* W */ #define MX828_GPT 0x8B /* W */ #define MX828_IRQ_MASK 0x8E /* W */ #define MX828_SELCALL 0x8D /* W16 */ #define MX828_AUD_CTRL 0x8A /* W16 */ #define MX828_IRQ_FLAG 0x8F /* R */ struct encdec { unsigned char state; /* 0 = idle */ int chan; unsigned char req[NUM_CHANS]; unsigned char dcsrx[NUM_CHANS]; unsigned char ctrx[NUM_CHANS]; unsigned char dcstx[NUM_CHANS]; unsigned char cttx[NUM_CHANS]; unsigned char saudio_ctrl[NUM_CHANS]; unsigned char saudio_setup[NUM_CHANS]; unsigned char txcode[NUM_CHANS]; unsigned long lastcmd; int myindex[NUM_CHANS]; unsigned long waittime; unsigned char retstate; } ; struct pciradio { struct pci_dev *dev; struct zt_span span; unsigned char ios; int usecount; unsigned int intcount; int dead; int pos; int freeregion; int nchans; spinlock_t lock; int remote_locked; unsigned char rxbuf[SERIAL_BUFLEN]; unsigned short rxindex; unsigned long srxtimer; unsigned char txbuf[SERIAL_BUFLEN]; unsigned short txindex; unsigned short txlen; unsigned char pasave; unsigned char pfsave; volatile unsigned long ioaddr; dma_addr_t readdma; dma_addr_t writedma; volatile unsigned int *writechunk; /* Double-word aligned write memory */ volatile unsigned int *readchunk; /* Double-word aligned read memory */ unsigned char saudio_status[NUM_CHANS]; char gotcor[NUM_CHANS]; char gotct[NUM_CHANS]; char newctcssstate[NUM_CHANS]; char ctcssstate[NUM_CHANS]; char gotrx[NUM_CHANS]; char gotrx1[NUM_CHANS]; char gottx[NUM_CHANS]; char lasttx[NUM_CHANS]; int gotrxtimer[NUM_CHANS]; int ctcsstimer[NUM_CHANS]; int debouncetime[NUM_CHANS]; int ctcssacquiretime[NUM_CHANS]; int ctcsstalkofftime[NUM_CHANS]; int bursttime[NUM_CHANS]; int bursttimer[NUM_CHANS]; unsigned char remmode[NUM_CHANS]; unsigned short present_code[NUM_CHANS]; unsigned short last_code[NUM_CHANS]; unsigned short rxcode[NUM_CHANS][NUM_CODES + 1]; unsigned short rxclass[NUM_CHANS][NUM_CODES + 1]; unsigned short txcode[NUM_CHANS][NUM_CODES + 1];; unsigned char radmode[NUM_CHANS]; #define RADMODE_INVERTCOR 1 #define RADMODE_IGNORECOR 2 #define RADMODE_EXTTONE 4 #define RADMODE_EXTINVERT 8 #define RADMODE_IGNORECT 16 #define RADMODE_NOENCODE 32 unsigned char corthresh[NUM_CHANS]; struct zt_chan chans[NUM_CHANS]; unsigned char mx828_addr; struct encdec encdec; unsigned long lastremcmd; }; static struct pciradio *ifaces[RAD_MAX_IFACES]; static void pciradio_release(struct pciradio *rad); static int debug = 0; struct tonedef { int code; unsigned char b1; unsigned char b2; } ; #include "radfw.h" static struct tonedef cttable_tx [] = { {0,0,0}, {670,0xE,0xB1}, {693,0xE,0x34}, {719,0xD,0xB1}, {744,0xD,0x3B}, {770,0xC,0xC9}, {797,0xC,0x5A}, {825,0xB,0xEF}, {854,0xB,0x87}, {885,0xB,0x1F}, {915,0xA,0xC2}, {948,0xA,0x62}, {974,0xA,0x1B}, {1000,0x9,0xD8}, {1035,0x9,0x83}, {1072,0x9,0x2F}, {1109,0x8,0xE0}, {1148,0x8,0x93}, {1188,0x8,0x49}, {1230,0x8,0x1}, {1273,0x7,0xBC}, {1318,0x7,0x78}, {1365,0x7,0x36}, {1413,0x6,0xF7}, {1462,0x6,0xBC}, {1514,0x6,0x80}, {1567,0x6,0x48}, {1598,0x6,0x29}, {1622,0x6,0x12}, {1679,0x5,0xDD}, {1738,0x5,0xAA}, {1799,0x5,0x79}, {1835,0x5,0x5D}, {1862,0x5,0x49}, {1899,0x5,0x2F}, {1928,0x5,0x1B}, {1966,0x5,0x2}, {1995,0x4,0xEF}, {2035,0x4,0xD6}, {2065,0x4,0xC4}, {2107,0x4,0xAC}, {2181,0x4,0x83}, {2257,0x4,0x5D}, {2291,0x4,0x4C}, {2336,0x4,0x37}, {2418,0x4,0x12}, {2503,0x3,0xEF}, {2541,0x3,0xE0}, {0,0,0} } ; static struct tonedef cttable_rx [] = { {0,0,0}, {670,0x3,0xD8}, {693,0x4,0x9}, {719,0x4,0x1B}, {744,0x4,0x4E}, {770,0x4,0x83}, {797,0x4,0x94}, {825,0x4,0xCB}, {854,0x5,0x2}, {885,0x5,0x14}, {915,0x5,0x4C}, {948,0x5,0x87}, {974,0x5,0x94}, {1000,0x5,0xCB}, {1035,0x6,0x7}, {1072,0x6,0x45}, {1109,0x6,0x82}, {1148,0x6,0xC0}, {1188,0x6,0xD1}, {1230,0x7,0x10}, {1273,0x7,0x50}, {1318,0x7,0xC0}, {1365,0x8,0x2}, {1413,0x8,0x44}, {1462,0x8,0x86}, {1514,0x8,0xC9}, {1567,0x9,0xC}, {1598,0x9,0x48}, {1622,0x9,0x82}, {1679,0x9,0xC6}, {1738,0xA,0xB}, {1799,0xA,0x84}, {1835,0xA,0xC2}, {1862,0xA,0xC9}, {1899,0xB,0x8}, {1928,0xB,0x44}, {1966,0xB,0x83}, {1995,0xB,0x8A}, {2035,0xB,0xC9}, {2065,0xC,0x6}, {2107,0xC,0x46}, {2181,0xC,0xC3}, {2257,0xD,0x41}, {2291,0xD,0x48}, {2336,0xD,0x89}, {2418,0xE,0x8}, {2503,0xE,0x88}, {2541,0xE,0xC7}, {0,0,0} }; static struct { int code; char b3; char b2; char b1; } dcstable[] = { {0,0,0,0}, {23,0x76,0x38,0x13}, {25,0x6B,0x78,0x15}, {26,0x65,0xD8,0x16}, {31,0x51,0xF8,0x19}, {32,0x5F,0x58,0x1A}, {43,0x5B,0x68,0x23}, {47,0x0F,0xD8,0x27}, {51,0x7C,0xA8,0x29}, {54,0x6F,0x48,0x2C}, {65,0x5D,0x18,0x35}, {71,0x67,0x98,0x39}, {72,0x69,0x38,0x3A}, {73,0x2E,0x68,0x3B}, {74,0x74,0x78,0x3C}, {114,0x35,0xE8,0x4C}, {115,0x72,0xB8,0x4D}, {116,0x7C,0x18,0x4E}, {125,0x07,0xB8,0x55}, {131,0x3D,0x38,0x59}, {132,0x33,0x98,0x5A}, {134,0x2E,0xD8,0x5C}, {143,0x37,0xA8,0x63}, {152,0x1E,0xC8,0x6A}, {155,0x44,0xD8,0x6D}, {156,0x4A,0x78,0x6E}, {162,0x6B,0xC8,0x72}, {165,0x31,0xD8,0x75}, {172,0x05,0xF8,0x7A}, {174,0x18,0xB8,0x7C}, {205,0x6E,0x98,0x85}, {223,0x68,0xE8,0x93}, {226,0x7B,0x08,0x96}, {243,0x45,0xB8,0xA3}, {244,0x1F,0xA8,0xA4}, {245,0x58,0xF8,0xA5}, {251,0x62,0x78,0xA9}, {261,0x17,0x78,0xB1}, {263,0x5E,0x88,0xB3}, {265,0x43,0xC8,0xB5}, {271,0x79,0x48,0xB9}, {306,0x0C,0xF8,0xC6}, {311,0x38,0xD8,0xC9}, {315,0x6C,0x68,0xCD}, {331,0x23,0xE8,0xD9}, {343,0x29,0x78,0xE3}, {346,0x3A,0x98,0xE6}, {351,0x0E,0xB8,0xE9}, {364,0x68,0x58,0xF4}, {365,0x2F,0x08,0xF5}, {371,0x15,0x88,0xF9}, {411,0x77,0x69,0x09}, {412,0x79,0xC9,0x0A}, {413,0x3E,0x99,0x0B}, {423,0x4B,0x99,0x13}, {431,0x6C,0x59,0x19}, {432,0x62,0xF9,0x1A}, {445,0x7B,0x89,0x25}, {464,0x27,0xE9,0x34}, {465,0x60,0xB9,0x35}, {466,0x6E,0x19,0x36}, {503,0x3C,0x69,0x43}, {506,0x2F,0x89,0x46}, {516,0x41,0xB9,0x4E}, {532,0x0E,0x39,0x5A}, {546,0x19,0xE9,0x66}, {565,0x0C,0x79,0x75}, {606,0x5D,0x99,0x86}, {612,0x67,0x19,0x8A}, {624,0x0F,0x59,0x94}, {627,0x01,0xF9,0x97}, {631,0x72,0x89,0x99}, {632,0x7C,0x29,0x9A}, {654,0x4C,0x39,0xAC}, {662,0x24,0x79,0xB2}, {664,0x39,0x39,0xB4}, {703,0x22,0xB9,0xC3}, {712,0x0B,0xD9,0xCA}, {723,0x39,0x89,0xD3}, {731,0x1E,0x49,0xD9}, {732,0x10,0xE9,0xDA}, {734,0x0D,0xA9,0xDC}, {743,0x14,0xD9,0xE3}, {754,0x20,0xF9,0xEC}, {0,0,0,0} }; static int gettxtone(int code) { int i; if (!code) return(0); for(i = 0; cttable_tx[i].code || (!i); i++) { if (cttable_tx[i].code == code) { return (i); } } return(-1); } static int getrxtone(int code) { int i; if (!code) return(0); for(i = 0; cttable_rx[i].code || (!i); i++) { if (cttable_rx[i].code == code) { return (i); } } return(-1); } static int getdcstone(int code) { int i; if (!code) return(0); for(i = 0; dcstable[i].code || (!i); i++) { if (dcstable[i].code == code) { return (i); } } return(-1); } void __pciradio_setcreg(struct pciradio *rad, unsigned char reg, unsigned char val) { outb(val, rad->ioaddr + RAD_REGBASE + ((reg & 0xf) << 2)); } unsigned char __pciradio_getcreg(struct pciradio *rad, unsigned char reg) { return inb(rad->ioaddr + RAD_REGBASE + ((reg & 0xf) << 2)); } void rbi_out(struct pciradio *rad, int n, unsigned char *rbicmd) { unsigned long flags; int x; DECLARE_WAIT_QUEUE_HEAD(mywait); for(;;) { spin_lock_irqsave(&rad->lock,flags); x = rad->remote_locked || (__pciradio_getcreg(rad,0xc) & 2); if (!x) rad->remote_locked = 1; spin_unlock_irqrestore(&rad->lock,flags); if (x) interruptible_sleep_on_timeout(&mywait,2); else break; } spin_lock_irqsave(&rad->lock,flags); /* enable and address RBI serializer */ __pciradio_setcreg(rad,0xf,rad->pfsave | (n << 4) | 0x40); /* output commands */ for(x = 0; x < 5; x++) __pciradio_setcreg(rad,0xc,rbicmd[x]); /* output it */ __pciradio_setcreg(rad,0xb,1); rad->remote_locked = 0; spin_unlock_irqrestore(&rad->lock,flags); return; } /* * Output a command to the MX828 over the serial bus */ void mx828_command(struct pciradio *rad,int channel, unsigned char command, unsigned char *byte1, unsigned char *byte2) { if(channel > 3) return; rad->mx828_addr = channel; __pciradio_setcreg(rad,0,channel); if (byte1) __pciradio_setcreg(rad,1,*byte1); if (byte2) __pciradio_setcreg(rad,2,*byte2); __pciradio_setcreg(rad,3,command); } void mx828_command_wait(struct pciradio *rad,int channel, unsigned char command, unsigned char *byte1, unsigned char *byte2) { DECLARE_WAIT_QUEUE_HEAD(mywait); unsigned long flags; spin_lock_irqsave(&rad->lock,flags); while(rad->encdec.state) { spin_unlock_irqrestore(&rad->lock,flags); interruptible_sleep_on_timeout(&mywait,2); spin_lock_irqsave(&rad->lock,flags); } rad->encdec.lastcmd = jiffies + 1000; spin_unlock_irqrestore(&rad->lock,flags); while(__pciradio_getcreg(rad,0xc) & 1); rad->encdec.lastcmd = jiffies + 1000; spin_lock_irqsave(&rad->lock,flags); rad->encdec.lastcmd = jiffies + 1000; mx828_command(rad,channel,command,byte1,byte2); spin_unlock_irqrestore(&rad->lock,flags); rad->encdec.lastcmd = jiffies + 1000; while(__pciradio_getcreg(rad,0xc) & 1); rad->encdec.lastcmd = jiffies; } static void _do_encdec(struct pciradio *rad) { int i,n; unsigned char byte1 = 0,byte2 = 0; /* return doing nothing if busy */ if ((rad->encdec.lastcmd + 2) > jiffies) return; if (__pciradio_getcreg(rad,0xc) & 1) return; n = 0; byte2 = 0; switch(rad->encdec.state) { case 0: for(i = 0; i < rad->nchans; i++) { n = (unsigned)(i - rad->intcount) % rad->nchans; if (rad->encdec.req[n]) break; } if (i >= rad->nchans) return; rad->encdec.req[n] = 0; rad->encdec.dcsrx[n] = 0; rad->encdec.ctrx[n] = 0; rad->encdec.dcstx[n] = 0; rad->encdec.cttx[n] = 0; rad->encdec.myindex[n] = 0; rad->encdec.req[n] = 0; rad->encdec.chan = n; /* if something in code 0 for rx, is DCS */ if (rad->rxcode[n][0]) rad->encdec.dcsrx[n] = 1; else { /* otherwise, if something in other codes, is CT rx */ for(i = 1; i <= NUM_CODES; i++) { if (rad->rxcode[n][1]) rad->encdec.ctrx[n] = 1; } } /* get index for tx code. Will be 0 if not receiving a CT */ rad->encdec.myindex[n] = 0; if (rad->gotrx[n] && rad->encdec.ctrx[n] && (rad->present_code[n])) rad->encdec.myindex[n] = rad->present_code[n]; /* get actual tx code from array */ rad->encdec.txcode[n] = rad->txcode[n][rad->encdec.myindex[n]]; if (rad->encdec.txcode[n] & 0x8000) rad->encdec.dcstx[n] = 1; else if (rad->encdec.txcode[n]) rad->encdec.cttx[n] = 1; if (rad->radmode[n] & RADMODE_NOENCODE) rad->encdec.dcstx[n] = rad->encdec.cttx[n] = 0; if ((!rad->gottx[n]) || rad->bursttimer[n]) rad->encdec.dcstx[n] = rad->encdec.cttx[n] = 0; rad->encdec.saudio_ctrl[n] = 0; rad->encdec.saudio_setup[n] = 0; rad->encdec.state = 1; break; case 1: if (rad->encdec.dcstx[rad->encdec.chan] && (!rad->encdec.dcsrx[rad->encdec.chan])) /* if to transmit DCS */ { rad->encdec.saudio_setup[rad->encdec.chan] |= 3; rad->encdec.saudio_ctrl[rad->encdec.chan] |= 0x80; byte1 = dcstable[rad->encdec.txcode[rad->encdec.chan] & 0x7fff].b1; mx828_command(rad,rad->encdec.chan, MX828_DCS1, &byte1, &byte2 ); rad->encdec.state = 2; break; } rad->encdec.state = 4; break; case 2: byte1 = dcstable[rad->encdec.txcode[rad->encdec.chan] & 0x7fff].b2; mx828_command(rad,rad->encdec.chan, MX828_DCS2, &byte1, &byte2 ); rad->encdec.state = 3; break; case 3: byte1 = dcstable[rad->encdec.txcode[rad->encdec.chan] & 0x7fff].b3; mx828_command(rad,rad->encdec.chan, MX828_DCS3, &byte1, &byte2 ); rad->encdec.state = 4; break; case 4: if (rad->encdec.cttx[rad->encdec.chan]) { rad->encdec.saudio_ctrl[rad->encdec.chan] |= 0x80; byte1 = cttable_tx[rad->encdec.txcode[rad->encdec.chan]].b1; byte2 = cttable_tx[rad->encdec.txcode[rad->encdec.chan]].b2; mx828_command(rad,rad->encdec.chan, MX828_TX_TONE, &byte1, &byte2 ); } rad->encdec.state = 5; break; case 5: if (rad->encdec.dcsrx[rad->encdec.chan]) { rad->encdec.saudio_setup[rad->encdec.chan] |= 1; rad->encdec.saudio_ctrl[rad->encdec.chan] |= 0x41; byte1 = dcstable[rad->rxcode[rad->encdec.chan][0]].b1; mx828_command(rad,rad->encdec.chan, MX828_DCS1, &byte1, &byte2 ); rad->encdec.state = 6; break; } rad->encdec.state = 8; break; case 6: byte1 = dcstable[rad->rxcode[rad->encdec.chan][0]].b2; mx828_command(rad,rad->encdec.chan, MX828_DCS2, &byte1, &byte2 ); rad->encdec.state = 7; break; case 7: byte1 = dcstable[rad->rxcode[rad->encdec.chan][0]].b3; mx828_command(rad,rad->encdec.chan, MX828_DCS3, &byte1, &byte2 ); rad->encdec.state = 8; break; case 8: if (rad->encdec.ctrx[rad->encdec.chan]) { rad->encdec.saudio_setup[rad->encdec.chan] |= 0x80; rad->encdec.saudio_ctrl[rad->encdec.chan] |= 0x60; } byte1 = rad->encdec.saudio_setup[rad->encdec.chan]; mx828_command(rad,rad->encdec.chan, MX828_SAUDIO_SETUP, &byte1, &byte2 ); rad->encdec.state = 9; break; case 9: byte1 = rad->encdec.saudio_ctrl[rad->encdec.chan]; mx828_command(rad,rad->encdec.chan, MX828_SAUDIO_CTRL, &byte1, &byte2 ); rad->encdec.state = 10; break; case 10: rad->encdec.chan = 0; rad->encdec.state = 0; break; } } static inline void pciradio_transmitprep(struct pciradio *rad, unsigned char ints) { volatile unsigned int *writechunk; int x; if (ints & 0x01) /* Write is at interrupt address. Start writing from normal offset */ writechunk = rad->writechunk; else writechunk = rad->writechunk + ZT_CHUNKSIZE; /* Calculate Transmission */ zt_transmit(&rad->span); for (x=0;xchans[0].writechunk[x] << 24); writechunk[x] |= (rad->chans[1].writechunk[x] << 16); writechunk[x] |= (rad->chans[2].writechunk[x] << 8); writechunk[x] |= (rad->chans[3].writechunk[x]); } } static inline void pciradio_receiveprep(struct pciradio *rad, unsigned char ints) { volatile unsigned int *readchunk; int x; if (ints & 0x08) readchunk = rad->readchunk + ZT_CHUNKSIZE; else /* Read is at interrupt address. Valid data is available at normal offset */ readchunk = rad->readchunk; for (x=0;xchans[0].readchunk[x] = (readchunk[x] >> 24) & 0xff; rad->chans[1].readchunk[x] = (readchunk[x] >> 16) & 0xff; rad->chans[2].readchunk[x] = (readchunk[x] >> 8) & 0xff; rad->chans[3].readchunk[x] = (readchunk[x]) & 0xff; } for (x=0;xnchans;x++) { zt_ec_chunk(&rad->chans[x], rad->chans[x].readchunk, rad->chans[x].writechunk); } zt_receive(&rad->span); } static void pciradio_stop_dma(struct pciradio *rad); static void pciradio_reset_serial(struct pciradio *rad); static void pciradio_restart_dma(struct pciradio *rad); #ifdef LEAVE_THIS_COMMENTED_OUT #ifdef LINUX26 static irqreturn_t pciradio_interrupt(int irq, void *dev_id, struct pt_regs *regs) #else static void pciradio_interrupt(int irq, void *dev_id, struct pt_regs *regs) #endif #endif ZAP_IRQ_HANDLER(pciradio_interrupt) { struct pciradio *rad = dev_id; unsigned char ints,byte1,byte2,gotcor,gotctcss,gotslowctcss,ctcss; int i,x,gotrx; ints = inb(rad->ioaddr + RAD_INTSTAT); outb(ints, rad->ioaddr + RAD_INTSTAT); if (!ints) #ifdef LINUX26 return IRQ_NONE; #else return; #endif if (ints & 0x10) { /* Stop DMA, wait for watchdog */ printk("RADIO PCI Master abort\n"); pciradio_stop_dma(rad); #ifdef LINUX26 return IRQ_RETVAL(1); #else return; #endif } if (ints & 0x20) { printk("RADIO PCI Target abort\n"); #ifdef LINUX26 return IRQ_RETVAL(1); #else return; #endif } if (ints & 0x0f) { rad->intcount++; x = rad->intcount % rad->nchans; /* freeze */ __pciradio_setcreg(rad,0,rad->mx828_addr | 4); /* read SAUDIO_STATUS for the proper channel */ byte1 = rad->saudio_status[x] = __pciradio_getcreg(rad,x); /* thaw */ __pciradio_setcreg(rad,0,rad->mx828_addr); /* get COR input */ byte2 = __pciradio_getcreg(rad,9); /* get bit for this channel */ gotcor = byte2 & (1 << x); if (rad->radmode[x] & RADMODE_INVERTCOR) gotcor = !gotcor; rad->gotcor[x] = gotcor; if (rad->radmode[x] & RADMODE_IGNORECOR) gotcor = 1; gotslowctcss = 0; if ((byte1 & RAD_CTCSSVALID) && ((byte1 & RAD_CTCSSMASK) != RAD_CTCSSOTHER)) gotslowctcss = 1; gotctcss = 1; ctcss = 0; /* set ctcss to 1 if decoding ctcss */ if (!rad->rxcode[x][0]) { for(i = 1; i <= NUM_CODES; i++) { if (rad->rxcode[x][i]) { ctcss = 1; break; } } } if (ctcss) { if ((!(byte1 & 0x40)) || ((!rad->gotrx[x]) && (!gotslowctcss))) gotctcss = 0; } rad->present_code[x] = 0; if (rad->rxcode[x][0]) { if (byte1 & 0x80) gotctcss = gotslowctcss = 1; else gotctcss = 0; } else if (gotslowctcss) rad->present_code[x] = (byte1 & RAD_CTCSSMASK) + 1; if (rad->radmode[x] & RADMODE_EXTTONE) { unsigned mask = 1 << (x + 4); /* they're on the UIOB's */ unsigned char byteuio; /* set UIOB as input */ byteuio = __pciradio_getcreg(rad,0xe); byteuio |= mask; __pciradio_setcreg(rad,0xe,byteuio); /* get UIO input */ byteuio = __pciradio_getcreg(rad,8); if (rad->radmode[x] & RADMODE_EXTINVERT) gotctcss = gotslowctcss = ((byteuio & mask) == 0); else gotctcss = gotslowctcss = ((byteuio & mask) != 0); } rad->gotct[x] = gotslowctcss; if ((rad->radmode[x] & RADMODE_IGNORECT) || ((!(rad->radmode[x] & RADMODE_EXTTONE)) && (!ctcss))) { gotctcss = 1; gotslowctcss = 1; rad->present_code[x] = 0; } if(rad->newctcssstate[x] != gotctcss){ rad->newctcssstate[x] = gotctcss; if(rad->newctcssstate[x]) rad->ctcsstimer[x]=rad->ctcssacquiretime[x]; else rad->ctcsstimer[x]=rad->ctcsstalkofftime[x]; } else{ if(!rad->ctcsstimer[x]) rad->ctcssstate[x] = rad->newctcssstate[x]; else rad->ctcsstimer[x]--; } gotrx = gotcor && rad->ctcssstate[x]; if (gotrx != rad->gotrx[x]) { rad->gotrxtimer[x] = rad->debouncetime[x]; } rad->gotrx[x] = gotrx; if (rad->present_code[x] != rad->last_code[x]) { rad->encdec.req[x] = 1; rad->last_code[x] = rad->present_code[x]; } _do_encdec(rad); for(x = 0; x < rad->nchans; x++) { unsigned char mask = 1 << x; if (rad->gottx[x] != rad->lasttx[x]) { if (rad->gottx[x]) { rad->bursttimer[x] = 0; rad->pasave |= mask; __pciradio_setcreg(rad, 0xa, rad->pasave); } else { if (!rad->bursttime[x]) { rad->pasave &= ~mask; __pciradio_setcreg(rad, 0xa, rad->pasave); } else { rad->bursttimer[x] = rad->bursttime[x]; } } rad->encdec.req[x] = 1; rad->lasttx[x] = rad->gottx[x]; } if (rad->bursttimer[x]) { /* if just getting to zero */ if (!(--rad->bursttimer[x])) { unsigned char mask = 1 << x; rad->pasave &= ~mask; __pciradio_setcreg(rad, 0xa, rad->pasave); } } /* if timer active */ if (rad->gotrxtimer[x]) { /* if just getting to zero */ if (!(--rad->gotrxtimer[x])) { unsigned char mask; mask = 1 << (x + 4); rad->pasave &= ~mask; if (gotctcss) rad->pasave |= mask; __pciradio_setcreg(rad, 0xa, rad->pasave); if (rad->gotrx[x] != rad->gotrx1[x]) { if (rad->gotrx[x]) { if (debug) { if (rad->present_code[x]) printk("Chan %d got rx (ctcss code %d)\n",x + 1, cttable_rx[rad->rxcode[x][rad->present_code[x]]].code); else printk("Chan %d got rx\n",x + 1); } zt_hooksig(&rad->chans[x],ZT_RXSIG_OFFHOOK); } else { if (debug) printk("Chan %d lost rx\n",x + 1); zt_hooksig(&rad->chans[x],ZT_RXSIG_ONHOOK); } rad->encdec.req[x] = 1; } rad->gotrx1[x] = rad->gotrx[x]; } } } /* process serial if any */ /* send byte if there is one in buffer to send */ if (rad->txlen && (rad->txlen != rad->txindex)) { /* if tx not busy */ if (!(__pciradio_getcreg(rad,9) & 0x80)) { __pciradio_setcreg(rad, 4, rad->txbuf[rad->txindex++]); } } rad->srxtimer++; /* if something in rx to read */ while(__pciradio_getcreg(rad,9) & 0x10) { unsigned char c = __pciradio_getcreg(rad,4); rad->srxtimer = 0; if (rad->rxindex < RAD_SERIAL_BUFLEN) { rad->rxbuf[rad->rxindex++] = c; } udelay(1); } pciradio_receiveprep(rad, ints); pciradio_transmitprep(rad, ints); i = 0; for(x = 0; x < 4; x++) { if (rad->gottx[x]) i |= (1 << (x * 2)); if (rad->gotrx[x]) i |= (2 << (x * 2)); } /* output LED's */ __pciradio_setcreg(rad, 9, i); } #ifdef LINUX26 return IRQ_RETVAL(1); #endif } static int pciradio_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data) { int i,mycode; unsigned long flags; unsigned char byte1,byte2,mask; union { struct zt_radio_stat s; struct zt_radio_param p; } stack; struct pciradio *rad = chan->pvt; DECLARE_WAIT_QUEUE_HEAD(mywait); switch (cmd) { case ZT_RADIO_GETPARAM: if (copy_from_user(&stack.p,(struct zt_radio_param *)data,sizeof(struct zt_radio_param))) return -EFAULT; spin_lock_irqsave(&rad->lock,flags); stack.p.data = 0; /* start with 0 value in output */ switch(stack.p.radpar) { case ZT_RADPAR_INVERTCOR: if (rad->radmode[chan->chanpos - 1] & RADMODE_INVERTCOR) stack.p.data = 1; break; case ZT_RADPAR_IGNORECOR: if (rad->radmode[chan->chanpos - 1] & RADMODE_IGNORECOR) stack.p.data = 1; break; case ZT_RADPAR_IGNORECT: if (rad->radmode[chan->chanpos - 1] & RADMODE_IGNORECT) stack.p.data = 1; break; case ZT_RADPAR_NOENCODE: if (rad->radmode[chan->chanpos - 1] & RADMODE_NOENCODE) stack.p.data = 1; break; case ZT_RADPAR_CORTHRESH: stack.p.data = rad->corthresh[chan->chanpos - 1] & 7; break; case ZT_RADPAR_EXTRXTONE: if (rad->radmode[chan->chanpos - 1] & RADMODE_EXTTONE) { stack.p.data = 1; if (rad->radmode[chan->chanpos - 1] & RADMODE_EXTINVERT) { stack.p.data = 2; } } break; case ZT_RADPAR_NUMTONES: stack.p.data = NUM_CODES; break; case ZT_RADPAR_RXTONE: if ((stack.p.index < 1) || (stack.p.index > NUM_CODES)) { spin_unlock_irqrestore(&rad->lock,flags); return -EINVAL; } stack.p.data = cttable_rx[rad->rxcode[chan->chanpos - 1][stack.p.index] & 0x7fff].code; break; case ZT_RADPAR_RXTONECLASS: if ((stack.p.index < 1) || (stack.p.index > NUM_CODES)) { spin_unlock_irqrestore(&rad->lock,flags); return -EINVAL; } stack.p.data = rad->rxclass[chan->chanpos - 1][stack.p.index] & 0xffff; break; case ZT_RADPAR_TXTONE: if (stack.p.index > NUM_CODES) { spin_unlock_irqrestore(&rad->lock,flags); return -EINVAL; } stack.p.data = cttable_tx[rad->txcode[chan->chanpos - 1][stack.p.index] & 0x7fff].code; /* if a DCS tone, return as such */ if (rad->txcode[chan->chanpos - 1][stack.p.index] & 0x8000) stack.p.data |= 0x8000; break; case ZT_RADPAR_DEBOUNCETIME: stack.p.data = rad->debouncetime[chan->chanpos - 1]; break; case ZT_RADPAR_CTCSSACQUIRETIME: stack.p.data = rad->ctcssacquiretime[chan->chanpos - 1]; break; case ZT_RADPAR_CTCSSTALKOFFTIME: stack.p.data = rad->ctcsstalkofftime[chan->chanpos - 1]; break; case ZT_RADPAR_BURSTTIME: stack.p.data = rad->bursttime[chan->chanpos - 1]; break; case ZT_RADPAR_UIODATA: stack.p.data = 0; byte1 = __pciradio_getcreg(rad,8); if (byte1 & (1 << (chan->chanpos - 1))) stack.p.data |= 1; if (byte1 & (1 << (chan->chanpos + 3))) stack.p.data |= 2; break; case ZT_RADPAR_UIOMODE: stack.p.data = 0; byte1 = __pciradio_getcreg(rad,0xe); if (byte1 & (1 << (chan->chanpos - 1))) stack.p.data |= 1; if (byte1 & (1 << (chan->chanpos + 3))) stack.p.data |= 2; break; case ZT_RADPAR_REMMODE: stack.p.data = rad->remmode[chan->chanpos - 1]; break; default: spin_unlock_irqrestore(&rad->lock,flags); return -EINVAL; } spin_unlock_irqrestore(&rad->lock,flags); if (copy_to_user((struct zt_radio_param *)data,&stack.p,sizeof(struct zt_radio_param))) return -EFAULT; break; case ZT_RADIO_SETPARAM: if (copy_from_user(&stack.p,(struct zt_radio_param *)data,sizeof(struct zt_radio_param))) return -EFAULT; spin_lock_irqsave(&rad->lock,flags); switch(stack.p.radpar) { case ZT_RADPAR_INVERTCOR: if (stack.p.data) rad->radmode[chan->chanpos - 1] |= RADMODE_INVERTCOR; else rad->radmode[chan->chanpos - 1] &= ~RADMODE_INVERTCOR; break; case ZT_RADPAR_IGNORECOR: if (stack.p.data) rad->radmode[chan->chanpos - 1] |= RADMODE_IGNORECOR; else rad->radmode[chan->chanpos - 1] &= ~RADMODE_IGNORECOR; break; case ZT_RADPAR_IGNORECT: if (stack.p.data) rad->radmode[chan->chanpos - 1] |= RADMODE_IGNORECT; else rad->radmode[chan->chanpos - 1] &= ~RADMODE_IGNORECT; break; case ZT_RADPAR_NOENCODE: if (stack.p.data) rad->radmode[chan->chanpos - 1] |= RADMODE_NOENCODE; else rad->radmode[chan->chanpos - 1] &= ~RADMODE_NOENCODE; break; case ZT_RADPAR_CORTHRESH: if ((stack.p.data < 0) || (stack.p.data > 7)) { spin_unlock_irqrestore(&rad->lock,flags); return -EINVAL; } rad->corthresh[chan->chanpos - 1] = stack.p.data; byte1 = 0xc0 | (rad->corthresh[chan->chanpos - 1] << 2); spin_unlock_irqrestore(&rad->lock,flags); mx828_command_wait(rad,chan->chanpos - 1, MX828_GEN_CTRL, &byte1, &byte2); spin_lock_irqsave(&rad->lock,flags); break; case ZT_RADPAR_EXTRXTONE: if (stack.p.data) rad->radmode[chan->chanpos - 1] |= RADMODE_EXTTONE; else rad->radmode[chan->chanpos - 1] &= ~RADMODE_EXTTONE; if (stack.p.data > 1) rad->radmode[chan->chanpos - 1] |= RADMODE_EXTINVERT; else rad->radmode[chan->chanpos - 1] &= ~RADMODE_EXTINVERT; break; case ZT_RADPAR_INITTONE: for(i = 0; i <= NUM_CODES; i++) { rad->rxcode[chan->chanpos - 1][i] = 0; rad->rxclass[chan->chanpos - 1][i] = 0; rad->txcode[chan->chanpos - 1][i] = 0; } spin_unlock_irqrestore(&rad->lock,flags); for(i = 0; i < NUM_CODES; i++) { /* set to no encode/decode */ byte1 = 0; mx828_command_wait(rad,chan->chanpos - 1, MX828_SAUDIO_CTRL, &byte1, &byte2 ); /* set rx tone to none */ byte1 = i << 4; byte2 = 0; mx828_command_wait(rad,chan->chanpos - 1, MX828_RX_TONE, &byte1, &byte2 ); } spin_lock_irqsave(&rad->lock,flags); break; case ZT_RADPAR_RXTONE: if (!stack.p.index) /* if RX DCS mode */ { if ((stack.p.data < 0) || (stack.p.data > 777)) { spin_unlock_irqrestore(&rad->lock,flags); return -EINVAL; } mycode = getdcstone(stack.p.data); if (mycode < 0) { spin_unlock_irqrestore(&rad->lock,flags); return -EINVAL; } rad->rxcode[chan->chanpos - 1][0] = mycode; rad->encdec.req[chan->chanpos - 1] = 1; break; } if ((stack.p.index < 1) || (stack.p.index > NUM_CODES)) { spin_unlock_irqrestore(&rad->lock,flags); return -EINVAL; } mycode = getrxtone(stack.p.data); if (mycode < 0) { spin_unlock_irqrestore(&rad->lock,flags); return -EINVAL; } rad->rxcode[chan->chanpos - 1][stack.p.index] = mycode; byte1 = cttable_rx[mycode].b1 | ((stack.p.index - 1) << 4); byte2 = cttable_rx[mycode].b2; spin_unlock_irqrestore(&rad->lock,flags); mx828_command_wait(rad,chan->chanpos - 1, MX828_RX_TONE, &byte1, &byte2 ); spin_lock_irqsave(&rad->lock,flags); /* zot out DCS one if there */ rad->rxcode[chan->chanpos - 1][0] = 0; rad->encdec.req[chan->chanpos - 1] = 1; break; case ZT_RADPAR_RXTONECLASS: if ((stack.p.index < 1) || (stack.p.index > NUM_CODES)) { spin_unlock_irqrestore(&rad->lock,flags); return -EINVAL; } rad->rxclass[chan->chanpos - 1][stack.p.index] = stack.p.data & 0xffff; break; case ZT_RADPAR_TXTONE: if (stack.p.index > NUM_CODES) { spin_unlock_irqrestore(&rad->lock,flags); return -EINVAL; } if (stack.p.data & 0x8000) /* if dcs */ mycode = getdcstone(stack.p.data & 0x7fff); else mycode = gettxtone(stack.p.data); if (mycode < 0) { spin_unlock_irqrestore(&rad->lock,flags); return -EINVAL; } if (stack.p.data & 0x8000) mycode |= 0x8000; rad->txcode[chan->chanpos - 1][stack.p.index] = mycode; rad->encdec.req[chan->chanpos - 1] = 1; break; case ZT_RADPAR_DEBOUNCETIME: rad->debouncetime[chan->chanpos - 1] = stack.p.data; break; case ZT_RADPAR_CTCSSACQUIRETIME: rad->ctcssacquiretime[chan->chanpos - 1] = stack.p.data; break; case ZT_RADPAR_CTCSSTALKOFFTIME: rad->ctcsstalkofftime[chan->chanpos - 1] = stack.p.data; break; case ZT_RADPAR_BURSTTIME: rad->bursttime[chan->chanpos - 1] = stack.p.data; break; case ZT_RADPAR_UIODATA: byte1 = __pciradio_getcreg(rad,8); byte1 &= ~(1 << (chan->chanpos - 1)); byte1 &= ~(1 << (chan->chanpos + 3)); if (stack.p.data & 1) byte1 |= (1 << (chan->chanpos - 1)); if (stack.p.data & 2) byte1 |= (1 << (chan->chanpos + 3)); __pciradio_setcreg(rad,8,byte1); break; case ZT_RADPAR_UIOMODE: byte1 = __pciradio_getcreg(rad,0xe); byte1 &= ~(1 << (chan->chanpos - 1)); byte1 &= ~(1 << (chan->chanpos + 3)); if (stack.p.data & 1) byte1 |= (1 << (chan->chanpos - 1)); if (stack.p.data & 2) byte1 |= (1 << (chan->chanpos + 3)); __pciradio_setcreg(rad,0xe,byte1); break; case ZT_RADPAR_REMMODE: rad->remmode[chan->chanpos - 1] = stack.p.data; break; case ZT_RADPAR_REMCOMMAND: /* if no remote mode, return an error */ if (rad->remmode[chan->chanpos - 1] == ZT_RADPAR_REM_NONE) { spin_unlock_irqrestore(&rad->lock,flags); return -EINVAL; } i = 0; if (rad->remmode[chan->chanpos - 1] == ZT_RADPAR_REM_RBI1) { /* set UIOA and UIOB for output */ byte1 = __pciradio_getcreg(rad,0xe); mask = (1 << (chan->chanpos - 1)) | (1 << (chan->chanpos + 3)); byte2 = byte1 & (~mask); i = (byte2 != byte1); __pciradio_setcreg(rad,0xe,byte2); byte1 = __pciradio_getcreg(rad,8); mask = 1 << (chan->chanpos - 1); byte2 = byte1 | mask; i = (byte2 != byte1); __pciradio_setcreg(rad,8,byte2); spin_unlock_irqrestore(&rad->lock,flags); if (i || (jiffies < rad->lastremcmd + 10)) interruptible_sleep_on_timeout(&mywait,10); rad->lastremcmd = jiffies; rbi_out(rad,chan->chanpos - 1,(unsigned char *)&stack.p.data); spin_lock_irqsave(&rad->lock,flags); break; } spin_unlock_irqrestore(&rad->lock,flags); for(;;) { int x; spin_lock_irqsave(&rad->lock,flags); x = rad->remote_locked || (__pciradio_getcreg(rad,0xc) & 2); if (!x) rad->remote_locked = 1; spin_unlock_irqrestore(&rad->lock,flags); if (x) interruptible_sleep_on_timeout(&mywait,2); else break; } spin_lock_irqsave(&rad->lock,flags); /* set UIOA for input and UIOB for output */ byte1 = __pciradio_getcreg(rad,0xe); mask = 1 << (chan->chanpos + 3); /* B an output */ byte2 = byte1 & (~mask); byte2 |= 1 << (chan->chanpos - 1); /* A in input */ __pciradio_setcreg(rad,0xe,byte2); byte1 = __pciradio_getcreg(rad,8); byte2 = byte1 | mask; byte2 |= 1 << (chan->chanpos - 1); byte2 |= 1 << (chan->chanpos + 3); __pciradio_setcreg(rad,8,byte2); spin_unlock_irqrestore(&rad->lock,flags); if (byte1 != byte2) interruptible_sleep_on_timeout(&mywait,3); while (jiffies < rad->lastremcmd + 10) interruptible_sleep_on_timeout(&mywait,10); rad->lastremcmd = jiffies; for(;;) { if (!(__pciradio_getcreg(rad,0xc) & 2)) break; interruptible_sleep_on_timeout(&mywait,2); } spin_lock_irqsave(&rad->lock,flags); /* enable and address async serializer */ __pciradio_setcreg(rad,0xf,rad->pfsave | ((chan->chanpos - 1) << 4) | 0x80); /* copy tx buffer */ memcpy(rad->txbuf,stack.p.buf,stack.p.index); rad->txlen = stack.p.index; rad->txindex = 0; rad->rxindex = 0; rad->srxtimer = 0; memset(stack.p.buf,0,SERIAL_BUFLEN); stack.p.index = 0; if (stack.p.data) for(;;) { rad->rxbuf[rad->rxindex] = 0; if ((rad->rxindex < stack.p.data) && (rad->srxtimer < SRX_TIMEOUT) && ((rad->remmode[chan->chanpos - 1] == ZT_RADPAR_REM_SERIAL) || (!strchr((char *)rad->rxbuf,'\r')))) { spin_unlock_irqrestore(&rad->lock,flags); interruptible_sleep_on_timeout(&mywait,2); spin_lock_irqsave(&rad->lock,flags); continue; } memset(stack.p.buf,0,SERIAL_BUFLEN); if (stack.p.data && (rad->rxindex > stack.p.data)) rad->rxindex = stack.p.data; if (rad->rxindex) memcpy(stack.p.buf,rad->rxbuf,rad->rxindex); stack.p.index = rad->rxindex; break; } /* wait for done if in SERIAL_ASCII mode, or if no Rx aftwards */ if ((rad->remmode[chan->chanpos - 1] == ZT_RADPAR_REM_SERIAL_ASCII) || (!stack.p.data)) { /* wait for TX to be done if not already */ while(rad->txlen && (rad->txindex < rad->txlen)) { spin_unlock_irqrestore(&rad->lock,flags); interruptible_sleep_on_timeout(&mywait,2); spin_lock_irqsave(&rad->lock,flags); } /* disable and un-address async serializer */ __pciradio_setcreg(rad,0xf,rad->pfsave); } rad->remote_locked = 0; spin_unlock_irqrestore(&rad->lock,flags); if (rad->remmode[chan->chanpos - 1] == ZT_RADPAR_REM_SERIAL_ASCII) interruptible_sleep_on_timeout(&mywait,100); if (copy_to_user((struct zt_radio_stat *)data,&stack.p,sizeof(struct zt_radio_param))) return -EFAULT; return 0; default: spin_unlock_irqrestore(&rad->lock,flags); return -EINVAL; } spin_unlock_irqrestore(&rad->lock,flags); break; case ZT_RADIO_GETSTAT: spin_lock_irqsave(&rad->lock,flags); /* start with clean object */ memset(&stack.s,0,sizeof(struct zt_radio_stat)); /* if we have rx */ if (rad->gotrx[chan->chanpos - 1]) { stack.s.radstat |= ZT_RADSTAT_RX; if (rad->rxcode[chan->chanpos - 1][0]) stack.s.ctcode_rx = dcstable[rad->rxcode[chan->chanpos - 1][0]].code | 0x8000; else { stack.s.ctcode_rx = cttable_rx[rad->rxcode[chan->chanpos - 1][rad->present_code[chan->chanpos - 1]]].code; stack.s.ctclass = rad->rxclass[chan->chanpos - 1][rad->present_code[chan->chanpos - 1]]; } } /* if we have tx */ if (rad->gottx[chan->chanpos - 1]) { unsigned short x,myindex; stack.s.radstat |= ZT_RADSTAT_TX; stack.s.radstat |= ZT_RADSTAT_TX; myindex = 0; if ((!rad->rxcode[chan->chanpos - 1][0]) && (rad->present_code[chan->chanpos - 1])) myindex = rad->present_code[chan->chanpos - 1]; x = rad->txcode[chan->chanpos - 1][myindex]; if (x & 0x8000) stack.s.ctcode_tx = dcstable[x & 0x7fff].code | 0x8000; else stack.s.ctcode_tx = cttable_tx[x].code; } if (rad->radmode[chan->chanpos - 1] & RADMODE_IGNORECOR) stack.s.radstat |= ZT_RADSTAT_IGNCOR; if (rad->radmode[chan->chanpos - 1] & RADMODE_IGNORECT) stack.s.radstat |= ZT_RADSTAT_IGNCT; if (rad->radmode[chan->chanpos - 1] & RADMODE_NOENCODE) stack.s.radstat |= ZT_RADSTAT_NOENCODE; if (rad->gotcor[chan->chanpos - 1]) stack.s.radstat |= ZT_RADSTAT_RXCOR; if (rad->gotct[chan->chanpos - 1]) stack.s.radstat |= ZT_RADSTAT_RXCT; spin_unlock_irqrestore(&rad->lock,flags); if (copy_to_user((struct zt_radio_stat *)data,&stack.s,sizeof(struct zt_radio_stat))) return -EFAULT; break; default: return -ENOTTY; } return 0; } static int pciradio_open(struct zt_chan *chan) { struct pciradio *rad = chan->pvt; if (rad->dead) return -ENODEV; rad->usecount++; #ifndef LINUX26 MOD_INC_USE_COUNT; #endif return 0; } static int pciradio_watchdog(struct zt_span *span, int event) { printk("PCI RADIO: Restarting DMA\n"); pciradio_restart_dma(span->pvt); return 0; } static int pciradio_close(struct zt_chan *chan) { struct pciradio *rad = chan->pvt; rad->usecount--; #ifndef LINUX26 MOD_DEC_USE_COUNT; #endif /* If we're dead, release us now */ if (!rad->usecount && rad->dead) pciradio_release(rad); return 0; } static int pciradio_hooksig(struct zt_chan *chan, zt_txsig_t txsig) { struct pciradio *rad = chan->pvt; switch(txsig) { case ZT_TXSIG_START: case ZT_TXSIG_OFFHOOK: rad->gottx[chan->chanpos - 1] = 1; break; case ZT_TXSIG_ONHOOK: rad->gottx[chan->chanpos - 1] = 0; break; default: printk("pciradio: Can't set tx state to %d\n", txsig); break; } if (debug) printk("pciradio: Setting Radio hook state to %d on chan %d\n", txsig, chan->chanpos); return 0; } static int pciradio_initialize(struct pciradio *rad) { int x; /* Zapata stuff */ sprintf(rad->span.name, "PCIRADIO/%d", rad->pos); sprintf(rad->span.desc, "Board %d", rad->pos + 1); rad->span.deflaw = ZT_LAW_MULAW; for (x=0;xnchans;x++) { sprintf(rad->chans[x].name, "PCIRADIO/%d/%d", rad->pos, x); rad->chans[x].sigcap = ZT_SIG_SF | ZT_SIG_EM; rad->chans[x].chanpos = x+1; rad->chans[x].pvt = rad; rad->debouncetime[x] = RAD_GOTRX_DEBOUNCE_TIME; rad->ctcssacquiretime[x] = RAD_CTCSS_ACQUIRE_TIME; rad->ctcsstalkofftime[x] = RAD_CTCSS_TALKOFF_TIME; } rad->span.chans = rad->chans; rad->span.channels = rad->nchans; rad->span.hooksig = pciradio_hooksig; rad->span.open = pciradio_open; rad->span.close = pciradio_close; rad->span.flags = ZT_FLAG_RBS; rad->span.ioctl = pciradio_ioctl; rad->span.watchdog = pciradio_watchdog; init_waitqueue_head(&rad->span.maintq); rad->span.pvt = rad; if (zt_register(&rad->span, 0)) { printk("Unable to register span with zaptel\n"); return -1; } return 0; } static void wait_just_a_bit(int foo) { long newjiffies; newjiffies = jiffies + foo; while(jiffies < newjiffies); } static int pciradio_hardware_init(struct pciradio *rad) { unsigned char byte1,byte2; int x; unsigned long endjif; /* Signal Reset */ outb(0x01, rad->ioaddr + RAD_CNTL); /* Reset PCI Interface chip and registers (and serial) */ outb(0x06, rad->ioaddr + RAD_CNTL); /* Setup our proper outputs */ rad->ios = 0xfe; outb(rad->ios, rad->ioaddr + RAD_AUXD); /* Set all to outputs except AUX 3 & 4, which are inputs */ outb(0x67, rad->ioaddr + RAD_AUXC); /* Select alternate function for AUX0 */ outb(0x4, rad->ioaddr + RAD_AUXFUNC); /* Wait 1/4 of a sec */ wait_just_a_bit(HZ/4); /* attempt to load the Xilinx Chip */ /* De-assert CS+Write */ rad->ios |= XCS; outb(rad->ios, rad->ioaddr + RAD_AUXD); /* Assert PGM */ rad->ios &= ~XPGM; outb(rad->ios, rad->ioaddr + RAD_AUXD); /* wait for INIT and DONE to go low */ endjif = jiffies + 10; while (inb(rad->ioaddr + RAD_AUXR) & (XINIT | XDONE) && (jiffies <= endjif)); if (endjif < jiffies) { printk("Timeout waiting for INIT and DONE to go low\n"); return -1; } if (debug) printk("fwload: Init and done gone to low\n"); /* De-assert PGM */ rad->ios |= XPGM; outb(rad->ios, rad->ioaddr + RAD_AUXD); /* wait for INIT to go high (clearing done */ endjif = jiffies + 10; while (!(inb(rad->ioaddr + RAD_AUXR) & XINIT) && (jiffies <= endjif)); if (endjif < jiffies) { printk("Timeout waiting for INIT to go high\n"); return -1; } if (debug) printk("fwload: Init went high (clearing done)\nNow loading...\n"); /* Assert CS+Write */ rad->ios &= ~XCS; outb(rad->ios, rad->ioaddr + RAD_AUXD); for (x = 0; x < sizeof(radfw); x++) { /* write the byte */ outb(radfw[x],rad->ioaddr + RAD_REGBASE); /* if DONE signal, we're done, exit */ if (inb(rad->ioaddr + RAD_AUXR) & XDONE) break; /* if INIT drops, we're screwed, exit */ if (!(inb(rad->ioaddr + RAD_AUXR) & XINIT)) break; } if (debug) printk("fwload: Transferred %d bytes into chip\n",x); /* Wait for FIFO to clear */ endjif = jiffies + 2; while (jiffies < endjif); /* wait */ printk("Transfered %d bytes into chip\n",x); /* De-assert CS+Write */ rad->ios |= XCS; outb(rad->ios, rad->ioaddr + RAD_AUXD); if (debug) printk("fwload: Loading done!\n"); /* Wait for FIFO to clear */ endjif = jiffies + 2; while (jiffies < endjif); /* wait */ if (!(inb(rad->ioaddr + RAD_AUXR) & XINIT)) { printk("Drove Init low!! CRC Error!!!\n"); return -1; } if (!(inb(rad->ioaddr + RAD_AUXR) & XDONE)) { printk("Did not get DONE signal. Short file maybe??\n"); return -1; } wait_just_a_bit(2); /* get the thingy started */ outb(0,rad->ioaddr + RAD_REGBASE); outb(0,rad->ioaddr + RAD_REGBASE); printk("Xilinx Chip successfully loaded, configured and started!!\n"); wait_just_a_bit(HZ/4); /* Back to normal, with automatic DMA wrap around */ outb(0x30 | 0x01, rad->ioaddr + RAD_CNTL); /* Configure serial port for MSB->LSB operation */ outb(0xc1, rad->ioaddr + RAD_SERCTL); /* DEBUG set double dlck to 0 SR */ rad->pasave = 0; __pciradio_setcreg(rad,0xa,rad->pasave); __pciradio_setcreg(rad,0xf,rad->pfsave); __pciradio_setcreg(rad,8,0xff); __pciradio_setcreg(rad,0xe,0xff); __pciradio_setcreg(rad,9,0); rad->pfsave = 0; /* Delay FSC by 0 so it's properly aligned */ outb(/* 1 */ 0, rad->ioaddr + RAD_FSCDELAY); /* Setup DMA Addresses */ outl(rad->writedma, rad->ioaddr + RAD_DMAWS); /* Write start */ outl(rad->writedma + ZT_CHUNKSIZE * 4 - 4, rad->ioaddr + RAD_DMAWI); /* Middle (interrupt) */ outl(rad->writedma + ZT_CHUNKSIZE * 8 - 4, rad->ioaddr + RAD_DMAWE); /* End */ outl(rad->readdma, rad->ioaddr + RAD_DMARS); /* Read start */ outl(rad->readdma + ZT_CHUNKSIZE * 4 - 4, rad->ioaddr + RAD_DMARI); /* Middle (interrupt) */ outl(rad->readdma + ZT_CHUNKSIZE * 8 - 4, rad->ioaddr + RAD_DMARE); /* End */ /* Clear interrupts */ outb(0xff, rad->ioaddr + RAD_INTSTAT); /* Wait 1/4 of a second more */ wait_just_a_bit(HZ/4); for(x = 0; x < rad->nchans; x++) { mx828_command_wait(rad,x, MX828_GEN_RESET, &byte1, &byte2 ); byte1 = 0x3f; byte2 = 0x3f; mx828_command_wait(rad,x, MX828_AUD_CTRL, &byte1, &byte2 ); byte1 = 0; mx828_command_wait(rad,x, MX828_SAUDIO_SETUP, &byte1, &byte2 ); byte1 = 0; mx828_command_wait(rad,x, MX828_SAUDIO_CTRL, &byte1, &byte2 ); byte1 = 0xc8; /* default COR thresh is 2 */ mx828_command_wait(rad,x, MX828_GEN_CTRL, &byte1, &byte2); rad->corthresh[x] = 2; } /* Wait 1/4 of a sec */ wait_just_a_bit(HZ/4); return 0; } static void pciradio_enable_interrupts(struct pciradio *rad) { /* Enable interrupts (we care about all of them) */ outb(0x3f, rad->ioaddr + RAD_MASK0); /* No external interrupts */ outb(0x00, rad->ioaddr + RAD_MASK1); } static void pciradio_restart_dma(struct pciradio *rad) { /* Reset Master and serial */ outb(0x31, rad->ioaddr + RAD_CNTL); outb(0x01, rad->ioaddr + RAD_OPER); } static void pciradio_start_dma(struct pciradio *rad) { /* Reset Master and serial */ outb(0x3f, rad->ioaddr + RAD_CNTL); set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1); outb(0x31, rad->ioaddr + RAD_CNTL); outb(0x01, rad->ioaddr + RAD_OPER); } static void pciradio_stop_dma(struct pciradio *rad) { outb(0x00, rad->ioaddr + RAD_OPER); } static void pciradio_reset_serial(struct pciradio *rad) { /* Reset serial */ outb(0x3f, rad->ioaddr + RAD_CNTL); } static void pciradio_disable_interrupts(struct pciradio *rad) { outb(0x00, rad->ioaddr + RAD_MASK0); outb(0x00, rad->ioaddr + RAD_MASK1); } static int __devinit pciradio_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { int res; struct pciradio *rad; int x; static int initd_ifaces=0; if(initd_ifaces){ memset((void *)ifaces,0,(sizeof(struct pciradio *))*RAD_MAX_IFACES); initd_ifaces=1; } for (x=0;x= RAD_MAX_IFACES) { printk("Too many interfaces\n"); return -EIO; } if (pci_enable_device(pdev)) { res = -EIO; } else { rad = kmalloc(sizeof(struct pciradio), GFP_KERNEL); if (rad) { int i; ifaces[x] = rad; memset(rad, 0, sizeof(struct pciradio)); spin_lock_init(&rad->lock); rad->nchans = 4; rad->ioaddr = pci_resource_start(pdev, 0); rad->dev = pdev; rad->pos = x; for(i = 0; i < rad->nchans; i++) rad->lasttx[x] = rad->gotrx1[i] = -1; /* Keep track of whether we need to free the region */ if (request_region(rad->ioaddr, 0xff, "pciradio")) rad->freeregion = 1; /* Allocate enough memory for two zt chunks, receive and transmit. Each sample uses 32 bits. Allocate an extra set just for control too */ rad->writechunk = pci_alloc_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, &rad->writedma); if (!rad->writechunk) { printk("pciradio: Unable to allocate DMA-able memory\n"); if (rad->freeregion) release_region(rad->ioaddr, 0xff); return -ENOMEM; } rad->readchunk = rad->writechunk + ZT_MAX_CHUNKSIZE * 2; /* in doublewords */ rad->readdma = rad->writedma + ZT_MAX_CHUNKSIZE * 8; /* in bytes */ if (pciradio_initialize(rad)) { printk("pciradio: Unable to intialize\n"); /* Set Reset Low */ x=inb(rad->ioaddr + RAD_CNTL); outb((~0x1)&x, rad->ioaddr + RAD_CNTL); outb(x, rad->ioaddr + RAD_CNTL); __pciradio_setcreg(rad,8,0xff); __pciradio_setcreg(rad,0xe,0xff); /* Free Resources */ free_irq(pdev->irq, rad); if (rad->freeregion) release_region(rad->ioaddr, 0xff); pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)rad->writechunk, rad->writedma); kfree(rad); return -EIO; } /* Enable bus mastering */ pci_set_master(pdev); /* Keep track of which device we are */ pci_set_drvdata(pdev, rad); if (pciradio_hardware_init(rad)) { unsigned char x; /* Set Reset Low */ x=inb(rad->ioaddr + RAD_CNTL); outb((~0x1)&x, rad->ioaddr + RAD_CNTL); outb(x, rad->ioaddr + RAD_CNTL); __pciradio_setcreg(rad,8,0xff); __pciradio_setcreg(rad,0xe,0xff); /* Free Resources */ free_irq(pdev->irq, rad); if (rad->freeregion) release_region(rad->ioaddr, 0xff); pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)rad->writechunk, rad->writedma); pci_set_drvdata(pdev, NULL); zt_unregister(&rad->span); kfree(rad); return -EIO; } if (request_irq(pdev->irq, pciradio_interrupt, ZAP_IRQ_SHARED, "pciradio", rad)) { printk("pciradio: Unable to request IRQ %d\n", pdev->irq); if (rad->freeregion) release_region(rad->ioaddr, 0xff); pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)rad->writechunk, rad->writedma); pci_set_drvdata(pdev, NULL); kfree(rad); return -EIO; } /* Enable interrupts */ pciradio_enable_interrupts(rad); /* Initialize Write/Buffers to all blank data */ memset((void *)rad->writechunk,0,ZT_MAX_CHUNKSIZE * 2 * 2 * 4); /* Start DMA */ pciradio_start_dma(rad); printk("Found a PCI Radio Card\n"); res = 0; } else res = -ENOMEM; } return res; } static void pciradio_release(struct pciradio *rad) { zt_unregister(&rad->span); if (rad->freeregion) release_region(rad->ioaddr, 0xff); kfree(rad); printk("Freed a PCI RADIO card\n"); } static void __devexit pciradio_remove_one(struct pci_dev *pdev) { struct pciradio *rad = pci_get_drvdata(pdev); if (rad) { /* Stop any DMA */ pciradio_stop_dma(rad); pciradio_reset_serial(rad); /* In case hardware is still there */ pciradio_disable_interrupts(rad); /* Immediately free resources */ pci_free_consistent(pdev, ZT_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)rad->writechunk, rad->writedma); free_irq(pdev->irq, rad); /* Reset PCI chip and registers */ outb(0x3e, rad->ioaddr + RAD_CNTL); /* Clear Reset Line */ outb(0x3f, rad->ioaddr + RAD_CNTL); __pciradio_setcreg(rad,8,0xff); __pciradio_setcreg(rad,0xe,0xff); /* Release span, possibly delayed */ if (!rad->usecount) pciradio_release(rad); else rad->dead = 1; } } static struct pci_device_id pciradio_pci_tbl[] = { { 0xe159, 0x0001, 0xe16b, PCI_ANY_ID, 0, 0, (unsigned long)"PCIRADIO" }, { 0 } }; MODULE_DEVICE_TABLE(pci, pciradio_pci_tbl); static struct pci_driver pciradio_driver = { name: "pciradio", probe: pciradio_init_one, #ifdef LINUX26 remove: __devexit_p(pciradio_remove_one), #else remove: pciradio_remove_one, #endif suspend: NULL, resume: NULL, id_table: pciradio_pci_tbl, }; static int __init pciradio_init(void) { int res; res = zap_pci_module(&pciradio_driver); if (res) return -ENODEV; return 0; } static void __exit pciradio_cleanup(void) { pci_unregister_driver(&pciradio_driver); } #ifdef LINUX26 module_param(debug, int, 0600); #else MODULE_PARM(debug, "i"); #endif MODULE_DESCRIPTION("Zapata Telephony PCI Radio Card Zaptel Driver"); MODULE_AUTHOR("Jim Dixon "); #ifdef MODULE_LICENSE MODULE_LICENSE("GPL"); #endif module_init(pciradio_init); module_exit(pciradio_cleanup); zaptel-1.4.11/kernel/tormenta2.rbt0000644000000000000000000214653310751714440015520 0ustar rootrootXilinx ASCII Bitstream Created by Bitstream F.23 Design name: tormenta2.ncd Architecture: spartan2 Part: 2s50pq208 Date: Thu Oct 10 09:00:52 2002 Bits: 559200 11111111111111111111111111111111 10101010100110010101010101100110 00110000000000001000000000000001 00000000000000000000000000000111 00110000000000010110000000000001 00000000000000000000000000001011 00110000000000010010000000000001 00000000100000000011111100101101 00110000000000001100000000000001 00000000000000000000000000000000 00110000000000001000000000000001 00000000000000000000000000001001 00110000000000000010000000000001 00000000000000000000000000000000 00110000000000001000000000000001 00000000000000000000000000000001 00110000000000000100000000000000 01010000000000000011111000000100 00000000000100100011000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000100 10000000000000000000000000000000 00000000000000000000000000000000 00000000000100100011000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000010000000000100 10000000000000000000000000000000 00000000000000000000000000000000 00000000000000100000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 10000000000000000000000000000000 00000000000000000000000000000000 00000000000000100000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 10000000000000000000000000000000 00000000000000000000000000000000 00000000000100100000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000100 10000000000000000000000000000000 00000000000000000000000000000000 00000000000100100000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000100 10000000000000000000000000000000 00000000000000000000000000000000 00000000000100100000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000010000000000100 00000000000000000000000000000000 00000000000000000000000000000000 11111111000100100000000000000000 00000000000000011000000000000000 01000000000000000001100000000000 00000100000000000000000010000000 00000000011000000000000000011000 00000000000010100000000000000010 10000000000000000010000000000000 00101000000000000000001000000000 00000000000000000000000000100000 00000000000010000001111111000100 00000000000000000000000000000000 00000000000000000000000000000000 11000000000001011111101000000000 11111111100000000011111100000000 10001111111110000000001111111110 00000000111111111000000000111111 11100000000011111111100000000011 11111110000000001111111110000000 00111111111000000000111111110000 00000011011111100000000011111111 10000000001111111110000000001111 11111000000000111111000000000000 01110000000000000000000000000000 00000000000000000000000000000000 10000000000100001110001000000000 10111011100000000010111000110100 00001011101110000000001011101110 00000000101110111000000000101110 11100000000010111011100000000010 11101110000000001011101110000000 00101110111000000000101110111000 00000010101011100000000010111011 10000000001011101110000000001011 10111000000000101110000000000100 00110000000000000000000000000000 00000000000000000000000000000000 10001000000001011100100000000000 10100011000000000010110010000000 00001011001100000010011010001100 00000000101100110000000000101000 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010010011000000000010110011 00000000001011001100000000001011 00110000000001101110001000000001 01110000000000000000000000000000 00000000000000000000000000000000 11000000000101011010000000000000 10111011000000000010111011000010 00001011101100000000001011101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000001011101100000000 00101110110000000000101110110010 10000010111011000000000010111011 00000000001011101100000000011011 10110000000000101111000000000100 01100000000000000000000000000000 00000000000000000000000000000000 00000000000101011110110100000000 11111011000000000011111000010000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110111100 00000011011011000000000011111011 00000000001111101100000000001111 10110000010000111100100000000100 01110000000000000000000000000000 00000000000000000000000000000000 11100000000000011011000001000000 11111111000000000011111010100100 00001111111100000000000111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111110111000 00000011101111000000000011111111 00000000001111111100000000001111 11110000000000111111100000000000 01100000000000000000000000000000 00000000000000000000000000000000 01000000000100001010110000000000 11111011000000010011111000010000 00101100101100000000001111101100 00000000111110110000000000110110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111100110000 00000011101011000000000011111011 00000000001111101100000000001111 10110000000000111101000000000100 00100000000000000000000000000000 00000000000000000000000000000000 11001000000001010010000000000000 10111011000101100010111010000000 00001000101100000000001011101100 00000000101110110000000000100110 11000000000010111011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010001011000000000010111011 00000000001011101100000000001011 10111000100000101111001000000000 01000000000000000000000000000000 00000000000000000000000000000000 11100000000001010100010000000000 10110011000000000010110001000000 00001000001100000000001001001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100000000 00000010100011000000000010110011 00000000001011001100000000001011 00111110000000101111000000000000 01010000000000000000000000000000 00000000000000000000000000000000 01100000000000010001001000000000 10110111100000000010110100100000 00001000011110000100001011011110 00000000101101111000000000101101 11100000000010110111100000000010 11011110000000001011011110000000 00101101111000000000101101001000 00000010000111100000000010110111 10000000001011011110000000001011 01111000000000101101100000000000 01000000000000000000000000000000 00000000000000000000000000000000 01001000000010000000110001000000 11110011000000000011110011000000 00001100001100010010001111001100 00000000111100110000000000111100 11000000000011110011000000000011 11001100000000001111001100000000 00111100110000000000111100000000 00000011100011000000000011110011 00000000001111001100000000001111 00110000000000111101101000000010 00000000000000000000000000000000 00000000000000000000000000000000 01000000000111011011000000010000 11111111000000000011111111000100 00001111111100000000001111111100 00001000111111110000000000110111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111000000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111101000000000110 01100000000000000000000000000000 00000000000000000000000000000000 10101000000011011110010000010000 11111011000000000011111001000000 00001100101100000000001111101100 00001000111110110000000001111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111100000000 00000011001011000000000011111011 00000000001111101100000000001111 10110000000000111110101000000000 01110000000000000000000000000000 00000000000000000000000000000000 01001000000000011001000000000000 10110111000000000010110001000000 00001000011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101000000 00000010000111000000000010110111 00000000001011011100000000001011 01110000000000101101001000000100 01100000000000000000000000000000 00000000000000000000000000000000 11000001000000001001111000000000 10110111100000000010110111100000 00011000011110000001001011011110 00000001101101111000000100101001 11100000000010110111100000000010 11011110000000001011011110000000 00101101111000000000101111000000 00000010000111100000000010110111 10000000001011011110000000001011 01111000000000101111000000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000100101001100000000000000 10110011000000000010110011000000 00011000001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100000000 00000010000011000000000010110011 00000000001011001100000000001011 00110000000000101101001100000100 00110000000000000000000000000000 00000000000000000000000000000000 11101000000101011011100000000000 11111010000000000011111110011100 00101100101000000000001111101000 00000000111110100000000000111110 10000000000011111010000000000011 11101000000000001111101000000000 00111110100000000000111111100000 00000011001010000000000011111010 00000000001111101000000000001111 00100000000000111111101000000100 01100000000000000000000000000000 00000000000000000000000000000000 01001000000000001110000010000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000100000000111101001000000000 00110000000000000000000000000000 00000000000000000000000000000000 00001000000100001110010000000000 11111001100000000011110001000000 00001101100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000110000001000000100 00110000000000000000000000000000 00000000000000000000000000000000 10000000000001000110010000000000 10111001000100000010111001000000 00001000100100000000001011100100 00000000101110010000000000101110 01000000000010111001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10011000000010100010000000000000 00010000000000000000000000000000 00000000000000000000000000000000 00011000000001010010110000000000 10111001000000000010111001000000 00001000100100000000001011100100 00000000101110010000000000101110 01000000000010111001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010010100000100000011000000000 01000000000000000000000000000000 00000000000000000000000000000000 00001000000001000000010000000000 10110001100000000010110001001000 00101000000100000000001011000100 00000000100100010000000001101100 01000000000010110001000000000010 11000100000000001011000100000000 00101100010000000000100100010010 10000010110001000000000010110001 00000000001011000100000000001011 00010000000000100000001000000001 00000000000000000000000000000000 00000000000000000000000000000000 10111000000001010110000000000000 11111000000000000011111000000000 00001100100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000010 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000110010111000000011 01010000000000000000000000000000 00000000000000000000000000000000 10011000000101011111010000000000 11111001000001000011111101000100 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111111010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111110011000000110 01110000000000000000000000000000 00000000000000000000000000000000 10011000000001011110010000000000 11001001000000000011111001000000 00001100100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011001001000000000011111001 00000000001111100100000000001111 01010000000000111110011000000000 01110000000000000000000000000000 00000000000000000000000000000000 00111000000100001110000000000000 10001000000000000010111000000000 00001000100000000000001011100000 00000000101110000000000000101110 00000000000010111000000000000010 11100000000000001011100000000000 00101110000000000000101110000000 00000010101000000000000010111000 00000000001011100000000000001011 10000000000000101100111000000100 00110000000000000000000000000000 00000000000000000000000000000000 00001000000001011110010000000000 10000001000000000010100001000000 00001000000100000000001011000100 00000000101100010000000000101100 01000000000010110001000000000010 10000100000000001011000100000000 00101100010000000000101110010000 00000010000001000000000010110001 00000000001011000100000000001011 00010000000001101100001000000001 01110000000000000000000000000000 00000000000000000000000000000000 00011000000101011010010000000000 10001001000000000010111001001010 00001000100100000000001011100100 00000000101110010000000000101110 01000000000010111001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010101001000000000010111001 00000000001011100100000000001011 10010000000000101100011000000100 01100000000000000000000000000000 00000000000000000000000000000000 10100000000101011100010001000010 11001001000000010011111001000000 00101100100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111100010000 00000011001001000000000011111001 00000000001111100100000000001111 10010000000000111110100000000100 00100000000000000000000000000000 00000000000000000000000000000000 00101000000000011010011000000000 11111011000000010011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111100101000000000 00100000000000000000000000000000 00000000000000000000000000000000 00101000000100001010000000000000 11001000000000000011110000000000 00001100100000000000001111100000 00000000111110000000000000110110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000100000110000101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00100000000001010010100000000000 10001010000000000010111010000000 00001000101000000000001011101000 00000000101110100000000000100110 10000000000010111010000000000010 11101000000000001011101000000000 00101110100000000000101110100000 00000010111010000000000010111010 00000000001011101000000000001011 11100000000000100000101000000000 00000000000000000000000000000000 00000000000000000000000000000000 00101000000001010100110000000010 10000010000001000010110011000000 00001000001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000100100101000000000 01010000000000000000000000000000 00000000000000000000000000000000 10100000000000010011110000000000 10000111010000000010110111000000 00001000011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01111000000000100100100000000000 01000000000000000000000000000000 00000000000000000000000000000000 10101000000010000001111000000000 11000100100000010011110011100000 00101100011110000000001111011110 00000000111101111000000000111101 11100000000011110111100000000011 11011110000000001111011110000000 00111101111000000000111101111000 00000011110111100000000011110111 10000000001111011110000000001111 01101000000000110100101000000010 00000000000000000000000000000000 00000000000000000000000000000000 00001000000111011000110000000000 11111000011000000011111011000000 00001111101100000000001111101100 00000000111110110000000000110110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000010001111 10000000000010111000001000000110 01100000000000000000000000000000 00000000000000000000000000000000 11000000000001011111111000000000 11111110110000100011001111100000 00001100111110000000001101111110 00000000111111111000000000111111 11100000000011111111100000000011 11111110000000001111111110000000 00111111111000000000111111111000 00000011001111100000000011111111 10000000001111111110000000001111 11111000000000111101000000000000 01110000000000000000000000000000 00000000000000000000000000000000 10101000000100011001110000100000 10110111000000000011010111000000 00001000011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000011110111000000000010110111 00000000001011011100000000001011 01100010000000101110101000000100 01100000000000000000000000000000 00000000000000000000000000000000 00010000000000001001110000000000 10110110000000000010000111000000 00001000011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010000111000000000010110111 00000000001011011100000000001011 01110000000000101100010000000000 00100000000000000000000000000000 00000000000000000000000000000000 01100000000101001100110000000000 10110010000000000010010011000000 00001000001100000000001011001100 00000000101100110000000000100100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00000000000001101101100100000100 00110000000000000000000000000000 00000000000000000000000000000000 11111000000101011010110100000000 11111011000000000011001011000010 00101100101100000000001101101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011001011000000000011111011 00000000001111101100000000001111 10010000000000111110101000000100 01100000000000000000000000000000 00000000000000000000000000000000 10000100000000001110110000000000 11111011000000010011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111100110000 00000011111011000000000011111011 00000010001111101100000000001111 10010000000000111110010000000000 00110000000000000000000000000000 00000000000000000000000000000000 10000000000100001111110000100000 11111101100000010011111011000010 00001111111100000000001110111100 00000000111111110000000000111111 11000000000010111111000000000011 11111100000000001111111100000000 00111111110000000000111110110000 00000011001111000000000011111111 00000000001111111100000000001111 11101000000000111110000001000100 00110000000000000000000000000000 00000000000000000000000000000000 10000001000001000110110000000100 10111000110110000010111011000000 00001001101100000000001011101100 00000000101110110000000000101110 11000000000010011011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010101011000000000010111011 00000000001011101100000000001011 10000000000000101110000101100000 00010000000000000000000000000000 00000000000000000000000000000000 10000000000001010010110000000000 10111001000000000010111011000000 00001011101100000000001001101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010001011000000000010111011 00000000001011101100000001001011 10010010000100101110000000000000 01010000000000000000000000000000 00000000000000000000000000000000 00001000000001000000110000000000 10110001000000000010110011000000 00001001001100000000001011001100 00000000101100110000000000101100 11000000000110010011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010100011000000000010110011 00000000001011001100000000001011 00000000000000101100001000000000 00000000000000000000000000000000 00000000000000000000000000000000 10000000000011010110110000000000 11111001000000000011111011000000 00001111101100000000001110101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011001011000000000011111011 00000000001111101100000000001111 10110000000000111110000000000010 00010000000000000000000000000000 00000000000000000000000000000000 10100000000111011111110000000000 11110100000001000011111111000000 00001101111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11000000000000111110100000000110 01110000000000000000000000000000 00000000000000000000000000000000 11000000000001011111111000000000 11111111000000000011111111100000 00001111111110000000001111111110 00000000111111111000000000111111 11100000000011111111100000000011 11111110000000001111110010000000 00111111111000000000111111111000 00000011111111100000000011111111 10000000001111111110000000001111 11001000000000110111000000000000 01110000000000000000000000000000 00000000000000000000000000000000 10000000000100001110111000000000 10111011110100010010111011100000 00001011101110000000001110101110 00000000101110111000000000101110 11100000000010111011100000000010 11101110000000001011100010000000 00101110111000000000101110111000 00000010111011100000000010111011 10000000001011101110000000001011 10001000000000100010000000000100 00110000000000000000000000000000 00000000000000000000000000000000 10001000000001011100110000000000 10100011000001000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011000000000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00000000000001100110001000000001 01110000000000000000000000000000 00000000000000000000000000000000 11000000000101011010110000010000 10111011000000000010111011000000 00001011101100000000001010101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000011011100000001000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000011011 10110000000000100111000000000100 01100000000000000000000000000000 00000000000000000000000000000000 01000000000101011110110000000000 11111111000000100011111011000000 00001111101100000000001011101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000010111011 00000000001111101100000000001011 10011001000000110101000000000100 01110000000000000000000000000000 00000000000000000000000000000000 11100000000000011011110000000000 11111111000000000000111111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000100001111111100100000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11000000000000111011100000000000 01100000000000000000000000000000 00000000000000000000000000000000 01000000000100001010110000000000 11111011001000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111100101000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10010000000000111101000000000100 00100000000000000000000000000000 00000000000000000000000000000000 11001000000001010010110000000000 10111111100000000010111011000000 00001011101100000000001011101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000001011100100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 00110000000000101111001000000000 01000000000000000000000000000000 00000000000000000000000000000000 11100000000001010100110000000000 10110011010000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011000000000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00100010000000101111100100000000 01010000000000000000000000000000 00000000000000000000000000000000 00100000000000010001111000000000 10110111100000000010110111100000 00001011011110000000001011011110 00000000101101111000000000101101 11100000000010110111100000000010 11011110000000001011010010000000 00101101111000000000101101111000 00000010110111100000000010110111 10000000001011011110000000001011 01001000000000101100100000000000 01000000000000000000000000000000 00000000000000000000000000000000 01001000000010000000110001000000 11110011000010000011110011000000 00001111001100000000001111001100 00000000111100110000000000111100 11000000000011110011000000000011 11001100000000001111001100000000 00111100110000000000111100110001 00000011110011000000000011110011 00000000001111001100000000001111 00100000000000111101001000000010 00000000000000000000000000000000 00000000000000000000000000000000 01000000000111011011110000010000 11111111000000100011111111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111101000000 00111111110000000000111111110000 01000011111111000000000011111111 00000000001111111100000000001111 11110000000000111101000000000110 01100000000000000000000000000000 00000000000000000000000000000000 10101000000001011110110000000000 11111111100000000011001011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101000000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10111000000000110010101000000000 01110000000000000000000000000000 00000000000000000000000000000000 01001000000100011001110000000000 10110111100000000011010111000000 00001110011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011000000000 00101101110000000000101101110000 00010010110111000000000010110111 00000000001011011100000000001011 01000000000000110101001000000100 01100000000000000000000000000000 00000000000000000000000000000000 11000000000000001001111000000000 10110011100000000010100111100000 00011011011110000000001011011110 00000000101101111000000000101101 11100000000010110111100000000010 11011110000000001011011110000000 01101101111000000000101101111000 00000010110111100000000010110111 10000000001011011110000000001011 01111000000001100011000000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000101001100110000000000 10110011000000000010110011000000 00001010001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100110000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110010000000100101001000000100 00110000000000000000000000000000 00000000000000000000000000000000 11101000000101011010100000000000 11111010000000000011101010000000 00001111101000000000001111101000 00000000111110100000000000111110 10000000000011111010000000000011 11101000000000001111101010000000 00111110100000010001111110100000 00000011111010000000000011111010 00000000001111101000000000001111 11100000000000110011101000000100 01100000000000000000000000000000 00000000000000000000000000000000 01001000000000001110000000000000 11111000000000000011011000000000 00001110100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000100000000111101001000000000 00110000000000000000000000000000 00000000000000000000000000000000 00001000000100001110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111101100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111100001000000100 00110000000000000000000000000000 00000000000000000000000000000000 10000000000001000110010000000000 10111001000000000010111001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000000010111001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10011100000000101110000000000000 00010000000000000000000000000000 00000000000000000000000000000000 00011000000001010010010000000000 10111001100000000010111001000000 00001011100100000000001011100100 00000000101010010000000000101110 01000000000010111001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010101000000101100011000000000 01000000000000000000000000000000 00000000000000000000000000000000 00001000000001000000010000000000 10110001101010000010110001000000 00001011000100000000001011000100 00000000101100010000000000101100 01000000000010110001000000000010 11000100000000001011000100000000 00101100010000000000101100010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101100001000000001 00000000000000000000000000000000 00000000000000000000000000000000 10111000000011010110000000000000 11111000001000000011111000000000 00001111100000000000001111100000 00000000111010000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111110111000000011 01010000000000000000000000000000 00000000000000000000000000000000 10011000000011011110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111101100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 01010000000000111110011000000110 01110000000000000000000000000000 00000000000000000000000000000000 00011000000001011110010000000000 11111101100000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 11010000000000111100011000000000 01110000000000000000000000000000 00000000000000000000000000000000 00111000000100001110000000000000 10111000010100000010111000000000 00001110100000000000001011100000 00000000101110000000000000101110 00000000000010111000000000000010 11100000000000001011100000000000 00101110000000000000101110000000 00000010111000000000000010111000 00000000001011100000000000001011 10100000000000101100111000000100 00110000000000000000000000000000 00000000000000000000000000000000 00001000000001011100010000000000 10110001000000000010110001000000 00001011000100000000001011000100 00000000101100010000000000101100 01000000000010110001000000000010 11000100000000001011000100000000 00101100010000000000101100010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101100001000000001 01110000000000000000000000000000 00000000000000000000000000000000 00011000000101011010010000000000 10111001000000000000111001000000 00001010100100000000001011100100 00000000101110010000000000101110 01000000000010111001000000000010 11100100000000011011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000011011 10010000010000101100011000000100 01100000000000000000000000000000 00000000000000000000000000000000 10100000000101010110010000000000 11111001000000000010111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100110010000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10011000000000111110100000000100 01110000000000000000000000000000 00000000000000000000000000000000 00101000000000011010010000000100 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100110000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10011001000000111100101000000000 01100000000000000000000000000000 00000000000000000000000000000000 00101000000100001010000000000000 11111000000000000011001000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000100000000111100101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00101000000001010010100000000000 10111110100001000010001010000000 00001011101000000000001011101000 00000000101110100000000000101110 10000000000010111010000000000010 11101000000000001011101000000000 00101110100000000000101110100000 00000010111010000000000010111010 00000000001011101000000000001011 11100000100000101100101000000000 01000000000000000000000000000000 00000000000000000000000000000000 00101000000001010100110000000000 10110000000000001010100011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00111000000000101100001000000000 01010000000000000000000000000000 00000000000000000000000000000000 10100000000000010001110000000000 10110100110000000010100111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01100000000000101110000000000000 01000000000000000000000000000000 00000000000000000000000000000000 10101000000010000001111000001000 11110100100000000011100111100000 00001111011110000000001111011110 00000000111101111000000000111101 11100000000011110111100000000011 11011110000000001111011110000000 00111101111000000000111101111000 00000011110111100000000011110111 10000000001111011110000000001111 01011000000000111110101000000010 00000000000000000000000000000000 00000000000000000000000000000000 00001000010011011010110000000000 11110000000000100011011011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10000000000000111100001000000110 01100000000000000000000000000000 00000000000000000000000000000000 00000000000001011111111000000000 11111110100000000011001111100100 00001111111110000000001111111110 00000000111111111000000000111111 11100000000011111111100000000011 11111110000000001111011110000000 00110011111000000000111111111000 00000011111111100000000011111111 10000000001111111110000000001111 11111001000000110000000000000000 01110000000000000000000000000000 00000000000000000000000000000000 10101000000100011001110000000000 10110110000000000010000111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101001110000000000101101110000 00000010110111000000000010110111 00000000001011011100000100001011 01100000000010100010101000000100 01100000000000000000000000000000 00000000000000000000000000000000 00000000000000001001110000000000 10110110000000000010000111000000 00011011011100000000001011011100 00000000101001110000000000101101 11000000000010110111000000000010 11011100000000001011111100000000 00100001110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 11110000100001100000000000000000 00100000000000000000000000000000 00000000000000000000000000000000 00100000000101001100110000000000 10110000000000000010000011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101000110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00101100000000100000100000000100 00110000000000000000000000000000 00000000000000000000000000000000 10101000000101011010110000000000 11111001000000001011001011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00110010110000000000111110110000 00000011111011000000000010111011 00000000001111101100000000001011 00110000000000110010101100000100 01100000000000000000000000000000 00000000000000000000000000000000 10000000000000001110110000000000 11111000010000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111110000000000000 00110000000000000000000000000000 00000000000000000000000000000000 00000001000100001111110000000000 11110101000000000011001111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11000100100000110000000001000100 00110000000000000000000000000000 00000000000000000000000000000000 10000001000001000110110000000000 10111001000000000010001011000000 00001011101100000000001011101100 00000000101110110000000000101110 11000000000010011011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10001000000000101010000001000000 00010000000000000000000000000000 00000000000000000000000000000000 10000000000001010010110000000000 10111011000010000010001011000000 00001011101100000000001011101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10010100000000100010000000000000 01000000000000000000000000000000 00000000000000000000000000000000 00001000000001000000110000000000 10110010000000000010000011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010010011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 10010000000000101000001000000001 00000000000000000000000000000000 00000000000000000000000000000000 00000000000011010110110000000000 11111011000000000011001011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10000000000000110000100000000011 01010000000000000000000000000000 00000000000000000000000000000000 10100000000111011111110000000100 11110101000000000011111111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011011111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 01000000000000111110000000000110 01110000000000000000000000000000 00000000000000000000000000000000 11000000000001011111101000000000 11111100100000000011111111100000 00001101111110010000001101111110 01001000110011111000000000110111 00000000000011111111100000000011 11111100000000001101111110000000 00111111111000000000111111111000 00000011111111100000000011111111 10000000001111111110000000001111 11111000000000111111000000000100 01110000000000000000000000000000 00000000000000000000000000000000 11000000000100001110011000000000 10111000100000000010111011100000 00001011101100000000001000001100 00001000100010111000000000101110 10110000000010111011100000000010 11111110000000001010101110000000 00101110111000000000101110111000 00000010111011100000000010111011 10000000001011101110000000001011 10111000000000101111000000000100 00110000000000000000000000000000 00000000000000000000000000000000 11001000000001011100100000000000 10110001000000000010110011000000 00001011001100100001001001001100 10000011100000110000000000101100 00010000000010110011000000000010 11001100000000001001001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101111001000000001 01110000000000000000000000000000 00000000000000000000000000000000 11000000000100011010010100000000 10111011000000000010111011000000 00001011001100000000001000001100 00000000100010110000001000001110 11000110000010111011000000000010 11101100000000000010101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101111000000000000 01100000000000000000000000000000 00000000000000000000000000000000 11000000000101011110110000000000 11111010010000000011111011000000 01001101101100000001001101101100 00000000110010110000000000111110 01100000000010111011000000000011 11101100000000001101101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111101010000000000 01110000000000000000000000000000 00000000000000000000000000000000 11100000000000011011011100000000 11111110000000000011111111000000 00000011111100000000001111111100 00000000111111110000010000001110 11100000000011111111000000000011 11101100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111111100000000000 01100000000000000000000000000000 00000000000000000000000000000000 01000100000100001010110100000000 11101001010000000011111011000000 00001101101100001000001111101100 11000000110010110000000000111110 00010000000011001011000000000011 11001100000100001110101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111101010000000000 00100000000000000000000000000000 00000000000000000000000000000000 11011000000001010010010000000001 10001011000000000010111011000000 00001001101111000000001011101111 00000000110110110000000000101110 11000000000011011011000000000010 11111100000000001000101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101111001000000100 01000000000000000000000000000000 00000000000000000000000000000000 11100000000001010100000000010000 10100001000000000010110011000000 00001011001100000000001011001100 00000000100100110000000000101100 00000000010010000011000000000000 11001100000000001010001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101111000000000000 00010000000000000000000000000000 00000000000000000000000000000000 10110000100000010011001000001000 10000100100000000110110111100001 00001011011110000000001011011110 00000000100101111000010000101101 00100000000010010111100000000010 11011110000000001010011110000000 00101101111000000000101101111000 00000010110111100000000010110111 10000000001011011110000000001011 01111000000000101110110000000100 00010000000000000000000000000000 00000000000000000000000000000000 01001000000010000000000000000000 10100001000000000011110011000000 00001111001100001000001111001100 00000000110100110001000000111100 10000000000011000011000000000011 11001100000000001110001100000000 00111100110000000000111100110000 00000011110011000000000011110011 00000000001111001100000000001111 00110001000000111101001000000010 00010000000000000000000000000000 00000000000000000000000000000000 01000000000111011001000001000000 11111110000100000011111111000000 00001101111100000000001111111100 00000000111111110000000000111111 10000000000011111111000000000011 11111100000000001101111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111101000000000000 01100000000000000000000000000000 00000000000000000000000000000000 10101000000001011110100000010000 11111011001010000001111011000000 00001111101100000001101100101110 00000000110010110000000000111110 01000000000011001011000000000011 11101100110000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111100001000000000 01110000000000000000000000000000 00000000000000000000000000000000 11001000100100011001000000000000 00110110000000000010110111000000 00001011011100000000001000111100 00000000101001110000000000101100 11000000000010100111000000000010 11011100010000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101111001000000110 01100000000000000000000000000000 00000000000000000000000000000000 10000000000000001001101000000000 10110101110000000010110111100000 00001011011110000000001000011110 00000000100001111000000000101101 01100000000010000111100000000010 11011110100000001011011110000000 00101101111000000000101101111000 00000010110111100000000010110111 10000000001011011110000000001011 01111000000000101100100000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000101001100001110000000 10110010100000010110110011000000 00001011101100000000001000001100 00000000101000110000000000101100 11111000000010100011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101101101000000000 00110000000000000000000000000000 00000000000000000000000000000000 11100000000101011011100000100000 11110010000000000011111010000000 00001111101000000000001100101000 00000000110010100000000000111111 10110000000011001010000000000011 11101000000000001111101000000000 00111110100000000000111110100000 00000011111010000000000011111010 00000000001111101000000000001111 10100000000000111111101100000100 01110000000000000000000000000000 00000000000000000000000000000000 01001000000000001110000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000111100 00000100000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111101001000000000 01100000000000000000000000000000 00000000000000000000000000000000 00001000000100001110010000000100 11111011000000100011001001000000 00001111100110000000001110100110 00000000111110010000000000111110 01000000000011001001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111100001000000100 00100000000000000000000000000000 00000000000000000000000000000000 10000000000001000110010000000000 10111001000000000010101001000000 00001011100100000000001000100110 00000000101110010000000000101110 01000000000010001001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000100101110000000000000 00010000000000000000000000000000 00000000000000000000000000000000 00011000000001010010010000000000 10111011000000000010001001000000 00001011100100100000001010100100 10000000101110010000000000101110 01000000000010001001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101100111000000000 01000000000000000000000000000000 00000000000000000000000000000000 00001000000001000000010000000000 10111001000000000010100001000000 00001011000100000000001000000100 00000000101100010000000000101100 01001000000010000001000000100010 11000100101000001011000100000000 00101100010000000000101100010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101100101000000101 00000000000000000000000000000000 00000000000000000000000000000000 10111000000011010110000000000000 11111000000000000011001000000000 00001111001001010000001110101001 01000000111110000000000000111110 00000000001011001000000000000011 11100000100000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111110111000000011 01010000000000000000000000000000 00000000000000000000000000000000 10011000000111011111010000000000 11111001000000000010111001000000 00001111100100000000001111100100 00000000111110010000000000111111 01000100000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111110011000000100 01110000000000000000000000000000 00000000000000000000000000000000 00011000000001011100010000000000 11111001000000000011111001000000 00001111110100000000001100110100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111100011000000000 01110000000000000000000000000000 00000000000000000000000000000000 01111000000100001110000000000000 10111000000000100010111000000000 00001011100000000000001101100000 00000000101110000000000000101110 00000000000010111000000000000010 11100000000000001011100000000000 00101110000000000000101110000000 00000010111000000000000010111000 00000000001011100000000000001011 10000000000000101100111000000110 00110000000000000000000000000000 00000000000000000000000000000000 01001000000001011100010000000000 10110001000000000110110001000000 00001011000100000000001000000100 00000000101100010000000000101100 01000000000010110001000000000010 11000100000000001011000100000000 00101100010000000000101100010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101101001000000000 00100000000000000000000000000000 00000000000000000000000000000000 00011000000101011010010000000000 10111001000110000110111001000000 00001011100100000000001001100100 00000000101110010000000000101110 01000000000010111001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101100011000000000 00100000000000000000000000000000 00000000000000000000000000000000 10100000000101011110010000000000 11111001100000000011111001000000 00001111100100000000001100100100 00000000111110010000000000111110 01101100000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111110100000000100 01110000000000000000000000000000 00000000000000000000000000000000 01101000000000011010010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000010000111110 01100000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111101001000000000 01100000000000000000000000000000 00000000000000000000000000000000 00101000000100001010000000000000 11101000010000000011111000000000 00001111100000000000001111100000 00000000110010000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111100001000000100 00100000000000000000000000000000 00000000000000000000000000000000 00101000000001010010100000000000 10001010000000000010111010000000 00001011111011000000001011111001 00000000100010100000000000101110 10000000000010111010000000000010 11101000000000001011101000000000 00101110100000000000101110100000 00000010111010000000000010111010 00000000001011101000000000001011 10100000000000101100101000000000 01000000000000000000000000000000 00000000000000000000000000000000 00101000000001010100110000000000 10100011000000000010110011000000 00001011101111001000001011001111 00100000100000110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101100101100000000 01010000000000000000000000000000 00000000000000000000000000000000 10100000000000010011111000000000 10000111000000000010110111000000 00001011011100001000001001011011 00000000100001110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101110000000000100 01000000000000000000000000000000 00000000000000000000000000000000 10101000000010000001111000000000 11100111100000000011110111100000 00001111011110000000001111111110 00000010110001111000000000111101 11100000000011110111100000000011 11011110000000001111011110000000 00111101111000000000111101111000 00000011110111100000000011110111 10000000001111011110000000001111 01111000011000111110001000000010 00000000000000000000000000000000 00000000000000000000000000000000 00001000000111011010110000000000 11111011000000100011111011000000 00001111101100000000001111100100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111100001000000100 01100000000000000000000000000000 00000000000000000000000000000000 00000000000001011111111000000000 11111111100000100101111111100100 00001111110110010000001100110110 00000000110011111000000000111111 11100000000011111111100000000011 11111110000000001110111110000000 00111111111000000000111111111000 00000011011111100000000011111111 10000000001111111110000000001111 11111000000000111100000000000100 00100000000000000000000000000000 00000000000000000000000000000000 10101000000100011001110000000000 10110111000000000110110111000000 00001011110000000000001101010000 00000000101001110000000000111101 11000000000010110111000000000010 11011100000000001000011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110001000000101110101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00000000000000001001110000000000 10110111000000000010110111000000 01001011010100000010001000011100 00000000100001110000000000101101 11000000000010110111000000000010 11011100000000001010011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101100000000000000 00100000000000000000000000000000 00000000000000000000000000000000 00100000000101001100110010000000 10110011010100000010110011000000 00001011100100000000001000100000 00000000101000110000000000101000 11100100000010110011000000000010 11001100000000001000001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101100100000000100 00100000000000000000000000000000 00000000000000000000000000000000 10101000000101011010111110000000 11111011010000000011111011000000 00001111101000000010101000101100 00000000110010110000000000101110 11010100000011111011000000000011 11101100000000001110101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000001000111 10110000001100101110101100000100 01100000000000000000000000000000 00000000000000000000000000000000 10000000000000001110110000000000 11111011001000000011111011000000 00001111100000000000001111101001 00000000111110110000000000111110 11000000000011111011000000000011 11001100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111110000000000000 00110000000000000000000000000000 00000000000000000000000000000000 00000001000100001111110000000000 11111111000000000011111111000000 00001111111010000000001100111000 00000000110011110000000000111101 11000000000011001111000000000011 11101100000000001100111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000000011 11110000000000111100100001000100 00110000000000000000000000000000 00000000000000000000000000000000 10000000000001000110110000000000 10111011000001000010111011000000 00001011101011010000001010101011 00100000110110110000000000101110 11000000000010101011000000000010 11101100000000001010101100000000 00101110110000000000101110110000 00000010011011000000000010111011 00000000000011101100000000001011 10110000000000101110100001000000 00010000000000000000000000000000 00000000000000000000000000000000 10000000000000010010110000000000 10111011000000000110111011000000 00001011101101000000001000100100 01000000100010110000000000101110 11000000000010001011000000000010 11101100000000001000101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000000001101100000000001011 10110000000000101110000000000000 01000000000000000000000000000000 00000000000000000000000000000000 00001000000001000000110000000000 10110011000000000010110011000001 00001011000000000000001000000000 00000000100100110000000000100100 11000000001010000011000000000010 11001100000000001010001100000000 00101100110000000000101100110000 00000010010011000000000010110011 00000000001011001100000000001011 00110000000000101100001000000001 00000000000000000000000000000000 00000000000000000000000000000000 00000000000011010110110000000000 11111011000000000011111011000000 01001111100000000000101100000100 00000000110010110000000000111110 11000000000011001011000000000011 11101100000000001100101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111100000000000011 01010000000000000000000000000000 00000000000000000000000000000000 10100000000111011111110000000000 11111111000000000010111111000000 00001111110000000000001111110000 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000001111110100001000110 01110000000000000000000000000000 00000000000000000000000000000000 11000000000001011111111000000000 11111111001000000011001111100000 00001111111110000000001111111110 00000000111111111000000000111111 11100000000011111111100000000011 00111110000000001111111110000000 00111111111000000000111111110000 00000011011111100000000011111111 10000000001111111110000000001111 11111000000000110011000000000000 01110000000000000000000000000000 00000000000000000000000000000000 10100000000100001110111000000000 10111111110100000000001011100000 00001011101110000000001011101110 00000000101110111000000000101110 11100000000010111011100000000010 10101110000000001011101110000000 00101110111000000000101111110000 00000010101011100000000010111011 10000000001011101110000000001011 10110000000000101010000000000100 00110000000000000000000000000000 00000000000000000000000000000000 10001000000001011100110000000100 10110001000001000010000011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010111001000000000010 00001100000000001011001100000000 00101100110000000000101100110000 00000010010011000000000010110011 00000000001011001100000000001011 00110000000000100010001000000001 01110000000000000000000000000000 00000000000000000000000000000000 11100000000101011010110000000000 10111000000010000010001011000000 00001011101100000000001011101100 00000000101110110000000000100110 11000000000110111001110000000010 10101100000000001011101100000000 00100110110000000000101110110000 00000010101011000000000010111011 00000000001011101100000000001011 10110000000000101011000000000100 01100000000000000000000000000000 00000000000000000000000000000000 00000000000101011110110000000000 11111101000000001011001011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011110000000011 00101100000000001111101100000000 00111110110000000000111110110000 00000011011011000000000011111011 00000000001111101100000000001111 10110000000000110000000000000100 01110000000000000000000000000000 00000000000000000000000000000000 11000000000000011011110000000000 11110101000000000011111111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100001000 00111111110000000000111110110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111111100000000000 01100000000000000000000000000000 00000000000000000000000000000000 01000000000100001010110000000000 11111011000000000011101011000000 00001111101100000000001101101100 00000000111110110000000000111110 11000000000011111001000100000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011001011000000000011111011 00000000001111101100000000001111 10110000000000111101000000000100 00100000000000000000000000000000 00000000000000000000000000000000 11001000000001010010110000000000 10111011000000000010001011000000 00001001101100000000001001101100 00000000101110110000000000101110 11000000000010110001000000000010 11101100000000001011101100001000 00101110110000000000101111110000 00001010001011000000000010011011 00000000001011101100000000001011 10110000000000101111001000000000 01000000000000000000000000000000 00000000000000000000000000000000 11100000000001010100110000000000 10110011100100000010100011000000 00001001001100000000001011001100 00000000101100110000000000101100 11000000000010110010000000000010 11001100000000001011001111000000 00101100110000000000101110110000 00000010000011000000000010010011 00000000001011001100000000001011 10110000000000101111100000000000 01010000000000000000000000000000 00000000000000000000000000000000 01100000000000010001111000000000 10110111100000000010000111100000 00001001011110000000001011011110 00000000101101111000000000101101 11100000000010110111100000000010 11011110000000001011011110010000 00101101111000000000101101111001 00000010000111100000000010010111 10000000001011011110000000001011 01111000000000101101100000000000 01000000000000000000000000000000 00000000000000000000000000000000 01001000000010000000110001000000 11110001000000000011100011000000 00001101001100000000001111001100 00000000111100110000000000111100 11000000000011110011000000000011 11001100000000001111001100000000 00111100110000000000111100110000 00000011000011000000000011010011 00000000001111001100000000001111 00110000000000111101001000000010 00000000000000000000000000000000 00000000000000000000000000000000 01000000000111011011110000010100 11110101100000000011111111000000 00001101111100000000001101111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000100 00111111110000000000111111110100 00000011111111000000000011011111 00000000001111111100000000001111 11110000000000111101000000000110 01100000000000000000000000000000 00000000000000000000000000000000 10001000000001011110110000000000 11110001011000000011001011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 00101100000000001111001110000000 00110010110000000000111110110001 00001011001011000000000011111011 00000000001111101100000000001111 10110000000000111110101000000000 01110000000000000000000000000000 00000000000000000000000000000000 01001000000100011001110000000000 10110101000010010000000111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 10011100000000001011011100000000 00110101110000000000101100110010 00000010000111000000000010110111 00000000001011011100000000001011 01110000000000101101001000000100 01100000000000000000000000000000 00000000000000000000000000000000 11000001000000001001111000000100 10110111100000100000000111100000 00001011011110000000001011011110 00000000101101111000000000101101 11100000000010111111100000000010 00011110000000001011011110000000 00100001111000000000101101111000 00000010000111100000000010110111 10000000001011011110000000001011 01111000000000101111000000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000101001100110000000000 10110011010100001010000011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 10001100000000001011001100000000 00100100110000000000101100110000 00000010000011000000000010110011 00000000001011001100000000001011 00110000010000101101001000000100 00110000000000000000000000000000 00000000000000000000000000000000 11101000000101011010100000000000 11110110110000000011001010000000 01001111101000000000001111101000 00000000111110100000000000111110 10000000000011111110000000000011 00101000000000001111101000000000 00110010100000000000111110100000 00000011001010000000000011111010 00000000001111101000000000001111 10100000000000111111101000000100 01100000000000000000000000000000 00000000000000000000000000000000 01001000000000001110000000010000 11111000000010000011111000000000 00001111100000000000000111100000 00000000111110000000000000111110 00000000000011111000100000000011 11100000000000001111100001000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111101001000000000 00110000000000000000000000000000 00000000000000000000000000000000 00001000000100001110010000000000 11111001000000000011001001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001100000000011 00100100000000001111100100100000 00111110010000000000111100010000 00000011001001000000000011111001 00000000001111100100000000001111 10010000000000111100001000000100 00110000000000000000000000000000 00000000000000000000000000000000 10000000100001000110010000000000 10111001000000000110001001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000000010110001100000000011 01100100000000001011100111001000 00101110010000000000101110010000 00000010001001000000000010111001 00000000001011100100000000001011 10010000000000101110000000000000 00010000000000000000000000000000 00000000000000000000000000000000 00011000000001010010010000000000 10111001000001000010001001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000000010111001001000000010 00100100000000001011100100000000 00101110010000000000101110010000 00000010001001000000000010111001 00000000001011100100000000001011 10010000000000101100011000000000 01000000000000000000000000000000 00000000000000000000000000000000 00001000000001000000010000000000 10111001001010000010100001000000 00001011000100000000001011000100 00000000101100010000000000101100 01000000000010111001000000000010 01000100000000001011000100000000 00101100010000000000101100010010 10000010000001000000000010110001 00000000001011000100000000001011 00010000000000101100001000000001 00000000000000000000000000000000 00000000000000000000000000000000 10111000000011010110000000000000 11111000001000001010001000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 00100000000000001111100000000000 00111110000000000100111110001010 00001011001000000000000011111000 00000000001111100000000000001111 10000000000000111110111000000011 01010000000000000000000000000000 00000000000000000000000000000000 10011000000111011110010000000000 11111101000000000011011001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011110101000000000011 11100100000000001111100100000000 00111110010000000000111110010010 10000011111001000000000011111001 00000000001111100100000000001111 10010010100000111110011000000110 01110000000000000000000000000000 00000000000000000000000000000000 10011000000001011110010000000000 11111101100000001011001001000000 00001011100100000000001111100100 00000000111110010000000000111110 01000000000011111101000000000011 11100100000000001111110100000000 00111110010000000000111110010000 00000000101001000000000011111001 00000000001111100100000000001111 10010000000000111110011000000000 01110000000000000000000000000000 00000000000000000000000000000000 00111000000100001110000000010000 10111000000000000011011000000000 00001011100000000000001011100000 00000000101110000000000000101110 00000000000010111000000000000010 11100000000000001011100000000000 00101110000000000000101110000000 00000010101000000000000010111000 00000000001011100000000000001011 10000000000000101100111000000100 00110000000000000000000000000000 00000000000000000000000000000000 00001000000001011100010000000000 10110001010000001010000001000000 00001011000100000000001011000100 00000000101100010000000000101100 01000000000010110001100000000010 11000100000000001011000100000000 00101100010000000000101100010000 00000010000001000000000010110001 00000000001011000100000000001011 00010000000000101100001000000001 01110000000000000000000000000000 00000000000000000000000000000000 00011000000101011010010000000000 10111001001000000010011001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000000010111001000001000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010101001000000000010111001 00000000001011100100000000000011 10010000010000101100011000000100 01100000000000000000000000000000 00000000000000000000000000000000 10100000000101011110010000001000 11111001001000100011001001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001010000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011001001000000000011111001 00000000001111100100000000001111 10010000000000111110100000000100 00100000000000000000000000000000 00000000000000000000000000000000 00101000000000011010010000000000 11110001100000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001101000000011 11100100000000001111100100001000 00111110010000000000111100010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111100101000000000 00100000000000000000000000000000 00000000000000000000000000000000 00101000000100001010000000000000 11111000010000000011001000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000010000 00111110000000000100111110000000 00001011001000000001000011111000 00000000001111100000000000001111 10000000000000111100101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00100000000001010010100000000000 10111010100000001010001010000000 00001011101000000000001011101000 00000000101110100000000000101110 10000000000010111010101000000010 11101000000000001011111000000000 00101110100000000000101110100000 00000010001010000000000010111010 00000000001011101000000000001011 10100000010000101100101000000000 00000000000000000000000000000000 00000000000000000000000000000000 00101000000001010100110000000000 10110011100000000010000011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110001000000000010 11001100000000001011001110000000 00101100110000010000101100110000 00000010000011000000000010110011 00000000001011001100000000001011 00110000000000101100101000000000 01010000000000000000000000000000 00000000000000000000000000000000 10100000000000010001110000000000 10110111010000000010000111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011010000000000 00101101110000000000101101110000 00000010000111000000000010110111 00000000001011011100000000001011 01110010000000101100100000000000 01000000000000000000000000000000 00000000000000000000000000000000 10101000000010000001111000000000 11110011100000001011000111100000 00001111011110000000001111011110 00000000111101111000000000111101 11100000010011110111100000000011 11011110000000001111010010000000 00111101111000000000111100111000 00000011000111100000000011110111 10000000001111011110000000001111 01111000000000111100101000000010 00000000000000000000000000000000 00000000000000000000000000000000 00001000000111011010110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000000111100000000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110001000000111100001000000110 01100000000000000000000000000000 00000000000000000000000000000000 11000000000001011111111000000000 11111111100000000011001111100000 00001111111110000000001111111110 00000000111111111000000000111111 11100000000011111111100000000011 11111110000000001011110010010000 00111111111000000000111111111000 10000011001111100000000011111111 10000000001111111110000000001011 11111001000000111101000000000100 01110000000000000000000000000000 00000000000000000000000000000000 10101000000100011001110000000000 10110101000000000010000111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011010000000000 00101101110000000000101101110000 00000010100111000000000010110111 00000000001011011100000000001011 01110000000100101110101000000110 01100000000000000000000000000000 00000000000000000000000000000000 00010000000000001001110000000000 10110011000000000010000111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011010000000010 00101101110000000000101100110000 00000010000111000000000010110111 00000000001011011100000000001011 01110000001000101100011000000000 00100000000000000000000000000000 00000000000000000000000000000000 01100000000101001100110000000000 10110001001000000010000011000000 00001011001100000000001011001100 00000000101100110000000001101100 11000000000010110011010010000010 11001100000000001011000000000000 00101100110000000000101110110000 00000010100011000000000010110011 00000000001011001100000000001011 00110000000000101101100000000000 00110000000000000000000000000000 00000000000000000000000000000000 11111000000101011010110000000000 11111011000000001011001011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011010000000011 11101100000000001111100000000000 00111110110000000000111111110000 00000011001011000000000011111011 00000000001011101100000000001111 11110000000000111110111000000100 01100000000000000000000000000000 00000000000000000000000000000000 10000100000000001110110000000000 11111011000000010011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111100001000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001011101100000000001111 10110000000000111110000000000000 00110000000000000000000000000000 00000000000000000000000000000000 10000000000100001111110000000000 11110111000000000011001111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111111100000000011 11111100000010001111110000000000 00111111110000000000111111110000 00000011001111000000000011111111 00000000001111111100000101001111 11110000000100111110000001100100 00110000000000000000000000000000 00000000000000000000000000000000 10000001000001000110110000001000 10111011000000000000101011000000 00001011101100000000001011101100 00000000101110110000000000101110 11000000000010111011100000000010 11101100000000001011100011100000 00101110110000000000101110110000 00000010101011000000000010111011 00000010001011101100000000001011 10110000000000101110000001000000 00010000000000000000000000000000 00000000000000000000000000000000 10000000000001010010110000000000 10111011000000000010001011000000 00001011101100000000001011101100 00000000101110110000000000101010 11000000000010111011000100000010 11101100000000001011100010000000 00101110110000000000101110110000 00000010001011000000000010111011 00000000001011101100000000001011 10110000000000101110000000000000 01010000000000000000000000000000 00000000000000000000000000000000 00001000000001000000110000000000 10110001000000000010100011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000011011000000000000 00101100110000000000101100110000 00000010100011000000000010110011 00000000001011001100000000001011 00110000000000101100001000000101 00000000000000000000000000000000 00000000000000000000000000000000 10000000000011010110110000000000 11111011000000001011001011000000 00001111101100000000001111101100 00000000111110110000000000111010 11000000000011111011000000000011 11101100000000001111100000000000 00111110110000000000111110110000 00000011001011000000000011111011 00000000001111101100000001001111 10110000000100111110000000000010 00000000000000000000000000000000 00000000000000000000000000000000 10100000000111011111110000010000 11111101000000000011111111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000000111110000000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000011111111100000000001111 11110000000000111110100000000100 01110000000000000000000000000000 00000000000000000000000000000000 11000000000011011111111000000000 11101111100000000011111111100000 01001111111110000000001100111110 00000000111111111000000000111111 11100000000011111111100000000011 11111110000000001111111110000000 00111111111000000000111111111000 00000011111111100000000011111111 10000000001111111110000000001111 11111000000000111011000000000000 01110000000000000000000000000000 00000000000000000000000000000000 11000000000000001110111000000000 10111011100000000010111011100000 00001011101000100000001000101110 00000000101110111000000000101110 11100000000010111011100000000010 11101110000000001011101100000000 00101110111000000000101110111000 00000010111011100000000010111011 10000000001011101110000000001011 10111000000000101111000000000000 00110000000000000000000000000000 00000000000000000000000000000000 11001000000001011100110000000000 10100011000000000010110011000000 00001011000100001000111001001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001010 00110000000000101011001000000001 01110000000000000000000000000000 00000000000000000000000000000000 11000000000101011010110000000000 10111011000000000110111011000000 00001011000100001000001001101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000010000101111000000000100 01100000000000000000000000000000 00000000000000000000000000000000 10010000000101011110110000000000 11101011000000000011111011000000 10001111100100010000001101101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001011101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111000100000000000 01110000000000000000000000000000 00000000000000000000000000000000 11100000000000011011110000000000 11111111000001000011111111000000 00001111110000000001001110111100 00000100111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111111100000000100 01100000000000000000000000000000 00000000000000000000000000000000 01010000000100001010110000000000 11101011000000000011111011000000 01001111100101100000101100101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000110001010100000100 00100000000000000000000000000000 00000000000000000000000000000000 11001000000001010010110000000000 10111011000010000000111011000000 10001011101101000000001000101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10111000000000100011001000000000 01000000000000000000000000000000 00000000000000000000000000000000 11100000000001010100110000001000 10110011111001000000110011000000 00001011001100010000001001001100 00000000001100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110011000000100011000000000000 00000000000000000000000000000000 00000000000000000000000000000000 11110000000000010001111000000100 10110111100000000010110111100000 00001011011010010000011001011110 00000000101101111000000000101101 11100000000010110111100000000010 11011110000000001011011110000000 00101101111000000000101101111000 00000010110111100000000010110111 10000000001011011110000000001011 01111000000010100011110000000000 00000000000000000000000000000000 00000000000000000000000000000000 01001010000000000000110000000000 11110011000000000011110011000000 10011111101100010110001101001100 00000000111100110001000000111100 11000000000011110011000000000011 11001100000000001111001100000000 00111100110000000000111100110000 00000011110011000000000011110011 00000000001111001100000000001111 00110000000000110001101000000110 00000000000000000000000000000000 00000000000000000000000000000000 01000000000101011011110000000000 11111111000000000011111111000000 00001111111000010000001110111100 00000000111111110000010000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 01110000000001111101000000000110 00100000000000000000000000000000 00000000000000000000000000000000 10101000000001011110110000000000 11111011000000000011111011000000 00011111100111001000001100101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111100001000000000 01110000000000000000000000000000 00000000000000000000000000000000 11001000100100011001110000000000 10110111000000000010110111000000 00001011110100000000001000011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101111001000000000 01100000000000000000000000000000 00000000000000000000000000000000 10000000000000001001111000000000 10110111100000000010110111100000 00001010010110000001001000011110 00000000101001111000000000101101 11100000000010110111100000000010 11011110000000001011011110000000 00101101111000000000101101111000 00000010110111100000000010100111 10000000001011011110000000001010 01111000000000101100100000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000101001100110000000000 10110011000000000010110011000000 00011011001100110000001000001100 00010000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101101001000000100 00110000000000000000000000000000 00000000000000000000000000000000 11100000000101011010100000000000 11111010000000000011111010000000 00001110101000000000101100101000 00000000111010100000000000111110 10000000000011111010000000000011 11101000000000001111101000000000 00101110100000000000111110100000 00000011111010000000000011101010 00000000001111101000000000001110 10100000000000101111101000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000000001110000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000100000000111101001000000100 00100000000000000000000000000000 00000000000000000000000000000000 00001000000100001110010000000000 11111001000000000011101001000000 00001111101100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000110000001000000100 00100000000000000000000000000000 00000000000000000000000000000000 10000000000001000110010000000000 10110001000000000010001001000000 00001011100110010000001011100100 00000000101110010000000000101110 01000000000010111001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 00010000100000101010000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00011000000001010010010000000000 10111001010000000010001001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000000010111001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000100000011000000000 01000000000000000000000000000000 00000000000000000000000000000000 00001000000001000000010000000000 10110001000000000010000001000000 10001011001100000000001011000100 00000000100100010000000000101100 01000000000010110001000000000010 11000100000000001011000100000000 00101100010000000000101100010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101000001000000001 00000000000000000000000000000000 00000000000000000000000000000000 10111000000011010110000000000100 11111000000000001011101000000000 00001111100001010000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000110010111000000111 01010000000000000000000000000000 00000000000000000000000000000000 10011000000111011110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100110101000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111110111100000110 01110000000000000000000000000000 00000000000000000000000000000000 10011000000001011110010000000001 11111101000000001011001001000000 00001111110100000000001100100100 00000000111110010000000000111110 01000000000111111001000000000011 11100100000000001111100100010000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 11010000000000111110111000000001 01110000000000000000000000000000 00000000000000000000000000000000 01111000000100001110000000000000 10111000000000000010001000000000 00001011000000000000001000100000 00000000101110000000000000101110 00000000000011111000000000000010 11100000000000001011100010100000 00101110000000000000101110000000 00000010111000000000000010111000 00000000001011100000000000001011 10000000000000101100011000000000 00110000000000000000000000000000 00000000000000000000000000000000 01001000000001011100010000000000 10110001000000000010010001000000 00011011000100000000011001000100 00000000101100010000000000101100 01000000000010110001000000000010 11000100000000001011000100100000 00101100010000000000101100010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000001101101001000000001 01100000000000000000000000000000 00000000000000000000000000000000 00011000000101011010010000000001 10111011000000000010011001000000 00001011001100000000001001100100 00000000101110010000000000101110 01000000000010101001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000010011011 10010000000000101100011000000100 00100000000000000000000000000000 00000000000000000000000000000000 10100000000101011110010000000000 10111001000000100011011001000000 01001111100111110000101101100100 00000000111110010000000000111110 01000000000010111001000000000011 11100100000000001011100100000000 00111110010000000000101110010000 00000011111001000000000011111001 00000000001111100100000000001011 10010000000000111110000000000000 00100000000000000000000000000000 00000000000000000000000000000000 01101000000000011010010000000000 11111001000000000011101001000000 00001111100110000000001110100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000100000111101101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00101000000100001010000000000000 11111000000001000011111000000000 00001111100000011000001100100000 00000000111110000000000000111110 00000000000011111000000001000011 11100000000000001111100000000000 00110010000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111100101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00101000000001010010100000000000 10110110000010010010111010000000 00001011111010000000001000101000 00000000101110100000000000101110 10000000000010111010000000000010 11101000000000001011101000000000 00101010100000000000111010100000 00000010111010000000000010111010 00000000001011101000000000001011 11101100000000101100001000000000 00000000000000000000000000000000 00000000000000000000000000000000 00101000000001010100110000000000 10110000000000000010110011000000 00001011001111000000001001001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00100000110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00111000000000101100001000000000 01010000000000000000000000000000 00000000000000000000000000000000 10100000000000010001110000000000 10110101000000000010110111000000 00001011010000000000001001011100 00000000101101110000001000101101 11000000000010110111000000000010 11011100000000001011011110000000 00101001110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01100000100000101100100000000000 01000000000000000000000000000000 00000000000000000000000000000000 10101000000010000001111000000000 11110100100000000011110111100000 01001111011110000000101101011110 00000000101101111000000000111101 11100000000011110111100000000011 11011110000000001111111110000000 00110001111000000000101101111000 00000011110111100000000011110111 10000000001111011110000000001111 01111000000000111100001000000110 00000000000000000000000000000000 00000000000000000000000000000000 00001000000111011010110000000000 11111000000000000011111011000000 10001111101000000000001110101100 00001000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111010110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111100001000000110 01100000000000000000000000000000 00000000000000000000000000000000 01000000000001011111111000000000 11111110100000000011111111100000 00011111011110000000001110111110 00000000111111111001000000111111 11100100000001111111100000000011 11111110000000001111111110000000 00111111111000000000111111111000 00000011111111100000000011111111 10000000001111111110000000001111 11111000000000101101100000000000 00100000000000000000000000000000 00000000000000000000000000000000 10101000000100011001110000000000 11100111000100000010110111000000 00001011010100100000001101011100 00000000101101110000000000111101 11000000000011110111000000000010 11011100000000001011011100000000 00101101110000000000111001110000 00000010110111000000000010110111 00000000001011011100000000001011 01000000000000101110101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00010000000000001001110000000000 10110110000000000010110111000000 00001010111100000000001011011100 00000000101101110000000100101101 11000000000110110111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001010 01100000000000101100010000000000 00100000000000000000000000000000 00000000000000000000000000000000 01101000000101001100110000000000 10100010000000000010110011000000 00001011100000000000001000001100 00000000101100110000000000101000 11000000000010100011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000000011 00000000000000101101000100000100 00100000000000000000000000000000 00000000000000000000000000000000 10111000000101011010110000000000 11111000000000000011111011000000 00001110101100001000001011101100 00001000111110110000000000101110 11000000000010111011000000000011 11101100000000001111111100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10010000000000101110001000000000 01100000000000000000000000000000 00000000000000000000000000000000 10000000000000001110110000000000 11101001010000000011111011000000 00001111100000001000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111010110000 00000011111011000000000011111011 00000000001111101100000000001111 10000000001100111110010100000100 00110000000000000000000000000000 00000000000000000000000000000000 10000000000100001111110000000000 11111100001000000011111111000000 00001111110110000000001100111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11011000000000111110000001000100 00110000000000000000000000000000 00000000000000000000000000000000 10000000000000000110110000000000 10111001110000000010111011000000 00001011100001000000001111101100 00000000101110110000000000101110 11000000000011001011000000000010 11101100000000001011111100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10010000000000101110000001100000 00010000000000000000000000000000 00000000000000000000000000000000 10000000000001010010110000001000 10111010000000000010111011000000 01001011101000100000011000101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110010000000101110100000000000 01010000000000000000000000000000 00000000000000000000000000000000 00001000000001000000110000000001 10110001000000000010110011000000 00001011000000000000101001001100 00000000101100110000000000100100 11000000000010000011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00000000000000101100101000000000 00000000000000000000000000000000 00000000000000000000000000000000 10000000000011010110110000000000 10111010000000000011111011000000 00001111101100000000001100101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10100000000000111110000000000010 00010000000000000000000000000000 00000000000000000000000000000000 10100000000111011111110000000000 11111101000000000011111111000000 00001111110000000000001110111100 00000000111111110000000000111111 11000000000011101111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000001001111 11000000000000111110100000100110 01110000000000000000000000000000 00000000000000000000000000000000 11000000000011011111111000000000 11111111100000000011111111100000 00001111111110000000001111111110 00000000111111111000000000111111 11100000000011111111100000000011 11111110000000001111111110000000 00111111110000000000110011111000 00000011010100100000001011001111 10000000001111111100000000001111 11111000000000111111000000000000 01110000000000000000000000000000 00000000000000000000000000000000 11000000000000001110111000000000 10111011100000000010111011100000 00001011101110000000001110101110 00000000101110111000000000101110 11100001000010111011100000000010 11101110000000001011101110000000 00101111110000000000101000110000 00000010001000100000000010001011 10000000001011111110000000001011 10111000000000101111000000000100 00110000000000000000000000000000 00000000000000000000000000000000 11001000000001011100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000100100110000 00000010110010000000000010000011 00000000001011001100000000001011 00110000000000101111001000000001 01110000000000000000000000000000 00000000000000000000000000000000 11000000000101011010110000000000 10111011000000000010111011000000 00001011101100000000001010101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000001011101100000010 00101110110000000000101110110000 00000010111010000010000010001011 00000000001011101100000000001011 10110000000000101111000000000100 01100000000000000000000000000000 00000000000000000000000000000000 10000100000101011110110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000110110110000 00000011111000010000000011001011 00000000001111101100000000001111 10110000000000111100000000000000 01110000000000000000000000000000 00000000000000000000000000000000 11100000000000011011110000000000 11111111000000000011111111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111100110000000000111011110000 01000011001101100100000011111111 00000000001111101100000000001111 11110000000000111111110000000100 01100000000000000000000000000000 00000000000000000000000000000000 01000000000100001010110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000010110010110000 00000011111010000000000011011011 00000000001111101100000100001110 10110000000000111101010000000100 00100000000000000000000000000000 00000000000000000000000000000000 11011000000000010010110000000000 10111011000000000010111011000000 00001110101100000000001011101100 00000000101110110000000000101110 11000000000010111011000010000010 11101100000000001011101100000000 00101111110000000000100010110000 00000010000011000000000010001011 00000000001011111100000000001000 10110000000000101111001000000000 01000000000000000000000000000000 00000000000000000000000000000000 11100000000001010100110000000000 10110011000000000010110011000000 00001001001100000000001011001100 00000000101100110000000000101100 11000000000010110011100000000010 11001100000000001011001100000000 00101100110000000000100010110000 00000010100001000000000010010011 00000000001011001100000000001010 00110000000000101111000000000000 00000000000000000000000000000000 00000000000000000000000000000000 11110000100000010001111000000100 10110111100000000010110111100000 00001010011110000000001011011110 00000000101101111000000000101101 11100000000010110111100000000010 11011110000000001011011110000000 00101101111000000000100001111001 00000010001101100000000010000111 10000000001011011100000000001000 01111000000001101111110000000000 00000000000000000000000000000000 00000000000000000000000000000000 01001000000000000000110001000000 11110011000000000011110011000000 00001111001100000000001111001100 00000000111100110000000000111100 11000000000011110011000000000011 11001100000000001111001100010000 00111100110000000000110000110000 00000011100001000000000011010011 00000000001111001100010000001110 00110000000000111101001000000010 00000000000000000000000000000000 00000000000000000000000000000000 01000000000101011011110000000000 11111111000000000011111111000000 00001110111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000010 11111100000000001111111100000000 00111111110001000000111111110000 01000011101101000000000011111111 00000000001111111100100000001111 11110000000000111101000000000110 00100000000000000000000000000000 00000000000000000000000000000000 10101000000001011110110000000100 11111011000000100011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110111010100000110010110000 00000011001010000000000011111011 00000000001111101100110000001100 10110000000000111100001000000000 01110000000000000000000000000000 00000000000000000000000000000000 11001000100100011001110000000000 10110111000000000010110111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110100000000101001110000 00000010000111000000000010110111 00000000001011001100010000001010 01110000000000101111001000000000 01100000000000000000000000000000 00000000000000000000000000000000 10000001000000001001111000000000 10110111100000000010110111100000 00001011011110000000001010011110 00000000101001111000000000101101 11100000000010110111100000000010 11011110000000001011011110000000 00101101110000000000100001110000 00000010000110100000000010110111 10000000001011011110100000001000 01111000000000101100100000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000100101001100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001001001100000000 00101100110000000000101000110000 00000010000011110000000010110011 00000000001011001100000000001010 00110000010000101101101000000100 00110000000000000000000000000000 00000000000000000000000000000000 11100000000101011010100000001000 11111010000000000011111010000000 00001111101000000000001111101000 00000000111110100000000000111110 10000000000011111010000000000011 11101000000000001111101000000000 00111110100000000010110010100000 00000010001110101000000010111010 00000000001111101000000000001000 10100000000000101111101000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000000001110000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000010 00111100000000000010111110000100 00000011111000001000000011111000 00000000001111000000000000001111 10000000010000111101001000000100 00100000000000000000000000000000 00000000000000000000000000000000 00001000000100001110010000000000 11111001000000000011111001000000 00001101100100000000001111100100 00000000111110010000000000111110 01000000000011111001100000000011 11100100000000001111100100000000 00111110010000000000110110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111100001000000100 00100000000000000000000000000000 00000000000000000000000000000000 10000000000001000110010000000000 10111001000001000010111001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000000010111001100000000010 11100100000000001011100100000000 00101110010000000000110110010110 00000010111001000000000010111001 00000000001011100100000000001000 10010000000000101110100000000000 00000000000000000000000000000000 00000000000000000000000000000000 00011000000001010010010000000000 10111001000000000010111001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000000010111001001000000010 11100100000000001011100100000000 00101110010000000000100110010000 00000010111001000000000010111001 00000000001011100100000000001010 10010000000000101100011000000000 01000000000000000000000000000000 00000000000000000000000000000000 00001000000001000000010000000000 10110001000000000010110001000000 00001011000100000000001011000100 00000000101100010000000000101100 01000000000010110001000000000110 11000100000000001011000100000000 00101100010010100010100100010000 00000010110001000000000010110001 00000010011011000100101000001000 00010000000000101100001000000001 00000000000000000000000000000000 00000000000000000000000000000000 10111000000011010110000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000101110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111100001010000000110110000000 00000011111000000000000111111000 00000000001111100000100100011110 10000000001001111110111000000111 01010000000000000000000000000000 00000000000000000000000000000000 10011000000111011110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000001 11100100000000001111100100000010 00111110011010100000111100010010 10000011111101000000000011111001 00000000001111100100000000001110 10010000000000111110011000000110 01110000000000000000000000000000 00000000000000000000000000000000 10011000000101011110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111101000000000011 11100100000000001111100100000000 00111110010000000000110011010000 00000011001101000000000011111001 00000000001111100100000000001111 10010000000000111110111000000100 01110000000000000000000000000000 00000000000000000000000000000000 01111000000010001110000000000000 10111000000000000010111000000000 00001011100000000000001011100000 00000000111110000000000000101110 00000000000010111000000000000010 11100000000000001011100000000000 00101110000000000000100010000000 00000010001000000000000010111000 00000000001011100000000000001011 10000000000000111100111000000010 00110000000000000000000000000000 00000000000000000000000000000000 01001000000001011100010000000000 10110001000000000010110001000000 00001011000100000000001011000100 00000000101100010000000000101100 01000000000010110001000000000010 11000100000000001011000100000000 00101100010000000010100000010000 00000010010001000000000010110001 00000000001011000100000000001011 00010000000000101101001000000000 00100000000000000000000000000000 00000000000000000000000000000000 00011000000001011010010000000000 10111001000000000010111001000000 00001011100100000000001011100100 00000000101010010000000000101110 01000000000010111001000000000010 11100100000000001011100100000000 00101110010000000000100010010000 00000010011001000000000010111001 00000000001011100100000000001011 10010000010000101000011000000000 00100000000000000000000000000000 00000000000000000000000000000000 10100000000001011110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000101110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000110010010000 01000011011001100100000011111001 00000000001111100100000000001011 10010000000000101110100000000100 00100000000000000000000000000000 00000000000000000000000000000000 01101000000000011010010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011101001100000000011111001 00000000001111100100000000001111 10010000000000111101101000000000 00100000000000000000000000000000 00000000000000000000000000000000 00101000000000001010000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000110010000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111100101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00100000000001010010100000000000 10111010000000000010111010000000 00001011101000000000001011101000 00000000101110100000000000101110 10000000000010111010100000000010 11101000000000001011101000000000 00101110100000000000110101100000 00000010111010000000000010111010 00000000001011101000000000001011 10100000000000101100001000000000 00000000000000000000000000000000 00000000000000000000000000000000 00101000000001010100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110001100000000110 11001100000000001011001100000000 00101110110000000000100000000000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101100001100000000 01010000000000000000000000000000 00000000000000000000000000000000 10100000000100010001110000000000 10110111000000000010110111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010110111000010000010 11011100000000001011011100000000 00101101110000000000100101001000 00000010110111000000000010110111 00000000001011011100000001001011 01110000000000101100100000000000 01000000000000000000000000000000 00000000000000000000000000000000 10101000000000000001111000000000 11110111100000000011110111100000 00001111011110000000001111011110 00000000101101111000000000111101 11100000000011110111100000000011 11011110000000001111011110000000 00111111111100000000110001010000 00000011110111100000000011110111 10000000001111011110000000001111 01111000000000111100101000000110 00000000000000000000000000000000 00000000000000000000000000000000 00001000000101011010110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000100001111101100000000 00111110110010100000111110010000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111100001000000110 01100000000000000000000000000000 00000000000000000000000000000000 11000000000001011111111001000000 11111111100000000011111111100000 00001111111110000000001111111110 00000000111111111000000000111111 11100000000011111111100000000011 11111110000000001111111110000000 00111111111000000000111011001000 00000011000111100000000011001111 10000000001111111110000000001100 11111001000000111101100000000000 00100000000000000000000000000000 00000000000000000000000000000000 10101000000100011001110000000000 10110111000000000010110111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000001 00101101110000000000100001000000 00000011010111000100000011010111 00000000001011011100000000001101 01110000001000101110101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00010000000000001001110000001000 10110111000000000010110111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101001010000 00000010001111000000000010000111 00000000001011011100000000001000 01110000001000001100010000000000 00100000000000000000000000000000 00000000000000000000000000000000 01100000000101001100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101110110000000000100010010000 00000010010011000000000010010011 00000000001011001100000000001001 00110000000000101101000000000100 00110000000000000000000000000000 00000000000000000000000000000000 11101000000101011010110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011110011000000000011 11101100000000001111101100000000 00111111110000000010111010100000 00000011001011010000000011001011 00000000001111101100000000001000 10110000000000111110111000000000 01100000000000000000000000000000 00000000000000000000000000000000 10010100000000001110110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000010011 11101100000000001111101100000000 00111110110000000000111110100000 00000011111011001000000011111011 00000000001111001100000100001111 10110000000000111110100000000100 00110000000000000000000000000000 00000000000000000000000000000000 10000000000100001111110000000000 11111111000000000011111111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 00111100000000001111111100000000 00111110110000000000110011110001 00000011001111000000000011111111 00000000001111101100000000001100 11110000000000111110000001000100 00110000000000000000000000000000 00000000000000000000000000000000 10000000000001000110110000000000 10111011000000000010111011000000 00001011101100000000001011101100 00000000101110110000000000101110 11000000000010111011100000000010 00101100000000001011101100000000 00101110110000000000100010110000 01000010101011000000000010111011 00000000001011101100000000001010 10110000000000101110010001100000 00010000000000000000000000000000 00000000000000000000000000000000 10000000000001010010110000000000 10111011000000000010111011000000 00001011101100000000001011101100 00000000101110110000000000101110 11000000000010111011000100000010 00101100000000001011101100000000 00101110110000000000100010100000 00000010001011000000000010111011 00000000001011101100000000001000 10110000000100101110000000000000 01010000000000000000000000000000 00000000000000000000000000000000 00001000000001000000110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 00001100000000001011001100000000 00101100110000000000100000100000 00000010100011000000000010110011 00000000001011001100000000001010 00110000000000101100001000000100 00000000000000000000000000000000 00000000000000000000000000000000 10000000000011010110110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 00101100000000001111101100000000 00111111110000000000110000110000 00010011001011000001000011111011 00000000001111101100000000001100 10110000000000111110000000000010 00010000000000000000000000000000 00000000000000000000000000000000 10100000000111011111110000000000 11111111000000000011111111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000010011111111000000000011 11111100000000001111111100000010 00111111110000000010111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111110100000100100 01110000000000000000000000000000 00000000000000000000000000000000 11000000000011011111111000000000 11111111100000000011111111100000 00001111111110000000011111111110 01000000111111111000000000110011 11100000000011111111110000000011 00111110000000001111111110000000 00111111111000000000111111111000 00000011111111100000000011111111 10000000001111111110000000001111 11111000000000111111000000000000 01110000000000000000000000000000 00000000000000000000000000000000 10000000000010001110111000000000 10111011100000000010111011100000 00001011101110000000001011101100 10000000101110111000000000101010 11100000000010111011000000000011 01101110000000001011101110000000 00101110111000000000101110111000 00000010111011100000000010111011 10000000001011101110000100001011 10111000000000101111000000000000 00110000000000000000000000000000 00000000000000000000000000000000 10001000000001011100110000000000 10110011000000000010110011000000 00001011001100000000011011001100 00000000101100110000000000100000 11000000000010110011001000000010 00001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001010 00110000000000101011001000000001 01110000000000000000000000000000 00000000000000000000000000000000 11000000000001011010110000000000 10111011000000000010111011000000 00001011101100000001001011101100 00000000101110110000000000101010 11000000000010111011000000000010 01101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000010000101111100000000100 01100000000000000000000000000000 00000000000000000000000000000000 00000000000101011110110000000000 11111011000000000011111001000100 00001111101100000000001011101100 00000000111100110000000000110010 11000000000011110011000000000011 00101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000100111100100000000000 01110000000000000000000000000000 00000000000000000000000000000000 11100000000000011011110000000000 11111111000000000011111101100000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111111100000000100 01100000000000000000000000000000 00000000000000000000000000000000 01000000000100001010110000000000 11111011000000000011111001010000 00001111101100000000001111101100 01000000111110110000000000111110 11000000000011111011001000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111101010000000100 00100000000000000000000000000000 00000000000000000000000000000000 11001000000001010010110000000000 10111011000000000010111011000010 10001011101100000000001011101111 01000000101110110110000000101110 11000000000010111011101000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101111001000000000 01000000000000000000000000000000 00000000000000000000000000000000 11000000000001000100110000000000 10110011000000000010110010100000 00001001001100000000001011001100 00000000101100110010000000101100 11000000000010110011010000100010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101111001000000000 00000000000000000000000000000000 00000000000000000000000000000000 01100000000000000101111000000000 10110111100000000010110111000000 00001011011110000000001011011110 00000000101101111000000000101101 11100000000010110111100000000010 11011110000000001011011110000000 00101101111000000000101101111000 00000010110111100000000010110111 10000000001011011110000000001011 01111000000000101111110000000000 00000000000000000000000000000000 00000000000000000000000000000000 01001000000000000100110000000000 11110011000000000011110010010100 00001101001100000000001111001100 00000000111100110000000101111100 11000000010011110011000000000011 11001100000000001111001100000000 00111100110000000000111100110000 00000011110011000000000011110011 00000000001111001100000000001111 00110000000000111101101000000110 00000000000000000000000000000000 00000000000000000000000000000000 01000000000101011011110000000000 11111111000000100011111110000000 00001111111100000001001111111100 00000000111111110000000101111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111101000000000110 00100000000000000000000000000000 00000000000000000000000000000000 00001000000101011110110000000000 11111011000000000011111010100000 00011101101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111100101000000000 01110000000000000000000000000000 00000000000000000000000000000000 01001000000000011001110000000000 10110111000000000010110111000000 00001000011100000000001011011100 00000001101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101111001000000000 01100000000000000000000000000000 00000000000000000000000000000000 00100000000100001001111000000000 10110111100000000010111101100000 01001000011110000101001010011110 00010000101001111000000000101101 11100000010010110111100000000010 11011110000000001011011110000000 00101101111000000000101101111000 00000010110111100000000010110111 10000000001011011110000000001011 01111000000000101100000000000000 00100000000000000000000000000000 00000000000000000000000000000000 01101000000101001100110000000000 10110011000000000010110011000000 00001000001100000000001011001100 00000100101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101101001000000100 00110000000000000000000000000000 00000000000000000000000000000000 11101000000101011110100000000000 11111010000000000011111110101100 00001101101000000000001111101000 00000000111110100000000000111110 10000000000011111010000000000011 11101000000000001111101000000000 00111110100000000000111110100000 00000011111010000000000011111010 00000000001111101000000000001111 10100000000000111111101000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000000011010000000000000 11111000000000000011111000000000 00001111100000000000001111100001 00000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111101001000000100 00100000000000000000000000000000 00000000000000000000000000000000 00001000000100001010010000000000 11111001000000000011111001000000 00001111100100000000001111100100 10000000110010010100000000111110 01000000000011111001001000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111100101000000100 00100000000000000000000000000000 00000000000000000000000000000000 10000000000001000110010000000000 10111001000000000010111001100000 00001011100100000000001011100100 00100010100010011100000000101110 01000000000010111001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101110100000000000 00000000000000000000000000000000 00000000000000000000000000000000 00111000000001010010010000000000 10111001000000000010111001000100 00001011100100000000001011000100 00000000100010010000000000101110 01000000000010111001000010000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101100011000000000 01000000000000000000000000000000 00000000000000000000000000000000 00101000000001000000010000000000 10110001000000000010110001000000 00001011000100000000001011000100 00000000100000110000000000101100 01000000000010110001000000000010 11000100000000001011000100000000 00101100010000000000101100010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101100001000000001 00000000000000000000000000000000 00000000000000000000000000000000 10111000000001010110000000000000 11111000000000000011111000000000 00001111100000000000001111100001 01000000110010000000000000111110 00000000000011111000010100000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111110011000000111 01010000000000000000000000000000 00000000000000000000000000000000 10011000000101011110010000000000 11111001000000000011110111000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111110011000000110 01110000000000000000000000000000 00000000000000000000000000000000 10011000000101011010010000000000 11111001000000000011111101000000 00001111100100000000001111110100 00000000111111010000000000111110 01000000000011111101000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111110111000000001 01110000000000000000000000000000 00000000000000000000000000000000 00111000000100001110000000000000 10111000000000000010111000000000 01001011100000000000001110000000 00000000111110000000000000101110 00000000000010111000000000000010 11100000000000001011100000000000 00101110000000000000101110000000 00000011101000000000000010111000 00000000001011100000000000001011 10000000000000101100011000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000001001000010000000000 10110001000000000010110001000000 00001011000100000000001011000100 00000000101100010000000000101100 01000000010010110001000000000110 11000100000000001011000100000000 00101100010000000000101100010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101101001000000001 00100000000000000000000000000000 00000000000000000000000000000000 00011000000000000010010000000000 10111001000000000010111001000000 00001011100100000000001010101100 00000001101010010000000000101110 01000000000010111001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010101001000000000010111001 00000000001011100100000000001011 10010000000000101100011000000100 00100000000000000000000000000000 00000000000000000000000000000000 10100000000001011110010000000000 11111001000000000011111001110000 00000111100100000000001111100100 00000000101110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000101110100000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000000011010010000000000 11111001000000000011111001110000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011101001000000000011111001 00000000001111100100000000001111 10010000000000111101001000000100 00100000000000000000000000000000 00000000000000000000000000000000 00001000000000001010000000000000 11111000000000000011111000010000 00001111100000000000001111100000 00000000110110000000000000111110 00000000010011111000100000001011 00100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111100101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00101000000101010010100000000000 10111010000000000010111010100000 00001011101000000100001011111011 00000000110111101000000000101110 10000000000010111110000000000010 00101000000000001011101000000000 00101110100000000000101110100000 00000010111010000000000010111010 00000000001011101000000000001011 10100000000000101100001000000000 00000000000000000000000000000000 00000000000000000000000000000000 00101000000001010100110000000000 10110011000000000010110011000000 00001011001100000000001011001101 00100000100000111000000000101100 11000000000010110011000100000010 01001100000000001010001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101100001100000000 01010000000000000000000000000000 00000000000000000000000000000000 10000000000100010001110000000000 10110111000000000010110101010000 00001011011100000000001011011011 00000000100101110000100000101101 11000000000010110101100000000010 01011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101100100000000000 01000000000000000000000000000000 00000000000000000000000000000000 10001000000010000001111000000000 11110111100000000011110111100000 00001111011110000000001111011110 00000000110001101000000000111101 11100000000011111111100000000011 01011110000000001110011110000000 00111101111000000000101101111000 00000011110111100000000011110111 10000000001111011110000000001111 01111000000000111100101000000110 00000000000000000000000000000000 00000000000000000000000000000000 00001000000001011010110000000000 11111011000000000011111001000000 00001111101100000000001111100000 00000000111110000000000000111110 11000000000011111011000000000011 10101100000000001101101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000011111 10110000000000111100001000000010 01100000000000000000000000000000 00000000000000000000000000000000 01000000000001001011111000000000 11111111100000000011110111100000 00001110111110000000001111111110 00000000110001011000000000110011 11100000000010111111100000000011 11111110000000001111111110000000 00111111111000000000111111111000 00000011111111100000000011111111 10000000001111111110000000001111 11111000000000111101100000000000 00100000000000000000000000000000 00000000000000000000000000000000 10101000000110001001110000000000 10110111000001000010110111000100 00011000011100000000001110111000 00000000101001110000000000110101 11000000000010110100001000000010 11011100000000001011011100000000 00101101110000000000111001110000 00000011110111000000000010110111 00000000001011011100000000001111 01110000000000101110001000000000 00100000000000000000000000000000 00000000000000000000000000000000 00010000000000001001110000000000 10110111000000000010110101000000 00001010011100000000001011011100 00000000100001000000000000100001 11000000000010110101000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101000011001000000 00100000000000000000000000000000 00000000000000000000000000000000 01100000000001001000110000000000 10110011000000000010110001110000 00001000001100000000001010101000 00000000101000000000000000100100 11000000000010111001000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010100011000000000010110011 00000000001011001100000000001010 00110000000000101101000000000100 00110000000000000000000000000000 00000000000000000000000000000000 10100000000101011010110000000000 11111011000000000011110011000010 00001110101100000000001111100100 00001000110010110000000000110010 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000010111011000000000010111011 00000000001111101100000001001011 10110000000100111110111000000000 01100000000000000000000000000000 00000000000000000000000000000000 10000100000000001110110000000000 11111011000000000011111011000000 00001111101100000000001111100101 00000100111110100100000000111110 11000000000011111001010000000011 11101100000000001111101100000000 00111110110000000000111010110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000001100111110100000000100 00110000000000000000000000000000 00000000000000000000000000000000 10100000000100001111110000000000 11111111000000000011111111110010 00001100111100000000001111111000 01000000110011110000010000110011 11000000000011111111100100001011 00111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111110000001000100 00110000000000000000000000000000 00000000000000000000000000000000 10100001000001000110110000000000 10111011000000000010111011100000 00001010101100000001001011100000 00000000100000000110000000101010 11000000000011111001000000000010 00101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000011101011 00000000001011101100000000001011 10110000001000101110000001000000 00010000000000000000000000000000 00000000000000000000000000000000 10000000000001010010110000000000 10111011000000000010111011000000 00001000101100000000001011100100 00000000100010010000000000101010 11000000000010111011000010000010 00101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101110000000000000 01010000000000000000000000000000 00000000000000000000000000000000 00001000000101000000110000000000 10110011000000000010111011000000 00001010001100000100001011000000 00000010100000100000000000101000 11000000000010100001000000000010 00001100000000001011001100000000 00101100110000000000101100110000 00000010010011000000000010110011 00000010001011001100000000001001 00110000000000101100001000000000 00000000000000000000000000000000 00000000000000000000000000000000 10000000000011010110110000000000 10111011000000000011111011000000 00001100101100000000001111100100 00001000110010010000000000111010 11000000000010111011000000000011 00101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111110000000000110 00010000000000000000000000000000 00000000000000000000000000000000 10100000000101011111110000000000 11111111000000000001111111000000 00001111111100000000001111110000 00000000111111000000000000111111 11000000000011111101000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011101111 00000000001111111100000000001111 11110000000000111110100000100110 01110000000000000000000000000000 00000000000000000000000000000000 11000000000011011111111000000000 11111111100000000011111111100000 00001111111110000000001101111110 00000000111111111000000000111111 00000000000011001100000000000011 11110000000000001100110000000000 00110011000000000000110011000000 00000011111101000000000011001111 10000000011111111110000000011111 11111000000000111011000000000001 01100000000000000000000000000000 00000000000000000000000000000000 11000000000000001110111000000000 10111011100000000010111011100000 00001011101100000000001000101110 00000000101110111000010000101110 00000001000010001000100000000010 11100000000000001100100010000000 00100010001000000000100010001000 00000010111001100000000010001011 10000000001011101110000000001011 10111000000101101111000000000000 00110000000000000000000000000000 00000000000000000000000000000000 11001000000001011100110000000000 10110011000000000010110011000000 00001011001100000000001001001100 00000000101100110000000000101100 01000000000010010001000000000010 11000000000000001001001000000001 00100100000000000000100000000000 00000010110001000000000010010011 00000000001011001100000000001011 00110000000000101111001000000001 00110000000000000000000000000000 00000000000000000000000000000000 11000000000101011010110000000000 10111011000000000010111011000000 00001011001100000000001001101100 00000000101110110000000000101110 01000000000010011001000000000010 11100000011000101000101000000000 00100110000000000000100010000000 10000010111001000010000010011011 00000000001011101100000000001011 10110000010001101111000000000100 01100000000000000000000000000000 00000000000000000000000000000000 10010000000101011110110000000000 11111011000000000010111011000000 00001111101100000000001101101100 00000000111110110000000000111110 10000000001011011000000100010011 11100011000000101101100100000000 10110110011000000010110010000101 00010010111001010100001011011011 00000000001011101100000000001011 10110000000000111000100000000000 01110000000000000000000000000000 00000000000000000000000000000000 11100000000000011011110000000000 11111111000000000011111111000000 00001111111100000000001110111100 00000000111111110000000000111101 10000000000011101000100000000011 11100010000000001111110100000000 00111011011001000000111110001000 00000011110001100000000011101111 00000000001111111100000000001111 11110000000000111111100000000100 01100000000000000000000000000000 00000000000000000000000000000000 01000000000100001010110000000000 11111011000000000011111011000000 00001111101100000000001110101100 00000000111110110000000000111110 11000000000011101001001000000011 00000001000000101100001100000000 00110100010000000000110010000100 00000011001001010000000011001011 00000000001111101100000000001111 10110000001000111101010000000100 00100000000000000000000000000000 00000000000000000000000000000000 11011000000001010010110000000000 10111011000000000010111011000000 00001011101100000000001000101100 00000000101110110000000000101110 11000000000010001001011000000010 00100000000000001101101100000100 00100010011100100010100010000000 00001010001001000000000010001011 00000000001011101110010000001011 10110000010000101111001000000000 01000000000000000000000000000000 00000000000000000000000000000000 11100000000001010100110000001000 10110011000000000010110011000000 00001011001100000000001010001100 00000000101100110000000000101100 00000000000010100010110000001010 00001100000000001000000010000100 00100000101100100000100000110000 00001010000010000000001010000011 00000000001011001101000000001011 00110000000001101111001000000000 00000000000000000000000000000000 00000000000000000000000000000000 11110000000000010001111000000000 10110111100000000010110111100000 00001011011110000000001000011110 00000000101101111000000001101101 00100000000010000110100000000010 00011110000000101001010010001000 00100000101001000000100001111001 00000010000110100000000010010111 10000000001011011110001000001011 01111000000000101111110000000000 00000000000000000000000000000000 00000000000000000000000000000000 01001000000000000000110000000100 11110011000000100011110011000000 00001011101100000000001110001100 00000000111100110000000000111110 01000000000011100011000000000011 00001100000000001100001000000000 00110100100001000000100000110001 00000011000010000000000011000011 00000000001111001100000000001111 00110000000000111101101000000110 00000000000000000000000000000000 00000000000000000000000000000000 01000000100101011011110000000000 11111111000000000011111111000000 00001111111100000000001110111100 00000000111111110000000000111111 01000000000011111111000100000011 11111100010000001111011000010000 10111111100001000000111111110001 00000011111110100100000011101111 00000000001111111100000000001111 11110000000000111101000000000110 00100000000000000000000000000000 00000000000000000000000000000000 10101000000001011110110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 10000000000011011010000000000011 00101110000000001100100100000000 00110010110000000000110010111000 00000011001010000000000011011011 00000000001111101100000000011111 10110000000000111100001000000000 01110000000000000000000000000000 00000000000000000000000000000000 11001000100100011001110000000000 10110111000000000010110111000000 00001011011100000000001011011100 00000000101101110000000000101111 10000000000010000110000000000010 00001100000000001000010100000000 00110001110000000000100000110000 00000010000010000000010110000111 00000000001011011100000000001011 01110000000000111011001000000000 01100000000000000000000000000000 00000000000000000000000000000000 10000001000000001001111000010000 10110111100000000010110111100000 00001011011110000000001011011110 00000000101101111000000000101101 11100000000010010011100000000010 00011110000000001000001110000000 00100000111000000000100101111000 00000010000110100000000010000111 10000000001011011110000000001011 01111000010000101100100000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000101001100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000100000010000011000000000010 00001100000000001000001100000000 00100000110000000000100000110000 00000010000010000000000010000011 00000000001011001100000000001011 00110000000000101001001000000100 00110000000000000000000000000000 00000000000000000000000000000000 11100000000101011010100000000000 11111010000000000011111010000000 00001111101000000000001011101000 00000000111110100000000000111110 10100000000011011010000000001011 00101000000000101100101001000000 10110010100100000010110110100000 00001011001110000000001011001010 00000000001011101000000000001011 10100000000000101111101000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000000001110000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000010000111100 00000000000011110000010000000011 11100000000000001111100000001000 00111000000000100000111110000000 00000011110100000000000011111000 00000000001111100000000000001111 10000000000000111001001000000100 00100000000000000000000000000000 00000000000000000000000000000000 00001000000100001110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011001001010000000011 00100100000000001111000100000000 00110010010000000000110010010000 00000011111001000000000011001001 00000000001111100100000000001111 10010000000000111100001000000100 00100000000000000000000000000000 00000000000000000000000000000000 10000010000001000110010000000000 10111001000000000010111001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000010010001001111000000010 00100100000000001011100100000000 00100010010000000000100010010000 00100010111001000000000010001001 00000000001011100100000000001011 10010000000000101110000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00011000000001010010010000000000 10111001000000000010011001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000000010001101000000000010 00110100000000001011110100100000 00100011010101000000100011010000 00000010111101000000000010001001 00000000001011100100000000001011 10010000000000101100011000000000 01000000000000000000000000000000 00000000000000000000000000000000 00001000000001000000010000000000 10110001000000000010110001000000 00001011000100000000001011000100 00000000100100010000000000101101 01001011001010000101001010001010 00010100101000001011010100101000 10100001010010100000100001010010 10000010110101001010000010000001 00000000001011000100000000001011 00010000000000101100001000000001 00000000000000000000000000000000 00000000000000000000000000000000 10111000000011010110000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00001000000011001000001000000011 00100000100000001111100000100000 00110010000010000010110010000010 00000011111100001000001011001000 00000000001111100000000100011111 10000000000000111110111000000111 01010000000000000000000000000000 00000000000000000000000000000000 10011000000111011110010000000000 11111001000000000011111001000000 00001111100100101000001111100100 00000000111110010000000000111110 01101010000011111001000000000011 11100110101000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000001111110111000000110 01110000000000000000000000000000 00000000000000000000000000000000 10011000000001011110010000000000 11111001000000000011111001000000 00001111100100000000001110100100 00000000111110010000000000111110 01000000000011010101000000000011 11100100000000001100110100000000 00110011010000000000110010010000 00000011111001000000000011111001 00000000001111110100000000001111 10010000000000111110111000000000 01110000000000000000000000000000 00000000000000000000000000000000 01111000000100001110000000000000 11111000000000000010111000000000 00001011100000000000001011100000 00000000101110000000000000101100 00000000000011011000000000000010 11000000000000001100100000000000 00100010000000000000110110000000 00000010111000000000000110111000 00000000001011100000000000001111 10000000000000101100011000000100 00110000000000000000000000000000 00000000000000000000000000000000 01001000000001011100010000000000 10110001000000000010110001000000 00001011000100000000001010000100 00000000101100010000000000101100 01000000000010010001000000000010 11000100000010001001000100000000 00100000010000000000100000010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101101001000000000 00100000000000000000000000000000 00000000000000000000000000000000 00011000000101011010010000000000 10101001000000000010111001000000 00001011100100000000001011100100 00000000101110010000000000101100 01010000000010011001010000000010 11100100000000001000100100100000 00100010010000000000100110010000 00000010111001000000000010111001 00000000001011100100000000001010 10010000000000101100011000000100 00100000000000000000000000000000 00000000000000000000000000000000 10100000000101011110010000000000 10111001000000000010111001000000 00001111100100000000001110100100 00000000111110010000000000111110 01000000000011011001000000000011 11100100000000101101100100000000 10110010010000000000110010010000 00000011111001000000000010111001 00000000001111100100000000001011 10010000000000111110100000000000 00100000000000000000000000000000 00000000000000000000000000000000 01101000000000011010010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000011111100100000000001111 10010000000000111101101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00101000000100001010000000000000 11111000000000000011101000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011001000000010000011 01100000000000001100000000000000 00111110000000100000111110000000 00000011111000000000000011111000 00000000001111100000000000001110 10000000000000111100101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00100000000001010010100000000000 10111010000000000010111010000000 00001011101000000000001011101000 00000000101110100000000000101110 10000000000010001110010000000010 00101000000000001000101010000000 00101101101100000000101110100000 00000010111110000000000010111010 00000000001011111000011000001000 10100000000000101100001000000000 00000000000000000000000000000000 00000000000000000000000000000000 00101000000001010100110000000000 10110011000000000010100011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010000001010100000010 00101100000000001000001110000000 00101100111100000000101100110000 00000010110010000000000010110011 00000000001011001111000000001010 00110000000000101100001000000000 01010000000000000000000000000000 00000000000000000000000000000000 10100000000000010001110000000000 10110111000000000010110111000000 00001011011100100000001011011100 00000000101101110000000000101101 11000000000010000110100000000010 00011100000000001000010100001000 00101101000000100000101101110000 00000010110110000000000010110111 00000000001011011110000000001000 01110000000000101100100000000000 01000000000000000000000000000000 00000000000000000000000000000000 10101000000010000001111000000000 11110111100000000011100111100000 00001111011110110000001111011110 00000000111101111000000000111101 11101000000011000110100000000011 01011111000000101100010110000000 00111101001000000000111101111000 00000011110110100000000011110111 10000000001111011110000000001110 01111000000100111100101000000010 00000000000000000000000000000000 00000000000000000000000000000000 00001000000111011010110000000000 11111011000000000011111011000000 00001111101101110000001111101100 00000000111110110000000100111110 11001100011011111010000000001011 11101100100000001111100100000000 00111110000000000000111110110000 00000011111010000000000011111011 00000000001111001100000000001111 10110000000000111100001000000110 01100000000000000000000000000000 00000000000000000000000000000000 11000000000001011111111001000000 11111111100000000011111111100000 00001111111110000000001100111110 00000000111111111000000000111011 11110000000011000110100000100011 00111111000001001111110110000010 00110011001000000000111111111000 00000011001110100100001011001111 10000000001111111110000000001111 11111000000000111101100000000000 00100000000000000000000000000000 00000000000000000000000000000000 10101000000100011001110000000000 10110111000000000010110111000000 00001011011100000000001101011100 00000000101101110000000000111011 11001000000011010110011000000010 00111100000000001010010100000000 00100001000100000000101101110000 00000010000110000000000010000111 00000000001011010000000000011011 01110000000000111110101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00010000000000001001110000010000 10110111000000000010110111000000 00001011011100000000001001011100 00000000101101110000000000101001 11000000100010000110000000000010 00011100000000001011010100000000 00100001000000000000101101110000 00000010000110010000100110000111 00000000001011011100000000001011 01110000000000101100010010000000 00100000000000000000000000000000 00000000000000000000000000000000 01100000000101001100110000000000 10110011000000000010110011000000 10001011101100000000001001001100 00000000101100110000000000101010 11000000001010010010000000001010 00001100000000001010000100000000 00100000000000000000101100110000 00000010000010100000000010000011 00000000001011000000000000011011 00110000000000101001100100000100 00100000000000000000000000000000 00000000000000000000000000000000 11101000000101011010110000000000 11111011000000000011111011000000 00001111111100000000001001101100 00000000111110110000000000111011 11000000000010001010000000000011 00111100000000101111100100000000 10110010000000000000111110110000 00001010001010011000000010001011 00000000001111100000000000001011 10110000000000101110111000000000 01100000000000000000000000000000 00000000000000000000000000000000 10010100000000001110110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011110010010000000011 11101100000000001111000100000000 00111110000100000000111100110000 00000011110010000000000011111011 00000000001111100000000000001111 10110000000000111110000000000100 00110000000000000000000000000000 00000000000000000000000000000000 10000000000100001111110000000000 11111111000000000011111111000000 00011111111100000000001100111100 00000000111111110000000000111111 11000000000011001110001000000011 00111100000000001110100100010000 00110001000000000000110010110000 00000011001010000000000011001111 00000000001111110010000000001100 11110000000000111110010001000100 00110000000000000000000000000000 00000000000000000000000000000000 10000000000001000110110000000000 10111011000000000010111011000000 00001011101100000000001010101100 00000000101110110000000000100110 11000000000011011010110000000010 00101100000000001101100100000000 00100010001100000010100010110000 00001010001010000000000010001011 00000000001011000001000000001010 10110000001000101110000001000000 00010000000000000000000000000000 00000000000000000000000000000000 10000000000001010010110000000000 10111011000000000010111011000000 00001011101100000000011000101100 00000000101110110000000000100110 11000000000010001010000000000010 00001100000000001010100100000000 00100010001000000000100010110000 00000010101010000000000010001011 00000000001011101101100000001000 10110000000000101110000000000000 01010000000000000000000000000000 00000000000000000000000000000000 00001000000001000000110000000000 10110011000000000010110011000000 00001011001100000000001010001100 00000000101100110000000000100100 11000000000010010010000000000010 00001100000000001001000100000000 10100000000000000010100000110000 00011010100010000000000010000011 00000000001011000000000000000010 00110000000000101100101000000100 00000000000000000000000000000000 00000000000000000000000000000000 10000000000011010110110000000000 10111011000000000011111011000000 00001011011100000000001100101100 00000000111110110000000000110111 11000000000011001010000000001011 00111100000000101110100100000000 00110010000000000000110010110000 00010011101010000000001011001011 00000000001111101100000000001100 10110000000000111110000000100010 00010000000000000000000000000000 00000000000000000000000000000000 10100000000111011111110000000000 11111111000000000011111111000000 00001111111100000000001111111100 00000000111111110000000000110111 11000000000011111110000000000011 11111100000000001111110100000010 00111111000000000000111111110000 00000011011110000000000011111111 00000000001111110000000000001111 11110000000100111110100000000100 01110000000000000000000000000000 00000000000000000000000000000000 11000000000001011111111000000000 11111100000000000011001111100000 00001111111110000000001111111110 00000000111111111000000000111111 11100000110011111110100001000011 00111110000000001111111110000000 00111111111000000000110111111000 00000011111111100000000011111111 10000000001111111110000000001111 11111000000000111111000000000000 01110000000000000000000000000000 00000000000000000000000000000000 10000000000100001110111000000000 10111000110000000010001011100000 00001011101110000000001011101110 00000000101110111000000000101110 11100000100010111001100000000010 00101110000000001011101110000000 00101110111000000000101110111000 00000010111011100000000010111011 10000000001011101110000000001011 10111000000000101111000000000110 00110000000000000000000000000000 00000000000000000000000000000000 10001000000001011100110000000000 10110000010000001010000011000000 00001011001100000000001011001100 00000000101000110000000000101100 11000000000010111011000000000010 00001100000010001011001100000000 00101100110000000000100100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101111001000000001 01110000000000000000000000000000 00000000000000000000000000000000 11000000000101011010110000000000 10111000000110000010001011000000 00001011101100000000001011101100 00000000101110110000000000101110 11000000000010111011100000000010 00101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000000011101100000000001011 10110000000000101111000000000000 01100000000000000000000000000000 00000000000000000000000000000000 01000000000101011110110000000000 11111100110000000011001011000000 00001111101100000000001111101100 00000000111010110000000000111110 11000000000011111010100000000011 00101100000000001111101100000000 00111110110000000000110110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111101010000000100 01110000000000000000000000000000 00000000000000000000000000000000 11100000000000011011110000000000 11110000100000000011111111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111111100000000000 01100000000000000000000000000000 00000000000000000000000000000000 01000000000100001010110000000000 11111010011000001011001011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011001000000011 10101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111101010000000100 00100000000000000000000000000000 00000000000000000000000000000000 11001000000001010010111000000000 10111000010000000110001011000000 00001011101100000000001011101100 00000000101110110000000000001110 11000000000010110011000000000011 01101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101111001000000000 01000000000000000000000000000000 00000000000000000000000000000000 11100000000001010100110000000000 10110011100100000010000011000000 00000011001100000000001011001100 00000000101100110000000000001100 11000000000010110010010000000010 10001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101111100000000000 00010000000000000000000000000000 00000000000000000000000000000000 00100000000000010001111000000000 10110111100000000010000111100000 00001001011110000000001001011110 00000001101101111000000000101101 11100000000010110111100100000010 01011110000000001011011110000000 00101101111000000000101101111000 00000010110111100000000010010111 10000000001011011110000000001011 01111000000000101110110000000100 00010000000000000000000000000000 00000000000000000000000000000000 01001000000010000000110000100000 11110011000000000010000011000000 00001111001100000000001111001100 00000000111100110000000000111100 11000000000011110011000000000011 10001100010000001111001100000000 00111100110000000000111100110000 00000011110011000000000011110011 00000000001111001100000000001111 00110000000000111101101000000010 00010000000000000000000000000000 00000000000000000000000000000000 01000000000111011011110000000000 11111111000100000011111111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011110111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111101000000000100 01100000000000000000000000000000 00000000000000000000000000000000 10101000000001011110110000000000 11111000000000000011001011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011110010000000000011 00101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111100001000000000 01110000000000000000000000000000 00000000000000000000000000000000 01001000000100011001110000000000 10110110000000000010000111000000 00001011011100000000001011011100 00010000101101110000000000101101 11000000000010110111000000000010 10011100000000001011011100000000 00111101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101111001000000110 01100000000000000000000000000000 00000000000000000000000000000000 11000000000000001001111000000000 10110010100000000010010111100000 00001011011110000000001011011110 00000000101101111000000000101101 11100000000010110111100000000010 00011110000000001011011110000000 00101101111000000000101101111000 00000010110111100000000010110111 10000000001011011110000000001011 01111000000000101100100000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000101001100110000000000 10110010011100000010000011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000100000010 10001100000000001011001100000000 00101000110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101101001000000000 00110000000000000000000000000000 00000000000000000000000000000000 11101000000101011010100000000000 11111110000000001011011010000001 00001111101000000000001111101000 00000000111110100000000000111110 10000000000011110110100000000011 00101000000000001111101000000000 00101110100000000000111110100000 00000011111010000000000011111010 00000000001111101000000000001111 10100000000000111111101000000100 01110000000000000000000000000000 00000000000000000000000000000000 01001000000000001110000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000010000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111101001000000000 01100000000000000000000000000000 00000000000000000000000000000000 00001000000100001110010000000000 11111001000000000011001001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000001011 00100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111100001000000100 00100000000000000000000000000000 00000000000000000000000000000000 10000000000001000110010100000000 10110001110000000010001001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000000010111001000100000010 00100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000001000101110000000000000 00010000000000000000000000000000 00000000000000000000000000000000 00011000000001010010010100000000 10111001001000000010001001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000000010111001000000000010 00100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101100111000000000 01000000000000000000000000000000 00000000000000000000000000000000 00001000000001000000010000000000 10110011001000000010000001000000 00001011000100000000001011000100 00000000101100010000000000101100 01000000000010110011000000000010 00000100000000001011000100000000 00101100010000000000101100010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101100101000000101 00000000000000000000000000000000 00000000000000000000000000000000 10111000000011010110000000000000 11111000000000001011001000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 00100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111110111000000011 01010000000000000000000000000000 00000000000000000000000000000000 10011000000111011110010000000000 11111101000100000011111001000000 00001111100100000000001111100100 00000000101110010000000000111110 01000000000011111101000000000011 11100100000000001111100100000000 01111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111110011000000100 01110000000000000000000000000000 00000000000000000000000000000000 00011000000001011110010000000000 11111101100000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111101000001000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111100011000000000 01110000000000000000000000000000 00000000000000000000000000000000 00111000000100001110000000000000 10111000000000000010111000000000 00001011100000000000001011100000 00000000101110000000000000101110 00000000000010111000000000000010 11100000000000001011100000000000 00101110000000000000101110000000 00000010111000000000000010111000 00000000001011100000000000001011 10000000000000101100111000000110 00110000000000000000000000000000 00000000000000000000000000000000 00001000000001011100010000000000 10110001010000000010110001000000 01001011000100000000011011000100 00000001101100010000000000101100 01000000000010110001000000000010 11000100000000001011000100000000 00101100010000000000101100010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101101001000000000 00100000000000000000000000000000 00000000000000000000000000000000 00011000000101011010010000000000 10111001000000000010111001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000000010111001010000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101100011000000000 00100000000000000000000000000000 00000000000000000000000000000000 10100000000101011110010000000000 11111001000000000010111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001110100000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111110100000000100 01110000000000000000000000000000 00000000000000000000000000000000 00101000000000011010110000100000 11111001010000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000110011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111101001000000000 01100000000000000000000000000000 00000000000000000000000000000000 00101000000100001010000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000001000000011 00100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111100001000000100 00100000000000000000000000000000 00000000000000000000000000000000 00101000000001010010101110000000 10111110101000000010111010000000 00001011101000000001001011101000 00000000101110100000000000101110 10000000000010111110011000000011 01101000000000001011101000000000 00101110100000000000101110100000 00000010111010000000000010111010 00000000001011101000000000001011 10100000000000101100101000000000 01000000000000000000000000000000 00000000000000000000000000000000 00101000000001010100100100000000 10110010000000000010110011000000 00001011001100000000001011001100 00000001101100110000000000101100 11000000000010110011000000000010 00001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101100101000000000 01010000000000000000000000000000 00000000000000000000000000000000 10100000000000010001000000000000 10110100000000000010110111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010110111100000000010 01011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101110000000000100 01000000000000000000000000000000 00000000000000000000000000000000 10101000000010000001101000001000 11110111100000000010110111100001 10001111011110000000001111011110 00000000111101111000000000111101 11100000010011110111100000100011 00011110000000001111011110000000 00111101111000000000111101111000 00000011110111100000000011110111 10000000001111011110000000001111 01111000000000111110001000000010 00000000000000000000000000000000 00000000000000000000000000000000 00001000000111011010000110101000 11111010000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011110011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001101101100000000001111 10110000000000111100001000000100 01100000000000000000000000000000 00000000000000000000000000000000 00000000000001011111111000000000 11100100100100000011101111100000 00001111111110000000001111111110 00000000111111111000000000111111 11100000000011111111100000000011 10111110010000001111111110010000 00111111111001000000111111111000 00000011111111100000000011111111 10000000001111111110000000001111 11111000000000111100000000000100 00100000000000000000000000000000 00000000000000000000000000000000 10101000000100011001010100000000 10000100000000000010000111000100 00001011011100000000001011011100 00000000101101110000000000101101 11000001000010110111000000000010 10011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101110101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00000000000000001001110000000000 10100101000000000110100111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010111111010010000010 00011100000001001011011100000001 00101101110000000000001101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101100000000000000 00100000000000000000000000000000 00000000000000000000000000000000 00100000000101001100010000000000 10000000100000000110000011000000 00001011001100000000001011001100 00000000101100110000000001101100 11000000000010110011100000000010 10001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101100100000000000 00100000000000000000000000000000 00000000000000000000000000000000 10101000000101011010100000000000 11100010000010000011101011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011110010010000000011 10101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111110101000000000 01000000000000000000000000000000 00000000000000000000000000000000 10000000000000001110100100000000 11111000000000000011111011000000 00001111101100000000001111101100 00000100111110110000000000111110 11000000000011111011010000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001011101100000000001111 10110000000000111110000000000000 00110000000000000000000000000000 00000000000000000000000000000000 00000001000100001111111000000000 11111111000000100011101111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111101000000000011 00111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000001001111 11110000000100111100100001000000 00110000000000000000000000000000 00000000000000000000000000000000 10000001010001000110111100000000 10111011010000000010001011000001 00001011101100000000001001101100 00000000101110110000000000111010 11000000000010111001100000000010 10101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101110100001000100 00010000000000000000000000000000 00000000000000000000000000000000 10000000000001010010000001000000 10111000010000000010101011000000 00011011101100000000001011101100 00000000101110110000000000101110 11000000000010111011100010000010 00101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101110000000000000 01000000000000000000000000000000 00000000000000000000000000000000 00001000000001000000000000000000 10111000000000000010100011000000 00001011001100000000001001001100 00000000101100110000000000101000 11000000000010110011000000000010 10001100000000001011001100000000 00101100110000000000101100110000 00000010010011000000000010110011 00000000001011001100000000001011 00110000000000101100001000000101 00000000000000000000000000000000 00000000000000000000000000000000 00000000000011010110010000000000 11111001000000000011101011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 00101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111100000000100011 01010000000000000000000000000000 00000000000000000000000000000000 10100000000110011101010000000000 11111101000000000011011111000000 00001111111100000000001111111100 00000000111111110000000000111011 11000000000011110111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111110100100000000 01110000000000000000000000000000 00000000000000000000000000000000 11000000000001011111111000000000 11111111100000000011111111100000 00001111111110000000001111111110 00000000111111111000000000110111 11100000000011001111100000000011 11111110000000001111111110000000 00111111111000000000111111111000 00000011111111100000000011111111 10000000001111111110000000001111 11001000000000111111000000000101 01100000000000000000000000000000 00000000000000000000000000000000 10000000000100001110111000000000 10111011100000000010111011100000 00001011001100000000001011101110 00000000101100110000000000100010 11000000000011011011100000000010 11101110000000001011101110000000 00101110111000000000101110111000 00000010111011100000000010111011 10000000001011101110000000001011 10101000000000101110000000000110 00110000000000000000000000000000 00000000000000000000000000000000 10001000000001011100110000000000 10110011000000000010110011000000 00001011001100000000001010001100 00000000101100110000000000100100 11000000000010000011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00010000000000101110001000000001 00110000000000000000000000000000 00000000000000000000000000000000 11000000000101011010110000000000 10111011000000000010111011000000 00001011101100000000001011101100 00000000101110110000000000100010 11000000000010011011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10000100010000101111000000000000 01100000000000000000000000000000 00000000000000000000000000000000 01000000000101011110110000001000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000110110 11000000000011001011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10000000000000111100000000000100 01110000000000000000000000000000 00000000000000000000000000000000 11100000000000011011110000000000 10111111000000000011111111000000 00001101111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001101111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11100000000000111111100000000000 01100000000000000000000000000000 00000000000000000000000000000000 01000000000100001010110000000000 11111011000000000011111011000000 00001101101100000000001110101100 00000000111110110000000000111010 11000000000011101011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110100000000111101000000000100 00100000000000000000000000000000 00000000000000000000000000000000 11001000000001010010110000000000 10111011000000000010111011000000 00001011101100000000001000101100 00000000101110110000000000100010 11000000000010001011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10100000000000101111001000000000 01000000000000000000000000000000 00000000000000000000000000000000 11100000000001010100110000000000 10110011000000000010110011000000 00001011001100000000001010001100 00000000101110110000000000101010 11000000000010100011000000000010 11001100000000001001001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00000000000000101111100000000000 01010000000000000000000000000000 00000000000000000000000000000000 00100000000000010001111000000000 10110111100000000010110111100000 00001011011110000000001000011110 00000000101101111000000000100001 11100000000010000111100000000010 11011110000000001011011110000000 00101101111000000000101101111000 00000010110111100000000010110111 10000000001011011110000000001011 01111000000000101101100000000000 01000000000000000000000000000000 00000000000000000000000000000000 01001000000010000000110000000000 11110011000000000011110011000000 00001111001100000000001110001100 00000000111100110000000000111010 11000000000011100011000000000011 11001100000000001111001100000000 00111100110000000000101100110000 00000011110011000000000011110011 00000000001111001100000000001111 00010000000000111101001000000010 00000000000000000000000000000000 00000000000000000000000000000000 01000000000111011011110000000000 11111111000000000011111111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11010000000000111101000000000110 01100000000000000000000000000000 00000000000000000000000000000000 10101000000001011110110000000000 11111011000000000011111011000000 00001111101110000000001101101100 00000000111110111000000000110010 11000000001011001011000000000011 11101100000000001111101100000000 00111110110000000000111010110000 00000011111011000000000011111011 00000000001111101100000000001111 10001000000000110110101000000000 01110000000000000000000000000000 00000000000000000000000000000000 01001000000100011001110000000000 10110111000000000010110111000000 00001011111100000000001000011100 00000000101101110000000000100011 11000000000010000111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000010001011 01110000000000100001001000000100 01100000000000000000000000000000 00000000000000000000000000000000 11000000000000001001111000000000 10110111100000000010110111100000 00001011011110000000001001011110 00000000101101111000000010100001 11100000000010000111100000000010 11011110000000001011011110000000 00101101111000000000101101111000 00000010110111100000000010110111 10000000001011011110000000001011 11111000000000100111000000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000101001100110000000000 10110011000000000010110011000000 00001011001100000000001000001100 00000000101100110000000000100000 11000000000010000011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000100001001000000100 00110000000000000000000000000000 00000000000000000000000000000000 11101000000101011010100000000000 11111010000000000011111010000000 00001111101000000000001101101000 00000000111110100000000000110010 10000000000011001010000000000011 11101000000000001111101000000000 00111110100000000000111110100000 00000011111010000000000011111010 00000000001111101000000000001111 11101000100000110111101000000100 01100000000000000000000000000000 00000000000000000000000000000000 01001000000000001110000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111101001000000000 00110000000000000000000000000000 00000000000000000000000000000000 00001000000100001110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011001001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111100001000000100 00110000000000000000000000000000 00000000000000000000000000000000 10000000000001000110010000000000 10111001000000000010111001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000001010001001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101110000000000000 00010000000000000000000000000000 00000000000000000000000000000000 00011000000001010010010000000000 10111001000000000010111001000000 00001011100100000000001011100100 00000000101110010000000000101100 01000000000010001001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101100011000000000 01000000000000000000000000000000 00000000000000000000000000000000 00001000000001000000010000000000 10110001000000000010110001000000 00001011000100000000001011000100 00000000101100010000000000101100 01000000000010000001000000000010 11000100000000001011000100000000 00101100010000000000101100010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101100001000000001 00000000000000000000000000000000 00000000000000000000000000000000 10111000000011010110000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111100000000000000111110 00000000000011001000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111110111000000011 01010000000000000000000000000000 00000000000000000000000000000000 10011000000111011110010000000000 11111001000000000011111001000000 00001111100100101000001111100100 00000000111110011010100000111110 01101010000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 01010000000000111110011000000110 01110000000000000000000000000000 00000000000000000000000000000000 00011000000001011110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000110010 01000000000011001001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111110011000000000 01110000000000000000000000000000 00000000000000000000000000000000 00111000000100001110000000000000 10111000000000000010111000000000 00001011100000000000001011100000 00000000101110000000000000101000 00000000000010101000000000000010 11100000000000001011100000000000 00101110000000000000101110000000 00000010111000000000000010111000 00000000001011100000000000001011 10100000000000101100111000000100 00110000000000000000000000000000 00000000000000000000000000000000 00001000000001011100010000000000 10110001000000000010110001000000 00001011000100000000001011000100 00000000101100010000000000100000 01000000000010000001000000000010 11000100000000001011000100000000 00101100010000000000101100010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101100001000000001 01110000000000000000000000000000 00000000000000000000000000000000 00011000000101011010010000000000 10111001000000000010111001000000 00001011100100000000001011100100 00000000101100010000000000101010 01000000000010101001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101100011000000100 01100000000000000000000000000000 00000000000000000000000000000000 10100000000101011110010000001000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000110010 01000000000011001001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111110100000000100 00100000000000000000000000000000 00000000000000000000000000000000 00101000000000011010010000000000 10111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10011010000000111100101000000000 00100000000000000000000000000000 00000000000000000000000000000000 00101000000100001010000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000110010 00000000000011001000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111100101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00101000000001010010100000000000 10111010000000000010111010000000 00001001101000000000001001101000 00000000101110100000000010100010 10000000001010001010000000000010 11101000000000001011101000000000 00101110100000000000101110100000 00000010111010000000000010111010 00000000001011101000000000001011 10100000000000101100101000000000 00000000000000000000000000000000 00000000000000000000000000000000 00101000000001010100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000100010 11000000000010000011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101100101000000000 01010000000000000000000000000000 00000000000000000000000000000000 10100000000000010001110000000000 10110111000000000010110111000000 00001001011100100000001001011100 00000000101101110001000000100001 11000000000010000111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101100100000000000 01000000000000000000000000000000 00000000000000000000000000000000 10101000000010000001111000000000 11110111100000000011110111100000 00001111011110000000001111011110 00000000111111111010000000110001 11100000000011000111100000000011 11011110000000001111011110000000 00111101111000000000111101111000 00000011110111100000000011110111 10000000001111011110000000001111 01111000000000111100101000000010 00000000000000000000000000000000 00000000000000000000000000000000 00001000000111011010110000000000 11111011000000000011111011000000 00000101101100011000001001101100 00000000111110110000100000111110 11010100000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011011011000000000011111011 00000000001111101100000000001111 10110000000000111100001000000110 01100000000000000000000000000000 00000000000000000000000000000000 00000000000001011111111000000000 11111111100000000011111111100000 00001111111110000000001100111110 00000000111111111000000000111011 11110000000011011111100000000011 11111110000000001111111110000000 00111111111000000000111111111000 00000011111111100000000011111111 10000000001101111110000000001110 01111000000000110001000000000000 01110000000000000000000000000000 00000000000000000000000000000000 10101000000100011001110000000000 10110111000000000010110111000000 00001011011100000000001101011100 00000000101101110000000000110101 11000000000010100111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000100000110110101000000100 01100000000000000000000000000000 00000000000000000000000000000000 00000000000000001001110000000000 10110111000000000010110111000000 00001011011100000000001000011100 00000000101101110000000000101001 11000000000010010111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010010111000000000010110111 00000000001011011100000000001011 11110000000000100000010010000000 00100000000000000000000000000000 00000000000000000000000000000000 00100000000101001100110000000000 10110011000000000010110011000000 00001011101100000000001001001100 00000000101110110000000000100100 11000000000010100011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000010001011 00111100000000100101101000000100 00110000000000000000000000000000 00000000000000000000000000000000 10101000000101011010110000000000 11111011000000000011111011000000 00001111111100000000001100101100 00000000111111110000000000111011 11000000000011011011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001101101100000000001110 10111101000000110010101000000100 01100000000000000000000000000000 00000000000000000000000000000000 10000000000000001110110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111110010000000000 00110000000000000000000000000000 00000000000000000000000000000000 00000001000100001111110000000000 11111111000000000011111111000000 00001111111100000000001100111100 00000000111111110000000000110011 11000000000011001111000000000011 11111100000000001110111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000000001 11110000000000111110000001000100 00110000000000000000000000000000 00000000000000000000000000000000 10000001000001000110110000000000 10111011000000000010111011000000 00001011101100000000001010101100 00000000101110110000000000101010 11000000000010101011000000000010 11101100000000001001101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000000011101100000001001001 10110000001000101110000001000000 00010000000000000000000000000000 00000000000000000000000000000000 10000000000001010010110000000000 10111011000000000010111011000000 00001011101100000000001010101100 00000000101110110000000000100000 11000000000010001011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010111011000001000010111011 00000000001001101100000000001001 10110000000000101110000000000000 01010000000000000000000000000000 00000000000000000000000000000000 00001000000001000000110000000000 10110011000000000010110011000000 00001011001100000000001010001100 00000000101100110000000000101000 11000000000010100011000000000010 11001100000000001001001100000000 00101100110000000000101100110000 00000000110011000000000010110011 00000000001011001100000000001001 00110000000000101100001000000100 00000000000000000000000000000000 00000000000000000000000000000000 00000000000011010110110000000000 11111011000000000011111011000000 00001111011100000000001100101100 00000000111101110000000000110001 11000000000011001011000000000011 11101100000000001110101100000000 00111110110000000000111110110000 00000001111011000000000011111011 00000000001111101100000000001101 10110000000000111110000000000010 00010000000000000000000000000000 00000000000000000000000000000000 10100000000111011111110000000000 11111111000000000011111111000000 00001111111100000000001011111100 00000000111111110000001000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000011000001110100000000100 01110000000000000000000000000000 00000000000000000000000000000000 11000000000001011111111000000000 11101111100000000011101111100000 00001111111110000000001111111110 00000000111111111000000000111111 11100000000011111111100000000011 00111110000000001111111110000000 00111111111000000000111111111000 00000011111111100000000011111111 10000000001111111110000000001111 11111000000000111111000000000000 01110000000000000000000000000000 00000000000000000000000000000000 10000000000100001110111000000000 10111011100000000000111011100000 00001011101110000000001011101110 00000000101110111000000000101110 11100000000010111011100000010010 10101110000000001011101110000000 00101110111000000000111010111000 00000010111011100000000010111011 10000000001011101110000000001011 10111000000000101111000000000000 00110000000000000000000000000000 00000000000000000000000000000000 10001000000001011100110000000000 10110011000000000110100011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 00001100000010001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101111001000000001 01110000000000000000000000000000 00000000000000000000000000000000 11000000000101011010110000000000 10111011000000000010111011000000 00001011101100000000001011101100 00000000101110110000000000101110 11000000000010111011000000000010 10101100000000001011101100000000 00101110110000000000100110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101111000000000100 01100000000000000000000000000000 00000000000000000000000000000000 01000000000101011110110000000000 11101011000000000011101011000000 00001111101100000000001011101100 00000000111110110000000000111110 11000000000011111011000000000011 00101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111100010000000000 01110000000000000000000000000000 00000000000000000000000000000000 11100000000000011011110000000000 11111111000000000011111111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111011110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111111100000000100 01000000000000000000000000000000 00000000000000000000000000000000 01000000000100001010110000000000 11111011000000000011011011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111101000000000100 00100000000000000000000000000000 00000000000000000000000000000000 11001000000001010010110000000100 10111011000000000010111011000000 00001011101100000000001011101100 00000000101110110000000000101110 11000000000010110011110100000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101111011000000000 01000000000000000000000000000000 00000000000000000000000000000000 11100000000001010100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000100100110000000000101100 11000000000010110011000100000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101111000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00100000000000000001111000000000 10110111100000000010110111100000 00001011011110000000001011011110 00000000101101111000000000101101 11100001000010110111100000000010 11011110000000001011011110000000 00101101111000000000101101111000 00000010110111100000000010110111 10000000001011011110000000001011 01111000000000101110110000000000 00000000000000000000000000000000 00000000000000000000000000000000 01001000000010000000110000000000 11110011000000000011110011000000 00001111001100000000001111001100 00000000110100110000000000111100 11000000000011110011000000000011 11001100010000001111001100000000 00111100110000000000111100110000 00000011110011000000000011110011 00000000001111001100000000001111 00110000000000111101001000000110 00000000000000000000000000000000 00000000000000000000000000000000 01000000000111001011110000000000 11111111000000000011111111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000000 11111100000100001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001011111100000000001111 11110000000000111101000000000110 00100000000000000000000000000000 00000000000000000000000000000000 10101000000001011110110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000101100001000000000 01110000000000000000000000000000 00000000000000000000000000000000 01001000000100011001110000000000 10110111000000000010110111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101111001000000000 01100000000000000000000000000000 00000000000000000000000000000000 11000000000000001001111000000000 10100111100000000010110111100000 00001011011110000000001011011110 00000000101101111000000000101101 11100000000010110111100000000010 11011110000000001011011110000000 00101101111000000000101101111000 00000010110111100000000010110111 10000000001011011110000000001011 01111000000000101100100000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000101001100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101101101000000100 00110000000000000000000000000000 00000000000000000000000000000000 11101000000101011010100000000000 11101010000000000010111010000000 00001011101000000000001111101000 00000000111110100000000000111110 10000000000011111010000000000011 11101000000001001111101000000010 00111110100000000000111110100000 00000011111010000000000011111010 00000000001111101000000000001111 10100000000000101111101000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000000001110000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111101001000000100 00100000000000000000000000000000 00000000000000000000000000000000 00001000000100001110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001100000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111100001000000100 00100000000000000000000000000000 00000000000000000000000000000000 10000000000001000110010000000000 10111001000000000010111001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000000010111001000100000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101110000000000000 00010000000000000000000000000000 00000000000000000000000000000000 00011000000001010010010000000000 10111001000000000010111001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000000010111001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101100011000000000 01000000000000000000000000000000 00000000000000000000000000000000 00001000000001000000010000000000 10110001000000000010110001000000 00001011000100000000001011000100 00000000101100010000000000101100 01000000000010110001000000000010 11000100000000001011000100000000 00101100010000000000101100010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101100001000000001 00000000000000000000000000000000 00000000000000000000000000000000 10111000000011010110000000000000 11111000000001000111111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111010000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111110111000000111 01010000000000000000000000000000 00000000000000000000000000000000 10011000000111011110010000000001 11111001000000000111111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000001111110111000000110 01110000000000000000000000000000 00000000000000000000000000000000 00011000000001011110010000000000 11101001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111101000001000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001110 10010000000000111000111000000000 01110000000000000000000000000000 00000000000000000000000000000000 00111000000100001110000000000000 10111000000000000010111000000000 00001011100000000000001011100000 00000000101110000000000000101110 00000000000010111000000000000010 11100000000000001011100000000000 00101110000000000000101110000000 00000010111000000000000010111000 00000000001011100000000000001011 10000000000000101100011000000000 00100000000000000000000000000000 00000000000000000000000000000000 00001000000001011100010000000000 10100001000000000010110001000000 00001011000100000000001010000100 00000000101100010000000000101100 01000000000010110001000000100010 11000100000000001011000100000000 00101100010000000000101100010000 00000010110001000000000010110001 00000000001011000100000000001010 00010000000000101001001000000001 00100000000000000000000000000000 00000000000000000000000000000000 00011000000101011010010000010000 10111001000001000010111001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000000010111001000001000010 11100100000000001011100100000100 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000010000101100011000000100 00100000000000000000000000000000 00000000000000000000000000000000 10100000000101011110010000000000 11101001000000000011111001000000 00001011100100000000001110100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001110 10010000000000111010100000000000 00100000000000000000000000000000 00000000000000000000000000000000 00101000000000011010010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000100111111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111101101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00101000000100001010000000000000 11101000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000111111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111100101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00101000000001010010100000000000 10111010000000000010111010000000 00001011101000000000001011101000 00000000101110100000000000101110 10000000000010111110110100000010 11101000000000001011101000000000 00101110100000000000100110100000 00000010111010000000000011101010 00000000001011101000000000001011 10100000000000101100001000000000 00000000000000000000000000000000 00000000000000000000000000000000 00101000000001010100110000000000 10100011000000000010110011000000 00001011001100000000011011001100 00000000101100110000000000101100 11000000000010110011110000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101100101000000000 01010000000000000000000000000000 00000000000000000000000000000000 10100000000000010001110000010000 10110111000001000010110111000000 00001011011100000000001011011100 00000100101101110000000000101101 11000000000010110110010000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010100111 00000000001011011100000000001011 01110000000000101100100000000000 01100000000000000000000000000000 00000000000000000000000000000000 10101000000010000001111000000000 11100111100000000011110111100000 00001111011110000000001111011110 00000000111101111000000000111101 11100000000010110101100000000011 11011110000000001111011110000000 00111101111000000000111101111000 00000011110111100000000011110111 10000000001111011110000000001111 01111000000000111100101000000110 00000000000000000000000000000000 00000000000000000000000000000000 00001000000111011010110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000110110110000 00000011111011000000000011101011 00000000001111101100000000001111 10110000000000111100001000000110 01100000000000000000000000000000 00000000000000000000000000000000 00000000000000011111111000000000 11111111100000010011111111100000 01001111111110000010001111111110 00000000111111111000000000111111 11100000000011111111100000000011 11111110000000001111111110000000 00111111111000000000111111111000 00000011111111100000000011111111 10000000001111111110000000001111 11111000000000111101000000000100 00100000000000000000000000000000 00000000000000000000000000000000 10101000000100011001110001000000 11110111000100000010110111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010110111010000000010 11011100000000001110011100000000 00111001110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101110101000000010 00100000000000000000000000000000 00000000000000000000000000000000 00000000000000001001110000000000 10110111000000000010110111000000 00001011011100000000001011011100 00000000101001110000000000100101 11000000000010100111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101100000000000000 00100000000000000000000000000000 00000000000000000000000000000000 00100000000101001100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001010001100000000 00101000110000000000100100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101101000000000000 00100000000000000000000000000000 00000000000000000000000000000000 10101000000101011010110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000110110 11000000000011101000000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111110101100000100 01100000000000000000000000000000 00000000000000000000000000000000 10000000000000001110110000000000 11101011000000000011111011000000 00001111101100000000001111101100 00000100111110110000000000111110 11000000000011111000000000000011 11101100000010001111101100000000 00111110110000000001111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111110100000000000 00010000000000000000000000000000 00000000000000000000000000000000 00000001000100001111110000000000 11111111000000000011111111000000 00001111111100000000001111111100 00000000111011110000000000111111 11000000000011111101000000000011 11111100000000001111111100000000 00111111110000000001111111110000 00100011111111000000000011111111 00000000001111111100000001001111 11110000000100111100000101000100 00110000000000000000000000000000 00000000000000000000000000000000 10000001000001000110110000000000 11101011000000000010111011000000 00001011101100000000001011101100 00000000101110110000000000101110 11000000000010111001110000000010 11101100000000001001101100000000 00101110110000000001101110110000 00000010111011000000000011101011 00000000001011101100000000001011 10110000000000101110000001000000 00010000000000000000000000000000 00000000000000000000000000000000 10000000000001010010110000000000 10111011000000000010111011000000 00001011101100000000001011101100 00000000101110110000000000101010 11000000000010111001100000000110 11101100000000001011101100000001 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101110000000000000 01010000000000000000000000000000 00000000000000000000000000000000 00001000000001000000110000000000 10100011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110001000000000110 11001100000000001001001100000000 00101100110000000000101100110000 00000010110011000000000010100011 00000000001011001100000000001011 00110000000000101100001000000001 00000000000000000000000000000000 00000000000000000000000000000000 00000000000011010110110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111010 11000000000010111001000000000011 11101100000000001111101100000000 00111110110000000000101110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111100000000100110 00010000000000000000000000000000 00000000000000000000000000000000 10100000000111011111110000000000 11111111000000000011111111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111101000000000000 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000010001111111100000000001111 11110000000000111110100000000011 01100000000000000000000000000000 00000000000000000000000000000000 11000000000001011111111000000000 11111111100000000011111111100000 00001111111110000000001111111110 00000000111111111000000000111111 11100000000011111111100000000011 11111110000000001111111110000000 00111111111000000000111111111000 00000011111111100000000011111111 10000000001111111110000000001111 11001000000000110011000000000000 01110000000000000000000000000000 00000000000000000000000000000000 10000000000100001110111000000000 10111011100000000010111011100000 00001011101110000000001011101110 00000000101110111000000000101110 11100000000010111011100000000010 11101110000000001011101110000000 00101110111000000000101110111000 00000010111011100000000010111011 10000000001011101110000000001011 10001000000000100011000000000000 00110000000000000000000000000000 00000000000000000000000000000000 10001000000001011100110000000000 10100011000000000010110011000000 00001011001100000000001010001100 00000000101100110000000000101000 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010100011000000000010110011 00000000001011001100000000001011 10000000000000100011001000000001 01110000000000000000000000000000 00000000000000000000000000000000 11000000000101011010110000000000 10111011000000000010111011000000 00001011101100000001001011101100 00000000101110110000000000100110 11000000000010111011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000010100011000000000100 01100000000000000000000000000000 00000000000000000000000000000000 01000000000101011110110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10100100100000110000000000000000 01110000000000000000000000000000 00000000000000000000000000000000 11100000000000011011110000000000 11111111000000000011111111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011011111000000000011111111 00000000001111111100000000001111 11000000000000111111100000000100 01100000000000000000000000000000 00000000000000000000000000000000 01000000000100001010110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000100111110110000001000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10100000000000111101000000000100 00100000000000000000000000000000 00000000000000000000000000000000 11001000000001010010110000000000 10111011000000000010111011000000 00001011101100000000001011101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000001001011 00110000000000101111011000000000 01000000000000000000000000000000 00000000000000000000000000000000 11100000000001010100110000000000 10110011000000000010110011000000 00001001001100000000001001001100 00000000101100110000000000100100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010010011000000000010110011 00000000001011001100000000001011 00010000000000101111101000000000 00000000000000000000000000000000 00000000000000000000000000000000 00100000000000010001111000000000 10110111100000000010110111100000 00001011011110000000001011011110 00000000101101111000000000101101 11100000000010110111100000000010 11011110000000001011011110000000 00101101111000000000101101111000 00000010110111100000000010110111 10000000001011011110000000001011 01011000000000101111110000000000 00000000000000000000000000000000 00000000000000000000000000000000 01001000000010000000110000000000 11110011000000000011110011000000 00001101001100000000001111001100 00000000111100110000000000111100 11000000000011110011000000000011 11001100000000001111001100000000 00111100110000000000111100110000 00000011110011000000000011110011 00000000001111001100000000001111 00000000000000111101101000000110 00000000000000000000000000000000 00000000000000000000000000000000 01000000000111011011110000000000 11111111000000000011111111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111101000000000110 00100000000000000000000000000000 00000000000000000000000000000000 10101000000011011110110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111010110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111100001000000000 01110000000000000000000000000000 00000000000000000000000000000000 01001000000000011001110000000000 10110111000000000010110111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01010000000000101111001000000000 01100000000000000000000000000000 00000000000000000000000000000000 11000000000000001001111000000000 10110111100000000010110111100000 00001011011110000000001011011110 00000000101001111000000000101001 11100000000010110111100000000010 11011110000000001011011110000000 00101101111000000000101101111000 00000010110111100000000010110111 10000000001011011110000000001011 01101000000000101100100000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000101001100110000000000 10110011000000000010110011000000 00001011001100000001011011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101101001000000100 00110000000000000000000000000000 00000000000000000000000000000000 11101000000101011010100000000000 11111010000000000011111010000000 00001111101000000000001111101000 00000000111010100000000000111110 10000000000011111010000000000011 11101000000000001111101000000000 00111110100000000000111110100000 00000011111010000000000011111010 00000000001111101000000000001111 11100000100000111111101000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000000001110000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111101001000000100 00100000000000000000000000000000 00000000000000000000000000000000 00001000000100001110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000110110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111100001000000100 00100000000000000000000000000000 00000000000000000000000000000000 10000000000001000110010000000000 10111001000000000010111001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000000010111001000000000011 11100100000000001011100100000000 00101110010000000000100110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101110000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00011000000001010010010000000000 10111001000000000010111001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000000010111001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010101001000000000010111001 00000000001011100100000000011011 10010000000000101100011000000000 01000000000000000000000000000000 00000000000000000000000000000000 00001000000001000000010000000000 10110001000000000010110001000000 00001011000100000000001011000100 00000000100100010000000000101100 01000000000010110001000000000010 11000100000000001011000100000000 00101100010000000000101100010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101100001000000001 00100000000000000000000000000000 00000000000000000000000000000000 10111000000001010110000000000000 11111000000000000010111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011101000000000000011111000 00000000001111100000000000001111 10000000000000111110111000000111 01010000000000000000000000000000 00000000000000000000000000000000 10011000000101011110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 10100100000000001111100100000000 00111110010000000000110110010000 00000011111001000000000011111001 00000000001111100100000000001111 11010000000000111110111000000110 01110000000000000000000000000000 00000000000000000000000000000000 00011000000001011110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 00010000000000111110111000000000 01110000000000000000000000000000 00000000000000000000000000000000 00111000000100001110000000000000 10111000000000000010111000000000 00001011100000000000001011100000 00000000101110000000000000101110 00000000000010111000000000000010 11100000000000001011100000000000 00101110000000000000101110000000 00000010111000000000000010111000 00000000001011100000000000001011 10000000000000101100011000000000 00110000000000000000000000000000 00000000000000000000000000000000 00001000000001011100010000000000 10110001000000000010100001000000 00001011000100000000001011000100 00000000101100010000000000101100 01000000000010110001000000000010 11000100000000001011000100000000 00101100010000000000101100010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101101001000000000 00100000000000000000000000000000 00000000000000000000000000000000 00011000000101011010010000000000 10111001000000000010111001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000000010111001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000011011 10010000100000101100011000000100 00100000000000000000000000000000 00000000000000000000000000000000 10100000000101011110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010100001000111110100000000000 00100000000000000000000000000000 00000000000000000000000000000000 00101000000000011010010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10011010000000111101101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00101000000100001010000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000100000000110000101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00101000000001010010100000000000 10111010000000000010111010000000 00001011101000000000001011101000 00000000101110100000000000101110 10000000000010111010000000000010 11101000000000001011101000000000 00101110100000000000101110100000 00000010111010000000000010111010 00000000001011101000000000001011 10100000000000100000001000000000 00000000000000000000000000000000 00000000000000000000000000000000 00101000000001010100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000100100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000001001011 00110000000000100100001000000000 01010000000000000000000000000000 00000000000000000000000000000000 10100000000000010001110000000000 10110111000000000010110111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 11111000000000100100100000000000 01000000000000000000000000000000 00000000000000000000000000000000 10101000000010000001111000000000 11110111100000000011110111100000 00001111011110000000001111011110 00000000111101111000000000111101 11100000000011110111100000000011 11011110000000001111011110000000 00111101111000000000111101111000 00000011110111100000000011110111 10000000001111011110000000001111 01111000000000110100101000000110 00000000000000000000000000000000 00000000000000000000000000000000 00001000000111011010110000000000 11111011000000000011111011000001 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000010001111 10110000000010111000001000000110 01100000000000000000000000000000 00000000000000000000000000000000 00000000000001011111111000000000 11111111100000000011111111100000 00001111111110000000001111111110 00000000111111111000000000111111 11100000000011111111100000000011 11111110000000001111111110000000 00111111111000000000111111111000 00000011111111100000000011111111 10000000001111111110000000001111 11111000000000111101100000000000 00100000000000000000000000000000 00000000000000000000000000000000 10101000000100011001110000000000 10110111000000000010110111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000100001011011100000000001011 01110010000000101110101000000000 00100000000000000000000000000000 00000000000000000000000000000000 00000000000000001001110000000000 10110111000000000010110111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101100010010000000 00100000000000000000000000000000 00000000000000000000000000000000 00100000000101001100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000011011 00111100000000101101000000000100 00100000000000000000000000000000 00000000000000000000000000000000 10101000000101011010110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10111000100000111110101000000000 01100000000000000000000000000000 00000000000000000000000000000000 10000000000000001110110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000001001111101100000000001111 10110000000000111110110000000100 00110000000000000000000000000000 00000000000000000000000000000000 00000001000100001111110000000000 11111111000000000011111111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000100000111110000001000100 00110000000000000000000000000000 00000000000000000000000000000000 10000001000001000110110000000000 10111011000000000010111011000000 00001011101100000000001011101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010111011000001000010111011 00000000001011101100000101001011 10110000001000101110000101000000 00010000000000000000000000000000 00000000000000000000000000000000 10000000000001010010110000000000 10111011000000000010111011000000 00001011101100000000001001101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101110000000000000 01010000000000000000000000000000 00000000000000000000000000000000 00001000000001000000110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101100001000000001 00000000000000000000000000000000 00000000000000000000000000000000 00000000000011010110110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111110000000100110 00000000000000000000000000000000 00000000000000000000000000000000 10100000000111011111110000000000 11111111000000000011111111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000010100111110100000000110 01110000000000000000000000000000 00000000000000000000000000000000 11000000000001011111111000000000 11101111100000000011111111100000 00001111111110010000001101110000 10000000110011111000000000111011 11100000000011111111000000000011 00110010000000001111111110000000 00111111111000000000111111111000 00000011111111100000000011111111 10000000001111111110000000001111 11111000000000111111000000000100 01110000000000000000000000000000 00000000000000000000000000000000 10000000000100001110111000000000 11111011100000000011101011100000 00001011101100000000001000101011 00000000100010111000000000111010 11100000000010111011110100000010 00100000000000001011101110000000 00101110111000000000101110111000 00000010111011100000000010111011 10000000001011101110000000001011 10111000000000101110000000000000 00110000000000000000000000000000 00000000000000000000000000000000 10001000000001011100110000000000 10110011000000000010110011000000 00001011001100000000101000000000 01000100100000110000000001101100 11000000000010110011000000000110 00000100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101110001000000001 01110000000000000000000000000000 00000000000000000000000000000000 11000000000101011010110000000000 10111011000000000010111011000000 00001011001100000000001000100001 00000000100010110000000000101110 11000000000010111011000001000010 00100110001000001011101100000000 00101110110000000000101110111000 10000010111011000000000010111011 00000000001011101100000000001011 10110000000000101111000000000000 01100000000000000000000000000000 00000000000000000000000000000000 01000000000101011110110000000000 11101011000000000011111011000000 00001111101100000000001101100110 01000010110010110000000000111110 11000000000011111011000000000011 00100010000000001111101100000000 00111110110000000000111110111000 00100011111011000000000011111011 00000000001111101100000000001111 10110000000000111100000000000000 01110000000000000000000000000000 00000000000000000000000000000000 11100000000000011011110000000000 11101111000000000011101111000000 00001111111100000000000111111000 00000000111111110000000000111011 11000000000011111111000001001011 11110000000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111111100000000000 01100000000000000000000000000000 00000000000000000000000000000000 01000000000100001010110000000000 11111011000000000011111011000000 00001111101100000000001110001100 00000000111110110000000000111110 11000000000011111011000110000011 11101101000000001100101100000000 00111110110001000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111101000000000000 00100000000000000000000000000000 00000000000000000000000000000000 11001000000001010010110000000000 10111011000000000010111011000000 00001011101111110000001000101100 00000000101110110000000000101110 11000000000010110111000000000010 11101100000000001010101100000000 00101110111101000000101110010000 00000010111011000000000010111011 00000100001011101100000000001011 10110000000000101111001000000000 01000000000000000000000000000000 00000000000000000000000000000000 11100000000001010100110000000000 10110011000000000010110011000000 00001011001100000000001000000000 00001000101100110000000000101100 11000000000010110011110000000010 11000000000000001000001100000000 00101100111000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101111000000000100 00000000000000000000000000000000 00000000000000000000000000000000 00100000000000000001111000000000 10110111100000000010110111100000 00001011011110000100101000011110 00000000101101111000000000100101 11100000000010110111100000000010 11010010000000001010011110000000 00101101111000000000101101110001 00000010110111100000000010110111 10000000001011011110000000001011 01111000000000101100100000000000 00000000000000000000000000000000 00000000000000000000000000000000 01001000000010000000110000000000 11110011000000000011110011000000 00001111101100000001001110000000 00000000111100110000000000111100 11000000000011110011000000000011 11100000000000001100001100000000 00111100110000000000111100110000 00000111110011000000000011110011 00000000001111001100000000001111 00110000000000111101001000000110 00000000000000000000000000000000 00000000000000000000000000000000 01000000000111001011110000000000 11111111000000000011111111000000 00001111111100000000001111111000 00000000111111110000000000111111 11000000000011111111000010000011 11110100000000011111111100000000 00111111110000000000111111110001 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111101000000000110 00100000000000000000000000000000 00000000000000000000000000000000 10101000000001011110110000000000 11111011000000000011111011000000 00001111101100000000101100100100 00000000110010110000000000111110 11000000000011111011100000000011 00100000000000001111101100000000 00111100111000000000110010110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111100001000000000 01110000000000000000000000000000 00000000000000000000000000000000 01001000000000011001110000000000 10110111000000000010110111000000 00001011111100000000001000011100 00000000110101110000000001101101 11000000000010110111001000000010 00011000000000001011011100000000 00101101110000000000110101100000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101101001000000000 01100000000000000000000000000000 00000000000000000000000000000000 11000000000000001001111000000000 10110111100000000010110111100000 00001011011110000000001000000110 00000000100001111000000000101001 11100000000010110011101000000010 00011010000000001011011110000000 00101101111000000000100001111000 00000010110111100000000010110111 10000000001011011110000000001011 01111000000000101100100000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000101001100110000000000 10110011000000000010110011000000 00011011001100000000001000001110 00000000100100110000000000101100 11000000000010110011000001000010 00101100000000001011001100000000 00101100110000000000100100111101 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101101101000000100 00110000000000000000000000000000 00000000000000000000000000000000 11101000000101011010100000000000 11111010000000000011111010000000 00001111101000000000001100111011 00000000110010100000000000111110 10000000000011111010000000000011 00111010100000001111101000000000 00111110100000000000110011100101 00000011111010000000010011111010 00000100001111101000000000001111 10100000000000111111101000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000000001110000000000000 11111000000000000011111000000000 00001111100000000000001111100000 01100000111110000000000000111110 00000000000011111000000000001011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111101001000000100 00100000000000000000000000000000 00000000000000000000000000000000 00001000000100001110010000000000 11111001000000000011111001000000 00001111100100000000001100000100 00000000110010010000000000111110 01000000000111111001100000000011 11100110000000001100100100000000 00111110010000000000111110010000 00100011111001000000000011111001 00000000001111100100000000001111 10010000000000111100001000000100 00100000000000000000000000000000 00000000000000000000000000000000 10000000000001000110010000000000 10111001000000000010111001000000 00001011100110010000101000100100 00000000101010010000000000101110 01000000000110111001010000000010 11100110000000001000100100000000 00101110010100000000101110010000 00000010111001000000000011111001 00000000001011100100000000001011 10010000000000101110000000000000 00010000000000000000000000000000 00000000000000000000000000000000 00011000000001010010010000000000 10111001000000000010111001000000 00001011000100001000001000100100 00000000100010010000000000101110 01000000010010111001000101000010 11100100010000001000100100000000 01101110010000100000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101100011000000000 01000000000000000000000000000000 00000000000000000000000000000000 00001000000001000000010000000000 10110001000000000010110001000000 00001011000100000000001000000100 10000000101000010000000000101100 01000000000010110001001000000010 11000100000000101000000100000000 01101100010000000000100100010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101100001000000001 00000000000000000000000000000000 00000000000000000000000000000000 10111000000001000110000000000000 11111000000000000011111000000000 00001111100001010000001100100000 00000000110010000000010000111110 00000000000010111010000000000011 11100001010010001100100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111110111000000111 01010000000000000000000000000000 00000000000000000000000000000000 10011000000111001110010000000000 11111001000000000011111001000000 00001111100100000000001111110100 01000000111110010000000000111110 01000000000011111001000101000011 11110100000000001111100100000000 00111110010000000000111111010000 00000011111001000000000011101001 00000000001111100100000000001111 10010000000000111110111000000110 01110000000000000000000000000000 00000000000000000000000000000000 00011000000000011110010000000000 11111001000000000011111001000000 00001111110100000000001111100100 00000000110110010000000000111110 01000000000011111101000000001011 01110100000000001100100100000000 00111111010000000000110010010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111100111000000101 01110000000000000000000000000000 00000000000000000000000000000000 00111000000100001110000000000000 10111000000000000010111000000000 00001110000000000000001011100000 00000000110110000000000000101110 00000000000010111000000000000010 00100010100000001101100000000000 00101110000000000000110110000000 00000011101000000000000010111000 00000000001011100000000000001011 10000000000000101100011000000010 00110000000000000000000000000000 00000000000000000000000000000000 00001000000001011100010000000000 10110001000000000010100001000000 00001011000100000000011011000100 00000000101100010000000000101100 01000000000010110001000000000010 00001110001000001000000100000000 00101100010000000000100000010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101101001000000001 01100000000000000000000000000000 00000000000000000000000000000000 00011000000100011010010000000000 10111001000000000010111001000000 00001010100100000000001011100100 00000000100110010000000000101110 01000000000010111001000000000010 00100100100000001001100100000100 00101110010000000000100110010100 00000010101001000000000010111001 00000000001011100100000000001011 10010000000000101100011000000000 01100000000000000000000000000000 00000000000000000000000000000000 10100000000101011110010000000000 11111001000000000011101001000000 00001111100100000000001111100111 00100000111110010000000000111110 01000000000011111001000000000011 01100100000000001100100100000000 00111100010000000000110010010000 00000011111001000000010011111001 00000000001111100100000000001111 10010000000000111110100000000100 00100000000000000000000000000000 00000000000000000000000000000000 00101000000000011010010000000000 11111001000000000011111001000000 00001110100100000000001111100111 00000000111010010000000000111110 01000000000011111001000010000011 11100100000000001111100100000000 00111110010000000000111110010100 00000001111001000000000011111001 00000000001011100100000000001111 10010000000000111101101000000000 00100000000000000000000000000000 00000000000000000000000000000000 00101000000100001010000000000000 11111000000000000011111000000000 00001111100000100000001100000000 00000000110110000000000000111110 00000000000111111000000100000011 11100000000000001100100000000000 00111110000010000000111110000100 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111100101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00101000000001010010100000000000 10111010000000000010111010000000 00001011111011000000101000101000 00000000111110100000000000111010 10000000000010110110000000000010 01101000000000101000101000000000 00101111100110000000111110100000 00000010111010000000000011101010 00000000001011101000000000001011 10100000000000101100001000000000 00000000000000000000000000000000 00000000000000000000000000000000 00101000000001010100110000000000 10110011000000000010110011000000 00001011001110000000001001001100 00000000100000110000000000101100 11000000000010110011110000000010 11101100000000001000001100000000 00101100001000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101100001000000000 01010000000000000000000000000000 00000000000000000000000000000000 10100000000000010001110000000000 10110111000000000010110111000000 00001011010110001000001001001100 00000000101001110000000000100001 11000000000010110111000000000110 01011100000000001000011100000000 00101101100000000000101001110000 00000010110111000000000010100111 00000000001011011100000000001011 01110000000000101100100000000000 01000000000000000000000000000000 00000000000000000000000000000000 10101000000010000001111000000000 11110111100000000011110111100000 00001111011110000000001101011110 00000100100001111000000000111101 11100000000010110110100000000011 11110110000000001100011110000000 00111101001000000000101101111000 00000011110111100000000011110111 10000000011111011110000000001111 01111000000000111100101000000110 00000000000000000000000000000000 00000000000000000000000000000000 00001000000111011010110000000000 11111011000000000011111011000000 00001111101000000000001110101100 00000000111110110000000000111010 11000000000011111011000001000011 11100100000000001111101100000000 00111110100000000000111110110000 00000011111011000000000011101011 00000000001111101100000000001111 10110000000000111100001000000110 01100000000000000000000000000000 00000000000000000000000000000000 00000000000001011111111000000000 11111111100000000011111111100000 00001111111110000000001100111110 00000000111111111000000000111111 11100000000011111110100000000011 00111110000000001100111110000000 00111111001000000000111111111000 00000011111111100000000011111111 10000000001111111110000000001111 11111000000000111101100000000000 00100000000000000000000000000000 00000000000000000000000000000000 10101000000100011001110000000000 10110111000000000011110111000000 00001011110000000000011000011100 00000000101101110000000000101101 11000000000010110110000000000011 01011100000000001101011100000000 00101101000000000000111001110001 10000011110111000000000010110111 00000000001011011100000000001011 01110000000000101110101000000000 00100000000000000000000000000000 00000000000000000000000000000000 00000000000000001001110000000000 10110111000000000010110111000000 00001011010100000000001000011100 00000000101101110000000000101101 11000000000010110110000000000010 00110100000000001001011100000000 00101101010000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101100000000000000 00100000000000000000000000000000 00000000000000000000000000000000 00100000000101001100110000000000 10110011000000000010100011000000 00001011100000000000001000001111 01001000101100110000000000101100 11000000000010110010000000000010 01100101001000001001001100000000 00101100000000000000101100110000 00000010100011000000010010110011 00000000001011001100000000001011 00110000000000101101000100000100 00100000000000000000000000000000 00000000000000000000000000000000 10101000000101011010110000000000 11111011000000000010111011000000 00001111101000000000101100101100 00001000111110110000000000111110 11000000000011111001000000000011 00101101000000001101101100000000 00111110000000000000111110111000 00000010111011000001000011111011 00000000001111101100000000001111 10110000000000111110101100000000 01100000000000000000000000000000 00000000000000000000000000000000 10000000000000001110110000000000 11111011000000000011111011000000 00001111101001000000001111101100 10000100111110110000000000111110 11000000000011111011000000000011 11101110000000001111101100000000 00111110000000000000111010110010 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111110100000000100 00110000000000000000000000000000 00000000000000000000000000000000 00000001000100001111110000000000 11111111000000000011111111000000 00001111111111000000001110011100 00000000110011110000000000111111 11000000000011111110000000000011 00110100000000001100111100000000 00111111000000000000111111110000 00000011001111000000000011111111 00000000001111111100000000001111 11110000000000111100000101000100 00110000000000000000000000000000 00000000000000000000000000000000 10000001000001000110110000000000 10111011000000000010111011000000 00001011101000000000101000101100 00000000100010110000000000101110 11000000000010110011100000000011 01110100000000001000101100000000 00101110001000000000101100110000 00000011111011000000000010111011 00000000001011101100000000001011 10110000000000101110000001000000 00010000000000000000000000000000 00000000000000000000000000000000 10000000000001010010110000000000 10111011000000000010111011000000 00001011100101000000001000101100 00000000100010110000000000101110 11000000000010111010000100000010 00100110000000001000101100000000 00101110000001000000101110110000 00000010001011000000000010111011 00000000001011101100000000001011 10110000000000101110000000000000 01010000000000000000000000000000 00000000000000000000000000000000 00001000000001000000110000000000 10110011000000000010110011000000 00001001000000000000001000001100 00000010100000110000000000101100 11000000000010110010000000000010 01000100000000001000001100000000 00101100000000000000101110110000 00000010010011000000000010110011 00000000001011001100000000001011 00110000000000101100001000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000011010110110000000000 11111011000000000010111011000000 00001111100100000000001110101100 00000000110010110000000000101110 11000000000011111010000000000011 00101100000000001100101100000000 00111110010000000000111110110000 00000011001011000000000011111011 00000000001111101100000000001111 10110000000000111100000000000110 00010000000000000000000000000000 00000000000000000000000000000000 10100000000111011111110000000000 11111111000000000011111111000000 00001111110000000000001111111100 00000000111111110000000000111111 11000000000011110110000000000011 11011100000000001111111100000000 00111111000000000100111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111110100000000110 01110000000000000000000000000000 00000000000000000000000000000000 11000000000001011111111000000000 11111111100000000011111111100000 00001111111110000000001110111110 00000000111111111000000000111111 11100000000011111111100000000011 11111110000000001111111110000000 00111111111000000000111111111000 00000011111111100000000011001111 10000000001111111110000000001111 11111000000000111011000000000000 01110000000000000000000000000000 00000000000000000000000000000000 10000000000000001110111000000000 10111011100000000010111011100000 00001011101110000000001100101110 00000000101110111000000000101110 11100000000010111011100000000010 11101110000000001011101110000000 00101110111000000000101110111000 00000010111011100000000011011011 10000000001011101110000000001110 10111000000000101111000000000000 00110000000000000000000000000000 00000000000000000000000000000000 10001000000001011100110000000000 10100011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00100100110000000000101100110000 00000010110011000000000010000011 00000000001011001100000000001011 00110000000000101111001000000001 01110000000000000000000000000000 00000000000000000000000000000000 11000000000101011010110000000000 10111011000000000010111011000000 00001011101100000000001010101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010011011 00000000001011101100000000001010 10110000000000101111100000000100 01100000000000000000000000000000 00000000000000000000000000000000 00000000000001011110110000000000 11111011000000000011111011000000 00001111001100000000001111101100 00000000111110110000000000111110 11000000000010111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011110011000000000011001011 00000000001111101100000000001111 10110000000000111100100000000000 01110000000000000000000000000000 00000000000000000000000000000000 11100000000100011011110000000000 11111111000000000011111111000000 00001111111100000000001101111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000011111111100000000001111 11110000000000111111100000000100 01100000000000000000000000000000 00000000000000000000000000000000 01000000000100001010110000000000 11111011000000000011101011000000 00001111101100000000001100101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011101011000100000011111011 00000000001111101100000000001111 10110000000000111101000000000100 00100000000000000000000000000000 00000000000000000000000000000000 11001000000001010010110000000000 10111011000000000010111011000000 00001011101100000000001000101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101110001100001011 10110000000000101111000000000000 01000000000000000000000000000000 00000000000000000000000000000000 11000000000001000000110000000000 10110011000000000010100011000000 00001011001110010000001001001100 00000000101100110000000000101100 11000000000010110011000000000010 10001100000000001011001100000000 00101100110000000000101100110000 00000010100011110010000010110011 00000000001011001111001000001011 00110000000000101111000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00100000000000000001111000000000 10110111100000000010110111100000 00001011011100000000001001011110 00000000101101111000000000101101 11100000000010110111100000000010 11011110000000001011011110000000 00101101111000000000101101111000 00000010110111100000000010110111 10000000001011011110000000011011 01111000000000001111111000000000 00000000000000000000000000000000 00000000000000000000000000000000 01001000000110000000110000000000 11110011000000000011100011000000 00001111001100010000001101001100 00000000111100110000000000111100 11000000000011110011000000000011 11001100000000001111001100000000 00111100110000000000111100110000 00000011100011000000000011110011 00000000001111001100010000001111 00110000000000111101101000000110 00000000000000000000000000000000 00000000000000000000000000000000 01000000000111001011110000000000 11111111000000000011111111000000 00001111011100100000001110111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000100011111 11110000000000111101000000000010 00100000000000000000000000000000 00000000000000000000000000000000 00001000000101011110110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111010110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111100101000000000 01110000000000000000000000000000 00000000000000000000000000000000 01001000000010011001110000000000 10110111000000000010110111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101111001000000000 01100000000000000000000000000000 00000000000000000000000000000000 00100000000000001001111000000000 10110111100000000010110111100000 00001011011110000000011011011110 00000000101101111000000000101101 11100000000010110111100000000010 11011110000000001011011110000000 00101001111000000000101101111000 00000010110111100000000110110111 10000000001011011110000000001011 01111000000000101100000000000000 00100000000000000000000000000000 00000000000000000000000000000000 11101000000001001100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000001011011001100000000001011 00110000000000101101001000000100 00110000000000000000000000000000 00000000000000000000000000000000 11101000000101001010100000000000 11111010000000000011111010000000 00001111101000000000001111101000 00000000111110100000000000111110 10000000000011111010000000000011 11101000000000001111101000000000 00111010100000000000111110100000 00000011110010000000000011111010 00000000001111101000000000001111 10100000000000111111101000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000000001010000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111101001000000100 00100000000000000000000000000000 00000000000000000000000000000000 10001000000100001010010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011011001 00000000001111100100010000001111 10010000000000111100001000000100 00100000000000000000000000000000 00000000000000000000000000000000 10000000000001000010010000000000 10111001000000000010111001000000 00001011100100100000001011100100 00000000101110010000000000101110 01000000000010111001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001001000000010001001 00000000001011100110000000001011 10010000000000101110000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00011000000001010010010000000000 10111001000000000010111001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000000010101001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010011001 00000000001011100100000000001011 10010000000000101100011000000000 01000000000000000000000000000000 00000000000000000000000000000000 00001000000001000000010000000000 10110001000000000010110001000000 00001011000100000000001011000100 00000000101100010000000000101100 01000000000010110001000000000010 11000100000000001011000100000000 00101100010000000000101100010000 00000010110001000000000010000001 00000000001011001100000000001011 00010000000000101100001000000001 00000000000000000000000000000000 00000000000000000000000000000000 10111000000111010110000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011101000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011011000 00000000001111100000000000001111 10000000000000111110111000000111 01010000000000000000000000000000 00000000000000000000000000000000 10111000000111011110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111110111100000110 01110000000000000000000000000000 00000000000000000000000000000000 00111000000101011110010000000000 11111001000000000011111001000000 00001111110100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111101000000000011111001 00000000001111110100000000001111 10010000000100111110111000000000 01110000000000000000000000000000 00000000000000000000000000000000 00011000000000001010000000000000 10111000000000000011101000000000 00001011100000000000001011100000 00000000101110000000000000101110 00000000000010111000000000000010 11100000000000001011100000000000 00101110000000000000101110000000 00000010111000000000000010111000 00000000001011100000000000001011 10000000000000101100011000000000 00110000000000000000000000000000 00000000000000000000000000000000 01001000000001001000010000000000 10110001000000000010110001000000 00001011000100000000001011000100 00000000101100010000000000101100 01000000000010110001000000000010 11000100000000001011000100000000 00101000010000000000101100010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101101001000000000 00100000000000000000000000000000 00000000000000000000000000000000 00011000000101001010010000000000 10111001000000000010101001000000 10001011101100000000001011100100 00000000101110010000000000101110 01000000000010111001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000001001011100100000000001011 10010000000000101100011000000100 00100000000000000000000000000000 00000000000000000000000000000000 10100000000101001110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111010010000000000111110010000 00000011111001000000000011111001 00000000011111100100000000001111 10010000000000111110000000000000 00100000000000000000000000000000 00000000000000000000000000000000 01101000000000001010010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100001000001111 10010000000000111101101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00101000000100001010000000000000 11111000000000000011101000000000 00001111100000001000001110100000 00000000111110000000000000111110 00000000000011101000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000010000011111000 00000000001111100000000000001111 10000000000000111100101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00001000000001000010100000000000 10111010000000000010111010000000 00001011111010000000001011101000 00000000101110100000000000101110 10000000000010111010000000000010 11101000000000001011101000000000 00101110100000000000101110100000 00000010111110000000000010111010 00000000001011111001000000000011 10100000000000101100001000000000 00000000000000000000000000000000 00000000000000000000000000000000 00001000000001010100110000000000 10110011000000000010100011000000 00001011001100000000001010001100 00000000101100110000000000101100 11000000000010100011000000000010 10001100000000001011001100000000 00101000110000000000101100110000 00000010110011100000000010110011 00000000001011001110000000001011 00110000000000101100001000000000 01010000000000000000000000000000 00000000000000000000000000000000 00100000000000010001110000000000 10110111000000000010110111000000 00001011011100001000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111010000000110110111 00000000001011010101000000001011 01110000000000101100000000000000 01000000000000000000000000000000 00000000000000000000000000000000 00101000000110000001111000000000 11110111100000000011100111100000 00001111011110000000001110011110 00000000111101111000000000111101 11100000000011100111100000000011 11011110000000001111011110000000 00111101111000000000111101111000 00000011110111100000000011110111 10000000001111011110000010001111 01111000001000111100101000000110 00000000000000000000000000000000 00000000000000000000000000000000 00001000000111011010110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111010000000000011111011 00000000001111100000000000001111 10110000000000111100001000000110 01100000000000000000000000000000 00000000000000000000000000000000 01100000000001001011111000000000 11111111100000000011111111100000 00001111111010010000001111111110 00000000111111111000000000111111 11100000000011111111100000000011 11111110000000001111111110000000 00111111111000000000111111111000 00000011111110100100000011111111 10000000001111111010000000001100 11111000000000111101000000000001 00100000000000000000000000000000 00000000000000000000000000000000 10101000000000001001110000000000 10110111000000000010110111000000 00001011010000000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110101000000000011100111 00000000001011011100000000001101 01110000000000101110101000000000 00100000000000000000000000000000 00000000000000000000000000000000 00000000000000001001110000000000 10110111000000000010110111000000 00001011011000000000011011011100 00000000101001110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110110000000000110110111 00000000001011010000000000001000 01110000000000101100010000000000 00100000000000000000000000000000 00000000000000000000000000000000 01000000000101001000110000000000 10110011000000000010110011000000 00001011000000000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000110110000000000000010100011 00000000001011000000000000011001 00110000000000101101000000000100 00100000000000000000000000000000 00000000000000000000000000000000 10101000000001011010110000000000 11111011000000000011111011000000 00001111100100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111001000000000011111011 00000000001111001100000000001100 10110000000000111110101000000000 01100000000000000000000000000000 00000000000000000000000000000000 10100000000100001110110000000000 11111011000000000011111011000000 00001111100100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000111101011 00000010001111100100000000001111 10110000000000111110110000000100 00110000000000000000000000000000 00000000000000000000000000000000 00000001000100001111110000000000 11111111000000000011111111000000 00001111110000000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111101100000000011111111 00000000001111111100000000101100 11110000000000111110000001000100 00110000000000000000000000000000 00000000000000000000000000000000 10000001000001000110110000000000 10111011000000000010111011000000 00001011100011000000001011101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010111010100000000010111011 00000000001011100000000000001000 10110000000000101110010001100000 00010000000000000000000000000000 00000000000000000000000000000000 10000000000001010110110000000000 10111011000000000010111011000000 00001011101100010000001011101100 00000000101110110000000000101110 11000000000010101011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010111000000100000010111011 00000000001011101000000001001000 10110000000100101110000000000000 01010000000000000000000000000000 00000000000000000000000000000000 00001000000001000000110000000000 10110011000000000010110011000000 00001011000100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110001000000000010110011 00000000001011001100000000001000 00110000000000101100001000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000110000110110000000000 11111011000000000011111011000000 00001111101000000000001111101100 00000000111110110000000000111110 11000000000011101011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111000000000000011111011 00000000001111100000000000001100 10110000000000101110100000000110 00010000000000000000000000000000 00000000000000000000000000000000 10100000000111011011110000000000 11111111000000000011111111000000 00001111110000000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111100000000000011111111 00000000001111010000000000001111 11110000000000111110000000100110 01110000000000000000000000000000 00000000000000000000000000000000 11000000000001011111111000000000 11111111100000000011111111100000 00001111111110000000001111111110 00000000111111111000000000111111 11100000000011111110100000000011 10111100000000101100110110000000 00110011111000000000111111111000 00000011001111100000000011111111 10000000001111111110000000001111 11111000000000111111000000000100 01110000000000000000000000000000 00000000000000000000000000000000 10000000000100001110111000000000 10111011100000000010111011100000 00001011101110000100001011101110 00011000101110111000001000101110 11100000000010111010100000000010 00111110000000101000100100000000 00100010111000010000101110111000 00000011011011100000000010111011 10000000001011101110000000001011 10111000000000101110000000000100 00110000000000000000000000000000 00000000000000000000000000000000 10001000000001011100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010111010000000000010 10000100000000001010001100000000 00100000110000000000101100110000 00000010000011000000000010110011 00000000001011001100000000001011 00110000000000101110001000000001 01110000000000000000000000000000 00000000000000000000000000000000 11000000000101011010110000000000 10111011000000000010111011000000 00001011101100000000001011101100 00000000101110110000000000101110 11000000000010111010100010010010 00100100000000001000100100000000 00100010110000000000101110110000 00000010011011000000000010111011 00000000001011101100000000001011 10110000000000101111000000000000 01100000000000000000000000000000 00000000000000000000000000000000 01000000000101011110110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000100111110110000000000111110 11000000010011111010110000000011 10111100000000101110100100000000 00110010110000000000111100110000 00100011001011000000000011111011 00000000001111101100000000001111 10110000000000111101000000000000 01110000000000000000000000000000 00000000000000000000000000000000 11100000000000011011110000000000 11111111000000000011111111000000 00001111111100000000001111111100 00000000111111110000000000100111 11000000000011111110000000000011 11101100011000101111111100000000 10111111110000000000111111110000 00010011111111000000000011111111 00000000001111111100000000001111 11110000000000111111100000000000 01100000000000000000000000000000 00000000000000000000000000000000 01000000000100001010110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111010010000000011 11000100000000001100101100000000 00111110110000000000110110110010 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111101000000000000 00100000000000000000000000000000 00000000000000000000000000000000 11001000000001010010110000000000 10111011000000000010111011000000 00001011101100000100001011101100 00000000101110110000000000101110 11000000000010110010000000000010 11100101001000101000101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101111001000000100 01000000000000000000000000000000 00000000000000000000000000000000 11100000000001010100110000000000 10110011000000000010110011000000 00001001001100000000001011001100 00000000101100110000000000100100 11000000000010110000100100000010 11000100000000101000100100000000 00101100110000000000100100110100 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101111100000000000 00010000000000000000000000000000 00000000000000000000000000000000 00100000000000010001111000000000 10110111100000000010110111100000 00001001011110000000001011011110 00000100101101111000000000101101 11100000000010110100100000000010 11010110010000001000010110000000 00101101111000000000101101111000 00000010110111100000000010110111 10000000000011011110000000001011 01111000000000101100100000000100 00010000000000000000000000000000 00000000000000000000000000000000 01001000000010000000110000000000 11110011000000000011110011000000 00001101001100000000001111001100 00000000111100110000000000111100 11000000000011110010000000000011 11001100000000001100001100000000 00111100110000000000110100110000 00000011110011000000000011110011 00000000001111001100000000001111 00110000000000111101101000000010 00010000000000000000000000000000 00000000000000000000000000000000 01000000000111011011110000000000 11111111000000000011111111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111100000100000011 11111111000000001111110100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111101000000000000 01100000000000000000000000000000 00000000000000000000000000000000 10101000000001011110110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111001000000000011 11100101000000001110100100000000 00111110110000000000111100111000 00000011001011000000000011111011 00000000001111101100000000001111 10110000000000111100001000000000 01110000000000000000000000000000 00000000000000000000000000000000 01001000000100011001110000000000 10110111000000000010110111000000 00001011011100000001001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11010100000000001000011100000000 00101101110000000000101101110000 00000011010111000000000010110111 00000000001011011100000000001011 01110000000000101101001000000110 01100000000000000000000000000000 00000000000000000000000000000000 11000000000000001001111000000000 10110111100000000010110111100000 00001011011110000000001011011110 00000000101101111000000000101101 11100000000010110111100000000010 11011110000000001010011111000000 00101101111000000000101101111000 00000010000111100000000010110111 10000000001011011110000000001011 01111000000000101100100000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000101001100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000111010010 11001100000000001000001110000000 00101100110000000000101100110000 00000010010011000000000010110011 00000000001011001100000000001011 00110000000000101101001000000000 00110000000000000000000000000000 00000000000000000000000000000000 11101000000101011010100000000000 11111010000000000011111010000000 00001111101000000000001111101000 00000000111110100000000000111110 10000000000011110110100000000011 11101000000000001110101000000001 00111110100000010000111110100000 00000011001010000000000011111010 00000000001111101000000000001111 10100000000000111111101100000100 01110000000000000000000000000000 00000000000000000000000000000000 01001000000000001110000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000100 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111101001000000000 01100000000000000000000000000000 00000000000000000000000000000000 00001000000100001110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001110001000011 00100100000000001100100100000000 00111110010000000000111110011001 00000000111001000000000011111001 00000000001111100100000000001111 10010000000000111100001000000100 00100000000000000000000000000000 00000000000000000000000000000000 10000000000001000110010000000000 10111001000000000010111001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000000010111001100000001010 00000100000000001000100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101110000000000000 00010000000000000000000000000000 00000000000000000000000000000000 00011000000001010010010000000000 10111001000000000010111001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000000010111001000000000010 00100110001000101000100100000001 00101110010000010000101110010000 10000010111001000000000010111001 00000000001011100100000000001011 10010000000000101100111000000000 01000000000000000000000000000000 00000000000000000000000000000000 00001000000001000000010000000000 10110001000000000010010001000000 00001011000100000000001011000100 00000000101100010000000000101100 01000000000010110001000000000010 00000100100000001000000100000000 00101100010000000000101100010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101100101000000101 00000000000000000000000000000000 00000000000000000000000000000000 10111000000011010110000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 00100000000000101100100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111110111000000011 01010000000000000000000000000000 00000000000000000000000000000000 10011000000111011110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000010011111101000001000011 11010100010000101111110100101000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001101100100000000001111 10010000000000111110011000000100 01110000000000000000000000000000 00000000000000000000000000000000 00011000000001011110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111101000000000011 10110110000000101100100100000000 00110010010000000000111111010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111100011000000100 01110000000000000000000000000000 00000000000000000000000000000000 00111000000100001110000000000000 10111000000000000010111000000000 00001011100000000000001011100000 00000000101110000000000000101110 00000000000010111000000000000010 00100000000000001000100010100000 00110110000000010000101110000000 00000000111000000000000010111000 00000000001011100000000000001011 10000000000000101100111000000100 00110000000000000000000000000000 00000000000000000000000000000000 00001000000001011100010000000000 10110001000000000010110001000000 00001011000100000000001011000100 00000000101000010000000000101100 01000000000010111001000000000010 10000101000000001000100100001000 00100000010000000000101100010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101101001000000000 00100000000000000000000000000000 00000000000000000000000000000000 00011000000101011010010000000000 10111001000000000010111001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000000010111001001000000010 00100100100000001000100100000100 00100110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101100011000000100 00100000000000000000000000000000 00000000000000000000000000000000 10100000000101011110010000000000 11111001000000000011111001000000 00001111100100000000001011100100 00000000111010010000000000111110 01000000000011111001100000000011 10000100000000001100000110000000 00110010010000000000111110010000 01000011111001000000000011111001 00000000001111100100000000001111 10010000000000111110100000000100 01110000000000000000000000000000 00000000000000000000000000000000 00101000000000011010010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001100000000011 11100110001000101111100100100000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111101001000000000 01100000000000000000000000000000 00000000000000000000000000000000 00101000000100001010000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 00100000000001001100100000000100 00111110000000000000111110000001 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111100001000000100 00000000000000000000000000000000 00000000000000000000000000000000 00101000000001010010100000000000 10111010000000000010111010000000 00001011101000000000001011101000 00000000101110100000000000101110 10000000000010110010100000000011 01111001000001001010101000000000 00101110100000000000101111101100 00000010111010000000000010111010 00000000001011101000000000001011 10100000000000101100101000000000 01000000000000000000000000000000 00000000000000000000000000000000 00101000000001010100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110001000000000010 00001000000000001000001100000000 00101100110000000000101100101100 10000010110011000000000010110011 00000000001011001100000000001011 00110000000000101100101100000000 01010000000000000000000000000000 00000000000000000000000000000000 10100000000000010001110000000000 10110111000000000010110111000000 00001011011100000000001001011100 00000000101101110000000000101101 11000000000010111101010000000010 01011001000000001010011100000000 00101101110000000000101101100000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101110000000000000 01000000000000000000000000000000 00000000000000000000000000000000 10101000000010000001111000000000 11110111100000000010110111100000 00001111011110000000001111011110 00000000111101111000000000111101 11100000000011110101100000000011 00011110000000001100011110000000 00111101111000000000111101011000 00000011110111100000000011110111 10000000001111011110000000001111 01111000000000111110001000000010 00000000000000000000000000000000 00000000000000000000000000000000 00001000000111011010110000000000 11111011000000000011111011000000 00001111101100000100001111101100 00000000111110110000000000111110 11000000000011110001000000000011 11000000000000001111101100000000 00111110110000000000111110000000 00000011111011000000000011111011 00000000001101101100000000001111 10110000000000111100001000000110 01100000000000000000000000000000 00000000000000000000000000000000 00000000000001011111111000000000 11111111100000000011101111100000 00001111111110000000001111111110 00000000111111111000000000111111 11100000000011111101100000000011 10111010000000001100111110000000 00111111111000000000111111001000 00000011111111100000000011111111 10000000001111111110000000001111 11111000000000111100000000000100 00100000000000000000000000000000 00000000000000000000000000000000 10101000000100011001110000000000 10110111000000000011100111000000 00001011011100000000001111011100 00000000101101110000000000111101 11000000000010110101000000000010 00011000010000001000011100000000 00101101110000000000101101000000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101110101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00000000000000001001110000000000 10110111000000000010110111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010111111000000000010 10010100000000001000011100001000 00101101110000000000101101000000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101100000000000000 00100000000000000000000000000000 00000000000000000000000000000000 00100000000101001100110000000000 10110011000000000010110011000000 00001011001100000000001010001100 00000000101100110000000000101000 11000000000010110011100000000010 00000000000000101000001110000000 00101100110000000000101100000000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101100100000000000 00100000000000000000000000000000 00000000000000000000000000000000 10101000000101011010110000000000 11111011000000000011111011000000 00001111101100000000001011101100 00000000111110110000000000101110 11000000000011111011100010000011 10000000000000101100111110000000 00111110110000000000111110000000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111110101000000000 01100000000000000000000000000000 00000000000000000000000000000000 10000000000000001110110000000000 11111011000000000011101011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111001000000100011 01100000000000001111101100000000 00111110110000000000111110000000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111110000000000000 00110000000000000000000000000000 00000000000000000000000000000000 00000001000100001111110000000000 11111111000000000011111111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11100100000000001100111100000000 00111111110000000000111111011000 00000011111111000000000011111111 00000000001101111100000000001111 11110000000000111100100001000000 00110000000000000000000000000000 00000000000000000000000000000000 10000001000001000110110000000000 10111011000000000010111011000000 00001011101100000100001011101100 00000000101110110000001000101110 11000000000010111001100000010010 11100010000000101000111100000000 00101110110000000000101110001001 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101110100001000100 00010000000000000000000000000000 00000000000000000000000000000000 10000000000001010010110000000000 10111011000000000010111011000000 00001011101100000000001011101100 00000000101110110000000000101110 11000000000010111011000100000010 11100010001000001000101100000000 00101110110000000000101110000000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101110000000000000 01000000000000000000000000000000 00000000000000000000000000000000 00001000000001000000110000000000 10110011000000000010110011000000 00001011001100000000001001001100 00000000101100110000000000100100 11000000000010010001000000000010 11000000000000001000001100000000 00101100110000000000101100000000 00000010010011000000000010110011 00000000001011001100000000001011 00110000000000101100001000000101 00000000000000000000000000000000 00000000000000000000000000000000 00000000000011010110110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000010011111011000000000011 11100000000010001100101100000000 00111110110000000000111110000000 00000011111011000000000011111011 00000000001101101100000000001111 10110000000000111100000000000011 01010000000000000000000000000000 00000000000000000000000000000000 10100000000111011111110000000000 11111111000000000011111111000000 00001111111100000000001111111100 00000000001111110000000001111111 11000000000011110111000000000011 11110000000000001111111100000000 00111111110000000000111111000000 00000011111111000000000011111111 00000000001111111100000000001101 11110000000000111110100000000000 01110000000000000000000000000000 00000000000000000000000000000000 11000000000001011111111000000000 11111111100000000011111111100000 00001111111110000000001111111110 00000000111111111000000000111111 11100000000011111111100000000011 11111110000000001111111110000000 00111111111000000000111111111000 00000011111111100000000011111100 10000000001111111110000000001111 11111000000000111111000000000001 01100000000000000000000000000000 00000000000000000000000000000000 10100000000100001110111000000000 10111011100000000010111011100000 00001011101110000000001011101110 00000000101110111000000000101110 11100000000010111011100000000010 11101110000000001011101110000000 00101110111000000000101110111000 00000010111011100000000010111001 10000000001011101110000000001011 10111000000000101110100000000100 00110000000000000000000000000000 00000000000000000000000000000000 10001000000001011100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010100011000000000010110010 00000000001011001100000000001011 00110000000000101110001000000001 00110000000000000000000000000000 00000000000000000000000000000000 11100000000101011010110000000000 10111011000000000010111011000000 00001011101100000100001011101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101111100000000100 01100000000000000000000000000000 00000000000000000000000000000000 00000000000100011110110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111000 10000000001111101100000000001111 10110000000000111100000000000100 01110000000000000000000000000000 00000000000000000000000000000000 11100000000000011011110000000000 11111111000000000001111111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111100 10010000001111111100000000001111 11110000000000111111100000000000 01100000000000000000000000000000 00000000000000000000000000000000 01000000000100001010110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111001 00000000001111101100000000001111 10110000000000111101000000000100 00100000000000000000000000000000 00000000000000000000000000000000 11001000000001010010110000000000 10111011000000000010111011000000 00001011101100000000001110101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111001 00000000001011101100000000001011 10110000010000101111001000000000 01000000000000000000000000000000 00000000000000000000000000000000 11100000000001010100110000000001 10110011000000000010110011000000 00001001001100000000001001001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010010000 00000000001011001100000000001011 00110000000000101111100000000000 01010000000000000000000000000000 00000000000000000000000000000000 00100000000000010001111000000100 10110111100000000010110111100000 00001011011110000000001010011110 00000000101101111000000000101101 11100000000010110111100000000010 11011110000000001011011110000000 00101101111000000000101101111000 00000010110111100000000010110101 10000000001011011110000000001011 01111000000000101101100000000000 01000000000000000000000000000000 00000000000000000000000000000000 01001000000010000000110000000000 11110011000000000011110011000000 00001111001100000000001111001100 00000000111100110000000000111100 11000000000011110011000000000011 11001100000000001111001100000000 00111100110000000000101100110000 00000011110011000000000011110010 00100000001111001100010000001111 00110000000000111101001000000010 00000000000000000000000000000000 00000000000000000000000000000000 01000000000011011011110000000000 11111111000000000011111111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111101000000000010 01100000000000000000000000000000 00000000000000000000000000000000 10001000000001011110110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111010110000 00000011111011000000000011111010 00000000001111101100000000001111 10110000000000111110001000000000 01110000000000000000000000000000 00000000000000000000000000000000 01001000000100011001110000000000 10110111000000000010110111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110110 00000000001011011100000000001011 01110000000000101101001000000100 01100000000000000000000000000000 00000000000000000000000000000000 11000000000000001001111000000000 10110111100000000010110111100000 00001011011110000000001011011110 00000000101101111000000000101101 11100000000010110111100000000010 11011110000000001011011110000000 00101101111000000000101101111000 00000010110111100000000010110111 10000000001011011110000000001011 01111000010001101111000000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000101001100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 11000000001011001100000000001011 00110000000000101101001000000100 00110000000000000000000000000000 00000000000000000000000000000000 11101000000101011010100000000000 11111010000000000011111010000000 00001111101000000000001111101000 00000000111110100000000000111110 10000000000011111010000000000011 11101000000000001111101000000000 00111110100000000000111110100000 00000011111010000000000011111110 11011000001111101000000000001111 10100000000000111111101100000100 01100000000000000000000000000000 00000000000000000000000000000000 01001000000000001110000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111101001000000000 00110000000000000000000000000000 00000000000000000000000000000000 10001000000100001110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111100001000000100 00110000000000000000000000000000 00000000000000000000000000000000 10000000000001000110010000000000 10111001000000000010111001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000000010111001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101110000000000000 00010000000000000000000000000000 00000000000000000000000000000000 00011000000001010010010000000000 10111001000000000010111001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000000010111001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101100011000000000 01000000000000000000000000000000 00000000000000000000000000000000 00001000000001000000010000000000 10110001000000000010110001000000 00001011000100000000001011000100 00000000101100010000000000101100 01000000000010110001000000000010 11000100000000001011000100000000 00101100010000000000101100010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101100001000000001 00000000000000000000000000000000 00000000000000000000000000000000 10111000000011010110000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111110111000000011 01010000000000000000000000000000 00000000000000000000000000000000 10011000000111011110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000100011111101 00000000001111100100000000001111 10010000000000111110011000000110 01110000000000000000000000000000 00000000000000000000000000000000 00011000000001011110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111110011000000000 01110000000000000000000000000000 00000000000000000000000000000000 00111000000100001110000000000000 10111000000000000010111000000000 00001011100000000000001011100000 00000000101110000000000000101110 00000000000010111000000000000010 11100000000000001011100000000000 00101110000000000000101110000000 00000010111000000000000010111000 00000000001011100000000000001011 10000000000000101100111000000100 00110000000000000000000000000000 00000000000000000000000000000000 00001000000001011100010000000000 10110001000000000010110001000000 00001011000100000000001011000100 00000000101100010000000000101100 01000000000010110001000000000010 11000100000000001011000100000000 00101100010000000000101100010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101100001000000001 01110000000000000000000000000000 00000000000000000000000000000000 00011000000101011010010000000000 10111001000000000010111001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000000010111001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00001100001011100100000000001011 10010000000000101100011000000100 01100000000000000000000000000000 00000000000000000000000000000000 10100000000101001010010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 11000000001111100100000000001111 10010000000000111110100000000100 00100000000000000000000000000000 00000000000000000000000000000000 00101000000000001010010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00100000001111100100000000001111 10010000000000111100101000000000 00100000000000000000000000000000 00000000000000000000000000000000 00101000000100001010000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111100101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00101000000001000010100000000000 10111010000000000010111010000000 00001011101000000000001011101000 00000000101110100000000000101110 10000000000010111010000000000010 11101000000000001011101000000000 00101110100000000000101110100000 00000010111010000000000010111010 00000000001011101000000000001011 10100000000000101100101000000000 00000000000000000000000000000000 00000000000000000000000000000000 00101000000001010100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101100101000000000 01010000000000000000000000000000 00000000000000000000000000000000 00100000000000010001110000000000 10110111000000000010110111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000010001011 01110000000000101100100000000000 01000000000000000000000000000000 00000000000000000000000000000000 00101000000010000001111000000000 11110111100000000011110111100000 00001111011110000000001111011110 00000000111101111000000000111101 11100000000011110111100000000011 11011110000000001111011110000000 00111101111000000000111101111000 00000011110111100000000011110111 10000000001111011110000000001111 01111000000000111100101000000010 00000000000000000000000000000000 00000000000000000000000000000000 00001000000111011010110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111100001000000110 01100000000000000000000000000000 00000000000000000000000000000000 01000000000001011111111000000000 11111111100000000011111111100000 00001111111110000000001111111110 00000000111111111000000000111111 11100000000011111111100000000011 11111110000000001111111110000000 00111111111000000000111111111000 00000011111111100000000011110111 10000000001100111110000000001111 11111000000100111101000000000000 01110000000000000000000000000000 00000000000000000000000000000000 10101000000100011001110000000000 10110111000000000010110111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001101011100000000001011 01110000000000101110101000000100 01100000000000000000000000000000 00000000000000000000000000000000 00000000000000001001110000000000 10110111000000000010110111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010111111 00000000001010011100000000001011 01110000000000101100010000000000 00100000000000000000000000000000 00000000000000000000000000000000 01100000000101001100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00001000001011001100000000001011 00110000000000101101100000000100 00110000000000000000000000000000 00000000000000000000000000000000 10101000000101011010110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001110101100000000001111 10110000000000111110101000000100 01100000000000000000000000000000 00000000000000000000000000000000 10000000000000001110110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001001101100000000000111 10110000000000111110010000000000 00110000000000000000000000000000 00000000000000000000000000000000 00000001000100001111110000000000 11111111000000000011111111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001100111100000001001111 11110000010100111110000001100100 00110000000000000000000000000000 00000000000000000000000000000000 10000001000001000110110000000000 10111011000000000010111011000000 00001011101100000000001011101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010110011 00000000001000101100000000001011 10110000000000101110000101000000 00010000000000000000000000000000 00000000000000000000000000000000 10000000000001010110110000000000 10111011000000000010111011000000 00001011101100000000001011101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001000101100000001001011 10110000010000101110000000000000 01010000000000000000000000000000 00000000000000000000000000000000 00001000000000000000110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010111011 00000000001000001100000000001011 00110000000000101100001000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000010000110110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001100101100000000001111 10110000000000111110000000000010 00010000000000000000000000000000 00000000000000000000000000000000 10100000000111011111110000000000 11111111000000000011111111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000101111111100000000001111 11110000000000111110100000000010 01110000000000000000000000000000 00000000000000000000000000000000 11000000000000011111111000000000 11111111100000000011111111100000 00001111110110000001001101111110 00000000111111111000000000111111 11100000000011111111100000000011 11111110000000001111111110000000 00111111111000000000111111111000 00000011111111100000000011111111 10000000001111111110000000001111 11111000000000111111000000000100 01110000000000000000000000000000 00000000000000000000000000000000 10000000000000001110111000000000 10111011100000000010111011100000 00001011100110000000001000001100 00100000101110111000000000101110 11100000000010111011100000000010 11101110000001001011101110000000 00101110111000000000101110111000 00000010111011100000000010111011 10000000001011101110000000001011 10111000000000101110000000000010 00110000000000000000000000000000 00000000000000000000000000000000 10001000000001011100110000000000 10110011000000000010100011000000 00001010001100000000001001001100 10000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000001 00101100110000000001101100110000 00000010110011000000000010110011 00000000001011001100000000001010 00110000000000101010001000000001 01100000000000000000000000000000 00000000000000000000000000000000 11000000000101011010110000000000 10111011000000000010111011000000 00001011101100001000001000101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101111000000000001 01110000000000000000000000000000 00000000000000000000000000000000 01000000000101011110110000000000 11111011000000000011111011000000 00001111101111000000001101101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111100000000000100 01110000000000000000000000000000 00000000000000000000000000000000 11100000000000011011110000000000 11111111000000000011111111000000 10001111111110100000001110111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00010011111111000000000011111111 00000000001111111100000000001111 11110000000000111111100000000000 01100000000000000000000000000000 00000000000000000000000000000000 01000000000100001010110000000000 11111011000000000011111011000000 00001111101110100010101100101100 00100010110010110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111101000000000100 00100000000000000000000000000000 00000000000000000000000000000000 11001000000001010010110000000000 10111011000000000010111011000000 00001011001110000000001000101111 00000000100010110000000000111110 11000000000010111011000000000010 11101100000010001011101100000000 00101110110000000000101110110000 00000011111011000000000010111011 00000000001011101100000000001011 10110000000000101111001000000000 01000000000000000000000000000000 00000000000000000000000000000000 11100000000001010100110000000000 10110011000000000010110011000000 00001011000001000000001000001101 00000000100000110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101111000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00100000000000010001111000000000 10110111100000000010110111100000 00001011011010000000001000011110 00100000100001111000000000101001 11100000000010110111100000000010 11011110000000011011011110000000 00101101111000000000101101111000 00000010100111100000000010110111 10000000001011011110000000001011 01111000000000101100100000000000 00000000000000000000000000000000 00000000000000000000000000000000 01001000000000000000110000000000 11110011000000000011110011000000 00001111000100000000001100001100 00000000110000110000010001101100 11000000000011110011000000000011 11001100010000001111001100000000 00111100110000000000111100110000 00000010110011000000000011110011 00000000001111001100000000001111 00110000000000111101001000000110 00000000000000000000000000000000 00000000000000000000000000000000 01000000000111011011110000000000 11111111000000000011111111000000 00001111011000000000001111111100 01000000111111110000000000111111 11000000000011111111000000000011 11111100000100001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111101000000000110 01100000000000000000000000000000 00000000000000000000000000000000 10101000000001011110110000000000 11111011000000000011111011000000 00001111001010000000001100001100 00000000110010110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111100001000000000 01110000000000000000000000000000 00000000000000000000000000000000 01001000000100011001110000000000 10110111000000000010110111000000 00001011011100000000001101011100 00000000101001110000000000111001 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101101001000000000 01100000000000000000000000000000 00000000000000000000000000000000 11000000000000001001111000000000 10110111100000000010110111100000 00001010011110000010001000011110 00000000100001111000000000101101 11100000000010110111100000000010 11011110000000001011011110000000 00101101111000000000101101111000 00000010110111100000000010110111 10000000001011011110000000001011 01111000000000101100100000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000101001100110000000000 10110011000000000010110011000000 00001011001100100000101001001100 00000000000000110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000100100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101101101000000100 00110000000000000000000000000000 00000000000000000000000000000000 11101000000101011010100000000000 11111010000000000011111010000000 00001111111000001000001100101000 00000010110010100000000000111110 10000000000011111010000000000011 11101000000000001111101000000000 00111110100000000000111110100000 00000011111010000000000011111010 00000000001111101000000000001111 10100000000000111111101000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000000001110000000000000 11111000000000000011111000000000 10001111100001000000001111100000 00000000111110000000000000111010 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111101001000000100 00100000000000000000000000000000 00000000000000000000000000000000 00001000000100001110010000000000 11111001000000000011111001000000 00001111100100000000001111100111 00000000110010010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111100001000000100 00100000000000000000000000000000 00000000000000000000000000000000 10000000000001000110010000000000 10111001000000000010011001000000 00001011100111001000001011100111 00000000100010010000000000101110 01000000000010111001000001000010 11100100000000001011100100000000 00101110010000000000100110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101110000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00011000000001010010010000000000 10111001000000000010011001000000 00001011100110000000001011000101 00000000100010010000000000101110 01000000000010111001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101100011000000000 01000000000000000000000000000000 00000000000000000000000000000000 00001000000001000000010000000000 10110001000000000010010001000000 00001011000100000000001011000100 00000010101000010000000000101100 01000000000010110001000000000010 11000100000000001011000100000000 00101100010000000000101100010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101100001000000001 00100000000000000000000000000000 00000000000000000000000000000000 10111000000011010110000000000000 11111000000000000011011000000000 00001111100000000000001111100001 01000000110010000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111110111000000111 01010000000000000000000000000000 00000000000000000000000000000000 10011000000111011110010000000000 11111001000000000011011001000000 00001111110100000000001111100100 00000000110110010000000000111110 01000000000011111001000000000010 11100100000000001111100100000000 00111110010000000000110110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111110111100000110 01110000000000000000000000000000 00000000000000000000000000000000 00011000000001011110010000000000 11101001000000000011111001000000 00001111110100000000001111110100 00000000110010010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111100111000000001 01110000000000000000000000000000 00000000000000000000000000000000 00111000000100001110000000000000 10111000000000000010111000000000 00001011100000000000001011100000 00000010100010000000000000101110 00000000000011111000000000000010 11100000000000001011100000000000 00101110000000000000101110000000 00000010111000000000000010111000 00000000001110100000000000001011 10000000000000101100011000000000 00110000000000000000000000000000 00000000000000000000000000000000 00001000000001011100010000000000 10100001000000000010110001000000 00001011000100000000001011000100 00000000100100010000000000101100 01000000000010110001000000000010 11000100000000001011000100000000 00101100010000000000101100010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101101001000000001 01100000000000000000000000000000 00000000000000000000000000000000 00011000000101011010010000000000 10111001000000000010111001000000 00001011100100100000001011000100 00000000100110010000000000101110 01000000000010101001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001010100100000000001011 10010000000000101100011000000100 00100000000000000000000000000000 00000000000000000000000000000000 10100000000101011110010000000000 11101001000000000011111001000000 00001111100101100000001111100100 00000010110110010000000000111110 01000000000010111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111110000000000000 00100000000000000000000000000000 00000000000000000000000000000000 00101000000000011010010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111010010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001110100100000000001111 10010000000000111101101100000100 00100000000000000000000000000000 00000000000000000000000000000000 00101000000100001010000000000000 11111000000000000011111000000000 00001111100001000000001111100000 10000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000100 00011110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111100101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00101000000001010010100000000000 10111010000000000010111010000000 00001011111010001000001011111010 10000000101110100000000000101110 10000000000010111010000000000010 11101000000000001011101000000000 00101110100000000000101110100000 00000010111010000000000010111010 00000000001011101000000000001011 10100000000000101100001000000000 00000000000000000000000000000000 00000000000000000000000000000000 00101000000001010100110000000000 10110011000000000010110011000000 00001011001101100000001011001110 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101100001000000000 01010000000000000000000000000000 00000000000000000000000000000000 10100000000000010001110000000000 10110111000000000010110111000000 00001011010100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101100100000000000 01000000000000000000000000000000 00000000000000000000000000000000 10101000000010000001111000000000 11110111100000000011110111100000 00001111010110000000001111011110 00000000111101111000000000111101 11100000000011110111100000000011 11011110000000001111011110000000 00111101111000000000101101111000 00000011110111100000000011110111 10000000001111011110000000001111 01111000000000111100001000000110 00000000000000000000000000000000 00000000000000000000000000000000 00001000000111011010110000000000 11111011000000000011111011000000 00001111100100000000001111101000 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111100001000000110 01100000000000000000000000000000 00000000000000000000000000000000 00000000000101011111111000000000 11111111100000000011111111100000 00001111011110000000001100110110 00000000110011111000000000111111 11100000000011111111100000000011 11111110000000001111111110000000 00111111111000000000111111111000 00000011111111100000000011111111 10000000001111111110000000001111 11111000000000111101100000000000 00100000000000000000000000000000 00000000000000000000000000000000 10101000000100011001110000000000 10110111000000000010110111000000 00001011011101000000001101011100 00000000100001110000000000111101 11000000000011110111000000000010 11011100000000001011011100000000 00111101110000000000111001110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101110101000000000 00100000000000000000000000000000 00000000000000000000000000000000 00000000000000001001110000000000 10110111000000000010110111000000 00001010011000000000001001011000 00000000100001110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001010 01110000000000101100000000000000 00100000000000000000000000000000 00000000000000000000000000000000 00100000000101001100110000000000 10110011000000000010110011000000 00001011001000010000101000001000 00000000100000110000000000001000 11000000000000100011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101101000000000100 00100000000000000000000000000000 00000000000000000000000000000000 10101000000001011010110000000000 10111011000000000011111011000000 00001111000100000000001001101000 00000010110010110000000000101110 11000000000010111011000000000011 11101100000000001111101100000000 00111110110000000000101110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111110001000000000 01100000000000000000000000000000 00000000000000000000000000000000 10000000000000001110110000000000 11111011000000000011111011000000 10001111100101100000001111101100 00000000111110110000000000111110 11000000000111111011000000000011 11101100000001001111101100000000 00111010110000000000111010110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111110000000000100 00110000000000000000000000000000 00000000000000000000000000000000 00000001000000001111110000000000 11101111000000000011111111000000 00001111110100000000001100110010 00000000111111110000000000111111 11000000000011111111000001000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111100000001000100 00110000000000000000000000000000 00000000000000000000000000000000 10000001000001000110110000000000 10111011000000000010111011000000 00001011100011000000001010101001 00000000101110110000000000101110 11000000000010111011000000000010 11101100000100001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101110000001000000 00010000000000000000000000000000 00000000000000000000000000000000 10000000000001010010110000000000 10111011000000000010111011000000 00001011100110000000001000100101 01000000101010110000000000101110 11000000000010111011000000000110 11101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101110100000000000 01010000000000000000000000000000 00000000000000000000000000000000 00001000000001000000110000000000 10110011000000000010110011000000 00001011000100000000101000001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101100101000000001 00000000000000000000000000000000 00000000000000000000000000000000 00000000000011010110110000000000 11111011000000000011111011000000 00001111100000000000001100000000 00000000111010110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111100000000000110 00000000000000000000000000000000 00000000000000000000000000000000 10100000000111011111110000000000 11111111000000000011111111000000 00001111110000000000001110111000 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000001111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111110100000000110 01110000000000000000000000000000 00000000000000000000000000000000 11000000000011011111111000000000 11111111100000100011111111100000 00001101111110000000001111111110 00000000111111111000000000111111 11100000000011111111100000000011 11111110000000001111111110000000 00111111111000000000111111111000 00000011111111100000000011111111 10000000001111111110000000001111 11111000000000111111000000000001 01100000000000000000000000000000 00000000000000000000000000000000 11100000000000001110111000000000 10111011100000000010111011100000 00001011101110000000001011101110 00000000101110111000000000101110 11100000000010111011100000000010 11101110000000001011101110000000 00101110111000000000101110111000 00000010111011100000000010111011 10000010001011101110000000001011 10111000000000101111000000000000 00110000000000000000000000000000 00000000000000000000000000000000 11001000000001011100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001001001100000000 00101100110000000000101100110000 00000010100011000000000010110011 00000000001011001100000000001011 00110000000000101111001000000001 00110000000000000000000000000000 00000000000000000000000000000000 11100000000101011010110000000000 10111011000000000010111011000000 00001011101100000000001011101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101111000000000100 01100000000000000000000000000000 00000000000000000000000000000000 00000000000101011110110000000000 11111011000000000011111011000000 00001101101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000100001111 10110000000000111100000000000000 01110000000000000000000000000000 00000000000000000000000000000000 11100000000000011011110000010000 11111111000000000011111111000000 00000111111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000001000111111100000000100 01000000000000000000000000000000 00000000000000000000000000000000 01010100000100001010110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000110110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111101000000000100 00100000000000000000000000000000 00000000000000000000000000000000 11001000000001010010110000000000 10111011000000000010111011000000 00001011101100000000001011101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101111011000000000 01000000000000000000000000000000 00000000000000000000000000000000 11100000000001010100110000001000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010010011000000000010110011 00000000001011001100000000001001 00110000000000101111000100000000 00000000000000000000000000000000 00000000000000000000000000000000 10110000000000010001111000000000 10110111100000000010110111100000 00001011011110000000001011011110 00000000101101111000000000101101 11100000000010110111100000000010 11011110000000001011011110000000 00101101111000000000101101111000 00000010110111100000000010110111 10000000001011011110000000001011 01111000000000101111111000000000 00000000000000000000000000000000 00000000000000000000000000000000 01001000000000000000110000000000 11110011000000000011110011000000 00001111001100000000001111001100 00000000111100110000000000111100 11000000000011110011000000000011 11001100000000001111001100000000 00111100110000000000101100110000 00000011110011000000000011110011 00000000001111001100000000001111 00110000000000111101001100000110 00000000000000000000000000000000 00000000000000000000000000000000 01000000000101011011110000000000 11111111000000000011111111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111101000000000010 00100000000000000000000000000000 00000000000000000000000000000000 10001000000001011110110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111010110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111100001000000000 01110000000000000000000000000000 00000000000000000000000000000000 11001000000100011001110000000000 10110111000000000010110111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000011110111000000000011110111 00000000001011011100000000001111 01110000000000111111001000000000 01100000000000000000000000000000 00000000000000000000000000000000 10000000000000001001111000000000 10110111100000000010110111100000 00001011011110000000001011011110 00000000101001111000000000101101 11100000000010110111100000000010 11011110000000001011011110000000 00101101111000000000101101111000 00000010110111100000000010110111 10000000001011011110000000001011 01111000000000101100100000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000101001100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010100011000000000010100011 00000000001011001100000000001010 00110000000000101001101000000100 00110000000000000000000000000000 00000000000000000000000000000000 11101000000101011010100000000000 11111010000000000011111010000000 00001111101000000000001111101000 00000000111110100000000000111110 10000000000011111010000000000011 11101000000000001111101000000000 00111110100000000000111110100000 00000010111010000000000010111010 00000000001011101000000000001011 10100000000000101111101000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000000001110000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111101001000000100 00100000000000000000000000000000 00000000000000000000000000000000 10001000000100001110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000110110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111100001000000100 00100000000000000000000000000000 00000000000000000000000000000000 10000000000001000110010000000000 10111001000000000010111001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000000010111001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000000011 10010000000000101110000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00011000000001010010010000000000 10111001000000000010111001000000 00001001100100000000001011100100 00000000101110010000000000101110 01000000000010111001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101100011000000000 01000000000000000000000000000000 00000000000000000000000000000000 00001000000001000000010000000000 10110001000000000010110001000000 00001011000100000000001011000100 00000000101100010000000000101100 01000000000010110001000000000010 11000100000000001011000100000000 00101100010000000000101100010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101100001000000001 00100000000000000000000000000000 00000000000000000000000000000000 10111000000011010110000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111110111000000111 01010000000000000000000000000000 00000000000000000000000000000000 10011000000111011110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000011111100100000000001111 10010000000000111110111000000110 01110000000000000000000000000000 00000000000000000000000000000000 00011000000011011110010000000000 11111001000000000011111001000000 00001111100100000000001110100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011101001000000000111111001 00000000001111100100000000001111 10010000000000111110111000000000 01110000000000000000000000000000 00000000000000000000000000000000 00111000000000001110000000000000 10111000000000000010111000000000 00001011100000000000001011100000 00000000111010000000000000101110 00000000000010111000000000000010 11100000000000001011100000000000 00101110000000000000101110000000 00000010111000000000000010111000 00000000001011100000000000001111 10000000000000111100011000000000 00110000000000000000000000000000 00000000000000000000000000000000 01001000000001011100010000000000 10110001000000000010110001000000 00001011000100000000001010000100 00000000101100010000000000101100 01000000000010110001000000000010 11000100000000001011000100000000 00101100010000000000101100010000 00000010100001000000000010110001 00000000001011000100000000001011 00010000000000101101001000000000 00100000000000000000000000000000 00000000000000000000000000000000 00011000000101011010010000000000 10111001000000000010111001000000 00001011100100000000001011100100 00000000101010010000000000101110 01000000000010111001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001010 10010000000000101000011000000100 00100000000000000000000000000000 00000000000000000000000000000000 10100000000101001010010000000000 11111001000000000011111001000000 00001111100100000000001110100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011101001000000000010111001 00000000001111100100000000001011 10010000000000101110100000000000 00100000000000000000000000000000 00000000000000000000000000000000 01101000000000001010010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111010010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111101101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00101000000100001010000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000010001111100000000000001111 10000000000000111100101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00101000000001000010100000000000 10111010000000000010111010000000 00001011101000000000001011101000 00000000101110100000000000101110 10000000000010111010000000000011 10101000000000001011101000000000 00101110100000000000101110100000 00000010111010000000000010111010 00000000001011101000000000001011 10100000000000101100001000000000 01000000000000000000000000000000 00000000000000000000000000000000 00101000000001010100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101100001100000000 01010000000000000000000000000000 00000000000000000000000000000000 00100000000000010001110000000000 10110111000000000010110111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 10011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000100101100100000000000 01000000000000000000000000000000 00000000000000000000000000000000 00101000000000000001111000000000 11110111100000000010110111100000 00001111011110000000001111011110 00000000111101111000000000111101 11100000000011110111100000000011 11011110000000001111011110000000 00111101111000000000111101111000 00000011110111100000000011110111 10000000001111011110000000001111 01111000000000111100101000000110 00000000000000000000000000000000 00000000000000000000000000000000 00001000000101011010110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 10101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111100001000000110 01100000000000000000000000000000 00000000000000000000000000000000 01000000000001011111111000000000 11111111100000000011111111100000 00001110111110000000001111111110 00000000111011111000000000111111 11100000000011111111100000000011 11111110000000001111111110000000 00111111111000000000111111111000 00000011111111100000000011111111 10000000001111111110000000001111 11111000000000111101100000000000 00100000000000000000000000000000 00000000000000000000000000000000 10101000000100011001110000000000 10110111000000000010110111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001111 01110000000000101110101000000000 00100000000000000000000000000000 00000000000000000000000000000000 00000000000000001001110000000000 10110111000000000010110111000000 00001010011100000000001011011100 00000000101001110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101001110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101100010000000000 00100000000000000000000000000000 00000000000000000000000000000000 01100000000101001100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001010 00110000000000101101001000000100 00100000000000000000000000000000 00000000000000000000000000000000 10101000000101011010110000000000 11111011000000000011111011000000 00001110101100000000001011101100 00000000111010110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111010110000 00000010111011000000000011111011 00000000001111101100000000001011 10110000000000111110101000000000 01100000000000000000000000000000 00000000000000000000000000000000 10000000000000001110110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000010000111110110000000100 00110000000000000000000000000000 00000000000000000000000000000000 00000001000100001111110000000000 11111111000000000011111111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001101 11110000000000111110000001000100 00110000000000000000000000000000 00000000000000000000000000000000 10000000000001000110110000000000 10111011000000000010111011000000 00001011101100000000001011101100 00000000101110110000000000111110 11000000000010111011000000000011 10101100000000001011101100000000 00101110110000000000101110110000 00000011111011000000000010111011 00000000001011101100000000001011 10110000010000101110000001100000 00010000000000000000000000000000 00000000000000000000000000000000 10000000000001010110110000000000 10111011000000000010111011000000 00001011101100000000001011101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101110000000000000 01010000000000000000000000000000 00000000000000000000000000000000 00001000000000000000110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101000 11000000000010110011000000000010 10001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101100001000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000010000110110000000000 11111011000000000010111011000000 00001111101100000000001111101100 00000000111110110000000000101110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001101 10110000000000111110000000000110 00010000000000000000000000000000 00000000000000000000000000000000 10100000000110011111110000000000 11111111000000000011111111000000 00001111111100000000011111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011101111000000000011111111 00000000001111111100000000001111 11110000001000111110100000100010 01110000000000000000000000000000 00000000000000000000000000000000 11000000000000011111111000000000 11111111100000000011111111100000 00001101111110000000001111111110 00000000111111111000000000111111 11100000000011111111100000000011 11111100000000001011111110000000 00111111111000000000111111111000 00000011111111100000000011111111 10000000001111111110000000001111 11111000000000111111000000000000 01110000000000000000000000000000 00000000000000000000000000000000 10000000000000001110111000000000 10111011100000000010111011100000 00001011101110000000001011101110 00000000101110111000000000101110 11100000000010111011100000000010 11111110000000001011101110000000 00101110111000000000101110111000 00000010011011100000000010111011 10000000001011101110000000001011 10111000000000101110000000000110 00110000000000000000000000000000 00000000000000000000000000000000 10001000000001011100110000000000 10110011000000000010110011000001 00001011001100000100001011001100 00000000101100110000000000001000 11000000000010110011000000000010 11001100000000001001001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001010 00110000000000101010001000000001 01100000000000000000000000000000 00000000000000000000000000000000 11000000000101011010110000000000 10111011000000000010111011000000 00001011101100000000001011101100 00000000101110110000000000101110 11000000000010111011000000000010 11111100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101111000000000001 01110000000000000000000000000000 00000000000000000000000000000000 01000000000101011110110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111010 11000000000011111011000000000010 11101100000000001111101100000000 00111110110000011000111110110000 00000001111011000000000011111011 00000000001111101100000000001111 10110000000000111101000000000100 01110000000000000000000000000000 00000000000000000000000000000000 11100000000000011011110000000000 11111111000000000011111111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011011111000000000011111111 00000000001111111100000000001111 11110000000000111111100000000000 01100000000000000000000000000000 00000000000000000000000000000000 01000000000100001010110000000000 11111011000000000011111011000000 00011111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100001000001111101100000000 00111110110000000000111110110000 00000111111011000000000011111011 00000000001111101100000000001111 10110000000000111101000000000100 00100000000000000000000000000000 00000000000000000000000000000000 11001000000001010010110000000000 10111011000000100010111011000001 10001011101100000000001011101100 00001000101110110000000000111110 11000000000010111011000000000010 11101111000000001110101100000000 00101110110000000000101110110000 00000011111011000000000010111011 00000000001011101100000000001011 10110000000000101111001000000000 01000000000000000000000000000000 00000000000000000000000000000000 11100000000001010100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001101010000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101111000000000000 00010000000000000000000000000000 00000000000000000000000000000000 00100000000000010001111000000000 10110111100000000010110111100000 10011011011110000010001011011110 00000000101101111000000000101001 11100000000010110111100000000010 11011110000000001010011110000000 00101101111000000000101101111000 00000010100111100000000010110111 10000000001011011110000000001011 01111000000000101100100000000100 00010000000000000000000000000000 00000000000000000000000000000000 01001000000000000000110000000000 11110011000000000011110011000000 00001011001100000000001111001100 00000000111100110000000000101100 11000000000011110011000000000011 11001100000000001111001100000000 00111100110000000000111100110000 00000010110011000000000011110011 00000000001111001100000000001111 00110000000000111101001000000010 00010000000000000000000000000000 00000000000000000000000000000000 01000000000111011011110000000000 11111111000000000011111111000000 00001111111100000010001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111110000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111101000000000100 01100000000000000000000000000000 00000000000000000000000000000000 10101000000001011110110000000000 11111011000000000011111011000000 00001110101100000001001111101100 00000000011110110000000000111110 11000000000011111011000000000011 11001100010000001100101100000000 00111110110000000000101110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111100001000000000 01110000000000000000000000000000 00000000000000000000000000000000 01001000000100011001110000000000 10110111000000000010110111000000 00000011011100000000001011011100 00000001101101110000000000111001 11000000000010010111000000000010 11011100100000001010011100000000 00101101110000000000001101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101101001000000110 01100000000000000000000000000000 00000000000000000000000000000000 11000000000000001001111000000000 10110111100000000010110111100000 00001011011110000000001010011110 00000001101001111000000000101101 11100000000010110111100000000010 11011110000000001000011110000000 00101101111000000000101101111000 00100010110111100000000010110111 10000000001011011110000000001011 01111000000000101100100000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000101001100110000000000 10110011000000000010110011000000 00001011001100000100001011001100 00000000101100110000000000101100 11000000000010010011000000000010 11001100000000001010001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101101101000000000 00110000000000000000000000000000 00000000000000000000000000000000 11101000000101011010100000000000 11111010000000000011111010000000 00001111101000000000001111101000 00000000111110100000000000111110 10000000000011111010000000000011 11101000000000001100101000000000 00111110100000000000111110100000 00000011111010000000000011111010 00000000001111101000000000001111 10100000000000111111101000000100 01010000000000000000000000000000 00000000000000000000000000000000 01001000000000001110000000000000 11111000000000000011111000000000 00001111100000000001001111100000 00000100111110000000000000111010 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111101001000000000 01100000000000000000000000000000 00000000000000000000000000000000 00001000000100001110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001100100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111100001000000100 00100000000000000000000000000000 00000000000000000000000000000000 10000000000001000110010000000000 10111001000000000010111001000000 00001011100100000000001011100100 00000000111010010000000000101110 01000000000010111001000000010010 11010101000000001000100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101110000000000000 00010000000000000000000000000000 00000000000000000000000000000000 00011000000000010010010000000000 10111001000000000010111001000000 00011011100100000000001011100100 00000000101110010000000000101110 01000000000010111001000000000010 11100100000000001000100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101100111000000000 01000000000000000000000000000000 00000000000000000000000000000000 00001000000001000000010000000000 10110001000000000110110001000000 00001011000100000000001011000100 00000000101000010000000000101100 01000000000010110001000000000010 11000100001000101000000100000000 00101100010000000000101100010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101100101000000101 00000000000000000000000000000000 00000000000000000000000000000000 10111000000011000010000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11101010100000001100100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111110111000000011 01010000000000000000000000000000 00000000000000000000000000000000 10011000000011011110010000000000 11111001000000000011111001000000 00001111100100000000001011100100 00000000111010010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111110011000000100 01110000000000000000000000000000 00000000000000000000000000000000 00011000000001011110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000101110010000000000111110 01000000000011111001000000000011 11110110000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111100011000000000 01110000000000000000000000000000 00000000000000000000000000000000 00111000000100001110000000000000 10111000000000000010111000000000 00001011100000000000001011100000 00000000101110000000000000101110 00000000000010111000000000000010 11100000000000001011100000000000 00101110000000000000101110000000 00000110111000000000000010111000 00000000001011100000000000001011 10000000000000101100111000000110 00100000000000000000000000000000 00000000000000000000000000000000 00001000000001011100010000000000 10110001000000000010110001000000 00001011000100000000001011000100 00000100101100010000000001101100 01000000000010110001000000000010 11000101000000001011000100000000 00101100010000000000101100010000 00000000110001000000000010110001 00000000001011000100000000001010 00010000000000101101001000000001 00100000000000000000000000000000 00000000000000000000000000000000 00011000000100011010010000000000 10111001000000000010111001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000000010111001000000000010 11100100000000011011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101100011000000000 00100000000000000000000000000000 00000000000000000000000000000000 10100000000101011110010000001000 11111001000000000011111001000000 00001111100100000000001011100100 00000001101110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000010111001000000000011111001 00000000001111100100000000001111 10010000000000111110100000000100 01110000000000000000000000000000 00000000000000000000000000000000 00101000010000011010010000000000 11111001000000000011111001000000 00001111100100000010001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111101001000000000 01100000000000000000000000000000 00000000000000000000000000000000 00101000000100001010000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000100000001011100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111100001000000100 00100000000000000000000000000000 00000000000000000000000000000000 00101000000001010010100000000000 10111010000000000010111010000000 00001011101000000001001011101000 00000000111010100000000000101110 10000000000010111010000000000010 11111000000000001011101000000000 00101110100000001000101110100000 00000010111010000000000010111010 00000000001011101000000000001011 10100000000000101100101000000000 01000000000000000000000000000000 00000000000000000000000000000000 00101000000001010100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000001100110000000000001100 11000000000010110011000000000010 11000100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101100101000000000 01010000000000000000000000000000 00000000000000000000000000000000 10100000000000010001110000000000 10110111000000000010110111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11010101000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101110000000000100 01000000000000000000000000000000 00000000000000000000000000000000 10101000000010000001111000000000 11110111100000000011110111100000 00001111011110000000001111011110 00000000111101111000000001111101 11100000010011110111100000100011 11010110000000001111011110000000 00111101111000000000111101111000 00000011110111100000000011110111 10000000001111011110000000001111 01111000000000111110001000000010 00100000000000000000000000000000 00000000000000000000000000000000 00001000000011011010110000001000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111010110000000000111110 11000000000011111011000000000011 11100100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001011 10110000000000111100001000000100 01100000000000000000000000000000 00000000000000000000000000000000 00000000000001011111111000000000 11111111100100000011111111100100 00001011111110010000001111111110 00000000111111111000000000111111 11100000000011111111100000000011 11110110000000001100111110000000 00111111111000000000111111111000 00000011111111100000000011111111 10000000001111111110000000001111 11111000000000111100000000000000 00100000000000000000000000000000 00000000000000000000000000000000 10101000000100011001110000000000 10110111000000000010110111000000 00001011011100000100001011011100 01010000101101110000000000101101 11000000000010110111000000000010 11010101000000001010011100000000 00101101110000000000101101110000 00000001100111000000000010110111 00000000001011011100000000001011 01110000000000101110001000000110 00100000000000000000000000000000 00000000000000000000000000000000 00000000000000001001110000000000 10110111000000010010110111000000 00000010011100000010001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11000100000000001001011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101000000000000000 00100000000000000000000000000000 00000000000000000000000000000000 00100000000101001100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000100101100110000001000101100 11000000000010110011000000000010 11000100000000001011001100000000 00101100110000000000101100110000 00000000100011000000000010110011 00000000001011001100000000000011 00110000000000101100100000000000 00100000000000000000000000000000 00000000000000000000000000000000 10101000000101011010110000000000 11111011000000000011111011000000 00001111101100000000001011101100 00000000111110110000000000001110 11000000000011111011000000000011 11000100000000001101101100000000 00111110110000000000101110110000 00000010111011000000000011111011 00000000001111101100000000001011 10110000000000111110101100000100 01100000000000000000000000000000 00000000000000000000000000000000 10000000000000001110110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000100111110 11000000010011111011000000000011 11101100000000001110101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111110000000000000 00110000000000000000000000000000 00000000000000000000000000000000 00000001000100001111110000000000 11111111000000000011111111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11110100100000001101111100000000 00111111110000000001111111110000 00000011101111000000000011111111 00000000001111111100000000001111 11110000000000111100100001000100 00010000000000000000000000000000 00000000000000000000000000000000 10000001000001000110110000000000 10111011000000000010111011000000 00001011101100000000001011101100 00000000101110110000000000111110 11000000000010111011000000000010 11101110000000001000101100000000 00101110110000000000101110110000 00000011101011000000000010111011 00000000001011101100000000001011 10110000000000101110100001000000 00010000000000000000000000000000 00000000000000000000000000000000 10000000000001010010110000000000 10111011000000000010101011000000 00001011101100000000001011101100 00000000101110110000000000101110 11000000000010111011000000000010 11101000000000001001101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101110000000000000 01000000000000000000000000000000 00000000000000000000000000000000 00001000000001000000110000000000 10110011000000000010110011000000 00011011001100000000001011001100 00000001101100110000000000101000 11000000000010110011000000000010 11001100000000001000001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000011011 00110000000000101100001000000100 00000000000000000000000000000000 00000000000000000000000000000000 00000000000011010110110000000000 11111011000000000011101011000000 00001111101100000000001111101100 00000000111110110000000000101110 11000000000011111011000000000011 11101100000000001101101100000000 00111110110000000000101110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111100000000000011 00010000000000000000000000000000 00000000000000000000000000000000 10100000000110011111110000000000 11111111000000000011111111000000 00001111111100000000011111111100 00000000111111110000000001111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000001111111110000 00000011101111000000000011111111 00000000001111111100000000011111 11110000000000111110100000000101 01110000000000000000000000000000 00000000000000000000000000000000 11000000000001011111111000000000 11101111100000000011111111100001 10001111111110000000001101111110 00000000111111111000000000111111 11100000000011111111100000000011 11111110000000001111111110000000 00111111111000000000111111111000 00000011111111100000000011111111 10000000001111111110000000001111 11111000000000111111000000000000 01110000000000000000000000000000 00000000000000000000000000000000 10000000000100001110111000000000 10111011100000000011101011100000 00001011101110000000001011101110 00000000101110111000000000101110 11100000000010111011100000000010 11101110000000001011101110000000 00101110111000000000101110111000 00000011111011100000000010111011 10000000001111101110000000001111 10111000010000101110000000000100 00110000000000000000000000000000 00000000000000000000000000000000 10001000000001011100110000000000 10100011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00100100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101110001000000001 01110000000000000000000000000000 00000000000000000000000000000000 11000000000101011010110000000000 10111011000000000010101011000000 00001011101100000000001011101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010101011000000000000111011 00000000001010101100000000001010 10110000000001101111000000000100 01100000000000000000000000000000 00000000000000000000000000000000 00000000000101011110110000000000 11101011000000000011111011000000 00001111101100000000001101101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000010111011000000000011111011 00000000001011101100000000001011 10110000000000111100000000000100 01110000000000000000000000000000 00000000000000000000000000000000 11100000000000011011110000000000 11111111000000000011111111000000 00001111111100000000000111111100 00000000111111110000000000111111 11000000000001111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111111100000000000 01100000000000000000000000000000 00000000000000000000000000000000 01000000000100001010110000010000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111101000000000100 00100000000000000000000000000000 00000000000000000000000000000000 11001000010001010010110000000000 10111011000000000010111011000000 00001011101100000000001011101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101111001000000000 01000000000000000000000000000000 00000000000000000000000000000000 11100000000001010100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101111100100000000 01010000000000000000000000000000 00000000000000000000000000000000 01100000000000010001111000000000 10110111100000000010110111100000 00001011011110000000001011011110 00000000101101111000000000101101 11100000000010110111100000000010 11011110000000001011011110000000 00101101111000000000101101111000 00000010110111100000000010110111 10000000001011011110000000001011 01111000000000101101100000000000 01000000000000000000000000000000 00000000000000000000000000000000 01001000000010000000110000000000 11110011000000000011110011000000 00001111001100000000001111001100 00000000111100110000000000111100 11000000000011110011000000000011 11001100000000001111001100000000 00111100110000000000111100110000 00000011110011000000000011110011 00000000001111001100000000001111 00110000000000111101001000000010 00000000000000000000000000000000 00000000000000000000000000000000 01000000000111011011110000000000 11111111000000000011111111000000 00001111111100000000011111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111101000000000010 01100000000000000000000000000000 00000000000000000000000000000000 10101000000001011110110000000000 11111011000000000011111011000000 00001110101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000001111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111110101000000000 01110000000000000000000000000000 00000000000000000000000000000000 01001000000100011001110000000000 10110111000000000010110111000000 00001011011100000000001111011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001110011100000000001111 01110000000000111101001000000100 01100000000000000000000000000000 00000000000000000000000000000000 11000000000000001001111000000000 10110111100000000010110111100000 00001010011110000000001011011110 00000000101101111000000000101101 11100000000010110111100000000010 11011110000000001011011110000000 00101101111000000000101101111000 01000010110111100000000010110111 10000000001011011110000000001011 01111000000000101111000000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000101001100110000000000 10110011000000000010110011000000 00001011001100000000001010001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000100100110000 00000010110011000000000010110011 00000000001010001100000000001010 00110000000000101001001000000100 00110000000000000000000000000000 00000000000000000000000000000000 11101000000101011010100000000000 11111010000000000011111010000000 00001110101000000000001011101000 00000000111110100000000000111110 10000000000011111010000000000011 11101000000000001111101000000000 00111110100000000000111110100000 00000011111010000000000011111010 00000000001111101000000000001011 10100000000000101111101000000100 01100000000000000000000000000000 00000000000000000000000000000000 01001000000000001110000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001110100000000001001111 10000000000000111101001000000000 00110000000000000000000000000000 00000000000000000000000000000000 00001000000100001110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111100001000000100 00110000000000000000000000000000 00000000000000000000000000000000 10000000000001000110010000000000 10111001000000000000111001000000 00001011100100000000001011100100 00000000100110010000000000101110 01000000000010111001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101110000000000000 00010000000000000000000000000000 00000000000000000000000000000000 00011000000001010010010000000000 10111001000000000010111001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000000010111001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101100011000000000 01000000000000000000000000000000 00000000000000000000000000000000 00001000000000000000010000000000 10110001000000000010110001000000 00001011000100000000001011000100 00000000101100010000000000101100 01000000000010110001000000000010 11000100000000001011000100000000 00101100010000000000101100010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101100001000000001 00100000000000000000000000000000 00000000000000000000000000000000 10111000000011000110000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111110111000000011 01010000000000000000000000000000 00000000000000000000000000000000 10011000000111011110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000110110010000000000111110 01000000000011111001000000000010 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111110011000000110 01110000000000000000000000000000 00000000000000000000000000000000 10011000000001011110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111110011000000000 01110000000000000000000000000000 00000000000000000000000000000000 00111000000100001110000000000000 11111000000000000011101000000000 00001011100000000000001011100000 00000000101110000000000000101110 00000000000010111000000000000010 11100000000000001011100000000000 00101110000000000000001110000000 00000010111000000000000011111000 00000000001011100000000000001111 10000000000000101100111000000100 00010000000000000000000000000000 00000000000000000000000000000000 00001000000001011100010000000000 10110001000000000010110001000000 00001011000100000000001011000100 00000000101100010000000000101100 01000000000010110001000000000010 11000100000000001011000100000000 00101100010000000000101100010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101100001000000001 01110000000000000000000000000000 00000000000000000000000000000000 00011000000101011010010000000000 10101001000000000010101001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000000010111001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010101001 00000000001011100100000000001010 10010000000000101100011000000100 01100000000000000000000000000000 00000000000000000000000000000000 10100000000101011110010000000000 10111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000010111001 00000000001111100100000000001011 10010000000000111110100000000100 00100000000000000000000000000000 00000000000000000000000000000000 00101000000000011010010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111100101000000000 00100000000000000000000000000000 00000000000000000000000000000000 00101000000100001010000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111100101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00101000000001010010100000000000 10111010000000000010111010000000 00001011101000000000001011101000 00000000101110100000000000101110 10000000000010111010000000000010 11101000000000001011101000000000 00101110100000000000101110100000 00000010111010000000000010111010 00000000001011101000000000001011 10100000000000101100101000000000 00000000000000000000000000000000 00000000000000000000000000000000 00101000000001010100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101100101000000000 01010000000000000000000000000000 00000000000000000000000000000000 10100000000000010001110000000000 10110111000000000010110111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101100100000000000 01000000000000000000000000000000 00000000000000000000000000000000 10101000000010000001111000010000 11110111100000000011110111100000 00001111011110000000001111011110 00000000111101111000000000111101 11100000000011110111100000000011 11011110000000001111011110000000 00111101111000000000111101111000 00000011110111100000000011110111 10000000001111011110000000001111 01111000000000111100101000000010 00000000000000000000000000000000 00000000000000000000000000000000 00001000000111011010110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000111111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000001000111100001000000110 01100000000000000000000000000000 00000000000000000000000000000000 01000000000001011111111000000000 11111111100000000011111111100000 00001111111110000000001111111110 00000000111111111000000000111111 11100000000011111111100000000011 11111110000000001111111110000000 00111111111000000000111111111000 00000011111111100000000011111111 10000000001111111110000000001111 11111000000000111101000000000000 01110000000000000000000000000000 00000000000000000000000000000000 10101000000100011001110001000000 10110111000000000010110111000000 00001011011100000000001110011100 00000000101101110000000001101101 11000000000011100111000000000010 11011100000000011011011100000000 00101101110000000000101101110000 00000011110111000000000011110111 00000000001011011100000000001110 01110000000000111110101000000100 01100000000000000000000000000000 00000000000000000000000000000000 00010000000000001001110000000000 10110111000000000010110111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101100010000000000 00100000000000000000000000000000 00000000000000000000000000000000 01100000000101001100110000000000 10110011000000000010110011000000 00001011001100000000001010001100 00000000101100110000000000101100 11000000000010100011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010100011000000000010100011 00000000001011001100000000001010 00110000000000101001100100000100 00110000000000000000000000000000 00000000000000000000000000000000 10111000000101011010110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000001000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000010111011000000000010111011 00000000001111101100000000001011 10110000000000101110101000000100 01100000000000000000000000000000 00000000000000000000000000000000 10000000000000001110110000000000 11111011000000000011111011000000 00001111101100000000001110101100 00000000111110110000000000111110 11000000000011101011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000011001110 10110000000000111110010100000000 00110000000000000000000000000000 00000000000000000000000000000000 10010000000100001111110000000000 11111111000000000011111111000000 00001111111100000000001110111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000001111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111110000001000100 00110000000000000000000000000000 00000000000000000000000000000000 10000001000001000110110000000000 10111011000000000010111011000000 00001011101100000000001011101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000000011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101110000001100000 00010000000000000000000000000000 00000000000000000000000000000000 10000000000001010010110000000000 10111011000000000010111011000000 00001011101100000000001011101100 00000000101110110000000000001110 11000000000010111011000000000010 11101100000000001011101100000000 00101010110000000000101110110000 00000010111011000000000110111011 00000000001011101100000000001011 10110000000100101110000000000000 01010000000000000000000000000000 00000000000000000000000000000000 00001000000001000000110000011000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101100001000000001 00000000000000000000000000000000 00000000000000000000000000000000 10000000000011010110110000000000 11111011000000000011111011000000 00001111101100000000001110101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000101110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111110000000000010 00000000000000000000000000000000 00000000000000000000000000000000 10100000000111011111110000000000 11111111000000000011111111000000 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000010000111111110000 00000011111111000000000011111111 00000000001111111100000000011111 11110000000000111110100000000111 01110000000000000000000000000000 00000000000000000000000000000000 11000000000001011111011000000000 11001111100000000011001100000000 00001000111110000000001100111110 00000100111111111000010000111111 11100000000011111111100000000011 11111110000000001111111110000000 00111111111000000000111111111000 00000011111111100000000011111111 10000000001111111110000000001111 11111000000000111111000000000000 01110000000000000000000000000000 00000000000000000000000000000000 10000000000100001110010000000000 10001010000000000010001010000000 00001000101100000000101000101110 00000000101110111000000000101110 11100000000010111011100000000010 11101110000000001011101110000000 00101110111000000000101110111000 00000010111011100000100010111011 10000000001011101110000000001011 10111000000000101110000000000110 00110000000000000000000000000000 00000000000000000000000000000000 10001000000001011110110000000010 10001011000000000010000000000000 01001000001100000000001000001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000110110011000000000010110011 00000000001011001100000000001011 00110000000000101110001000000001 01110000000000000000000000000000 00000000000000000000000000000000 11000000000101011010011000000000 10001011000000000010001011010000 00001000001100000100001000101100 00000000101110110000000100101110 11000000000010111011000000000010 11101100000000001011101100000000 00101110110000010000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101111000000000000 01100000000000000000000000000000 00000000000000000000000000000000 01000000000101011110111110000100 11000010100000001011001000000000 00101100101100000000001100101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000001001111101100000100001111 10110000000000111101000000000100 01110000000000000000000000000000 00000000000000000000000000000000 11100000000000011011010000000000 11111110101000100011111100000000 00101111111100000010001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000100111111110000 00010011111111000000000011111111 00000000001111111100000000001111 11110000000000111111100000000000 01100000000000000000000000000000 00000000000000000000000000000000 01000000000100001010110100000000 11001011000100000011000011010010 00001000101100000000001011101100 00000000111110110000000000111110 11000000010011111011000001000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000010111011 00000000001111101100000000001111 10110000000000111101000000000100 00100000000000000000000000000000 00000000000000000000000000000000 11001000000001010000110010000000 10001010000000100010001011000011 00001000101111011000001011101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000001011101100000000 00101110110000001000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101111001000000000 01000000000000000000000000000000 00000000000000000000000000000000 11100000000001010100010000000000 10000011000010010010000001000000 00101000001110000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101111000000000000 00010000000000000000000000000000 00000000000000000000000000000000 00100000000000010001001000000010 10001110100000000010000111100100 00001000011110000000001011011110 00000000101101111000000000101101 11100000000010110111100000000010 11011110000000001011011110000000 00101101111000000000101101111000 00000010110111100000100010110111 10000000001011011110000000001011 01111000000000101100100000000000 00010000000000000000000000000000 00000000000000000000000000000000 01001000000010000010110000000000 11000011000000010011001000000100 00101100001100010000001111001100 00000000111100110000000000111100 11000000000011110011000000000011 11001100000000001111001100000000 00111100110000000000111100110000 00000011110011000100000011110011 00000000001111001100000000001111 00110000000000111101001000000010 00010000000000000000000000000000 00000000000000000000000000000000 01000000000111011011110000000010 11110100000000101011111110000100 00001111111100010000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000010 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111101000000000110 01100000000000000000000000000000 00000000000000000000000000000000 10101000000001011100010000000010 11001011000000000010001001010010 01001100101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000000111101100000000001111 10110000000000111100001000000000 01110000000000000000000000000000 00000000000000000000000000000000 01001000000100011001010000000000 10001110000000000010000101000000 00001000011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000100101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101101001000000110 01000000000000000000000000000000 00000000000000000000000000000000 11000000000000001011111000100000 10000111100000000010000110100010 00001000011110000000001011011110 00000000101101111000000000101101 11100000000010110111100000000010 11011110000000001011011110000000 00101101111000000000001101111000 00000010110111100000000010110111 10000000001011011110000000001011 01111000000000101100100000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000101001100111000000000 10000000010010001010000011000000 00001000001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101101101000000000 00110000000000000000000000000000 00000000000000000000000000000000 11101000000101011001100100000000 11001110010000010011001010010000 00101100101000000000001111101000 00010000111110100000000000111110 10000000000011111010000000000011 11101000000000001111101000000000 00101110100000000000111110100000 00000011111010000000000011111010 00000000001111101000000000001111 10100000000000111111101000000100 01110000000000000000000000000000 00000000000000000000000000000000 01001000000000001110000000100000 11111000000000000011110000010010 00001111100000000000001111100000 00000100111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111101001000000000 01100000000000000000000000000000 00000000000000000000000000000000 00001000000100001110011000000000 11001001000100000011001011000100 00001100100111000100001100100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111100001000000100 00100000000000000000000000000000 00000000000000000000000000000000 10000000000001000110011100001000 10001001110000000010001001110000 00101000100110000000101000100100 00000000101110010000000000101110 01000000000010111001000000000010 11100100000010001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101110000000000000 00010000000000000000000000000000 00000000000000000000000000000000 00011000000001010010010001000010 10000011010000000010001001000000 01001000000100000000001000100100 00000000101110010000000000101110 01000000000010111001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101100111000000000 01000000000000000000000000000000 00000000000000000000000000000000 00001000000001000010011000000000 10000001010000001010000011001000 00001000000101000010101000000100 00000000101100010000000000101100 01000000000010110001000000000010 11000100000000001011000100000000 00101100010000000000101100010000 00000010110001000000010010110001 00000000001011000100000000001011 00010000000100101100101000000101 00000000000000000000000000000000 00000000000000000000000000000000 10111000000011010110000100000000 11001000010000010011000000000101 00001100101001000000001100100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 01111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111110111000000011 01010000000000000000000000000000 00000000000000000000000000000000 10011000000111011111010000100000 11111101000000000011111001010000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 01000011111001000000000011111001 00000000001111100100000000001111 10010000000000111110011000000100 01110000000000000000000000000000 00000000000000000000000000000000 00011000000001011110010000000000 11001001000000000011001001000000 00001100100100000000000111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000000111100100000000001111 10010000000000111100011000000000 01110000000000000000000000000000 00000000000000000000000000000000 00111000000100001100000000000010 10001000000000001010001000000000 00001000110000000000001011100000 00000000101110000000000000101110 00000000000010111000000000000010 11100000000000001011100000000000 00101110000000000000101110000000 00000010111000000000000010111000 00000000001011100000000000001011 10000000000000101100111000000110 00100000000000000000000000000000 00000000000000000000000000000000 00001000000001011101010000000010 10000101000000000010000101000000 00001000010100000100001001000100 00000000101100010000000000101100 01000000000010110001000000000010 11000100000000001001000100000000 01101100010000000000001100010000 00100000110001000000000010110001 00000000001011000100000000001011 00010000000000101101001000000001 00100000000000000000000000000000 00000000000000000000000000000000 00011000000101011010011000001000 10000101000000000010000101000000 00001000111100000000001011100100 00000000101110010000000000101110 01000000000010111001000000000010 11100100000000001011100100000000 00101110010000000000100110010000 00000000111001000000000010111001 00000000001011100100000000001011 10010000000000101100011000000000 00100000000000000000000000000000 00000000000000000000000000000000 10100000000101011110010010000010 11001001001000000011001001101000 00101100100100000000001101100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001101100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111110100000000100 01110000000000000000000000000000 00000000000000000000000000000000 00101000000000011010010000100100 11111001100101000011111001001000 00001111100100000000001111100100 00000100111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111101001000000000 01100000000000000000000000000000 00000000000000000000000000000000 00101000000100001010000100000000 11001000110001000011001000100000 00001111100000000000001100100000 00001000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000001010011111000 00000000000111100000000001001111 10000000010000111100001000000100 00000000000000000000000000000000 00000000000000000000000000000000 00101000000001010010101100000000 10001010000000000010001010001000 00001011101000000000001000101000 00000000101110100000000000101110 10000000000010111010000000000010 11101000000010001011101000000010 00101110100000000000101110100000 00000010111010000000000010111010 00000000001011101000000000001011 10100000000000101100101000000000 01000000000000000000000000000000 00000000000000000000000000000000 00101000000001010110110101000000 10000011000000000010000011100000 00001011001110000000001000001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101100101000000000 01010000000000000000000000000000 00000000000000000000000000000000 10100000000000010001110000000000 10000111000000001010000111000000 00001011011111000000001000011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000010 00101101110000000000101101110000 01000010110111000000000010110111 00000000001011011100000000001011 01110000000000101110000000000100 01100000000000000000000000000000 00000000000000000000000000000000 10101000000010000001101000000010 11001111100000001011000111100000 00001111111010010000101100011110 00001000111101111000000000111101 11100000100011110111100000000011 11011110000000001111011110000000 00011101111000000000111101111000 00000011110111100000100011110111 10000000001111011110000000001111 01111000000000111110001000000010 00000000000000000000000000000000 00000000000000000000000000000000 00001000000111011010000000000000 11111000000000000011111010000000 00001111101000000010001111101100 00000000111110110000000000111110 11000000000011111011000000000010 11101100000001001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001011101100000000001111 10110000000000111100001000000100 01100000000000000000000000000000 00000000000000000000000000000000 00000000000001011111111000000000 11001111100000000011001111100100 00001100111110000000001010111110 01000000111111111000001000011111 11100000100001111111100000000011 11111110000000001111111110010000 00111111111000000000111111111001 00000010111111100100100011111111 10000000001111111110000000001011 11111001000000111100000000000000 00100000000000000000000000000000 00000000000000000000000000000000 10101000000000011001110000000000 10000111001010000010000101000010 00001000011100100000001000011100 00000000001101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101110001 00010010010111000000000010110111 00000000001011011100000000001011 01110000000000101110101000000110 00100000000000000000000000000000 00000000000000000000000000000000 00000000000100001001100000000000 10000111000000010110000111000000 10001000010000000100001000011100 00000000101101110000000000100101 11000000000010110111000000000010 11011100000000001011011100000010 00101101110000000000101101110000 00100000110111000000100010110111 00000000001011011100000000001011 01110000001000101100000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00100000000101001110001001000000 10001000000000100100001000110000 00001000100000000000001000001100 00000000101100110000000001100100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000010000100100110000 00000010010011000000000010110011 00000000001011001100000100001011 00110000000000101100100100000000 00100000000000000000000000000000 00000000000000000000000000000000 10101000000101011010110000000010 11001001010000010011001011000000 00001100101100000000100100101100 00000000111110110000000000110110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000001111011000000000011111011 00000000001111101100000000001111 10110000000000111110101000000100 01100000000000000000000000000000 00000000000000000000000000000000 10000000000000001110110100000000 11111011000000000011111011000000 00001111100000000000001111101100 00000000111110110000000100111110 11000000010011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00010011011011000000000011111011 00000000001111101100000001001111 10110000000000111110000000000000 00010000000000000000000000000000 00000000000000000000000000000000 00000001000100001111110000100000 11001101000010000011001101000010 01001100111100000000001101111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111100100001000100 00110000000000000000000000000000 00000000000000000000000000000000 10000001000001000110010110010000 10001000010000000010001000010000 00001000101000000000011000101100 00000000101110110000000000101110 11000000000010111011000001000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101110100001000000 00010000000000000000000000000000 00000000000000000000000000000000 10000000000001010010001000000010 10001000100010000010001010110000 00001000101110000010001000101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000001011101100000000 00101010110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101110000000000000 01000000000000000000000000000000 00000000000000000000000000000000 00001000000001000000000000000010 10000011000000001010000000000000 01001000000000000000001000001100 00000100101100110000000000101100 11000000000010110011000000010010 11001100000000001011001100000000 00001100110000000000101100110000 00000000110011000000000110110011 00000000001011001100000001001011 00110000000000101100001000000101 00000000000000000000000000000000 00000000000000000000000000000000 00000000000001010100100000000000 11000000000000000011000011000000 01001100000100000000101100101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111100000000000011 01010000000000000000000000000000 00000000000000000000000000000000 10100000000101011111000000000000 11111100000000000011111100000000 00000111110000000100001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000010000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111110100000000000 01110000000000000000000000000000 00000000000000000000000000000000 11000000000001011111111000000000 11111111100000000011111111100000 00001110111110000000001101111110 00000000111111111000000000111111 11100000000011111111100000000011 11111110000000001101111110000000 00111111111000000000111111111000 00000011111111100000000011111111 10000000001111111110000000001111 11111000000000111111000000000000 01110000000000000000000000000000 00000000000000000000000000000000 10000000000100001110111000000000 10111011100000000010111011100000 00001011101110000001001011101110 00000000101110111000000000101110 11100000100010111011100000000010 11101110000000001011101110000000 00101110111000000000101110111000 00000010111011100000000010111011 10000000001011101110000000001011 10111000000000101110000000000100 00110000000000000000000000000000 00000000000000000000000000000000 10001000000001011100110000000000 10110011000000000010110011000000 00001010001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00100100110000001000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101110001000000001 01110000000000000000000000000000 00000000000000000000000000000000 11000000000101011010110000000000 10111011000000000010111011000000 00001011101100000000001011101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000100111011000000000000111011 00000000001011101100000000001011 10110000000000101111000000000100 01100000000000000000000000000000 00000000000000000000000000000000 00000000000101011110110000000000 11111011000001010011111011000000 01001110101100000000001101101100 00000000111110110000000000111110 11000000000011111011000001000011 11101100000000001101101100000000 00111110110000000000111110110000 00000011111011000001000011111011 00000000001111101100000000001111 10110000000000111100100000000100 01110000000000000000000000000000 00000000000000000000000000000000 11100000000000011011110000000000 11111111000000000011111111000000 00000111111100000000001011111100 00000000111111110000000000011111 11000000000001111111000000000011 11111100000000001111111100000000 01111111110000000000111111110000 00010011111111000000000011111111 00000000001111111100000000001111 11110000000000111111100000000000 01100000000000000000000000000000 00000000000000000000000000000000 01000000000100001010110000000000 11111011000000000011111011000000 00001110101100000000001110101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111101000000000100 00100000000000000000000000000000 00000000000000000000000000000000 11001000000001010010110000000000 10111011000000000010111011000000 00001011101100000000001011101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101111001000000000 01000000000000000000000000000000 00000000000000000000000000000000 11100000000001010100110000000000 10110011000000000010110011000001 00000011001100000100000011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000001000000110011 00000000001011001100000000001011 00110000000000101111000000000000 01010000000000000000000000000000 00000000000000000000000000000000 01100000000000010001111000000000 10110111100000000010110111100000 00001011011110000000001011011110 00000000101101111000000001101101 11100000000010110111100000000010 11011110000000001011011110000000 00101101111000000000101101111000 00000010110111100000000010110111 10000000001011011110000000001011 01111000000000101101100000000000 01000000000000000000000000000000 00000000000000000000000000000000 01001000000010000000110000000000 11110011000000000011110011000000 00001111001100010000001110001100 00000000111100110000000001111100 11000000000011110011000001010011 11001100000000001111001100000000 00111100110001000000111100110000 01000011110011000000000011110011 00000000001111001100000000001111 00110000000000111101101000000010 00000000000000000000000000000000 00000000000000000000000000000000 01000000000111011011110000000000 11111111000000000011111111000000 00001111111100000100001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000010000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111101000000000110 01100000000000000000000000000000 00000000000000000000000000000000 10101000000001011110110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111110101000000000 01110000000000000000000000000000 00000000000000000000000000000000 01001000000100011001110000000000 10110111000000000010110111000000 00001011011100000000011011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000001101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101101001000000100 01100000000000000000000000000000 00000000000000000000000000000000 11000001000000001001111000000000 10110111100000000010110111100000 00001011011110000000001011011110 00000000101101111000000000101101 11100000000010110111100000000010 11011110000000001011011110000000 00101101111000000000101101111000 00000010110111100000000010110111 10000000001011011110000000001011 01111000000000101111000000000000 00000000000000000000000000000000 00000000000000000000000000000000 01001000000101001100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000100101100110000000000101100 11000000000010110011000000100010 11001100000000001011001100000000 00101100110000000001100100110000 00000010010011000000000010110011 00000000001011001100000000001011 00110000000000101101001000000100 00110000000000000000000000000000 00000000000000000000000000000000 11101000100101011010100000000000 11111010000000000011111010000000 00001111101000000000001111101000 00000000111110100000000000111110 10000000000011111010000000000011 11101000000000001111101000000000 00111110100000000000111110100000 00000011111010000000000011111010 00000000001111101000000000001111 10100000000000111111101000000100 01100000000000000000000000000000 00000000000000000000000000000000 01001010000000001110000000000000 11111000000000010011111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000001001111 10000000000000111101001000000000 00110000000000000000000000000000 00000000000000000000000000000000 00001010000100001110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111100001000000100 00110000000000000000000000000000 00000000000000000000000000000000 10000000000001000110010000000000 10111001000000000010111001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000000010111001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101110000000000000 00010000000000000000000000000000 00000000000000000000000000000000 00011000000001010010010000000000 10111001000000000010111001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000000010111001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101100011000000000 01000000000000000000000000000000 00000000000000000000000000000000 00001000000001000000010000000000 10110001000000000010110001000000 00001011000100000000001011000100 00000000101100010000000000101100 01000000000010110001000000000010 11000100000000001011000100000000 00101100010000000000101100010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101100001000000001 00100000000000000000000000000000 00000000000000000000000000000000 10111000000011010110000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111110111000000011 01010000000000000000000000000000 00000000000000000000000000000000 10011000000111011110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000010 11100100000000001011100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111110011000000110 01110000000000000000000000000000 00000000000000000000000000000000 10011000000001011110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111110011000000000 01110000000000000000000000000000 00000000000000000000000000000000 00111000000100001110000000000001 10111000000000000010111000000000 00001011100000000000001011100000 00000000101110000000000000101110 00000000000010111000000000000010 11100000000000001011100000000000 00101110000000000000101110000000 00000000111000000000000010111000 00000000001011100000000000001011 10000000010000101100111000000100 00110000000000000000000000000000 00000000000000000000000000000000 00001000000001011100010000000000 10110001000000000010110001000000 00001011000100000000001011000100 00000000101100010000000000101100 01000000000010110001000000000010 11000100000000001011000100000000 00101100010000000000101100010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101100001000000001 01010000000000000000000000000000 00000000000000000000000000000000 00011000000101011010010000000000 10111001000000000010111001000000 00001011100100000000001011100100 00000000101110010000000000101110 01000000100010111001000000000010 11100100000000001011100100000000 00101110010000010000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101100011000000100 01100000000000000000000000000000 00000000000000000000000000000000 10100000000101011110010000000000 10111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111110100000000100 00100000000000000000000000000000 00000000000000000000000000000000 00101000000000011010010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111100101000010000 00100000000000000000000000000000 00000000000000000000000000000000 00101000000100001010000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000001000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111100101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00100000100001010010100000000000 10111010000000000010111010000000 00001011101000000000001011101000 00000000101110100000000000101110 10000000000010111010000000000010 11101000000000001011101000000000 00101110100000000000101110100000 00000010111010000000000010111010 00000000001011101000000000001011 10100000000000101100101000000000 00000000000000000000000000000000 00000000000000000000000000000000 00101000000001010100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101100101000000000 01010000000000000000000000000000 00000000000000000000000000000000 10100000000000010001110000000000 10110111000000000010110111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111000001000010110111 00000000001011011100000000001011 01110000000000101100100000000000 01000000000000000000000000000000 00000000000000000000000000000000 10101000000010000001111000000000 11110111100000000011110111100000 00001111011110000000001111011110 00000000111101111000000000111101 11100000000011110111100000000011 11011110000000001111011110000000 00111101111000000000111101111000 00000011110111100000000011110111 10000000001111011110000000001111 01111000000000111100101000000010 00000000000000000000000000000000 00000000000000000000000000000000 00001000000111011010110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111100001000000010 01100000000000000000000000000000 00000000000000000000000000000000 11000000000001011111111000001000 11111111100000000011111111100000 00001111111110000000001111111110 00000000111111111000000000111111 11100000000011111111100000000011 11111110000000001111111110000000 00111111111000000000111111111000 00000011111111100000000011111111 10000000000111111110000000001111 11111000000000111101000000000000 01110000000000000000000000000000 00000000000000000000000000000000 11101000000100011001110000000000 10110111000000000010110111000000 00001011011100000000001011011100 00000000101101110000000100101101 11000000000110110111000000000010 11011100000001001011011100000000 00101101110000000000101101110000 00000010110111000100000010110111 00000000001011011100000000011011 01110000000000101110101000000100 01100000000000000000000000000000 00000000000000000000000000000000 01000000000000001001110000000000 10110111000000000010110111000000 00001011011100000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101100010001000000 00100000000000000000000000000000 00000000000000000000000000000000 00100000000101001100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000001000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101101101000000100 00110000000000000000000000000000 00000000000000000000000000000000 11101000000101011010110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000111111011000000000011111011 00000010001111101100000011001111 10110000000100111110111000000100 01100000000000000000000000000000 00000000000000000000000000000000 10000000000000001110110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000010001111101100000100 00111110110000000000111110110000 00000011111011000000100011111011 00000001001111101100000000001111 10110000001000111110000000000000 00110000000000000000000000000000 00000000000000000000000000000000 11000000000100001111110000000000 11111111000000000011111111000000 00001111111100000000001111111100 00000000111111110000000000111011 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111110000001000100 00110000000000000000000000000000 00000000000000000000000000000000 10000001000001000110110000000000 10111011000000000010111011000000 00001011101100000000000011101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101110000001000000 00010000000000000000000000000000 00000000000000000000000000000000 10000000000001010010110000000000 10111011000000000010111011000000 00001011101100000000001011101100 00000000101110110000000000101110 11000000000010111011000000000010 11101100000000001011101100000001 00101110110000000000101110110000 00000010111011000000000010111011 00000100000001101100000000001011 10110000000000101110000000000000 01010000000000000000000000000000 00000000000000000000000000000000 00001000000001000000110000000100 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000100010110011 00000100001011001100000000001011 00110000000000101100001000000001 00000000000000000000000000000000 00000000000000000000000000000000 10000000000011010110110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111010 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111110000000000010 00000000000000000000000000000000 00000000000000000000000000000000 11100000000111011111110000000000 11111111000000000011111111000001 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000010000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111110100000000110 01110000000000000000000000000000 00000000000000000000000000000000 11000000000001011111111000000000 11000100100000100011001111100000 00001100111010000000001111111110 00000000110011111000000000111111 11100000000011111111100000000011 11111110000000001100111110000110 00111111111000000000111111111000 00000011111111100000000011001111 10000000001111111110000000001111 11111000000000111111000000000000 01110000000000000000000000000000 00000000000000000000000000000000 10000000000100001110111000000000 10001001100001100010001011100001 00001000101010000000001011101110 00000010100010111000000000101110 11100001100010111011100000000010 11101110000000101000101110000000 00101110111000000000101110111000 01000010111011100000010010001011 10000000001011101110000000001011 10111000000000101110000000000100 00110000000000000000000000000000 00000000000000000000000000000000 10001000000001011100110000000000 10011010000000000010010011000000 00001001001000000000001011001100 00000000100000110000000000101100 11000000000010110011000000000010 11001100000000001000001100000000 00101100110000001000001100110000 00000010110011000000001010010011 00000000001011001100000000001011 00110000000000101110001000000001 01110000000000000000000000000000 00000000000000000000000000000000 11000000000101011010110000000000 10011001000000000010011011000000 01001001101000000010001011101100 00000000100010110000000000101110 11000000000010111011000000000010 11101100000000001000101100000000 00101110110000010000101110110000 00000010111011000000000010011011 00000000001011101100000000001011 10110000000000101111000000000100 01100000000000000000000000000000 00000000000000000000000000000000 00000000000101001000110000000000 11011011100100000011010011000000 00001101101000000100001111101100 00000010110010110000000000111110 11000000000011111011000000000011 11101100000000001100101100000000 00111110110000000000101110110000 00000011111011000000100011011011 00000000001111101100000000001111 10110000000000111100000000000000 01010000000000000000000000000000 00000000000000000000000000000000 11100001000000001011110000001000 11101100000000010011101111000000 00001110111000000001001111111100 00000000111111110000000000110111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000100111111110000 00010011111111000000000011101111 00000000001111111100000000001111 11110000000000111111100000000100 01100000000000000000000000000000 00000000000000000000000000000000 01000000000100001010110000000000 11001011000000000011001011000000 00001100101000010010001100101100 00010000111110110000000000111110 11000000000011111011000000110011 11101100000010001111101100000000 00111110110000000000111110110000 01100011111011000000000011111011 00000000001111101100000000001111 10110000000000111101000000000100 00100000000000000000000000000000 00000000000000000000000000000000 11001000000001000010110000000100 10000010000000000010001011000001 00001000101011000000001000001100 00000000101110110000000000101110 11000000000010111011000000000010 11001100000000001011101100000000 00101110110000000000101110110000 00000010110011000000000010111011 00000000001011101100000000001011 10110000000000101111001000000000 01000000000000000000000000000000 00000000000000000000000000000000 11100000000001010100110000000000 10000000000000000010010011000000 00001001001010000000001000001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000000000101111000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00100000000000010001111100000000 10001100110000000010010111110000 10001001011011000000001000011110 00000000101101111000000000101101 11100000000010110111100000000010 11011110000000001011011110000000 00101101111000000000101101111000 00100010110111100000010010110111 10000000001011011110000000001011 01111000000000101100100000010100 00000000000000000000000000000000 00000000000000000000000000000000 01001000000010000000110000000000 11000010000000000011010011000100 00001101001000010000001100001100 00000000111100110000000000111100 11000000100011110011000000000011 11001100000000001111001100000000 00111100110001000000111100110000 00000011110011000000000011110011 00000000001111001100000000001111 00110000000000111101001000000010 00000000000000000000000000000000 00000000000000000000000000000000 01000000000111011000110000000000 11111010000000100011100011000001 00001010001000000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000010001111101100000000 00111110110000001000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111101000000000100 00100000000000000000000000000000 00000000000000000000000000000000 10101000000001011110110000000000 11110000000000000010001011000000 00001111101000000100001111101100 00001000011110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000101110110000 00000011110011100001001011001011 00000000001111101100000000001111 10110000000000111100001000000000 01110000000000000000000000000000 00000000000000000000000000000000 01001000000100011001110000000000 10110100000000000010000111000000 00001011011000000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000000 00101101110000000100101101110000 00000010110111000000000010000111 00000000001011011100000000001011 01110000001000101101001000000100 01000000000000000000000000000000 00000000000000000000000000000000 11000000000000001001111000000000 10111110100000001010000111100000 00001011011010000000001011011110 00000000101101111000000000101101 11100000000010110111100000000010 11011110000000001011011110000001 00101101111000000000001101111000 00000010110111100000000010000111 10000000001011011110000000001011 01111000000000101100100000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000101001100110000000000 10110010000000000010000011000000 00001011001000000000001011001100 00000000101100110000000001101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000010000101100110000 00000010110011000000000010000011 00000000001011001100000000001011 00110000000000101101101000000100 00110000000000000000000000000000 00000000000000000000000000000000 11101000000101011010100000000000 11111110000000000011001010000000 00001111111000000000001111101000 00000000111110100000000000111110 10000000000011111010000000000011 11101000000000001111101000000010 00111110100000000000111110100000 00000011111010000000000011001010 00000000001111101000000000001111 10100000000000111111101000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000000001110000000001000 11111000100000001011111000000000 00001111100000000000001111100000 00000100111110000000000000111110 00000000000011111000000000000011 11100000000010001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111101001000000100 00100000000000000000000000000000 00000000000000000000000000000000 00001000000100001110010000000000 11111001000000001011001001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111100001000000100 00100000000000000000000000000000 00000000000000000000000000000000 10000000000000000110010000000000 10110001000000000010001001000001 00001011100100000000001110100100 00000000101110010000000000101110 01000000000010111001000000000010 11100100000000001011100100000100 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101110000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00011000000001000010011000000001 10111011100001000010001001100000 00001011100110000000001011100100 00000000101110010000000000101010 01000000000010111001000000000010 11100100000000001011100100000010 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101100011000000000 01000000000000000000000000000000 00000000000000000000000000000000 00001000000001000000010000010000 10110001000000000010000001000000 00001011000100000001001010000100 00000000101100010000000000101100 01000000000010110001000000000010 11000100000010011011000100000000 00101100010000000000101100010000 00000010110001000000010010110001 00000000001011000100000000001011 00010000000100101100001000000001 00000000000000000000000000000000 00000000000000000000000000000000 10111000000010010110000000000000 11111000000000000011001000000001 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111110111000000011 01010000000000000000000000000000 00000000000000000000000000000000 10011000000111011111010000000000 11111101000000000011111001000000 00001111100100000000001110100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 01000011111001000000000011111001 00000000001111100100000000001111 10010000000000111110111000000110 01110000000000000000000000000000 00000000000000000000000000000000 00011000000001011110010000000000 11111011000000000011001001000000 00001111100100000000001111110100 00000000111110010000000000110110 01000000000011111001000000000011 11110100000000001111100100000000 00111110010000000000111110010000 00000011111101000000000011001001 00000000001111100100000000001111 10010000000000111100111000000000 01110000000000000000000000000000 00000000000000000000000000000000 00111100000100001110000000000000 10111000000000000010001000000000 00001011110000000000001011100000 00000000001110000000000000101110 00000000000010111000000000010010 11100000000000001011100000000000 00101110000000000000101110000000 00000010111000000000000010001000 00000000001011100000000000001011 10000000000000101100011000000000 00010000000000000000000000000000 00000000000000000000000000000000 00001000000001011101010000000000 10111101000000000010010101000001 00001011010100000000001011000100 00000000101100010000000000101100 01000000000010110001000000000010 11000100000000001011000100000000 00101100010000000000101100010000 00000010110001000000001010000001 00000000001011000100000000001011 00010000000000101101001000000000 00100000000000000000000000000000 00000000000000000000000000000000 00011000000101011010010000000000 10111101100000001010011101000000 00001011110100000000001011100100 00010000101110010000000000101110 01000000000110111001000000100010 11100100000001000011100100000101 00101110010000000000100110010000 00000010111001000000000010001001 00000000011011100100000000001011 10010000000000101100011000000100 00100000000000000000000000000000 00000000000000000000000000000000 10101000000101001010010000010000 11111001100000000011011001000000 00001111100100000000001111100100 00000000111110010000000100110110 01000000100011111001000000100011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011001001 00000000001111100100000010001111 10010000000000111110100000000000 00100000000000000000000000000000 00000000000000000000000000000000 00101010000000001010010000000000 11111001000000000011101001000000 00001111100100000000001111100100 00000100111110010000000000101110 01000000000011111001000000000001 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111101101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00101010000100001010000000000000 11111000000000000011111000000000 00001111110000100000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000000001001111100000000000 00111110000000000000011110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111100101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00101000100001000010100000000100 10110010000000000010111010000000 00001011101000000000001011101000 00000000101110100000000000101110 10000000000010111010000000000010 11101000000000001011101000000000 00101110100000000000101110100000 00000010110010000000000010111010 00000000001011101000000000001011 10100000000000101100001000000000 00000000000000000000000000000000 00000000000000000000000000000000 00101000000001010100110000000000 10110011000000100010110011000000 00001011001000000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000100010110011 00000000001011001100000000001011 00110000000000101100001100000000 01010000000000000000000000000000 00000000000000000000000000000000 00100000000000010001100000010000 10110110000000000010110110000000 00001011011000000000001011011100 00000000101101110000000000101101 11000000000010110111000000000010 11011100000000001011011100000001 00101101110000000000101101110000 00000010110111000000000010110111 00000000001011011100000000001011 01110000000000101100100000000000 01000000000000000000000000000000 00000000000000000000000000000000 00111000000010000001011000000000 11110101100000000011110101100000 00001111010010000000001111011110 00000000111101111000001000111101 11100000000011110111100000100011 11011110000000001111011110000000 00111101111000000000111101111000 00000011110111100000000011110111 10000000001111011110000000001111 01111000000000111100101000000110 00000000000000000000000000000000 00000000000000000000000000000000 00001000000111011010000000000000 11111000000000000011111000000000 10001111100000000000001111101100 00010100111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000010 00111110110000000000111110110000 01000011111011000000000011111011 00000000001111101100000000001111 10110000000000111100001000000110 01100000000000000000000000000000 00000000000000000000000000000000 01000000000001011111111000000010 11001111100000000011111111100000 00001111111110010000001111111110 00000000111111111001000000111111 11100000000011111111100000000011 11111110000000001111111110010000 00111111111001000000111111111000 00000011110111100000000011001111 10000000001111111110000000001111 11111000000000111101100000000000 00100000000000000000000000000000 00000000000000000000000000000000 10101000000100011001100001010000 11010110000100000010110110000000 00001011011100000000001001011100 00000100111101110000000100101101 11000000010010110111000100000010 11011100000000001011011100000000 00111101110000000000101101110000 01010010110111000000010010000111 00000000001011011100000000001011 01110000000000101110101000000000 00100000000000000000000000000000 00000000000000000000000000000000 10000000000000001011010000000000 10000101000010000010110101000000 00001011010110000000011001011100 00000000101001110000000001101101 11000000000010110111000000000010 11011100000000001011011100000010 01100101110000000001101101110000 00000010110111000000000010000111 00000000001011011100000000001011 01110000000000101100000000000000 00100000000000000000000000000000 00000000000000000000000000000000 01100000000101001100000000000010 10000000100000000010110000000000 00001011000100000000001001001100 00000100101100110000000000101100 11000000000110110011000001000010 11001100000100000011001100000100 00101000110000010000101100110000 00000010110011000001001010000011 00000100001011001100000100001011 00110000000000101101000000000100 00100000000000000000000000000000 00000000000000000000000000000000 10101000000101011010110000000000 10000011110000000011111011000000 00001111101000000000001101101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001011101100000000 00101110110000000000111110110000 00000011111011000001000011001011 00000000001111101100000000001111 10110000001100111110101000000000 01100000000000000000000000000000 00000000000000000000000000000000 10000000000000001110100000010000 11111010000010000011111010000000 01001111101000000000001101101100 00000000111010110000000100111110 11000000000011111011000000000011 11101100000000001111101100000000 01111110110000000000111110110000 00000011111011000000000011111011 00000010001111101100000001001111 10110000000000111110100000010100 00110000000000000000000000000000 00000000000000000000000000000000 00000001000100001111010000000000 11111101000000000011001101000000 00001111110000000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000100111111110000 00010011111111000000100011111111 00000000001111111100000000001111 11110000000000111100000001000100 00110000000000000000000000000000 00000000000000000000000000000000 11000001000001000110000000010000 10111000000000000010001000000000 00001011100000000100001011101100 00010000101110110000000000101110 11000001000110111011000000010010 11101100000000001011101100000000 00101110110000000000101110110000 00000010111011000001000010111011 00000000001011101100000000001011 10110000000000101110000001000000 00010000000000000000000000000000 00000000000000000000000000000000 11000000000001010010110000001000 10111011000000000010001011000000 00001011101100000000001010101100 00000000101110110000000000101110 11000000010010101011000000010010 11101100000010001011101100000000 00101110110000000000101110110000 00000000111011000000000010111011 00000000001011101100000001001011 10110000000100101110000000000000 01010000000000000000000000000000 00000000000000000000000000000000 00001000010000000000100000000000 10111010000000001010000010000000 01001011001100000001001011001100 00000000101100110000000000101100 11000000000010110011000000010010 11001100000000001011001100000001 00101100110000000000101100110000 00000010110011000000010010110011 00000000001011001100000001001011 00110000000000101100001000000001 00000000000000000000000000000000 00000000000000000000000000000000 01000000000011000110010000000000 11111001000000000011001001000000 00001111100100000000001110101100 00000000111110110000000000111110 11000000000011101011000000000011 11101100000010001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000011100000000000110 00000000000000000000000000000000 00000000000000000000000000000000 10100000000111011101000000000000 01111100000001000011111100000001 00001111110100000100001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000011111111100000000 00111111110000010000111111110000 01000011111111000001000011111111 00000000001111111100000000001111 11110000010000111110100000000010 01110000000000000000000000000000 00000000000000000000000000000000 11000000000001011111111000000010 11001111100000000011111111100000 10001111111110000000001101111110 00001000111111111000000000111111 11100000000011111111100000000011 11111110000000001111111110000000 00111111111000000000111111111000 00000011011111100000011011001111 10000000001111111110000000001111 11111000000000111111000000000000 01110000000000000000000000000000 00000000000000000000000000000000 10000000000100001110111000000000 10001011100000000010111011100000 00001011101110000001001011101110 00001000101110111000001100101110 11100000010010111011100000010010 11101110000000001011101110000000 00101110111000000000101110111000 00010010011011100000000010001011 10000000001011101110000000001011 10111000000000101110000000000100 00110000000000000000000000000000 00000000000000000000000000000000 10001000000001011100110000000000 10000011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101100110000 00000010110011000000000010000011 00000000001011001100000000001011 00110000000000101110001000000001 01110000000000000000000000000000 00000000000000000000000000000000 11000000000100011010110000000000 10001011000001000010111011000000 00001011101100000000001011101100 00000000101110110000000000100110 11000000000000111011000001000010 11101100000000001011101100000000 00101110110000001000101110110000 00000110011011000000000010001011 00000000001011101100000000000011 10110000000000101111000000000100 01100000000000000000000000000000 00000000000000000000000000000000 00000000000101011110110000000000 11001011000000000011111011000000 00001111101100000000001101101100 00000000111110110000000000111110 11000001000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011011011000000010011001011 00000100001111101100000000001111 10110000000000111101000000000100 01110000000000000000000000000000 00000000000000000000000000000000 11100000000000011011110000000000 11111111000001000011111111000000 00000111111100000100001111111100 00000000111111110000000000101111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00010011111111000001000011111111 00000000001111111100000000001111 11110000000000111111100000000000 01100000000000000000000000000000 00000000000000000000000000000000 01000000000100001010110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00011000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00010011111011000000010011111011 00000100001111101100000000001111 10110000000000111101000000000100 00100000000000000000000000000000 00000000000000000000000000000000 11001000000001010000110000000000 10111011000001000010111011000000 00001011101100000100001011101100 00000000111110110000010000101110 11000000000010111011000000000010 11101100000000001011101100000000 00101110110000000000101110110000 00000000110011000001000010111011 00000000001011101100000000001011 10110000000000101111001000000000 01000000000000000000000000000000 00000000000000000000000000000000 11100000000001010100110000010000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000001100110000 00000010110011000000000010110011 00000000001011001100000100000011 00110000000000101111100000000000 01010000000000000000000000000000 00000000000000000000000000000000 01100000010000010001111000000000 10110111100000000110110111100000 00001011011110000000001011011110 00000000101101111000000000101101 11100000000010110111100000000010 11011110000000001011011110000100 00101101111000000000101101111000 00000010110111100000000010110111 10000000001011011110000000001011 01111000000000101100100000000000 01000000000000000000000000000000 00000000000000000000000000000000 01001000000010000000110000000000 11110011000000000011110011000001 00001111001100010000001111001100 00000000111100110000000000111100 11000000000011110011000000000011 11001100000000001111001100000000 00111100110001000100111100110000 00000011110011000000000011110011 00000000001111001100000000001111 00110000000000111101001000000010 00000000000000000000000000000000 00000000000000000000000000000000 01000000000111011011110000000001 11111111000000000011111111000000 00000111111100010100001111111100 00000000111011110000000001111111 11000000000011111111000000010011 11111100010000001111111100010000 00111111110000000000111111110001 00010111111111000000000011111111 00000000001111111100000000001111 11110000000000111101000000000010 01100000000000000000000000000000 00000000000000000000000000000000 10101000000001011100111000000000 11001011000000000011111011000000 00001111101100000000001111001110 00000000110010110000000000111110 11000000000011111011000000000011 11001110000000001100101100000000 00111110110000001000111110110000 00000011110011100000000011001011 00000000001111101100000000001111 10110000000000111110101000000000 01110000000000000000000000000000 00000000000000000000000000000000 01001000000100011001110000000000 10000111000000000010110111000000 00001011011100000001001011011100 00000000100001110000000001101101 11000000000010110111000000000010 11011100000000001000011100000100 00101101110000000000100101110000 00000010110111000000000010000111 00000000001011011100000000001011 01110000000000101101001000000100 01100000000000000000000000000000 00000000000000000000000000000000 11000000000000001001111000000010 10000111100000000010110111100000 00001011011110000000001011011110 00010011100101111000000000101101 11100000000010110111100001100010 11011110000010101000011110000000 00101101111000000000101101111000 00000010110111100000011010000111 10000100001011011110000000001011 01111000000000101111000000000000 00100000000000000000000000000000 00000000000000000000000000000000 01001000000101001100110000000000 10000011000000010010110011000000 00001011001100000000001011001100 00000000100100110000000000101100 11000000000010110011000000000010 11001100000000001000001100000001 00101100110000000001100100110000 00000010110011000000000010000011 00000000001011001100000000001011 00110000000000101101001000000100 00110000000000000000000000000000 00000000000000000000000000000000 11101000000101011010100000000000 11001010000000000011111010000000 00001111101000000000001111101000 00000000110110100000000000111110 10000000000011111010000000000111 11101000000000001100101000000000 00111110100000000000111110100000 01000011111010000000000011001010 00000000011111101000000000001111 10100000000000111111101000000100 01100000000000000000000000000000 00000000000000000000000000000000 01001000000000001110000000000000 11111000000000100011111000000000 00001011100000000000001111100000 00000000111010000000000000111110 00000000000011111000000000000111 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000001001111 10000000000100111101001000000000 00110000000000000000000000000000 00000000000000000000000000000000 00001000000100001110010000000000 11111001000000000011101001000000 00001111100100000000001111100100 00000000111110010000000000111110 01000000000011111001000000000011 11100100000001001111100100000000 00111110010000000000111110010000 01100011111001000000000011111001 00000000001111100100000000001111 10010000000000111100001000000100 00110000000000000000000000000000 00000000000000000000000000000000 10000000000001000110010000000000 10111001000000000010111001000000 00001011100100000000001011100100 00000000100110010000000000101110 01000000000010111001000000000010 11100100000000001011100100000000 00101110010000000000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101110000000000000 00010000000000000000000000000000 00000000000000000000000000000000 00011000000001010010010000000000 10111001000000000010111001000001 00001011100100000000001011100100 00000000101110010000000000101110 01000000000010111001000000000010 10100100000000001011100100000000 00101110010000000000001110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101100011000000000 01000000000000000000000000000000 00000000000000000000000000000000 00001000000001000000010000000000 10110001000000000010110001000000 00001011000100000000001011000100 00000000101100010000000000101100 01000000000010110001000000010010 11000100000000001011000100000000 00101100010000000000101100010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101100001000000001 00000000000000000000000000000000 00000000000000000000000000000000 10111000000011010110000000000000 11111000000000000011101000000000 00001111100000000000001111100000 00000000111110000000000000111110 00000000000011111000000000000011 11100000000000001111100000000000 00111110000000000000111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111110111000000011 01010000000000000000000000000000 00000000000000000000000000000000 10011000000111011110010000000000 11111001000000000011111001000000 01001111100100000000001111100100 00000000110110010000000000111110 01000000000011111001000000000001 11100100000001001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111110011000000110 01110000000000000000000000000000 00000000000000000000000000000000 10011000000001011111010000000000 11111001000000000011111001000000 00001111100100000000001111110100 00000000111110010000000000110110 01000000000011111001000000000011 11110100000000001111100100000000 00111110010000000000111110010000 00000011111101000000000011111001 00000000001111100100000000001111 10010000000000111100011000000001 01100000000000000000000000000000 00000000000000000000000000000000 00111000000100001110000000000000 10111000000000000010111000000000 00001011100000000000001011100000 00000000101110000000000000101110 00000000000010111000000000000010 11100000000000001011100000000000 00101110000000000000101110000000 00000010111000000000010010111000 00000000001011100000000000001011 10000000000000101100111000000100 00110000000000000000000000000000 00000000000000000000000000000000 00001000000000001100010000000000 10110001000000000010110001000000 00001011000100000000001011000100 00000000101100010000000000101100 01000000000010110001000000000010 11000100000000001010000100000000 00101100010000000000101100010000 00000010110001000000000010110001 00000000001011000100000000001011 00010000000000101100001000000001 00110000000000000000000000000000 00000000000000000000000000000000 00011000000101011010010000000000 10111001000000000010111001000000 00001011100100000000011011100100 00000000101110010000000100101110 01000000000010111001000001000010 11100100000000001011100100000000 00101110010000010000101110010000 00000010111001000000000010111001 00000000001011100100000000001011 10010000000000101100011000000100 01100000000000000000000000000000 00000000000000000000000000000000 10100000000101011110010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00010000111110010000010000110110 01000000000011111001000000000011 11100100000000001110100100000000 00111110010000000000111110010000 00000010111001000000000011111001 00000000001111100100000000001111 10010000000000111110100000000100 01110000000000000000000000000000 00000000000000000000000000000000 00101000000000011010010000000000 11111001000000000011111001000000 00001111100100000000001111100100 00000000111110010000000000101110 01000000000011111001000000000011 11100100000000001111100100000000 00111110010000000000111110010000 00000011111001000000000011111001 00000000001111100100000000001111 10010000000000111100101000000000 01100000000000000000000000000000 00000000000000000000000000000000 00101000000100000010000000000000 11111000000000000011111000000000 00001111100000000000001111100000 00000000111110000000000001111110 00000001000011111000000000000011 11100000000000001111100000000000 00111110000000000001111110000000 00000011111000000000000011111000 00000000001111100000000000001111 10000000000000111100101000000100 00100000000000000000000000000000 00000000000000000000000000000000 00101000000001010010100000000000 10111010000000000010111010000000 00001011101000000000001011101000 00000000101110100000000000101110 10000000000010111010000000000010 11101000000000001011101000000000 00101110100000000000101110100000 00000011101010000000000010111010 00000000001011101000000000001011 10100000000000101100101000000000 01000000000000000000000000000000 00000000000000000000000000000000 00101000000001010100110000010000 10110011000000000010110011000000 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000100 00101100110000000000101100110000 00000010110011000000000010110011 00000000001011001100000000001011 00110000010000101100101000000000 01010000000000000000000000000000 00000000000000000000000000000000 10100000010000010001110000000000 10110111000000000010110111000000 00011011011100000000001011011100 00000000101101110000000000001101 11000000000010110111000000000010 11011100000000001011011100000001 00101101110000000000101101110000 00000000100111000000000010110111 00000000001011011100000000001011 01110000000000101110100000000000 01000000000000000000000000000000 00000000000000000000000000000000 10101000000010000001111000000000 11110111100001000111110111100000 00001111011110000000001111011110 00000000111101111000000000101101 11100000000011110111100000000011 11011110000000001111011110000000 00111101111000000000101101111000 01000011110111100000000011110111 10000000001111011110000000001111 01111000000000111110101000000010 00000000000000000000000000000000 00000000000000000000000000000000 00001000000111011010110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000100111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111100001000000110 01100000000000000000000000000000 00000000000000000000000000000000 01000000000001011111111000000000 11111111100000000011111111100100 00001111111110000000001111111110 00000000111111111000011000111111 11100000000011101111100000000011 11111110000000001111111110000000 00111111111000000000111111111001 00000011111111100000000011111111 00100000001111111110000000001111 11111000000000111100000000000000 01110000000000000000000000000000 00000000000000000000000000000000 10101000000100011001110000000000 10110111000100000010110111000000 00001011011100000000001011011100 00000000101101110001000000101101 11000000010010110111000000000010 11011100000010001011011100000000 00101101110000000000101101110001 00000010110111000100000010110111 00000000001011011100000010001011 01110000000000101110101000000100 01100000000000000000000000000000 00000000000000000000000000000000 00011000000000001001110000000000 10110111000000000010110111000001 00011011011100000000001011011100 00000000101101110000000000101101 11000000000010100111000000000010 11011100000000001011011100000000 00101101110000000000101101110000 00000110110111000000000010110111 00010000001011011100000000001011 01110000000000101100000000000000 00100000000000000000000000000000 00000000000000000000000000000000 01100000000100001100110000000000 10110011000000000010110011000000 00001011001100000000001011001100 00000101101100110000000000101100 11000001000010110011000000000010 11001100000000001011001100000000 00101100110000000001101100110000 01000010110011000000000010110011 00000000001011001100000000001011 00110000000000101100100000000100 00110000000000000000000000000000 00000000000000000000000000000000 10111000000101011010110000000000 11111011000000000111111011000000 00001111101100000010001111101100 00000000111110110000000000111110 11000000000011101011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111110101000000100 01100000000000000000000000000000 00000000000000000000000000000000 10000000000000001110110000000000 11111011000000000011111011000000 00001111101100000000001111101100 00000000111110110000000000111110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000111110110000 00000011111011000000000011111011 00000001001111101100000000000111 10110000000000111110000000000000 00110000000000000000000000000000 00000000000000000000000000000000 10000000000100001111110000000000 11111111000000000011111111000000 00001111111100000000001110111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000000000111111110000 00000011111111000000000011111111 00000000001111111100000000001111 11110000000000111100000001000100 00110000000000000000000000000000 00000000000000000000000000000000 10000001000001000110110000000000 10111011000000010011101011000000 00001011101100000000000011101100 00000000101110110000000001101110 11000000000010111011000000000010 11101100000000001011101100000000 00101110110000000001111010110000 00000011101011000000110010111011 00000100001011101100000000001011 10110000000000101110000001000000 00010000000000000000000000000000 00000000000000000000000000000000 10000000000001010010110000000000 10111011000000000010111011000000 00001011101100000000001011101100 00000000101110110000010000101110 11000000000010111011000000000110 11101100000000001011101100000000 00101110110000010000101110110000 00000010111011000000000010111011 00000000001011101100000000001011 10110000000000101110000000000000 01000000000000000000000000000000 00000000000000000000000000000000 00001000000001000000110000000100 10110011000000000010100011000001 00001011001100000000001011001100 00000000101100110000000000101100 11000000000010110011000000000010 11001100000000001011001100000000 00101100110000000000101000110000 00010010100011000001100010110011 00000100001011001100000000001011 00110000000000101100001000000000 00000000000000000000000000000000 00000000000000000000000000000000 10000000000011010110110000000100 11111011000000100011111011000000 10001111101100000000001110101100 00000000101110110000000000101110 11000000000011111011000000000011 11101100000000001111101100000000 00111110110000000000101110110000 00000011111011000000000011111011 00000000001111101100000000001111 10110000000000111100000000000011 00010000000000000000000000000000 00000000000000000000000000000000 10100000000111011111110000000000 11111111000000000011111111000001 00001111111100000000001111111100 00000000111111110000000000111111 11000000000011111111000000000011 11111100000000001111111100000000 00111111110000010000111011110000 00000011101111000000000011111111 00000000001111111100000000001111 11110000000000111110100100000011 01110000000000000000000000000000 00000000000000000000000000000000 00000000110001010000000000000010 01110001010000001001110000010000 00110111000111000101010111000001 00000011011100000100000010011100 00010000001101110001010000001101 11000111000000110111000111000001 11011100010100000111011100010100 00010101110000010000000101110000 01000000010111000001000001010111 00000100000111011100000000100001 00000000000000000000000000000000 00000000000000000000000000000000 00000000110000010100010000100101 01110001000000010101110001000000 01010111000100000001010001000100 00000101011100010000000001011100 01000000010101110001000001010101 11000100000001010011000100000001 01011100010000000101011100010000 00011100100001000000010000110001 00000001110111000100000001010111 00010000000101011100000000010001 00010000000000000000000000000000 00000000000000000000000000000000 00000000100001000000001000000001 00100000100000000100100000100000 00010010000110000000000010000010 00000001001000001000000001001000 00100000000100100000100000000100 10000010000000000010000010000000 01001000011000000001001000011000 00000100100000100000000101110000 10000000010010000010000000010010 00001000000001001000000000100000 01000000000000000000000000000000 00000000000000000000000000000000 00000000100000000000000000000001 01100000000000000101100000000000 00010110000000000000010110000000 00000001011000000000010001010000 00000000000101100000000000000101 10000100000000010110000100000000 01011000000000000001011000001000 00000001100000000010010101100000 00000000010110000000000000010110 00000000000101011000000000110001 00010000000000000000000000000000 00000000000000000000000000000000 00000000010001010100100101000101 01110010000000010001110010000000 01000111001000000000010111001000 00000101011100100000000000011100 10000000010101110010000000010101 11001000000001010111001000000000 01011100110000000001011100100000 00000101110010000000010101110010 00000001010111001000000001000111 00100000000100011100000000010001 01010000000000000000000000000000 00000000000000000000000000000000 00000000110001010100000000000000 01100000000000000001100000000000 00000110000000000000000110000000 00000000011000000000000100011000 00010000000001100000000000000001 10000000000000000110000000000000 00011000000000000000011000000000 00000000100001000000000001100000 00000000000110000000000000000110 00010000000000011000000000110001 01000000000000000000000000000000 00000000000000000000000000000000 00000000110001010100100000000100 00100010000000010000100010010000 01000010000000000000000010001000 00000100001000000000000100001000 10000000010000100010000000010000 10001000000001000010001000000000 00001000101000000000001000000100 00000000100001000000010000100000 00000001000010000000000001000010 00110000000100001000000000100001 00000000000000000000000000000000 00000000000000000000000000000000 00000000110001010100111100000101 01000010100000010101000011100000 01010100000000000000010100001010 00000101010000001000000101010000 11100000010101000010110000010101 00001010000001010100001111000001 01010000111000000101010000000000 00000100000000100000000101000000 11000000010100000010000001000100 00101100000000010000000000010001 01010000000000000000000000000000 00000000000000000000000000000000 00000000100000000001110100000001 00010011000000000101010111000000 00010101011100000001010101011100 00000001000001110000000001000001 11000000000100000111000000000100 01011100000000010101001100000000 01000101110000000001010100110000 00000101010111000000000101010011 00000000010001011100000000010101 00110000000001000100000000100000 01000000000000000000000000000000 00000000000000000000000000000000 00000000100001000000010000000000 00010000000000000001000001000000 00000100001110000000000100000000 00000000000000000000000000000000 01100001000001000000000000000000 01000000000000000100000110000000 00000100010000000000010000110000 00000001000011000000000001000000 00000001000001001000000000000100 00010000000000000100000100100001 00010000000000000000000000000000 00000000000000000000000000000000 00000000110000010110000000000010 00011000000000001000001000000000 00100000100000000000100000100000 00000010000010000000000110000010 00000000001000001000000010001000 01100000000000100000100000000000 10000110000000000010000010000000 00001000001001000000001000001000 00000000100001100000000000100000 10000000000010000100000100010001 01010000000000000000000000000000 00000000000000000000000000000000 00000000110001010001000000000101 01100000000000010101100100000000 01010110010000000000110110010000 00000001001001000000000001001001 00000000010101100100000000010101 10010000000000010110000000000000 01011001000000000001011000000000 00011101100100100000011101100000 00000001010110010000000001110110 00000000000101011000000000010001 00000000000000000000000000000000 00000000000000000000000000000000 00000000110001010100000000000001 01100000000000001101100000000000 00110110001000000000010110000000 00000111011000000000000011011000 00000001001101100000000000001101 10000000000001110110000000000001 11011000000000000101011000100000 00010101100010000000010101110000 00000000010110001000000001010110 00000000000111011000000000100001 00010000000000000000000000000000 00000000000000000000000000000000 00000000110001010100001000000100 00110000100001010000110000100000 01000011000011000001000011000010 00000100001100001000000000001100 00100001010000110000100001010000 11000010000001000011000010000001 00001100001000000010001100001000 00000000110000100000010001100000 10000001100011000010000001100011 00001000000100001100000000110001 01010000000000000000000000000000 00000000000000000000000000000000 00000000100000000000000000000000 00110000000000000000110000000000 00000011000000000000000011000000 00000000001100100000000000001100 00000000000000110000000000000000 11000000000000000011000000000000 00001100000000000000001100000000 00000000110000000000000000100010 00000000000011000000000000000011 00000000000000001100000000000001 01000000000000000000000000000000 00000000000000000000000000000000 00000000100000000000001000000001 00110000100000000100110000100000 00010011000010000001010011000010 00000101001100101100000001001100 00100000000100110000100000000100 11000010000000010011000010000000 01001100001000000001001100001100 00000100110000110000000100110010 11000000010011000011000000010011 00001000000001001100000000110001 01000000000000000000000000000000 00000000000000000000000000000000 00000000110001010100001000000101 01100000100000010101100000100000 01010110000011000001000110000010 00000001011000001100000000001000 00100000010101100000100000010101 10000010000000010110000010000000 01011000001000000001011000001100 00010101100000110000000101100000 11000001010111000011000001010110 00001000000001011000000000010000 01010000000000000000000000000000 00000000000000000000000000000000 00000000110001010100001000000000 00100000100000000000100000100000 00000010000010000000000011000010 00000000011000001000000100001000 00100000000000100000100000000000 10000010000000000010000010000000 00001000001000000000001000001000 00000000110000100000010000110000 10000000000110000010000000000011 00001000000000001000000000110001 00000000000000000000000000000000 00000000000000000000000000000000 00000000110001010001001000000100 01100000100000010001100100100000 01000110010010000001000011010010 00000000001001001000000100001001 00100000010001100100100000010001 10000010000000000110010010000000 00011001001000000000011001001000 00010000110100100000010000110100 10000001000010000010000001000011 01001000000000011000000000000001 01000000000000000000000000000000 00000000000000000000000000000000 00000000010001010110000000000101 01011000000000010101011000000000 01000101100000000000000001100000 00000001010110000000000100000010 00000000010101011000000000010101 01100000000001010101100000000001 01010110000000000001010110000000 00010100011000000000010100011000 00000000010001100000000000010001 10000000000101010100000000000001 01010000000000000000000000000000 00000000000000000000000000000000 00000000100001000010011000000001 01000001100000000101000001100000 00010100000110000000010100000110 00000001010000011000000001010000 01100000000101000001100000000101 00000110000000010100000110000000 01010000011000000001010000011000 00000001000000100000000101000001 10000000010100000110000000010100 00011000000001010000000000010001 00010000000000000000000000000000 00000000000000000000000000000000 00000000100000000001001000000001 00000000100000000100000100100000 00010000010010000000010000010010 00000001000001001000000001000001 00100000000100100100100000000100 00000010000000010000010010000100 01000001001000000001000001001000 00010100000100100000000100000100 10000001010000000010000000010000 01001000000001000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000110001010100011000000011 01010001100000001101010001100000 00110101000110000000110101000110 00000011010100011000000111000000 01100000001101010001100000001101 01000110000000110101000110000000 11010100011000000001010100011000 00000101010001100000001101010001 10000000110101000110000000110101 00011000000011010100000000110001 01010000000000000000000000000000 00000000000000000000000000000000 00000000110001010100001000000111 01110001100000010101110001100000 00010111000110000000110111000110 00000000011100011000001001011100 01100000000101110001000000010101 11000110000000010111000110000000 01011100011000001110011100011000 00010101110001100000011101110001 10000001010111000110000001110111 00011000000001011100000000010001 00000000000000000000000000000000 00000000000000000000000000000000 00000000010001010100011000000011 01110001100000001101110001100000 01100111000110000101010111000110 00000010011100011000000011011100 01100000011101110001100000001101 11000110000001100111000110000001 11011100011000000010011100011000 00010001110001100000010101110001 10000000010111000110000001010111 00011000000011011100000000000001 01000000000000000000000000000000 00000000000000000000000000000000 00000000010001010100011000000101 01110001100000010101110001100000 01010111000110000001000011000110 00000101011100011000000000011100 01100001010101110001100000010100 11000110000101010111000110000001 01011100011000000101011100011000 00011000110001100000011001110001 10000001100111000110000001000011 00011000000101011100000000000001 01010000000000000000000000000000 00000000000000000000000000000000 00000000000000000000001000000001 00100000100000000100100000100000 00010010000010000000010111000010 00000001001000001000000001001000 00100000000100100000100000000101 10000010000000010010000010000000 01001000001000000001001000001000 00000101110000100000000100110000 10000000010010000010000000010111 00001000000001001000000000010000 00000000000000000000000000000000 00000000000000000000000000000000 00000000010000000000011000000001 01100001100000000101100001100000 00010110000110000000010110000110 00000001011000011000000001001000 01100000000101100001100000000101 10000110000001010110000110000001 00011000011000000001011000011000 00000101100001100000000101100001 10000000010010000110000000010110 00011000000001011000000000100001 01000000000000000000000000000000 00000000000000000000000000000000 00000000010001010100000000000101 01110000000000010101110000000000 00010011000000000001010011000000 00000101001100000000000001001100 00000000000000110000000000010101 11000000000000010111000000000001 01011100000000000101011100000000 00000101110000000000010100110000 00000001000111000000000000010011 00000000000101011100000000110001 00010000000000000000000000000000 00000000000000000000000000000000 00000000010001000100001100000000 01100000100000000001100000110000 00000010000010000000000010000010 00000000001000001000000100011000 00100000000000100000100000000001 10000010000000000110000010000000 00011000001000000000011000001000 00000000000000100000000000100000 10000000000110000010000000000010 00001000000000011000000000000001 00010000000000000000000000000000 00000000000000000000000000000000 00000000010001000100001000000100 00100000100000010000100000100000 00000110000010000001000110001010 00000100011000001000000100001000 10100000000001100100100000010000 10000010000000000010000010000001 00001000001000000100001000001000 00000000100000100000010000100000 10000001000010000010000000000110 00001000000100001000000000010001 00000000000000000000000000000000 00000000000000000000000000000000 00000000010001000100001100000101 01000000100000010101000000100000 01010101000011000001010101000011 00000101010100001100000101010100 00110000010101010000100000010101 00000010000000010100000010000000 01010000001000000101010000001000 00000100000100110000000100000000 10000000010100000011000001000101 00001000000101010000000000010001 01010000000000000000000000000000 00000000000000000000000000000000 00000000000000010000001100000001 00010000110000000101010000110000 00010101000011000000010101001010 00000001010100001000000001010100 10100000000101010000100000000101 01000011000000010101000010000000 01010100001100000001010100001100 00000101010000110000000101010000 10000000010101000011000000010101 00001000000001010100000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000010000100000000000 00010010000000000001000000000000 00000100000000000000000100000000 00000000011000000000000000011000 00000000000001000010000000000001 00001000000000000100001000000000 00010000100000000000010000100000 01000001000100000000000001000010 00000001000110000000000000000100 00100000000000010000000000010001 01010000000000000000000000000000 00000000000000000000000000000000 00000000010001000100001100000010 00010000100000001000000010100000 00100000001010000000100000000010 00000010000000001000000110000000 00100000001000000000100000001000 00000010000000100000000010000000 10000000001000000010000000001000 00001000000110100100001000000000 10000000100000001010000000100000 00001000000010000000000000110001 01010000000000000000000000000000 00000000000000000000000000000000 00000000000001010100000000001001 01100000000000010101100000000000 00010110000000000000110110000000 00000101011000000000001001011000 00000000000101100100000010010101 10000000000000010110000000000001 01011000000000000101011000000000 00011101100000000000011101100000 00000001010110000000000010110110 00000000001001011000000000010001 00000000000000000000000000000000 00000000000000000000000000000000 00000000110001010100000000000010 01100000000000011101100000000000 00010110000000000000010111000000 00000000011000000000000001001000 00000000001101100000000000000101 10000000000000010110000000000000 10011000000000000011011000000000 00000101110000000000000101110000 00000000110010000000000000010111 00000000000011011000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000100 00110000000000000000110000000000 01000011000000000000000110000000 00000100001100000000000000001000 00000001010000110100000000000000 11000000000000000011000000000001 00001100000000000100001100000000 00010001100000000000010001100000 00000000100010000000000001000110 00000000000100001100000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000010000000000 00110100000000000000110001101000 00000011010000000001000010000100 00000000001101000000000000001000 00000000000000110101000000000000 11010100000001000011010000000000 00001101010000000000001101000000 00000000100101001000000000100100 00000000000010010000000000000010 00000000000000001100000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000011000000001 00110001010000010100110001010000 00010011000101000001010011000110 10000001001100010000000001001000 01000000000100110101100000000100 11000101000000010011000100000000 01001100010100000001001100010100 01010100111001011000010100110001 00000000010010000101000001010011 00010000000001001100000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000010001100000101 01101000110000000101101000110000 01000110100011000001010100100011 10000101011010001100000001011010 00110000010101101101110000010101 10100011000001010110100011000001 01011010000100000101001010001100 00010001101000100000010101101000 11000001010110100011000001010110 10001100000100011000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000010000000000 00100100000000000000100011000000 00000010011000000000000010000100 00000000001001000000000100001000 00000000000000100100000000000000 10010101000000000010010000000000 00001001000000000000001001000000 00000000100111000000000000110100 00000000000010011000000000000010 00000000000000001000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000100000000100 01100010000100000001100000000100 01000110000000010001000110000000 01000100011000000001000100011000 00000100010001100010000000010001 10001000000001000110001000010001 00011000100000000100001000100001 00010001100000000100010000110010 00010001000110000000010001000110 00100001000100011000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000001000101 01010000000100000101010000000000 01000101000000100000000101000000 01100101010100000001000100010100 00000100010001010000000100010101 01000000010101010101000000010001 00010100000100000100010100000000 00000101010000010000000100010000 00010000010101000000010000000101 00000001000101010100000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000100000100001 01000010000000000001000010000010 00010101001000001000000101001000 00100001010100100000100000010100 10000010000101010010000000000101 00001000000000010100001000000000 01010000100000000001010000100010 10000101000010000010000101010010 00001000010100001000001000010101 00100000100001010000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000101000000001 00000010100000000100000010100000 01000000001010010000010000001010 00000100000000101000000100000000 10100000000100000010100000000100 00001010000000010000001010000000 01000000101000000001000000101001 01000100000010100000000100000010 10000000010000001010000000000000 00101000000001000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000110010000011 01010011000000000101010011000000 00100001001100000000000101001100 00000010000100110000000000000100 11001000001000010011000000000101 01001100000000010101001100100000 11010100110000000011010100110001 00001101010011000000001000010011 00000000010101001100000000100001 00110010000011010100000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000100010000101 01110010000000010001110010000000 01010111001000000001010111001000 00001101011100100000001101011100 10001000010101100010000000011001 11001000000001000111001000001001 01011100100000000100011100100000 00001001110010000000011101100010 00000001010111001000000001110111 00100000100101011100000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000001100001000 01001000110001000001000000110000 10000100000011000000000100000011 00001000010000001100000000010000 00110000100001000000110000000001 00000011000100000100100011000000 00010000001100000000010010001100 00000001000000110000000001001000 11000000000100000011000100000100 10001100001000010000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000011111111111111 01001111111111111101001111111111 11110100111111111111110100111111 11111111010011111111111111010011 11111111111101000111111111011101 00011111111111110100111111111111 11010011111111111111010011111111 11111101001111111111111101001111 11111111110100111111111111110100 11111111111111010000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000011111111111011 00001011001101111101001111111111 10110000101101111111110100111110 11011011000010110011011011000010 11011111101100000111101101011101 00011110110111110100101101111111 11010011111111111111010010110111 11111101001111111111101100001011 00110110110000101100110110110000 10110111111011000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000011111111111100 01001100110011111101001111111111 11000100110011111111110100111111 00111100010011001100111100010011 00111111110001000111110011011101 00011111001111110100110011111111 11010011111111111111010011001111 11111101001111111111110001001100 11001111000100110011001111000100 11001111111100010000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000011101100011110 01001110110111111001001000110111 11100100100011011110000100100011 00011110010010001100011000010010 00110001111001000110110001011101 00011011011111100100111011000111 10010011101101111110010011101101 11100001001000110111100001001110 11000110000100100011011110000100 11101100011110010000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000100000010 01110000010000001001110000010000 00100111000001000000100111000001 00000010011100000100000010011100 00010000001100110000010000001001 11000001000000100111000001000001 10011100000100010110011100000100 00001001110000010000001001110000 01000000100111000001000001100111 00000100000110011100000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000010000000101 01110001000000010101110001000000 01010111000100000001010111000100 00000101011100010000000101011100 01000000010100110001000000010101 11000100000001010111000100000001 01011100010000000101011100010000 00010101110001000000010101110001 00000001010111000100000001010111 00010000000101011100000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000001000000001 00100000100000000100100000100000 00010010000010000000010010000010 00000001001000001000000001001000 00100000000100100000100000000100 10000010000000010010000010000000 01001000001000000001001000001000 00000100100000100000000100100000 10000000010010000010000000010010 00001000000001001000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 01100000000000000001100000000000 00000110000000000000000110000000 00000000011000000000000000011000 00000000000001100000000000000001 10000000000000000110000000000000 00011000000000010000011000000000 00000001100000000001000001100000 00000000000110000000000000000110 00000000000000011000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000100000000100 01110010000000010001110010000000 01000111001000000001000111001000 00000100011100100000000100011100 10000000010001110010000000010001 11001000000001000111001000000000 00011100100000000000011100100000 00010001110010000000010001110010 00000001000111001000000000000111 00100000000000011100000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 01100000000000000001100000000000 00000110000000000000000110000000 00000000011000000000000000011000 00000000000001100000000000000001 10000000000000000110000000000000 00011000000000000000011000000000 00000001100000000000000001100000 00000000000110000000000000000110 00000000000000011000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000100000000100 00100010000000010000100010000000 01000010001000000001000010001000 00000100001000100000000100001000 10000000010000100010000000010000 10001000000001000010001000000000 00001000100000000000001000100000 00010000100010000000010000100010 00000001000010001000000000000010 00100000000000001000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000010101000000100 01001010100000010001001010100000 01000100101010000001000100101010 00000100010010101000000100010010 10100000010001001010100000010001 00101010000001000100101010000001 00010010101000000000010010101000 00010001001010100000010001001010 10000001000100101010000001000100 10101000000100010000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00001000110000000000110000000000 01010011000000000001010011000000 00000101001100000000000101001100 00000000010100110000000000010100 11000000000001010011000000000001 01001100000000000101001100000000 00010100110000000100010100110000 00000001010011000000000001010011 00000000000101001100000000000101 00110000000000010100000000010000 00000000000000000000000000000000 00000000000000000000000000000000 00000000110000000000000000000000 01000000000000000001000000000000 00000100000000000000000100000000 00000000010000000000000000010000 00000001000001000000000000000001 00000000000000000100000000000000 00010000000000000000010000000000 00000001000000000000000001000000 00000000000100000000000000000100 00000000000000010000000000110000 00000000000000000000000000000000 00000000000000000000000000000000 00001000110000000100000000000010 00000000000000001000000000000000 00100000000000000000100000000000 00000010000000000000000010000000 00000000001000000000000000001000 00000000000000100000000000000000 10000000000000000010000000000000 00001000000000000000001000000000 00000000100000000000000000100000 00000000000010000000000000110000 00000000000000000000000000000000 00000000000000000000000000000000 00001000110000000100000000000100 01100000000000010001100000000000 01000110000000000000000110000000 00000000011000000000000100011000 00000000010001100000000000010001 10000000000010000110000000000000 00011000000000000000011000000000 00010001100000000000000001100000 00000001000110000000000000000110 00000000000000011000000000110000 00000000000000000000000000000000 00000000000000000000000000000000 00010000000000010100000000000010 01100000000000001001100000000000 00100110000000000000100110000000 00010110011000000000000010011000 00000000001001100000000000001001 10000000000000100110000000000000 10011000000000000010011000000000 00001001100000000000001001100000 00000000100110000000000000100110 00000000000010011000001000010001 01010000000000000000000000000000 00000000000000000000000000000000 01000000010001010100001000000100 00110000100000010000110000100000 01000011000010000001000011000010 00000100001100001000000100001100 00100000010000110000100000010000 11000010000001000011000010000001 00001100001000000100001100001000 00010000110000100000010000110000 10000001000011000010000001000011 00001000000100001100000000010001 01010000000000000000000000000000 00000000000000000000000000000000 01000000000000000000000000000000 00110000000000000000110000000000 00000011000000000000000011000000 00000000001100000000000000001100 00000000000000110000000000000000 11000000000000000011000000000000 00001100000000000000001100000000 00000000110000000000000000110000 00000000000011000000000000000011 00000000000000001100000000110001 00000000000000000000000000000000 00000000000000000000000000000000 01000000000000000000001000000000 00110000100000000000110000100000 00000011000010000000000011000010 00000000001100001000000000001100 00100000000000110000100000000000 11000010000000000011000010000000 00001100001000000000001100001000 00000000110000100000000000110000 10000000000011000010000000000011 00001000000000001100000000000000 00000000000000000000000000000000 00000000000000000000000000000000 01000000010001010100001000000100 01100000100000010001100000100000 01000110000010000001000110000010 00000000011000001000000100011000 00100000010001100000100000010001 10000010000001000110000010000001 00011000001000000100011000001000 00010001100000100000010001100000 10000001000110000010000001000110 00001000000100011000000000010001 01010000000000000000000000000000 00000000000000000000000000000000 01000000000000010100001000000000 00100000100000000000100000100000 00000010000010000000000010000010 00000000001000001000000000001000 00100000000000100000100000000000 10000010000000000010000010000000 00001000001000000000001000001000 00000000100000100000000000100000 10000000000010000010000000000010 00001000000000001000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 01010000010000010100001000000100 01100000100000010001100000100000 01000110000010000001000110000010 00000000011000001000000100011000 00100000010001100000100000010001 10000010000001000110000010000001 00011000001000000100011000001000 00010001100000100000010001100000 10000001000110000010000001000110 00001000000100011000000000010000 01000000000000000000000000000000 00000000000000000000000000000000 01000000010001010100000000000100 01010000000000010001010000000000 01000101000000000001000101000000 00000000010100000000000100010100 00000000010001010000000000010001 01000000000001000101000000000001 00010100000000000100010100000000 00010001010000000000010001010000 00000001000101000000000001000101 00000000000100010100001000010001 01010000000000000000000000000000 00000000000000000000000000000000 01001000010000010000011000000000 01000001100000000001000001100000 00000100000110000000000100000110 00000100010000011000000000010000 01100000000001000001100000000001 00000110000000000100000110000000 00010000011000000000010000011000 00000001000001100000000001000001 10000000000100000110000000000100 00011000000000010000000000010000 00000000000000000000000000000000 00000000000000000000000000000000 01001000000001000000001000000001 00000000100000000100000000100000 00010000000010000000010000000010 00000001000000001000000001000000 00100000000100000000100000000100 00000010000000010000000010000000 01000000001000000001000000001000 00000100000000100000000100000000 10000000010000000010000000010000 00001000000001000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 01000000010001010100011000000011 01010001100000001101010001100000 00110101000110000000110101000110 00000011010100011000000011010100 01100000001101010001100000001101 01000110000000110101000110000000 11010100011000000011010100011000 00001101010001100000001101010001 10000000110101000110000000110101 00011000000011010100000000010001 01010000000000000000000000000000 00000000000000000000000000000000 00000000000000010000011000000100 01110001100000010001110001100000 01000111000110000001000111000110 00000100011100011000000100011100 01100000010001110001100000010001 11000110000001000111000110000001 00011100011000000100011100011000 00010001110001100000010001110001 10000001000111000110000001000111 00011000000100011100000000000000 00000000000000000000000000000000 00000000000000000000000000000000 01000000000000010100011000000000 01110001100000001001110001100000 00100111000110000000100111000110 00000010011100011000010110011100 01100000001001110001100000001001 11000110000000100111000110000000 10011100011000000010011100011000 00011001110001100000001001110001 10000000100111000110000000100111 00011000000010011100000000010001 00010000000000000000000000000000 00000000000000000000000000000000 01010000010001010100011000000001 01110001100000010101110001100000 01010111000110000001010111000110 00000101011100011000000101011100 01100000010101110001100000010101 11000110000001010111000110000001 01011100011000000101011100011000 00010101110001100000010101110001 10000001010111000110000001010111 00011000000101011100001000010001 01010000000000000000000000000000 00000000000000000000000000000000 01000000000000010000001000000001 00100000100000000100100000100000 00010010000010000000010010000010 00000001001000001000000001001000 00100000000100100000100000000100 10000010000000010010000010000000 01001000001000000001001000001000 00000100100000100000000100100000 10000000010010000010000000010010 00001000000001001000000000010001 01000000000000000000000000000000 00000000000000000000000000000000 01000000000000000000011000000000 01100001100000000001100001100000 00000110000110000000000110000110 00000000011000011000000000011000 01100000000001100001100000000001 10000110000000000110000110000000 00011000011000000000011000011000 00000001100001100000000001100001 10000000000110000110000000000110 00011000000000011000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000010001010110000000000100 01111000000000010001111000000000 01000111100000000001000111100000 00000100011110000000000000011110 00000000010001111000000000010001 11100000000001000111100000000001 00011110000000000100011110000000 00000001111000000000010001111000 00000001000111100000000001000111 10000000000100011100000000010001 01010000000000000000000000000000 00000000000000000000000000000000 01000000000000010100001000000000 01100000100000000001100000100000 00000110000010000000000110000010 00000000011000001000000000011000 00100000000001100000100000000001 10000010000000000110000010000000 00011000001000000000011000001000 00000001100000100000000001100000 10000000000110000010000000000110 00001000000000011000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 01000000000000010100001000000100 00100000100000010000100000100000 01000010000010000001000010000010 00000100001000001000000000001000 00100000010000100000100000010000 10000010000001000010000010000001 00001000001000000100001000001000 00000000100000100000010000100000 10000001000010000010000001000010 00001000000100001000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 01000000010001010100001000000100 01000000100000010001000000100000 01000100000010000001000100000010 00000100010000001000000100010000 00100001010001000000100000010001 00000010000001000100000010000001 00010000001000000100010000001000 00010001000000100000010001000000 10000001000100000010000001000100 00001000000100010000000000010001 01010000000000000000000000000000 00000000000000000000000000000000 01000000000000000000001100000001 00000000110000000001010000110000 00000101000011000000000101000011 00000000010100001100000000010100 00110000000001010000110000000001 01000011000000000101000011000000 00010100001100000000010100001100 00000001010000110000000001010000 11000000000101000011000000000101 00001100000000010100000000000000 00000000000000000000000000000000 00000000000000000000000000000000 01000000000000000000100000000100 01000010000000000001000010000001 00000100001000000000000100001000 00000000010000100000000000010000 10000000000001000010000000000001 00001000000000000100001000000000 00010000100000000000010000100000 00000000000010000000000001000010 00000000000100001000000000000100 00100000000000010000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 01000000010001010100001000000000 00000000100000001000000000100000 00100000000010000000100000000010 00000010000000001000000010000000 00100000001000000000100000001000 00000010000000100000000010000000 10000000001000000010000000001000 00001000000000100000001000000000 10000000100000000010000000100000 00001000000010000000000000010001 01010000000000000000000000000000 00000000000000000000000000000000 01000000000000010100000000000100 01100000000000010001100000000000 01000110000000000001000110000000 00000100011000000000000000011000 00000000010001100000000000010001 10000000000001000110000000000001 00011000000000000100011000000000 00100100100000000000010001100000 00000001000110000000000001000110 00000000000100011000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 01000000000000010100000000000010 01100000000000001001100000000000 00000110000000000000100110000000 00000010011000000000000010011000 00000000001001100000000000001001 10000000000100100110000000000000 10011000000000000110011000000000 00001001100000000000001001100000 00000000100110000000000100100110 00000000000010011000000000000001 00010000000000000000000000000000 00000000000000000000000000000000 01000000010001010110000000000100 00111000000000010000111000000000 00000011100000000001000011100000 00000100001110000000000100001110 00000000010000111000000000010000 11100000000000000011100000000001 00001110000000000100001110000000 00010000111000000000010000111000 00000001000011100000000001000011 10000000000100001100000000010001 01010000000000000000000000000000 00000000000000000000000000000000 01010000000000000000000100000000 00110000010000000000110000010000 00000011000001000000000011000001 00000000001100000100000000001100 00010000000000110000010000000000 11000001000000000011000001000000 00001100000100000000001100000100 00000000110000010000000000110000 01000000000011000001000000000011 00000100000000001100000000000001 00000000000000000000000000000000 00000000000000000000000000000000 01000000000000000000010100000000 00110001010000000000110001010000 00000011000101000000000011000101 00010000001100010100000000001100 01010000000000110001010000000000 11000101000000000011000101000000 00001100010100000000001100010100 00000000110001010000000000110001 01000000000011000101000000000011 00010100000000001100001000010000 01000000000000000000000000000000 00000000000000000000000000000000 01000000010001010100001100000100 01100000110000010001100000110000 01000110000011000001000110000011 00000100011000001100000100011000 00110000010001100000110000010001 10000011000001000110000011000001 00011000001100000000011000001100 00010001100000110000010001100000 11000001000110000011000001000110 00001100000100011000000000010001 01010000000000000000000000000000 00000000000000000000000000000000 01000000000000010100000000000000 00100000000000000000100000000000 00000010000000000000000010000000 00000000001000000000000000001000 00000000000000100000000000000000 10000000000000000010000000000000 00001000000000000000001000000000 00000000100000000000000000100000 00000000000010000000000000000010 00000000000000001000000000110000 00000000000000000000000000000000 00000000000000000000000000000000 01000000000000010000100001000100 01100010000100010001100010000100 01000110001000010001000110001000 01000100011000100001000100011000 10000100010001100010000100010001 10001000010001000110001000010001 00011000100001000000011000100001 00010001100010000100010001100010 00010001000110001000010001000110 00100001000100011000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 01000000010001010100000001000100 01010000000100010001010000000100 01000101000000010001000101000000 01000100010100000001000100010100 00000100010001010000000100010001 01000000010001000101000000010001 00010100000001000100010100000001 00010100000000000100010001010000 00010001000101000000010001000101 00000001000100010100000000010001 01010000000000000000000000000000 00000000000000000000000000000000 01000000000001010000100000100000 01000010000010000001000010000010 00000100001000001000000100001000 00100000010000100000100000010000 10000010000001000010000010000001 00001000001000000100001000001000 00010000100000100000010000100000 10000001000010000010000001000010 00001000000100001000001000000100 00100000100000010000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000101000000001 00000010100000000100000010100000 01010000001010000000010000001010 00000001000000101000010001000000 10100000000100000010100000000100 00001010000000010000001010000000 01000000101000000001000000101000 00000100000010100000000100000010 10000000010000001010000000010000 00101000000001000000000000010001 01000000000000000000000000000000 00000000000000000000000000000000 01000000010001010100110100000011 01010011010000001101010011010000 00010101001101000000110101001101 00000011010100110100000011010100 11010000001101010011010000001101 01001101000000010101001101000000 11010100110100000011010100110100 00001101010011010000001101010011 01000000110101001101000000110101 00110100000011010100000000010001 01010000000000000000000000000000 00000000000000000000000000000000 01000000000000010100100000000100 01110010000000010001110010000000 01000111001000000001000111001000 00000000011100100000000100011100 10000000010001110010000000010001 11001000000001000111001000000001 00011100100000000000011100100000 00010001110010000000010001110010 00000001000101001000000001000111 00100000000100011100000000110001 00010000000000000000000000000000 00000000000000000000000000000000 00000000000000000010001100011000 01001000110001100001001000110001 10000100100011000110000100100011 00011000010010001100011000010010 00110001100001001000110001100001 00100011000110000100100011000110 00010010001100011000010010001100 01100001001000110001100001001000 11000110000100100011000110000100 10001100011000010000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000011111111111111 01001111111111111101001111111111 11110100111111111111110100111111 11111111010011111111111111010011 11111111111101001111111111111101 00111111111111110100111111111111 11010011111111111111010011111111 11111101001111111111111101001111 11111111110100111111111111110100 11111111111111010000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000010110011011011 00001011001101101100001011001101 10110000101100110110110000101100 11011011000010110011011011000010 11001101101100001011001101101100 00101100110110110000101100110110 11000010110011011011000010110011 01101100001011001101101100001011 00110110110000101100110110110000 10110011011011000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000011001100111100 01001100110011110001001100110011 11000100110011001111000100110011 00111100010011001100111100010011 00110011110001001100110011110001 00110011001111000100110011001111 00010011001100111100010011001100 11110001001100110011110001001100 11001111000100110011001111000100 11001100111100010000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000011101101111110 01001110110111111001001110110111 11100100111011011111100100111011 01111110010011101101111110010011 10110111111001001110110111111001 00111011011111100100111011011111 10010011101101111110010011101101 11111001001110110111111001001110 11011111100100111011011111100100 11101101111110010000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000001010000101 00100000001000010000000100101000 01000001000010100001000000010010 10000010001100001010000011000101 00101000010000000000101000011000 00010010100001000010000010100001 00000000001010000111000100001010 00010100000000001000010000101100 10100001000000000010010001000010 00001001000100001000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000100 00010000000100010000010000000000 01000010001010000001000000111000 00000110000001000000000100001000 00000000010100110010000000010100 00011000000001010011010000000001 11000000000000000111000100000000 00010000000000000000010000111000 00000001000000000010010001000000 00000000000100000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000011000010000101 00100100100000010000100000000000 01000011000000100001000010000000 10000101001000000001000100001000 00001000011000100000001000011000 10000000100001110011001000100001 11001010000010000111001000000010 00010100000100101000010000100000 00100001000000110000000001000010 00000001000100001000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000101 00000000100100010000101100000000 01000011000000000001000010000000 00000100001000000001000100001111 00000000010000110000000000010000 10000000000001110000010000000001 10001011000000000101001100000000 00010100000000000000010000010000 00000001000000000000000001000010 00000000000100001000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000010000000 00010100001000001100110100001000 00000001000010100000010011000000 10000001000001000010000011000001 00001000001100000000001000000000 00010000100000110001010000100000 00001000000010000000000000000010 00000100110100001000000000110000 00100000000000000000000000000000 00000010000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00001000000000000000001000000001 00000000100100000000000000000000 00000010000000000000010001000010 00000011000000001000000000001000 00100000000100000000100000001000 00000010000000100000000010000000 00000000001000000000000000001000 00000100100000100000000100110000 10000000000000000000000000000000 00001000000000000000001000000000 00000000000000000000000000000000 00000000000000000000000000000000 00001000000000000001000010000001 00100010101000000000100110001100 00000001001000100000100010001000 10000011000001100010000000001010 10001000001100000010001000000100 00001000100000010010111000100000 00001000100010000000000000100010 00000000111110001000000100111110 00100000000010011000110000000010 00100010000000001000001000000000 00000000000000000000000000000000 00000000000000000000000000000000 00001000000000000000100000000011 00000010000000001100110110100000 00000001001010000000010001001000 00000010000000100000000000001000 10000000001000000000000000000000 00001000000000000010001000000000 00001010100000000000000000100000 00001000110010000000001100011010 00000000000010001010010000000010 00100000000000001000001000000000 00000000000000000000000000000000 00000000000000000000000000000000 00001000000000000011101010000111 00101010001000010000010010101000 01000011001000010001000010001000 10000101000100101010000101000000 10101000011000000010101000010000 01001010100001100001001010100001 10000001101010000100000100101010 00010100111010001000010100000010 00100001000000001000100001000000 00100010000100000000001000000000 00000000000000000000000000000000 00000000000000000000000000000000 00001000000000000001100000000100 00101110000000010000100010000000 01000011001010000001000011101000 00000101000010100000000100000001 10000000011100000010000000010000 11101010000001010010011000000001 00001100100000000100001100100000 00010100110110100000011100100110 00000001000001111000000001000001 00101001000100000000001000000000 00000000000000000000000000000000 00000000000000000000000000000000 00001000000000000000000010000100 00000000101000010000110100000100 01000011000000100001000010100010 10000000001010000010000101001010 00001000011100000000001000010000 11010000100001100001100000100000 01001000000010000101001000000010 00010100100000001000011100110000 10100001000010100000100001000010 00000010000100001000001000000000 00000000000000000000000000000000 00000000000000000000000000000000 00001000000100000000000000000111 00100000000000010000110000000000 01000001010010000001000011010010 00000110000001000000000101001000 00000000011000110100000000011100 01110000000001010011010000000001 01000000000000000101000001000000 00011100100000100100011000100000 10000001110001000000000001110001 00000000000100001000001000000100 00000000000000000000000000000000 00000000000000000000000000000000 00001000000000000010000010000111 00000100101000010000100000100000 01110000010000100001010000010000 10000101001101000010000111001110 00001000010100100000001000011100 01000010100001110000000000100001 00000001000010000111001110000010 00011000100000001000011100010000 00100001110011010000100001000000 00000001000100001000001000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000001001000000001 00001000000000000000010100000100 01000010000000000000100010100010 00000101000110001000000100001000 00000000001000100100100000010000 01000000000001000010100010000000 00000000001000000111000001001000 00010100100100000000011000100000 10000001000000000000000000000011 11000000000000000100000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000010000001 00100100101000000000100100000000 01000010010010100000010011000010 10000111001001000010000100001110 00001000000100110100001000010000 10000000100001000011100000100000 00001000000010000111000001000010 00010100000000101000010100111000 10100001000000000000000000000010 01000010000000001000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000100001000000000000011 00100000100000000000000100100100 00000001100010000000000011000000 00000001001100000000000011001000 00100000000100101000000000000000 00100010000000000010000000000000 00001001000000000010001100000000 00001100001000100100000100101000 00000000110011010010000000000001 00001000000000001000000000000100 00100000000000000000000000000000 00000000000000000000000000000000 00000000000000000001000000010000 01000000100000000000000000000000 00000000000000000001000000010000 00000000000000000000000000000000 00000000000100000000000000000000 10010000000000000000000000000000 00000000000000000001000000000000 00000000100100000010000000000000 00000000000000000000000000000000 00000000001000001000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00111100001111000011000000000000 10000000100000000000000000000000 00010000000000000000000000110000 10000000000000001000000000000000 00000000000100000010000000010000 00110000100000000000000010000000 00000000000000000000000000100000 00010000001100000000000000000000 01000000000000000000000000010000 00000000000000000000111100001111 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000011001 10000000000110011000000000111111 11011001101111111101100110000000 00011001101111111101100100000000 00011111101100101011100011001111 10000000000000000001100110100110 00000000000000011000111101001011 01101000010000000001100110000000 00011001110000000011111111011001 10111111110110011000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000001000000000111110 10111110101111101011111010000000 00000000000000000010000000000000 00010010000100101000011010000010 00010110100000000001011010100000 00000000000001100000010000000000 00010000000000000000000000000000 00000000000000000010100000010000 00111110100101101100000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000010001000 01000100100000010100000110000000 00000000000000000000000000000000 11000000000000000000000000000000 00000000000000000000000000000000 00000000110000000000000000000000 00000000000000000000000000000000 00000000000000001000000101111000 01000001101100010000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000011111111111111 11111111111111111100000000000000 00000000000000000000000000111111 11111111111111111111111111000000 00000000000000000000000000000000 00111111101111111111111111111111 11000000000000000000000000000000 00000000001111111111111111101111 11111101110000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000011111111111111 11111111111111111100000000000000 00000000000000000000000000101101 11111111101011101111111111000000 00000000000000000000000000000000 00111111101111111111111111111110 00000000000000000000000000000000 00000000001101111111111011111111 01111111110000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000011111111111111 11111111111111111100000000000000 00000000000000000000000000111101 11111111111111111011111111000000 00000000000000000000000000000000 00111111101111111111111111111111 11000000000000000000000000000000 00000000001111111111111111111111 11111111110000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000011111111111111 11111111111111111100000000000000 00000000000000000000000000111111 11111111111111111111111111000000 00000000000000000000000000000000 00111111111111111111111111111111 11000000000000000000000000000000 00000000001111111111111111111111 11111111110000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000011111111111111 11111111111111111100000000000000 00000000000000000000000000111111 11111111111111111111111111000000 00000000000000000000000000000000 00111111111111111111111100111111 11000000000000000000000000000000 00000000001111111111111111111111 11111111110000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000011111111111111 11111111111111111100000000000000 00000000000000000000000000111111 11111111101111111111111111000000 00000000000000000000000000000000 00111111111111111011111111111111 11000000000000000000000000000000 00000000001111111111111100111111 11111111110000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000011000111 00100100101000010000100000001000 01000001000000100001000010010010 10000100000000001010000000001000 00101000010000010000101000011000 10110010110001010000010010100001 00001000001010000100000100001010 00010000101100101000011100000100 10110001000001000000100001000000 00000010000100000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000001000111 00010000100000010000110000000000 01000011000000000001000001110000 00000101000010000000000000001001 00000000010000100000000000011100 01000000000001100000100000000001 00000000000000000111001000000000 00010000001000000000011100101100 00000001000010000000000001000000 00000000000100000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000001000011000111 00101000001000010000100100101100 01000011000010100001000010000000 10000110000001000010000000001000 00001000010000010000001100011100 10000000100001010000010000100001 00001000000010000101000000000001 00010000100000001000011100000000 00000001000011000000010001000000 00001010000100000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000001000000000100 00101000000000010000010100000000 01000011000000000001000010000000 00000100000001000000000000001101 00000000010000000000000000011000 00000000000001010000010000000001 00000010000000000110000100000001 00010000100000000000010000010000 00010001000010110010000001000000 00001000000100000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000010001011000000 00100000101000000000000100001000 00000010000000100000000010000000 10000000000000000010000000000101 00001000001100100000001000000100 00100000110000000000000000100000 10001001000010000010000000000010 00001100000000000100000000000000 00110000000000010000010000000000 00000001000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00001000000000000000000001000000 00000000000000000000010000100000 00000000000010000000000001000010 00000000000000001000000000001100 00100000000100010000100000001000 00000010000000000000000010000000 01000000001000000001000000001000 00001100010000100100000000100000 10000000000000000010000000000001 00001000000000000100001000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000001101000000000 00100110001000000000100110101100 00000010001000100000010010001000 10000001000001100010000000001101 10001000001100100010001100000100 10011000100000000000011000100000 10001001100010000010000000100010 00001100100010000100000000011110 00100000000010011000000000000010 00101010000000001000001000000000 00000000000000000000000000000000 00000000000000000000000000000000 00001000000000000010100000000000 00000110100000000000000010000000 00000010001000000000010000001000 00000001000000100000000000000010 10000000001000000010000000000000 10001000000000000000011000000000 00001000100000000000000000100000 00000100000110000100000000001010 00000000000010001000000000000010 00100000000000001000001000000000 00000000000000000000000000000000 00000000000000000000000000000000 00001000000000000000101010000111 00101010101000010000010110001000 01000001001010100001000010001010 10000101000100101010000110000001 10101000011000000010101000010000 01101000100001010001001010100001 01000001101010000100000000101001 00010100000010100000011100100010 10000001000001011010000001000001 00101001000100000000001000000000 00000000000000000000000000000000 00000000000000000000000000000000 00001000000000000010100000000111 00110010000000010000110010000000 01010011001000000001000001101000 00000111000010100000000101000100 10000000011100100010000000010000 10101000000001100010001010000001 10001000100000000100000000100001 00011000110010000100011100010110 00000001000010001000010001000010 00100001000100000100001000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000010000111 00110000001000010000110100001000 01000010000000010001000010100000 10000111001010000010000110001000 00001000010100010000001000010000 01000010100001010000100000100001 01000101000010000101000000000010 00010100111000001000011100100000 00100001000001100000000001000001 00000001000100001000001000000000 00000000000000000000000000000000 00000000000000000000000000000000 00001000000100000001000000000111 00010100000000011100010000100000 01100011000000000001110001000000 00000101000111000000000101001100 00000000010100100000000000011100 11000010000001110011010000000001 11001100000000000101000010000000 00011100010100000100011100010100 00000001110011000000010001110010 00000001000111001100001000000100 00000000000000000000000000000000 00000000000000000000000000000000 00001000000000000000001010000100 00001000001000010000000000001000 01000010010000010001000010000000 10000111000000000010000101000010 00001000010000100000001000010100 00010000100001110010100010100001 01001010000010000101000000000010 00011100000000001000010100100000 00110001100001100000010001000010 01000010000100000000001000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000001000000000000 00000100100000000000000100100000 00000010000010000000000011110010 00000011000010001000000010001001 00100000000100100000100000001000 01100010000001000010000000000000 10000001001000000011000000001000 00011000100100100000001000101000 10000000010010010010000000000010 00001001000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000001000010000000 00100100001000000000100000101000 00000011000000100000000010010000 10000011001001000010000001001100 00001000000000111100001000000100 10010010100001000010100000100000 01001000000010000011000001000001 00010100100000000100000100101000 00100000000011000000010000000010 01000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000100001010001000000000 00100000000000000000101000000000 00000010100000010000000011000000 00000001001000000000000001001000 00000000001000111000000000000000 10000000000000110010000010000000 00000000000000000000000010000001 00000000100100000000000000110000 00000000100010000000000000000011 10000001000000000000000000000100 00100000000000000000000000000000 00000000000000000000000000000000 00000000000000000001000000000000 01000000000000000000000000000000 00000000000000000001000000010000 00000000000000000000000000000000 00000000000100000000000000000000 10010000000000000000000000000000 00000000000000000001000010000000 00100000100100000000000000000000 00000000000000000000000000000000 00000000001000001000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00111100001111000011000000000000 10100000000000000000000000000000 00010000000000000000000000110000 10000000000000001000000000000000 00000000000000000010000000010000 10110000100000000000000010000000 00000000000000000001000000100000 00010000101100000000000001000000 11000000000000000000000000010000 00000000000000000000111100001111 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000100000000111111 11011001101111111101100110000000 00100110010110011001100100000000 00011111001100010111100000011101 11011001100000000010011001000000 00000000000010001000001111001000 01101111100000000001100110000000 00000000110000000011111111011001 10111111110110011000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000101000 00101001001010000010000001000000 00000000000000000010000010000000 00000100100001101000010010000110 00000000000000000000000000100000 10000000000000101001001000010000 10000100000000000000000000000000 00000000100000000010100000000000 00101000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000010000100 10000001000000010101000100000000 00000000000000000000000000000000 11000000000000000000000000000000 00000000000000000000000000000000 00000000100000000000000000000000 00000000000000000000000000000000 00000000000000001000000101111000 01001000101100010100000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000011111111111111 11111111111111111100000000000000 00000000000000000000000000101111 11111011111111111110111111000000 00000000000000000000000000000000 00011111100111111001111111011111 11000000000000000000000000000000 00000000001011111111111111111111 11110111110000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000011111111111111 11111111111111111100000000000000 00000000000000000000000000111111 01011111010011101111111111000000 00000000000000000000000000000000 00101111011011110110111111111101 01000000000000000000000000000000 00000000001111110011111101001111 11111111110000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000011111111111111 11111111111111111100000000000000 00000000000000000000000000011111 11111111101111111111111111000000 00000000000000000000000000000000 00101111001111111011111111111111 11000000000000000000000000000000 00000000001111110111111110111111 11111111110000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000011111111111111 11111111111111111100000000000000 00000000000000000000000000111111 11111111111111111111111111000000 00000000000000000000000000000000 00111111111111111111111111111111 11000000000000000000000000000000 00000000001111111111111011111111 11111111110000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000011111111111111 11111111111111111100000000000000 00000000000000000000000000111111 11111111111111111111111111000000 00000000000000000000000000000000 00111111111111111111111110111111 11000000000000000000000000000000 00000000001111111111111111111111 11111111110000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000011111111111111 11111111111111111100000000000000 00000000000000000000000000111111 11111111111111111111111111000000 00000000000000000000000000000000 00111111111111111111111111111111 11000000000000000000000000000000 00000000001111111111111111111111 11111111110000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00110000000000000010000000000001 00000010000000000000000000000000 00110000000000000100001100001100 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00110000000000000010000000000001 00000010000000100000000000000000 00110000000000000100001100000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00110000000000000000000000000001 00000000000000001010100001101000 00110000000000001000000000000001 00000000000000000000000000000011 00110000000000000100000000001100 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00110000000000001000000000000001 00000000000000000000000000000101 00110000000000001010000000000001 00000000000000000000000000000000 00110000000000000000000000000001 00000000000000001110000101011010 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 zaptel-1.4.11/kernel/Kbuild0000644000000000000000000000351711012636464014221 0ustar rootrootifdef ECHO_CAN_NAME ECHO_CAN_CFLAGS := -DECHO_CAN_FROMENV -DECHO_CAN_$(ECHO_CAN_NAME) endif obj-m := $(KBUILD_OBJ_M) EXTRA_CFLAGS := -I$(src) -DSTANDALONE_ZAPATA EXTRA_CFLAGS += $(ECHO_CAN_CFLAGS) # 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 zaptel-objs := zaptel-base.o ifeq ($(ARCH),i386) ifneq ($(wildcard $(src)/hpec/hpec_x86_32.o_shipped),) HPEC_PRESENT=yes zaptel-objs += hpec/hpec_x86_32.o endif endif ifeq ($(ARCH),x86_64) ifneq ($(wildcard $(src)/hpec/hpec_x86_64.o_shipped),) HPEC_PRESENT=yes zaptel-objs += hpec/hpec_x86_64.o endif endif ifeq ($(HPEC_PRESENT),yes) EXTRA_CFLAGS += -DECHO_CAN_HPEC -I$(src)/hpec $(obj)/zaptel-base.o: $(src)/hpec/hpec_zaptel.h $(src)/hpec/hpec_user.h endif $(obj)/pciradio.o: $(obj)/radfw.h $(obj)/tor2.o: $(obj)/tor2fw.h hostprogs-y := $(obj)/makefw $(obj)/tor2fw.h: $(src)/tormenta2.rbt $(obj)/makefw $(obj)/makefw $< tor2fw > $@ $(obj)/radfw.h: $(src)/pciradio.rbt $(obj)/makefw $(obj)/makefw $< radfw > $@ $(obj)/makefw: $(src)/makefw.c $(HOSTCC) -o $@ $^ # set CONFIG_ZAPTEL_MMX for a number of CPU types. # Right now this part is not enabled, unless you build with # ZAPTEL_MMX_AUTO=something . ZAPMMX_WHITELIST_i386 = M586MMX M686 MPENTIUMII MPENTIUMIII MPENTIUMM \ MPENTIUM4 MVIAC3_2 ZAPMMX_WHITELIST_x86_64 = # A list of configuration variables to test: CONFIG_M686 , etc. ZAPMMX_CONFIG_VARS := $(ZAPMMX_WHITELIST_$(ARCH):%=CONFIG_%) # expand them: ZAPMMX_CONFIG_VALS := $(strip $(foreach var,$(ZAPMMX_CONFIG_VARS),$(var)) ) ifneq (,$(ZAPTEL_MMX_AUTO)) ifneq (,$(ZAPMMX_CONFIG_VALS)) # TODO: make that CFLAGS_zaptel-base.o += -DCONFIG_ZAPTEL_MMX endif endif zaptel-1.4.11/kernel/wcusb.h0000644000000000000000000000705510751714440014361 0ustar rootroot #ifndef _WCUSB_H #define _WCUSB_H #include #include #include #include #include #if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,19) #define USB2420 #endif #include "zaptel.h" #define WC_MAX_IFACES 128 #define POWERSAVE_TIME 4000 /* Powersaving timeout for devices with a proslic */ /* Various registers and data ports on the tigerjet part */ #define WCUSB_SPORT0 0x26 #define WCUSB_SPORT1 0x27 #define WCUSB_SPORT2 0x28 #define WCUSB_SPORT_CTRL 0x29 #define WC_AUX0 0x1 #define WC_AUX1 0x2 #define WC_AUX2 0x4 #define WC_AUX3 0x8 #define CONTROL_TIMEOUT_MS (500) /* msec */ #define CONTROL_TIMEOUT_JIFFIES ((CONTROL_TIMEOUT_MS * HZ) / 1000) #define REQUEST_NORMAL 4 #define FLAG_RUNNING (1 << 0) /* Important data structures and data types */ /* States for the Proslic read state machine */ typedef enum { STATE_WCREAD_WRITEREG, STATE_WCREAD_READRES, STATE_WCWRITE_WRITEREG, STATE_WCWRITE_WRITERES, } proslic_state_t; /* Used for current stream state */ typedef enum { STREAM_NORMAL, /* Sends normal (unmodified) audio data */ STREAM_DTMF, /* (For keypad device) Sends dtmf data */ } stream_t; /* States for the Keypad state machine */ typedef enum { STATE_FOR_LOOP_1_OUT, STATE_FOR_LOOP_2_IN, STATE_FOR_LOOP_PROC_DATA, STATE_FOR_LOOP_CLEAR_DIGIT, } keypad_state_t; /* Device types. For radical changes in a new device, use a switch based on the device type */ typedef enum { WC_KEYPAD, /* The tigerjet phone with the keypad. That was a bugger to implement */ WC_PROSLIC, /* For various devices with a proslic */ } dev_type_t; struct wc_keypad_data { keypad_state_t state; /* Current state in the keypad detect routine */ #ifdef USB2420 struct urb urb; /* urb used for the keypad data transport ... can't remember whether it is used or not */ #else urb_t urb; /* urb used for the keypad data transport ... can't remember whether it is used or not */ #endif int running; char data; char data12; char tmp; int scanned_event; int i; int count; /* DTMF tone generation stuff for zaptel */ struct zt_tone_state ts; struct zt_tone *tone; }; struct stinky_urb { #ifdef USB2420 struct urb urb; #ifndef LINUX26 struct iso_packet_descriptor isoframe[1]; #endif #else urb_t urb; iso_packet_descriptor_t isoframe[1]; #endif }; struct wc_usb_pvt { const char *variety; struct usb_device *dev; dev_type_t devclass; int usecount; int dead; struct zt_span span; struct zt_chan chan; struct stinky_urb dataread[2]; struct stinky_urb datawrite[2]; #ifdef USB2420 struct urb control; struct usb_ctrlrequest dr; #else urb_t control; devrequest dr; #endif proslic_state_t controlstate; int urbcount; int flags; int timer; int lowpowertimer; int idletxhookstate; int hookstate; __u8 newtxhook; __u8 txhook; int pos; unsigned char auxstatus; unsigned char wcregindex; unsigned char wcregbuf[4]; unsigned char wcregval; short readchunk[ZT_MAX_CHUNKSIZE * 2]; short writechunk[ZT_MAX_CHUNKSIZE * 2]; stream_t sample; void *pvt_data; }; struct wc_usb_desc { char *name; int flags; }; #endif zaptel-1.4.11/kernel/datamods/0002755000000000000000000000000011017303252014643 5ustar rootrootzaptel-1.4.11/kernel/datamods/Makefile0000644000000000000000000000154410751714440016316 0ustar rootroot.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) SUBDIRS=$(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 zaptel-1.4.11/kernel/datamods/hdlc_ppp.c0000644000000000000000000000503210751714440016607 0ustar rootroot/* * 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; } zaptel-1.4.11/kernel/datamods/hdlc_fr.c0000644000000000000000000007204110751714440016423 0ustar rootroot/* * 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) dev = alloc_netdev(sizeof(struct net_device_stats), "pvceth%d", ether_setup); else dev = alloc_netdev(sizeof(struct net_device_stats), "pvc%d", dlci_setup); 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; } zaptel-1.4.11/kernel/datamods/hdlc_raw.c0000644000000000000000000000432010751714440016600 0ustar rootroot/* * 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; } zaptel-1.4.11/kernel/datamods/hdlc_cisco.c0000644000000000000000000002072010751714440017111 0ustar rootroot/* * 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; } zaptel-1.4.11/kernel/datamods/syncppp.c0000644000000000000000000011575510751714440016530 0ustar rootroot/* * 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: syncppp.c 3793 2008-02-04 23:00:48Z tzafrir $ */ #undef DEBUG #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 (unsigned long arg); 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)) { init_timer(&p->pp_timer); p->pp_timer.function=sppp_cp_timeout; p->pp_timer.expires=jiffies+s*HZ; p->pp_timer.data=(unsigned long)p; p->pp_flags |= PP_TIMO; add_timer(&p->pp_timer); } } 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"); zaptel-1.4.11/kernel/datamods/hdlc_raw_eth.c0000644000000000000000000000541110751714440017442 0ustar rootroot/* * 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; } zaptel-1.4.11/kernel/datamods/hdlc_generic.c0000644000000000000000000001641110751714440017427 0ustar rootroot/* * 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; dev = alloc_netdev(sizeof(hdlc_device), "hdlc%d", hdlc_setup); 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); zaptel-1.4.11/kernel/makefw.c0000644000000000000000000000410110751714440014470 0ustar rootroot/* Xilinx firmware convertor program. * * * Written by Jim Dixon . * * Copyright (C) 2001 Jim Dixon / Zapata Telephony. * Copyright (C) 2001 Linux Support Services, Inc. * * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under thet erms 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. * * Primary Author: Mark Spencer * */ #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); } zaptel-1.4.11/kernel/tor2.c0000644000000000000000000013211010761356330014107 0ustar rootroot/* * Tormenta 2 Quad-T1 PCI Driver * * Written by Mark Spencer * Based on previous works, designs, and archetectures conceived and * written by Jim Dixon . * * Copyright (C) 2001 Jim Dixon / Zapata Telephony. * Copyright (C) 2001, Linux Support Services, 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 "zaptel.h" #ifdef LINUX26 #include #endif #define NEED_PCI_IDS #include "tor2-hw.h" #include "tor2fw.h" /* * 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. */ /* #define ENABLE_TASKLETS */ /* this stuff needs to work for 64 bit systems, however using the macro causes it to take twice as long */ /* #define FIXTHISFOR64 */ /* as of now, un-comment for 32 bit only system */ #define SPANS_PER_CARD 4 #define MAX_SPANS 16 #define FLAG_STARTED (1 << 0) #define TYPE_T1 1 /* is a T1 card */ #define TYPE_E1 2 /* is an E1 card */ struct tor2_chan { /* Private pointer for channel. We want to know our channel and span */ struct tor2 *tor; int span; /* Index from 0 */ }; struct tor2_span { /* Private pointer for span. We want to know our span number and pointer to the tor device */ struct tor2 *tor; int span; /* Index from 0 */ }; struct tor2 { /* This structure exists one per card */ struct pci_dev *pci; /* Pointer to PCI device */ int num; /* Which card we are */ int syncsrc; /* active sync source */ int syncs[SPANS_PER_CARD]; /* sync sources */ int psyncs[SPANS_PER_CARD]; /* span-relative sync sources */ int alarmtimer[SPANS_PER_CARD]; /* Alarm timer */ char *type; /* Type of tormenta 2 card */ int irq; /* IRQ used by device */ int order; /* Order */ int flags; /* Device flags */ int syncpos[SPANS_PER_CARD]; /* span-relative sync sources */ int master; /* Are we master */ unsigned long plx_region; /* phy addr of PCI9030 registers */ unsigned long plx_len; /* length of PLX window */ volatile unsigned short *plx; /* Virtual representation of local space */ unsigned long xilinx32_region; /* 32 bit Region allocated to Xilinx */ unsigned long xilinx32_len; /* Length of 32 bit Xilinx region */ volatile unsigned int *mem32; /* Virtual representation of 32 bit Xilinx memory area */ unsigned long xilinx8_region; /* 8 bit Region allocated to Xilinx */ unsigned long xilinx8_len; /* Length of 8 bit Xilinx region */ volatile unsigned char *mem8; /* Virtual representation of 8 bit Xilinx memory area */ struct zt_span spans[SPANS_PER_CARD]; /* Spans */ struct tor2_span tspans[SPANS_PER_CARD]; /* Span data */ struct zt_chan *chans[SPANS_PER_CARD]; /* Pointers to blocks of 24(30/31) contiguous zt_chans for each span */ struct tor2_chan tchans[32 * SPANS_PER_CARD]; /* Channel user data */ unsigned char txsigs[SPANS_PER_CARD][16]; /* Copy of tx sig registers */ int loopupcnt[SPANS_PER_CARD]; /* loop up code counter */ int loopdowncnt[SPANS_PER_CARD];/* loop down code counter */ int spansstarted; /* number of spans started */ spinlock_t lock; /* lock context */ unsigned char leds; /* copy of LED register */ unsigned char ec_chunk1[SPANS_PER_CARD][32][ZT_CHUNKSIZE]; /* first EC chunk buffer */ unsigned char ec_chunk2[SPANS_PER_CARD][32][ZT_CHUNKSIZE]; /* second EC chunk buffer */ #ifdef ENABLE_TASKLETS int taskletrun; int taskletsched; int taskletpending; int taskletexec; int txerrors; struct tasklet_struct tor2_tlet; #endif int cardtype; /* card type, T1 or E1 */ unsigned int *datxlt; /* pointer to datxlt structure */ unsigned int passno; /* number of interrupt passes */ }; #define t1out(tor,span,reg,val) tor->mem8[((span - 1) * 0x100) + reg] = val #define t1in(tor,span,reg) tor->mem8[((span - 1) * 0x100) + reg] #ifdef ENABLE_TASKLETS static void tor2_tasklet(unsigned long data); #endif #define GPIOC (PLX_LOC_GPIOC >> 1) /* word-oriented address for PLX GPIOC reg. (32 bit reg.) */ #define LAS2BRD (0x30 >> 1) #define LAS3BRD (0x34 >> 1) #define INTCSR (0x4c >> 1) /* word-oriented address for PLX INTCSR reg. */ #define PLX_INTENA 0x43 /* enable, hi-going, level trigger */ #define SYNCREG 0x400 #define CTLREG 0x401 #define LEDREG 0x402 #define STATREG 0x400 #define SWREG 0x401 #define CTLREG1 0x404 #define INTENA (1 + ((loopback & 3) << 5)) #define OUTBIT (2 + ((loopback & 3) << 5)) #define E1DIV 0x10 #define INTACK (0x80 + ((loopback & 3) << 5)) #define INTACTIVE 2 #define MASTER (1 << 3) /* un-define this if you dont want NON-REV A hardware support */ /* #define NONREVA 1 */ #define SYNCSELF 0 #define SYNC1 1 #define SYNC2 2 #define SYNC3 3 #define SYNC4 4 #define SYNCEXTERN 5 #define LEDRED 2 #define LEDGREEN 1 #define MAX_TOR_CARDS 64 struct tor2 *cards[MAX_TOR_CARDS]; /* signalling bits */ #define TOR_ABIT 8 #define TOR_BBIT 4 static int debug; static int japan; static int loopback; static int highestorder; static int timingcable; static void set_clear(struct tor2 *tor); static int tor2_startup(struct zt_span *span); static int tor2_shutdown(struct zt_span *span); static int tor2_rbsbits(struct zt_chan *chan, int bits); static int tor2_maint(struct zt_span *span, int cmd); static int tor2_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data); ZAP_IRQ_HANDLER(tor2_intr); /* translations of data channels for 24 channels in a 32 bit PCM highway */ unsigned datxlt_t1[] = { 1 ,2 ,3 ,5 ,6 ,7 ,9 ,10,11,13,14,15,17,18,19,21,22,23,25,26,27,29,30,31 }; /* translations of data channels for 30/31 channels in a 32 bit PCM highway */ unsigned datxlt_e1[] = { 1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, 25,26,27,28,29,30,31 }; static int tor2_spanconfig(struct zt_span *span, struct zt_lineconfig *lc) { int i; struct tor2_span *p = span->pvt; if (debug) printk("Tor2: Configuring span %d\n", span->spanno); span->syncsrc = p->tor->syncsrc; /* remove this span number from the current sync sources, if there */ for (i = 0; i < SPANS_PER_CARD; i++) { if (p->tor->syncs[i] == span->spanno) { p->tor->syncs[i] = 0; p->tor->psyncs[i] = 0; } } p->tor->syncpos[p->span] = lc->sync; /* if a sync src, put it in the proper place */ if (lc->sync) { p->tor->syncs[lc->sync - 1] = span->spanno; p->tor->psyncs[lc->sync - 1] = p->span + 1; } /* If we're already running, then go ahead and apply the changes */ if (span->flags & ZT_FLAG_RUNNING) return tor2_startup(span); return 0; } static int tor2_chanconfig(struct zt_chan *chan, int sigtype) { int alreadyrunning; unsigned long flags; struct tor2_chan *p = chan->pvt; alreadyrunning = chan->span->flags & ZT_FLAG_RUNNING; if (debug) { if (alreadyrunning) printk("Tor2: Reconfigured channel %d (%s) sigtype %d\n", chan->channo, chan->name, sigtype); else printk("Tor2: Configured channel %d (%s) sigtype %d\n", chan->channo, chan->name, sigtype); } /* nothing more to do if an E1 */ if (p->tor->cardtype == TYPE_E1) return 0; spin_lock_irqsave(&p->tor->lock, flags); if (alreadyrunning) set_clear(p->tor); spin_unlock_irqrestore(&p->tor->lock, flags); return 0; } static int tor2_open(struct zt_chan *chan) { #ifndef LINUX26 MOD_INC_USE_COUNT; #endif return 0; } static int tor2_close(struct zt_chan *chan) { #ifndef LINUX26 MOD_DEC_USE_COUNT; #endif return 0; } static void init_spans(struct tor2 *tor) { int x, y, c; for (x = 0; x < SPANS_PER_CARD; x++) { sprintf(tor->spans[x].name, "Tor2/%d/%d", tor->num, x + 1); snprintf(tor->spans[x].desc, sizeof(tor->spans[x].desc) - 1, "Tormenta 2 (PCI) Quad %s Card %d Span %d", (tor->cardtype == TYPE_T1) ? "T1" : "E1", tor->num, x + 1); tor->spans[x].manufacturer = "Digium"; zap_copy_string(tor->spans[x].devicetype, tor->type, sizeof(tor->spans[x].devicetype)); snprintf(tor->spans[x].location, sizeof(tor->spans[x].location) - 1, "PCI Bus %02d Slot %02d", tor->pci->bus->number, PCI_SLOT(tor->pci->devfn) + 1); tor->spans[x].spanconfig = tor2_spanconfig; tor->spans[x].chanconfig = tor2_chanconfig; tor->spans[x].startup = tor2_startup; tor->spans[x].shutdown = tor2_shutdown; tor->spans[x].rbsbits = tor2_rbsbits; tor->spans[x].maint = tor2_maint; tor->spans[x].open = tor2_open; tor->spans[x].close = tor2_close; if (tor->cardtype == TYPE_T1) { tor->spans[x].channels = 24; tor->spans[x].deflaw = ZT_LAW_MULAW; tor->spans[x].linecompat = ZT_CONFIG_AMI | ZT_CONFIG_B8ZS | ZT_CONFIG_D4 | ZT_CONFIG_ESF; tor->spans[x].spantype = "T1"; } else { tor->spans[x].channels = 31; tor->spans[x].deflaw = ZT_LAW_ALAW; tor->spans[x].linecompat = ZT_CONFIG_HDB3 | ZT_CONFIG_CCS | ZT_CONFIG_CRC4; tor->spans[x].spantype = "E1"; } tor->spans[x].chans = tor->chans[x]; tor->spans[x].flags = ZT_FLAG_RBS; tor->spans[x].ioctl = tor2_ioctl; tor->spans[x].pvt = &tor->tspans[x]; tor->tspans[x].tor = tor; tor->tspans[x].span = x; init_waitqueue_head(&tor->spans[x].maintq); for (y=0;yspans[x].channels;y++) { struct zt_chan *mychans = tor->chans[x] + y; sprintf(mychans->name, "Tor2/%d/%d/%d", tor->num, x + 1, y + 1); mychans->sigcap = ZT_SIG_EM | ZT_SIG_CLEAR | ZT_SIG_FXSLS | ZT_SIG_FXSGS | ZT_SIG_FXSKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_FXOKS | ZT_SIG_CAS | ZT_SIG_SF | ZT_SIG_EM_E1; c = (x * tor->spans[x].channels) + y; mychans->pvt = &tor->tchans[c]; mychans->chanpos = y + 1; tor->tchans[c].span = x; tor->tchans[c].tor = tor; } } } static int __devinit tor2_launch(struct tor2 *tor) { if (tor->spans[0].flags & ZT_FLAG_REGISTERED) return 0; printk("Tor2: Launching card: %d\n", tor->order); if (zt_register(&tor->spans[0], 0)) { printk(KERN_ERR "Unable to register span %s\n", tor->spans[0].name); return -1; } if (zt_register(&tor->spans[1], 0)) { printk(KERN_ERR "Unable to register span %s\n", tor->spans[1].name); zt_unregister(&tor->spans[0]); return -1; } if (zt_register(&tor->spans[2], 0)) { printk(KERN_ERR "Unable to register span %s\n", tor->spans[2].name); zt_unregister(&tor->spans[0]); zt_unregister(&tor->spans[1]); return -1; } if (zt_register(&tor->spans[3], 0)) { printk(KERN_ERR "Unable to register span %s\n", tor->spans[3].name); zt_unregister(&tor->spans[0]); zt_unregister(&tor->spans[1]); zt_unregister(&tor->spans[2]); return -1; } tor->plx[INTCSR] = cpu_to_le16(PLX_INTENA); /* enable PLX interrupt */ #ifdef ENABLE_TASKLETS tasklet_init(&tor->tor2_tlet, tor2_tasklet, (unsigned long)tor); #endif return 0; } static int __devinit tor2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { int res,x,f; struct tor2 *tor; unsigned long endjif; volatile unsigned long *gpdata_io,*lasdata_io; unsigned long gpdata,lasdata; res = pci_enable_device(pdev); if (res) return res; tor = kmalloc(sizeof(struct tor2), GFP_KERNEL); if (!tor) return -ENOMEM; memset(tor,0,sizeof(struct tor2)); spin_lock_init(&tor->lock); for (x = 0; x < SPANS_PER_CARD; x++) { tor->chans[x] = kmalloc(sizeof(struct zt_chan) * 31,GFP_KERNEL); if (!tor->chans[x]) return -ENOMEM; memset(tor->chans[x],0,sizeof(struct zt_chan) * 31); } /* Load the resources */ tor->pci = pdev; tor->irq = pdev->irq; if (tor->irq < 1) { printk(KERN_ERR "No IRQ allocated for device\n"); goto err_out_free_tor; } tor->plx_region = pci_resource_start(pdev, 0); tor->plx_len = pci_resource_len(pdev, 0); tor->plx = ioremap(tor->plx_region, tor->plx_len); /* We don't use the I/O space, so we dont do anything with section 1 */ tor->xilinx32_region = pci_resource_start(pdev, 2); tor->xilinx32_len = pci_resource_len(pdev, 2); tor->mem32 = ioremap(tor->xilinx32_region, tor->xilinx32_len); tor->xilinx8_region = pci_resource_start(pdev, 3); tor->xilinx8_len = pci_resource_len(pdev, 3); tor->mem8 = ioremap(tor->xilinx8_region, tor->xilinx8_len); /* Record what type */ tor->type = (char *)ent->driver_data; /* Verify existence and accuracy of resources */ if (!tor->plx_region || !tor->plx || (pci_resource_flags(pdev, 0) & IORESOURCE_IO)) { printk(KERN_ERR "Invalid PLX 9030 Base resource\n"); goto err_out_free_tor; } if (!tor->xilinx32_region || !tor->mem32 || (pci_resource_flags(pdev, 2) & IORESOURCE_IO)) { printk(KERN_ERR "Invalid Xilinx 32 bit Base resource\n"); goto err_out_free_tor; } if (!tor->xilinx8_region || !tor->mem8 || (pci_resource_flags(pdev, 3) & IORESOURCE_IO)) { printk(KERN_ERR "Invalid Xilinx 8 bit Base resource\n"); goto err_out_free_tor; } /* Request regions */ if (!request_mem_region(tor->plx_region, tor->plx_len, tor->type)) { printk(KERN_ERR "Unable to reserve PLX memory %08lx window at %08lx\n", tor->plx_len, tor->plx_region); goto err_out_free_tor; } if (!request_mem_region(tor->xilinx32_region, tor->xilinx32_len, tor->type)) { printk(KERN_ERR "Unable to reserve Xilinx 32 bit memory %08lx window at %08lx\n", tor->xilinx32_len, tor->xilinx32_region); goto err_out_release_plx_region; } if (!request_mem_region(tor->xilinx8_region, tor->xilinx8_len, tor->type)) { printk(KERN_ERR "Unable to reserve Xilinx memory %08lx window at %08lx\n", tor->xilinx8_len, tor->xilinx8_region); goto err_out_release_plx_region; } pci_set_drvdata(pdev, tor); printk("Detected %s at 0x%lx/0x%lx irq %d\n", tor->type, tor->xilinx32_region, tor->xilinx8_region,tor->irq); for (x = 0; x < MAX_TOR_CARDS; x++) { if (!cards[x]) break; } if (x >= MAX_TOR_CARDS) { printk("No cards[] slot available!!\n"); goto err_out_release_all; } tor->num = x; cards[x] = tor; /* start programming mode */ gpdata_io = (unsigned long *)&tor->plx[GPIOC]; gpdata = le32_to_cpu(*gpdata_io); gpdata |= GPIO_WRITE; /* make sure WRITE is not asserted */ *gpdata_io = cpu_to_le32(gpdata); gpdata &= ~GPIO_PROGRAM; /* activate the PROGRAM signal */ *gpdata_io = cpu_to_le32(gpdata); /* wait for INIT and DONE to go low */ endjif = jiffies + 10; while (le32_to_cpu(*gpdata_io) & (GPIO_INIT | GPIO_DONE) && (jiffies <= endjif)); if (endjif < jiffies) { printk("Timeout waiting for INIT and DONE to go low\n"); goto err_out_release_all; } if (debug) printk("fwload: Init and done gone to low\n"); gpdata |= GPIO_PROGRAM; *gpdata_io = cpu_to_le32(gpdata); /* de-activate the PROGRAM signal */ /* wait for INIT to go high (clearing done */ endjif = jiffies + 10; while (!(le32_to_cpu(*gpdata_io) & GPIO_INIT) && (jiffies <= endjif)); if (endjif < jiffies) { printk("Timeout waiting for INIT to go high\n"); goto err_out_release_all; } if (debug) printk("fwload: Init went high (clearing done)\nNow loading...\n"); /* assert WRITE signal */ gpdata &= ~GPIO_WRITE; *gpdata_io = cpu_to_le32(gpdata); for (x = 0; x < sizeof(tor2fw); x++) { /* write the byte */ *tor->mem8 = tor2fw[x]; /* if DONE signal, we're done, exit */ if (le32_to_cpu(*gpdata_io) & GPIO_DONE) break; /* if INIT drops, we're screwed, exit */ if (!(le32_to_cpu(*gpdata_io) & GPIO_INIT)) break; } if (debug) printk("fwload: Transferred %d bytes into chip\n",x); /* Wait for FIFO to clear */ endjif = jiffies + 2; while (jiffies < endjif); /* wait */ /* de-assert write signal */ gpdata |= GPIO_WRITE; *gpdata_io = cpu_to_le32(gpdata); if (debug) printk("fwload: Loading done!\n"); /* Wait for FIFO to clear */ endjif = jiffies + 2; while (jiffies < endjif); /* wait */ if (!(le32_to_cpu(*gpdata_io) & GPIO_INIT)) { printk("Drove Init low!! CRC Error!!!\n"); goto err_out_release_all; } if (!(le32_to_cpu(*gpdata_io) & GPIO_DONE)) { printk("Did not get DONE signal. Short file maybe??\n"); goto err_out_release_all; } printk("Xilinx Chip successfully loaded, configured and started!!\n"); tor->mem8[SYNCREG] = 0; tor->mem8[CTLREG] = 0; tor->mem8[CTLREG1] = 0; tor->mem8[LEDREG] = 0; /* set the LA2BRD register so that we enable block transfer, read pre-fetch, and set to maximum read pre-fetch size */ lasdata_io = (unsigned long *)&tor->plx[LAS2BRD]; lasdata = *lasdata_io; lasdata |= 0x39; *lasdata_io = lasdata; /* set the LA3BRD register so that we enable block transfer */ lasdata_io = (unsigned long *)&tor->plx[LAS3BRD]; lasdata = *lasdata_io; lasdata |= 1; *lasdata_io = lasdata; /* check part revision data */ x = t1in(tor,1,0xf) & 15; #ifdef NONREVA if (x > 3) { tor->mem8[CTLREG1] = NONREVA; } #endif for (x = 0; x < 256; x++) tor->mem32[x] = 0x7f7f7f7f; if (request_irq(tor->irq, tor2_intr, ZAP_IRQ_SHARED_DISABLED, "tor2", tor)) { printk(KERN_ERR "Unable to request tormenta IRQ %d\n", tor->irq); goto err_out_release_all; } if (t1in(tor,1,0xf) & 0x80) { printk("Tormenta 2 Quad E1/PRA Card\n"); tor->cardtype = TYPE_E1; tor->datxlt = datxlt_e1; } else { printk("Tormenta 2 Quad T1/PRI Card\n"); tor->cardtype = TYPE_T1; tor->datxlt = datxlt_t1; } init_spans(tor); tor->order = tor->mem8[SWREG]; printk("Detected Card number: %d\n", tor->order); /* Launch cards as appropriate */ x = 0; for (;;) { /* Find a card to activate */ f = 0; for (x=0;cards[x];x++) { if (cards[x]->order <= highestorder) { tor2_launch(cards[x]); if (cards[x]->order == highestorder) f = 1; } } /* If we found at least one, increment the highest order and search again, otherwise stop */ if (f) highestorder++; else break; } return 0; err_out_release_all: release_mem_region(tor->xilinx32_region, tor->xilinx32_len); release_mem_region(tor->xilinx8_region, tor->xilinx8_len); err_out_release_plx_region: release_mem_region(tor->plx_region, tor->plx_len); err_out_free_tor: if (tor->plx) iounmap((void *)tor->plx); if (tor->mem8) iounmap((void *)tor->mem8); if (tor->mem32) iounmap((void *)tor->mem32); if (tor) { for (x = 0; x < 3; x++) kfree(tor->chans[x]); kfree(tor); } return -ENODEV; } static struct pci_driver tor2_driver; static void __devexit tor2_remove(struct pci_dev *pdev) { int x; struct tor2 *tor; tor = pci_get_drvdata(pdev); if (!tor) BUG(); tor->mem8[SYNCREG] = 0; tor->mem8[CTLREG] = 0; tor->mem8[LEDREG] = 0; tor->plx[INTCSR] = cpu_to_le16(0); free_irq(tor->irq, tor); if (tor->spans[0].flags & ZT_FLAG_REGISTERED) zt_unregister(&tor->spans[0]); if (tor->spans[1].flags & ZT_FLAG_REGISTERED) zt_unregister(&tor->spans[1]); if (tor->spans[2].flags & ZT_FLAG_REGISTERED) zt_unregister(&tor->spans[2]); if (tor->spans[3].flags & ZT_FLAG_REGISTERED) zt_unregister(&tor->spans[3]); release_mem_region(tor->plx_region, tor->plx_len); release_mem_region(tor->xilinx32_region, tor->xilinx32_len); release_mem_region(tor->xilinx8_region, tor->xilinx8_len); if (tor->plx) iounmap((void *)tor->plx); if (tor->mem8) iounmap((void *)tor->mem8); if (tor->mem32) iounmap((void *)tor->mem32); cards[tor->num] = 0; pci_set_drvdata(pdev, NULL); for (x = 0; x < 3; x++) if (tor->chans[x]) kfree(tor->chans[x]); kfree(tor); } static struct pci_driver tor2_driver = { name: "tormenta2", probe: tor2_probe, #ifdef LINUX26 remove: __devexit_p(tor2_remove), #else remove: tor2_remove, #endif id_table: tor2_pci_ids, }; static int __init tor2_init(void) { int res; res = zap_pci_module(&tor2_driver); printk("Registered Tormenta2 PCI\n"); return res; } static void __exit tor2_cleanup(void) { pci_unregister_driver(&tor2_driver); printk("Unregistered Tormenta2\n"); } static void set_clear(struct tor2 *tor) { int i,j,s; unsigned short val=0; for (s = 0; s < SPANS_PER_CARD; s++) { for (i = 0; i < 24; i++) { j = (i/8); if (tor->spans[s].chans[i].flags & ZT_FLAG_CLEAR) val |= 1 << (i % 8); if ((i % 8)==7) { #if 0 printk("Putting %d in register %02x on span %d\n", val, 0x39 + j, 1 + s); #endif t1out(tor,1 + s, 0x39 + j, val); val = 0; } } } } static int tor2_rbsbits(struct zt_chan *chan, int bits) { u_char m,c; int k,n,b; struct tor2_chan *p = chan->pvt; unsigned long flags; #if 0 printk("Setting bits to %d on channel %s\n", bits, chan->name); #endif if (p->tor->cardtype == TYPE_E1) { /* do it E1 way */ if (chan->chanpos == 16) return 0; n = chan->chanpos - 1; if (chan->chanpos > 16) n--; k = p->span; b = (n % 15) + 1; c = p->tor->txsigs[k][b]; m = (n / 15) * 4; /* nibble selector */ c &= (15 << m); /* keep the other nibble */ c |= (bits & 15) << (4 - m); /* put our new nibble here */ p->tor->txsigs[k][b] = c; /* output them to the chip */ t1out(p->tor,k + 1,0x40 + b,c); return 0; } n = chan->chanpos - 1; k = p->span; b = (n / 8); /* get byte number */ m = 1 << (n & 7); /* get mask */ c = p->tor->txsigs[k][b]; c &= ~m; /* clear mask bit */ /* set mask bit, if bit is to be set */ if (bits & ZT_ABIT) c |= m; p->tor->txsigs[k][b] = c; spin_lock_irqsave(&p->tor->lock, flags); t1out(p->tor,k + 1,0x70 + b,c); b += 3; /* now points to b bit stuff */ /* get current signalling values */ c = p->tor->txsigs[k][b]; c &= ~m; /* clear mask bit */ /* set mask bit, if bit is to be set */ if (bits & ZT_BBIT) c |= m; /* save new signalling values */ p->tor->txsigs[k][b] = c; /* output them into the chip */ t1out(p->tor,k + 1,0x70 + b,c); b += 3; /* now points to c bit stuff */ /* get current signalling values */ c = p->tor->txsigs[k][b]; c &= ~m; /* clear mask bit */ /* set mask bit, if bit is to be set */ if (bits & ZT_CBIT) c |= m; /* save new signalling values */ p->tor->txsigs[k][b] = c; /* output them into the chip */ t1out(p->tor,k + 1,0x70 + b,c); b += 3; /* now points to d bit stuff */ /* get current signalling values */ c = p->tor->txsigs[k][b]; c &= ~m; /* clear mask bit */ /* set mask bit, if bit is to be set */ if (bits & ZT_DBIT) c |= m; /* save new signalling values */ p->tor->txsigs[k][b] = c; /* output them into the chip */ t1out(p->tor,k + 1,0x70 + b,c); spin_unlock_irqrestore(&p->tor->lock, flags); return 0; } static int tor2_shutdown(struct zt_span *span) { int i; int tspan; int wasrunning; unsigned long flags; struct tor2_span *p = span->pvt; tspan = p->span + 1; if (tspan < 0) { printk("Tor2: Span '%d' isn't us?\n", span->spanno); return -1; } spin_lock_irqsave(&p->tor->lock, flags); wasrunning = span->flags & ZT_FLAG_RUNNING; span->flags &= ~ZT_FLAG_RUNNING; /* Zero out all registers */ if (p->tor->cardtype == TYPE_E1) { for (i = 0; i < 192; i++) t1out(p->tor,tspan, i, 0); } else { for (i = 0; i < 160; i++) t1out(p->tor,tspan, i, 0); } if (wasrunning) p->tor->spansstarted--; spin_unlock_irqrestore(&p->tor->lock, flags); if (!(p->tor->spans[0].flags & ZT_FLAG_RUNNING) && !(p->tor->spans[1].flags & ZT_FLAG_RUNNING) && !(p->tor->spans[2].flags & ZT_FLAG_RUNNING) && !(p->tor->spans[3].flags & ZT_FLAG_RUNNING)) /* No longer in use, disable interrupts */ p->tor->mem8[CTLREG] = 0; if (debug) printk("Span %d (%s) shutdown\n", span->spanno, span->name); return 0; } static int tor2_startup(struct zt_span *span) { unsigned long endjif; int i; int tspan; unsigned long flags; char *coding; char *framing; char *crcing; int alreadyrunning; struct tor2_span *p = span->pvt; tspan = p->span + 1; if (tspan < 0) { printk("Tor2: Span '%d' isn't us?\n", span->spanno); return -1; } spin_lock_irqsave(&p->tor->lock, flags); alreadyrunning = span->flags & ZT_FLAG_RUNNING; /* initialize the start value for the entire chunk of last ec buffer */ for (i = 0; i < span->channels; i++) { memset(p->tor->ec_chunk1[p->span][i], ZT_LIN2X(0,&span->chans[i]),ZT_CHUNKSIZE); memset(p->tor->ec_chunk2[p->span][i], ZT_LIN2X(0,&span->chans[i]),ZT_CHUNKSIZE); } /* Force re-evaluation of the timing source */ if (timingcable) p->tor->syncsrc = -1; if (p->tor->cardtype == TYPE_E1) { /* if this is an E1 card */ unsigned char tcr1,ccr1,tcr2; if (!alreadyrunning) { p->tor->mem8[SYNCREG] = SYNCSELF; p->tor->mem8[CTLREG] = E1DIV; p->tor->mem8[LEDREG] = 0; /* Force re-evaluation of sync src */ /* Zero out all registers */ for (i = 0; i < 192; i++) t1out(p->tor,tspan, i, 0); /* Set up for Interleaved Serial Bus operation in byte mode */ /* Set up all the spans every time, so we are sure they are in a consistent state. If we don't, a card without all its spans configured misbehaves in strange ways. */ t1out(p->tor,1,0xb5,9); t1out(p->tor,2,0xb5,8); t1out(p->tor,3,0xb5,8); t1out(p->tor,4,0xb5,8); t1out(p->tor,tspan,0x1a,4); /* CCR2: set LOTCMC */ for (i = 0; i <= 8; i++) t1out(p->tor,tspan,i,0); for (i = 0x10; i <= 0x4f; i++) if (i != 0x1a) t1out(p->tor,tspan,i,0); t1out(p->tor,tspan,0x10,0x20); /* RCR1: Rsync as input */ t1out(p->tor,tspan,0x11,6); /* RCR2: Sysclk=2.048 Mhz */ t1out(p->tor,tspan,0x12,9); /* TCR1: TSiS mode */ } ccr1 = 0; crcing = ""; tcr1 = 9; /* base TCR1 value: TSis mode */ tcr2 = 0; if (span->lineconfig & ZT_CONFIG_CCS) { ccr1 |= 8; /* CCR1: Rx Sig mode: CCS */ coding = "CCS"; } else { tcr1 |= 0x20; coding = "CAS"; } if (span->lineconfig & ZT_CONFIG_HDB3) { ccr1 |= 0x44; /* CCR1: TX and RX HDB3 */ framing = "HDB3"; } else framing = "AMI"; if (span->lineconfig & ZT_CONFIG_CRC4) { ccr1 |= 0x11; /* CCR1: TX and TX CRC4 */ tcr2 |= 0x02; /* TCR2: CRC4 bit auto */ crcing = "/CRC4"; } t1out(p->tor,tspan,0x12,tcr1); t1out(p->tor,tspan,0x13,tcr2); t1out(p->tor,tspan,0x14,ccr1); t1out(p->tor,tspan, 0x18, 0x20); /* 120 Ohm, normal */ if (!alreadyrunning) { t1out(p->tor,tspan,0x1b,0x8a); /* CCR3: LIRST & TSCLKM */ t1out(p->tor,tspan,0x20,0x1b); /* TAFR */ t1out(p->tor,tspan,0x21,0x5f); /* TNAFR */ t1out(p->tor,tspan,0x40,0xb); /* TSR1 */ for (i = 0x41; i <= 0x4f; i++) t1out(p->tor,tspan,i,0x55); for (i = 0x22; i <= 0x25; i++) t1out(p->tor,tspan,i,0xff); /* Wait 100 ms */ endjif = jiffies + 10; spin_unlock_irqrestore(&p->tor->lock, flags); while (jiffies < endjif); /* wait 100 ms */ spin_lock_irqsave(&p->tor->lock, flags); t1out(p->tor,tspan,0x1b,0x9a); /* CCR3: set also ESR */ t1out(p->tor,tspan,0x1b,0x82); /* CCR3: TSCLKM only now */ span->flags |= ZT_FLAG_RUNNING; p->tor->spansstarted++; /* enable interrupts */ p->tor->mem8[CTLREG] = INTENA | E1DIV; } spin_unlock_irqrestore(&p->tor->lock, flags); if (debug) { if (alreadyrunning) printk("Tor2: Reconfigured span %d (%s/%s%s) 120 Ohms\n", span->spanno, coding, framing, crcing); else printk("Tor2: Startup span %d (%s/%s%s) 120 Ohms\n", span->spanno, coding, framing, crcing); } } else { /* is a T1 card */ if (!alreadyrunning) { p->tor->mem8[SYNCREG] = SYNCSELF; p->tor->mem8[CTLREG] = 0; p->tor->mem8[LEDREG] = 0; /* Zero out all registers */ for (i = 0; i < 160; i++) t1out(p->tor,tspan, i, 0); /* Set up for Interleaved Serial Bus operation in byte mode */ /* Set up all the spans every time, so we are sure they are in a consistent state. If we don't, a card without all its spans configured misbehaves in strange ways. */ t1out(p->tor,1,0x94,9); t1out(p->tor,2,0x94,8); t1out(p->tor,3,0x94,8); t1out(p->tor,4,0x94,8); /* Full-on Sync required (RCR1) */ t1out(p->tor,tspan, 0x2b, 8); /* RSYNC is an input (RCR2) */ t1out(p->tor,tspan, 0x2c, 8); /* RBS enable (TCR1) */ t1out(p->tor,tspan, 0x35, 0x10); /* TSYNC to be output (TCR2) */ t1out(p->tor,tspan, 0x36, 4); /* Tx & Rx Elastic store, sysclk(s) = 2.048 mhz, loopback controls (CCR1) */ t1out(p->tor,tspan, 0x37, 0x9c); /* Set up received loopup and loopdown codes */ t1out(p->tor,tspan, 0x12, 0x22); t1out(p->tor,tspan, 0x14, 0x80); t1out(p->tor,tspan, 0x15, 0x80); /* Setup japanese mode if appropriate */ t1out(p->tor,tspan,0x19,(japan ? 0x80 : 0x00)); /* no local loop */ t1out(p->tor,tspan,0x1e,(japan ? 0x80 : 0x00)); /* no local loop */ } /* Enable F bits pattern */ i = 0x20; if (span->lineconfig & ZT_CONFIG_ESF) i = 0x88; if (span->lineconfig & ZT_CONFIG_B8ZS) i |= 0x44; t1out(p->tor,tspan, 0x38, i); if (i & 0x80) coding = "ESF"; else coding = "SF"; if (i & 0x40) framing = "B8ZS"; else { framing = "AMI"; t1out(p->tor,tspan,0x7e,0x1c); /* F bits pattern (0x1c) into FDL register */ } t1out(p->tor,tspan, 0x7c, span->txlevel << 5); if (!alreadyrunning) { /* LIRST to reset line interface */ t1out(p->tor,tspan, 0x0a, 0x80); /* Wait 100 ms */ endjif = jiffies + 10; spin_unlock_irqrestore(&p->tor->lock, flags); while (jiffies < endjif); /* wait 100 ms */ spin_lock_irqsave(&p->tor->lock, flags); t1out(p->tor,tspan,0x0a,0x30); /* LIRST back to normal, Resetting elastic stores */ span->flags |= ZT_FLAG_RUNNING; p->tor->spansstarted++; /* enable interrupts */ p->tor->mem8[CTLREG] = INTENA; } set_clear(p->tor); spin_unlock_irqrestore(&p->tor->lock, flags); if (debug) { if (alreadyrunning) printk("Tor2: Reconfigured span %d (%s/%s) LBO: %s\n", span->spanno, coding, framing, zt_lboname(span->txlevel)); else printk("Tor2: Startup span %d (%s/%s) LBO: %s\n", span->spanno, coding, framing, zt_lboname(span->txlevel)); } } if (p->tor->syncs[0] == span->spanno) printk("SPAN %d: Primary Sync Source\n",span->spanno); if (p->tor->syncs[1] == span->spanno) printk("SPAN %d: Secondary Sync Source\n",span->spanno); if (p->tor->syncs[2] == span->spanno) printk("SPAN %d: Tertiary Sync Source\n",span->spanno); if (p->tor->syncs[3] == span->spanno) printk("SPAN %d: Quaternary Sync Source\n",span->spanno); return 0; } static int tor2_maint(struct zt_span *span, int cmd) { struct tor2_span *p = span->pvt; int tspan = p->span + 1; if (p->tor->cardtype == TYPE_E1) { switch(cmd) { case ZT_MAINT_NONE: t1out(p->tor,tspan,0xa8,0); /* no loops */ break; case ZT_MAINT_LOCALLOOP: t1out(p->tor,tspan,0xa8,0x40); /* local loop */ break; case ZT_MAINT_REMOTELOOP: t1out(p->tor,tspan,0xa8,0x80); /* remote loop */ break; case ZT_MAINT_LOOPUP: case ZT_MAINT_LOOPDOWN: case ZT_MAINT_LOOPSTOP: return -ENOSYS; default: printk("Tor2: Unknown maint command: %d\n", cmd); break; } return 0; } switch(cmd) { case ZT_MAINT_NONE: t1out(p->tor,tspan,0x19,(japan ? 0x80 : 0x00)); /* no local loop */ t1out(p->tor,tspan,0x0a,0); /* no remote loop */ break; case ZT_MAINT_LOCALLOOP: t1out(p->tor,tspan,0x19,0x40 | (japan ? 0x80 : 0x00)); /* local loop */ t1out(p->tor,tspan,0x0a,0); /* no remote loop */ break; case ZT_MAINT_REMOTELOOP: t1out(p->tor,tspan,0x1e,(japan ? 0x80 : 0x00)); /* no local loop */ t1out(p->tor,tspan,0x0a,0x40); /* remote loop */ break; case ZT_MAINT_LOOPUP: t1out(p->tor,tspan,0x30,2); /* send loopup code */ t1out(p->tor,tspan,0x12,0x22); /* send loopup code */ t1out(p->tor,tspan,0x13,0x80); /* send loopup code */ break; case ZT_MAINT_LOOPDOWN: t1out(p->tor,tspan,0x30,2); /* send loopdown code */ t1out(p->tor,tspan,0x12,0x62); /* send loopdown code */ t1out(p->tor,tspan,0x13,0x90); /* send loopdown code */ break; case ZT_MAINT_LOOPSTOP: t1out(p->tor,tspan,0x30,0); /* stop sending loopup code */ break; default: printk("Tor2: Unknown maint command: %d\n", cmd); break; } return 0; } static inline void tor2_run(struct tor2 *tor) { int x,y; for (x = 0; x < SPANS_PER_CARD; x++) { if (tor->spans[x].flags & ZT_FLAG_RUNNING) { /* since the Tormenta 2 PCI is double-buffered, you need to delay the transmit data 2 entire chunks so that the transmit will be in sync with the receive */ for (y=0;yspans[x].channels;y++) { zt_ec_chunk(&tor->spans[x].chans[y], tor->spans[x].chans[y].readchunk, tor->ec_chunk2[x][y]); memcpy(tor->ec_chunk2[x][y],tor->ec_chunk1[x][y], ZT_CHUNKSIZE); memcpy(tor->ec_chunk1[x][y], tor->spans[x].chans[y].writechunk, ZT_CHUNKSIZE); } zt_receive(&tor->spans[x]); } } for (x = 0; x < SPANS_PER_CARD; x++) { if (tor->spans[x].flags & ZT_FLAG_RUNNING) zt_transmit(&tor->spans[x]); } } #ifdef ENABLE_TASKLETS static void tor2_tasklet(unsigned long data) { struct tor2 *tor = (struct tor2 *)data; tor->taskletrun++; if (tor->taskletpending) { tor->taskletexec++; tor2_run(tor); } tor->taskletpending = 0; } #endif static int syncsrc = 0; static int syncnum = 0 /* -1 */; static int syncspan = 0; #ifdef DEFINE_SPINLOCK static DEFINE_SPINLOCK(synclock); #else static spinlock_t synclock = SPIN_LOCK_UNLOCKED; #endif static int tor2_findsync(struct tor2 *tor) { int i; int x; unsigned long flags; int p; int nonzero; int newsyncsrc = 0; /* Zaptel span number */ int newsyncnum = 0; /* tor2 card number */ int newsyncspan = 0; /* span on given tor2 card */ spin_lock_irqsave(&synclock, flags); #if 1 if (!tor->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 < SPANS_PER_CARD; i++) { if (cards[x]->syncpos[i]) { nonzero = 1; if ((cards[x]->syncpos[i] == p) && !(cards[x]->spans[i].alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_LOOPBACK)) && (cards[x]->spans[i].flags & ZT_FLAG_RUNNING)) { /* This makes a good sync source */ newsyncsrc = cards[x]->spans[i].spanno; newsyncnum = x; newsyncspan = i + 1; /* Jump out */ goto found; } } } } if (nonzero) p++; else break; } found: if ((syncnum != newsyncnum) || (syncsrc != newsyncsrc) || (newsyncspan != syncspan)) { syncnum = newsyncnum; syncsrc = newsyncsrc; syncspan = newsyncspan; if (debug) printk("New syncnum: %d, syncsrc: %d, syncspan: %d\n", syncnum, syncsrc, syncspan); } } #endif /* update sync src info */ if (tor->syncsrc != syncsrc) { tor->syncsrc = syncsrc; /* Update sync sources */ for (i = 0; i < SPANS_PER_CARD; i++) { tor->spans[i].syncsrc = tor->syncsrc; } if (syncnum == tor->num) { #if 1 /* actually set the sync register */ tor->mem8[SYNCREG] = syncspan; #endif if (debug) printk("Card %d, using sync span %d, master\n", tor->num, syncspan); tor->master = MASTER; } else { #if 1 /* time from the timing cable */ tor->mem8[SYNCREG] = SYNCEXTERN; #endif tor->master = 0; if (debug) printk("Card %d, using Timing Bus, NOT master\n", tor->num); } } spin_unlock_irqrestore(&synclock, flags); return 0; } ZAP_IRQ_HANDLER(tor2_intr) { int n, i, j, k, syncsrc; unsigned int rxword,txword; unsigned char c, rxc; unsigned char abits, bbits; struct tor2 *tor = (struct tor2 *) dev_id; /* make sure its a real interrupt for us */ if (!(tor->mem8[STATREG] & INTACTIVE)) /* if not, just return */ { #ifdef LINUX26 return IRQ_NONE; #else return; #endif } if (tor->cardtype == TYPE_E1) /* set outbit, interrupt enable, and ack interrupt */ tor->mem8[CTLREG] = OUTBIT | INTENA | INTACK | E1DIV | tor->master; else /* set outbit, interrupt enable, and ack interrupt */ tor->mem8[CTLREG] = OUTBIT | INTENA | INTACK | tor->master; #if 0 if (!tor->passno) printk("Interrupt handler\n"); #endif /* do the transmit output */ for (n = 0; n < tor->spans[0].channels; n++) { for (i = 0; i < ZT_CHUNKSIZE; i++) { /* span 1 */ txword = tor->spans[0].chans[n].writechunk[i] << 24; /* span 2 */ txword |= tor->spans[1].chans[n].writechunk[i] << 16; /* span 3 */ txword |= tor->spans[2].chans[n].writechunk[i] << 8; /* span 4 */ txword |= tor->spans[3].chans[n].writechunk[i]; /* write to part */ #ifdef FIXTHISFOR64 tor->mem32[tor->datxlt[n] + (32 * i)] = txword; #else tor->mem32[tor->datxlt[n] + (32 * i)] = cpu_to_le32(txword); #endif } } /* Do the receive input */ for (n = 0; n < tor->spans[0].channels; n++) { for (i = 0; i < ZT_CHUNKSIZE; i++) { /* read from */ #ifdef FIXTHISFOR64 rxword = tor->mem32[tor->datxlt[n] + (32 * i)]; #else rxword = le32_to_cpu(tor->mem32[tor->datxlt[n] + (32 * i)]); #endif /* span 1 */ tor->spans[0].chans[n].readchunk[i] = rxword >> 24; /* span 2 */ tor->spans[1].chans[n].readchunk[i] = (rxword & 0xff0000) >> 16; /* span 3 */ tor->spans[2].chans[n].readchunk[i] = (rxword & 0xff00) >> 8; /* span 4 */ tor->spans[3].chans[n].readchunk[i] = rxword & 0xff; } } i = tor->passno & 15; /* if an E1 card, do rx signalling for it */ if ((i < 3) && (tor->cardtype == TYPE_E1)) { /* if an E1 card */ for (j = (i * 5); j < (i * 5) + 5; j++) { for (k = 1; k <= SPANS_PER_CARD; k++) { c = t1in(tor,k,0x31 + j); rxc = c & 15; if (rxc != tor->spans[k - 1].chans[j + 16].rxsig) { /* Check for changes in received bits */ if (!(tor->spans[k - 1].chans[j + 16].sig & ZT_SIG_CLEAR)) zt_rbsbits(&tor->spans[k - 1].chans[j + 16], rxc); } rxc = c >> 4; if (rxc != tor->spans[k - 1].chans[j].rxsig) { /* Check for changes in received bits */ if (!(tor->spans[k - 1].chans[j].sig & ZT_SIG_CLEAR)) zt_rbsbits(&tor->spans[k - 1].chans[j], rxc); } } } } /* if a T1, do the signalling */ if ((i < 12) && (tor->cardtype == TYPE_T1)) { k = (i / 3); /* get span */ n = (i % 3); /* get base */ abits = t1in(tor,k + 1, 0x60 + n); bbits = t1in(tor,k + 1, 0x63 + n); for (j=0; j< 8; j++) { /* Get channel number */ i = (n * 8) + j; rxc = 0; if (abits & (1 << j)) rxc |= ZT_ABIT; if (bbits & (1 << j)) rxc |= ZT_BBIT; if (tor->spans[k].chans[i].rxsig != rxc) { /* Check for changes in received bits */ if (!(tor->spans[k].chans[i].sig & ZT_SIG_CLEAR)) { zt_rbsbits(&tor->spans[k].chans[i], rxc); } } } } for (i = 0; i < SPANS_PER_CARD; i++) { /* Go thru all the spans */ /* if alarm timer, and it's timed out */ if (tor->alarmtimer[i]) { if (!--tor->alarmtimer[i]) { /* clear recover status */ tor->spans[i].alarms &= ~ZT_ALARM_RECOVER; if (tor->cardtype == TYPE_E1) t1out(tor,i + 1,0x21,0x5f); /* turn off yel */ else t1out(tor,i + 1,0x35,0x10); /* turn off yel */ zt_alarm_notify(&tor->spans[i]); /* let them know */ } } } i = tor->passno & 15; if ((i >= 10) && (i <= 13) && !(tor->passno & 0x30)) { j = 0; /* clear this alarm status */ i -= 10; if (tor->cardtype == TYPE_T1) { c = t1in(tor,i + 1,0x31); /* get RIR2 */ tor->spans[i].rxlevel = c >> 6; /* get rx level */ t1out(tor,i + 1,0x20,0xff); c = t1in(tor,i + 1,0x20); /* get the status */ /* detect the code, only if we are not sending one */ if ((!tor->spans[i].mainttimer) && (c & 0x80)) /* if loop-up code detected */ { /* set into remote loop, if not there already */ if ((tor->loopupcnt[i]++ > 80) && (tor->spans[i].maintstat != ZT_MAINT_REMOTELOOP)) { t1out(tor,i + 1,0x1e,(japan ? 0x80 : 0x00)); /* no local loop */ t1out(tor,i + 1,0x0a,0x40); /* remote loop */ tor->spans[i].maintstat = ZT_MAINT_REMOTELOOP; } } else tor->loopupcnt[i] = 0; /* detect the code, only if we are not sending one */ if ((!tor->spans[i].mainttimer) && (c & 0x40)) /* if loop-down code detected */ { /* if in remote loop, get out of it */ if ((tor->loopdowncnt[i]++ > 80) && (tor->spans[i].maintstat == ZT_MAINT_REMOTELOOP)) { t1out(tor,i + 1,0x1e,(japan ? 0x80 : 0x00)); /* no local loop */ t1out(tor,i + 1,0x0a,0); /* no remote loop */ tor->spans[i].maintstat = ZT_MAINT_NONE; } } else tor->loopdowncnt[i] = 0; if (c & 3) /* if red alarm */ { j |= ZT_ALARM_RED; } if (c & 8) /* if blue alarm */ { j |= ZT_ALARM_BLUE; } } else { /* its an E1 card */ t1out(tor,i + 1,6,0xff); c = t1in(tor,i + 1,6); /* get the status */ if (c & 9) /* if red alarm */ { j |= ZT_ALARM_RED; } if (c & 2) /* if blue alarm */ { j |= ZT_ALARM_BLUE; } } /* only consider previous carrier alarm state */ tor->spans[i].alarms &= (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_NOTOPEN); n = 1; /* set to 1 so will not be in yellow alarm if we dont care about open channels */ /* if to have yellow alarm if nothing open */ if (tor->spans[i].lineconfig & ZT_CONFIG_NOTOPEN) { /* go thru all chans, and count # open */ for (n = 0,k = 0; k < tor->spans[i].channels; k++) { if (((tor->chans[i] + k)->flags & ZT_FLAG_OPEN) || ((tor->chans[i] + k)->flags & ZT_FLAG_NETDEV)) n++; } /* if none open, set alarm condition */ if (!n) j |= ZT_ALARM_NOTOPEN; } /* if no more alarms, and we had some */ if ((!j) && tor->spans[i].alarms) { tor->alarmtimer[i] = ZT_ALARMSETTLE_TIME; } if (tor->alarmtimer[i]) j |= ZT_ALARM_RECOVER; /* if going into alarm state, set yellow alarm */ if ((j) && (!tor->spans[i].alarms)) { if (tor->cardtype == TYPE_E1) t1out(tor,i + 1,0x21,0x7f); else t1out(tor,i + 1,0x35,0x11); } if (c & 4) /* if yellow alarm */ j |= ZT_ALARM_YELLOW; if (tor->spans[i].maintstat || tor->spans[i].mainttimer) j |= ZT_ALARM_LOOPBACK; tor->spans[i].alarms = j; c = (LEDRED | LEDGREEN) << (2 * i); tor->leds &= ~c; /* mask out bits for this span */ /* light LED's if span configured and running */ if (tor->spans[i].flags & ZT_FLAG_RUNNING) { if (j & ZT_ALARM_RED) tor->leds |= LEDRED << (2 * i); else if (j & ZT_ALARM_YELLOW) tor->leds |= (LEDRED | LEDGREEN) << (2 * i); else tor->leds |= LEDGREEN << (2 * i); } tor->mem8[LEDREG] = tor->leds; zt_alarm_notify(&tor->spans[i]); } if (!(tor->passno % 1000)) /* even second boundary */ { /* do all spans */ for (i = 1; i <= SPANS_PER_CARD; i++) { if (tor->cardtype == TYPE_E1) { /* add this second's BPV count to total one */ tor->spans[i - 1].bpvcount += t1in(tor,i,1) + (t1in(tor,i,0) << 8); if (tor->spans[i - 1].lineconfig & ZT_CONFIG_CRC4) { tor->spans[i - 1].crc4count += t1in(tor,i,3) + ((t1in(tor,i,2) & 3) << 8); tor->spans[i - 1].ebitcount += t1in(tor,i,5) + ((t1in(tor,i,4) & 3) << 8); } tor->spans[i - 1].fascount += (t1in(tor,i,4) >> 2) + ((t1in(tor,i,2) & 0x3F) << 6); } else { /* add this second's BPV count to total one */ tor->spans[i - 1].bpvcount += t1in(tor,i,0x24) + (t1in(tor,i,0x23) << 8); } } } if (!timingcable) { /* re-evaluate active sync src (no cable version) */ tor->syncsrc = 0; syncsrc = 0; /* if primary sync specified, see if we can use it */ if (tor->psyncs[0]) { /* if no alarms, use it */ if (!(tor->spans[tor->psyncs[0] - 1].alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_LOOPBACK))) { tor->syncsrc = tor->psyncs[0]; syncsrc = tor->syncs[0]; } } /* if any others specified, see if we can use them */ for (i = 1; i < SPANS_PER_CARD; i++) { /* if we dont have one yet, and there is one specified at this level, see if we can use it */ if ((!tor->syncsrc) && (tor->psyncs[i])) { /* if no alarms, use it */ if (!(tor->spans[tor->psyncs[i] - 1].alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_LOOPBACK))) { tor->syncsrc = tor->psyncs[i]; syncsrc = tor->syncs[i]; } } } /* update sync src info */ for (i = 0; i < SPANS_PER_CARD; i++) tor->spans[i].syncsrc = syncsrc; /* actually set the sync register */ tor->mem8[SYNCREG] = tor->syncsrc; } else /* Timing cable version */ tor2_findsync(tor); tor->passno++; #ifdef ENABLE_TASKLETS if (!tor->taskletpending) { tor->taskletpending = 1; tor->taskletsched++; tasklet_hi_schedule(&tor->tor2_tlet); } else { tor->txerrors++; } #else tor2_run(tor); #endif /* We are not the timing bus master */ if (tor->cardtype == TYPE_E1) /* clear OUTBIT and enable interrupts */ tor->mem8[CTLREG] = INTENA | E1DIV | tor->master; else /* clear OUTBIT and enable interrupts */ tor->mem8[CTLREG] = INTENA | tor->master; #ifdef LINUX26 return IRQ_RETVAL(1); #endif } static int tor2_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data) { switch(cmd) { default: return -ENOTTY; } return 0; } MODULE_AUTHOR("Mark Spencer"); MODULE_DESCRIPTION("Tormenta 2 PCI Quad T1 or E1 Zaptel Driver"); #ifdef MODULE_LICENSE MODULE_LICENSE("GPL"); #endif #ifdef LINUX26 module_param(debug, int, 0600); module_param(loopback, int, 0600); module_param(timingcable, int, 0600); module_param(japan, int, 0600); #else MODULE_PARM(debug, "i"); MODULE_PARM(loopback, "i"); MODULE_PARM(timingcable, "i"); MODULE_PARM(japan, "i"); #endif MODULE_DEVICE_TABLE(pci, tor2_pci_ids); module_init(tor2_init); module_exit(tor2_cleanup); zaptel-1.4.11/kernel/wctdm.h0000644000000000000000000000351410751714440014350 0ustar rootroot/* * Wilcard S100P FXS Interface Driver for Zapata Telephony interface * * Written by Mark Spencer * * Copyright (C) 2001, Linux Support Services, 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. * */ #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 (ZT_CODE, 60, struct wctdm_stats) #define WCTDM_GET_REGS _IOR (ZT_CODE, 61, struct wctdm_regs) #define WCTDM_SET_REG _IOW (ZT_CODE, 62, struct wctdm_regop) #define WCTDM_SET_ECHOTUNE _IOW (ZT_CODE, 63, struct wctdm_echo_coefs) #endif /* _WCTDM_H */ zaptel-1.4.11/kernel/torisa.c0000644000000000000000000010050710761356330014527 0ustar rootroot/* * Zapata Telephony "Tormenta" ISA card LINUX driver, version 2.2 11/29/01 * * 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. * * Modified from original tor.c by Mark Spencer * original by Jim Dixon */ #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) #include #endif #include #include #include #include #include #include #include #include #ifdef STANDALONE_ZAPATA #include "zaptel.h" #else #include #endif #ifdef LINUX26 #include #endif /* Board address offsets (specified in word (not byte) offsets) */ #define DDATA 0 /* Data I/O Register */ #define DADDR 0x100 /* Dallas Card Address Reg., 0x200 in byte offset higher */ #define CTLREG 0x100 /* Control/Status Reg., 0x200 in byte offset */ /* Control register bits */ #define OUTBIT 8 /* Status output bit (for external measurements) */ #define INTENA 4 /* Interrupt enable bit */ #define MASTERVAL 0x41 /* Enable E1 master clock on Rev. B board */ #define ENA16 0x80 /* 16 bit bus cycle enable bit */ #define TYPE_T1 1 /* is a T1 card */ #define TYPE_E1 2 /* is an E1 card */ #define E1SYNCSTABLETHRESH 15000 /* amount of samples needed for E1 Sync stability */ static int syncsrc; static int syncs[2]; static int debug; #define MASTERCLOCK (*clockvals) /* value for master clock */ /* clock values */ static u_char clockvals_t1[] = {MASTERVAL,0x12,0x22,MASTERVAL}; static u_char clockvals_e1[] = {MASTERVAL,0x13,0x23,MASTERVAL}; static u_char *clockvals; /* translations of data channels for 24 channels in a 32 bit PCM highway */ unsigned datxlt_t1[] = { 0, 1 ,2 ,3 ,5 ,6 ,7 ,9 ,10,11,13,14,15,17,18,19,21,22,23,25,26,27,29,30,31 }; /* translations of data channels for 30/31 channels in a 32 bit PCM highway */ unsigned datxlt_e1[] = { 0, 1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24, 25,26,27,28,29,30,31 }; unsigned int *datxlt; /* This is the order that the data (audio) channels get scanned in. This was done in this rather poopy manner because when outputting (and inputting) a sine wave, such as in the case of TDD, any repeated samples (because of PCM bus contention) will result in nasty-sounding distortion. The Mitel STPA chips (MT8920) have a contention mechanism, which results in a situation where, if the processor accesses a timeslot that is currently being transmitted or received, it will HOLD the bus until it is done with the timeslot. This means that there can be cases where we are trying to write to a timeslot, and its already outputting the same value as the last one (since we didnt get there in time), and in a sine-wave output, distortion will occur. In any other output, it will be utterly un-noticeable. So, what we do is use a pattern that gives us the most flexibility in how long our interrupt latency is (note: Even with this, our interrupt latency must be between 4 and 28 microseconds!!!) Essentially we receive the interrupt just after the 24th channel is read. It will take us AT LEAST 30 microseconds to read it, but could take as much as 35 microseconds to read all the channels. In any case it's the very first thing we do in the interrupt handler. Worst case (30 microseconds) is that the MT8920 has only moved 7 channels. That's where the 6 comes from. */ static int chseq_t1[] = { 6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,1,2,3,4,5 } ; static int chseq_e1[] = { 6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,1,2,3,4,5 } ; static int *chseq; struct torisa_pvt { int span; }; static struct zt_span spans[2]; static struct zt_chan chans[64]; static struct torisa_pvt pvts[64]; static u_char txsigs[2][16]; static int loopupcnt[2]; static int loopdowncnt[2]; static int alarmtimer[2]; static int channels_per_span = 24; static int card_type = TYPE_T1; static int prefmaster = 0; static int spansstarted = 0; #ifdef DEFINE_RWLOCK static DEFINE_RWLOCK(torisa); #else static rwlock_t torisa = RW_LOCK_UNLOCKED; #endif static u_char readdata[2][64][ZT_MAX_CHUNKSIZE]; static u_char writedata[2][64][ZT_MAX_CHUNKSIZE]; static u_char last_ecwrite[2][32]; static int curread; static unsigned long base; volatile static unsigned short *maddr; static int irq; static unsigned int irqcount = 0; static unsigned int taskletsched = 0; static unsigned int taskletrun = 0; static unsigned int taskletexec = 0; /* set the control register */ static void setctlreg(unsigned char val) { volatile register char *cp; cp = (char *) &maddr[CTLREG]; *cp = val; } /* output a byte to one of the registers in one of the Dallas T-1 chips */ static void t1out(int spanno, int loc, unsigned char val) { register int n; volatile register char *cp; /* get the memory offset */ n = spanno << 9; /* point a char * at the address location */ cp = (char *) &maddr[DADDR + n]; *cp = loc; /* set address in T1 chip */ /* point a char * at the data location */ cp = (char *) &maddr[DDATA + n]; *cp = val; /* out the value */ } /* get a byte from one of the registers in one of the Dallas T-1 chips */ static unsigned char t1in(int spanno, int loc) { register int n; volatile register char *cp; /* get the memory offset */ n = spanno << 9; /* point a char * at the address location */ cp = (char *) &maddr[DADDR + n]; *cp = loc; /* set address in T1 chip */ cp = (char *) &maddr[DDATA + n]; /* point a char * at the data location */ return(*cp); } /* get input from the status register */ static unsigned char getctlreg(void) { register char *cp; cp = (char *) &maddr[CTLREG]; return(*cp); } static void set_clear(void) { int i,j,s; unsigned short val=0; for (s=0;s<2;s++) { for (i=0;ipvt; unsigned long flags; #if 0 printk("Setting bits to %x hex on channel %s\n", bits, chan->name); #endif if (card_type == TYPE_E1) { /* do it E1 way */ if (chan->chanpos > 30) return 0; /* cant do this for chan 31 */ n = chan->chanpos - 1; k = p->span; b = (n % 15) + 1; c = txsigs[k][b]; m = (n / 15) * 4; /* nibble selector */ c &= (15 << m); /* keep the other nibble */ c |= (bits & 15) << (4 - m); /* put our new nibble here */ txsigs[k][b] = c; /* output them into the chip */ t1out(k + 1,0x40 + b,c); return 0; } n = chan->chanpos - 1; k = p->span; b = (n / 8); /* get byte number */ m = 1 << (n & 7); /* get mask */ c = txsigs[k][b]; c &= ~m; /* clear mask bit */ /* set mask bit, if bit is to be set */ if (bits & ZT_ABIT) c |= m; txsigs[k][b] = c; write_lock_irqsave(&torisa, flags); t1out(k + 1,0x70 + b,c); b += 3; /* now points to b bit stuff */ /* get current signalling values */ c = txsigs[k][b]; c &= ~m; /* clear mask bit */ /* set mask bit, if bit is to be set */ if (bits & ZT_BBIT) c |= m; /* save new signalling values */ txsigs[k][b] = c; /* output them into the chip */ t1out(k + 1,0x70 + b,c); b += 3; /* now points to c bit stuff */ /* get current signalling values */ c = txsigs[k][b]; c &= ~m; /* clear mask bit */ /* set mask bit, if bit is to be set */ if (bits & ZT_CBIT) c |= m; /* save new signalling values */ txsigs[k][b] = c; /* output them into the chip */ t1out(k + 1,0x70 + b,c); b += 3; /* now points to d bit stuff */ /* get current signalling values */ c = txsigs[k][b]; c &= ~m; /* clear mask bit */ /* set mask bit, if bit is to be set */ if (bits & ZT_DBIT) c |= m; /* save new signalling values */ txsigs[k][b] = c; /* output them into the chip */ t1out(k + 1,0x70 + b,c); write_unlock_irqrestore(&torisa, flags); return 0; } static inline int getspan(struct zt_span *span) { if (span == spans) return 1; if (span == spans + 1) return 2; return -1; } static int torisa_shutdown(struct zt_span *span) { int i; int tspan; int wasrunning; unsigned long flags; tspan = getspan(span); if (tspan < 0) { printk("TorISA: Span '%d' isn't us?\n", span->spanno); return -1; } write_lock_irqsave(&torisa, flags); wasrunning = span->flags & ZT_FLAG_RUNNING; span->flags &= ~ZT_FLAG_RUNNING; /* Zero out all registers */ for (i = 0; i< 0xff; i++) t1out(tspan, i, 0); if (wasrunning) spansstarted--; write_unlock_irqrestore(&torisa, flags); if (!spans[0].flags & ZT_FLAG_RUNNING && !spans[1].flags & ZT_FLAG_RUNNING) /* No longer in use, disable interrupts */ setctlreg(clockvals[syncsrc]); if (debug) printk("Span %d (%s) shutdown\n", span->spanno, span->name); return 0; } static int torisa_startup(struct zt_span *span) { unsigned long endjif; int i; int tspan; unsigned long flags; char *coding; char *framing; char *crcing; int alreadyrunning; tspan = getspan(span); if (tspan < 0) { printk("TorISA: Span '%d' isn't us?\n", span->spanno); return -1; } write_lock_irqsave(&torisa, flags); alreadyrunning = span->flags & ZT_FLAG_RUNNING; /* initialize the start value for the last ec buffer */ for(i = 0; i < span->channels; i++) { last_ecwrite[tspan - 1][i] = ZT_LIN2X(0,&span->chans[i]); } crcing = ""; if (card_type == TYPE_T1) { /* if its a T1 card */ if (!alreadyrunning) { setctlreg(MASTERCLOCK); /* Zero out all registers */ for (i = 0x20; i< 0x40; i++) t1out(tspan, i, 0); for (i = 0x60; i< 0x80; i++) t1out(tspan, i, 0); /* Full-on Sync required (RCR1) */ t1out(tspan, 0x2b, 8); /* RSYNC is an input (RCR2) */ t1out(tspan, 0x2c, 8); /* RBS enable (TCR1) */ t1out(tspan, 0x35, 0x10); /* TSYNC to be output (TCR2) */ t1out(tspan, 0x36, 4); /* Tx & Rx Elastic store, sysclk = 2.048 mhz, loopback controls (CCR1) */ t1out(tspan, 0x37, 0x8c); } /* Enable F bits pattern */ i = 0x20; if (span->lineconfig & ZT_CONFIG_ESF) i = 0x88; if (span->lineconfig & ZT_CONFIG_B8ZS) i |= 0x44; t1out(tspan, 0x38, i); if (i & 0x80) coding = "ESF"; else coding = "SF"; if (i & 0x40) framing = "B8ZS"; else { framing = "AMI"; t1out(tspan,0x7e,0x1c); /* F bits pattern (0x1c) into FDL register */ } t1out(tspan, 0x7c, span->txlevel << 5); if (!alreadyrunning) { /* LIRST to 1 in CCR3 */ t1out(tspan, 0x30, 1); /* Wait 100 ms */ endjif = jiffies + 10; write_unlock_irqrestore(&torisa, flags); while(jiffies < endjif); /* wait 100 ms */ write_lock_irqsave(&torisa, flags); t1out(tspan,0x30,0x40); /* set CCR3 to 0x40, resetting Elastic Store */ span->flags |= ZT_FLAG_RUNNING; spansstarted++; #if 0 printk("Enabling interrupts: %d\n", clockvals[syncsrc] | INTENA); #endif /* output the clock info and enable interrupts */ setctlreg(clockvals[syncsrc] | INTENA); } set_clear(); /* this only applies to a T1 */ } else { /* if its an E1 card */ u_char ccr1 = 0, tcr1 = 0; if (!alreadyrunning) { t1out(tspan,0x1a,4); /* CCR2: set LOTCMC */ for(i = 0; i <= 8; i++) t1out(tspan,i,0); for(i = 0x10; i <= 0x4f; i++) if (i != 0x1a) t1out(tspan,i,0); t1out(tspan,0x10,0x20); /* RCR1: Rsync as input */ t1out(tspan,0x11,6); /* RCR2: Sysclk=2.048 Mhz */ t1out(tspan,0x12,8); /* TCR1: TSiS mode */ } tcr1 = 8; /* base TCR1 value: TSis mode */ if (span->lineconfig & ZT_CONFIG_CCS) { ccr1 |= 8; /* CCR1: Rx Sig mode: CCS */ coding = "CCS"; } else { tcr1 |= 0x20; coding = "CAS"; } if (span->lineconfig & ZT_CONFIG_HDB3) { ccr1 |= 0x44; /* CCR1: TX and RX HDB3 */ framing = "HDB3"; } else framing = "AMI"; if (span->lineconfig & ZT_CONFIG_CRC4) { ccr1 |= 0x11; /* CCR1: TX and TX CRC4 */ crcing = "/CRC4"; } t1out(tspan,0x12,tcr1); t1out(tspan,0x14,ccr1); t1out(tspan, 0x18, 0x80); if (!alreadyrunning) { t1out(tspan,0x1b,0x8a); /* CCR3: LIRST & TSCLKM */ t1out(tspan,0x20,0x1b); /* TAFR */ t1out(tspan,0x21,0x5f); /* TNAFR */ t1out(tspan,0x40,0xb); /* TSR1 */ for(i = 0x41; i <= 0x4f; i++) t1out(tspan,i,0x55); for(i = 0x22; i <= 0x25; i++) t1out(tspan,i,0xff); /* Wait 100 ms */ endjif = jiffies + 10; write_unlock_irqrestore(&torisa, flags); while(jiffies < endjif); /* wait 100 ms */ write_lock_irqsave(&torisa, flags); t1out(tspan,0x1b,0x9a); /* CCR3: set also ESR */ t1out(tspan,0x1b,0x82); /* CCR3: TSCLKM only now */ /* output the clock info and enable interrupts */ setctlreg(clockvals[syncsrc] | INTENA); } } write_unlock_irqrestore(&torisa, flags); if (debug) { if (card_type == TYPE_T1) { if (alreadyrunning) printk("TorISA: Reconfigured span %d (%s/%s) LBO: %s\n", span->spanno, coding, framing, zt_lboname(span->txlevel)); else printk("TorISA: Startup span %d (%s/%s) LBO: %s\n", span->spanno, coding, framing, zt_lboname(span->txlevel)); } else { if (alreadyrunning) printk("TorISA: Reconfigured span %d (%s/%s%s) 120 ohms\n", span->spanno, coding, framing, crcing); else printk("TorISA: Startup span %d (%s/%s%s) 120 ohms\n", span->spanno, coding, framing, crcing); } } if (syncs[0] == span->spanno) printk("SPAN %d: Primary Sync Source\n",span->spanno); if (syncs[1] == span->spanno) printk("SPAN %d: Secondary Sync Source\n",span->spanno); return 0; } static int torisa_spanconfig(struct zt_span *span, struct zt_lineconfig *lc) { if (debug) printk("TorISA: Configuring span %d\n", span->spanno); span->syncsrc = syncsrc; /* remove this span number from the current sync sources, if there */ if (syncs[0] == span->spanno) syncs[0] = 0; if (syncs[1] == span->spanno) syncs[1] = 0; /* if a sync src, put it in proper place */ if (lc->sync) syncs[lc->sync - 1] = span->spanno; /* If we're already running, then go ahead and apply the changes */ if (span->flags & ZT_FLAG_RUNNING) return torisa_startup(span); return 0; } static int torisa_chanconfig(struct zt_chan *chan, int sigtype) { int alreadyrunning; unsigned long flags; alreadyrunning = chan->span->flags & ZT_FLAG_RUNNING; if (debug) { if (alreadyrunning) printk("TorISA: Reconfigured channel %d (%s) sigtype %d\n", chan->channo, chan->name, sigtype); else printk("TorISA: Configured channel %d (%s) sigtype %d\n", chan->channo, chan->name, sigtype); } write_lock_irqsave(&torisa, flags); if (alreadyrunning && (card_type == TYPE_T1)) set_clear(); write_unlock_irqrestore(&torisa, flags); return 0; } static int torisa_open(struct zt_chan *chan) { #ifndef LINUX26 MOD_INC_USE_COUNT; #endif return 0; } static int torisa_close(struct zt_chan *chan) { #ifndef LINUX26 MOD_DEC_USE_COUNT; #endif return 0; } static int torisa_maint(struct zt_span *span, int cmd) { int tspan = getspan(span); switch(cmd) { case ZT_MAINT_NONE: t1out(tspan,0x1a,4); /* clear system */ break; case ZT_MAINT_LOCALLOOP: t1out(tspan,0x1a,5); /* local loopback */ break; case ZT_MAINT_REMOTELOOP: t1out(tspan,0x37,6); /* remote loopback */ break; case ZT_MAINT_LOOPUP: if (card_type == TYPE_E1) return -ENOSYS; t1out(tspan,0x30,2); /* send loopup code */ break; case ZT_MAINT_LOOPDOWN: if (card_type == TYPE_E1) return -ENOSYS; t1out(tspan,0x30,4); /* send loopdown code */ break; case ZT_MAINT_LOOPSTOP: if (card_type == TYPE_T1) t1out(tspan,0x30,0); /* stop sending loopup code */ break; default: printk("torisa: Unknown maint command: %d\n", cmd); break; } return 0; } static int taskletpending; static struct tasklet_struct torisa_tlet; static void torisa_tasklet(unsigned long data) { int x,y; u_char mychunk[2][ZT_CHUNKSIZE]; taskletrun++; if (taskletpending) { taskletexec++; /* Perform receive data calculations. Reverse to run most likely master last */ if (spans[1].flags & ZT_FLAG_RUNNING) { /* Perform echo cancellation */ for (x=0;x> (j * 8)) & 0xff; readdata[curread][j * channels_per_span + n - 1][passno % ZT_CHUNKSIZE] = rxc; } } i = passno & 127; /* if an E1 card, do rx signalling for it */ if (i < 3 && (card_type == TYPE_E1)) { /* if an E1 card */ for(j = (i * 3); j < (i * 3) + 5; j++) { for(k = 1,x = j; k <= 2; k++,x += channels_per_span) { c = t1in(k,0x31 + j); rxc = c & 15; if (rxc != chans[x + 15].rxsig) { /* Check for changes in received bits */ if (!(chans[x + 15].sig & ZT_SIG_CLEAR)) zt_rbsbits(&chans[x + 15], rxc); } rxc = c >> 4; if (rxc != chans[x].rxsig) { /* Check for changes in received bits */ if (!(chans[x].sig & ZT_SIG_CLEAR)) zt_rbsbits(&chans[x], rxc); } } } } /* if a t1 card, do rx signalling for it */ if ((i < 6) && (card_type == TYPE_T1)) { k = (i / 3); /* get span */ n = (i % 3); /* get base */ abits = t1in(k + 1, 0x60 + n); bbits = t1in(k + 1, 0x63 + n); cbits = t1in(k + 1, 0x66 + n); dbits = t1in(k + 1, 0x69 + n); for (j=0; j< 8; j++) { /* Get channel number */ i = (k * 24) + (n * 8) + j; rxc = 0; if (abits & (1 << j)) rxc |= ZT_ABIT; if (bbits & (1 << j)) rxc |= ZT_BBIT; if (cbits & (1 << j)) rxc |= ZT_CBIT; if (dbits & (1 << j)) rxc |= ZT_DBIT; if (chans[i].rxsig != rxc) { /* Check for changes in received bits */ if (!(chans[i].sig & ZT_SIG_CLEAR)) zt_rbsbits(&chans[i], rxc); } } } if (!(passno & 0x7)) { for(i = 0; i < 2; i++) { /* if alarm timer, and it's timed out */ if (alarmtimer[i]) { if (!--alarmtimer[i]) { /* clear recover status */ spans[i].alarms &= ~ZT_ALARM_RECOVER; if (card_type == TYPE_T1) t1out(i + 1,0x35,0x10); /* turn off yel */ else t1out(i + 1,0x21,0x5f); /* turn off remote alarm */ zt_alarm_notify(&spans[i]); /* let them know */ } } } } i = passno & 511; if ((i == 100) || (i == 101)) { j = 0; /* clear this alarm status */ i -= 100; if (card_type == TYPE_T1) { c = t1in(i + 1,0x31); /* get RIR2 */ spans[i].rxlevel = c >> 6; /* get rx level */ t1out(i + 1,0x20,0xff); c = t1in(i + 1,0x20); /* get the status */ /* detect the code, only if we are not sending one */ if ((!spans[i].mainttimer) && (c & 0x80)) /* if loop-up code detected */ { /* set into remote loop, if not there already */ if ((loopupcnt[i]++ > 80) && (spans[i].maintstat != ZT_MAINT_REMOTELOOP)) { t1out(i + 1,0x37,0x9c); /* remote loopback */ spans[i].maintstat = ZT_MAINT_REMOTELOOP; } } else loopupcnt[i] = 0; /* detect the code, only if we are not sending one */ if ((!spans[i].mainttimer) && (c & 0x40)) /* if loop-down code detected */ { /* if in remote loop, get out of it */ if ((loopdowncnt[i]++ > 80) && (spans[i].maintstat == ZT_MAINT_REMOTELOOP)) { t1out(i + 1,0x37,0x8c); /* normal */ spans[i].maintstat = ZT_MAINT_NONE; } } else loopdowncnt[i] = 0; if (c & 3) /* if red alarm */ { j |= ZT_ALARM_RED; } if (c & 8) /* if blue alarm */ { j |= ZT_ALARM_BLUE; } } else { /* its an E1 card */ t1out(i + 1,6,0xff); c = t1in(i + 1,6); /* get the status */ if (c & 9) /* if red alarm */ { j |= ZT_ALARM_RED; } if (c & 2) /* if blue alarm */ { j |= ZT_ALARM_BLUE; } } /* only consider previous carrier alarm state */ spans[i].alarms &= (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_NOTOPEN); n = 1; /* set to 1 so will not be in yellow alarm if we dont care about open channels */ /* if to have yellow alarm if nothing open */ if (spans[i].lineconfig & ZT_CONFIG_NOTOPEN) { /* go thru all chans, and count # open */ for(n = 0,k = (i * channels_per_span); k < (i * channels_per_span) + channels_per_span; k++) { if ((chans[k].flags & ZT_FLAG_OPEN) || (chans[k].flags & ZT_FLAG_NETDEV)) n++; } /* if none open, set alarm condition */ if (!n) j |= ZT_ALARM_NOTOPEN; } /* if no more alarms, and we had some */ if ((!j) && spans[i].alarms) { alarmtimer[i] = ZT_ALARMSETTLE_TIME; } if (alarmtimer[i]) j |= ZT_ALARM_RECOVER; /* if going into alarm state, set yellow (remote) alarm */ if ((j) && (!spans[i].alarms)) { if (card_type == TYPE_T1) t1out(i + 1,0x35,0x11); else t1out(i + 1,0x21,0x7f); } if (c & 4) /* if yellow alarm */ j |= ZT_ALARM_YELLOW; if (spans[i].maintstat || spans[i].mainttimer) j |= ZT_ALARM_LOOPBACK; spans[i].alarms = j; zt_alarm_notify(&spans[i]); } if (!(passno % 8000)) /* even second boundary */ { /* do both spans */ for(i = 1; i <= 2; i++) { if (card_type == TYPE_T1) { /* add this second's BPV count to total one */ spans[i - 1].bpvcount += t1in(i,0x24) + (t1in(i,0x23) << 8); } else { /* add this second's BPV count to total one */ spans[i - 1].bpvcount += t1in(i,1) + (t1in(i,0) << 8); } } } /* re-evaluate active sync src */ mysyncsrc = 0; /* if primary sync specified, see if we can use it */ if (syncs[0]) { /* if no alarms, use it */ if (!(spans[syncs[0] - 1].alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_LOOPBACK))) mysyncsrc = syncs[0]; } /* if we dont have one yet, and there is a secondary, see if we can use it */ if ((!mysyncsrc) && (syncs[1])) { /* if no alarms, use it */ if (!(spans[syncs[1] - 1].alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_LOOPBACK))) mysyncsrc = syncs[1]; } /* on the E1 card, the PLL takes a bit of time to lock going between internal and external clocking. There needs to be some settle time before actually changing the source, otherwise it will oscillate between in and out of sync */ if (card_type == TYPE_E1) { /* if stable, add to count */ if (lastsyncsrc == mysyncsrc) mysynccnt++; else mysynccnt = 0; lastsyncsrc = mysyncsrc; /* if stable sufficiently long, change it */ if (mysynccnt >= E1SYNCSTABLETHRESH) { mysynccnt = 0; syncsrc = mysyncsrc; } } else syncsrc = mysyncsrc; /* otherwise on a T1 card, just use current value */ /* update sync src info */ spans[0].syncsrc = spans[1].syncsrc = syncsrc; /* If this is the last pass, then prepare the next set */ /* clear outbit, restore interrupt enable */ setctlreg(clockvals[syncsrc] | INTENA); #ifdef LINUX26 return IRQ_RETVAL(1); #endif } static int torisa_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data) { struct torisa_debug td; switch(cmd) { case TORISA_GETDEBUG: td.txerrors = txerrors; td.irqcount = irqcount; td.taskletsched = taskletsched; td.taskletrun = taskletrun; td.taskletexec = taskletexec; td.span1flags = spans[0].flags; td.span2flags = spans[1].flags; if (copy_to_user((struct torisa_debug *)data, &td, sizeof(td))) return -EFAULT; return 0; default: return -ENOTTY; } return 0; } static int __init tor_init(void) { if (!base) { printk("Specify address with base=0xNNNNN\n"); return -EIO; } if (tor_probe()) { printk(KERN_ERR "No ISA tormenta card found at %05lx\n", base); return -EIO; } if (request_irq(irq, torisa_intr, ZAP_IRQ_DISABLED, "torisa", NULL)) { printk(KERN_ERR "Unable to request tormenta IRQ %d\n", irq); return -EIO; } if (!request_mem_region(base, 4096, "Tormenta ISA")) { printk(KERN_ERR "Unable to request 4k memory window at %lx\n", base); free_irq(irq, NULL); return -EIO; } strcpy(spans[0].name, "TorISA/1"); zap_copy_string(spans[0].desc, "ISA Tormenta Span 1", sizeof(spans[0].desc)); spans[0].manufacturer = "Digium"; zap_copy_string(spans[0].devicetype, "Tormenta ISA", sizeof(spans[0].devicetype)); spans[0].spanconfig = torisa_spanconfig; spans[0].chanconfig = torisa_chanconfig; spans[0].startup = torisa_startup; spans[0].shutdown = torisa_shutdown; spans[0].rbsbits = torisa_rbsbits; spans[0].maint = torisa_maint; spans[0].open = torisa_open; spans[0].close = torisa_close; spans[0].channels = channels_per_span; spans[0].chans = &chans[0]; spans[0].flags = ZT_FLAG_RBS; spans[0].ioctl = torisa_ioctl; spans[0].irq = irq; if (card_type == TYPE_E1) { spans[0].spantype = "E1"; spans[0].linecompat = ZT_CONFIG_AMI | ZT_CONFIG_B8ZS | ZT_CONFIG_D4 | ZT_CONFIG_ESF; spans[0].deflaw = ZT_LAW_ALAW; } else { spans[0].spantype = "T1"; spans[0].linecompat = ZT_CONFIG_HDB3 | ZT_CONFIG_CCS | ZT_CONFIG_CRC4; spans[0].deflaw = ZT_LAW_MULAW; } spans[1] = spans[0]; strcpy(spans[1].name, "TorISA/2"); strcpy(spans[1].desc, "ISA Tormenta Span 2"); spans[1].chans = &chans[channels_per_span]; init_waitqueue_head(&spans[0].maintq); init_waitqueue_head(&spans[1].maintq); make_chans(); if (zt_register(&spans[0], prefmaster)) { printk(KERN_ERR "Unable to register span %s\n", spans[0].name); return -EIO; } if (zt_register(&spans[1], 0)) { printk(KERN_ERR "Unable to register span %s\n", spans[1].name); zt_unregister(&spans[0]); return -EIO; } tasklet_init(&torisa_tlet, torisa_tasklet, (long)0); printk("TORISA Loaded\n"); return 0; } #if !defined(LINUX26) static int __init set_tor_base(char *str) { base = simple_strtol(str, NULL, 0); return 1; } __setup("tor=", set_tor_base); #endif static void __exit tor_exit(void) { free_irq(irq, NULL); release_mem_region(base, 4096); if (spans[0].flags & ZT_FLAG_REGISTERED) zt_unregister(&spans[0]); if (spans[1].flags & ZT_FLAG_REGISTERED) zt_unregister(&spans[1]); } MODULE_AUTHOR("Mark Spencer "); MODULE_DESCRIPTION("Tormenta ISA Zapata Telephony Driver"); #ifdef MODULE_LICENSE MODULE_LICENSE("GPL"); #endif #ifdef LINUX26 module_param(prefmaster, int, 0600); module_param(base, long, 0600); module_param(irq, int, 0600); module_param(syncsrc, int, 0600); module_param(debug, int, 0600); #else MODULE_PARM(prefmaster, "i"); MODULE_PARM(base, "i"); MODULE_PARM(irq, "i"); MODULE_PARM(syncsrc, "i"); MODULE_PARM(debug, "i"); #endif module_init(tor_init); module_exit(tor_exit); zaptel-1.4.11/kernel/arith.h0000644000000000000000000001745710751714440014354 0ustar rootroot#ifndef _ZAPTEL_ARITH_H #define _ZAPTEL_ARITH_H /* * Handy add/subtract functions to operate on chunks of shorts. * Feel free to add customizations for additional architectures * */ #ifdef CONFIG_ZAPTEL_MMX #ifdef ZT_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 (ZT_CHUNKSIZE == 8) #define ACSS(a,b) __ACSS(a,b) #define SCSS(a,b) __SCSS(a,b) #elif (ZT_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 < ZT_CHUNKSIZE; x++) dst[x] = __builtin_bfin_sub_fr1x16(dst[x], src[x]); #else int sum; for (x = 0; x < ZT_CHUNKSIZE; x++) { sum = dst[x] - src[x]; if (sum > 32767) sum = 32767; else if (sum < -32768) sum = -32768; dst[x] = sum; } #endif } #endif /* ZT_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 * * Adapted from the wctdm24xxp and wcte11xp drivers originally * written by Mark Spencer * Matthew Fredrickson * William Meadows * * Copyright (C) 2007, 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 "zaptel.h" #include "voicebus.h" #include "wcte12xp.h" #include "vpmadt032.h" #include "GpakApi.h" extern struct t1 *ifaces[WC_MAX_IFACES]; extern int vpmnlptype; extern int vpmnlpthresh; extern int vpmnlpmaxsupp; #ifdef VPM_SUPPORT inline void vpm150m_cmd_dequeue(struct t1 *wc, volatile unsigned char *writechunk, int whichframe) { struct vpm150m_cmd *curcmd = NULL; struct vpm150m *vpm150m = wc->vpm150m; int x; unsigned char leds = ~((wc->intcount / 1000) % 8) & 0x7; /* Skip audio */ writechunk += 66; if (test_bit(VPM150M_SPIRESET, &vpm150m->control) || test_bit(VPM150M_HPIRESET, &vpm150m->control)) { debug_printk(1, "HW Resetting VPMADT032 ...\n"); for (x = 0; x < 4; x++) { if (!x) { if (test_and_clear_bit(VPM150M_SPIRESET, &vpm150m->control)) writechunk[CMD_BYTE(x, 0, 1)] = 0x08; else if (test_and_clear_bit(VPM150M_HPIRESET, &vpm150m->control)) writechunk[CMD_BYTE(x, 0, 1)] = 0x0b; } else writechunk[CMD_BYTE(x, 0, 1)] = 0x00 | leds; writechunk[CMD_BYTE(x, 1, 1)] = 0; writechunk[CMD_BYTE(x, 2, 1)] = 0x00; } return; } /* Search for something waiting to transmit */ for (x = 0; x < VPM150M_MAX_COMMANDS; x++) { if ((vpm150m->cmdq[x].flags & (__VPM150M_RD | __VPM150M_WR)) && !(vpm150m->cmdq[x].flags & (__VPM150M_FIN | __VPM150M_TX))) { curcmd = &vpm150m->cmdq[x]; curcmd->ident = wc->txident; curcmd->flags |= __VPM150M_TX; break; } } if (curcmd) { #if 0 printk("Found command txident = %d, desc = 0x%x, addr = 0x%x, data = 0x%x\n", curcmd->txident, curcmd->desc, curcmd->addr, curcmd->data); #endif if (curcmd->flags & __VPM150M_RWPAGE) { /* Set CTRL access to page*/ writechunk[CMD_BYTE(0, 0, 1)] = (0x8 << 4); writechunk[CMD_BYTE(0, 1, 1)] = 0; writechunk[CMD_BYTE(0, 2, 1)] = 0x20; /* Do a page write */ if (curcmd->flags & __VPM150M_WR) writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | 0x4) << 4); else writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | 0x4 | 0x1) << 4); writechunk[CMD_BYTE(1, 1, 1)] = 0; if (curcmd->flags & __VPM150M_WR) writechunk[CMD_BYTE(1, 2, 1)] = curcmd->data[0] & 0xf; else writechunk[CMD_BYTE(1, 2, 1)] = 0; if (curcmd->flags & __VPM150M_WR) { /* Fill in buffer to size */ writechunk[CMD_BYTE(2, 0, 1)] = 0; writechunk[CMD_BYTE(2, 1, 1)] = 0; writechunk[CMD_BYTE(2, 2, 1)] = 0; } else { /* Do reads twice b/c of vpmadt032 bug */ writechunk[CMD_BYTE(2, 0, 1)] = ((0x8 | 0x4 | 0x1) << 4); writechunk[CMD_BYTE(2, 1, 1)] = 0; writechunk[CMD_BYTE(2, 2, 1)] = 0; } /* Clear XADD */ writechunk[CMD_BYTE(3, 0, 1)] = (0x8 << 4); writechunk[CMD_BYTE(3, 1, 1)] = 0; writechunk[CMD_BYTE(3, 2, 1)] = 0; /* Fill in buffer to size */ writechunk[CMD_BYTE(4, 0, 1)] = 0; writechunk[CMD_BYTE(4, 1, 1)] = 0; writechunk[CMD_BYTE(4, 2, 1)] = 0; } else { /* Set address */ writechunk[CMD_BYTE(0, 0, 1)] = ((0x8 | 0x4) << 4); writechunk[CMD_BYTE(0, 1, 1)] = (curcmd->address >> 8) & 0xff; writechunk[CMD_BYTE(0, 2, 1)] = curcmd->address & 0xff; /* Send/Get our data */ if (curcmd->flags & __VPM150M_WR) { if (curcmd->datalen > 1) writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | (0x1 << 1)) << 4); else writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | (0x3 << 1)) << 4); } else if (curcmd->datalen > 1) writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | (0x1 << 1) | 0x1) << 4); else writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | (0x3 << 1) | 0x1) << 4); writechunk[CMD_BYTE(1, 1, 1)] = (curcmd->data[0] >> 8) & 0xff; writechunk[CMD_BYTE(1, 2, 1)] = curcmd->data[0] & 0xff; if (curcmd->flags & __VPM150M_WR) { /* Fill in */ writechunk[CMD_BYTE(2, 0, 1)] = 0; writechunk[CMD_BYTE(2, 1, 1)] = 0; writechunk[CMD_BYTE(2, 2, 1)] = 0; } else { /* Do this again for reads b/c of the bug in vpmadt032 */ writechunk[CMD_BYTE(2, 0, 1)] = ((0x8 | (0x3 << 1) | 0x1) << 4); writechunk[CMD_BYTE(2, 1, 1)] = (curcmd->data[0] >> 8) & 0xff; writechunk[CMD_BYTE(2, 2, 1)] = curcmd->data[0] & 0xff; } if (curcmd->datalen > 1) { if (curcmd->flags & __VPM150M_WR) writechunk[CMD_BYTE(3, 0, 1)] = ((0x8 | (0x1 << 1)) << 4); else writechunk[CMD_BYTE(3, 0, 1)] = ((0x8 | (0x1 << 1) | 0x1) << 4); writechunk[CMD_BYTE(3, 1, 1)] = (curcmd->data[1] >> 8) & 0xff; writechunk[CMD_BYTE(3, 2, 1)] = curcmd->data[1] & 0xff; } else { /* Fill in the rest */ writechunk[CMD_BYTE(3, 0, 1)] = 0; writechunk[CMD_BYTE(3, 1, 1)] = 0; writechunk[CMD_BYTE(3, 2, 1)] = 0; } if (curcmd->datalen > 2) { if (curcmd->flags & __VPM150M_WR) writechunk[CMD_BYTE(4, 0, 1)] = ((0x8 | (0x1 << 1)) << 4); else writechunk[CMD_BYTE(4, 0, 1)] = ((0x8 | (0x1 << 1) | 0x1) << 4); writechunk[CMD_BYTE(4, 1, 1)] = (curcmd->data[2] >> 8) & 0xff; writechunk[CMD_BYTE(4, 2, 1)] = curcmd->data[2] & 0xff; } else { /* Fill in the rest */ writechunk[CMD_BYTE(4, 0, 1)] = 0; writechunk[CMD_BYTE(4, 1, 1)] = 0; writechunk[CMD_BYTE(4, 2, 1)] = 0; } } } else if (test_and_clear_bit(VPM150M_SWRESET, &vpm150m->control)) { debug_printk(1, "Booting VPMADT032\n"); for (x = 0; x < 7; x++) { if (x == 0) writechunk[CMD_BYTE(x, 0, 1)] = (0x8 << 4); else writechunk[CMD_BYTE(x, 0, 1)] = 0x00; writechunk[CMD_BYTE(x, 1, 1)] = 0; if (x == 0) writechunk[CMD_BYTE(x, 2, 1)] = 0x01; else writechunk[CMD_BYTE(x, 2, 1)] = 0x00; } } else { for (x = 0; x < 7; x++) { writechunk[CMD_BYTE(x, 0, 1)] = 0x00; writechunk[CMD_BYTE(x, 1, 1)] = 0x00; writechunk[CMD_BYTE(x, 2, 1)] = 0x00; } } /* Add our leds in */ for (x = 0; x < 7; x++) writechunk[CMD_BYTE(x, 0, 1)] |= leds; #if 0 int y; for (x = 0; x < 7; x++) { for (y = 0; y < 3; y++) { if (writechunk[CMD_BYTE(x, y, 1)] & 0x2) { module_printk("the test bit is high for byte %d\n", y); } } } #endif /* Now let's figure out if we need to check for DTMF */ /* polling */ if (test_bit(VPM150M_ACTIVE, &vpm150m->control) && !whichframe && !(wc->intcount % 100)) queue_work(vpm150m->wq, &vpm150m->work_dtmf); #if 0 /* This may be needed sometime in the future to troubleshoot ADT related issues. */ if (test_bit(VPM150M_ACTIVE, &vpm150m->control) && !whichframe && !(wc->intcount % 10000)) queue_work(vpm150m->wq, &vpm150m->work_debug); #endif } inline void vpm150m_cmd_decipher(struct t1 *wc, volatile unsigned char *readchunk) { unsigned char ident; int x, i; /* Skip audio */ readchunk += 66; /* Search for any pending results */ for (x = 0; x < VPM150M_MAX_COMMANDS; x++) { if ((wc->vpm150m->cmdq[x].flags & (__VPM150M_RD | __VPM150M_WR)) && (wc->vpm150m->cmdq[x].flags & (__VPM150M_TX)) && !(wc->vpm150m->cmdq[x].flags & (__VPM150M_FIN))) { ident = wc->vpm150m->cmdq[x].ident; if (ident == wc->rxident) { /* Store result */ for (i = 0; i < wc->vpm150m->cmdq[x].datalen; i++) { wc->vpm150m->cmdq[x].data[i] = (0xff & readchunk[CMD_BYTE((2 + i), 1, 1)]) << 8; wc->vpm150m->cmdq[x].data[i] |= readchunk[CMD_BYTE((2 + i), 2, 1)]; } if (wc->vpm150m->cmdq[x].flags & __VPM150M_WR) { /* Go ahead and clear out writes since they need no acknowledgement */ wc->vpm150m->cmdq[x].flags = 0; } else wc->vpm150m->cmdq[x].flags |= __VPM150M_FIN; break; } } } } static inline struct t1 * wc_find_iface(unsigned short dspid) { int i; struct t1 *ret = NULL; unsigned long flags; spin_lock_irqsave(&ifacelock, flags); for (i = 0; i < WC_MAX_IFACES; i++) if (ifaces[i] && ifaces[i]->vpm150m && (ifaces[i]->vpm150m->dspid == dspid)) ret = ifaces[i]; spin_unlock_irqrestore(&ifacelock, flags); return ret; } static struct vpm150m_cmd * vpm150m_empty_slot(struct t1 *wc) { unsigned int x; for (x = 0; x < VPM150M_MAX_COMMANDS; x++) { if (!wc->vpm150m->cmdq[x].flags) { return &wc->vpm150m->cmdq[x]; } } return NULL; } /* Wait for any outstanding commands to be completed. */ static inline int vpm150m_io_wait(struct t1 *wc) { int x; int ret=0; for (x=0; x < VPM150M_MAX_COMMANDS;) { if (wc->vpm150m->cmdq[x].flags) { if ((ret=schluffen(&wc->regq))) { return ret; } x=0; } else { ++x; } } return ret; } int t1_vpm150m_getreg_full_async(struct t1 *wc, int pagechange, unsigned int len, unsigned short addr, unsigned short *outbuf, struct vpm150m_cmd **hit_p) { int ret=0; unsigned long flags; BUG_ON(!hit_p); spin_lock_irqsave(&wc->reglock, flags); (*hit_p) = vpm150m_empty_slot(wc); if (*hit_p) { (*hit_p)->flags = __VPM150M_RD; if (pagechange) { (*hit_p)->flags |= __VPM150M_RWPAGE; } (*hit_p)->datalen = len; (*hit_p)->address = addr; memset((*hit_p)->data, 0, len*sizeof(outbuf[0])); } else { ret = -EBUSY; } spin_unlock_irqrestore(&wc->reglock, flags); return ret; } int t1_vpm150m_getreg_full_return(struct t1 *wc, int pagechange, unsigned int len, unsigned short addr, unsigned short *outbuf, struct vpm150m_cmd **hit_p) { int ret = 0; unsigned long flags; BUG_ON(!hit_p); spin_lock_irqsave(&wc->reglock, flags); do { if ((*hit_p)->flags & __VPM150M_FIN) { memcpy(outbuf, (*hit_p)->data, len*(sizeof(outbuf[0]))); (*hit_p)->flags = 0; (*hit_p) = NULL; ret = 0; } else { spin_unlock_irqrestore(&wc->reglock, flags); if ((ret=schluffen(&wc->regq))) { return ret; } spin_lock_irqsave(&wc->reglock, flags); ret = -EBUSY; } } while (-EBUSY == ret); spin_unlock_irqrestore(&wc->reglock, flags); return ret; } int t1_vpm150m_getreg_full(struct t1 *wc, int pagechange, unsigned int len, unsigned short addr, unsigned short *outbuf) { struct vpm150m_cmd *hit = 0; int ret = 0; do { ret = t1_vpm150m_getreg_full_async(wc, pagechange, len, addr, outbuf, &hit); if (!hit) { if ( -EBUSY == ret ) { if ((ret = schluffen(&wc->regq))) return ret; } BUG_ON( 0 != ret); } } while (!hit); ret = t1_vpm150m_getreg_full_return(wc, pagechange, len, addr, outbuf, &hit); return ret; } int t1_vpm150m_setreg_full(struct t1 *wc, int pagechange, unsigned int len, unsigned int addr, unsigned short *data) { unsigned long flags; struct vpm150m_cmd *hit; int ret, i; do { spin_lock_irqsave(&wc->reglock, flags); hit = vpm150m_empty_slot(wc); if (hit) { hit->flags = __VPM150M_WR; if (pagechange) hit->flags |= __VPM150M_RWPAGE; hit->address = addr; hit->datalen = len; for (i = 0; i < len; i++) hit->data[i] = data[i]; } spin_unlock_irqrestore(&wc->reglock, flags); if (!hit) { if ((ret = schluffen(&wc->regq))) return ret; } } while (!hit); return (hit) ? 0 : -1; } int t1_vpm150m_setpage(struct t1 *wc, unsigned short addr) { addr &= 0xf; /* Let's optimize this a little bit */ if (wc->vpm150m->curpage == addr) return 0; else { wc->vpm150m->curpage = addr; } return t1_vpm150m_setreg_full(wc, 1, 1, 0, &addr); } unsigned char t1_vpm150m_getpage(struct t1 *wc) { unsigned short res; t1_vpm150m_getreg_full(wc, 1, 1, 0, &res); return res; } int t1_vpm150m_setreg(struct t1 *wc, unsigned int len, unsigned int addr, unsigned short *data) { int res; t1_vpm150m_setpage(wc, addr >> 16); if ((addr >> 16) != ((addr + len) >> 16)) module_printk("setreg: You found it!\n"); res = t1_vpm150m_setreg_full(wc, 0, len, addr & 0xffff, data); return res; } unsigned short t1_vpm150m_getreg(struct t1 *wc, unsigned int len, unsigned int addr, unsigned short *data) { unsigned short res; t1_vpm150m_setpage(wc, addr >> 16); if ((addr >> 16) != ((addr + len) >> 16)) module_printk("getreg: You found it!\n"); res = t1_vpm150m_getreg_full(wc, 0, len, addr & 0xffff, data); return res; } static char vpm150mtone_to_zaptone(GpakToneCodes_t tone) { switch (tone) { case DtmfDigit0: return '0'; case DtmfDigit1: return '1'; case DtmfDigit2: return '2'; case DtmfDigit3: return '3'; case DtmfDigit4: return '4'; case DtmfDigit5: return '5'; case DtmfDigit6: return '6'; case DtmfDigit7: return '7'; case DtmfDigit8: return '8'; case DtmfDigit9: return '9'; case DtmfDigitPnd: return '#'; case DtmfDigitSt: return '*'; case DtmfDigitA: return 'A'; case DtmfDigitB: return 'B'; case DtmfDigitC: return 'C'; case DtmfDigitD: return 'D'; case EndofCngDigit: return 'f'; default: return 0; } } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) static void vpm150m_echocan_bh(void *data) { struct vpm150m *vpm150m = data; #else static void vpm150m_echocan_bh(struct work_struct *data) { struct vpm150m *vpm150m = container_of(data, struct vpm150m, work_echocan); #endif struct t1 *wc = vpm150m->wc; struct list_head *task; struct list_head *next_task; unsigned long flags; list_for_each_safe(task, next_task, &vpm150m->worklist) { struct vpm150m_workentry *we = list_entry(task, struct vpm150m_workentry, list); struct zt_chan *chan = we->chan; int deflaw; int res; GPAK_AlgControlStat_t pstatus; if (we->params.tap_length) { /* configure channel for the ulaw/alaw */ unsigned int start = wc->intcount; if (memcmp(&we->params, &vpm150m->chan_params[chan->chanpos - 1], sizeof(we->params))) { /* set parameters */ vpm150m->chan_params[chan->chanpos - 1] = we->params; } deflaw = chan->span->deflaw; debug_printk(1, "Enabling EC on channel %d (law %d)\n", chan->chanpos, deflaw); if (deflaw == 2) /* alaw */ res = gpakAlgControl(vpm150m->dspid, chan->chanpos - 1, EnableALawSwCompanding, &pstatus); else if (deflaw == 1) /* alaw */ res = gpakAlgControl(vpm150m->dspid, chan->chanpos - 1, EnableMuLawSwCompanding, &pstatus); else { module_printk("Undefined law for channel %d.\n", chan->chanpos); res = -1; } if (res) { module_printk("Unable to set SW Companding on channel %d (reason %d)\n", chan->chanpos, res); } res = gpakAlgControl(vpm150m->dspid, chan->chanpos - 1, EnableEcanA, &pstatus); debug_printk(2, "Echo can enable took %d ms\n", wc->intcount - start); } else { unsigned int start = wc->intcount; debug_printk(1, "Disabling EC on channel %d\n", chan->chanpos); res = gpakAlgControl(vpm150m->dspid, chan->chanpos - 1, BypassSwCompanding, &pstatus); if (res) module_printk("Unable to disable sw companding on echo cancellation channel %d (reason %d)\n", chan->chanpos, res); res = gpakAlgControl(vpm150m->dspid, chan->chanpos - 1, BypassEcanA, &pstatus); if (res) module_printk("Unable to disable echo can on channel %d (reason %d)\n", chan->chanpos, res); debug_printk(2, "Echocan disable took %d ms\n", wc->intcount - start); } if (res) { module_printk("Unable to toggle echo cancellation on channel %d (reason %d)\n", chan->chanpos, res); } spin_lock_irqsave(&vpm150m->lock, flags); list_del(task); spin_unlock_irqrestore(&vpm150m->lock, flags); kfree(we); } } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) static void vpm150m_debug_bh(void *data) { struct vpm150m *vpm150m = data; #else static void vpm150m_debug_bh(struct work_struct *data) { struct vpm150m *vpm150m = container_of(data, struct vpm150m, work_debug); #endif unsigned short int FrammingError1Count, FramingError2Count, FramingError3Count, DmaStopErrorCount, DmaSlipStatsBuffer; if (gpakReadFramingStats(vpm150m->dspid, &FrammingError1Count, &FramingError2Count, &FramingError3Count, &DmaStopErrorCount, &DmaSlipStatsBuffer)) { module_printk("There was an error getting framing stats.\n"); } if (FrammingError1Count||FramingError2Count||FramingError3Count||DmaStopErrorCount||DmaSlipStatsBuffer) { module_printk("FramingStats Error: %d %d %d %d %d\n", FrammingError1Count, FramingError2Count, FramingError3Count, DmaStopErrorCount, DmaSlipStatsBuffer); } } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) static void vpm150m_dtmf_bh(void *data) { struct vpm150m *vpm150m = data; #else static void vpm150m_dtmf_bh(struct work_struct *data) { struct vpm150m *vpm150m = container_of(data, struct vpm150m, work_dtmf); #endif struct t1 *wc = vpm150m->wc; int i; for (i = 0; i < wc->span.channels; i++) { int enable = -1; if (test_bit(i, &vpm150m->desireddtmfmutestate)) { if (!test_bit(i, &vpm150m->curdtmfmutestate)) { enable = 1; } } else { if (test_bit(i, &vpm150m->curdtmfmutestate)) { enable = 0; } } if (enable > -1) { unsigned int start = wc->intcount; GPAK_AlgControlStat_t pstatus; int res; if (enable) { res = gpakAlgControl(vpm150m->dspid, i, EnableDTMFMuteA, &pstatus); debug_printk(2, "DTMF mute enable took %d ms\n", wc->intcount - start); } else { res = gpakAlgControl(vpm150m->dspid, i, DisableDTMFMuteA, &pstatus); debug_printk(2, "DTMF mute disable took %d ms\n", wc->intcount - start); } if (!res) change_bit(i, &vpm150m->curdtmfmutestate); } } if (test_bit(VPM150M_DTMFDETECT, &vpm150m->control)) { unsigned short channel; GpakAsyncEventCode_t eventcode; GpakAsyncEventData_t eventdata; gpakReadEventFIFOMessageStat_t res; unsigned int start = wc->intcount; do { res = gpakReadEventFIFOMessage(vpm150m->dspid, &channel, &eventcode, &eventdata); debug_printk(3, "ReadEventFIFOMessage took %d ms\n", wc->intcount - start); if (res == RefInvalidEvent || res == RefDspCommFailure) { module_printk("Uh oh (%d)\n", res); continue; } if (eventcode == EventToneDetect) { GpakToneCodes_t tone = eventdata.toneEvent.ToneCode; int duration = eventdata.toneEvent.ToneDuration; char zaptone = vpm150mtone_to_zaptone(tone); debug_printk(1, "Channel %d: Detected DTMF tone %d of duration %d\n", channel + 1, tone, duration); if (test_bit(channel, &wc->dtmfmask) && (eventdata.toneEvent.ToneDuration > 0)) { struct zt_chan *chan = &wc->chans[channel]; module_printk("DTMF detected channel=%d tone=%d duration=%d\n", channel + 1, tone, duration); if ((tone != EndofMFDigit) && (zaptone != 0)) { vpm150m->curtone[channel] = tone; if (test_bit(channel, &vpm150m->curdtmfmutestate)) { unsigned long flags; int y; /* Mute the audio data buffers */ spin_lock_irqsave(&chan->lock, flags); for (y = 0; y < chan->numbufs; y++) { if ((chan->inreadbuf > -1) && (chan->readidx[y])) memset(chan->readbuf[chan->inreadbuf], ZT_XLAW(0, chan), chan->readidx[y]); } spin_unlock_irqrestore(&chan->lock, flags); } if (!test_bit(channel, &wc->dtmfactive)) { debug_printk(1,"Queuing DTMFDOWN %c\n", zaptone); set_bit(channel, &wc->dtmfactive); zt_qevent_lock(chan, (ZT_EVENT_DTMFDOWN | zaptone)); } } else if ((tone == EndofMFDigit) && test_bit(channel, &wc->dtmfactive)) { debug_printk(1,"Queuing DTMFUP %c\n", vpm150mtone_to_zaptone(vpm150m->curtone[channel])); zt_qevent_lock(chan, (ZT_EVENT_DTMFUP | vpm150mtone_to_zaptone(vpm150m->curtone[channel]))); clear_bit(channel, &wc->dtmfactive); } } } } while ((res == RefEventAvail)); } return; } void t1_vpm150m_init(struct t1 *wc) { struct vpm150m *vpm150m; unsigned short i; unsigned short reg; unsigned long flags; gpakPingDspStat_t pingstatus; gpakDownloadStatus_t downloadstatus; struct t1_firmware fw; struct firmware embedded_firmware; const struct firmware *firmware = &embedded_firmware; #if !defined(HOTPLUG_FIRMWARE) extern void _binary_zaptel_fw_vpmadt032_bin_size; extern u8 _binary_zaptel_fw_vpmadt032_bin_start[]; #else static const char vpmadt032_firmware[] = "zaptel-fw-vpmadt032.bin"; struct pci_dev* pdev = voicebus_get_pci_dev(wc->vb); #endif #if 0 unsigned short omsg[4] = { 0xdead, 0xbeef, 0x1111, 0x2222}; unsigned short imsg[4]; #endif if (!vpmsupport) { module_printk("VPM Support Disabled\n"); wc->vpm150m = NULL; return; } vpm150m = kmalloc(sizeof(struct vpm150m), GFP_KERNEL); if (!vpm150m) { module_printk("Unable to allocate VPMADT032!\n"); return; } memset(vpm150m, 0, sizeof(struct vpm150m)); /* Init our vpm150m struct */ sema_init(&vpm150m->sem, 1); vpm150m->curpage = 0x80; for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++) { if (ifaces[i] == wc) vpm150m->dspid = i; } debug_printk(1, "Setting VPMADT032 DSP ID to %d\n", vpm150m->dspid); spin_lock_irqsave(&wc->reglock, flags); wc->vpm150m = vpm150m; spin_unlock_irqrestore(&wc->reglock, flags); for (i = 0; i < 10; i++) schluffen(&wc->regq); debug_printk(1, "Looking for VPMADT032 by testing page access: "); for (i = 0; i < 0xf; i++) { int x; for (x = 0; x < 3; x++) { t1_vpm150m_setpage(wc, i); reg = t1_vpm150m_getpage(wc); if (reg != i) { /* If they have debug turned on we want them to be able to * report where in the code the module failed to come up. */ debug_printk(1, "Either no VPMADT032 module present or the module failed VPM page access test (%x != %x)\n", i, reg); goto failed_exit; } } } debug_printk(1, "Passed\n"); set_bit(VPM150M_HPIRESET, &vpm150m->control); msleep(2000); /* Set us up to page 0 */ t1_vpm150m_setpage(wc, 0); debug_printk(1, "VPMADT032 now doing address test: "); for (i = 0; i < 16; i++) { int x; for (x = 0; x < 2; x++) { t1_vpm150m_setreg(wc, 1, 0x1000, &i); t1_vpm150m_getreg(wc, 1, 0x1000, ®); if (reg != i) { module_printk("VPMADT032 Failed address test: sent %x != %x on try %d\n", i, reg, x); goto failed_exit; } } } debug_printk(1, "Passed\n"); #define TEST_SIZE 2 if (debug) { int i; unsigned short msg[TEST_SIZE]; set_bit(VPM150M_HPIRESET, &vpm150m->control); msleep(2000); gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); for (i = 0; i< TEST_SIZE; i++) printk("%x ", msg[i]); printk("\n"); for (i = 0; i< TEST_SIZE; i++) msg[i] = 0xdead; gpakWriteDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); gpakWriteDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); for (i = 0; i< TEST_SIZE; i++) printk("%x ", msg[i]); printk("\n"); gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); for (i = 0; i< TEST_SIZE; i++) printk("%x ", msg[i]); printk("\n"); for (i = 0; i< TEST_SIZE; i++) msg[i] = 0xbeef; gpakWriteDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); for (i = 0; i< TEST_SIZE; i++) printk("%x ", msg[i]); printk("\n"); gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); for (i = 0; i< TEST_SIZE; i++) printk("%x ", msg[i]); printk("\n"); for (i = 0; i< TEST_SIZE; i++) msg[i] = 0x1111; gpakWriteDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); for (i = 0; i< TEST_SIZE; i++) printk("%x ", msg[i]); printk("\n"); gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); for (i = 0; i< TEST_SIZE; i++) printk("%x ", msg[i]); printk("\n"); for (i = 0; i< TEST_SIZE; i++) msg[i] = 0x2222; gpakWriteDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); for (i = 0; i< TEST_SIZE; i++) printk("%x ", msg[i]); printk("\n"); gpakReadDspMemory(vpm150m->dspid, 0x1000, TEST_SIZE, msg); for (i = 0; i< TEST_SIZE; i++) printk("%x ", msg[i]); printk("\n"); } #if defined(HOTPLUG_FIRMWARE) if ((request_firmware(&firmware, vpmadt032_firmware, &pdev->dev) != 0) || !firmware) { printk("VPMADT032: firmware %s not available from userspace\n", vpmadt032_firmware); goto failed_exit; } #else embedded_firmware.data = _binary_zaptel_fw_vpmadt032_bin_start; embedded_firmware.size = (size_t) &_binary_zaptel_fw_vpmadt032_bin_size; #endif fw.fw = firmware; fw.offset = 0; set_bit(VPM150M_HPIRESET, &vpm150m->control); while (test_bit(VPM150M_HPIRESET, &vpm150m->control)) schluffen(&wc->regq); module_printk("VPMADT032 Loading firwmare... "); downloadstatus = gpakDownloadDsp(vpm150m->dspid, &fw); if (firmware != &embedded_firmware) release_firmware(firmware); if (downloadstatus != 0) { module_printk("Unable to download firmware to VPMADT032 with cause %d\n", downloadstatus); goto failed_exit; } else { module_printk("Success\n"); } set_bit(VPM150M_SWRESET, &vpm150m->control); while (test_bit(VPM150M_SWRESET, &vpm150m->control)) schluffen(&wc->regq); msleep(700); #if 0 } #endif pingstatus = gpakPingDsp(vpm150m->dspid, &vpm150m->version); if (!pingstatus) { debug_printk(1, "Version of DSP is %x\n", vpm150m->version); } else { module_printk("Unable to ping the DSP (%d)!\n", pingstatus); goto failed_exit; } /* workqueue for DTMF and wc->span functions that cannot sleep */ spin_lock_init(&vpm150m->lock); vpm150m->wq = create_singlethread_workqueue("wcte12xp"); vpm150m->wc = wc; if (!vpm150m->wq) { module_printk("Unable to create work queue!\n"); goto failed_exit; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) INIT_WORK(&vpm150m->work_echocan, vpm150m_echocan_bh, vpm150m); INIT_WORK(&vpm150m->work_dtmf, vpm150m_dtmf_bh, vpm150m); INIT_WORK(&vpm150m->work_debug, vpm150m_debug_bh, vpm150m); #else INIT_WORK(&vpm150m->work_echocan, vpm150m_echocan_bh); INIT_WORK(&vpm150m->work_dtmf, vpm150m_dtmf_bh); INIT_WORK(&vpm150m->work_debug, vpm150m_debug_bh); #endif INIT_LIST_HEAD(&wc->vpm150m->worklist); /* list of echocan tasks */ if (vpm150m_config_hw(wc)) { goto failed_exit; } return; failed_exit: if (vpm150m->wq) { destroy_workqueue(vpm150m->wq); } spin_lock_irqsave(&wc->reglock, flags); wc->vpm150m = NULL; spin_unlock_irqrestore(&wc->reglock, flags); kfree(vpm150m); return; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadDspMemory - Read DSP memory. * * FUNCTION * This function reads a contiguous block of words from DSP memory starting at * the specified address. * * RETURNS * nothing * */ void gpakReadDspMemory( unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ unsigned int NumWords, /* number of contiguous words to read */ DSP_WORD *pWordValues /* pointer to array of word values variable */ ) { struct t1 *wc = wc_find_iface(DspId); int i; int transcount; int ret; vpm150m_io_wait(wc); if ( NumWords < VPM150M_MAX_COMMANDS ) { struct vpm150m_cmd* cmds[VPM150M_MAX_COMMANDS] = {0}; t1_vpm150m_setpage(wc, DspAddress >> 16); DspAddress &= 0xffff; for (i=0; i < NumWords; ++i) { ret = t1_vpm150m_getreg_full_async(wc,0,1,DspAddress+i,&pWordValues[i], &cmds[i]); if (0 != ret) { return; } } for (i=NumWords-1; i >=0; --i) { ret = t1_vpm150m_getreg_full_return(wc,0,1,DspAddress+i,&pWordValues[i], &cmds[i]); if (0 != ret) { return; } } } else { for (i = 0; i < NumWords;) { if ((NumWords - i) > VPM150M_MAX_DATA) transcount = VPM150M_MAX_DATA; else transcount = NumWords - i; t1_vpm150m_getreg(wc, transcount, DspAddress + i, &pWordValues[i]); i += transcount; } } return; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakWriteDspMemory - Write DSP memory. * * FUNCTION * This function writes a contiguous block of words to DSP memory starting at * the specified address. * * RETURNS * nothing * */ void gpakWriteDspMemory( unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ unsigned int NumWords, /* number of contiguous words to write */ DSP_WORD *pWordValues /* pointer to array of word values to write */ ) { struct t1 *wc = wc_find_iface(DspId); int i; int transcount; if (wc && wc->vpm150m) { for (i = 0; i < NumWords;) { if ((NumWords - i) > VPM150M_MAX_DATA) transcount = VPM150M_MAX_DATA; else transcount = NumWords - i; t1_vpm150m_setreg(wc, transcount, DspAddress + i, &pWordValues[i]); i += transcount; } } return; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakHostDelay - Delay for a fixed time interval. * * FUNCTION * This function delays for a fixed time interval before returning. The time * interval is the Host Port Interface sampling period when polling a DSP for * replies to command messages. * * RETURNS * nothing * */ void gpakHostDelay(void) { } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakLockAccess - Lock access to the specified DSP. * * FUNCTION * This function aquires exclusive access to the specified DSP. * * RETURNS * nothing * */ void gpakLockAccess(unsigned short DspId) { struct t1 *wc; wc = wc_find_iface(DspId); if (wc) { struct vpm150m *vpm = wc->vpm150m; if (vpm) down_interruptible(&vpm->sem); } } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakUnlockAccess - Unlock access to the specified DSP. * * FUNCTION * This function releases exclusive access to the specified DSP. * * RETURNS * nothing * */ void gpakUnlockAccess(unsigned short DspId) { struct t1 *wc; wc = wc_find_iface(DspId); if (wc) { struct vpm150m *vpm = wc->vpm150m; if (vpm) up(&vpm->sem); } } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadFile - Read a block of bytes from a G.PAK Download file. * * FUNCTION * This function reads a contiguous block of bytes from a G.PAK Download file * starting at the current file position. * * RETURNS * The number of bytes read from the file. * -1 indicates an error occurred. * 0 indicates all bytes have been read (end of file) * */ int gpakReadFile( GPAK_FILE_ID FileId, /* G.PAK Download File Identifier */ unsigned char *pBuffer, /* pointer to buffer for storing bytes */ unsigned int NumBytes /* number of bytes to read */ ) { struct t1_firmware *fw = FileId; unsigned int i, count; if (!fw || !fw->fw) return -1; if (NumBytes > (fw->fw->size - fw->offset)) count = fw->fw->size - fw->offset; else count = NumBytes; for (i = 0; i < count; i++) pBuffer[i] = fw->fw->data[fw->offset + i]; fw->offset += count; return count; } int vpm150m_config_hw(struct t1 *wc) { struct vpm150m *vpm150m = wc->vpm150m; gpakConfigPortStatus_t configportstatus; GpakPortConfig_t portconfig; GPAK_PortConfigStat_t pstatus; GpakChannelConfig_t chanconfig; GPAK_ChannelConfigStat_t cstatus; GPAK_AlgControlStat_t algstatus; int res, i; memset(&portconfig, 0, sizeof(GpakPortConfig_t)); /* First Serial Port config */ portconfig.SlotsSelect1 = SlotCfgNone; portconfig.FirstBlockNum1 = 0; portconfig.FirstSlotMask1 = 0x0000; portconfig.SecBlockNum1 = 1; portconfig.SecSlotMask1 = 0x0000; portconfig.SerialWordSize1 = SerWordSize8; portconfig.CompandingMode1 = cmpNone; portconfig.TxFrameSyncPolarity1 = FrameSyncActHigh; portconfig.RxFrameSyncPolarity1 = FrameSyncActHigh; portconfig.TxClockPolarity1 = SerClockActHigh; portconfig.RxClockPolarity1 = SerClockActHigh; portconfig.TxDataDelay1 = DataDelay0; portconfig.RxDataDelay1 = DataDelay0; portconfig.DxDelay1 = Disabled; portconfig.ThirdSlotMask1 = 0x0000; portconfig.FouthSlotMask1 = 0x0000; portconfig.FifthSlotMask1 = 0x0000; portconfig.SixthSlotMask1 = 0x0000; portconfig.SevenSlotMask1 = 0x0000; portconfig.EightSlotMask1 = 0x0000; /* Second Serial Port config */ portconfig.SlotsSelect2 = SlotCfg8Groups; portconfig.FirstBlockNum2 = 0; portconfig.FirstSlotMask2 = 0x5554; portconfig.SecBlockNum2 = 1; portconfig.SecSlotMask2 = 0x5555; portconfig.ThirdSlotMask2 = 0x5555; portconfig.FouthSlotMask2 = 0x5555; portconfig.SerialWordSize2 = SerWordSize8; portconfig.CompandingMode2 = cmpNone; portconfig.TxFrameSyncPolarity2 = FrameSyncActHigh; portconfig.RxFrameSyncPolarity2 = FrameSyncActHigh; portconfig.TxClockPolarity2 = SerClockActHigh; portconfig.RxClockPolarity2 = SerClockActHigh; portconfig.TxDataDelay2 = DataDelay0; portconfig.RxDataDelay2 = DataDelay0; portconfig.DxDelay2 = Disabled; portconfig.FifthSlotMask2 = 0x0001; portconfig.SixthSlotMask2 = 0x0000; portconfig.SevenSlotMask2 = 0x0000; portconfig.EightSlotMask2 = 0x0000; /* Third Serial Port Config */ portconfig.SlotsSelect3 = SlotCfg8Groups; portconfig.FirstBlockNum3 = 0; portconfig.FirstSlotMask3 = 0x5554; portconfig.SecBlockNum3 = 1; portconfig.SecSlotMask3 = 0x5555; portconfig.SerialWordSize3 = SerWordSize8; portconfig.CompandingMode3 = cmpNone; portconfig.TxFrameSyncPolarity3 = FrameSyncActHigh; portconfig.RxFrameSyncPolarity3 = FrameSyncActHigh; portconfig.TxClockPolarity3 = SerClockActHigh; portconfig.RxClockPolarity3 = SerClockActLow; portconfig.TxDataDelay3 = DataDelay0; portconfig.RxDataDelay3 = DataDelay0; portconfig.DxDelay3 = Disabled; portconfig.ThirdSlotMask3 = 0x5555; portconfig.FouthSlotMask3 = 0x5555; portconfig.FifthSlotMask3 = 0x0001; portconfig.SixthSlotMask3 = 0x0000; portconfig.SevenSlotMask3 = 0x0000; portconfig.EightSlotMask3 = 0x0000; if ((configportstatus = gpakConfigurePorts(vpm150m->dspid, &portconfig, &pstatus))) { module_printk("Configuration of ports failed (%d)!\n", configportstatus); return -1; } else { debug_printk(1, "Configured McBSP ports successfully\n"); } if ((res = gpakPingDsp(vpm150m->dspid, &vpm150m->version))) { module_printk("Error pinging DSP (%d)\n", res); return -1; } for (i = 0; i < 32; i++) { /* Let's configure a channel */ chanconfig.PcmInPortA = 3; chanconfig.PcmInSlotA = (i + 1) * 2; chanconfig.PcmOutPortA = 2; chanconfig.PcmOutSlotA = (i + 1) * 2; chanconfig.PcmInPortB = 2; chanconfig.PcmInSlotB = (i + 1) * 2; chanconfig.PcmOutPortB = 3; chanconfig.PcmOutSlotB = (i + 1) * 2; if (vpmdtmfsupport) { chanconfig.ToneTypesA = DTMF_tone; chanconfig.MuteToneA = Enabled; chanconfig.FaxCngDetA = Enabled; } else { chanconfig.ToneTypesA = Null_tone; chanconfig.MuteToneA = Disabled; chanconfig.FaxCngDetA = Disabled; } chanconfig.ToneTypesB = Null_tone; chanconfig.EcanEnableA = Enabled; chanconfig.EcanEnableB = Disabled; chanconfig.MuteToneB = Disabled; chanconfig.FaxCngDetB = Disabled; chanconfig.SoftwareCompand = cmpNone; chanconfig.FrameRate = rate10ms; chanconfig.EcanParametersA.EcanTapLength = 1024; chanconfig.EcanParametersA.EcanNlpType = vpmnlptype; chanconfig.EcanParametersA.EcanAdaptEnable = 1; chanconfig.EcanParametersA.EcanG165DetEnable = 1; chanconfig.EcanParametersA.EcanDblTalkThresh = 6; chanconfig.EcanParametersA.EcanNlpThreshold = vpmnlpthresh; chanconfig.EcanParametersA.EcanNlpConv = 0; chanconfig.EcanParametersA.EcanNlpUnConv = 0; chanconfig.EcanParametersA.EcanNlpMaxSuppress = vpmnlpmaxsupp; chanconfig.EcanParametersA.EcanCngThreshold = 43; chanconfig.EcanParametersA.EcanAdaptLimit = 50; chanconfig.EcanParametersA.EcanCrossCorrLimit = 15; chanconfig.EcanParametersA.EcanNumFirSegments = 3; chanconfig.EcanParametersA.EcanFirSegmentLen = 64; chanconfig.EcanParametersB.EcanTapLength = 1024; chanconfig.EcanParametersB.EcanNlpType = vpmnlptype; chanconfig.EcanParametersB.EcanAdaptEnable = 1; chanconfig.EcanParametersB.EcanG165DetEnable = 1; chanconfig.EcanParametersB.EcanDblTalkThresh = 6; chanconfig.EcanParametersB.EcanNlpThreshold = vpmnlpthresh; chanconfig.EcanParametersB.EcanNlpConv = 0; chanconfig.EcanParametersB.EcanNlpUnConv = 0; chanconfig.EcanParametersB.EcanNlpMaxSuppress = vpmnlpmaxsupp; chanconfig.EcanParametersB.EcanCngThreshold = 43; chanconfig.EcanParametersB.EcanAdaptLimit = 50; chanconfig.EcanParametersB.EcanCrossCorrLimit = 15; chanconfig.EcanParametersB.EcanNumFirSegments = 3; chanconfig.EcanParametersB.EcanFirSegmentLen = 64; if ((res = gpakConfigureChannel(vpm150m->dspid, i, tdmToTdm, &chanconfig, &cstatus))) { module_printk("Unable to configure channel (%d)\n", res); if (res == 1) { module_printk("Reason %d\n", cstatus); } return -1; } if ((res = gpakAlgControl(vpm150m->dspid, i, BypassEcanA, &algstatus))) { module_printk("Unable to disable echo can on channel %d (reason %d:%d)\n", i + 1, res, algstatus); return -1; } if (vpmdtmfsupport) { if ((res = gpakAlgControl(vpm150m->dspid, i, DisableDTMFMuteA, &algstatus))) { module_printk("Unable to disable dtmf muting on channel %d (reason %d:%d)\n", i + 1, res, algstatus); return -1; } } } if ((res = gpakPingDsp(vpm150m->dspid, &vpm150m->version))) { module_printk("Error pinging DSP (%d)\n", res); return -1; } /* Turn on DTMF detection */ if (vpmdtmfsupport) set_bit(VPM150M_DTMFDETECT, &vpm150m->control); set_bit(VPM150M_ACTIVE, &vpm150m->control); return 0; } #endif zaptel-1.4.11/kernel/wcte12xp/base.c0000644000000000000000000013366511012614743015623 0ustar rootroot/* * Digium, Inc. Wildcard TE12xP T1/E1 card Driver * * Written by Michael Spiceland * * Adapted from the wctdm24xxp and wcte11xp drivers originally * written by Mark Spencer * Matthew Fredrickson * William Meadows * * Copyright (C) 2007-2008, 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 #ifdef LINUX26 #include #endif #include "zaptel.h" #include "../wct4xxp/wct4xxp.h" /* For certain definitions */ #include "../voicebus.h" #include "wcte12xp.h" #if defined(VPM_SUPPORT) #include "vpmadt032.h" #include "GpakApi.h" #endif struct pci_driver te12xp_driver; static int chanmap_t1[] = { 2,1,0, 6,5,4, 10,9,8, 14,13,12, 18,17,16, 22,21,20, 26,25,24, 30,29,28 }; static int chanmap_e1[] = { 2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12, 19,18,17,16, 23,22,21,20, 27,26,25,24, 31,30,29,28 }; static int chanmap_e1uc[] = { 3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12, 19,18,17,16, 23,22,21,20, 27,26,25,24, 31,30,29,28 }; int debug = 0; static int j1mode = 0; static int alarmdebounce = 0; static int loopback = 0; static int t1e1override = -1; static int unchannelized = 0; static int latency = VOICEBUS_DEFAULT_LATENCY; #ifdef VPM_SUPPORT int vpmsupport = 1; int vpmdtmfsupport = 0; int vpmtsisupport = 0; int vpmnlptype = 1; int vpmnlpthresh = 24; int vpmnlpmaxsupp = 0; #endif struct t1 *ifaces[WC_MAX_IFACES]; spinlock_t ifacelock = SPIN_LOCK_UNLOCKED; struct t1_desc { char *name; int flags; }; static struct t1_desc te120p = { "Wildcard TE120P", 0 }; static struct t1_desc te122 = { "Wildcard TE122", 0 }; static struct t1_desc te121 = { "Wildcard TE121", 0 }; int schluffen(wait_queue_head_t *q) { DECLARE_WAITQUEUE(wait, current); add_wait_queue(q, &wait); current->state = TASK_INTERRUPTIBLE; if (!signal_pending(current)) schedule(); current->state = TASK_RUNNING; remove_wait_queue(q, &wait); if (signal_pending(current)) return -ERESTARTSYS; return(0); } static inline int empty_slot(struct t1 *wc) { unsigned int x; for (x = 0; x < sizeof(wc->cmdq.cmds) / sizeof(wc->cmdq.cmds[0]); x++) { if (!wc->cmdq.cmds[x].flags && !wc->cmdq.cmds[x].address) return x; } return -1; } static inline void cmd_dequeue(struct t1 *wc, volatile unsigned char *writechunk, int eframe, int slot) { struct command *curcmd=NULL; unsigned int x; /* Skip audio */ writechunk += 66; /* Search for something waiting to transmit */ if ((slot < 6) && (eframe) && (eframe < ZT_CHUNKSIZE - 1)) { /* only 6 useable cs slots per */ /* framer */ for (x = 0; x < sizeof(wc->cmdq.cmds) / sizeof(wc->cmdq.cmds[0]); x++) { if ((wc->cmdq.cmds[x].flags & (__CMD_RD | __CMD_WR | __CMD_LEDS | __CMD_PINS)) && !(wc->cmdq.cmds[x].flags & (__CMD_TX | __CMD_FIN))) { curcmd = &wc->cmdq.cmds[x]; wc->cmdq.cmds[x].flags |= __CMD_TX; wc->cmdq.cmds[x].ident = wc->txident; break; } } if (!curcmd) { curcmd = &wc->dummy; /* If nothing else, use filler */ curcmd->address = 0x4a; curcmd->data = 0x00; curcmd->flags = __CMD_RD; } curcmd->cs_slot = slot; if (curcmd->flags & __CMD_WR) writechunk[CMD_BYTE(slot,0,0)] = 0x0c; /* 0c write command */ else if (curcmd->flags & __CMD_LEDS) writechunk[CMD_BYTE(slot,0,0)] = 0x10 | ((curcmd->address) & 0x0E); /* led set command */ else if (curcmd->flags & __CMD_PINS) writechunk[CMD_BYTE(slot,0,0)] = 0x30; /* CPLD2 pin state */ else writechunk[CMD_BYTE(slot,0,0)] = 0x0a; /* read command */ writechunk[CMD_BYTE(slot,1,0)] = curcmd->address; writechunk[CMD_BYTE(slot,2,0)] = curcmd->data; } } static inline void cmd_decipher(struct t1 *wc, volatile unsigned char *readchunk) { unsigned char ident, cs_slot; unsigned int x; unsigned int is_vpm = 0; /* Skip audio */ readchunk += 66; /* Search for any pending results */ for (x = 0; x < sizeof(wc->cmdq.cmds) / sizeof(wc->cmdq.cmds[0]); x++) { if ((wc->cmdq.cmds[x].flags & (__CMD_RD | __CMD_WR | __CMD_LEDS | __CMD_PINS)) && (wc->cmdq.cmds[x].flags & (__CMD_TX)) && !(wc->cmdq.cmds[x].flags & (__CMD_FIN))) { ident = wc->cmdq.cmds[x].ident; cs_slot = wc->cmdq.cmds[x].cs_slot; if (ident == wc->rxident) { /* Store result */ wc->cmdq.cmds[x].data |= readchunk[CMD_BYTE(cs_slot,2,is_vpm)]; /*printk("answer in rxident=%d cs_slot=%d is %d CMD_BYTE=%d jiffies=%d\n", ident, cs_slot, last_read_command, CMD_BYTE(cs_slot, 2), jiffies); */ wc->cmdq.cmds[x].flags |= __CMD_FIN; if (wc->cmdq.cmds[x].flags & (__CMD_WR | __CMD_LEDS)) /* clear out writes (and leds) since they need no ack */ memset(&wc->cmdq.cmds[x], 0, sizeof(wc->cmdq.cmds[x])); } } } } static inline int t1_setreg_full(struct t1 *wc, int addr, int val, int inisr, int vpm_num) { unsigned long flags; int hit; int ret; do { if (!inisr) spin_lock_irqsave(&wc->reglock, flags); hit = empty_slot(wc); if (hit > -1) { wc->cmdq.cmds[hit].address = addr; wc->cmdq.cmds[hit].data = val; wc->cmdq.cmds[hit].flags |= __CMD_WR; if(vpm_num >= 0) { wc->cmdq.cmds[hit].flags |= __CMD_VPM; wc->cmdq.cmds[hit].vpm_num = vpm_num; } } if (inisr) break; spin_unlock_irqrestore(&wc->reglock, flags); if (hit < 0) { if ((ret = schluffen(&wc->regq))) return ret; } } while (hit < 0); return (hit > -1) ? 0 : -1; } static inline int t1_setreg(struct t1 *wc, int addr, int val) { return t1_setreg_full(wc, addr, val, 0, NOT_VPM); } /*************************************************************************** * clean_leftovers() * * Check for unconsumed isr register reads and clean them up. **************************************************************************/ static inline void clean_leftovers(struct t1 *wc) { unsigned int x; int count = 0; /* find our requested command */ for (x = 0; x < sizeof(wc->cmdq.cmds) / sizeof(wc->cmdq.cmds[0]); x++) { if ((wc->cmdq.cmds[x].flags & __CMD_RD) && (wc->cmdq.cmds[x].flags & __CMD_ISR) && !(wc->cmdq.cmds[x].flags & __CMD_FIN)) { debug_printk(1,"leftover isr read! %d", count); memset(&wc->cmdq.cmds[x], 0, sizeof(wc->cmdq.cmds[x])); } } } /******************************************************************** * t1_getreg_isr() * * Called in interrupt context to retrieve a value already requested * by the normal t1_getreg(). *******************************************************************/ static inline int t1_getreg_isr(struct t1 *wc, int addr) { int hit=-1; int ret; unsigned int x; /* find our requested command */ for (x = 0;x < sizeof(wc->cmdq.cmds) / sizeof(wc->cmdq.cmds[0]); x++) { if ((wc->cmdq.cmds[x].flags & __CMD_RD) && (wc->cmdq.cmds[x].address==addr)) { if (wc->cmdq.cmds[x].flags & __CMD_FIN) { hit = x; break; } else { /* still in progress. */ return -1; } } } if (hit < 0) { debug_printk(2, "t1_getreg_isr() no addr=%02x\n", addr); return -1; /* oops, couldn't find it */ } ret = wc->cmdq.cmds[hit].data; memset(&wc->cmdq.cmds[hit], 0, sizeof(struct command)); return ret; } static inline int t1_getreg_full(struct t1 *wc, int addr, int inisr, int vpm_num) { unsigned long flags; int hit; int ret = 0; do { if (!inisr) { spin_lock_irqsave(&wc->reglock, flags); } hit = empty_slot(wc); if (hit > -1) { wc->cmdq.cmds[hit].address = addr; wc->cmdq.cmds[hit].data = 0x00; wc->cmdq.cmds[hit].flags |= __CMD_RD; if(vpm_num >= 0) { wc->cmdq.cmds[hit].flags |= __CMD_VPM; wc->cmdq.cmds[hit].vpm_num = vpm_num; } if (inisr) wc->cmdq.cmds[hit].flags |= __CMD_ISR; } if (inisr) /* must be requested in t1_getreg_isr() */ return (hit > -1) ? 0 : -1; else { spin_unlock_irqrestore(&wc->reglock, flags); } if (hit < 0) { if ((ret = schluffen(&wc->regq))) return ret; } } while (hit < 0); do { spin_lock_irqsave(&wc->reglock, flags); if (wc->cmdq.cmds[hit].flags & __CMD_FIN) { ret = wc->cmdq.cmds[hit].data; memset(&wc->cmdq.cmds[hit], 0, sizeof(wc->cmdq.cmds[hit])); hit = -1; } spin_unlock_irqrestore(&wc->reglock, flags); if (hit > -1) { if ((ret = schluffen(&wc->regq))) return ret; } } while (hit > -1); return ret; } static inline int t1_getreg(struct t1 *wc, int addr, int inisr) { return t1_getreg_full(wc, addr, inisr, NOT_VPM); } static inline int t1_setleds(struct t1 *wc, int leds, int inisr) { unsigned long flags; int hit; int ret = 0; leds = ~leds & 0x0E; /* invert the LED bits (3 downto 1)*/ do { if (!inisr) { spin_lock_irqsave(&wc->reglock, flags); } hit = empty_slot(wc); if (hit > -1) { wc->cmdq.cmds[hit].flags |= __CMD_LEDS; wc->cmdq.cmds[hit].address = leds; } if (inisr) { break; } else { spin_unlock_irqrestore(&wc->reglock, flags); } if (hit < 0) { if ((ret = schluffen(&wc->regq))) return ret; } } while (hit < 0); return (hit > -1) ? 0 : -1; } static inline int t1_getpins(struct t1 *wc, int inisr) { unsigned long flags; int hit; int ret = 0; do { spin_lock_irqsave(&wc->reglock, flags); hit = empty_slot(wc); if (hit > -1) { wc->cmdq.cmds[hit].address = 0x00; wc->cmdq.cmds[hit].data = 0x00; wc->cmdq.cmds[hit].flags |= __CMD_PINS; } spin_unlock_irqrestore(&wc->reglock, flags); if (inisr) return (hit > -1) ? 0 : -1; if (hit < 0) { if ((ret = schluffen(&wc->regq))) return ret; } } while (hit < 0); do { spin_lock_irqsave(&wc->reglock, flags); if (wc->cmdq.cmds[hit].flags & __CMD_FIN) { ret = wc->cmdq.cmds[hit].data; memset(&wc->cmdq.cmds[hit], 0, sizeof(wc->cmdq.cmds[hit])); hit = -1; } spin_unlock_irqrestore(&wc->reglock, flags); if (hit > -1) { if ((ret = schluffen(&wc->regq))) return ret; } } while (hit > -1); return ret; } static void __t1xxp_set_clear(struct t1 *wc, int channo) { int i,j; int ret; unsigned short val=0; for (i = 0; i < 24; i++) { j = (i / 8); if (wc->span.chans[i].flags & ZT_FLAG_CLEAR) val |= 1 << (7 - (i % 8)); if (((i % 8)==7) && /* write byte every 8 channels */ ((channo < 0) || /* channo=-1 means all channels */ (j == (channo-1)/8) )) { /* only the register for this channo */ ret = t1_setreg_full(wc, 0x2f + j, val, 1, NOT_VPM); if (ret < 0) module_printk("set_clear failed for chan %d!\n",i); val = 0; } } } static void t1_release(struct t1 *wc) { zt_unregister(&wc->span); kfree(wc); printk("Freed a Wildcard TE12xP\n"); } static void t4_serial_setup(struct t1 *wc) { module_printk("Setting up global serial parameters for %s\n", wc->spantype == TYPE_E1 ? (unchannelized ? "Unchannelized E1" : "E1") : "T1"); t1_setreg(wc, 0x85, 0xe0); /* GPC1: Multiplex mode enabled, FSC is output, active low, RCLK from channel 0 */ t1_setreg(wc, 0x08, 0x05); /* IPC: Interrupt push/pull active low */ /* Global clocks (8.192 Mhz CLK) */ t1_setreg(wc, 0x92, 0x00); t1_setreg(wc, 0x93, 0x18); t1_setreg(wc, 0x94, 0xfb); t1_setreg(wc, 0x95, 0x0b); t1_setreg(wc, 0x96, 0x00); t1_setreg(wc, 0x97, 0x0b); t1_setreg(wc, 0x98, 0xdb); t1_setreg(wc, 0x99, 0xdf); /* Configure interrupts */ t1_setreg(wc, 0x46, 0xc0); /* GCR: Interrupt on Activation/Deactivation of AIX, LOS */ /* Configure system interface */ t1_setreg(wc, 0x3e, 0x0a /* 0x02 */); /* SIC1: 4.096 Mhz clock/bus, double buffer receive / transmit, byte interleaved */ t1_setreg(wc, 0x3f, 0x00); /* SIC2: No FFS, no center receive eliastic buffer, phase 0 */ t1_setreg(wc, 0x40, 0x04); /* SIC3: Edges for capture */ t1_setreg(wc, 0x44, 0x30); /* CMR1: RCLK is at 8.192 Mhz dejittered */ t1_setreg(wc, 0x45, 0x00); /* CMR2: We provide sync and clock for tx and rx. */ t1_setreg(wc, 0x22, 0x00); /* XC0: Normal operation of Sa-bits */ t1_setreg(wc, 0x23, 0x04); /* XC1: 0 offset */ t1_setreg(wc, 0x24, 0x00); /* RC0: Just shy of 255 */ t1_setreg(wc, 0x25, 0x05); /* RC1: The rest of RC0 */ /* Configure ports */ t1_setreg(wc, 0x80, 0x00); /* PC1: SPYR/SPYX input on RPA/XPA */ t1_setreg(wc, 0x81, 0x22); /* PC2: RMFB/XSIG output/input on RPB/XPB */ t1_setreg(wc, 0x82, 0x65); /* PC3: Some unused stuff */ t1_setreg(wc, 0x83, 0x35); /* PC4: Some more unused stuff */ t1_setreg(wc, 0x84, 0x31); /* PC5: XMFS active low, SCLKR is input, RCLK is output */ t1_setreg(wc, 0x86, 0x03); /* PC6: CLK1 is Tx Clock output, CLK2 is 8.192 Mhz from DCO-R */ t1_setreg(wc, 0x3b, 0x00); /* Clear LCR1 */ } static void t1_configure_t1(struct t1 *wc, 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; fmr1 = 0x9e; /* FMR1: Mode 0, T1 mode, CRC on for ESF, 2.048 Mhz system data rate, no XAIS */ fmr2 = 0x22; /* FMR2: no payload loopback, auto send yellow alarm */ if (loopback) fmr2 |= 0x4; if (j1mode) 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 */ t1_setreg(wc, 0x1d, fmr1); t1_setreg(wc, 0x1e, fmr2); /* Configure line interface */ if (lineconfig & ZT_CONFIG_AMI) { line = "AMI"; fmr0 = 0xa0; } else { line = "B8ZS"; fmr0 = 0xf0; } if (lineconfig & ZT_CONFIG_D4) { framing = "D4"; } else { framing = "ESF"; fmr4 |= 0x2; fmr2 |= 0xc0; } t1_setreg(wc, 0x1c, fmr0); t1_setreg(wc, 0x20, fmr4); t1_setreg(wc, 0x21, 0x40); /* FMR5: Enable RBS mode */ t1_setreg(wc, 0x37, 0xf8); /* LIM1: Clear data in case of LOS, Set receiver threshold (0.5V), No remote loop, no DRS */ t1_setreg(wc, 0x36, 0x08); /* LIM0: Enable auto long haul mode, no local loop (must be after LIM1) */ t1_setreg(wc, 0x02, 0x50); /* CMDR: Reset the receiver and transmitter line interface */ t1_setreg(wc, 0x02, 0x00); /* CMDR: Reset the receiver and transmitter line interface */ t1_setreg(wc, 0x3a, lim2); /* LIM2: 50% peak amplitude is a "1" */ t1_setreg(wc, 0x38, 0x0a); /* PCD: LOS after 176 consecutive "zeros" */ t1_setreg(wc, 0x39, 0x15); /* PCR: 22 "ones" clear LOS */ if (j1mode) t1_setreg(wc, 0x24, 0x80); /* J1 overide */ /* Generate pulse mask for T1 */ switch (mytxlevel) { case 3: t1_setreg(wc, 0x26, 0x07); /* XPM0 */ t1_setreg(wc, 0x27, 0x01); /* XPM1 */ t1_setreg(wc, 0x28, 0x00); /* XPM2 */ break; case 2: t1_setreg(wc, 0x26, 0x8c); /* XPM0 */ t1_setreg(wc, 0x27, 0x11); /* XPM1 */ t1_setreg(wc, 0x28, 0x01); /* XPM2 */ break; case 1: t1_setreg(wc, 0x26, 0x8c); /* XPM0 */ t1_setreg(wc, 0x27, 0x01); /* XPM1 */ t1_setreg(wc, 0x28, 0x00); /* XPM2 */ break; case 0: default: t1_setreg(wc, 0x26, 0xd7); /* XPM0 */ t1_setreg(wc, 0x27, 0x22); /* XPM1 */ t1_setreg(wc, 0x28, 0x01); /* XPM2 */ break; } module_printk("Span configured for %s/%s\n", framing, line); } static void t1_configure_e1(struct t1 *wc, int lineconfig) { unsigned int fmr2, fmr1, fmr0; unsigned int cas = 0; char *crc4 = ""; char *framing, *line; fmr1 = 0x46; /* 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 (unchannelized) fmr2 |= 0x30; if (loopback) fmr2 |= 0x4; if (lineconfig & ZT_CONFIG_CRC4) { fmr1 |= 0x08; /* CRC4 transmit */ fmr2 |= 0xc0; /* CRC4 receive */ crc4 = "/CRC4"; } t1_setreg(wc, 0x1d, fmr1); t1_setreg(wc, 0x1e, fmr2); /* Configure line interface */ if (lineconfig & ZT_CONFIG_AMI) { line = "AMI"; fmr0 = 0xa0; } else { line = "HDB3"; fmr0 = 0xf0; } if (lineconfig & ZT_CONFIG_CCS) { framing = "CCS"; } else { framing = "CAS"; cas = 0x40; } t1_setreg(wc, 0x1c, fmr0); if (unchannelized) t1_setreg(wc, 0x1f, 0x40); t1_setreg(wc, 0x37, 0xf0 /*| 0x6 */ ); /* LIM1: Clear data in case of LOS, Set receiver threshold (0.5V), No remote loop, no DRS */ t1_setreg(wc, 0x36, 0x08); /* LIM0: Enable auto long haul mode, no local loop (must be after LIM1) */ t1_setreg(wc, 0x02, 0x50); /* CMDR: Reset the receiver and transmitter line interface */ t1_setreg(wc, 0x02, 0x00); /* CMDR: Reset the receiver and transmitter line interface */ /* Condition receive line interface for E1 after reset */ t1_setreg(wc, 0xbb, 0x17); t1_setreg(wc, 0xbc, 0x55); t1_setreg(wc, 0xbb, 0x97); t1_setreg(wc, 0xbb, 0x11); t1_setreg(wc, 0xbc, 0xaa); t1_setreg(wc, 0xbb, 0x91); t1_setreg(wc, 0xbb, 0x12); t1_setreg(wc, 0xbc, 0x55); t1_setreg(wc, 0xbb, 0x92); t1_setreg(wc, 0xbb, 0x0c); t1_setreg(wc, 0xbb, 0x00); t1_setreg(wc, 0xbb, 0x8c); t1_setreg(wc, 0x3a, 0x20); /* LIM2: 50% peak amplitude is a "1" */ t1_setreg(wc, 0x38, 0x0a); /* PCD: LOS after 176 consecutive "zeros" */ t1_setreg(wc, 0x39, 0x15); /* PCR: 22 "ones" clear LOS */ t1_setreg(wc, 0x20, 0x9f); /* XSW: Spare bits all to 1 */ if (unchannelized) t1_setreg(wc, 0x21, 0x3c); else t1_setreg(wc, 0x21, 0x1c|cas); /* XSP: E-bit set when async. AXS auto, XSIF to 1 */ /* Generate pulse mask for E1 */ t1_setreg(wc, 0x26, 0x54); /* XPM0 */ t1_setreg(wc, 0x27, 0x02); /* XPM1 */ t1_setreg(wc, 0x28, 0x00); /* XPM2 */ module_printk("Span configured for %s/%s%s\n", framing, line, crc4); } static void t1xxp_framer_start(struct t1 *wc, struct zt_span *span) { int alreadyrunning = wc->span.flags & ZT_FLAG_RUNNING; unsigned long flags; if (wc->spantype == TYPE_E1) { /* if this is an E1 card */ t1_configure_e1(wc, span->lineconfig); } else { /* is a T1 card */ t1_configure_t1(wc, span->lineconfig, span->txlevel); __t1xxp_set_clear(wc, -1); } spin_lock_irqsave(&wc->reglock, flags); if (!alreadyrunning) wc->span.flags |= ZT_FLAG_RUNNING; spin_unlock_irqrestore(&wc->reglock, flags); } static int t1xxp_startup(struct zt_span *span) { struct t1 *wc = span->pvt; int i; /* initialize the start value for the entire chunk of last ec buffer */ for (i = 0; i < span->channels; i++) { memset(wc->ec_chunk1[i], ZT_LIN2X(0, &span->chans[i]), ZT_CHUNKSIZE); memset(wc->ec_chunk2[i], ZT_LIN2X(0, &span->chans[i]), ZT_CHUNKSIZE); } /* Reset framer with proper parameters and start */ t1xxp_framer_start(wc, span); debug_printk(1, "Calling startup (flags is %d)\n", span->flags); return 0; } static int t1xxp_shutdown(struct zt_span *span) { struct t1 *wc = span->pvt; unsigned long flags; t1_setreg(wc, 0x46, 0x41); /* GCR: Interrupt on Activation/Deactivation of AIX, LOS */ spin_lock_irqsave(&wc->reglock, flags); span->flags &= ~ZT_FLAG_RUNNING; spin_unlock_irqrestore(&wc->reglock, flags); return 0; } static int t1xxp_chanconfig(struct zt_chan *chan, int sigtype) { struct t1 *wc = chan->pvt; int alreadyrunning = chan->span->flags & ZT_FLAG_RUNNING; if (alreadyrunning && (wc->spantype != TYPE_E1)) __t1xxp_set_clear(wc, chan->channo); return 0; } static int t1xxp_spanconfig(struct zt_span *span, struct zt_lineconfig *lc) { struct t1 *wc = span->pvt; /* Do we want to SYNC on receive or not */ wc->sync = lc->sync; if (wc->sync) wc->ctlreg |= 0x80; else wc->ctlreg &= ~0x80; /* If already running, apply changes immediately */ if (span->flags & ZT_FLAG_RUNNING) return t1xxp_startup(span); return 0; } static int t1xxp_rbsbits(struct zt_chan *chan, int bits) { u_char m,c; int n,b; struct t1 *wc = chan->pvt; unsigned long flags; debug_printk(2, "Setting bits to %d on channel %s\n", bits, chan->name); if (wc->spantype == TYPE_E1) { /* 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; spin_unlock_irqrestore(&wc->reglock, flags); /* output them to the chip */ t1_setreg_full(wc,0x71 + b,c,1,NOT_VPM); } else if (wc->span.lineconfig & ZT_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; spin_unlock_irqrestore(&wc->reglock, flags); /* output them to the chip */ t1_setreg_full(wc,0x70 + b,c,1,NOT_VPM); t1_setreg_full(wc,0x70 + b + 6,c,1,NOT_VPM); } else if (wc->span.lineconfig & ZT_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; spin_unlock_irqrestore(&wc->reglock, flags); /* output them to the chip */ t1_setreg_full(wc,0x70 + b,c,1,NOT_VPM); } debug_printk(2,"Finished setting RBS bits\n"); return 0; } static inline void __t1_check_sigbits_reads(struct t1 *wc) { int i; if (!(wc->span.flags & ZT_FLAG_RUNNING)) return; if (wc->spantype == TYPE_E1) { for (i = 0; i < 15; i++) { if (t1_getreg(wc, 0x71 + i, 1)) wc->isrreaderrors++; } } else if (wc->span.lineconfig & ZT_CONFIG_D4) { for (i = 0; i < 24; i+=4) { if (t1_getreg(wc, 0x70 + (i >> 2), 1)) wc->isrreaderrors++; } } else { for (i = 0; i < 24; i+=2) { if (t1_getreg(wc, 0x70 + (i >> 1), 1)) wc->isrreaderrors++; } } } static inline void __t1_check_sigbits(struct t1 *wc) { int a,i,rxs; if (!(wc->span.flags & ZT_FLAG_RUNNING)) return; if (wc->spantype == TYPE_E1) { for (i = 0; i < 15; i++) { a = t1_getreg_isr(wc, 0x71 + i); if (a > -1) { /* Get high channel in low bits */ rxs = (a & 0xf); if (!(wc->span.chans[i+16].sig & ZT_SIG_CLEAR)) { if (wc->span.chans[i+16].rxsig != rxs) { spin_unlock(&wc->reglock); zt_rbsbits(&wc->span.chans[i+16], rxs); spin_lock(&wc->reglock); } } rxs = (a >> 4) & 0xf; if (!(wc->span.chans[i].sig & ZT_SIG_CLEAR)) { if (wc->span.chans[i].rxsig != rxs) { spin_unlock(&wc->reglock); zt_rbsbits(&wc->span.chans[i], rxs); spin_lock(&wc->reglock); } } } } } else if (wc->span.lineconfig & ZT_CONFIG_D4) { for (i = 0; i < 24; i+=4) { a = t1_getreg_isr(wc, 0x70 + (i>>2)); if (a > -1) { /* Get high channel in low bits */ rxs = (a & 0x3) << 2; if (!(wc->span.chans[i+3].sig & ZT_SIG_CLEAR)) { if (wc->span.chans[i+3].rxsig != rxs) { spin_unlock(&wc->reglock); zt_rbsbits(&wc->span.chans[i+3], rxs); spin_lock(&wc->reglock); } } rxs = (a & 0xc); if (!(wc->span.chans[i+2].sig & ZT_SIG_CLEAR)) { if (wc->span.chans[i+2].rxsig != rxs) { spin_unlock(&wc->reglock); zt_rbsbits(&wc->span.chans[i+2], rxs); spin_lock(&wc->reglock); } } rxs = (a >> 2) & 0xc; if (!(wc->span.chans[i+1].sig & ZT_SIG_CLEAR)) { if (wc->span.chans[i+1].rxsig != rxs) { spin_unlock(&wc->reglock); zt_rbsbits(&wc->span.chans[i+1], rxs); spin_lock(&wc->reglock); } } rxs = (a >> 4) & 0xc; if (!(wc->span.chans[i].sig & ZT_SIG_CLEAR)) { if (wc->span.chans[i].rxsig != rxs) { spin_unlock(&wc->reglock); zt_rbsbits(&wc->span.chans[i], rxs); spin_lock(&wc->reglock); } } } } } else { for (i = 0; i < 24; i+=2) { a = t1_getreg_isr(wc, 0x70 + (i>>1)); if (a > -1) { /* Get high channel in low bits */ rxs = (a & 0xf); if (!(wc->span.chans[i+1].sig & ZT_SIG_CLEAR)) { if (wc->span.chans[i+1].rxsig != rxs) { spin_unlock(&wc->reglock); zt_rbsbits(&wc->span.chans[i+1], rxs); spin_lock(&wc->reglock); } } rxs = (a >> 4) & 0xf; if (!(wc->span.chans[i].sig & ZT_SIG_CLEAR)) { if (wc->span.chans[i].rxsig != rxs) { spin_unlock(&wc->reglock); zt_rbsbits(&wc->span.chans[i], rxs); spin_lock(&wc->reglock); } } } } } } static int t1xxp_maint(struct zt_span *span, int cmd) { struct t1 *wc = span->pvt; if (wc->spantype == TYPE_E1) { switch (cmd) { case ZT_MAINT_NONE: module_printk("XXX Turn off local and remote loops E1 XXX\n"); break; case ZT_MAINT_LOCALLOOP: module_printk("XXX Turn on local loopback E1 XXX\n"); break; case ZT_MAINT_REMOTELOOP: module_printk("XXX Turn on remote loopback E1 XXX\n"); break; case ZT_MAINT_LOOPUP: module_printk("XXX Send loopup code E1 XXX\n"); break; case ZT_MAINT_LOOPDOWN: module_printk("XXX Send loopdown code E1 XXX\n"); break; case ZT_MAINT_LOOPSTOP: module_printk("XXX Stop sending loop codes E1 XXX\n"); break; default: module_printk("Unknown E1 maint command: %d\n", cmd); break; } } else { switch (cmd) { case ZT_MAINT_NONE: module_printk("XXX Turn off local and remote loops T1 XXX\n"); break; case ZT_MAINT_LOCALLOOP: module_printk("XXX Turn on local loop and no remote loop XXX\n"); break; case ZT_MAINT_REMOTELOOP: module_printk("XXX Turn on remote loopup XXX\n"); break; case ZT_MAINT_LOOPUP: t1_setreg(wc, 0x21, 0x50); /* FMR5: Nothing but RBS mode */ break; case ZT_MAINT_LOOPDOWN: t1_setreg(wc, 0x21, 0x60); /* FMR5: Nothing but RBS mode */ break; case ZT_MAINT_LOOPSTOP: t1_setreg(wc, 0x21, 0x40); /* FMR5: Nothing but RBS mode */ break; default: module_printk("Unknown T1 maint command: %d\n", cmd); break; } } return 0; } static int t1xxp_open(struct zt_chan *chan) { struct t1 *wc = chan->pvt; if (wc->dead) return -ENODEV; wc->usecount++; #ifndef LINUX26 MOD_INC_USE_COUNT; #else try_module_get(THIS_MODULE); #endif return 0; } static int t1xxp_close(struct zt_chan *chan) { struct t1 *wc = chan->pvt; wc->usecount--; #ifndef LINUX26 MOD_DEC_USE_COUNT; #else module_put(THIS_MODULE); #endif /* If we're dead, release us now */ if (!wc->usecount && wc->dead) t1_release(wc); return 0; } static int t1xxp_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data) { unsigned int x; struct t1 *wc = chan->pvt; switch (cmd) { case WCT4_GET_REGS: /* Since all register access was moved into the voicebus * module....this was removed. Although...why does the client * library need access to the registers (debugging)? \todo .. */ WARN_ON(1); return -ENOSYS; break; #ifdef VPM_SUPPORT case ZT_TONEDETECT: if (get_user(x, (int *) data)) return -EFAULT; if (!wc->vpm150m) return -ENOSYS; if (wc->vpm150m && (x && !vpmdtmfsupport)) return -ENOSYS; if (x & ZT_TONEDETECT_ON) { set_bit(chan->chanpos - 1, &wc->dtmfmask); module_printk("turning on tone detection\n"); } else { clear_bit(chan->chanpos - 1, &wc->dtmfmask); module_printk("turning off tone detection\n"); } if (x & ZT_TONEDETECT_MUTE) { if(wc->vpm150m) set_bit(chan->chanpos - 1, &wc->vpm150m->desireddtmfmutestate); } else { if(wc->vpm150m) clear_bit(chan->chanpos - 1, &wc->vpm150m->desireddtmfmutestate); } return 0; #endif default: return -ENOTTY; } return 0; } #ifdef VPM_SUPPORT #include "adt_lec.c" static int t1xxp_echocan_with_params(struct zt_chan *chan, struct zt_echocanparams *ecp, struct zt_echocanparam *p) { struct adt_lec_params params; struct t1 *wc = chan->pvt; struct vpm150m *vpm150m = wc->vpm150m; unsigned int flags; struct vpm150m_workentry *work; unsigned int ret; if (!wc->vpm150m) return -ENODEV; adt_lec_init_defaults(¶ms, 32); if ((ret = adt_lec_parse_params(¶ms, ecp, p))) return ret; /* we can't really control the tap length, but the value is used to control whether the ec is on or off, so translate it */ params.tap_length = ecp->tap_length ? 1 : 0; if (!(work = kmalloc(sizeof(*work), GFP_KERNEL))) return -ENOMEM; work->params = params; work->wc = wc; work->chan = chan; spin_lock_irqsave(&vpm150m->lock, flags); list_add_tail(&work->list, &vpm150m->worklist); spin_unlock_irqrestore(&vpm150m->lock, flags); /* we must do this later since we cannot sleep in the echocan function */ if (test_bit(VPM150M_ACTIVE, &vpm150m->control)) queue_work(vpm150m->wq, &vpm150m->work_echocan); return 0; /* how do I return the status since it is done later by the workqueue? */ } #endif static int t1_software_init(struct t1 *wc) { int x; struct pci_dev* dev; dev = voicebus_get_pci_dev(wc->vb); /* Find position */ for (x = 0; x < sizeof(ifaces) / sizeof(ifaces[0]); x++) { if (ifaces[x] == wc) { debug_printk(1, "software init for card %d\n",x); break; } } if (x == sizeof(ifaces) / sizeof(ifaces[0])) return -1; t4_serial_setup(wc); wc->num = x; sprintf(wc->span.name, "WCT1/%d", wc->num); snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Card %d", wc->variety, wc->num); wc->span.manufacturer = "Digium"; strncpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype) - 1); #if defined(VPM_SUPPORT) if (wc->vpm150m) strncat(wc->span.devicetype, " with VPMADT032", sizeof(wc->span.devicetype) - 1); #endif snprintf(wc->span.location, sizeof(wc->span.location) - 1, "PCI Bus %02d Slot %02d", dev->bus->number, PCI_SLOT(dev->devfn) + 1); wc->span.spanconfig = t1xxp_spanconfig; wc->span.chanconfig = t1xxp_chanconfig; wc->span.irq = dev->irq; wc->span.startup = t1xxp_startup; wc->span.shutdown = t1xxp_shutdown; wc->span.rbsbits = t1xxp_rbsbits; wc->span.maint = t1xxp_maint; wc->span.open = t1xxp_open; wc->span.close = t1xxp_close; wc->span.ioctl = t1xxp_ioctl; #ifdef VPM_SUPPORT wc->span.echocan_with_params = t1xxp_echocan_with_params; #endif if (wc->spantype == TYPE_E1) { if (unchannelized) wc->span.channels = 32; else wc->span.channels = 31; wc->span.spantype = "E1"; wc->span.linecompat = ZT_CONFIG_HDB3 | ZT_CONFIG_CCS | ZT_CONFIG_CRC4; wc->span.deflaw = ZT_LAW_ALAW; } else { wc->span.channels = 24; wc->span.spantype = "T1"; wc->span.linecompat = ZT_CONFIG_AMI | ZT_CONFIG_B8ZS | ZT_CONFIG_D4 | ZT_CONFIG_ESF; wc->span.deflaw = ZT_LAW_MULAW; } wc->span.chans = wc->chans; wc->span.flags = ZT_FLAG_RBS; wc->span.pvt = wc; init_waitqueue_head(&wc->span.maintq); for (x = 0; x < wc->span.channels; x++) { sprintf(wc->chans[x].name, "WCT1/%d/%d", wc->num, x + 1); wc->chans[x].sigcap = ZT_SIG_EM | ZT_SIG_CLEAR | ZT_SIG_EM_E1 | ZT_SIG_FXSLS | ZT_SIG_FXSGS | ZT_SIG_MTP2 | ZT_SIG_FXSKS | ZT_SIG_FXOLS | ZT_SIG_DACS_RBS | ZT_SIG_FXOGS | ZT_SIG_FXOKS | ZT_SIG_CAS | ZT_SIG_SF; wc->chans[x].pvt = wc; wc->chans[x].chanpos = x + 1; } if (zt_register(&wc->span, 0)) { module_printk("Unable to register span with Zaptel\n"); return -1; } wc->initialized = 1; return 0; } #ifdef VPM_SUPPORT static inline unsigned char t1_vpm_in(struct t1 *wc, int unit, const unsigned int addr) { return t1_getreg_full(wc, addr, 0, unit); } static inline unsigned char t1_vpm_out(struct t1 *wc, int unit, const unsigned int addr, const unsigned char val) { return t1_setreg_full(wc, addr, val, 0, unit); } #endif static int t1_hardware_post_init(struct t1 *wc) { unsigned int reg; int x; /* T1 or E1 */ if (t1e1override > -1) { if (t1e1override) wc->spantype = TYPE_E1; else wc->spantype = TYPE_T1; } else { if (t1_getpins(wc,0) & 0x01) /* returns 1 for T1 mode */ wc->spantype = TYPE_T1; else wc->spantype = TYPE_E1; } debug_printk(1, "spantype: %s\n", wc->spantype==1 ? "T1" : "E1"); if (wc->spantype == TYPE_E1) { if (unchannelized) wc->chanmap = chanmap_e1uc; else wc->chanmap = chanmap_e1; } else wc->chanmap = chanmap_t1; /* what version of the FALC are we using? */ reg = t1_setreg(wc, 0x4a, 0xaa); reg = t1_getreg(wc, 0x4a, 0); debug_printk(1, "FALC version: %08x\n", reg); /* make sure reads and writes work */ for (x = 0; x < 256; x++) { t1_setreg(wc, 0x14, x); if ((reg = t1_getreg(wc, 0x14, 0)) != x) module_printk("Wrote '%x' but read '%x'\n", x, reg); } /* all LED's blank */ wc->ledtestreg = UNSET_LED_ORANGE(wc->ledtestreg); wc->ledtestreg = UNSET_LED_REDGREEN(wc->ledtestreg); t1_setleds(wc, wc->ledtestreg, 0); #ifdef VPM_SUPPORT t1_vpm150m_init(wc); if (wc->vpm150m) { module_printk("VPM present and operational (Firmware version %x)\n", wc->vpm150m->version); wc->ctlreg |= 0x10; /* turn on vpm (RX audio from vpm module) */ if (vpmtsisupport) { debug_printk(1, "enabling VPM TSI pin\n"); wc->ctlreg |= 0x01; /* turn on vpm timeslot interchange pin */ } } #endif return 0; } static inline void __t1_check_alarms_reads(struct t1 *wc) { if (!(wc->span.flags & ZT_FLAG_RUNNING)) return; if (t1_getreg(wc, 0x4c, 1)) wc->isrreaderrors++; if (t1_getreg(wc, 0x20, 1)) wc->isrreaderrors++; if (t1_getreg(wc, 0x4d, 1)) wc->isrreaderrors++; } static inline void __t1_check_alarms(struct t1 *wc) { unsigned char c,d; int alarms; int x,j; unsigned char fmr4; /* must read this always */ if (!(wc->span.flags & ZT_FLAG_RUNNING)) return; c = t1_getreg_isr(wc, 0x4c); fmr4 = t1_getreg_isr(wc, 0x20); /* must read this even if we don't use it */ d = t1_getreg_isr(wc, 0x4d); /* Assume no alarms */ alarms = 0; /* And consider only carrier alarms */ wc->span.alarms &= (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_NOTOPEN); if (wc->spantype == TYPE_E1) { 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) { t1_setreg_full(wc, 0x20, 0x9f | 0x20, 1, NOT_VPM); /* LIM0: Force RAI High */ wc->flags.nmf = 1; module_printk("NMF workaround on!\n"); } t1_setreg_full(wc, 0x1e, 0xc3, 1, NOT_VPM); /* Reset to CRC4 mode */ t1_setreg_full(wc, 0x1c, 0xf2, 1, NOT_VPM); /* Force Resync */ t1_setreg_full(wc, 0x1c, 0xf0, 1, NOT_VPM); /* Force Resync */ } else if (!(c & 0x02)) { if (wc->flags.nmf) { t1_setreg_full(wc, 0x20, 0x9f, 1, NOT_VPM); /* LIM0: Clear forced RAI */ wc->flags.nmf = 0; module_printk("NMF workaround off!\n"); } } } else { /* Detect loopup code if we're not sending one */ if ((!wc->span.mainttimer) && (d & 0x08)) { /* Loop-up code detected */ if ((wc->loopupcnt++ > 80) && (wc->span.maintstat != ZT_MAINT_REMOTELOOP)) { t1_setreg_full(wc, 0x36, 0x08, 1, NOT_VPM); /* LIM0: Disable any local loop */ t1_setreg_full(wc, 0x37, 0xf6, 1, NOT_VPM); /* LIM1: Enable remote loop */ wc->span.maintstat = ZT_MAINT_REMOTELOOP; } } else wc->loopupcnt = 0; /* Same for loopdown code */ if ((!wc->span.mainttimer) && (d & 0x10)) { /* Loop-down code detected */ if ((wc->loopdowncnt++ > 80) && (wc->span.maintstat == ZT_MAINT_REMOTELOOP)) { t1_setreg_full(wc, 0x36, 0x08, 1, NOT_VPM); /* LIM0: Disable any local loop */ t1_setreg_full(wc, 0x37, 0xf0, 1, NOT_VPM); /* LIM1: Disable remote loop */ wc->span.maintstat = ZT_MAINT_NONE; } } else wc->loopdowncnt = 0; } if (wc->span.lineconfig & ZT_CONFIG_NOTOPEN) { for (x=0,j=0;x < wc->span.channels;x++) if ((wc->span.chans[x].flags & ZT_FLAG_OPEN) || (wc->span.chans[x].flags & ZT_FLAG_NETDEV)) j++; if (!j) alarms |= ZT_ALARM_NOTOPEN; } if (c & 0xa0) { if (wc->alarmcount >= alarmdebounce) { if (!unchannelized) alarms |= ZT_ALARM_RED; } else wc->alarmcount++; } else wc->alarmcount = 0; if (c & 0x4) alarms |= ZT_ALARM_BLUE; /* Keep track of recovering */ if ((!alarms) && wc->span.alarms) wc->alarmtimer = ZT_ALARMSETTLE_TIME; if (wc->alarmtimer) alarms |= ZT_ALARM_RECOVER; /* If receiving alarms, go into Yellow alarm state */ if (alarms && !wc->flags.sendingyellow) { module_printk("Setting yellow alarm\n"); /* We manually do yellow alarm to handle RECOVER and NOTOPEN, otherwise it's auto anyway */ t1_setreg_full(wc, 0x20, fmr4 | 0x20, 1, NOT_VPM); wc->flags.sendingyellow = 1; } else if (!alarms && wc->flags.sendingyellow) { module_printk("Clearing yellow alarm\n"); /* We manually do yellow alarm to handle RECOVER */ t1_setreg_full(wc, 0x20, fmr4 & ~0x20, 1, NOT_VPM); wc->flags.sendingyellow = 0; } if ((c & 0x10) && !unchannelized) alarms |= ZT_ALARM_YELLOW; if (wc->span.mainttimer || wc->span.maintstat) alarms |= ZT_ALARM_LOOPBACK; wc->span.alarms = alarms; spin_unlock(&wc->reglock); zt_alarm_notify(&wc->span); spin_lock(&wc->reglock); } static inline void __handle_leds(struct t1 *wc) { if (wc->span.alarms & (ZT_ALARM_RED | ZT_ALARM_BLUE)) { wc->blinktimer++; if (wc->blinktimer == 160) wc->ledtestreg = SET_LED_RED(wc->ledtestreg); if (wc->blinktimer == 480) { wc->ledtestreg = UNSET_LED_REDGREEN(wc->ledtestreg); wc->blinktimer = 0; } } else if (wc->span.alarms & ZT_ALARM_YELLOW) { wc->yellowtimer++; if (!(wc->yellowtimer % 2)) wc->ledtestreg = SET_LED_RED(wc->ledtestreg); else wc->ledtestreg = SET_LED_GREEN(wc->ledtestreg); } else { if (wc->span.maintstat != ZT_MAINT_NONE) wc->ledtestreg = SET_LED_ORANGE(wc->ledtestreg); else wc->ledtestreg = UNSET_LED_ORANGE(wc->ledtestreg); if (wc->span.flags & ZT_FLAG_RUNNING) wc->ledtestreg = SET_LED_GREEN(wc->ledtestreg); else wc->ledtestreg = UNSET_LED_REDGREEN(wc->ledtestreg); } if (wc->ledtestreg != wc->ledlastvalue) { t1_setleds(wc, wc->ledtestreg, 1); wc->ledlastvalue = wc->ledtestreg; } } static void __t1_do_counters(struct t1 *wc) { if (wc->alarmtimer) { if (!--wc->alarmtimer) { wc->span.alarms &= ~(ZT_ALARM_RECOVER); zt_alarm_notify(&wc->span); } } } static inline void t1_isr_misc(struct t1 *wc) { const unsigned int x = wc->intcount & 0x3f; int buffer_count = voicebus_current_latency(wc->vb); if (unlikely(!wc->initialized)) return; __handle_leds(wc); __t1_do_counters(wc); if ( 0 == x ) { __t1_check_sigbits_reads(wc); } else if ( 1 == x ) { if (!(wc->intcount & 0x30)) { __t1_check_alarms_reads(wc); wc->alarms_read=1; } } else if ( x == buffer_count*2) { __t1_check_sigbits(wc); } else if ( x == (buffer_count*2)+1 ) { if (wc->alarms_read) { __t1_check_alarms(wc); wc->alarms_read=0; } } else if ( x == (buffer_count*2)+2) { clean_leftovers(wc); } } static inline void t1_transmitprep(struct t1 *wc, unsigned char* writechunk) { int x; int y; int chan; /* Calculate Transmission */ if (likely(wc->initialized)) { spin_unlock(&wc->reglock); zt_transmit(&wc->span); spin_lock(&wc->reglock); } for (x = 0; x < ZT_CHUNKSIZE; x++) { if (likely(wc->initialized)) { for (chan = 0; chan < wc->span.channels; chan++) writechunk[(chan+1)*2] = wc->chans[chan].writechunk[x]; } /* process the command queue */ for (y = 0; y < 7; y++) { cmd_dequeue(wc, writechunk, x, y); } #ifdef VPM_SUPPORT if(likely(wc->vpm150m)) { vpm150m_cmd_dequeue(wc, writechunk, x); } #endif if (x < ZT_CHUNKSIZE - 1) { writechunk[EFRAME_SIZE] = wc->ctlreg; writechunk[EFRAME_SIZE + 1] = wc->txident++; } writechunk += (EFRAME_SIZE + EFRAME_GAP); } } static inline void cmd_retransmit(struct t1 *wc) { unsigned int x; for (x = 0; x < sizeof(wc->cmdq.cmds) / sizeof(wc->cmdq.cmds[0]); x++) { if (!(wc->cmdq.cmds[x].flags & __CMD_FIN)) { wc->cmdq.cmds[x].flags &= ~(__CMD_TX) ; /* clear __CMD_TX */ wc->cmdq.cmds[x].ident = 0; } } } static inline void t1_receiveprep(struct t1 *wc, unsigned char* readchunk) { int x,chan; unsigned char expected; for (x = 0; x < ZT_CHUNKSIZE; x++) { if (likely(wc->initialized)) { for (chan = 0; chan < wc->span.channels; chan++) { wc->chans[chan].readchunk[x]= readchunk[(chan+1)*2]; } } if (x < ZT_CHUNKSIZE - 1) { expected = wc->rxident+1; wc->rxident = readchunk[EFRAME_SIZE + 1]; wc->statreg = readchunk[EFRAME_SIZE + 2]; if (wc->rxident != expected) { wc->span.irqmisses++; cmd_retransmit(wc); if (unlikely(debug && wc->initialized)) module_printk("oops: rxident=%d expected=%d x=%d\n", wc->rxident, expected, x); } } cmd_decipher(wc, readchunk); #ifdef VPM_SUPPORT if(wc->vpm150m) vpm150m_cmd_decipher(wc, readchunk); #endif readchunk += (EFRAME_SIZE + EFRAME_GAP); } /* echo cancel */ if (likely(wc->initialized)) { spin_unlock(&wc->reglock); for (x = 0; x < wc->span.channels; x++) { zt_ec_chunk(&wc->chans[x], wc->chans[x].readchunk, wc->ec_chunk2[x]); memcpy(wc->ec_chunk2[x],wc->ec_chunk1[x],ZT_CHUNKSIZE); memcpy(wc->ec_chunk1[x],wc->chans[x].writechunk,ZT_CHUNKSIZE); } zt_receive(&wc->span); spin_lock(&wc->reglock); } /* Wake up anyone sleeping to read/write a new register */ wake_up_interruptible(&wc->regq); } static void t1_handle_transmit(void* vbb, void* context) { struct t1* wc = context; /* Either this function is called from within interrupt context, or * the reglock will never be acquired from interrupt context, so it's * safe to grab it without locking interrupt. */ memset(vbb, 0, SFRAME_SIZE); spin_lock(&wc->reglock); wc->txints++; t1_transmitprep(wc, vbb); wc->intcount++; t1_isr_misc(wc); spin_unlock(&wc->reglock); voicebus_transmit(wc->vb, vbb); } static void t1_handle_receive(void* vbb, void* context) { struct t1* wc = context; wc->rxints++; /* Either this function is called from within interrupt context, or * the reglock will never be acquired from interrupt context, so it's * safe to grab it without locking interrupt. */ spin_lock(&wc->reglock); t1_receiveprep(wc, vbb); spin_unlock(&wc->reglock); } static int __devinit te12xp_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { struct t1 *wc; struct t1_desc *d = (struct t1_desc *) ent->driver_data; unsigned int x; int res; int startinglatency; for (x = 0; x < sizeof(ifaces) / sizeof(ifaces[0]); x++) if (!ifaces[x]) break; if (x >= sizeof(ifaces) / sizeof(ifaces[0])) { module_printk("Too many interfaces\n"); return -EIO; } retry: wc = kmalloc(sizeof(*wc), GFP_KERNEL); if (!wc) return -ENOMEM; ifaces[x] = wc; memset(wc, 0, sizeof(*wc)); spin_lock_init(&wc->reglock); wc->variety = d->name; wc->txident = 1; init_waitqueue_head(&wc->regq); snprintf(wc->name, sizeof(wc->name)-1, "wcte12xp%d", x); if ((res=voicebus_init(pdev, SFRAME_SIZE, wc->name, t1_handle_receive, t1_handle_transmit, wc, &wc->vb))) { WARN_ON(1); kfree(wc); return res; } /* Keep track of which device we are */ pci_set_drvdata(pdev, wc); if (VOICEBUS_DEFAULT_LATENCY != latency) { voicebus_set_minlatency(wc->vb, latency); } voicebus_start(wc->vb); startinglatency = voicebus_current_latency(wc->vb); t1_hardware_post_init(wc); t1_software_init(wc); if (voicebus_current_latency(wc->vb) > startinglatency) { /* The voicebus library increased the latency during * initialization because the host wasn't able to service the * interrupts from the adapter quickly enough. In this case, * we'll increase our latency and restart the initialization. */ printk(KERN_NOTICE "%s: Restarting board initialization " \ "after increasing latency.\n", wc->name); latency = voicebus_current_latency(wc->vb); zt_unregister(&wc->span); voicebus_release(wc->vb); wc->vb = NULL; kfree(wc); wc = NULL; goto retry; } module_printk("Found a %s\n", wc->variety); return 0; } static void __devexit te12xp_remove_one(struct pci_dev *pdev) { struct t1 *wc = pci_get_drvdata(pdev); #ifdef VPM_SUPPORT unsigned long flags; struct vpm150m *vpm150m = wc->vpm150m; #endif if (!wc) return; #ifdef VPM_SUPPORT if(vpm150m) { clear_bit(VPM150M_DTMFDETECT, &vpm150m->control); clear_bit(VPM150M_ACTIVE, &vpm150m->control); flush_workqueue(vpm150m->wq); destroy_workqueue(vpm150m->wq); } #endif BUG_ON(!wc->vb); voicebus_release(wc->vb); wc->vb = NULL; if (debug && wc->isrreaderrors) debug_printk(1, "isrreaderrors=%d\n", wc->isrreaderrors); #ifdef VPM_SUPPORT if(vpm150m) { spin_lock_irqsave(&wc->reglock, flags); wc->vpm150m = NULL; vpm150m->wc = NULL; spin_unlock_irqrestore(&wc->reglock, flags); kfree(wc->vpm150m); } #endif /* Release span, possibly delayed */ if (!wc->usecount) t1_release(wc); else wc->dead = 1; } static struct pci_device_id te12xp_pci_tbl[] = { { 0xd161, 0x0120, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &te120p}, { 0xd161, 0x8000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &te121}, { 0xd161, 0x8001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &te122}, { 0 } }; MODULE_DEVICE_TABLE(pci, te12xp_pci_tbl); struct pci_driver te12xp_driver = { name: "wcte12xp", probe: te12xp_init_one, #ifdef LINUX26 remove: __devexit_p(te12xp_remove_one), #else remove: te12xp_remove_one, #endif suspend: NULL, resume: NULL, id_table: te12xp_pci_tbl, }; static int __init te12xp_init(void) { int res; res = zap_pci_module(&te12xp_driver); return res ? -ENODEV : 0; } static void __exit te12xp_cleanup(void) { pci_unregister_driver(&te12xp_driver); } #ifdef LINUX26 module_param(debug, int, S_IRUGO | S_IWUSR); module_param(loopback, int, S_IRUGO | S_IWUSR); module_param(t1e1override, int, S_IRUGO | S_IWUSR); module_param(j1mode, int, S_IRUGO | S_IWUSR); module_param(alarmdebounce, int, S_IRUGO | S_IWUSR); module_param(latency, int, S_IRUGO | S_IWUSR); #ifdef VPM_SUPPORT module_param(vpmsupport, int, S_IRUGO | S_IWUSR); module_param(vpmdtmfsupport, int, S_IRUGO | S_IWUSR); module_param(vpmtsisupport, int, S_IRUGO | S_IWUSR); #endif #else MODULE_PARM(debug, "i"); MODULE_PARM(loopback, "i"); MODULE_PARM(t1e1override, "i"); MODULE_PARM(j1mode, "i"); MODULE_PARM(alarmdebounce, "i"); #ifdef VPM_SUPPORT MODULE_PARM(vpmsupport, "i"); MODULE_PARM(vpmdtmfsupport, "i"); MODULE_PARM(vpmtsisupport, "i"); MODULE_PARM(vpmnlptype, "i"); MODULE_PARM(vpmnlpthresh, "i"); MODULE_PARM(vpmnlpmaxsupp, "i"); #endif #endif #ifdef MODULE_LICENSE MODULE_LICENSE("GPL"); #endif module_init(te12xp_init); module_exit(te12xp_cleanup); zaptel-1.4.11/kernel/wcte12xp/Kbuild0000644000000000000000000000111110773007372015665 0ustar rootrootobj-m += wcte12xp.o FIRM_DIR := ../../firmware EXTRA_CFLAGS := -I$(src)/.. -Wno-undef ifeq ($(HOTPLUG_FIRMWARE),yes) EXTRA_CFLAGS+=-DHOTPLUG_FIRMWARE endif wcte12xp-objs := base.o vpmadt032.o GpakApi.o ../voicebus.o ifneq ($(HOTPLUG_FIRMWARE),yes) wcte12xp-objs += $(FIRM_DIR)/zaptel-fw-vpmadt032.o endif $(obj)/$(FIRM_DIR)/zaptel-fw-vpmadt032.o: $(obj)/base.o $(MAKE) -C $(obj)/$(FIRM_DIR) zaptel-fw-vpmadt032.o $(obj)/base.o: $(src)/vpmadt032.h $(src)/wcte12xp.h $(obj)/base.o: $(src)/../zaptel.h $(obj)/vpmadt032.o: $(src)/vpmadt032.h $(obj)/GpakApi.o: $(src)/GpakApi.h zaptel-1.4.11/kernel/wcte12xp/GpakApi.h0000644000000000000000000006202310775452562016235 0ustar rootroot/* * Copyright (c) 2005 , Adaptive Digital Technologies, Inc. * * File Name: GpakApi.h * * Description: * This file contains the function prototypes and data types for the user * API functions that communicate with DSPs executing G.PAK software. The * file is used by application software in the host processor connected to * C55X G.PAK DSPs via a Host Port Interface. * * Version: 1.0 * * Revision History: * 06/15/05 - Initial release. * 11/15/2006 - 24 TDM-TDM Channels EC release * * This program has been released under the terms of the GPL version 2 by * permission of Adaptive Digital Technologies, Inc. The standard * GPL disclaimer is given inline below for your convenience. * * 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 _GPAKAPI_H /* prevent multiple inclusion */ #define _GPAKAPI_H #include "GpakErrs.h" #include "gpakenum.h" // Bit masks to select which algorithm's parameters to update: Or-together the // desired masks into the UpdateBits function parameter. #define DTMF_UPDATE_MASK 0x0010 // update DTMF params, MinLevel, SNRFlag and Freq #define DTMF_TWIST_UPDATE_MASK 0x0020 // update DTMF TWIST system params #define DTMF_VALID_MASK 0x0080 // update DTMF ValidMask params #define DSP_DEBUG_BUFF_SIZE 42 // units of 16-bit words /* Definition of an Asynchronous Event Data Structure */ typedef union { struct { GpakToneCodes_t ToneCode; // detected tone code unsigned short int ToneDuration; // tone duration GpakTdmDirection Direction; // detected on A r B side short int DebugToneStatus;// reserved for debug info } toneEvent; } GpakAsyncEventData_t; /* Definition of an Echo Canceller Parameters information structure. */ typedef struct { short int EcanTapLength; // Echo Can Num Taps (tail length) short int EcanNlpType; // Echo Can NLP Type short int EcanAdaptEnable; // Echo Can Adapt Enable flag short int EcanG165DetEnable; // Echo Can G165 Detect Enable flag short int EcanDblTalkThresh; // Echo Can Double Talk threshold short int EcanNlpThreshold; // Echo Can NLP threshold short int EcanNlpConv; // Dynamic NLP control, NLP limit when EC about to converged short int EcanNlpUnConv;// Dynamic NLP control, NLP limit when EC not converged yet short int EcanNlpMaxSuppress; // suppression level for NLP_SUPP mode short int EcanCngThreshold; // Echo Can CNG Noise threshold short int EcanAdaptLimit; // Echo Can Max Adapts per frame short int EcanCrossCorrLimit; // Echo Can Cross Correlation limit short int EcanNumFirSegments; // Echo Can Num FIR Segments short int EcanFirSegmentLen; // Echo Can FIR Segment Length } GpakEcanParms_t; /* Definition of a Channel Configuration information structure. */ typedef struct { GpakSerialPort_t PcmInPortA; // A side PCM Input Serial Port Id unsigned short int PcmInSlotA; // A side PCM Input Time Slot GpakSerialPort_t PcmOutPortA; // A side PCM Output Serial Port Id unsigned short int PcmOutSlotA; // A side PCM Output Time Slot GpakSerialPort_t PcmInPortB; // B side PCM Input Serial Port Id unsigned short int PcmInSlotB; // B side PCM Input Time Slot GpakSerialPort_t PcmOutPortB; // B side PCM Output Serial Port Id unsigned short int PcmOutSlotB; // B side PCM Output Time Slot GpakToneTypes ToneTypesA; // A side Tone Detect Types GpakToneTypes ToneTypesB; // B side Tone Detect Types GpakActivation EcanEnableA; // Echo Cancel A Enabled GpakActivation EcanEnableB; // Echo Cancel B Enabled GpakEcanParms_t EcanParametersA; // Echo Cancel parameters GpakEcanParms_t EcanParametersB; // Echo Cancel parameters GpakCompandModes SoftwareCompand; // software companding GpakRate_t FrameRate; // Gpak Frame Rate GpakActivation MuteToneA; // A side mute DTMF Enabled GpakActivation MuteToneB; // B side mute DTMF Enabled GpakActivation FaxCngDetA; // A side FaxCng Tone Detector Enabled GpakActivation FaxCngDetB; // B side FaxCng Tone Detector Enabled } GpakChannelConfig_t; /* Definition of a Serial Port Configuration Structure */ typedef struct { GpakSlotCfg_t SlotsSelect1; // port 1 Slot selection unsigned short int FirstBlockNum1; // port 1 first group Block Number unsigned short int FirstSlotMask1; // port 1 first group Slot Mask unsigned short int SecBlockNum1; // port 1 second group Block Number unsigned short int SecSlotMask1; // port 1 second group Slot Mask GpakSerWordSize_t SerialWordSize1; // port 1 serial word size GpakCompandModes CompandingMode1; // port 1 companding mode GpakSerFrameSyncPol_t TxFrameSyncPolarity1; // port 1 Tx Frame Sync Polarity GpakSerFrameSyncPol_t RxFrameSyncPolarity1; // port 1 Rx Frame Sync Polarity GpakSerClockPol_t TxClockPolarity1; // port 1 Tx Clock Polarity GpakSerClockPol_t RxClockPolarity1; // port 1 Rx Clock Polarity GpakSerDataDelay_t TxDataDelay1; // port 1 Tx data delay GpakSerDataDelay_t RxDataDelay1; // port 1 Rx data delay GpakActivation DxDelay1; // port 1 DX Delay unsigned short int ThirdSlotMask1; // port 1 3rd group Slot Mask unsigned short int FouthSlotMask1; // port 1 4th group Slot Mask unsigned short int FifthSlotMask1; // port 1 5th group Slot Mask unsigned short int SixthSlotMask1; // port 1 6th group Slot Mask unsigned short int SevenSlotMask1; // port 1 7th group Slot Mask unsigned short int EightSlotMask1; // port 1 8th group Slot Mask GpakSlotCfg_t SlotsSelect2; // port 2 Slot selection unsigned short int FirstBlockNum2; // port 2 first group Block Number unsigned short int FirstSlotMask2; // port 2 first group Slot Mask unsigned short int SecBlockNum2; // port 2 second group Block Number unsigned short int SecSlotMask2; // port 2 second group Slot Mask GpakSerWordSize_t SerialWordSize2; // port 2 serial word size GpakCompandModes CompandingMode2; // port 2 companding mode GpakSerFrameSyncPol_t TxFrameSyncPolarity2; // port 2 Tx Frame Sync Polarity GpakSerFrameSyncPol_t RxFrameSyncPolarity2; // port 2 Rx Frame Sync Polarity GpakSerClockPol_t TxClockPolarity2; // port 2 Tx Clock Polarity GpakSerClockPol_t RxClockPolarity2; // port 2 Rx Clock Polarity GpakSerDataDelay_t TxDataDelay2; // port 2 Tx data delay GpakSerDataDelay_t RxDataDelay2; // port 2 Rx data delay GpakActivation DxDelay2; // port 2 DX Delay unsigned short int ThirdSlotMask2; // port 2 3rd group Slot Mask unsigned short int FouthSlotMask2; // port 2 4th group Slot Mask unsigned short int FifthSlotMask2; // port 2 5th group Slot Mask unsigned short int SixthSlotMask2; // port 2 6th group Slot Mask unsigned short int SevenSlotMask2; // port 2 7th group Slot Mask unsigned short int EightSlotMask2; // port 2 8th group Slot Mask GpakSlotCfg_t SlotsSelect3; // port 3 Slot selection unsigned short int FirstBlockNum3; // port 3 first group Block Number unsigned short int FirstSlotMask3; // port 3 first group Slot Mask unsigned short int SecBlockNum3; // port 3 second group Block Number unsigned short int SecSlotMask3; // port 3 second group Slot Mask GpakSerWordSize_t SerialWordSize3; // port 3 serial word size GpakCompandModes CompandingMode3; // port 3 companding mode GpakSerFrameSyncPol_t TxFrameSyncPolarity3; // port 3 Tx Frame Sync Polarity GpakSerFrameSyncPol_t RxFrameSyncPolarity3; // port 3 Rx Frame Sync Polarity GpakSerClockPol_t TxClockPolarity3; // port 3 Tx Clock Polarity GpakSerClockPol_t RxClockPolarity3; // port 3 Rx Clock Polarity GpakSerDataDelay_t TxDataDelay3; // port 3 Tx data delay GpakSerDataDelay_t RxDataDelay3; // port 3 Rx data delay GpakActivation DxDelay3; // port 3 DX Delay unsigned short int ThirdSlotMask3; // port 3 3rd group Slot Mask unsigned short int FouthSlotMask3; // port 3 4th group Slot Mask unsigned short int FifthSlotMask3; // port 3 5th group Slot Mask unsigned short int SixthSlotMask3; // port 3 6th group Slot Mask unsigned short int SevenSlotMask3; // port 3 7th group Slot Mask unsigned short int EightSlotMask3; // port 3 8th group Slot Mask } GpakPortConfig_t; /* Definition of a Tone Generation Parameter Structure */ /* typedef struct { GpakToneGenType_t ToneType; // Tone Type unsigned short int Frequency[4]; // Frequency (Hz) short int Level[4]; // Frequency's Level (1 dBm) unsigned short int OnTime[4]; // On Times (msecs) unsigned short int OffTime[4]; // Off Times (msecs) } GpakToneGenParms_t; */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* gpakConfigureChannel return status. */ typedef enum { CcsSuccess = 0, /* Channel Configured successfully */ CcsParmError = 1, /* Channel Config Parameter error */ CcsInvalidChannel = 2, /* invalid channel */ CcsInvalidDsp = 3, /* invalid DSP */ CcsDspCommFailure = 4 /* failed to communicate with DSP */ } gpakConfigChanStatus_t; /* * gpakConfigureChannel - Configure a DSP's Channel. * * FUNCTION * This function configures a DSP's Channel. * * RETURNS * Status code indicating success or a specific error. * */ extern gpakConfigChanStatus_t gpakConfigureChannel( unsigned short int DspId, // DSP identifier unsigned short int ChannelId, // channel identifier GpakChanType ChannelType, // channel type GpakChannelConfig_t *pChanConfig, // pointer to channel config info GPAK_ChannelConfigStat_t *pStatus // pointer to Channel Config Status ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* gpakTearDownChannel return status. */ typedef enum { TdsSuccess = 0, /* Channel Tear Down successful */ TdsError = 1, /* Channel Tear Down error */ TdsInvalidChannel = 2, /* invalid channel */ TdsInvalidDsp = 3, /* invalid DSP */ TdsDspCommFailure = 4 /* failed to communicate with DSP */ } gpakTearDownStatus_t; /* * gpakTearDownChannel - Tear Down a DSP's Channel. * * FUNCTION * This function tears down a DSP's Channel. * * RETURNS * Status code indicating success or a specific error. * */ extern gpakTearDownStatus_t gpakTearDownChannel( unsigned short int DspId, // DSP identifier unsigned short int ChannelId, // channel identifier GPAK_TearDownChanStat_t *pStatus // pointer to Tear Down Status ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* gpakAlgControl return status. */ typedef enum { AcSuccess = 0, /* control successful */ AcInvalidChannel = 1, /* invalid channel identifier */ AcInvalidDsp = 2, /* invalid DSP */ AcParmError = 3, /* invalid control parameter */ AcDspCommFailure = 4 /* failed to communicate with DSP */ } gpakAlgControlStat_t; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakAlgControl - Control an Algorithm. * * FUNCTION * This function controls an Algorithm * * RETURNS * Status code indicating success or a specific error. * */ extern gpakAlgControlStat_t gpakAlgControl( unsigned short int DspId, // DSP identifier unsigned short int ChannelId, // channel identifier GpakAlgCtrl_t ControlCode, // algorithm control code GPAK_AlgControlStat_t *pStatus // pointer to return status ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* gpakConfigurePorts return status. */ typedef enum { CpsSuccess = 0, /* Serial Ports configured successfully */ CpsParmError = 1, /* Configure Ports Parameter error */ CpsInvalidDsp = 2, /* invalid DSP */ CpsDspCommFailure = 3 /* failed to communicate with DSP */ } gpakConfigPortStatus_t; /* * gpakConfigurePorts - Configure a DSP's serial ports. * * FUNCTION * This function configures a DSP's serial ports. * * RETURNS * Status code indicating success or a specific error. * */ extern gpakConfigPortStatus_t gpakConfigurePorts( unsigned short int DspId, // DSP identifier GpakPortConfig_t *pPortConfig, // pointer to Port Config info GPAK_PortConfigStat_t *pStatus // pointer to Port Config Status ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* gpakDownloadDsp return status. */ typedef enum { GdlSuccess = 0, /* DSP download successful */ GdlFileReadError = 1, /* error reading Download file */ GdlInvalidFile = 2, /* invalid Download file content */ GdlInvalidDsp = 3 /* invalid DSP */ } gpakDownloadStatus_t; /* * gpakDownloadDsp - Download a DSP's Program and initialized Data memory. * * FUNCTION * This function reads a DSP's Program and Data memory image from the * specified file and writes the image to the DSP's memory. * * RETURNS * Status code indicating success or a specific error. * */ extern gpakDownloadStatus_t gpakDownloadDsp( unsigned short int DspId, // DSP identifier GPAK_FILE_ID FileId // G.PAK download file identifier ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* gpakReadEventFIFOMessage return status */ typedef enum { RefEventAvail = 0, /* an event was successfully read from the fifo */ RefNoEventAvail = 1, /* no event was in the fifo */ RefInvalidDsp = 2, /* invalid DSP identifier */ RefInvalidEvent = 3, /* invalid event */ RefDspCommFailure = 4 /* error communicating with DSP */ } gpakReadEventFIFOMessageStat_t; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadEventFIFOMessage - read from the event fifo * * FUNCTION * This function reads a single event from the event fifo if one is available * * RETURNS * Status code indicating success or a specific error. * * Note: This function should be called in a loop until the return status * indicates that the fifo is empty. */ extern gpakReadEventFIFOMessageStat_t gpakReadEventFIFOMessage( unsigned short int DspId, // DSP identifier unsigned short int *pChannelId, // pointer to channel identifier GpakAsyncEventCode_t *pEventCode, // pointer to Event Code GpakAsyncEventData_t *pEventData // pointer to Event Data Struct ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /* gpakPingDsp return status values */ typedef enum { PngSuccess = 0, /* DSP responded successfully */ PngInvalidDsp = 1, /* invalid DSP identifier */ PngDspCommFailure = 2 /* error communicating with DSP */ } gpakPingDspStat_t; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakPingDsp - ping the DSP to see if it's alive * * FUNCTION * This function checks if the DSP is still communicating with the host * * RETURNS * Status code indicating success or a specific error. */ extern gpakPingDspStat_t gpakPingDsp( unsigned short int DspId, // DSP identifier unsigned short int *pDspSwVersion // DSP software version ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /* gpakSerialTxFixedValue return status values */ typedef enum { TfvSuccess = 0, /* operation successful */ TfvInvalidChannel = 1, /* invalid channel identifier */ TfvInvalidDsp = 2, /* invalid DSP identifier */ TfvDspCommFailure = 3 /* failed to communicate with DSP */ } gpakSerialTxFixedValueStat_t; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakSerialTxFixedValue - transmit a fixed value on a timeslot * * FUNCTION * This function controls transmission of a fixed value out onto a serial * port's timeslot. * * RETURNS * Status code indicating success or a specific error. */ extern gpakSerialTxFixedValueStat_t gpakSerialTxFixedValue( unsigned short int DspId, // DSP identifier unsigned short int ChannelId, // channel identifier GpakSerialPort_t PcmOutPort, // PCM Output Serial Port Id unsigned short int PcmOutSlot, // PCM Output Time Slot unsigned short int Value, // 16-bit value GpakActivation State // activation state ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /* gpakControlTdmLoopBack return status values */ typedef enum { ClbSuccess = 0, /* operation successful */ ClbSerPortInactive = 1, /* serial port is inactive */ ClbInvalidDsp = 2, /* invalid DSP identifier */ ClbDspCommFailure = 3 /* failed to communicate with DSP */ } gpakControlTdmLoopBackStat_t; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakControlTdmLoopBack - control a serial port's loopback state * * FUNCTION * This function enables/disables the tdm input to output looback mode on a * serial port * * RETURNS * Status code indicating success or a specific error. */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ gpakControlTdmLoopBackStat_t gpakControlTdmLoopBack( unsigned short int DspId, // DSP identifier GpakSerialPort_t SerialPort, // Serial Port Id GpakActivation LoopBackState // Loopback State ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /* gpakReadCpuUsage return status values */ typedef enum { RcuSuccess = 0, /* operation successful */ RcuInvalidDsp = 1, /* invalid DSP identifier */ RcuDspCommFailure = 2 /* communication failure */ } gpakReadCpuUsageStat_t; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadCpuUsage - read the cpu usage statistics * * FUNCTION * This function reads cpu utilization from the DSP. * * RETURNS * Status code indicating success or a specific error. */ extern gpakReadCpuUsageStat_t gpakReadCpuUsage( unsigned short int DspId, // DSP identifier unsigned short int *pPeakUsage, // pointer to peak usage variable unsigned short int *pPrev1SecPeakUsage // peak usage over previous 1 second ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /* gpakResetCpuUsageStats return status values */ typedef enum { RstcSuccess = 0, /* operation successful */ RstcInvalidDsp = 1, /* invalid DSP identifier */ RstcDspCommFailure = 2 /* communication failure */ } gpakResetCpuUsageStat_t; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakResetCpuUsageStats - reset the cpu usage statistics * * FUNCTION * This function resets the cpu utilization statistics * * RETURNS * Status code indicating success or a specific error. */ extern gpakResetCpuUsageStat_t gpakResetCpuUsageStats( unsigned short int DspId // DSP identifier ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /* gpakReadFramingStats return status values */ typedef enum { RfsSuccess = 0, /* operation successful */ RfsInvalidDsp = 1, /* invalid DSP identifier */ RfsDspCommFailure = 2 /* communication failure */ } gpakReadFramingStatsStatus_t; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadFramingStats * * FUNCTION * This function reads a DSP's framing interrupt statistics * * RETURNS * Status code indicating success or a specific error. */ extern gpakReadFramingStatsStatus_t gpakReadFramingStats( unsigned short int DspId, // DSP identifier unsigned short int *pFramingError1Count, // port 1 Framing error count unsigned short int *pFramingError2Count, // port 2 Framing error count unsigned short int *pFramingError3Count, // port 3 Framing error count unsigned short int *pDmaStopErrorCount, // DMA-stoppage error count unsigned short int *pDmaSlipStatsBuffer // DMA slips count ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /* gpakResetFramingStats return values */ typedef enum { RstfSuccess = 0, /* operation successful */ RstfInvalidDsp = 1, /* invalid DSP identifier */ RstfDspCommFailure = 2 /* communication failure */ } gpakResetFramingStatsStatus_t; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakResetFramingStats - reset a DSP's framing interrupt statistics * * FUNCTION * This function resets a DSP's framing interrupt statistics * * RETURNS * Status code indicating success or a specific error. */ extern gpakResetFramingStatsStatus_t gpakResetFramingStats( unsigned short int DspId // DSP identifier ); typedef enum { RmmSuccess =0, RmmInvalidDsp = 1, RmmSizeTooBig = 2, RmmFailure = 3, RmmInvalidAddress = 4 } gpakReadDSPMemoryStat_t; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakResetFramingStats - read a section of DSP memory * to get access DSP registers, since 0x00--0x60 not HPI-accessable * * FUNCTION * This function resets a DSP's framing interrupt statistics * * RETURNS * Status code indicating success or a specific error. */ extern gpakReadDSPMemoryStat_t gpakReadDSPMemoryMap( unsigned short int DspId, // Dsp Identifier unsigned short int *pDest, // Buffer on host to hold DSP memory map DSP_ADDRESS BufrBaseAddress, // DSP memory users want to read out unsigned short int MemoryLength_Word16 // Length of memory section read out, unit is 16-bit word ); typedef enum { GPIOSuccess =0, GPIOInvalidDsp = 1, GPIODspCommFailure = 2 }gpakAccessGPIOStat_t; extern gpakAccessGPIOStat_t gpakAccessGPIO( unsigned short int DspId, // DSP identifier GpakGPIOCotrol_t gpakControlGPIO,// select oeration, changeDIR/write/read unsigned short int *pGPIOValue // pointer for the read/write value or DIR mask ); /* gpakWriteSystemParms return status. */ typedef enum { WspSuccess = 0, /* System Parameters written successfully */ WspParmError = 1, /* Write System Parms's Parameter error */ WspInvalidDsp = 2, /* invalid DSP */ WspDspCommFailure = 3 /* failed to communicate with DSP */ } gpakWriteSysParmsStatus_t; /* Definition of a System Parameters information structure. */ typedef struct { /* DTMF Parameters */ short int MinSigLevel; /* 0 = Disabled, Min Sig Power Level for detection */ short int SNRFlag; /* 0 = Disabled, relax SNR tolerances */ short int FreqDeviation; /* 0 = Disabled, X Percent Deviation times 10 (e.g. 1.7% is entered as 17) */ short int DtmfFwdTwist; /* 0 to 8 db */ short int DtmfRevTwist; /* 0 to 8 db */ short int DtmfValidityMask; /* This flag allows users to relax the trailing conditions of the tone */ } GpakSystemParms_t; /* gpakReadSystemParms return status. */ typedef enum { RspSuccess = 0, /* System Parameters read successfully */ RspInvalidDsp = 1, /* invalid DSP */ RspDspCommFailure = 2 /* failed to communicate with DSP */ } gpakReadSysParmsStatus_t; extern gpakReadSysParmsStatus_t gpakReadSystemParms( unsigned short int DspId, // DSP identifier GpakSystemParms_t *pSysParms /* pointer to System Parms info var */ ); extern gpakWriteSysParmsStatus_t gpakWriteSystemParms( unsigned short int DspId, // DSP identifier GpakSystemParms_t *pSysParms, /* pointer to System Parms info var */ unsigned short int UpdateBits, /* input: flags indicating which parms to update */ GPAK_SysParmsStat_t *pStatus /* pointer to Write System Parms Status */ ); #endif // end multiple inclusion zaptel-1.4.11/kernel/wcte12xp/GpakApi.c0000644000000000000000000016540110775452562016234 0ustar rootroot/* * 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. The standard * GPL disclaimer is given inline below for your convenience. * * 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 "zaptel.h" #include "GpakHpi.h" #include "vpmadt032.h" #include "GpakApi.h" #include "gpakenum.h" #ifdef VPM_SUPPORT /* DSP to Host interface block offsets. */ #define REPLY_MSG_PNTR_OFFSET 0 /* I/F blk offset to Reply Msg Pointer */ #define CMD_MSG_PNTR_OFFSET 2 /* I/F blk offset to Command Msg Pointer */ #define EVENT_MSG_PNTR_OFFSET 4 /* I/F blk offset to Event Msg Pointer */ #define PKT_BUFR_MEM_OFFSET 6 /* I/F blk offset to Packet Buffer memory */ #define DSP_STATUS_OFFSET 8 /* I/F blk offset to DSP Status */ #define VERSION_ID_OFFSET 9 /* I/F blk offset to G.PAK Version Id */ #define MAX_CMD_MSG_LEN_OFFSET 10 /* I/F blk offset to Max Cmd Msg Length */ #define CMD_MSG_LEN_OFFSET 11 /* I/F blk offset to Command Msg Length */ #define REPLY_MSG_LEN_OFFSET 12 /* I/F blk offset to Reply Msg Length */ #define NUM_CHANNELS_OFFSET 13 /* I/F blk offset to Num Built Channels */ #define NUM_PKT_CHANNELS_OFFSET 14 /* I/F blk offset to Num Pkt Channels */ #define NUM_CONFERENCES_OFFSET 15 /* I/F blk offset to Num Conferences */ //#define CPU_USAGE_OFFSET_1MS 16 /* I/F blk offset to CPU Usage statistics */ #define CPU_USAGE_OFFSET 18 /* I/F blk offset to CPU Usage statistics */ //#define CPU_USAGE_OFFSET_10MS 20 /* I/F blk offset to CPU Usage statistics */ #define FRAMING_STATS_OFFSET 22 /* I/F blk offset to Framing statistics */ //#define GPAK_RELEASE_Rate rate10ms // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = // Macro to reconstruct a 32-bit value from two 16-bit values. // Parameter p32: 32-bit-wide destination // Parameter p16: 16-bit-wide source array of length 2 words #define RECONSTRUCT_LONGWORD(p32, p16) p32 = (DSP_ADDRESS)p16[0]<<16; \ p32 |= (unsigned long)p16[1] // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = /* DSP Status value definitions. */ #define DSP_INIT_STATUS 0x5555 /* DSP Initialized status value */ #define HOST_INIT_STATUS 0xAAAA /* Host Initialized status value */ /* Circular packet buffer information structure offsets. */ #define CB_BUFR_BASE 0 /* pointer to base of circular buffer */ #define CB_BUFR_SIZE 2 /* size of buffer (words) */ #define CB_BUFR_PUT_INDEX 3 /* offset in buffer for next write */ #define CB_BUFR_TAKE_INDEX 4 /* offset in buffer for next read */ #define CIRC_BUFFER_INFO_STRUCT_SIZE 6 /* Miscellaneous definitions. */ #define MSG_BUFFER_SIZE 100 /* size (words) of Host msg buffer */ #define WORD_BUFFER_SIZE 84 /* size of DSP Word buffer (words) */ #ifdef __TMS320C55XX__ // debug sections if not on host #pragma DATA_SECTION(pDspIfBlk,"GPAKAPIDEBUG_SECT") #pragma DATA_SECTION(MaxCmdMsgLen,"GPAKAPIDEBUG_SECT") #pragma DATA_SECTION(MaxChannels,"GPAKAPIDEBUG_SECT") #pragma DATA_SECTION(DlByteBufr,"GPAKAPIDEBUG_SECT") #pragma DATA_SECTION(DlWordBufr,"GPAKAPIDEBUG_SECT") #pragma DATA_SECTION(pEventFifoAddress,"GPAKAPIDEBUG_SECT") #endif /* Host variables related to Host to DSP interface. */ static DSP_ADDRESS pDspIfBlk[MAX_DSP_CORES]; /* DSP address of I/F block */ static DSP_WORD MaxCmdMsgLen[MAX_DSP_CORES]; /* max Cmd msg length (octets) */ static unsigned short int MaxChannels[MAX_DSP_CORES]; /* max num channels */ //static unsigned short int MaxPktChannels[MAX_DSP_CORES]; /* max num pkt channels */ //static unsigned short int MaxConfs[MAX_DSP_CORES]; /* max num conferences */ //static DSP_ADDRESS pPktInBufr[MAX_DSP_CORES][MAX_PKT_CHANNELS]; /* Pkt In buffer */ //static DSP_ADDRESS pPktOutBufr[MAX_DSP_CORES][MAX_PKT_CHANNELS]; /* Pkt Out buffer */ static DSP_ADDRESS pEventFifoAddress[MAX_DSP_CORES]; /* event fifo */ static unsigned char DlByteBufr[DOWNLOAD_BLOCK_SIZE * 2]; /* Dowload byte buf */ static DSP_WORD DlWordBufr[DOWNLOAD_BLOCK_SIZE]; /* Dowload word buffer */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * CheckDspReset - Check if the DSP was reset. * * FUNCTION * This function determines if the DSP was reset and is ready. If reset * occurred, it reads interface parameters and calculates DSP addresses. * * RETURNS * -1 = DSP is not ready. * 0 = Reset did not occur. * 1 = Reset occurred. * */ static int CheckDspReset( int DspId /* DSP Identifier (0 to MaxDSPCores-1) */ ) { DSP_ADDRESS IfBlockPntr; /* Interface Block pointer */ DSP_WORD DspStatus; /* DSP Status */ DSP_WORD DspChannels; /* number of DSP channels */ DSP_WORD Temp[2]; #if 0 DSP_WORD DspConfs; /* number of DSP conferences */ DSP_ADDRESS PktBufrMem; /* address of Packet Buffer */ unsigned short int i; /* loop index / counter */ #endif /* Read the pointer to the Interface Block. */ gpakReadDspMemory(DspId, DSP_IFBLK_ADDRESS, 2, Temp); RECONSTRUCT_LONGWORD(IfBlockPntr, Temp); /* If the pointer is zero, return with an indication the DSP is not ready. */ if (IfBlockPntr == 0) return (-1); /* Read the DSP's Status. */ gpakReadDspMemory(DspId, IfBlockPntr + DSP_STATUS_OFFSET, 1, &DspStatus); /* If status indicates the DSP was reset, read the DSP's interface parameters and calculate DSP addresses. */ if (DspStatus == DSP_INIT_STATUS || ((DspStatus == HOST_INIT_STATUS) && (pDspIfBlk[DspId] == 0))) { /* Save the address of the DSP's Interface Block. */ pDspIfBlk[DspId] = IfBlockPntr; /* Read the DSP's interface parameters. */ gpakReadDspMemory(DspId, IfBlockPntr + MAX_CMD_MSG_LEN_OFFSET, 1, &(MaxCmdMsgLen[DspId])); /* read the number of configured DSP channels */ gpakReadDspMemory(DspId, IfBlockPntr + NUM_CHANNELS_OFFSET, 1, &DspChannels); if (DspChannels > MAX_CHANNELS) MaxChannels[DspId] = MAX_CHANNELS; else MaxChannels[DspId] = (unsigned short int) DspChannels; #if 0 /* read the number of configured DSP conferences */ gpakReadDspMemory(DspId, IfBlockPntr + NUM_CONFERENCES_OFFSET, 1, &DspConfs); if (DspConfs > MAX_CONFS) MaxConfs[DspId] = MAX_CONFS; else MaxConfs[DspId] = (unsigned short int) DspConfs; /* read the number of configured DSP packet channels */ gpakReadDspMemory(DspId, IfBlockPntr + NUM_PKT_CHANNELS_OFFSET, 1, &DspChannels); if (DspChannels > MAX_PKT_CHANNELS) MaxPktChannels[DspId] = MAX_PKT_CHANNELS; else MaxPktChannels[DspId] = (unsigned short int) DspChannels; /* read the pointer to the circular buffer infor struct table */ gpakReadDspMemory(DspId, IfBlockPntr + PKT_BUFR_MEM_OFFSET, 2, Temp); RECONSTRUCT_LONGWORD(PktBufrMem, Temp); /* Determine the addresses of each channel's Packet buffers. */ for (i = 0; i < MaxPktChannels[DspId]; i++) { pPktInBufr[DspId][i] = PktBufrMem; pPktOutBufr[DspId][i] = PktBufrMem + CIRC_BUFFER_INFO_STRUCT_SIZE; PktBufrMem += (CIRC_BUFFER_INFO_STRUCT_SIZE*2); } #endif /* read the pointer to the event fifo info struct */ gpakReadDspMemory(DspId, IfBlockPntr + EVENT_MSG_PNTR_OFFSET, 2, Temp); RECONSTRUCT_LONGWORD(pEventFifoAddress[DspId], Temp); /* Set the DSP Status to indicate the host recognized the reset. */ DspStatus = HOST_INIT_STATUS; gpakWriteDspMemory(DspId, IfBlockPntr + DSP_STATUS_OFFSET, 1, &DspStatus); /* Return with an indication that a reset occurred. */ return (1); } /* If status doesn't indicate the host recognized a reset, return with an indication the DSP is not ready. */ if ((DspStatus != HOST_INIT_STATUS) || (pDspIfBlk[DspId] == 0)) return (-1); /* Return with an indication that a reset did not occur. */ return (0); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * WriteDspCmdMessage - Write a Host Command/Request message to DSP. * * FUNCTION * This function writes a Host Command/Request message into DSP memory and * informs the DSP of the presence of the message. * * RETURNS * -1 = Unable to write message (msg len or DSP Id invalid or DSP not ready) * 0 = Temporarily unable to write message (previous Cmd Msg busy) * 1 = Message written successfully * */ static int WriteDspCmdMessage( int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ DSP_WORD *pMessage, /* pointer to Command message */ DSP_WORD MsgLength /* length of message (octets) */ ) { DSP_WORD CmdMsgLength; /* current Cmd message length */ DSP_WORD Temp[2]; DSP_ADDRESS BufferPointer; /* message buffer pointer */ /* Check if the DSP was reset and is ready. */ if (CheckDspReset(DspId) == -1) return (-1); /* Make sure the message length is valid. */ if ((MsgLength < 1) || (MsgLength > MaxCmdMsgLen[DspId])) return (-1); /* Make sure a previous Command message is not in use by the DSP. */ gpakReadDspMemory(DspId, pDspIfBlk[DspId] + CMD_MSG_LEN_OFFSET, 1, &CmdMsgLength); if (CmdMsgLength != 0) return (0); /* Purge any previous Reply message that wasn't read. */ gpakWriteDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_LEN_OFFSET, 1, &CmdMsgLength); /* Copy the Command message into DSP memory. */ gpakReadDspMemory(DspId, pDspIfBlk[DspId] + CMD_MSG_PNTR_OFFSET, 2, Temp); RECONSTRUCT_LONGWORD(BufferPointer, Temp); gpakWriteDspMemory(DspId, BufferPointer, (MsgLength + 1) / 2, pMessage); /* Store the message length in DSP's Command message length (flags DSP that a Command message is ready). */ CmdMsgLength = MsgLength; gpakWriteDspMemory(DspId, pDspIfBlk[DspId] + CMD_MSG_LEN_OFFSET, 1, &CmdMsgLength); /* Return with an indication the message was written. */ return (1); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * ReadDspReplyMessage - Read a DSP Reply message from DSP. * * FUNCTION * This function reads a DSP Reply message from DSP memory. * * RETURNS * -1 = Unable to write message (msg len or DSP Id invalid or DSP not ready) * 0 = No message available (DSP Reply message empty) * 1 = Message read successfully (message and length stored in variables) * */ static int ReadDspReplyMessage( int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ DSP_WORD *pMessage, /* pointer to Reply message buffer */ DSP_WORD *pMsgLength /* pointer to msg length var (octets) */ ) { DSP_WORD MsgLength; /* message length */ DSP_ADDRESS BufferPointer; /* message buffer pointer */ DSP_WORD Temp[2]; /* Check if the DSP was reset and is ready. */ if (CheckDspReset(DspId) == -1) return (-1); /* Check if a Reply message is ready. */ gpakReadDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_LEN_OFFSET, 1, &MsgLength); if (MsgLength == 0) return (0); /* Make sure the message length is valid. */ if (MsgLength > *pMsgLength) return (-1); /* Copy the Reply message from DSP memory. */ gpakReadDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_PNTR_OFFSET, 2, Temp); RECONSTRUCT_LONGWORD(BufferPointer, Temp); gpakReadDspMemory(DspId, BufferPointer, (MsgLength + 1) / 2, pMessage); /* Store the message length in the message length variable. */ *pMsgLength = MsgLength; /* Indicate a Reply message is not ready. */ MsgLength = 0; gpakWriteDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_LEN_OFFSET, 1, &MsgLength); /* Return with an indication the message was read. */ return (1); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * ReadCircBuffer - Read from a DSP circular buffer. * * FUNCTION * This function reads a block of words from a DSP circular buffer. The Take * address is incremented by the number of words read adjusting for buffer * wrap. * * RETURNS * nothing * */ static void ReadCircBuffer( int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ DSP_ADDRESS BufrBaseAddress, /* address of base of circular buffer */ DSP_ADDRESS BufrLastAddress, /* address of last word in buffer */ DSP_ADDRESS *TakeAddress, /* pointer to address in buffer for read */ DSP_WORD *pWordBuffer, /* pointer to buffer for words read */ DSP_WORD NumWords /* number of words to read */ ) { DSP_WORD WordsTillEnd; /* number of words until end of buffer */ /* Determine the number of words from the start address until the end of the buffer. */ WordsTillEnd = BufrLastAddress - *TakeAddress + 1; /* If a buffer wrap will occur, read the first part at the end of the buffer followed by the second part at the beginning of the buffer. */ if (NumWords > WordsTillEnd) { gpakReadDspMemory(DspId, *TakeAddress, WordsTillEnd, pWordBuffer); gpakReadDspMemory(DspId, BufrBaseAddress, NumWords - WordsTillEnd, &(pWordBuffer[WordsTillEnd])); *TakeAddress = BufrBaseAddress + NumWords - WordsTillEnd; } /* If a buffer wrap will not occur, read all words starting at the current take address in the buffer. */ else { gpakReadDspMemory(DspId, *TakeAddress, NumWords, pWordBuffer); if (NumWords == WordsTillEnd) *TakeAddress = BufrBaseAddress; else *TakeAddress = *TakeAddress + NumWords; } return; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * VerifyReply - Verify the reply message is correct for the command sent. * * FUNCTION * This function verifies correct reply message content for the command that * was just sent. * * RETURNS * 0 = Incorrect * 1 = Correct * */ static int VerifyReply( DSP_WORD *pMsgBufr, /* pointer to Reply message buffer */ int CheckType, /* reply check type */ DSP_WORD CheckValue /* reply check value */ ) { /* Verify Channel or Conference Id. */ if (CheckType == 1) { if (((pMsgBufr[1] >> 8) & 0xFF) != CheckValue) return (0); } /* Verify Test Mode Id. */ else if (CheckType == 2) { if (pMsgBufr[1] != CheckValue) return (0); } /* Return with an indication of correct reply. */ return (1); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * TransactCmd - Send a command to the DSP and receive it's reply. * * FUNCTION * This function sends the specified command to the DSP and receives the DSP's * reply. * * RETURNS * Length of reply message (0 = Failure) * */ static unsigned int TransactCmd( int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ DSP_WORD *pMsgBufr, /* pointer to Cmd/Reply message buffer */ DSP_WORD CmdLength, /* length of command message (octets) */ DSP_WORD ReplyType, /* required type of reply message */ DSP_WORD ReplyLength, /* required length of reply message (octets) */ int ReplyCheckType, /* reply check type */ DSP_WORD ReplyCheckValue /* reply check value */ ) { int FuncStatus; /* function status */ int LoopCount; /* wait loop counter */ DSP_WORD RcvReplyLength; /* received Reply message length */ DSP_WORD RcvReplyType; /* received Reply message type code */ DSP_WORD RetValue; /* return value */ /* Default the return value to indicate a failure. */ RetValue = 0; /* Lock access to the DSP. */ gpakLockAccess(DspId); /* Attempt to write the command message to the DSP. */ LoopCount = 0; while ((FuncStatus = WriteDspCmdMessage(DspId, pMsgBufr, CmdLength)) != 1) { if (FuncStatus == -1) break; if (++LoopCount > MAX_WAIT_LOOPS) break; gpakHostDelay(); } /* Attempt to read the reply message from the DSP if the command message was sent successfully. */ if (FuncStatus == 1) { for (LoopCount = 0; LoopCount < MAX_WAIT_LOOPS; LoopCount++) { RcvReplyLength = MSG_BUFFER_SIZE * 2; FuncStatus = ReadDspReplyMessage(DspId, pMsgBufr, &RcvReplyLength); if (FuncStatus == 1) { RcvReplyType = (pMsgBufr[0] >> 8) & 0xFF; if ((RcvReplyLength >= ReplyLength) && (RcvReplyType == ReplyType) && VerifyReply(pMsgBufr, ReplyCheckType, ReplyCheckValue)) { RetValue = RcvReplyLength; break; } else if (RcvReplyType == MSG_NULL_REPLY) break; } else if (FuncStatus == -1) break; gpakHostDelay(); } } /* Unlock access to the DSP. */ gpakUnlockAccess(DspId); /* Return the length of the reply message (0 = failure). */ return (RetValue); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakConfigurePorts - Configure a DSP's serial ports. * * FUNCTION * This function configures a DSP's serial ports. * * RETURNS * Status code indicating success or a specific error. * */ gpakConfigPortStatus_t gpakConfigurePorts( unsigned short int DspId, /* DSP Id (0 to MaxDSPCores-1) */ GpakPortConfig_t *pPortConfig, /* pointer to Port Config info */ GPAK_PortConfigStat_t *pStatus /* pointer to Port Config Status */ ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (CpsInvalidDsp); /* Build the Configure Serial Ports message. */ MsgBuffer[0] = MSG_CONFIGURE_PORTS << 8; MsgBuffer[1] = (DSP_WORD) ((pPortConfig->SlotsSelect1 << 12) | ((pPortConfig->FirstBlockNum1 << 8) & 0x0F00) | ((pPortConfig->SecBlockNum1 << 4) & 0x00F0)); MsgBuffer[2] = (DSP_WORD) pPortConfig->FirstSlotMask1; MsgBuffer[3] = (DSP_WORD) pPortConfig->SecSlotMask1; MsgBuffer[4] = (DSP_WORD) ((pPortConfig->SlotsSelect2 << 12) | ((pPortConfig->FirstBlockNum2 << 8) & 0x0F00) | ((pPortConfig->SecBlockNum2 << 4) & 0x00F0)); MsgBuffer[5] = (DSP_WORD) pPortConfig->FirstSlotMask2; MsgBuffer[6] = (DSP_WORD) pPortConfig->SecSlotMask2; MsgBuffer[7] = (DSP_WORD) ((pPortConfig->SlotsSelect3 << 12) | ((pPortConfig->FirstBlockNum3 << 8) & 0x0F00) | ((pPortConfig->SecBlockNum3 << 4) & 0x00F0)); MsgBuffer[8] = (DSP_WORD) pPortConfig->FirstSlotMask3; MsgBuffer[9] = (DSP_WORD) pPortConfig->SecSlotMask3; MsgBuffer[10] = (DSP_WORD) (((pPortConfig->DxDelay1 << 11) & 0x0800) | ((pPortConfig->RxDataDelay1 << 9) & 0x0600) | ((pPortConfig->TxDataDelay1 << 7) & 0x0180) | ((pPortConfig->RxClockPolarity1 << 6) & 0x0040) | ((pPortConfig->TxClockPolarity1 << 5) & 0x0020) | ((pPortConfig->RxFrameSyncPolarity1 << 4) & 0x0010) | ((pPortConfig->TxFrameSyncPolarity1 << 3) & 0x0008) | ((pPortConfig->CompandingMode1 << 1) & 0x0006) | (pPortConfig->SerialWordSize1 & 0x0001)); MsgBuffer[11] = (DSP_WORD) (((pPortConfig->DxDelay2 << 11) & 0x0800) | ((pPortConfig->RxDataDelay2 << 9) & 0x0600) | ((pPortConfig->TxDataDelay2 << 7) & 0x0180) | ((pPortConfig->RxClockPolarity2 << 6) & 0x0040) | ((pPortConfig->TxClockPolarity2 << 5) & 0x0020) | ((pPortConfig->RxFrameSyncPolarity2 << 4) & 0x0010) | ((pPortConfig->TxFrameSyncPolarity2 << 3) & 0x0008) | ((pPortConfig->CompandingMode2 << 1) & 0x0006) | (pPortConfig->SerialWordSize1 & 0x0001)); MsgBuffer[12] = (DSP_WORD) (((pPortConfig->DxDelay3 << 11) & 0x0800) | ((pPortConfig->RxDataDelay3 << 9) & 0x0600) | ((pPortConfig->TxDataDelay3 << 7) & 0x0180) | ((pPortConfig->RxClockPolarity3 << 6) & 0x0040) | ((pPortConfig->TxClockPolarity3 << 5) & 0x0020) | ((pPortConfig->RxFrameSyncPolarity3 << 4) & 0x0010) | ((pPortConfig->TxFrameSyncPolarity3 << 3) & 0x0008) | ((pPortConfig->CompandingMode3 << 1) & 0x0006) | (pPortConfig->SerialWordSize3 & 0x0001)); MsgBuffer[13] = (DSP_WORD) pPortConfig->ThirdSlotMask1; MsgBuffer[14] = (DSP_WORD) pPortConfig->FouthSlotMask1; MsgBuffer[15] = (DSP_WORD) pPortConfig->FifthSlotMask1; MsgBuffer[16] = (DSP_WORD) pPortConfig->SixthSlotMask1; MsgBuffer[17] = (DSP_WORD) pPortConfig->SevenSlotMask1; MsgBuffer[18] = (DSP_WORD) pPortConfig->EightSlotMask1; MsgBuffer[19] = (DSP_WORD) pPortConfig->ThirdSlotMask2;; MsgBuffer[20] = (DSP_WORD) pPortConfig->FouthSlotMask2; MsgBuffer[21] = (DSP_WORD) pPortConfig->FifthSlotMask2;; MsgBuffer[22] = (DSP_WORD) pPortConfig->SixthSlotMask2; MsgBuffer[23] = (DSP_WORD) pPortConfig->SevenSlotMask2;; MsgBuffer[24] = (DSP_WORD) pPortConfig->EightSlotMask2; MsgBuffer[25] = (DSP_WORD) pPortConfig->ThirdSlotMask3;; MsgBuffer[26] = (DSP_WORD) pPortConfig->FouthSlotMask3; MsgBuffer[27] = (DSP_WORD) pPortConfig->FifthSlotMask3;; MsgBuffer[28] = (DSP_WORD) pPortConfig->SixthSlotMask3; MsgBuffer[29] = (DSP_WORD) pPortConfig->SevenSlotMask3;; MsgBuffer[30] = (DSP_WORD) pPortConfig->EightSlotMask3; /* Attempt to send the Configure Serial Ports message to the DSP and receive it's reply. */ if (!TransactCmd(DspId, MsgBuffer, 62, MSG_CONFIG_PORTS_REPLY, 4, 0, 0)) return (CpsDspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ *pStatus = (GPAK_PortConfigStat_t) (MsgBuffer[1] & 0xFF); if (*pStatus == Pc_Success) return (CpsSuccess); else return (CpsParmError); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakConfigureChannel - Configure a DSP's Channel. * * FUNCTION * This function configures a DSP's Channel. * * RETURNS * Status code indicating success or a specific error. * */ gpakConfigChanStatus_t gpakConfigureChannel( unsigned short int DspId, /* DSP Id (0 to MaxDSPCores-1) */ unsigned short int ChannelId, /* Channel Id (0 to MaxChannels-1) */ GpakChanType ChannelType, /* Channel Type */ GpakChannelConfig_t *pChanConfig, /* pointer to Channel Config info */ GPAK_ChannelConfigStat_t *pStatus /* pointer to Channel Config Status */ ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ DSP_WORD MsgLength; /* message length */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (CcsInvalidDsp); /* Make sure the Channel Id is valid. */ if (ChannelId >= MaxChannels[DspId]) return (CcsInvalidChannel); /* Build the Configure Channel message based on the Channel Type. */ switch (ChannelType) { /* PCM to Packet channel type. */ case tdmToTdm: MsgBuffer[2] = (DSP_WORD) ((pChanConfig->PcmInPortA << 8) | (pChanConfig->PcmInSlotA & 0xFF)); MsgBuffer[3] = (DSP_WORD) ((pChanConfig->PcmOutPortA << 8) | (pChanConfig->PcmOutSlotA & 0xFF)); MsgBuffer[4] = (DSP_WORD) ((pChanConfig->PcmInPortB << 8) | (pChanConfig->PcmInSlotB & 0xFF)); MsgBuffer[5] = (DSP_WORD) ((pChanConfig->PcmOutPortB << 8) | (pChanConfig->PcmOutSlotB & 0xFF)); MsgBuffer[6] = (DSP_WORD) ( ((pChanConfig->FaxCngDetB <<11) & 0x0800) | ((pChanConfig->FaxCngDetA <<10) & 0x0400) | ((pChanConfig->MuteToneB << 9) & 0x0200) | ((pChanConfig->MuteToneA << 8) & 0x0100) | ((pChanConfig->FrameRate << 6) & 0x00C0) | ((pChanConfig->ToneTypesB << 5) & 0x0020) | ((pChanConfig->ToneTypesA << 4) & 0x0010) | ((pChanConfig->SoftwareCompand & 3) << 2) | (pChanConfig->EcanEnableB << 1) | (pChanConfig->EcanEnableA & 1) ); MsgBuffer[7] = (DSP_WORD) pChanConfig->EcanParametersA.EcanTapLength; MsgBuffer[8] = (DSP_WORD) pChanConfig->EcanParametersA.EcanNlpType; MsgBuffer[9] = (DSP_WORD) pChanConfig->EcanParametersA.EcanAdaptEnable; MsgBuffer[10] = (DSP_WORD) pChanConfig->EcanParametersA.EcanG165DetEnable; MsgBuffer[11] = (DSP_WORD) pChanConfig->EcanParametersA.EcanDblTalkThresh; MsgBuffer[12] = (DSP_WORD) pChanConfig->EcanParametersA.EcanNlpThreshold; MsgBuffer[13] = (DSP_WORD) pChanConfig->EcanParametersA.EcanNlpConv; MsgBuffer[14] = (DSP_WORD) pChanConfig->EcanParametersA.EcanNlpUnConv; MsgBuffer[15] = (DSP_WORD) pChanConfig->EcanParametersA.EcanNlpMaxSuppress; MsgBuffer[16] = (DSP_WORD) pChanConfig->EcanParametersA.EcanCngThreshold; MsgBuffer[17] = (DSP_WORD) pChanConfig->EcanParametersA.EcanAdaptLimit; MsgBuffer[18] = (DSP_WORD) pChanConfig->EcanParametersA.EcanCrossCorrLimit; MsgBuffer[19] = (DSP_WORD) pChanConfig->EcanParametersA.EcanNumFirSegments; MsgBuffer[20] = (DSP_WORD) pChanConfig->EcanParametersA.EcanFirSegmentLen; MsgBuffer[21] = (DSP_WORD) pChanConfig->EcanParametersB.EcanTapLength; MsgBuffer[22] = (DSP_WORD) pChanConfig->EcanParametersB.EcanNlpType; MsgBuffer[23] = (DSP_WORD) pChanConfig->EcanParametersB.EcanAdaptEnable; MsgBuffer[24] = (DSP_WORD) pChanConfig->EcanParametersB.EcanG165DetEnable; MsgBuffer[25] = (DSP_WORD) pChanConfig->EcanParametersB.EcanDblTalkThresh; MsgBuffer[26] = (DSP_WORD) pChanConfig->EcanParametersB.EcanNlpThreshold; MsgBuffer[27] = (DSP_WORD) pChanConfig->EcanParametersB.EcanNlpConv; MsgBuffer[28] = (DSP_WORD) pChanConfig->EcanParametersB.EcanNlpUnConv; MsgBuffer[29] = (DSP_WORD) pChanConfig->EcanParametersB.EcanNlpMaxSuppress; MsgBuffer[30] = (DSP_WORD) pChanConfig->EcanParametersB.EcanCngThreshold; MsgBuffer[31] = (DSP_WORD) pChanConfig->EcanParametersB.EcanAdaptLimit; MsgBuffer[32] = (DSP_WORD) pChanConfig->EcanParametersB.EcanCrossCorrLimit; MsgBuffer[33] = (DSP_WORD) pChanConfig->EcanParametersB.EcanNumFirSegments; MsgBuffer[34] = (DSP_WORD) pChanConfig->EcanParametersB.EcanFirSegmentLen; MsgLength = 70; // byte number == 35*2 break; /* Unknown (invalid) channel type. */ default: *pStatus = Cc_InvalidChannelType; return (CcsParmError); } MsgBuffer[0] = MSG_CONFIGURE_CHANNEL << 8; MsgBuffer[1] = (DSP_WORD) ((ChannelId << 8) | (ChannelType & 0xFF)); /* Attempt to send the Configure Channel message to the DSP and receive it's reply. */ if (!TransactCmd(DspId, MsgBuffer, MsgLength, MSG_CONFIG_CHAN_REPLY, 4, 1, (DSP_WORD) ChannelId)) return (CcsDspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ *pStatus = (GPAK_ChannelConfigStat_t) (MsgBuffer[1] & 0xFF); if (*pStatus == Cc_Success) return (CcsSuccess); else return (CcsParmError); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakTearDownChannel - Tear Down a DSP's Channel. * * FUNCTION * This function tears down a DSP's Channel. * * RETURNS * Status code indicating success or a specific error. * */ gpakTearDownStatus_t gpakTearDownChannel( unsigned short int DspId, /* DSP Id (0 to MaxDSPCores-1) */ unsigned short int ChannelId, /* Channel Id (0 to MaxChannels-1) */ GPAK_TearDownChanStat_t *pStatus /* pointer to Tear Down Status */ ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (TdsInvalidDsp); /* Make sure the Channel Id is valid. */ if (ChannelId >= MaxChannels[DspId]) return (TdsInvalidChannel); /* Build the Tear Down Channel message. */ MsgBuffer[0] = MSG_TEAR_DOWN_CHANNEL << 8; MsgBuffer[1] = (DSP_WORD) (ChannelId << 8); /* Attempt to send the Tear Down Channel message to the DSP and receive it's reply. */ if (!TransactCmd(DspId, MsgBuffer, 3, MSG_TEAR_DOWN_REPLY, 4, 1, (DSP_WORD) ChannelId)) return (TdsDspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ *pStatus = (GPAK_TearDownChanStat_t) (MsgBuffer[1] & 0xFF); if (*pStatus == Td_Success) return (TdsSuccess); else return (TdsError); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakAlgControl - Control an Algorithm. * * FUNCTION * This function controls an Algorithm * * RETURNS * Status code indicating success or a specific error. * */ gpakAlgControlStat_t gpakAlgControl( unsigned short int DspId, // DSP identifier unsigned short int ChannelId, // channel identifier GpakAlgCtrl_t ControlCode, // algorithm control code GPAK_AlgControlStat_t *pStatus // pointer to return status ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (AcInvalidDsp); /* Make sure the Channel Id is valid. */ if (ChannelId >= MaxChannels[DspId]) return (AcInvalidChannel); MsgBuffer[0] = MSG_ALG_CONTROL << 8; MsgBuffer[1] = (DSP_WORD) ((ChannelId << 8) | (ControlCode & 0xFF)); /* Attempt to send the Tear Down Channel message to the DSP and receive it's reply. */ //need_reply_len; if (!TransactCmd(DspId, MsgBuffer, 4, MSG_ALG_CONTROL_REPLY, 4, 1, (DSP_WORD) ChannelId)) return (AcDspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ *pStatus = (GPAK_AlgControlStat_t) (MsgBuffer[1] & 0xFF); if (*pStatus == Ac_Success) return (AcSuccess); else return (AcParmError); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadEventFIFOMessage - read from the event fifo * * FUNCTION * This function reads a single event from the event fifo if one is available * * RETURNS * Status code indicating success or a specific error. * * Notes: This function should be called in a loop until the return status * indicates that the fifo is empty. * * If the event code equals "EventLoopbackTeardownComplete", then the * contents of *pChannelId hold the coderBlockId that was assigned to * the loopback coder that was torn down. */ gpakReadEventFIFOMessageStat_t gpakReadEventFIFOMessage( unsigned short int DspId, // DSP identifier unsigned short int *pChannelId, // pointer to channel identifier GpakAsyncEventCode_t *pEventCode, // pointer to Event Code GpakAsyncEventData_t *pEventData // pointer to Event Data Struct ) { DSP_WORD WordBuffer[WORD_BUFFER_SIZE]; /* DSP words buffer */ GpakAsyncEventCode_t EventCode; /* DSP's event code */ DSP_WORD EventDataLength; /* Length of event to read */ DSP_WORD ChannelId; /* DSP's channel Id */ DSP_ADDRESS EventInfoAddress; /* address of EventFIFO info structure */ DSP_ADDRESS BufrBaseAddress; /* base address of EventFIFO buffer */ DSP_ADDRESS BufrLastAddress; /* last address of EventFIFO buffer */ DSP_ADDRESS TakeAddress; /* current take address in fifo buffer */ DSP_WORD BufrSize; /* size (in words) of event FIFO buffer */ DSP_WORD PutIndex; /* event fifo put index */ DSP_WORD TakeIndex; /* event fifo take index */ DSP_WORD WordsReady; /* number words ready for read out of event fifo */ DSP_WORD EventError; /* flag indicating error with event fifo msg */ #if 0 DSP_WORD *pDebugData; /* debug data buffer pointer in event data struct */ #endif /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (RefInvalidDsp); /* Lock access to the DSP. */ gpakLockAccess(DspId); /* Check if the DSP was reset and is ready. */ if (CheckDspReset(DspId) == -1) { gpakUnlockAccess(DspId); return (RefDspCommFailure); } /* Check if an event message is ready in the DSP. */ EventInfoAddress = pEventFifoAddress[DspId]; gpakReadDspMemory(DspId, EventInfoAddress, CIRC_BUFFER_INFO_STRUCT_SIZE, WordBuffer); RECONSTRUCT_LONGWORD(BufrBaseAddress, ((DSP_WORD *)&WordBuffer[CB_BUFR_BASE])); BufrSize = WordBuffer[CB_BUFR_SIZE]; PutIndex = WordBuffer[CB_BUFR_PUT_INDEX]; TakeIndex = WordBuffer[CB_BUFR_TAKE_INDEX]; if (PutIndex >= TakeIndex) WordsReady = PutIndex - TakeIndex; else WordsReady = PutIndex + BufrSize - TakeIndex; if (WordsReady < 2) { gpakUnlockAccess(DspId); return (RefNoEventAvail); } /* Read the event header from the DSP's Event FIFO. */ TakeAddress = BufrBaseAddress + TakeIndex; BufrLastAddress = BufrBaseAddress + BufrSize - 1; ReadCircBuffer(DspId, BufrBaseAddress, BufrLastAddress, &TakeAddress, WordBuffer, 2); TakeIndex += 2; if (TakeIndex >= BufrSize) TakeIndex -= BufrSize; ChannelId = (WordBuffer[0] >> 8) & 0xFF; EventCode = (GpakAsyncEventCode_t)(WordBuffer[0] & 0xFF); EventDataLength = WordBuffer[1]; EventError = 0; switch (EventCode) { case EventToneDetect: if (EventDataLength > WORD_BUFFER_SIZE) { gpakUnlockAccess(DspId); return (RefInvalidEvent); } ReadCircBuffer(DspId, BufrBaseAddress, BufrLastAddress, &TakeAddress, WordBuffer, EventDataLength); pEventData->toneEvent.ToneCode = (GpakToneCodes_t) (WordBuffer[0] & 0xFF); pEventData->toneEvent.ToneDuration = WordBuffer[1]; pEventData->toneEvent.Direction = WordBuffer[2]; pEventData->toneEvent.DebugToneStatus = WordBuffer[3]; TakeIndex += EventDataLength; if (TakeIndex >= BufrSize) TakeIndex -= BufrSize; if (EventDataLength != 4) EventError = 1; break; default: EventError = 1; break; }; /* Update the Take index in the DSP's Packet Out buffer information. */ gpakWriteDspMemory(DspId, EventInfoAddress + CB_BUFR_TAKE_INDEX, 1, &TakeIndex); /* Unlock access to the DSP. */ gpakUnlockAccess(DspId); if (EventError) return(RefInvalidEvent); *pChannelId = ChannelId; *pEventCode = EventCode; return(RefEventAvail); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakPingDsp - ping the DSP to see if it's alive * * FUNCTION * This function checks if the DSP is still communicating with the host * and returns the DSP SW version * * RETURNS * Status code indicating success or a specific error. */ gpakPingDspStat_t gpakPingDsp( unsigned short int DspId, // DSP identifier unsigned short int *pDspSwVersion // DSP software version ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ DSP_WORD DspStatus; /* DSP's reply status */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (PngInvalidDsp); /* send value of 1, DSP increments it */ MsgBuffer[0] = (MSG_PING << 8); /* Attempt to send the ping message to the DSP and receive it's reply. */ if (!TransactCmd(DspId, MsgBuffer, 1, MSG_PING_REPLY, 6, 0, 0)) return (PngDspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ DspStatus = (MsgBuffer[1] & 0xFF); if (DspStatus == 0) { *pDspSwVersion = MsgBuffer[2]; return (PngSuccess); } else return (PngDspCommFailure); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakSerialTxFixedValue - transmit a fixed value on a timeslot * * FUNCTION * This function controls transmission of a fixed value out onto a serial * port's timeslot. * * RETURNS * Status code indicating success or a specific error. */ gpakSerialTxFixedValueStat_t gpakSerialTxFixedValue( unsigned short int DspId, // DSP identifier unsigned short int ChannelId, // channel identifier GpakSerialPort_t PcmOutPort, // PCM Output Serial Port Id unsigned short int PcmOutSlot, // PCM Output Time Slot unsigned short int Value, // 16-bit value GpakActivation State // activation state ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ DSP_WORD DspStatus; /* DSP's reply status */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (TfvInvalidDsp); /* Make sure the Channel Id is valid. */ if (ChannelId >= MaxChannels[DspId]) return (TfvInvalidChannel); /* Build the message. */ MsgBuffer[0] = MSG_SERIAL_TXVAL << 8; MsgBuffer[1] = (DSP_WORD) ((ChannelId << 8) | (State & 0xFF)); MsgBuffer[2] = (DSP_WORD) ((PcmOutPort << 8) | (PcmOutSlot & 0xFF)); MsgBuffer[3] = (DSP_WORD) Value; /* Attempt to send the message to the DSP and receive it's reply. */ //need_reply_len; if (!TransactCmd(DspId, MsgBuffer, 8, MSG_SERIAL_TXVAL_REPLY, 4, 1, ChannelId)) return (TfvDspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ DspStatus = (MsgBuffer[1] & 0xFF); if (DspStatus == 0) return (TfvSuccess); else return (TfvDspCommFailure); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakControlTdmLoopBack - control a serial port's loopback state * * FUNCTION * This function enables/disables the tdm input to output looback mode on a * serial port * * RETURNS * Status code indicating success or a specific error. */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ gpakControlTdmLoopBackStat_t gpakControlTdmLoopBack( unsigned short int DspId, // DSP identifier GpakSerialPort_t SerialPort, // Serial Port Id GpakActivation LoopBackState // Loopback State ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ DSP_WORD DspStatus; /* DSP's reply status */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (ClbInvalidDsp); /* Build the message. */ MsgBuffer[0] = MSG_TDM_LOOPBACK << 8; MsgBuffer[1] = (DSP_WORD) ((SerialPort << 8) | (LoopBackState & 0xFF)); /* Attempt to send the message to the DSP and receive it's reply. */ //need_reply_len; if (!TransactCmd(DspId, MsgBuffer, 4, MSG_TDM_LOOPBACK_REPLY, 4, 0, 0)) return (ClbDspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ DspStatus = (MsgBuffer[1] & 0xFF); if (DspStatus == 0) return (ClbSuccess); else return (ClbDspCommFailure); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadCpuUsage - Read CPU usage statistics from a DSP. * * FUNCTION * This function reads the CPU usage statistics from a DSP's memory. The * average CPU usage in units of .1 percent are obtained for each of the frame * rates. * * RETURNS * Status code indicating success or a specific error. * */ gpakReadCpuUsageStat_t gpakReadCpuUsage( unsigned short int DspId, // Dsp Identifier unsigned short int *pPeakUsage, // pointer to peak usage variable unsigned short int *pPrev1SecPeakUsage // peak usage over previous 1 second ) { DSP_WORD ReadBuffer[2]; /* DSP read buffer */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (RcuInvalidDsp); /* Lock access to the DSP. */ gpakLockAccess(DspId); /* Check if the DSP was reset and is ready. */ if (CheckDspReset(DspId) == -1) return (RcuDspCommFailure); /* Read the CPU Usage statistics from the DSP. */ gpakReadDspMemory(DspId, pDspIfBlk[DspId] + CPU_USAGE_OFFSET, 2, ReadBuffer); /* Unlock access to the DSP. */ gpakUnlockAccess(DspId); /* Store the usage statistics in the specified variables. */ *pPrev1SecPeakUsage = ReadBuffer[0]; *pPeakUsage = ReadBuffer[1]; /* Return with an indication the usage staistics were read successfully. */ return (RcuSuccess); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakResetCpuUsageStats - reset the cpu usage statistics * * FUNCTION * This function resets the cpu utilization statistics * * RETURNS * Status code indicating success or a specific error. */ gpakResetCpuUsageStat_t gpakResetCpuUsageStats( unsigned short int DspId // DSP identifier ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ DSP_WORD DspStatus; /* DSP's reply status */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (RstcInvalidDsp); MsgBuffer[0] = (MSG_RESET_USAGE_STATS << 8); /* Attempt to send the message to the DSP and receive it's reply. */ //need_reply_len; if (!TransactCmd(DspId, MsgBuffer, 2, MSG_RESET_USAGE_STATS_REPLY, 4, 0, 0)) return (RstcDspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ DspStatus = (MsgBuffer[1] & 0xFF); if (DspStatus == 0) return (RstcSuccess); else return (RstcDspCommFailure); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadFramingStats * * FUNCTION * This function reads a DSP's framing interrupt statistics * * RETURNS * Status code indicating success or a specific error. */ gpakReadFramingStatsStatus_t gpakReadFramingStats( unsigned short int DspId, // DSP identifier unsigned short int *pFramingError1Count, // port 1 Framing error count unsigned short int *pFramingError2Count, // port 2 Framing error count unsigned short int *pFramingError3Count, // port 3 Framing error count unsigned short int *pDmaStopErrorCount, // DMA-stoppage error count unsigned short int *pDmaSlipStatsBuffer // DMA slips count ) { DSP_WORD ReadBuffer[10]; /* DSP read buffer */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (RfsInvalidDsp); /* Lock access to the DSP. */ gpakLockAccess(DspId); /* Check if the DSP was reset and is ready. */ if (CheckDspReset(DspId) == -1) return (RfsDspCommFailure); /* Read the framing interrupt statistics from the DSP. */ gpakReadDspMemory(DspId, pDspIfBlk[DspId] + FRAMING_STATS_OFFSET, 10, ReadBuffer); /* Unlock access to the DSP. */ gpakUnlockAccess(DspId); /* Store the framing statistics in the specified variables. */ *pFramingError1Count = ReadBuffer[0]; *pFramingError2Count = ReadBuffer[1]; *pFramingError3Count = ReadBuffer[2]; *pDmaStopErrorCount = ReadBuffer[3]; if(pDmaSlipStatsBuffer != 0) // If users want to get the DMA slips count { pDmaSlipStatsBuffer[0] = ReadBuffer[4]; pDmaSlipStatsBuffer[1] = ReadBuffer[5]; pDmaSlipStatsBuffer[2] = ReadBuffer[6]; pDmaSlipStatsBuffer[3] = ReadBuffer[7]; pDmaSlipStatsBuffer[4] = ReadBuffer[8]; pDmaSlipStatsBuffer[5] = ReadBuffer[9]; } /* Return with an indication the statistics were read successfully. */ return (RfsSuccess); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakResetFramingStats - reset a DSP's framing interrupt statistics * * FUNCTION * This function resets a DSP's framing interrupt statistics * * RETURNS * Status code indicating success or a specific error. */ gpakResetFramingStatsStatus_t gpakResetFramingStats( unsigned short int DspId // DSP identifier ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ DSP_WORD DspStatus; /* DSP's reply status */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (RstfInvalidDsp); MsgBuffer[0] = (MSG_RESET_FRAME_STATS << 8); /* Attempt to send the message to the DSP and receive it's reply. */ //need_reply_len; if (!TransactCmd(DspId, MsgBuffer, 2, MSG_RESET_FRAME_STATS_REPLY, 4, 0, 0)) return (RstfDspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ DspStatus = (MsgBuffer[1] & 0xFF); if (DspStatus == 0) return (RstfSuccess); else return (RstfDspCommFailure); } /* * gpakDownloadDsp - Download a DSP's Program and initialized Data memory. * * FUNCTION * This function reads a DSP's Program and Data memory image from the * specified file and writes the image to the DSP's memory. * * RETURNS * Status code indicating success or a specific error. * */ gpakDownloadStatus_t gpakDownloadDsp( unsigned short DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ GPAK_FILE_ID FileId /* G.PAK Download File Identifier */ ) { gpakDownloadStatus_t RetStatus; /* function return status */ int NumRead; /* number of file bytes read */ DSP_ADDRESS Address; /* DSP address */ unsigned int WordCount; /* number of words in record */ unsigned int NumWords; /* number of words to read/write */ unsigned int i; /* loop index / counter */ unsigned int j; /* loop index */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (GdlInvalidDsp); /* Lock access to the DSP. */ gpakLockAccess(DspId); RetStatus = GdlSuccess; while (RetStatus == GdlSuccess) { /* Read a record header from the file. */ NumRead = gpakReadFile(FileId, DlByteBufr, 6); if (NumRead == -1) { RetStatus = GdlFileReadError; break; } if (NumRead != 6) { RetStatus = GdlInvalidFile; break; } Address = (((DSP_ADDRESS) DlByteBufr[1]) << 16) | (((DSP_ADDRESS) DlByteBufr[2]) << 8) | ((DSP_ADDRESS) DlByteBufr[3]); WordCount = (((unsigned int) DlByteBufr[4]) << 8) | ((unsigned int) DlByteBufr[5]); /* Check for the End Of File record. */ if (DlByteBufr[0] == 0xFF) break; /* Verify the record is for a valid memory type. */ if ((DlByteBufr[0] != 0x00) && (DlByteBufr[0] != 0x01)) { RetStatus = GdlInvalidFile; break; } /* Read a block of words at a time from the file and write to the DSP's memory .*/ while (WordCount != 0) { if (WordCount < DOWNLOAD_BLOCK_SIZE) NumWords = WordCount; else NumWords = DOWNLOAD_BLOCK_SIZE; WordCount -= NumWords; NumRead = gpakReadFile(FileId, DlByteBufr, NumWords * 2); if (NumRead == -1) { RetStatus = GdlFileReadError; break; } if (NumRead != (NumWords * 2)) { RetStatus = GdlInvalidFile; break; } for (i = 0, j = 0; i < NumWords; i++, j += 2) DlWordBufr[i] = (((DSP_WORD) DlByteBufr[j]) << 8) | ((DSP_WORD) DlByteBufr[j + 1]); gpakWriteDspMemory(DspId, Address, NumWords, DlWordBufr); Address += ((DSP_ADDRESS) NumWords); } } /* Unlock access to the DSP. */ gpakUnlockAccess(DspId); /* Return with an indication of success or failure. */ return (RetStatus); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadCpuUsage - Read CPU usage statistics from a DSP. * * FUNCTION * This function reads the memory map register section of DSP memory. * * RETURNS * Status code indicating success or a specific error. * */ gpakReadDSPMemoryStat_t gpakReadDSPMemoryMap( unsigned short int DspId, // Dsp Identifier unsigned short int *pDest, // Buffer on host to hold DSP memory map DSP_ADDRESS BufrBaseAddress, // DSP memory users want to read out unsigned short int MemoryLength_Word16 // Length of memory section read out, unit is 16-bit word ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ DSP_WORD DspStatus; /* DSP reply's status */ int i; /* loop index / counter */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (RmmInvalidDsp); /* Verify the message buffer is large enough */ if (MSG_BUFFER_SIZE < MemoryLength_Word16 ) return (RmmSizeTooBig); MsgBuffer[0] = MSG_READ_DSP_MEMORY << 8; MsgBuffer[1] = (DSP_WORD) ((BufrBaseAddress >> 16) & 0xFFFF); MsgBuffer[2] = (DSP_WORD) (BufrBaseAddress & 0xFFFF); MsgBuffer[3] = (DSP_WORD) MemoryLength_Word16; /* Attempt to send the Read memory section message to the DSP and receive it's reply. */ //need_reply_len; if (!TransactCmd(DspId, MsgBuffer, 8, MSG_READ_DSP_MEMORY_REPLY, (MemoryLength_Word16+2)*2, 0, 0) ) return (RmmInvalidAddress); /* Return with an indication of success or failure based on the return status in the reply message. */ DspStatus = (MsgBuffer[1] & 0xFF); if (DspStatus != 0) return (RmmFailure); for (i = 0; i < MemoryLength_Word16; i++) pDest[i] = (short int) MsgBuffer[2 + i]; return (RmmSuccess); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakAccessGPIO - change Direction/read/write the GPIO on DSP * * FUNCTION * This function read/write GPIO and change the GPIO direction * * * RETURNS * Status code indicating success or a specific error. */ gpakAccessGPIOStat_t gpakAccessGPIO( unsigned short int DspId, // DSP identifier GpakGPIOCotrol_t gpakControlGPIO,// select oeration, changeDIR/write/read unsigned short int *pGPIOValue // DSP software version ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ DSP_WORD DspStatus; /* DSP's reply status */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (GPIOInvalidDsp); /* send value of 1, DSP increments it */ MsgBuffer[0] = (MSG_ACCESSGPIO << 8); MsgBuffer[1] = (DSP_WORD) ((gpakControlGPIO << 8) | (*pGPIOValue & 0xFF) ); /* Attempt to send the ping message to the DSP and receive it's reply. */ if (!TransactCmd(DspId, MsgBuffer, 4, MSG_ACCESSGPIO_REPLY, 6, 0, 0)) return (GPIODspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ DspStatus = (MsgBuffer[1] & 0xFF); if (DspStatus == 0) { *pGPIOValue = MsgBuffer[2]; return (GPIOSuccess); } else return (GPIODspCommFailure); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakWriteSystemParms - Write a DSP's System Parameters. * * FUNCTION * This function writes a DSP's System Parameters information. * * Note: * Or-together the desired bit-mask #defines that are listed below. Only * those algorithm parameters whose bit-mask is selected in the UpdateBits * function parameter will be updated. * * RETURNS * Status code indicating success or a specific error. * */ gpakWriteSysParmsStatus_t gpakWriteSystemParms( unsigned short int DspId, // DSP identifier GpakSystemParms_t *pSysParms, /* pointer to System Parms info var */ unsigned short int UpdateBits, /* input: flags indicating which parms to update */ GPAK_SysParmsStat_t *pStatus /* pointer to Write System Parms Status */ ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ DSP_WORD DspStatus; /* DSP's reply status */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (WspInvalidDsp); /* Build the Write System Parameters message. */ MsgBuffer[0] = MSG_WRITE_SYS_PARMS << 8; if (UpdateBits & DTMF_UPDATE_MASK) { MsgBuffer[1] |= DTMF_UPDATE_MASK; MsgBuffer[8] = (DSP_WORD) pSysParms->MinSigLevel; MsgBuffer[9] = (DSP_WORD) (pSysParms->FreqDeviation & 0xff); if (pSysParms->SNRFlag) MsgBuffer[9] |= (1<<8); } MsgBuffer[10] = (DSP_WORD) 0; if (UpdateBits & DTMF_TWIST_UPDATE_MASK) { MsgBuffer[1] |= DTMF_TWIST_UPDATE_MASK; MsgBuffer[10] |= (DSP_WORD) (pSysParms->DtmfFwdTwist & 0x000f); MsgBuffer[10] |= (DSP_WORD) ((pSysParms->DtmfRevTwist << 4) & 0x00f0); } if (UpdateBits & DTMF_VALID_MASK) { MsgBuffer[1] |= DTMF_VALID_MASK; MsgBuffer[11] = (DSP_WORD) (pSysParms->DtmfValidityMask & 0x00ff); } /* Attempt to send the ping message to the DSP and receive it's reply. */ if (!TransactCmd(DspId, MsgBuffer, 24, MSG_WRITE_SYS_PARMS_REPLY, 6, 0, 0)) return (WspDspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ *pStatus = (GPAK_SysParmsStat_t) (MsgBuffer[2] ); DspStatus = (MsgBuffer[1] & 0xFF); if (DspStatus == 0) return (WspSuccess); else return (WspDspCommFailure); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadSystemParms - Read a DSP's System Parameters. * * FUNCTION * This function reads a DSP's System Parameters information. * * RETURNS * Status code indicating success or a specific error. * */ gpakReadSysParmsStatus_t gpakReadSystemParms( unsigned short int DspId, // DSP identifier GpakSystemParms_t *pSysParms /* pointer to System Parms info var */ ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (RspInvalidDsp); /* Build the Read System Parameters message. */ MsgBuffer[0] = MSG_READ_SYS_PARMS << 8; /* Attempt to send the ping message to the DSP and receive it's reply. */ if (!TransactCmd(DspId, MsgBuffer, 2, MSG_READ_SYS_PARMS_REPLY, 22, 0, 0)) return (RspDspCommFailure); /* Extract the System Parameters information from the message. */ pSysParms->DtmfValidityMask = (short int)(MsgBuffer[7]) ; pSysParms->MinSigLevel = (short int)MsgBuffer[8]; pSysParms->SNRFlag = (short int)((MsgBuffer[9]>>8) & 0x1); pSysParms->FreqDeviation = (short int)(MsgBuffer[9] & 0xff); pSysParms->DtmfFwdTwist = (short int)MsgBuffer[10] & 0x000f; pSysParms->DtmfRevTwist = (short int)(MsgBuffer[10] >> 4) & 0x000f; /* Return with an indication that System Parameters info was obtained. */ return (RspSuccess); } #endif zaptel-1.4.11/kernel/wcte12xp/gpakenum.h0000644000000000000000000001376010775452562016534 0ustar rootroot/* * 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. The standard * GPL disclaimer is given inline below for your convenience. * * 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 _GPAKENUM_H /* prevent multiple inclusion */ #define _GPAKENUM_H /* G.PAK Serial Port Word Size */ typedef enum { SerWordSize8 = 0, // 8-bit seial word SerWordSize16 = 1 // 16-bit serial word } GpakSerWordSize_t; /* G.PAK Serial Port FrameSync Polarity */ typedef enum { FrameSyncActLow = 0, // active low frame sync signal FrameSyncActHigh = 1 // active high frame sync signal } GpakSerFrameSyncPol_t; /* G.PAK Serial Port Clock Polarity */ typedef enum { SerClockActLow = 0, // active low serial clock SerClockActHigh = 1 // active high serial clock } GpakSerClockPol_t; /* G.PAK Serial Port Data Delay */ typedef enum { DataDelay0 = 0, // no data delay DataDelay1 = 1, // 1-bit data delay DataDelay2 = 2 // 2-bit data delay } GpakSerDataDelay_t; /* G.PAK Serial Port Ids. */ typedef enum { SerialPortNull = 0, // null serial port SerialPort1 = 1, // first PCM serial stream port (McBSP0) SerialPort2 = 2, // second PCM serial stream port (McBSP1) SerialPort3 = 3 // third PCM serial stream port (McBSP2) } GpakSerialPort_t; /* G.PAK serial port Slot Configuration selection codes. */ typedef enum { SlotCfgNone = 0, // no time slots used SlotCfg2Groups = 2, // 2 groups of 16 time slots used, 32 Channels system SlotCfg8Groups = 8 // 8-partition mode for 128-channel system } GpakSlotCfg_t; /* G.PAK serial port Companding Mode codes. */ typedef enum { cmpPCMU=0, // u-Law cmpPCMA=1, // A-Law cmpNone=2 // none } GpakCompandModes; /* G.PAK Active/Inactive selection codes. */ typedef enum { Disabled=0, // Inactive Enabled=1 // Active } GpakActivation; /* G.PAK Channel Type codes. */ typedef enum { inactive=0, // channel inactive tdmToTdm=1 // tdmToTdm } GpakChanType; /* G.PAK Algorithm control commands */ typedef enum { EnableEcanA = 0, // Enable A side echo canceller BypassEcanA = 1, // Bypass A side echo canceller ResetEcanA = 2, // Reset A side echo canceller EnableEcanB = 3, // Enable B side echo canceller BypassEcanB = 4, // Bypass B side echo canceller ResetEcanB = 5, // Reset B side echo canceller EnableMuLawSwCompanding = 6,// Enable Mu-law Software companding EnableALawSwCompanding = 7, // Enable Mu-law Software companding BypassSwCompanding = 8, // Bypass Software companding EnableDTMFMuteA = 9, // Mute A side Dtmf digit after tone detected DisableDTMFMuteA = 10, // Do not mute A side Dtmf digit once tone detected EnableDTMFMuteB = 11, // Mute B side Dtmf digit after tone detected DisableDTMFMuteB = 12, // Do not mute B side Dtmf digit once tone detected EnableFaxCngDetectA = 13, // Enable A side Fax CNG detector, channel must be configed already DisableFaxCngDetectA = 14, // Disable A side Fax CNG detector, channel must be configed already EnableFaxCngDetectB = 15, // Enable B side Fax CNG detector, channel must be configed already DisableFaxCngDetectB = 16 // Disable B side Fax CNG detector, channel must be configed already } GpakAlgCtrl_t; /* G.PAK Tone types. */ typedef enum { Null_tone = 0, // no tone detection DTMF_tone = 1 // DTMF tone } GpakToneTypes; /* G.PAK direction. */ typedef enum { TDMAToB = 0, // A to B TDMBToA = 1 // B to A } GpakTdmDirection; typedef enum { rate1ms=0, rate2ms=1, rate10ms=2 } GpakRate_t; /* G.PAK Asynchronous Event Codes */ typedef enum { EventToneDetect = 0, // Tone detection event EventDSPDebug = 7 // DSP debug data event } GpakAsyncEventCode_t; /* G.PAK MF Tone Code Indices */ typedef enum { DtmfDigit1 = 0, // DTMF Digit 1 DtmfDigit2 = 1, // DTMF Digit 2 DtmfDigit3 = 2, // DTMF Digit 3 DtmfDigitA = 3, // DTMF Digit A DtmfDigit4 = 4, // DTMF Digit 4 DtmfDigit5 = 5, // DTMF Digit 5 DtmfDigit6 = 6, // DTMF Digit 6 DtmfDigitB = 7, // DTMF Digit B DtmfDigit7 = 8, // DTMF Digit 7 DtmfDigit8 = 9, // DTMF Digit 8 DtmfDigit9 = 10, // DTMF Digit 9 DtmfDigitC = 11, // DTMF Digit C DtmfDigitSt = 12, // DTMF Digit * DtmfDigit0 = 13, // DTMF Digit 0 DtmfDigitPnd = 14, // DTMF Digit # DtmfDigitD = 15, // DTMF Digit D FaxCngDigit = 90, // Fax Calling Tone (1100 Hz) EndofMFDigit = 100, // End of MF digit EndofCngDigit = 101 // End of Cng Digit } GpakToneCodes_t; /* GPIO control code*/ typedef enum { GPIO_READ = 0, GPIO_WRITE = 1, GPIO_DIR = 2 } GpakGPIOCotrol_t; #endif // end multiple inclusion zaptel-1.4.11/kernel/wcte12xp/wcte12xp.h0000644000000000000000000001120110773007372016357 0ustar rootroot/* * Digium, Inc. Wildcard TE12xP T1/E1 card Driver * * Written by Michael Spiceland * * Adapted from the wctdm24xxp and wcte11xp drivers originally * written by Mark Spencer * Matthew Fredrickson * William Meadows * * Copyright (C) 2007, Digium, Inc. * * All rights reserved. * * 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 _WCTE12XP_H #define _WCTE12XP_H #ifdef LINUX26 /* Comment to disable VPM support */ #define VPM_SUPPORT 1 #endif #define WC_MAX_IFACES 8 #ifdef VPM_SUPPORT #define MAX_TDM_CHAN 31 #endif #define SDI_CLK (0x00010000) #define SDI_DOUT (0x00020000) #define SDI_DREAD (0x00040000) #define SDI_DIN (0x00080000) #define EFRAME_SIZE 108 #define ERING_SIZE 16 /* Maximum ring size */ #define EFRAME_GAP 20 #define SFRAME_SIZE ((EFRAME_SIZE * ZT_CHUNKSIZE) + (EFRAME_GAP * (ZT_CHUNKSIZE - 1))) #define PCI_WINDOW_SIZE ((2 * 2 * 2 * SFRAME_SIZE) + (2 * ERING_SIZE * 4)) #define MAX_COMMANDS 7*7*2*2 /* 42 bytes /3 (cntl,addr,data) /2 (cs) */ #define NUM_EC 4 #define __CMD_VPM (1 << 16) /* flag for VPM action */ #define __CMD_ISR (1 << 17) /* flag for ISR reads */ #define __CMD_PINS (1 << 18) /* CPLD pin read */ #define __CMD_LEDS (1 << 19) /* LED Operation */ #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 __LED_ORANGE (1<<3) #define __LED_GREEN (1<<2) #define __LED_RED (1<<1) #define SET_LED_ORANGE(a) a | __LED_ORANGE #define SET_LED_RED(a) (a | __LED_RED) & ~__LED_GREEN #define SET_LED_GREEN(a) (a | __LED_GREEN) & ~__LED_RED #define UNSET_LED_ORANGE(a) a & ~__LED_ORANGE #define UNSET_LED_REDGREEN(a) a | __LED_RED | __LED_GREEN #define CMD_WR(a,b) (((a) << 8) | (b) | __CMD_WR) #define CMD_RD(a) (((a) << 8) | __CMD_RD) #define CMD_LEDS(a) (((a) << 8) | __CMD_LEDS) //#define CMD_BYTE(slot, a) (slot*6)+(a*2) /* only even slots */ #define CMD_BYTE(slot, a, is_vpm) (slot*6)+(a*2)+is_vpm /* only even slots */ //TODO: make a separate macro #define TYPE_T1 1 #define TYPE_E1 2 #define NOT_VPM -1 #define module_printk(fmt, args...) printk("%s: " fmt, te12xp_driver.name, ## args) #define debug_printk(level, fmt, args...) if (debug >= level) printk("%s (%s): " fmt, te12xp_driver.name, __FUNCTION__, ## args) extern spinlock_t ifacelock; struct command { unsigned short address; unsigned char data; unsigned char ident; unsigned int flags; unsigned char cs_slot; unsigned char vpm_num; /* ignored for all but vpm commmands */ }; struct cmdq { struct command cmds[MAX_COMMANDS]; }; struct vpm150m; struct t1 { spinlock_t reglock; unsigned char txident; unsigned char rxident; unsigned char statreg; /* bit 0 = vpmadt032 int */ int spantype; struct { unsigned int nmf:1; unsigned int sendingyellow:1; } flags; unsigned char txsigs[16]; /* Copy of tx sig registers */ int num; int alarmcount; /* How much red alarm we've seen */ int alarmdebounce; char *variety; char name[80]; unsigned int intcount; int sync; int dead; int blinktimer; int alarmtimer; int yellowtimer; int ledlastvalue; int alarms_read; int checktiming; /* Set >0 to cause the timing source to be checked */ int loopupcnt; int loopdowncnt; int initialized; int *chanmap; unsigned char ledtestreg; unsigned char ec_chunk1[32][ZT_CHUNKSIZE]; unsigned char ec_chunk2[32][ZT_CHUNKSIZE]; struct zt_span span; /* Span */ struct zt_chan chans[32]; /* Channels */ wait_queue_head_t regq; struct cmdq cmdq; struct command dummy; /* preallocate for dummy noop command */ unsigned char ctlreg; unsigned int rxints; unsigned int txints; int usecount; struct voicebus* vb; unsigned int isrreaderrors; #ifdef VPM_SUPPORT int vpm; struct vpm150m *vpm150m; unsigned long dtmfactive; unsigned long dtmfmask; unsigned long dtmfmutemask; #endif }; int schluffen(wait_queue_head_t *q); #endif zaptel-1.4.11/kernel/wcte12xp/GpakErrs.h0000644000000000000000000001465110775452562016443 0ustar rootroot/* * 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. The standard * GPL disclaimer is given inline below for your convenience. * * 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 _GPAKERRS_H /* prevent multiple inclusion */ #define _GPAKERRS_H /* Configure Serial Ports reply status codes. */ typedef enum { Pc_Success = 0, /* serial ports configured successfully */ Pc_ChannelsActive = 1, /* unable to configure while channels active */ Pc_TooManySlots1 = 2, /* too many slots selected for port 1 */ Pc_InvalidBlockCombo1 = 3, /* invalid combination of blocks for port 1 */ Pc_NoSlots1 = 4, /* no slots selected for port 1 */ Pc_InvalidSlots1 = 5, /* invalid slot (> max) selected for port 1 */ Pc_TooManySlots2 = 6, /* too many slots selected for port 2 */ Pc_InvalidBlockCombo2 = 7, /* invalid combination of blocks for port 2 */ Pc_NoSlots2 = 8, /* no slots selected for port 2 */ Pc_InvalidSlots2 = 9, /* invalid slot (> max) selected for port 2 */ Pc_TooManySlots3 = 10, /* too many slots selected for port 3 */ Pc_InvalidBlockCombo3 = 11, /* invalid combination of blocks for port 3 */ Pc_NoSlots3 = 12, /* no slots selected for port 3 */ Pc_InvalidSlots3 = 13 /* invalid slot (> max) selected for port 3 */ } GPAK_PortConfigStat_t; /* Configure Channel reply status codes. */ typedef enum { Cc_Success = 0, /* channel configured successfully */ Cc_InvalidChannelType = 1, /* invalid Channel Type */ Cc_InvalidChannel = 2, /* invalid Channel A Id */ Cc_ChannelActiveA = 3, /* Channel A is currently active */ Cc_InvalidInputPortA = 4, /* invalid Input A Port */ Cc_InvalidInputSlotA = 5, /* invalid Input A Slot */ Cc_BusyInputSlotA = 6, /* busy Input A Slot */ Cc_InvalidOutputPortA = 7, /* invalid Output A Port */ Cc_InvalidOutputSlotA = 8, /* invalid Output A Slot */ Cc_BusyOutputSlotA = 9, /* busy Output A Slot */ Cc_InvalidInputPortB = 10, /* invalid Input B Port */ Cc_InvalidInputSlotB = 11, /* invalid Input B Slot */ Cc_BusyInputSlotB = 12, /* busy Input B Slot */ Cc_InvalidPktInCodingA = 13, /* invalid Packet In A Coding */ Cc_InvalidPktOutCodingA = 14, /* invalid Packet Out A Coding */ Cc_InvalidPktInSizeA = 15, /* invalid Packet In A Frame Size */ Cc_InvalidPktOutSizeA = 16, /* invalid Packet Out A Frame Size */ Cc_ChanTypeNotConfigured = 21, /* channel type was not configured */ Cc_InsuffECResources = 22, /* insufficient ecan resources avail. */ Cc_InsuffTDMResources = 23, /* insufficient tdm block resources avail. */ Cc_InsuffPktBufResources = 25, /* insufficient pkt buffer resources avail. */ Cc_InsuffPcmBufResources = 26, /* insufficient pcm buffer resources avail. */ Cc_BadPcmEcNlpType = 30, /* invalid EC Nlp type */ Cc_BadPcmEcTapLength = 31, /* invalid EC tap length */ Cc_BadPcmEcDblTalkThresh = 32, /* invalid EC double-talk threshold */ Cc_BadPcmEcNlpThreshold = 33, /* invalid EC Nlp threshold */ Cc_BadPcmEcCngThreshold = 34, /* invalid EC Cng threshold */ Cc_BadPcmEcAdaptLimit = 35, /* invalid EC Adapt Limit */ Cc_BadPcmEcCrossCorrLim = 36, /* invalid EC Cross Correlation Limit */ Cc_BadPcmEcNumFirSegs = 37, /* invalid EC Number of FirSegments */ Cc_BadPcmEcFirSegLen = 38, /* invalid EC Fir Segment Length */ /*Cc_InvalidNumEcsEnabled = 48, */ /* more than 1 Ec enabled on channel */ Cc_InvalidFrameRate = 49, /* invalid gpak frame rate */ Cc_InvalidSoftCompand = 50, /* invalid softCompanding type */ Cc_InvalidMuteToneA = 51, /* invalid MuteToneA set, no detector */ Cc_InvalidMuteToneB = 52, /* invalid MuteToneB set, no detector */ Cc_InsuffFaxCngDetResources = 53 /* insufficient tdm block resources avail. */ } GPAK_ChannelConfigStat_t; /* Tear Down Channel reply status codes. */ typedef enum { Td_Success = 0, /* channel torn down successfully */ Td_InvalidChannel = 1, /* invalid Channel Id */ Td_ChannelNotActive = 2 /* channel is not active */ } GPAK_TearDownChanStat_t; typedef enum { Ac_Success = 0, /* algorithm control is successfull */ Ac_InvalidChannel = 1, /* invalid channel identifier */ Ac_InvalidCode = 2, /* invalid algorithm control code */ Ac_ECNotEnabled = 3, /* echo canceller was not allocated */ Ac_InvalidSoftComp = 4, /* invalid softcompanding, 'cause serial port not in companding mode */ Ac_InvalidDTMFMuteA = 5, /* A side invalid Mute, since no dtmf detector */ Ac_InvalidDTMFMuteB = 6, /* B side invalid Mute, since no dtmf detector */ Ac_InvalidFaxCngA = 7, /* A side FAXCNG detector not available */ Ac_InvalidFaxCngB = 8, /* B side FAXCNG detector not available */ Ac_InvalidSysConfig = 9 /* No new system parameters (DTMF config) wrriten yet */ } GPAK_AlgControlStat_t; /* Write System Parameters reply status codes. */ typedef enum { Sp_Success = 0, /* System Parameters written successfully */ Sp_BadTwistThresh = 29 /* invalid twist threshold */ } GPAK_SysParmsStat_t; #endif /* prevent multiple inclusion */ zaptel-1.4.11/kernel/wcte12xp/vpmadt032.h0000644000000000000000000001212610751714440016426 0ustar rootroot/* * Digium, Inc. Wildcard TE12xP T1/E1 card Driver * * Written by Michael Spiceland * * Adapted from the wctdm24xxp and wcte11xp drivers originally * written by Mark Spencer * Matthew Fredrickson * William Meadows * * Copyright (C) 2007, Digium, Inc. * * All rights reserved. * * 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 _VPM150M_H #define _VPM150M_H #include "wcte12xp.h" #include "adt_lec.h" struct t1_firmware { const struct firmware *fw; unsigned int offset; }; /* Host and DSP system dependent related definitions. */ #define MAX_DSP_CORES 128 /* maximum number of DSP cores */ //#define MAX_CONFS 1 /* maximum number of conferences */ //#define MAX_PKT_CHANNELS 8 /* maximum number of packet channels */ #define MAX_CHANNELS 32 /* maximum number of channels */ #define MAX_WAIT_LOOPS 50 /* max number of wait delay loops */ #define DSP_IFBLK_ADDRESS 0x0100 /* DSP address of I/F block pointer */ #define DOWNLOAD_BLOCK_SIZE 512 /* download block size (DSP words) */ //#define MAX_CIDPAYLOAD_BYTES 512 /* max size of a CID payload (octets) */ typedef unsigned short DSP_WORD; /* 16 bit DSP word */ typedef unsigned int DSP_ADDRESS; /* 32 bit DSP address */ typedef struct t1_firmware* GPAK_FILE_ID; /* G.PAK Download file identifier */ #define __VPM150M_RWPAGE (1 << 4) #define __VPM150M_RD (1 << 3) #define __VPM150M_WR (1 << 2) #define __VPM150M_FIN (1 << 1) #define __VPM150M_TX (1 << 0) #define VPM150M_HPI_CONTROL 0x00 #define VPM150M_HPI_ADDRESS 0x02 #define VPM150M_HPI_DATA 0x03 #define VPM150M_MAX_COMMANDS 8 /* Some Bit ops for different operations */ #define VPM150M_SPIRESET 0 #define VPM150M_HPIRESET 1 #define VPM150M_SWRESET 2 #define VPM150M_DTMFDETECT 3 #define VPM150M_ACTIVE 4 #define VPM150M_MAX_DATA 1 struct vpm150m_cmd { unsigned short address; unsigned short data[VPM150M_MAX_DATA]; unsigned char ident; unsigned char datalen; unsigned int flags; unsigned char cs_slot; }; struct vpm150m { unsigned short dspid; unsigned long control; unsigned char curpage; unsigned short version; struct vpm150m_cmd cmdq[VPM150M_MAX_COMMANDS]; spinlock_t lock; /* control access to list of bottom half tasks */ struct semaphore sem; struct workqueue_struct *wq; struct work_struct work_dtmf; struct work_struct work_debug; struct work_struct work_echocan; struct list_head worklist; unsigned char curtone[32]; unsigned long curdtmfmutestate; unsigned long desireddtmfmutestate; struct adt_lec_params chan_params[32]; struct t1 *wc; }; /* linked list for vpm echocan workqueue*/ struct vpm150m_workentry { struct list_head list; struct t1 *wc; /* what card are we dealing with? */ struct zt_chan *chan; /* what channels are we going to deal with? */ struct adt_lec_params params; /* how should we behave? */ }; extern int debug; extern int vpmsupport; extern int vpmdtmfsupport; extern struct pci_driver te12xp_driver; void t1_vpm150m_init(struct t1 *wc); void vpm150m_cmd_dequeue(struct t1 *wc, volatile unsigned char *writechunk, int whichframe); void vpm150m_cmd_decipher(struct t1 *wc, volatile unsigned char *readchunk); int vpm150m_config_hw(struct t1 *wc); /* gpak API functions */ void gpakReadDspMemory( unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ unsigned int NumWords, /* number of contiguous words to read */ DSP_WORD *pWordValues /* pointer to array of word values variable */ ); void gpakWriteDspMemory( unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ unsigned int NumWords, /* number of contiguous words to write */ DSP_WORD *pWordValues /* pointer to array of word values to write */ ); void gpakHostDelay(void); void gpakLockAccess( unsigned short int DspId /* DSP Identifier (0 to MAX_DSP_CORES-1) */ ); void gpakUnlockAccess( unsigned short int DspId /* DSP Identifier (0 to MAX_DSP_CORES-1) */ ); int gpakReadFile( GPAK_FILE_ID FileId, /* G.PAK Download File Identifier */ unsigned char *pBuffer, /* pointer to buffer for storing bytes */ unsigned int NumBytes /* number of bytes to read */ ); #endif zaptel-1.4.11/kernel/wcte12xp/GpakHpi.h0000644000000000000000000000726510775452562016253 0ustar rootroot/* * 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. The standard * GPL disclaimer is given inline below for your convenience. * * 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 _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 */ zaptel-1.4.11/kernel/kb1ec_const.h0000644000000000000000000000463610751714440015433 0ustar rootroot/* Important constants for tuning kb1 echo can */ #ifndef _MEC2_CONST_H #define _MEC2_CONST_H /* 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 #endif /* _MEC2_CONST_H */ zaptel-1.4.11/kernel/oct612x/0002755000000000000000000000000011017303261014255 5ustar rootrootzaptel-1.4.11/kernel/oct612x/Makefile0000644000000000000000000000224510645765316015741 0ustar rootrootCFLAGS=-V3.4 -ffunction-sections -I/lib/modules/$(shell uname -r)/build/include -Iinclude -Ioctdeviceapi -Ioctdeviceapi/oct6100api -DGFP_ATOMIC=0 -Dkmalloc=calloc -Dkfree=free LDFLAGS=-V3.4 -Wl,-Map -Wl,test.map -Wl,--gc-sections APIDIR=octdeviceapi/oct6100api/oct6100_api OCTASIC_OBJS=$(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 \ $(APIDIR)/oct6100_user.o \ apilib/bt/octapi_bt0.o \ apilib/largmath/octapi_largmath.o \ apilib/llman/octapi_llman.o all: test test.o: test.c test: test.o $(OCTASIC_OBJS) clean: rm -rf test test.o rm -rf $(OCTASIC_OBJS) zaptel-1.4.11/kernel/oct612x/apilib/0002755000000000000000000000000011017303260015514 5ustar rootrootzaptel-1.4.11/kernel/oct612x/apilib/largmath/0002755000000000000000000000000011017303260017313 5ustar rootrootzaptel-1.4.11/kernel/oct612x/apilib/largmath/octapi_largmath.c0000644000000000000000000004215510700513330022621 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 zaptel-1.4.11/kernel/oct612x/apilib/llman/0002755000000000000000000000000011017303260016617 5ustar rootrootzaptel-1.4.11/kernel/oct612x/apilib/llman/octapi_llman.c0000644000000000000000000026256110700513330021436 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 **********************************************/ zaptel-1.4.11/kernel/oct612x/apilib/llman/octapi_llman_private.h0000644000000000000000000001655610700513330023176 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__*/ zaptel-1.4.11/kernel/oct612x/apilib/bt/0002755000000000000000000000000011017303260016121 5ustar rootrootzaptel-1.4.11/kernel/oct612x/apilib/bt/octapi_bt0_private.h0000644000000000000000000000644210700513330022053 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__*/ zaptel-1.4.11/kernel/oct612x/apilib/bt/octapi_bt0.c0000644000000000000000000011067610700513330020321 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 zaptel-1.4.11/kernel/oct612x/octasic-helper0000755000000000000000000000177310466370541017127 0ustar rootroot#!/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 zaptel-1.4.11/kernel/oct612x/include/0002755000000000000000000000000011017303261015700 5ustar rootrootzaptel-1.4.11/kernel/oct612x/include/apilib/0002755000000000000000000000000011017303260017137 5ustar rootrootzaptel-1.4.11/kernel/oct612x/include/apilib/octapi_bt0.h0000644000000000000000000000660410700513330021337 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__*/ zaptel-1.4.11/kernel/oct612x/include/apilib/octapi_llman.h0000644000000000000000000002226410700513330021755 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/apilib/octapi_largmath.h0000644000000000000000000000637010700513330022451 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/octosdependant.h0000644000000000000000000001073110700513330021061 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 #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__ */ zaptel-1.4.11/kernel/oct612x/include/digium_unused.h0000644000000000000000000003036110553760471020731 0ustar rootroot/* 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 zaptel-1.4.11/kernel/oct612x/include/octtype.h0000644000000000000000000000765510700513330017551 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 ----------------------------------------------------------------------------*/ /***************************** 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; #ifndef NULL #define NULL 0 #endif #endif /*-------------------------------------------------------------------------- C language ----------------------------------------------------------------------------*/ #ifdef __cplusplus } #endif #endif /* __OCTTYPE_H__ */ zaptel-1.4.11/kernel/oct612x/include/octrpc/0002755000000000000000000000000011017303261017172 5ustar rootrootzaptel-1.4.11/kernel/oct612x/include/octrpc/rpc_protocol.h0000644000000000000000000000773210700513330022055 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/octrpc/oct6100_rpc_protocol.h0000644000000000000000000003054610700513330023230 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/0002755000000000000000000000000011017303261017466 5ustar rootrootzaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_mixer_pub.h0000644000000000000000000000507010700513330023003 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_conf_bridge_pub.h0000644000000000000000000001331710700513330024123 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_channel_inst.h0000644000000000000000000002266510700513330023467 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 ***************************************/ typedef struct _OCT6100_API_CHANNEL_TDM_ { /* Laws. */ UINT8 byRinPcmLaw; UINT8 bySinPcmLaw; UINT8 byRoutPcmLaw; UINT8 bySoutPcmLaw; /* 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; UINT8 byRinNumTssts; UINT8 bySinNumTssts; UINT8 byRoutNumTssts; UINT8 bySoutNumTssts; } tOCT6100_API_CHANNEL_TDM, *tPOCT6100_API_CHANNEL_TDM; typedef struct _OCT6100_API_CHANNEL_VQE_ { UINT8 fEnableNlp; UINT8 fEnableTailDisplacement; UINT16 usTailDisplacement; UINT16 usTailLength; UINT8 fSinDcOffsetRemoval; UINT8 fRinDcOffsetRemoval; UINT8 fRinLevelControl; UINT8 fSoutLevelControl; UINT8 fRinAutomaticLevelControl; UINT8 fSoutAutomaticLevelControl; OCT_INT8 chRinAutomaticLevelControlTargetDb; OCT_INT8 chSoutAutomaticLevelControlTargetDb; UINT8 fRinHighLevelCompensation; OCT_INT8 chRinHighLevelCompensationThresholdDb; UINT8 bySoutAutomaticListenerEnhancementGainDb; UINT8 fSoutNaturalListenerEnhancement; UINT8 fSoutAdaptiveNoiseReduction; UINT8 fDtmfToneRemoval; UINT8 fAcousticEcho; UINT8 byComfortNoiseMode; UINT8 byNonLinearityBehaviorA; UINT8 byNonLinearityBehaviorB; OCT_INT8 chRinLevelControlGainDb; OCT_INT8 chSoutLevelControlGainDb; OCT_INT8 chDefaultErlDb; OCT_INT8 chAecDefaultErlDb; UINT8 fRoutNoiseReduction; OCT_INT8 chRoutNoiseReductionLevelGainDb; OCT_INT8 chAnrSnrEnhancementDb; UINT8 fEnableMusicProtection; UINT8 fIdleCodeDetection; UINT8 byAnrVoiceNoiseSegregation; UINT8 bySoutNaturalListenerEnhancementGainDb; UINT16 usToneDisablerVqeActivationDelay; UINT16 usAecTailLength; UINT8 byDoubleTalkBehavior; UINT8 fSoutNoiseBleaching; UINT8 fSoutConferencingNoiseReduction; } tOCT6100_API_CHANNEL_VQE, *tPOCT6100_API_CHANNEL_VQE; typedef struct _OCT6100_API_CHANNEL_CODEC_ { UINT8 byAdpcmNibblePosition; UINT8 fEnableSilenceSuppression; UINT8 byEncoderPort; UINT8 byEncodingRate; UINT8 byDecoderPort; UINT8 byDecodingRate; UINT8 byPhase; UINT8 byPhasingType; } 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; /* Count used to manage entry handles allocated to user. */ UINT8 byEntryOpenCnt; /* Is this a bidirectionnal channel? */ UINT8 fBiDirChannel; /* Enable tone disabler? */ UINT8 fEnableToneDisabler; /* 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; /* User channel ID, transparently passed to the user. */ UINT32 ulUserChanId; /* 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; /* Current echo operation mode. */ UINT8 byEchoOperationMode; /* 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; UINT8 byToneDisablerStatus; /*=======================================================================*/ /*=======================================================================*/ /* Bridge information. */ UINT16 usBridgeIndex; UINT8 fMute; UINT8 fTap; UINT8 fBeingTapped; UINT8 fCopyEventCreated; UINT16 usLoadEventIndex; UINT16 usSubStoreEventIndex; UINT16 usFlexConfParticipantIndex; UINT16 usTapBridgeIndex; UINT16 usTapChanIndex; /*=======================================================================*/ /*=======================================================================*/ /* Buffer playout information. */ UINT32 ulRinBufWritePtr; UINT32 ulRinBufSkipPtr; UINT8 fSoutBufPlaying; UINT8 fRinBufPlaying; UINT8 fRinBufPlayoutNotifyOnStop; UINT8 fRinBufPlayoutRepeatUsed; UINT32 ulSoutBufWritePtr; UINT32 ulSoutBufSkipPtr; UINT8 fSoutBufPlayoutNotifyOnStop; UINT8 fSoutBufPlayoutRepeatUsed; UINT8 fRinHardStop; UINT8 fSoutHardStop; UINT32 ulRinUserBufPlayoutEventId; UINT32 ulSoutUserBufPlayoutEventId; UINT8 byRinPlayoutStopEventType; UINT8 bySoutPlayoutStopEventType; UINT8 fRinBufAdded; UINT8 fSoutBufAdded; UINT8 fBufPlayoutActive; /*=======================================================================*/ /*=======================================================================*/ /* Copy events information. */ /* Number of copy events created. */ UINT16 usCopyEventCnt; /*=======================================================================*/ /*=======================================================================*/ /* Extended tone detection info. */ /* Enable extended tone detection. */ UINT8 fEnableExtToneDetection; UINT16 usExtToneChanIndex; UINT16 usExtToneMixerIndex; UINT16 usExtToneTsiIndex; /* Mode of operation of the channel based on the extended tone detection configuration. */ UINT32 ulExtToneChanMode; /*=======================================================================*/ /* Tone detection state. */ /* This array is configured as follow. */ /* Index 0 contain event 0 to 31 and Index 1 contains event 32 - 55 */ UINT32 aulToneConf[ 2 ]; UINT32 ulLastSSToneDetected; UINT32 ulLastSSToneTimestamp; /*=======================================================================*/ /*=======================================================================*/ /* Index of the phasing TSST */ UINT16 usPhasingTsstIndex; /* State of the codec structure associated to this channel. */ UINT8 fSinSoutCodecActive; UINT8 fRinRoutCodecActive; /* Codec configuration. */ tOCT6100_API_CHANNEL_CODEC CodecConfig; /*=======================================================================*/ /* Nlp Conf Dword, index 0 contains the dword where the dword is located. and index 1 is the actual value of the dword.*/ UINT32 aulNlpConfDword[ cOCT6100_MAX_NLP_CONF_DWORD ][ 2 ]; } 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; /* Count used to manage entry handles allocated to user. */ UINT8 byEntryOpenCnt; } tOCT6100_API_BIDIR_CHANNEL, *tPOCT6100_API_BIDIR_CHANNEL; #endif /* __OCT6100_CHANNEL_INST_H__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_tlv_inst.h0000644000000000000000000000451210700513330022653 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_apimi.h0000644000000000000000000000426610700513330022116 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_interrupts_inst.h0000644000000000000000000001054710700513330024272 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_defines.h0000644000000000000000000006024010700513330022426 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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.*/ #define cOCT6100_INTERNAL_SUPER_ARRAY_SIZE 1024 /* in words.*/ /* 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 #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.*/ #define cOCT6100_MAX_ECHO_CHANNELS 672 #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 4096 #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.*/ #define cOCT6100_MAX_MIXER_EVENTS 1344 #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 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_phasing_tsst_pub.h0000644000000000000000000000505510700513330024370 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_playout_buf_inst.h0000644000000000000000000000557010700513330024404 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_chip_stats_pub.h0000644000000000000000000001026310700513330024020 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_adpcm_chan_inst.h0000644000000000000000000000460110700513330024122 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_phasing_tsst_inst.h0000644000000000000000000000441710700513330024560 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_adpcm_chan_pub.h0000644000000000000000000000540610700513330023737 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_debug_inst.h0000644000000000000000000000720010700513330023131 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_events_pub.h0000644000000000000000000000621510700513330023165 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_channel_pub.h0000644000000000000000000003313710700513330023274 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_errors.h0000644000000000000000000016600510700513330022333 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_chip_open_inst.h0000644000000000000000000003264110700513330024016 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 ]; UINT16 ausSuperArray1[ cOCT6100_INTERNAL_SUPER_ARRAY_SIZE ]; UINT16 ausSuperArray2[ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_api.h0000644000000000000000000000475710700513330021575 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_remote_debug_inst.h0000644000000000000000000000443410700513330024512 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_tsst_inst.h0000644000000000000000000000374110700513330023046 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_mixer_inst.h0000644000000000000000000000476710700513330023206 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_tsi_cnct_pub.h0000644000000000000000000000475610700513330023477 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_events_inst.h0000644000000000000000000000425010700513330023351 0ustar rootroot /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_api_inst.h0000644000000000000000000000763310700513330022626 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_chip_stats_inst.h0000644000000000000000000000477210700513330024217 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_apiud.h0000644000000000000000000002152110700513330022112 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 UINT32 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_remote_debug_pub.h0000644000000000000000000000427310700513330024324 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_conf_bridge_inst.h0000644000000000000000000000637510700513330024320 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_interrupts_pub.h0000644000000000000000000000600310700513330024073 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_chip_open_pub.h0000644000000000000000000001626010700513330023626 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_tone_detection_pub.h0000644000000000000000000000513710700513330024666 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_debug_pub.h0000644000000000000000000000474310700513330022753 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_playout_buf_pub.h0000644000000000000000000001656410700513330024222 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_tsi_cnct_inst.h0000644000000000000000000000441010700513330023651 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/oct6100api/oct6100_tone_detection_inst.h0000644000000000000000000000327010700513330025051 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/octtypevx.h0000644000000000000000000000617710700513330020125 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/octtypewin.h0000644000000000000000000000555510700513330020264 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/octmac.h0000644000000000000000000000666410700513330017327 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/include/octdef.h0000644000000000000000000000633710700513330017322 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/get_discards0000755000000000000000000000253510473710216016650 0ustar rootroot#!/usr/bin/php zaptel-1.4.11/kernel/oct612x/octdeviceapi/0002755000000000000000000000000011017303257016721 5ustar rootrootzaptel-1.4.11/kernel/oct612x/octdeviceapi/oct6100api/0002755000000000000000000000000011017303260020501 5ustar rootrootzaptel-1.4.11/kernel/oct612x/octdeviceapi/oct6100api/oct6100_adpcm_chan_priv.h0000644000000000000000000001177310700513330025151 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/octdeviceapi/oct6100api/oct6100_miscellaneous_priv.h0000644000000000000000000004410510700513330025732 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 ) /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: mOCT6100_RETRIEVE_NLP_CONF_DWORD 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 ------------------------------------------------------------------------------- IN f_pApiInst Pointer to API instance. This memory is used to keep the present state of the chip and all its resources. IN f_pChanEntry Pointer to an API channel structure.. IN f_ulAddress Address that needs to be modified.. IN f_pulConfigDword Pointer to the content stored in the API located at the desired address. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ #define mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInst, f_pChanEntry, f_ulAddress, f_pulConfigDword, f_ulResult ) \ { \ UINT32 _ulFirstEmptyIndex = 0xFFFFFFFF; \ UINT32 _i; \ \ f_ulResult = cOCT6100_ERR_FATAL_8E; \ (*f_pulConfigDword) = cOCT6100_INVALID_VALUE; \ \ /* 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 ]; \ f_ulResult = cOCT6100_ERR_OK; \ } \ } \ \ if ( ( _i == cOCT6100_MAX_NLP_CONF_DWORD ) && ( _ulFirstEmptyIndex == 0xFFFFFFFF ) ) \ { \ /* Nothing to do here, a fatal error occured, no memory was left. */ \ } \ else \ { \ if ( f_ulResult != cOCT6100_ERR_OK ) \ { \ tOCT6100_READ_PARAMS _ReadParams; \ UINT16 _usReadData; \ \ /* We did not found any entry, let's create a new entry.*/ \ f_pChanEntry->aulNlpConfDword[ _ulFirstEmptyIndex ][ 0 ] = f_ulAddress; \ \ _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, f_ulResult ); \ if ( f_ulResult == cOCT6100_ERR_OK ) \ { \ /* Save data.*/ \ (*f_pulConfigDword) = _usReadData << 16; \ \ /* Read the last 16 bits .*/ \ _ReadParams.ulReadAddress += 2; \ mOCT6100_DRIVER_READ_API( _ReadParams, f_ulResult ); \ if ( f_ulResult == cOCT6100_ERR_OK ) \ { \ /* Save data.*/ \ (*f_pulConfigDword) |= _usReadData; \ f_ulResult = cOCT6100_ERR_OK; \ } \ } \ } \ } \ } /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ Function: mOCT6100_SAVE_NLP_CONF_DWORD Description: This function stores a configuration Dword within an API channel structure and then writes it into the chip. ------------------------------------------------------------------------------- | 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. IN f_pChanEntry Pointer to an API channel structure.. IN f_ulAddress Address that needs to be modified.. IN f_pulConfigDword content to be stored in the API located at the desired address. \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ #define mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInst, f_pChanEntry, f_ulAddress, f_ulConfigDword, f_ulResult ) \ { \ UINT32 _i; \ UINT32 _ulLastValue = 0x0; \ \ /* 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.*/ \ _ulLastValue = f_pChanEntry->aulNlpConfDword[ _i ][ 1 ]; \ f_pChanEntry->aulNlpConfDword[ _i ][ 1 ] = f_ulConfigDword; \ break; \ } \ } \ \ if ( _i == cOCT6100_MAX_NLP_CONF_DWORD ) \ { \ f_ulResult = cOCT6100_ERR_FATAL_8F; \ } \ else \ { \ /* 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; \ \ /* Check if it is worth calling the user function. */ \ if ( ( f_ulConfigDword & 0xFFFF0000 ) != ( _ulLastValue & 0xFFFF0000 ) ) \ { \ /* Write the first 16 bits. */ \ _WriteParams.ulWriteAddress = f_ulAddress; \ _WriteParams.usWriteData = (UINT16)((f_ulConfigDword >> 16) & 0xFFFF); \ mOCT6100_DRIVER_WRITE_API( _WriteParams, f_ulResult ); \ } \ else \ { \ f_ulResult = cOCT6100_ERR_OK; \ } \ \ if ( f_ulResult == cOCT6100_ERR_OK ) \ { \ if ( ( f_ulConfigDword & 0x0000FFFF ) != ( _ulLastValue & 0x0000FFFF ) ) \ { \ /* Write the last word. */ \ _WriteParams.ulWriteAddress = f_ulAddress + 2; \ _WriteParams.usWriteData = (UINT16)(f_ulConfigDword & 0xFFFF); \ mOCT6100_DRIVER_WRITE_API( _WriteParams, f_ulResult ); \ } \ } \ } \ } #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 ); #endif /* __OCT6100_MISCELLANEOUS_PRIV_H__ */ zaptel-1.4.11/kernel/oct612x/octdeviceapi/oct6100api/oct6100_tone_detection_priv.h0000644000000000000000000001001310700513330026061 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/octdeviceapi/oct6100api/oct6100_events_priv.h0000644000000000000000000000602710700513330024374 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/octdeviceapi/oct6100api/oct6100_channel_priv.h0000644000000000000000000004724110700513330024503 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ zaptel-1.4.11/kernel/oct612x/octdeviceapi/oct6100api/oct6100_api/0002755000000000000000000000000011017303257022434 5ustar rootrootzaptel-1.4.11/kernel/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_phasing_tsst.c0000644000000000000000000007641310700513330026464 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 "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 zaptel-1.4.11/kernel/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_user.c0000644000000000000000000003710310700513330024725 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 zaptel-1.4.11/kernel/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_mixer.c0000644000000000000000000015774110700513330025106 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 zaptel-1.4.11/kernel/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_debug.c0000644000000000000000000015042610700513330025041 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 zaptel-1.4.11/kernel/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_tsi_cnct.c0000644000000000000000000010427010700513330025555 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 zaptel-1.4.11/kernel/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_tone_detection.c0000644000000000000000000011354710700513330026761 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 zaptel-1.4.11/kernel/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_playout_buf.c0000644000000000000000000035536710700513330026317 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 ); mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChannel, ulAddress, ulTempData, ulResult ); 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 ); mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChannel, ulAddress, ulTempData, ulResult ); 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; mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChannel, ulAddress, ulTempData, ulResult ); 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; mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChannel, ulAddress, ulTempData, ulResult ); 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; 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. */ 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; 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 ); ulTempData &= ( ~ulMask ); /* Check if the skip need to be clean or not. */ if ( f_pBufferPlayoutStop->fStopCleanly == FALSE ) ulTempData |= 0x1 << ulIgnoreBitOfst; mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChannel, ulAddress, ulTempData, ulResult ); 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; mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChannel, ulAddress, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /*=======================================================================*/ /*=======================================================================*/ /* 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 |= ulSkipPtr << ulSkipPtrBitOfst; mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChannel, ulAddress, ulTempData, ulResult ); 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; mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChannel, ulAddress, &ulTempData, ulResult ); 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; mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChannel, ulAddress, ulTempData, ulResult ); if ( ulResult != cOCT6100_ERR_OK ) return ulResult; /* Now is the appropriate time to skip! */ 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 ); ulTempData &= ( ~ulMask ); /* Set the skip bit. */ ulTempData |= 0x1 << ulIgnoreBitOfst; mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChannel, ulAddress, ulTempData, ulResult ); 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 zaptel-1.4.11/kernel/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_chip_stats.c0000644000000000000000000004266110700513330026115 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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_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 zaptel-1.4.11/kernel/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_tsst.c0000644000000000000000000004356710700513330024757 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 zaptel-1.4.11/kernel/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_conf_bridge.c0000644000000000000000000110137110700513330026210 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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; mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChanEntry, ulBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); 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. */ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChanEntry, ulBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); 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. */ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChanEntry, ulBaseAddress + ulFeatureBytesOffset, &ulTempData, ulResult ); 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. */ mOCT6100_SAVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChanEntry, ulBaseAddress + ulFeatureBytesOffset, ulTempData, ulResult ); 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 zaptel-1.4.11/kernel/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_adpcm_chan.c0000644000000000000000000013127510700513330026031 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 zaptel-1.4.11/kernel/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_chip_open.c0000644000000000000000000070663710700513330025732 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 *******************************/ #include #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 = 672; 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 = 2048; 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 = 1; 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 < cOCT6100_NUM_PGSP_EVENT_OUT || 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 ); 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 zaptel-1.4.11/kernel/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_remote_debug.c0000644000000000000000000016566510700513330026427 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 zaptel-1.4.11/kernel/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_tlv.c0000644000000000000000000021336410700513330024561 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 "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 zaptel-1.4.11/kernel/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_events.c0000644000000000000000000014603310700513330025256 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 = cOCT6100_INVALID_VALUE; pEchoChannel->ulLastSSToneTimestamp = 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 = cOCT6100_INVALID_VALUE; pEchoChannel->ulLastSSToneTimestamp = 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. */ mOCT6100_RETRIEVE_NLP_CONF_DWORD( f_pApiInstance, pEchoChannel, ulPlayoutBaseAddress + ulWritePtrBytesOfst, &ulTempData, ulResult ); 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 zaptel-1.4.11/kernel/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_memory.c0000644000000000000000000006652610700513330025272 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 zaptel-1.4.11/kernel/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_miscellaneous.c0000644000000000000000000004277610700513330026626 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 zaptel-1.4.11/kernel/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_channel.c0000644000000000000000000200314010700513330025353 0ustar rootroot/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 *******************************/ #include #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