dahdi-linux-2.2.0-rc4/0000755000175000017500000000000011202066027013645 5ustar maniacmaniacdahdi-linux-2.2.0-rc4/Makefile0000644000175000017500000001547311176776014015335 0ustar maniacmaniac# # Makefile for DAHDI Linux kernel modules # # Copyright (C) 2001-2009 Digium, Inc. # # PWD:=$(shell pwd) ifndef DEB_HOST_GNU_TYPE UNAME_M:=$(shell uname -m) else UNAME_M:=$(DEB_HOST_GNU_TYPE) endif DAHDI_MODULES_EXTRA:=$(MODULES_EXTRA:%=%.o) $(SUBDIRS_EXTRA:%=%/) # 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 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 # Set HOTPLUG_FIRMWARE=no to override automatic building with hotplug support # if it is enabled in the kernel. ifeq (yes,$(HAS_KSRC)) HOTPLUG_FIRMWARE:=$(shell if grep -q '^CONFIG_FW_LOADER=[ym]' $(KCONFIG); then echo "yes"; else echo "no"; fi) endif MODULE_ALIASES:=wcfxs wctdm8xxp wct2xxp INST_HEADERS:=kernel.h user.h fasthdlc.h wctdm_user.h dahdi_config.h DAHDI_BUILD_ALL:=m KMAKE=$(MAKE) -C $(KSRC) SUBDIRS=$(PWD)/drivers/dahdi DAHDI_INCLUDE=$(PWD)/include DAHDI_MODULES_EXTRA="$(DAHDI_MODULES_EXTRA)" HOTPLUG_FIRMWARE=$(HOTPLUG_FIRMWARE) ifneq (,$(wildcard $(DESTDIR)/etc/udev/rules.d)) DYNFS:=yes endif ROOT_PREFIX:= ASCIIDOC:=asciidoc ASCIIDOC_CMD:=$(ASCIIDOC) -n -a toc -a toclevels=4 GENERATED_DOCS:=README.html ifneq ($(wildcard .version),) DAHDIVERSION:=$(shell cat .version) else ifneq ($(wildcard .svn),) DAHDIVERSION:=$(shell build_tools/make_version . dahdi/linux) endif endif all: modules 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 DAHDI_BUILD_ALL=$(DAHDI_BUILD_ALL) include/dahdi/version.h: FORCE @DAHDIVERSION="${DAHDIVERSION}" build_tools/make_version_h > $@.tmp @if cmp -s $@.tmp $@ ; then :; else \ mv $@.tmp $@ ; \ fi @rm -f $@.tmp prereq: include/dahdi/version.h firmware-loaders stackcheck: checkstack modules ./checkstack kernel/*.ko kernel/*/*.ko install: all install-modules install-devices install-include install-firmware install-xpp-firm @echo "###################################################" @echo "###" @echo "### DAHDI installed successfully." @echo "### If you have not done so before, install the package" @echo "### dahdi-tools." @echo "###" @echo "###################################################" uninstall: uninstall-modules uninstall-devices uninstall-include uninstall-firmware install-modconf: build_tools/genmodconf $(BUILDVER) "$(ROOT_PREFIX)" "$(filter-out dahdi dahdi_dummy xpp dahdi_transcode dahdi_dynamic,$(BUILD_MODULES)) $(MODULE_ALIASES)" @if [ -d /etc/modutils ]; then \ /sbin/update-modules ; \ fi install-xpp-firm: $(MAKE) -C drivers/dahdi/xpp/firmwares install install-firmware: ifeq ($(HOTPLUG_FIRMWARE),yes) $(MAKE) -C drivers/dahdi/firmware hotplug-install DESTDIR=$(DESTDIR) HOTPLUG_FIRMWARE=$(HOTPLUG_FIRMWARE) endif uninstall-firmware: $(MAKE) -C drivers/dahdi/firmware hotplug-uninstall DESTDIR=$(DESTDIR) firmware-loaders: $(MAKE) -C drivers/dahdi/firmware firmware-loaders install-include: for hdr in $(INST_HEADERS); do \ install -D -m 644 include/dahdi/$$hdr $(DESTDIR)/usr/include/dahdi/$$hdr; \ done -@rm -f $(DESTDIR)/usr/include/zaptel/*.h -@rmdir $(DESTDIR)/usr/include/zaptel uninstall-include: for hdr in $(INST_HEADERS); do \ rm -f $(DESTDIR)/usr/include/dahdi/$$hdr; \ done -rmdir $(DESTDIR)/usr/include/dahdi install-devices: ifndef DYNFS mkdir -p $(DESTDIR)/dev/dahdi rm -f $(DESTDIR)/dev/dahdi/ctl rm -f $(DESTDIR)/dev/dahdi/channel rm -f $(DESTDIR)/dev/dahdi/pseudo rm -f $(DESTDIR)/dev/dahdi/timer rm -f $(DESTDIR)/dev/dahdi/transcode rm -f $(DESTDIR)/dev/dahdi/253 rm -f $(DESTDIR)/dev/dahdi/252 rm -f $(DESTDIR)/dev/dahdi/251 rm -f $(DESTDIR)/dev/dahdi/250 mknod $(DESTDIR)/dev/dahdi/ctl c 196 0 mknod $(DESTDIR)/dev/dahdi/transcode c 196 250 mknod $(DESTDIR)/dev/dahdi/timer c 196 253 mknod $(DESTDIR)/dev/dahdi/channel c 196 254 mknod $(DESTDIR)/dev/dahdi/pseudo c 196 255 N=1; \ while [ $$N -lt 250 ]; do \ rm -f $(DESTDIR)/dev/dahdi/$$N; \ mknod $(DESTDIR)/dev/dahdi/$$N c 196 $$N; \ N=$$[$$N+1]; \ done else # DYNFS install -d $(DESTDIR)/etc/udev/rules.d build_tools/genudevrules > $(DESTDIR)/etc/udev/rules.d/dahdi.rules install -m 644 drivers/dahdi/xpp/xpp.rules $(DESTDIR)/etc/udev/rules.d/ endif uninstall-devices: ifndef DYNFS -rm -rf $(DESTDIR)/dev/dahdi else # DYNFS rm -f $(DESTDIR)/etc/udev/rules.d/dahdi.rules endif install-modules: modules ifndef DESTDIR @if modinfo zaptel > /dev/null 2>&1; then \ echo -n "Removing Zaptel modules for kernel $(KVERS), please wait..."; \ build_tools/uninstall-modules zaptel $(KVERS); \ rm -rf /lib/modules/$(KVERS)/zaptel; \ echo "done."; \ fi build_tools/uninstall-modules dahdi $(KVERS) endif $(KMAKE) INSTALL_MOD_PATH=$(DESTDIR) INSTALL_MOD_DIR=dahdi modules_install [ `id -u` = 0 ] && /sbin/depmod -a $(KVERS) || : uninstall-modules: ifdef DESTDIR @echo "Uninstalling modules is not supported with a DESTDIR specified." @exit 1 else @if modinfo dahdi > /dev/null 2>&1 ; then \ echo -n "Removing DAHDI modules for kernel $(KVERS), please wait..."; \ build_tools/uninstall-modules dahdi $(KVERS); \ rm -rf /lib/modules/$(KVERS)/dahdi; \ echo "done."; \ fi [ `id -u` = 0 ] && /sbin/depmod -a $(KVERS) || : endif 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: ifneq (no,$(HAS_KSRC)) $(KMAKE) clean endif @rm -f $(GENERATED_DOCS) $(MAKE) -C drivers/dahdi/firmware clean distclean: dist-clean dist-clean: clean @rm -f include/dahdi/version.h @$(MAKE) -C drivers/dahdi/firmware dist-clean @rm -f drivers/dahdi/vpmadt032_loader/*.o_shipped firmware-download: @$(MAKE) -C drivers/dahdi/firmware all test: ./test-script $(DESTDIR)/lib/modules/$(KVERS) dahdi docs: $(GENERATED_DOCS) README.html: README $(ASCIIDOC_CMD) -o $@ $< .PHONY: distclean dist-clean clean all install devices modules stackcheck install-udev update install-modules install-include uninstall-modules firmware-download install-xpp-firm firmware-loaders FORCE: dahdi-linux-2.2.0-rc4/README0000644000175000017500000004647711135146632014555 0ustar maniacmaniacDAHDI Telephony Interface Driver ================================= Asterisk Development Team $Revision: 5749 $, $Date: 2009-01-19 12:59:38 -0600 (Mon, 19 Jan 2009) $ DAHDI stands for Digium Asterisk Hardware Device Interface. This package contains the kernel modules for DAHDI. For the required userspace tools see the package dahdi-tools. 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 - wcb4xxp: * Digium B410: PCI quad-port BRI - tor2: Tormenta quad-span T1/E1 card from the Zapata Telephony project Analog Cards ~~~~~~~~~~~~ - wctdm24xxp: * Digium TDM2400P/AEX2400: up to 24 analog ports * Digium TDM800P/AEX800: up to 8 analog ports * Digium TDM410P/AEX410: 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 (including the digital BRI and E1/T1 modules) - wcfxo: X100P, similar and clones. A simple single-port FXO card Other Drivers ~~~~~~~~~~~~~ - pciradio: Zapata Telephony PCI Quad Radio Interface - wctc4xxp: Digium hardware transcoder cards (also need dahdi_transcode) - dahdi_dynamic_eth: TDM over Ethernet (TDMoE) driver. Requires dahdi_dynamic - dahdi_dynamic_loc: Mirror a local span. Requires dahdi_dynamic - dahdi_dummy: A dummy driver that only provides a DAHDI timing source. Installation ------------ If all is well, you just need to run the following: make make install You'll need the utilities provided in the package dahdi-tools to configure DAHDI devices on your system. If using `sudo` to build/install, you may need to add /sbin to your PATH. If you still have problems, read further. Build Requirements ~~~~~~~~~~~~~~~~~~ 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. TODO: copy build requirement from Zaptel README. Installing 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= Extra Modules ~~~~~~~~~~~~~ To build extra modules / modules directory not included in the DAHDI distribution, use the optional variables MODULES_EXTRA and SUBDIRS_EXTRA: make MODULES_EXTRA="mod1 mod2" make MODULES_EXTRA="mod1 mod2" SUBDIRS_EXTRA="subdir1/ subdir1/" Installing the B410P drivers with mISDN ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DAHDI includes the wcb4xxp driver for the B410P, however, support for the B410P was historically provided by mISDN. If you would like to use the mISDN driver with the B410P, please comment out the wcb4xxp line in /etc/dahdi/modules. This will prevent DAHDI from loading wcb4xxp which will conflict with the mISDN driver. To install the mISDN driver for the B410P, please see http://www.misdn.org for more information, but the following sequence of steps is roughly equivalent to 'make b410p' from previous releases. wget http://www.misdn.org/downloads/releases/mISDN-1_1_8.tar.gz wget http://www.misdn.org/downloads/releases/mISDNuser-1_1_8.tar.gz tar xfz mISDN-1_1_8.tar.gz tar xfz mISDNuser-1_1_8.tar.gz pushd mISDN-1_1_8 make install popd pushd mISDNuser-1_1_8 make install popd /usr/sbin/misdn-init config You will then also want to make sure /etc/init.d/misdn-init is started automatically with either 'chkconfig --add misdn-init' or 'update-rc.d misdn-init defaults 15 30' depending on your distribution. NOTE: At the time this was written, misdn-1.1.8 is not compatible the 2.6.25 kernel. Please use a kernel version 2.6.25 or earlier. OSLEC ~~~~~ http://www.rowetel.com/ucasterisk/oslec.html[OSLEC] is an Open Source Line Echo Canceller. It is currently in the staging subtree of the mainline kernel and will hopefully be fully merged at around version 2.6.29. The echo canceller module dahdi_echocan_oslec provides a DAHDI echo canceller module that uses the code from OSLEC. As OSLEC has not been accepted into mainline yet, its interface is not set in stone and thus this driver may need to change. Thus it is not built by default. Luckily the structure of the dahdi-linux tree matches that of the kernel tree. Hence you can basically copy drivers/staging/echo and place it under driver/staging/echo . In fact, dahdi_echocan_oslec assumes that this is where the oslec code lies. If it is elsewhere you'll need to fix the #include line. Thus for the moment, the simplest way to build OSLEC with dahdi is: 1. Copy the directory `drivers/staging/echo` from a recent kernel tree (at least 2.6.28-rc1) to the a subdirectory with the same name in the dahdi-linux tree. 2. Edit drivers/dahdi/Kbuild and unrem the two lines related to OSLEC. After doing that, you'll see the following when building (running 'make') ... CC [M] /home/tzafrir/dahdi-linux/drivers/dahdi/dahdi_echocan_oslec.o CC [M] /home/tzafrir/dahdi-linux/drivers/dahdi/../staging/echo/echo.o ... As this is an experimental driver, problems building and using it should be reported on the https://lists.sourceforge.net/lists/listinfo/freetel-oslec[OSLEC mailing list]. 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. Example line: options dahdi debug=1 The module parameters can normally be modified at runtime through sysfs: pungenday:~# cat /sys/module/dahdi/parameters/debug 0 pungenday:~# echo 1 >/sys/module/dahdi/parameters/debug pungenday:~# cat /sys/module/dahdi/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: - dahdi_dummy: * 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: 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 - DAHDI 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 (dahdi):: 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_dahdi 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 . Internals --------- DAHDI Device Files ~~~~~~~~~~~~~~~~~~~ Userspace programs will usually interact with DAHDI through device files under the /dev/dahdi directory (pedantically: characted device files with major number 196) . Those device files can be generated statically or dynamically through the udev system. * /dev/dahdi/ctl (196:0) - a general device file for various information and control operations on the DAHDI channels. * /dev/dahdi/NNN (196:NNN) - for NNN in the range 1-249. A device file for DAHDI channel NNN. It can be used to read data from the channel and write data to the channel. * /dev/dahdi/transcode (196:250) - Used to connect to a DAHDI transcoding device. * /dev/dahdi/timer (196:253) - Allows setting timers. Used anywhere? * /dev/dahdi/channel (196:254) - Can be used to open an arbitrary DAHDI channel. This is an alternative to /dev/dahdi/NNN that is not limited to 249 channels. * /dev/dahdi/pseudo (196:255) - A timing-only device. Every time you open it, a new DAHDI channel is created. That DAHDI channel is "pseudo" - DAHDI recieves no data in it, and only sends garbage data with the same timing as the DAHDI timing master device. DAHDI 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. DAHDI "ticks" once per millisecond (1000 times per second). On each tick every active DAHDI channel reads and 8 bytes of data. Asterisk also uses this for timing, through a DAHDI 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 DAHDI hardware at all. Even a digital card may be used for other uses or is simply not connected to a provider. DAHDI 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 dahdi_dummy to provide timing alone without needing any DAHDI hardware. It will work with most systems and kernels. You can check the DAHDI timing source with dahdi_test, which is a small utility that is included with DAHDI. It runs in cycles. In each such cycle it tries to read 8192 bytes, and sees how long it takes. If DAHDI is not loaded or you don't have the device files, it will fail immediately. If you lack a timing device it will hang forever in the first cycle. Otherwise 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 dahdi_dummy, you can either look at title of its span in /proc/dahdi file for a "source:" in the description. Or even run: strings dahdi.ko | grep source: Spans and Channels ~~~~~~~~~~~~~~~~~~ DAHDI provides telephony *channels* to the userspace applications. Those channels are channels are incorperated 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/dahdi ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A simple way to get the current list of spans and channels each span contains is the files under /proc/dahdi . /proc/dahdi is generated by DAHDI as it loads. As each span registers to DAHDI, a file under /proc/dahdi 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 dahdi_cfg. Before being configured by dahdi_cfg: This is DAHDI channel 2, whose name is 'XPP_FXS/0/0/1'. 2 XPP_FXS/0/0/1 After being configured by dahdi_cfg: 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, DAHDI strives to maintain a stable interface to userspace programs. The API of DAHDI to userspace programs, dahdi/user.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. DAHDI'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 DAHDI 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 DAHDI_EXAMPLE _IOWR (DAHDI_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 DAHDI_EXAMPLE_V1 _IOWR (DAHDI_CODE, 62, struct zt_example_v1) #define DAHDI_EXAMPLE _IOWR (DAHDI_CODE, 62, struct zt_example) ------------------------------------ We actually have here two different ioctls: the old DAHDI_EXAMPLE would be 0xC0044A3E . DAHDI_EXAMPLE_V1 would have the same value. But the new value of DAHDI_EXAMPLE would be 0xC0084A3E . (TODO: fix ioctl values) Programs built with the original dahdi/user.h (before the change) use the original ioctl, whether or not the kernel 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 dahdi/user.h, but the loaded kernel code (modules) are of the older version. Thus the userspace program will try to use the newer DAHDI_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 all versions of DAHDI. Alarm Types ~~~~~~~~~~~ An alarm indicates that a port is not available for some reason. Thus it is probably not a good idea to try to call out through it. Red Alarm ^^^^^^^^^ Your T1/E1 port will go into red alarm when it cannot maintain synchronization with the remote switch. A red alarm typically indicates either a physical wiring problem, loss of connectivity, or a framing and/or line-coding mismatch with the remote switch. When your T1/E1 port loses sync, it will transmit a yellow alarm to the remote switch to indicate that it's having a problem receiving signal from the remote switch. The easy way to remember this is that the R in red stands for "right here" and "receive"... indicating that we're having a problem right here receiving the signal from the remote switch. Yellow Alarm ^^^^^^^^^^^^ (RAI -- Remote Alarm Indication) Your T1/E1 port will go into yellow alarm when it receives a signal from the remote switch that the port on that remote switch is in red alarm. This essentially means that the remote switch is not able to maintain sync with you, or is not receiving your transmission. The easy way to remember this is that the Y in yellow stands for "yonder"... indicating that the remote switch (over yonder) isn't able to see what you're sending. Blue Alarm ^^^^^^^^^^ (AIS -- Alarm Indication Signal) Your T1/E1 port will go into blue alarm when it receives all unframed 1s on all timeslots from the remote switch. This is a special signal to indicate that the remote switch is having problems with its upstream connection. dahdi_tool and Asterisk don't correctly indicate a blue alarm at this time. The easy way to remember this is that streams are blue, so a blue alarm indicates a problem upstream from the switch you're connected to. Recovering from Alarm ^^^^^^^^^^^^^^^^^^^^^ TODO: explain. Loopback ^^^^^^^^ Not really an alarm. Indicates that a span is not available, as the port is in either a local or remote loopback mode. Not Open ^^^^^^^^ Something is not connected. Used by e.g. the drivers of the Astribank to indicate a span that belongs to a device that has been disconnected but is still being used by userspace programs and thus can't e destroyed. License ------- This package is distributed under the terms of the GNU General Public License Version 2, except for some components which are distributed under the terms of the GNU Lesser General Public License Version 2.1. Both licenses are included in this directory, and each file is clearly marked as to which license applies. If you wish to use the DAHDI drivers in an application for which the license terms are not appropriate (e.g. a proprietary embedded system), licenses under more flexible terms can be readily obtained through Digium, Inc. at reasonable cost. Reporting Bugs -------------- Please report bug and patches to the Asterisk bug tracker at http://bugs.digium.com in the "DAHDI" category. Links ----- - http://asterisk.org/[] - The Asterisk PBX - http://voip-info.org/[] - http://voip-info.org/wiki/view/DAHDI[] - http://docs.tzafrir.org.il/dahdi-linux/README.html[Up-to-date HTML version of this file] dahdi-linux-2.2.0-rc4/LICENSE.LGPL0000644000175000017500000006346711046164220015427 0ustar maniacmaniac GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! dahdi-linux-2.2.0-rc4/.version0000644000175000017500000000001211202066016015322 0ustar maniacmaniac2.2.0-rc4 dahdi-linux-2.2.0-rc4/UPGRADE.txt0000644000175000017500000000733411046420461015506 0ustar maniacmaniac===================================================================== === Information for upgrading from Zaptel 1.2 or 1.4 to DAHDI 2.0 === ===================================================================== Upgrading from Zaptel to DAHDI is fairly straightforward; install this package using the installation instructions, and then reconfigure and rebuild Asterisk; Asterisk 1.4 releases later than 1.4.21, and all releases of Asterisk 1.6, will automatically use DAHDI in preference to Zaptel, even if Zaptel is still installed on the system. Important notes about upgrading: * The Zaptel package, which included both kernel modules and userspace tools for configuring and managing the modules, has been split into two packages: dahdi-linux: kernel modules dahdi-tools: userspace tools In addition, there is a dahdi-linux-complete package that contains both dahdi-linux and dahdi-tools for simplified installation. Note: The dahdi-linux and dahdi-tools packages have *separate* version numbers; they will not be released 'in sync', and it is perfectly acceptable to use (for example) dahdi-tools 2.0.6 with dahdi-linux 2.0.11. The dahdi-linux-complete package version number will always include *both* of these version numbers so that you will know what is included in it. Notes about the dahdi-linux package: * The primary kernel modules have changed names; the new names are: zaptel.ko -> dahdi.ko ztd-eth.ko -> dahdi_dynamic_eth.ko ztd-loc.ko -> dahdi_dynamic_loc.ko ztdummy.ko -> dahdi_dummy.ko ztdynamic.ko -> dahdi_dynamic.ko zttranscode.ko -> dahdi_transcode.ko * The kernel modules for card drivers have *not* changed names, although the wcusb and torisa drivers are no longer included. * This package no longer includes the 'menuselect' utility for choosing which modules to build; all modules that can be built are built automatically. * It is no longer possible to select a software echo canceler at compile time to build into dahdi.ko; all four included echo cancelers (MG2, KB1, SEC and SEC2) are built as loadable modules, and if the Digium HPEC binary object file has been placed into the proper directory the HPEC module will be built as well. Any or all of these modules can be loaded at the same time, and the echo canceler to be used on the system's channels can be configured using the dahdi_cfg tool from the dahdi-tools package. Note: It is *mandatory* to configure an echo canceler for the system's channels using dahdi_cfg unless the interface cards in use have echo canceler modules available and enabled. There is *no* default software echo canceler with DAHDI. Notes about the dahdi-tools package: * Many tool names have changed: ztcfg -> dahdi_cfg ztmonitor -> dahdi_monitor ztscan -> dahdi_scan ztspeed -> dahdi_speed zttest -> dahdi_test zttool -> dahdi_tool zapconf -> dahdi_genconf (deprecates genzaptelconf) * The system configuration file has moved from /etc/zaptel.conf to /etc/dahdi/system.conf. * The dahdi_cfg tool can now be used to select an echo canceler on a channel-by-channel basis in the system configuration file; see system.conf.sample for examples of how to do this. * The configuration for XPP init_card_* scripts is done now in /etc/dahdi/xpp.conf and uses a simple syntax (example included). For PRI modules, the 'pri_protocol' setting, determines how to configure it (E1/T1). * In Astribank PRI modules, the LED behaviour represents which ports are *CLOCK MASTER* (red color) and which are *CLOCK SLAVE* (green color). Usually (but not always), this corresponds to the NT/TE settings in Asterisk. dahdi-linux-2.2.0-rc4/include/0000755000175000017500000000000011202066027015270 5ustar maniacmaniacdahdi-linux-2.2.0-rc4/include/dahdi/0000755000175000017500000000000011202066027016341 5ustar maniacmaniacdahdi-linux-2.2.0-rc4/include/dahdi/Kbuild0000644000175000017500000000012711026016414017475 0ustar maniacmaniacheader-y += kernel.h header-y += user.h header-y += wctdm_user.h header-y += version.h dahdi-linux-2.2.0-rc4/include/dahdi/wctdm_user.h0000644000175000017500000000316511046164220020673 0ustar maniacmaniac/* * Wildcard S100P FXS Interface Driver for DAHDI Telephony interface * * Written by Mark Spencer * * Copyright (C) 2001-2008, Digium, Inc. * * All rights reserved. * */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ #ifndef _WCTDM_H #define _WCTDM_H #include #define NUM_REGS 109 #define NUM_INDIRECT_REGS 105 struct wctdm_stats { int tipvolt; /* TIP voltage (mV) */ int ringvolt; /* RING voltage (mV) */ int batvolt; /* VBAT voltage (mV) */ }; struct wctdm_regs { unsigned char direct[NUM_REGS]; unsigned short indirect[NUM_INDIRECT_REGS]; }; struct wctdm_regop { int indirect; unsigned char reg; unsigned short val; }; struct wctdm_echo_coefs { unsigned char acim; unsigned char coef1; unsigned char coef2; unsigned char coef3; unsigned char coef4; unsigned char coef5; unsigned char coef6; unsigned char coef7; unsigned char coef8; }; #define WCTDM_GET_STATS _IOR (DAHDI_CODE, 60, struct wctdm_stats) #define WCTDM_GET_REGS _IOR (DAHDI_CODE, 61, struct wctdm_regs) #define WCTDM_SET_REG _IOW (DAHDI_CODE, 62, struct wctdm_regop) #define WCTDM_SET_ECHOTUNE _IOW (DAHDI_CODE, 63, struct wctdm_echo_coefs) #endif /* _WCTDM_H */ dahdi-linux-2.2.0-rc4/include/dahdi/kernel.h0000644000175000017500000011340011176115504017776 0ustar maniacmaniac/* * DAHDI Telephony Interface * * Written by Mark Spencer * Based on previous works, designs, and architectures conceived and * written by Jim Dixon . * * Copyright (C) 2001 Jim Dixon / Zapata Telephony. * Copyright (C) 2001 - 2008 Digium, Inc. * * All rights reserved. * */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ /*! * \file * \brief DAHDI kernel interface definitions */ #ifndef _DAHDI_KERNEL_H #define _DAHDI_KERNEL_H #include #include #include #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) #include #endif #include #include #ifdef CONFIG_DAHDI_NET #include #endif #ifdef CONFIG_DAHDI_PPP #include #include #include #endif #include #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) #define dahdi_pci_module pci_register_driver #else #define dahdi_pci_module pci_module_init #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19) #define DAHDI_IRQ_HANDLER(a) static irqreturn_t a(int irq, void *dev_id) #else #define DAHDI_IRQ_HANDLER(a) static irqreturn_t a(int irq, void *dev_id, struct pt_regs *regs) #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) #define DAHDI_IRQ_SHARED IRQF_SHARED #define DAHDI_IRQ_DISABLED IRQF_DISABLED #define DAHDI_IRQ_SHARED_DISABLED IRQF_SHARED | IRQF_DISABLED #else #define DAHDI_IRQ_SHARED SA_SHIRQ #define DAHDI_IRQ_DISABLED SA_INTERRUPT #define DAHDI_IRQ_SHARED_DISABLED SA_SHIRQ | SA_INTERRUPT #endif #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16) #ifndef dev_notice #define dev_notice(dev, format, arg...) \ dev_printk(KERN_NOTICE , dev , format , ## arg) #endif #endif /*! Default chunk size for conferences and such -- static right now, might make variable sometime. 8 samples = 1 ms = most frequent service interval possible for a USB device */ #define DAHDI_CHUNKSIZE 8 #define DAHDI_MIN_CHUNKSIZE DAHDI_CHUNKSIZE #define DAHDI_DEFAULT_CHUNKSIZE DAHDI_CHUNKSIZE #define DAHDI_MAX_CHUNKSIZE DAHDI_CHUNKSIZE #define DAHDI_CB_SIZE 2 #define RING_DEBOUNCE_TIME 2000 /*!< 2000 ms ring debounce time */ typedef struct { int32_t gain; int32_t a1; int32_t a2; int32_t b1; int32_t b2; int32_t z1; int32_t z2; } biquad2_state_t; typedef struct { biquad2_state_t notch; int notch_level; int channel_level; int tone_present; int tone_cycle_duration; int good_cycles; int hit; } echo_can_disable_detector_state_t; struct sf_detect_state { long x1; long x2; long y1; long y2; long e1; long e2; int samps; int lastdetect; }; struct dahdi_tone_state { int v1_1; int v2_1; int v3_1; int v1_2; int v2_2; int v3_2; int modulate; }; /*! \brief Conference queue structure */ struct confq { u_char buffer[DAHDI_CHUNKSIZE * DAHDI_CB_SIZE]; u_char *buf[DAHDI_CB_SIZE]; int inbuf; int outbuf; }; struct dahdi_chan; struct dahdi_echocan_state; /*! Features a DAHDI echo canceler (software or hardware) can provide to the DAHDI core. */ struct dahdi_echocan_features { /*! Able to detect CED tone (2100 Hz with phase reversals) in the transmit direction. * If the echocan can detect this tone, it may report it it as an event (see * the events.CED_tx_detected field of dahdi_echocan_state), and if it will automatically * disable itself or its non-linear processor, then the NLP_automatic feature flag should also * be set so that the DAHDI core doesn't bother trying to do so. */ u32 CED_tx_detect:1; /*! Able to detect CED tone (2100 Hz with phase reversals) in the receive direction. * If the echocan can detect this tone, it may report it it as an event (see * the events.CED_rx_detected field of dahdi_echocan_state), and if it will automatically * disable itself or its non-linear processor, then the NLP_automatic flag feature should also * be set so that the DAHDI core doesn't bother trying to do so. */ u32 CED_rx_detect:1; /*! Able to detect CNG tone (1100 Hz) in the transmit direction. */ u32 CNG_tx_detect:1; /*! Able to detect CNG tone (1100 Hz) in the receive direction. */ u32 CNG_rx_detect:1; /*! If the echocan's NLP can be enabled and disabled without requiring destruction * and recreation of the state structure, this feature flag should be set and the * echocan_NLP_toggle field of the dahdi_echocan_ops structure should be filled with a * pointer to the function to perform that operation. */ u32 NLP_toggle:1; /*! If the echocan will automatically disable itself (or even just its NLP) based on * detection of a CED tone in either direction, this feature flag should be set (along * with the tone detection feature flags). */ u32 NLP_automatic:1; }; /*! Operations (methods) that can be performed on a DAHDI echo canceler instance (state * structure) after it has been created, by either a software or hardware echo canceller. * The echo canceler must populate the owner field of the dahdi_echocan_state structure * with a pointer to the relevant operations structure for that instance. */ struct dahdi_echocan_ops { /*! The name of the echocan that created this structure. */ const char *name; /*! \brief Free an echocan state structure. * \param[in,out] ec Pointer to the state structure to free. * * \return Nothing. */ void (*echocan_free)(struct dahdi_chan *chan, struct dahdi_echocan_state *ec); /*! \brief Process an array of audio samples through the echocan. * \param[in,out] ec Pointer to the state structure. * \param[in,out] isig The receive direction data (will be modified). * \param[in] iref The transmit direction data. * \param[in] size The number of elements in the isig and iref arrays. * * Note: This function can also return events in the events field of the * dahdi_echocan_state structure. If it can do so, then the echocan does * not need to provide the echocan_events function. * * \return Nothing. */ void (*echocan_process)(struct dahdi_echocan_state *ec, short *isig, const short *iref, u32 size); /*! \brief Retrieve events from the echocan. * \param[in,out] ec Pointer to the state structure. * * * If any events have occurred, the events field of the dahdi_echocan_state * structure should be updated to include them. * * \return Nothing. */ void (*echocan_events)(struct dahdi_echocan_state *ec); /*! \brief Feed a sample (and its position) for echocan training. * \param[in,out] ec Pointer to the state structure. * \param[in] pos The tap position to be 'trained'. * \param[in] val The receive direction sample for the specified tap position. * * \retval Zero if training should continue. * \retval Non-zero if training is complete. */ int (*echocan_traintap)(struct dahdi_echocan_state *ec, int pos, short val); /*! \brief Enable or disable non-linear processing (NLP) in the echocan. * \param[in,out] ec Pointer to the state structure. * \param[in] enable Zero to disable, non-zero to enable. * * \return Nothing. */ void (*echocan_NLP_toggle)(struct dahdi_echocan_state *ec, unsigned int enable); }; /*! A factory for creating instances of software echo cancelers to be used on DAHDI channels. */ struct dahdi_echocan_factory { /*! The name of the factory. */ const char *name; /*! Pointer to the module that owns this factory; the module's reference count will be * incremented/decremented by the DAHDI core as needed. */ struct module *owner; /*! \brief Function to create an instance of the echocan. * \param[in] ecp Structure defining parameters to be used for the instance creation. * \param[in] p Pointer to the beginning of an (optional) array of user-defined parameters. * \param[out] ec Pointer to the state structure that is created, if any. * * \retval Zero on success. * \retval Non-zero on failure (return value will be returned to userspace so it should be a * standard error number). */ int (*echocan_create)(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec); }; /*! \brief Register an echo canceler factory with the DAHDI core. * \param[in] ec Pointer to the dahdi_echocan_factory structure to be registered. * * \retval Zero on success. * \retval Non-zero on failure (return value will be a standard error number). */ int dahdi_register_echocan_factory(const struct dahdi_echocan_factory *ec); /*! \brief Unregister a previously-registered echo canceler factory from the DAHDI core. * \param[in] ec Pointer to the dahdi_echocan_factory structure to be unregistered. * * \return Nothing. */ void dahdi_unregister_echocan_factory(const struct dahdi_echocan_factory *ec); enum dahdi_echocan_mode { __ECHO_MODE_MUTE = 1 << 8, ECHO_MODE_IDLE = 0, ECHO_MODE_PRETRAINING = 1 | __ECHO_MODE_MUTE, ECHO_MODE_STARTTRAINING = 2 | __ECHO_MODE_MUTE, ECHO_MODE_AWAITINGECHO = 3 | __ECHO_MODE_MUTE, ECHO_MODE_TRAINING = 4 | __ECHO_MODE_MUTE, ECHO_MODE_ACTIVE = 5, ECHO_MODE_FAX = 6, }; /*! An instance of a DAHDI echo canceler (software or hardware). */ struct dahdi_echocan_state { /*! Pointer to a dahdi_echocan_ops structure of operations that can be * performed on this instance. */ const struct dahdi_echocan_ops *ops; /*! State data used by the DAHDI core's CED detector for the transmit * direction, if needed. */ echo_can_disable_detector_state_t txecdis; /*! State data used by the DAHDI core's CED detector for the receive * direction, if needed. */ echo_can_disable_detector_state_t rxecdis; /*! Features offered by the echo canceler that provided this instance. */ struct dahdi_echocan_features features; struct { /*! The mode the echocan is currently in. */ enum dahdi_echocan_mode mode; /*! The last tap position that was fed to the echocan's training function. */ u32 last_train_tap; /*! How many samples to wait before beginning the training operation. */ u32 pretrain_timer; } status; /*! This structure contains event flags, allowing the echocan to report * events that occurred as it processed the transmit and receive streams * of samples. Each call to the echocan_process operation for this * instance may report events, so the structure should be cleared before * calling that operation. */ union dahdi_echocan_events { u32 all; struct { /*! CED tone was detected in the transmit direction. If the * echocan automatically disables its NLP when this occurs, * it must also signal the NLP_auto_disabled event during the *same* * call to echocan_process that reports the CED detection. */ u32 CED_tx_detected:1; /*! CED tone was detected in the receive direction. If the * echocan automatically disables its NLP when this occurs, * it must also signal the NLP_auto_disabled event during the *same* * call to echocan_process that reports the CED detection. */ u32 CED_rx_detected:1; /*! CNG tone was detected in the transmit direction. */ u32 CNG_tx_detected:1; /*! CNG tone was detected in the receive direction. */ u32 CNG_rx_detected:1; /*! The echocan disabled its NLP automatically. */ u32 NLP_auto_disabled:1; /*! The echocan enabled its NLP automatically. */ u32 NLP_auto_enabled:1; }; } events; }; struct dahdi_chan { #ifdef CONFIG_DAHDI_NET /*! \note Must be first */ struct dahdi_hdlc *hdlcnetdev; #endif #ifdef CONFIG_DAHDI_PPP struct ppp_channel *ppp; struct tasklet_struct ppp_calls; int do_ppp_wakeup; int do_ppp_error; struct sk_buff_head ppp_rq; #endif #ifdef BUFFER_DEBUG int statcount; int lastnumbufs; #endif spinlock_t lock; char name[40]; /* Specified by DAHDI */ /*! \brief DAHDI channel number */ int channo; int chanpos; unsigned long flags; long rxp1; long rxp2; long rxp3; int txtone; int tx_v2; int tx_v3; int v1_1; int v2_1; int v3_1; int toneflags; struct sf_detect_state rd; struct dahdi_chan *master; /*!< Our Master channel (could be us) */ /*! \brief Next slave (if appropriate) */ int nextslave; u_char *writechunk; /*!< Actual place to write to */ u_char swritechunk[DAHDI_MAX_CHUNKSIZE]; /*!< Buffer to be written */ u_char *readchunk; /*!< Actual place to read from */ u_char sreadchunk[DAHDI_MAX_CHUNKSIZE]; /*!< Preallocated static area */ short *readchunkpreec; /*! Pointer to tx and rx gain tables */ u_char *rxgain; u_char *txgain; /*! Whether or not we have allocated gains or are using the default */ int gainalloc; /* Specified by driver, readable by DAHDI */ void *pvt; /*!< Private channel data */ struct file *file; /*!< File structure */ struct dahdi_span *span; /*!< Span we're a member of */ int sig; /*!< Signalling */ int sigcap; /*!< Capability for signalling */ __u32 chan_alarms; /*!< alarms status */ /* Used only by DAHDI -- NO DRIVER SERVICEABLE PARTS BELOW */ /* Buffer declarations */ u_char *readbuf[DAHDI_MAX_NUM_BUFS]; /*!< read buffer */ int inreadbuf; int outreadbuf; wait_queue_head_t readbufq; /*!< read wait queue */ u_char *writebuf[DAHDI_MAX_NUM_BUFS]; /*!< write buffers */ int inwritebuf; int outwritebuf; wait_queue_head_t writebufq; /*!< write wait queue */ int blocksize; /*!< Block size */ int eventinidx; /*!< out index in event buf (circular) */ int eventoutidx; /*!< in index in event buf (circular) */ unsigned int eventbuf[DAHDI_MAX_EVENTSIZE]; /*!< event circ. buffer */ wait_queue_head_t eventbufq; /*!< event wait queue */ wait_queue_head_t txstateq; /*!< waiting on the tx state to change */ int readn[DAHDI_MAX_NUM_BUFS]; /*!< # of bytes ready in read buf */ int readidx[DAHDI_MAX_NUM_BUFS]; /*!< current read pointer */ int writen[DAHDI_MAX_NUM_BUFS]; /*!< # of bytes ready in write buf */ int writeidx[DAHDI_MAX_NUM_BUFS]; /*!< current write pointer */ int numbufs; /*!< How many buffers in channel */ int txbufpolicy; /*!< Buffer policy */ int rxbufpolicy; /*!< Buffer policy */ int txdisable; /*!< Disable transmitter */ int rxdisable; /*!< Disable receiver */ /* Tone zone stuff */ struct dahdi_zone *curzone; /*!< Zone for selecting tones */ int tonezone; /*!< Tone zone for this channel */ struct dahdi_tone *curtone; /*!< Current tone we're playing (if any) */ int tonep; /*!< Current position in tone */ struct dahdi_tone_state ts; /*!< Tone state */ /* Pulse dial stuff */ int pdialcount; /*!< pulse dial count */ /*! Ring cadence */ int ringcadence[DAHDI_MAX_CADENCE]; int firstcadencepos; /*!< Where to restart ring cadence */ /* Digit string dialing stuff */ int digitmode; /*!< What kind of tones are we sending? */ char txdialbuf[DAHDI_MAX_DTMF_BUF]; int dialing; int afterdialingtimer; int cadencepos; /*!< Where in the cadence we are */ /* I/O Mask */ int iomask; /*! I/O Mux signal mask */ wait_queue_head_t sel; /*! thingy for select stuff */ /* HDLC state machines */ struct fasthdlc_state txhdlc; struct fasthdlc_state rxhdlc; int infcs; /* Conferencing stuff */ int confna; /*! conference number (alias) */ int _confn; /*! Actual conference number */ int confmode; /*! conference mode */ int confmute; /*! conference mute mode */ /* Incoming and outgoing conference chunk queues for communicating between DAHDI master time and other boards */ struct confq confin; struct confq confout; short getlin[DAHDI_MAX_CHUNKSIZE]; /*!< Last transmitted samples */ unsigned char getraw[DAHDI_MAX_CHUNKSIZE]; /*!< Last received raw data */ short getlin_lastchunk[DAHDI_MAX_CHUNKSIZE]; /*!< Last transmitted samples from last chunk */ short putlin[DAHDI_MAX_CHUNKSIZE]; /*!< Last received samples */ unsigned char putraw[DAHDI_MAX_CHUNKSIZE]; /*!< Last received raw data */ short conflast[DAHDI_MAX_CHUNKSIZE]; /*!< Last conference sample -- base part of channel */ short conflast1[DAHDI_MAX_CHUNKSIZE]; /*!< Last conference sample -- pseudo part of channel */ short conflast2[DAHDI_MAX_CHUNKSIZE]; /*!< Previous last conference sample -- pseudo part of channel */ /*! The echo canceler module that should be used to create an instance when this channel needs one */ const struct dahdi_echocan_factory *ec_factory; /*! The echo canceler module that owns the instance currently on this channel, if one is present */ const struct dahdi_echocan_factory *ec_current; /*! The state data of the echo canceler instance in use */ struct dahdi_echocan_state *ec_state; /* RBS timings */ int prewinktime; /*!< pre-wink time (ms) */ int preflashtime; /*!< pre-flash time (ms) */ int winktime; /*!< wink time (ms) */ int flashtime; /*!< flash time (ms) */ int starttime; /*!< start time (ms) */ int rxwinktime; /*!< rx wink time (ms) */ int rxflashtime; /*!< rx flash time (ms) */ int debouncetime; /*!< FXS GS sig debounce time (ms) */ int pulsebreaktime; /*!< pulse line open time (ms) */ int pulsemaketime; /*!< pulse line closed time (ms) */ int pulseaftertime; /*!< pulse time between digits (ms) */ /*! RING debounce timer */ int ringdebtimer; /*! RING trailing detector to make sure a RING is really over */ int ringtrailer; /* PULSE digit receiver stuff */ int pulsecount; int pulsetimer; /* RBS timers */ int itimerset; /*!< what the itimer was set to last */ int itimer; int otimer; /* RBS state */ int gotgs; int txstate; int rxsig; int txsig; int rxsigstate; /* non-RBS rx state */ int rxhooksig; int txhooksig; int kewlonhook; /*! Idle signalling if CAS signalling */ int idlebits; int deflaw; /*! 1 = mulaw, 2=alaw, 0=undefined */ short *xlaw; #ifdef OPTIMIZE_CHANMUTE int chanmute; /*!< no need for PCM data */ #endif #ifdef CONFIG_CALC_XLAW unsigned char (*lineartoxlaw)(short a); #else unsigned char *lin2x; #endif }; #ifdef CONFIG_DAHDI_NET struct dahdi_hdlc { struct net_device *netdev; struct dahdi_chan *chan; }; #endif /*! Define the maximum block size */ #define DAHDI_MAX_BLOCKSIZE 8192 #define DAHDI_DEFAULT_WINKTIME 150 /*!< 150 ms default wink time */ #define DAHDI_DEFAULT_FLASHTIME 750 /*!< 750 ms default flash time */ #define DAHDI_DEFAULT_PREWINKTIME 50 /*!< 50 ms before wink */ #define DAHDI_DEFAULT_PREFLASHTIME 50 /*!< 50 ms before flash */ #define DAHDI_DEFAULT_STARTTIME 1500 /*!< 1500 ms of start */ #define DAHDI_DEFAULT_RINGTIME 2000 /*!< 2000 ms of ring on (start, FXO) */ #if 0 #define DAHDI_DEFAULT_RXWINKTIME 250 /*!< 250ms longest rx wink */ #endif #define DAHDI_DEFAULT_RXWINKTIME 300 /*!< 300ms longest rx wink (to work with the Atlas) */ #define DAHDI_DEFAULT_RXFLASHTIME 1250 /*!< 1250ms longest rx flash */ #define DAHDI_DEFAULT_DEBOUNCETIME 600 /*!< 600ms of FXS GS signalling debounce */ #define DAHDI_DEFAULT_PULSEMAKETIME 50 /*!< 50 ms of line closed when dial pulsing */ #define DAHDI_DEFAULT_PULSEBREAKTIME 50 /*!< 50 ms of line open when dial pulsing */ #define DAHDI_DEFAULT_PULSEAFTERTIME 750 /*!< 750ms between dial pulse digits */ #define DAHDI_MINPULSETIME (15 * 8) /*!< 15 ms minimum */ #ifdef SHORT_FLASH_TIME #define DAHDI_MAXPULSETIME (80 * 8) /*!< we need 80 ms, not 200ms, as we have a short flash */ #else #define DAHDI_MAXPULSETIME (200 * 8) /*!< 200 ms maximum */ #endif #define DAHDI_PULSETIMEOUT ((DAHDI_MAXPULSETIME / 8) + 50) #define DAHDI_RINGTRAILER (50 * 8) /*!< Don't consider a ring "over" until it's been gone at least this much time */ #define DAHDI_LOOPCODE_TIME 10000 /*!< send loop codes for 10 secs */ #define DAHDI_ALARMSETTLE_TIME 5000 /*!< allow alarms to settle for 5 secs */ #define DAHDI_AFTERSTART_TIME 500 /*!< 500ms after start */ #define DAHDI_RINGOFFTIME 4000 /*!< Turn off ringer for 4000 ms */ #define DAHDI_KEWLTIME 500 /*!< 500ms for kewl pulse */ #define DAHDI_AFTERKEWLTIME 300 /*!< 300ms after kewl pulse */ #define DAHDI_MAX_PRETRAINING 1000 /*!< 1000ms max pretraining time */ #ifdef FXSFLASH #define DAHDI_FXSFLASHMINTIME 450 /*!< min 450ms */ #define DAHDI_FXSFLASHMAXTIME 550 /*!< max 550ms */ #endif struct dahdi_chardev { const char *name; __u8 minor; }; int dahdi_register_chardev(struct dahdi_chardev *dev); int dahdi_unregister_chardev(struct dahdi_chardev *dev); /*! \brief defines for transmit signalling */ enum dahdi_txsig { DAHDI_TXSIG_ONHOOK, /*!< On hook */ DAHDI_TXSIG_OFFHOOK, /*!< Off hook */ DAHDI_TXSIG_START, /*!< Start / Ring */ DAHDI_TXSIG_KEWL, /*!< Drop battery if possible */ /*! Leave this as the last entry */ DAHDI_TXSIG_TOTAL, }; enum dahdi_rxsig { DAHDI_RXSIG_ONHOOK, DAHDI_RXSIG_OFFHOOK, DAHDI_RXSIG_START, DAHDI_RXSIG_RING, DAHDI_RXSIG_INITIAL }; enum { /* Span flags */ DAHDI_FLAGBIT_REGISTERED= 0, DAHDI_FLAGBIT_RUNNING = 1, DAHDI_FLAGBIT_RBS = 12, /*!< Span uses RBS signalling */ /* Channel flags */ DAHDI_FLAGBIT_DTMFDECODE= 2, /*!< Channel supports native DTMF decode */ DAHDI_FLAGBIT_MFDECODE = 3, /*!< Channel supports native MFr2 decode */ DAHDI_FLAGBIT_ECHOCANCEL= 4, /*!< Channel supports native echo cancellation */ DAHDI_FLAGBIT_HDLC = 5, /*!< Perform HDLC */ DAHDI_FLAGBIT_NETDEV = 6, /*!< Send to network */ DAHDI_FLAGBIT_PSEUDO = 7, /*!< Pseudo channel */ DAHDI_FLAGBIT_CLEAR = 8, /*!< Clear channel */ DAHDI_FLAGBIT_AUDIO = 9, /*!< Audio mode channel */ DAHDI_FLAGBIT_OPEN = 10, /*!< Channel is open */ DAHDI_FLAGBIT_FCS = 11, /*!< Calculate FCS */ /* Reserve 12 for uniqueness with span flags */ DAHDI_FLAGBIT_LINEAR = 13, /*!< Talk to user space in linear */ DAHDI_FLAGBIT_PPP = 14, /*!< PPP is available */ DAHDI_FLAGBIT_T1PPP = 15, DAHDI_FLAGBIT_SIGFREEZE = 16, /*!< Freeze signalling */ DAHDI_FLAGBIT_NOSTDTXRX = 17, /*!< Do NOT do standard transmit and receive on every interrupt */ DAHDI_FLAGBIT_LOOPED = 18, /*!< Loopback the receive data from the channel to the transmit */ DAHDI_FLAGBIT_MTP2 = 19, /*!< Repeats last message in buffer and also discards repeating messages sent to us */ DAHDI_FLAGBIT_HDLC56 = 20, /*!< Sets the given channel (if in HDLC mode) to use 56K HDLC instead of 64K */ }; /* map flagbits to flag masks */ #define DAHDI_FLAG(x) (1 << (DAHDI_FLAGBIT_ ## x)) /*! This is a redefinition of the flags from above to allow use of the * legacy drivers that do not use the kernel atomic bit testing and * changing routines. * * See the above descriptions for DAHDI_FLAGBIT_.... for documentation * about function. */ /* Span flags */ #define DAHDI_FLAG_REGISTERED DAHDI_FLAG(REGISTERED) #define DAHDI_FLAG_RUNNING DAHDI_FLAG(RUNNING) #define DAHDI_FLAG_RBS DAHDI_FLAG(RBS) /* Channel flags */ #define DAHDI_FLAG_DTMFDECODE DAHDI_FLAG(DTMFDECODE) #define DAHDI_FLAG_MFDECODE DAHDI_FLAG(MFDECODE) #define DAHDI_FLAG_ECHOCANCEL DAHDI_FLAG(ECHOCANCEL) #define DAHDI_FLAG_HDLC DAHDI_FLAG(HDLC) #define DAHDI_FLAG_NETDEV DAHDI_FLAG(NETDEV) #define DAHDI_FLAG_PSEUDO DAHDI_FLAG(PSEUDO) #define DAHDI_FLAG_CLEAR DAHDI_FLAG(CLEAR) #define DAHDI_FLAG_AUDIO DAHDI_FLAG(AUDIO) #define DAHDI_FLAG_OPEN DAHDI_FLAG(OPEN) #define DAHDI_FLAG_FCS DAHDI_FLAG(FCS) /* Reserve 12 for uniqueness with span flags */ #define DAHDI_FLAG_LINEAR DAHDI_FLAG(LINEAR) #define DAHDI_FLAG_PPP DAHDI_FLAG(PPP) #define DAHDI_FLAG_T1PPP DAHDI_FLAG(T1PPP) #define DAHDI_FLAG_SIGFREEZE DAHDI_FLAG(SIGFREEZE) #define DAHDI_FLAG_NOSTDTXRX DAHDI_FLAG(NOSTDTXRX) #define DAHDI_FLAG_LOOPED DAHDI_FLAG(LOOPED) #define DAHDI_FLAG_MTP2 DAHDI_FLAG(MTP2) #define DAHDI_FLAG_HDLC56 DAHDI_FLAG(HDLC56) struct dahdi_span { spinlock_t lock; void *pvt; /*!< Private stuff */ char name[40]; /*!< Span name */ char desc[80]; /*!< Span description */ const char *spantype; /*!< span type in text form */ const char *manufacturer; /*!< span's device manufacturer */ char devicetype[80]; /*!< span's device type */ char location[40]; /*!< span device's location in system */ int deflaw; /*!< Default law (DAHDI_MULAW or DAHDI_ALAW) */ int alarms; /*!< Pending alarms on span */ unsigned long flags; int irq; /*!< IRQ for this span's hardware */ int lbo; /*!< Span Line-Buildout */ int lineconfig; /*!< Span line configuration */ int linecompat; /*!< Span line compatibility */ int channels; /*!< Number of channels in span */ int txlevel; /*!< Tx level */ int rxlevel; /*!< Rx level */ int syncsrc; /*!< current sync src (gets copied here) */ unsigned int bpvcount; /*!< BPV counter */ unsigned int crc4count; /*!< CRC4 error counter */ unsigned int ebitcount; /*!< current E-bit error count */ unsigned int fascount; /*!< current FAS error count */ int maintstat; /*!< Maintenance state */ wait_queue_head_t maintq; /*!< Maintenance queue */ int mainttimer; /*!< Maintenance timer */ int irqmisses; /*!< Interrupt misses */ int timingslips; /*!< Clock slips */ struct dahdi_chan **chans; /*!< Member channel structures */ /* ==== Span Callback Operations ==== */ /*! Req: Set the requested chunk size. This is the unit in which you must report results for conferencing, etc */ int (*setchunksize)(struct dahdi_span *span, int chunksize); /*! Opt: Configure the span (if appropriate) */ int (*spanconfig)(struct dahdi_span *span, struct dahdi_lineconfig *lc); /*! Opt: Start the span */ int (*startup)(struct dahdi_span *span); /*! Opt: Shutdown the span */ int (*shutdown)(struct dahdi_span *span); /*! Opt: Enable maintenance modes */ int (*maint)(struct dahdi_span *span, int mode); #ifdef DAHDI_SYNC_TICK /*! Opt: send sync to spans */ int (*sync_tick)(struct dahdi_span *span, int is_master); #endif /* ==== Channel Callback Operations ==== */ /*! Opt: Set signalling type (if appropriate) */ int (*chanconfig)(struct dahdi_chan *chan, int sigtype); /*! Opt: Prepare a channel for I/O */ int (*open)(struct dahdi_chan *chan); /*! Opt: Close channel for I/O */ int (*close)(struct dahdi_chan *chan); /*! Opt: IOCTL */ int (*ioctl)(struct dahdi_chan *chan, unsigned int cmd, unsigned long data); /*! Opt: Provide echo cancellation on a channel */ int (*echocan_create)(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec); /* Okay, now we get to the signalling. You have several options: */ /* Option 1: If you're a T1 like interface, you can just provide a rbsbits function and we'll assert robbed bits for you. Be sure to set the DAHDI_FLAG_RBS in this case. */ /*! Opt: If the span uses A/B bits, set them here */ int (*rbsbits)(struct dahdi_chan *chan, int bits); /*! Option 2: If you don't know about sig bits, but do have their equivalents (i.e. you can disconnect battery, detect off hook, generate ring, etc directly) then you can just specify a sethook function, and we'll call you with appropriate hook states to set. Still set the DAHDI_FLAG_RBS in this case as well */ int (*hooksig)(struct dahdi_chan *chan, enum dahdi_txsig hookstate); /*! Option 3: If you can't use sig bits, you can write a function which handles the individual hook states */ int (*sethook)(struct dahdi_chan *chan, int hookstate); /*! Opt: Dacs the contents of chan2 into chan1 if possible */ int (*dacs)(struct dahdi_chan *chan1, struct dahdi_chan *chan2); /*! Opt: Used to tell an onboard HDLC controller that there is data ready to transmit */ void (*hdlc_hard_xmit)(struct dahdi_chan *chan); /* Used by DAHDI only -- no user servicable parts inside */ int spanno; /*!< Span number for DAHDI */ int offset; /*!< Offset within a given card */ int lastalarms; /*!< Previous alarms */ /*! If the watchdog detects no received data, it will call the watchdog routine */ int (*watchdog)(struct dahdi_span *span, int cause); #ifdef CONFIG_DAHDI_WATCHDOG int watchcounter; int watchstate; #endif }; struct dahdi_transcoder_channel { void *pvt; struct dahdi_transcoder *parent; wait_queue_head_t ready; __u32 built_fmts; #define DAHDI_TC_FLAG_BUSY 1 #define DAHDI_TC_FLAG_CHAN_BUILT 2 #define DAHDI_TC_FLAG_NONBLOCK 3 #define DAHDI_TC_FLAG_DATA_WAITING 4 unsigned long flags; u32 dstfmt; u32 srcfmt; }; static inline int dahdi_tc_is_built(struct dahdi_transcoder_channel *dtc) { return test_bit(DAHDI_TC_FLAG_CHAN_BUILT, &dtc->flags); } static inline void dahdi_tc_set_built(struct dahdi_transcoder_channel *dtc) { set_bit(DAHDI_TC_FLAG_CHAN_BUILT, &dtc->flags); } static inline void dahdi_tc_clear_built(struct dahdi_transcoder_channel *dtc) { clear_bit(DAHDI_TC_FLAG_CHAN_BUILT, &dtc->flags); } static inline int dahdi_tc_is_nonblock(struct dahdi_transcoder_channel *dtc) { return test_bit(DAHDI_TC_FLAG_NONBLOCK, &dtc->flags); } static inline void dahdi_tc_set_nonblock(struct dahdi_transcoder_channel *dtc) { set_bit(DAHDI_TC_FLAG_NONBLOCK, &dtc->flags); } static inline void dahdi_tc_clear_nonblock(struct dahdi_transcoder_channel *dtc) { clear_bit(DAHDI_TC_FLAG_NONBLOCK, &dtc->flags); } static inline int dahdi_tc_is_data_waiting(struct dahdi_transcoder_channel *dtc) { return test_bit(DAHDI_TC_FLAG_DATA_WAITING, &dtc->flags); } static inline int dahdi_tc_is_busy(struct dahdi_transcoder_channel *dtc) { return test_bit(DAHDI_TC_FLAG_BUSY, &dtc->flags); } static inline void dahdi_tc_set_busy(struct dahdi_transcoder_channel *dtc) { set_bit(DAHDI_TC_FLAG_BUSY, &dtc->flags); } static inline void dahdi_tc_clear_busy(struct dahdi_transcoder_channel *dtc) { clear_bit(DAHDI_TC_FLAG_BUSY, &dtc->flags); } static inline void dahdi_tc_set_data_waiting(struct dahdi_transcoder_channel *dtc) { set_bit(DAHDI_TC_FLAG_DATA_WAITING, &dtc->flags); } static inline void dahdi_tc_clear_data_waiting(struct dahdi_transcoder_channel *dtc) { clear_bit(DAHDI_TC_FLAG_DATA_WAITING, &dtc->flags); } struct dahdi_transcoder { struct list_head active_list_node; struct list_head registration_list_node; char name[80]; int numchannels; unsigned int srcfmts; unsigned int dstfmts; struct file_operations fops; int (*allocate)(struct dahdi_transcoder_channel *channel); int (*release)(struct dahdi_transcoder_channel *channel); /* Transcoder channels */ struct dahdi_transcoder_channel channels[0]; }; #define DAHDI_WATCHDOG_NOINTS (1 << 0) #define DAHDI_WATCHDOG_INIT 1000 #define DAHDI_WATCHSTATE_UNKNOWN 0 #define DAHDI_WATCHSTATE_OK 1 #define DAHDI_WATCHSTATE_RECOVERING 2 #define DAHDI_WATCHSTATE_FAILED 3 struct dahdi_dynamic_driver { /*! Driver name (e.g. Eth) */ char name[20]; /*! Driver description */ char desc[80]; /*! Create a new transmission pipe */ void *(*create)(struct dahdi_span *span, char *address); /*! Destroy a created transmission pipe */ void (*destroy)(void *tpipe); /*! Transmit a given message */ int (*transmit)(void *tpipe, unsigned char *msg, int msglen); /*! Flush any pending messages */ int (*flush)(void); struct dahdi_dynamic_driver *next; }; /*! \brief Receive a dynamic span message */ void dahdi_dynamic_receive(struct dahdi_span *span, unsigned char *msg, int msglen); /*! \brief Register a dynamic driver */ int dahdi_dynamic_register(struct dahdi_dynamic_driver *driver); /*! \brief Unregister a dynamic driver */ void dahdi_dynamic_unregister(struct dahdi_dynamic_driver *driver); /*! Receive on a span. The DAHDI interface will handle all the calculations for all member channels of the span, pulling the data from the readchunk buffer */ int dahdi_receive(struct dahdi_span *span); /*! Prepare writechunk buffers on all channels for this span */ int dahdi_transmit(struct dahdi_span *span); /*! Abort the buffer currently being receive with event "event" */ void dahdi_hdlc_abort(struct dahdi_chan *ss, int event); /*! Indicate to DAHDI that the end of frame was received and rotate buffers */ void dahdi_hdlc_finish(struct dahdi_chan *ss); /*! Put a chunk of data into the current receive buffer */ void dahdi_hdlc_putbuf(struct dahdi_chan *ss, unsigned char *rxb, int bytes); /*! Get a chunk of data from the current transmit buffer. Returns -1 if no data * is left to send, 0 if there is data remaining in the current message to be sent * and 1 if the currently transmitted message is now done */ int dahdi_hdlc_getbuf(struct dahdi_chan *ss, unsigned char *bufptr, unsigned int *size); /*! Register a span. Returns 0 on success, -1 on failure. Pref-master is non-zero if we should have preference in being the master device */ int dahdi_register(struct dahdi_span *span, int prefmaster); /*! Allocate / free memory for a transcoder */ struct dahdi_transcoder *dahdi_transcoder_alloc(int numchans); void dahdi_transcoder_free(struct dahdi_transcoder *ztc); /*! \brief Register a transcoder */ int dahdi_transcoder_register(struct dahdi_transcoder *tc); /*! \brief Unregister a transcoder */ int dahdi_transcoder_unregister(struct dahdi_transcoder *tc); /*! \brief Alert a transcoder */ int dahdi_transcoder_alert(struct dahdi_transcoder_channel *ztc); /*! \brief Unregister a span */ int dahdi_unregister(struct dahdi_span *span); /*! \brief Gives a name to an LBO */ char *dahdi_lboname(int lbo); /*! \brief Tell DAHDI about changes in received rbs bits */ void dahdi_rbsbits(struct dahdi_chan *chan, int bits); /*! \brief Tell DAHDI abou changes in received signalling */ void dahdi_hooksig(struct dahdi_chan *chan, enum dahdi_rxsig rxsig); /*! \brief Queue an event on a channel */ void dahdi_qevent_nolock(struct dahdi_chan *chan, int event); /*! \brief Queue an event on a channel, locking it first */ void dahdi_qevent_lock(struct dahdi_chan *chan, int event); /*! \brief Notify a change possible change in alarm status on a channel */ void dahdi_alarm_channel(struct dahdi_chan *chan, int alarms); /*! \brief Notify a change possible change in alarm status on a span */ void dahdi_alarm_notify(struct dahdi_span *span); /*! \brief Initialize a tone state */ void dahdi_init_tone_state(struct dahdi_tone_state *ts, struct dahdi_tone *zt); /*! \brief Get a given MF tone struct, suitable for dahdi_tone_nextsample. */ struct dahdi_tone *dahdi_mf_tone(const struct dahdi_chan *chan, char digit, int digitmode); /* Echo cancel a receive and transmit chunk for a given channel. This should be called by the low-level driver as close to the interface as possible. ECHO CANCELLATION IS NO LONGER AUTOMATICALLY DONE AT THE DAHDI LEVEL. dahdi_ec_chunk will not echo cancel if it should not be doing so. rxchunk is modified in-place */ void dahdi_ec_chunk(struct dahdi_chan *chan, unsigned char *rxchunk, const unsigned char *txchunk); void dahdi_ec_span(struct dahdi_span *span); extern struct file_operations *dahdi_transcode_fops; /* Don't use these directly -- they're not guaranteed to be there. */ extern short __dahdi_mulaw[256]; extern short __dahdi_alaw[256]; #ifdef CONFIG_CALC_XLAW u_char __dahdi_lineartoulaw(short a); u_char __dahdi_lineartoalaw(short a); #else extern u_char __dahdi_lin2mu[16384]; extern u_char __dahdi_lin2a[16384]; #endif /*! \brief Used by dynamic DAHDI -- don't use directly */ void dahdi_set_dynamic_ioctl(int (*func)(unsigned int cmd, unsigned long data)); /*! \brief Used by DAHDI HPEC module -- don't use directly */ void dahdi_set_hpec_ioctl(int (*func)(unsigned int cmd, unsigned long data)); /*! \brief Used privately by DAHDI. Avoid touching directly */ struct dahdi_tone { int fac1; int init_v2_1; int init_v3_1; int fac2; int init_v2_2; int init_v3_2; int tonesamples; /*!< How long to play this tone before going to the next (in samples) */ struct dahdi_tone *next; /* Next tone in this sequence */ int modulate; }; static inline short dahdi_tone_nextsample(struct dahdi_tone_state *ts, struct dahdi_tone *zt) { /* follow the curves, return the sum */ int p; ts->v1_1 = ts->v2_1; ts->v2_1 = ts->v3_1; ts->v3_1 = (zt->fac1 * ts->v2_1 >> 15) - ts->v1_1; ts->v1_2 = ts->v2_2; ts->v2_2 = ts->v3_2; ts->v3_2 = (zt->fac2 * ts->v2_2 >> 15) - ts->v1_2; /* Return top 16 bits */ if (!ts->modulate) return ts->v3_1 + ts->v3_2; /* we are modulating */ p = ts->v3_2 - 32768; if (p < 0) p = -p; p = ((p * 9) / 10) + 1; return (ts->v3_1 * p) >> 15; } static inline short dahdi_txtone_nextsample(struct dahdi_chan *ss) { /* follow the curves, return the sum */ ss->v1_1 = ss->v2_1; ss->v2_1 = ss->v3_1; ss->v3_1 = (ss->txtone * ss->v2_1 >> 15) - ss->v1_1; return ss->v3_1; } /* These are the right functions to use. */ #define DAHDI_MULAW(a) (__dahdi_mulaw[(a)]) #define DAHDI_ALAW(a) (__dahdi_alaw[(a)]) #define DAHDI_XLAW(a,c) (c->xlaw[(a)]) #ifdef CONFIG_CALC_XLAW #define DAHDI_LIN2MU(a) (__dahdi_lineartoulaw((a))) #define DAHDI_LIN2A(a) (__dahdi_lineartoalaw((a))) #define DAHDI_LIN2X(a,c) ((c)->lineartoxlaw((a))) #else /* Use tables */ #define DAHDI_LIN2MU(a) (__dahdi_lin2mu[((unsigned short)(a)) >> 2]) #define DAHDI_LIN2A(a) (__dahdi_lin2a[((unsigned short)(a)) >> 2]) /* Manipulate as appropriate for x-law */ #define DAHDI_LIN2X(a,c) ((c)->lin2x[((unsigned short)(a)) >> 2]) #endif /* CONFIG_CALC_XLAW */ /* Data formats for capabilities and frames alike (from Asterisk) */ /*! G.723.1 compression */ #define DAHDI_FORMAT_G723_1 (1 << 0) /*! GSM compression */ #define DAHDI_FORMAT_GSM (1 << 1) /*! Raw mu-law data (G.711) */ #define DAHDI_FORMAT_ULAW (1 << 2) /*! Raw A-law data (G.711) */ #define DAHDI_FORMAT_ALAW (1 << 3) /*! ADPCM (G.726, 32kbps) */ #define DAHDI_FORMAT_G726 (1 << 4) /*! ADPCM (IMA) */ #define DAHDI_FORMAT_ADPCM (1 << 5) /*! Raw 16-bit Signed Linear (8000 Hz) PCM */ #define DAHDI_FORMAT_SLINEAR (1 << 6) /*! LPC10, 180 samples/frame */ #define DAHDI_FORMAT_LPC10 (1 << 7) /*! G.729A audio */ #define DAHDI_FORMAT_G729A (1 << 8) /*! SpeeX Free Compression */ #define DAHDI_FORMAT_SPEEX (1 << 9) /*! iLBC Free Compression */ #define DAHDI_FORMAT_ILBC (1 << 10) /*! Maximum audio format */ #define DAHDI_FORMAT_MAX_AUDIO (1 << 15) /*! Maximum audio mask */ #define DAHDI_FORMAT_AUDIO_MASK ((1 << 16) - 1) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14) #define kzalloc(a, b) kcalloc(1, a, b) #endif #endif /* _DAHDI_KERNEL_H */ dahdi-linux-2.2.0-rc4/include/dahdi/user.h0000644000175000017500000010542611176410450017503 0ustar maniacmaniac/* * DAHDI Telephony Interface * * Written by Mark Spencer * Based on previous works, designs, and architectures conceived and * written by Jim Dixon . * * Copyright (C) 2001 Jim Dixon / Zapata Telephony. * Copyright (C) 2001 - 2008 Digium, Inc. * * All rights reserved. * */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU Lesser General Public License Version 2.1 as published * by the Free Software Foundation. See the LICENSE.LGPL file * included with this program for more details. * * In addition, when this program is distributed with Asterisk in * any form that would qualify as a 'combined work' or as a * 'derivative work' (but not mere aggregation), you can redistribute * and/or modify the combination under the terms of the license * provided with that copy of Asterisk, instead of the license * terms granted here. */ #ifndef _DAHDI_USER_H #define _DAHDI_USER_H #include #include #ifndef ELAST #define ELAST 500 #endif /* Per-span configuration values */ #define DAHDI_CONFIG_TXLEVEL 7 /* bits 0-2 are tx level */ /* Line configuration */ /* These apply to T1 */ #define DAHDI_CONFIG_D4 (1 << 4) #define DAHDI_CONFIG_ESF (1 << 5) #define DAHDI_CONFIG_AMI (1 << 6) #define DAHDI_CONFIG_B8ZS (1 << 7) /* These apply to E1 */ #define DAHDI_CONFIG_CCS (1 << 8) /* CCS (ISDN) instead of CAS (Robbed Bit) */ #define DAHDI_CONFIG_HDB3 (1 << 9) /* HDB3 instead of AMI (line coding) */ #define DAHDI_CONFIG_CRC4 (1 << 10) /* CRC4 framing */ #define DAHDI_CONFIG_NOTOPEN (1 << 16) /* Signalling types */ #define DAHDI_SIG_BROKEN (1 << 31) /* The port is broken and/or failed initialization */ #define __DAHDI_SIG_FXO (1 << 12) /* Never use directly */ #define __DAHDI_SIG_FXS (1 << 13) /* Never use directly */ #define DAHDI_SIG_NONE (0) /* Channel not configured */ #define DAHDI_SIG_FXSLS ((1 << 0) | __DAHDI_SIG_FXS) /* FXS, Loopstart */ #define DAHDI_SIG_FXSGS ((1 << 1) | __DAHDI_SIG_FXS) /* FXS, Groundstart */ #define DAHDI_SIG_FXSKS ((1 << 2) | __DAHDI_SIG_FXS) /* FXS, Kewlstart */ #define DAHDI_SIG_FXOLS ((1 << 3) | __DAHDI_SIG_FXO) /* FXO, Loopstart */ #define DAHDI_SIG_FXOGS ((1 << 4) | __DAHDI_SIG_FXO) /* FXO, Groupstart */ #define DAHDI_SIG_FXOKS ((1 << 5) | __DAHDI_SIG_FXO) /* FXO, Kewlstart */ #define DAHDI_SIG_EM (1 << 6) /* Ear & Mouth (E&M) */ /* The following are all variations on clear channel */ #define __DAHDI_SIG_DACS (1 << 16) #define DAHDI_SIG_CLEAR (1 << 7) /* Clear channel */ #define DAHDI_SIG_HDLCRAW ((1 << 8) | DAHDI_SIG_CLEAR) /* Raw unchecked HDLC */ #define DAHDI_SIG_HDLCFCS ((1 << 9) | DAHDI_SIG_HDLCRAW) /* HDLC with FCS calculation */ #define DAHDI_SIG_HDLCNET ((1 << 10) | DAHDI_SIG_HDLCFCS) /* HDLC Network */ #define DAHDI_SIG_SLAVE (1 << 11) /* Slave to another channel */ #define DAHDI_SIG_SF (1 << 14) /* Single Freq. tone only, no sig bits */ #define DAHDI_SIG_CAS (1 << 15) /* Just get bits */ #define DAHDI_SIG_DACS (__DAHDI_SIG_DACS | DAHDI_SIG_CLEAR) /* Cross connect */ #define DAHDI_SIG_EM_E1 (1 << 17) /* E1 E&M Variation */ #define DAHDI_SIG_DACS_RBS ((1 << 18) | __DAHDI_SIG_DACS) /* Cross connect w/ RBS */ #define DAHDI_SIG_HARDHDLC ((1 << 19) | DAHDI_SIG_CLEAR) #define DAHDI_SIG_MTP2 ((1 << 20) | DAHDI_SIG_HDLCFCS) /* MTP2 support Need HDLC bitstuff and FCS calcuation too */ /* tone flag values */ #define DAHDI_REVERSE_RXTONE 1 /* reverse polarity rx tone logic */ #define DAHDI_REVERSE_TXTONE 2 /* reverse polarity tx tone logic */ #define DAHDI_ABIT (1 << 3) #define DAHDI_BBIT (1 << 2) #define DAHDI_CBIT (1 << 1) #define DAHDI_DBIT (1 << 0) #define DAHDI_BITS_ABCD (DAHDI_ABIT | DAHDI_BBIT | DAHDI_CBIT | DAHDI_DBIT) #define DAHDI_BITS_ABD (DAHDI_ABIT | DAHDI_BBIT | DAHDI_DBIT) #define DAHDI_BITS_ACD (DAHDI_ABIT | DAHDI_CBIT | DAHDI_DBIT) #define DAHDI_BITS_BCD (DAHDI_BBIT | DAHDI_CBIT | DAHDI_DBIT) #define DAHDI_BITS_AC (DAHDI_ABIT | DAHDI_CBIT) #define DAHDI_BITS_BD (DAHDI_BBIT | DAHDI_DBIT) #define DAHDI_MAJOR 196 #define DAHDI_MAX_BLOCKSIZE 8192 #define DAHDI_DEFAULT_NUM_BUFS 2 #define DAHDI_MAX_NUM_BUFS 32 #define DAHDI_MAX_BUF_SPACE 32768 #define DAHDI_DEFAULT_BLOCKSIZE 1024 #define DAHDI_DEFAULT_MTR_MRU 2048 /*! Define the default network block size */ #define DAHDI_DEFAULT_MTU_MRU 2048 #define DAHDI_POLICY_IMMEDIATE 0 /* Start play/record immediately */ #define DAHDI_POLICY_WHEN_FULL 1 /* Start play/record when buffer is full */ #define DAHDI_POLICY_HALF_FULL 2 /* Start play/record when buffer is half full. Note -- This policy only works on tx buffers */ #define DAHDI_GET_PARAMS_RETURN_MASTER 0x40000000 #define DAHDI_TONE_ZONE_MAX 128 #define DAHDI_TONE_ZONE_DEFAULT -1 /* To restore default */ #define DAHDI_TONE_STOP -1 #define DAHDI_TONE_DIALTONE 0 #define DAHDI_TONE_BUSY 1 #define DAHDI_TONE_RINGTONE 2 #define DAHDI_TONE_CONGESTION 3 #define DAHDI_TONE_CALLWAIT 4 #define DAHDI_TONE_DIALRECALL 5 #define DAHDI_TONE_RECORDTONE 6 #define DAHDI_TONE_INFO 7 #define DAHDI_TONE_CUST1 8 #define DAHDI_TONE_CUST2 9 #define DAHDI_TONE_STUTTER 10 #define DAHDI_TONE_MAX 16 #define DAHDI_TONE_DTMF_BASE 64 #define DAHDI_TONE_MFR1_BASE 80 #define DAHDI_TONE_MFR2_FWD_BASE 96 #define DAHDI_TONE_MFR2_REV_BASE 112 enum { DAHDI_TONE_DTMF_0 = DAHDI_TONE_DTMF_BASE, DAHDI_TONE_DTMF_1, DAHDI_TONE_DTMF_2, DAHDI_TONE_DTMF_3, DAHDI_TONE_DTMF_4, DAHDI_TONE_DTMF_5, DAHDI_TONE_DTMF_6, DAHDI_TONE_DTMF_7, DAHDI_TONE_DTMF_8, DAHDI_TONE_DTMF_9, DAHDI_TONE_DTMF_s, DAHDI_TONE_DTMF_p, DAHDI_TONE_DTMF_A, DAHDI_TONE_DTMF_B, DAHDI_TONE_DTMF_C, DAHDI_TONE_DTMF_D }; #define DAHDI_TONE_DTMF_MAX DAHDI_TONE_DTMF_D enum { DAHDI_TONE_MFR1_0 = DAHDI_TONE_MFR1_BASE, DAHDI_TONE_MFR1_1, DAHDI_TONE_MFR1_2, DAHDI_TONE_MFR1_3, DAHDI_TONE_MFR1_4, DAHDI_TONE_MFR1_5, DAHDI_TONE_MFR1_6, DAHDI_TONE_MFR1_7, DAHDI_TONE_MFR1_8, DAHDI_TONE_MFR1_9, DAHDI_TONE_MFR1_KP, DAHDI_TONE_MFR1_ST, DAHDI_TONE_MFR1_STP, DAHDI_TONE_MFR1_ST2P, DAHDI_TONE_MFR1_ST3P, }; #define DAHDI_TONE_MFR1_MAX DAHDI_TONE_MFR1_ST3P enum { DAHDI_TONE_MFR2_FWD_1 = DAHDI_TONE_MFR2_FWD_BASE, DAHDI_TONE_MFR2_FWD_2, DAHDI_TONE_MFR2_FWD_3, DAHDI_TONE_MFR2_FWD_4, DAHDI_TONE_MFR2_FWD_5, DAHDI_TONE_MFR2_FWD_6, DAHDI_TONE_MFR2_FWD_7, DAHDI_TONE_MFR2_FWD_8, DAHDI_TONE_MFR2_FWD_9, DAHDI_TONE_MFR2_FWD_10, DAHDI_TONE_MFR2_FWD_11, DAHDI_TONE_MFR2_FWD_12, DAHDI_TONE_MFR2_FWD_13, DAHDI_TONE_MFR2_FWD_14, DAHDI_TONE_MFR2_FWD_15, }; #define DAHDI_TONE_MFR2_FWD_MAX DAHDI_TONE_MFR2_FWD_15 enum { DAHDI_TONE_MFR2_REV_1 = DAHDI_TONE_MFR2_REV_BASE, DAHDI_TONE_MFR2_REV_2, DAHDI_TONE_MFR2_REV_3, DAHDI_TONE_MFR2_REV_4, DAHDI_TONE_MFR2_REV_5, DAHDI_TONE_MFR2_REV_6, DAHDI_TONE_MFR2_REV_7, DAHDI_TONE_MFR2_REV_8, DAHDI_TONE_MFR2_REV_9, DAHDI_TONE_MFR2_REV_10, DAHDI_TONE_MFR2_REV_11, DAHDI_TONE_MFR2_REV_12, DAHDI_TONE_MFR2_REV_13, DAHDI_TONE_MFR2_REV_14, DAHDI_TONE_MFR2_REV_15, }; #define DAHDI_TONE_MFR2_REV_MAX DAHDI_TONE_MFR2_REV_15 #define DAHDI_LAW_DEFAULT 0 /* Default law for span */ #define DAHDI_LAW_MULAW 1 /* Mu-law */ #define DAHDI_LAW_ALAW 2 /* A-law */ #define DAHDI_DIAL_OP_APPEND 1 #define DAHDI_DIAL_OP_REPLACE 2 #define DAHDI_DIAL_OP_CANCEL 3 #define DAHDI_MAX_CADENCE 16 #define DAHDI_TONEDETECT_ON (1 << 0) /* Detect tones */ #define DAHDI_TONEDETECT_MUTE (1 << 1) /* Mute audio in received channel */ /* Define the max # of outgoing DTMF, MFR1 or MFR2 digits to queue */ #define DAHDI_MAX_DTMF_BUF 256 #define DAHDI_MAX_EVENTSIZE 64 /* 64 events max in buffer */ /* Value for DAHDI_HOOK, set to ON hook */ #define DAHDI_ONHOOK 0 /* Value for DAHDI_HOOK, set to OFF hook */ #define DAHDI_OFFHOOK 1 /* Value for DAHDI_HOOK, wink (off hook momentarily) */ #define DAHDI_WINK 2 /* Value for DAHDI_HOOK, flash (on hook momentarily) */ #define DAHDI_FLASH 3 /* Value for DAHDI_HOOK, start line */ #define DAHDI_START 4 /* Value for DAHDI_HOOK, ring line (same as start line) */ #define DAHDI_RING 5 /* Value for DAHDI_HOOK, turn ringer off */ #define DAHDI_RINGOFF 6 /* Flush and stop the read (input) process */ #define DAHDI_FLUSH_READ 1 /* Flush and stop the write (output) process */ #define DAHDI_FLUSH_WRITE 2 /* Flush and stop both (input and output) processes */ #define DAHDI_FLUSH_BOTH (DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE) /* Flush the event queue */ #define DAHDI_FLUSH_EVENT 4 /* Flush everything */ #define DAHDI_FLUSH_ALL (DAHDI_FLUSH_BOTH | DAHDI_FLUSH_EVENT) #define DAHDI_MAX_SPANS 128 /* Max, 128 spans */ #define DAHDI_MAX_CHANNELS 1024 /* Max, 1024 channels */ #define DAHDI_MAX_CONF 1024 /* Max, 1024 conferences */ /* Conference modes */ #define DAHDI_CONF_MODE_MASK 0xFF /* mask for modes */ #define DAHDI_CONF_NORMAL 0 /* normal mode */ #define DAHDI_CONF_MONITOR 1 /* monitor mode (rx of other chan) */ #define DAHDI_CONF_MONITORTX 2 /* monitor mode (tx of other chan) */ #define DAHDI_CONF_MONITORBOTH 3 /* monitor mode (rx & tx of other chan) */ #define DAHDI_CONF_CONF 4 /* conference mode */ #define DAHDI_CONF_CONFANN 5 /* conference announce mode */ #define DAHDI_CONF_CONFMON 6 /* conference monitor mode */ #define DAHDI_CONF_CONFANNMON 7 /* conference announce/monitor mode */ #define DAHDI_CONF_REALANDPSEUDO 8 /* real and pseudo port both on conf */ #define DAHDI_CONF_DIGITALMON 9 /* Do not decode or interpret */ #define DAHDI_CONF_MONITOR_RX_PREECHO 10 /* monitor mode (rx of other chan) - before echo can is done */ #define DAHDI_CONF_MONITOR_TX_PREECHO 11 /* monitor mode (tx of other chan) - before echo can is done */ #define DAHDI_CONF_MONITORBOTH_PREECHO 12 /* monitor mode (rx & tx of other chan) - before echo can is done */ #define DAHDI_CONF_FLAG_MASK 0xFF00 /* mask for flags */ #define DAHDI_CONF_LISTENER 0x100 /* is a listener on the conference */ #define DAHDI_CONF_TALKER 0x200 /* is a talker on the conference */ #define DAHDI_CONF_PSEUDO_LISTENER 0x400 /* pseudo is a listener on the conference */ #define DAHDI_CONF_PSEUDO_TALKER 0x800 /* pseudo is a talker on the conference */ /* Alarm Condition bits */ #define DAHDI_ALARM_NONE 0 /* No alarms */ #define DAHDI_ALARM_RECOVER 1 /* Recovering from alarm */ #define DAHDI_ALARM_LOOPBACK 2 /* In loopback */ #define DAHDI_ALARM_YELLOW 4 /* Yellow Alarm */ #define DAHDI_ALARM_RED 8 /* Red Alarm */ #define DAHDI_ALARM_BLUE 16 /* Blue Alarm */ #define DAHDI_ALARM_NOTOPEN 32 /* Maintenance modes */ #define DAHDI_MAINT_NONE 0 /* Normal Mode */ #define DAHDI_MAINT_LOCALLOOP 1 /* Local Loopback */ #define DAHDI_MAINT_REMOTELOOP 2 /* Remote Loopback */ #define DAHDI_MAINT_LOOPUP 3 /* send loopup code */ #define DAHDI_MAINT_LOOPDOWN 4 /* send loopdown code */ #define DAHDI_MAINT_LOOPSTOP 5 /* stop sending loop codes */ /* Flag Value for IOMUX, read avail */ #define DAHDI_IOMUX_READ 1 /* Flag Value for IOMUX, write avail */ #define DAHDI_IOMUX_WRITE 2 /* Flag Value for IOMUX, write done */ #define DAHDI_IOMUX_WRITEEMPTY 4 /* Flag Value for IOMUX, signalling event avail */ #define DAHDI_IOMUX_SIGEVENT 8 /* Flag Value for IOMUX, Do Not Wait if nothing to report */ #define DAHDI_IOMUX_NOWAIT 0x100 /* Ret. Value for GET/WAIT Event, no event */ #define DAHDI_EVENT_NONE 0 /* Ret. Value for GET/WAIT Event, Went Onhook */ #define DAHDI_EVENT_ONHOOK 1 /* Ret. Value for GET/WAIT Event, Went Offhook or got Ring */ #define DAHDI_EVENT_RINGOFFHOOK 2 /* Ret. Value for GET/WAIT Event, Got Wink or Flash */ #define DAHDI_EVENT_WINKFLASH 3 /* Ret. Value for GET/WAIT Event, Got Alarm */ #define DAHDI_EVENT_ALARM 4 /* Ret. Value for GET/WAIT Event, Got No Alarm (after alarm) */ #define DAHDI_EVENT_NOALARM 5 /* Ret. Value for GET/WAIT Event, HDLC Abort frame */ #define DAHDI_EVENT_ABORT 6 /* Ret. Value for GET/WAIT Event, HDLC Frame overrun */ #define DAHDI_EVENT_OVERRUN 7 /* Ret. Value for GET/WAIT Event, Bad FCS */ #define DAHDI_EVENT_BADFCS 8 /* Ret. Value for dial complete */ #define DAHDI_EVENT_DIALCOMPLETE 9 /* Ret Value for ringer going on */ #define DAHDI_EVENT_RINGERON 10 /* Ret Value for ringer going off */ #define DAHDI_EVENT_RINGEROFF 11 /* Ret Value for hook change complete */ #define DAHDI_EVENT_HOOKCOMPLETE 12 /* Ret Value for bits changing on a CAS / User channel */ #define DAHDI_EVENT_BITSCHANGED 13 /* Ret value for the beginning of a pulse coming on its way */ #define DAHDI_EVENT_PULSE_START 14 /* Timer event -- timer expired */ #define DAHDI_EVENT_TIMER_EXPIRED 15 /* Timer event -- ping ready */ #define DAHDI_EVENT_TIMER_PING 16 /* Polarity reversal event */ #define DAHDI_EVENT_POLARITY 17 /* Ring Begin event */ #define DAHDI_EVENT_RINGBEGIN 18 /* Echo can disabled event */ #define DAHDI_EVENT_EC_DISABLED 19 /* Channel was disconnected. Hint user to close channel */ #define DAHDI_EVENT_REMOVED 20 /* A neon MWI pulse was detected */ #define DAHDI_EVENT_NEONMWI_ACTIVE 21 /* No neon MWI pulses were detected over some period of time */ #define DAHDI_EVENT_NEONMWI_INACTIVE 22 /* A CED tone was detected on the channel in the transmit direction */ #define DAHDI_EVENT_TX_CED_DETECTED 23 /* A CED tone was detected on the channel in the receive direction */ #define DAHDI_EVENT_RX_CED_DETECTED 24 /* A CNG tone was detected on the channel in the transmit direction */ #define DAHDI_EVENT_TX_CNG_DETECTED 25 /* A CNG tone was detected on the channel in the receive direction */ #define DAHDI_EVENT_RX_CNG_DETECTED 26 /* The echo canceler's NLP (only) was disabled */ #define DAHDI_EVENT_EC_NLP_DISABLED 27 /* The echo canceler's NLP (only) was enabled */ #define DAHDI_EVENT_EC_NLP_ENABLED 28 #define DAHDI_EVENT_PULSEDIGIT (1 << 16) /* This is OR'd with the digit received */ #define DAHDI_EVENT_DTMFDOWN (1 << 17) /* Ditto for DTMF key down event */ #define DAHDI_EVENT_DTMFUP (1 << 18) /* Ditto for DTMF key up event */ /* Transcoder related definitions */ struct dahdi_transcoder_formats { __u32 srcfmt; __u32 dstfmt; }; struct dahdi_transcoder_info { __u32 tcnum; char name[80]; __u32 numchannels; __u32 dstfmts; __u32 srcfmts; }; #define DAHDI_MAX_ECHOCANPARAMS 8 /* ioctl definitions */ #define DAHDI_CODE 0xDA /* * Get/Set Transfer Block Size. */ #define DAHDI_GET_BLOCKSIZE _IOR(DAHDI_CODE, 1, int) #define DAHDI_SET_BLOCKSIZE _IOW(DAHDI_CODE, 1, int) /* * Flush Buffer(s) and stop I/O */ #define DAHDI_FLUSH _IOW(DAHDI_CODE, 3, int) /* * Wait for Write to Finish */ #define DAHDI_SYNC _IO(DAHDI_CODE, 4) /* * Get/set channel parameters */ struct dahdi_params { int channo; /* Channel number */ int spanno; /* Span itself */ int chanpos; /* Channel number in span */ int sigtype; /* read-only */ int sigcap; /* read-only */ int rxisoffhook; /* read-only */ int rxbits; /* read-only */ int txbits; /* read-only */ int txhooksig; /* read-only */ int rxhooksig; /* read-only */ int curlaw; /* read-only -- one of DAHDI_LAW_MULAW or DAHDI_LAW_ALAW */ int idlebits; /* read-only -- What is considered the idle state */ char name[40]; /* Name of channel */ int prewinktime; int preflashtime; int winktime; int flashtime; int starttime; int rxwinktime; int rxflashtime; int debouncetime; int pulsebreaktime; int pulsemaketime; int pulseaftertime; __u32 chan_alarms; /* alarms on this channel */ }; #define DAHDI_GET_PARAMS_V1 _IOR(DAHDI_CODE, 5, struct dahdi_params) #define DAHDI_GET_PARAMS _IOWR(DAHDI_CODE, 5, struct dahdi_params) #define DAHDI_SET_PARAMS _IOW(DAHDI_CODE, 5, struct dahdi_params) /* * Set Hookswitch Status */ #define DAHDI_HOOK _IOW(DAHDI_CODE, 7, int) /* * Get Signalling Event */ #define DAHDI_GETEVENT _IOR(DAHDI_CODE, 8, int) /* * Wait for something to happen (IO Mux) */ #define DAHDI_IOMUX _IOWR(DAHDI_CODE, 9, int) /* * Get Span Status */ struct dahdi_spaninfo { int spanno; /* span number */ char name[20]; /* Name */ char desc[40]; /* Description */ int alarms; /* alarms status */ int txlevel; /* what TX level is set to */ int rxlevel; /* current RX level */ int bpvcount; /* current BPV count */ int crc4count; /* current CRC4 error count */ int ebitcount; /* current E-bit error count */ int fascount; /* current FAS error count */ int irqmisses; /* current IRQ misses */ int syncsrc; /* span # of current sync source, or 0 for free run */ int numchans; /* number of configured channels on this span */ int totalchans; /* total number of channels on the span */ int totalspans; /* total number of spans in entire system */ int lbo; /* line build out */ int lineconfig; /* framing/coding */ char lboname[40]; /* line build out in text form */ char location[40]; /* span's device location in system */ char manufacturer[40]; /* manufacturer of span's device */ char devicetype[40]; /* span's device type */ int irq; /* span's device IRQ */ int linecompat; /* signaling modes possible on this span */ char spantype[6]; /* type of span in text form */ }; #define DAHDI_SPANSTAT _IOWR(DAHDI_CODE, 10, struct dahdi_spaninfo) /* * Set Maintenance Mode */ struct dahdi_maintinfo { int spanno; /* span number 1-2 */ int command; /* command */ }; #define DAHDI_MAINT _IOW(DAHDI_CODE, 11, struct dahdi_maintinfo) /* * Get/Set Conference Mode */ struct dahdi_confinfo { int chan; /* channel number, 0 for current */ int confno; /* conference number */ int confmode; /* conferencing mode */ }; #define DAHDI_GETCONF_V1 _IOR(DAHDI_CODE, 12, struct dahdi_confinfo) #define DAHDI_GETCONF _IOWR(DAHDI_CODE, 12, struct dahdi_confinfo) #define DAHDI_SETCONF_V1 _IOW(DAHDI_CODE, 12, struct dahdi_confinfo) #define DAHDI_SETCONF _IOWR(DAHDI_CODE, 13, struct dahdi_confinfo) /* * Setup or Remove Conference Link */ #define DAHDI_CONFLINK _IOW(DAHDI_CODE, 14, struct dahdi_confinfo) /* * Display Conference Diagnostic Information on Console */ #define DAHDI_CONFDIAG_V1 _IOR(DAHDI_CODE, 15, int) #define DAHDI_CONFDIAG _IOW(DAHDI_CODE, 15, int) /* * Get/Set Channel audio gains */ struct dahdi_gains { int chan; /* channel number, 0 for current */ unsigned char rxgain[256]; /* Receive gain table */ unsigned char txgain[256]; /* Transmit gain table */ }; #define DAHDI_GETGAINS_V1 _IOR(DAHDI_CODE, 16, struct dahdi_gains) #define DAHDI_GETGAINS _IOWR(DAHDI_CODE, 16, struct dahdi_gains) #define DAHDI_SETGAINS _IOW(DAHDI_CODE, 16, struct dahdi_gains) /* * Set Line (T1) Configurations */ struct dahdi_lineconfig { int span; /* Which span number (0 to use name) */ char name[20]; /* Name of span to use */ int lbo; /* line build-outs */ int lineconfig; /* line config parameters (framing, coding) */ int sync; /* what level of sync source we are */ }; #define DAHDI_SPANCONFIG _IOW(DAHDI_CODE, 18, struct dahdi_lineconfig) /* * Set Channel Configuration */ struct dahdi_chanconfig { int chan; /* Channel we're applying this to (0 to use name) */ char name[40]; /* Name of channel to use */ int sigtype; /* Signal type */ int deflaw; /* Default law (DAHDI_LAW_DEFAULT, DAHDI_LAW_MULAW, or DAHDI_LAW_ALAW) */ int master; /* Master channel if sigtype is DAHDI_SLAVE */ int idlebits; /* Idle bits (if this is a CAS channel) or channel to monitor (if this is DACS channel) */ char netdev_name[16];/* name for the hdlc network device*/ }; #define DAHDI_CHANCONFIG _IOW(DAHDI_CODE, 19, struct dahdi_chanconfig) /* * Set Conference to mute mode */ #define DAHDI_CONFMUTE _IOW(DAHDI_CODE, 20, int) /* * Send a particular tone (see DAHDI_TONE_*) */ #define DAHDI_SENDTONE _IOW(DAHDI_CODE, 21, int) /* * Get/Set your region for tones */ #define DAHDI_GETTONEZONE _IOR(DAHDI_CODE, 22, int) #define DAHDI_SETTONEZONE _IOW(DAHDI_CODE, 22, int) /* * Master unit only -- set default zone (see DAHDI_TONE_ZONE_*) */ #define DAHDI_DEFAULTZONE _IOW(DAHDI_CODE, 24, int) /* * Load a tone zone from a dahdi_tone_def_header */ struct dahdi_tone_def { int tone; /* See DAHDI_TONE_* */ int next; /* What the next position in the cadence is (They're numbered by the order the appear here) */ int samples; /* How many samples to play for this cadence */ int shift; /* How much to scale down the volume (2 is nice) */ /* Now come the constants we need to make tones */ /* Calculate the next 6 factors using the following equations: l = , f1 = , f2 = gain = pow(10.0, (l - 3.14) / 20.0) * 65536.0 / 2.0; // Frequency factor 1 fac_1 = 2.0 * cos(2.0 * M_PI * (f1/8000.0)) * 32768.0; // Last previous two samples init_v2_1 = sin(-4.0 * M_PI * (f1/8000.0)) * gain; init_v3_1 = sin(-2.0 * M_PI * (f1/8000.0)) * gain; // Frequency factor 2 fac_2 = 2.0 * cos(2.0 * M_PI * (f2/8000.0)) * 32768.0; // Last previous two samples init_v2_2 = sin(-4.0 * M_PI * (f2/8000.0)) * gain; init_v3_2 = sin(-2.0 * M_PI * (f2/8000.0)) * gain; */ int fac1; int init_v2_1; int init_v3_1; int fac2; int init_v2_2; int init_v3_2; int modulate; }; struct dahdi_tone_def_header { int count; /* How many samples follow */ int zone; /* Which zone we are loading */ int ringcadence[DAHDI_MAX_CADENCE]; /* Ring cadence in ms (0=on, 1=off, ends with 0 value) */ char name[40]; /* Informational name of zone */ /* immediately follow this structure with dahdi_tone_def structures */ struct dahdi_tone_def tones[0]; }; #define DAHDI_LOADZONE _IOW(DAHDI_CODE, 25, struct dahdi_tone_def_header) /* * Free a tone zone */ #define DAHDI_FREEZONE _IOW(DAHDI_CODE, 26, int) /* * Get/Set buffer policy */ struct dahdi_bufferinfo { int txbufpolicy; /* Policy for handling receive buffers */ int rxbufpolicy; /* Policy for handling receive buffers */ int numbufs; /* How many buffers to use */ int bufsize; /* How big each buffer is */ int readbufs; /* How many read buffers are full (read-only) */ int writebufs; /* How many write buffers are full (read-only) */ }; #define DAHDI_GET_BUFINFO _IOR(DAHDI_CODE, 27, struct dahdi_bufferinfo) #define DAHDI_SET_BUFINFO _IOW(DAHDI_CODE, 27, struct dahdi_bufferinfo) /* * Get/Set dialing parameters */ struct dahdi_dialparams { int mfv1_tonelen; /* MF R1 tone length for digits */ int dtmf_tonelen; /* DTMF tone length */ int mfr2_tonelen; /* MF R2 tone length */ int reserved[3]; /* Reserved for future expansion -- always set to 0 */ }; #define DAHDI_GET_DIALPARAMS _IOR(DAHDI_CODE, 29, struct dahdi_dialparams) #define DAHDI_SET_DIALPARAMS _IOW(DAHDI_CODE, 29, struct dahdi_dialparams) /* * Append, replace, or cancel a dial string */ struct dahdi_dialoperation { int op; char dialstr[DAHDI_MAX_DTMF_BUF]; }; #define DAHDI_DIAL _IOW(DAHDI_CODE, 31, struct dahdi_dialoperation) /* * Set a clear channel into audio mode */ #define DAHDI_AUDIOMODE _IOW(DAHDI_CODE, 32, int) /* * Enable or disable echo cancellation on a channel * * For ECHOCANCEL: * The number is zero to disable echo cancellation and non-zero * to enable echo cancellation. If the number is between 32 * and 1024, it will also set the number of taps in the echo canceller * * For ECHOCANCEL_PARAMS: * The structure contains parameters that should be passed to the * echo canceler instance for the selected channel. */ #define DAHDI_ECHOCANCEL _IOW(DAHDI_CODE, 33, int) struct dahdi_echocanparam { char name[16]; __s32 value; }; struct dahdi_echocanparams { /* 8 taps per millisecond */ __u32 tap_length; /* number of parameters supplied */ __u32 param_count; /* immediately follow this structure with dahdi_echocanparam structures */ struct dahdi_echocanparam params[0]; }; #define DAHDI_ECHOCANCEL_PARAMS _IOW(DAHDI_CODE, 33, struct dahdi_echocanparams) /* * Return a channel's channel number */ #define DAHDI_CHANNO _IOR(DAHDI_CODE, 34, int) /* * Return a flag indicating whether channel is currently dialing */ #define DAHDI_DIALING _IOR(DAHDI_CODE, 35, int) /* * Set a clear channel into HDLC w/out FCS checking/calculation mode */ #define DAHDI_HDLCRAWMODE _IOW(DAHDI_CODE, 36, int) /* * Set a clear channel into HDLC w/ FCS mode */ #define DAHDI_HDLCFCSMODE _IOW(DAHDI_CODE, 37, int) /* * Specify a channel on generic channel selector - must be done before * performing any other ioctls */ #define DAHDI_SPECIFY _IOW(DAHDI_CODE, 38, int) /* * Temporarily set the law on a channel to * DAHDI_LAW_DEFAULT, DAHDI_LAW_ALAW, or DAHDI_LAW_MULAW. Is reset on close. */ #define DAHDI_SETLAW _IOW(DAHDI_CODE, 39, int) /* * Temporarily set the channel to operate in linear mode when non-zero * or default law if 0 */ #define DAHDI_SETLINEAR _IOW(DAHDI_CODE, 40, int) /* * Set a clear channel into HDLC w/ PPP interface mode */ #define DAHDI_HDLCPPP _IOW(DAHDI_CODE, 41, int) /* * Set the ring cadence for FXS interfaces */ struct dahdi_ring_cadence { int ringcadence[DAHDI_MAX_CADENCE]; }; #define DAHDI_SETCADENCE _IOW(DAHDI_CODE, 42, struct dahdi_ring_cadence) /* * Get/Set the signaling bits for CAS interface */ #define DAHDI_GETRXBITS _IOR(DAHDI_CODE, 43, int) #define DAHDI_SETTXBITS _IOW(DAHDI_CODE, 43, int) /* * Display Channel Diagnostic Information on Console */ #define DAHDI_CHANDIAG_V1 _IOR(DAHDI_CODE, 44, int) #define DAHDI_CHANDIAG _IOW(DAHDI_CODE, 44, int) /* * Set Channel's SF Tone Configuration */ struct dahdi_sfconfig { int chan; /* Channel we're applying this to (0 to use name) */ char name[40]; /* Name of channel to use */ long rxp1; /* receive tone det. p1 */ long rxp2; /* receive tone det. p2 */ long rxp3; /* receive tone det. p3 */ int txtone; /* Tx tone factor */ int tx_v2; /* initial v2 value */ int tx_v3; /* initial v3 value */ int toneflag; /* Tone flags */ }; #define DAHDI_SFCONFIG _IOW(DAHDI_CODE, 46, struct dahdi_sfconfig) /* * Set timer expiration (in samples) */ #define DAHDI_TIMERCONFIG _IOW(DAHDI_CODE, 47, int) /* * Acknowledge timer expiration (number to acknowledge, or -1 for all) */ #define DAHDI_TIMERACK _IOW(DAHDI_CODE, 48, int) /* * Get Conference to mute mode */ #define DAHDI_GETCONFMUTE _IOR(DAHDI_CODE, 49, int) /* * Request echo training in some number of ms (with muting in the mean time) */ #define DAHDI_ECHOTRAIN _IOW(DAHDI_CODE, 50, int) /* * Set on hook transfer for n number of ms -- implemnted by low level driver */ #define DAHDI_ONHOOKTRANSFER _IOW(DAHDI_CODE, 51, int) /* * Queue Ping */ #define DAHDI_TIMERPING _IO(DAHDI_CODE, 52) /* * Acknowledge ping */ #define DAHDI_TIMERPONG _IO(DAHDI_CODE, 53) /* * Get/set signalling freeze */ #define DAHDI_GETSIGFREEZE _IOR(DAHDI_CODE, 54, int) #define DAHDI_SETSIGFREEZE _IOW(DAHDI_CODE, 54, int) /* * Perform an indirect ioctl (on a specified channel via master interface) */ struct dahdi_indirect_data { int chan; int op; void *data; }; #define DAHDI_INDIRECT _IOWR(DAHDI_CODE, 56, struct dahdi_indirect_data) /* * Get the version of DAHDI that is running, and a description * of the compiled-in echo cancellers (if any) */ struct dahdi_versioninfo { char version[80]; char echo_canceller[80]; }; #define DAHDI_GETVERSION _IOR(DAHDI_CODE, 57, struct dahdi_versioninfo) /* * Put the channel in loopback mode (receive from the channel is * transmitted back on the interface) */ #define DAHDI_LOOPBACK _IOW(DAHDI_CODE, 58, int) /* Attach the desired echo canceler module (or none) to a channel in an audio-supporting mode, so that when the channel needs an echo canceler that module will be used to supply one. */ struct dahdi_attach_echocan { int chan; /* Channel we're applying this to */ char echocan[16]; /* Name of echo canceler to attach to this channel (leave empty to have no echocan attached */ }; #define DAHDI_ATTACH_ECHOCAN _IOW(DAHDI_CODE, 59, struct dahdi_attach_echocan) /* * 60-80 are reserved for private drivers * 80-85 are reserved for dynamic span stuff */ /* * Create a dynamic span */ struct dahdi_dynamic_span { char driver[20]; /* Which low-level driver to use */ char addr[40]; /* Destination address */ int numchans; /* Number of channels */ int timing; /* Timing source preference */ int spanno; /* Span number (filled in by DAHDI) */ }; #define DAHDI_DYNAMIC_CREATE _IOWR(DAHDI_CODE, 80, struct dahdi_dynamic_span) /* * Destroy a dynamic span */ #define DAHDI_DYNAMIC_DESTROY _IOW(DAHDI_CODE, 81, struct dahdi_dynamic_span) /* * Set the HW gain for a device */ struct dahdi_hwgain { __s32 newgain; /* desired gain in dB but x10. -3.5dB would be -35 */ __u32 tx:1; /* 0=rx; 1=tx */ }; #define DAHDI_SET_HWGAIN _IOW(DAHDI_CODE, 86, struct dahdi_hwgain) /* * Enable tone detection -- implemented by low level driver */ #define DAHDI_TONEDETECT _IOW(DAHDI_CODE, 91, int) /* * Set polarity -- implemented by individual driver. 0 = forward, 1 = reverse */ #define DAHDI_SETPOLARITY _IOW(DAHDI_CODE, 92, int) /* * Transcoder operations */ /* DAHDI_TRANSCODE_OP is an older interface that is deprecated and no longer * supported. */ #define DAHDI_TRANSCODE_OP _IOWR(DAHDI_CODE, 93, int) #define DAHDI_TC_CODE 'T' #define DAHDI_TC_ALLOCATE _IOW(DAHDI_TC_CODE, 1, struct dahdi_transcoder_formats) #define DAHDI_TC_GETINFO _IOWR(DAHDI_TC_CODE, 2, struct dahdi_transcoder_info) /* * VMWI Specification */ struct dahdi_vmwi_info { unsigned int vmwi_type; }; #define DAHDI_VMWI_LREV (1 << 0) /* Line Reversal */ #define DAHDI_VMWI_HVDC (1 << 1) /* HV 90VDC */ #define DAHDI_VMWI_HVAC (1 << 2) /* HV 90VAC Neon lamp */ /* * VoiceMail Waiting Indication (VMWI) -- implemented by low-level driver. * Value: number of waiting messages (hence 0: switch messages off). */ #define DAHDI_VMWI _IOWR(DAHDI_CODE, 94, int) #define DAHDI_VMWI_CONFIG _IOW(DAHDI_CODE, 95, struct dahdi_vmwi_info) /* * Startup or Shutdown a span */ #define DAHDI_STARTUP _IOW(DAHDI_CODE, 99, int) #define DAHDI_SHUTDOWN _IOW(DAHDI_CODE, 100, int) #define DAHDI_HDLC_RATE _IOW(DAHDI_CODE, 101, int) /* Put a channel's echo canceller into 'FAX mode' if possible */ #define DAHDI_ECHOCANCEL_FAX_MODE _IOW(DAHDI_CODE, 102, int) struct torisa_debug { unsigned int txerrors; unsigned int irqcount; unsigned int taskletsched; unsigned int taskletrun; unsigned int taskletexec; int span1flags; int span2flags; }; /* Special torisa ioctl */ #define TORISA_GETDEBUG _IOW(DAHDI_CODE, 60, struct torisa_debug) /* Get current status IOCTL */ /* Defines for Radio Status (dahdi_radio_stat.radstat) bits */ #define DAHDI_RADSTAT_RX 1 /* currently "receiving " */ #define DAHDI_RADSTAT_TX 2 /* currently "transmitting" */ #define DAHDI_RADSTAT_RXCT 4 /* currently receiving continuous tone with current settings */ #define DAHDI_RADSTAT_RXCOR 8 /* currently receiving COR (irrelevant of COR ignore) */ #define DAHDI_RADSTAT_IGNCOR 16 /* currently ignoring COR */ #define DAHDI_RADSTAT_IGNCT 32 /* currently ignoring CTCSS/DCS decode */ #define DAHDI_RADSTAT_NOENCODE 64 /* currently blocking CTCSS/DCS encode */ struct dahdi_radio_stat { unsigned short ctcode_rx; /* code of currently received CTCSS or DCS, 0 for none */ unsigned short ctclass; /* class of currently received CTCSS or DCS code */ unsigned short ctcode_tx; /* code of currently encoded CTCSS or DCS, 0 for none */ unsigned char radstat; /* status bits of radio */ }; #define DAHDI_RADIO_GETSTAT _IOR(DAHDI_CODE, 57, struct dahdi_radio_stat) /* Get/Set a radio channel parameter */ /* Defines for Radio Parameters (dahdi_radio_param.radpar) */ #define DAHDI_RADPAR_INVERTCOR 1 /* invert the COR signal (0/1) */ #define DAHDI_RADPAR_IGNORECOR 2 /* ignore the COR signal (0/1) */ #define DAHDI_RADPAR_IGNORECT 3 /* ignore the CTCSS/DCS decode (0/1) */ #define DAHDI_RADPAR_NOENCODE 4 /* block the CTCSS/DCS encode (0/1) */ #define DAHDI_RADPAR_CORTHRESH 5 /* COR trigger threshold (0-7) */ #define DAHDI_RADPAR_EXTRXTONE 6 /* 0 means use internal decoder, 1 means UIOA logic true is CT decode, 2 means UIOA logic false is CT decode */ #define DAHDI_RADPAR_NUMTONES 7 /* returns maximum tone index (curently 15) */ #define DAHDI_RADPAR_INITTONE 8 /* init all tone indexes to 0 (no tones) */ #define DAHDI_RADPAR_RXTONE 9 /* CTCSS tone, (1-32) or DCS tone (1-777), or 0 meaning no tone, set index also (1-15) */ #define DAHDI_RADPAR_RXTONECLASS 10 /* Tone class (0-65535), set index also (1-15) */ #define DAHDI_RADPAR_TXTONE 11 /* CTCSS tone (1-32) or DCS tone (1-777) or 0 to indicate no tone, to transmit for this tone index (0-32, 0 disables transmit CTCSS), set index also (0-15) */ #define DAHDI_RADPAR_DEBOUNCETIME 12 /* receive indication debounce time, milliseconds (1-999) */ #define DAHDI_RADPAR_BURSTTIME 13 /* end of transmit with no CT tone in milliseconds (0-999) */ #define DAHDI_RADPAR_UIODATA 14 /* read/write UIOA and UIOB data. Bit 0 is UIOA, bit 1 is UIOB */ #define DAHDI_RADPAR_UIOMODE 15 /* 0 means UIOA and UIOB are both outputs, 1 means UIOA is input, UIOB is output, 2 means UIOB is input and UIOA is output, 3 means both UIOA and UIOB are inputs. Note mode for UIOA is overridden when in EXTRXTONE mode. */ #define DAHDI_RADPAR_REMMODE 16 /* Remote control data mode */ #define DAHDI_RADPAR_REM_NONE 0 /* no remote control data mode */ #define DAHDI_RADPAR_REM_RBI1 1 /* Doug Hall RBI-1 data mode */ #define DAHDI_RADPAR_REM_SERIAL 2 /* Serial Data, 9600 BPS */ #define DAHDI_RADPAR_REM_SERIAL_ASCII 3 /* Serial Ascii Data, 9600 BPS */ #define DAHDI_RADPAR_REMCOMMAND 17 /* Remote conrtol write data block & do cmd */ #define DAHDI_RADPAR_DEEMP 18 /* Audio De-empahsis (on or off) */ #define DAHDI_RADPAR_PREEMP 19 /* Audio Pre-empahsis (on or off) */ #define DAHDI_RADPAR_RXGAIN 20 /* Audio (In to system) Rx Gain */ #define DAHDI_RADPAR_TXGAIN 21 /* Audio (Out from system) Tx Gain */ #define RAD_SERIAL_BUFLEN 128 struct dahdi_radio_param { unsigned short radpar; /* param identifier */ unsigned short index; /* tone number */ int data; /* param */ int data2; /* param 2 */ unsigned char buf[RAD_SERIAL_BUFLEN]; }; #define DAHDI_RADIO_GETPARAM _IOR(DAHDI_CODE, 58, struct dahdi_radio_param) #define DAHDI_RADIO_SETPARAM _IOW(DAHDI_CODE, 58, struct dahdi_radio_param) /*! \brief Size-limited null-terminating string copy. \param dst The destination buffer \param src The source string \param size The size of the destination buffer \return Nothing. This is similar to \a strncpy, with two important differences: - the destination buffer will \b always be null-terminated - the destination buffer is not filled with zeros past the copied string length These differences make it slightly more efficient, and safer to use since it will not leave the destination buffer unterminated. There is no need to pass an artificially reduced buffer size to this function (unlike \a strncpy), and the buffer does not need to be initialized to zeroes prior to calling this function. */ static inline void dahdi_copy_string(char *dst, const char *src, unsigned int size) { while (*src && size) { *dst++ = *src++; size--; } if (__builtin_expect(!size, 0)) dst--; *dst = '\0'; } #endif /* _DAHDI_USER_H */ dahdi-linux-2.2.0-rc4/include/dahdi/dahdi_config.h0000644000175000017500000001056211176115504021121 0ustar maniacmaniac/* * DAHDI configuration options * */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ #ifndef _DAHDI_CONFIG_H #define _DAHDI_CONFIG_H #ifdef __KERNEL__ #include #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) #include #else #include #endif #endif /* DAHDI compile time options */ /* * Uncomment if you have a European phone, or any other phone with a * short flash time. * This will stop the flash being mis-detected as a pulse dial "1" on * phones with short flashes */ /* #define SHORT_FLASH_TIME */ /* * Uncomment to disable calibration and/or DC/DC converter tests * (not generally recommended) */ /* #define NO_CALIBRATION */ /* #define NO_DCDC */ /* * Boost ring voltage (Higher ring voltage, takes more power) * Note: this only affects the wcfxsusb and wcusb drivers; all other * drivers have a 'boostringer' module parameter. */ /* #define BOOST_RINGER */ /* * Define CONFIG_CALC_XLAW if you have a small number of channels and/or * a small level 2 cache, to optimize for few channels * */ /* #define CONFIG_CALC_XLAW */ /* * Define if you want MMX optimizations in DAHDI * * Note: CONFIG_DAHDI_MMX is generally incompatible with AMD * processors and can cause system instability! * */ /* #define CONFIG_DAHDI_MMX */ /* We now use the linux kernel config to detect which options to use */ /* You can still override them below */ #if defined(CONFIG_HDLC) || defined(CONFIG_HDLC_MODULE) #define DAHDI_HDLC_TYPE_TRANS #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3) #define HDLC_MAINTAINERS_ARE_MORE_STUPID_THAN_I_THOUGHT #endif #endif #ifdef CONFIG_PPP #define CONFIG_DAHDI_PPP #endif /* * Uncomment CONFIG_DAHDI_NET to enable SyncPPP, CiscoHDLC, and Frame Relay * support. */ /* #define CONFIG_DAHDI_NET */ /* * Uncomment CONFIG_OLD_HDLC_API if your are compiling with CONFIG_DAHDI_NET * defined and you are using the old kernel HDLC interface (or if you get * an error about ETH_P_HDLC while compiling). */ /* #define CONFIG_OLD_HDLC_API */ /* * Uncomment for Generic PPP support (i.e. ZapRAS) */ /* #define CONFIG_DAHDI_PPP */ /* * Uncomment to enable "watchdog" to monitor if interfaces * stop taking interrupts or otherwise misbehave */ /* #define CONFIG_DAHDI_WATCHDOG */ /* * Uncomment the following to include extra debugging output. */ /* #define CONFIG_DAHDI_DEBUG */ /* * Uncomment for Non-standard FXS groundstart start state (A=Low, B=Low) * particularly for CAC channel bank groundstart FXO ports. */ /* #define CONFIG_CAC_GROUNDSTART */ /* * Uncomment if you happen have an early TDM400P Rev H which * sometimes forgets its PCI ID to have wcfxs match essentially all * subvendor ID's */ /* #define TDM_REVH_MATCHALL */ /* * Uncomment the following if you want to support E&M trunks being * able to "flash" after going off-hook (dont ask why, just nod :-) ). * * NOTE: *DO NOT* Enable "EMFLASH" and "EMPULSE" at the same time!! * */ /* #define EMFLASH */ /* * Uncomment the following if you want to support E&M trunks being * able to recognize Dial Pulse digits. This can validly be enabled * so that either Dial Pulse or DTMF/MF tones will be recognized, but * the drawback is that the ONHOOK will take an extra {rxwinktime} * to be recognized. * * NOTE: *DO NOT* Enable "EMFLASH" and "EMPULSE" at the same time!! * */ /* #define EMPULSE */ /* * Comment out the following if you dont want events to indicate the * beginning of an incoming ring. Most non-Asterisk applications will * want this commented out. */ #define RINGBEGIN /* * Uncomment the following if you need to support FXS Flash events. * Most applications will want this commented out. */ /* #define FXSFLASH */ /* * Enable sync_tick() calls. Allows low-level drivers to synchronize * their internal clocks to the DAHDI master clock. */ #define DAHDI_SYNC_TICK /* * Skip processing PCM if low-level driver won't use it anyway */ /* #define OPTIMIZE_CHANMUTE */ #endif dahdi-linux-2.2.0-rc4/include/dahdi/fasthdlc.h0000644000175000017500000002756211060053105020311 0ustar maniacmaniac/* * Mark's Mythical Table-based raw HDLC implementation * * This is designed to be a very fast, but memory efficient * implementation of standard HDLC protocol. * * This table based HDLC technology is PATENT PENDING, but will always be * remain freely distributable under the terms of the GPL version 2. * * For non-GPL licensing, please contact Mark Spencer at * the below e-mail address. * * Copyright (C) 2001-2008, Digium, Inc. * * Written by Mark Spencer * */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ #ifndef _FASTHDLC_H #define _FASTHDLC_H enum fasthdlc_mode { FASTHDLC_MODE_64 = 0, FASTHDLC_MODE_56, }; struct fasthdlc_state { int state; /* What state we are in */ unsigned int data; /* Our current data queue */ int bits; /* Number of bits in our data queue */ int ones; /* Number of ones */ enum fasthdlc_mode mode; }; #ifdef FAST_HDLC_NEED_TABLES #define RETURN_COMPLETE_FLAG (0x1000) #define RETURN_DISCARD_FLAG (0x2000) #define RETURN_EMPTY_FLAG (0x4000) /* Unlike most HDLC implementations, we define only two states, when we are in a valid frame, and when we are searching for a frame header */ #define FRAME_SEARCH 0 #define PROCESS_FRAME 1 /* HDLC Search State table -- Look for a frame header. The return value of this table is as follows: |---8---|---7---|---6---|---5---|---4---|---3---|---2---|---1---| | Z E R O E S | Next | Bits Consumed | |-------|-------|-------|-------|-------|-------|-------|-------| The indexes for this table are the state (0 or 1) and the next 8 bits of the stream. Note that this table is only used for state 0 and 1. The user should discard the top "bits consumed" bits of data before the next call. "Next state" represents the actual next state for decoding. */ static unsigned char hdlc_search[256]; /* HDLC Data Table The indexes to this table are the number of one's we've seen so far (0-5) and the next 10 bits of input (which is enough to guarantee us that we will retrieve at least one byte of data (or frame or whatever). The format for the return value is: Bits 15: Status (1=Valid Data, 0=Control Frame (see bits 7-0 for type)) Bits 14-12: Number of ones in a row, so far Bits 11-8: The number of bits consumed (0-10) Bits 7-0: The return data (if appropriate) The next state is simply bit #15 */ #define CONTROL_COMPLETE 1 #define CONTROL_ABORT 2 #define STATUS_MASK (1 << 15) #define STATUS_VALID (1 << 15) #define STATUS_CONTROL (0 << 15) #define STATE_MASK (1 << 15) #define ONES_MASK (7 << 12) #define DATA_MASK (0xff) static unsigned short hdlc_frame[6][1024]; static unsigned int minbits[2] = { 8, 10 }; /* Last, but not least, we have the encoder table. It takes as its indices the number of ones so far and a byte of data and returns an int composed of the following fields: Bots 31-22: Actual Data Bits 21-16: Unused Bits 15-8: Number of ones Bits 3-0: Number of bits of output (13-4) to use Of course we could optimize by reducing to two tables, but I don't really think it's worth the trouble at this point. */ static unsigned int hdlc_encode[6][256]; static inline char hdlc_search_precalc(unsigned char c) { int x, p=0; /* Look for a flag. If this isn't a flag, line us up for the next possible shot at a flag */ /* If it's a flag, we go to state 1, and have consumed 8 bits */ if (c == 0x7e) return 0x10 | 8; /* If it's an abort, we stay in the same state and have consumed 8 bits */ if (c == 0x7f) return 0x00 | 8; /* If it's all 1's, we state in the same state and have consumed 8 bits */ if (c == 0xff) return 0x00 | 8; /* If we get here, we must have at least one zero in us but we're not the flag. So, start at the end (LSB) and work our way to the top (MSB) looking for a zero. The position of that 0 is most optimistic start of a real frame header */ x=1; p=7; while(p && (c & x)) { x <<= 1; p--; } return p; } #ifdef DEBUG_PRECALC static inline void hdlc_search_print(char c, char r) { int x=0x80; while(x) { printf("%s", c & x ? "1" : "0"); x >>= 1; } printf(" => State %d, Consume %d\n", (r & 0x10) >> 4, r & 0xf); } #endif #define HFP(status, ones, bits, data) \ ((status) | ((ones) << 12) | ((bits) << 8) | (data)) static inline unsigned int hdlc_frame_precalc(unsigned char x, unsigned short c) { /* Assume we have seen 'x' one's so far, and have read the bottom 10 bytes of c (MSB first). Now, we HAVE to have a byte of data or a frame or something. We are assumed to be at the beginning of a byte of data or something */ unsigned char ones = x; unsigned char data=0; int bits=0; int consumed=0; while(bits < 8) { data >>=1; consumed++; if (ones == 5) { /* We've seen five ones */ if (c & 0x0200) { /* Another one -- Some sort of signal frame */ if ((!(c & 0x0100)) && (bits == 6)) { /* This is a frame terminator (10) */ return HFP(0, 0, 8, CONTROL_COMPLETE); } else { /* Yuck! It's something else... Abort this entire frame, and start looking for a good frame */ return HFP(0, 0, consumed+1, CONTROL_ABORT); } } else { /* It's an inserted zero, just skip it */ ones = 0; data <<= 1; } } else { /* Add it to our bit list, LSB to MSB */ if (c & 0x0200) { data |= 0x80; ones++; } else ones=0; bits++; } c <<= 1; } /* Consume the extra 0 now rather than later. */ if (ones == 5) { ones = 0; consumed++; } return HFP(STATUS_VALID, ones, consumed, data); } #ifdef DEBUG_PRECALC static inline void hdlc_frame_print(unsigned char x, unsigned short c, unsigned int res) { int z=0x0200; char *status[] = { "Control", "Valid", }; printf("%d one's then ", x); while(z) { printf("%s", c & z ? "1" : "0"); z >>= 1; } printf(" => Status %s, ", res & STATUS_MASK ? "1" : "0"); printf("Consumed: %d, ", (res & 0x0f00) >> 8); printf("Status: %s, ", status[(res & STATUS_MASK) >> 15]); printf("Ones: %d, ", (res & ONES_MASK) >> 12); printf("Data: %02x\n", res & 0xff); } #endif static inline unsigned int hdlc_encode_precalc(int x, unsigned char y) { int bits=0; int ones=x; unsigned short data=0; int z; for (z=0;z<8;z++) { /* Zero-stuff if needed */ if (ones == 5) { /* Stuff a zero */ data <<= 1; ones=0; bits++; } if (y & 0x01) { /* There's a one */ data <<= 1; data |= 0x1; ones++; bits++; } else { data <<= 1; ones = 0; bits++; } y >>= 1; } /* Special case -- Stuff the zero at the end if appropriate */ if (ones == 5) { /* Stuff a zero */ data <<= 1; ones=0; bits++; } data <<= (10-bits); return (data << 22) | (ones << 8) | (bits); } #ifdef DEBUG_PRECALC static inline void hdlc_encode_print(int x, unsigned char y, unsigned int val) { unsigned int z; unsigned short c; printf("%d ones, %02x (", x, y); z = 0x80; while(z) { printf("%s", y & z ? "1" : "0"); z >>= 1; } printf(") encoded as "); z = 1 << 31; for (x=0;x<(val & 0xf);x++) { printf("%s", val & z ? "1" : "0"); z >>= 1; } printf(" with %d ones now, %d bits in len\n", (val & 0xf00) >> 8, val & 0xf); } #endif static inline void fasthdlc_precalc(void) { int x; int y; /* First the easy part -- the searching */ for (x=0;x<256;x++) { hdlc_search[x] = hdlc_search_precalc(x); #ifdef DEBUG_PRECALC hdlc_search_print(x, hdlc_search[x]); #endif } /* Now the hard part -- the frame tables */ for (x=0;x<6;x++) { /* Given the # of preceeding ones, process the next byte of input (up to 10 actual bits) */ for (y=0;y<1024;y++) { hdlc_frame[x][y] = hdlc_frame_precalc(x, y); #ifdef DEBUG_PRECALC hdlc_frame_print(x, y, hdlc_frame[x][y]); #endif } } /* Now another not-so-hard part, the encoding table */ for (x=0;x<6;x++) { for (y=0;y<256;y++) { hdlc_encode[x][y] = hdlc_encode_precalc(x,y); #ifdef DEBUG_PRECALC hdlc_encode_print(x,y,hdlc_encode[x][y]); #endif } } } static inline void fasthdlc_init(struct fasthdlc_state *h, enum fasthdlc_mode mode) { /* Initializes all states appropriately */ h->mode = mode; h->state = 0; h->bits = 0; h->data = 0; h->ones = 0; } static inline int fasthdlc_tx_load_nocheck(struct fasthdlc_state *h, unsigned char c) { unsigned int res; res = hdlc_encode[h->ones][c]; h->ones = (res & 0xf00) >> 8; h->data |= (res & 0xffc00000) >> h->bits; h->bits += (res & 0xf); return 0; } static inline int fasthdlc_tx_load(struct fasthdlc_state *h, unsigned char c) { /* Gotta have at least 10 bits left */ if (h->bits > 22) return -1; return fasthdlc_tx_load_nocheck(h, c); } static inline int fasthdlc_tx_frame_nocheck(struct fasthdlc_state *h) { h->ones = 0; h->data |= ( 0x7e000000 >> h->bits); h->bits += 8; return 0; } static inline int fasthdlc_tx_frame(struct fasthdlc_state *h) { if (h->bits > 24) return -1; return fasthdlc_tx_frame_nocheck(h); } static inline int fasthdlc_tx_need_data(struct fasthdlc_state *h) { if (h->mode == FASTHDLC_MODE_56) { if (h->bits < 7) return 1; } else { if (h->bits < 8) return 1; } return 0; } static inline int fasthdlc_tx_run_nocheck(struct fasthdlc_state *h) { unsigned char b; if (h->mode == FASTHDLC_MODE_56) { b = h->data >> 25; h->bits -= 7; h->data <<= 7; return ((b & 0x7f) << 1) | 1; } else { b = h->data >> 24; h->bits -= 8; h->data <<= 8; return b; } } static inline int fasthdlc_tx_run(struct fasthdlc_state *h) { if (h->bits < 8) return -1; return fasthdlc_tx_run_nocheck(h); } static inline int fasthdlc_rx_load_nocheck(struct fasthdlc_state *h, unsigned char b) { if (h->mode == FASTHDLC_MODE_56) { h->data |= (b >> 1) << (25-h->bits); h->bits += 7; } else { /* Put the new byte in the data stream */ h->data |= b << (24-h->bits); h->bits += 8; } return 0; } static inline int fasthdlc_rx_load(struct fasthdlc_state *h, unsigned char b) { /* Make sure we have enough space */ if (h->bits > 24) return -1; return fasthdlc_rx_load_nocheck(h, b); } /* Returns a data character if available, logical OR'd with zero or more of RETURN_COMPLETE_FLAG, RETURN_DISCARD_FLAG, and RETURN_EMPTY_FLAG, signifying a complete frame, a discarded frame, or there is nothing to return. */ static inline int fasthdlc_rx_run(struct fasthdlc_state *h) { unsigned short next; int retval=RETURN_EMPTY_FLAG; while ((h->bits >= minbits[h->state]) && (retval == RETURN_EMPTY_FLAG)) { /* Run until we can no longer be assured that we will have enough bits to continue */ switch(h->state) { case FRAME_SEARCH: /* Look for an HDLC frame, keying from the top byte. */ next = hdlc_search[h->data >> 24]; h->bits -= next & 0x0f; h->data <<= next & 0x0f; h->state = next >> 4; h->ones = 0; break; case PROCESS_FRAME: /* Process as much as the next ten bits */ next = hdlc_frame[h->ones][h->data >> 22]; h->bits -= ((next & 0x0f00) >> 8); h->data <<= ((next & 0x0f00) >> 8); h->state = (next & STATE_MASK) >> 15; h->ones = (next & ONES_MASK) >> 12; switch(next & STATUS_MASK) { case STATUS_CONTROL: if (next & CONTROL_COMPLETE) { /* A complete, valid frame received */ retval = (RETURN_COMPLETE_FLAG); /* Stay in this state */ h->state = 1; } else { /* An abort (either out of sync of explicit) */ retval = (RETURN_DISCARD_FLAG); } break; case STATUS_VALID: retval = (next & DATA_MASK); } } } return retval; } #endif /* FAST_HDLC_NEED_TABLES */ #endif dahdi-linux-2.2.0-rc4/drivers/0000755000175000017500000000000011202066027015323 5ustar maniacmaniacdahdi-linux-2.2.0-rc4/drivers/dahdi/0000755000175000017500000000000011202066032016370 5ustar maniacmaniacdahdi-linux-2.2.0-rc4/drivers/dahdi/ecdis.h0000644000175000017500000000672211176115504017650 0ustar maniacmaniac/* * SpanDSP - a series of DSP components for telephony * * ec_disable_detector.h - A detector which should eventually meet the * G.164/G.165 requirements for detecting the * 2100Hz echo cancellor disable tone. * * Written by Steve Underwood * * Copyright (C) 2001 Steve Underwood * * All rights reserved. * */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ #include "biquad.h" #define FALSE 0 #define TRUE (!FALSE) static inline void echo_can_disable_detector_init (echo_can_disable_detector_state_t *det) { /* Elliptic notch */ /* This is actually centred at 2095Hz, but gets the balance we want, due to the asymmetric walls of the notch */ biquad2_init (&det->notch, (int32_t) (-0.7600000*32768.0), (int32_t) (-0.1183852*32768.0), (int32_t) (-0.5104039*32768.0), (int32_t) ( 0.1567596*32768.0), (int32_t) ( 1.0000000*32768.0)); det->channel_level = 0; det->notch_level = 0; det->tone_present = FALSE; det->tone_cycle_duration = 0; det->good_cycles = 0; det->hit = 0; } /*- End of function --------------------------------------------------------*/ static inline int echo_can_disable_detector_update (echo_can_disable_detector_state_t *det, int16_t amp) { int16_t notched; notched = biquad2 (&det->notch, amp); /* Estimate the overall energy in the channel, and the energy in the notch (i.e. overall channel energy - tone energy => noise). Use abs instead of multiply for speed (is it really faster?). Damp the overall energy a little more for a stable result. Damp the notch energy a little less, so we don't damp out the blip every time the phase reverses */ det->channel_level += ((abs(amp) - det->channel_level) >> 5); det->notch_level += ((abs(notched) - det->notch_level) >> 4); if (det->channel_level >= 70) { /* There is adequate energy in the channel. Is it mostly at 2100Hz? */ if (det->notch_level*6 < det->channel_level) { det->tone_cycle_duration++; /* The notch says yes, so we have the tone. */ if (!det->tone_present) { /* Do we get a kick every 450+-25ms? */ if ((det->tone_cycle_duration >= (425 * 8)) && (det->tone_cycle_duration <= (475 * 8))) { /* It's ANS/PR (CED with polarity reversals), so wait for at least three cycles before returning a hit. */ det->good_cycles++; if (det->good_cycles > 2) det->hit = TRUE; } det->tone_cycle_duration = 0; det->tone_present = TRUE; } else if (det->tone_cycle_duration >= 600 * 8) { /* It's ANS (CED without polarity reversals) so return a hit. */ det->hit = TRUE; } } else { det->tone_present = FALSE; } } else { det->tone_present = FALSE; det->tone_cycle_duration = 0; det->good_cycles = 0; } return det->hit; } /*- End of function --------------------------------------------------------*/ /*- End of file ------------------------------------------------------------*/ dahdi-linux-2.2.0-rc4/drivers/dahdi/wcfxo.c0000644000175000017500000007036411101704316017676 0ustar maniacmaniac/* * Wildcard X100P FXO Interface Driver for DAHDI Telephony interface * * Written by Mark Spencer * Matthew Fredrickson * * Copyright (C) 2001-2008, Digium, Inc. * * All rights reserved. * */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ #include #include #include #include #include #include #include #include #include #include /* 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 dahdi_span span; struct dahdi_chan _chan; struct dahdi_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[DAHDI_CHUNKSIZE]; struct reg oldregs[DAHDI_CHUNKSIZE]; unsigned char lasttx[DAHDI_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 dahdi_transmit() anyway */ if (!(ints & 3)) { /* Calculate Transmission */ dahdi_transmit(&wc->span); return; } /* Remember what it was we just sent */ memcpy(wc->lasttx, wc->chan->writechunk, DAHDI_CHUNKSIZE); if (ints & 0x01) { /* Write is at interrupt address. Start writing from normal offset */ writechunk = wc->writechunk; } else { writechunk = wc->writechunk + DAHDI_CHUNKSIZE * 2; } dahdi_transmit(&wc->span); for (x=0;xflags & FLAG_INVERTSER) writechunk[x << 1] = cpu_to_le32( ~((unsigned short)(DAHDI_XLAW(wc->chan->writechunk[x], wc->chan))| 0x1) << 16 ); else writechunk[x << 1] = cpu_to_le32( ((unsigned short)(DAHDI_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(KERN_DEBUG "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 + DAHDI_CHUNKSIZE * 2; /* Keep track of how quickly our peg alternates */ wc->pegtimer+=DAHDI_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(KERN_DEBUG "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] = DAHDI_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(KERN_DEBUG "RING!\n"); dahdi_hooksig(wc->chan, DAHDI_RXSIG_RING); wc->ring = 1; } if (wc->ring && !wc->pegcount) { /* No more ring */ if (debug) printk(KERN_DEBUG "NO RING!\n"); dahdi_hooksig(wc->chan, DAHDI_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*/ dahdi_ec_chunk(wc->chan, wc->chan->readchunk, wc->lasttx); /* Receive the result */ dahdi_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); DAHDI_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) return IRQ_NONE; 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(KERN_INFO "FXO PCI Master abort\n"); /* Stop DMA andlet the watchdog start it again */ wcfxo_stop_dma(wc); return IRQ_RETVAL(1); } if (ints & 0x20) { printk(KERN_INFO "PCI Target abort\n"); return IRQ_RETVAL(1); } 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(KERN_DEBUG "Battery loss: %d (%d debounce)\n", b, wc->battdebounce); #endif if (wc->battery && !wc->battdebounce) { if (debug) printk(KERN_DEBUG "NO BATTERY!\n"); wc->battery = 0; #ifdef JAPAN if ((!wc->ohdebounce) && wc->offhook) { dahdi_hooksig(&wc->chan, DAHDI_RXSIG_ONHOOK); if (debug) printk(KERN_DEBUG "Signalled On Hook\n"); #ifdef ZERO_BATT_RING wc->onhook++; #endif } #else dahdi_hooksig(wc->chan, DAHDI_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 = DAHDI_ALARM_RED; dahdi_alarm_notify(&wc->span); } } else if (b == 0xf) { if (!wc->battery && !wc->battdebounce) { if (debug) printk(KERN_DEBUG "BATTERY!\n"); #ifdef ZERO_BATT_RING if (wc->onhook) { wc->onhook = 0; dahdi_hooksig(&wc->chan, DAHDI_RXSIG_OFFHOOK); if (debug) printk(KERN_DEBUG "Signalled Off Hook\n"); } #else dahdi_hooksig(wc->chan, DAHDI_RXSIG_OFFHOOK); #endif wc->battery = 1; wc->nobatttimer = 0; wc->battdebounce = BATT_DEBOUNCE; if (wc->span.alarms) { wc->span.alarms = 0; dahdi_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 } return IRQ_RETVAL(1); } static int wcfxo_setreg(struct wcfxo *wc, unsigned char reg, unsigned char value) { int x; if (wc->wregcount < DAHDI_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(KERN_NOTICE "wcfxo: Out of space to write register %02x with %02x\n", reg, value); return -1; } static int wcfxo_open(struct dahdi_chan *chan) { struct wcfxo *wc = chan->pvt; if (wc->dead) return -ENODEV; wc->usecount++; return 0; } static int wcfxo_watchdog(struct dahdi_span *span, int event) { printk(KERN_INFO "FXO: Restarting DMA\n"); wcfxo_restart_dma(span->pvt); return 0; } static int wcfxo_close(struct dahdi_chan *chan) { struct wcfxo *wc = chan->pvt; wc->usecount--; /* If we're dead, release us now */ if (!wc->usecount && wc->dead) wcfxo_release(wc); return 0; } static int wcfxo_hooksig(struct dahdi_chan *chan, enum dahdi_txsig txsig) { struct wcfxo *wc = chan->pvt; int reg=0; switch(txsig) { case DAHDI_TXSIG_START: case DAHDI_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 DAHDI_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(KERN_NOTICE "wcfxo: Can't set tx state to %d\n", txsig); } if (debug) printk(KERN_DEBUG "Setting hook state to %d (%02x)\n", txsig, reg); return 0; } static int wcfxo_initialize(struct wcfxo *wc) { /* DAHDI 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"; dahdi_copy_string(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype)); wc->chan->sigcap = DAHDI_SIG_FXSKS | DAHDI_SIG_FXSLS | DAHDI_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 = DAHDI_FLAG_RBS; wc->span.deflaw = DAHDI_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 (dahdi_register(&wc->span, 0)) { printk(KERN_NOTICE "Unable to register span with DAHDI\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 + DAHDI_CHUNKSIZE * 8 - 4, wc->ioaddr + WC_DMAWI); /* Middle (interrupt) */ outl(wc->writedma + DAHDI_CHUNKSIZE * 16 - 4, wc->ioaddr + WC_DMAWE); /* End */ outl(wc->readdma, wc->ioaddr + WC_DMARS); /* Read start */ outl(wc->readdma + DAHDI_CHUNKSIZE * 8 - 4, wc->ioaddr + WC_DMARI); /* Middle (interrupt) */ outl(wc->readdma + DAHDI_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 + (DAHDI_CHUNKSIZE * HZ) / 800); printk(KERN_INFO "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 + (DAHDI_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 + (DAHDI_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 + (DAHDI_CHUNKSIZE * HZ) / 800); reg15 = 0x0; /* Go ahead and attenuate transmit signal by 6 db */ if (quiet) { printk(KERN_INFO "wcfxo: Attenuating transmit signal for quiet operation\n"); reg15 |= (quiet & 0x3) << 4; } if (boost) { printk(KERN_INFO "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(KERN_DEBUG " 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->chan = &wc->_chan; 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, DAHDI_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, &wc->writedma); if (!wc->writechunk) { printk(KERN_NOTICE "wcfxo: Unable to allocate DMA-able memory\n"); if (wc->freeregion) release_region(wc->ioaddr, 0xff); return -ENOMEM; } wc->readchunk = wc->writechunk + DAHDI_MAX_CHUNKSIZE * 4; /* in doublewords */ wc->readdma = wc->writedma + DAHDI_MAX_CHUNKSIZE * 16; /* in bytes */ if (wcfxo_initialize(wc)) { printk(KERN_NOTICE "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, DAHDI_IRQ_SHARED, "wcfxo", wc)) { printk(KERN_NOTICE "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,DAHDI_MAX_CHUNKSIZE * 2 * 2 * 2 * 4); /* Start DMA */ wcfxo_start_dma(wc); /* Initialize DAA (after it's started) */ if (wcfxo_init_daa(wc)) { printk(KERN_NOTICE "Failed to initailize DAA, giving up...\n"); wcfxo_stop_dma(wc); wcfxo_disable_interrupts(wc); dahdi_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(KERN_INFO "Found a Wildcard FXO: %s\n", wc->variety); return 0; } static void wcfxo_release(struct wcfxo *wc) { dahdi_unregister(&wc->span); if (wc->freeregion) release_region(wc->ioaddr, 0xff); kfree(wc); printk(KERN_INFO "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, DAHDI_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, .remove = __devexit_p(wcfxo_remove_one), .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(KERN_NOTICE "Invalid/unknown operating mode specified. Please choose one of:\n"); for (x=0;x"); MODULE_LICENSE("GPL v2"); module_init(wcfxo_init); module_exit(wcfxo_cleanup); dahdi-linux-2.2.0-rc4/drivers/dahdi/Makefile0000644000175000017500000000026011026016414020031 0ustar maniacmaniacifdef 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 dahdi-linux-2.2.0-rc4/drivers/dahdi/wctdm24xxp/0000755000175000017500000000000011202066031020413 5ustar maniacmaniacdahdi-linux-2.2.0-rc4/drivers/dahdi/wctdm24xxp/Makefile0000644000175000017500000000026011026016414022055 0ustar maniacmaniacifdef 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 dahdi-linux-2.2.0-rc4/drivers/dahdi/wctdm24xxp/base.c0000644000175000017500000035453711202062373021517 0ustar maniacmaniac/* * Wildcard TDM2400P TDM FXS/FXO Interface Driver for DAHDI Telephony interface * * Written by Mark Spencer * Support for TDM800P and VPM150M by Matthew Fredrickson * * Copyright (C) 2005 - 2009 Digium, Inc. * All rights reserved. * * Sections for QRV cards written by Jim Dixon * Copyright (C) 2006, Jim Dixon and QRV Communications * All rights reserved. * */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ /* For QRV DRI cards, gain is signed short, expressed in hundredths of db (in reference to 1v Peak @ 1000Hz) , as follows: Rx Gain: -11.99 to 15.52 db Tx Gain - No Pre-Emphasis: -35.99 to 12.00 db Tx Gain - W/Pre-Emphasis: -23.99 to 0.00 db */ #include #include #include #include #include #include #include #include #include #include #include #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) #include #else #include #endif #include #include #include "proslic.h" #include "wctdm24xxp.h" #include "adt_lec.h" #include "voicebus/GpakCust.h" #include "voicebus/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; /* Following define is a logical exclusive OR to determine if the polarity of an fxs line is to be reversed. * The items taken into account are: * overall polarity reversal for the module, * polarity reversal for the port, * and the state of the line reversal MWI indicator */ #define POLARITY_XOR(card) ( (reversepolarity != 0) ^ (wc->mods[(card)].fxs.reversepolarity != 0) ^ (wc->mods[(card)].fxs.vmwi_linereverse != 0) ) static int reversepolarity = 0; static alpha indirect_regs[] = { {0,255,"DTMF_ROW_0_PEAK",0x55C2}, {1,255,"DTMF_ROW_1_PEAK",0x51E6}, {2,255,"DTMF_ROW2_PEAK",0x4B85}, {3,255,"DTMF_ROW3_PEAK",0x4937}, {4,255,"DTMF_COL1_PEAK",0x3333}, {5,255,"DTMF_FWD_TWIST",0x0202}, {6,255,"DTMF_RVS_TWIST",0x0202}, {7,255,"DTMF_ROW_RATIO_TRES",0x0198}, {8,255,"DTMF_COL_RATIO_TRES",0x0198}, {9,255,"DTMF_ROW_2ND_ARM",0x0611}, {10,255,"DTMF_COL_2ND_ARM",0x0202}, {11,255,"DTMF_PWR_MIN_TRES",0x00E5}, {12,255,"DTMF_OT_LIM_TRES",0x0A1C}, {13,0,"OSC1_COEF",0x7B30}, {14,1,"OSC1X",0x0063}, {15,2,"OSC1Y",0x0000}, {16,3,"OSC2_COEF",0x7870}, {17,4,"OSC2X",0x007D}, {18,5,"OSC2Y",0x0000}, {19,6,"RING_V_OFF",0x0000}, {20,7,"RING_OSC",0x7EF0}, {21,8,"RING_X",0x0160}, {22,9,"RING_Y",0x0000}, {23,255,"PULSE_ENVEL",0x2000}, {24,255,"PULSE_X",0x2000}, {25,255,"PULSE_Y",0x0000}, //{26,13,"RECV_DIGITAL_GAIN",0x4000}, // playback volume set lower {26,13,"RECV_DIGITAL_GAIN",0x2000}, // playback volume set lower {27,14,"XMIT_DIGITAL_GAIN",0x4000}, //{27,14,"XMIT_DIGITAL_GAIN",0x2000}, {28,15,"LOOP_CLOSE_TRES",0x1000}, {29,16,"RING_TRIP_TRES",0x3600}, {30,17,"COMMON_MIN_TRES",0x1000}, {31,18,"COMMON_MAX_TRES",0x0200}, {32,19,"PWR_ALARM_Q1Q2",0x07C0}, {33,20,"PWR_ALARM_Q3Q4", 0x4C00 /* 0x2600 */}, {34,21,"PWR_ALARM_Q5Q6",0x1B80}, {35,22,"LOOP_CLOSURE_FILTER",0x8000}, {36,23,"RING_TRIP_FILTER",0x0320}, {37,24,"TERM_LP_POLE_Q1Q2",0x008C}, {38,25,"TERM_LP_POLE_Q3Q4",0x0100}, {39,26,"TERM_LP_POLE_Q5Q6",0x0010}, {40,27,"CM_BIAS_RINGING",0x0C00}, {41,64,"DCDC_MIN_V",0x0C00}, {42,255,"DCDC_XTRA",0x1000}, {43,66,"LOOP_CLOSE_TRES_LOW",0x1000}, }; #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; #define MS_PER_HOOKCHECK (1) #define NEONMWI_ON_DEBOUNCE (100/MS_PER_HOOKCHECK) static int neonmwi_monitor = 0; /* Note: this causes use of full wave ring detect */ static int neonmwi_level = 75; /* neon mwi trip voltage */ static int neonmwi_envelope = 10; static int neonmwi_offlimit = 16000; /* Time in milliseconds the monitor is checked before saying no message is waiting */ static int neonmwi_offlimit_cycles; /* Time in milliseconds the monitor is checked before saying no message is waiting */ static int vpmsupport = 1; static int vpmnlptype = DEFAULT_NLPTYPE; static int vpmnlpthresh = DEFAULT_NLPTHRESH; static int vpmnlpmaxsupp = DEFAULT_NLPMAXSUPP; static int echocan_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec); static void echocan_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec); static const struct dahdi_echocan_features vpm100m_ec_features = { .NLP_automatic = 1, .CED_tx_detect = 1, .CED_rx_detect = 1, }; static const struct dahdi_echocan_features vpm150m_ec_features = { .NLP_automatic = 1, .CED_tx_detect = 1, .CED_rx_detect = 1, }; static const struct dahdi_echocan_ops vpm100m_ec_ops = { .name = "VPM100M", .echocan_free = echocan_free, }; static const struct dahdi_echocan_ops vpm150m_ec_ops = { .name = "VPM150M", .echocan_free = echocan_free, }; 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; } void setchanconfig_from_state(struct vpmadt032 *vpm, int channel, GpakChannelConfig_t *chanconfig) { const struct vpmadt032_options *options; GpakEcanParms_t *p; BUG_ON(!vpm); options = &vpm->options; chanconfig->PcmInPortA = 3; chanconfig->PcmInSlotA = channel; chanconfig->PcmOutPortA = SerialPortNull; chanconfig->PcmOutSlotA = channel; chanconfig->PcmInPortB = 2; chanconfig->PcmInSlotB = channel; chanconfig->PcmOutPortB = 3; chanconfig->PcmOutSlotB = channel; chanconfig->ToneTypesA = Null_tone; chanconfig->MuteToneA = Disabled; chanconfig->FaxCngDetA = Disabled; chanconfig->ToneTypesB = Null_tone; chanconfig->EcanEnableA = Enabled; chanconfig->EcanEnableB = Disabled; chanconfig->MuteToneB = Disabled; chanconfig->FaxCngDetB = Disabled; switch (vpm->span->deflaw) { case DAHDI_LAW_MULAW: chanconfig->SoftwareCompand = cmpPCMU; break; case DAHDI_LAW_ALAW: chanconfig->SoftwareCompand = cmpPCMA; break; default: chanconfig->SoftwareCompand = cmpPCMU; break; } chanconfig->FrameRate = rate2ms; p = &chanconfig->EcanParametersA; vpmadt032_get_default_parameters(p); p->EcanNlpType = vpm->curecstate[channel].nlp_type; p->EcanNlpThreshold = vpm->curecstate[channel].nlp_threshold; p->EcanNlpMaxSuppress = vpm->curecstate[channel].nlp_max_suppress; memcpy(&chanconfig->EcanParametersB, &chanconfig->EcanParametersA, sizeof(chanconfig->EcanParametersB)); } static int config_vpmadt032(struct vpmadt032 *vpm) { int res, i; GpakPortConfig_t portconfig = {0}; gpakConfigPortStatus_t configportstatus; GPAK_PortConfigStat_t pstatus; GpakChannelConfig_t chanconfig; GPAK_ChannelConfigStat_t cstatus; GPAK_AlgControlStat_t algstatus; /* First Serial Port config */ portconfig.SlotsSelect1 = SlotCfgNone; portconfig.FirstBlockNum1 = 0; portconfig.FirstSlotMask1 = 0x0000; portconfig.SecBlockNum1 = 1; portconfig.SecSlotMask1 = 0x0000; portconfig.SerialWordSize1 = SerWordSize8; portconfig.CompandingMode1 = cmpNone; portconfig.TxFrameSyncPolarity1 = FrameSyncActHigh; portconfig.RxFrameSyncPolarity1 = FrameSyncActHigh; portconfig.TxClockPolarity1 = SerClockActHigh; portconfig.RxClockPolarity1 = SerClockActHigh; portconfig.TxDataDelay1 = DataDelay0; portconfig.RxDataDelay1 = DataDelay0; portconfig.DxDelay1 = Disabled; portconfig.ThirdSlotMask1 = 0x0000; portconfig.FouthSlotMask1 = 0x0000; portconfig.FifthSlotMask1 = 0x0000; portconfig.SixthSlotMask1 = 0x0000; portconfig.SevenSlotMask1 = 0x0000; portconfig.EightSlotMask1 = 0x0000; /* Second Serial Port config */ portconfig.SlotsSelect2 = SlotCfg2Groups; portconfig.FirstBlockNum2 = 0; portconfig.FirstSlotMask2 = 0xffff; portconfig.SecBlockNum2 = 1; portconfig.SecSlotMask2 = 0xffff; portconfig.SerialWordSize2 = SerWordSize8; portconfig.CompandingMode2 = cmpNone; portconfig.TxFrameSyncPolarity2 = FrameSyncActHigh; portconfig.RxFrameSyncPolarity2 = FrameSyncActHigh; portconfig.TxClockPolarity2 = SerClockActHigh; portconfig.RxClockPolarity2 = SerClockActLow; portconfig.TxDataDelay2 = DataDelay0; portconfig.RxDataDelay2 = DataDelay0; portconfig.DxDelay2 = Disabled; portconfig.ThirdSlotMask2 = 0x0000; portconfig.FouthSlotMask2 = 0x0000; portconfig.FifthSlotMask2 = 0x0000; portconfig.SixthSlotMask2 = 0x0000; portconfig.SevenSlotMask2 = 0x0000; portconfig.EightSlotMask2 = 0x0000; /* Third Serial Port Config */ portconfig.SlotsSelect3 = SlotCfg2Groups; portconfig.FirstBlockNum3 = 0; portconfig.FirstSlotMask3 = 0xffff; portconfig.SecBlockNum3 = 1; portconfig.SecSlotMask3 = 0xffff; portconfig.SerialWordSize3 = SerWordSize8; portconfig.CompandingMode3 = cmpNone; portconfig.TxFrameSyncPolarity3 = FrameSyncActHigh; portconfig.RxFrameSyncPolarity3 = FrameSyncActHigh; portconfig.TxClockPolarity3 = SerClockActHigh; portconfig.RxClockPolarity3 = SerClockActLow; portconfig.TxDataDelay3 = DataDelay0; portconfig.RxDataDelay3 = DataDelay0; portconfig.DxDelay3 = Disabled; portconfig.ThirdSlotMask3 = 0x0000; portconfig.FouthSlotMask3 = 0x0000; portconfig.FifthSlotMask3 = 0x0000; portconfig.SixthSlotMask3 = 0x0000; portconfig.SevenSlotMask3 = 0x0000; portconfig.EightSlotMask3 = 0x0000; if ((configportstatus = gpakConfigurePorts(vpm->dspid, &portconfig, &pstatus))) { printk(KERN_NOTICE "Configuration of ports failed (%d)!\n", configportstatus); return -1; } else { if (vpm->options.debug & DEBUG_ECHOCAN) printk(KERN_DEBUG "Configured McBSP ports successfully\n"); } if ((res = gpakPingDsp(vpm->dspid, &vpm->version))) { printk(KERN_NOTICE "Error pinging DSP (%d)\n", res); return -1; } for (i = 0; i < vpm->span->channels; ++i) { vpm->curecstate[i].tap_length = 0; vpm->curecstate[i].nlp_type = vpm->options.vpmnlptype; vpm->curecstate[i].nlp_threshold = vpm->options.vpmnlpthresh; vpm->curecstate[i].nlp_max_suppress = vpm->options.vpmnlpmaxsupp; memcpy(&vpm->desiredecstate[i], &vpm->curecstate[i], sizeof(vpm->curecstate[i])); /* set_vpmadt032_chanconfig_from_state(&vpm->curecstate[i], &vpm->options, i, &chanconfig); !!! */ vpm->setchanconfig_from_state(vpm, i, &chanconfig); if ((res = gpakConfigureChannel(vpm->dspid, i, tdmToTdm, &chanconfig, &cstatus))) { printk(KERN_NOTICE "Unable to configure channel #%d (%d)", i, res); if (res == 1) { printk(", reason %d", cstatus); } printk("\n"); return -1; } if ((res = gpakAlgControl(vpm->dspid, i, BypassEcanA, &algstatus))) { printk(KERN_NOTICE "Unable to disable echo can on channel %d (reason %d:%d)\n", i + 1, res, algstatus); return -1; } } if ((res = gpakPingDsp(vpm->dspid, &vpm->version))) { printk(KERN_NOTICE "Error pinging DSP (%d)\n", res); return -1; } set_bit(VPM150M_ACTIVE, &vpm->control); return 0; } static inline void cmd_dequeue_vpmadt032(struct wctdm *wc, unsigned char *writechunk, int whichframe) { unsigned long flags; struct vpmadt032_cmd *curcmd = NULL; struct vpmadt032 *vpmadt032 = wc->vpmadt032; 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, &vpmadt032->control) || test_bit(VPM150M_HPIRESET, &vpmadt032->control)) { if (debug & DEBUG_ECHOCAN) printk(KERN_INFO "HW Resetting VPMADT032...\n"); for (x = 24; x < 28; x++) { if (x == 24) { if (test_and_clear_bit(VPM150M_SPIRESET, &vpmadt032->control)) writechunk[CMD_BYTE(x, 0, 0)] = 0x08; else if (test_and_clear_bit(VPM150M_HPIRESET, &vpmadt032->control)) writechunk[CMD_BYTE(x, 0, 0)] = 0x0b; } else writechunk[CMD_BYTE(x, 0, 0)] = 0x00 | leds; writechunk[CMD_BYTE(x, 1, 0)] = 0; writechunk[CMD_BYTE(x, 2, 0)] = 0x00; } spin_unlock_irqrestore(&wc->reglock, flags); return; } if ((curcmd = vpmadt032_get_ready_cmd(vpmadt032))) { curcmd->txident = wc->txident; #if 0 // if (printk_ratelimit()) printk(KERN_DEBUG "Transmitting txident = %d, desc = 0x%x, addr = 0x%x, data = 0x%x\n", curcmd->txident, curcmd->desc, curcmd->address, curcmd->data); #endif if (curcmd->desc & __VPM150M_RWPAGE) { /* Set CTRL access to page*/ 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 & 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->address >> 8) & 0xff; writechunk[CMD_BYTE(24, 2, 0)] = curcmd->address & 0xff; /* Send/Get our data */ writechunk[CMD_BYTE(25, 0, 0)] = (curcmd->desc & __VPM150M_WR) ? ((0x8 | (0x3 << 1)) << 4) : ((0x8 | (0x3 << 1) | 0x1) << 4); writechunk[CMD_BYTE(25, 1, 0)] = (curcmd->data >> 8) & 0xff; writechunk[CMD_BYTE(25, 2, 0)] = curcmd->data & 0xff; writechunk[CMD_BYTE(26, 0, 0)] = 0; writechunk[CMD_BYTE(26, 1, 0)] = 0; writechunk[CMD_BYTE(26, 2, 0)] = 0; /* Fill in the rest */ writechunk[CMD_BYTE(27, 0, 0)] = 0; writechunk[CMD_BYTE(27, 1, 0)] = 0; writechunk[CMD_BYTE(27, 2, 0)] = 0; } } else if (test_and_clear_bit(VPM150M_SWRESET, &vpmadt032->control)) { printk(KERN_INFO "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; } } /* 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, &vpmadt032->control) && !whichframe && !(wc->intcount % 100)) { schedule_work(&vpmadt032->work); } spin_unlock_irqrestore(&wc->reglock, flags); } 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(KERN_DEBUG "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; } 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) { ; } 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(KERN_DEBUG "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 } static inline void cmd_decipher_vpmadt032(struct wctdm *wc, unsigned char *readchunk) { unsigned long flags; struct vpmadt032 *vpm = wc->vpmadt032; struct vpmadt032_cmd *cmd; BUG_ON(!vpm); /* If the hardware is not processing any commands currently, then * there is nothing for us to do here. */ if (list_empty(&vpm->active_cmds)) { return; } spin_lock_irqsave(&vpm->list_lock, flags); cmd = list_entry(vpm->active_cmds.next, struct vpmadt032_cmd, node); if (wc->rxident == cmd->txident) { list_del_init(&cmd->node); } else { cmd = NULL; } spin_unlock_irqrestore(&vpm->list_lock, flags); if (!cmd) { return; } /* Skip audio */ readchunk += 24; /* Store result */ cmd->data = (0xff & readchunk[CMD_BYTE(25, 1, 0)]) << 8; cmd->data |= readchunk[CMD_BYTE(25, 2, 0)]; if (cmd->desc & __VPM150M_WR) { /* Writes do not need any acknowledgement */ list_add_tail(&cmd->node, &vpm->free_cmds); } else { cmd->desc |= __VPM150M_FIN; complete(&cmd->complete); } #if 0 // if (printk_ratelimit()) printk(KERN_DEBUG "Received txident = %d, desc = 0x%x, addr = 0x%x, data = 0x%x\n", cmd->txident, cmd->desc, cmd->address, cmd->data); #endif } static inline void cmd_decipher(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(KERN_DEBUG "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)) { dahdi_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); } if (!x) wc->blinktimer++; if (wc->vpm100) { for (y=24;y<28;y++) { if (!x) { cmd_checkisr(wc, y); } cmd_dequeue(wc, writechunk, y, x); } #ifdef FANCY_ECHOCAN if (wc->vpm100 && wc->blinktimer >= 0xf) { wc->blinktimer = -1; wc->echocanpos++; } #endif } else if (wc->vpmadt032) { cmd_dequeue_vpmadt032(wc, writechunk, x); } if (x < DAHDI_CHUNKSIZE - 1) { writechunk[EFRAME_SIZE] = wc->ctlreg; writechunk[EFRAME_SIZE + 1] = wc->txident++; 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; } 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; } 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); } /* TODO: this should go in the dahdi_voicebus module... */ static inline void cmd_vpmadt032_retransmit(struct wctdm *wc) { unsigned long flags; struct vpmadt032 *vpmadt032 = wc->vpmadt032; struct vpmadt032_cmd *cmd, *temp; BUG_ON(!vpmadt032); /* By moving the commands back to the pending list, they will be * transmitted when room is available */ spin_lock_irqsave(&vpmadt032->list_lock, flags); list_for_each_entry_safe(cmd, temp, &vpmadt032->active_cmds, node) { cmd->desc &= ~(__VPM150M_TX); list_move_tail(&cmd->node, &vpmadt032->pending_cmds); } spin_unlock_irqrestore(&vpmadt032->list_lock, flags); } 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->vpmadt032) cmd_vpmadt032_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_decipher(wc, readchunk, y); } if (wc->vpm100) { for (y=NUM_CARDS;y < NUM_CARDS + NUM_EC; y++) cmd_decipher(wc, readchunk, y); } else if (wc->vpmadt032) { cmd_decipher_vpmadt032(wc, readchunk); } 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)) dahdi_ec_chunk(wc->chans[x], wc->chans[x]->readchunk, wc->chans[x]->writechunk); } dahdi_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(KERN_NOTICE " ##### 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(KERN_NOTICE "%s", 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(KERN_NOTICE "!!!!!!! %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(KERN_DEBUG "Init Indirect Registers completed successfully.\n"); } else { printk(KERN_NOTICE " !!!!! 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(KERN_NOTICE "Power alarm (%02x) on module %d, resetting!\n", res, card + 1); if (wc->mods[card].fxs.lasttxhook == 4) { wc->mods[card].fxs.lasttxhook = POLARITY_XOR(card) ? 0x15 : 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(KERN_NOTICE "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(KERN_NOTICE "Power alarm on module %d, resetting!\n", card + 1); if (wc->mods[card].fxs.lasttxhook == 4) { wc->mods[card].fxs.lasttxhook = POLARITY_XOR(card) ? 0x15 : 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(KERN_NOTICE "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(KERN_DEBUG "QRV channel %d rx state changed to %d\n",qrvcard,wc->qrvhook[qrvcard + 2]); dahdi_hooksig(wc->chans[qrvcard], (b1) ? DAHDI_RXSIG_OFFHOOK : DAHDI_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(KERN_DEBUG "QRV channel %d rx state changed to %d\n",qrvcard + 1,wc->qrvhook[qrvcard + 3]); dahdi_hooksig(wc->chans[qrvcard + 1], (b1) ? DAHDI_RXSIG_OFFHOOK : DAHDI_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; unsigned int abs_voltage; 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 || neonmwi_monitor) { /* Look for ring status bits (Ring Detect Signal Negative and * Ring Detect Signal Positive) to transition back and forth * some number of times to indicate that a ring is occurring. * Provide some number of samples to allow for the transitions * to occur before ginving up. * NOTE: neon mwi voltages will trigger one of these bits to go active * but not to have transitions between the two bits (i.e. no negative * to positive or positive to negative transversals ) */ res = wc->cmdq[card].isrshadow[0] & 0x60; if (0 == wc->mods[card].fxo.wasringing) { if (res) { /* Look for positive/negative crossings in ring status reg */ fxo->wasringing = 2; fxo->ringdebounce = ringdebounce /16; fxo->lastrdtx = res; fxo->lastrdtx_count = 0; } } else if (2 == fxo->wasringing) { /* If ring detect signal has transversed */ if (res && res != fxo->lastrdtx) { /* if there are at least 3 ring polarity transversals */ if(++fxo->lastrdtx_count >= 2) { fxo->wasringing = 1; if (debug) printk("FW RING on %d/%d!\n", wc->span.spanno, card + 1); dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_RING); fxo->ringdebounce = ringdebounce / 16; } else { fxo->lastrdtx = res; fxo->ringdebounce = ringdebounce / 16; } /* ring indicator (positve or negative) has not transitioned, check debounce count */ } else if (--fxo->ringdebounce == 0) { fxo->wasringing = 0; } } else { /* I am in ring state */ if (res) { /* If any ringdetect bits are still active */ fxo->ringdebounce = ringdebounce / 16; } else if (--fxo->ringdebounce == 0) { fxo->wasringing = 0; if (debug) printk("FW NO RING on %d/%d!\n", wc->span.spanno, card + 1); dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_OFFHOOK); } } } else { res = wc->cmdq[card].isrshadow[0]; if ((res & 0x60) && (fxo->battery == BATTERY_PRESENT)) { fxo->ringdebounce += (DAHDI_CHUNKSIZE * 16); if (fxo->ringdebounce >= DAHDI_CHUNKSIZE * ringdebounce) { if (!fxo->wasringing) { fxo->wasringing = 1; dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_RING); if (debug) printk(KERN_DEBUG "RING on %d/%d!\n", wc->span.spanno, card + 1); } fxo->ringdebounce = DAHDI_CHUNKSIZE * ringdebounce; } } else { fxo->ringdebounce -= DAHDI_CHUNKSIZE * 4; if (fxo->ringdebounce <= 0) { if (fxo->wasringing) { fxo->wasringing = 0; dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_OFFHOOK); if (debug) printk(KERN_DEBUG "NO RING on %d/%d!\n", wc->span.spanno, card + 1); } fxo->ringdebounce = 0; } } } } b = wc->cmdq[card].isrshadow[1]; /* Voltage */ abs_voltage = abs(b); if (fxovoltage) { if (!(wc->intcount % 100)) { printk(KERN_INFO "Port %d: Voltage: %d Debounce %d\n", card + 1, b, fxo->battdebounce); } } if (abs_voltage < 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(KERN_DEBUG "NO BATTERY on %d/%d!\n", wc->span.spanno, card + 1); #ifdef JAPAN if (!wc->ohdebounce && wc->offhook) { dahdi_hooksig(&wc->chans[card], DAHDI_RXSIG_ONHOOK); if (debug) printk(KERN_DEBUG "Signalled On Hook\n"); #ifdef ZERO_BATT_RING wc->onhook++; #endif } #else dahdi_hooksig(wc->chans[card], DAHDI_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(KERN_DEBUG "BATTERY on %d/%d (%s)!\n", wc->span.spanno, card + 1, (b < 0) ? "-" : "+"); #ifdef ZERO_BATT_RING if (wc->onhook) { wc->onhook = 0; dahdi_hooksig(&wc->chans[card], DAHDI_RXSIG_OFFHOOK); if (debug) printk(KERN_DEBUG "Signalled Off Hook\n"); } #else dahdi_hooksig(wc->chans[card], DAHDI_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 */ dahdi_alarm_channel(wc->chans[card], fxo->battery == BATTERY_LOST ? DAHDI_ALARM_RED : DAHDI_ALARM_NONE); } } if (fxo->polaritydebounce) { fxo->polaritydebounce--; if (fxo->polaritydebounce < 1) { if (fxo->lastpol != fxo->polarity) { if (debug & DEBUG_CARD) printk(KERN_DEBUG "%lu Polarity reversed (%d -> %d)\n", jiffies, fxo->polarity, fxo->lastpol); if (fxo->polarity) dahdi_qevent_lock(wc->chans[card], DAHDI_EVENT_POLARITY); fxo->polarity = fxo->lastpol; } } } /* Look for neon mwi pulse */ if (neonmwi_monitor && !wc->mods[card].fxo.offhook) { /* Look for 4 consecutive voltage readings * where the voltage is over the neon limit but * does not vary greatly from the last reading */ if (fxo->battery == 1 && abs_voltage > neonmwi_level && (0 == fxo->neonmwi_last_voltage || (b >= fxo->neonmwi_last_voltage - neonmwi_envelope && b <= fxo->neonmwi_last_voltage + neonmwi_envelope ))) { fxo->neonmwi_last_voltage = b; if (NEONMWI_ON_DEBOUNCE == fxo->neonmwi_debounce) { fxo->neonmwi_offcounter = neonmwi_offlimit_cycles; if(0 == fxo->neonmwi_state) { dahdi_qevent_lock(wc->chans[card], DAHDI_EVENT_NEONMWI_ACTIVE); fxo->neonmwi_state = 1; if (debug) printk("NEON MWI active for card %d\n", card+1); } fxo->neonmwi_debounce++; /* terminate the processing */ } else if (NEONMWI_ON_DEBOUNCE > fxo->neonmwi_debounce) { fxo->neonmwi_debounce++; } else { /* Insure the count gets reset */ fxo->neonmwi_offcounter = neonmwi_offlimit_cycles; } } else { fxo->neonmwi_debounce = 0; fxo->neonmwi_last_voltage = 0; } /* If no neon mwi pulse for given period of time, indicte no neon mwi state */ if (fxo->neonmwi_state && 0 < fxo->neonmwi_offcounter ) { fxo->neonmwi_offcounter--; if (0 == fxo->neonmwi_offcounter) { dahdi_qevent_lock(wc->chans[card], DAHDI_EVENT_NEONMWI_INACTIVE); fxo->neonmwi_state = 0; if (debug) printk("NEON MWI cleared for card %d\n", card+1); } } } #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(KERN_DEBUG "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 * DAHDI_CHUNKSIZE; #if 0 printk(KERN_DEBUG "Sustaining hook %d, %d\n", hook, wc->mods[card].fxs.debounce); #endif if (!wc->mods[card].fxs.debounce) { #if 0 printk(KERN_DEBUG "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(KERN_DEBUG "wctdm: Card %d Going off hook\n", card); dahdi_hooksig(wc->chans[card], DAHDI_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(KERN_DEBUG "wctdm: Card %d Going on hook\n", card); dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_ONHOOK); wc->mods[card].fxs.oldrxhook = 0; } } } wc->mods[card].fxs.lastrxhook = hook; } static inline void wctdm_vpm_check(struct wctdm *wc, int x) { if (wc->cmdq[x].isrshadow[0]) { if (debug & DEBUG_ECHOCAN) printk(KERN_DEBUG "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(KERN_DEBUG "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; } } static int echocan_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec) { struct wctdm *wc = chan->pvt; const struct dahdi_echocan_ops *ops; const struct dahdi_echocan_features *features; if (!wc->vpm100 && !wc->vpmadt032) return -ENODEV; if (wc->vpmadt032) { ops = &vpm150m_ec_ops; features = &vpm150m_ec_features; } else { ops = &vpm100m_ec_ops; features = &vpm100m_ec_features; } if (wc->vpm100 && (ecp->param_count > 0)) { printk(KERN_WARNING "%s echo canceller does not support parameters; failing request\n", ops->name); return -EINVAL; } *ec = wc->ec[chan->chanpos - 1]; (*ec)->ops = ops; (*ec)->features = *features; if (wc->vpm100) { int channel; int unit; channel = (chan->chanpos - 1); unit = (chan->chanpos - 1) & 0x3; if (wc->vpm100 < 2) channel >>= 2; if (debug & DEBUG_ECHOCAN) printk(KERN_DEBUG "echocan: Unit is %d, Channel is %d length %d\n", unit, channel, ecp->tap_length); wctdm_vpm_out(wc, unit, channel, 0x3e); return 0; } else if (wc->vpmadt032) { return vpmadt032_echocan_create(wc->vpmadt032, chan->chanpos-1, ecp, p); } else { return -ENODEV; } } static void echocan_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec) { struct wctdm *wc = chan->pvt; memset(ec, 0, sizeof(*ec)); if (wc->vpm100) { int channel; int unit; channel = (chan->chanpos - 1); unit = (chan->chanpos - 1) & 0x3; if (wc->vpm100 < 2) channel >>= 2; if (debug & DEBUG_ECHOCAN) printk(KERN_DEBUG "echocan: Unit is %d, Channel is %d length 0\n", unit, channel); wctdm_vpm_out(wc, unit, channel, 0x01); } else if (wc->vpmadt032) { vpmadt032_echocan_free(wc->vpmadt032, chan, ec); } } 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 = POLARITY_XOR(x) ? 0x6 : 0x2; /* OHT mode when idle */ } else { if (wc->mods[x].fxs.ohttimer) { wc->mods[x].fxs.ohttimer-= DAHDI_CHUNKSIZE; if (!wc->mods[x].fxs.ohttimer) { wc->mods[x].fxs.idletxhookstate = POLARITY_XOR(x) ? 0x5 : 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); /* Data enqueued here */ /* wctdm_setreg_intr(wc, x, 64, wc->mods[x].fxs.lasttxhook); */ } else if (wc->mods[x].fxs.lasttxhook == 0x6) { /* Apply the change if appropriate */ wc->mods[x].fxs.lasttxhook = 0x15; wc->sethook[x] = CMD_WR(64, wc->mods[x].fxs.lasttxhook); /* Data enqueued here */ /* 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); } } } if (wc->vpm100 > 0) { for (x=NUM_CARDS;xrxints++; wctdm_receiveprep(wc, vbb); } static 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(KERN_DEBUG "VoiceDAA System: %02x\n", blah & 0xf); return 0; } static int wctdm_proslic_insane(struct wctdm *wc, int card) { int blah, reg1, insane_report; insane_report=0; blah = wctdm_getreg(wc, card, 0); if (debug & DEBUG_CARD) printk(KERN_DEBUG "ProSLIC on module %d, product %d, version %d\n", card, (blah & 0x30) >> 4, (blah & 0xf)); #if 0 if ((blah & 0x30) >> 4) { printk(KERN_DEBUG "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; } /* let's be really sure this is an FXS before we continue */ reg1 = wctdm_getreg(wc, card, 1); if ((0x80 != (blah & 0xf0)) || (0x88 != reg1)) { if (debug & DEBUG_CARD) printk("DEBUG: not FXS b/c reg0=%x or reg1 != 0x88 (%x).\n", blah, reg1); return -1; } if ((blah & 0xf) < 2) { printk(KERN_INFO "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(KERN_NOTICE "ProSLIC on module %d insane (1) %d should be 2\n", card, blah); return -1; } else if ( insane_report) printk(KERN_NOTICE "ProSLIC on module %d Reg 8 Reads %d Expected is 0x2\n",card,blah); blah = wctdm_getreg(wc, card, 64); if (blah != 0x0) { printk(KERN_NOTICE "ProSLIC on module %d insane (2)\n", card); return -1; } else if ( insane_report) printk(KERN_NOTICE "ProSLIC on module %d Reg 64 Reads %d Expected is 0x0\n",card,blah); blah = wctdm_getreg(wc, card, 11); if (blah != 0x33) { printk(KERN_NOTICE "ProSLIC on module %d insane (3)\n", card); return -1; } else if ( insane_report) printk(KERN_NOTICE "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(KERN_DEBUG "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(KERN_NOTICE "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(KERN_DEBUG "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(KERN_NOTICE "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(KERN_DEBUG "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(KERN_DEBUG "Loop current out of range! Setting to default 20mA!\n"); } else if (debug & DEBUG_CARD) printk(KERN_DEBUG "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(KERN_DEBUG "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(KERN_DEBUG "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(KERN_NOTICE "Timeout waiting for calibration of module %d\n", card); return -1; } } if (debug & DEBUG_CARD) { /* Print calibration parameters */ printk(KERN_DEBUG "Calibration Vector Regs 98 - 107: \n"); for (x=98;x<108;x++) { printk(KERN_DEBUG "%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(KERN_NOTICE "Cannot adjust gain. Unsupported module type!\n"); return -1; } if (tx) { if (debug) printk(KERN_DEBUG "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(KERN_NOTICE "FXO tx gain is out of range (%d)\n", gain); return -1; } } else { /* rx */ if (debug) printk(KERN_DEBUG "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(KERN_NOTICE "FXO rx gain is out of range (%d)\n", gain); return -1; } } return 0; } static int set_vmwi(struct wctdm *wc, int chan_idx) { int x; /* Presently only supports line reversal MWI */ if (wc->mods[chan_idx].fxs.vmwi_active_messages && wc->mods[chan_idx].fxs.vmwisetting.vmwi_type & DAHDI_VMWI_LREV){ wc->mods[chan_idx].fxs.vmwi_linereverse = 1; } else { wc->mods[chan_idx].fxs.vmwi_linereverse = 0; } /* Set line polarity for new VMWI state */ if (POLARITY_XOR(chan_idx)) { wc->mods[chan_idx].fxs.idletxhookstate |= 0x14; /* Do not set while currently ringing or open */ if (wc->mods[chan_idx].fxs.lasttxhook != 0x04 && wc->mods[chan_idx].fxs.lasttxhook != 0x00) { wc->mods[chan_idx].fxs.lasttxhook |= 0x14; wc->sethook[chan_idx] = CMD_WR(64, wc->mods[chan_idx].fxs.lasttxhook); } } else { wc->mods[chan_idx].fxs.idletxhookstate &= ~0x04; /* Do not set while currently ringing or open */ if (wc->mods[chan_idx].fxs.lasttxhook != 0x04 && wc->mods[chan_idx].fxs.lasttxhook != 0x00) { x = wc->mods[chan_idx].fxs.lasttxhook; x &= ~0x04; x |= 0x10; wc->mods[chan_idx].fxs.lasttxhook = x; wc->sethook[chan_idx] = CMD_WR(64, wc->mods[chan_idx].fxs.lasttxhook); } } if (debug) { printk(KERN_DEBUG "Setting VMWI on channel %d, messages=%d, lrev=%d\n", chan_idx, wc->mods[chan_idx].fxs.vmwi_active_messages, wc->mods[chan_idx].fxs.vmwi_linereverse ); } 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 || neonmwi_monitor) { /* 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(KERN_NOTICE "VoiceDAA did not bring up ISO link properly!\n"); return -1; } if (debug & DEBUG_CARD) printk(KERN_DEBUG "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(KERN_DEBUG "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; /* Initialize VMWI settings */ memset(&(wc->mods[card].fxs.vmwisetting), 0, sizeof(wc->mods[card].fxs.vmwisetting)); wc->mods[card].fxs.vmwi_linereverse = 0; /* By default, don't send on hook */ if (!reversepolarity != !wc->mods[card].fxs.reversepolarity) { wc->mods[card].fxs.idletxhookstate = 5; } else { 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(KERN_NOTICE "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(KERN_NOTICE "ProSLIC module %d failed leakage test. Check for short circuit\n", card); } /* Power up again */ if (wctdm_powerup_proslic(wc, card, fast)) { printk(KERN_NOTICE "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(KERN_NOTICE "Proslic failed on Manual Calibration\n"); if (wctdm_proslic_manual_calibrate(wc, card)) { printk(KERN_NOTICE "Proslic Failed on Second Attempt to Calibrate Manually. (Try -DNO_CALIBRATION in Makefile)\n"); return -1; } printk(KERN_INFO "Proslic Passed Manual Calibration on Second Attempt\n"); } } else { if(wctdm_proslic_calibrate(wc, card)) { //printk(KERN_NOTICE "ProSlic died on Auto Calibration.\n"); if (wctdm_proslic_calibrate(wc, card)) { printk(KERN_NOTICE "Proslic Failed on Second Attempt to Auto Calibrate\n"); return -1; } printk(KERN_INFO "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(KERN_NOTICE "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(KERN_INFO "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(KERN_INFO "Reducing fast ring power on slot %d (50V peak)\n", card + 1); } else printk(KERN_INFO "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(KERN_INFO "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(KERN_INFO "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(KERN_DEBUG "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 = wc->mods[card].fxs.idletxhookstate; wctdm_setreg(wc, card, 64, wc->mods[card].fxs.lasttxhook); 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 dahdi_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(KERN_DEBUG "@@@@@ 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(KERN_DEBUG "@@@@@ 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(KERN_DEBUG "@@@@@ 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(KERN_DEBUG "@@@@@ 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(KERN_DEBUG "@@@@@ 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(KERN_DEBUG "@@@@@ 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(KERN_DEBUG "@@@@@ 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(KERN_DEBUG "@@@@@ 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(KERN_DEBUG "@@@@@ setting reg 0x10 to %02x hex\n",(unsigned char)l); return; } static int wctdm_ioctl(struct dahdi_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 dahdi_hwgain hwgain; struct wctdm *wc = chan->pvt; int x; union { struct dahdi_radio_stat s; struct dahdi_radio_param p; } stack; switch (cmd) { case DAHDI_ONHOOKTRANSFER: if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) return -EINVAL; if (get_user(x, (__user 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 || wc->mods[chan->chanpos - 1].fxs.lasttxhook == 0x5) { /* Apply the change if appropriate */ wc->mods[chan->chanpos - 1].fxs.lasttxhook = POLARITY_XOR(chan->chanpos -1) ? 0x16 : 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 DAHDI_VMWI_CONFIG: if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) return -EINVAL; if (copy_from_user(&(wc->mods[chan->chanpos - 1].fxs.vmwisetting), (__user void *) data, sizeof(wc->mods[chan->chanpos - 1].fxs.vmwisetting))) return -EFAULT; set_vmwi(wc, chan->chanpos - 1); break; case DAHDI_VMWI: if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) return -EINVAL; if (get_user(x, (__user int *) data)) return -EFAULT; if (0 > x) return -EFAULT; wc->mods[chan->chanpos - 1].fxs.vmwi_active_messages = x; set_vmwi(wc, chan->chanpos - 1); 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((__user void *) 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((__user void *)data, ®s, sizeof(regs))) return -EFAULT; break; case WCTDM_SET_REG: if (copy_from_user(®op, (__user void *) data, sizeof(regop))) return -EFAULT; if (regop.indirect) { if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) return -EINVAL; printk(KERN_INFO "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(KERN_INFO "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(KERN_INFO "-- Setting echo registers: \n"); if (copy_from_user(&echoregs, (__user void *) 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(KERN_INFO "-- Set echo registers successfully\n"); break; } else { return -EINVAL; } break; case DAHDI_SET_HWGAIN: if (copy_from_user(&hwgain, (__user void *) data, sizeof(hwgain))) return -EFAULT; wctdm_set_hwgain(wc, chan->chanpos-1, hwgain.newgain, hwgain.tx); if (debug) printk(KERN_DEBUG "Setting hwgain on channel %d to %d for %s direction\n", chan->chanpos-1, hwgain.newgain, hwgain.tx ? "tx" : "rx"); break; #ifdef VPM_SUPPORT case DAHDI_TONEDETECT: /* Hardware DTMF detection is not supported. */ return -ENOSYS; #endif case DAHDI_SETPOLARITY: if (get_user(x, (__user int *) data)) return -EFAULT; if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) return -EINVAL; /* Can't change polarity while ringing or when open */ if ((wc->mods[chan->chanpos -1 ].fxs.lasttxhook == 0x04) || (wc->mods[chan->chanpos -1 ].fxs.lasttxhook == 0x00)) return -EINVAL; if (x) { wc->mods[chan->chanpos -1 ].fxs.reversepolarity = 1; } else { wc->mods[chan->chanpos -1 ].fxs.reversepolarity = 0; } if (POLARITY_XOR(chan->chanpos -1)) { wc->mods[chan->chanpos -1 ].fxs.idletxhookstate |= 0x14; wc->mods[chan->chanpos -1 ].fxs.lasttxhook |= 0x14; } else { wc->mods[chan->chanpos -1 ].fxs.idletxhookstate &= ~0x04; x = wc->mods[chan->chanpos -1 ].fxs.lasttxhook; x &= ~0x04; x |= 0x10; wc->mods[chan->chanpos -1 ].fxs.lasttxhook = x; } wc->sethook[chan->chanpos - 1] = CMD_WR(64, wc->mods[chan->chanpos - 1].fxs.lasttxhook); break; case DAHDI_RADIO_GETPARAM: if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_QRV) return -ENOTTY; if (copy_from_user(&stack.p, (__user void *) data, sizeof(stack.p))) return -EFAULT; stack.p.data = 0; /* start with 0 value in output */ switch(stack.p.radpar) { case DAHDI_RADPAR_INVERTCOR: if (wc->radmode[chan->chanpos - 1] & RADMODE_INVERTCOR) stack.p.data = 1; break; case DAHDI_RADPAR_IGNORECOR: if (wc->radmode[chan->chanpos - 1] & RADMODE_IGNORECOR) stack.p.data = 1; break; case DAHDI_RADPAR_IGNORECT: if (wc->radmode[chan->chanpos - 1] & RADMODE_IGNORECT) stack.p.data = 1; break; case DAHDI_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 DAHDI_RADPAR_DEBOUNCETIME: stack.p.data = wc->debouncetime[chan->chanpos - 1]; break; case DAHDI_RADPAR_RXGAIN: stack.p.data = wc->rxgain[chan->chanpos - 1] - 1199; break; case DAHDI_RADPAR_TXGAIN: stack.p.data = wc->txgain[chan->chanpos - 1] - 3599; break; case DAHDI_RADPAR_DEEMP: stack.p.data = 0; if (wc->radmode[chan->chanpos - 1] & RADMODE_DEEMP) { stack.p.data = 1; } break; case DAHDI_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((__user void *) data, &stack.p, sizeof(stack.p))) return -EFAULT; break; case DAHDI_RADIO_SETPARAM: if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_QRV) return -ENOTTY; if (copy_from_user(&stack.p, (__user void *) data, sizeof(stack.p))) return -EFAULT; switch(stack.p.radpar) { case DAHDI_RADPAR_INVERTCOR: if (stack.p.data) wc->radmode[chan->chanpos - 1] |= RADMODE_INVERTCOR; else wc->radmode[chan->chanpos - 1] &= ~RADMODE_INVERTCOR; return 0; case DAHDI_RADPAR_IGNORECOR: if (stack.p.data) wc->radmode[chan->chanpos - 1] |= RADMODE_IGNORECOR; else wc->radmode[chan->chanpos - 1] &= ~RADMODE_IGNORECOR; return 0; case DAHDI_RADPAR_IGNORECT: if (stack.p.data) wc->radmode[chan->chanpos - 1] |= RADMODE_IGNORECT; else wc->radmode[chan->chanpos - 1] &= ~RADMODE_IGNORECT; return 0; case DAHDI_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 DAHDI_RADPAR_DEBOUNCETIME: wc->debouncetime[chan->chanpos - 1] = stack.p.data; return 0; case DAHDI_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 DAHDI_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 DAHDI_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 DAHDI_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 dahdi_chan *chan) { struct wctdm *wc = chan->pvt; int channo = chan->chanpos - 1; unsigned long flags; if (!(wc->cardflag & (1 << (chan->chanpos - 1)))) return -ENODEV; if (wc->dead) return -ENODEV; wc->usecount++; try_module_get(THIS_MODULE); /* Reset the mwi indicators */ spin_lock_irqsave(&wc->reglock, flags); wc->mods[channo].fxo.neonmwi_debounce = 0; wc->mods[channo].fxo.neonmwi_offcounter = 0; wc->mods[channo].fxo.neonmwi_state = 0; spin_unlock_irqrestore(&wc->reglock, flags); return 0; } static int wctdm_watchdog(struct dahdi_span *span, int event) { printk(KERN_INFO "TDM: Called watchdog\n"); return 0; } static int wctdm_close(struct dahdi_chan *chan) { struct wctdm *wc = chan->pvt; int x; signed char reg; wc->usecount--; module_put(THIS_MODULE); for (x=0;xcards;x++) { if (wc->modtype[x] == MOD_TYPE_FXS) { wc->mods[x].fxs.idletxhookstate = POLARITY_XOR(x) ? 5 : 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 dahdi_chan *chan, enum dahdi_txsig 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 DAHDI_TXSIG_START: case DAHDI_TXSIG_OFFHOOK: wc->qrvhook[chan->chanpos - 1] = 1; break; case DAHDI_TXSIG_ONHOOK: wc->qrvhook[chan->chanpos - 1] = 0; break; default: printk(KERN_NOTICE "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 DAHDI_TXSIG_START: case DAHDI_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 DAHDI_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(KERN_NOTICE "wctdm24xxp: Can't set tx state to %d\n", txsig); } } else { switch(txsig) { case DAHDI_TXSIG_ONHOOK: switch(chan->sig) { case DAHDI_SIG_EM: case DAHDI_SIG_FXOKS: case DAHDI_SIG_FXOLS: wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x10 | wc->mods[chan->chanpos - 1].fxs.idletxhookstate; break; case DAHDI_SIG_FXOGS: if (POLARITY_XOR(chan->chanpos -1)) { wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x17; } else { wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x13; } break; } break; case DAHDI_TXSIG_OFFHOOK: switch(chan->sig) { case DAHDI_SIG_EM: if (POLARITY_XOR(chan->chanpos -1)) { wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x11; } else { 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 DAHDI_TXSIG_START: wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x14; break; case DAHDI_TXSIG_KEWL: wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x10; break; default: printk(KERN_NOTICE "wctdm24xxp: Can't set tx state to %d\n", txsig); } if (debug & DEBUG_CARD) printk(KERN_DEBUG "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(KERN_NOTICE "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(KERN_NOTICE "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(KERN_NOTICE "wctdm_dacs_connect: Unsupported modtype for card %d\n", dstcard); return; } if (debug) printk(KERN_DEBUG "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(KERN_DEBUG "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(KERN_WARNING "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(KERN_WARNING "WARNING: wctdm_dacs_disconnect() called on unsupported modtype\n"); } wc->dacssrc[card] = -1; } } static int wctdm_dacs(struct dahdi_chan *dst, struct dahdi_chan *src) { struct wctdm *wc; if(!nativebridge) return 0; /* should this return -1 since unsuccessful? */ wc = dst->pvt; if(src) { wctdm_dacs_connect(wc, src->chanpos - 1, dst->chanpos - 1); if (debug) printk(KERN_DEBUG "dacs connecct: %d -> %d!\n\n", src->chanpos, dst->chanpos); } else { wctdm_dacs_disconnect(wc, dst->chanpos - 1); if (debug) printk(KERN_DEBUG "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); /* DAHDI 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(KERN_INFO "ALAW override parameter detected. Device will be operating in ALAW\n"); wc->span.deflaw = DAHDI_LAW_ALAW; } else { wc->span.deflaw = DAHDI_LAW_MULAW; } for (x=0;xcards;x++) { sprintf(wc->chans[x]->name, "WCTDM/%d/%d", wc->pos, x); wc->chans[x]->sigcap = DAHDI_SIG_FXOKS | DAHDI_SIG_FXOLS | DAHDI_SIG_FXOGS | DAHDI_SIG_SF | DAHDI_SIG_EM | DAHDI_SIG_CLEAR; wc->chans[x]->sigcap |= DAHDI_SIG_FXSKS | DAHDI_SIG_FXSLS | DAHDI_SIG_SF | DAHDI_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 = DAHDI_FLAG_RBS; wc->span.ioctl = wctdm_ioctl; wc->span.watchdog = wctdm_watchdog; wc->span.dacs= wctdm_dacs; #ifdef VPM_SUPPORT if (vpmsupport) wc->span.echocan_create = echocan_create; #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 = DAHDI_SIG_FXSKS | DAHDI_SIG_FXSLS | DAHDI_SIG_SF | DAHDI_SIG_CLEAR; else if (wc->modtype[x] == MOD_TYPE_FXS) wc->chans[x]->sigcap = DAHDI_SIG_FXOKS | DAHDI_SIG_FXOLS | DAHDI_SIG_FXOGS | DAHDI_SIG_SF | DAHDI_SIG_EM | DAHDI_SIG_CLEAR; else if (wc->modtype[x] == MOD_TYPE_QRV) wc->chans[x]->sigcap = DAHDI_SIG_SF | DAHDI_SIG_EM | DAHDI_SIG_CLEAR; } else if (!(wc->chans[x]->sigcap & DAHDI_SIG_BROKEN)) { wc->chans[x]->sigcap = 0; } } if (wc->vpm100) { strncat(wc->span.devicetype, " with VPM100M", sizeof(wc->span.devicetype) - 1); } else if (wc->vpmadt032) { strncat(wc->span.devicetype, " with VPMADT032", sizeof(wc->span.devicetype) - 1); } } static int wctdm_vpm_init(struct wctdm *wc) { unsigned char reg; unsigned int mask; unsigned int ver; unsigned char vpmver=0; unsigned int i, x, y; for (x=0;xvpm100 = 0; return -ENODEV; } if (!x) { vpmver = wctdm_vpm_in(wc, x, 0x1a6) & 0xf; printk(KERN_INFO "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(KERN_INFO "VPM: A-law mode\n"); reg |= 0x01; } else { if (!x) printk(KERN_INFO "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); } /* TODO: What do the different values for vpm100 mean? */ if (vpmver == 0x01) { wc->vpm100 = 2; } else { wc->vpm100 = 1; } printk(KERN_INFO "Enabling VPM100 gain adjustments on any FXO ports found\n"); for (i = 0; i < wc->type; i++) { 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 */ } } return 0; } static void get_default_portconfig(GpakPortConfig_t *portconfig) { memset(portconfig, 0, sizeof(GpakPortConfig_t)); /* First Serial Port config */ portconfig->SlotsSelect1 = SlotCfgNone; portconfig->FirstBlockNum1 = 0; portconfig->FirstSlotMask1 = 0x0000; portconfig->SecBlockNum1 = 1; portconfig->SecSlotMask1 = 0x0000; portconfig->SerialWordSize1 = SerWordSize8; portconfig->CompandingMode1 = cmpNone; portconfig->TxFrameSyncPolarity1 = FrameSyncActHigh; portconfig->RxFrameSyncPolarity1 = FrameSyncActHigh; portconfig->TxClockPolarity1 = SerClockActHigh; portconfig->RxClockPolarity1 = SerClockActHigh; portconfig->TxDataDelay1 = DataDelay0; portconfig->RxDataDelay1 = DataDelay0; portconfig->DxDelay1 = Disabled; portconfig->ThirdSlotMask1 = 0x0000; portconfig->FouthSlotMask1 = 0x0000; portconfig->FifthSlotMask1 = 0x0000; portconfig->SixthSlotMask1 = 0x0000; portconfig->SevenSlotMask1 = 0x0000; portconfig->EightSlotMask1 = 0x0000; /* Second Serial Port config */ portconfig->SlotsSelect2 = SlotCfg2Groups; portconfig->FirstBlockNum2 = 0; portconfig->FirstSlotMask2 = 0xffff; portconfig->SecBlockNum2 = 1; portconfig->SecSlotMask2 = 0xffff; portconfig->SerialWordSize2 = SerWordSize8; portconfig->CompandingMode2 = cmpNone; portconfig->TxFrameSyncPolarity2 = FrameSyncActHigh; portconfig->RxFrameSyncPolarity2 = FrameSyncActHigh; portconfig->TxClockPolarity2 = SerClockActHigh; portconfig->RxClockPolarity2 = SerClockActLow; portconfig->TxDataDelay2 = DataDelay0; portconfig->RxDataDelay2 = DataDelay0; portconfig->DxDelay2 = Disabled; portconfig->ThirdSlotMask2 = 0x0000; portconfig->FouthSlotMask2 = 0x0000; portconfig->FifthSlotMask2 = 0x0000; portconfig->SixthSlotMask2 = 0x0000; portconfig->SevenSlotMask2 = 0x0000; portconfig->EightSlotMask2 = 0x0000; /* Third Serial Port Config */ portconfig->SlotsSelect3 = SlotCfg2Groups; portconfig->FirstBlockNum3 = 0; portconfig->FirstSlotMask3 = 0xffff; portconfig->SecBlockNum3 = 1; portconfig->SecSlotMask3 = 0xffff; portconfig->SerialWordSize3 = SerWordSize8; portconfig->CompandingMode3 = cmpNone; portconfig->TxFrameSyncPolarity3 = FrameSyncActHigh; portconfig->RxFrameSyncPolarity3 = FrameSyncActHigh; portconfig->TxClockPolarity3 = SerClockActHigh; portconfig->RxClockPolarity3 = SerClockActLow; portconfig->TxDataDelay3 = DataDelay0; portconfig->RxDataDelay3 = DataDelay0; portconfig->DxDelay3 = Disabled; portconfig->ThirdSlotMask3 = 0x0000; portconfig->FouthSlotMask3 = 0x0000; portconfig->FifthSlotMask3 = 0x0000; portconfig->SixthSlotMask3 = 0x0000; portconfig->SevenSlotMask3 = 0x0000; portconfig->EightSlotMask3 = 0x0000; } static int wctdm_locate_modules(struct wctdm *wc) { 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; wc->vpm100 = -1; for (x = wc->cards; x < wc->cards+NUM_EC; x++) wc->modtype[x] = MOD_TYPE_VPM; 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(KERN_DEBUG "Proslic module %d loop current is %dmA\n",x, ((readi*3)+20)); } printk(KERN_INFO "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(KERN_DEBUG "Proslic module %d loop current is %dmA\n",x, ((readi*3)+20)); } printk(KERN_INFO "Port %d: Installed -- MANUAL FXS\n",x + 1); } else { printk(KERN_NOTICE "Port %d: FAILED FXS (%s)\n", x + 1, fxshonormode ? fxo_modes[_opermode].name : "FCC"); wc->chans[x]->sigcap = DAHDI_SIG_BROKEN | __DAHDI_SIG_FXO; } } else if (!(ret = wctdm_init_voicedaa(wc, x, 0, 0, sane))) { wc->cardflag |= (1 << x); printk(KERN_INFO "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(KERN_INFO "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(KERN_DEBUG "Trying port %d with alternate chip select\n", x + 1); goto retry; } else { printk(KERN_NOTICE "Port %d: Not installed\n", x + 1); wc->modtype[x] = MOD_TYPE_NONE; wc->cardflag |= (1 << x); } } } } if (!vpmsupport) { printk(KERN_NOTICE "VPM: Support Disabled\n"); } else if (!wctdm_vpm_init(wc)) { printk(KERN_INFO "VPM: Present and operational (Rev %c)\n", 'A' + wc->vpm100 - 1); wc->ctlreg |= 0x10; } else { int res; struct vpmadt032_options options; GpakPortConfig_t portconfig; spin_lock_irqsave(&wc->reglock, flags); for (x = NUM_CARDS; x < NUM_CARDS + NUM_EC; x++) wc->modtype[x] = MOD_TYPE_NONE; spin_unlock_irqrestore(&wc->reglock, flags); options.debug = debug; options.vpmnlptype = vpmnlptype; options.vpmnlpthresh = vpmnlpthresh; options.vpmnlpmaxsupp = vpmnlpmaxsupp; wc->vpmadt032 = vpmadt032_alloc(&options, wc->board_name); if (!wc->vpmadt032) return -ENOMEM; wc->vpmadt032->setchanconfig_from_state = setchanconfig_from_state; wc->vpmadt032->context = wc; wc->vpmadt032->span = &wc->span; get_default_portconfig(&portconfig); res = vpmadt032_init(wc->vpmadt032, wc->vb); /* In case there was an error while we were loading the VPM module. */ if (voicebus_current_latency(wc->vb) > startinglatency) { vpmadt032_free(wc->vpmadt032); wc->vpmadt032 = NULL; return -EAGAIN; } if (res) { vpmadt032_free(wc->vpmadt032); wc->vpmadt032 = NULL; return res; } /* Now we need to configure the VPMADT032 module for this * particular board. */ res = config_vpmadt032(wc->vpmadt032); if (res) { vpmadt032_free(wc->vpmadt032); wc->vpmadt032 = NULL; return res; } printk(KERN_INFO "VPMADT032: Present and operational (Firmware version %x)\n", wc->vpmadt032->version); /* TODO what is 0x10 in this context? */ wc->ctlreg |= 0x10; } return 0; } static struct pci_driver wctdm_driver; static void free_wc(struct wctdm *wc) { unsigned int x; for (x = 0; x < sizeof(wc->chans)/sizeof(wc->chans[0]); x++) { if (wc->chans[x]) { kfree(wc->chans[x]); } if (wc->ec[x]) kfree(wc->ec[x]); } kfree(wc); } 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; neonmwi_offlimit_cycles = neonmwi_offlimit /MS_PER_HOOKCHECK; retry: if (!(wc = kmalloc(sizeof(*wc), GFP_KERNEL))) { 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, debug, &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); for (i = 0; i < wc->cards; i++) { if (!(wc->chans[i] = kmalloc(sizeof(*wc->chans[i]), GFP_KERNEL))) { free_wc(wc); return -ENOMEM; } memset(wc->chans[i], 0, sizeof(*wc->chans[i])); if (!(wc->ec[i] = kmalloc(sizeof(*wc->ec[i]), GFP_KERNEL))) { free_wc(wc); return -ENOMEM; } memset(wc->ec[i], 0, sizeof(*wc->ec[i])); } 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 DAHDI to come in now. */ if (dahdi_register(&wc->span, 0)) { printk(KERN_NOTICE "Unable to register span with DAHDI\n"); return -1; } wc->initialized = 1; printk(KERN_INFO "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) { dahdi_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); free_wc(wc); } static void __devexit wctdm_remove_one(struct pci_dev *pdev) { struct wctdm *wc = pci_get_drvdata(pdev); struct vpmadt032 *vpm = wc->vpmadt032; if (wc) { if (vpm) { clear_bit(VPM150M_DTMFDETECT, &vpm->control); clear_bit(VPM150M_ACTIVE, &vpm->control); flush_scheduled_work(); } voicebus_stop(wc->vb); if (vpm) { vpmadt032_free(wc->vpmadt032); wc->vpmadt032 = NULL; } /* Release span, possibly delayed */ if (!wc->usecount) { wctdm_release(wc); printk(KERN_INFO "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, .remove = __devexit_p(wctdm_remove_one), .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(KERN_NOTICE "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(KERN_NOTICE " %s\n", fxo_modes[x].name); printk(KERN_NOTICE "Note this option is CASE SENSITIVE!\n"); return -ENODEV; } if (!strcmp(opermode, "AUSTRALIA")) { boostringer = 1; fxshonormode = 1; } /* 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 = dahdi_pci_module(&wctdm_driver); if (res) return -ENODEV; return 0; } static void __exit wctdm_cleanup(void) { pci_unregister_driver(&wctdm_driver); } module_param(debug, int, 0600); module_param(fxovoltage, int, 0600); module_param(loopcurrent, int, 0600); module_param(reversepolarity, 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); module_param(neonmwi_monitor, int, 0600); module_param(neonmwi_level, int, 0600); module_param(neonmwi_envelope, int, 0600); module_param(neonmwi_offlimit, int, 0600); #ifdef VPM_SUPPORT module_param(vpmsupport, int, 0600); module_param(vpmnlptype, int, 0600); module_param(vpmnlpthresh, int, 0600); module_param(vpmnlpmaxsupp, int, 0600); #endif MODULE_DESCRIPTION("Wildcard VoiceBus Analog Card Driver"); MODULE_AUTHOR("Digium Incorporated "); MODULE_ALIAS("wctdm8xxp"); MODULE_ALIAS("wctdm4xxp"); MODULE_ALIAS("wcaex24xx"); MODULE_ALIAS("wcaex8xx"); MODULE_ALIAS("wcaex8xx"); MODULE_LICENSE("GPL v2"); module_init(wctdm_init); module_exit(wctdm_cleanup); dahdi-linux-2.2.0-rc4/drivers/dahdi/wctdm24xxp/Kbuild0000644000175000017500000000020511176111367021562 0ustar maniacmaniacobj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTDM24XXP) += wctdm24xxp.o EXTRA_CFLAGS += -I$(src)/.. -Wno-undef wctdm24xxp-objs := base.o dahdi-linux-2.2.0-rc4/drivers/dahdi/wctdm24xxp/wctdm24xxp.h0000644000175000017500000001342011176115504022622 0ustar maniacmaniac/* * Wildcard TDM2400P TDM FXS/FXO Interface Driver for DAHDI Telephony interface * * Written by Mark Spencer * Support for TDM800P and VPM150M by Matthew Fredrickson * * Copyright (C) 2005-2009 Digium, Inc. * * All rights reserved. * */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ #ifndef _WCTDM24XXP_H #define _WCTDM24XXP_H #include #include #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) #include #else #include #endif #include "voicebus/voicebus.h" #define NUM_FXO_REGS 60 #define WC_MAX_IFACES 128 /*! * \brief Default ringer debounce (in ms) */ #define DEFAULT_RING_DEBOUNCE 1024 #define POLARITY_DEBOUNCE 64 /* Polarity debounce (in ms) */ #define OHT_TIMER 6000 /* How long after RING to retain OHT */ #define FLAG_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 * DAHDI_CHUNKSIZE) + (EFRAME_GAP * (DAHDI_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 __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_HPI_CONTROL 0x00 #define VPM150M_HPI_ADDRESS 0x02 #define VPM150M_HPI_DATA 0x03 #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 "voicebus/GpakCust.h" #endif 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 dahdi_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 lastrdtx_count; int ringdebounce; int offhook; int battdebounce; int battalarm; enum battery_state battery; int lastpol; int polarity; int polaritydebounce; int neonmwi_state; int neonmwi_last_voltage; unsigned int neonmwi_debounce; unsigned int neonmwi_offcounter; } fxo; struct fxs { int oldrxhook; int debouncehook; int lastrxhook; int debounce; int ohttimer; int idletxhookstate; /* IDLE changing hook state */ int lasttxhook; /* Bits 0-3 are written to proslic reg 64, Bit 4 indicates if the last write is pending */ int palarms; struct dahdi_vmwi_info vmwisetting; int vmwi_active_messages; int vmwi_linereverse; int reversepolarity; /* polarity reversal */ 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]; /* Type is the maximum number of FXO/FXS ports supported */ int type; int vpm100; unsigned long dtmfactive; unsigned long dtmfmask; unsigned long dtmfmutemask; short dtmfenergy[NUM_CARDS]; short dtmfdigit[NUM_CARDS]; struct vpmadt032 *vpmadt032; #ifdef FANCY_ECHOCAN int echocanpos; int blinktimer; #endif struct voicebus *vb; struct dahdi_chan *chans[NUM_CARDS]; struct dahdi_echocan_state *ec[NUM_CARDS]; int initialized; }; int schluffen(wait_queue_head_t *q); extern spinlock_t ifacelock; extern struct wctdm *ifaces[WC_MAX_IFACES]; #endif dahdi-linux-2.2.0-rc4/drivers/dahdi/digits.h0000644000175000017500000000233711046164220020035 0ustar maniacmaniac/* * DAHDI Telephony * */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ #ifndef _DIGITS_H #define _DIGITS_H #define DEFAULT_DTMF_LENGTH 100 * DAHDI_CHUNKSIZE #define DEFAULT_MFR1_LENGTH 68 * DAHDI_CHUNKSIZE #define DEFAULT_MFR2_LENGTH 100 * DAHDI_CHUNKSIZE #define PAUSE_LENGTH 500 * DAHDI_CHUNKSIZE /* At the end of silence, the tone stops */ static struct dahdi_tone dtmf_silence = { .tonesamples = DEFAULT_DTMF_LENGTH, }; /* At the end of silence, the tone stops */ static struct dahdi_tone mfr1_silence = { .tonesamples = DEFAULT_MFR1_LENGTH, }; /* At the end of silence, the tone stops */ static struct dahdi_tone mfr2_silence = { .tonesamples = DEFAULT_MFR2_LENGTH, }; /* A pause in the dialing */ static struct dahdi_tone tone_pause = { .tonesamples = PAUSE_LENGTH, }; #endif dahdi-linux-2.2.0-rc4/drivers/dahdi/dahdi_echocan_sec2.c0000644000175000017500000002465211176115504022223 0ustar maniacmaniac/* * SpanDSP - a series of DSP components for telephony * * echo.c - An echo cancellor, suitable for electrical and acoustic * cancellation. This code does not currently comply with * any relevant standards (e.g. G.164/5/7/8). One day.... * * Written by Steve Underwood * * Copyright (C) 2001 Steve Underwood * * Based on a bit from here, a bit from there, eye of toad, * ear of bat, etc - plus, of course, my own 2 cents. * * All rights reserved. * */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ /* TODO: Finish the echo suppressor option, however nasty suppression may be Add an option to reintroduce side tone at -24dB under appropriate conditions. Improve double talk detector (iterative!) */ #include #include #include #include #include #include #include #include static int debug; #define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args) #define debug_printk(level, fmt, args...) if (debug >= level) printk(KERN_DEBUG "%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args) #include "fir.h" #ifndef NULL #define NULL 0 #endif #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE (!FALSE) #endif #define NONUPDATE_DWELL_TIME 600 /* 600 samples, or 75ms */ /* * According to Jim... */ #define MIN_TX_POWER_FOR_ADAPTION 512 #define MIN_RX_POWER_FOR_ADAPTION 64 /* * According to Steve... */ /* #define MIN_TX_POWER_FOR_ADAPTION 4096 #define MIN_RX_POWER_FOR_ADAPTION 64 */ static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec); static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec); static void echo_can_process(struct dahdi_echocan_state *ec, short *isig, const short *iref, u32 size); static int echo_can_traintap(struct dahdi_echocan_state *ec, int pos, short val); static const struct dahdi_echocan_factory my_factory = { .name = "SEC2", .owner = THIS_MODULE, .echocan_create = echo_can_create, }; static const struct dahdi_echocan_ops my_ops = { .name = "SEC2", .echocan_free = echo_can_free, .echocan_process = echo_can_process, .echocan_traintap = echo_can_traintap, }; struct ec_pvt { struct dahdi_echocan_state dahdi; int tx_power; int rx_power; int clean_rx_power; int rx_power_threshold; int nonupdate_dwell; fir16_state_t fir_state; int16_t *fir_taps16; /* 16-bit version of FIR taps */ int32_t *fir_taps32; /* 32-bit version of FIR taps */ int curr_pos; int taps; int tap_mask; int use_nlp; int use_suppressor; int32_t supp_test1; int32_t supp_test2; int32_t supp1; int32_t supp2; int32_t latest_correction; /* Indication of the magnitude of the latest adaption, or a code to indicate why adaption was skipped, for test purposes */ }; #define dahdi_to_pvt(a) container_of(a, struct ec_pvt, dahdi) static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec) { struct ec_pvt *pvt; size_t size; if (ecp->param_count > 0) { printk(KERN_WARNING "SEC2 does not support parameters; failing request\n"); return -EINVAL; } size = sizeof(*pvt) + ecp->tap_length * sizeof(int32_t) + ecp->tap_length * 3 * sizeof(int16_t); pvt = kzalloc(size, GFP_KERNEL); if (!pvt) return -ENOMEM; pvt->dahdi.ops = &my_ops; if (ecp->param_count > 0) { printk(KERN_WARNING "SEC-2 echo canceler does not support parameters; failing request\n"); return -EINVAL; } pvt->taps = ecp->tap_length; pvt->curr_pos = ecp->tap_length - 1; pvt->tap_mask = ecp->tap_length - 1; pvt->fir_taps32 = (int32_t *) (pvt + sizeof(*pvt)); pvt->fir_taps16 = (int16_t *) (pvt + sizeof(*pvt) + ecp->tap_length * sizeof(int32_t)); /* Create FIR filter */ fir16_create(&pvt->fir_state, pvt->fir_taps16, pvt->taps); pvt->rx_power_threshold = 10000000; pvt->use_suppressor = FALSE; /* Non-linear processor - a fancy way to say "zap small signals, to avoid accumulating noise". */ pvt->use_nlp = FALSE; *ec = &pvt->dahdi; return 0; } static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec) { struct ec_pvt *pvt = dahdi_to_pvt(ec); fir16_free(&pvt->fir_state); kfree(pvt); } static inline int16_t sample_update(struct ec_pvt *pvt, int16_t tx, int16_t rx) { int offset1; int offset2; int32_t echo_value; int clean_rx; int nsuppr; int i; int correction; /* Evaluate the echo - i.e. apply the FIR filter */ /* Assume the gain of the FIR does not exceed unity. Exceeding unity would seem like a rather poor thing for an echo cancellor to do :) This means we can compute the result with a total disregard for overflows. 16bits x 16bits -> 31bits, so no overflow can occur in any multiply. While accumulating we may overflow and underflow the 32 bit scale often. However, if the gain does not exceed unity, everything should work itself out, and the final result will be OK, without any saturation logic. */ /* Overflow is very much possible here, and we do nothing about it because of the compute costs */ /* 16 bit coeffs for the LMS give lousy results (maths good, actual sound bad!), but 32 bit coeffs require some shifting. On balance 32 bit seems best */ echo_value = fir16 (&pvt->fir_state, tx); /* And the answer is..... */ clean_rx = rx - echo_value; /* That was the easy part. Now we need to adapt! */ if (pvt->nonupdate_dwell > 0) pvt->nonupdate_dwell--; /* If there is very little being transmitted, any attempt to train is futile. We would either be training on the far end's noise or signal, the channel's own noise, or our noise. Either way, this is hardly good training, so don't do it (avoid trouble). */ /* If the received power is very low, either we are sending very little or we are already well adapted. There is little point in trying to improve the adaption under these circumstanceson, so don't do it (reduce the compute load). */ if (pvt->tx_power > MIN_TX_POWER_FOR_ADAPTION && pvt->rx_power > MIN_RX_POWER_FOR_ADAPTION) { /* This is a really crude piece of decision logic, but it does OK for now. */ if (pvt->tx_power > 2*pvt->rx_power) { /* There is no far-end speech detected */ if (pvt->nonupdate_dwell == 0) { /* ... and we are not in the dwell time from previous speech. */ /* nsuppr = saturate((clean_rx << 16)/pvt->tx_power); */ nsuppr = clean_rx >> 3; /* Update the FIR taps */ offset2 = pvt->curr_pos + 1; offset1 = pvt->taps - offset2; pvt->latest_correction = 0; for (i = pvt->taps - 1; i >= offset1; i--) { correction = pvt->fir_state.history[i - offset1]*nsuppr; /* Leak to avoid false training on signals with multiple strong correlations. */ pvt->fir_taps32[i] -= (pvt->fir_taps32[i] >> 12); pvt->fir_taps32[i] += correction; pvt->fir_state.coeffs[i] = pvt->fir_taps32[i] >> 15; pvt->latest_correction += abs(correction); } for ( ; i >= 0; i--) { correction = pvt->fir_state.history[i + offset2]*nsuppr; /* Leak to avoid false training on signals with multiple strong correlations. */ pvt->fir_taps32[i] -= (pvt->fir_taps32[i] >> 12); pvt->fir_taps32[i] += correction; pvt->fir_state.coeffs[i] = pvt->fir_taps32[i] >> 15; pvt->latest_correction += abs(correction); } } else { pvt->latest_correction = -1; } } else { pvt->nonupdate_dwell = NONUPDATE_DWELL_TIME; pvt->latest_correction = -2; } } else { pvt->nonupdate_dwell = 0; pvt->latest_correction = -3; } /* Calculate short term power levels using very simple single pole IIRs */ /* TODO: Is the nasty modulus approach the fastest, or would a real tx*tx power calculation actually be faster? */ pvt->tx_power += ((abs(tx) - pvt->tx_power) >> 5); pvt->rx_power += ((abs(rx) - pvt->rx_power) >> 5); pvt->clean_rx_power += ((abs(clean_rx) - pvt->clean_rx_power) >> 5); #if defined(XYZZY) if (pvt->use_suppressor) { pvt->supp_test1 += (pvt->fir_state.history[pvt->curr_pos] - pvt->fir_state.history[(pvt->curr_pos - 7) & pvt->tap_mask]); pvt->supp_test2 += (pvt->fir_state.history[(pvt->curr_pos - 24) & pvt->tap_mask] - pvt->fir_state.history[(pvt->curr_pos - 31) & pvt->tap_mask]); if (pvt->supp_test1 > 42 && pvt->supp_test2 > 42) supp_change = 25; else supp_change = 50; supp = supp_change + k1*pvt->supp1 + k2*pvt->supp2; pvt->supp2 = pvt->supp1; pvt->supp1 = supp; clean_rx *= (1 - supp); } #endif if (pvt->use_nlp && pvt->rx_power < 32) clean_rx = 0; /* Roll around the rolling buffer */ if (pvt->curr_pos <= 0) pvt->curr_pos = pvt->taps; pvt->curr_pos--; return clean_rx; } static void echo_can_process(struct dahdi_echocan_state *ec, short *isig, const short *iref, u32 size) { struct ec_pvt *pvt = dahdi_to_pvt(ec); u32 x; short result; for (x = 0; x < size; x++) { result = sample_update(pvt, *iref, *isig); *isig++ = result; ++iref; } } static int echo_can_traintap(struct dahdi_echocan_state *ec, int pos, short val) { struct ec_pvt *pvt = dahdi_to_pvt(ec); /* Reset hang counter to avoid adjustments after initial forced training */ pvt->nonupdate_dwell = pvt->taps << 1; if (pos >= pvt->taps) return 1; pvt->fir_taps32[pos] = val << 17; pvt->fir_taps16[pos] = val << 1; if (++pos >= pvt->taps) return 1; else return 0; } static int __init mod_init(void) { if (dahdi_register_echocan_factory(&my_factory)) { module_printk(KERN_ERR, "could not register with DAHDI core\n"); return -EPERM; } module_printk(KERN_NOTICE, "Registered echo canceler '%s'\n", my_factory.name); return 0; } static void __exit mod_exit(void) { dahdi_unregister_echocan_factory(&my_factory); } module_param(debug, int, S_IRUGO | S_IWUSR); MODULE_DESCRIPTION("DAHDI 'SEC2' Echo Canceler"); MODULE_AUTHOR("Steve Underwood "); MODULE_LICENSE("GPL"); module_init(mod_init); module_exit(mod_exit); dahdi-linux-2.2.0-rc4/drivers/dahdi/wctdm.c0000644000175000017500000022523611137622260017674 0ustar maniacmaniac/* * Wildcard TDM400P TDM FXS/FXO Interface Driver for DAHDI Telephony interface * * Written by Mark Spencer * Matthew Fredrickson * * Copyright (C) 2001-2008, Digium, Inc. * * All rights reserved. * */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ #include #include #include #include #include #include #include #include #include #include "proslic.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; #define POLARITY_XOR(card) ((reversepolarity!=0) ^ (wc->mod[(card)].fxs.reversepolarity!=0) ^ (wc->mod[(card)].fxs.vmwi_lrev!=0)) static int reversepolarity = 0; static alpha indirect_regs[] = { {0,255,"DTMF_ROW_0_PEAK",0x55C2}, {1,255,"DTMF_ROW_1_PEAK",0x51E6}, {2,255,"DTMF_ROW2_PEAK",0x4B85}, {3,255,"DTMF_ROW3_PEAK",0x4937}, {4,255,"DTMF_COL1_PEAK",0x3333}, {5,255,"DTMF_FWD_TWIST",0x0202}, {6,255,"DTMF_RVS_TWIST",0x0202}, {7,255,"DTMF_ROW_RATIO_TRES",0x0198}, {8,255,"DTMF_COL_RATIO_TRES",0x0198}, {9,255,"DTMF_ROW_2ND_ARM",0x0611}, {10,255,"DTMF_COL_2ND_ARM",0x0202}, {11,255,"DTMF_PWR_MIN_TRES",0x00E5}, {12,255,"DTMF_OT_LIM_TRES",0x0A1C}, {13,0,"OSC1_COEF",0x7B30}, {14,1,"OSC1X",0x0063}, {15,2,"OSC1Y",0x0000}, {16,3,"OSC2_COEF",0x7870}, {17,4,"OSC2X",0x007D}, {18,5,"OSC2Y",0x0000}, {19,6,"RING_V_OFF",0x0000}, {20,7,"RING_OSC",0x7EF0}, {21,8,"RING_X",0x0160}, {22,9,"RING_Y",0x0000}, {23,255,"PULSE_ENVEL",0x2000}, {24,255,"PULSE_X",0x2000}, {25,255,"PULSE_Y",0x0000}, //{26,13,"RECV_DIGITAL_GAIN",0x4000}, // playback volume set lower {26,13,"RECV_DIGITAL_GAIN",0x2000}, // playback volume set lower {27,14,"XMIT_DIGITAL_GAIN",0x4000}, //{27,14,"XMIT_DIGITAL_GAIN",0x2000}, {28,15,"LOOP_CLOSE_TRES",0x1000}, {29,16,"RING_TRIP_TRES",0x3600}, {30,17,"COMMON_MIN_TRES",0x1000}, {31,18,"COMMON_MAX_TRES",0x0200}, {32,19,"PWR_ALARM_Q1Q2",0x07C0}, {33,20,"PWR_ALARM_Q3Q4",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 #include #include "fxo_modes.h" #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 dahdi_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; int reversepolarity; /* Reverse Line */ int mwisendtype; struct dahdi_vmwi_info vmwisetting; int vmwi_active_messages; int vmwi_lrev:1; /* MWI Line Reversal*/ int vmwi_hvdc:1; /* MWI High Voltage DC Idle line */ int vmwi_hvac:1; /* MWI Neon High Voltage AC Idle line */ 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 dahdi_chan _chans[NUM_CARDS]; struct dahdi_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 fxovoltage; 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 + DAHDI_CHUNKSIZE; /* Calculate Transmission */ dahdi_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 += DAHDI_CHUNKSIZE; for (x=0;xchans[card].readchunk[x], (&(wc->chans[card]))); if ((sample > 10000) && (wc->mod[card].fxo.peg != 1)) { if (debug > 1) printk(KERN_DEBUG "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(KERN_DEBUG "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(KERN_DEBUG "RING on %d/%d!\n", wc->span.spanno, card + 1); if (!wc->mod[card].fxo.offhook) dahdi_hooksig(&wc->chans[card], DAHDI_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(KERN_DEBUG "NO RING on %d/%d!\n", wc->span.spanno, card + 1); dahdi_hooksig(&wc->chans[card], DAHDI_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 + DAHDI_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)) dahdi_ec_chunk(wc->chans[x], wc->chans[x]->readchunk, wc->chans[x]->writechunk); } dahdi_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(KERN_NOTICE " ##### 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(KERN_NOTICE "%s", 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(KERN_NOTICE "!!!!!!! %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(KERN_DEBUG "Init Indirect Registers completed successfully.\n"); } else { printk(KERN_NOTICE " !!!!! 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(KERN_NOTICE "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(KERN_NOTICE "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(KERN_NOTICE "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 errors = 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(KERN_DEBUG "Error (%02x) on card %d!\n", b, card + 1); errors++; } 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 (errors) return; if (!fxo->offhook) { if (fwringdetect) { res = wc->reg0shadow[card] & 0x60; if (fxo->ringdebounce) { --fxo->ringdebounce; if (res && (res != fxo->lastrdtx) && (fxo->battery == BATTERY_PRESENT)) { if (!fxo->wasringing) { fxo->wasringing = 1; if (debug) printk(KERN_DEBUG "RING on %d/%d!\n", wc->span.spanno, card + 1); dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_RING); } fxo->lastrdtx = res; fxo->ringdebounce = 10; } else if (!res) { if ((fxo->ringdebounce == 0) && fxo->wasringing) { fxo->wasringing = 0; if (debug) printk(KERN_DEBUG "NO RING on %d/%d!\n", wc->span.spanno, card + 1); dahdi_hooksig(wc->chans[card], DAHDI_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 += (DAHDI_CHUNKSIZE * 16); if (fxo->ringdebounce >= DAHDI_CHUNKSIZE * ringdebounce) { if (!fxo->wasringing) { fxo->wasringing = 1; dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_RING); if (debug) printk(KERN_DEBUG "RING on %d/%d!\n", wc->span.spanno, card + 1); } fxo->ringdebounce = DAHDI_CHUNKSIZE * ringdebounce; } } else { fxo->ringdebounce -= DAHDI_CHUNKSIZE * 4; if (fxo->ringdebounce <= 0) { if (fxo->wasringing) { fxo->wasringing = 0; dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_OFFHOOK); if (debug) printk(KERN_DEBUG "NO RING on %d/%d!\n", wc->span.spanno, card + 1); } fxo->ringdebounce = 0; } } } } b = wc->reg1shadow[card]; if (fxovoltage) { static int count = 0; if (!(count++ % 100)) { printk(KERN_DEBUG "Card %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(KERN_DEBUG "NO BATTERY on %d/%d!\n", wc->span.spanno, card + 1); #ifdef JAPAN if (!wc->ohdebounce && wc->offhook) { dahdi_hooksig(&wc->chans[card], DAHDI_RXSIG_ONHOOK); if (debug) printk(KERN_DEBUG "Signalled On Hook\n"); #ifdef ZERO_BATT_RING wc->onhook++; #endif } #else dahdi_hooksig(wc->chans[card], DAHDI_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(KERN_DEBUG "BATTERY on %d/%d (%s)!\n", wc->span.spanno, card + 1, (b < 0) ? "-" : "+"); #ifdef ZERO_BATT_RING if (wc->onhook) { wc->onhook = 0; dahdi_hooksig(&wc->chans[card], DAHDI_RXSIG_OFFHOOK); if (debug) printk(KERN_DEBUG "Signalled Off Hook\n"); } #else dahdi_hooksig(wc->chans[card], DAHDI_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 */ dahdi_alarm_channel(wc->chans[card], fxo->battery == BATTERY_LOST ? DAHDI_ALARM_RED : DAHDI_ALARM_NONE); } } if (fxo->polaritydebounce) { if (--fxo->polaritydebounce == 0) { if (fxo->lastpol != fxo->polarity) { if (debug) printk(KERN_DEBUG "%lu Polarity reversed (%d -> %d)\n", jiffies, fxo->polarity, fxo->lastpol); if (fxo->polarity) dahdi_qevent_lock(wc->chans[card], DAHDI_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(KERN_DEBUG "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 * DAHDI_CHUNKSIZE; #if 0 printk(KERN_DEBUG "Sustaining hook %d, %d\n", hook, wc->mod[card].fxs.debounce); #endif if (!wc->mod[card].fxs.debounce) { #if 0 printk(KERN_DEBUG "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(KERN_DEBUG "wctdm: Card %d Going off hook\n", card); dahdi_hooksig(wc->chans[card], DAHDI_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(KERN_DEBUG "wctdm: Card %d Going on hook\n", card); dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_ONHOOK); wc->mod[card].fxs.oldrxhook = 0; } } } wc->mod[card].fxs.lastrxhook = hook; } DAHDI_IRQ_HANDLER(wctdm_interrupt) { struct wctdm *wc = dev_id; unsigned char ints; int x; int mode; ints = inb(wc->ioaddr + WC_INTSTAT); if (!ints) return IRQ_NONE; outb(ints, wc->ioaddr + WC_INTSTAT); if (ints & 0x10) { /* Stop DMA, wait for watchdog */ printk(KERN_INFO "TDM PCI Master abort\n"); wctdm_stop_dma(wc); return IRQ_RETVAL(1); } if (ints & 0x20) { printk(KERN_INFO "PCI Target abort\n"); return IRQ_RETVAL(1); } 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; /* logical XOR 3 variables module parameter 'reversepolarity', global reverse all FXS lines. ioctl channel variable fxs 'reversepolarity', Line Reversal Alert Signal if required. ioctl channel variable fxs 'vmwi_lrev', VMWI pending. */ wc->mod[x].fxs.idletxhookstate = POLARITY_XOR(x) ? 0x6 : 0x2;/* OHT mode when idle */ } else { if (wc->mod[x].fxs.ohttimer) { wc->mod[x].fxs.ohttimer-= DAHDI_CHUNKSIZE; if (!wc->mod[x].fxs.ohttimer) { wc->mod[x].fxs.idletxhookstate = POLARITY_XOR(x) ? 0x5 : 0x1; /* Switch to Active : Reverse Forward */ if ((wc->mod[x].fxs.lasttxhook == 0x2) || (wc->mod[x].fxs.lasttxhook == 0x6)) { /* Apply the change if appropriate */ wc->mod[x].fxs.lasttxhook = POLARITY_XOR(x) ? 0x5 : 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); } return IRQ_RETVAL(1); } 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(KERN_DEBUG "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(KERN_DEBUG "ProSLIC on module %d, product %d, version %d\n", card, (blah & 0x30) >> 4, (blah & 0xf)); #if 0 if ((blah & 0x30) >> 4) { printk(KERN_DEBUG "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(KERN_NOTICE "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(KERN_NOTICE "ProSLIC on module %d insane (1) %d should be 2\n", card, blah); return -1; } else if ( insane_report) printk(KERN_NOTICE "ProSLIC on module %d Reg 8 Reads %d Expected is 0x2\n",card,blah); blah = wctdm_getreg(wc, card, 64); if (blah != 0x0) { printk(KERN_NOTICE "ProSLIC on module %d insane (2)\n", card); return -1; } else if ( insane_report) printk(KERN_NOTICE "ProSLIC on module %d Reg 64 Reads %d Expected is 0x0\n",card,blah); blah = wctdm_getreg(wc, card, 11); if (blah != 0x33) { printk(KERN_NOTICE "ProSLIC on module %d insane (3)\n", card); return -1; } else if ( insane_report) printk(KERN_NOTICE "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(KERN_DEBUG "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(KERN_NOTICE "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(KERN_NOTICE "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(KERN_NOTICE "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(KERN_DEBUG "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(KERN_DEBUG "Loop current out of range! Setting to default 20mA!\n"); } else if (debug) printk(KERN_DEBUG "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(KERN_DEBUG "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(KERN_DEBUG "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(KERN_NOTICE "Timeout waiting for calibration of module %d\n", card); return -1; } } if (debug) { /* Print calibration parameters */ printk(KERN_DEBUG "Calibration Vector Regs 98 - 107: \n"); for (x=98;x<108;x++) { printk(KERN_DEBUG "%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(KERN_NOTICE "Cannot adjust gain. Unsupported module type!\n"); return -1; } if (tx) { if (debug) printk(KERN_DEBUG "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(KERN_INFO "FXO tx gain is out of range (%d)\n", gain); return -1; } } else { /* rx */ if (debug) printk(KERN_DEBUG "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(KERN_INFO "FXO rx gain is out of range (%d)\n", gain); return -1; } } return 0; } static int set_vmwi(struct wctdm * wc, int chan_idx) { if (wc->mod[chan_idx].fxs.vmwi_active_messages){ wc->mod[chan_idx].fxs.vmwi_lrev = (wc->mod[chan_idx].fxs.vmwisetting.vmwi_type & DAHDI_VMWI_LREV)?1:0; wc->mod[chan_idx].fxs.vmwi_hvdc = (wc->mod[chan_idx].fxs.vmwisetting.vmwi_type & DAHDI_VMWI_HVDC)?1:0; wc->mod[chan_idx].fxs.vmwi_hvac = (wc->mod[chan_idx].fxs.vmwisetting.vmwi_type & DAHDI_VMWI_HVAC)?1:0; } else { wc->mod[chan_idx].fxs.vmwi_lrev = 0; wc->mod[chan_idx].fxs.vmwi_hvdc = 0; wc->mod[chan_idx].fxs.vmwi_hvac = 0; } if (debug) { printk(KERN_DEBUG "Setting VMWI on channel %d, messages=%d, lrev=%d, hvdc=%d, hvac=%d\n", chan_idx, wc->mod[chan_idx].fxs.vmwi_active_messages, wc->mod[chan_idx].fxs.vmwi_lrev, wc->mod[chan_idx].fxs.vmwi_hvdc, wc->mod[chan_idx].fxs.vmwi_hvac ); } if (POLARITY_XOR(chan_idx)) { wc->mod[chan_idx].fxs.idletxhookstate |= 0x4; /* Do not set while currently ringing or open */ if (wc->mod[chan_idx].fxs.lasttxhook != 0x04 && wc->mod[chan_idx ].fxs.lasttxhook != 0x00) { wc->mod[chan_idx ].fxs.lasttxhook |= 0x4; wctdm_setreg(wc, chan_idx, 64, wc->mod[chan_idx].fxs.lasttxhook); } } else { wc->mod[chan_idx].fxs.idletxhookstate &= ~0x04; /* Do not set while currently ringing or open */ if (wc->mod[chan_idx].fxs.lasttxhook != 0x04 && wc->mod[chan_idx].fxs.lasttxhook != 0x00) { wc->mod[chan_idx].fxs.lasttxhook &= ~0x04; wctdm_setreg(wc, chan_idx, 64, wc->mod[chan_idx].fxs.lasttxhook); } } 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(KERN_NOTICE "VoiceDAA did not bring up ISO link properly!\n"); return -1; } if (debug) printk(KERN_DEBUG "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(KERN_INFO "Adjusting gain\n"); wctdm_set_hwgain(wc, card, 7, 1); } if(debug) printk(KERN_DEBUG "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; /* default messages to none and method to FSK */ memset(&wc->mod[card].fxs.vmwisetting, 0, sizeof(wc->mod[card].fxs.vmwisetting)); wc->mod[card].fxs.vmwi_lrev = 0; wc->mod[card].fxs.vmwi_hvdc = 0; wc->mod[card].fxs.vmwi_hvac = 0; /* By default, don't send on hook */ if (!reversepolarity != !wc->mod[card].fxs.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(KERN_NOTICE "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(KERN_NOTICE "ProSLIC module %d failed leakage test. Check for short circuit\n", card); } /* Power up again */ if (wctdm_powerup_proslic(wc, card, fast)) { printk(KERN_NOTICE "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(KERN_NOTICE "Proslic failed on Manual Calibration\n"); if (wctdm_proslic_manual_calibrate(wc, card)) { printk(KERN_NOTICE "Proslic Failed on Second Attempt to Calibrate Manually. (Try -DNO_CALIBRATION in Makefile)\n"); return -1; } printk(KERN_NOTICE "Proslic Passed Manual Calibration on Second Attempt\n"); } } else { if(wctdm_proslic_calibrate(wc, card)) { //printk(KERN_NOTICE "ProSlic died on Auto Calibration.\n"); if (wctdm_proslic_calibrate(wc, card)) { printk(KERN_NOTICE "Proslic Failed on Second Attempt to Auto Calibrate\n"); return -1; } printk(KERN_NOTICE "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(KERN_NOTICE "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(KERN_INFO "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(KERN_INFO "Reducing fast ring power on slot %d (50V peak)\n", card + 1); } else printk(KERN_INFO "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(KERN_INFO "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(KERN_INFO "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(KERN_DEBUG "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->mod[card].fxs.lasttxhook = wc->mod[card].fxs.idletxhookstate; wctdm_setreg(wc, card, 64, wc->mod[card].fxs.lasttxhook); return 0; } static int wctdm_ioctl(struct dahdi_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 dahdi_hwgain hwgain; struct wctdm *wc = chan->pvt; int x; switch (cmd) { case DAHDI_ONHOOKTRANSFER: if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) return -EINVAL; if (get_user(x, (__user int *) data)) return -EFAULT; wc->mod[chan->chanpos - 1].fxs.ohttimer = x << 3; wc->mod[chan->chanpos - 1].fxs.idletxhookstate = POLARITY_XOR(chan->chanpos - 1) ? 0x6 : 0x2; /* OHT mode when idle */ if (wc->mod[chan->chanpos - 1].fxs.lasttxhook == 0x1 || wc->mod[chan->chanpos - 1].fxs.lasttxhook == 0x5) { /* Apply the change if appropriate */ wc->mod[chan->chanpos - 1].fxs.lasttxhook = POLARITY_XOR(chan->chanpos - 1) ? 0x6 : 0x2; wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mod[chan->chanpos - 1].fxs.lasttxhook); } break; case DAHDI_SETPOLARITY: if (get_user(x, (__user 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; wc->mod[chan->chanpos - 1].fxs.reversepolarity = x; if ( POLARITY_XOR(chan->chanpos - 1) ) 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 DAHDI_VMWI_CONFIG: if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) return -EINVAL; if (copy_from_user(&(wc->mod[chan->chanpos - 1].fxs.vmwisetting), (__user void *) data, sizeof(wc->mod[chan->chanpos - 1].fxs.vmwisetting))) return -EFAULT; set_vmwi(wc, chan->chanpos - 1); break; case DAHDI_VMWI: if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) return -EINVAL; if (get_user(x, (__user int *) data)) return -EFAULT; if (0 > x) return -EFAULT; wc->mod[chan->chanpos - 1].fxs.vmwi_active_messages = x; set_vmwi(wc, chan->chanpos - 1); 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((__user void *)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((__user void *)data, ®s, sizeof(regs))) return -EFAULT; break; case WCTDM_SET_REG: if (copy_from_user(®op, (__user void *) data, sizeof(regop))) return -EFAULT; if (regop.indirect) { if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS) return -EINVAL; printk(KERN_INFO "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(KERN_INFO "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(KERN_INFO "-- Setting echo registers: \n"); if (copy_from_user(&echoregs, (__user void *)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(KERN_INFO "-- Set echo registers successfully\n"); break; } else { return -EINVAL; } break; case DAHDI_SET_HWGAIN: if (copy_from_user(&hwgain, (__user void *) data, sizeof(hwgain))) return -EFAULT; wctdm_set_hwgain(wc, chan->chanpos-1, hwgain.newgain, hwgain.tx); if (debug) printk(KERN_DEBUG "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 dahdi_chan *chan) { struct wctdm *wc = chan->pvt; if (!(wc->cardflag & (1 << (chan->chanpos - 1)))) return -ENODEV; if (wc->dead) return -ENODEV; wc->usecount++; try_module_get(THIS_MODULE); return 0; } static int wctdm_watchdog(struct dahdi_span *span, int event) { printk(KERN_INFO "TDM: Restarting DMA\n"); wctdm_restart_dma(span->pvt); return 0; } static int wctdm_close(struct dahdi_chan *chan) { struct wctdm *wc = chan->pvt; wc->usecount--; module_put(THIS_MODULE); if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) { wc->mod[chan->chanpos - 1].fxs.idletxhookstate = POLARITY_XOR(chan->chanpos - 1) ? 0x5 : 0x1; } /* If we're dead, release us now */ if (!wc->usecount && wc->dead) wctdm_release(wc); return 0; } static int wctdm_hooksig(struct dahdi_chan *chan, enum dahdi_txsig txsig) { struct wctdm *wc = chan->pvt; if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) { /* XXX Enable hooksig for FXO XXX */ switch(txsig) { case DAHDI_TXSIG_START: case DAHDI_TXSIG_OFFHOOK: wc->mod[chan->chanpos - 1].fxo.offhook = 1; wctdm_setreg(wc, chan->chanpos - 1, 5, 0x9); break; case DAHDI_TXSIG_ONHOOK: wc->mod[chan->chanpos - 1].fxo.offhook = 0; wctdm_setreg(wc, chan->chanpos - 1, 5, 0x8); break; default: printk(KERN_NOTICE "wcfxo: Can't set tx state to %d\n", txsig); } } else { switch(txsig) { case DAHDI_TXSIG_ONHOOK: switch(chan->sig) { case DAHDI_SIG_FXOKS: case DAHDI_SIG_FXOLS: wc->mod[chan->chanpos-1].fxs.lasttxhook = (wc->mod[chan->chanpos-1].fxs.vmwi_hvac ? 4 : wc->mod[chan->chanpos-1].fxs.idletxhookstate); break; case DAHDI_SIG_EM: wc->mod[chan->chanpos-1].fxs.lasttxhook = wc->mod[chan->chanpos-1].fxs.idletxhookstate; break; case DAHDI_SIG_FXOGS: wc->mod[chan->chanpos-1].fxs.lasttxhook = 3; break; } break; case DAHDI_TXSIG_OFFHOOK: switch(chan->sig) { case DAHDI_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 DAHDI_TXSIG_START: wc->mod[chan->chanpos-1].fxs.lasttxhook = 4; break; case DAHDI_TXSIG_KEWL: wc->mod[chan->chanpos-1].fxs.lasttxhook = 0; break; default: printk(KERN_NOTICE "wctdm: Can't set tx state to %d\n", txsig); } if (debug) printk(KERN_DEBUG "Setting FXS hook state to %d (%02x)\n", txsig, wc->mod[chan->chanpos-1].fxs.lasttxhook); #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; /* DAHDI 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"; dahdi_copy_string(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype)); if (alawoverride) { printk(KERN_INFO "ALAW override parameter detected. Device will be operating in ALAW\n"); wc->span.deflaw = DAHDI_LAW_ALAW; } else { wc->span.deflaw = DAHDI_LAW_MULAW; } for (x = 0; x < NUM_CARDS; x++) { sprintf(wc->chans[x]->name, "WCTDM/%d/%d", wc->pos, x); wc->chans[x]->sigcap = DAHDI_SIG_FXOKS | DAHDI_SIG_FXOLS | DAHDI_SIG_FXOGS | DAHDI_SIG_SF | DAHDI_SIG_EM | DAHDI_SIG_CLEAR; wc->chans[x]->sigcap |= DAHDI_SIG_FXSKS | DAHDI_SIG_FXSLS | DAHDI_SIG_SF | DAHDI_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 = DAHDI_FLAG_RBS; wc->span.ioctl = wctdm_ioctl; wc->span.watchdog = wctdm_watchdog; init_waitqueue_head(&wc->span.maintq); wc->span.pvt = wc; if (dahdi_register(&wc->span, 0)) { printk(KERN_NOTICE "Unable to register span with DAHDI\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 = DAHDI_SIG_FXSKS | DAHDI_SIG_FXSLS | DAHDI_SIG_SF | DAHDI_SIG_CLEAR; else wc->chans[x]->sigcap = DAHDI_SIG_FXOKS | DAHDI_SIG_FXOLS | DAHDI_SIG_FXOGS | DAHDI_SIG_SF | DAHDI_SIG_EM | DAHDI_SIG_CLEAR; } else if (!(wc->chans[x]->sigcap & DAHDI_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(KERN_INFO "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(KERN_INFO "%02x != %02x\n", x, y); failed++; } } if (!failed) { printk(KERN_INFO "Freshmaker passed register test\n"); } else { printk(KERN_NOTICE "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(KERN_INFO "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 + DAHDI_CHUNKSIZE * 4 - 4, wc->ioaddr + WC_DMAWI); /* Middle (interrupt) */ outl(wc->writedma + DAHDI_CHUNKSIZE * 8 - 4, wc->ioaddr + WC_DMAWE); /* End */ outl(wc->readdma, wc->ioaddr + WC_DMARS); /* Read start */ outl(wc->readdma + DAHDI_CHUNKSIZE * 4 - 4, wc->ioaddr + WC_DMARI); /* Middle (interrupt) */ outl(wc->readdma + DAHDI_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(KERN_DEBUG "Proslic module %d loop current is %dmA\n",x, ((readi*3)+20)); } printk(KERN_INFO "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(KERN_DEBUG "Proslic module %d loop current is %dmA\n",x, ((readi*3)+20)); } printk(KERN_INFO "Module %d: Installed -- MANUAL FXS\n",x); } else { printk(KERN_NOTICE "Module %d: FAILED FXS (%s)\n", x, fxshonormode ? fxo_modes[_opermode].name : "FCC"); wc->chans[x]->sigcap = __DAHDI_SIG_FXO | DAHDI_SIG_BROKEN; } } else if (!(ret = wctdm_init_voicedaa(wc, x, 0, 0, sane))) { wc->cardflag |= (1 << x); printk(KERN_INFO "Module %d: Installed -- AUTO FXO (%s mode)\n",x, fxo_modes[_opermode].name); } else printk(KERN_NOTICE "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(KERN_NOTICE "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)); for (x=0; x < sizeof(wc->chans)/sizeof(wc->chans[0]); ++x) { wc->chans[x] = &wc->_chans[x]; } 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, DAHDI_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, &wc->writedma); if (!wc->writechunk) { printk(KERN_NOTICE "wctdm: Unable to allocate DMA-able memory\n"); if (wc->freeregion) release_region(wc->ioaddr, 0xff); return -ENOMEM; } wc->readchunk = wc->writechunk + DAHDI_MAX_CHUNKSIZE * 2; /* in doublewords */ wc->readdma = wc->writedma + DAHDI_MAX_CHUNKSIZE * 8; /* in bytes */ if (wctdm_initialize(wc)) { printk(KERN_NOTICE "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, DAHDI_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, DAHDI_IRQ_SHARED, "wctdm", wc)) { printk(KERN_NOTICE "wctdm: Unable to request IRQ %d\n", pdev->irq); if (wc->freeregion) release_region(wc->ioaddr, 0xff); pci_free_consistent(pdev, DAHDI_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)) { /* 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, DAHDI_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)wc->writechunk, wc->writedma); pci_set_drvdata(pdev, NULL); dahdi_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,DAHDI_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(KERN_INFO "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) { dahdi_unregister(&wc->span); if (wc->freeregion) release_region(wc->ioaddr, 0xff); kfree(wc); printk(KERN_INFO "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, DAHDI_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, .remove =__devexit_p(wctdm_remove_one), .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(KERN_NOTICE "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(KERN_INFO " %s\n", fxo_modes[x].name); printk(KERN_INFO "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 = dahdi_pci_module(&wctdm_driver); if (res) return -ENODEV; return 0; } static void __exit wctdm_cleanup(void) { pci_unregister_driver(&wctdm_driver); } module_param(debug, int, 0600); module_param(fxovoltage, 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); MODULE_DESCRIPTION("Wildcard TDM400P Driver"); MODULE_AUTHOR("Mark Spencer "); MODULE_ALIAS("wcfxs"); MODULE_LICENSE("GPL v2"); module_init(wctdm_init); module_exit(wctdm_cleanup); dahdi-linux-2.2.0-rc4/drivers/dahdi/proslic.h0000644000175000017500000001135011046164220020220 0ustar maniacmaniac/* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ // ProSlic Header File typedef struct { unsigned char address; unsigned char altaddr; char *name; unsigned short initial; } alpha; typedef struct { unsigned char chip_number; unsigned char DTMF_digit; unsigned char interrupt_line; unsigned char hook_status; unsigned long half_pulses[20]; // Contains the time stamps of incomming half pulses. unsigned char half_pulses_detected; // Contains the number of half pulses detected. unsigned char Pulse_digit; unsigned long On_Hook_time; unsigned long Off_Hook_time; } chipStruct; // Defines #define LPT 0X378 #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 dahdi-linux-2.2.0-rc4/drivers/dahdi/pciradio.c0000644000175000017500000014607111101704316020341 0ustar maniacmaniac/* * PCI RADIO Card DAHDI 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. * * */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ /* The PCI Radio Interface card interfaces up to 4 two-way radios (either a base/mobile radio or repeater system) to DAHDI 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 DAHDI radio interface. */ /* Latency tests: Without driver: 308496 With driver: 303826 (1.5 %) */ #include #include #include #include #include #include #include #include #include #include #include #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 DAHDI_RADPAR_CTCSSACQUIRETIME 18 /* DEBUG only, this belongs in dahdi.h */ #define DAHDI_RADPAR_CTCSSTALKOFFTIME 19 /* DEBUG only, this belongs in dahdi.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 dahdi_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 dahdi_chan _chans[NUM_CHANS]; struct dahdi_chan *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); } static void __pciradio_setcreg(struct pciradio *rad, unsigned char reg, unsigned char val) { outb(val, rad->ioaddr + RAD_REGBASE + ((reg & 0xf) << 2)); } static unsigned char __pciradio_getcreg(struct pciradio *rad, unsigned char reg) { return inb(rad->ioaddr + RAD_REGBASE + ((reg & 0xf) << 2)); } static 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 */ static 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); } static 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 + DAHDI_CHUNKSIZE; /* Calculate Transmission */ dahdi_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 + DAHDI_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++) { dahdi_ec_chunk(&rad->chans[x], rad->chans[x].readchunk, rad->chans[x].writechunk); } dahdi_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 static irqreturn_t pciradio_interrupt(int irq, void *dev_id, struct pt_regs *regs) #endif DAHDI_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) return IRQ_NONE; if (ints & 0x10) { /* Stop DMA, wait for watchdog */ printk(KERN_INFO "RADIO PCI Master abort\n"); pciradio_stop_dma(rad); return IRQ_RETVAL(1); } if (ints & 0x20) { printk(KERN_INFO "RADIO PCI Target abort\n"); return IRQ_RETVAL(1); } 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])) { 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])) { 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(KERN_DEBUG "Chan %d got rx (ctcss code %d)\n",x + 1, cttable_rx[rad->rxcode[x][rad->present_code[x]]].code); else printk(KERN_DEBUG "Chan %d got rx\n",x + 1); } dahdi_hooksig(&rad->chans[x],DAHDI_RXSIG_OFFHOOK); } else { if (debug) printk(KERN_DEBUG "Chan %d lost rx\n",x + 1); dahdi_hooksig(&rad->chans[x],DAHDI_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); } return IRQ_RETVAL(1); } static int pciradio_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long data) { int i,mycode; unsigned long flags; unsigned char byte1,byte2,mask; union { struct dahdi_radio_stat s; struct dahdi_radio_param p; } stack; struct pciradio *rad = chan->pvt; DECLARE_WAIT_QUEUE_HEAD(mywait); switch (cmd) { case DAHDI_RADIO_GETPARAM: if (copy_from_user(&stack.p, (__user void *) data, sizeof(stack.p))) return -EFAULT; spin_lock_irqsave(&rad->lock,flags); stack.p.data = 0; /* start with 0 value in output */ switch(stack.p.radpar) { case DAHDI_RADPAR_INVERTCOR: if (rad->radmode[chan->chanpos - 1] & RADMODE_INVERTCOR) stack.p.data = 1; break; case DAHDI_RADPAR_IGNORECOR: if (rad->radmode[chan->chanpos - 1] & RADMODE_IGNORECOR) stack.p.data = 1; break; case DAHDI_RADPAR_IGNORECT: if (rad->radmode[chan->chanpos - 1] & RADMODE_IGNORECT) stack.p.data = 1; break; case DAHDI_RADPAR_NOENCODE: if (rad->radmode[chan->chanpos - 1] & RADMODE_NOENCODE) stack.p.data = 1; break; case DAHDI_RADPAR_CORTHRESH: stack.p.data = rad->corthresh[chan->chanpos - 1] & 7; break; case DAHDI_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 DAHDI_RADPAR_NUMTONES: stack.p.data = NUM_CODES; break; case DAHDI_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 DAHDI_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 DAHDI_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 DAHDI_RADPAR_DEBOUNCETIME: stack.p.data = rad->debouncetime[chan->chanpos - 1]; break; case DAHDI_RADPAR_CTCSSACQUIRETIME: stack.p.data = rad->ctcssacquiretime[chan->chanpos - 1]; break; case DAHDI_RADPAR_CTCSSTALKOFFTIME: stack.p.data = rad->ctcsstalkofftime[chan->chanpos - 1]; break; case DAHDI_RADPAR_BURSTTIME: stack.p.data = rad->bursttime[chan->chanpos - 1]; break; case DAHDI_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 DAHDI_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 DAHDI_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((__user void *) data, &stack.p, sizeof(stack.p))) return -EFAULT; break; case DAHDI_RADIO_SETPARAM: if (copy_from_user(&stack.p, (__user void *) data, sizeof(stack.p))) return -EFAULT; spin_lock_irqsave(&rad->lock,flags); switch(stack.p.radpar) { case DAHDI_RADPAR_INVERTCOR: if (stack.p.data) rad->radmode[chan->chanpos - 1] |= RADMODE_INVERTCOR; else rad->radmode[chan->chanpos - 1] &= ~RADMODE_INVERTCOR; break; case DAHDI_RADPAR_IGNORECOR: if (stack.p.data) rad->radmode[chan->chanpos - 1] |= RADMODE_IGNORECOR; else rad->radmode[chan->chanpos - 1] &= ~RADMODE_IGNORECOR; break; case DAHDI_RADPAR_IGNORECT: if (stack.p.data) rad->radmode[chan->chanpos - 1] |= RADMODE_IGNORECT; else rad->radmode[chan->chanpos - 1] &= ~RADMODE_IGNORECT; break; case DAHDI_RADPAR_NOENCODE: if (stack.p.data) rad->radmode[chan->chanpos - 1] |= RADMODE_NOENCODE; else rad->radmode[chan->chanpos - 1] &= ~RADMODE_NOENCODE; break; case DAHDI_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 DAHDI_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 DAHDI_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 DAHDI_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 DAHDI_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 DAHDI_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 DAHDI_RADPAR_DEBOUNCETIME: rad->debouncetime[chan->chanpos - 1] = stack.p.data; break; case DAHDI_RADPAR_CTCSSACQUIRETIME: rad->ctcssacquiretime[chan->chanpos - 1] = stack.p.data; break; case DAHDI_RADPAR_CTCSSTALKOFFTIME: rad->ctcsstalkofftime[chan->chanpos - 1] = stack.p.data; break; case DAHDI_RADPAR_BURSTTIME: rad->bursttime[chan->chanpos - 1] = stack.p.data; break; case DAHDI_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 DAHDI_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 DAHDI_RADPAR_REMMODE: rad->remmode[chan->chanpos - 1] = stack.p.data; break; case DAHDI_RADPAR_REMCOMMAND: /* if no remote mode, return an error */ if (rad->remmode[chan->chanpos - 1] == DAHDI_RADPAR_REM_NONE) { spin_unlock_irqrestore(&rad->lock,flags); return -EINVAL; } i = 0; if (rad->remmode[chan->chanpos - 1] == DAHDI_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] == DAHDI_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] == DAHDI_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] == DAHDI_RADPAR_REM_SERIAL_ASCII) interruptible_sleep_on_timeout(&mywait,100); if (copy_to_user((__user void *) data, &stack.p, sizeof(stack.p))) return -EFAULT; return 0; default: spin_unlock_irqrestore(&rad->lock,flags); return -EINVAL; } spin_unlock_irqrestore(&rad->lock,flags); break; case DAHDI_RADIO_GETSTAT: spin_lock_irqsave(&rad->lock,flags); /* start with clean object */ memset(&stack.s, 0, sizeof(stack.s)); /* if we have rx */ if (rad->gotrx[chan->chanpos - 1]) { stack.s.radstat |= DAHDI_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 |= DAHDI_RADSTAT_TX; stack.s.radstat |= DAHDI_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 |= DAHDI_RADSTAT_IGNCOR; if (rad->radmode[chan->chanpos - 1] & RADMODE_IGNORECT) stack.s.radstat |= DAHDI_RADSTAT_IGNCT; if (rad->radmode[chan->chanpos - 1] & RADMODE_NOENCODE) stack.s.radstat |= DAHDI_RADSTAT_NOENCODE; if (rad->gotcor[chan->chanpos - 1]) stack.s.radstat |= DAHDI_RADSTAT_RXCOR; if (rad->gotct[chan->chanpos - 1]) stack.s.radstat |= DAHDI_RADSTAT_RXCT; spin_unlock_irqrestore(&rad->lock,flags); if (copy_to_user((__user void *) data, &stack.s, sizeof(stack.s))) return -EFAULT; break; default: return -ENOTTY; } return 0; } static int pciradio_open(struct dahdi_chan *chan) { struct pciradio *rad = chan->pvt; if (rad->dead) return -ENODEV; rad->usecount++; return 0; } static int pciradio_watchdog(struct dahdi_span *span, int event) { printk(KERN_INFO "PCI RADIO: Restarting DMA\n"); pciradio_restart_dma(span->pvt); return 0; } static int pciradio_close(struct dahdi_chan *chan) { struct pciradio *rad = chan->pvt; rad->usecount--; /* If we're dead, release us now */ if (!rad->usecount && rad->dead) pciradio_release(rad); return 0; } static int pciradio_hooksig(struct dahdi_chan *chan, enum dahdi_txsig txsig) { struct pciradio *rad = chan->pvt; switch(txsig) { case DAHDI_TXSIG_START: case DAHDI_TXSIG_OFFHOOK: rad->gottx[chan->chanpos - 1] = 1; break; case DAHDI_TXSIG_ONHOOK: rad->gottx[chan->chanpos - 1] = 0; break; default: printk(KERN_DEBUG "pciradio: Can't set tx state to %d\n", txsig); break; } if (debug) printk(KERN_DEBUG "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; /* DAHDI stuff */ sprintf(rad->span.name, "PCIRADIO/%d", rad->pos); sprintf(rad->span.desc, "Board %d", rad->pos + 1); rad->span.deflaw = DAHDI_LAW_MULAW; for (x=0;xnchans;x++) { sprintf(rad->chans[x].name, "PCIRADIO/%d/%d", rad->pos, x); rad->chans[x].sigcap = DAHDI_SIG_SF | DAHDI_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 = DAHDI_FLAG_RBS; rad->span.ioctl = pciradio_ioctl; rad->span.watchdog = pciradio_watchdog; init_waitqueue_head(&rad->span.maintq); rad->span.pvt = rad; if (dahdi_register(&rad->span, 0)) { printk(KERN_NOTICE "Unable to register span with DAHDI\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(KERN_DEBUG "Timeout waiting for INIT and DONE to go low\n"); return -1; } if (debug) printk(KERN_DEBUG "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(KERN_DEBUG "Timeout waiting for INIT to go high\n"); return -1; } if (debug) printk(KERN_DEBUG "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(KERN_DEBUG "fwload: Transferred %d bytes into chip\n",x); /* Wait for FIFO to clear */ endjif = jiffies + 2; while (jiffies < endjif); /* wait */ printk(KERN_DEBUG "Transfered %d bytes into chip\n",x); /* De-assert CS+Write */ rad->ios |= XCS; outb(rad->ios, rad->ioaddr + RAD_AUXD); if (debug) printk(KERN_INFO "fwload: Loading done!\n"); /* Wait for FIFO to clear */ endjif = jiffies + 2; while (jiffies < endjif); /* wait */ if (!(inb(rad->ioaddr + RAD_AUXR) & XINIT)) { printk(KERN_NOTICE "Drove Init low!! CRC Error!!!\n"); return -1; } if (!(inb(rad->ioaddr + RAD_AUXR) & XDONE)) { printk(KERN_INFO "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(KERN_INFO "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 + DAHDI_CHUNKSIZE * 4 - 4, rad->ioaddr + RAD_DMAWI); /* Middle (interrupt) */ outl(rad->writedma + DAHDI_CHUNKSIZE * 8 - 4, rad->ioaddr + RAD_DMAWE); /* End */ outl(rad->readdma, rad->ioaddr + RAD_DMARS); /* Read start */ outl(rad->readdma + DAHDI_CHUNKSIZE * 4 - 4, rad->ioaddr + RAD_DMARI); /* Middle (interrupt) */ outl(rad->readdma + DAHDI_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(KERN_NOTICE "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; rad->chans = rad->_chans; 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, DAHDI_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, &rad->writedma); if (!rad->writechunk) { printk(KERN_NOTICE "pciradio: Unable to allocate DMA-able memory\n"); if (rad->freeregion) release_region(rad->ioaddr, 0xff); return -ENOMEM; } rad->readchunk = rad->writechunk + DAHDI_MAX_CHUNKSIZE * 2; /* in doublewords */ rad->readdma = rad->writedma + DAHDI_MAX_CHUNKSIZE * 8; /* in bytes */ if (pciradio_initialize(rad)) { printk(KERN_INFO "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, DAHDI_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)) { /* 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, DAHDI_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)rad->writechunk, rad->writedma); pci_set_drvdata(pdev, NULL); dahdi_unregister(&rad->span); kfree(rad); return -EIO; } if (request_irq(pdev->irq, pciradio_interrupt, DAHDI_IRQ_SHARED, "pciradio", rad)) { printk(KERN_NOTICE "pciradio: Unable to request IRQ %d\n", pdev->irq); if (rad->freeregion) release_region(rad->ioaddr, 0xff); pci_free_consistent(pdev, DAHDI_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,DAHDI_MAX_CHUNKSIZE * 2 * 2 * 4); /* Start DMA */ pciradio_start_dma(rad); printk(KERN_INFO "Found a PCI Radio Card\n"); res = 0; } else res = -ENOMEM; } return res; } static void pciradio_release(struct pciradio *rad) { dahdi_unregister(&rad->span); if (rad->freeregion) release_region(rad->ioaddr, 0xff); kfree(rad); printk(KERN_INFO "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, DAHDI_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, .remove = __devexit_p(pciradio_remove_one), .id_table = pciradio_pci_tbl, }; static int __init pciradio_init(void) { int res; res = dahdi_pci_module(&pciradio_driver); if (res) return -ENODEV; return 0; } static void __exit pciradio_cleanup(void) { pci_unregister_driver(&pciradio_driver); } module_param(debug, int, 0600); MODULE_DESCRIPTION("DAHDI Telephony PCI Radio Card Driver"); MODULE_AUTHOR("Jim Dixon "); MODULE_LICENSE("GPL v2"); module_init(pciradio_init); module_exit(pciradio_cleanup); dahdi-linux-2.2.0-rc4/drivers/dahdi/dahdi_echocan_mg2.c0000644000175000017500000006453111176115504022054 0ustar maniacmaniac/* * ECHO_CAN_MG2 * * by Michael Gernoth * * Based upon kb1ec.h and mec2.h * * Copyright (C) 2002, Digium, Inc. * * Additional background on the techniques used in this code can be found in: * * Messerschmitt, David; Hedberg, David; Cole, Christopher; Haoui, Amine; * Winship, Peter; "Digital Voice Echo Canceller with a TMS32020," * in Digital Signal Processing Applications with the TMS320 Family, * pp. 415-437, Texas Instruments, Inc., 1986. * * A pdf of which is available by searching on the document title at http://www.ti.com/ * */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ #include #include #include #include #include #include #include #include static int debug; static int aggressive; #define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args) #define debug_printk(level, fmt, args...) if (debug >= level) printk("%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args) #define ABS(a) abs(a!=-32768?a:-32767) #define RESTORE_COEFFS {\ int x;\ memcpy(pvt->a_i, pvt->c_i, pvt->N_d*sizeof(int));\ for (x = 0; x < pvt->N_d; x++) {\ pvt->a_s[x] = pvt->a_i[x] >> 16;\ }\ pvt->backup = BACKUP;\ } /* Uncomment to provide summary statistics for overall echo can performance every 4000 samples */ /* #define MEC2_STATS 4000 */ /* Uncomment to generate per-sample statistics - this will severely degrade system performance and audio quality */ /* #define MEC2_STATS_DETAILED */ /* Uncomment to generate per-call DC bias offset messages */ /* #define MEC2_DCBIAS_MESSAGE */ /* Get optimized routines for math */ #include "arith.h" /* Important constants for tuning mg2 echo can */ /* Convergence (aka. adaptation) speed -- higher means slower */ #define DEFAULT_BETA1_I 2048 /* Constants for various power computations */ #define DEFAULT_SIGMA_LY_I 7 #define DEFAULT_SIGMA_LU_I 7 #define DEFAULT_ALPHA_ST_I 5 /* near-end speech detection sensitivity factor */ #define DEFAULT_ALPHA_YT_I 5 #define DEFAULT_CUTOFF_I 128 /* Define the near-end speech hangover counter: if near-end speech * is declared, hcntr is set equal to hangt (see pg. 432) */ #define DEFAULT_HANGT 600 /* in samples, so 600 samples = 75ms */ /* define the residual error suppression threshold */ #define DEFAULT_SUPPR_I 16 /* 16 = -24db */ /* This is the minimum reference signal power estimate level * that will result in filter adaptation. * If this is too low then background noise will cause the filter * coefficients to constantly be updated. */ #define MIN_UPDATE_THRESH_I 2048 /* The number of samples used to update coefficients using the * the block update method (M). It should be related back to the * length of the echo can. * ie. it only updates coefficients when (sample number MOD default_m) = 0 * * Getting this wrong may cause an oops. Consider yourself warned! */ #define DEFAULT_M 16 /* every 16th sample */ /* If AGGRESSIVE supression is enabled, then we start cancelling residual * echos again even while there is potentially the very end of a near-side * signal present. * This defines how many samples of DEFAULT_HANGT can remain before we * kick back in */ #define AGGRESSIVE_HCNTR 160 /* in samples, so 160 samples = 20ms */ /* Treat sample as error if it has a different sign as the * input signal and is this number larger in ABS() as * the input-signal */ #define MAX_SIGN_ERROR 3000 /* Number of coefficients really used for calculating the * simulated echo. The value specifies how many of the * biggest coefficients are used for calculating rs. * This helps on long echo-tails by artificially limiting * the number of coefficients for the calculation and * preventing overflows. * Comment this to deactivate the code */ #define USED_COEFFS 64 /* Backup coefficients every this number of samples */ #define BACKUP 256 /***************************************************************/ /* The following knobs are not implemented in the current code */ /* we need a dynamic level of suppression varying with the ratio of the power of the echo to the power of the reference signal this is done so that we have a smoother background. we have a higher suppression when the power ratio is closer to suppr_ceil and reduces logarithmically as we approach suppr_floor. */ #define SUPPR_FLOOR -64 #define SUPPR_CEIL -24 /* in a second departure, we calculate the residual error suppression * as a percentage of the reference signal energy level. The threshold * is defined in terms of dB below the reference signal. */ #define RES_SUPR_FACTOR -20 #define DC_NORMALIZE #ifndef NULL #define NULL 0 #endif #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE (!FALSE) #endif /* Generic circular buffer definition */ typedef struct { /* Pointer to the relative 'start' of the buffer */ int idx_d; /* The absolute size of the buffer */ int size_d; /* The actual sample - twice as large as we need, however we do store values at idx_d and idx_d+size_d */ short *buf_d; } echo_can_cb_s; static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec); static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec); static void echo_can_process(struct dahdi_echocan_state *ec, short *isig, const short *iref, u32 size); static int echo_can_traintap(struct dahdi_echocan_state *ec, int pos, short val); static void echocan_NLP_toggle(struct dahdi_echocan_state *ec, unsigned int enable); static const struct dahdi_echocan_factory my_factory = { .name = "MG2", .owner = THIS_MODULE, .echocan_create = echo_can_create, }; static const struct dahdi_echocan_features my_features = { .NLP_toggle = 1, }; static const struct dahdi_echocan_ops my_ops = { .name = "MG2", .echocan_free = echo_can_free, .echocan_process = echo_can_process, .echocan_traintap = echo_can_traintap, .echocan_NLP_toggle = echocan_NLP_toggle, }; struct ec_pvt { struct dahdi_echocan_state dahdi; /* an arbitrary ID for this echo can - this really should be settable from the calling channel... */ int id; /* absolute time - aka. sample number index - essentially the number of samples since this can was init'ed */ int i_d; /* Pre-computed constants */ /* ---------------------- */ /* Number of filter coefficents */ int N_d; /* Rate of adaptation of filter */ int beta2_i; /* Accumulators for power computations */ /* ----------------------------------- */ /* reference signal power estimate - aka. Average absolute value of y(k) */ int Ly_i; /* ... */ int Lu_i; /* Accumulators for signal detectors */ /* --------------------------------- */ /* Power estimate of the recent past of the near-end hybrid signal - aka. Short-time average of: 2 x |s(i)| */ int s_tilde_i; /* Power estimate of the recent past of the far-end receive signal - aka. Short-time average of: |y(i)| */ int y_tilde_i; /* Near end speech detection counter - stores Hangover counter time remaining, in samples */ int HCNTR_d; /* Circular buffers and coefficients */ /* --------------------------------- */ /* ... */ int *a_i; /* ... */ short *a_s; /* Backups */ int *b_i; int *c_i; /* Reference samples of far-end receive signal */ echo_can_cb_s y_s; /* Reference samples of near-end signal */ echo_can_cb_s s_s; /* Reference samples of near-end signal minus echo estimate */ echo_can_cb_s u_s; /* Reference samples of far-end receive signal used to calculate short-time average */ echo_can_cb_s y_tilde_s; /* Peak far-end receive signal */ /* --------------------------- */ /* Highest y_tilde value in the sample buffer */ short max_y_tilde; /* Index of the sample containing the max_y_tilde value */ int max_y_tilde_pos; #ifdef MEC2_STATS /* Storage for performance statistics */ int cntr_nearend_speech_frames; int cntr_residualcorrected_frames; int cntr_residualcorrected_framesskipped; int cntr_coeff_updates; int cntr_coeff_missedupdates; int avg_Lu_i_toolow; int avg_Lu_i_ok; #endif unsigned int aggressive:1; short lastsig; int lastcount; int backup; #ifdef DC_NORMALIZE int dc_estimate; #endif int use_nlp; }; #define dahdi_to_pvt(a) container_of(a, struct ec_pvt, dahdi) static inline void init_cb_s(echo_can_cb_s *cb, int len, void *where) { cb->buf_d = (short *)where; cb->idx_d = 0; cb->size_d = len; } static inline void add_cc_s(echo_can_cb_s *cb, short newval) { /* Can't use modulus because N+M isn't a power of two (generally) */ cb->idx_d--; if (cb->idx_d < (int)0) /* Whoops - the pointer to the 'start' wrapped around so reset it to the top of the buffer */ cb->idx_d += cb->size_d; /* Load two copies into memory */ cb->buf_d[cb->idx_d] = newval; cb->buf_d[cb->idx_d + cb->size_d] = newval; } static inline short get_cc_s(echo_can_cb_s *cb, int pos) { /* Load two copies into memory */ return cb->buf_d[cb->idx_d + pos]; } static inline void init_cc(struct ec_pvt *pvt, int N, int maxy, int maxu) { void *ptr = pvt; unsigned long tmp; /* Double-word align past end of state */ ptr += sizeof(*pvt); tmp = (unsigned long)ptr; tmp += 3; tmp &= ~3L; ptr = (void *)tmp; /* Reset parameters */ pvt->N_d = N; pvt->beta2_i = DEFAULT_BETA1_I; /* Allocate coefficient memory */ pvt->a_i = ptr; ptr += (sizeof(int) * pvt->N_d); pvt->a_s = ptr; ptr += (sizeof(short) * pvt->N_d); /* Allocate backup memory */ pvt->b_i = ptr; ptr += (sizeof(int) * pvt->N_d); pvt->c_i = ptr; ptr += (sizeof(int) * pvt->N_d); /* Reset Y circular buffer (short version) */ init_cb_s(&pvt->y_s, maxy, ptr); ptr += (sizeof(short) * (maxy) * 2); /* Reset Sigma circular buffer (short version for FIR filter) */ init_cb_s(&pvt->s_s, (1 << DEFAULT_ALPHA_ST_I), ptr); ptr += (sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) * 2); init_cb_s(&pvt->u_s, maxu, ptr); ptr += (sizeof(short) * maxu * 2); /* Allocate a buffer for the reference signal power computation */ init_cb_s(&pvt->y_tilde_s, pvt->N_d, ptr); /* Reset the absolute time index */ pvt->i_d = (int)0; /* Reset the power computations (for y and u) */ pvt->Ly_i = DEFAULT_CUTOFF_I; pvt->Lu_i = DEFAULT_CUTOFF_I; #ifdef MEC2_STATS /* set the identity */ pvt->id = (int)&ptr; /* Reset performance stats */ pvt->cntr_nearend_speech_frames = (int)0; pvt->cntr_residualcorrected_frames = (int)0; pvt->cntr_residualcorrected_framesskipped = (int)0; pvt->cntr_coeff_updates = (int)0; pvt->cntr_coeff_missedupdates = (int)0; pvt->avg_Lu_i_toolow = (int)0; pvt->avg_Lu_i_ok = (int)0; #endif /* Reset the near-end speech detector */ pvt->s_tilde_i = (int)0; pvt->y_tilde_i = (int)0; pvt->HCNTR_d = (int)0; } static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec) { struct ec_pvt *pvt = dahdi_to_pvt(ec); #if defined(DC_NORMALIZE) && defined(MEC2_DCBIAS_MESSAGE) printk(KERN_INFO "EC: DC bias calculated: %d V\n", pvt->dc_estimate >> 15); #endif kfree(pvt); } #ifdef DC_NORMALIZE short inline dc_removal(int *dc_estimate, short samp) { *dc_estimate += ((((int)samp << 15) - *dc_estimate) >> 9); return samp - (*dc_estimate >> 15); } #endif static inline short sample_update(struct ec_pvt *pvt, short iref, short isig) { /* Declare local variables that are used more than once */ /* ... */ int k; /* ... */ int rs; /* ... */ short u; /* ... */ int Py_i; /* ... */ int two_beta_i; #ifdef DC_NORMALIZE isig = dc_removal(&pvt->dc_estimate, isig); #endif /* flow A on pg. 428 */ /* eq. (16): high-pass filter the input to generate the next value; * push the current value into the circular buffer * * sdc_im1_d = sdc_d; * sdc_d = sig; * s_i_d = sdc_d; * s_d = s_i_d; * s_i_d = (float)(1.0 - gamma_d) * s_i_d * + (float)(0.5 * (1.0 - gamma_d)) * (sdc_d - sdc_im1_d); */ /* Update the Far-end receive signal circular buffers and accumulators */ /* ------------------------------------------------------------------- */ /* Delete the oldest sample from the power estimate accumulator */ pvt->y_tilde_i -= abs(get_cc_s(&pvt->y_s, (1 << DEFAULT_ALPHA_YT_I) - 1)) >> DEFAULT_ALPHA_YT_I; /* Add the new sample to the power estimate accumulator */ pvt->y_tilde_i += abs(iref) >> DEFAULT_ALPHA_ST_I; /* Push a copy of the new sample into its circular buffer */ add_cc_s(&pvt->y_s, iref); /* eq. (2): compute r in fixed-point */ rs = CONVOLVE2(pvt->a_s, pvt->y_s.buf_d + pvt->y_s.idx_d, pvt->N_d); rs >>= 15; if (pvt->lastsig == isig) { pvt->lastcount++; } else { pvt->lastcount = 0; pvt->lastsig = isig; } if (isig == 0) { u = 0; } else if (pvt->lastcount > 255) { /* We have seen the same input-signal more than 255 times, * we should pass it through uncancelled, as we are likely on hold */ u = isig; } else { int sign_error; if (rs < -32768) { rs = -32768; pvt->HCNTR_d = DEFAULT_HANGT; RESTORE_COEFFS; } else if (rs > 32767) { rs = 32767; pvt->HCNTR_d = DEFAULT_HANGT; RESTORE_COEFFS; } sign_error = ABS(rs) - ABS(isig); if (ABS(sign_error) > MAX_SIGN_ERROR) { rs = 0; RESTORE_COEFFS; } /* eq. (3): compute the output value (see figure 3) and the error * note: the error is the same as the output signal when near-end * speech is not present */ u = isig - rs; if (u / isig < 0) u = isig - (rs >> 1); } /* Push a copy of the output value sample into its circular buffer */ add_cc_s(&pvt->u_s, u); if (!pvt->backup) { /* Backup coefficients periodically */ pvt->backup = BACKUP; memcpy(pvt->c_i, pvt->b_i, pvt->N_d*sizeof(int)); memcpy(pvt->b_i, pvt->a_i, pvt->N_d*sizeof(int)); } else pvt->backup--; /* Update the Near-end hybrid signal circular buffers and accumulators */ /* ------------------------------------------------------------------- */ /* Delete the oldest sample from the power estimate accumulator */ pvt->s_tilde_i -= abs(get_cc_s(&pvt->s_s, (1 << DEFAULT_ALPHA_ST_I) - 1)); /* Add the new sample to the power estimate accumulator */ pvt->s_tilde_i += abs(isig); /* Push a copy of the new sample into it's circular buffer */ add_cc_s(&pvt->s_s, isig); /* Push a copy of the current short-time average of the far-end receive signal into it's circular buffer */ add_cc_s(&pvt->y_tilde_s, pvt->y_tilde_i); /* flow B on pg. 428 */ /* If the hangover timer isn't running then compute the new convergence factor, otherwise set Py_i to 32768 */ if (!pvt->HCNTR_d) { Py_i = (pvt->Ly_i >> DEFAULT_SIGMA_LY_I) * (pvt->Ly_i >> DEFAULT_SIGMA_LY_I); Py_i >>= 15; } else { Py_i = (1 << 15); } #if 0 /* Vary rate of adaptation depending on position in the file * Do not do this for the first (DEFAULT_UPDATE_TIME) secs after speech * has begun of the file to allow the echo cancellor to estimate the * channel accurately * Still needs conversion! */ if (pvt->start_speech_d != 0) { if (pvt->i_d > (DEFAULT_T0 + pvt->start_speech_d)*(SAMPLE_FREQ)) { pvt->beta2_d = max_cc_float(MIN_BETA, DEFAULT_BETA1 * exp((-1/DEFAULT_TAU)*((pvt->i_d/(float)SAMPLE_FREQ) - DEFAULT_T0 - pvt->start_speech_d))); } } else { pvt->beta2_d = DEFAULT_BETA1; } #endif /* Fixed point, inverted */ pvt->beta2_i = DEFAULT_BETA1_I; /* Fixed point version, inverted */ two_beta_i = (pvt->beta2_i * Py_i) >> 15; if (!two_beta_i) two_beta_i++; /* Update the Suppressed signal power estimate accumulator */ /* ------------------------------------------------------- */ /* Delete the oldest sample from the power estimate accumulator */ pvt->Lu_i -= abs(get_cc_s(&pvt->u_s, (1 << DEFAULT_SIGMA_LU_I) - 1)); /* Add the new sample to the power estimate accumulator */ pvt->Lu_i += abs(u); /* Update the Far-end reference signal power estimate accumulator */ /* -------------------------------------------------------------- */ /* eq. (10): update power estimate of the reference */ /* Delete the oldest sample from the power estimate accumulator */ pvt->Ly_i -= abs(get_cc_s(&pvt->y_s, (1 << DEFAULT_SIGMA_LY_I) - 1)) ; /* Add the new sample to the power estimate accumulator */ pvt->Ly_i += abs(iref); if (pvt->Ly_i < DEFAULT_CUTOFF_I) pvt->Ly_i = DEFAULT_CUTOFF_I; /* Update the Peak far-end receive signal detected */ /* ----------------------------------------------- */ if (pvt->y_tilde_i > pvt->max_y_tilde) { /* New highest y_tilde with full life */ pvt->max_y_tilde = pvt->y_tilde_i; pvt->max_y_tilde_pos = pvt->N_d - 1; } else if (--pvt->max_y_tilde_pos < 0) { /* Time to find new max y tilde... */ pvt->max_y_tilde = MAX16(pvt->y_tilde_s.buf_d + pvt->y_tilde_s.idx_d, pvt->N_d, &pvt->max_y_tilde_pos); } /* Determine if near end speech was detected in this sample */ /* -------------------------------------------------------- */ if (((pvt->s_tilde_i >> (DEFAULT_ALPHA_ST_I - 1)) > pvt->max_y_tilde) && (pvt->max_y_tilde > 0)) { /* Then start the Hangover counter */ pvt->HCNTR_d = DEFAULT_HANGT; RESTORE_COEFFS; #ifdef MEC2_STATS_DETAILED printk(KERN_INFO "Reset near end speech timer with: s_tilde_i %d, stmnt %d, max_y_tilde %d\n", pvt->s_tilde_i, (pvt->s_tilde_i >> (DEFAULT_ALPHA_ST_I - 1)), pvt->max_y_tilde); #endif #ifdef MEC2_STATS ++pvt->cntr_nearend_speech_frames; #endif } else if (pvt->HCNTR_d > (int)0) { /* otherwise, if it's still non-zero, decrement the Hangover counter by one sample */ #ifdef MEC2_STATS ++pvt->cntr_nearend_speech_frames; #endif pvt->HCNTR_d--; } /* Update coefficients if no near-end speech in this sample (ie. HCNTR_d = 0) * and we have enough signal to bother trying to update. * -------------------------------------------------------------------------- */ if (!pvt->HCNTR_d && /* no near-end speech present */ !(pvt->i_d % DEFAULT_M)) { /* we only update on every DEFAULM_M'th sample from the stream */ if (pvt->Lu_i > MIN_UPDATE_THRESH_I) { /* there is sufficient energy above the noise floor to contain meaningful data */ /* so loop over all the filter coefficients */ #ifdef USED_COEFFS int max_coeffs[USED_COEFFS]; int *pos; if (pvt->N_d > USED_COEFFS) memset(max_coeffs, 0, USED_COEFFS*sizeof(int)); #endif #ifdef MEC2_STATS_DETAILED printk(KERN_INFO "updating coefficients with: pvt->Lu_i %9d\n", pvt->Lu_i); #endif #ifdef MEC2_STATS pvt->avg_Lu_i_ok = pvt->avg_Lu_i_ok + pvt->Lu_i; ++pvt->cntr_coeff_updates; #endif for (k = 0; k < pvt->N_d; k++) { /* eq. (7): compute an expectation over M_d samples */ int grad2; grad2 = CONVOLVE2(pvt->u_s.buf_d + pvt->u_s.idx_d, pvt->y_s.buf_d + pvt->y_s.idx_d + k, DEFAULT_M); /* eq. (7): update the coefficient */ pvt->a_i[k] += grad2 / two_beta_i; pvt->a_s[k] = pvt->a_i[k] >> 16; #ifdef USED_COEFFS if (pvt->N_d > USED_COEFFS) { if (abs(pvt->a_i[k]) > max_coeffs[USED_COEFFS-1]) { /* More or less insertion-sort... */ pos = max_coeffs; while (*pos > abs(pvt->a_i[k])) pos++; if (*pos > max_coeffs[USED_COEFFS-1]) memmove(pos+1, pos, (USED_COEFFS-(pos-max_coeffs)-1)*sizeof(int)); *pos = abs(pvt->a_i[k]); } } #endif } #ifdef USED_COEFFS /* Filter out irrelevant coefficients */ if (pvt->N_d > USED_COEFFS) for (k = 0; k < pvt->N_d; k++) if (abs(pvt->a_i[k]) < max_coeffs[USED_COEFFS-1]) pvt->a_i[k] = pvt->a_s[k] = 0; #endif } else { #ifdef MEC2_STATS_DETAILED printk(KERN_INFO "insufficient signal to update coefficients pvt->Lu_i %5d < %5d\n", pvt->Lu_i, MIN_UPDATE_THRESH_I); #endif #ifdef MEC2_STATS pvt->avg_Lu_i_toolow = pvt->avg_Lu_i_toolow + pvt->Lu_i; ++pvt->cntr_coeff_missedupdates; #endif } } /* paragraph below eq. (15): if no near-end speech in the sample and * the reference signal power estimate > cutoff threshold * then perform residual error suppression */ #ifdef MEC2_STATS_DETAILED if (pvt->HCNTR_d == 0) printk(KERN_INFO "possibly correcting frame with pvt->Ly_i %9d pvt->Lu_i %9d and expression %d\n", pvt->Ly_i, pvt->Lu_i, (pvt->Ly_i/(pvt->Lu_i + 1))); #endif #ifndef NO_ECHO_SUPPRESSOR if (pvt->use_nlp) { if (pvt->aggressive) { if ((pvt->HCNTR_d < AGGRESSIVE_HCNTR) && (pvt->Ly_i > (pvt->Lu_i << 1))) { for (k = 0; k < 2; k++) { u = u * (pvt->Lu_i >> DEFAULT_SIGMA_LU_I) / ((pvt->Ly_i >> (DEFAULT_SIGMA_LY_I)) + 1); } #ifdef MEC2_STATS_DETAILED printk(KERN_INFO "aggresively correcting frame with pvt->Ly_i %9d pvt->Lu_i %9d expression %d\n", pvt->Ly_i, pvt->Lu_i, (pvt->Ly_i/(pvt->Lu_i + 1))); #endif #ifdef MEC2_STATS ++pvt->cntr_residualcorrected_frames; #endif } } else { if (pvt->HCNTR_d == 0) { if ((pvt->Ly_i/(pvt->Lu_i + 1)) > DEFAULT_SUPPR_I) { for (k = 0; k < 1; k++) { u = u * (pvt->Lu_i >> DEFAULT_SIGMA_LU_I) / ((pvt->Ly_i >> (DEFAULT_SIGMA_LY_I + 2)) + 1); } #ifdef MEC2_STATS_DETAILED printk(KERN_INFO "correcting frame with pvt->Ly_i %9d pvt->Lu_i %9d expression %d\n", pvt->Ly_i, pvt->Lu_i, (pvt->Ly_i/(pvt->Lu_i + 1))); #endif #ifdef MEC2_STATS ++pvt->cntr_residualcorrected_frames; #endif } #ifdef MEC2_STATS else { ++pvt->cntr_residualcorrected_framesskipped; } #endif } } } #endif #if 0 /* This will generate a non-linear supression factor, once converted */ if ((pvt->HCNTR_d == 0) && ((pvt->Lu_d/pvt->Ly_d) < DEFAULT_SUPPR) && (pvt->Lu_d/pvt->Ly_d > EC_MIN_DB_VALUE)) { suppr_factor = (10 / (float)(SUPPR_FLOOR - SUPPR_CEIL)) * log(pvt->Lu_d/pvt->Ly_d) - SUPPR_CEIL / (float)(SUPPR_FLOOR - SUPPR_CEIL); u_suppr = pow(10.0, (suppr_factor) * RES_SUPR_FACTOR / 10.0) * u_suppr; } #endif #ifdef MEC2_STATS /* Periodically dump performance stats */ if ((pvt->i_d % MEC2_STATS) == 0) { /* make sure to avoid div0's! */ if (pvt->cntr_coeff_missedupdates > 0) pvt->avg_Lu_i_toolow = (int)(pvt->avg_Lu_i_toolow / pvt->cntr_coeff_missedupdates); else pvt->avg_Lu_i_toolow = -1; if (pvt->cntr_coeff_updates > 0) pvt->avg_Lu_i_ok = (pvt->avg_Lu_i_ok / pvt->cntr_coeff_updates); else pvt->avg_Lu_i_ok = -1; printk(KERN_INFO "%d: Near end speech: %5d Residuals corrected/skipped: %5d/%5d Coefficients updated ok/low sig: %3d/%3d Lu_i avg ok/low sig %6d/%5d\n", pvt->id, pvt->cntr_nearend_speech_frames, pvt->cntr_residualcorrected_frames, pvt->cntr_residualcorrected_framesskipped, pvt->cntr_coeff_updates, pvt->cntr_coeff_missedupdates, pvt->avg_Lu_i_ok, pvt->avg_Lu_i_toolow); pvt->cntr_nearend_speech_frames = 0; pvt->cntr_residualcorrected_frames = 0; pvt->cntr_residualcorrected_framesskipped = 0; pvt->cntr_coeff_updates = 0; pvt->cntr_coeff_missedupdates = 0; pvt->avg_Lu_i_ok = 0; pvt->avg_Lu_i_toolow = 0; } #endif /* Increment the sample index and return the corrected sample */ pvt->i_d++; return u; } static void echo_can_process(struct dahdi_echocan_state *ec, short *isig, const short *iref, u32 size) { struct ec_pvt *pvt = dahdi_to_pvt(ec); u32 x; short result; for (x = 0; x < size; x++) { result = sample_update(pvt, *iref, *isig); *isig++ = result; ++iref; } } static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec) { int maxy; int maxu; size_t size; unsigned int x; char *c; struct ec_pvt *pvt; maxy = ecp->tap_length + DEFAULT_M; maxu = DEFAULT_M; if (maxy < (1 << DEFAULT_ALPHA_YT_I)) maxy = (1 << DEFAULT_ALPHA_YT_I); if (maxy < (1 << DEFAULT_SIGMA_LY_I)) maxy = (1 << DEFAULT_SIGMA_LY_I); if (maxu < (1 << DEFAULT_SIGMA_LU_I)) maxu = (1 << DEFAULT_SIGMA_LU_I); size = sizeof(**ec) + 4 + /* align */ sizeof(int) * ecp->tap_length + /* a_i */ sizeof(short) * ecp->tap_length + /* a_s */ sizeof(int) * ecp->tap_length + /* b_i */ sizeof(int) * ecp->tap_length + /* c_i */ 2 * sizeof(short) * (maxy) + /* y_s */ 2 * sizeof(short) * (1 << DEFAULT_ALPHA_ST_I) + /* s_s */ 2 * sizeof(short) * (maxu) + /* u_s */ 2 * sizeof(short) * ecp->tap_length; /* y_tilde_s */ pvt = kzalloc(size, GFP_KERNEL); if (!pvt) return -ENOMEM; pvt->dahdi.ops = &my_ops; pvt->aggressive = aggressive; pvt->dahdi.features = my_features; for (x = 0; x < ecp->param_count; x++) { for (c = p[x].name; *c; c++) *c = tolower(*c); if (!strcmp(p[x].name, "aggressive")) { pvt->aggressive = p[x].value ? 1 : 0; } else { printk(KERN_WARNING "Unknown parameter supplied to MG2 echo canceler: '%s'\n", p[x].name); kfree(pvt); return -EINVAL; } } init_cc(pvt, ecp->tap_length, maxy, maxu); /* Non-linear processor - a fancy way to say "zap small signals, to avoid accumulating noise". */ pvt->use_nlp = TRUE; *ec = &pvt->dahdi; return 0; } static int echo_can_traintap(struct dahdi_echocan_state *ec, int pos, short val) { struct ec_pvt *pvt = dahdi_to_pvt(ec); /* Set the hangover counter to the length of the can to * avoid adjustments occuring immediately after initial forced training */ pvt->HCNTR_d = pvt->N_d << 1; if (pos >= pvt->N_d) { memcpy(pvt->b_i, pvt->a_i, pvt->N_d*sizeof(int)); memcpy(pvt->c_i, pvt->a_i, pvt->N_d*sizeof(int)); return 1; } pvt->a_i[pos] = val << 17; pvt->a_s[pos] = val << 1; if (++pos >= pvt->N_d) { memcpy(pvt->b_i, pvt->a_i, pvt->N_d*sizeof(int)); memcpy(pvt->c_i, pvt->a_i, pvt->N_d*sizeof(int)); return 1; } return 0; } static void echocan_NLP_toggle(struct dahdi_echocan_state *ec, unsigned int enable) { struct ec_pvt *pvt = dahdi_to_pvt(ec); pvt->use_nlp = enable ? 1 : 0; } static int __init mod_init(void) { if (dahdi_register_echocan_factory(&my_factory)) { module_printk(KERN_ERR, "could not register with DAHDI core\n"); return -EPERM; } module_printk(KERN_NOTICE, "Registered echo canceler '%s'\n", my_factory.name); return 0; } static void __exit mod_exit(void) { dahdi_unregister_echocan_factory(&my_factory); } module_param(debug, int, S_IRUGO | S_IWUSR); module_param(aggressive, int, S_IRUGO | S_IWUSR); MODULE_DESCRIPTION("DAHDI 'MG2' Echo Canceler"); MODULE_AUTHOR("Michael Gernoth"); MODULE_LICENSE("GPL v2"); module_init(mod_init); module_exit(mod_exit); dahdi-linux-2.2.0-rc4/drivers/dahdi/tormenta2.rbt0000644000175000017500000214653311015035664021043 0ustar maniacmaniacXilinx 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 dahdi-linux-2.2.0-rc4/drivers/dahdi/Kbuild0000644000175000017500000001072711176111367017550 0ustar maniacmaniacobj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI) += dahdi.o obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_DUMMY) += dahdi_dummy.o obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_DYNAMIC) += dahdi_dynamic.o obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_DYNAMIC_LOC) += dahdi_dynamic_loc.o obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_DYNAMIC_ETH) += dahdi_dynamic_eth.o obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_TRANSCODE) += dahdi_transcode.o obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCT4XXP) += wct4xxp/ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTC4XXP) += wctc4xxp/ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTDM24XXP) += wctdm24xxp/ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE12XP) += wcte12xp/ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTDM) += wctdm.o obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_VOICEBUS) += voicebus/ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCB4XXP) += wcb4xxp/ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCT1XXP) += wct1xxp.o obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE11XP) += wcte11xp.o obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCFXO) += wcfxo.o obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_TOR2) += tor2.o obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_PCIRADIO) += pciradio.o obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPP) += xpp/ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_JPAH) += dahdi_echocan_jpah.o obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_STEVE) += dahdi_echocan_sec.o obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_STEVE2) += dahdi_echocan_sec2.o obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_KB1) += dahdi_echocan_kb1.o obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_MG2) += dahdi_echocan_mg2.o obj-m += $(DAHDI_MODULES_EXTRA) # Only enable this if you think you know what you're doing. This is not # supported yet: #obj-m += dahdi_echocan_oslec.o # # A quick and dirty way to build OSLEC, if you happened to place it # yourself in the dahdi source tree. This is experimental. See README # regarding OSLEC. #obj-m += ../staging/echo/ CFLAGS_MODULE += -I$(DAHDI_INCLUDE) -I$(src) ifndef HOTPLUG_FIRMWARE ifneq (,$(filter y m,$(CONFIG_FW_LOADER))) HOTPLUG_FIRMWARE := yes else HOTPLUG_FIRMWARE := no endif export HOTPLUG_FIRMWARE endif # fix typo present in CentOS and RHEL 2.6.9 kernels BAD_KERNELS_VERS := 22 34 34.0.1 34.0.2 BAD_KERNELS := $(foreach ver,$(BAD_KERNELS_VERS),2.6.9-$(ver).EL 2.6.9-$(ver).ELsmp) ifneq (,$(filter $(KVERS),$(BAD_KERNELS))) EXTRA_CFLAGS+=-Drw_lock_t=rwlock_t endif # A number of Fedora 10 (9 also?) kernels backported hrtimer to 2.6.27 # as part of an ALSA backport. TODO: Any better way to detect that? ifeq (1,$(shell fgrep -q ' hrtimer_set_expires' include/linux/hrtimer.h 2>/dev/null && echo 1)) EXTRA_CFLAGS+=-DHAVE_HRTIMER_ACCESSORS=1 endif dahdi-objs := dahdi-base.o ############################################################################### # VPMADT032 Loader ############################################################################### dahdi_vpmadt032_loader-objs := vpmadt032_loader/dahdi_vpmadt032_loader.o ifeq ($(ARCH),i386) ifneq ($(wildcard $(src)/vpmadt032_loader/vpmadt032_x86_32.o_shipped),) VPMADT032_LOADER_PRESENT=yes dahdi_vpmadt032_loader-objs += vpmadt032_loader/vpmadt032_x86_32.o obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_VPMADT032_LOADER) += dahdi_vpmadt032_loader.o endif else ifeq ($(ARCH),x86_64) ifneq ($(wildcard $(src)/vpmadt032_loader/vpmadt032_x86_64.o_shipped),) VPMADT032_LOADER_PRESENT=yes dahdi_vpmadt032_loader-objs += vpmadt032_loader/vpmadt032_x86_64.o obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_VPMADT032_LOADER) += dahdi_vpmadt032_loader.o endif endif endif ############################################################################### # HPEC Support ############################################################################### dahdi_echocan_hpec-objs := hpec/dahdi_echocan_hpec.o CFLAGS_dahdi_echocan_hpec.o := -I$(src)/hpec ifeq ($(ARCH),i386) ifneq ($(wildcard $(src)/hpec/hpec_x86_32.o_shipped),) HPEC_PRESENT=yes dahdi_echocan_hpec-objs += hpec/hpec_x86_32.o endif endif ifeq ($(ARCH),x86_64) ifneq ($(wildcard $(src)/hpec/hpec_x86_64.o_shipped),) HPEC_PRESENT=yes dahdi_echocan_hpec-objs += hpec/hpec_x86_64.o endif endif ifeq ($(HPEC_PRESENT),yes) obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_HPEC) += dahdi_echocan_hpec.o 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 $@ $^ clean-files := radfw.h tor2fw.h dahdi-linux-2.2.0-rc4/drivers/dahdi/dahdi_echocan_jpah.c0000644000175000017500000000706411176115504022307 0ustar maniacmaniac/* * ECHO_CAN_JPAH * * by Jason Parker * * Based upon mg2ec.h - sort of. * This "echo can" will completely hose your audio. * Don't use it unless you're absolutely sure you know what you're doing. * * Copyright (C) 2007-2008, Digium, Inc. * * All rights reserved. * */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ #include #include #include #include #include #include #include static int debug; #define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args) #define debug_printk(level, fmt, args...) if (debug >= level) printk("%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args) static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec); static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec); static void echo_can_process(struct dahdi_echocan_state *ec, short *isig, const short *iref, u32 size); static int echo_can_traintap(struct dahdi_echocan_state *ec, int pos, short val); static const struct dahdi_echocan_factory my_factory = { .name = "JPAH", .owner = THIS_MODULE, .echocan_create = echo_can_create, }; static const struct dahdi_echocan_ops my_ops = { .name = "JPAH", .echocan_free = echo_can_free, .echocan_process = echo_can_process, .echocan_traintap = echo_can_traintap, }; struct ec_pvt { struct dahdi_echocan_state dahdi; int blah; }; #define dahdi_to_pvt(a) container_of(a, struct ec_pvt, dahdi) static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec) { struct ec_pvt *pvt; if (ecp->param_count > 0) { printk(KERN_WARNING "JPAH does not support parameters; failing request\n"); return -EINVAL; } pvt = kzalloc(sizeof(*pvt), GFP_KERNEL); if (!pvt) return -ENOMEM; pvt->dahdi.ops = &my_ops; *ec = &pvt->dahdi; return 0; } static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec) { struct ec_pvt *pvt = dahdi_to_pvt(ec); kfree(pvt); } static void echo_can_process(struct dahdi_echocan_state *ec, short *isig, const short *iref, u32 size) { struct ec_pvt *pvt = dahdi_to_pvt(ec); u32 x; for (x = 0; x < size; x++) { if (pvt->blah < 2) { pvt->blah++; *isig++ = 0; } else { pvt->blah = 0; isig++; } } } static int echo_can_traintap(struct dahdi_echocan_state *ec, int pos, short val) { return 0; } static int __init mod_init(void) { if (dahdi_register_echocan_factory(&my_factory)) { module_printk(KERN_ERR, "could not register with DAHDI core\n"); return -EPERM; } module_printk(KERN_NOTICE, "Registered echo canceler '%s'\n", my_factory.name); return 0; } static void __exit mod_exit(void) { dahdi_unregister_echocan_factory(&my_factory); } module_param(debug, int, S_IRUGO | S_IWUSR); MODULE_DESCRIPTION("DAHDI Jason Parker Audio Hoser"); MODULE_AUTHOR("Jason Parker "); MODULE_LICENSE("GPL v2"); module_init(mod_init); module_exit(mod_exit); dahdi-linux-2.2.0-rc4/drivers/dahdi/dahdi_dynamic_eth.c0000644000175000017500000002343711101704316022164 0ustar maniacmaniac/* * Dynamic Span Interface for DAHDI (Ethernet Interface) * * Written by Mark Spencer * * Copyright (C) 2001-2008, Digium, Inc. * * All rights reserved. * */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ #include #include #include #include #include #include #include #include #include #include #define ETH_P_DAHDI_DETH 0xd00d struct ztdeth_header { unsigned short subaddr; }; /* We take the raw message, put it in an ethernet frame, and add a two byte addressing header at the top for future use */ #ifdef DEFINE_SPINLOCK static DEFINE_SPINLOCK(zlock); #else static spinlock_t zlock = SPIN_LOCK_UNLOCKED; #endif static struct sk_buff_head skbs; static struct ztdeth { unsigned char addr[ETH_ALEN]; unsigned short subaddr; /* Network byte order */ struct dahdi_span *span; char ethdev[IFNAMSIZ]; struct net_device *dev; struct ztdeth *next; } *zdevs = NULL; static struct dahdi_span *ztdeth_getspan(unsigned char *addr, unsigned short subaddr) { unsigned long flags; struct ztdeth *z; struct dahdi_span *span = NULL; spin_lock_irqsave(&zlock, flags); z = zdevs; while(z) { if (!memcmp(addr, z->addr, ETH_ALEN) && z->subaddr == subaddr) break; z = z->next; } if (z) span = z->span; spin_unlock_irqrestore(&zlock, flags); return span; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14) static int ztdeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) #else static int ztdeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt) #endif { struct dahdi_span *span; struct ztdeth_header *zh; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) zh = (struct ztdeth_header *)skb_network_header(skb); #else zh = (struct ztdeth_header *)skb->nh.raw; #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9) span = ztdeth_getspan(eth_hdr(skb)->h_source, zh->subaddr); #else span = ztdeth_getspan(skb->mac.ethernet->h_source, zh->subaddr); #endif if (span) { skb_pull(skb, sizeof(struct ztdeth_header)); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) skb_linearize(skb); #else skb_linearize(skb, GFP_KERNEL); #endif dahdi_dynamic_receive(span, (unsigned char *)skb->data, skb->len); } kfree_skb(skb); return 0; } static int ztdeth_notifier(struct notifier_block *block, unsigned long event, void *ptr) { struct net_device *dev = ptr; struct ztdeth *z; unsigned long flags; switch(event) { case NETDEV_GOING_DOWN: case NETDEV_DOWN: spin_lock_irqsave(&zlock, flags); z = zdevs; while(z) { /* Note that the device no longer exists */ if (z->dev == dev) z->dev = NULL; z = z->next; } spin_unlock_irqrestore(&zlock, flags); break; case NETDEV_UP: spin_lock_irqsave(&zlock, flags); z = zdevs; while(z) { /* Now that the device exists again, use it */ if (!strcmp(z->ethdev, dev->name)) z->dev = dev; z = z->next; } spin_unlock_irqrestore(&zlock, flags); break; } return 0; } static int ztdeth_transmit(void *pvt, unsigned char *msg, int msglen) { struct ztdeth *z; struct sk_buff *skb; struct ztdeth_header *zh; unsigned long flags; struct net_device *dev; unsigned char addr[ETH_ALEN]; unsigned short subaddr; /* Network byte order */ spin_lock_irqsave(&zlock, flags); z = pvt; if (z->dev) { /* Copy fields to local variables to remove spinlock ASAP */ dev = z->dev; memcpy(addr, z->addr, sizeof(z->addr)); subaddr = z->subaddr; spin_unlock_irqrestore(&zlock, flags); skb = dev_alloc_skb(msglen + dev->hard_header_len + sizeof(struct ztdeth_header) + 32); if (skb) { /* Reserve header space */ skb_reserve(skb, dev->hard_header_len + sizeof(struct ztdeth_header)); /* Copy message body */ memcpy(skb_put(skb, msglen), msg, msglen); /* Throw on header */ zh = (struct ztdeth_header *)skb_push(skb, sizeof(struct ztdeth_header)); zh->subaddr = subaddr; /* Setup protocol and such */ skb->protocol = __constant_htons(ETH_P_DAHDI_DETH); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) skb_set_network_header(skb, 0); #else skb->nh.raw = skb->data; #endif skb->dev = dev; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) dev_hard_header(skb, dev, ETH_P_DAHDI_DETH, addr, dev->dev_addr, skb->len); #else if (dev->hard_header) dev->hard_header(skb, dev, ETH_P_DAHDI_DETH, addr, dev->dev_addr, skb->len); #endif skb_queue_tail(&skbs, skb); } } else spin_unlock_irqrestore(&zlock, flags); return 0; } static int ztdeth_flush(void) { struct sk_buff *skb; /* Handle all transmissions now */ while ((skb = skb_dequeue(&skbs))) { dev_queue_xmit(skb); } return 0; } static struct packet_type ztdeth_ptype = { .type = __constant_htons(ETH_P_DAHDI_DETH), /* Protocol */ .dev = NULL, /* Device (NULL = wildcard) */ .func = ztdeth_rcv, /* Receiver */ }; static int digit2int(char d) { switch(d) { case 'F': case 'E': case 'D': case 'C': case 'B': case 'A': return d - 'A' + 10; case 'f': case 'e': case 'd': case 'c': case 'b': case 'a': return d - 'a' + 10; case '9': case '8': case '7': case '6': case '5': case '4': case '3': case '2': case '1': case '0': return d - '0'; } return -1; } static int hex2int(char *s) { int res; int tmp; /* Gotta be at least one digit */ if (strlen(s) < 1) return -1; /* Can't be more than two */ if (strlen(s) > 2) return -1; /* Grab the first digit */ res = digit2int(s[0]); if (res < 0) return -1; tmp = res; /* Grab the next */ if (strlen(s) > 1) { res = digit2int(s[1]); if (res < 0) return -1; tmp = tmp * 16 + res; } return tmp; } static void ztdeth_destroy(void *pvt) { struct ztdeth *z = pvt; unsigned long flags; struct ztdeth *prev=NULL, *cur; spin_lock_irqsave(&zlock, flags); cur = zdevs; while(cur) { if (cur == z) { if (prev) prev->next = cur->next; else zdevs = cur->next; break; } prev = cur; cur = cur->next; } spin_unlock_irqrestore(&zlock, flags); if (cur == z) { /* Successfully removed */ printk(KERN_INFO "TDMoE: Removed interface for %s\n", z->span->name); kfree(z); module_put(THIS_MODULE); } } static void *ztdeth_create(struct dahdi_span *span, char *addr) { struct ztdeth *z; char src[256]; char tmp[256], *tmp2, *tmp3, *tmp4 = NULL; int res,x; unsigned long flags; z = kmalloc(sizeof(struct ztdeth), GFP_KERNEL); if (z) { /* Zero it out */ memset(z, 0, sizeof(struct ztdeth)); /* Address should be /[/subaddr] */ dahdi_copy_string(tmp, addr, sizeof(tmp)); tmp2 = strchr(tmp, '/'); if (tmp2) { *tmp2 = '\0'; tmp2++; dahdi_copy_string(z->ethdev, tmp, sizeof(z->ethdev)); } else { printk(KERN_NOTICE "Invalid TDMoE address (no device) '%s'\n", addr); kfree(z); return NULL; } if (tmp2) { tmp4 = strchr(tmp2+1, '/'); if (tmp4) { *tmp4 = '\0'; tmp4++; } /* We don't have SSCANF :( Gotta do this the hard way */ tmp3 = strchr(tmp2, ':'); for (x=0;x<6;x++) { if (tmp2) { if (tmp3) { *tmp3 = '\0'; tmp3++; } res = hex2int(tmp2); if (res < 0) break; z->addr[x] = res & 0xff; } else break; if ((tmp2 = tmp3)) tmp3 = strchr(tmp2, ':'); } if (x != 6) { printk(KERN_NOTICE "TDMoE: Invalid MAC address in: %s\n", addr); kfree(z); return NULL; } } else { printk(KERN_NOTICE "TDMoE: Missing MAC address\n"); kfree(z); return NULL; } if (tmp4) { int sub = 0; int mul = 1; /* We have a subaddr */ tmp3 = tmp4 + strlen (tmp4) - 1; while (tmp3 >= tmp4) { if (*tmp3 >= '0' && *tmp3 <= '9') { sub += (*tmp3 - '0') * mul; } else { printk(KERN_NOTICE "TDMoE: Invalid subaddress\n"); kfree(z); return NULL; } mul *= 10; tmp3--; } z->subaddr = htons(sub); } z->dev = dev_get_by_name( #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) &init_net, #endif z->ethdev); if (!z->dev) { printk(KERN_NOTICE "TDMoE: Invalid device '%s'\n", z->ethdev); kfree(z); return NULL; } z->span = span; src[0] ='\0'; for (x=0;x<5;x++) sprintf(src + strlen(src), "%02x:", z->dev->dev_addr[x]); sprintf(src + strlen(src), "%02x", z->dev->dev_addr[5]); printk(KERN_INFO "TDMoE: Added new interface for %s at %s (addr=%s, src=%s, subaddr=%d)\n", span->name, z->dev->name, addr, src, ntohs(z->subaddr)); spin_lock_irqsave(&zlock, flags); z->next = zdevs; zdevs = z; spin_unlock_irqrestore(&zlock, flags); if(!try_module_get(THIS_MODULE)) printk(KERN_DEBUG "TDMoE: Unable to increment module use count\n"); } return z; } static struct dahdi_dynamic_driver ztd_eth = { "eth", "Ethernet", ztdeth_create, ztdeth_destroy, ztdeth_transmit, ztdeth_flush }; static struct notifier_block ztdeth_nblock = { .notifier_call = ztdeth_notifier, }; static int __init ztdeth_init(void) { dev_add_pack(&ztdeth_ptype); register_netdevice_notifier(&ztdeth_nblock); dahdi_dynamic_register(&ztd_eth); skb_queue_head_init(&skbs); return 0; } static void __exit ztdeth_exit(void) { dev_remove_pack(&ztdeth_ptype); unregister_netdevice_notifier(&ztdeth_nblock); dahdi_dynamic_unregister(&ztd_eth); } MODULE_DESCRIPTION("DAHDI Dynamic TDMoE Support"); MODULE_AUTHOR("Mark Spencer "); MODULE_LICENSE("GPL v2"); module_init(ztdeth_init); module_exit(ztdeth_exit); dahdi-linux-2.2.0-rc4/drivers/dahdi/datamods/0000755000175000017500000000000011202066031020163 5ustar maniacmaniacdahdi-linux-2.2.0-rc4/drivers/dahdi/datamods/Makefile0000644000175000017500000000154410751714440021643 0ustar maniacmaniac.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 dahdi-linux-2.2.0-rc4/drivers/dahdi/datamods/hdlc_ppp.c0000644000175000017500000000503210751714440022134 0ustar maniacmaniac/* * 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; } dahdi-linux-2.2.0-rc4/drivers/dahdi/datamods/hdlc_fr.c0000644000175000017500000007204110751714440021750 0ustar maniacmaniac/* * 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; } dahdi-linux-2.2.0-rc4/drivers/dahdi/datamods/hdlc_raw.c0000644000175000017500000000432010751714440022125 0ustar maniacmaniac/* * 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; } dahdi-linux-2.2.0-rc4/drivers/dahdi/datamods/hdlc_cisco.c0000644000175000017500000002072010751714440022436 0ustar maniacmaniac/* * 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; } dahdi-linux-2.2.0-rc4/drivers/dahdi/datamods/syncppp.c0000644000175000017500000011576111027030713022041 0ustar maniacmaniac/* * 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 4436 2008-06-20 22:40:11Z kpfleming $ */ #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 v2"); dahdi-linux-2.2.0-rc4/drivers/dahdi/datamods/hdlc_raw_eth.c0000644000175000017500000000541110751714440022767 0ustar maniacmaniac/* * 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; } dahdi-linux-2.2.0-rc4/drivers/dahdi/datamods/hdlc_generic.c0000644000175000017500000001641110751714440022754 0ustar maniacmaniac/* * 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); dahdi-linux-2.2.0-rc4/drivers/dahdi/makefw.c0000644000175000017500000000345011046411244020015 0ustar maniacmaniac/* Xilinx firmware convertor program. * * Written by Jim Dixon . * * Copyright (C) 2001 Jim Dixon / Zapata Telephony. * Copyright (C) 2001-2008 Digium, Inc. * * All rights reserved. * */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ #include #include #include #define SWATH 12 int main(int argc, char *argv[]) { FILE *fp; int i,j,nbytes; unsigned char c; char buf[300]; if (argc < 3) { puts("Usage... makefw filename.rbt array_name"); exit(1); } fp = fopen(argv[1],"r"); if (!fp) { perror("bit file open"); exit(1); } nbytes = 0; printf("static unsigned char %s[] = {\n",argv[2]); i = 0; while(fgets(buf,sizeof(buf) - 1,fp)) { if (!buf[0]) continue; if (buf[strlen(buf) - 1] < ' ') buf[strlen(buf) - 1] = 0; if (!buf[0]) continue; if (buf[strlen(buf) - 1] < ' ') buf[strlen(buf) - 1] = 0; if (!buf[0]) continue; if (strlen(buf) < 32) continue; if ((buf[0] != '0') && (buf[0] != '1')) continue; c = 0; for(j = 0; buf[j]; j++) { if (buf[j] > '0') c |= 1 << (j & 7); if ((j & 7) == 7) { nbytes++; if (i) printf(","); printf("0x%02x",c); if (i++ == SWATH) { printf(",\n"); i = 0; } c = 0; } } } printf("\n};\n\n"); fprintf(stderr,"Loaded %d bytes from file\n",nbytes); fclose(fp); exit(0); } dahdi-linux-2.2.0-rc4/drivers/dahdi/tor2.c0000644000175000017500000013373211137411244017441 0ustar maniacmaniac/* * 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-2008, Digium, Inc. * */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ #include #include #include #include #include #include #include #include #include #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 */ __iomem 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 */ __iomem 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 */ __iomem volatile unsigned char *mem8; /* Virtual representation of 8 bit Xilinx memory area */ struct dahdi_span spans[SPANS_PER_CARD]; /* Spans */ struct tor2_span tspans[SPANS_PER_CARD]; /* Span data */ struct dahdi_chan **chans[SPANS_PER_CARD]; /* Pointers to card channels */ 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][DAHDI_CHUNKSIZE]; /* first EC chunk buffer */ unsigned char ec_chunk2[SPANS_PER_CARD][32][DAHDI_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 static 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 dahdi_span *span); static int tor2_shutdown(struct dahdi_span *span); static int tor2_rbsbits(struct dahdi_chan *chan, int bits); static int tor2_maint(struct dahdi_span *span, int cmd); static int tor2_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long data); DAHDI_IRQ_HANDLER(tor2_intr); /* translations of data channels for 24 channels in a 32 bit PCM highway */ static 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 */ static 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 dahdi_span *span, struct dahdi_lineconfig *lc) { int i; struct tor2_span *p = span->pvt; if (debug) printk(KERN_INFO "Tor2: Configuring span %d\n", span->spanno); if ((lc->sync < 0) || (lc->sync >= SPANS_PER_CARD)) { printk(KERN_WARNING "%s %d: invalid span timing value %d.\n", THIS_MODULE->name, span->spanno, lc->sync); return -EINVAL; } 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 & DAHDI_FLAG_RUNNING) return tor2_startup(span); return 0; } static int tor2_chanconfig(struct dahdi_chan *chan, int sigtype) { int alreadyrunning; unsigned long flags; struct tor2_chan *p = chan->pvt; alreadyrunning = chan->span->flags & DAHDI_FLAG_RUNNING; if (debug) { if (alreadyrunning) printk(KERN_INFO "Tor2: Reconfigured channel %d (%s) sigtype %d\n", chan->channo, chan->name, sigtype); else printk(KERN_INFO "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 dahdi_chan *chan) { return 0; } static int tor2_close(struct dahdi_chan *chan) { return 0; } static void init_spans(struct tor2 *tor) { int x, y, c; /* TODO: a debug printk macro */ 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"; dahdi_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 = DAHDI_LAW_MULAW; tor->spans[x].linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS | DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF; tor->spans[x].spantype = "T1"; } else { tor->spans[x].channels = 31; tor->spans[x].deflaw = DAHDI_LAW_ALAW; tor->spans[x].linecompat = DAHDI_CONFIG_HDB3 | DAHDI_CONFIG_CCS | DAHDI_CONFIG_CRC4; tor->spans[x].spantype = "E1"; } tor->spans[x].chans = tor->chans[x]; tor->spans[x].flags = DAHDI_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 dahdi_chan *mychans = tor->chans[x][y]; sprintf(mychans->name, "Tor2/%d/%d/%d", tor->num, x + 1, y + 1); mychans->sigcap = DAHDI_SIG_EM | DAHDI_SIG_CLEAR | DAHDI_SIG_FXSLS | DAHDI_SIG_FXSGS | DAHDI_SIG_FXSKS | DAHDI_SIG_FXOLS | DAHDI_SIG_FXOGS | DAHDI_SIG_FXOKS | DAHDI_SIG_CAS | DAHDI_SIG_SF | DAHDI_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 (test_bit(DAHDI_FLAGBIT_REGISTERED, &tor->spans[0].flags)) return 0; printk(KERN_INFO "Tor2: Launching card: %d\n", tor->order); if (dahdi_register(&tor->spans[0], 0)) { printk(KERN_ERR "Unable to register span %s\n", tor->spans[0].name); return -1; } if (dahdi_register(&tor->spans[1], 0)) { printk(KERN_ERR "Unable to register span %s\n", tor->spans[1].name); dahdi_unregister(&tor->spans[0]); return -1; } if (dahdi_register(&tor->spans[2], 0)) { printk(KERN_ERR "Unable to register span %s\n", tor->spans[2].name); dahdi_unregister(&tor->spans[0]); dahdi_unregister(&tor->spans[1]); return -1; } if (dahdi_register(&tor->spans[3], 0)) { printk(KERN_ERR "Unable to register span %s\n", tor->spans[3].name); dahdi_unregister(&tor->spans[0]); dahdi_unregister(&tor->spans[1]); dahdi_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 void free_tor(struct tor2 *tor) { unsigned int x, f; for (x = 0; x < SPANS_PER_CARD; x++) { for (f = 0; f < (tor->cardtype == TYPE_E1 ? 31 : 24); f++) { if (tor->chans[x][f]) { kfree(tor->chans[x][f]); } } if (tor->chans[x]) kfree(tor->chans[x]); } kfree(tor); } static int __devinit tor2_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { int res,x,f; int ret = -ENODEV; struct tor2 *tor; unsigned long endjif; __iomem 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); /* 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(KERN_INFO "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(KERN_ERR "No cards[] slot available!!\n"); goto err_out_release_all; } tor->num = x; cards[x] = tor; /* start programming mode */ gpdata_io = (__iomem 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(KERN_ERR "Timeout waiting for INIT and DONE to go low\n"); goto err_out_release_all; } if (debug) printk(KERN_ERR "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(KERN_ERR "Timeout waiting for INIT to go high\n"); goto err_out_release_all; } if (debug) printk(KERN_ERR "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(KERN_DEBUG "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(KERN_DEBUG "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(KERN_ERR "Drove Init low!! CRC Error!!!\n"); goto err_out_release_all; } if (!(le32_to_cpu(*gpdata_io) & GPIO_DONE)) { printk(KERN_ERR "Did not get DONE signal. Short file maybe??\n"); goto err_out_release_all; } printk(KERN_INFO "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 = (__iomem 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 = (__iomem 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, DAHDI_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(KERN_INFO "Tormenta 2 Quad E1/PRA Card\n"); tor->cardtype = TYPE_E1; tor->datxlt = datxlt_e1; } else { printk(KERN_INFO "Tormenta 2 Quad T1/PRI Card\n"); tor->cardtype = TYPE_T1; tor->datxlt = datxlt_t1; } for (x = 0; x < SPANS_PER_CARD; x++) { int num_chans = tor->cardtype == TYPE_E1 ? 31 : 24; if (!(tor->chans[x] = kmalloc(num_chans * sizeof(*tor->chans[x]), GFP_KERNEL))) { printk(KERN_ERR "tor2: Not enough memory for chans[%d]\n", x); ret = -ENOMEM; goto err_out_release_all; } for (f = 0; f < (num_chans); f++) { if (!(tor->chans[x][f] = kmalloc(sizeof(*tor->chans[x][f]), GFP_KERNEL))) { printk(KERN_ERR "tor2: Not enough memory for chans[%d][%d]\n", x, f); ret = -ENOMEM; goto err_out_release_all; } memset(tor->chans[x][f], 0, sizeof(*tor->chans[x][f])); } } init_spans(tor); tor->order = tor->mem8[SWREG]; printk(KERN_INFO "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(tor->plx); if (tor->mem8) iounmap(tor->mem8); if (tor->mem32) iounmap(tor->mem32); if (tor) { free_tor(tor); } return -ENODEV; } static struct pci_driver tor2_driver; static void __devexit tor2_remove(struct pci_dev *pdev) { struct tor2 *tor; int i; 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); for (i = 0; i < SPANS_PER_CARD; ++i) { if (test_bit(DAHDI_FLAGBIT_REGISTERED, &tor->spans[i].flags)) dahdi_unregister(&tor->spans[i]); } 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(tor->plx); if (tor->mem8) iounmap(tor->mem8); if (tor->mem32) iounmap(tor->mem32); cards[tor->num] = NULL; pci_set_drvdata(pdev, NULL); free_tor(tor); } static struct pci_driver tor2_driver = { .name = "tormenta2", .probe = tor2_probe, .remove = __devexit_p(tor2_remove), .id_table = tor2_pci_ids, }; static int __init tor2_init(void) { int res; res = dahdi_pci_module(&tor2_driver); printk(KERN_INFO "Registered Tormenta2 PCI\n"); return res; } static void __exit tor2_cleanup(void) { pci_unregister_driver(&tor2_driver); printk(KERN_INFO "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 & DAHDI_FLAG_CLEAR) val |= 1 << (i % 8); if ((i % 8)==7) { #if 0 printk(KERN_DEBUG "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 dahdi_chan *chan, int bits) { u_char m,c; int k,n,b; struct tor2_chan *p = chan->pvt; unsigned long flags; #if 0 printk(KERN_DEBUG "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 & DAHDI_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 & DAHDI_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 & DAHDI_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 & DAHDI_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 dahdi_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(KERN_DEBUG "Tor2: Span '%d' isn't us?\n", span->spanno); return -1; } spin_lock_irqsave(&p->tor->lock, flags); wasrunning = span->flags & DAHDI_FLAG_RUNNING; span->flags &= ~DAHDI_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 & DAHDI_FLAG_RUNNING) && !(p->tor->spans[1].flags & DAHDI_FLAG_RUNNING) && !(p->tor->spans[2].flags & DAHDI_FLAG_RUNNING) && !(p->tor->spans[3].flags & DAHDI_FLAG_RUNNING)) /* No longer in use, disable interrupts */ p->tor->mem8[CTLREG] = 0; if (debug) printk(KERN_DEBUG"Span %d (%s) shutdown\n", span->spanno, span->name); return 0; } static int tor2_startup(struct dahdi_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(KERN_DEBUG "Tor2: Span '%d' isn't us?\n", span->spanno); return -1; } spin_lock_irqsave(&p->tor->lock, flags); alreadyrunning = span->flags & DAHDI_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], DAHDI_LIN2X(0,span->chans[i]),DAHDI_CHUNKSIZE); memset(p->tor->ec_chunk2[p->span][i], DAHDI_LIN2X(0,span->chans[i]),DAHDI_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 & DAHDI_CONFIG_CCS) { ccr1 |= 8; /* CCR1: Rx Sig mode: CCS */ coding = "CCS"; } else { tcr1 |= 0x20; coding = "CAS"; } if (span->lineconfig & DAHDI_CONFIG_HDB3) { ccr1 |= 0x44; /* CCR1: TX and RX HDB3 */ framing = "HDB3"; } else framing = "AMI"; if (span->lineconfig & DAHDI_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 |= DAHDI_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(KERN_INFO "Tor2: Reconfigured span %d (%s/%s%s) 120 Ohms\n", span->spanno, coding, framing, crcing); else printk(KERN_INFO "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 & DAHDI_CONFIG_ESF) i = 0x88; if (span->lineconfig & DAHDI_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 |= DAHDI_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(KERN_INFO "Tor2: Reconfigured span %d (%s/%s) LBO: %s\n", span->spanno, coding, framing, dahdi_lboname(span->txlevel)); else printk(KERN_INFO "Tor2: Startup span %d (%s/%s) LBO: %s\n", span->spanno, coding, framing, dahdi_lboname(span->txlevel)); } } if (p->tor->syncs[0] == span->spanno) printk(KERN_INFO "SPAN %d: Primary Sync Source\n",span->spanno); if (p->tor->syncs[1] == span->spanno) printk(KERN_INFO "SPAN %d: Secondary Sync Source\n",span->spanno); if (p->tor->syncs[2] == span->spanno) printk(KERN_INFO "SPAN %d: Tertiary Sync Source\n",span->spanno); if (p->tor->syncs[3] == span->spanno) printk(KERN_INFO "SPAN %d: Quaternary Sync Source\n",span->spanno); return 0; } static int tor2_maint(struct dahdi_span *span, int cmd) { struct tor2_span *p = span->pvt; int tspan = p->span + 1; if (p->tor->cardtype == TYPE_E1) { switch(cmd) { case DAHDI_MAINT_NONE: t1out(p->tor,tspan,0xa8,0); /* no loops */ break; case DAHDI_MAINT_LOCALLOOP: t1out(p->tor,tspan,0xa8,0x40); /* local loop */ break; case DAHDI_MAINT_REMOTELOOP: t1out(p->tor,tspan,0xa8,0x80); /* remote loop */ break; case DAHDI_MAINT_LOOPUP: case DAHDI_MAINT_LOOPDOWN: case DAHDI_MAINT_LOOPSTOP: return -ENOSYS; default: printk(KERN_NOTICE "Tor2: Unknown maint command: %d\n", cmd); break; } return 0; } switch(cmd) { case DAHDI_MAINT_NONE: t1out(p->tor,tspan,0x19,(japan ? 0x80 : 0x00)); /* no local loop */ t1out(p->tor,tspan,0x0a,0); /* no remote loop */ break; case DAHDI_MAINT_LOCALLOOP: t1out(p->tor,tspan,0x19,0x40 | (japan ? 0x80 : 0x00)); /* local loop */ t1out(p->tor,tspan,0x0a,0); /* no remote loop */ break; case DAHDI_MAINT_REMOTELOOP: t1out(p->tor,tspan,0x1e,(japan ? 0x80 : 0x00)); /* no local loop */ t1out(p->tor,tspan,0x0a,0x40); /* remote loop */ break; case DAHDI_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 DAHDI_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 DAHDI_MAINT_LOOPSTOP: t1out(p->tor,tspan,0x30,0); /* stop sending loopup code */ break; default: printk(KERN_NOTICE "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 & DAHDI_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++) { dahdi_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], DAHDI_CHUNKSIZE); memcpy(tor->ec_chunk1[x][y], tor->spans[x].chans[y]->writechunk, DAHDI_CHUNKSIZE); } dahdi_receive(&tor->spans[x]); } } for (x = 0; x < SPANS_PER_CARD; x++) { if (tor->spans[x].flags & DAHDI_FLAG_RUNNING) dahdi_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; /* DAHDI 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 & (DAHDI_ALARM_RED | DAHDI_ALARM_BLUE | DAHDI_ALARM_LOOPBACK)) && (cards[x]->spans[i].flags & DAHDI_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(KERN_DEBUG "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(KERN_DEBUG "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(KERN_DEBUG "Card %d, using Timing Bus, NOT master\n", tor->num); } } spin_unlock_irqrestore(&synclock, flags); return 0; } DAHDI_IRQ_HANDLER(tor2_intr) { int n, i, j, k, newsyncsrc; 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 */ { return IRQ_NONE; } 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(KERN_DEBUG "Interrupt handler\n"); #endif /* do the transmit output */ for (n = 0; n < tor->spans[0].channels; n++) { for (i = 0; i < DAHDI_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 < DAHDI_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 & DAHDI_SIG_CLEAR)) dahdi_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 & DAHDI_SIG_CLEAR)) dahdi_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 |= DAHDI_ABIT; if (bbits & (1 << j)) rxc |= DAHDI_BBIT; if (tor->spans[k].chans[i]->rxsig != rxc) { /* Check for changes in received bits */ if (!(tor->spans[k].chans[i]->sig & DAHDI_SIG_CLEAR)) { dahdi_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 &= ~DAHDI_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 */ dahdi_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 != DAHDI_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 = DAHDI_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 == DAHDI_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 = DAHDI_MAINT_NONE; } } else tor->loopdowncnt[i] = 0; if (c & 3) /* if red alarm */ { j |= DAHDI_ALARM_RED; } if (c & 8) /* if blue alarm */ { j |= DAHDI_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 |= DAHDI_ALARM_RED; } if (c & 2) /* if blue alarm */ { j |= DAHDI_ALARM_BLUE; } } /* only consider previous carrier alarm state */ tor->spans[i].alarms &= (DAHDI_ALARM_RED | DAHDI_ALARM_BLUE | DAHDI_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 & DAHDI_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 & DAHDI_FLAG_OPEN) || ((tor->chans[i][k])->flags & DAHDI_FLAG_NETDEV)) n++; } /* if none open, set alarm condition */ if (!n) j |= DAHDI_ALARM_NOTOPEN; } /* if no more alarms, and we had some */ if ((!j) && tor->spans[i].alarms) { tor->alarmtimer[i] = DAHDI_ALARMSETTLE_TIME; } if (tor->alarmtimer[i]) j |= DAHDI_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 |= DAHDI_ALARM_YELLOW; if (tor->spans[i].maintstat || tor->spans[i].mainttimer) j |= DAHDI_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 & DAHDI_FLAG_RUNNING) { if (j & DAHDI_ALARM_RED) tor->leds |= LEDRED << (2 * i); else if (j & DAHDI_ALARM_YELLOW) tor->leds |= (LEDRED | LEDGREEN) << (2 * i); else tor->leds |= LEDGREEN << (2 * i); } tor->mem8[LEDREG] = tor->leds; dahdi_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 & DAHDI_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; newsyncsrc = 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 & (DAHDI_ALARM_RED | DAHDI_ALARM_BLUE | DAHDI_ALARM_LOOPBACK))) { tor->syncsrc = tor->psyncs[0]; newsyncsrc = 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 & (DAHDI_ALARM_RED | DAHDI_ALARM_BLUE | DAHDI_ALARM_LOOPBACK))) { tor->syncsrc = tor->psyncs[i]; newsyncsrc = tor->syncs[i]; } } } /* update sync src info */ for (i = 0; i < SPANS_PER_CARD; i++) tor->spans[i].syncsrc = newsyncsrc; /* 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; return IRQ_RETVAL(1); } static int tor2_ioctl(struct dahdi_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 DAHDI Driver"); MODULE_LICENSE("GPL v2"); module_param(debug, int, 0600); module_param(loopback, int, 0600); module_param(timingcable, int, 0600); module_param(japan, int, 0600); MODULE_DEVICE_TABLE(pci, tor2_pci_ids); module_init(tor2_init); module_exit(tor2_cleanup); dahdi-linux-2.2.0-rc4/drivers/dahdi/arith.h0000644000175000017500000002047611046164220017665 0ustar maniacmaniac/* * Handy add/subtract functions to operate on chunks of shorts. * Feel free to add customizations for additional architectures * */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ #ifndef _DAHDI_ARITH_H #define _DAHDI_ARITH_H #ifdef CONFIG_DAHDI_MMX #ifdef DAHDI_CHUNKSIZE static inline void __ACSS(volatile short *dst, const short *src) { __asm__ __volatile__ ( "movq 0(%0), %%mm0;\n" "movq 0(%1), %%mm1;\n" "movq 8(%0), %%mm2;\n" "movq 8(%1), %%mm3;\n" "paddsw %%mm1, %%mm0;\n" "paddsw %%mm3, %%mm2;\n" "movq %%mm0, 0(%0);\n" "movq %%mm2, 8(%0);\n" : "=r" (dst) : "r" (src), "0" (dst) : "memory" #ifdef CLOBBERMMX , "%mm0", "%mm1", "%mm2", "%mm3" #endif ); } static inline void __SCSS(volatile short *dst, const short *src) { __asm__ __volatile__ ( "movq 0(%0), %%mm0;\n" "movq 0(%1), %%mm1;\n" "movq 8(%0), %%mm2;\n" "movq 8(%1), %%mm3;\n" "psubsw %%mm1, %%mm0;\n" "psubsw %%mm3, %%mm2;\n" "movq %%mm0, 0(%0);\n" "movq %%mm2, 8(%0);\n" : "=r" (dst) : "r" (src), "0" (dst) : "memory" #ifdef CLOBBERMMX , "%mm0", "%mm1", "%mm2", "%mm3" #endif ); } #if (DAHDI_CHUNKSIZE == 8) #define ACSS(a,b) __ACSS(a,b) #define SCSS(a,b) __SCSS(a,b) #elif (DAHDI_CHUNKSIZE > 8) static inline void ACSS(volatile short *dst, const short *src) { int x; for (x=0;x>= 4; /* Clear our accumulator, mm4 */ /* For every set of eight... Load 16 coefficients into four registers... Shift each word right 16 to make them shorts... Pack the resulting shorts into two registers... With the coefficients now in mm0 and mm2, load the history into mm1 and mm3... Multiply/add mm1 into mm0, and mm3 into mm2... Add mm2 into mm0 (without saturation, alas). Now we have two half-results. Accumulate in mm4 (again, without saturation, alas) */ __asm__ ( "pxor %%mm4, %%mm4;\n" "mov %1, %%edi;\n" "mov %2, %%esi;\n" "mov %3, %%ecx;\n" "1:" "movq 0(%%edi), %%mm0;\n" "movq 8(%%edi), %%mm1;\n" "movq 16(%%edi), %%mm2;\n" "movq 24(%%edi), %%mm3;\n" /* can't use 4/5 since 4 is the accumulator for us */ "movq 32(%%edi), %%mm6;\n" "movq 40(%%edi), %%mm7;\n" "psrad $16, %%mm0;\n" "psrad $16, %%mm1;\n" "psrad $16, %%mm2;\n" "psrad $16, %%mm3;\n" "psrad $16, %%mm6;\n" "psrad $16, %%mm7;\n" "packssdw %%mm1, %%mm0;\n" "packssdw %%mm3, %%mm2;\n" "packssdw %%mm7, %%mm6;\n" "movq 0(%%esi), %%mm1;\n" "movq 8(%%esi), %%mm3;\n" "movq 16(%%esi), %%mm7;\n" "pmaddwd %%mm1, %%mm0;\n" "pmaddwd %%mm3, %%mm2;\n" "pmaddwd %%mm7, %%mm6;\n" "paddd %%mm6, %%mm4;\n" "paddd %%mm2, %%mm4;\n" "paddd %%mm0, %%mm4;\n" /* Come back and do for the last few bytes */ "movq 48(%%edi), %%mm6;\n" "movq 56(%%edi), %%mm7;\n" "psrad $16, %%mm6;\n" "psrad $16, %%mm7;\n" "packssdw %%mm7, %%mm6;\n" "movq 24(%%esi), %%mm7;\n" "pmaddwd %%mm7, %%mm6;\n" "paddd %%mm6, %%mm4;\n" "add $64, %%edi;\n" "add $32, %%esi;\n" "dec %%ecx;\n" "jnz 1b;\n" "movq %%mm4, %%mm0;\n" "psrlq $32, %%mm0;\n" "paddd %%mm0, %%mm4;\n" "movd %%mm4, %0;\n" : "=r" (sum) : "r" (coeffs), "r" (hist), "r" (len) : "%ecx", "%edi", "%esi" ); return sum; } static inline void UPDATE(volatile int *taps, const short *history, const int nsuppr, const int ntaps) { int i; int correction; for (i=0;i>= 4; /* First, load up taps, */ __asm__ ( "pxor %%mm4, %%mm4;\n" "mov %0, %%edi;\n" "mov %1, %%esi;\n" "mov %3, %%ecx;\n" "1:" "jnz 1b;\n" "movq %%mm4, %%mm0;\n" "psrlq $32, %%mm0;\n" "paddd %%mm0, %%mm4;\n" "movd %%mm4, %0;\n" : "=r" (taps), "=r" (taps_short) : "r" (history), "r" (nsuppr), "r" (ntaps), "0" (taps) : "%ecx", "%edi", "%esi" ); #endif #if 1 for (i=0;i> 16; } #endif } static inline int CONVOLVE2(const short *coeffs, const short *hist, int len) { int sum; /* Divide length by 16 */ len >>= 4; /* Clear our accumulator, mm4 */ /* For every set of eight... Load in eight coefficients and eight historic samples, multliply add and accumulate the result */ __asm__ ( "pxor %%mm4, %%mm4;\n" "mov %1, %%edi;\n" "mov %2, %%esi;\n" "mov %3, %%ecx;\n" "1:" "movq 0(%%edi), %%mm0;\n" "movq 8(%%edi), %%mm2;\n" "movq 0(%%esi), %%mm1;\n" "movq 8(%%esi), %%mm3;\n" "pmaddwd %%mm1, %%mm0;\n" "pmaddwd %%mm3, %%mm2;\n" "paddd %%mm2, %%mm4;\n" "paddd %%mm0, %%mm4;\n" "movq 16(%%edi), %%mm0;\n" "movq 24(%%edi), %%mm2;\n" "movq 16(%%esi), %%mm1;\n" "movq 24(%%esi), %%mm3;\n" "pmaddwd %%mm1, %%mm0;\n" "pmaddwd %%mm3, %%mm2;\n" "paddd %%mm2, %%mm4;\n" "paddd %%mm0, %%mm4;\n" "add $32, %%edi;\n" "add $32, %%esi;\n" "dec %%ecx;\n" "jnz 1b;\n" "movq %%mm4, %%mm0;\n" "psrlq $32, %%mm0;\n" "paddd %%mm0, %%mm4;\n" "movd %%mm4, %0;\n" : "=r" (sum) : "r" (coeffs), "r" (hist), "r" (len) : "%ecx", "%edi", "%esi" ); return sum; } static inline short MAX16(const short *y, int len, int *pos) { int k; short max = 0; int bestpos = 0; for (k=0;k 32767) sum = 32767; else if (sum < -32768) sum = -32768; dst[x] = sum; } #endif } static inline void SCSS(short *dst, short *src) { int x; /* Subtract src from dst with saturation, storing in dst */ #ifdef BFIN for (x = 0; x < DAHDI_CHUNKSIZE; x++) dst[x] = __builtin_bfin_sub_fr1x16(dst[x], src[x]); #else int sum; for (x = 0; x < DAHDI_CHUNKSIZE; x++) { sum = dst[x] - src[x]; if (sum > 32767) sum = 32767; else if (sum < -32768) sum = -32768; dst[x] = sum; } #endif } #endif /* DAHDI_CHUNKSIZE */ static inline int CONVOLVE(const int *coeffs, const short *hist, int len) { int x; int sum = 0; for (x=0;x> 16) * hist[x]; return sum; } static inline int CONVOLVE2(const short *coeffs, const short *hist, int len) { int x; int sum = 0; for (x=0;x> 16; } } static inline short MAX16(const short *y, int len, int *pos) { int k; short max = 0; int bestpos = 0; for (k=0;k * Copyright (C) 2008 Xorcom, Inc. * * All rights reserved. * * Based on dahdi_echocan_hpec.c, Copyright (C) 2006-2008 Digium, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include /* Fix this if OSLEC is elsewhere */ #include "../staging/echo/oslec.h" //#include #include #define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args) static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec); static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec); static void echo_can_process(struct dahdi_echocan_state *ec, short *isig, const short *iref, u32 size); static int echo_can_traintap(struct dahdi_echocan_state *ec, int pos, short val); static const struct dahdi_echocan_factory my_factory = { .name = "OSLEC", .owner = THIS_MODULE, .echocan_create = echo_can_create, }; static const struct dahdi_echocan_ops my_ops = { .name = "OSLEC", .echocan_free = echo_can_free, .echocan_process = echo_can_process, .echocan_traintap = echo_can_traintap, }; struct ec_pvt { struct oslec_state *oslec; struct dahdi_echocan_state dahdi; }; #define dahdi_to_pvt(a) container_of(a, struct ec_pvt, dahdi) static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec) { struct ec_pvt *pvt = dahdi_to_pvt(ec); oslec_free(pvt->oslec); kfree(pvt); } static void echo_can_process(struct dahdi_echocan_state *ec, short *isig, const short *iref, u32 size) { struct ec_pvt *pvt = dahdi_to_pvt(ec); u32 SampleNum; for (SampleNum = 0; SampleNum < size; SampleNum++, iref++) { short iCleanSample; iCleanSample = oslec_update(pvt->oslec, *iref, *isig); *isig++ = iCleanSample; } } static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec) { struct ec_pvt *pvt; if (ecp->param_count > 0) { printk(KERN_WARNING "OSLEC does not support parameters; failing request\n"); return -EINVAL; } pvt = kzalloc(sizeof(*pvt), GFP_KERNEL); if (!pvt) return -ENOMEM; pvt->dahdi.ops = &my_ops; pvt->oslec = oslec_create(ecp->tap_length, ECHO_CAN_USE_ADAPTION | ECHO_CAN_USE_NLP | ECHO_CAN_USE_CLIP | ECHO_CAN_USE_TX_HPF | ECHO_CAN_USE_RX_HPF); if (!pvt->oslec) { kfree(pvt); *ec = NULL; return -ENOTTY; } else { *ec = &pvt->dahdi; return 0; } } static int echo_can_traintap(struct dahdi_echocan_state *ec, int pos, short val) { return 1; } static int __init mod_init(void) { if (dahdi_register_echocan_factory(&my_factory)) { module_printk(KERN_ERR, "could not register with DAHDI core\n"); return -EPERM; } module_printk(KERN_INFO, "Registered echo canceler '%s'\n", my_factory.name); return 0; } static void __exit mod_exit(void) { dahdi_unregister_echocan_factory(&my_factory); } MODULE_DESCRIPTION("DAHDI OSLEC wrapper"); MODULE_AUTHOR("Tzafrir Cohen "); MODULE_LICENSE("GPL"); module_init(mod_init); module_exit(mod_exit); dahdi-linux-2.2.0-rc4/drivers/dahdi/dahdi_dummy.c0000644000175000017500000001555111176111353021036 0ustar maniacmaniac/* * Dummy DAHDI Driver for DAHDI Telephony interface * * Required: kernel > 2.6.0 * * Written by Robert Pleh * 2.6 version by Tony Hoyle * Unified by Mark Spencer * * Converted to use HighResTimers on i386 by Jeffery Palmer * * Copyright (C) 2002, Hermes Softlab * Copyright (C) 2004-2009, Digium, Inc. * * All rights reserved. * */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ /* * To use the high resolution timers, in your kernel CONFIG_HIGH_RES_TIMERS * needs to be enabled (Processor type and features -> High Resolution * Timer Support), and optionally HPET (Processor type and features -> * HPET Timer Support) provides a better clock source. */ #include #if defined(CONFIG_HIGH_RES_TIMERS) && \ LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) #define USE_HIGHRESTIMER #endif #include #include #include #include #include #include #if defined(USE_HIGHRESTIMER) #include #else #include #endif #include #ifndef HAVE_HRTIMER_ACCESSORS #if defined(USE_HIGHRESTIMER) && \ (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28)) /* Compatibility with new hrtimer interface */ static inline ktime_t hrtimer_get_expires(const struct hrtimer *timer) { return timer->expires; } static inline void hrtimer_set_expires(struct hrtimer *timer, ktime_t time) { timer->expires = time; } #endif #endif struct dahdi_dummy { struct dahdi_span span; struct dahdi_chan _chan; struct dahdi_chan *chan; #if !defined(USE_HIGHRESTIMER) unsigned long calls_since_start; struct timespec start_interval; #endif }; static struct dahdi_dummy *ztd; static int debug = 0; #ifdef USE_HIGHRESTIMER #define CLOCK_SRC "HRtimer" static struct hrtimer zaptimer; #define DAHDI_RATE 1000 /* DAHDI ticks per second */ #define DAHDI_TIME (1000000 / DAHDI_RATE) /* DAHDI tick time in us */ #define DAHDI_TIME_NS (DAHDI_TIME * 1000) /* DAHDI tick time in ns */ #else #define CLOCK_SRC "Linux26" static struct timer_list timer; static atomic_t shutdown; #define JIFFIES_INTERVAL (HZ/250) /* 4ms is fine for dahdi_dummy */ #endif /* Different bits of the debug variable: */ #define DEBUG_GENERAL (1 << 0) #define DEBUG_TICKS (1 << 1) #if defined(USE_HIGHRESTIMER) static enum hrtimer_restart dahdi_dummy_hr_int(struct hrtimer *htmr) { unsigned long overrun; /* Trigger DAHDI */ dahdi_receive(&ztd->span); dahdi_transmit(&ztd->span); /* Overrun should always return 1, since we are in the timer that * expired. * We should worry if overrun is 2 or more; then we really missed * a tick */ overrun = hrtimer_forward(&zaptimer, hrtimer_get_expires(htmr), ktime_set(0, DAHDI_TIME_NS)); if(overrun > 1) { if(printk_ratelimit()) printk(KERN_NOTICE "dahdi_dummy: HRTimer missed %lu ticks\n", overrun - 1); } if(debug && DEBUG_TICKS) { static int count = 0; /* Printk every 5 seconds, good test to see if timer is * running properly */ if (count++ % 5000 == 0) printk(KERN_DEBUG "dahdi_dummy: 5000 ticks from hrtimer\n"); } /* Always restart the timer */ return HRTIMER_RESTART; } #else static unsigned long timespec_diff_ms(struct timespec *t0, struct timespec *t1) { long nanosec, sec; unsigned long ms; sec = (t1->tv_sec - t0->tv_sec); nanosec = (t1->tv_nsec - t0->tv_nsec); while (nanosec >= NSEC_PER_SEC) { nanosec -= NSEC_PER_SEC; ++sec; } while (nanosec < 0) { nanosec += NSEC_PER_SEC; --sec; } ms = (sec * 1000) + (nanosec / 1000000L); return ms; } static void dahdi_dummy_timer(unsigned long param) { unsigned long ms_since_start; struct timespec now; const unsigned long MAX_INTERVAL = 100000L; if (!atomic_read(&shutdown)) mod_timer(&timer, jiffies + JIFFIES_INTERVAL); now = current_kernel_time(); ms_since_start = timespec_diff_ms(&ztd->start_interval, &now); while (ms_since_start > ztd->calls_since_start) { ztd->calls_since_start++; dahdi_receive(&ztd->span); dahdi_transmit(&ztd->span); } if (ms_since_start > MAX_INTERVAL) { ztd->calls_since_start = 0; ztd->start_interval = now; } } #endif static int dahdi_dummy_initialize(struct dahdi_dummy *ztd) { /* DAHDI stuff */ ztd->chan = &ztd->_chan; sprintf(ztd->span.name, "DAHDI_DUMMY/1"); snprintf(ztd->span.desc, sizeof(ztd->span.desc) - 1, "%s (source: " CLOCK_SRC ") %d", ztd->span.name, 1); sprintf(ztd->chan->name, "DAHDI_DUMMY/%d/%d", 1, 0); dahdi_copy_string(ztd->span.devicetype, "DAHDI Dummy Timing", 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 = DAHDI_LAW_MULAW; init_waitqueue_head(&ztd->span.maintq); ztd->span.pvt = ztd; ztd->chan->pvt = ztd; if (dahdi_register(&ztd->span, 0)) { return -1; } return 0; } int init_module(void) { ztd = kzalloc(sizeof(*ztd), GFP_KERNEL); if (ztd == NULL) { printk(KERN_ERR "dahdi_dummy: Unable to allocate memory\n"); return -ENOMEM; } if (dahdi_dummy_initialize(ztd)) { printk(KERN_ERR "dahdi_dummy: Unable to intialize DAHDI driver\n"); kfree(ztd); return -ENODEV; } #if defined(USE_HIGHRESTIMER) printk(KERN_DEBUG "dahdi_dummy: Trying to load High Resolution Timer\n"); hrtimer_init(&zaptimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); printk(KERN_DEBUG "dahdi_dummy: Initialized High Resolution Timer\n"); /* Set timer callback function */ zaptimer.function = dahdi_dummy_hr_int; printk(KERN_DEBUG "dahdi_dummy: Starting High Resolution Timer\n"); hrtimer_start(&zaptimer, ktime_set(0, DAHDI_TIME_NS), HRTIMER_MODE_REL); printk(KERN_INFO "dahdi_dummy: High Resolution Timer started, good to go\n"); #else init_timer(&timer); timer.function = dahdi_dummy_timer; ztd->start_interval = current_kernel_time(); timer.expires = jiffies + JIFFIES_INTERVAL; atomic_set(&shutdown, 0); add_timer(&timer); #endif if (debug) printk(KERN_DEBUG "dahdi_dummy: init() finished\n"); return 0; } void cleanup_module(void) { #if defined(USE_HIGHRESTIMER) /* Stop high resolution timer */ hrtimer_cancel(&zaptimer); #else atomic_set(&shutdown, 1); del_timer_sync(&timer); #endif dahdi_unregister(&ztd->span); kfree(ztd); if (debug) printk(KERN_DEBUG "dahdi_dummy: cleanup() finished\n"); } module_param(debug, int, 0600); MODULE_DESCRIPTION("Timing-Only Driver"); MODULE_AUTHOR("Robert Pleh "); MODULE_LICENSE("GPL v2"); dahdi-linux-2.2.0-rc4/drivers/dahdi/wcte12xp/0000755000175000017500000000000011202066031020044 5ustar maniacmaniacdahdi-linux-2.2.0-rc4/drivers/dahdi/wcte12xp/Makefile0000644000175000017500000000026011026016414021506 0ustar maniacmaniacifdef 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 dahdi-linux-2.2.0-rc4/drivers/dahdi/wcte12xp/base.c0000644000175000017500000015021611202062375021136 0ustar maniacmaniac/* * 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-2009, Digium, Inc. * * All rights reserved. * */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "wct4xxp/wct4xxp.h" /* For certain definitions */ #include "voicebus/voicebus.h" #include "wcte12xp.h" #include "voicebus/GpakCust.h" #include "voicebus/GpakApi.h" struct pci_driver te12xp_driver; 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; int vpmsupport = 1; static int vpmtsisupport = 0; int vpmnlptype = DEFAULT_NLPTYPE; int vpmnlpthresh = DEFAULT_NLPTHRESH; int vpmnlpmaxsupp = DEFAULT_NLPMAXSUPP; static int echocan_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec); static void echocan_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec); static const struct dahdi_echocan_features vpm150m_ec_features = { .NLP_automatic = 1, .CED_tx_detect = 1, .CED_rx_detect = 1, }; static const struct dahdi_echocan_ops vpm150m_ec_ops = { .name = "VPM150M", .echocan_free = echocan_free, }; 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 }; #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) static kmem_cache_t *cmd_cache; #else static struct kmem_cache *cmd_cache; #endif static struct command *get_free_cmd(struct t1 *wc) { struct command *cmd; cmd = kmem_cache_alloc(cmd_cache, GFP_ATOMIC); if (cmd) { memset(cmd, 0, sizeof(*cmd)); INIT_LIST_HEAD(&cmd->node); } return cmd; } static void free_cmd(struct t1 *wc, struct command *cmd) { kmem_cache_free(cmd_cache, cmd); } static struct command *get_pending_cmd(struct t1 *wc) { struct command *cmd = NULL; unsigned long flags; spin_lock_irqsave(&wc->cmd_list_lock, flags); if (!list_empty(&wc->pending_cmds)) { cmd = list_entry(wc->pending_cmds.next, struct command, node); list_move_tail(&cmd->node, &wc->active_cmds); } spin_unlock_irqrestore(&wc->cmd_list_lock, flags); return cmd; } static void submit_cmd(struct t1 *wc, struct command *cmd) { unsigned long flags; if (cmd->flags & (__CMD_RD | __CMD_PINS)) init_completion(&cmd->complete); spin_lock_irqsave(&wc->cmd_list_lock, flags); list_add_tail(&cmd->node, &wc->pending_cmds); spin_unlock_irqrestore(&wc->cmd_list_lock, flags); } static void resend_cmds(struct t1 *wc) { unsigned long flags; spin_lock_irqsave(&wc->cmd_list_lock, flags); list_splice_init(&wc->active_cmds, &wc->pending_cmds); spin_unlock_irqrestore(&wc->cmd_list_lock, flags); } static void cmd_dequeue(struct t1 *wc, volatile unsigned char *writechunk, int eframe, int slot) { struct command *curcmd=NULL; u16 address; u8 data; u32 flags; /* Skip audio */ writechunk += 66; /* Search for something waiting to transmit */ if ((slot < 6) && (eframe) && (eframe < DAHDI_CHUNKSIZE - 1)) { /* only 6 useable cs slots per */ /* framer */ curcmd = get_pending_cmd(wc); if (curcmd) { curcmd->cs_slot = slot; curcmd->ident = wc->txident; address = curcmd->address; data = curcmd->data; flags = curcmd->flags; } else { /* If nothing else, use filler */ address = 0x4a; data = 0; flags = __CMD_RD; } if (flags & __CMD_WR) writechunk[CMD_BYTE(slot, 0, 0)] = 0x0c; /* 0c write command */ else if (flags & __CMD_LEDS) writechunk[CMD_BYTE(slot, 0, 0)] = 0x10 | ((address) & 0x0E); /* led set command */ else if (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)] = address; writechunk[CMD_BYTE(slot, 2, 0)] = data; } } static inline void cmd_decipher(struct t1 *wc, volatile unsigned char *readchunk) { struct command *cmd = NULL; unsigned long flags; const int IS_VPM = 0; /* Skip audio */ readchunk += 66; spin_lock_irqsave(&wc->cmd_list_lock, flags); while (!list_empty(&wc->active_cmds)) { cmd = list_entry(wc->active_cmds.next, struct command, node); if (cmd->ident != wc->rxident) break; if (cmd->flags & (__CMD_WR | __CMD_LEDS)) { /* Nobody is waiting on writes...so let's just * free them here. */ list_del(&cmd->node); free_cmd(wc, cmd); } else { cmd->data |= readchunk[CMD_BYTE(cmd->cs_slot, 2, IS_VPM)]; list_del_init(&cmd->node); complete(&cmd->complete); } } spin_unlock_irqrestore(&wc->cmd_list_lock, flags); } inline void cmd_decipher_vpmadt032(struct t1 *wc, unsigned char *readchunk) { unsigned long flags; struct vpmadt032 *vpm = wc->vpmadt032; struct vpmadt032_cmd *cmd; BUG_ON(!vpm); /* If the hardware is not processing any commands currently, then * there is nothing for us to do here. */ if (list_empty(&vpm->active_cmds)) { return; } spin_lock_irqsave(&vpm->list_lock, flags); cmd = list_entry(vpm->active_cmds.next, struct vpmadt032_cmd, node); if (wc->rxident == cmd->txident) { list_del_init(&cmd->node); } else { cmd = NULL; } spin_unlock_irqrestore(&vpm->list_lock, flags); if (!cmd) { return; } /* Skip audio */ readchunk += 66; /* Store result */ cmd->data = (0xff & readchunk[CMD_BYTE(2, 1, 1)]) << 8; cmd->data |= readchunk[CMD_BYTE(2, 2, 1)]; if (cmd->desc & __VPM150M_WR) { /* Writes do not need any acknowledgement */ list_add_tail(&cmd->node, &vpm->free_cmds); } else { cmd->desc |= __VPM150M_FIN; complete(&cmd->complete); } } static int config_vpmadt032(struct vpmadt032 *vpm) { int res, channel; GpakPortConfig_t portconfig = {0}; gpakConfigPortStatus_t configportstatus; GPAK_PortConfigStat_t pstatus; GpakChannelConfig_t chanconfig; GPAK_ChannelConfigStat_t cstatus; GPAK_AlgControlStat_t algstatus; /* First Serial Port config */ portconfig.SlotsSelect1 = SlotCfgNone; portconfig.FirstBlockNum1 = 0; portconfig.FirstSlotMask1 = 0x0000; portconfig.SecBlockNum1 = 1; portconfig.SecSlotMask1 = 0x0000; portconfig.SerialWordSize1 = SerWordSize8; portconfig.CompandingMode1 = cmpNone; portconfig.TxFrameSyncPolarity1 = FrameSyncActHigh; portconfig.RxFrameSyncPolarity1 = FrameSyncActHigh; portconfig.TxClockPolarity1 = SerClockActHigh; portconfig.RxClockPolarity1 = SerClockActHigh; portconfig.TxDataDelay1 = DataDelay0; portconfig.RxDataDelay1 = DataDelay0; portconfig.DxDelay1 = Disabled; portconfig.ThirdSlotMask1 = 0x0000; portconfig.FouthSlotMask1 = 0x0000; portconfig.FifthSlotMask1 = 0x0000; portconfig.SixthSlotMask1 = 0x0000; portconfig.SevenSlotMask1 = 0x0000; portconfig.EightSlotMask1 = 0x0000; /* Second Serial Port config */ portconfig.SlotsSelect2 = SlotCfg8Groups; portconfig.FirstBlockNum2 = 0; portconfig.FirstSlotMask2 = 0x5554; portconfig.SecBlockNum2 = 1; portconfig.SecSlotMask2 = 0x5555; portconfig.ThirdSlotMask2 = 0x5555; portconfig.FouthSlotMask2 = 0x5555; portconfig.SerialWordSize2 = SerWordSize8; portconfig.CompandingMode2 = cmpNone; portconfig.TxFrameSyncPolarity2 = FrameSyncActHigh; portconfig.RxFrameSyncPolarity2 = FrameSyncActHigh; portconfig.TxClockPolarity2 = SerClockActHigh; portconfig.RxClockPolarity2 = SerClockActHigh; portconfig.TxDataDelay2 = DataDelay0; portconfig.RxDataDelay2 = DataDelay0; portconfig.DxDelay2 = Disabled; portconfig.FifthSlotMask2 = 0x0001; portconfig.SixthSlotMask2 = 0x0000; portconfig.SevenSlotMask2 = 0x0000; portconfig.EightSlotMask2 = 0x0000; /* Third Serial Port Config */ portconfig.SlotsSelect3 = SlotCfg8Groups; portconfig.FirstBlockNum3 = 0; portconfig.FirstSlotMask3 = 0x5554; portconfig.SecBlockNum3 = 1; portconfig.SecSlotMask3 = 0x5555; portconfig.SerialWordSize3 = SerWordSize8; portconfig.CompandingMode3 = cmpNone; portconfig.TxFrameSyncPolarity3 = FrameSyncActHigh; portconfig.RxFrameSyncPolarity3 = FrameSyncActHigh; portconfig.TxClockPolarity3 = SerClockActHigh; portconfig.RxClockPolarity3 = SerClockActLow; portconfig.TxDataDelay3 = DataDelay0; portconfig.RxDataDelay3 = DataDelay0; portconfig.DxDelay3 = Disabled; portconfig.ThirdSlotMask3 = 0x5555; portconfig.FouthSlotMask3 = 0x5555; portconfig.FifthSlotMask3 = 0x0001; portconfig.SixthSlotMask3 = 0x0000; portconfig.SevenSlotMask3 = 0x0000; portconfig.EightSlotMask3 = 0x0000; if ((configportstatus = gpakConfigurePorts(vpm->dspid, &portconfig, &pstatus))) { printk(KERN_NOTICE "Configuration of ports failed (%d)!\n", configportstatus); return -1; } else { if (vpm->options.debug & DEBUG_ECHOCAN) printk(KERN_DEBUG "Configured McBSP ports successfully\n"); } if ((res = gpakPingDsp(vpm->dspid, &vpm->version))) { printk(KERN_NOTICE "Error pinging DSP (%d)\n", res); return -1; } for (channel = 0; channel < MAX_CHANNELS_PER_SPAN; ++channel) { vpm->curecstate[channel].tap_length = 0; vpm->curecstate[channel].nlp_type = vpm->options.vpmnlptype; vpm->curecstate[channel].nlp_threshold = vpm->options.vpmnlpthresh; vpm->curecstate[channel].nlp_max_suppress = vpm->options.vpmnlpmaxsupp; memcpy(&vpm->desiredecstate[channel], &vpm->curecstate[channel], sizeof(vpm->curecstate[channel])); vpm->setchanconfig_from_state(vpm, channel, &chanconfig); if ((res = gpakConfigureChannel(vpm->dspid, channel, tdmToTdm, &chanconfig, &cstatus))) { printk(KERN_NOTICE "Unable to configure channel #%d (%d)", channel, res); if (res == 1) { printk(", reason %d", cstatus); } printk("\n"); return -1; } if ((res = gpakAlgControl(vpm->dspid, channel, BypassEcanA, &algstatus))) { printk(KERN_NOTICE "Unable to disable echo can on channel %d (reason %d:%d)\n", channel + 1, res, algstatus); return -1; } } if ((res = gpakPingDsp(vpm->dspid, &vpm->version))) { printk(KERN_NOTICE "Error pinging DSP (%d)\n", res); return -1; } set_bit(VPM150M_ACTIVE, &vpm->control); return 0; } static void cmd_dequeue_vpmadt032(struct t1 *wc, unsigned char *writechunk, int whichframe) { struct vpmadt032_cmd *cmd; struct vpmadt032 *vpm = wc->vpmadt032; int x; unsigned char leds = ~((atomic_read(&wc->txints) / 1000) % 8) & 0x7; /* Skip audio */ writechunk += 66; if (test_bit(VPM150M_SPIRESET, &vpm->control) || test_bit(VPM150M_HPIRESET, &vpm->control)) { debug_printk(1, "HW Resetting VPMADT032 ...\n"); for (x = 0; x < 4; x++) { if (!x) { if (test_and_clear_bit(VPM150M_SPIRESET, &vpm->control)) writechunk[CMD_BYTE(x, 0, 1)] = 0x08; else if (test_and_clear_bit(VPM150M_HPIRESET, &vpm->control)) writechunk[CMD_BYTE(x, 0, 1)] = 0x0b; } else writechunk[CMD_BYTE(x, 0, 1)] = 0x00 | leds; writechunk[CMD_BYTE(x, 1, 1)] = 0; writechunk[CMD_BYTE(x, 2, 1)] = 0x00; } return; } if ((cmd = vpmadt032_get_ready_cmd(vpm))) { cmd->txident = wc->txident; #if 0 printk(KERN_DEBUG "Found command txident = %d, desc = 0x%x, addr = 0x%x, data = 0x%x\n", cmd->txident, cmd->desc, cmd->address, cmd->data); #endif if (cmd->desc & __VPM150M_RWPAGE) { /* Set CTRL access to page*/ writechunk[CMD_BYTE(0, 0, 1)] = (0x8 << 4); writechunk[CMD_BYTE(0, 1, 1)] = 0; writechunk[CMD_BYTE(0, 2, 1)] = 0x20; /* Do a page write */ if (cmd->desc & __VPM150M_WR) { writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | 0x4) << 4); } else { writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | 0x4 | 0x1) << 4); } writechunk[CMD_BYTE(1, 1, 1)] = 0; if (cmd->desc & __VPM150M_WR) { writechunk[CMD_BYTE(1, 2, 1)] = cmd->data & 0xf; } else { writechunk[CMD_BYTE(1, 2, 1)] = 0; } if (cmd->desc & __VPM150M_WR) { /* Fill in buffer to size */ writechunk[CMD_BYTE(2, 0, 1)] = 0; writechunk[CMD_BYTE(2, 1, 1)] = 0; writechunk[CMD_BYTE(2, 2, 1)] = 0; } else { /* Do reads twice b/c of vpmadt032 bug */ writechunk[CMD_BYTE(2, 0, 1)] = ((0x8 | 0x4 | 0x1) << 4); writechunk[CMD_BYTE(2, 1, 1)] = 0; writechunk[CMD_BYTE(2, 2, 1)] = 0; } /* Clear XADD */ writechunk[CMD_BYTE(3, 0, 1)] = (0x8 << 4); writechunk[CMD_BYTE(3, 1, 1)] = 0; writechunk[CMD_BYTE(3, 2, 1)] = 0; /* Fill in buffer to size */ writechunk[CMD_BYTE(4, 0, 1)] = 0; writechunk[CMD_BYTE(4, 1, 1)] = 0; writechunk[CMD_BYTE(4, 2, 1)] = 0; } else { /* Set address */ writechunk[CMD_BYTE(0, 0, 1)] = ((0x8 | 0x4) << 4); writechunk[CMD_BYTE(0, 1, 1)] = (cmd->address >> 8) & 0xff; writechunk[CMD_BYTE(0, 2, 1)] = cmd->address & 0xff; /* Send/Get our data */ if (cmd->desc & __VPM150M_WR) { writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | (0x3 << 1)) << 4); } else { writechunk[CMD_BYTE(1, 0, 1)] = ((0x8 | (0x3 << 1) | 0x1) << 4); } writechunk[CMD_BYTE(1, 1, 1)] = (cmd->data >> 8) & 0xff; writechunk[CMD_BYTE(1, 2, 1)] = cmd->data & 0xff; if (cmd->desc & __VPM150M_WR) { /* Fill in */ writechunk[CMD_BYTE(2, 0, 1)] = 0; writechunk[CMD_BYTE(2, 1, 1)] = 0; writechunk[CMD_BYTE(2, 2, 1)] = 0; } else { /* Do this again for reads b/c of the bug in vpmadt032 */ writechunk[CMD_BYTE(2, 0, 1)] = ((0x8 | (0x3 << 1) | 0x1) << 4); writechunk[CMD_BYTE(2, 1, 1)] = (cmd->data >> 8) & 0xff; writechunk[CMD_BYTE(2, 2, 1)] = cmd->data & 0xff; } /* Fill in the rest */ writechunk[CMD_BYTE(3, 0, 1)] = 0; writechunk[CMD_BYTE(3, 1, 1)] = 0; writechunk[CMD_BYTE(3, 2, 1)] = 0; /* Fill in the rest */ writechunk[CMD_BYTE(4, 0, 1)] = 0; writechunk[CMD_BYTE(4, 1, 1)] = 0; writechunk[CMD_BYTE(4, 2, 1)] = 0; } } else if (test_and_clear_bit(VPM150M_SWRESET, &vpm->control)) { debug_printk(1, "Booting VPMADT032\n"); for (x = 0; x < 7; x++) { if (0 == x) { writechunk[CMD_BYTE(x, 0, 1)] = (0x8 << 4); } else { writechunk[CMD_BYTE(x, 0, 1)] = 0x00; } writechunk[CMD_BYTE(x, 1, 1)] = 0; if (0 == x) { writechunk[CMD_BYTE(x, 2, 1)] = 0x01; } else { writechunk[CMD_BYTE(x, 2, 1)] = 0x00; } } } else { for (x = 0; x < 7; x++) { writechunk[CMD_BYTE(x, 0, 1)] = 0x00; writechunk[CMD_BYTE(x, 1, 1)] = 0x00; writechunk[CMD_BYTE(x, 2, 1)] = 0x00; } } /* Add our leds in */ for (x = 0; x < 7; x++) writechunk[CMD_BYTE(x, 0, 1)] |= leds; #if 0 int y; for (x = 0; x < 7; x++) { for (y = 0; y < 3; y++) { if (writechunk[CMD_BYTE(x, y, 1)] & 0x2) { module_printk("the test bit is high for byte %d\n", y); } } } #endif /* Now let's figure out if we need to check for DTMF */ /* polling */ if (test_bit(VPM150M_ACTIVE, &vpm->control) && !whichframe && !(atomic_read(&wc->txints) % 100)) schedule_work(&vpm->work); #if 0 /* This may be needed sometime in the future to troubleshoot ADT related issues. */ if (test_bit(VPM150M_ACTIVE, &vpm->control) && !whichframe && !(atomic_read(&wc->txints) % 10000)) queue_work(vpm->wq, &vpm->work_debug); #endif } static inline int t1_setreg_full(struct t1 *wc, int addr, int val, int vpm_num) { struct command *cmd; cmd = get_free_cmd(wc); if (!cmd) { WARN_ON(1); return -ENOMEM; } cmd->address = addr; cmd->data = val; cmd->flags |= __CMD_WR; if (vpm_num >= 0) { cmd->flags |= __CMD_VPM; cmd->vpm_num = vpm_num; } submit_cmd(wc, cmd); return 0; } static inline int t1_setreg(struct t1 *wc, int addr, int val) { return t1_setreg_full(wc, addr, val, NOT_VPM); } static inline int t1_getreg_full(struct t1 *wc, int addr, int vpm_num) { struct command *cmd = NULL; int ret; might_sleep(); cmd = get_free_cmd(wc); if (!cmd) return -ENOMEM; cmd->address = addr; cmd->data = 0x00; cmd->flags = __CMD_RD; if (vpm_num > -1) { cmd->flags |= __CMD_VPM; cmd->vpm_num = vpm_num; } submit_cmd(wc, cmd); wait_for_completion(&cmd->complete); ret = cmd->data; free_cmd(wc, cmd); return ret; } static int t1_getreg(struct t1 *wc, int addr) { return t1_getreg_full(wc, addr, NOT_VPM); } static void t1_setleds(struct t1 *wc, int leds) { struct command *cmd; leds = (~leds) & 0x0E; /* invert the LED bits (3 downto 1)*/ cmd = get_free_cmd(wc); if (!cmd) return; cmd->flags |= __CMD_LEDS; cmd->address = leds; submit_cmd(wc, cmd); } static inline int t1_getpins(struct t1 *wc, int inisr) { int ret = 0; struct command *cmd; cmd = get_free_cmd(wc); BUG_ON(!cmd); cmd->address = 0x00; cmd->data = 0x00; cmd->flags = __CMD_PINS; submit_cmd(wc, cmd); wait_for_completion(&cmd->complete); ret = cmd->data; free_cmd(wc, cmd); 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 & DAHDI_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, NOT_VPM); if (ret < 0) module_printk("set_clear failed for chan %d!\n",i); val = 0; } } } static void free_wc(struct t1 *wc) { unsigned int x; unsigned long flags; struct command *cmd; LIST_HEAD(list); for (x = 0; x < (wc->spantype == TYPE_E1 ? 31 : 24); x++) { kfree(wc->chans[x]); kfree(wc->ec[x]); } spin_lock_irqsave(&wc->cmd_list_lock, flags); list_splice_init(&wc->active_cmds, &list); list_splice_init(&wc->pending_cmds, &list); spin_unlock_irqrestore(&wc->cmd_list_lock, flags); while (!list_empty(&list)) { cmd = list_entry(list.next, struct command, node); list_del(&cmd->node); free_cmd(wc, cmd); } kfree(wc); } static void t1_release(struct t1 *wc) { dahdi_unregister(&wc->span); printk(KERN_INFO "Freed a Wildcard TE12xP.\n"); free_wc(wc); } 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 & DAHDI_CONFIG_AMI) { line = "AMI"; fmr0 = 0xa0; } else { line = "B8ZS"; fmr0 = 0xf0; } if (lineconfig & DAHDI_CONFIG_D4) { framing = "D4"; } else { framing = "ESF"; fmr4 |= 0x2; fmr2 |= 0xc0; } 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 & DAHDI_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 & DAHDI_CONFIG_AMI) { line = "AMI"; fmr0 = 0xa0; } else { line = "HDB3"; fmr0 = 0xf0; } if (lineconfig & DAHDI_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 dahdi_span *span) { 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); } set_bit(DAHDI_FLAGBIT_RUNNING, &wc->span.flags); } static int t1xxp_startup(struct dahdi_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], DAHDI_LIN2X(0, span->chans[i]), DAHDI_CHUNKSIZE); memset(wc->ec_chunk2[i], DAHDI_LIN2X(0, span->chans[i]), DAHDI_CHUNKSIZE); } /* Reset framer with proper parameters and start */ t1xxp_framer_start(wc, span); debug_printk(1, "Calling startup (flags is %lu)\n", span->flags); return 0; } static int t1xxp_shutdown(struct dahdi_span *span) { struct t1 *wc = span->pvt; t1_setreg(wc, 0x46, 0x41); /* GCR: Interrupt on Activation/Deactivation of AIX, LOS */ clear_bit(DAHDI_FLAGBIT_RUNNING, &span->flags); return 0; } static int t1xxp_chanconfig(struct dahdi_chan *chan, int sigtype) { struct t1 *wc = chan->pvt; if (test_bit(DAHDI_FLAGBIT_RUNNING, &chan->span->flags) && (wc->spantype != TYPE_E1)) { __t1xxp_set_clear(wc, chan->channo); } return 0; } static int t1xxp_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc) { struct t1 *wc = span->pvt; /* Do we want to SYNC on receive or not */ if (lc->sync) set_bit(7, &wc->ctlreg); else clear_bit(7, &wc->ctlreg); /* If already running, apply changes immediately */ if (test_bit(DAHDI_FLAGBIT_RUNNING, &span->flags)) return t1xxp_startup(span); return 0; } static int t1xxp_rbsbits(struct dahdi_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, NOT_VPM); } else if (wc->span.lineconfig & DAHDI_CONFIG_D4) { n = chan->chanpos - 1; b = (n / 4); spin_lock_irqsave(&wc->reglock, flags); c = wc->txsigs[b]; m = ((3 - (n % 4)) << 1); /* nibble selector */ c &= ~(0x3 << m); /* keep the other nibble */ c |= ((bits >> 2) & 0x3) << m; /* put our new nibble here */ wc->txsigs[b] = c; spin_unlock_irqrestore(&wc->reglock, flags); /* output them to the chip */ t1_setreg_full(wc, 0x70 + b, c, NOT_VPM); t1_setreg_full(wc, 0x70 + b + 6, c, NOT_VPM); } else if (wc->span.lineconfig & DAHDI_CONFIG_ESF) { n = chan->chanpos - 1; b = (n / 2); spin_lock_irqsave(&wc->reglock, flags); c = wc->txsigs[b]; m = ((n % 2) << 2); /* nibble selector */ c &= (0xf << m); /* keep the other nibble */ c |= (bits & 0xf) << (4 - m); /* put our new nibble here */ wc->txsigs[b] = c; spin_unlock_irqrestore(&wc->reglock, flags); /* output them to the chip */ t1_setreg_full(wc, 0x70 + b, c, NOT_VPM); } debug_printk(2,"Finished setting RBS bits\n"); return 0; } static inline void t1_check_sigbits(struct t1 *wc) { int a,i,rxs; if (!(test_bit(DAHDI_FLAGBIT_RUNNING, &wc->span.flags))) return; if (wc->spantype == TYPE_E1) { for (i = 0; i < 15; i++) { a = t1_getreg(wc, 0x71 + i); if (a > -1) { /* Get high channel in low bits */ rxs = (a & 0xf); if (!(wc->span.chans[i+16]->sig & DAHDI_SIG_CLEAR)) { if (wc->span.chans[i+16]->rxsig != rxs) { dahdi_rbsbits(wc->span.chans[i+16], rxs); } } rxs = (a >> 4) & 0xf; if (!(wc->span.chans[i]->sig & DAHDI_SIG_CLEAR)) { if (wc->span.chans[i]->rxsig != rxs) { dahdi_rbsbits(wc->span.chans[i], rxs); } } } } } else if (wc->span.lineconfig & DAHDI_CONFIG_D4) { for (i = 0; i < 24; i+=4) { a = t1_getreg(wc, 0x70 + (i>>2)); if (a > -1) { /* Get high channel in low bits */ rxs = (a & 0x3) << 2; if (!(wc->span.chans[i+3]->sig & DAHDI_SIG_CLEAR)) { if (wc->span.chans[i+3]->rxsig != rxs) { dahdi_rbsbits(wc->span.chans[i+3], rxs); } } rxs = (a & 0xc); if (!(wc->span.chans[i+2]->sig & DAHDI_SIG_CLEAR)) { if (wc->span.chans[i+2]->rxsig != rxs) { dahdi_rbsbits(wc->span.chans[i+2], rxs); } } rxs = (a >> 2) & 0xc; if (!(wc->span.chans[i+1]->sig & DAHDI_SIG_CLEAR)) { if (wc->span.chans[i+1]->rxsig != rxs) { dahdi_rbsbits(wc->span.chans[i+1], rxs); } } rxs = (a >> 4) & 0xc; if (!(wc->span.chans[i]->sig & DAHDI_SIG_CLEAR)) { if (wc->span.chans[i]->rxsig != rxs) { dahdi_rbsbits(wc->span.chans[i], rxs); } } } } } else { for (i = 0; i < 24; i+=2) { a = t1_getreg(wc, 0x70 + (i>>1)); if (a > -1) { /* Get high channel in low bits */ rxs = (a & 0xf); if (!(wc->span.chans[i+1]->sig & DAHDI_SIG_CLEAR)) { if (wc->span.chans[i+1]->rxsig != rxs) { dahdi_rbsbits(wc->span.chans[i+1], rxs); } } rxs = (a >> 4) & 0xf; if (!(wc->span.chans[i]->sig & DAHDI_SIG_CLEAR)) { if (wc->span.chans[i]->rxsig != rxs) { dahdi_rbsbits(wc->span.chans[i], rxs); } } } } } } static int t1xxp_maint(struct dahdi_span *span, int cmd) { struct t1 *wc = span->pvt; if (wc->spantype == TYPE_E1) { switch (cmd) { case DAHDI_MAINT_NONE: module_printk("XXX Turn off local and remote loops E1 XXX\n"); break; case DAHDI_MAINT_LOCALLOOP: module_printk("XXX Turn on local loopback E1 XXX\n"); break; case DAHDI_MAINT_REMOTELOOP: module_printk("XXX Turn on remote loopback E1 XXX\n"); break; case DAHDI_MAINT_LOOPUP: module_printk("XXX Send loopup code E1 XXX\n"); break; case DAHDI_MAINT_LOOPDOWN: module_printk("XXX Send loopdown code E1 XXX\n"); break; case DAHDI_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 DAHDI_MAINT_NONE: module_printk("XXX Turn off local and remote loops T1 XXX\n"); break; case DAHDI_MAINT_LOCALLOOP: module_printk("XXX Turn on local loop and no remote loop XXX\n"); break; case DAHDI_MAINT_REMOTELOOP: module_printk("XXX Turn on remote loopup XXX\n"); break; case DAHDI_MAINT_LOOPUP: t1_setreg(wc, 0x21, 0x50); /* FMR5: Nothing but RBS mode */ break; case DAHDI_MAINT_LOOPDOWN: t1_setreg(wc, 0x21, 0x60); /* FMR5: Nothing but RBS mode */ break; case DAHDI_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 dahdi_chan *chan) { if (!try_module_get(THIS_MODULE)) return -ENXIO; else return 0; } static int t1xxp_close(struct dahdi_chan *chan) { module_put(THIS_MODULE); return 0; } static int t1xxp_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long data) { 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; default: return -ENOTTY; } return 0; } static int echocan_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec) { struct t1 *wc = chan->pvt; if (!wc->vpmadt032) { return -ENODEV; } return vpmadt032_echocan_create(wc->vpmadt032, chan->chanpos - 1, ecp, p); } static void echocan_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec) { struct t1 *wc = chan->pvt; if (!wc->vpmadt032) return; vpmadt032_echocan_free(wc->vpmadt032, chan, ec); } static int t1_software_init(struct t1 *wc) { int x; int num; 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); num = x; sprintf(wc->span.name, "WCT1/%d", num); snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Card %d", wc->variety, num); wc->span.manufacturer = "Digium"; strncpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype) - 1); #if defined(VPM_SUPPORT) if (wc->vpmadt032) 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 if (vpmsupport) wc->span.echocan_create = echocan_create; #endif if (wc->spantype == TYPE_E1) { if (unchannelized) wc->span.channels = 32; else wc->span.channels = 31; wc->span.spantype = "E1"; wc->span.linecompat = DAHDI_CONFIG_HDB3 | DAHDI_CONFIG_CCS | DAHDI_CONFIG_CRC4; wc->span.deflaw = DAHDI_LAW_ALAW; } else { wc->span.channels = 24; wc->span.spantype = "T1"; wc->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS | DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF; wc->span.deflaw = DAHDI_LAW_MULAW; } wc->span.chans = wc->chans; set_bit(DAHDI_FLAGBIT_RBS, &wc->span.flags); 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", num, x + 1); wc->chans[x]->sigcap = DAHDI_SIG_EM | DAHDI_SIG_CLEAR | DAHDI_SIG_EM_E1 | DAHDI_SIG_FXSLS | DAHDI_SIG_FXSGS | DAHDI_SIG_MTP2 | DAHDI_SIG_FXSKS | DAHDI_SIG_FXOLS | DAHDI_SIG_DACS_RBS | DAHDI_SIG_FXOGS | DAHDI_SIG_FXOKS | DAHDI_SIG_CAS | DAHDI_SIG_SF; wc->chans[x]->pvt = wc; wc->chans[x]->chanpos = x + 1; } if (dahdi_register(&wc->span, 0)) { module_printk("Unable to register span with DAHDI\n"); return -1; } set_bit(INITIALIZED, &wc->bit_flags); 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, 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, unit); } #endif static void setchanconfig_from_state(struct vpmadt032 *vpm, int channel, GpakChannelConfig_t *chanconfig) { const struct vpmadt032_options *options; GpakEcanParms_t *p; BUG_ON(!vpm); options = &vpm->options; chanconfig->PcmInPortA = 3; chanconfig->PcmInSlotA = (channel + 1) * 2; chanconfig->PcmOutPortA = 2; chanconfig->PcmOutSlotA = (channel + 1) * 2; chanconfig->PcmInPortB = 2; chanconfig->PcmInSlotB = (channel + 1) * 2; chanconfig->PcmOutPortB = 3; chanconfig->PcmOutSlotB = (channel + 1) * 2; chanconfig->ToneTypesA = Null_tone; chanconfig->MuteToneA = Disabled; chanconfig->FaxCngDetA = Disabled; chanconfig->ToneTypesB = Null_tone; chanconfig->EcanEnableA = Enabled; chanconfig->EcanEnableB = Disabled; chanconfig->MuteToneB = Disabled; chanconfig->FaxCngDetB = Disabled; chanconfig->SoftwareCompand = cmpPCMU; chanconfig->FrameRate = rate10ms; p = &chanconfig->EcanParametersA; vpmadt032_get_default_parameters(p); p->EcanNlpType = vpm->curecstate[channel].nlp_type; p->EcanNlpThreshold = vpm->curecstate[channel].nlp_threshold; p->EcanNlpMaxSuppress = vpm->curecstate[channel].nlp_max_suppress; memcpy(&chanconfig->EcanParametersB, &chanconfig->EcanParametersA, sizeof(chanconfig->EcanParametersB)); } static int t1_hardware_post_init(struct t1 *wc) { struct vpmadt032_options options; unsigned int reg; int res; 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"); /* what version of the FALC are we using? */ reg = t1_setreg(wc, 0x4a, 0xaa); reg = t1_getreg(wc, 0x4a); 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); reg = t1_getreg(wc, 0x14); if (reg != x) module_printk("Wrote '%x' but read '%x'\n", x, reg); } t1_setleds(wc, wc->ledstate); #ifdef VPM_SUPPORT if (vpmsupport) { memset(&options, 0, sizeof(options)); options.debug = debug; options.vpmnlptype = vpmnlptype; options.vpmnlpthresh = vpmnlpthresh; options.vpmnlpmaxsupp = vpmnlpmaxsupp; wc->vpmadt032 = vpmadt032_alloc(&options, wc->name); if (!wc->vpmadt032) return -ENOMEM; wc->vpmadt032->context = wc; wc->vpmadt032->setchanconfig_from_state = setchanconfig_from_state; wc->vpmadt032->span = &wc->span; res = vpmadt032_init(wc->vpmadt032, wc->vb); if (res) { vpmadt032_free(wc->vpmadt032); wc->vpmadt032=NULL; return -EIO; } config_vpmadt032(wc->vpmadt032); module_printk("VPM present and operational (Firmware version %x)\n", wc->vpmadt032->version); wc->ctlreg |= 0x10; /* turn on vpm (RX audio from vpm module) */ if (vpmtsisupport) { debug_printk(1, "enabling VPM TSI pin\n"); wc->ctlreg |= 0x01; /* turn on vpm timeslot interchange pin */ } } else { module_printk("VPM Support Disabled\n"); wc->vpmadt032 = NULL; } #endif return 0; } 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 (!(test_bit(DAHDI_FLAGBIT_RUNNING, &wc->span.flags))) return; c = t1_getreg(wc, 0x4c); fmr4 = t1_getreg(wc, 0x20); /* must read this even if we don't use it */ d = t1_getreg(wc, 0x4d); /* Assume no alarms */ alarms = 0; /* And consider only carrier alarms */ wc->span.alarms &= (DAHDI_ALARM_RED | DAHDI_ALARM_BLUE | DAHDI_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, NOT_VPM); /* LIM0: Force RAI High */ wc->flags.nmf = 1; module_printk("NMF workaround on!\n"); } t1_setreg_full(wc, 0x1e, 0xc3, NOT_VPM); /* Reset to CRC4 mode */ t1_setreg_full(wc, 0x1c, 0xf2, NOT_VPM); /* Force Resync */ t1_setreg_full(wc, 0x1c, 0xf0, NOT_VPM); /* Force Resync */ } else if (!(c & 0x02)) { if (wc->flags.nmf) { t1_setreg_full(wc, 0x20, 0x9f, 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 != DAHDI_MAINT_REMOTELOOP)) { t1_setreg_full(wc, 0x36, 0x08, NOT_VPM); /* LIM0: Disable any local loop */ t1_setreg_full(wc, 0x37, 0xf6, NOT_VPM); /* LIM1: Enable remote loop */ wc->span.maintstat = DAHDI_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 == DAHDI_MAINT_REMOTELOOP)) { t1_setreg_full(wc, 0x36, 0x08, NOT_VPM); /* LIM0: Disable any local loop */ t1_setreg_full(wc, 0x37, 0xf0, NOT_VPM); /* LIM1: Disable remote loop */ wc->span.maintstat = DAHDI_MAINT_NONE; } } else wc->loopdowncnt = 0; } if (wc->span.lineconfig & DAHDI_CONFIG_NOTOPEN) { for (x=0,j=0;x < wc->span.channels;x++) if ((wc->span.chans[x]->flags & DAHDI_FLAG_OPEN) || (wc->span.chans[x]->flags & DAHDI_FLAG_NETDEV)) j++; if (!j) alarms |= DAHDI_ALARM_NOTOPEN; } if (c & 0xa0) { if (wc->alarmcount >= alarmdebounce) { if (!unchannelized) alarms |= DAHDI_ALARM_RED; } else wc->alarmcount++; } else wc->alarmcount = 0; if (c & 0x4) alarms |= DAHDI_ALARM_BLUE; /* Keep track of recovering */ if ((!alarms) && wc->span.alarms) wc->alarmtimer = jiffies + 5*HZ; if (wc->alarmtimer) alarms |= DAHDI_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, 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, NOT_VPM); wc->flags.sendingyellow = 0; } if ((c & 0x10) && !unchannelized) alarms |= DAHDI_ALARM_YELLOW; if (wc->span.mainttimer || wc->span.maintstat) alarms |= DAHDI_ALARM_LOOPBACK; wc->span.alarms = alarms; dahdi_alarm_notify(&wc->span); } static void handle_leds(struct t1 *wc) { unsigned char led; unsigned long flags; led = wc->ledstate; if (wc->span.alarms & (DAHDI_ALARM_RED | DAHDI_ALARM_BLUE)) { /* When we're in red alarm, blink the led once a second. */ if (time_after(jiffies, wc->blinktimer)) { led = (led & __LED_GREEN) ? SET_LED_RED(led) : UNSET_LED_REDGREEN(led); } } else if (wc->span.alarms & DAHDI_ALARM_YELLOW) { led = (led & __LED_RED) ? SET_LED_GREEN(led) : SET_LED_RED(led); } else { if (wc->span.maintstat != DAHDI_MAINT_NONE) led = SET_LED_ORANGE(led); else led = UNSET_LED_ORANGE(led); if (test_bit(DAHDI_FLAGBIT_RUNNING, &wc->span.flags)) led = SET_LED_GREEN(led); else led = UNSET_LED_REDGREEN(led); } if (led != wc->ledstate) { struct command *cmd; cmd = get_free_cmd(wc); if (cmd) { wc->blinktimer = jiffies + HZ/2; cmd->flags |= __CMD_LEDS; cmd->address = ~led & 0x0E; submit_cmd(wc, cmd); spin_lock_irqsave(&wc->reglock, flags); wc->ledstate = led; spin_unlock_irqrestore(&wc->reglock, flags); } } } static void t1_do_counters(struct t1 *wc) { if (wc->alarmtimer && time_after(jiffies, wc->alarmtimer)) { wc->span.alarms &= ~(DAHDI_ALARM_RECOVER); wc->alarmtimer = 0; dahdi_alarm_notify(&wc->span); } } static inline void t1_transmitprep(struct t1 *wc, unsigned char* writechunk) { int x; int y; int chan; /* Calculate Transmission */ if (likely(test_bit(INITIALIZED, &wc->bit_flags))) { dahdi_transmit(&wc->span); } for (x = 0; x < DAHDI_CHUNKSIZE; x++) { if (likely(test_bit(INITIALIZED, &wc->bit_flags))) { 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->vpmadt032)) { spin_lock(&wc->reglock); cmd_dequeue_vpmadt032(wc, writechunk, x); spin_unlock(&wc->reglock); } #endif if (x < DAHDI_CHUNKSIZE - 1) { writechunk[EFRAME_SIZE] = wc->ctlreg; writechunk[EFRAME_SIZE + 1] = wc->txident++; } writechunk += (EFRAME_SIZE + EFRAME_GAP); } } static inline void t1_receiveprep(struct t1 *wc, unsigned char* readchunk) { int x,chan; unsigned char expected; for (x = 0; x < DAHDI_CHUNKSIZE; x++) { if (likely(test_bit(INITIALIZED, &wc->bit_flags))) { for (chan = 0; chan < wc->span.channels; chan++) { wc->chans[chan]->readchunk[x]= readchunk[(chan+1)*2]; } } if (x < DAHDI_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++; resend_cmds(wc); if (unlikely(debug && test_bit(INITIALIZED, &wc->bit_flags))) module_printk("oops: rxident=%d expected=%d x=%d\n", wc->rxident, expected, x); } } cmd_decipher(wc, readchunk); #ifdef VPM_SUPPORT if (wc->vpmadt032) { spin_lock(&wc->reglock); cmd_decipher_vpmadt032(wc, readchunk); spin_unlock(&wc->reglock); } #endif readchunk += (EFRAME_SIZE + EFRAME_GAP); } /* echo cancel */ if (likely(test_bit(INITIALIZED, &wc->bit_flags))) { for (x = 0; x < wc->span.channels; x++) { dahdi_ec_chunk(wc->chans[x], wc->chans[x]->readchunk, wc->ec_chunk2[x]); memcpy(wc->ec_chunk2[x],wc->ec_chunk1[x],DAHDI_CHUNKSIZE); memcpy(wc->ec_chunk1[x],wc->chans[x]->writechunk,DAHDI_CHUNKSIZE); } dahdi_receive(&wc->span); } } static void t1_handle_transmit(void* vbb, void* context) { struct t1* wc = context; memset(vbb, 0, SFRAME_SIZE); atomic_inc(&wc->txints); t1_transmitprep(wc, vbb); voicebus_transmit(wc->vb, vbb); handle_leds(wc); } static void t1_handle_receive(void* vbb, void* context) { struct t1* wc = context; t1_receiveprep(wc, vbb); } #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) static void timer_work_func(void *param) { struct t1 *wc = param; #else static void timer_work_func(struct work_struct *work) { struct t1 *wc = container_of(work, struct t1, timer_work); #endif /* Called once every 100ms */ if (unlikely(!test_bit(INITIALIZED, &wc->bit_flags))) return; t1_do_counters(wc); t1_check_alarms(wc); t1_check_sigbits(wc); mod_timer(&wc->timer, jiffies + HZ/5); } static void te12xp_timer(unsigned long data) { struct t1 *wc = (struct t1 *)data; schedule_work(&wc->timer_work); return; } 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; unsigned int index = -1; for (x = 0; x < sizeof(ifaces) / sizeof(ifaces[0]); x++) { if (!ifaces[x]) { index = x; break; } } if (-1 == index) { module_printk("Too many interfaces\n"); return -EIO; } retry: if (!(wc = kmalloc(sizeof(*wc), GFP_KERNEL))) { return -ENOMEM; } ifaces[index] = wc; memset(wc, 0, sizeof(*wc)); wc->ledstate = -1; spin_lock_init(&wc->reglock); spin_lock_init(&wc->cmd_list_lock); INIT_LIST_HEAD(&wc->active_cmds); INIT_LIST_HEAD(&wc->pending_cmds); wc->variety = d->name; wc->txident = 1; # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) wc->timer.function = te12xp_timer; wc->timer.data = (unsigned long)wc; init_timer(&wc->timer); # else setup_timer(&wc->timer, te12xp_timer, (unsigned long)wc); # endif # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) INIT_WORK(&wc->timer_work, timer_work_func, wc); # else INIT_WORK(&wc->timer_work, timer_work_func); # endif snprintf(wc->name, sizeof(wc->name)-1, "wcte12xp%d", index); if ((res = voicebus_init(pdev, SFRAME_SIZE, wc->name, t1_handle_receive, t1_handle_transmit, wc, debug, &wc->vb))) { WARN_ON(1); free_wc(wc); ifaces[index] = NULL; 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); for (x = 0; x < (wc->spantype == TYPE_E1 ? 31 : 24); x++) { if (!(wc->chans[x] = kmalloc(sizeof(*wc->chans[x]), GFP_KERNEL))) { free_wc(wc); ifaces[index] = NULL; return -ENOMEM; } memset(wc->chans[x], 0, sizeof(*wc->chans[x])); if (!(wc->ec[x] = kmalloc(sizeof(*wc->ec[x]), GFP_KERNEL))) { free_wc(wc); ifaces[index] = NULL; return -ENOMEM; } memset(wc->ec[x], 0, sizeof(*wc->ec[x])); } mod_timer(&wc->timer, jiffies + HZ/5); 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); dahdi_unregister(&wc->span); voicebus_release(wc->vb); wc->vb = NULL; free_wc(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 vpmadt032 *vpm = wc->vpmadt032; #endif if (!wc) return; #ifdef VPM_SUPPORT if(vpm) { wc->vpmadt032 = NULL; clear_bit(VPM150M_DTMFDETECT, &vpm->control); clear_bit(VPM150M_ACTIVE, &vpm->control); } #endif clear_bit(INITIALIZED, &wc->bit_flags); del_timer_sync(&wc->timer); flush_scheduled_work(); del_timer_sync(&wc->timer); BUG_ON(!wc->vb); voicebus_release(wc->vb); wc->vb = NULL; #ifdef VPM_SUPPORT if(vpm) { spin_lock_irqsave(&wc->reglock, flags); spin_unlock_irqrestore(&wc->reglock, flags); vpmadt032_free(vpm); } #endif t1_release(wc); } 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, .remove = __devexit_p(te12xp_remove_one), .id_table = te12xp_pci_tbl, }; static int __init te12xp_init(void) { int res; #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) cmd_cache = kmem_cache_create(THIS_MODULE->name, sizeof(struct command), 0, #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 22) SLAB_HWCACHE_ALIGN | SLAB_STORE_USER, NULL, NULL); #else SLAB_HWCACHE_ALIGN, NULL, NULL); #endif #else cmd_cache = kmem_cache_create(THIS_MODULE->name, sizeof(struct command), 0, SLAB_HWCACHE_ALIGN, NULL); #endif if (!cmd_cache) return -ENOMEM; res = dahdi_pci_module(&te12xp_driver); if (res) { kmem_cache_destroy(cmd_cache); return -ENODEV; } return 0; } static void __exit te12xp_cleanup(void) { pci_unregister_driver(&te12xp_driver); kmem_cache_destroy(cmd_cache); } 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(vpmtsisupport, int, S_IRUGO | S_IWUSR); module_param(vpmnlptype, int, S_IRUGO); module_param(vpmnlpthresh, int, S_IRUGO); module_param(vpmnlpmaxsupp, int, S_IRUGO); #endif MODULE_DESCRIPTION("Wildcard VoiceBus Digital Card Driver"); MODULE_AUTHOR("Digium Incorporated "); MODULE_LICENSE("GPL v2"); module_init(te12xp_init); module_exit(te12xp_cleanup); dahdi-linux-2.2.0-rc4/drivers/dahdi/wcte12xp/Kbuild0000644000175000017500000000017611176111367021222 0ustar maniacmaniacobj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE12XP) += wcte12xp.o EXTRA_CFLAGS += -I$(src)/.. -Wno-undef wcte12xp-objs := base.o dahdi-linux-2.2.0-rc4/drivers/dahdi/wcte12xp/wcte12xp.h0000644000175000017500000001007311176115504021705 0ustar maniacmaniac/* * 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-2009, Digium, Inc. * * All rights reserved. * */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ #ifndef _WCTE12XP_H #define _WCTE12XP_H /* Comment to disable VPM support */ #define VPM_SUPPORT 1 #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 * DAHDI_CHUNKSIZE) + (EFRAME_GAP * (DAHDI_CHUNKSIZE - 1))) #define PCI_WINDOW_SIZE ((2 * 2 * 2 * SFRAME_SIZE) + (2 * ERING_SIZE * 4)) #define MAX_COMMANDS 16 #define NUM_EC 4 #define __CMD_VPM (1 << 16) /* flag for VPM action */ #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 __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(KERN_INFO "%s: " fmt, te12xp_driver.name, ## args) #define debug_printk(level, fmt, args...) if (debug >= level) printk(KERN_DEBUG "%s (%s): " fmt, te12xp_driver.name, __FUNCTION__, ## args) extern spinlock_t ifacelock; struct command { u8 data; u8 ident; u8 cs_slot; u8 vpm_num; /* ignored for all but vpm commmands */ u16 address; u32 flags; struct list_head node; struct completion complete; }; 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 alarmcount; /* How much red alarm we've seen */ char *variety; char name[80]; unsigned long blinktimer; int loopupcnt; int loopdowncnt; #define INITIALIZED 1 #define SHUTDOWN 2 unsigned long bit_flags; unsigned long alarmtimer; unsigned char ledstate; unsigned char ec_chunk1[32][DAHDI_CHUNKSIZE]; unsigned char ec_chunk2[32][DAHDI_CHUNKSIZE]; struct dahdi_span span; /* Span */ struct dahdi_chan *chans[32]; /* Channels */ struct dahdi_echocan_state *ec[32]; /* Echocan state for channels */ unsigned long ctlreg; struct voicebus* vb; atomic_t txints; int vpm100; struct vpmadt032 *vpmadt032; unsigned long dtmfactive; unsigned long dtmfmask; unsigned long dtmfmutemask; spinlock_t cmd_list_lock; struct list_head pending_cmds; struct list_head active_cmds; struct timer_list timer; struct work_struct timer_work; }; int schluffen(wait_queue_head_t *q); #endif dahdi-linux-2.2.0-rc4/drivers/dahdi/wcte12xp/GpakHpi.h0000644000175000017500000000663311046336665021573 0ustar maniacmaniac/* * Copyright (c) 2001, Adaptive Digital Technologies, Inc. * * File Name: GpakHpi.h * * Description: * This file contains common definitions related to the G.PAK interface * between a host processor and a DSP processor via the Host Port Interface. * * Version: 1.0 * * Revision History: * 10/17/01 - Initial release. * * This program has been released under the terms of the GPL version 2 by * permission of Adaptive Digital Technologies, Inc. * */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ #ifndef _GPAKHPI_H /* prevent multiple inclusion */ #define _GPAKHPI_H /* Definition of G.PAK Command/Reply message type codes. */ #define MSG_NULL_REPLY 0 /* Null Reply (unsupported Command) */ #define MSG_SYS_CONFIG_RQST 1 /* System Configuration Request */ #define MSG_SYS_CONFIG_REPLY 2 /* System Configuration Reply */ #define MSG_READ_SYS_PARMS 3 /* Read System Parameters */ #define MSG_READ_SYS_PARMS_REPLY 4 /* Read System Parameters Reply */ #define MSG_WRITE_SYS_PARMS 5 /* Write System Parameters */ #define MSG_WRITE_SYS_PARMS_REPLY 6 /* Write System Parameters Reply */ #define MSG_CONFIGURE_PORTS 7 /* Configure Serial Ports */ #define MSG_CONFIG_PORTS_REPLY 8 /* Configure Serial Ports Reply */ #define MSG_CONFIGURE_CHANNEL 9 /* Configure Channel */ #define MSG_CONFIG_CHAN_REPLY 10 /* Configure Channel Reply */ #define MSG_TEAR_DOWN_CHANNEL 11 /* Tear Down Channel */ #define MSG_TEAR_DOWN_REPLY 12 /* Tear Down Channel Reply */ #define MSG_CHAN_STATUS_RQST 13 /* Channel Status Request */ #define MSG_CHAN_STATUS_REPLY 14 /* Channel Status Reply */ #define MSG_TEST_MODE 17 /* Configure/Perform Test Mode */ #define MSG_TEST_REPLY 18 /* Configure/Perform Test Mode Reply */ #define MSG_ALG_CONTROL 27 /* algorithm control */ #define MSG_ALG_CONTROL_REPLY 28 /* algorithm control reply */ #define MSG_GET_TXCID_ADDRESS 29 /* get tx cid buffer start address */ #define MSG_GET_TXCID_ADDRESS_REPLY 30 /* get tx cid buffer start addr reply */ #define MSG_PING 35 /* ping command */ #define MSG_PING_REPLY 36 /* ping command reply */ #define MSG_SERIAL_TXVAL 37 /* transmit serial fixed value */ #define MSG_SERIAL_TXVAL_REPLY 38 /* transmit serial fixed value reply */ #define MSG_TDM_LOOPBACK 39 /* tdm loopback control */ #define MSG_TDM_LOOPBACK_REPLY 40 /* tdm loopback control reply */ #define MSG_RESET_USAGE_STATS 41 /* reset cpu usage stats */ #define MSG_RESET_USAGE_STATS_REPLY 42 /* reset cpu usage stats reply */ #define MSG_RESET_FRAME_STATS 47 /* reset framing stats */ #define MSG_RESET_FRAME_STATS_REPLY 48 /* reset framing stats reply */ #define MSG_READ_DSP_MEMORY 49 /* read small section of DSP's memory */ #define MSG_READ_DSP_MEMORY_REPLY 50 /* read memory reply */ #define MSG_ACCESSGPIO 51 #define MSG_ACCESSGPIO_REPLY 52 #endif /* prevent multiple inclusion */ dahdi-linux-2.2.0-rc4/drivers/dahdi/wcb4xxp/0000755000175000017500000000000011202066031017766 5ustar maniacmaniacdahdi-linux-2.2.0-rc4/drivers/dahdi/wcb4xxp/Makefile0000644000175000017500000000026511111102055021425 0ustar maniacmaniacifdef 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 endif dahdi-linux-2.2.0-rc4/drivers/dahdi/wcb4xxp/base.c0000644000175000017500000023012111176623216021061 0ustar maniacmaniac/* * WCB410P Quad-BRI PCI Driver * Written by Andrew Kohlsmith * * Copyright (C) 2008 Digium, Inc. * All rights reserved. * */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ #include #include #include /* printk() */ #include /* error codes */ #include #include /* size_t */ #include /* O_ACCMODE */ #include #include #include /* for PCI structures */ #include #include #include #include /* dev_err() */ #include #include /* cli(), *_flags */ #include /* copy_*_user */ #include /* work_struct */ #include /* timer_struct */ #include #include #include #include "wcb4xxp.h" #if (DAHDI_CHUNKSIZE != 8) #error Sorry, wcb4xxp does not support chunksize != 8 #endif //#define SIMPLE_BCHAN_FIFO //#define DEBUG_LOWLEVEL_REGS /* debug __pci_in/out, not b4xxp_setreg */ #define DEBUG_GENERAL (1 << 0) /* general debug messages */ #define DEBUG_DTMF (1 << 1) /* emit DTMF detector messages */ #define DEBUG_REGS (1 << 2) /* emit register read/write, but only if the kernel's DEBUG is defined */ #define DEBUG_FOPS (1 << 3) /* emit file operation messages */ #define DEBUG_ECHOCAN (1 << 4) #define DEBUG_ST_STATE (1 << 5) /* S/T state machine */ #define DEBUG_HDLC (1 << 6) /* HDLC controller */ #define DEBUG_ALARM (1 << 7) /* alarm changes */ #define DBG (debug & DEBUG_GENERAL) #define DBG_DTMF (debug & DEBUG_DTMF) #define DBG_REGS (debug & DEBUG_REGS) #define DBG_FOPS (debug & DEBUG_FOPS) #define DBG_EC (debug & DEBUG_ECHOCAN) #define DBG_ST (debug & DEBUG_ST_STATE) #define DBG_HDLC (debug & DEBUG_HDLC) #define DBG_ALARM (debug & DEBUG_ALARM) #define DBG_SPANFILTER ((1 << bspan->port) & spanfilter) static int debug = 0; static int spanfilter = 15; #ifdef LOOPBACK_SUPPORTED static int loopback = 0; #endif static int milliwatt = 0; static int pedanticpci = 0; static int teignorered = 0; static int alarmdebounce = 500; static int vpmsupport = 1; static int timer_1_ms = 2000; static int timer_3_ms = 30000; #if !defined(mmiowb) #define mmiowb() barrier() #endif #define MAX_B4_CARDS 64 static struct b4xxp *cards[MAX_B4_CARDS]; static int led_fader_table[] = { 0, 0, 0, 1, 2, 3, 4, 6, 8, 9, 11, 13, 16, 18, 20, 22, 24, 25, 27, 28, 29, 30, 31, 31, 32, 31, 31, 30, 29, 28, 27, 25, 23, 22, 20, 18, 16, 13, 11, 9, 8, 6, 4, 3, 2, 1, 0, 0, }; // #define CREATE_WCB4XXP_PROCFS_ENTRY #ifdef CREATE_WCB4XXP_PROCFS_ENTRY #define PROCFS_NAME "wcb4xxp" static struct proc_dir_entry *myproc; #endif /* Expansion; right now there's just one card and all of its idiosyncrasies. */ #define FLAG_yyy (1 << 0) #define FLAG_zzz (1 << 1) struct devtype { char *desc; unsigned int flags; }; static struct devtype wcb4xxp = { "Wildcard B410P", 0 }; static int echocan_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec); static void echocan_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec); static const struct dahdi_echocan_features my_ec_features = { .NLP_automatic = 1, .CED_tx_detect = 1, .CED_rx_detect = 1, }; static const struct dahdi_echocan_ops my_ec_ops = { .name = "HWEC", .echocan_free = echocan_free, }; #if 0 static const char *wcb4xxp_rcsdata = "$RCSfile: base.c,v $ $Revision: 6552 $"; static const char *build_stamp = "" __DATE__ " " __TIME__ ""; #endif /* * lowlevel PCI access functions * These are simply wrappers for the normal PCI access functions that the kernel provides, * except that they allow us to work around specific PCI quirks with module options. * Currently the only option supported is pedanticpci, which injects a (min.) 3us delay * after any PCI access to forcibly disable fast back-to-back transactions. * In the case of a PCI write, pedanticpci will also read from the status register, which * has the effect of flushing any pending PCI writes. */ static inline unsigned char __pci_in8(struct b4xxp *b4, const unsigned int reg) { unsigned char ret = ioread8(b4->addr + reg); #ifdef DEBUG_LOWLEVEL_REGS if (unlikely(DBG_REGS)) drv_dbg(b4->dev, "read 0x%02x from 0x%p\n", ret, b4->addr + reg); #endif if (unlikely(pedanticpci)) { udelay(3); } return ret; } static inline unsigned short __pci_in16(struct b4xxp *b4, const unsigned int reg) { unsigned short ret = ioread16(b4->addr + reg); #ifdef DEBUG_LOWLEVEL_REGS if (unlikely(DBG_REGS)) drv_dbg(b4->dev, "read 0x%04x from 0x%p\n", ret, b4->addr + reg); #endif if (unlikely(pedanticpci)) { udelay(3); } return ret; } static inline unsigned int __pci_in32(struct b4xxp *b4, const unsigned int reg) { unsigned int ret = ioread32(b4->addr + reg); #ifdef DEBUG_LOWLEVEL_REGS if (unlikely(DBG_REGS)) drv_dbg(b4->dev, "read 0x%04x from 0x%p\n", ret, b4->addr + reg); #endif if (unlikely(pedanticpci)) { udelay(3); } return ret; } static inline void __pci_out32(struct b4xxp *b4, const unsigned int reg, const unsigned int val) { #ifdef DEBUG_LOWLEVEL_REGS if (unlikely(DBG_REGS)) drv_dbg(b4->dev, "writing 0x%02x to 0x%p\n", val, b4->addr + reg); #endif iowrite32(val, b4->addr + reg); if (unlikely(pedanticpci)) { udelay(3); (void)ioread8(b4->addr + R_STATUS); } } static inline void __pci_out8(struct b4xxp *b4, const unsigned int reg, const unsigned char val) { #ifdef DEBUG_LOWLEVEL_REGS if (unlikely(DBG_REGS)) drv_dbg(b4->dev, "writing 0x%02x to 0x%p\n", val, b4->addr + reg); #endif iowrite8(val, b4->addr + reg); if (unlikely(pedanticpci)) { udelay(3); (void)ioread8(b4->addr + R_STATUS); } } /* * Standard I/O access functions * uses spinlocks to protect against multiple I/O accesses * DOES NOT automatically memory barrier */ static inline unsigned char b4xxp_getreg8(struct b4xxp *b4, const unsigned int reg) { unsigned int ret; unsigned long irq_flags; spin_lock_irqsave(&b4->reglock, irq_flags); #undef RETRY_REGISTER_READS #ifdef RETRY_REGISTER_READS switch (reg) { case A_Z1: case A_Z1H: case A_F2: case R_IRQ_OVIEW: case R_BERT_STA: case A_ST_RD_STA: case R_IRQ_FIFO_BL0: case A_Z2: case A_Z2H: case A_F1: case R_RAM_USE: case R_F0_CNTL: case A_ST_SQ_RD: case R_IRQ_FIFO_BL7: /* On pg 53 of the data sheet for the hfc, it states that we must * retry certain registers until we get two consecutive reads that are * the same. */ retry: ret = __pci_in8(b4, reg); if (ret != __pci_in8(b4, reg)) goto retry; break; default: #endif ret = __pci_in8(b4, reg); #ifdef RETRY_REGISTER_READS break; } #endif spin_unlock_irqrestore(&b4->reglock, irq_flags); #ifndef DEBUG_LOWLEVEL_REGS if (unlikely(DBG_REGS)) { dev_dbg(b4->dev, "read 0x%02x from 0x%p\n", ret, b4->addr + reg); } #endif return ret; } static inline unsigned int b4xxp_getreg32(struct b4xxp *b4, const unsigned int reg) { unsigned int ret; unsigned long irq_flags; spin_lock_irqsave(&b4->reglock, irq_flags); ret = __pci_in32(b4, reg); spin_unlock_irqrestore(&b4->reglock, irq_flags); #ifndef DEBUG_LOWLEVEL_REGS if (unlikely(DBG_REGS)) { dev_dbg(b4->dev, "read 0x%04x from 0x%p\n", ret, b4->addr + reg); } #endif return ret; } static inline unsigned short b4xxp_getreg16(struct b4xxp *b4, const unsigned int reg) { unsigned int ret; unsigned long irq_flags; spin_lock_irqsave(&b4->reglock, irq_flags); ret = __pci_in16(b4, reg); spin_unlock_irqrestore(&b4->reglock, irq_flags); #ifndef DEBUG_LOWLEVEL_REGS if (unlikely(DBG_REGS)) { dev_dbg(b4->dev, "read 0x%04x from 0x%p\n", ret, b4->addr + reg); } #endif return ret; } static inline void b4xxp_setreg32(struct b4xxp *b4, const unsigned int reg, const unsigned int val) { unsigned long irq_flags; #ifndef DEBUG_LOWLEVEL_REGS if (unlikely(DBG_REGS)) { dev_dbg(b4->dev, "writing 0x%02x to 0x%p\n", val, b4->addr + reg); } #endif spin_lock_irqsave(&b4->reglock, irq_flags); __pci_out32(b4, reg, val); spin_unlock_irqrestore(&b4->reglock, irq_flags); } static inline void b4xxp_setreg8(struct b4xxp *b4, const unsigned int reg, const unsigned char val) { unsigned long irq_flags; #ifndef DEBUG_LOWLEVEL_REGS if (unlikely(DBG_REGS)) { dev_dbg(b4->dev, "writing 0x%02x to 0x%p\n", val, b4->addr + reg); } #endif spin_lock_irqsave(&b4->reglock, irq_flags); __pci_out8(b4, reg, val); spin_unlock_irqrestore(&b4->reglock, irq_flags); } /* * A lot of the registers in the HFC are indexed. * this function sets the index, and then writes to the indexed register in an ordered fashion. * memory barriers are useless unless spinlocked, so that's what these wrapper functions do. */ static void b4xxp_setreg_ra(struct b4xxp *b4, unsigned char r, unsigned char rd, unsigned char a, unsigned char ad) { unsigned long irq_flags; spin_lock_irqsave(&b4->seqlock, irq_flags); b4xxp_setreg8(b4, r, rd); wmb(); b4xxp_setreg8(b4, a, ad); mmiowb(); spin_unlock_irqrestore(&b4->seqlock, irq_flags); } static unsigned char b4xxp_getreg_ra(struct b4xxp *b4, unsigned char r, unsigned char rd, unsigned char a) { unsigned long irq_flags; unsigned char val; spin_lock_irqsave(&b4->seqlock, irq_flags); b4xxp_setreg8(b4, r, rd); wmb(); val = b4xxp_getreg8(b4, a); mmiowb(); spin_unlock_irqrestore(&b4->seqlock, irq_flags); return val; } /* * HFC-4S GPIO routines * * the B410P uses the HFC-4S GPIO as follows: * GPIO 8..10: output, CPLD register select * GPIO12..15: output, 1 = enable power for port 1-4 * GPI16: input, 0 = echo can #1 interrupt * GPI17: input, 0 = echo can #2 interrupt * GPI23: input, 1 = NT power module installed * GPI24..27: input, NT power module problem on port 1-4 * GPI28..31: input, 1 = port 1-4 in NT mode */ /* initialize HFC-4S GPIO. Set up pin drivers before setting GPIO mode */ static void hfc_gpio_init(struct b4xxp *b4) { unsigned long irq_flags; spin_lock_irqsave(&b4->seqlock, irq_flags); flush_pci(); /* flush any pending PCI writes */ mb(); b4xxp_setreg8(b4, R_GPIO_EN0, 0x00); /* GPIO0..7 input */ b4xxp_setreg8(b4, R_GPIO_EN1, 0xf7); /* GPIO8..10,12..15 outputs, GPIO11 input */ b4xxp_setreg8(b4, R_GPIO_OUT1, 0x00); /* disable power, CPLD reg 0 */ mb(); b4xxp_setreg8(b4, R_GPIO_SEL, 0xf0); /* GPIO0..7 S/T, 8..15 GPIO */ mb(); spin_unlock_irqrestore(&b4->seqlock, irq_flags); } /* * HFC SRAM interface code. * This came from mattf, I don't even pretend to understand it, * It seems to be using undocumented features in the HFC. * I just added the __pci_in8() to ensure the PCI writes made it * to hardware by the time these functions return. */ static inline void enablepcibridge(struct b4xxp *b4) { b4xxp_setreg8(b4, R_BRG_PCM_CFG, 0x03); flush_pci(); } static inline void disablepcibridge(struct b4xxp *b4) { b4xxp_setreg8(b4, R_BRG_PCM_CFG, 0x02); flush_pci(); } /* NOTE: read/writepcibridge do not use __pci_in/out because they are using b4->ioaddr not b4->addr */ static inline unsigned char readpcibridge(struct b4xxp *b4, unsigned char address) { unsigned short cipv; unsigned char data; /* slow down a PCI read access by 1 PCI clock cycle */ b4xxp_setreg8(b4, R_CTRL, 0x4); wmb(); if (address == 0) cipv=0x4000; else cipv=0x5800; /* select local bridge port address by writing to CIP port */ iowrite16(cipv, b4->ioaddr + 4); wmb(); data = ioread8(b4->ioaddr); /* restore R_CTRL for normal PCI read cycle speed */ b4xxp_setreg8(b4, R_CTRL, 0x0); wmb(); flush_pci(); return data; } static inline void writepcibridge(struct b4xxp *b4, unsigned char address, unsigned char data) { unsigned short cipv; unsigned int datav; if (address == 0) cipv=0x4000; else cipv=0x5800; /* select local bridge port address by writing to CIP port */ iowrite16(cipv, b4->ioaddr + 4); wmb(); /* define a 32 bit dword with 4 identical bytes for write sequence */ datav = data | ( (__u32) data <<8) | ( (__u32) data <<16) | ( (__u32) data <<24); /* * write this 32 bit dword to the bridge data port * this will initiate a write sequence of up to 4 writes to the same address on the local bus * interface * the number of write accesses is undefined but >=1 and depends on the next PCI transaction * during write sequence on the local bus */ iowrite32(datav, b4->ioaddr); wmb(); flush_pci(); } /* CPLD access code, more or less copied verbatim from code provided by mattf. */ static inline void cpld_select_reg(struct b4xxp *b4, unsigned char reg) { b4xxp_setreg8(b4, R_GPIO_OUT1, reg); flush_pci(); } static inline void cpld_setreg(struct b4xxp *b4, unsigned char reg, unsigned char val) { cpld_select_reg(b4, reg); enablepcibridge(b4); writepcibridge(b4, 1, val); disablepcibridge(b4); } static inline unsigned char cpld_getreg(struct b4xxp *b4, unsigned char reg) { unsigned char data; cpld_select_reg(b4, reg); enablepcibridge(b4); data = readpcibridge(b4, 1); disablepcibridge(b4); return data; } /* * echo canceller code, verbatim from mattf. * I don't pretend to understand it. */ static inline void ec_select_addr(struct b4xxp *b4, unsigned short addr) { cpld_setreg(b4, 0, 0xff & addr); cpld_setreg(b4, 1, 0x01 & (addr >> 8)); } static inline unsigned short ec_read_data(struct b4xxp *b4) { unsigned short addr; unsigned short highbit; addr = cpld_getreg(b4, 0); highbit = cpld_getreg(b4, 1); addr = addr | (highbit << 8); return addr & 0x1ff; } static inline unsigned char ec_read(struct b4xxp *b4, int which, unsigned short addr) { unsigned char data; unsigned long flags; spin_lock_irqsave(&b4->seqlock, flags); ec_select_addr(b4, addr); if (!which) cpld_select_reg(b4, 2); else cpld_select_reg(b4, 3); enablepcibridge(b4); data = readpcibridge(b4, 1); disablepcibridge(b4); cpld_select_reg(b4, 0); spin_unlock_irqrestore(&b4->seqlock, flags); return data; } static inline void ec_write(struct b4xxp *b4, int which, unsigned short addr, unsigned char data) { unsigned char in; unsigned long flags; spin_lock_irqsave(&b4->seqlock, flags); ec_select_addr(b4, addr); enablepcibridge(b4); if (!which) cpld_select_reg(b4, 2); else cpld_select_reg(b4, 3); writepcibridge(b4, 1, data); cpld_select_reg(b4, 0); disablepcibridge(b4); spin_unlock_irqrestore(&b4->seqlock, flags); in = ec_read(b4, which, addr); if (in != data) { if (printk_ratelimit()) { dev_warn(b4->dev, "ec_write: Wrote 0x%02x to register 0x%02x " "of VPM %d but got back 0x%02x\n", data, addr, which, in); } } } #define NUM_EC 2 #define MAX_TDM_CHAN 32 #if 0 void ec_set_dtmf_threshold(struct b4xxp *b4, int threshold) { unsigned int x; for (x = 0; x < NUM_EC; x++) { ec_write(b4, x, 0xC4, (threshold >> 8) & 0xFF); ec_write(b4, x, 0xC5, (threshold & 0xFF)); } printk("VPM: DTMF threshold set to %d\n", threshold); } #endif static void ec_init(struct b4xxp *b4) { unsigned char b; unsigned int i, j, mask; /* Setup GPIO */ for (i=0; i < NUM_EC; i++) { b = ec_read(b4, i, 0x1a0); dev_info(b4->dev, "VPM %d/%d init: chip ver %02x\n", i, NUM_EC - 1, b); for (j=0; j < 4; j++) { ec_write(b4, i, 0x1a8 + j, 0x00); /* GPIO out */ ec_write(b4, i, 0x1ac + j, 0x00); /* GPIO dir */ ec_write(b4, i, 0x1b0 + j, 0x00); /* GPIO sel */ } /* Setup TDM path - sets fsync and tdm_clk as inputs */ b = ec_read(b4, i, 0x1a3); /* misc_con */ ec_write(b4, i, 0x1a3, b & ~0x02); /* Setup Echo length (512 taps) */ ec_write(b4, i, 0x022, 1); ec_write(b4, i, 0x023, 0xff); /* Setup timeslots */ ec_write(b4, i, 0x02f, 0x00); mask = 0x02020202 << (i * 4); /* Setup the tdm channel masks for all chips*/ for (j=0; j < 4; j++) ec_write(b4, i, 0x33 - j, (mask >> (j << 3)) & 0xff); /* Setup convergence rate */ if (DBG) dev_info(b4->dev, "setting A-law mode\n"); b = ec_read(b4, i, 0x20); b &= 0xe0; b |= 0x13; ec_write(b4, i, 0x20, b); if (DBG) dev_info(b4->dev, "reg 0x20 is 0x%02x\n", b); // ec_write(b4, i, 0x20, 0x38); #if 0 ec_write(b4, i, 0x24, 0x02); b = ec_read(b4, i, 0x24); #endif if (DBG) dev_info(b4->dev, "NLP threshold is set to %d (0x%02x)\n", b, b); /* Initialize echo cans */ for (j=0; j < MAX_TDM_CHAN; j++) { if (mask & (0x00000001 << j)) ec_write(b4, i, j, 0x00); } mdelay(10); /* Put in bypass mode */ for (j=0; j < MAX_TDM_CHAN; j++) { if (mask & (0x00000001 << j)) { ec_write(b4, i, j, 0x01); } } /* Enable bypass */ for (j=0; j < MAX_TDM_CHAN; j++) { if (mask & (0x00000001 << j)) ec_write(b4, i, 0x78 + j, 0x01); } } #if 0 ec_set_dtmf_threshold(b4, 1250); #endif } /* performs a register write and then waits for the HFC "busy" bit to clear */ static void hfc_setreg_waitbusy(struct b4xxp *b4, const unsigned int reg, const unsigned int val) { int timeout = 0; unsigned long start; const int TIMEOUT = HZ/4; /* 250ms */ start = jiffies; while (unlikely((b4xxp_getreg8(b4, R_STATUS) & V_BUSY))) { if (time_after(jiffies, start + TIMEOUT)) { timeout = 1; break; } }; mb(); b4xxp_setreg8(b4, reg, val); mb(); start = jiffies; while (likely((b4xxp_getreg8(b4, R_STATUS) & V_BUSY))) { if (time_after(jiffies, start + TIMEOUT)) { timeout = 1; break; } }; if (timeout) { if (printk_ratelimit()) dev_warn(b4->dev, "hfc_setreg_waitbusy(write 0x%02x to 0x%02x) timed out waiting for busy flag to clear!\n", val, reg); } } /* * reads an 8-bit register over over and over until the same value is read twice, then returns that value. */ static inline unsigned char hfc_readcounter8(struct b4xxp *b4, const unsigned int reg) { unsigned char r1, r2; unsigned long maxwait = 1048576; do { r1 = b4xxp_getreg8(b4, reg); r2 = b4xxp_getreg8(b4, reg); } while ((r1 != r2) && maxwait--); if (!maxwait) { if (printk_ratelimit()) dev_warn(b4->dev, "hfc_readcounter8(reg 0x%02x) timed out waiting for data to settle!\n", reg); } return r1; } /* * reads a 16-bit register over over and over until the same value is read twice, then returns that value. */ static inline unsigned short hfc_readcounter16(struct b4xxp *b4, const unsigned int reg) { unsigned short r1, r2; unsigned long maxwait = 1048576; do { r1 = b4xxp_getreg16(b4, reg); r2 = b4xxp_getreg16(b4, reg); } while ((r1 != r2) && maxwait--); if (!maxwait) { if (printk_ratelimit()) dev_warn(b4->dev, "hfc_readcounter16(reg 0x%02x) timed out waiting for data to settle!\n", reg); } return r1; } static inline unsigned int hfc_readcounter32(struct b4xxp *b4, const unsigned int reg) { unsigned int r1, r2; unsigned long maxwait = 1048576; do { r1 = b4xxp_getreg32(b4, reg); r2 = b4xxp_getreg32(b4, reg); } while ((r1 != r2) && maxwait--); if (!maxwait) { if (printk_ratelimit()) dev_warn(b4->dev, "hfc_readcounter32(reg 0x%02x) timed out waiting for data to settle!\n", reg); } return r1; } /* performs a soft-reset of the HFC-4S. This is as clean-slate as you can get to a hardware reset. */ static void hfc_reset(struct b4xxp *b4) { int b, c; /* all 32 FIFOs the same size (384 bytes), channel select data flow mode, sized for internal RAM */ b4xxp_setreg8(b4, R_FIFO_MD, V_FIFO_MD_00 | V_DF_MD_CSM | V_FIFO_SZ_00); flush_pci(); /* reset everything, wait 500us, then bring everything BUT the PCM system out of reset */ b4xxp_setreg8(b4, R_CIRM, HFC_FULL_RESET); flush_pci(); udelay(500); b4xxp_setreg8(b4, R_CIRM, V_PCM_RES); flush_pci(); udelay(500); /* * Now bring PCM out of reset and do a very basic setup of the PCM system to allow it to finish resetting correctly. * set F0IO as an output, and set up a 32-timeslot PCM bus * See Section 8.3 in the HFC-4S datasheet for more details. */ b4xxp_setreg8(b4, R_CIRM, 0x00); b4xxp_setreg8(b4, R_PCM_MD0, V_PCM_MD | V_PCM_IDX_MD1); flush_pci(); b4xxp_setreg8(b4, R_PCM_MD1, V_PLL_ADJ_00 | V_PCM_DR_2048); flush_pci(); /* now wait for R_F0_CNTL to reach at least 2 before continuing */ c=10; while ((b = b4xxp_getreg8(b4, R_F0_CNTL)) < 2 && c) { udelay(100); c--; } if (!c && b < 2) { dev_warn(b4->dev, "hfc_reset() did not get the green light from the PCM system!\n"); } } static inline void hfc_enable_fifo_irqs(struct b4xxp *b4) { b4xxp_setreg8(b4, R_IRQ_CTRL, V_FIFO_IRQ | V_GLOB_IRQ_EN); flush_pci(); } static inline void hfc_disable_fifo_irqs(struct b4xxp *b4) { b4xxp_setreg8(b4, R_IRQ_CTRL, V_GLOB_IRQ_EN); flush_pci(); } static void hfc_enable_interrupts(struct b4xxp *b4) { b4->running = 1; /* clear any pending interrupts */ b4xxp_getreg8(b4, R_STATUS); b4xxp_getreg8(b4, R_IRQ_MISC); b4xxp_getreg8(b4, R_IRQ_FIFO_BL0); b4xxp_getreg8(b4, R_IRQ_FIFO_BL1); b4xxp_getreg8(b4, R_IRQ_FIFO_BL2); b4xxp_getreg8(b4, R_IRQ_FIFO_BL3); b4xxp_getreg8(b4, R_IRQ_FIFO_BL4); b4xxp_getreg8(b4, R_IRQ_FIFO_BL5); b4xxp_getreg8(b4, R_IRQ_FIFO_BL6); b4xxp_getreg8(b4, R_IRQ_FIFO_BL7); b4xxp_setreg8(b4, R_IRQMSK_MISC, V_TI_IRQ); hfc_enable_fifo_irqs(b4); } static void hfc_disable_interrupts(struct b4xxp *b4) { b4xxp_setreg8(b4, R_IRQMSK_MISC, 0); b4xxp_setreg8(b4, R_IRQ_CTRL, 0); flush_pci(); b4->running = 0; } /* * Connects an S/T port's B channel to a host-facing FIFO through the PCM busses. * This bchan flow plan should match up with the EC requirements. * TODO: Interrupts are only enabled on the host FIFO RX side, since everything is (should be) synchronous. * *** performs no error checking of parameters *** */ static void hfc_assign_bchan_fifo_ec(struct b4xxp *b4, int port, int bchan) { int fifo, hfc_chan, ts; unsigned long irq_flags; static int first=1; if (first) { first = 0; dev_info(b4->dev, "Hardware echo cancellation enabled.\n"); } fifo = port * 2; hfc_chan = port * 4; ts = port * 8; if (bchan) { fifo += 1; hfc_chan += 1; ts += 4; } /* record the host's FIFO # in the span fifo array */ b4->spans[port].fifos[bchan] = fifo; spin_lock_irqsave(&b4->fifolock, irq_flags); if (DBG) dev_info(b4->dev, "port %d, B channel %d\n\tS/T -> PCM ts %d uses HFC chan %d via FIFO %d\n", port, bchan, ts + 1, hfc_chan, 16 + fifo); /* S/T RX -> PCM TX FIFO, transparent mode, no IRQ. */ hfc_setreg_waitbusy(b4, R_FIFO, ((16 + fifo) << V_FIFO_NUM_SHIFT)); b4xxp_setreg8(b4, A_CON_HDLC, V_IFF | V_HDLC_TRP | V_DATA_FLOW_110); b4xxp_setreg8(b4, A_CHANNEL, (hfc_chan << V_CH_FNUM_SHIFT)); b4xxp_setreg8(b4, R_SLOT, ((ts + 1) << V_SL_NUM_SHIFT)); b4xxp_setreg8(b4, A_SL_CFG, V_ROUT_TX_STIO1 | (hfc_chan << V_CH_SNUM_SHIFT)); hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_RES_FIFO); if (DBG) pr_info("\tPCM ts %d -> host uses HFC chan %d via FIFO %d\n", ts + 1, 16 + hfc_chan, fifo); /* PCM RX -> Host TX FIFO, transparent mode, enable IRQ. */ hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT) | V_FIFO_DIR); b4xxp_setreg8(b4, A_CON_HDLC, V_IFF | V_HDLC_TRP | V_DATA_FLOW_001); b4xxp_setreg8(b4, A_CHANNEL, ((16 + hfc_chan) << V_CH_FNUM_SHIFT) | V_CH_FDIR); b4xxp_setreg8(b4, R_SLOT, ((ts + 1) << V_SL_NUM_SHIFT) | 1); b4xxp_setreg8(b4, A_SL_CFG, V_ROUT_RX_STIO2 | ((16 + hfc_chan) << V_CH_SNUM_SHIFT) | 1); hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_RES_FIFO); // b4xxp_setreg8(b4, A_IRQ_MSK, V_IRQ); if (DBG) pr_info("\thost -> PCM ts %d uses HFC chan %d via FIFO %d\n", ts, 16 + hfc_chan, fifo); /* Host FIFO -> PCM TX */ hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT)); b4xxp_setreg8(b4, A_CON_HDLC, V_IFF | V_HDLC_TRP | V_DATA_FLOW_001); b4xxp_setreg8(b4, A_CHANNEL, ((16 + hfc_chan) << V_CH_FNUM_SHIFT)); b4xxp_setreg8(b4, R_SLOT, (ts << V_SL_NUM_SHIFT)); b4xxp_setreg8(b4, A_SL_CFG, V_ROUT_RX_STIO2 | ((16 + hfc_chan) << V_CH_SNUM_SHIFT)); hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_RES_FIFO); if (DBG) pr_info("\tPCM ts %d -> S/T uses HFC chan %d via FIFO %d\n", ts, hfc_chan, 16 + fifo); /* PCM -> S/T */ hfc_setreg_waitbusy(b4, R_FIFO, ((16 + fifo) << V_FIFO_NUM_SHIFT) | V_FIFO_DIR); b4xxp_setreg8(b4, A_CON_HDLC, V_IFF | V_HDLC_TRP | V_DATA_FLOW_110); b4xxp_setreg8(b4, A_CHANNEL, (hfc_chan << V_CH_FNUM_SHIFT) | V_CH_FDIR); b4xxp_setreg8(b4, R_SLOT, (ts << V_SL_NUM_SHIFT) | V_SL_DIR); b4xxp_setreg8(b4, A_SL_CFG, V_ROUT_TX_STIO2 | (hfc_chan << V_CH_SNUM_SHIFT) | V_CH_SDIR); hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_RES_FIFO); if (DBG) pr_info("\tPCM ts %d -> S/T uses HFC chan %d via FIFO %d\n", ts, hfc_chan, 16 + fifo); flush_pci(); /* ensure all those writes actually hit hardware */ spin_unlock_irqrestore(&b4->fifolock, irq_flags); } static void hfc_assign_bchan_fifo_noec(struct b4xxp *b4, int port, int bchan) { int fifo, hfc_chan, ts; unsigned long irq_flags; static int first=1; if (first) { first = 0; dev_info(b4->dev, "NOTE: hardware echo cancellation has been disabled\n"); } fifo = port * 2; hfc_chan = port * 4; ts = port * 8; if (bchan) { fifo += 1; hfc_chan += 1; ts += 4; } /* record the host's FIFO # in the span fifo array */ b4->spans[port].fifos[bchan] = fifo; spin_lock_irqsave(&b4->fifolock, irq_flags); if (DBG) dev_info(b4->dev, "port %d, B channel %d\n\thost -> S/T uses HFC chan %d via FIFO %d\n", port, bchan, hfc_chan, fifo); hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT)); b4xxp_setreg8(b4, A_CON_HDLC, V_IFF | V_HDLC_TRP | V_DATA_FLOW_000); b4xxp_setreg8(b4, A_CHANNEL, (hfc_chan << V_CH_FNUM_SHIFT)); hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_RES_FIFO); if (DBG) pr_info("\tS/T -> host uses HFC chan %d via FIFO %d\n", hfc_chan, fifo); hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT) | V_FIFO_DIR); b4xxp_setreg8(b4, A_CON_HDLC, V_IFF | V_HDLC_TRP | V_DATA_FLOW_000); b4xxp_setreg8(b4, A_CHANNEL, (hfc_chan << V_CH_FNUM_SHIFT) | V_CH_FDIR); hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_RES_FIFO); if (DBG) pr_info("\tPCM ts %d -> S/T uses HFC chan %d via FIFO %d\n", ts, hfc_chan, 16 + fifo); flush_pci(); /* ensure all those writes actually hit hardware */ spin_unlock_irqrestore(&b4->fifolock, irq_flags); } /* * Connects an S/T port's D channel to a host-facing FIFO. * Both TX and RX interrupts are enabled! * *** performs no error checking of parameters *** */ static void hfc_assign_dchan_fifo(struct b4xxp *b4, int port) { int fifo, hfc_chan; unsigned long irq_flags; fifo = port + 8; hfc_chan = (port * 4) + 2; /* record the host's FIFO # in the span fifo array */ b4->spans[port].fifos[2] = fifo; if (DBG) dev_info(b4->dev, "port %d, D channel\n\thost -> S/T uses HFC chan %d via FIFO %d\n", port, hfc_chan, fifo); spin_lock_irqsave(&b4->fifolock, irq_flags); /* Host FIFO -> S/T TX, HDLC mode, no IRQ. */ hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT)); b4xxp_setreg8(b4, A_CON_HDLC, V_IFF | V_TRP_IRQ | V_DATA_FLOW_000); b4xxp_setreg8(b4, A_CHANNEL, (hfc_chan << V_CH_FNUM_SHIFT)); b4xxp_setreg8(b4, A_SUBCH_CFG, 0x02); hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_RES_FIFO); if (DBG) pr_info("\tS/T -> host uses HFC chan %d via FIFO %d\n", hfc_chan, fifo); /* S/T RX -> Host FIFO, HDLC mode, IRQ will be enabled when port opened. */ hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT) | V_FIFO_DIR); b4xxp_setreg8(b4, A_CON_HDLC, V_IFF | V_TRP_IRQ | V_DATA_FLOW_000); b4xxp_setreg8(b4, A_CHANNEL, (hfc_chan << V_CH_FNUM_SHIFT) | V_CH_FDIR); b4xxp_setreg8(b4, A_SUBCH_CFG, 0x02); hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_RES_FIFO); if (DBG) pr_info("\n"); flush_pci(); /* ensure all those writes actually hit hardware */ spin_unlock_irqrestore(&b4->fifolock, irq_flags); } /* takes a read/write fifo pair and optionally resets it, optionally enabling the rx/tx interrupt */ static void hfc_reset_fifo_pair(struct b4xxp *b4, int fifo, int reset, int force_no_irq) { unsigned long irq_flags; spin_lock_irqsave(&b4->fifolock, irq_flags); hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT)); b4xxp_setreg8(b4, A_IRQ_MSK, (!force_no_irq && b4->fifo_en_txint & (1 << fifo)) ? V_IRQ : 0); if (reset) hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_RES_FIFO); hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT) | V_FIFO_DIR); b4xxp_setreg8(b4, A_IRQ_MSK, (!force_no_irq && b4->fifo_en_rxint & (1 << fifo)) ? V_IRQ : 0); if (reset) hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_RES_FIFO); spin_unlock_irqrestore(&b4->fifolock, irq_flags); } static void b4xxp_set_sync_src(struct b4xxp *b4, int port) { int b; if (port == -1) /* automatic */ b = 0; else b = (port & V_SYNC_SEL_MASK) | V_MAN_SYNC; b4xxp_setreg8(b4, R_ST_SYNC, b); } /* * Finds the highest-priority sync span that is not in alarm and returns it. * Note: the span #s in b4->spans[].sync are 1-based, and this returns * a 0-based span, or -1 if no spans are found. */ static int b4xxp_find_sync(struct b4xxp *b4) { int i, psrc, src; src = -1; /* default to automatic */ for (i=0; i < b4->numspans; i++) { psrc = b4->spans[i].sync; if (psrc > 0 && !b4->spans[psrc - 1].span.alarms) { src = psrc; break; } } return src - 1; } /* * allocates memory and pretty-prints a given S/T state engine state to it. * calling routine is responsible for freeing the pointer returned! * Performs no hardware access whatsoever, but does use GFP_KERNEL so do not call from IRQ context. * if full == 1, prints a "full" dump; otherwise just prints current state. */ static char *hfc_decode_st_state(struct b4xxp *b4, int port, unsigned char state, int full) { int nt, sta; char s[128], *str; const char *ststr[2][16] = { /* TE, NT */ { "RESET", "?", "SENSING", "DEACT.", "AWAIT.SIG", "IDENT.INPUT", "SYNCD", "ACTIVATED", "LOSTFRAMING", "?", "?", "?", "?", "?", "?", "?" }, { "RESET", "DEACT.", "PEND.ACT", "ACTIVE", "PEND.DEACT", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?" } }; if (!(str = kmalloc(256, GFP_KERNEL))) { dev_warn(b4->dev, "could not allocate mem for ST state decode string!\n"); return NULL; } nt = (b4->spans[port].te_mode == 0); sta = (state & V_ST_STA_MASK); sprintf(str, "P%d: %s state %c%d (%s)", port + 1, (nt ? "NT" : "TE"), (nt ? 'G' : 'F'), sta, ststr[nt][sta]); if (full) { sprintf(s, " SYNC: %s, RX INFO0: %s", ((state & V_FR_SYNC) ? "yes" : "no"), ((state & V_INFO0) ? "yes" : "no")); strcat(str, s); if (nt) { sprintf(s, ", T2 %s, auto G2->G3: %s", ((state & V_T2_EXP) ? "expired" : "OK"), ((state & V_G2_G3) ? "yes" : "no")); strcat(str, s); } } return str; } /* * sets an S/T port state machine to a given state. * if 'auto' is nonzero, will put the state machine back in auto mode after setting the state. */ static void hfc_handle_state(struct b4xxp_span *s); static void hfc_force_st_state(struct b4xxp *b4, int port, int state, int resume_auto) { b4xxp_setreg_ra(b4, R_ST_SEL, port, A_ST_RD_STA, state | V_ST_LD_STA); udelay(6); if (resume_auto) { b4xxp_setreg_ra(b4, R_ST_SEL, port, A_ST_RD_STA, state); } if (DBG_ST) { char *x; x = hfc_decode_st_state(b4, port, state, 1); dev_info(b4->dev, "forced port %d to state %d (auto: %d), new decode: %s\n", port + 1, state, resume_auto, x); kfree(x); } /* make sure that we activate any timers/etc needed by this state change */ hfc_handle_state(&b4->spans[port]); } /* figures out what to do when an S/T port's timer expires. */ static void hfc_timer_expire(struct b4xxp_span *s, int t_no) { struct b4xxp *b4 = s->parent; if (DBG_ST) dev_info(b4->dev, "%lu: hfc_timer_expire, Port %d T%d expired (value=%lu ena=%d)\n", b4->ticks, s->port + 1, t_no + 1, s->hfc_timers[t_no], s->hfc_timer_on[t_no]); /* * there are three timers associated with every HFC S/T port. * T1 is used by the NT state machine, and is the maximum time the NT side should wait for G3 (active) state. * T2 is not actually used in the driver, it is handled by the HFC-4S internally. * T3 is used by the TE state machine; it is the maximum time the TE side should wait for the INFO4 (activated) signal. */ /* First, disable the expired timer; hfc_force_st_state() may activate it again. */ s->hfc_timer_on[t_no] = 0; switch(t_no) { case HFC_T1: /* switch to G4 (pending deact.), resume auto mode */ hfc_force_st_state(b4, s->port, 4, 1); break; case HFC_T2: /* switch to G1 (deactivated), resume auto mode */ hfc_force_st_state(b4, s->port, 1, 1); break; case HFC_T3: /* switch to F3 (deactivated), resume auto mode */ hfc_force_st_state(b4, s->port, 3, 1); break; default: if (printk_ratelimit()) dev_warn(b4->dev, "hfc_timer_expire found an unknown expired timer (%d)??\n", t_no); } } /* * Run through the active timers on a card and deal with any expiries. * Also see if the alarm debounce time has expired and if it has, tell DAHDI. */ static void hfc_update_st_timers(struct b4xxp *b4) { int i, j; struct b4xxp_span *s; for (i=0; i < 4; i++) { s = &b4->spans[i]; for (j=HFC_T1; j <= HFC_T3; j++) { /* we don't really do timer2, it is expired by the state change handler */ if (j == HFC_T2) continue; if (s->hfc_timer_on[j] && time_after_eq(b4->ticks, s->hfc_timers[j])) { hfc_timer_expire(s, j); } } if (s->newalarm != s->span.alarms && time_after_eq(b4->ticks, s->alarmtimer)) { if (!s->te_mode || !teignorered) { s->span.alarms = s->newalarm; dahdi_alarm_notify(&s->span); if (DBG_ALARM) dev_info(b4->dev, "span %d: alarm %d debounced\n", i + 1, s->newalarm); if (!s->te_mode) b4xxp_set_sync_src(b4, b4xxp_find_sync(b4)); } } } } /* this is the driver-level state machine for an S/T port */ static void hfc_handle_state(struct b4xxp_span *s) { struct b4xxp *b4; unsigned char state, sta; int nt, newsync, oldalarm; unsigned long oldtimer; b4 = s->parent; nt = !s->te_mode; state = b4xxp_getreg_ra(b4, R_ST_SEL, s->port, A_ST_RD_STA); sta = (state & V_ST_STA_MASK); if (DBG_ST) { char *x; x = hfc_decode_st_state(b4, s->port, state, 1); dev_info(b4->dev, "port %d A_ST_RD_STA old=0x%02x now=0x%02x, decoded: %s\n", s->port + 1, s->oldstate, state, x); kfree(x); } oldalarm = s->newalarm; oldtimer = s->alarmtimer; if (nt) { switch(sta) { default: /* Invalid NT state */ case 0x0: /* NT state G0: Reset */ case 0x1: /* NT state G1: Deactivated */ case 0x4: /* NT state G4: Pending Deactivation */ s->newalarm = DAHDI_ALARM_RED; break; case 0x2: /* NT state G2: Pending Activation */ s->newalarm = DAHDI_ALARM_YELLOW; break; case 0x3: /* NT state G3: Active */ s->hfc_timer_on[HFC_T1] = 0; s->newalarm = 0; break; } } else { switch(sta) { default: /* Invalid TE state */ case 0x0: /* TE state F0: Reset */ case 0x2: /* TE state F2: Sensing */ case 0x3: /* TE state F3: Deactivated */ case 0x4: /* TE state F4: Awaiting Signal */ case 0x8: /* TE state F8: Lost Framing */ s->newalarm = DAHDI_ALARM_RED; break; case 0x5: /* TE state F5: Identifying Input */ case 0x6: /* TE state F6: Synchronized */ s->newalarm = DAHDI_ALARM_YELLOW; break; case 0x7: /* TE state F7: Activated */ s->hfc_timer_on[HFC_T3] = 0; s->newalarm = 0; break; } } s->alarmtimer = b4->ticks + alarmdebounce; s->oldstate = state; if (DBG_ALARM) { dev_info(b4->dev, "span %d: old alarm %d expires %ld, new alarm %d expires %ld\n", s->port + 1, oldalarm, oldtimer, s->newalarm, s->alarmtimer); } /* we only care about T2 expiry in G4. */ if (nt && (sta == 4) && (state & V_T2_EXP)) { if (s->hfc_timer_on[HFC_T2]) hfc_timer_expire(s, HFC_T2); /* handle T2 expiry */ } /* If we're in F3 and receiving INFO0, start T3 and jump to F4 */ if (!nt && (sta == 3) && (state & V_INFO0)) { s->hfc_timers[HFC_T3] = b4->ticks + timer_3_ms; s->hfc_timer_on[HFC_T3] = 1; if (DBG_ST) { dev_info(b4->dev, "port %d: receiving INFO0 in state 3, setting T3 and jumping to F4\n", s->port + 1); } hfc_force_st_state(b4, s->port, 4, 1); } /* read in R_BERT_STA to determine where our current sync source is */ newsync = b4xxp_getreg8(b4, R_BERT_STA) & 0x07; if (newsync != b4->syncspan) { if (printk_ratelimit()) dev_info(b4->dev, "new card sync source: port %d\n", newsync + 1); b4->syncspan = newsync; } } /* * resets an S/T interface to a given NT/TE mode */ static void hfc_reset_st(struct b4xxp_span *s) { int b; struct b4xxp *b4; b4 = s->parent; /* force state G0/F0 (reset), then force state 1/2 (deactivated/sensing) */ b4xxp_setreg_ra(b4, R_ST_SEL, s->port, A_ST_WR_STA, V_ST_LD_STA); flush_pci(); /* make sure write hit hardware */ udelay(10); /* set up the clock control register. Must be done before we activate the interface. */ if (s->te_mode) b = 0x0e; else b = 0x0c | (6 << V_ST_SMPL_SHIFT); b4xxp_setreg8(b4, A_ST_CLK_DLY, b); /* set TE/NT mode, enable B and D channels. */ b4xxp_setreg8(b4, A_ST_CTRL0, V_B1_EN | V_B2_EN | (s->te_mode ? 0 : V_ST_MD)); b4xxp_setreg8(b4, A_ST_CTRL1, V_G2_G3_EN | V_E_IGNO); b4xxp_setreg8(b4, A_ST_CTRL2, V_B1_RX_EN | V_B2_RX_EN); /* enable the state machine. */ b4xxp_setreg8(b4, A_ST_WR_STA, 0x00); flush_pci(); udelay(100); } static void hfc_start_st(struct b4xxp_span *s) { struct b4xxp *b4 = s->parent; b4xxp_setreg_ra(b4, R_ST_SEL, s->port, A_ST_WR_STA, V_ST_ACT_ACTIVATE); /* start T1 if in NT mode, T3 if in TE mode */ if (s->te_mode) { s->hfc_timers[HFC_T3] = b4->ticks + 500; /* 500ms wait first time, timer_t3_ms afterward. */ s->hfc_timer_on[HFC_T3] = 1; s->hfc_timer_on[HFC_T1] = 0; if (DBG_ST) dev_info(b4->dev, "setting port %d t3 timer to %lu\n", s->port + 1, s->hfc_timers[HFC_T3]); } else { s->hfc_timers[HFC_T1] = b4->ticks + timer_1_ms; s->hfc_timer_on[HFC_T1] = 1; s->hfc_timer_on[HFC_T3] = 0; if (DBG_ST) dev_info(b4->dev, "setting port %d t1 timer to %lu\n", s->port + 1, s->hfc_timers[HFC_T1]); } } #if 0 /* TODO: This function is not called anywhere */ static void hfc_stop_st(struct b4xxp_span *s) { b4xxp_setreg_ra(s->parent, R_ST_SEL, s->port, A_ST_WR_STA, V_ST_ACT_DEACTIVATE); s->hfc_timer_on[HFC_T1] = 0; s->hfc_timer_on[HFC_T2] = 0; s->hfc_timer_on[HFC_T3] = 0; } #endif /* * read in the HFC GPIO to determine each port's mode (TE or NT). * Then, reset and start the port. * the flow controller should be set up before this is called. */ static void hfc_init_all_st(struct b4xxp *b4) { int i, gpio, nt; struct b4xxp_span *s; gpio = b4xxp_getreg8(b4, R_GPI_IN3); for (i=0; i < 4; i++) { s = &b4->spans[i]; s->parent = b4; s->port = i; nt = ((gpio & (1 << (i + 4))) == 0); /* GPIO=0 = NT mode */ s->te_mode = !nt; dev_info(b4->dev, "Port %d: %s mode\n", i + 1, (nt ? "NT" : "TE")); hfc_reset_st(s); hfc_start_st(s); } } /* * Look at one B-channel FIFO and determine if we should exchange data with it. * It is assumed that the S/T port is active. * returns 1 if data was exchanged, 0 otherwise. */ static int hfc_poll_one_bchan_fifo(struct b4xxp_span *span, int c) { int fifo, zlen, z1, z2, ret; unsigned long irq_flags; struct b4xxp *b4; struct dahdi_chan *chan; ret = 0; b4 = span->parent; fifo = span->fifos[c]; chan = span->chans[c]; spin_lock_irqsave(&b4->fifolock, irq_flags); /* select RX FIFO */ hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT) | V_FIFO_DIR | V_REV); get_Z(z1, z2, zlen); /* TODO: error checking, full FIFO mostly */ if (zlen >= DAHDI_CHUNKSIZE) { *(unsigned int *)&chan->readchunk[0] = b4xxp_getreg32(b4, A_FIFO_DATA2); *(unsigned int *)&chan->readchunk[4] = b4xxp_getreg32(b4, A_FIFO_DATA2); /* * now TX FIFO * * Note that we won't write to the TX FIFO if there wasn't room in the RX FIFO. * The TX and RX sides should be kept pretty much lock-step. * * Write the last byte _NOINC so that if we don't get more data in time, we aren't leaking unknown data * (See HFC datasheet) */ hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT) | V_REV); b4xxp_setreg32(b4, A_FIFO_DATA2, *(unsigned int *) &chan->writechunk[0]); b4xxp_setreg32(b4, A_FIFO_DATA2, *(unsigned int *) &chan->writechunk[4]); ret = 1; } spin_unlock_irqrestore(&b4->fifolock, irq_flags); return ret; } /* * Run through all of the host-facing B-channel RX FIFOs, looking for at least 8 bytes available. * If a B channel RX fifo has enough data, perform the data transfer in both directions. * D channel is done in an interrupt handler. * The S/T port state must be active or we ignore the fifo. * Returns nonzero if there was at least DAHDI_CHUNKSIZE bytes in the FIFO */ static int hfc_poll_fifos(struct b4xxp *b4) { int ret=0, span; unsigned long irq_flags; for (span=0; span < b4->numspans; span++) { /* Make sure DAHDI's got this span up */ if (!(b4->spans[span].span.flags & DAHDI_FLAG_RUNNING)) continue; /* TODO: Make sure S/T port is in active state */ #if 0 if (span_not_active(s)) continue; #endif ret = hfc_poll_one_bchan_fifo(&b4->spans[span], 0); ret |= hfc_poll_one_bchan_fifo(&b4->spans[span], 1); } /* change the active FIFO one last time to make sure the last-changed FIFO updates its pointers (as per the datasheet) */ spin_lock_irqsave(&b4->fifolock, irq_flags); hfc_setreg_waitbusy(b4, R_FIFO, (31 << V_FIFO_NUM_SHIFT)); spin_unlock_irqrestore(&b4->fifolock, irq_flags); return ret; } /* NOTE: assumes fifo lock is held */ static inline void debug_fz(struct b4xxp *b4, int fifo, const char *prefix, char *buf) { int f1, f2, flen, z1, z2, zlen; get_F(f1, f2, flen); get_Z(z1, z2, zlen); sprintf(buf, "%s: (fifo %d): f1/f2/flen=%d/%d/%d, z1/z2/zlen=%d/%d/%d\n", prefix, fifo, f1, f2, flen, z1, z2, zlen); } /* enable FIFO RX int and reset the FIFO */ static int hdlc_start(struct b4xxp *b4, int fifo) { b4->fifo_en_txint |= (1 << fifo); b4->fifo_en_rxint |= (1 << fifo); hfc_reset_fifo_pair(b4, fifo, 1, 0); return 0; } /* disable FIFO ints and reset the FIFO */ static void hdlc_stop(struct b4xxp *b4, int fifo) { b4->fifo_en_txint &= ~(1 << fifo); b4->fifo_en_rxint &= ~(1 << fifo); hfc_reset_fifo_pair(b4, fifo, 1, 0); } /* * Inner loop for D-channel receive function. * Retrieves a full HDLC frame from the hardware. * If the hardware indicates that the frame is complete, * we check the HDLC engine's STAT byte and update DAHDI as needed. * * Returns the number of HDLC frames left in the FIFO. */ static int hdlc_rx_frame(struct b4xxp_span *bspan) { int fifo, i, j, zleft; int z1, z2, zlen, f1, f2, flen; unsigned char buf[WCB4XXP_HDLC_BUF_LEN]; char debugbuf[256]; unsigned long irq_flags; struct b4xxp *b4 = bspan->parent; fifo = bspan->fifos[2]; spin_lock_irqsave(&b4->fifolock, irq_flags); hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT) | V_FIFO_DIR); get_F(f1, f2, flen); get_Z(z1, z2, zlen); debug_fz(b4, fifo, "hdlc_rx_frame", debugbuf); spin_unlock_irqrestore(&b4->fifolock, irq_flags); if (DBG_HDLC && DBG_SPANFILTER) { pr_info("%s", debugbuf); } /* first check to make sure we really do have HDLC frames available to retrieve */ if (flen == 0) { if (DBG_HDLC && DBG_SPANFILTER) { dev_info(b4->dev, "hdlc_rx_frame(span %d): no frames available?\n", bspan->port + 1); } return flen; } zleft = zlen + 1; /* include STAT byte that the HFC injects after FCS */ do { if (zleft > WCB4XXP_HDLC_BUF_LEN) j = WCB4XXP_HDLC_BUF_LEN; else j = zleft; spin_lock_irqsave(&b4->fifolock, irq_flags); hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT) | V_FIFO_DIR); for (i=0; i < j; i++) buf[i] = b4xxp_getreg8(b4, A_FIFO_DATA0); spin_unlock_irqrestore(&b4->fifolock, irq_flags); /* don't send STAT byte to DAHDI */ if (bspan->sigchan) dahdi_hdlc_putbuf(bspan->sigchan, buf, (j == WCB4XXP_HDLC_BUF_LEN) ? j : j - 1); zleft -= j; if (DBG_HDLC && DBG_SPANFILTER) { dev_info(b4->dev, "hdlc_rx_frame(span %d): z1/z2/zlen=%d/%d/%d, zleft=%d\n", bspan->port + 1, z1, z2, zlen, zleft); for (i=0; i < j; i++) printk("%02x%c", buf[i], (i < ( j - 1)) ? ' ':'\n'); } } while (zleft > 0); /* Frame received, increment F2 and get an updated count of frames left */ spin_lock_irqsave(&b4->fifolock, irq_flags); hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_INC_F); get_F(f1, f2, flen); spin_unlock_irqrestore(&b4->fifolock, irq_flags); /* If this channel is not configured with a signalling span we don't * need to notify the rest of dahdi about this frame. */ if (!bspan->sigchan) return flen; ++bspan->frames_in; if (zlen < 3) { if (DBG_HDLC && DBG_SPANFILTER) dev_notice(b4->dev, "odd, zlen less then 3?\n"); dahdi_hdlc_abort(bspan->sigchan, DAHDI_EVENT_ABORT); } else { unsigned char stat = buf[i - 1]; /* if STAT != 0, indicates bad frame */ if (stat != 0x00) { if (DBG_HDLC && DBG_SPANFILTER) dev_info(b4->dev, "(span %d) STAT=0x%02x indicates frame problem: ", bspan->port + 1, stat); if (stat == 0xff) { if (DBG_HDLC && DBG_SPANFILTER) printk("HDLC Abort\n"); dahdi_hdlc_abort(bspan->sigchan, DAHDI_EVENT_ABORT); } else { if (DBG_HDLC && DBG_SPANFILTER) printk("Bad FCS\n"); dahdi_hdlc_abort(bspan->sigchan, DAHDI_EVENT_BADFCS); } /* STAT == 0, means frame was OK */ } else { if (DBG_HDLC && DBG_SPANFILTER) dev_info(b4->dev, "(span %d) Frame %d is good!\n", bspan->port + 1, bspan->frames_in); dahdi_hdlc_finish(bspan->sigchan); } } return flen; } /* * Takes one blob of data from DAHDI and shoots it out to the hardware. * The blob may or may not be a complete HDLC frame. * If it isn't, the D-channel FIFO interrupt handler will take care of pulling the rest. * Returns nonzero if there is still data to send in the current HDLC frame. */ static int hdlc_tx_frame(struct b4xxp_span *bspan) { struct b4xxp *b4 = bspan->parent; int res, i, fifo; int z1, z2, zlen; unsigned char buf[WCB4XXP_HDLC_BUF_LEN]; unsigned int size = sizeof(buf) / sizeof(buf[0]); char debugbuf[256]; unsigned long irq_flags; /* if we're ignoring TE red alarms and we are in alarm, restart the S/T state machine */ if (bspan->te_mode && teignorered && bspan->newalarm == DAHDI_ALARM_RED) { hfc_force_st_state(b4, bspan->port, 3, 1); } fifo = bspan->fifos[2]; res = dahdi_hdlc_getbuf(bspan->sigchan, buf, &size); spin_lock_irqsave(&b4->fifolock, irq_flags); hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT)); get_Z(z1, z2, zlen); debug_fz(b4, fifo, "hdlc_tx_frame", debugbuf); /* TODO: check zlen, etc. */ if (size > 0) { bspan->sigactive = 1; for (i=0; i < size; i++) b4xxp_setreg8(b4, A_FIFO_DATA0, buf[i]); /* * If we got a full frame from DAHDI, increment F and decrement our HDLC pending counter. * Otherwise, select the FIFO again (to start transmission) and make sure the * TX IRQ is enabled so we will get called again to finish off the data */ if (res != 0) { ++bspan->frames_out; bspan->sigactive = 0; hfc_setreg_waitbusy(b4, A_INC_RES_FIFO, V_INC_F); atomic_dec(&bspan->hdlc_pending); } else { hfc_setreg_waitbusy(b4, R_FIFO, (fifo << V_FIFO_NUM_SHIFT)); b4xxp_setreg8(b4, A_IRQ_MSK, V_IRQ); } } /* if there are no more frames pending, disable the interrupt. */ if (res == -1) { b4xxp_setreg8(b4, A_IRQ_MSK, 0); } spin_unlock_irqrestore(&b4->fifolock, irq_flags); if (DBG_HDLC && DBG_SPANFILTER) { dev_info(b4->dev, "%s", debugbuf); dev_info(b4->dev, "hdlc_tx_frame(span %d): DAHDI gave %d bytes for FIFO %d (res=%d)\n", bspan->port + 1, size, fifo, res); for (i=0; i < size; i++) printk("%02x%c", buf[i], (i < (size - 1)) ? ' ' : '\n'); if (size && res != 0) pr_info("Transmitted frame %d on span %d\n", bspan->frames_out - 1, bspan->port); } return(res == 0); } /* * b4xxp lowlevel functions * These are functions which impact more than just the HFC controller. * (those are named hfc_xxx()) */ /* * Performs a total reset of the card, reinitializes GPIO. * The card is initialized enough to have LEDs running, and that's about it. * Anything to do with audio and enabling any kind of processing is done in stage2. */ static void b4xxp_init_stage1(struct b4xxp *b4) { int i; hfc_reset(b4); /* total reset of controller */ hfc_gpio_init(b4); /* initialize controller GPIO for CPLD access */ ec_init(b4); /* initialize VPM and VPM GPIO */ b4xxp_setreg8(b4, R_IRQ_CTRL, 0x00); /* make sure interrupts are disabled */ flush_pci(); /* make sure PCI write hits hardware */ /* disable all FIFO interrupts */ for (i=0; i < HFC_NR_FIFOS; i++) { hfc_setreg_waitbusy(b4, R_FIFO, (i << V_FIFO_NUM_SHIFT)); b4xxp_setreg8(b4, A_IRQ_MSK, 0x00); /* disable the interrupt */ hfc_setreg_waitbusy(b4, R_FIFO, (i << V_FIFO_NUM_SHIFT) | V_FIFO_DIR); b4xxp_setreg8(b4, A_IRQ_MSK, 0x00); /* disable the interrupt */ flush_pci(); } /* clear any pending FIFO interrupts */ b4xxp_getreg8(b4, R_IRQ_FIFO_BL0); b4xxp_getreg8(b4, R_IRQ_FIFO_BL1); b4xxp_getreg8(b4, R_IRQ_FIFO_BL2); b4xxp_getreg8(b4, R_IRQ_FIFO_BL3); b4xxp_getreg8(b4, R_IRQ_FIFO_BL4); b4xxp_getreg8(b4, R_IRQ_FIFO_BL5); b4xxp_getreg8(b4, R_IRQ_FIFO_BL6); b4xxp_getreg8(b4, R_IRQ_FIFO_BL7); b4xxp_setreg8(b4, R_SCI_MSK, 0x00); /* mask off all S/T interrupts */ b4xxp_setreg8(b4, R_IRQMSK_MISC, 0x00); /* nothing else can generate an interrupt */ /* * set up the clock controller * we have a 24.576MHz crystal, so the PCM clock is 2x the incoming clock. */ b4xxp_setreg8(b4, R_BRG_PCM_CFG, 0x02); flush_pci(); udelay(100); /* wait a bit for clock to settle */ } /* * Stage 2 hardware init. * Sets up the flow controller, PCM and FIFOs. * Initializes the echo cancellers. * S/T interfaces are not initialized here, that is done later, in hfc_init_all_st(). * Interrupts are enabled and once the s/t interfaces are configured, chip should be pretty much operational. */ static void b4xxp_init_stage2(struct b4xxp *b4) { int span; /* * set up PCM bus. * HFC is PCM master. * C4IO, SYNC_I and SYNC_O unused. * 32 channels, frame signal positive polarity, active for 2 C4 clocks. * only the first two timeslots in each quad are active * STIO0 is transmit-only, STIO1 is receive-only. */ b4xxp_setreg8(b4, R_PCM_MD0, V_PCM_MD | V_PCM_IDX_MD1); flush_pci(); b4xxp_setreg8(b4, R_PCM_MD1, V_PLL_ADJ_00 | V_PCM_DR_2048); /* * set up the flow controller. * B channel map: * FIFO 0 connects Port 1 B0 using HFC channel 16 and PCM timeslots 0/1. * FIFO 1 connects Port 1 B1 using HFC channel 17 and PCM timeslots 4/5. * FIFO 2 connects Port 2 B0 using HFC channel 20 and PCM timeslots 8/9. * FIFO 3 connects Port 2 B1 using HFC channel 21 and PCM timeslots 12/13. * FIFO 4 connects Port 3 B0 using HFC channel 24 and PCM timeslots 16/17. * FIFO 5 connects Port 3 B1 using HFC channel 25 and PCM timeslots 20/21. * FIFO 6 connects Port 4 B0 using HFC channel 28 and PCM timeslots 24/25. * FIFO 7 connects Port 4 B1 using HFC channel 29 and PCM timeslots 28/29. * * All B channel FIFOs have their HDLC controller in transparent mode, * and only the FIFO for B0 on each port has its interrupt operational. * * D channels are handled by FIFOs 8-11. * FIFO 8 connects Port 1 D using HFC channel 3 * FIFO 9 connects Port 1 D using HFC channel 7 * FIFO 10 connects Port 1 D using HFC channel 11 * FIFO 11 connects Port 1 D using HFC channel 15 * * D channel FIFOs are operated in HDLC mode and interrupt on end of frame. */ for (span=0; span < b4->numspans; span++) { if (vpmsupport) { hfc_assign_bchan_fifo_ec(b4, span, 0); hfc_assign_bchan_fifo_ec(b4, span, 1); } else { hfc_assign_bchan_fifo_noec(b4, span, 0); hfc_assign_bchan_fifo_noec(b4, span, 1); } hfc_assign_dchan_fifo(b4, span); } /* set up the timer interrupt for 1ms intervals */ b4xxp_setreg8(b4, R_TI_WD, (2 << V_EV_TS_SHIFT)); /* * At this point, everything's set up and ready to go. * Don't actually enable the global interrupt pin. * DAHDI still needs to start up the spans, and we don't know exactly when. */ } static void b4xxp_setleds(struct b4xxp *b4, unsigned char val) { ec_write(b4, 0, 0x1a8 + 3, val); } static void b4xxp_set_span_led(struct b4xxp *b4, int span, unsigned char val) { int shift, spanmask; shift = span << 1; spanmask = ~(0x03 << shift); b4->ledreg &= spanmask; b4->ledreg |= (val << shift); b4xxp_setleds(b4, b4->ledreg); } static void b4xxp_update_leds(struct b4xxp *b4) { int i; struct b4xxp_span *bspan; b4->blinktimer++; for (i=0; i < b4->numspans; i++) { bspan = &b4->spans[i]; if (bspan->span.flags & DAHDI_FLAG_RUNNING) { if (bspan->span.alarms) { if (b4->blinktimer == (led_fader_table[b4->alarmpos] >> 1)) b4xxp_set_span_led(b4, i, LED_RED); if (b4->blinktimer == 0xf) b4xxp_set_span_led(b4, i, LED_OFF); } else if (bspan->span.mainttimer || bspan->span.maintstat) { if (b4->blinktimer == (led_fader_table[b4->alarmpos] >> 1)) b4xxp_set_span_led(b4, i, LED_GREEN); if (b4->blinktimer == 0xf) b4xxp_set_span_led(b4, i, LED_OFF); } else { /* No Alarm */ b4xxp_set_span_led(b4, i, LED_GREEN); } } else b4xxp_set_span_led(b4, i, LED_OFF); } if (b4->blinktimer == 0xf) { b4->blinktimer = -1; b4->alarmpos++; if (b4->alarmpos >= (sizeof(led_fader_table) / sizeof(led_fader_table[0]))) b4->alarmpos = 0; } } static int echocan_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec) { struct b4xxp_span *bspan = chan->span->pvt; int channel; if (chan->chanpos == 3) { printk(KERN_WARNING "Cannot enable echo canceller on D channel of span %d; failing request\n", chan->span->offset); return -EINVAL; } if (ecp->param_count > 0) { printk(KERN_WARNING "wcb4xxp echo canceller does not support parameters; failing request\n"); return -EINVAL; } *ec = &bspan->ec[chan->chanpos]; (*ec)->ops = &my_ec_ops; (*ec)->features = my_ec_features; if (DBG_EC) printk("Enabling echo cancellation on chan %d span %d\n", chan->chanpos, chan->span->offset); channel = (chan->span->offset * 8) + ((chan->chanpos - 1) * 4) + 1; ec_write(bspan->parent, chan->chanpos - 1, channel, 0x7e); return 0; } static void echocan_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec) { struct b4xxp_span *bspan = chan->span->pvt; int channel; memset(ec, 0, sizeof(*ec)); if (DBG_EC) printk("Disabling echo cancellation on chan %d span %d\n", chan->chanpos, chan->span->offset); channel = (chan->span->offset * 8) + ((chan->chanpos - 1) * 4) + 1; ec_write(bspan->parent, chan->chanpos - 1, channel, 0x01); } /* * Filesystem and DAHDI interfaces */ static int b4xxp_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long data) { switch(cmd) { default: return -ENOTTY; } return 0; } static int b4xxp_startup(struct dahdi_span *span) { struct b4xxp_span *bspan = span->pvt; struct b4xxp *b4 = bspan->parent; if (!b4->running) hfc_enable_interrupts(bspan->parent); return 0; } static int b4xxp_shutdown(struct dahdi_span *span) { struct b4xxp_span *bspan = span->pvt; hfc_disable_interrupts(bspan->parent); return 0; } /* resets all the FIFOs for a given span. Disables IRQs for the span FIFOs */ static void b4xxp_reset_span(struct b4xxp_span *bspan) { int i; struct b4xxp *b4 = bspan->parent; for (i=0; i < 3; i++) { hfc_reset_fifo_pair(b4, bspan->fifos[i], (i == 2) ? 1 : 0, 1); } b4xxp_set_sync_src(b4, b4xxp_find_sync(b4)); } /* spanconfig for us means to set up the HFC FIFO and channel mapping */ static int b4xxp_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc) { int i; struct b4xxp_span *bspan = span->pvt; struct b4xxp *b4 = bspan->parent; if (DBG) dev_info(b4->dev, "Configuring span %d\n", span->spanno); #if 0 if (lc->sync > 0 && bspan->te_mode) { dev_info(b4->dev, "Span %d is not in NT mode, removing from sync source list\n", span->spanno); lc->sync = 0; } #endif if (lc->sync < 0 || lc->sync > 4) { dev_info(b4->dev, "Span %d has invalid sync priority (%d), removing from sync source list\n", span->spanno, lc->sync); lc->sync = 0; } /* remove this span number from the current sync sources, if there */ for (i = 0; i < b4->numspans; i++) { if (b4->spans[i].sync == span->spanno) { b4->spans[i].sync = 0; } } /* if a sync src, put it in proper place */ b4->spans[span->offset].syncpos = lc->sync; if (lc->sync) { b4->spans[lc->sync - 1].sync = span->spanno; } b4xxp_reset_span(bspan); /* call startup() manually here, because DAHDI won't call the startup function unless it receives an IOCTL to do so, and dahdi_cfg doesn't. */ b4xxp_startup(&bspan->span); span->flags |= DAHDI_FLAG_RUNNING; return 0; } /* chanconfig for us means to configure the HDLC controller, if appropriate */ static int b4xxp_chanconfig(struct dahdi_chan *chan, int sigtype) { int alreadyrunning; struct b4xxp *b4 = chan->pvt; struct b4xxp_span *bspan = &b4->spans[chan->span->offset]; int fifo = bspan->fifos[2]; alreadyrunning = bspan->span.flags & DAHDI_FLAG_RUNNING; if (DBG_FOPS) { dev_info(b4->dev, "%s channel %d (%s) sigtype %08x\n", alreadyrunning ? "Reconfigured" : "Configured", chan->channo, chan->name, sigtype); } /* (re)configure signalling channel */ if ((sigtype == DAHDI_SIG_HARDHDLC) || (bspan->sigchan == chan)) { if (DBG_FOPS) dev_info(b4->dev, "%sonfiguring hardware HDLC on %s\n", ((sigtype == DAHDI_SIG_HARDHDLC) ? "C" : "Unc"), chan->name); if (alreadyrunning && bspan->sigchan) { hdlc_stop(b4, fifo); bspan->sigchan = NULL; } if (sigtype == DAHDI_SIG_HARDHDLC) { if (hdlc_start(b4, fifo)) { dev_warn(b4->dev, "Error initializing signalling controller\n"); return -1; } } bspan->sigchan = (sigtype == DAHDI_SIG_HARDHDLC) ? chan : NULL; bspan->sigactive = 0; atomic_set(&bspan->hdlc_pending, 0); } else { /* FIXME: shouldn't I be returning an error? */ } return 0; } static int b4xxp_open(struct dahdi_chan *chan) { struct b4xxp *b4 = chan->pvt; struct b4xxp_span *bspan = &b4->spans[chan->span->offset]; if (!try_module_get(THIS_MODULE)) { return -EBUSY; } if (DBG_FOPS && DBG_SPANFILTER) dev_info(b4->dev, "open() on chan %s (%i/%i)\n", chan->name, chan->channo, chan->chanpos); hfc_reset_fifo_pair(b4, bspan->fifos[chan->chanpos], 0, 0); return 0; } static int b4xxp_close(struct dahdi_chan *chan) { struct b4xxp *b4 = chan->pvt; struct b4xxp_span *bspan = &b4->spans[chan->span->offset]; module_put(THIS_MODULE); if (DBG_FOPS && DBG_SPANFILTER) dev_info(b4->dev, "close() on chan %s (%i/%i)\n", chan->name, chan->channo, chan->chanpos); hfc_reset_fifo_pair(b4, bspan->fifos[chan->chanpos], 1, 1); return 0; } /* DAHDI calls this when it has data it wants to send to the HDLC controller */ static void b4xxp_hdlc_hard_xmit(struct dahdi_chan *chan) { struct b4xxp *b4 = chan->pvt; int span = chan->span->offset; struct b4xxp_span *bspan = &b4->spans[span]; if ((DBG_FOPS || DBG_HDLC) && DBG_SPANFILTER) dev_info(b4->dev, "hdlc_hard_xmit on chan %s (%i/%i), span=%i\n", chan->name, chan->channo, chan->chanpos, span + 1); /* * increment the hdlc_pending counter and trigger the bottom-half so it * will be picked up and sent. */ if (bspan->sigchan == chan) { atomic_inc(&bspan->hdlc_pending); } } /* internal functions, not specific to the hardware or DAHDI */ /* initialize the span/chan structures. Doesn't touch hardware, although the callbacks might. */ static void init_spans(struct b4xxp *b4) { int i, j; struct b4xxp_span *bspan; struct dahdi_chan *chan; /* for each span on the card */ for (i=0; i < b4->numspans; i++) { bspan = &b4->spans[i]; bspan->parent = b4; bspan->span.irq = b4->pdev->irq; bspan->span.pvt = bspan; bspan->span.spantype = (bspan->te_mode) ? "TE" : "NT"; bspan->span.offset = i; bspan->span.channels = WCB4XXP_CHANNELS_PER_SPAN; bspan->span.flags = 0; bspan->span.deflaw = DAHDI_LAW_ALAW; /* For simplicty, we'll accept all line modes since BRI * ignores this setting anyway.*/ bspan->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS | DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF | DAHDI_CONFIG_HDB3 | DAHDI_CONFIG_CCS | DAHDI_CONFIG_CRC4; sprintf(bspan->span.name, "B4/%d/%d", b4->cardno, i+1); sprintf(bspan->span.desc, "B4XXP (PCI) Card %d Span %d", b4->cardno, i+1); bspan->span.manufacturer = "Digium"; dahdi_copy_string(bspan->span.devicetype, b4->variety, sizeof(bspan->span.devicetype)); sprintf(bspan->span.location, "PCI Bus %02d Slot %02d", b4->pdev->bus->number, PCI_SLOT(b4->pdev->devfn) + 1); bspan->span.spanconfig = b4xxp_spanconfig; bspan->span.chanconfig = b4xxp_chanconfig; bspan->span.startup = b4xxp_startup; bspan->span.shutdown = b4xxp_shutdown; bspan->span.open = b4xxp_open; bspan->span.close = b4xxp_close; bspan->span.ioctl = b4xxp_ioctl; bspan->span.hdlc_hard_xmit = b4xxp_hdlc_hard_xmit; if (vpmsupport) bspan->span.echocan_create = echocan_create; /* HDLC stuff */ bspan->sigchan = NULL; bspan->sigactive = 0; bspan->span.chans = bspan->chans; init_waitqueue_head(&bspan->span.maintq); /* now initialize each channel in the span */ for (j=0; j < WCB4XXP_CHANNELS_PER_SPAN; j++) { bspan->chans[j] = &bspan->_chans[j]; chan = bspan->chans[j]; chan->pvt = b4; sprintf(chan->name, "B4/%d/%d/%d", b4->cardno, i + 1, j + 1); /* The last channel in the span is the D-channel */ if (j == WCB4XXP_CHANNELS_PER_SPAN - 1) { chan->sigcap = DAHDI_SIG_HARDHDLC; } else { chan->sigcap = DAHDI_SIG_CLEAR | DAHDI_SIG_DACS; } chan->chanpos = j + 1; chan->writechunk = (void *)(bspan->writechunk + j * DAHDI_CHUNKSIZE); chan->readchunk = (void *)(bspan->readchunk + j * DAHDI_CHUNKSIZE); } } } static void b4xxp_bottom_half(unsigned long data); /* top-half interrupt handler */ DAHDI_IRQ_HANDLER(b4xxp_interrupt) { struct b4xxp *b4 = dev_id; unsigned char status; int i; /* Make sure it's really for us */ status = __pci_in8(b4, R_STATUS); if (!(status & HFC_INTS)) return IRQ_NONE; /* * since the interrupt is for us, read in the FIFO and misc IRQ status registers. * Don't replace the struct copies; OR in the new bits instead. * That way if we get behind, we don't lose anything. * We don't actually do any processing here, we simply flag the bottom-half to do the heavy lifting. */ if (status & V_FR_IRQSTA) { b4->fifo_irqstatus[0] |= __pci_in8(b4, R_IRQ_FIFO_BL0); b4->fifo_irqstatus[1] |= __pci_in8(b4, R_IRQ_FIFO_BL1); b4->fifo_irqstatus[2] |= __pci_in8(b4, R_IRQ_FIFO_BL2); b4->fifo_irqstatus[3] |= __pci_in8(b4, R_IRQ_FIFO_BL3); b4->fifo_irqstatus[4] |= __pci_in8(b4, R_IRQ_FIFO_BL4); b4->fifo_irqstatus[5] |= __pci_in8(b4, R_IRQ_FIFO_BL5); b4->fifo_irqstatus[6] |= __pci_in8(b4, R_IRQ_FIFO_BL6); b4->fifo_irqstatus[7] |= __pci_in8(b4, R_IRQ_FIFO_BL7); } if (status & V_MISC_IRQSTA) { b4->misc_irqstatus |= __pci_in8(b4, R_IRQ_MISC); } /* * Well, that was the plan. It appears that I can't do this in the bottom half * or I start to see data corruption (too long a time between IRQ and tasklet??) * So, I do the B-channel stuff right here in interrupt context. yuck. */ if (b4->misc_irqstatus & V_TI_IRQ) { hfc_poll_fifos(b4); for (i=0; i < b4->numspans; i++) { if (b4->spans[i].span.flags & DAHDI_FLAG_RUNNING) { dahdi_ec_span(&b4->spans[i].span); dahdi_receive(&b4->spans[i].span); dahdi_transmit(&b4->spans[i].span); } } } /* kick off bottom-half handler */ /* tasklet_hi_schedule(&b4->b4xxp_tlet); */ b4xxp_bottom_half((unsigned long)b4); return IRQ_RETVAL(1); } /* * The bottom half of course does all the heavy lifting for the interrupt. * * The original plan was to have the B channel RX FIFO interrupts enabled, and * to do the actual work here. Since that doesn't seem to work so well, we * poll the B channel FIFOs right in the interrupt handler and take care of the B * channel stuff there. The bottom half works for the timer interrupt and D * channel stuff. * * The HFC-4S timer interrupt is used to for several things: * - Update the S/T state machines, expire their timers, etc. * - Provide DAHDI's timing source, if so configured * - Update LEDs */ static void b4xxp_bottom_half(unsigned long data) { struct b4xxp *b4 = (struct b4xxp *)data; int i, j, k, gotrxfifo, fifo; unsigned char b, b2; if (b4->shutdown) return; gotrxfifo = 0; for (i=0; i < 8; i++) { b = b2 = b4->fifo_irqstatus[i]; for (j=0; j < b4->numspans; j++) { fifo = i*4 + j; if (b & V_IRQ_FIFOx_TX) { if (fifo >=8 && fifo <= 11) { /* d-chan fifo */ /* * WOW I don't like this. * It's bad enough that I have to send a fake frame to get an HDLC TX FIFO interrupt, * but now, I have to loop until the whole frame is read, or I get RX interrupts * (even though the chip says HDLC mode gives an IRQ when a *full frame* is received). * Yuck. It works well, but yuck. */ do { k = hdlc_tx_frame(&b4->spans[fifo - 8]); } while (k); } else { if (printk_ratelimit()) dev_warn(b4->dev, "Got FIFO TX int from non-d-chan FIFO %d??\n", fifo); } } if (b & V_IRQ_FIFOx_RX) { if (fifo >=8 && fifo <= 11) { /* * I have to loop here until hdlc_rx_frame says there are no more frames waiting. * for whatever reason, the HFC will not generate another interrupt if there are * still HDLC frames waiting to be received. * i.e. I get an int when F1 changes, not when F1 != F2. */ do { k = hdlc_rx_frame(&b4->spans[fifo - 8]); } while (k); } else { if (printk_ratelimit()) dev_warn(b4->dev, "Got FIFO RX int from non-d-chan FIFO %d??\n", fifo); } } b >>= 2; } /* zero the bits we just processed */ b4->fifo_irqstatus[i] &= ~b2; } /* * timer interrupt * every tick (1ms), check the FIFOs and run through the S/T port timers. * every 100ms or so, look for S/T state machine changes. */ if (b4->misc_irqstatus & V_TI_IRQ) { /* * We should check the FIFOs here, but I'm seeing this tasklet getting scheduled FAR too late to be useful. * For now, we're handling that in the IRQ handler itself. (ICK!!) */ b4->ticks++; hfc_update_st_timers(b4); b4xxp_update_leds(b4); /* every 100ms or so, look at the S/T interfaces to see if they changed state */ if (!(b4->ticks % 100)) { b = b4xxp_getreg8(b4, R_SCI); if (b) { for (i=0; i < b4->numspans; i++) { if (b & (1 << i)) hfc_handle_state(&b4->spans[i]); } } } /* We're supposed to kick DAHDI here, too, but again, seeing too much latency between the interrupt and the bottom-half. */ /* clear the timer interrupt flag. */ b4->misc_irqstatus &= ~V_TI_IRQ; } /* * Check for outgoing HDLC frame requests * The HFC does not generate TX interrupts when there is room to send, so * I use an atomic counter that is incremented every time DAHDI wants to send * a frame, and decremented every time I send a frame. It'd be better if I could * just use the interrupt handler, but the HFC seems to trigger a FIFO TX IRQ * only when it has finished sending a frame, not when one can be sent. */ for (i=0; i < b4->numspans; i++) { struct b4xxp_span *bspan = &b4->spans[i]; if (atomic_read(&bspan->hdlc_pending)) { do { k = hdlc_tx_frame(bspan); } while (k); } } } /********************************************************************************* proc stuff *****/ #ifdef CREATE_WCB4XXP_PROCFS_ENTRY static int b4xxp_proc_read_one(char *buf, struct b4xxp *b4) { struct dahdi_chan *chan; int len, i, j; char str[80], sBuf[4096]; *sBuf=0; sprintf(sBuf, "Card %d, PCI identifier %s, IRQ %d\n", b4->cardno + 1, b4->dev->bus_id, b4->irq); strcat(sBuf,"Tx:\n"); for (j=0; j<8; j++) { for (i=0; i<12; i++) { chan = b4->spans[i/3].chans[i%3]; sprintf(str, "%02x ", chan->writechunk[j]); strcat(sBuf, str); } strcat(sBuf, "\n"); } strcat(sBuf, "\nRx:\n"); for (j=0; j < 8; j++) { for (i=0; i < 12; i++) { chan = b4->spans[i / 3].chans[i % 3]; sprintf(str, "%02x%c", chan->readchunk[j], (i == 11) ? '\n' : ' '); strcat(sBuf, str); } } strcat(sBuf, "\nPort states:\n"); for (i=0; i < 4; i++) { int state; char *x; struct b4xxp_span *s = &b4->spans[i]; state = b4xxp_getreg_ra(b4, R_ST_SEL, s->port, A_ST_RD_STA); x = hfc_decode_st_state(b4, s->port, state, 0); sprintf(str, "%s\n", x); strcat(sBuf, str); kfree(x); } len = sprintf(buf, "%s\n%s\nTicks: %ld\n", sBuf, str, b4->ticks); return len; } static int b4xxp_proc_read(char *buf, char **start, off_t offset, int count, int *eof, void *data) { struct b4xxp **b4_cards = data; char sBuf[256]; int i, len; len = sprintf(buf, "WCB4XXP Card Information\n"); for (i=0; b4_cards[i] != NULL; i++) { if (i) len += sprintf(buf + len, "\n-----\n"); len += b4xxp_proc_read_one(buf + len, b4_cards[i]); } *sBuf = 0; strcat(sBuf, "\n-----\n\nAudio: "); #ifdef LOOPBACK_SUPPORTED if (loopback >= 3) strcat(sBuf, "DAHDI and S/T"); else if (loopback == 2) strcat(sBuf, "DAHDI"); else if (loopback == 1) strcat(sBuf, "S/T"); else strcat(sBuf, "not"); strcat(sBuf, " looped back"); #else strcat(sBuf, "not looped back"); #endif if (milliwatt) strcat(sBuf, ", outgoing S/T replaced with mu-law milliwatt tone"); len += sprintf(buf + len, "%s\n", sBuf); if (alarmdebounce) sprintf(sBuf, "Alarms: debounced (%dms)", alarmdebounce); else strcpy(sBuf, "Alarms: not debounced"); len += sprintf(buf + len, "%s\nT1 timer period %dms\nT3 timer period %dms\n", sBuf, timer_1_ms, timer_3_ms); *eof = 1; return len; } #endif /* CREATE_WCB4XXP_PROCFS_ENTRY */ static int __devinit b4xx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { int x, ret; struct b4xxp *b4; struct devtype *dt; dt = (struct devtype *)(ent->driver_data); dev_info(&pdev->dev, "probe called for b4xx...\n"); if ((ret = pci_enable_device(pdev))) goto err_out_disable_pdev; if ((ret = pci_request_regions(pdev, dt->desc))) { dev_err(&pdev->dev, "Unable to request regions!\n"); goto err_out_disable_pdev; } if (!pdev->irq) { /* we better have an IRQ */ dev_err(&pdev->dev, "Device has no associated IRQ?\n"); ret = -EIO; goto err_out_release_regions; } if (!(b4 = kzalloc(sizeof(struct b4xxp), GFP_KERNEL))) { dev_err(&pdev->dev, "Couldn't allocate memory for b4xxp structure!\n"); ret = -ENOMEM; goto err_out_release_regions; } /* card found, enabled and main struct allocated. Fill it out. */ b4->magic = WCB4XXP_MAGIC; b4->variety = dt->desc; b4->pdev = pdev; b4->dev = &pdev->dev; pci_set_drvdata(pdev, b4); b4->ioaddr = pci_iomap(pdev, 0, 0); b4->addr = pci_iomap(pdev, 1, 0); b4->irq = pdev->irq; spin_lock_init(&b4->reglock); spin_lock_init(&b4->seqlock); spin_lock_init(&b4->fifolock); x = b4xxp_getreg8(b4, R_CHIP_ID); if (x != 0xc0) { /* wrong chip? */ dev_err(&pdev->dev, "Unknown/unsupported controller detected (R_CHIP_ID = 0x%02x)\n", x); goto err_out_free_mem; } /* future proofing */ b4->chiprev = b4xxp_getreg8(b4, R_CHIP_RV); /* check for various board-specific flags and modify init as necessary */ /* if (dt->flags & FLAG_XXX) use_flag_somehow(); */ /* TODO: determine whether this is a 2, 4 or 8 port card */ b4->numspans = 4; b4->syncspan = -1; /* sync span is unknown */ if (b4->numspans > MAX_SPANS_PER_CARD) { dev_err(b4->dev, "Driver does not know how to handle a %d span card!\n", b4->numspans); goto err_out_free_mem; } dev_info(b4->dev, "Identified %s (controller rev %d) at %p, IRQ %i\n", b4->variety, b4->chiprev, b4->ioaddr, b4->irq); /* look for the next free card structure */ for (x=0; x < MAX_B4_CARDS; x++) { if (!cards[x]) break; } if (x >= MAX_B4_CARDS) { dev_err(&pdev->dev, "Attempt to register more than %i cards, aborting!\n", MAX_B4_CARDS); goto err_out_free_mem; } /* update the cards array, make sure the b4xxp struct knows where in the array it is */ b4->cardno = x; cards[x] = b4; b4xxp_init_stage1(b4); if (request_irq(pdev->irq, b4xxp_interrupt, DAHDI_IRQ_SHARED_DISABLED, "b4xxp", b4)) { dev_err(b4->dev, "Unable to request IRQ %d\n", pdev->irq); ret = -EIO; goto err_out_del_from_card_array; } /* initialize the tasklet structure */ /* TODO: perhaps only one tasklet for any number of cards in the system... don't need one per card I don't think. */ tasklet_init(&b4->b4xxp_tlet, b4xxp_bottom_half, (unsigned long)b4); /* interrupt allocated and tasklet initialized, it's now safe to finish initializing the hardware */ b4xxp_init_stage2(b4); hfc_init_all_st(b4); /* initialize the DAHDI structures, and let DAHDI know it has some new hardware to play with */ init_spans(b4); for (x=0; x < b4->numspans; x++) { if (dahdi_register(&b4->spans[x].span, 0)) { dev_err(b4->dev, "Unable to register span %s\n", b4->spans[x].span.name); goto err_out_unreg_spans; } } #if 0 /* Launch cards as appropriate */ for (;;) { /* Find a card to activate */ f = 0; for (x=0; cards[x]; x++) { if (cards[x]->order <= highestorder) { b4_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; } #else dev_info(b4->dev, "Did not do the highestorder stuff\n"); #endif ret = 0; return ret; /* 'x' will have the failing span #. (0-3). We need to unregister everything before it. */ err_out_unreg_spans: while (x) { dahdi_unregister(&b4->spans[x].span); x--; }; b4xxp_init_stage1(b4); /* full reset, re-init to "no-irq" state */ free_irq(pdev->irq, b4); err_out_del_from_card_array: for (x=0; x < MAX_B4_CARDS; x++) { if (cards[x] == b4) { b4->cardno = -1; cards[x] = NULL; break; } } if (x >= MAX_B4_CARDS) dev_err(&pdev->dev, "b4 struct @ %p should be in cards array but isn't?!\n", b4); err_out_free_mem: pci_set_drvdata(pdev, NULL); pci_iounmap(pdev, b4->ioaddr); pci_iounmap(pdev, b4->addr); kfree(b4); err_out_release_regions: pci_release_regions(pdev); err_out_disable_pdev: pci_disable_device(pdev); return ret; } static void __devexit b4xxp_remove(struct pci_dev *pdev) { struct b4xxp *b4 = pci_get_drvdata(pdev); int i; if (b4) { b4->shutdown = 1; for (i=b4->numspans - 1; i >= 0; i--) { dahdi_unregister(&b4->spans[i].span); } b4xxp_init_stage1(b4); free_irq(pdev->irq, b4); pci_set_drvdata(pdev, NULL); pci_iounmap(pdev, b4->ioaddr); pci_iounmap(pdev, b4->addr); pci_release_regions(pdev); pci_disable_device(pdev); b4->ioaddr = b4->addr = NULL; b4->magic = 0; tasklet_kill(&b4->b4xxp_tlet); kfree(b4); } dev_info(&pdev->dev, "Driver unloaded.\n"); return; } static struct pci_device_id b4xx_ids[] __devinitdata = { { 0xd161, 0xb410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)&wcb4xxp }, { 0, } }; static struct pci_driver b4xx_driver = { .name = "wcb4xxp", .probe = b4xx_probe, .remove = __devexit_p(b4xxp_remove), .id_table = b4xx_ids, }; static int __init b4xx_init(void) { #ifdef CREATE_WCB4XXP_PROCFS_ENTRY if (!(myproc = create_proc_read_entry(PROCFS_NAME, 0444, NULL, b4xxp_proc_read, cards))) { printk(KERN_ERR "%s: ERROR: Could not initialize /proc/%s\n",THIS_MODULE->name, PROCFS_NAME); } #endif if (dahdi_pci_module(&b4xx_driver)) return -ENODEV; return 0; } static void __exit b4xx_exit(void) { #ifdef CREATE_WCB4XXP_PROCFS_ENTRY remove_proc_entry(PROCFS_NAME, NULL); #endif pci_unregister_driver(&b4xx_driver); } module_param(debug, int, S_IRUGO | S_IWUSR); module_param(spanfilter, int, S_IRUGO | S_IWUSR); #ifdef LOOKBACK_SUPPORTED module_param(loopback, int, S_IRUGO | S_IWUSR); #endif module_param(milliwatt, int, S_IRUGO | S_IWUSR); module_param(pedanticpci, int, S_IRUGO); module_param(teignorered, int, S_IRUGO | S_IWUSR); module_param(alarmdebounce, int, S_IRUGO | S_IWUSR); module_param(vpmsupport, int, S_IRUGO); module_param(timer_1_ms, int, S_IRUGO | S_IWUSR); module_param(timer_3_ms, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "bitmap: 1=general 2=dtmf 4=regops 8=fops 16=ec 32=st state 64=hdlc 128=alarm"); MODULE_PARM_DESC(spanfilter, "debug filter for spans. bitmap: 1=port 1, 2=port 2, 4=port 3, 8=port 4"); #ifdef LOOKBACK_SUPPORTED MODULE_PARM_DESC(loopback, "TODO: bitmap: 1=loop back S/T port 2=loop back DAHDI"); #endif MODULE_PARM_DESC(milliwatt, "1=replace outgoing S/T data with mu-law milliwatt"); MODULE_PARM_DESC(pedanticpci, "1=disable PCI back-to-back transfers and flush all PCI writes immediately"); MODULE_PARM_DESC(teignorered, "1=ignore (do not inform DAHDI) if a red alarm exists in TE mode"); MODULE_PARM_DESC(alarmdebounce, "msec to wait before set/clear alarm condition"); MODULE_PARM_DESC(vpmsupport, "1=enable hardware EC, 0=disable hardware EC"); MODULE_PARM_DESC(timer_1_ms, "NT: msec to wait for link activation, TE: unused."); MODULE_PARM_DESC(timer_3_ms, "TE: msec to wait for link activation, NT: unused."); MODULE_AUTHOR("Digium Incorporated "); MODULE_DESCRIPTION("B410P quad-port BRI module driver."); MODULE_LICENSE("GPL"); MODULE_DEVICE_TABLE(pci, b4xx_ids); module_init(b4xx_init); module_exit(b4xx_exit); dahdi-linux-2.2.0-rc4/drivers/dahdi/wcb4xxp/wcb4xxp.h0000644000175000017500000004713211176115504021557 0ustar maniacmaniac/* * Wilcard B410P Quad-BRI Interface Driver for Zapata Telephony interface * Written by Andrew Kohlsmith */ #ifndef _B4XX_H_ #define _B4XX_H_ #include #define HFC_NR_FIFOS 32 #define HFC_ZMIN 0x80 /* from datasheet */ #define HFC_ZMAX 0x1ff #define HFC_FMIN 0x00 #define HFC_FMAX 0x0f /* * yuck. Any reg which is not mandated read/write or read-only is write-only. * Also, there are dozens of registers with the same address. * Additionally, there are array registers (A_) which have an index register * These A_ registers require an index register to be written to indicate WHICH in the array you want. */ #define R_CIRM 0x00 /* WO */ #define R_CTRL 0x01 /* WO */ #define R_BRG_PCM_CFG 0x02 /* WO */ #define A_Z12 0x04 /* RO */ #define A_Z1L 0x04 /* RO */ #define A_Z1 0x04 /* RO */ #define A_Z1H 0x05 /* RO */ #define A_Z2L 0x06 /* RO */ #define A_Z2 0x06 /* RO */ #define A_Z2H 0x07 /* RO */ #define R_RAM_ADDR0 0x08 /* WO */ #define R_RAM_ADDR1 0x09 /* WO */ #define R_RAM_ADDR2 0x0a /* WO */ #define R_FIRST_FIFO 0x0b /* WO */ #define R_RAM_MISC 0x0c /* WO */ #define A_F1 0x0c /* RO */ #define A_F12 0x0c /* RO */ #define R_FIFO_MD 0x0d /* WO */ #define A_F2 0x0d /* RO */ #define A_INC_RES_FIFO 0x0e /* WO */ #define R_FSM_IDX 0x0f /* WO */ #define R_FIFO 0x0f /* WO */ #define R_SLOT 0x10 /* WO */ #define R_IRQ_OVIEW 0x10 /* RO */ #define R_IRQMSK_MISC 0x11 /* WO */ #define R_IRQ_MISC 0x11 /* RO */ #define R_SCI_MSK 0x12 /* WO */ #define R_SCI 0x12 /* RO */ #define R_IRQ_CTRL 0x13 /* WO */ #define R_PCM_MD0 0x14 /* WO */ #define R_CONF_OFLOW 0x14 /* RO */ #define R_PCM_MD1 0x15 /* WO */ #define R_PCM_MD2 0x15 /* WO */ #define R_SH0H 0x15 /* WO */ #define R_SH1H 0x15 /* WO */ #define R_SH0L 0x15 /* WO */ #define R_SH1L 0x15 /* WO */ #define R_SL_SEL0 0x15 /* WO */ #define R_SL_SEL1 0x15 /* WO */ #define R_SL_SEL2 0x15 /* WO */ #define R_SL_SEL3 0x15 /* WO */ #define R_SL_SEL4 0x15 /* WO */ #define R_SL_SEL5 0x15 /* WO */ #define R_SL_SEL6 0x15 /* WO */ #define R_SL_SEL7 0x15 /* WO */ #define R_RAM_USE 0x15 /* RO */ #define R_ST_SEL 0x16 /* WO */ #define R_CHIP_ID 0x16 /* RO */ #define R_ST_SYNC 0x17 /* WO */ #define R_BERT_STA 0x17 /* RO */ #define R_CONF_EN 0x18 /* WO */ #define R_F0_CNTL 0x18 /* RO */ #define R_F0_CNTH 0x19 /* RO */ #define R_TI_WD 0x1a /* WO */ #define R_BERT_ECL 0x1a /* RO */ #define R_BERT_WD_MD 0x1b /* WO */ #define R_BERT_ECH 0x1b /* RO */ #define R_DTMF 0x1c /* WO */ #define R_STATUS 0x1c /* RO */ #define R_DTMF_N 0x1d /* WO */ #define R_CHIP_RV 0x1f /* RO */ #define A_ST_WR_STA 0x30 /* WO */ #define A_ST_RD_STA 0x30 /* RO */ #define A_ST_CTRL0 0x31 /* WO */ #define A_ST_CTRL1 0x32 /* WO */ #define A_ST_CTRL2 0x33 /* WO */ #define A_ST_SQ_WR 0x34 /* WO */ #define A_ST_SQ_RD 0x34 /* RO */ #define A_ST_CLK_DLY 0x37 /* WO */ #define R_PWM0 0x38 /* WO */ #define R_PWM1 0x39 /* WO */ #define A_ST_B1_TX 0x3c /* WO */ #define A_ST_B1_RX 0x3c /* RO */ #define A_ST_B2_TX 0x3d /* WO */ #define A_ST_B2_RX 0x3d /* RO */ #define A_ST_D_TX 0x3e /* WO */ #define A_ST_D_RX 0x3e /* RO */ #define A_ST_E_RX 0x3f /* RO */ #define R_GPIO_OUT0 0x40 /* WO */ #define R_GPIO_IN0 0x40 /* RO */ #define R_GPIO_OUT1 0x41 /* WO */ #define R_GPIO_IN1 0x41 /* RO */ #define R_GPIO_EN0 0x42 /* WO */ #define R_GPIO_EN1 0x43 /* WO */ #define R_GPIO_SEL 0x44 /* WO */ #define R_GPI_IN0 0x44 /* RO */ #define R_GPI_IN1 0x45 /* RO */ #define R_PWM_MD 0x46 /* WO */ #define R_GPI_IN2 0x46 /* RO */ #define R_GPI_IN3 0x47 /* RO */ #define A_FIFO_DATA2 0x80 /* RW */ #define A_FIFO_DATA0 0x80 /* RW */ #define A_FIFO_DATA1 0x80 /* RW */ #define A_FIFO_DATA2_NOINC 0x84 /* WO */ #define A_FIFO_DATA0_NOINC 0x84 /* WO */ #define A_FIFO_DATA1_NOINC 0x84 /* WO */ #define R_INT_DATA 0x88 /* RO */ #define R_RAM_DATA 0xc0 /* RW */ #define R_IRQ_FIFO_BL0 0xc8 /* RO */ #define R_IRQ_FIFO_BL1 0xc9 /* RO */ #define R_IRQ_FIFO_BL2 0xca /* RO */ #define R_IRQ_FIFO_BL3 0xcb /* RO */ #define R_IRQ_FIFO_BL4 0xcc /* RO */ #define R_IRQ_FIFO_BL5 0xcd /* RO */ #define R_IRQ_FIFO_BL6 0xce /* RO */ #define R_IRQ_FIFO_BL7 0xcf /* RO */ #define A_SL_CFG 0xd0 /* WO */ #define A_CONF 0xd1 /* WO */ #define A_CH_MSK 0xf4 /* WO */ #define A_CON_HDLC 0xfa /* WO */ #define A_SUBCH_CFG 0xfb /* WO */ #define A_CHANNEL 0xfc /* WO */ #define A_FIFO_SEQ 0xfd /* WO */ #define A_IRQ_MSK 0xff /* WO */ /* R_CIRM bits */ #define V_SRES (1 << 3) /* soft reset (group 0) */ #define V_HFC_RES (1 << 4) /* HFC reset (group 1) */ #define V_PCM_RES (1 << 5) /* PCM reset (group 2) */ #define V_ST_RES (1 << 6) /* S/T reset (group 3) */ #define V_RLD_EPR (1 << 7) /* EEPROM reload */ #define HFC_FULL_RESET (V_SRES | V_HFC_RES | V_PCM_RES | V_ST_RES | V_RLD_EPR) /* A_IRQ_MSK bits */ #define V_IRQ (1 << 0) /* FIFO interrupt enable */ #define V_BERT_EN (1 << 1) /* enable BERT */ #define V_MIX_IRQ (1 << 2) /* mixed interrupt enable (frame + transparent mode) */ /* R_STATUS bits */ #define V_BUSY (1 << 0) /* 1=HFC busy, limited register access */ #define V_PROC (1 << 1) /* 1=HFC in processing phase */ #define V_LOST_STA (1 << 3) /* 1=frames have been lost */ #define V_SYNC_IN (1 << 4) /* level on SYNC_I pin */ #define V_EXT_IRQSTA (1 << 5) /* 1=external interrupt */ #define V_MISC_IRQSTA (1 << 6) /* 1=misc interrupt has occurred */ #define V_FR_IRQSTA (1 << 7) /* 1=fifo interrupt has occured */ #define HFC_INTS (V_EXT_IRQSTA | V_MISC_IRQSTA | V_FR_IRQSTA) /* R_SCI/R_SCI_MSK bits */ #define V_SCI_ST0 (1 << 0) /* state change for port 1 */ #define V_SCI_ST1 (1 << 1) /* state change for port 2 */ #define V_SCI_ST2 (1 << 2) /* state change for port 3 */ #define V_SCI_ST3 (1 << 3) /* state change for port 4 */ /* R_IRQ_FIFO_BLx bits */ #define V_IRQ_FIFOx_TX (1 << 0) /* FIFO TX interrupt occurred */ #define V_IRQ_FIFOx_RX (1 << 1) /* FIFO RX interrupt occurred */ #define IRQ_FIFOx_TXRX (V_IRQ_FIFOx_TX | V_IRQ_FIFOx_RX) /* R_IRQ_MISC / R_IRQMSK_MISC bits */ #define V_TI_IRQ (1 << 1) /* timer elapsed */ #define V_IRQ_PROC (1 << 2) /* processing/non-processing transition */ #define V_DTMF_IRQ (1 << 3) /* DTMF detection completed */ #define V_EXT_IRQ (1 << 5) /* external interrupt occured */ /* R_IRQ_CTRL bits */ #define V_FIFO_IRQ (1 << 0) /* enable any unmasked FIFO IRQs */ #define V_GLOB_IRQ_EN (1 << 3) /* enable any unmasked IRQs */ #define V_IRQ_POL (1 << 4) /* 1=IRQ active high */ /* R_BERT_WD_MD bits */ #define V_BERT_ERR (1 << 3) /* 1=generate an error bit in BERT stream */ #define V_AUTO_WD_RES (1 << 5) /* 1=automatically kick the watchdog */ #define V_WD_RES (1 << 7) /* 1=kick the watchdog (bit auto clears) */ /* R_TI_WS bits */ #define V_EV_TS_SHIFT (0) #define V_EV_TS_MASK (0x0f) #define V_WD_TS_SHIFT (4) #define V_WD_TS_MASK (0xf0) /* R_BRG_PCM_CFG bits */ #define V_PCM_CLK (1 << 5) /* 1=PCM clk = OSC, 0 = PCM clk is 2x OSC */ /* R_PCM_MD0 bits */ #define V_PCM_MD (1 << 0) /* 1=PCM master */ #define V_C4_POL (1 << 1) /* 1=F0IO sampled on rising edge of C4IO */ #define V_F0_NEG (1 << 2) /* 1=negative polarity of F0IO */ #define V_F0_LEN (1 << 3) /* 1=F0IO active for 2 C4IO clocks */ #define V_PCM_IDX_SEL0 (0x0 << 4) /* reg15 = R_SL_SEL0 */ #define V_PCM_IDX_SEL1 (0x1 << 4) /* reg15 = R_SL_SEL1 */ #define V_PCM_IDX_SEL2 (0x2 << 4) /* reg15 = R_SL_SEL2 */ #define V_PCM_IDX_SEL3 (0x3 << 4) /* reg15 = R_SL_SEL3 */ #define V_PCM_IDX_SEL4 (0x4 << 4) /* reg15 = R_SL_SEL4 */ #define V_PCM_IDX_SEL5 (0x5 << 4) /* reg15 = R_SL_SEL5 */ #define V_PCM_IDX_SEL6 (0x6 << 4) /* reg15 = R_SL_SEL6 */ #define V_PCM_IDX_SEL7 (0x7 << 4) /* reg15 = R_SL_SEL7 */ #define V_PCM_IDX_MD1 (0x9 << 4) /* reg15 = R_PCM_MD1 */ #define V_PCM_IDX_MD2 (0xa << 4) /* reg15 = R_PCM_MD2 */ #define V_PCM_IDX_SH0L (0xc << 4) /* reg15 = R_SH0L */ #define V_PCM_IDX_SH0H (0xd << 4) /* reg15 = R_SH0H */ #define V_PCM_IDX_SH1L (0xe << 4) /* reg15 = R_SH1L */ #define V_PCM_IDX_SH1H (0xf << 4) /* reg15 = R_SH1H */ #define V_PCM_IDX_MASK (0xf0) /* R_PCM_MD1 bits */ #define V_CODEC_MD (1 << 0) /* no damn idea */ #define V_PLL_ADJ_00 (0x0 << 2) /* adj 4 times by 0.5 system clk cycles */ #define V_PLL_ADJ_01 (0x1 << 2) /* adj 3 times by 0.5 system clk cycles */ #define V_PLL_ADJ_10 (0x2 << 2) /* adj 2 times by 0.5 system clk cycles */ #define V_PLL_ADJ_11 (0x3 << 2) /* adj 1 time by 0.5 system clk cycles */ #define V_PCM_DR_2048 (0x0 << 4) /* 2.048Mbps, 32 timeslots */ #define V_PCM_DR_4096 (0x1 << 4) /* 4.096Mbps, 64 timeslots */ #define V_PCM_DR_8192 (0x2 << 4) /* 8.192Mbps, 128 timeslots */ #define V_PCM_LOOP (1 << 6) /* 1=internal loopback */ #define V_PLL_ADJ_MASK (0x3 << 2) #define V_PCM_DR_MASK (0x3 << 4) /* A_SL_CFG bits */ #define V_CH_SDIR (1 << 0) /* 1=HFC channel receives data from PCM TS */ #define V_ROUT_TX_DIS (0x0 << 6) /* disabled, output disabled */ #define V_ROUT_TX_LOOP (0x1 << 6) /* internally looped, output disabled */ #define V_ROUT_TX_STIO1 (0x2 << 6) /* output data to STIO1 */ #define V_ROUT_TX_STIO2 (0x3 << 6) /* output data to STIO2 */ #define V_ROUT_RX_DIS (0x0 << 6) /* disabled, input data ignored */ #define V_ROUT_RX_LOOP (0x1 << 6) /* internally looped, input data ignored */ #define V_ROUT_RX_STIO2 (0x2 << 6) /* channel data comes from STIO1 */ #define V_ROUT_RX_STIO1 (0x3 << 6) /* channel data comes from STIO2 */ #define V_CH_SNUM_SHIFT (1) #define V_CH_SNUM_MASK (31 << 1) /* A_CON_HDLC bits */ #define V_IFF (1 << 0) /* Inter-Frame Fill: 0=0x7e, 1=0xff */ #define V_HDLC_TRP (1 << 1) /* 0=HDLC mode, 1=transparent */ #define V_TRP_IRQ_0 (0x0 << 2) /* FIFO enabled, no interrupt */ #define V_TRP_IRQ_64 (0x1 << 2) /* FIFO enabled, int @ 64 bytes */ #define V_TRP_IRQ_128 (0x2 << 2) /* FIFO enabled, int @ 128 bytes */ #define V_TRP_IRQ_256 (0x3 << 2) /* FIFO enabled, int @ 256 bytes */ #define V_TRP_IRQ_512 (0x4 << 2) /* FIFO enabled, int @ 512 bytes */ #define V_TRP_IRQ_1024 (0x5 << 2) /* FIFO enabled, int @ 1024 bytes */ #define V_TRP_IRQ_2048 (0x6 << 2) /* FIFO enabled, int @ 2048 bytes */ #define V_TRP_IRQ_4096 (0x7 << 2) /* FIFO enabled, int @ 4096 bytes */ #define V_TRP_IRQ (0x1 << 2) /* FIFO enabled, interrupt at end of frame (HDLC mode) */ #define V_DATA_FLOW_000 (0x0 << 5) /* see A_CON_HDLC reg description in datasheet */ #define V_DATA_FLOW_001 (0x1 << 5) /* see A_CON_HDLC reg description in datasheet */ #define V_DATA_FLOW_010 (0x2 << 5) /* see A_CON_HDLC reg description in datasheet */ #define V_DATA_FLOW_011 (0x3 << 5) /* see A_CON_HDLC reg description in datasheet */ #define V_DATA_FLOW_100 (0x4 << 5) /* see A_CON_HDLC reg description in datasheet */ #define V_DATA_FLOW_101 (0x5 << 5) /* see A_CON_HDLC reg description in datasheet */ #define V_DATA_FLOW_110 (0x6 << 5) /* see A_CON_HDLC reg description in datasheet */ #define V_DATA_FLOW_111 (0x7 << 5) /* see A_CON_HDLC reg description in datasheet */ /* R_FIFO bits */ #define V_FIFO_DIR (1 << 0) /* 1=RX FIFO data */ #define V_REV (1 << 7) /* 1=MSB first */ #define V_FIFO_NUM_SHIFT (1) #define V_FIFO_NUM_MASK (0x3e) /* A_CHANNEL bits */ #define V_CH_FDIR (1 << 0) /* 1=HFC chan for RX data */ #define V_CH_FNUM_SHIFT (1) #define V_CH_FNUM_MASK (0x3e) /* R_SLOT bits */ #define V_SL_DIR (1 << 0) /* 1=timeslot will RX PCM data from bus */ #define V_SL_NUM_SHIFT (1) #define V_SL_NUM_MASK (0xfe) /* A_INC_RES_FIFO bits */ #define V_INC_F (1 << 0) /* 1=increment FIFO F-counter (bit auto-clears) */ #define V_RES_FIFO (1 << 1) /* 1=reset FIFO (bit auto-clears) */ #define V_RES_LOST (1 << 2) /* 1=reset LOST error (bit auto-clears) */ /* R_FIFO_MD bits */ #define V_FIFO_MD_00 (0x0 << 0) #define V_FIFO_MD_01 (0x1 << 0) #define V_FIFO_MD_10 (0x2 << 0) #define V_FIFO_MD_11 (0x3 << 0) #define V_DF_MD_SM (0x0 << 2) /* simple data flow mode */ #define V_DF_MD_CSM (0x1 << 2) /* channel select mode */ #define V_DF_MD_FSM (0x3 << 2) /* FIFO sequence mode */ #define V_FIFO_SZ_00 (0x0 << 4) #define V_FIFO_SZ_01 (0x1 << 4) #define V_FIFO_SZ_10 (0x2 << 4) #define V_FIFO_SZ_11 (0x3 << 4) /* A_SUBCH_CFG bits */ #define V_BIT_CNT_8BIT (0) /* process 8 bits */ #define V_BIT_CNT_1BIT (1) /* process 1 bit */ #define V_BIT_CNT_2BIT (2) /* process 2 bits */ #define V_BIT_CNT_3BIT (3) /* process 3 bits */ #define V_BIT_CNT_4BIT (4) /* process 4 bits */ #define V_BIT_CNT_5BIT (5) /* process 5 bits */ #define V_BIT_CNT_6BIT (6) /* process 6 bits */ #define V_BIT_CNT_7BIT (7) /* process 7 bits */ #define V_LOOP_FIFO (1 << 6) /* loop FIFO data */ #define V_INV_DATA (1 << 7) /* invert FIFO data */ #define V_START_BIT_SHIFT (3) #define V_START_BIT_MASK (0x38) /* R_ST_SYNC bits */ #define V_MAN_SYNC (1 << 3) /* 1=manual sync mode */ #define V_SYNC_SEL_MASK (0x03) /* A_ST_WR_STA bits */ #define V_ST_SET_STA_MASK (0x0f) #define V_ST_LD_STA (1 << 4) /* 1=force ST_SET_STA mode, must be manually cleared 6us later */ #define V_ST_ACT_NOP (0x0 << 5) /* NOP */ #define V_ST_ACT_DEACTIVATE (0x2 << 5) /* start deactivation. auto-clears */ #define V_ST_ACT_ACTIVATE (0x3 << 5) /* start activation. auto-clears. */ #define V_SET_G2_G3 (1 << 7) /* 1=auto G2->G3 in NT mode. auto-clears after transition. */ /* A_ST_RD_STA */ #define V_ST_STA_MASK (0x0f) #define V_FR_SYNC (1 << 4) /* 1=synchronized */ #define V_T2_EXP (1 << 5) /* 1=T2 expired (NT only) */ #define V_INFO0 (1 << 6) /* 1=INFO0 */ #define V_G2_G3 (1 << 7) /* 1=allows G2->G3 (NT only, auto-clears) */ /* A_ST_CLK_DLY bits */ #define V_ST_SMPL_SHIFT (4) /* A_ST_CTRL0 bits */ #define V_B1_EN (1 << 0) /* 1=B1-channel transmit */ #define V_B2_EN (1 << 1) /* 1=B2-channel transmit */ #define V_ST_MD (1 << 2) /* 0=TE, 1=NT */ #define V_D_PRIO (1 << 3) /* D-Chan priority 0=high, 1=low */ #define V_SQ_EN (1 << 4) /* S/Q bits transmit (1=enabled) */ #define V_96KHZ (1 << 5) /* 1=transmit test signal */ #define V_TX_LI (1 << 6) /* 0=capacitive line mode, 1=non-capacitive */ #define V_ST_STOP (1 << 7) /* 1=power down */ /* A_ST_CTRL1 bits */ #define V_G2_G3_EN (1 << 0) /* 1=G2->G3 allowed without V_SET_G2_G3 */ #define V_D_HI (1 << 2) /* 1=D-chan reset */ #define V_E_IGNO (1 << 3) /* TE:1=ignore Echan, NT:should always be 1. */ #define V_E_LO (1 << 4) /* NT only: 1=force Echan low */ #define V_B12_SWAP (1 << 7) /* 1=swap B1/B2 */ /* A_ST_CTRL2 bits */ #define V_B1_RX_EN (1 << 0) /* 1=enable B1 RX */ #define V_B2_RX_EN (1 << 1) /* 1=enable B2 RX */ #define V_ST_TRI (1 << 6) /* 1=tristate S/T output buffer */ #define NUM_REGS 0xff #define NUM_PCI 12 /* From this point down, things only the kernel needs to know about */ #ifdef __KERNEL__ #define HFC_T1 0 #define HFC_T2 1 #define HFC_T3 2 #define WCB4XXP_MAGIC 0xb410c0de #define MAX_SPANS_PER_CARD 4 #define WCB4XXP_CHANNELS_PER_SPAN 3 /* 2 B-channels and 1 D-Channel for each BRI span */ #define WCB4XXP_HDLC_BUF_LEN 32 /* arbitrary, just the max # of byts we will send to DAHDI per call */ struct b4xxp_span { struct b4xxp *parent; int port; /* which S/T port this span belongs to */ unsigned char writechunk[WCB4XXP_CHANNELS_PER_SPAN * DAHDI_CHUNKSIZE]; unsigned char readchunk[WCB4XXP_CHANNELS_PER_SPAN * DAHDI_CHUNKSIZE]; int sync; /* sync priority */ int syncpos; /* sync priority */ int oldstate; /* old state machine state */ int newalarm; /* alarm to send to zaptel once alarm timer expires */ unsigned long alarmtimer; int te_mode; /* 1=TE, 0=NT */ unsigned long hfc_timers[WCB4XXP_CHANNELS_PER_SPAN]; /* T1, T2, T3 */ int hfc_timer_on[WCB4XXP_CHANNELS_PER_SPAN]; /* 1=timer active */ int fifos[WCB4XXP_CHANNELS_PER_SPAN]; /* B1, B2, D <--> host fifo numbers */ /* HDLC controller fields */ struct dahdi_chan *sigchan; /* pointer to the signalling channel for this span */ int sigactive; /* nonzero means we're in the middle of sending an HDLC frame */ atomic_t hdlc_pending; /* hdlc_hard_xmit() increments, hdlc_tx_frame() decrements */ int frames_out; int frames_in; struct dahdi_span span; /* zaptel span info for this span */ struct dahdi_chan *chans[WCB4XXP_CHANNELS_PER_SPAN]; /* Individual channels */ struct dahdi_echocan_state ec[WCB4XXP_CHANNELS_PER_SPAN]; /* echocan state for each channel */ struct dahdi_chan _chans[WCB4XXP_CHANNELS_PER_SPAN]; /* Backing memory */ }; /* This structure exists one per card */ struct b4xxp { unsigned magic; /* magic value to make sure we're looking at our struct */ char *variety; int chiprev; /* revision of HFC-4S */ struct pci_dev *pdev; /* Pointer to PCI device */ struct device *dev; /* kernel dev struct (from pdev->dev) */ void __iomem *addr; /* I/O address (memory mapped) */ void __iomem *ioaddr; /* I/O address (index based) */ int irq; /* IRQ used by device */ spinlock_t reglock; /* lock for all register accesses */ spinlock_t seqlock; /* lock for "sequence" accesses that must be ordered */ spinlock_t fifolock; /* lock for all FIFO accesses (reglock must be available) */ volatile unsigned long ticks; unsigned long fifo_en_rxint; /* each bit is the RX int enable for that FIFO */ unsigned long fifo_en_txint; /* each bit is the TX int enable for that FIFO */ unsigned char fifo_irqstatus[8]; /* top-half ORs in new interrupts, bottom-half ANDs them out */ unsigned char misc_irqstatus; /* same for this */ unsigned char st_irqstatus; /* same for this too */ unsigned int numspans; int blinktimer; /* for the fancy LED alarms */ int alarmpos; /* ditto */ int cardno; /* Which card we are */ int globalconfig; /* Whether global setup has been done */ int syncspan; /* span that HFC uses for sync on this card */ int running; /* interrupts are enabled */ struct b4xxp_span spans[MAX_SPANS_PER_CARD]; /* Individual spans */ int order; /* Order */ int flags; /* Device flags */ int master; /* Are we master */ int ledreg; /* copy of the LED Register */ unsigned int gpio; unsigned int gpioctl; int spansstarted; /* number of spans started */ /* Flags for our bottom half */ unsigned int shutdown; /* 1=bottom half doesn't process anything, just returns */ struct tasklet_struct b4xxp_tlet; }; /* CPLD access bits */ #define B4_RDADDR 0 #define B4_WRADDR 1 #define B4_COUNT 2 #define B4_DMACTRL 3 #define B4_INTR 4 #define B4_VERSION 6 #define B4_LEDS 7 #define B4_GPIOCTL 8 #define B4_GPIO 9 #define B4_LADDR 10 #define B4_LDATA 11 #define B4_LCS (1 << 11) #define B4_LCS2 (1 << 12) #define B4_LALE (1 << 13) #define B4_LFRMR_CS (1 << 10) /* Framer's ChipSelect signal */ #define B4_ACTIVATE (1 << 12) #define B4_LREAD (1 << 15) #define B4_LWRITE (1 << 16) #define LED_OFF (0) #define LED_RED (1) #define LED_GREEN (2) #define get_F(f1, f2, flen) { \ f1 = hfc_readcounter8(b4, A_F1); \ f2 = hfc_readcounter8(b4, A_F2); \ flen = f1 - f2; \ \ if(flen < 0) \ flen += (HFC_FMAX - HFC_FMIN) + 1; \ } #define get_Z(z1, z2, zlen) { \ z1 = hfc_readcounter16(b4, A_Z1); \ z2 = hfc_readcounter16(b4, A_Z2); \ zlen = z1 - z2; \ \ if(zlen < 0) \ zlen += (HFC_ZMAX - HFC_ZMIN) + 1; \ } #define flush_pci() (void)ioread8(b4->addr + R_STATUS) #endif /* __KERNEL__ */ #endif /* _B4XX_H_ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/wcb4xxp/Kbuild0000644000175000017500000000016411137730310021131 0ustar maniacmaniacobj-m += wcb4xxp.o EXTRA_CFLAGS += -I$(src)/.. -Wno-undef wcb4xxp-objs := base.o $(obj)/base.o: $(src)/wcb4xxp.h dahdi-linux-2.2.0-rc4/drivers/dahdi/firmware/0000755000175000017500000000000011202066031020203 5ustar maniacmaniacdahdi-linux-2.2.0-rc4/drivers/dahdi/firmware/Makefile0000644000175000017500000001644511176111367021672 0ustar maniacmaniac# # DAHDI # # Makefile for firmware downloading/installation # # Copyright (C) 2007-2009, Digium, Inc. # # Joshua Colp # # This program is free software, distributed under the terms of # the GNU General Public License # .PHONY: dist-clean clean all uninstall have_download install object-build hotplug-install hotplug-dirs hotplug-uninstall make_firmware_object firmware-loaders OCT6114_064_VERSION:=1.05.01 OCT6114_128_VERSION:=1.05.01 TC400M_VERSION:=MR6.12 VPMADT032_VERSION:=1.17.0 FIRMWARE_URL:=http://downloads.digium.com/pub/telephony/firmware/releases ALL_FIRMWARE=FIRMWARE-OCT6114-064 FIRMWARE-OCT6114-128 FIRMWARE-TC400M # Firmware files should use the naming convention: dahdi-fw--- or dahdi-fw-- # First example: dahdi-fw-oct6114-064-1.05.01 # This means this is version 1.05.01 of the oct6114-064 firmware # Second example: dahdi-fw-tc400m-MR5.6 # This means this is version MR5.6 of the tc400m firmware # Build a list of firmware package filenames we need FIRMWARE:=$(ALL_FIRMWARE:FIRMWARE-OCT6114-064=dahdi-fw-oct6114-064-$(OCT6114_064_VERSION).tar.gz) FIRMWARE:=$(FIRMWARE:FIRMWARE-OCT6114-128=dahdi-fw-oct6114-128-$(OCT6114_128_VERSION).tar.gz) FIRMWARE:=$(FIRMWARE:FIRMWARE-TC400M=dahdi-fw-tc400m-$(TC400M_VERSION).tar.gz) FWLOADERS:=dahdi-fwload-vpmadt032-$(VPMADT032_VERSION).tar.gz # Build a list of object files if hotplug will not be used OBJECT_FILES:=$(ALL_FIRMWARE:FIRMWARE-OCT6114-064=dahdi-fw-oct6114-064.o) OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-OCT6114-128=dahdi-fw-oct6114-128.o) OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-TC400M=dahdi-fw-tc400m.o) # Force usage of wget, for now DOWNLOAD=wget WGET=wget # If "fetch" is used, --continue is not a valid option. ifeq ($(WGET),wget) WGET_ARGS:=--continue endif all: $(FIRMWARE) # Clean up any downloaded/extracted firmware packages dist-clean: clean rm -f dahdi-fw-*.bin rm -f dahdi-fw-*.tar.gz rm -f dahdi-fwload-*.tar.gz rm -f make_firmware_object # Clean up anything we built clean: rm -f dahdi-fw-*.o # Download and extract firmware tarballs dahdi-fw-%.tar.gz: @if ( [ "$(HOTPLUG_FIRMWARE)" = "no" ] ) || ( [ -d $(DESTDIR)/usr/lib/hotplug/firmware ] && ! [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.$(subst .tar.gz,,$*) ] ) || ( [ -d $(DESTDIR)/lib/firmware ] && ! [ -f $(DESTDIR)/lib/firmware/.$(subst .tar.gz,,$*) ] ); then \ echo "Attempting to download $@"; \ if test ! -f $@; then $(DOWNLOAD) $(WGET_ARGS) $(FIRMWARE_URL)/$@; fi; \ if test ! -f $@; then exit 1; fi; \ (cat $@ | gzip -d | tar -xof -) \ fi firmware-loaders: $(FWLOADERS) .PHONY: dahdi-fwload-vpmadt032-$(VPMADT032_VERSION).tar.gz dahdi-fwload-vpmadt032-$(VPMADT032_VERSION).tar.gz: @if test ! -f $@; then echo "Attempting to download $@"; $(DOWNLOAD) $(WGET_ARGS) $(FIRMWARE_URL)/$@; fi; \ if test ! -f $@; then exit 1; fi; \ (cd ../../..; cat drivers/dahdi/firmware/$@ | gzip -d | tar -xof -) # Create object files suitable for linking against object-build: $(FIRMWARE) $(OBJECT_FILES) $(DESTDIR)/usr/lib/hotplug/firmware $(DESTDIR)/lib/firmware: mkdir -p $@ # Install all downloaded firmware images for hotplug usage hotplug-install: $(DESTDIR)/usr/lib/hotplug/firmware $(DESTDIR)/lib/firmware $(FIRMWARE) ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-064-$(OCT6114_064_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-064-$(OCT6114_064_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes) @echo "Installing dahdi-fw-oct6114-064.bin to hotplug firmware directories" @install -m 644 dahdi-fw-oct6114-064.bin $(DESTDIR)/usr/lib/hotplug/firmware @rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-064-* @touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-064-$(OCT6114_064_VERSION) @install -m 644 dahdi-fw-oct6114-064.bin $(DESTDIR)/lib/firmware @rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-064-* @touch $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-064-$(OCT6114_064_VERSION) else @echo "Firmware dahdi-fw-oct6114-064.bin is already installed with required version $(OCT6114_064_VERSION)" endif ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-128-$(OCT6114_128_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-128-$(OCT6114_128_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes) @echo "Installing dahdi-fw-oct6114-128.bin to hotplug firmware directories" @install -m 644 dahdi-fw-oct6114-128.bin $(DESTDIR)/usr/lib/hotplug/firmware @rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-128-* @touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-128-$(OCT6114_128_VERSION) @install -m 644 dahdi-fw-oct6114-128.bin $(DESTDIR)/lib/firmware @rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-128-* @touch $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-128-$(OCT6114_128_VERSION) else @echo "Firmware dahdi-fw-oct6114-128.bin is already installed with required version $(OCT6114_128_VERSION)" endif ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-tc400m-$(TC400M_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-tc400m-$(TC400M_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes) @echo "Installing dahdi-fw-tc400m.bin to hotplug firmware directories" @install -m 644 dahdi-fw-tc400m.bin $(DESTDIR)/usr/lib/hotplug/firmware @rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-tc400m-* @touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-tc400m-$(TC400M_VERSION) @install -m 644 dahdi-fw-tc400m.bin $(DESTDIR)/lib/firmware @rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-tc400m-* @touch $(DESTDIR)/lib/firmware/.dahdi-fw-tc400m-$(TC400M_VERSION) else @echo "Firmware dahdi-fw-tc400m.bin is already installed with required version $(TC400M_VERSION)" endif # Uninstall any installed dahdi firmware images from hotplug firmware directories hotplug-uninstall: if [ -d $(DESTDIR)/usr/lib/hotplug/firmware ]; then \ rm -f $(DESTDIR)/usr/lib/hotplug/firmware/dahdi-fw-*.bin; \ rm -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw*; \ fi if [ -d $(DESTDIR)/lib/firmware ]; then \ rm -f $(DESTDIR)/lib/firmware/dahdi-fw-*.bin; \ rm -f $(DESTDIR)/lib/firmware/.dahdi-fw*; \ fi make_firmware_object: make_firmware_object.in ../dahdi-base.o @export BFDNAME=`LANG=C objdump -f ../dahdi-base.o | grep -e "dahdi-base.o:" | sed "s/.*file format \(.*\)/\1/"`; \ export BFDARCH=`LANG=C objdump -f ../dahdi-base.o | grep -e "architecture:" | sed "s/.*ture: \(.*\),.*/\1/"`; \ sed -e s/BFDNAME/$${BFDNAME}/ -e s/BFDARCH/$${BFDARCH}/ $< > $@ @chmod +x $@ # Build object file of an oct6114 064 firmware image for linking dahdi-fw-oct6114-064.o: dahdi-fw-oct6114-064-$(OCT6114_064_VERSION).tar.gz dahdi-fw-oct6114-064.bin make_firmware_object @echo Making firmware object file for dahdi-fw-oct6114-064.bin ./make_firmware_object dahdi-fw-oct6114-064.bin $@ # Build object file of an oct6114 128 firmware image for linking dahdi-fw-oct6114-128.o: dahdi-fw-oct6114-128-$(OCT6114_128_VERSION).tar.gz dahdi-fw-oct6114-128.bin make_firmware_object @echo Making firmware object file for dahdi-fw-oct6114-128.bin ./make_firmware_object dahdi-fw-oct6114-128.bin $@ # Build object file of a TC400M firmware image for linking dahdi-fw-tc400m.o: dahdi-fw-tc400m-$(TC400M_VERSION).tar.gz dahdi-fw-tc400m.bin make_firmware_object @echo Making firmware object file for dahdi-fw-tc400m.bin ./make_firmware_object dahdi-fw-tc400m.bin $@ dahdi-linux-2.2.0-rc4/drivers/dahdi/firmware/make_firmware_object.in0000644000175000017500000000035711026033022024675 0ustar maniacmaniac#!/bin/sh -e # make an object file from a raw binary firmware file # arguments: # 1 - firmware file # 2 - output file objcopy -I binary ${1} -B BFDARCH -O BFDNAME ${2} --rename-section .data=.rodata,alloc,load,data,contents,readonly dahdi-linux-2.2.0-rc4/drivers/dahdi/voicebus/0000755000175000017500000000000011202066027020213 5ustar maniacmaniacdahdi-linux-2.2.0-rc4/drivers/dahdi/voicebus/Makefile0000644000175000017500000000026011176623226021663 0ustar maniacmaniacifdef 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 dahdi-linux-2.2.0-rc4/drivers/dahdi/voicebus/voicebus.c0000644000175000017500000012232511176111367022213 0ustar maniacmaniac/* * VoiceBus(tm) Interface Library. * * Written by Shaun Ruffell * and based on previous work by Mark Spencer , * Matthew Fredrickson , and * Michael Spiceland * * Copyright (C) 2007-2009 Digium, Inc. * * All rights reserved. * VoiceBus is a registered trademark of Digium. * */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ #include #include #include #include #include #include #include #include #include #include "voicebus.h" #include "vpmadtreg.h" #include "GpakCust.h" #define assert(__x__) BUG_ON(!(__x__)) #define INTERRUPT 0 /* Run the deferred processing in the ISR. */ #define TASKLET 1 /* Run in a tasklet. */ #define TIMER 2 /* Run in a system timer. */ #define WORKQUEUE 3 /* Run in a workqueue. */ #ifndef VOICEBUS_DEFERRED #define VOICEBUS_DEFERRED INTERRUPT #endif #if VOICEBUS_DEFERRED == WORKQUEUE #define VOICEBUS_ALLOC_FLAGS GFP_KERNEL #else #define VOICEBUS_ALLOC_FLAGS GFP_ATOMIC #endif #if VOICEBUS_DEFERRED == TIMER #if HZ < 1000 /* \todo Put an error message here. */ #endif #endif /*! The number of descriptors in both the tx and rx descriptor ring. */ #define DRING_SIZE (1 << 5) /* Must be a power of 2 */ #define DRING_MASK (DRING_SIZE-1) /* Interrupt status' reported in SR_CSR5 */ #define TX_COMPLETE_INTERRUPT 0x00000001 #define TX_STOPPED_INTERRUPT 0x00000002 #define TX_UNAVAILABLE_INTERRUPT 0x00000004 #define TX_JABBER_TIMEOUT_INTERRUPT 0x00000008 #define TX_UNDERFLOW_INTERRUPT 0x00000020 #define RX_COMPLETE_INTERRUPT 0x00000040 #define RX_UNAVAILABLE_INTERRUPT 0x00000080 #define RX_STOPPED_INTERRUPT 0x00000100 #define RX_WATCHDOG_TIMEOUT_INTERRUPT 0x00000200 #define TIMER_INTERRUPT 0x00000800 #define FATAL_BUS_ERROR_INTERRUPT 0x00002000 #define ABNORMAL_INTERRUPT_SUMMARY 0x00008000 #define NORMAL_INTERRUPT_SUMMARY 0x00010000 #define SR_CSR5 0x0028 #define NAR_CSR6 0x0030 #define IER_CSR7 0x0038 #define CSR7_TCIE 0x00000001 /* tx complete */ #define CSR7_TPSIE 0x00000002 /* tx processor stopped */ #define CSR7_TDUIE 0x00000004 /* tx desc unavailable */ #define CSR7_TUIE 0x00000020 /* tx underflow */ #define CSR7_RCIE 0x00000040 /* rx complete */ #define CSR7_RUIE 0x00000080 /* rx desc unavailable */ #define CSR7_RSIE 0x00000100 /* rx processor stopped */ #define CSR7_FBEIE 0x00002000 /* fatal bus error */ #define CSR7_AIE 0x00008000 /* abnormal enable */ #define CSR7_NIE 0x00010000 /* normal enable */ #define DEFAULT_INTERRUPTS (CSR7_TCIE | CSR7_TPSIE | CSR7_TDUIE | \ CSR7_RUIE | CSR7_RSIE | CSR7_FBEIE | \ CSR7_AIE | CSR7_NIE) #define CSR9 0x0048 #define CSR9_MDC 0x00010000 #define CSR9_MDO 0x00020000 #define CSR9_MMC 0x00040000 #define CSR9_MDI 0x00080000 #define OWN_BIT (1 << 31) /* In memory structure shared by the host and the adapter. */ struct voicebus_descriptor { u32 des0; u32 des1; u32 buffer1; u32 container; /* Unused */ } __attribute__((packed)); struct voicebus_descriptor_list { /* Pointer to an array of descriptors to give to hardware. */ struct voicebus_descriptor *desc; /* Read completed buffers from the head. */ unsigned int head; /* Write ready buffers to the tail. */ unsigned int tail; /* Array to save the kernel virtual address of pending buffers. */ void *pending[DRING_SIZE]; /* PCI Bus address of the descriptor list. */ dma_addr_t desc_dma; /*! either DMA_FROM_DEVICE or DMA_TO_DEVICE */ unsigned int direction; /*! The number of buffers currently submitted to the hardware. */ atomic_t count; /*! The number of bytes to pad each descriptor for cache alignment. */ unsigned int padding; }; /*! * \brief Represents a VoiceBus interface on a Digium telephony card. */ struct voicebus { /*! Name of this card. */ const char *board_name; /*! The system pci device for this VoiceBus interface. */ struct pci_dev *pdev; /*! Protects access to card registers and this structure. You should * hold this lock before accessing most of the members of this data * structure or the card registers. */ spinlock_t lock; /*! The size of the transmit and receive buffers for this card. */ u32 framesize; /*! The number of u32s in the host system cache line. */ u8 cache_line_size; /*! Pool to allocate memory for the tx and rx descriptor rings. */ struct voicebus_descriptor_list rxd; struct voicebus_descriptor_list txd; /*! Level of debugging information. 0=None, 5=Insane. */ atomic_t debuglevel; /*! Cache of buffer objects. */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) kmem_cache_t *buffer_cache; #else struct kmem_cache *buffer_cache; #endif /*! Base address of the VoiceBus interface registers in I/O space. */ u32 iobase; /*! The IRQ line for this VoiceBus interface. */ unsigned int irq; #if VOICEBUS_DEFERRED == WORKQUEUE /*! Process buffers in the context of this workqueue. */ struct workqueue_struct *workqueue; /*! Work item to process tx / rx buffers. */ struct work_struct workitem; #elif VOICEBUS_DEFERRED == TASKLET /*! Process buffers in the context of a tasklet. */ struct tasklet_struct tasklet; #elif VOICEBUS_DEFERRED == TIMER /*! Process buffers in a timer without generating interrupts. */ struct timer_list timer; #endif /*! Callback function to board specific module to process frames. */ void (*handle_receive)(void *vbb, void *context); void (*handle_transmit)(void *vbb, void *context); /*! Data to pass to the receive and transmit callback. */ void *context; struct completion stopped_completion; /*! Flags */ unsigned long flags; /* \todo see about removing this... */ u32 sdi; /*! Number of tx buffers to queue up before enabling interrupts. */ unsigned int min_tx_buffer_count; }; /* * Use the following macros to lock the VoiceBus interface, and it won't * matter if the deferred processing is running inside the interrupt handler, * in a tasklet, or in a workqueue. */ #if VOICEBUS_DEFERRED == WORKQUEUE /* * When the deferred processing is running in a workqueue, voicebus will never * be locked from the context of the interrupt handler, and therefore we do * not need to lock interrupts. */ #define LOCKS_VOICEBUS #define LOCKS_FROM_DEFERRED #define VBLOCK(_vb_) spin_lock(&((_vb_)->lock)) #define VBUNLOCK(_vb_) spin_unlock(&((_vb_)->lock)) #define VBLOCK_FROM_DEFERRED(_vb_) spin_lock(&((_vb_)->lock)) #define VBUNLOCK_FROM_DEFERRED(_vb_) spin_lock(&((_vb_)->lock)) #else #define LOCKS_VOICEBUS unsigned long _irqflags #define LOCKS_FROM_DEFERRED #define VBLOCK(_vb_) spin_lock_irqsave(&((_vb_)->lock), _irqflags) #define VBUNLOCK(_vb_) spin_unlock_irqrestore(&((_vb_)->lock), _irqflags) #define VBLOCK_FROM_DEFERRED(_vb_) spin_lock(&((_vb_)->lock)) #define VBUNLOCK_FROM_DEFERRED(_vb_) spin_lock(&((_vb_)->lock)) #endif #define VB_PRINTK(_vb, _lvl, _fmt, _args...) \ printk(KERN_##_lvl "%s: " _fmt, (_vb)->board_name, ## _args) /* Bit definitions for struct voicebus.flags */ #define TX_UNDERRUN 1 #define RX_UNDERRUN 2 #define IN_DEFERRED_PROCESSING 3 #define STOP 4 #define STOPPED 5 #if VOICEBUS_DEFERRED == WORKQUEUE #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) /*! \brief Make the current task real-time. */ static void vb_setup_deferred(void *data) #else static void vb_setup_deferred(struct work_struct *work) #endif { struct sched_param param = { .sched_priority = 99 }; sched_setscheduler(current, SCHED_FIFO, ¶m); } /*! \brief Schedule a work item to make the voicebus workqueue real-time. */ static void vb_set_workqueue_priority(struct voicebus *vb) { #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) DECLARE_WORK(deferred_setup, vb_setup_deferred, NULL); #else DECLARE_WORK(deferred_setup, vb_setup_deferred); #endif queue_work(vb->workqueue, &deferred_setup); flush_workqueue(vb->workqueue); } #endif #endif #ifdef DBG static inline int assert_in_vb_deferred(struct voicebus *vb) { assert(test_bit(IN_DEFERRED_PROCESSING, &vb->flags)); } static inline void start_vb_deferred(struct voicebus *vb) { set_bit(IN_DEFERRED_PROCESSING, &vb->flags); } static inline void stop_vb_deferred(struct voicebus *vb) { clear_bit(IN_DEFERRED_PROCESSING, &vb->flags); } #else #define assert_in_vb_deferred(_x_) do {; } while (0) #define start_vb_deferred(_x_) do {; } while (0) #define stop_vb_deferred(_x_) do {; } while (0) #endif static inline struct voicebus_descriptor * vb_descriptor(struct voicebus_descriptor_list *dl, int index) { struct voicebus_descriptor *d; d = (struct voicebus_descriptor *)((u8*)dl->desc + ((sizeof(*d) + dl->padding) * index)); return d; } static int vb_initialize_descriptors(struct voicebus *vb, struct voicebus_descriptor_list *dl, u32 des1, unsigned int direction) { int i; struct voicebus_descriptor *d; const u32 END_OF_RING = 0x02000000; assert(dl); /* * Add some padding to each descriptor to ensure that they are * aligned on host system cache-line boundaries, but only for the * cache-line sizes that we support. * */ if ((0x08 == vb->cache_line_size) || (0x10 == vb->cache_line_size) || (0x20 == vb->cache_line_size)) { dl->padding = (vb->cache_line_size*sizeof(u32)) - sizeof(*d); } else { dl->padding = 0; } dl->desc = pci_alloc_consistent(vb->pdev, (sizeof(*d) + dl->padding) * DRING_SIZE, &dl->desc_dma); if (!dl->desc) return -ENOMEM; memset(dl->desc, 0, (sizeof(*d) + dl->padding) * DRING_SIZE); for (i = 0; i < DRING_SIZE; ++i) { d = vb_descriptor(dl, i); d->des1 = des1; } d->des1 |= cpu_to_le32(END_OF_RING); dl->direction = direction; atomic_set(&dl->count, 0); return 0; } static int vb_initialize_tx_descriptors(struct voicebus *vb) { return vb_initialize_descriptors( vb, &vb->txd, 0xe4800000 | vb->framesize, DMA_TO_DEVICE); } static int vb_initialize_rx_descriptors(struct voicebus *vb) { return vb_initialize_descriptors( vb, &vb->rxd, vb->framesize, DMA_FROM_DEVICE); } /*! \brief Use to set the minimum number of buffers queued to the hardware * before enabling interrupts. */ int voicebus_set_minlatency(struct voicebus *vb, unsigned int ms) { LOCKS_VOICEBUS; /* * One millisecond of latency means that we have 3 buffers pending, * since two are always going to be waiting in the TX fifo on the * interface chip. * */ #define MESSAGE "%d ms is an invalid value for minumum latency. Setting to %d ms.\n" if (DRING_SIZE < ms) { VB_PRINTK(vb, WARNING, MESSAGE, ms, DRING_SIZE); return -EINVAL; } else if (VOICEBUS_DEFAULT_LATENCY > ms) { VB_PRINTK(vb, WARNING, MESSAGE, ms, VOICEBUS_DEFAULT_LATENCY); return -EINVAL; } VBLOCK(vb); vb->min_tx_buffer_count = ms; VBUNLOCK(vb); return 0; } EXPORT_SYMBOL(voicebus_set_minlatency); void voicebus_get_handlers(struct voicebus *vb, void **handle_receive, void **handle_transmit, void **context) { LOCKS_VOICEBUS; BUG_ON(!handle_receive); BUG_ON(!handle_transmit); BUG_ON(!context); VBLOCK(vb); *handle_receive = vb->handle_receive; *handle_transmit = vb->handle_transmit; *context = vb->context; VBUNLOCK(vb); return; } EXPORT_SYMBOL(voicebus_get_handlers); void voicebus_set_handlers(struct voicebus *vb, void (*handle_receive)(void *buffer, void *context), void (*handle_transmit)(void *buffer, void *context), void *context) { LOCKS_VOICEBUS; BUG_ON(!handle_receive); BUG_ON(!handle_transmit); BUG_ON(!context); VBLOCK(vb); vb->handle_receive = handle_receive; vb->handle_transmit = handle_transmit; vb->context = context; VBUNLOCK(vb); } EXPORT_SYMBOL(voicebus_set_handlers); /*! \brief Returns the number of buffers currently on the transmit queue. */ int voicebus_current_latency(struct voicebus *vb) { LOCKS_VOICEBUS; int latency; VBLOCK(vb); latency = vb->min_tx_buffer_count; VBUNLOCK(vb); return latency; } EXPORT_SYMBOL(voicebus_current_latency); /*! * \brief Read one of the hardware control registers without acquiring locks. */ static inline u32 __vb_getctl(struct voicebus *vb, u32 addr) { return le32_to_cpu(inl(vb->iobase + addr)); } /*! * \brief Read one of the hardware control registers with locks held. */ static inline u32 vb_getctl(struct voicebus *vb, u32 addr) { LOCKS_VOICEBUS; u32 val; VBLOCK(vb); val = __vb_getctl(vb, addr); VBUNLOCK(vb); return val; } /*! * \brief Returns whether or not the interface is running. * * NOTE: Running in this case means whether or not the hardware reports the * transmit processor in any state but stopped. * * \return 1 of the process is stopped, 0 if running. */ static int vb_is_stopped(struct voicebus *vb) { u32 reg; reg = vb_getctl(vb, SR_CSR5); reg = (reg >> 17) & 0x38; return (0 == reg) ? 1 : 0; } static void vb_cleanup_descriptors(struct voicebus *vb, struct voicebus_descriptor_list *dl) { unsigned int i; struct voicebus_descriptor *d; assert(vb_is_stopped(vb)); for (i = 0; i < DRING_SIZE; ++i) { d = vb_descriptor(dl, i); if (d->buffer1) { d->buffer1 = 0; assert(dl->pending[i]); voicebus_free(vb, dl->pending[i]); dl->pending[i] = NULL; } d->des0 &= ~OWN_BIT; } dl->head = 0; dl->tail = 0; atomic_set(&dl->count, 0); } static void vb_free_descriptors(struct voicebus *vb, struct voicebus_descriptor_list *dl) { if (NULL == dl->desc) { WARN_ON(1); return; } vb_cleanup_descriptors(vb, dl); pci_free_consistent( vb->pdev, (sizeof(struct voicebus_descriptor)+dl->padding)*DRING_SIZE, dl->desc, dl->desc_dma); } /*! * \brief Write one of the hardware control registers without acquiring locks. */ static inline void __vb_setctl(struct voicebus *vb, u32 addr, u32 val) { wmb(); outl(cpu_to_le32(val), vb->iobase + addr); } /*! * \brief Write one of the hardware control registers with locks held. */ static inline void vb_setctl(struct voicebus *vb, u32 addr, u32 val) { LOCKS_VOICEBUS; VBLOCK(vb); __vb_setctl(vb, addr, val); VBUNLOCK(vb); } static int __vb_sdi_clk(struct voicebus *vb) { unsigned int ret; vb->sdi &= ~CSR9_MDC; __vb_setctl(vb, 0x0048, vb->sdi); ret = __vb_getctl(vb, 0x0048); vb->sdi |= CSR9_MDC; __vb_setctl(vb, 0x0048, vb->sdi); return (ret & CSR9_MDI) ? 1 : 0; } static void __vb_sdi_sendbits(struct voicebus *vb, u32 bits, int count) { vb->sdi &= ~CSR9_MMC; __vb_setctl(vb, 0x0048, vb->sdi); while (count--) { if (bits & (1 << count)) vb->sdi |= CSR9_MDO; else vb->sdi &= ~CSR9_MDO; __vb_sdi_clk(vb); } } static void vb_setsdi(struct voicebus *vb, int addr, u16 val) { LOCKS_VOICEBUS; u32 bits; /* Send preamble */ bits = 0xffffffff; VBLOCK(vb); __vb_sdi_sendbits(vb, bits, 32); bits = (0x5 << 12) | (1 << 7) | (addr << 2) | 0x2; __vb_sdi_sendbits(vb, bits, 16); __vb_sdi_sendbits(vb, val, 16); VBUNLOCK(vb); } static void vb_enable_io_access(struct voicebus *vb) { LOCKS_VOICEBUS; u32 reg; assert(vb->pdev); VBLOCK(vb); pci_read_config_dword(vb->pdev, 0x0004, ®); reg |= 0x00000007; pci_write_config_dword(vb->pdev, 0x0004, reg); VBUNLOCK(vb); } /*! \todo Insert comments... * context: !in_interrupt() */ void* voicebus_alloc(struct voicebus *vb) { void *vbb; vbb = kmem_cache_alloc(vb->buffer_cache, VOICEBUS_ALLOC_FLAGS); return vbb; } void voicebus_setdebuglevel(struct voicebus *vb, u32 level) { atomic_set(&vb->debuglevel, level); } EXPORT_SYMBOL(voicebus_setdebuglevel); int voicebus_getdebuglevel(struct voicebus *vb) { return atomic_read(&vb->debuglevel); } EXPORT_SYMBOL(voicebus_getdebuglevel); /*! \brief Resets the voicebus hardware interface. */ static int vb_reset_interface(struct voicebus *vb) { unsigned long timeout; u32 reg; u32 pci_access; const u32 DEFAULT_PCI_ACCESS = 0xfff80002; BUG_ON(in_interrupt()); switch (vb->cache_line_size) { case 0x08: pci_access = DEFAULT_PCI_ACCESS | (0x1 << 14); break; case 0x10: pci_access = DEFAULT_PCI_ACCESS | (0x2 << 14); break; case 0x20: pci_access = DEFAULT_PCI_ACCESS | (0x3 << 14); break; default: if (atomic_read(&vb->debuglevel)) VB_PRINTK(vb, WARNING, "Host system set a cache size "\ "of %d which is not supported. " \ "Disabling memory write line and memory read line.\n", vb->cache_line_size); pci_access = 0xfe584202; break; } /* The transmit and receive descriptors will have the same padding. */ pci_access |= ((vb->txd.padding / sizeof(u32)) << 2) & 0x7c; vb_setctl(vb, 0x0000, pci_access | 1); timeout = jiffies + HZ/10; /* 100ms interval */ do { reg = vb_getctl(vb, 0x0000); } while ((reg & 0x00000001) && time_before(jiffies, timeout)); if (reg & 0x00000001) { VB_PRINTK(vb, ERR, "Hardware did not come out of reset "\ "within 100ms!"); return -EIO; } vb_setctl(vb, 0x0000, pci_access); return 0; } static int vb_initialize_interface(struct voicebus *vb) { u32 reg; vb_cleanup_descriptors(vb, &vb->txd); vb_cleanup_descriptors(vb, &vb->rxd); /* Pass bad packets, runt packets, disable SQE function, * store-and-forward */ vb_setctl(vb, 0x0030, 0x00280048); /* ...disable jabber and the receive watchdog. */ vb_setctl(vb, 0x0078, 0x00000013); /* Tell the card where the descriptors are in host memory. */ vb_setctl(vb, 0x0020, (u32)vb->txd.desc_dma); vb_setctl(vb, 0x0018, (u32)vb->rxd.desc_dma); reg = vb_getctl(vb, 0x00fc); vb_setctl(vb, 0x00fc, (reg & ~0x7) | 0x7); vb_setsdi(vb, 0x00, 0x0100); vb_setsdi(vb, 0x16, 0x2100); reg = vb_getctl(vb, 0x00fc); vb_setctl(vb, 0x00fc, (reg & ~0x7) | 0x4); vb_setsdi(vb, 0x00, 0x0100); vb_setsdi(vb, 0x16, 0x2100); reg = vb_getctl(vb, 0x00fc); /* * The calls to setsdi above toggle the reset line of the CPLD. Wait * here to give the CPLD time to stabilize after reset. */ msleep(10); return ((reg&0x7) == 0x4) ? 0 : -EIO; } #define OWNED(_d_) (((_d_)->des0)&OWN_BIT) #define SET_OWNED(_d_) do { wmb(); (_d_)->des0 |= OWN_BIT; wmb(); } while (0) #ifdef DBG static void dump_descriptor(struct voicebus *vb, volatile struct voicebus_descriptor *d) { VB_PRINTK(vb, DEBUG, "Displaying descriptor at address %08x\n", (unsigned int)d); VB_PRINTK(vb, DEBUG, " des0: %08x\n", d->des0); VB_PRINTK(vb, DEBUG, " des1: %08x\n", d->des1); VB_PRINTK(vb, DEBUG, " buffer1: %08x\n", d->buffer1); VB_PRINTK(vb, DEBUG, " container: %08x\n", d->container); } static void show_buffer(struct voicebus *vb, void *vbb) { int x; unsigned char *c; c = vbb; printk(KERN_DEBUG "Packet %d\n", count); printk(KERN_DEBUG ""); for (x = 1; x <= vb->framesize; ++x) { printk("%02x ", c[x]); if (x % 16 == 0) printk("\n"); } printk(KERN_DEBUG "\n\n"); } #endif static inline int vb_submit(struct voicebus *vb, struct voicebus_descriptor_list *dl, void *vbb) { volatile struct voicebus_descriptor *d; unsigned int tail = dl->tail; assert_in_vb_deferred(vb); d = vb_descriptor(dl, tail); if (unlikely(d->buffer1)) { /* Do not overwrite a buffer that is still in progress. */ WARN_ON(1); voicebus_free(vb, vbb); return -EBUSY; } dl->pending[tail] = vbb; dl->tail = (++tail) & DRING_MASK; d->buffer1 = dma_map_single( &vb->pdev->dev, vbb, vb->framesize, dl->direction); SET_OWNED(d); /* That's it until the hardware is done with it. */ atomic_inc(&dl->count); return 0; } static inline void* vb_retrieve(struct voicebus *vb, struct voicebus_descriptor_list *dl) { volatile struct voicebus_descriptor *d; void *vbb; unsigned int head = dl->head; assert_in_vb_deferred(vb); d = vb_descriptor(dl, head); if (d->buffer1 && !OWNED(d)) { dma_unmap_single(&vb->pdev->dev, d->buffer1, vb->framesize, dl->direction); vbb = dl->pending[head]; dl->head = (++head) & DRING_MASK; d->buffer1 = 0; atomic_dec(&dl->count); return vbb; } else { return NULL; } } /*! * \brief Give a frame to the hardware to transmit. * */ int voicebus_transmit(struct voicebus *vb, void *vbb) { return vb_submit(vb, &vb->txd, vbb); } EXPORT_SYMBOL(voicebus_transmit); /*! * \brief Give a frame to the hardware to use for receiving. * */ static inline int vb_submit_rxb(struct voicebus *vb, void *vbb) { return vb_submit(vb, &vb->rxd, vbb); } /*! * \brief Remove the next completed transmit buffer (txb) from the tx * descriptor ring. * * NOTE: This function doesn't need any locking because only one instance is * ever running on the deferred processing routine and it only looks at * the head pointer. The deferred routine should only ever be running * on one processor at a time (no multithreaded workqueues allowed!) * * Context: Must be called from the voicebus deferred workqueue. * * \return Pointer to buffer, or NULL if not available. */ static inline void * vb_get_completed_txb(struct voicebus *vb) { return vb_retrieve(vb, &vb->txd); } static inline void * vb_get_completed_rxb(struct voicebus *vb) { return vb_retrieve(vb, &vb->rxd); } /*! * \brief Free a buffer for reuse. * */ void voicebus_free(struct voicebus *vb, void *vbb) { kmem_cache_free(vb->buffer_cache, vbb); } /*! * \brief Instruct the hardware to check for a new tx descriptor. */ static inline void __vb_tx_demand_poll(struct voicebus *vb) { __vb_setctl(vb, 0x0008, 0x00000000); } /*! * \brief Command the hardware to check if it owns the next transmit * descriptor. */ static void vb_tx_demand_poll(struct voicebus *vb) { LOCKS_VOICEBUS; VBLOCK(vb); __vb_tx_demand_poll(vb); VBUNLOCK(vb); } /*! * \brief Command the hardware to check if it owns the next receive * descriptor. */ static inline void __vb_rx_demand_poll(struct voicebus *vb) { __vb_setctl(vb, 0x0010, 0x00000000); } static void vb_rx_demand_poll(struct voicebus *vb) { LOCKS_VOICEBUS; VBLOCK(vb); __vb_rx_demand_poll(vb); VBUNLOCK(vb); } static void __vb_enable_interrupts(struct voicebus *vb) { __vb_setctl(vb, IER_CSR7, DEFAULT_INTERRUPTS); } static void __vb_disable_interrupts(struct voicebus *vb) { __vb_setctl(vb, IER_CSR7, 0); } static void vb_disable_interrupts(struct voicebus *vb) { LOCKS_VOICEBUS; VBLOCK(vb); __vb_disable_interrupts(vb); VBUNLOCK(vb); } /*! * \brief Starts the VoiceBus interface. * * When the VoiceBus interface is started, it is actively transferring * frames to and from the backend of the card. This means the card will * generate interrupts. * * This function should only be called from process context, with interrupts * enabled, since it can sleep while running the self checks. * * \return zero on success. -EBUSY if device is already running. */ int voicebus_start(struct voicebus *vb) { LOCKS_VOICEBUS; u32 reg; int i; void *vbb; int ret; assert(!in_interrupt()); if (!vb_is_stopped(vb)) return -EBUSY; ret = vb_reset_interface(vb); if (ret) return ret; ret = vb_initialize_interface(vb); if (ret) return ret; /* We must set up a minimum of three buffers to start with, since two * are immediately read into the TX FIFO, and the descriptor of the * third is read as soon as the first buffer is done. */ /* * NOTE: handle_transmit is normally only called in the context of the * deferred processing thread. Since the deferred processing thread * is known to not be running at this point, it is safe to call the * handle transmit as if it were. */ start_vb_deferred(vb); /* Ensure that all the rx slots are ready for a buffer. */ for (i = 0; i < DRING_SIZE; ++i) { vbb = voicebus_alloc(vb); if (unlikely(NULL == vbb)) { BUG_ON(1); /* \todo I need to make sure the driver can recover * from this condition. .... */ } else { vb_submit_rxb(vb, vbb); } } for (i = 0; i < vb->min_tx_buffer_count; ++i) { vbb = voicebus_alloc(vb); if (unlikely(NULL == vbb)) BUG_ON(1); else vb->handle_transmit(vbb, vb->context); } stop_vb_deferred(vb); VBLOCK(vb); clear_bit(STOP, &vb->flags); clear_bit(STOPPED, &vb->flags); #if VOICEBUS_DEFERRED == TIMER vb->timer.expires = jiffies + HZ/1000; add_timer(&vb->timer); #else /* Clear the interrupt status register. */ __vb_setctl(vb, SR_CSR5, 0xffffffff); __vb_enable_interrupts(vb); #endif /* Start the transmit and receive processors. */ reg = __vb_getctl(vb, 0x0030); __vb_setctl(vb, 0x0030, reg|0x00002002); /* Tell the interface to poll the tx and rx descriptors. */ __vb_rx_demand_poll(vb); __vb_tx_demand_poll(vb); VBUNLOCK(vb); assert(!vb_is_stopped(vb)); return 0; } EXPORT_SYMBOL(voicebus_start); static void vb_clear_start_transmit_bit(struct voicebus *vb) { LOCKS_VOICEBUS; u32 reg; VBLOCK(vb); reg = __vb_getctl(vb, NAR_CSR6); reg &= ~0x00002000; __vb_setctl(vb, NAR_CSR6, reg); VBUNLOCK(vb); } static void vb_clear_start_receive_bit(struct voicebus *vb) { LOCKS_VOICEBUS; u32 reg; VBLOCK(vb); reg = __vb_getctl(vb, NAR_CSR6); reg &= ~0x00000002; __vb_setctl(vb, NAR_CSR6, reg); VBUNLOCK(vb); } static unsigned long vb_wait_for_completion_timeout(struct completion *x, unsigned long timeout) { #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) /* There is a race condition here. If x->done is reset to 0 * before the call to wait_for_completion after this thread wakes. */ timeout = wait_event_timeout(x->wait, x->done, timeout); if (timeout) wait_for_completion(x); return timeout; #else return wait_for_completion_timeout(x, timeout); #endif } /*! * \brief Stops the VoiceBus interface. * * Stops the VoiceBus interface and waits for any outstanding DMA transactions * to complete. When this functions returns the VoiceBus interface tx and rx * states will both be suspended. * * Only call this function from process context, with interrupt enabled, * without any locks held since it sleeps. * * \return zero on success, -1 on error. */ int voicebus_stop(struct voicebus *vb) { assert(!in_interrupt()); if (vb_is_stopped(vb)) return 0; INIT_COMPLETION(vb->stopped_completion); set_bit(STOP, &vb->flags); vb_clear_start_transmit_bit(vb); vb_clear_start_receive_bit(vb); if (vb_wait_for_completion_timeout(&vb->stopped_completion, HZ)) { assert(vb_is_stopped(vb)); } else { VB_PRINTK(vb, WARNING, "Timeout while waiting for board to "\ "stop.\n"); vb_clear_start_transmit_bit(vb); vb_clear_start_receive_bit(vb); set_bit(STOPPED, &vb->flags); vb_disable_interrupts(vb); } #if VOICEBUS_DEFERRED == TIMER del_timer_sync(&vb->timer); #endif return 0; } EXPORT_SYMBOL(voicebus_stop); /*! * \brief Prepare the interface for module unload. * * Stop the interface and free all the resources allocated by the driver. The * caller should have returned all VoiceBus buffers to the VoiceBus layer * before calling this function. * * context: !in_interrupt() */ void voicebus_release(struct voicebus *vb) { assert(!in_interrupt()); /* quiesce the hardware */ voicebus_stop(vb); #if VOICEBUS_DEFERRED == WORKQUEUE destroy_workqueue(vb->workqueue); #elif VOICEBUS_DEFERRED == TASKLET tasklet_kill(&vb->tasklet); #endif vb_reset_interface(vb); #if VOICEBUS_DEFERRED != TIMER free_irq(vb->pdev->irq, vb); #endif /* Cleanup memory and software resources. */ vb_free_descriptors(vb, &vb->txd); vb_free_descriptors(vb, &vb->rxd); kmem_cache_destroy(vb->buffer_cache); release_region(vb->iobase, 0xff); pci_disable_device(vb->pdev); kfree(vb); } EXPORT_SYMBOL(voicebus_release); static void __vb_increase_latency(struct voicebus *vb) { static int __warn_once = 1; void *vbb; int latency; assert_in_vb_deferred(vb); latency = atomic_read(&vb->txd.count); if (DRING_SIZE == latency) { if (__warn_once) { /* We must subtract two from this number since there * are always two buffers in the TX FIFO. */ VB_PRINTK(vb, ERR, "ERROR: Unable to service card within %d ms "\ "and unable to further increase latency.\n", DRING_SIZE-2); __warn_once = 0; } } else { /* Because there are 2 buffers in the transmit FIFO on the * hardware, setting 3 ms of latency means that the host needs * to be able to service the cards within 1ms. This is because * the interface will load up 2 buffers into the TX FIFO then * attempt to read the 3rd descriptor. If the OWN bit isn't * set, then the hardware will set the TX descriptor not * available interrupt. */ VB_PRINTK(vb, INFO, "Missed interrupt. " \ "Increasing latency to %d ms in order to compensate.\n", latency+1); /* Set the minimum latency in case we're restarted...we don't * want to wait for the buffer to grow to this depth again in * that case. */ voicebus_set_minlatency(vb, latency+1); vbb = voicebus_alloc(vb); if (unlikely(NULL == vbb)) BUG_ON(1); else vb->handle_transmit(vbb, vb->context); } } /*! * \brief Actually process the completed transmit and receive buffers. * * NOTE: This function may be called either from a tasklet, workqueue, or * directly in the interrupt service routine depending on * VOICEBUS_DEFERRED. */ static inline void vb_deferred(struct voicebus *vb) { void *vbb; #ifdef DBG static int count; #endif int underrun = test_bit(TX_UNDERRUN, &vb->flags); start_vb_deferred(vb); if (unlikely(underrun)) { /* When we've underrun our FIFO, for some reason we're not * able to keep enough transmit descriptors pending. This can * happen if either interrupts or this deferred processing * function is not run soon enough (within 1ms when using the * default 3 transmit buffers to start). In this case, we'll * insert an additional transmit buffer onto the descriptor * list which decreases the sensitivity to latency, but also * adds more delay to the TDM and SPI data. */ __vb_increase_latency(vb); } /* Always handle the transmit buffers first. */ while ((vbb = vb_get_completed_txb(vb))) vb->handle_transmit(vbb, vb->context); if (unlikely(underrun)) { vb_rx_demand_poll(vb); vb_tx_demand_poll(vb); clear_bit(TX_UNDERRUN, &vb->flags); } while ((vbb = vb_get_completed_rxb(vb))) { vb->handle_receive(vbb, vb->context); vb_submit_rxb(vb, vbb); } stop_vb_deferred(vb); } /*! * \brief Interrupt handler for VoiceBus interface. * * NOTE: This handler is optimized for the case where only a single interrupt * condition will be generated at a time. * * ALSO NOTE: Only access the interrupt status register from this function * since it doesn't employ any locking on the voicebus interface. */ static irqreturn_t #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) vb_isr(int irq, void *dev_id, struct pt_regs *regs) #else vb_isr(int irq, void *dev_id) #endif { struct voicebus *vb = dev_id; u32 int_status; int_status = __vb_getctl(vb, SR_CSR5); /* Mask out the reserved bits. */ int_status &= ~(0xfc004010); int_status &= 0x7fff; if (!int_status) return IRQ_NONE; if (likely(int_status & TX_COMPLETE_INTERRUPT)) { /* ******************************************************** */ /* NORMAL INTERRUPT CASE */ /* ******************************************************** */ # if VOICEBUS_DEFERRED == WORKQUEUE queue_work(vb->workqueue, &vb->workitem); # elif VOICEBUS_DEFERRED == TASKLET tasklet_schedule(&vb->tasklet); # else vb_deferred(vb); # endif __vb_setctl(vb, SR_CSR5, TX_COMPLETE_INTERRUPT); } else { /* ******************************************************** */ /* ABNORMAL / ERROR CONDITIONS */ /* ******************************************************** */ if ((int_status & TX_UNAVAILABLE_INTERRUPT)) { /* This can happen if the host fails to service the * interrupt within the required time interval (1ms * for each buffer on the queue). Increasing the * depth of the tx queue (up to a maximum of * DRING_SIZE) can make the driver / system more * tolerant of interrupt latency under periods of * heavy system load, but also increases the general * latency that the driver adds to the voice * conversations. */ set_bit(TX_UNDERRUN, &vb->flags); # if VOICEBUS_DEFERRED == WORKQUEUE queue_work(vb->workqueue, &vb->workitem); # elif VOICEBUS_DEFERRED == TASKLET tasklet_schedule(&vb->tasklet); # else vb_deferred(vb); # endif } if (int_status & FATAL_BUS_ERROR_INTERRUPT) VB_PRINTK(vb, ERR, "Fatal Bus Error detected!\n"); if (int_status & TX_STOPPED_INTERRUPT) { assert(test_bit(STOP, &vb->flags)); __vb_disable_interrupts(vb); complete(&vb->stopped_completion); } if (int_status & RX_STOPPED_INTERRUPT) { assert(test_bit(STOP, &vb->flags)); if (vb_is_stopped(vb)) { __vb_disable_interrupts(vb); complete(&vb->stopped_completion); } } /* Clear the interrupt(s) */ __vb_setctl(vb, SR_CSR5, int_status); } return IRQ_HANDLED; } #if VOICEBUS_DEFERRED == TIMER /*! \brief Called if the deferred processing is to happen in the context of * the timer. */ static void vb_timer(unsigned long data) { unsigned long start = jiffies; struct voicebus *vb = (struct voicebus *)data; #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) vb_isr(0, vb, 0); #else vb_isr(0, vb); #endif if (!test_bit(STOPPED, &vb->flags)) { vb->timer.expires = start + HZ/1000; add_timer(&vb->timer); } } #endif #if VOICEBUS_DEFERRED == WORKQUEUE static void #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) vb_workfunc(void *data) { struct voicebus *vb = data; #else vb_workfunc(struct work_struct *work) { struct voicebus *vb = container_of(work, struct voicebus, workitem); #endif vb_deferred(vb); } #elif VOICEBUS_DEFERRED == TASKLET static void vb_tasklet(unsigned long data) { struct voicebus *vb = (struct voicebus *)data; vb_deferred(vb); } #endif /* #if VOICEBUS_DEFERRED == WORKQUEUE */ /*! * \brief Initalize the voicebus interface. * * This function must be called in process context since it may sleep. * \todo Complete this description. */ int voicebus_init(struct pci_dev *pdev, u32 framesize, const char *board_name, void (*handle_receive)(void *vbb, void *context), void (*handle_transmit)(void *vbb, void *context), void *context, u32 debuglevel, struct voicebus **vbp ) { int retval = 0; struct voicebus *vb; assert(NULL != pdev); assert(NULL != board_name); assert(framesize); assert(NULL != handle_receive); assert(NULL != handle_transmit); /* ---------------------------------------------------------------- Initialize the pure software constructs. ---------------------------------------------------------------- */ *vbp = NULL; vb = kmalloc(sizeof(*vb), GFP_KERNEL); if (NULL == vb) { VB_PRINTK(vb, DEBUG, "Failed to allocate memory for voicebus "\ "interface.\n"); retval = -ENOMEM; goto cleanup; } memset(vb, 0, sizeof(*vb)); voicebus_setdebuglevel(vb, debuglevel); /* \todo make sure there is a note that the caller needs to make sure * board_name stays in memory until voicebus_release is called. */ vb->board_name = board_name; spin_lock_init(&vb->lock); init_completion(&vb->stopped_completion); vb->pdev = pdev; set_bit(STOP, &vb->flags); clear_bit(IN_DEFERRED_PROCESSING, &vb->flags); vb->framesize = framesize; vb->min_tx_buffer_count = VOICEBUS_DEFAULT_LATENCY; #if VOICEBUS_DEFERRED == WORKQUEUE /* NOTE: This workqueue must be single threaded because locking is not * used when buffers are removed or added to the descriptor list, and * there should only be one producer / consumer (the hardware or the * deferred processing function). */ vb->workqueue = create_singlethread_workqueue(board_name); # if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) INIT_WORK(&vb->workitem, vb_workfunc, vb); # else INIT_WORK(&vb->workitem, vb_workfunc); # endif # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18) vb_set_workqueue_priority(vb); # endif #elif VOICEBUS_DEFERRED == TASKLET tasklet_init(&vb->tasklet, vb_tasklet, (unsigned long)vb); #elif VOICEBUS_DEFERRED == TIMER init_timer(&vb->timer); vb->timer.function = vb_timer; vb->timer.data = (unsigned long)vb; #endif vb->handle_receive = handle_receive; vb->handle_transmit = handle_transmit; vb->context = context; /* \todo This cache should be shared by all instances supported by * this driver. */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) vb->buffer_cache = kmem_cache_create(board_name, vb->framesize, 0, #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 22) SLAB_HWCACHE_ALIGN | SLAB_STORE_USER, NULL, NULL); #else SLAB_HWCACHE_ALIGN, NULL, NULL); #endif #else vb->buffer_cache = kmem_cache_create(board_name, vb->framesize, 0, SLAB_HWCACHE_ALIGN, NULL); #endif if (NULL == vb->buffer_cache) { VB_PRINTK(vb, ERR, "Failed to allocate buffer cache.\n"); goto cleanup; } /* ---------------------------------------------------------------- Configure the hardware / kernel module interfaces. ---------------------------------------------------------------- */ if (pci_read_config_byte(vb->pdev, 0x0c, &vb->cache_line_size)) { VB_PRINTK(vb, ERR, "Failed read of cache line " \ "size from PCI configuration space.\n"); goto cleanup; } if (pci_enable_device(pdev)) { VB_PRINTK(vb, ERR, "Failed call to pci_enable_device.\n"); retval = -EIO; goto cleanup; } /* \todo This driver should be modified to use the memory mapped I/O as opposed to IO space for portability and performance. */ if (0 == (pci_resource_flags(pdev, 0)&IORESOURCE_IO)) { VB_PRINTK(vb, ERR, "BAR0 is not IO Memory.\n"); retval = -EIO; goto cleanup; } vb->iobase = pci_resource_start(pdev, 0); if (NULL == request_region(vb->iobase, 0xff, board_name)) { VB_PRINTK(vb, ERR, "IO Registers are in use by another " \ "module.\n"); retval = -EIO; goto cleanup; } retval = vb_initialize_tx_descriptors(vb); if (retval) goto cleanup; retval = vb_initialize_rx_descriptors(vb); if (retval) goto cleanup; /* ---------------------------------------------------------------- Configure the hardware interface. ---------------------------------------------------------------- */ pci_set_master(pdev); vb_enable_io_access(vb); #if VOICEBUS_DEFERRED != TIMER #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) # define VB_IRQ_SHARED SA_SHIRQ #else # define VB_IRQ_SHARED IRQF_SHARED #endif if (request_irq(pdev->irq, vb_isr, VB_IRQ_SHARED, vb->board_name, vb)) { assert(0); goto cleanup; } #endif *vbp = vb; return retval; cleanup: if (NULL == vb) return retval; #if VOICEBUS_DEFERRED == WORKQUEUE if (vb->workqueue) destroy_workqueue(vb->workqueue); #elif VOICEBUS_DEFERRED == TASKLET tasklet_kill(&vb->tasklet); #endif /* Cleanup memory and software resources. */ if (vb->txd.desc) vb_free_descriptors(vb, &vb->txd); if (vb->rxd.desc) vb_free_descriptors(vb, &vb->rxd); if (vb->buffer_cache) kmem_cache_destroy(vb->buffer_cache); if (vb->iobase) release_region(vb->iobase, 0xff); if (vb->pdev) pci_disable_device(vb->pdev); kfree(vb); assert(0 != retval); return retval; } EXPORT_SYMBOL(voicebus_init); /*! \brief Return the pci_dev in use by this voicebus interface. */ struct pci_dev * voicebus_get_pci_dev(struct voicebus *vb) { return vb->pdev; } EXPORT_SYMBOL(voicebus_get_pci_dev); static spinlock_t loader_list_lock; static struct list_head binary_loader_list; /** * vpmadtreg_loadfirmware - Load the vpmadt032 firmware. * @vb: The voicebus device to load. */ int vpmadtreg_loadfirmware(struct voicebus *vb) { struct vpmadt_loader *loader; int ret = 0; int loader_present = 0; might_sleep(); /* First check to see if a loader is already loaded into memory. */ spin_lock(&loader_list_lock); loader_present = !(list_empty(&binary_loader_list)); spin_unlock(&loader_list_lock); if (!loader_present) { ret = request_module("dahdi_vpmadt032_loader"); if (ret) return ret; } spin_lock(&loader_list_lock); if (!list_empty(&binary_loader_list)) { loader = list_entry(binary_loader_list.next, struct vpmadt_loader, node); if (try_module_get(loader->owner)) { spin_unlock(&loader_list_lock); ret = loader->load(vb); module_put(loader->owner); } else { spin_unlock(&loader_list_lock); printk(KERN_INFO "Failed to find a registered loader after loading module.\n"); ret = -ENODEV; } } else { spin_unlock(&loader_list_lock); printk(KERN_INFO "Failed to find a registered loader after loading module.\n"); ret = -1; } return ret; } /* Called by the binary loader module when it is ready to start loading * firmware. */ int vpmadtreg_register(struct vpmadt_loader *loader) { spin_lock(&loader_list_lock); list_add_tail(&loader->node, &binary_loader_list); spin_unlock(&loader_list_lock); return 0; } EXPORT_SYMBOL(vpmadtreg_register); int vpmadtreg_unregister(struct vpmadt_loader *loader) { int removed = 0; struct vpmadt_loader *cur, *temp; list_for_each_entry_safe(cur, temp, &binary_loader_list, node) { if (loader == cur) { list_del_init(&cur->node); removed = 1; break; } } WARN_ON(!removed); return 0; } EXPORT_SYMBOL(vpmadtreg_unregister); int __init voicebus_module_init(void) { int res; /* This registration with dahdi.ko will fail since the span is not * defined, but it will make sure that this module is a dependency of * dahdi.ko, so that when it is being unloded, this module will be * unloaded as well. */ dahdi_register(0, 0); INIT_LIST_HEAD(&binary_loader_list); spin_lock_init(&loader_list_lock); res = vpmadt032_module_init(); if (res) return res; return 0; } void __exit voicebus_module_cleanup(void) { WARN_ON(!list_empty(&binary_loader_list)); } MODULE_DESCRIPTION("Voicebus Interface w/VPMADT032 support"); MODULE_AUTHOR("Digium Incorporated "); MODULE_LICENSE("GPL"); module_init(voicebus_module_init); module_exit(voicebus_module_cleanup); dahdi-linux-2.2.0-rc4/drivers/dahdi/voicebus/GpakCust.h0000644000175000017500000002041511202062373022107 0ustar maniacmaniac/* * Copyright (c) 2005, Adaptive Digital Technologies, Inc. * * File Name: GpakCust.h * * Description: * This file contains host system dependent definitions and prototypes of * functions to support generic G.PAK API functions. The file is used when * integrating G.PAK API functions in a specific host processor environment. * * Note: This file may need to be modified by the G.PAK system integrator. * * Version: 1.0 * * Revision History: * 06/15/05 - Initial release. * * This program has been released under the terms of the GPL version 2 by * permission of Adaptive Digital Technologies, Inc. * */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ #ifndef _GPAKCUST_H /* prevent multiple inclusion */ #define _GPAKCUST_H #include #include #include #include "gpakenum.h" #include "adt_lec.h" #define DEBUG_ECHOCAN (1 << 1) /* Host and DSP system dependent related definitions. */ #define MAX_DSP_CORES 128 /* maximum number of DSP cores */ #define MAX_CHANNELS 32 /* maximum number of channels */ #define MAX_WAIT_LOOPS 50 /* max number of wait delay loops */ #define DSP_IFBLK_ADDRESS 0x0100 /* DSP address of I/F block pointer */ #define DOWNLOAD_BLOCK_SIZE 512 /* download block size (DSP words) */ #define VPM150M_MAX_COMMANDS 8 #define __VPM150M_RWPAGE (1 << 4) #define __VPM150M_RD (1 << 3) #define __VPM150M_WR (1 << 2) #define __VPM150M_FIN (1 << 1) #define __VPM150M_TX (1 << 0) #define __VPM150M_RWPAGE (1 << 4) #define __VPM150M_RD (1 << 3) #define __VPM150M_WR (1 << 2) #define __VPM150M_FIN (1 << 1) #define __VPM150M_TX (1 << 0) /* Some Bit ops for different operations */ #define VPM150M_SPIRESET 0 #define VPM150M_HPIRESET 1 #define VPM150M_SWRESET 2 #define VPM150M_DTMFDETECT 3 #define VPM150M_ACTIVE 4 #define NLPTYPE_NONE 0 #define NLPTYPE_MUTE 1 #define NLPTYPE_RANDOM_NOISE 2 #define HOTH_NOISE_NLPTYPE 3 #define NLPTYPE_SUPPRESS 4 #define NLPTYPE_RESERVED 5 #define NLPTYPE_AUTOSUPPRESS 6 #define DEFAULT_NLPTYPE NLPTYPE_AUTOSUPPRESS /* This is the threshold (in dB) for enabling and disabling of the NLP */ #define DEFAULT_NLPTHRESH 22 #define DEFAULT_NLPMAXSUPP 10 struct vpmadt032_cmd { struct list_head node; __le32 address; __le16 data; u8 desc; u8 txident; struct completion complete; }; /* Contains the options used when initializing the vpmadt032 module */ struct vpmadt032_options { int vpmnlptype; int vpmnlpthresh; int vpmnlpmaxsupp; u32 debug; u32 channels; }; struct GpakChannelConfig; #define MAX_CHANNELS_PER_SPAN 32 struct vpmadt032 { void *context; const struct dahdi_span *span; struct work_struct work; struct workqueue_struct *wq; int dspid; struct semaphore sem; unsigned long control; unsigned char curpage; unsigned short version; struct adt_lec_params curecstate[MAX_CHANNELS_PER_SPAN]; struct adt_lec_params desiredecstate[MAX_CHANNELS_PER_SPAN]; spinlock_t list_lock; /* Commands that are ready to be used. */ struct list_head free_cmds; /* Commands that are waiting to be processed. */ struct list_head pending_cmds; /* Commands that are currently in progress by the VPM module */ struct list_head active_cmds; unsigned char curtone[MAX_CHANNELS_PER_SPAN]; struct vpmadt032_options options; void (*setchanconfig_from_state)(struct vpmadt032 *vpm, int channel, struct GpakChannelConfig *chanconfig); /* This must be last */ char wq_name[0]; }; struct voicebus; struct dahdi_chan; struct dahdi_echocanparams; struct dahdi_echocanparam; struct dahdi_echocan_state; char vpmadt032tone_to_zaptone(GpakToneCodes_t tone); int vpmadt032_init(struct vpmadt032 *vpm, struct voicebus *vb); struct vpmadt032 *vpmadt032_alloc(struct vpmadt032_options *options, const char *board_name); void vpmadt032_free(struct vpmadt032 *vpm); int vpmadt032_echocan_create(struct vpmadt032 *vpm, int channo, struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p); void vpmadt032_echocan_free(struct vpmadt032 *vpm, struct dahdi_chan *chan, struct dahdi_echocan_state *ec); struct GpakEcanParms; void vpmadt032_get_default_parameters(struct GpakEcanParms *p); /* If there is a command ready to go to the VPMADT032, return it, otherwise NULL */ static inline struct vpmadt032_cmd *vpmadt032_get_ready_cmd(struct vpmadt032 *vpm) { unsigned long flags; struct vpmadt032_cmd *cmd; spin_lock_irqsave(&vpm->list_lock, flags); if (list_empty(&vpm->pending_cmds)) { spin_unlock_irqrestore(&vpm->list_lock, flags); return NULL; } cmd = list_entry(vpm->pending_cmds.next, struct vpmadt032_cmd, node); list_move_tail(&cmd->node, &vpm->active_cmds); spin_unlock_irqrestore(&vpm->list_lock, flags); return cmd; } int vpmadt032_module_init(void); typedef __u16 DSP_WORD; /* 16 bit DSP word */ typedef __u32 DSP_ADDRESS; /* 32 bit DSP address */ typedef __u32 GPAK_FILE_ID; /* G.PAK Download file identifier */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadDspMemory - Read DSP memory. * * FUNCTION * This function reads a contiguous block of words from DSP memory starting at * the specified address. * * RETURNS * nothing * */ extern void gpakReadDspMemory( unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ unsigned int NumWords, /* number of contiguous words to read */ DSP_WORD *pWordValues /* pointer to array of word values variable */ ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakWriteDspMemory - Write DSP memory. * * FUNCTION * This function writes a contiguous block of words to DSP memory starting at * the specified address. * * RETURNS * nothing * */ extern void gpakWriteDspMemory( unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ unsigned int NumWords, /* number of contiguous words to write */ DSP_WORD *pWordValues /* pointer to array of word values to write */ ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakHostDelay - Delay for a fixed time interval. * * FUNCTION * This function delays for a fixed time interval before returning. The time * interval is the Host Port Interface sampling period when polling a DSP for * replies to command messages. * * RETURNS * nothing * */ extern void gpakHostDelay(void); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakLockAccess - Lock access to the specified DSP. * * FUNCTION * This function aquires exclusive access to the specified DSP. * * RETURNS * nothing * */ extern void gpakLockAccess( unsigned short int DspId /* DSP Identifier (0 to MAX_DSP_CORES-1) */ ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakUnlockAccess - Unlock access to the specified DSP. * * FUNCTION * This function releases exclusive access to the specified DSP. * * RETURNS * nothing * */ extern void gpakUnlockAccess( unsigned short int DspId /* DSP Identifier (0 to MAX_DSP_CORES-1) */ ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadFile - Read a block of bytes from a G.PAK Download file. * * FUNCTION * This function reads a contiguous block of bytes from a G.PAK Download file * starting at the current file position. * * RETURNS * The number of bytes read from the file. * -1 indicates an error occurred. * 0 indicates all bytes have been read (end of file) * */ extern int gpakReadFile( GPAK_FILE_ID FileId, /* G.PAK Download File Identifier */ unsigned char *pBuffer, /* pointer to buffer for storing bytes */ unsigned int NumBytes /* number of bytes to read */ ); #endif /* prevent multiple inclusion */ dahdi-linux-2.2.0-rc4/drivers/dahdi/voicebus/Kbuild0000644000175000017500000000024311176111367021357 0ustar maniacmaniacobj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_VOICEBUS) += dahdi_voicebus.o dahdi_voicebus-objs := voicebus.o GpakCust.o GpakApi.o EXTRA_CFLAGS := -I$(src)/.. -Wno-undef dahdi-linux-2.2.0-rc4/drivers/dahdi/voicebus/GpakApi.h0000644000175000017500000006075511202062373021715 0ustar maniacmaniac/* * Copyright (c) 2005 , Adaptive Digital Technologies, Inc. * * File Name: GpakApi.h * * Description: * This file contains the function prototypes and data types for the user * API functions that communicate with DSPs executing G.PAK software. The * file is used by application software in the host processor connected to * C55X G.PAK DSPs via a Host Port Interface. * * Version: 1.0 * * Revision History: * 06/15/05 - Initial release. * 11/15/2006 - 24 TDM-TDM Channels EC release */ #ifndef _GPAKAPI_H /* prevent multiple inclusion */ #define _GPAKAPI_H #include "gpakErrs.h" #include "gpakenum.h" // Bit masks to select which algorithm's parameters to update: Or-together the // desired masks into the UpdateBits function parameter. #define DTMF_UPDATE_MASK 0x0010 // update DTMF params, MinLevel, SNRFlag and Freq #define DTMF_TWIST_UPDATE_MASK 0x0020 // update DTMF TWIST system params #define DTMF_VALID_MASK 0x0080 // update DTMF ValidMask params #define DSP_DEBUG_BUFF_SIZE 42 // units of 16-bit words /* Definition of an Asynchronous Event Data Structure */ typedef union { struct { GpakToneCodes_t ToneCode; // detected tone code unsigned short int ToneDuration; // tone duration GpakTdmDirection Direction; // detected on A r B side short int DebugToneStatus;// reserved for debug info } toneEvent; } GpakAsyncEventData_t; /* Definition of an Echo Canceller Parameters information structure. */ typedef struct GpakEcanParms { short int EcanTapLength; // Echo Can Num Taps (tail length) short int EcanNlpType; // Echo Can NLP Type short int EcanAdaptEnable; // Echo Can Adapt Enable flag short int EcanG165DetEnable; // Echo Can G165 Detect Enable flag short int EcanDblTalkThresh; // Echo Can Double Talk threshold short int EcanMaxDoubleTalkThres; // Maximum double-talk threshold short int EcanNlpThreshold; // Echo Can NLP threshold short int EcanNlpConv; // Dynamic NLP control, NLP limit when EC about to converged short int EcanNlpUnConv;// Dynamic NLP control, NLP limit when EC not converged yet short int EcanNlpMaxSuppress; // suppression level for NLP_SUPP mode short int EcanCngThreshold; // Echo Can CNG Noise threshold short int EcanAdaptLimit; // Echo Can Max Adapts per frame short int EcanCrossCorrLimit; // Echo Can Cross Correlation limit short int EcanNumFirSegments; // Echo Can Num FIR Segments short int EcanFirSegmentLen; // Echo Can FIR Segment Length short int EcanTandemOperationEnable; //Enable tandem operation short int EcanMixedFourWireMode; // Handle possible 4-wire (echo-free) lines short int EcanReconvergenceCheckEnable; // Handle possible 4-wire (echo-free) lines } GpakEcanParms_t; /* Definition of a Channel Configuration information structure. */ typedef struct GpakChannelConfig { GpakSerialPort_t PcmInPortA; // A side PCM Input Serial Port Id unsigned short int PcmInSlotA; // A side PCM Input Time Slot GpakSerialPort_t PcmOutPortA; // A side PCM Output Serial Port Id unsigned short int PcmOutSlotA; // A side PCM Output Time Slot GpakSerialPort_t PcmInPortB; // B side PCM Input Serial Port Id unsigned short int PcmInSlotB; // B side PCM Input Time Slot GpakSerialPort_t PcmOutPortB; // B side PCM Output Serial Port Id unsigned short int PcmOutSlotB; // B side PCM Output Time Slot GpakToneTypes ToneTypesA; // A side Tone Detect Types GpakToneTypes ToneTypesB; // B side Tone Detect Types GpakActivation EcanEnableA; // Echo Cancel A Enabled GpakActivation EcanEnableB; // Echo Cancel B Enabled GpakEcanParms_t EcanParametersA; // Echo Cancel parameters GpakEcanParms_t EcanParametersB; // Echo Cancel parameters GpakCompandModes SoftwareCompand; // software companding GpakRate_t FrameRate; // Gpak Frame Rate GpakActivation MuteToneA; // A side mute DTMF Enabled GpakActivation MuteToneB; // B side mute DTMF Enabled GpakActivation FaxCngDetA; // A side FaxCng Tone Detector Enabled GpakActivation FaxCngDetB; // B side FaxCng Tone Detector Enabled } GpakChannelConfig_t; /* Definition of a Serial Port Configuration Structure */ typedef struct GpakPortConfig { GpakSlotCfg_t SlotsSelect1; // port 1 Slot selection unsigned short int FirstBlockNum1; // port 1 first group Block Number unsigned short int FirstSlotMask1; // port 1 first group Slot Mask unsigned short int SecBlockNum1; // port 1 second group Block Number unsigned short int SecSlotMask1; // port 1 second group Slot Mask GpakSerWordSize_t SerialWordSize1; // port 1 serial word size GpakCompandModes CompandingMode1; // port 1 companding mode GpakSerFrameSyncPol_t TxFrameSyncPolarity1; // port 1 Tx Frame Sync Polarity GpakSerFrameSyncPol_t RxFrameSyncPolarity1; // port 1 Rx Frame Sync Polarity GpakSerClockPol_t TxClockPolarity1; // port 1 Tx Clock Polarity GpakSerClockPol_t RxClockPolarity1; // port 1 Rx Clock Polarity GpakSerDataDelay_t TxDataDelay1; // port 1 Tx data delay GpakSerDataDelay_t RxDataDelay1; // port 1 Rx data delay GpakActivation DxDelay1; // port 1 DX Delay unsigned short int ThirdSlotMask1; // port 1 3rd group Slot Mask unsigned short int FouthSlotMask1; // port 1 4th group Slot Mask unsigned short int FifthSlotMask1; // port 1 5th group Slot Mask unsigned short int SixthSlotMask1; // port 1 6th group Slot Mask unsigned short int SevenSlotMask1; // port 1 7th group Slot Mask unsigned short int EightSlotMask1; // port 1 8th group Slot Mask GpakSlotCfg_t SlotsSelect2; // port 2 Slot selection unsigned short int FirstBlockNum2; // port 2 first group Block Number unsigned short int FirstSlotMask2; // port 2 first group Slot Mask unsigned short int SecBlockNum2; // port 2 second group Block Number unsigned short int SecSlotMask2; // port 2 second group Slot Mask GpakSerWordSize_t SerialWordSize2; // port 2 serial word size GpakCompandModes CompandingMode2; // port 2 companding mode GpakSerFrameSyncPol_t TxFrameSyncPolarity2; // port 2 Tx Frame Sync Polarity GpakSerFrameSyncPol_t RxFrameSyncPolarity2; // port 2 Rx Frame Sync Polarity GpakSerClockPol_t TxClockPolarity2; // port 2 Tx Clock Polarity GpakSerClockPol_t RxClockPolarity2; // port 2 Rx Clock Polarity GpakSerDataDelay_t TxDataDelay2; // port 2 Tx data delay GpakSerDataDelay_t RxDataDelay2; // port 2 Rx data delay GpakActivation DxDelay2; // port 2 DX Delay unsigned short int ThirdSlotMask2; // port 2 3rd group Slot Mask unsigned short int FouthSlotMask2; // port 2 4th group Slot Mask unsigned short int FifthSlotMask2; // port 2 5th group Slot Mask unsigned short int SixthSlotMask2; // port 2 6th group Slot Mask unsigned short int SevenSlotMask2; // port 2 7th group Slot Mask unsigned short int EightSlotMask2; // port 2 8th group Slot Mask GpakSlotCfg_t SlotsSelect3; // port 3 Slot selection unsigned short int FirstBlockNum3; // port 3 first group Block Number unsigned short int FirstSlotMask3; // port 3 first group Slot Mask unsigned short int SecBlockNum3; // port 3 second group Block Number unsigned short int SecSlotMask3; // port 3 second group Slot Mask GpakSerWordSize_t SerialWordSize3; // port 3 serial word size GpakCompandModes CompandingMode3; // port 3 companding mode GpakSerFrameSyncPol_t TxFrameSyncPolarity3; // port 3 Tx Frame Sync Polarity GpakSerFrameSyncPol_t RxFrameSyncPolarity3; // port 3 Rx Frame Sync Polarity GpakSerClockPol_t TxClockPolarity3; // port 3 Tx Clock Polarity GpakSerClockPol_t RxClockPolarity3; // port 3 Rx Clock Polarity GpakSerDataDelay_t TxDataDelay3; // port 3 Tx data delay GpakSerDataDelay_t RxDataDelay3; // port 3 Rx data delay GpakActivation DxDelay3; // port 3 DX Delay unsigned short int ThirdSlotMask3; // port 3 3rd group Slot Mask unsigned short int FouthSlotMask3; // port 3 4th group Slot Mask unsigned short int FifthSlotMask3; // port 3 5th group Slot Mask unsigned short int SixthSlotMask3; // port 3 6th group Slot Mask unsigned short int SevenSlotMask3; // port 3 7th group Slot Mask unsigned short int EightSlotMask3; // port 3 8th group Slot Mask } GpakPortConfig_t; /* Definition of a Tone Generation Parameter Structure */ /* typedef struct { GpakToneGenType_t ToneType; // Tone Type unsigned short int Frequency[4]; // Frequency (Hz) short int Level[4]; // Frequency's Level (1 dBm) unsigned short int OnTime[4]; // On Times (msecs) unsigned short int OffTime[4]; // Off Times (msecs) } GpakToneGenParms_t; */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* gpakConfigureChannel return status. */ typedef enum { CcsSuccess = 0, /* Channel Configured successfully */ CcsParmError = 1, /* Channel Config Parameter error */ CcsInvalidChannel = 2, /* invalid channel */ CcsInvalidDsp = 3, /* invalid DSP */ CcsDspCommFailure = 4 /* failed to communicate with DSP */ } gpakConfigChanStatus_t; /* * gpakConfigureChannel - Configure a DSP's Channel. * * FUNCTION * This function configures a DSP's Channel. * * RETURNS * Status code indicating success or a specific error. * */ extern gpakConfigChanStatus_t gpakConfigureChannel( unsigned short int DspId, // DSP identifier unsigned short int ChannelId, // channel identifier GpakChanType ChannelType, // channel type GpakChannelConfig_t *pChanConfig, // pointer to channel config info GPAK_ChannelConfigStat_t *pStatus // pointer to Channel Config Status ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* gpakTearDownChannel return status. */ typedef enum { TdsSuccess = 0, /* Channel Tear Down successful */ TdsError = 1, /* Channel Tear Down error */ TdsInvalidChannel = 2, /* invalid channel */ TdsInvalidDsp = 3, /* invalid DSP */ TdsDspCommFailure = 4 /* failed to communicate with DSP */ } gpakTearDownStatus_t; /* * gpakTearDownChannel - Tear Down a DSP's Channel. * * FUNCTION * This function tears down a DSP's Channel. * * RETURNS * Status code indicating success or a specific error. * */ extern gpakTearDownStatus_t gpakTearDownChannel( unsigned short int DspId, // DSP identifier unsigned short int ChannelId, // channel identifier GPAK_TearDownChanStat_t *pStatus // pointer to Tear Down Status ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* gpakAlgControl return status. */ typedef enum { AcSuccess = 0, /* control successful */ AcInvalidChannel = 1, /* invalid channel identifier */ AcInvalidDsp = 2, /* invalid DSP */ AcParmError = 3, /* invalid control parameter */ AcDspCommFailure = 4 /* failed to communicate with DSP */ } gpakAlgControlStat_t; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakAlgControl - Control an Algorithm. * * FUNCTION * This function controls an Algorithm * * RETURNS * Status code indicating success or a specific error. * */ extern gpakAlgControlStat_t gpakAlgControl( unsigned short int DspId, // DSP identifier unsigned short int ChannelId, // channel identifier GpakAlgCtrl_t ControlCode, // algorithm control code GPAK_AlgControlStat_t *pStatus // pointer to return status ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* gpakConfigurePorts return status. */ typedef enum { CpsSuccess = 0, /* Serial Ports configured successfully */ CpsParmError = 1, /* Configure Ports Parameter error */ CpsInvalidDsp = 2, /* invalid DSP */ CpsDspCommFailure = 3 /* failed to communicate with DSP */ } gpakConfigPortStatus_t; /* * gpakConfigurePorts - Configure a DSP's serial ports. * * FUNCTION * This function configures a DSP's serial ports. * * RETURNS * Status code indicating success or a specific error. * */ extern gpakConfigPortStatus_t gpakConfigurePorts( unsigned short int DspId, // DSP identifier const GpakPortConfig_t *pPortConfig, // pointer to Port Config info GPAK_PortConfigStat_t *pStatus // pointer to Port Config Status ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* gpakDownloadDsp return status. */ typedef enum { GdlSuccess = 0, /* DSP download successful */ GdlFileReadError = 1, /* error reading Download file */ GdlInvalidFile = 2, /* invalid Download file content */ GdlInvalidDsp = 3 /* invalid DSP */ } gpakDownloadStatus_t; /* * gpakDownloadDsp - Download a DSP's Program and initialized Data memory. * * FUNCTION * This function reads a DSP's Program and Data memory image from the * specified file and writes the image to the DSP's memory. * * RETURNS * Status code indicating success or a specific error. * */ extern gpakDownloadStatus_t gpakDownloadDsp( unsigned short int DspId, // DSP identifier GPAK_FILE_ID FileId // G.PAK download file identifier ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* gpakReadEventFIFOMessage return status */ typedef enum { RefEventAvail = 0, /* an event was successfully read from the fifo */ RefNoEventAvail = 1, /* no event was in the fifo */ RefInvalidDsp = 2, /* invalid DSP identifier */ RefInvalidEvent = 3, /* invalid event */ RefDspCommFailure = 4 /* error communicating with DSP */ } gpakReadEventFIFOMessageStat_t; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadEventFIFOMessage - read from the event fifo * * FUNCTION * This function reads a single event from the event fifo if one is available * * RETURNS * Status code indicating success or a specific error. * * Note: This function should be called in a loop until the return status * indicates that the fifo is empty. */ extern gpakReadEventFIFOMessageStat_t gpakReadEventFIFOMessage( unsigned short int DspId, // DSP identifier unsigned short int *pChannelId, // pointer to channel identifier GpakAsyncEventCode_t *pEventCode, // pointer to Event Code GpakAsyncEventData_t *pEventData // pointer to Event Data Struct ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /* gpakPingDsp return status values */ typedef enum { PngSuccess = 0, /* DSP responded successfully */ PngInvalidDsp = 1, /* invalid DSP identifier */ PngDspCommFailure = 2 /* error communicating with DSP */ } gpakPingDspStat_t; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakPingDsp - ping the DSP to see if it's alive * * FUNCTION * This function checks if the DSP is still communicating with the host * * RETURNS * Status code indicating success or a specific error. */ extern gpakPingDspStat_t gpakPingDsp( unsigned short int DspId, // DSP identifier unsigned short int *pDspSwVersion // DSP software version ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /* gpakSerialTxFixedValue return status values */ typedef enum { TfvSuccess = 0, /* operation successful */ TfvInvalidChannel = 1, /* invalid channel identifier */ TfvInvalidDsp = 2, /* invalid DSP identifier */ TfvDspCommFailure = 3 /* failed to communicate with DSP */ } gpakSerialTxFixedValueStat_t; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakSerialTxFixedValue - transmit a fixed value on a timeslot * * FUNCTION * This function controls transmission of a fixed value out onto a serial * port's timeslot. * * RETURNS * Status code indicating success or a specific error. */ extern gpakSerialTxFixedValueStat_t gpakSerialTxFixedValue( unsigned short int DspId, // DSP identifier unsigned short int ChannelId, // channel identifier GpakSerialPort_t PcmOutPort, // PCM Output Serial Port Id unsigned short int PcmOutSlot, // PCM Output Time Slot unsigned short int Value, // 16-bit value GpakActivation State // activation state ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /* gpakControlTdmLoopBack return status values */ typedef enum { ClbSuccess = 0, /* operation successful */ ClbSerPortInactive = 1, /* serial port is inactive */ ClbInvalidDsp = 2, /* invalid DSP identifier */ ClbDspCommFailure = 3 /* failed to communicate with DSP */ } gpakControlTdmLoopBackStat_t; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakControlTdmLoopBack - control a serial port's loopback state * * FUNCTION * This function enables/disables the tdm input to output looback mode on a * serial port * * RETURNS * Status code indicating success or a specific error. */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ gpakControlTdmLoopBackStat_t gpakControlTdmLoopBack( unsigned short int DspId, // DSP identifier GpakSerialPort_t SerialPort, // Serial Port Id GpakActivation LoopBackState // Loopback State ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /* gpakReadCpuUsage return status values */ typedef enum { RcuSuccess = 0, /* operation successful */ RcuInvalidDsp = 1, /* invalid DSP identifier */ RcuDspCommFailure = 2 /* communication failure */ } gpakReadCpuUsageStat_t; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadCpuUsage - read the cpu usage statistics * * FUNCTION * This function reads cpu utilization from the DSP. * * RETURNS * Status code indicating success or a specific error. */ extern gpakReadCpuUsageStat_t gpakReadCpuUsage( unsigned short int DspId, // DSP identifier unsigned short int *pPeakUsage, // pointer to peak usage variable unsigned short int *pPrev1SecPeakUsage // peak usage over previous 1 second ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /* gpakResetCpuUsageStats return status values */ typedef enum { RstcSuccess = 0, /* operation successful */ RstcInvalidDsp = 1, /* invalid DSP identifier */ RstcDspCommFailure = 2 /* communication failure */ } gpakResetCpuUsageStat_t; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakResetCpuUsageStats - reset the cpu usage statistics * * FUNCTION * This function resets the cpu utilization statistics * * RETURNS * Status code indicating success or a specific error. */ extern gpakResetCpuUsageStat_t gpakResetCpuUsageStats( unsigned short int DspId // DSP identifier ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /* gpakReadFramingStats return status values */ typedef enum { RfsSuccess = 0, /* operation successful */ RfsInvalidDsp = 1, /* invalid DSP identifier */ RfsDspCommFailure = 2 /* communication failure */ } gpakReadFramingStatsStatus_t; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadFramingStats * * FUNCTION * This function reads a DSP's framing interrupt statistics * * RETURNS * Status code indicating success or a specific error. */ extern gpakReadFramingStatsStatus_t gpakReadFramingStats( unsigned short int DspId, // DSP identifier unsigned short int *pFramingError1Count, // port 1 Framing error count unsigned short int *pFramingError2Count, // port 2 Framing error count unsigned short int *pFramingError3Count, // port 3 Framing error count unsigned short int *pDmaStopErrorCount, // DMA-stoppage error count unsigned short int *pDmaSlipStatsBuffer // DMA slips count ); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /* gpakResetFramingStats return values */ typedef enum { RstfSuccess = 0, /* operation successful */ RstfInvalidDsp = 1, /* invalid DSP identifier */ RstfDspCommFailure = 2 /* communication failure */ } gpakResetFramingStatsStatus_t; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakResetFramingStats - reset a DSP's framing interrupt statistics * * FUNCTION * This function resets a DSP's framing interrupt statistics * * RETURNS * Status code indicating success or a specific error. */ extern gpakResetFramingStatsStatus_t gpakResetFramingStats( unsigned short int DspId // DSP identifier ); typedef enum { RmmSuccess =0, RmmInvalidDsp = 1, RmmSizeTooBig = 2, RmmFailure = 3, RmmInvalidAddress = 4 } gpakReadDSPMemoryStat_t; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakResetFramingStats - read a section of DSP memory * to get access DSP registers, since 0x00--0x60 not HPI-accessable * * FUNCTION * This function resets a DSP's framing interrupt statistics * * RETURNS * Status code indicating success or a specific error. */ extern gpakReadDSPMemoryStat_t gpakReadDSPMemoryMap( unsigned short int DspId, // Dsp Identifier unsigned short int *pDest, // Buffer on host to hold DSP memory map DSP_ADDRESS BufrBaseAddress, // DSP memory users want to read out unsigned short int MemoryLength_Word16 // Length of memory section read out, unit is 16-bit word ); typedef enum { GPIOSuccess =0, GPIOInvalidDsp = 1, GPIODspCommFailure = 2 }gpakAccessGPIOStat_t; extern gpakAccessGPIOStat_t gpakAccessGPIO( unsigned short int DspId, // DSP identifier GpakGPIOCotrol_t gpakControlGPIO,// select oeration, changeDIR/write/read unsigned short int *pGPIOValue // pointer for the read/write value or DIR mask ); /* gpakWriteSystemParms return status. */ typedef enum { WspSuccess = 0, /* System Parameters written successfully */ WspParmError = 1, /* Write System Parms's Parameter error */ WspInvalidDsp = 2, /* invalid DSP */ WspDspCommFailure = 3 /* failed to communicate with DSP */ } gpakWriteSysParmsStatus_t; /* Definition of a System Parameters information structure. */ typedef struct { /* DTMF Parameters */ short int MinSigLevel; /* 0 = Disabled, Min Sig Power Level for detection */ short int SNRFlag; /* 0 = Disabled, relax SNR tolerances */ short int FreqDeviation; /* 0 = Disabled, X Percent Deviation times 10 (e.g. 1.7% is entered as 17) */ short int DtmfFwdTwist; /* 0 to 8 db */ short int DtmfRevTwist; /* 0 to 8 db */ short int DtmfValidityMask; /* This flag allows users to relax the trailing conditions of the tone */ } GpakSystemParms_t; /* gpakReadSystemParms return status. */ typedef enum { RspSuccess = 0, /* System Parameters read successfully */ RspInvalidDsp = 1, /* invalid DSP */ RspDspCommFailure = 2 /* failed to communicate with DSP */ } gpakReadSysParmsStatus_t; extern gpakReadSysParmsStatus_t gpakReadSystemParms( unsigned short int DspId, // DSP identifier GpakSystemParms_t *pSysParms /* pointer to System Parms info var */ ); extern gpakWriteSysParmsStatus_t gpakWriteSystemParms( unsigned short int DspId, // DSP identifier GpakSystemParms_t *pSysParms, /* pointer to System Parms info var */ unsigned short int UpdateBits, /* input: flags indicating which parms to update */ GPAK_SysParmsStat_t *pStatus /* pointer to Write System Parms Status */ ); #endif // end multiple inclusion dahdi-linux-2.2.0-rc4/drivers/dahdi/voicebus/vpmadtreg.h0000644000175000017500000000214411176111367022366 0ustar maniacmaniac/* * vpmadtreg.h - Registration utility for firmware loaders. * * Allows drivers for boards that host VPMAD032 modules to initiate firmware * loads. * * Written by Digium Incorporated * * Copyright (C) 2008-2009 Digium, Inc. All rights reserved. * * See http://www.asterisk.org for more information about the Asterisk * project. Please do not directly contact any of the maintainers of this * project for assistance; the project provides a web site, mailing lists and * IRC channels for your use. * * This program is free software, distributed under the terms of the GNU * General Public License Version 2 as published by the Free Software * Foundation. See the LICENSE file included with this program for more * details. */ #ifndef __VPMADTREG_H__ #define __VPMADTREG_H__ struct vpmadt032; struct voicebus; struct vpmadt_loader { struct module *owner; struct list_head node; int (*load)(struct voicebus *); }; int vpmadtreg_register(struct vpmadt_loader *loader); int vpmadtreg_unregister(struct vpmadt_loader *loader); int vpmadtreg_loadfirmware(struct voicebus *vb); #endif dahdi-linux-2.2.0-rc4/drivers/dahdi/voicebus/GpakApi.c0000644000175000017500000016373611176111367021723 0ustar maniacmaniac/* * Copyright (c) 2005, Adaptive Digital Technologies, Inc. * * File Name: GpakApi.c * * Description: * This file contains user API functions to communicate with DSPs executing * G.PAK software. The file is integrated into the host processor connected * to C55X G.PAK DSPs via a Host Port Interface. * * Version: 1.0 * * Revision History: * 06/15/05 - Initial release. * 11/15/2006 - 24 TDM-TDM Channels EC release * * This program has been released under the terms of the GPL version 2 by * permission of Adaptive Digital Technologies, Inc. * */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ #include "GpakHpi.h" #include "GpakCust.h" #include "GpakApi.h" #include "gpakenum.h" /* DSP to Host interface block offsets. */ #define REPLY_MSG_PNTR_OFFSET 0 /* I/F blk offset to Reply Msg Pointer */ #define CMD_MSG_PNTR_OFFSET 2 /* I/F blk offset to Command Msg Pointer */ #define EVENT_MSG_PNTR_OFFSET 4 /* I/F blk offset to Event Msg Pointer */ #define PKT_BUFR_MEM_OFFSET 6 /* I/F blk offset to Packet Buffer memory */ #define DSP_STATUS_OFFSET 8 /* I/F blk offset to DSP Status */ #define VERSION_ID_OFFSET 9 /* I/F blk offset to G.PAK Version Id */ #define MAX_CMD_MSG_LEN_OFFSET 10 /* I/F blk offset to Max Cmd Msg Length */ #define CMD_MSG_LEN_OFFSET 11 /* I/F blk offset to Command Msg Length */ #define REPLY_MSG_LEN_OFFSET 12 /* I/F blk offset to Reply Msg Length */ #define NUM_CHANNELS_OFFSET 13 /* I/F blk offset to Num Built Channels */ #define NUM_PKT_CHANNELS_OFFSET 14 /* I/F blk offset to Num Pkt Channels */ #define NUM_CONFERENCES_OFFSET 15 /* I/F blk offset to Num Conferences */ //#define CPU_USAGE_OFFSET_1MS 16 /* I/F blk offset to CPU Usage statistics */ #define CPU_USAGE_OFFSET 18 /* I/F blk offset to CPU Usage statistics */ //#define CPU_USAGE_OFFSET_10MS 20 /* I/F blk offset to CPU Usage statistics */ #define FRAMING_STATS_OFFSET 22 /* I/F blk offset to Framing statistics */ //#define GPAK_RELEASE_Rate rate10ms // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = // Macro to reconstruct a 32-bit value from two 16-bit values. // Parameter p32: 32-bit-wide destination // Parameter p16: 16-bit-wide source array of length 2 words #define RECONSTRUCT_LONGWORD(p32, p16) p32 = (DSP_ADDRESS)p16[0]<<16; \ p32 |= (unsigned long)p16[1] // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = /* DSP Status value definitions. */ #define DSP_INIT_STATUS 0x5555 /* DSP Initialized status value */ #define HOST_INIT_STATUS 0xAAAA /* Host Initialized status value */ /* Circular packet buffer information structure offsets. */ #define CB_BUFR_BASE 0 /* pointer to base of circular buffer */ #define CB_BUFR_SIZE 2 /* size of buffer (words) */ #define CB_BUFR_PUT_INDEX 3 /* offset in buffer for next write */ #define CB_BUFR_TAKE_INDEX 4 /* offset in buffer for next read */ #define CIRC_BUFFER_INFO_STRUCT_SIZE 6 /* Miscellaneous definitions. */ #define MSG_BUFFER_SIZE 100 /* size (words) of Host msg buffer */ #define WORD_BUFFER_SIZE 84 /* size of DSP Word buffer (words) */ #ifdef __TMS320C55XX__ // debug sections if not on host #pragma DATA_SECTION(pDspIfBlk,"GPAKAPIDEBUG_SECT") #pragma DATA_SECTION(MaxCmdMsgLen,"GPAKAPIDEBUG_SECT") #pragma DATA_SECTION(MaxChannels,"GPAKAPIDEBUG_SECT") #pragma DATA_SECTION(DlByteBufr,"GPAKAPIDEBUG_SECT") #pragma DATA_SECTION(DlWordBufr,"GPAKAPIDEBUG_SECT") #pragma DATA_SECTION(pEventFifoAddress,"GPAKAPIDEBUG_SECT") #endif /* Host variables related to Host to DSP interface. */ static DSP_ADDRESS pDspIfBlk[MAX_DSP_CORES]; /* DSP address of I/F block */ static DSP_WORD MaxCmdMsgLen[MAX_DSP_CORES]; /* max Cmd msg length (octets) */ static unsigned short int MaxChannels[MAX_DSP_CORES]; /* max num channels */ //static unsigned short int MaxPktChannels[MAX_DSP_CORES]; /* max num pkt channels */ //static unsigned short int MaxConfs[MAX_DSP_CORES]; /* max num conferences */ //static DSP_ADDRESS pPktInBufr[MAX_DSP_CORES][MAX_PKT_CHANNELS]; /* Pkt In buffer */ //static DSP_ADDRESS pPktOutBufr[MAX_DSP_CORES][MAX_PKT_CHANNELS]; /* Pkt Out buffer */ static DSP_ADDRESS pEventFifoAddress[MAX_DSP_CORES]; /* event fifo */ static unsigned char DlByteBufr[DOWNLOAD_BLOCK_SIZE * 2]; /* Dowload byte buf */ static DSP_WORD DlWordBufr[DOWNLOAD_BLOCK_SIZE]; /* Dowload word buffer */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * CheckDspReset - Check if the DSP was reset. * * FUNCTION * This function determines if the DSP was reset and is ready. If reset * occurred, it reads interface parameters and calculates DSP addresses. * * RETURNS * -1 = DSP is not ready. * 0 = Reset did not occur. * 1 = Reset occurred. * */ static int CheckDspReset( int DspId /* DSP Identifier (0 to MaxDSPCores-1) */ ) { DSP_ADDRESS IfBlockPntr; /* Interface Block pointer */ DSP_WORD DspStatus; /* DSP Status */ DSP_WORD DspChannels; /* number of DSP channels */ DSP_WORD Temp[2]; /* Read the pointer to the Interface Block. */ gpakReadDspMemory(DspId, DSP_IFBLK_ADDRESS, 2, Temp); RECONSTRUCT_LONGWORD(IfBlockPntr, Temp); /* If the pointer is zero, return with an indication the DSP is not ready. */ if (IfBlockPntr == 0) return (-1); /* Read the DSP's Status. */ gpakReadDspMemory(DspId, IfBlockPntr + DSP_STATUS_OFFSET, 1, &DspStatus); /* If status indicates the DSP was reset, read the DSP's interface parameters and calculate DSP addresses. */ if (DspStatus == DSP_INIT_STATUS || ((DspStatus == HOST_INIT_STATUS) && (pDspIfBlk[DspId] == 0))) { /* Save the address of the DSP's Interface Block. */ pDspIfBlk[DspId] = IfBlockPntr; /* Read the DSP's interface parameters. */ gpakReadDspMemory(DspId, IfBlockPntr + MAX_CMD_MSG_LEN_OFFSET, 1, &(MaxCmdMsgLen[DspId])); /* read the number of configured DSP channels */ gpakReadDspMemory(DspId, IfBlockPntr + NUM_CHANNELS_OFFSET, 1, &DspChannels); if (DspChannels > MAX_CHANNELS) MaxChannels[DspId] = MAX_CHANNELS; else MaxChannels[DspId] = (unsigned short int) DspChannels; /* read the pointer to the event fifo info struct */ gpakReadDspMemory(DspId, IfBlockPntr + EVENT_MSG_PNTR_OFFSET, 2, Temp); RECONSTRUCT_LONGWORD(pEventFifoAddress[DspId], Temp); /* Set the DSP Status to indicate the host recognized the reset. */ DspStatus = HOST_INIT_STATUS; gpakWriteDspMemory(DspId, IfBlockPntr + DSP_STATUS_OFFSET, 1, &DspStatus); /* Return with an indication that a reset occurred. */ return (1); } /* If status doesn't indicate the host recognized a reset, return with an indication the DSP is not ready. */ if ((DspStatus != HOST_INIT_STATUS) || (pDspIfBlk[DspId] == 0)) return (-1); /* Return with an indication that a reset did not occur. */ return (0); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * WriteDspCmdMessage - Write a Host Command/Request message to DSP. * * FUNCTION * This function writes a Host Command/Request message into DSP memory and * informs the DSP of the presence of the message. * * RETURNS * -1 = Unable to write message (msg len or DSP Id invalid or DSP not ready) * 0 = Temporarily unable to write message (previous Cmd Msg busy) * 1 = Message written successfully * */ static int WriteDspCmdMessage( int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ DSP_WORD *pMessage, /* pointer to Command message */ DSP_WORD MsgLength /* length of message (octets) */ ) { DSP_WORD CmdMsgLength; /* current Cmd message length */ DSP_WORD Temp[2]; DSP_ADDRESS BufferPointer; /* message buffer pointer */ /* Check if the DSP was reset and is ready. */ if (CheckDspReset(DspId) == -1) return (-1); /* Make sure the message length is valid. */ if ((MsgLength < 1) || (MsgLength > MaxCmdMsgLen[DspId])) return (-1); /* Make sure a previous Command message is not in use by the DSP. */ gpakReadDspMemory(DspId, pDspIfBlk[DspId] + CMD_MSG_LEN_OFFSET, 1, &CmdMsgLength); if (CmdMsgLength != 0) return (0); /* Purge any previous Reply message that wasn't read. */ gpakWriteDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_LEN_OFFSET, 1, &CmdMsgLength); /* Copy the Command message into DSP memory. */ gpakReadDspMemory(DspId, pDspIfBlk[DspId] + CMD_MSG_PNTR_OFFSET, 2, Temp); RECONSTRUCT_LONGWORD(BufferPointer, Temp); gpakWriteDspMemory(DspId, BufferPointer, (MsgLength + 1) / 2, pMessage); /* Store the message length in DSP's Command message length (flags DSP that a Command message is ready). */ CmdMsgLength = MsgLength; gpakWriteDspMemory(DspId, pDspIfBlk[DspId] + CMD_MSG_LEN_OFFSET, 1, &CmdMsgLength); /* Return with an indication the message was written. */ return (1); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * ReadDspReplyMessage - Read a DSP Reply message from DSP. * * FUNCTION * This function reads a DSP Reply message from DSP memory. * * RETURNS * -1 = Unable to write message (msg len or DSP Id invalid or DSP not ready) * 0 = No message available (DSP Reply message empty) * 1 = Message read successfully (message and length stored in variables) * */ static int ReadDspReplyMessage( int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ DSP_WORD *pMessage, /* pointer to Reply message buffer */ DSP_WORD *pMsgLength /* pointer to msg length var (octets) */ ) { DSP_WORD MsgLength; /* message length */ DSP_ADDRESS BufferPointer; /* message buffer pointer */ DSP_WORD Temp[2]; /* Check if the DSP was reset and is ready. */ if (CheckDspReset(DspId) == -1) return (-1); /* Check if a Reply message is ready. */ gpakReadDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_LEN_OFFSET, 1, &MsgLength); if (MsgLength == 0) return (0); /* Make sure the message length is valid. */ if (MsgLength > *pMsgLength) return (-1); /* Copy the Reply message from DSP memory. */ gpakReadDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_PNTR_OFFSET, 2, Temp); RECONSTRUCT_LONGWORD(BufferPointer, Temp); gpakReadDspMemory(DspId, BufferPointer, (MsgLength + 1) / 2, pMessage); /* Store the message length in the message length variable. */ *pMsgLength = MsgLength; /* Indicate a Reply message is not ready. */ MsgLength = 0; gpakWriteDspMemory(DspId, pDspIfBlk[DspId] + REPLY_MSG_LEN_OFFSET, 1, &MsgLength); /* Return with an indication the message was read. */ return (1); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * ReadCircBuffer - Read from a DSP circular buffer. * * FUNCTION * This function reads a block of words from a DSP circular buffer. The Take * address is incremented by the number of words read adjusting for buffer * wrap. * * RETURNS * nothing * */ static void ReadCircBuffer( int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ DSP_ADDRESS BufrBaseAddress, /* address of base of circular buffer */ DSP_ADDRESS BufrLastAddress, /* address of last word in buffer */ DSP_ADDRESS *TakeAddress, /* pointer to address in buffer for read */ DSP_WORD *pWordBuffer, /* pointer to buffer for words read */ DSP_WORD NumWords /* number of words to read */ ) { DSP_WORD WordsTillEnd; /* number of words until end of buffer */ /* Determine the number of words from the start address until the end of the buffer. */ WordsTillEnd = BufrLastAddress - *TakeAddress + 1; /* If a buffer wrap will occur, read the first part at the end of the buffer followed by the second part at the beginning of the buffer. */ if (NumWords > WordsTillEnd) { gpakReadDspMemory(DspId, *TakeAddress, WordsTillEnd, pWordBuffer); gpakReadDspMemory(DspId, BufrBaseAddress, NumWords - WordsTillEnd, &(pWordBuffer[WordsTillEnd])); *TakeAddress = BufrBaseAddress + NumWords - WordsTillEnd; } /* If a buffer wrap will not occur, read all words starting at the current take address in the buffer. */ else { gpakReadDspMemory(DspId, *TakeAddress, NumWords, pWordBuffer); if (NumWords == WordsTillEnd) *TakeAddress = BufrBaseAddress; else *TakeAddress = *TakeAddress + NumWords; } return; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * VerifyReply - Verify the reply message is correct for the command sent. * * FUNCTION * This function verifies correct reply message content for the command that * was just sent. * * RETURNS * 0 = Incorrect * 1 = Correct * */ static int VerifyReply( DSP_WORD *pMsgBufr, /* pointer to Reply message buffer */ int CheckType, /* reply check type */ DSP_WORD CheckValue /* reply check value */ ) { /* Verify Channel or Conference Id. */ if (CheckType == 1) { if (((pMsgBufr[1] >> 8) & 0xFF) != CheckValue) return (0); } /* Verify Test Mode Id. */ else if (CheckType == 2) { if (pMsgBufr[1] != CheckValue) return (0); } /* Return with an indication of correct reply. */ return (1); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * TransactCmd - Send a command to the DSP and receive it's reply. * * FUNCTION * This function sends the specified command to the DSP and receives the DSP's * reply. * * RETURNS * Length of reply message (0 = Failure) * */ static unsigned int TransactCmd( int DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ DSP_WORD *pMsgBufr, /* pointer to Cmd/Reply message buffer */ DSP_WORD CmdLength, /* length of command message (octets) */ DSP_WORD ReplyType, /* required type of reply message */ DSP_WORD ReplyLength, /* required length of reply message (octets) */ int ReplyCheckType, /* reply check type */ DSP_WORD ReplyCheckValue /* reply check value */ ) { int FuncStatus; /* function status */ int LoopCount; /* wait loop counter */ DSP_WORD RcvReplyLength; /* received Reply message length */ DSP_WORD RcvReplyType; /* received Reply message type code */ DSP_WORD RetValue; /* return value */ /* Default the return value to indicate a failure. */ RetValue = 0; /* Lock access to the DSP. */ gpakLockAccess(DspId); /* Attempt to write the command message to the DSP. */ LoopCount = 0; while ((FuncStatus = WriteDspCmdMessage(DspId, pMsgBufr, CmdLength)) != 1) { if (FuncStatus == -1) break; if (++LoopCount > MAX_WAIT_LOOPS) break; gpakHostDelay(); } /* Attempt to read the reply message from the DSP if the command message was sent successfully. */ if (FuncStatus == 1) { for (LoopCount = 0; LoopCount < MAX_WAIT_LOOPS; LoopCount++) { RcvReplyLength = MSG_BUFFER_SIZE * 2; FuncStatus = ReadDspReplyMessage(DspId, pMsgBufr, &RcvReplyLength); if (FuncStatus == 1) { RcvReplyType = (pMsgBufr[0] >> 8) & 0xFF; if ((RcvReplyLength >= ReplyLength) && (RcvReplyType == ReplyType) && VerifyReply(pMsgBufr, ReplyCheckType, ReplyCheckValue)) { RetValue = RcvReplyLength; break; } else if (RcvReplyType == MSG_NULL_REPLY) break; } else if (FuncStatus == -1) break; gpakHostDelay(); } } /* Unlock access to the DSP. */ gpakUnlockAccess(DspId); /* Return the length of the reply message (0 = failure). */ return (RetValue); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakConfigurePorts - Configure a DSP's serial ports. * * FUNCTION * This function configures a DSP's serial ports. * * RETURNS * Status code indicating success or a specific error. * */ gpakConfigPortStatus_t gpakConfigurePorts( unsigned short int DspId, /* DSP Id (0 to MaxDSPCores-1) */ const GpakPortConfig_t *pPortConfig, /* pointer to Port Config info */ GPAK_PortConfigStat_t *pStatus /* pointer to Port Config Status */ ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (CpsInvalidDsp); /* Build the Configure Serial Ports message. */ MsgBuffer[0] = MSG_CONFIGURE_PORTS << 8; MsgBuffer[1] = (DSP_WORD) ((pPortConfig->SlotsSelect1 << 12) | ((pPortConfig->FirstBlockNum1 << 8) & 0x0F00) | ((pPortConfig->SecBlockNum1 << 4) & 0x00F0)); MsgBuffer[2] = (DSP_WORD) pPortConfig->FirstSlotMask1; MsgBuffer[3] = (DSP_WORD) pPortConfig->SecSlotMask1; MsgBuffer[4] = (DSP_WORD) ((pPortConfig->SlotsSelect2 << 12) | ((pPortConfig->FirstBlockNum2 << 8) & 0x0F00) | ((pPortConfig->SecBlockNum2 << 4) & 0x00F0)); MsgBuffer[5] = (DSP_WORD) pPortConfig->FirstSlotMask2; MsgBuffer[6] = (DSP_WORD) pPortConfig->SecSlotMask2; MsgBuffer[7] = (DSP_WORD) ((pPortConfig->SlotsSelect3 << 12) | ((pPortConfig->FirstBlockNum3 << 8) & 0x0F00) | ((pPortConfig->SecBlockNum3 << 4) & 0x00F0)); MsgBuffer[8] = (DSP_WORD) pPortConfig->FirstSlotMask3; MsgBuffer[9] = (DSP_WORD) pPortConfig->SecSlotMask3; MsgBuffer[10] = (DSP_WORD) (((pPortConfig->DxDelay1 << 11) & 0x0800) | ((pPortConfig->RxDataDelay1 << 9) & 0x0600) | ((pPortConfig->TxDataDelay1 << 7) & 0x0180) | ((pPortConfig->RxClockPolarity1 << 6) & 0x0040) | ((pPortConfig->TxClockPolarity1 << 5) & 0x0020) | ((pPortConfig->RxFrameSyncPolarity1 << 4) & 0x0010) | ((pPortConfig->TxFrameSyncPolarity1 << 3) & 0x0008) | ((pPortConfig->CompandingMode1 << 1) & 0x0006) | (pPortConfig->SerialWordSize1 & 0x0001)); MsgBuffer[11] = (DSP_WORD) (((pPortConfig->DxDelay2 << 11) & 0x0800) | ((pPortConfig->RxDataDelay2 << 9) & 0x0600) | ((pPortConfig->TxDataDelay2 << 7) & 0x0180) | ((pPortConfig->RxClockPolarity2 << 6) & 0x0040) | ((pPortConfig->TxClockPolarity2 << 5) & 0x0020) | ((pPortConfig->RxFrameSyncPolarity2 << 4) & 0x0010) | ((pPortConfig->TxFrameSyncPolarity2 << 3) & 0x0008) | ((pPortConfig->CompandingMode2 << 1) & 0x0006) | (pPortConfig->SerialWordSize2 & 0x0001)); MsgBuffer[12] = (DSP_WORD) (((pPortConfig->DxDelay3 << 11) & 0x0800) | ((pPortConfig->RxDataDelay3 << 9) & 0x0600) | ((pPortConfig->TxDataDelay3 << 7) & 0x0180) | ((pPortConfig->RxClockPolarity3 << 6) & 0x0040) | ((pPortConfig->TxClockPolarity3 << 5) & 0x0020) | ((pPortConfig->RxFrameSyncPolarity3 << 4) & 0x0010) | ((pPortConfig->TxFrameSyncPolarity3 << 3) & 0x0008) | ((pPortConfig->CompandingMode3 << 1) & 0x0006) | (pPortConfig->SerialWordSize3 & 0x0001)); MsgBuffer[13] = (DSP_WORD) pPortConfig->ThirdSlotMask1; MsgBuffer[14] = (DSP_WORD) pPortConfig->FouthSlotMask1; MsgBuffer[15] = (DSP_WORD) pPortConfig->FifthSlotMask1; MsgBuffer[16] = (DSP_WORD) pPortConfig->SixthSlotMask1; MsgBuffer[17] = (DSP_WORD) pPortConfig->SevenSlotMask1; MsgBuffer[18] = (DSP_WORD) pPortConfig->EightSlotMask1; MsgBuffer[19] = (DSP_WORD) pPortConfig->ThirdSlotMask2;; MsgBuffer[20] = (DSP_WORD) pPortConfig->FouthSlotMask2; MsgBuffer[21] = (DSP_WORD) pPortConfig->FifthSlotMask2;; MsgBuffer[22] = (DSP_WORD) pPortConfig->SixthSlotMask2; MsgBuffer[23] = (DSP_WORD) pPortConfig->SevenSlotMask2;; MsgBuffer[24] = (DSP_WORD) pPortConfig->EightSlotMask2; MsgBuffer[25] = (DSP_WORD) pPortConfig->ThirdSlotMask3;; MsgBuffer[26] = (DSP_WORD) pPortConfig->FouthSlotMask3; MsgBuffer[27] = (DSP_WORD) pPortConfig->FifthSlotMask3;; MsgBuffer[28] = (DSP_WORD) pPortConfig->SixthSlotMask3; MsgBuffer[29] = (DSP_WORD) pPortConfig->SevenSlotMask3;; MsgBuffer[30] = (DSP_WORD) pPortConfig->EightSlotMask3; /* Attempt to send the Configure Serial Ports message to the DSP and receive it's reply. */ if (!TransactCmd(DspId, MsgBuffer, 62, MSG_CONFIG_PORTS_REPLY, 4, 0, 0)) return (CpsDspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ *pStatus = (GPAK_PortConfigStat_t) (MsgBuffer[1] & 0xFF); if (*pStatus == Pc_Success) return (CpsSuccess); else return (CpsParmError); } EXPORT_SYMBOL(gpakConfigurePorts); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakConfigureChannel - Configure a DSP's Channel. * * FUNCTION * This function configures a DSP's Channel. * * RETURNS * Status code indicating success or a specific error. * */ gpakConfigChanStatus_t gpakConfigureChannel( unsigned short int DspId, /* DSP Id (0 to MaxDSPCores-1) */ unsigned short int ChannelId, /* Channel Id (0 to MaxChannels-1) */ GpakChanType ChannelType, /* Channel Type */ GpakChannelConfig_t *pChanConfig, /* pointer to Channel Config info */ GPAK_ChannelConfigStat_t *pStatus /* pointer to Channel Config Status */ ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ DSP_WORD MsgLength; /* message length */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (CcsInvalidDsp); /* Make sure the Channel Id is valid. */ if (ChannelId >= MaxChannels[DspId]) return (CcsInvalidChannel); /* Build the Configure Channel message based on the Channel Type. */ switch (ChannelType) { /* PCM to Packet channel type. */ case tdmToTdm: MsgBuffer[2] = (DSP_WORD) ((pChanConfig->PcmInPortA << 8) | (pChanConfig->PcmInSlotA & 0xFF)); MsgBuffer[3] = (DSP_WORD) ((pChanConfig->PcmOutPortA << 8) | (pChanConfig->PcmOutSlotA & 0xFF)); MsgBuffer[4] = (DSP_WORD) ((pChanConfig->PcmInPortB << 8) | (pChanConfig->PcmInSlotB & 0xFF)); MsgBuffer[5] = (DSP_WORD) ((pChanConfig->PcmOutPortB << 8) | (pChanConfig->PcmOutSlotB & 0xFF)); MsgBuffer[6] = (DSP_WORD) ( ((pChanConfig->FaxCngDetB <<11) & 0x0800) | ((pChanConfig->FaxCngDetA <<10) & 0x0400) | ((pChanConfig->MuteToneB << 9) & 0x0200) | ((pChanConfig->MuteToneA << 8) & 0x0100) | ((pChanConfig->FrameRate << 6) & 0x00C0) | ((pChanConfig->ToneTypesB << 5) & 0x0020) | ((pChanConfig->ToneTypesA << 4) & 0x0010) | ((pChanConfig->SoftwareCompand & 3) << 2) | (pChanConfig->EcanEnableB << 1) | (pChanConfig->EcanEnableA & 1) ); MsgBuffer[7] = (DSP_WORD) pChanConfig->EcanParametersA.EcanTapLength; MsgBuffer[8] = (DSP_WORD) pChanConfig->EcanParametersA.EcanNlpType; MsgBuffer[9] = (DSP_WORD) pChanConfig->EcanParametersA.EcanAdaptEnable; MsgBuffer[10] = (DSP_WORD) pChanConfig->EcanParametersA.EcanG165DetEnable; MsgBuffer[11] = (DSP_WORD) pChanConfig->EcanParametersA.EcanDblTalkThresh; MsgBuffer[12] = (DSP_WORD) pChanConfig->EcanParametersA.EcanNlpThreshold; MsgBuffer[13] = (DSP_WORD) pChanConfig->EcanParametersA.EcanNlpConv; MsgBuffer[14] = (DSP_WORD) pChanConfig->EcanParametersA.EcanNlpUnConv; MsgBuffer[15] = (DSP_WORD) pChanConfig->EcanParametersA.EcanNlpMaxSuppress; MsgBuffer[16] = (DSP_WORD) pChanConfig->EcanParametersA.EcanCngThreshold; MsgBuffer[17] = (DSP_WORD) pChanConfig->EcanParametersA.EcanAdaptLimit; MsgBuffer[18] = (DSP_WORD) pChanConfig->EcanParametersA.EcanCrossCorrLimit; MsgBuffer[19] = (DSP_WORD) pChanConfig->EcanParametersA.EcanNumFirSegments; MsgBuffer[20] = (DSP_WORD) pChanConfig->EcanParametersA.EcanFirSegmentLen; MsgBuffer[21] = (DSP_WORD) pChanConfig->EcanParametersB.EcanTapLength; MsgBuffer[22] = (DSP_WORD) pChanConfig->EcanParametersB.EcanNlpType; MsgBuffer[23] = (DSP_WORD) pChanConfig->EcanParametersB.EcanAdaptEnable; MsgBuffer[24] = (DSP_WORD) pChanConfig->EcanParametersB.EcanG165DetEnable; MsgBuffer[25] = (DSP_WORD) pChanConfig->EcanParametersB.EcanDblTalkThresh; MsgBuffer[26] = (DSP_WORD) pChanConfig->EcanParametersB.EcanNlpThreshold; MsgBuffer[27] = (DSP_WORD) pChanConfig->EcanParametersB.EcanNlpConv; MsgBuffer[28] = (DSP_WORD) pChanConfig->EcanParametersB.EcanNlpUnConv; MsgBuffer[29] = (DSP_WORD) pChanConfig->EcanParametersB.EcanNlpMaxSuppress; MsgBuffer[30] = (DSP_WORD) pChanConfig->EcanParametersB.EcanCngThreshold; MsgBuffer[31] = (DSP_WORD) pChanConfig->EcanParametersB.EcanAdaptLimit; MsgBuffer[32] = (DSP_WORD) pChanConfig->EcanParametersB.EcanCrossCorrLimit; MsgBuffer[33] = (DSP_WORD) pChanConfig->EcanParametersB.EcanNumFirSegments; MsgBuffer[34] = (DSP_WORD) pChanConfig->EcanParametersB.EcanFirSegmentLen; MsgBuffer[35] = (DSP_WORD) ( ((pChanConfig->EcanParametersB.EcanReconvergenceCheckEnable <<5) & 0x20) | ((pChanConfig->EcanParametersA.EcanReconvergenceCheckEnable <<4) & 0x10) | ((pChanConfig->EcanParametersB.EcanTandemOperationEnable <<3) & 0x8) | ((pChanConfig->EcanParametersA.EcanTandemOperationEnable <<2) & 0x4) | ((pChanConfig->EcanParametersB.EcanMixedFourWireMode << 1) & 0x2) | (pChanConfig->EcanParametersA.EcanMixedFourWireMode & 1) ); MsgBuffer[36] = (DSP_WORD) pChanConfig->EcanParametersA.EcanMaxDoubleTalkThres; MsgBuffer[37] = (DSP_WORD) pChanConfig->EcanParametersB.EcanMaxDoubleTalkThres; MsgLength = 76; // byte number == 38*2 break; /* Unknown (invalid) channel type. */ default: *pStatus = Cc_InvalidChannelType; return (CcsParmError); } MsgBuffer[0] = MSG_CONFIGURE_CHANNEL << 8; MsgBuffer[1] = (DSP_WORD) ((ChannelId << 8) | (ChannelType & 0xFF)); /* Attempt to send the Configure Channel message to the DSP and receive it's reply. */ if (!TransactCmd(DspId, MsgBuffer, MsgLength, MSG_CONFIG_CHAN_REPLY, 4, 1, (DSP_WORD) ChannelId)) return (CcsDspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ *pStatus = (GPAK_ChannelConfigStat_t) (MsgBuffer[1] & 0xFF); if (*pStatus == Cc_Success) return (CcsSuccess); else return (CcsParmError); } EXPORT_SYMBOL(gpakConfigureChannel); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakTearDownChannel - Tear Down a DSP's Channel. * * FUNCTION * This function tears down a DSP's Channel. * * RETURNS * Status code indicating success or a specific error. * */ gpakTearDownStatus_t gpakTearDownChannel( unsigned short int DspId, /* DSP Id (0 to MaxDSPCores-1) */ unsigned short int ChannelId, /* Channel Id (0 to MaxChannels-1) */ GPAK_TearDownChanStat_t *pStatus /* pointer to Tear Down Status */ ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (TdsInvalidDsp); /* Make sure the Channel Id is valid. */ if (ChannelId >= MaxChannels[DspId]) return (TdsInvalidChannel); /* Build the Tear Down Channel message. */ MsgBuffer[0] = MSG_TEAR_DOWN_CHANNEL << 8; MsgBuffer[1] = (DSP_WORD) (ChannelId << 8); /* Attempt to send the Tear Down Channel message to the DSP and receive it's reply. */ if (!TransactCmd(DspId, MsgBuffer, 3, MSG_TEAR_DOWN_REPLY, 4, 1, (DSP_WORD) ChannelId)) return (TdsDspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ *pStatus = (GPAK_TearDownChanStat_t) (MsgBuffer[1] & 0xFF); if (*pStatus == Td_Success) return (TdsSuccess); else return (TdsError); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakAlgControl - Control an Algorithm. * * FUNCTION * This function controls an Algorithm * * RETURNS * Status code indicating success or a specific error. * */ gpakAlgControlStat_t gpakAlgControl( unsigned short int DspId, // DSP identifier unsigned short int ChannelId, // channel identifier GpakAlgCtrl_t ControlCode, // algorithm control code GPAK_AlgControlStat_t *pStatus // pointer to return status ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (AcInvalidDsp); /* Make sure the Channel Id is valid. */ if (ChannelId >= MaxChannels[DspId]) return (AcInvalidChannel); MsgBuffer[0] = MSG_ALG_CONTROL << 8; MsgBuffer[1] = (DSP_WORD) ((ChannelId << 8) | (ControlCode & 0xFF)); /* Attempt to send the Tear Down Channel message to the DSP and receive it's reply. */ //need_reply_len; if (!TransactCmd(DspId, MsgBuffer, 4, MSG_ALG_CONTROL_REPLY, 4, 1, (DSP_WORD) ChannelId)) return (AcDspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ *pStatus = (GPAK_AlgControlStat_t) (MsgBuffer[1] & 0xFF); if (*pStatus == Ac_Success) return (AcSuccess); else return (AcParmError); } EXPORT_SYMBOL(gpakAlgControl); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadEventFIFOMessage - read from the event fifo * * FUNCTION * This function reads a single event from the event fifo if one is available * * RETURNS * Status code indicating success or a specific error. * * Notes: This function should be called in a loop until the return status * indicates that the fifo is empty. * * If the event code equals "EventLoopbackTeardownComplete", then the * contents of *pChannelId hold the coderBlockId that was assigned to * the loopback coder that was torn down. */ gpakReadEventFIFOMessageStat_t gpakReadEventFIFOMessage( unsigned short int DspId, // DSP identifier unsigned short int *pChannelId, // pointer to channel identifier GpakAsyncEventCode_t *pEventCode, // pointer to Event Code GpakAsyncEventData_t *pEventData // pointer to Event Data Struct ) { DSP_WORD WordBuffer[WORD_BUFFER_SIZE]; /* DSP words buffer */ GpakAsyncEventCode_t EventCode; /* DSP's event code */ DSP_WORD EventDataLength; /* Length of event to read */ DSP_WORD ChannelId; /* DSP's channel Id */ DSP_ADDRESS EventInfoAddress; /* address of EventFIFO info structure */ DSP_ADDRESS BufrBaseAddress; /* base address of EventFIFO buffer */ DSP_ADDRESS BufrLastAddress; /* last address of EventFIFO buffer */ DSP_ADDRESS TakeAddress; /* current take address in fifo buffer */ DSP_WORD BufrSize; /* size (in words) of event FIFO buffer */ DSP_WORD PutIndex; /* event fifo put index */ DSP_WORD TakeIndex; /* event fifo take index */ DSP_WORD WordsReady; /* number words ready for read out of event fifo */ DSP_WORD EventError; /* flag indicating error with event fifo msg */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (RefInvalidDsp); /* Lock access to the DSP. */ gpakLockAccess(DspId); /* Check if the DSP was reset and is ready. */ if (CheckDspReset(DspId) == -1) { gpakUnlockAccess(DspId); return (RefDspCommFailure); } /* Check if an event message is ready in the DSP. */ EventInfoAddress = pEventFifoAddress[DspId]; gpakReadDspMemory(DspId, EventInfoAddress, CIRC_BUFFER_INFO_STRUCT_SIZE, WordBuffer); RECONSTRUCT_LONGWORD(BufrBaseAddress, ((DSP_WORD *)&WordBuffer[CB_BUFR_BASE])); BufrSize = WordBuffer[CB_BUFR_SIZE]; PutIndex = WordBuffer[CB_BUFR_PUT_INDEX]; TakeIndex = WordBuffer[CB_BUFR_TAKE_INDEX]; if (PutIndex >= TakeIndex) WordsReady = PutIndex - TakeIndex; else WordsReady = PutIndex + BufrSize - TakeIndex; if (WordsReady < 2) { gpakUnlockAccess(DspId); return (RefNoEventAvail); } /* Read the event header from the DSP's Event FIFO. */ TakeAddress = BufrBaseAddress + TakeIndex; BufrLastAddress = BufrBaseAddress + BufrSize - 1; ReadCircBuffer(DspId, BufrBaseAddress, BufrLastAddress, &TakeAddress, WordBuffer, 2); TakeIndex += 2; if (TakeIndex >= BufrSize) TakeIndex -= BufrSize; ChannelId = (WordBuffer[0] >> 8) & 0xFF; EventCode = (GpakAsyncEventCode_t)(WordBuffer[0] & 0xFF); EventDataLength = WordBuffer[1]; EventError = 0; switch (EventCode) { case EventToneDetect: if (EventDataLength > WORD_BUFFER_SIZE) { gpakUnlockAccess(DspId); return (RefInvalidEvent); } ReadCircBuffer(DspId, BufrBaseAddress, BufrLastAddress, &TakeAddress, WordBuffer, EventDataLength); pEventData->toneEvent.ToneCode = (GpakToneCodes_t) (WordBuffer[0] & 0xFF); pEventData->toneEvent.ToneDuration = WordBuffer[1]; pEventData->toneEvent.Direction = WordBuffer[2]; pEventData->toneEvent.DebugToneStatus = WordBuffer[3]; TakeIndex += EventDataLength; if (TakeIndex >= BufrSize) TakeIndex -= BufrSize; if (EventDataLength != 4) EventError = 1; break; default: EventError = 1; break; }; /* Update the Take index in the DSP's Packet Out buffer information. */ gpakWriteDspMemory(DspId, EventInfoAddress + CB_BUFR_TAKE_INDEX, 1, &TakeIndex); /* Unlock access to the DSP. */ gpakUnlockAccess(DspId); if (EventError) return(RefInvalidEvent); *pChannelId = ChannelId; *pEventCode = EventCode; return(RefEventAvail); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakPingDsp - ping the DSP to see if it's alive * * FUNCTION * This function checks if the DSP is still communicating with the host * and returns the DSP SW version * * RETURNS * Status code indicating success or a specific error. */ gpakPingDspStat_t gpakPingDsp( unsigned short int DspId, // DSP identifier unsigned short int *pDspSwVersion // DSP software version ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ DSP_WORD DspStatus; /* DSP's reply status */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (PngInvalidDsp); /* send value of 1, DSP increments it */ MsgBuffer[0] = (MSG_PING << 8); /* Attempt to send the ping message to the DSP and receive it's reply. */ if (!TransactCmd(DspId, MsgBuffer, 1, MSG_PING_REPLY, 6, 0, 0)) return (PngDspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ DspStatus = (MsgBuffer[1] & 0xFF); if (DspStatus == 0) { *pDspSwVersion = MsgBuffer[2]; return (PngSuccess); } else return (PngDspCommFailure); } EXPORT_SYMBOL(gpakPingDsp); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakSerialTxFixedValue - transmit a fixed value on a timeslot * * FUNCTION * This function controls transmission of a fixed value out onto a serial * port's timeslot. * * RETURNS * Status code indicating success or a specific error. */ gpakSerialTxFixedValueStat_t gpakSerialTxFixedValue( unsigned short int DspId, // DSP identifier unsigned short int ChannelId, // channel identifier GpakSerialPort_t PcmOutPort, // PCM Output Serial Port Id unsigned short int PcmOutSlot, // PCM Output Time Slot unsigned short int Value, // 16-bit value GpakActivation State // activation state ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ DSP_WORD DspStatus; /* DSP's reply status */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (TfvInvalidDsp); /* Make sure the Channel Id is valid. */ if (ChannelId >= MaxChannels[DspId]) return (TfvInvalidChannel); /* Build the message. */ MsgBuffer[0] = MSG_SERIAL_TXVAL << 8; MsgBuffer[1] = (DSP_WORD) ((ChannelId << 8) | (State & 0xFF)); MsgBuffer[2] = (DSP_WORD) ((PcmOutPort << 8) | (PcmOutSlot & 0xFF)); MsgBuffer[3] = (DSP_WORD) Value; /* Attempt to send the message to the DSP and receive it's reply. */ //need_reply_len; if (!TransactCmd(DspId, MsgBuffer, 8, MSG_SERIAL_TXVAL_REPLY, 4, 1, ChannelId)) return (TfvDspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ DspStatus = (MsgBuffer[1] & 0xFF); if (DspStatus == 0) return (TfvSuccess); else return (TfvDspCommFailure); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakControlTdmLoopBack - control a serial port's loopback state * * FUNCTION * This function enables/disables the tdm input to output looback mode on a * serial port * * RETURNS * Status code indicating success or a specific error. */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ gpakControlTdmLoopBackStat_t gpakControlTdmLoopBack( unsigned short int DspId, // DSP identifier GpakSerialPort_t SerialPort, // Serial Port Id GpakActivation LoopBackState // Loopback State ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ DSP_WORD DspStatus; /* DSP's reply status */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (ClbInvalidDsp); /* Build the message. */ MsgBuffer[0] = MSG_TDM_LOOPBACK << 8; MsgBuffer[1] = (DSP_WORD) ((SerialPort << 8) | (LoopBackState & 0xFF)); /* Attempt to send the message to the DSP and receive it's reply. */ //need_reply_len; if (!TransactCmd(DspId, MsgBuffer, 4, MSG_TDM_LOOPBACK_REPLY, 4, 0, 0)) return (ClbDspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ DspStatus = (MsgBuffer[1] & 0xFF); if (DspStatus == 0) return (ClbSuccess); else return (ClbDspCommFailure); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadCpuUsage - Read CPU usage statistics from a DSP. * * FUNCTION * This function reads the CPU usage statistics from a DSP's memory. The * average CPU usage in units of .1 percent are obtained for each of the frame * rates. * * RETURNS * Status code indicating success or a specific error. * */ gpakReadCpuUsageStat_t gpakReadCpuUsage( unsigned short int DspId, // Dsp Identifier unsigned short int *pPeakUsage, // pointer to peak usage variable unsigned short int *pPrev1SecPeakUsage // peak usage over previous 1 second ) { DSP_WORD ReadBuffer[2]; /* DSP read buffer */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (RcuInvalidDsp); /* Lock access to the DSP. */ gpakLockAccess(DspId); /* Check if the DSP was reset and is ready. */ if (CheckDspReset(DspId) == -1) return (RcuDspCommFailure); /* Read the CPU Usage statistics from the DSP. */ gpakReadDspMemory(DspId, pDspIfBlk[DspId] + CPU_USAGE_OFFSET, 2, ReadBuffer); /* Unlock access to the DSP. */ gpakUnlockAccess(DspId); /* Store the usage statistics in the specified variables. */ *pPrev1SecPeakUsage = ReadBuffer[0]; *pPeakUsage = ReadBuffer[1]; /* Return with an indication the usage staistics were read successfully. */ return (RcuSuccess); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakResetCpuUsageStats - reset the cpu usage statistics * * FUNCTION * This function resets the cpu utilization statistics * * RETURNS * Status code indicating success or a specific error. */ gpakResetCpuUsageStat_t gpakResetCpuUsageStats( unsigned short int DspId // DSP identifier ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ DSP_WORD DspStatus; /* DSP's reply status */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (RstcInvalidDsp); MsgBuffer[0] = (MSG_RESET_USAGE_STATS << 8); /* Attempt to send the message to the DSP and receive it's reply. */ //need_reply_len; if (!TransactCmd(DspId, MsgBuffer, 2, MSG_RESET_USAGE_STATS_REPLY, 4, 0, 0)) return (RstcDspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ DspStatus = (MsgBuffer[1] & 0xFF); if (DspStatus == 0) return (RstcSuccess); else return (RstcDspCommFailure); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadFramingStats * * FUNCTION * This function reads a DSP's framing interrupt statistics * * RETURNS * Status code indicating success or a specific error. */ gpakReadFramingStatsStatus_t gpakReadFramingStats( unsigned short int DspId, // DSP identifier unsigned short int *pFramingError1Count, // port 1 Framing error count unsigned short int *pFramingError2Count, // port 2 Framing error count unsigned short int *pFramingError3Count, // port 3 Framing error count unsigned short int *pDmaStopErrorCount, // DMA-stoppage error count unsigned short int *pDmaSlipStatsBuffer // DMA slips count ) { DSP_WORD ReadBuffer[10]; /* DSP read buffer */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (RfsInvalidDsp); /* Lock access to the DSP. */ gpakLockAccess(DspId); /* Check if the DSP was reset and is ready. */ if (CheckDspReset(DspId) == -1) return (RfsDspCommFailure); /* Read the framing interrupt statistics from the DSP. */ gpakReadDspMemory(DspId, pDspIfBlk[DspId] + FRAMING_STATS_OFFSET, 10, ReadBuffer); /* Unlock access to the DSP. */ gpakUnlockAccess(DspId); /* Store the framing statistics in the specified variables. */ *pFramingError1Count = ReadBuffer[0]; *pFramingError2Count = ReadBuffer[1]; *pFramingError3Count = ReadBuffer[2]; *pDmaStopErrorCount = ReadBuffer[3]; if(pDmaSlipStatsBuffer != 0) // If users want to get the DMA slips count { pDmaSlipStatsBuffer[0] = ReadBuffer[4]; pDmaSlipStatsBuffer[1] = ReadBuffer[5]; pDmaSlipStatsBuffer[2] = ReadBuffer[6]; pDmaSlipStatsBuffer[3] = ReadBuffer[7]; pDmaSlipStatsBuffer[4] = ReadBuffer[8]; pDmaSlipStatsBuffer[5] = ReadBuffer[9]; } /* Return with an indication the statistics were read successfully. */ return (RfsSuccess); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakResetFramingStats - reset a DSP's framing interrupt statistics * * FUNCTION * This function resets a DSP's framing interrupt statistics * * RETURNS * Status code indicating success or a specific error. */ gpakResetFramingStatsStatus_t gpakResetFramingStats( unsigned short int DspId // DSP identifier ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ DSP_WORD DspStatus; /* DSP's reply status */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (RstfInvalidDsp); MsgBuffer[0] = (MSG_RESET_FRAME_STATS << 8); /* Attempt to send the message to the DSP and receive it's reply. */ //need_reply_len; if (!TransactCmd(DspId, MsgBuffer, 2, MSG_RESET_FRAME_STATS_REPLY, 4, 0, 0)) return (RstfDspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ DspStatus = (MsgBuffer[1] & 0xFF); if (DspStatus == 0) return (RstfSuccess); else return (RstfDspCommFailure); } /* * gpakDownloadDsp - Download a DSP's Program and initialized Data memory. * * FUNCTION * This function reads a DSP's Program and Data memory image from the * specified file and writes the image to the DSP's memory. * * RETURNS * Status code indicating success or a specific error. * */ gpakDownloadStatus_t gpakDownloadDsp( unsigned short DspId, /* DSP Identifier (0 to MaxDSPCores-1) */ GPAK_FILE_ID FileId /* G.PAK Download File Identifier */ ) { gpakDownloadStatus_t RetStatus; /* function return status */ int NumRead; /* number of file bytes read */ DSP_ADDRESS Address; /* DSP address */ unsigned int WordCount; /* number of words in record */ unsigned int NumWords; /* number of words to read/write */ unsigned int i; /* loop index / counter */ unsigned int j; /* loop index */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (GdlInvalidDsp); /* Lock access to the DSP. */ gpakLockAccess(DspId); RetStatus = GdlSuccess; while (RetStatus == GdlSuccess) { /* Read a record header from the file. */ NumRead = gpakReadFile(FileId, DlByteBufr, 6); if (NumRead == -1) { RetStatus = GdlFileReadError; break; } if (NumRead != 6) { RetStatus = GdlInvalidFile; break; } Address = (((DSP_ADDRESS) DlByteBufr[1]) << 16) | (((DSP_ADDRESS) DlByteBufr[2]) << 8) | ((DSP_ADDRESS) DlByteBufr[3]); WordCount = (((unsigned int) DlByteBufr[4]) << 8) | ((unsigned int) DlByteBufr[5]); /* Check for the End Of File record. */ if (DlByteBufr[0] == 0xFF) break; /* Verify the record is for a valid memory type. */ if ((DlByteBufr[0] != 0x00) && (DlByteBufr[0] != 0x01)) { RetStatus = GdlInvalidFile; break; } /* Read a block of words at a time from the file and write to the DSP's memory .*/ while (WordCount != 0) { if (WordCount < DOWNLOAD_BLOCK_SIZE) NumWords = WordCount; else NumWords = DOWNLOAD_BLOCK_SIZE; WordCount -= NumWords; NumRead = gpakReadFile(FileId, DlByteBufr, NumWords * 2); if (NumRead == -1) { RetStatus = GdlFileReadError; break; } if (NumRead != (NumWords * 2)) { RetStatus = GdlInvalidFile; break; } for (i = 0, j = 0; i < NumWords; i++, j += 2) DlWordBufr[i] = (((DSP_WORD) DlByteBufr[j]) << 8) | ((DSP_WORD) DlByteBufr[j + 1]); gpakWriteDspMemory(DspId, Address, NumWords, DlWordBufr); Address += ((DSP_ADDRESS) NumWords); } } /* Unlock access to the DSP. */ gpakUnlockAccess(DspId); /* Return with an indication of success or failure. */ return (RetStatus); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadCpuUsage - Read CPU usage statistics from a DSP. * * FUNCTION * This function reads the memory map register section of DSP memory. * * RETURNS * Status code indicating success or a specific error. * */ gpakReadDSPMemoryStat_t gpakReadDSPMemoryMap( unsigned short int DspId, // Dsp Identifier unsigned short int *pDest, // Buffer on host to hold DSP memory map DSP_ADDRESS BufrBaseAddress, // DSP memory users want to read out unsigned short int MemoryLength_Word16 // Length of memory section read out, unit is 16-bit word ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ DSP_WORD DspStatus; /* DSP reply's status */ int i; /* loop index / counter */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (RmmInvalidDsp); /* Verify the message buffer is large enough */ if (MSG_BUFFER_SIZE < MemoryLength_Word16 ) return (RmmSizeTooBig); MsgBuffer[0] = MSG_READ_DSP_MEMORY << 8; MsgBuffer[1] = (DSP_WORD) ((BufrBaseAddress >> 16) & 0xFFFF); MsgBuffer[2] = (DSP_WORD) (BufrBaseAddress & 0xFFFF); MsgBuffer[3] = (DSP_WORD) MemoryLength_Word16; /* Attempt to send the Read memory section message to the DSP and receive it's reply. */ //need_reply_len; if (!TransactCmd(DspId, MsgBuffer, 8, MSG_READ_DSP_MEMORY_REPLY, (MemoryLength_Word16+2)*2, 0, 0) ) return (RmmInvalidAddress); /* Return with an indication of success or failure based on the return status in the reply message. */ DspStatus = (MsgBuffer[1] & 0xFF); if (DspStatus != 0) return (RmmFailure); for (i = 0; i < MemoryLength_Word16; i++) pDest[i] = (short int) MsgBuffer[2 + i]; return (RmmSuccess); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakAccessGPIO - change Direction/read/write the GPIO on DSP * * FUNCTION * This function read/write GPIO and change the GPIO direction * * * RETURNS * Status code indicating success or a specific error. */ gpakAccessGPIOStat_t gpakAccessGPIO( unsigned short int DspId, // DSP identifier GpakGPIOCotrol_t gpakControlGPIO,// select oeration, changeDIR/write/read unsigned short int *pGPIOValue // DSP software version ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ DSP_WORD DspStatus; /* DSP's reply status */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (GPIOInvalidDsp); /* send value of 1, DSP increments it */ MsgBuffer[0] = (MSG_ACCESSGPIO << 8); MsgBuffer[1] = (DSP_WORD) ((gpakControlGPIO << 8) | (*pGPIOValue & 0xFF) ); /* Attempt to send the ping message to the DSP and receive it's reply. */ if (!TransactCmd(DspId, MsgBuffer, 4, MSG_ACCESSGPIO_REPLY, 6, 0, 0)) return (GPIODspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ DspStatus = (MsgBuffer[1] & 0xFF); if (DspStatus == 0) { *pGPIOValue = MsgBuffer[2]; return (GPIOSuccess); } else return (GPIODspCommFailure); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakWriteSystemParms - Write a DSP's System Parameters. * * FUNCTION * This function writes a DSP's System Parameters information. * * Note: * Or-together the desired bit-mask #defines that are listed below. Only * those algorithm parameters whose bit-mask is selected in the UpdateBits * function parameter will be updated. * * RETURNS * Status code indicating success or a specific error. * */ gpakWriteSysParmsStatus_t gpakWriteSystemParms( unsigned short int DspId, // DSP identifier GpakSystemParms_t *pSysParms, /* pointer to System Parms info var */ unsigned short int UpdateBits, /* input: flags indicating which parms to update */ GPAK_SysParmsStat_t *pStatus /* pointer to Write System Parms Status */ ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ DSP_WORD DspStatus; /* DSP's reply status */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (WspInvalidDsp); /* Build the Write System Parameters message. */ MsgBuffer[0] = MSG_WRITE_SYS_PARMS << 8; if (UpdateBits & DTMF_UPDATE_MASK) { MsgBuffer[1] |= DTMF_UPDATE_MASK; MsgBuffer[8] = (DSP_WORD) pSysParms->MinSigLevel; MsgBuffer[9] = (DSP_WORD) (pSysParms->FreqDeviation & 0xff); if (pSysParms->SNRFlag) MsgBuffer[9] |= (1<<8); } MsgBuffer[10] = (DSP_WORD) 0; if (UpdateBits & DTMF_TWIST_UPDATE_MASK) { MsgBuffer[1] |= DTMF_TWIST_UPDATE_MASK; MsgBuffer[10] |= (DSP_WORD) (pSysParms->DtmfFwdTwist & 0x000f); MsgBuffer[10] |= (DSP_WORD) ((pSysParms->DtmfRevTwist << 4) & 0x00f0); } if (UpdateBits & DTMF_VALID_MASK) { MsgBuffer[1] |= DTMF_VALID_MASK; MsgBuffer[11] = (DSP_WORD) (pSysParms->DtmfValidityMask & 0x00ff); } /* Attempt to send the ping message to the DSP and receive it's reply. */ if (!TransactCmd(DspId, MsgBuffer, 24, MSG_WRITE_SYS_PARMS_REPLY, 6, 0, 0)) return (WspDspCommFailure); /* Return with an indication of success or failure based on the return status in the reply message. */ *pStatus = (GPAK_SysParmsStat_t) (MsgBuffer[2] ); DspStatus = (MsgBuffer[1] & 0xFF); if (DspStatus == 0) return (WspSuccess); else return (WspDspCommFailure); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadSystemParms - Read a DSP's System Parameters. * * FUNCTION * This function reads a DSP's System Parameters information. * * RETURNS * Status code indicating success or a specific error. * */ gpakReadSysParmsStatus_t gpakReadSystemParms( unsigned short int DspId, // DSP identifier GpakSystemParms_t *pSysParms /* pointer to System Parms info var */ ) { DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */ /* Make sure the DSP Id is valid. */ if (DspId >= MAX_DSP_CORES) return (RspInvalidDsp); /* Build the Read System Parameters message. */ MsgBuffer[0] = MSG_READ_SYS_PARMS << 8; /* Attempt to send the ping message to the DSP and receive it's reply. */ if (!TransactCmd(DspId, MsgBuffer, 2, MSG_READ_SYS_PARMS_REPLY, 22, 0, 0)) return (RspDspCommFailure); /* Extract the System Parameters information from the message. */ pSysParms->DtmfValidityMask = (short int)(MsgBuffer[7]) ; pSysParms->MinSigLevel = (short int)MsgBuffer[8]; pSysParms->SNRFlag = (short int)((MsgBuffer[9]>>8) & 0x1); pSysParms->FreqDeviation = (short int)(MsgBuffer[9] & 0xff); pSysParms->DtmfFwdTwist = (short int)MsgBuffer[10] & 0x000f; pSysParms->DtmfRevTwist = (short int)(MsgBuffer[10] >> 4) & 0x000f; /* Return with an indication that System Parameters info was obtained. */ return (RspSuccess); } dahdi-linux-2.2.0-rc4/drivers/dahdi/voicebus/gpakenum.h0000644000175000017500000001333511176111367022210 0ustar maniacmaniac/* * Copyright (c) 2005, Adaptive Digital Technologies, Inc. * * File Name: gpakenum.h * * Description: * This file contains common enumerations related to G.PAK application * software. * * Version: 1.0 * * Revision History: * 06/15/05 - Initial release. * * This program has been released under the terms of the GPL version 2 by * permission of Adaptive Digital Technologies, Inc. * */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ #ifndef _GPAKENUM_H /* prevent multiple inclusion */ #define _GPAKENUM_H /* G.PAK Serial Port Word Size */ typedef enum { SerWordSize8 = 0, // 8-bit seial word SerWordSize16 = 1 // 16-bit serial word } GpakSerWordSize_t; /* G.PAK Serial Port FrameSync Polarity */ typedef enum { FrameSyncActLow = 0, // active low frame sync signal FrameSyncActHigh = 1 // active high frame sync signal } GpakSerFrameSyncPol_t; /* G.PAK Serial Port Clock Polarity */ typedef enum { SerClockActLow = 0, // active low serial clock SerClockActHigh = 1 // active high serial clock } GpakSerClockPol_t; /* G.PAK Serial Port Data Delay */ typedef enum { DataDelay0 = 0, // no data delay DataDelay1 = 1, // 1-bit data delay DataDelay2 = 2 // 2-bit data delay } GpakSerDataDelay_t; /* G.PAK Serial Port Ids. */ typedef enum { SerialPortNull = 0, // null serial port SerialPort1 = 1, // first PCM serial stream port (McBSP0) SerialPort2 = 2, // second PCM serial stream port (McBSP1) SerialPort3 = 3 // third PCM serial stream port (McBSP2) } GpakSerialPort_t; /* G.PAK serial port Slot Configuration selection codes. */ typedef enum { SlotCfgNone = 0, // no time slots used SlotCfg2Groups = 2, // 2 groups of 16 time slots used, 32 Channels system SlotCfg8Groups = 8 // 8-partition mode for 128-channel system } GpakSlotCfg_t; /* G.PAK serial port Companding Mode codes. */ typedef enum { cmpPCMU=0, // u-Law cmpPCMA=1, // A-Law cmpNone=2 // none } GpakCompandModes; /* G.PAK Active/Inactive selection codes. */ typedef enum { Disabled=0, // Inactive Enabled=1 // Active } GpakActivation; /* G.PAK Channel Type codes. */ typedef enum { inactive=0, // channel inactive tdmToTdm=1 // tdmToTdm } GpakChanType; /* G.PAK Algorithm control commands */ typedef enum { EnableEcanA = 0, // Enable A side echo canceller BypassEcanA = 1, // Bypass A side echo canceller ResetEcanA = 2, // Reset A side echo canceller EnableEcanB = 3, // Enable B side echo canceller BypassEcanB = 4, // Bypass B side echo canceller ResetEcanB = 5, // Reset B side echo canceller EnableMuLawSwCompanding = 6,// Enable Mu-law Software companding EnableALawSwCompanding = 7, // Enable Mu-law Software companding BypassSwCompanding = 8, // Bypass Software companding EnableDTMFMuteA = 9, // Mute A side Dtmf digit after tone detected DisableDTMFMuteA = 10, // Do not mute A side Dtmf digit once tone detected EnableDTMFMuteB = 11, // Mute B side Dtmf digit after tone detected DisableDTMFMuteB = 12, // Do not mute B side Dtmf digit once tone detected EnableFaxCngDetectA = 13, // Enable A side Fax CNG detector, channel must be configed already DisableFaxCngDetectA = 14, // Disable A side Fax CNG detector, channel must be configed already EnableFaxCngDetectB = 15, // Enable B side Fax CNG detector, channel must be configed already DisableFaxCngDetectB = 16 // Disable B side Fax CNG detector, channel must be configed already } GpakAlgCtrl_t; /* G.PAK Tone types. */ typedef enum { Null_tone = 0, // no tone detection DTMF_tone = 1 // DTMF tone } GpakToneTypes; /* G.PAK direction. */ typedef enum { TDMAToB = 0, // A to B TDMBToA = 1 // B to A } GpakTdmDirection; typedef enum { rate1ms=0, rate2ms=1, rate10ms=2 } GpakRate_t; /* G.PAK Asynchronous Event Codes */ typedef enum { EventToneDetect = 0, // Tone detection event EventDSPDebug = 7 // DSP debug data event } GpakAsyncEventCode_t; /* G.PAK MF Tone Code Indices */ typedef enum { DtmfDigit1 = 0, // DTMF Digit 1 DtmfDigit2 = 1, // DTMF Digit 2 DtmfDigit3 = 2, // DTMF Digit 3 DtmfDigitA = 3, // DTMF Digit A DtmfDigit4 = 4, // DTMF Digit 4 DtmfDigit5 = 5, // DTMF Digit 5 DtmfDigit6 = 6, // DTMF Digit 6 DtmfDigitB = 7, // DTMF Digit B DtmfDigit7 = 8, // DTMF Digit 7 DtmfDigit8 = 9, // DTMF Digit 8 DtmfDigit9 = 10, // DTMF Digit 9 DtmfDigitC = 11, // DTMF Digit C DtmfDigitSt = 12, // DTMF Digit * DtmfDigit0 = 13, // DTMF Digit 0 DtmfDigitPnd = 14, // DTMF Digit # DtmfDigitD = 15, // DTMF Digit D FaxCngDigit = 90, // Fax Calling Tone (1100 Hz) EndofMFDigit = 100, // End of MF digit EndofCngDigit = 101 // End of Cng Digit } GpakToneCodes_t; /* GPIO control code*/ typedef enum { GPIO_READ = 0, GPIO_WRITE = 1, GPIO_DIR = 2 } GpakGPIOCotrol_t; #endif // end multiple inclusion dahdi-linux-2.2.0-rc4/drivers/dahdi/voicebus/gpakErrs.h0000644000175000017500000001421411176111367022154 0ustar maniacmaniac/* * Copyright (c) 2002 - 2004, Adaptive Digital Technologies, Inc. * * File Name: GpakErrs.h * * Description: * This file contains DSP reply status codes used by G.PAK API functions to * indicate specific errors. * * Version: 1.0 * * Revision History: * 10/17/01 - Initial release. * 07/03/02 - Updates for conferencing. * 06/15/04 - Tone type updates. * * This program has been released under the terms of the GPL version 2 by * permission of Adaptive Digital Technologies, Inc. */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ #ifndef _GPAKERRS_H /* prevent multiple inclusion */ #define _GPAKERRS_H /* Configure Serial Ports reply status codes. */ typedef enum { Pc_Success = 0, /* serial ports configured successfully */ Pc_ChannelsActive = 1, /* unable to configure while channels active */ Pc_TooManySlots1 = 2, /* too many slots selected for port 1 */ Pc_InvalidBlockCombo1 = 3, /* invalid combination of blocks for port 1 */ Pc_NoSlots1 = 4, /* no slots selected for port 1 */ Pc_InvalidSlots1 = 5, /* invalid slot (> max) selected for port 1 */ Pc_TooManySlots2 = 6, /* too many slots selected for port 2 */ Pc_InvalidBlockCombo2 = 7, /* invalid combination of blocks for port 2 */ Pc_NoSlots2 = 8, /* no slots selected for port 2 */ Pc_InvalidSlots2 = 9, /* invalid slot (> max) selected for port 2 */ Pc_TooManySlots3 = 10, /* too many slots selected for port 3 */ Pc_InvalidBlockCombo3 = 11, /* invalid combination of blocks for port 3 */ Pc_NoSlots3 = 12, /* no slots selected for port 3 */ Pc_InvalidSlots3 = 13 /* invalid slot (> max) selected for port 3 */ } GPAK_PortConfigStat_t; /* Configure Channel reply status codes. */ typedef enum { Cc_Success = 0, /* channel configured successfully */ Cc_InvalidChannelType = 1, /* invalid Channel Type */ Cc_InvalidChannel = 2, /* invalid Channel A Id */ Cc_ChannelActiveA = 3, /* Channel A is currently active */ Cc_InvalidInputPortA = 4, /* invalid Input A Port */ Cc_InvalidInputSlotA = 5, /* invalid Input A Slot */ Cc_BusyInputSlotA = 6, /* busy Input A Slot */ Cc_InvalidOutputPortA = 7, /* invalid Output A Port */ Cc_InvalidOutputSlotA = 8, /* invalid Output A Slot */ Cc_BusyOutputSlotA = 9, /* busy Output A Slot */ Cc_InvalidInputPortB = 10, /* invalid Input B Port */ Cc_InvalidInputSlotB = 11, /* invalid Input B Slot */ Cc_BusyInputSlotB = 12, /* busy Input B Slot */ Cc_InvalidPktInCodingA = 13, /* invalid Packet In A Coding */ Cc_InvalidPktOutCodingA = 14, /* invalid Packet Out A Coding */ Cc_InvalidPktInSizeA = 15, /* invalid Packet In A Frame Size */ Cc_InvalidPktOutSizeA = 16, /* invalid Packet Out A Frame Size */ Cc_ChanTypeNotConfigured = 21, /* channel type was not configured */ Cc_InsuffECResources = 22, /* insufficient ecan resources avail. */ Cc_InsuffTDMResources = 23, /* insufficient tdm block resources avail. */ Cc_InsuffPktBufResources = 25, /* insufficient pkt buffer resources avail. */ Cc_InsuffPcmBufResources = 26, /* insufficient pcm buffer resources avail. */ Cc_BadPcmEcNlpType = 30, /* invalid EC Nlp type */ Cc_BadPcmEcTapLength = 31, /* invalid EC tap length */ Cc_BadPcmEcDblTalkThresh = 32, /* invalid EC double-talk threshold */ Cc_BadPcmEcNlpThreshold = 33, /* invalid EC Nlp threshold */ Cc_BadPcmEcCngThreshold = 34, /* invalid EC Cng threshold */ Cc_BadPcmEcAdaptLimit = 35, /* invalid EC Adapt Limit */ Cc_BadPcmEcCrossCorrLim = 36, /* invalid EC Cross Correlation Limit */ Cc_BadPcmEcNumFirSegs = 37, /* invalid EC Number of FirSegments */ Cc_BadPcmEcFirSegLen = 38, /* invalid EC Fir Segment Length */ /*Cc_InvalidNumEcsEnabled = 48, */ /* more than 1 Ec enabled on channel */ Cc_InvalidFrameRate = 49, /* invalid gpak frame rate */ Cc_InvalidSoftCompand = 50, /* invalid softCompanding type */ Cc_InvalidMuteToneA = 51, /* invalid MuteToneA set, no detector */ Cc_InvalidMuteToneB = 52, /* invalid MuteToneB set, no detector */ Cc_InsuffFaxCngDetResources = 53 /* insufficient tdm block resources avail. */ } GPAK_ChannelConfigStat_t; /* Tear Down Channel reply status codes. */ typedef enum { Td_Success = 0, /* channel torn down successfully */ Td_InvalidChannel = 1, /* invalid Channel Id */ Td_ChannelNotActive = 2 /* channel is not active */ } GPAK_TearDownChanStat_t; typedef enum { Ac_Success = 0, /* algorithm control is successfull */ Ac_InvalidChannel = 1, /* invalid channel identifier */ Ac_InvalidCode = 2, /* invalid algorithm control code */ Ac_ECNotEnabled = 3, /* echo canceller was not allocated */ Ac_InvalidSoftComp = 4, /* invalid softcompanding, 'cause serial port not in companding mode */ Ac_InvalidDTMFMuteA = 5, /* A side invalid Mute, since no dtmf detector */ Ac_InvalidDTMFMuteB = 6, /* B side invalid Mute, since no dtmf detector */ Ac_InvalidFaxCngA = 7, /* A side FAXCNG detector not available */ Ac_InvalidFaxCngB = 8, /* B side FAXCNG detector not available */ Ac_InvalidSysConfig = 9 /* No new system parameters (DTMF config) wrriten yet */ } GPAK_AlgControlStat_t; /* Write System Parameters reply status codes. */ typedef enum { Sp_Success = 0, /* System Parameters written successfully */ Sp_BadTwistThresh = 29 /* invalid twist threshold */ } GPAK_SysParmsStat_t; #endif /* prevent multiple inclusion */ dahdi-linux-2.2.0-rc4/drivers/dahdi/voicebus/GpakCust.c0000644000175000017500000005170711202062373022112 0ustar maniacmaniac/* * Copyright (c) 2005, Adaptive Digital Technologies, Inc. * Copyright (c) 2005-2009, Digium Incorporated * * File Name: GpakCust.c * * Description: * This file contains host system dependent functions to support generic * G.PAK API functions. The file is integrated into the host processor * connected to C55x G.PAK DSPs via a Host Port Interface. * * Note: This file is supplied by Adaptive Digital Technologies and * modified by Digium in order to support the VPMADT032 modules. * * This program has been released under the terms of the GPL version 2 by * permission of Adaptive Digital Technologies, Inc. * */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ #include #include #include #include #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) #include #else #include #endif #include #include #include "GpakCust.h" #include "GpakApi.h" #include "adt_lec.h" #include "voicebus.h" #include "vpmadtreg.h" static rwlock_t ifacelock; static struct vpmadt032 *ifaces[MAX_DSP_CORES]; static inline struct vpmadt032 *find_iface(const unsigned short dspid) { struct vpmadt032 *ret; read_lock(&ifacelock); if (ifaces[dspid]) { ret = ifaces[dspid]; } else { ret = NULL; } read_unlock(&ifacelock); return ret; } static struct vpmadt032_cmd *vpmadt032_get_free_cmd(struct vpmadt032 *vpm) { unsigned long flags; struct vpmadt032_cmd *cmd; might_sleep(); spin_lock_irqsave(&vpm->list_lock, flags); if (list_empty(&vpm->free_cmds)) { spin_unlock_irqrestore(&vpm->list_lock, flags); cmd = kmalloc(sizeof(struct vpmadt032_cmd), GFP_KERNEL); if (unlikely(!cmd)) return NULL; memset(cmd, 0, sizeof(*cmd)); } else { cmd = list_entry(vpm->free_cmds.next, struct vpmadt032_cmd, node); list_del_init(&cmd->node); spin_unlock_irqrestore(&vpm->list_lock, flags); } init_completion(&cmd->complete); return cmd; } /* Wait for any outstanding commands to the VPMADT032 to complete */ static inline int vpmadt032_io_wait(struct vpmadt032 *vpm) { unsigned long flags; int empty; while (1) { spin_lock_irqsave(&vpm->list_lock, flags); empty = list_empty(&vpm->pending_cmds) && list_empty(&vpm->active_cmds); spin_unlock_irqrestore(&vpm->list_lock, flags); if (empty) { break; } else { msleep(1); } } return 0; } /* Issue a read command to a register on the VPMADT032. We'll get the results * later. */ static struct vpmadt032_cmd *vpmadt032_getreg_full_async(struct vpmadt032 *vpm, int pagechange, unsigned short addr) { unsigned long flags; struct vpmadt032_cmd *cmd; cmd = vpmadt032_get_free_cmd(vpm); if (!cmd) return NULL; cmd->desc = (pagechange) ? __VPM150M_RWPAGE | __VPM150M_RD : __VPM150M_RD; cmd->address = addr; cmd->data = 0; spin_lock_irqsave(&vpm->list_lock, flags); list_add_tail(&cmd->node, &vpm->pending_cmds); spin_unlock_irqrestore(&vpm->list_lock, flags); return cmd; } /* Get the results from a previous call to vpmadt032_getreg_full_async. */ int vpmadt032_getreg_full_return(struct vpmadt032 *vpm, int pagechange, u16 addr, u16 *outbuf, struct vpmadt032_cmd *cmd) { unsigned long flags; int ret = -EIO; BUG_ON(!cmd); wait_for_completion(&cmd->complete); if (cmd->desc & __VPM150M_FIN) { *outbuf = cmd->data; cmd->desc = 0; ret = 0; } /* Just throw this command back on the ready list. */ spin_lock_irqsave(&vpm->list_lock, flags); list_add_tail(&cmd->node, &vpm->free_cmds); spin_unlock_irqrestore(&vpm->list_lock, flags); return ret; } /* Read one of the registers on the VPMADT032 */ static int vpmadt032_getreg_full(struct vpmadt032 *vpm, int pagechange, u16 addr, u16 *outbuf) { struct vpmadt032_cmd *cmd; cmd = vpmadt032_getreg_full_async(vpm, pagechange, addr); if (unlikely(!cmd)) { return -ENOMEM; } return vpmadt032_getreg_full_return(vpm, pagechange, addr, outbuf, cmd); } static int vpmadt032_setreg_full(struct vpmadt032 *vpm, int pagechange, unsigned int addr, u16 data) { unsigned long flags; struct vpmadt032_cmd *cmd; cmd = vpmadt032_get_free_cmd(vpm); if (!cmd) return -ENOMEM; cmd->desc = cpu_to_le16((pagechange) ? (__VPM150M_WR|__VPM150M_RWPAGE) : __VPM150M_WR); cmd->address = cpu_to_le16(addr); cmd->data = cpu_to_le16(data); spin_lock_irqsave(&vpm->list_lock, flags); list_add_tail(&cmd->node, &vpm->pending_cmds); spin_unlock_irqrestore(&vpm->list_lock, flags); return 0; } static int vpmadt032_setpage(struct vpmadt032 *vpm, u16 addr) { addr &= 0xf; /* We do not need to set the page if we're already on the page we're * interested in. */ if (vpm->curpage == addr) return 0; else vpm->curpage = addr; return vpmadt032_setreg_full(vpm, 1, 0, addr); } static unsigned char vpmadt032_getpage(struct vpmadt032 *vpm) { unsigned short res; const int pagechange = 1; vpmadt032_getreg_full(vpm, pagechange, 0, &res); return res; } static int vpmadt032_getreg(struct vpmadt032 *vpm, unsigned int addr, u16 *data) { unsigned short res; vpmadt032_setpage(vpm, addr >> 16); res = vpmadt032_getreg_full(vpm, 0, addr & 0xffff, data); return res; } static int vpmadt032_setreg(struct vpmadt032 *vpm, unsigned int addr, u16 data) { int res; vpmadt032_setpage(vpm, addr >> 16); res = vpmadt032_setreg_full(vpm, 0, addr & 0xffff, data); return res; } static int vpmadt032_enable_ec(struct vpmadt032 *vpm, int channel) { int res; GPAK_AlgControlStat_t pstatus; GpakAlgCtrl_t control; if (vpm->span) { control = (DAHDI_LAW_ALAW == vpm->span->deflaw) ? EnableALawSwCompanding : EnableMuLawSwCompanding; } else { control = EnableMuLawSwCompanding; } printk(KERN_DEBUG "Enabling ecan on channel: %d (%s)\n", channel, ((control == EnableMuLawSwCompanding) ? "MuLaw" : "ALaw")); res = gpakAlgControl(vpm->dspid, channel, control, &pstatus); if (res) { printk(KERN_WARNING "Unable to set SW Companding on " \ "channel %d (reason %d)\n", channel, res); } res = gpakAlgControl(vpm->dspid, channel, EnableEcanA, &pstatus); return res; } static int vpmadt032_disable_ec(struct vpmadt032 *vpm, int channel) { int res; GPAK_AlgControlStat_t pstatus; printk(KERN_DEBUG "Disabling ecan on channel: %d\n", channel); res = gpakAlgControl(vpm->dspid, channel, BypassSwCompanding, &pstatus); if (res) { printk(KERN_WARNING "Unable to disable sw companding on " \ "echo cancellation channel %d (reason %d)\n", channel, res); } res = gpakAlgControl(vpm->dspid, channel, BypassEcanA, &pstatus); return res; } /** * vpmadt032_bh - Changes the echocan parameters on the vpmadt032 module. * * This function is typically scheduled to run in the workqueue by the * vpmadt032_echocan_with_params function. This is because communicating with * the hardware can take some time while messages are sent to the VPMADT032 * module and the driver waits for the responses. */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) static void vpmadt032_bh(void *data) { struct vpmadt032 *vpm = data; #else static void vpmadt032_bh(struct work_struct *data) { struct vpmadt032 *vpm = container_of(data, struct vpmadt032, work); #endif struct adt_lec_params *curstate, *desiredstate; int channel; /* Sweep through all the echo can channels on the VPMADT032 module, * looking for ones where the desired state does not match the current * state. */ for (channel = 0; channel < vpm->span->channels; channel++) { GPAK_AlgControlStat_t pstatus; int res = 1; curstate = &vpm->curecstate[channel]; desiredstate = &vpm->desiredecstate[channel]; if ((desiredstate->nlp_type != curstate->nlp_type) || (desiredstate->nlp_threshold != curstate->nlp_threshold) || (desiredstate->nlp_max_suppress != curstate->nlp_max_suppress)) { GPAK_ChannelConfigStat_t cstatus; GPAK_TearDownChanStat_t tstatus; GpakChannelConfig_t chanconfig; if (vpm->options.debug & DEBUG_ECHOCAN) printk(KERN_DEBUG "Reconfiguring chan %d for nlp %d, nlp_thresh %d, and max_supp %d\n", channel + 1, vpm->desiredecstate[channel].nlp_type, desiredstate->nlp_threshold, desiredstate->nlp_max_suppress); vpm->setchanconfig_from_state(vpm, channel, &chanconfig); res = gpakTearDownChannel(vpm->dspid, channel, &tstatus); if (res) goto vpm_bh_out; res = gpakConfigureChannel(vpm->dspid, channel, tdmToTdm, &chanconfig, &cstatus); if (res) goto vpm_bh_out; if (!desiredstate->tap_length) { res = gpakAlgControl(vpm->dspid, channel, BypassSwCompanding, &pstatus); if (res) printk("Unable to disable sw companding on echo cancellation channel %d (reason %d)\n", channel, res); res = gpakAlgControl(vpm->dspid, channel, BypassEcanA, &pstatus); } } else if (desiredstate->tap_length != curstate->tap_length) { if (desiredstate->tap_length) res = vpmadt032_enable_ec(vpm, channel); else res = vpmadt032_disable_ec(vpm, channel); } vpm_bh_out: if (!res) *curstate = *desiredstate; } return; } #include "adt_lec.c" static void vpmadt032_check_and_schedule_update(struct vpmadt032 *vpm, int channo) { int update; /* Only update the parameters if the new state of the echo canceller * is different than the current state. */ update = memcmp(&vpm->curecstate[channo], &vpm->desiredecstate[channo], sizeof(vpm->curecstate[channo])); if (update && test_bit(VPM150M_ACTIVE, &vpm->control)) { /* Since updating the parameters can take a bit of time while * the driver sends messages to the VPMADT032 and waits for * their responses, we'll push the work of updating the * parameters to a work queue so the caller can continue to * proceed with setting up the call. */ queue_work(vpm->wq, &vpm->work); } } int vpmadt032_echocan_create(struct vpmadt032 *vpm, int channo, struct dahdi_echocanparams *ecp, struct dahdi_echocanparam *p) { unsigned int ret; ret = adt_lec_parse_params(&vpm->desiredecstate[channo], ecp, p); if (ret) return ret; if (vpm->options.debug & DEBUG_ECHOCAN) printk(KERN_DEBUG "echocan: Channel is %d length %d\n", channo, ecp->tap_length); /* The driver cannot control the number of taps on the VPMADT032 * module. Instead, it uses tap_length to enable or disable the echo * cancellation. */ vpm->desiredecstate[channo].tap_length = (ecp->tap_length) ? 1 : 0; vpmadt032_check_and_schedule_update(vpm, channo); return 0; } EXPORT_SYMBOL(vpmadt032_echocan_create); void vpmadt032_echocan_free(struct vpmadt032 *vpm, struct dahdi_chan *chan, struct dahdi_echocan_state *ec) { int channo = chan->chanpos - 1; adt_lec_init_defaults(&vpm->desiredecstate[channo], 0); vpm->desiredecstate[channo].nlp_type = vpm->options.vpmnlptype; vpm->desiredecstate[channo].nlp_threshold = vpm->options.vpmnlpthresh; vpm->desiredecstate[channo].nlp_max_suppress = vpm->options.vpmnlpmaxsupp; if (vpm->options.debug & DEBUG_ECHOCAN) printk(KERN_DEBUG "echocan: Channel is %d length 0\n", channo); vpmadt032_check_and_schedule_update(vpm, channo); } EXPORT_SYMBOL(vpmadt032_echocan_free); struct vpmadt032 * vpmadt032_alloc(struct vpmadt032_options *options, const char *board_name) { struct vpmadt032 *vpm; int i; const char *suffix = "-vpm"; size_t length; might_sleep(); length = strlen(board_name) + strlen(suffix) + 1; /* Add a little extra to store the wq_name. */ vpm = kzalloc(sizeof(*vpm) + length, GFP_KERNEL); if (!vpm) return NULL; strcpy(vpm->wq_name, board_name); strcat(vpm->wq_name, suffix); /* Init our vpmadt032 struct */ memcpy(&vpm->options, options, sizeof(*options)); spin_lock_init(&vpm->list_lock); INIT_LIST_HEAD(&vpm->free_cmds); INIT_LIST_HEAD(&vpm->pending_cmds); INIT_LIST_HEAD(&vpm->active_cmds); sema_init(&vpm->sem, 1); vpm->curpage = 0x80; vpm->dspid = -1; /* Do not use the global workqueue for processing these events. Some of * the operations can take 100s of ms, most of that time spent sleeping. * On single CPU systems, this unduly serializes operations accross * multiple vpmadt032 instances. */ vpm->wq = create_singlethread_workqueue(vpm->wq_name); if (!vpm->wq) { kfree(vpm); return NULL; } /* Place this structure in the ifaces array so that the DspId from the * Gpak Library can be used to locate it. */ write_lock(&ifacelock); for (i=0; idspid = i; break; } } write_unlock(&ifacelock); if (-1 == vpm->dspid) { kfree(vpm); printk(KERN_NOTICE "Unable to initialize another vpmadt032 modules\n"); vpm = NULL; } else if (vpm->options.debug & DEBUG_ECHOCAN) { printk(KERN_DEBUG "Setting VPMADT032 DSP ID to %d\n", vpm->dspid); } return vpm; } EXPORT_SYMBOL(vpmadt032_alloc); int vpmadt032_init(struct vpmadt032 *vpm, struct voicebus *vb) { int i; u16 reg; int res = -EFAULT; gpakPingDspStat_t pingstatus; BUG_ON(!vpm->setchanconfig_from_state); BUG_ON(!vpm->wq); might_sleep(); if (vpm->options.debug & DEBUG_ECHOCAN) printk(KERN_DEBUG "VPMADT032 Testing page access: "); for (i = 0; i < 0xf; i++) { int x; for (x = 0; x < 3; x++) { vpmadt032_setpage(vpm, i); reg = vpmadt032_getpage(vpm); if (reg != i) { if (vpm->options.debug & DEBUG_ECHOCAN) printk(KERN_DEBUG "Failed: Sent %x != %x VPMADT032 Failed HI page test\n", i, reg); res = -ENODEV; goto failed_exit; } } } if (vpm->options.debug & DEBUG_ECHOCAN) printk(KERN_DEBUG "Passed\n"); set_bit(VPM150M_HPIRESET, &vpm->control); msleep(2000); while (test_bit(VPM150M_HPIRESET, &vpm->control)) msleep(1); /* Set us up to page 0 */ vpmadt032_setpage(vpm, 0); if (vpm->options.debug & DEBUG_ECHOCAN) printk(KERN_DEBUG "VPMADT032 now doing address test: "); for (i = 0; i < 16; i++) { int x; for (x = 0; x < 2; x++) { vpmadt032_setreg(vpm, 0x1000, i); vpmadt032_getreg(vpm, 0x1000, ®); if (reg != i) { printk("VPMADT032 Failed address test\n"); goto failed_exit; } } } if (vpm->options.debug & DEBUG_ECHOCAN) printk("Passed\n"); set_bit(VPM150M_HPIRESET, &vpm->control); while (test_bit(VPM150M_HPIRESET, &vpm->control)) msleep(1); res = vpmadtreg_loadfirmware(vb); if (res) { struct pci_dev *pdev = voicebus_get_pci_dev(vb); dev_printk(KERN_INFO, &pdev->dev, "Failed to load the firmware.\n"); return res; } vpm->curpage = -1; set_bit(VPM150M_SWRESET, &vpm->control); while (test_bit(VPM150M_SWRESET, &vpm->control)) msleep(1); pingstatus = gpakPingDsp(vpm->dspid, &vpm->version); if (!pingstatus) { if (vpm->options.debug & DEBUG_ECHOCAN) printk(KERN_DEBUG "Version of DSP is %x\n", vpm->version); } else { printk(KERN_NOTICE "VPMADT032 Failed! Unable to ping the DSP (%d)!\n", pingstatus); res = -1; goto failed_exit; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) INIT_WORK(&vpm->work, vpmadt032_bh, vpm); #else INIT_WORK(&vpm->work, vpmadt032_bh); #endif return 0; failed_exit: return res; } EXPORT_SYMBOL(vpmadt032_init); void vpmadt032_get_default_parameters(struct GpakEcanParms *p) { memset(p, 0, sizeof(*p)); p->EcanTapLength = 1024; p->EcanNlpType = DEFAULT_NLPTYPE; p->EcanAdaptEnable = 1; p->EcanG165DetEnable = 1; p->EcanDblTalkThresh = 6; p->EcanMaxDoubleTalkThres = 40; p->EcanNlpThreshold = DEFAULT_NLPTHRESH; p->EcanNlpConv = 0; p->EcanNlpUnConv = 12; p->EcanNlpMaxSuppress = DEFAULT_NLPMAXSUPP; p->EcanCngThreshold = 43; p->EcanAdaptLimit = 50; p->EcanCrossCorrLimit = 15; p->EcanNumFirSegments = 3; p->EcanFirSegmentLen = 48; p->EcanReconvergenceCheckEnable = 2; p->EcanTandemOperationEnable = 0; p->EcanMixedFourWireMode = 0; } EXPORT_SYMBOL(vpmadt032_get_default_parameters); void vpmadt032_free(struct vpmadt032 *vpm) { unsigned long flags; struct vpmadt032_cmd *cmd; LIST_HEAD(local_list); BUG_ON(!vpm); BUG_ON(!vpm->wq); destroy_workqueue(vpm->wq); /* Move all the commands onto the local list protected by the locks */ spin_lock_irqsave(&vpm->list_lock, flags); list_splice(&vpm->pending_cmds, &local_list); list_splice(&vpm->active_cmds, &local_list); list_splice(&vpm->free_cmds, &local_list); spin_unlock_irqrestore(&vpm->list_lock, flags); while (!list_empty(&local_list)) { cmd = list_entry(local_list.next, struct vpmadt032_cmd, node); list_del(&cmd->node); kfree(cmd); } BUG_ON(ifaces[vpm->dspid] != vpm); write_lock(&ifacelock); ifaces[vpm->dspid] = NULL; write_unlock(&ifacelock); kfree(vpm); } EXPORT_SYMBOL(vpmadt032_free); int vpmadt032_module_init(void) { rwlock_init(&ifacelock); memset(ifaces, 0, sizeof(ifaces)); return 0; } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadDspMemory - Read DSP memory. * * FUNCTION * This function reads a contiguous block of words from DSP memory starting at * the specified address. * * RETURNS * nothing * */ void gpakReadDspMemory( unsigned short int DspId, /* DSP Identifier (0 to MAX_DSP_CORES-1) */ DSP_ADDRESS DspAddress, /* DSP's memory address of first word */ unsigned int NumWords, /* number of contiguous words to read */ DSP_WORD *pWordValues /* pointer to array of word values variable */ ) { struct vpmadt032 *vpm = find_iface(DspId); int i; int ret; vpmadt032_io_wait(vpm); if ( NumWords < VPM150M_MAX_COMMANDS ) { struct vpmadt032_cmd *cmds[VPM150M_MAX_COMMANDS] = {0}; vpmadt032_setpage(vpm, DspAddress >> 16); DspAddress &= 0xffff; for (i=0; i < NumWords; ++i) { if (!(cmds[i] = vpmadt032_getreg_full_async(vpm,0,DspAddress+i))) { return; } } for (i=NumWords-1; i >=0; --i) { ret = vpmadt032_getreg_full_return(vpm,0,DspAddress+i,&pWordValues[i], cmds[i]); if (0 != ret) { return; } } } else { for (i=0; isem)) { return; } } } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakUnlockAccess - Unlock access to the specified DSP. * * FUNCTION * This function releases exclusive access to the specified DSP. * * RETURNS * nothing * */ void gpakUnlockAccess(unsigned short DspId) { struct vpmadt032 *vpm; vpm = find_iface(DspId); if (vpm) { up(&vpm->sem); } } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * gpakReadFile - Read a block of bytes from a G.PAK Download file. * * FUNCTION * This function reads a contiguous block of bytes from a G.PAK Download file * starting at the current file position. * * RETURNS * The number of bytes read from the file. * -1 indicates an error occurred. * 0 indicates all bytes have been read (end of file) * */ int gpakReadFile( GPAK_FILE_ID FileId, /* G.PAK Download File Identifier */ unsigned char *pBuffer, /* pointer to buffer for storing bytes */ unsigned int NumBytes /* number of bytes to read */ ) { /* The firmware is loaded into the part by a closed-source firmware * loader, and therefore this function should never be called. */ WARN_ON(1); return -1; } dahdi-linux-2.2.0-rc4/drivers/dahdi/voicebus/voicebus.h0000644000175000017500000000407011176111367022214 0ustar maniacmaniac/* * VoiceBus(tm) Interface Library. * * Written by Shaun Ruffell * and based on previous work by Mark Spencer , * Matthew Fredrickson , and * Michael Spiceland * * Copyright (C) 2007-2009 Digium, Inc. * * All rights reserved. * */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ #ifndef __VOICEBUS_H__ #define __VOICEBUS_H__ struct voicebus; #define VOICEBUS_DEFAULT_LATENCY 3 void voicebus_setdebuglevel(struct voicebus *vb, u32 level); int voicebus_getdebuglevel(struct voicebus *vb); struct pci_dev * voicebus_get_pci_dev(struct voicebus *vb); int voicebus_init(struct pci_dev* pdev, u32 framesize, const char *board_name, void (*handle_receive)(void *buffer, void *context), void (*handle_transmit)(void *buffer, void *context), void *context, u32 debuglevel, struct voicebus **vb_p); void voicebus_get_handlers(struct voicebus *vb, void **handle_receive, void **handle_transmit, void **context); void voicebus_set_handlers(struct voicebus *vb, void (*handle_receive)(void *buffer, void *context), void (*handle_transmit)(void *buffer, void *context), void *context); void voicebus_release(struct voicebus *vb); int voicebus_start(struct voicebus *vb); int voicebus_stop(struct voicebus *vb); void * voicebus_alloc(struct voicebus* vb); void voicebus_free(struct voicebus *vb, void *vbb); int voicebus_transmit(struct voicebus *vb, void *vbb); int voicebus_set_minlatency(struct voicebus *vb, unsigned int milliseconds); int voicebus_current_latency(struct voicebus *vb) ; #endif /* __VOICEBUS_H__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/voicebus/GpakHpi.h0000644000175000017500000000665311176111367021731 0ustar maniacmaniac/* * Copyright (c) 2001, Adaptive Digital Technologies, Inc. * * File Name: GpakHpi.h * * Description: * This file contains common definitions related to the G.PAK interface * between a host processor and a DSP processor via the Host Port Interface. * * Version: 1.0 * * Revision History: * 10/17/01 - Initial release. * * This program has been released under the terms of the GPL version 2 by * permission of Adaptive Digital Technologies, Inc. * */ /* * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2 as published by the * Free Software Foundation. See the LICENSE file included with * this program for more details. */ #ifndef _GPAKHPI_H /* prevent multiple inclusion */ #define _GPAKHPI_H /* Definition of G.PAK Command/Reply message type codes. */ #define MSG_NULL_REPLY 0 /* Null Reply (unsupported Command) */ #define MSG_SYS_CONFIG_RQST 1 /* System Configuration Request */ #define MSG_SYS_CONFIG_REPLY 2 /* System Configuration Reply */ #define MSG_READ_SYS_PARMS 3 /* Read System Parameters */ #define MSG_READ_SYS_PARMS_REPLY 4 /* Read System Parameters Reply */ #define MSG_WRITE_SYS_PARMS 5 /* Write System Parameters */ #define MSG_WRITE_SYS_PARMS_REPLY 6 /* Write System Parameters Reply */ #define MSG_CONFIGURE_PORTS 7 /* Configure Serial Ports */ #define MSG_CONFIG_PORTS_REPLY 8 /* Configure Serial Ports Reply */ #define MSG_CONFIGURE_CHANNEL 9 /* Configure Channel */ #define MSG_CONFIG_CHAN_REPLY 10 /* Configure Channel Reply */ #define MSG_TEAR_DOWN_CHANNEL 11 /* Tear Down Channel */ #define MSG_TEAR_DOWN_REPLY 12 /* Tear Down Channel Reply */ #define MSG_CHAN_STATUS_RQST 13 /* Channel Status Request */ #define MSG_CHAN_STATUS_REPLY 14 /* Channel Status Reply */ #define MSG_TEST_MODE 17 /* Configure/Perform Test Mode */ #define MSG_TEST_REPLY 18 /* Configure/Perform Test Mode Reply */ #define MSG_ALG_CONTROL 27 /* algorithm control */ #define MSG_ALG_CONTROL_REPLY 28 /* algorithm control reply */ #define MSG_GET_TXCID_ADDRESS 29 /* get tx cid buffer start address */ #define MSG_GET_TXCID_ADDRESS_REPLY 30 /* get tx cid buffer start addr reply */ #define MSG_PING 35 /* ping command */ #define MSG_PING_REPLY 36 /* ping command reply */ #define MSG_SERIAL_TXVAL 37 /* transmit serial fixed value */ #define MSG_SERIAL_TXVAL_REPLY 38 /* transmit serial fixed value reply */ #define MSG_TDM_LOOPBACK 39 /* tdm loopback control */ #define MSG_TDM_LOOPBACK_REPLY 40 /* tdm loopback control reply */ #define MSG_RESET_USAGE_STATS 41 /* reset cpu usage stats */ #define MSG_RESET_USAGE_STATS_REPLY 42 /* reset cpu usage stats reply */ #define MSG_RESET_FRAME_STATS 47 /* reset framing stats */ #define MSG_RESET_FRAME_STATS_REPLY 48 /* reset framing stats reply */ #define MSG_READ_DSP_MEMORY 49 /* read small section of DSP's memory */ #define MSG_READ_DSP_MEMORY_REPLY 50 /* read memory reply */ #define MSG_ACCESSGPIO 51 #define MSG_ACCESSGPIO_REPLY 52 #endif /* prevent multiple inclusion */ dahdi-linux-2.2.0-rc4/drivers/dahdi/voicebus/vpmadtreg.c0000644000175000017500000000162211176111367022361 0ustar maniacmaniac/* * vpmadtreg.c - Registration utility for firmware loaders. * * Allows drivers for boards that host VPMAD032 modules to initiate firmware * loads. * * Written by Digium Incorporated * * Copyright (C) 2008-2009 Digium, Inc. All rights reserved. * * See http://www.asterisk.org for more information about the Asterisk * project. Please do not directly contact any of the maintainers of this * project for assistance; the project provides a web site, mailing lists and * IRC channels for your use. * * This program is free software, distributed under the terms of the GNU * General Public License Version 2 as published by the Free Software * Foundation. See the LICENSE file included with this program for more * details. */ #include #include #include #include "voicebus.h" #include "GpakCust.h" #include "vpmadtreg.h" dahdi-linux-2.2.0-rc4/drivers/dahdi/Kconfig0000644000175000017500000001556711176111367017725 0ustar maniacmaniac# # DAHDI configuration # menuconfig DAHDI tristate "DAHDI support" select CRC_CCITT default m ---help--- DAHDI basic infrastructure. To compile this driver as a module, choose M here: the module will be called dahdi. If unsure, say Y. config DAHDI_ECHOCAN tristate "DADHI Echo Cancelers (software)" depends on DAHDI default DAHDI config DAHDI_ECHOCAN_MG2 tristate "DADHI MG2 Echo Canceler" depends on DAHDI_ECHOCAN default DAHDI_ECHOCAN ---help--- To compile this driver as a module, choose M here: the module will be called dahdi_echocancel_mg2. If unsure, say Y. config DAHDI_ECHOCAN_KB1 tristate "DADHI KB1 Echo Canceler" depends on DAHDI_ECHOCAN default DAHDI_ECHOCAN ---help--- To compile this driver as a module, choose M here: the module will be called dahdi_echocancel_kb1. If unsure, say Y. config DAHDI_ECHOCAN_SEC tristate "DADHI SEC Echo Canceler" depends on DAHDI_ECHOCAN default DAHDI_ECHOCAN ---help--- To compile this driver as a module, choose M here: the module will be called dahdi_echocancel_sec. If unsure, say Y. config DAHDI_ECHOCAN_SEC2 tristate "DADHI SEC2 Echo Canceler" depends on DAHDI_ECHOCAN default DAHDI_ECHOCAN ---help--- To compile this driver as a module, choose M here: the module will be called dahdi_echocancel_sec2. If unsure, say Y. config DAHDI_ECHOCAN_HPEC tristate "DADHI HPEC Echo Canceler" depends on DAHDI_ECHOCAN default DAHDI_ECHOCAN ---help--- To compile this driver as a module, choose M here: the module will be called dahdi_echocancel_hpec. If unsure, say Y. config DAHDI_WCTDM tristate "Digium Wildcard TDM400P Support" depends on DAHDI && PCI default DAHDI ---help--- This driver provides support for the Digium Wildcard TDM400P. To compile this driver as a module, choose M here: the module will be called wctdm. If unsure, say Y. config DAHDI_WCT4XXP tristate "Digium Wildcard dual- and quad-T1/E1/J1 Support" depends on DAHDI && PCI default DAHDI ---help--- This driver provides support for the following Digium Wildcard products: * TE205/206/207/210/211/212P (PCI/PCI-X) * TE220 (PCI-E) * TE405/406/407/410/411/412P (PCI/PCI-X) * TE420 (PCI-E) To compile this driver as a module, choose M here: the module will be called wct4xxp. If unsure, say Y. config DAHDI_TRANSCODE tristate "DAHDI transcoding support" depends on DAHDI default DAHDI ---help--- DAHDI transcoding infrastructure. To compile this driver as a module, choose M here: the module will be called dahdi_transcode. If unsure, say Y. config DAHDI_WCTC4XXP tristate "Digium Wildcard TC400B Support" depends on DAHDI_TRANSCODE && PCI default DAHDI ---help--- This driver provides support for the Digium Wildcard TC400B. To compile this driver as a module, choose M here: the module will be called wctc4xxp. If unsure, say Y. config DAHDI_VOICEBUS tristate "VoiceBus(tm) Interface Library" depends on PCI default DAHDI ---help--- This driver provides the common interface for telephony cards that use the VoiceBus(tm) interface. It also contains common supporting libraries for the VPMADT032 hardware echo cancelation module that is available for the VoiceBus cards. To compile this driver as a module, choose M here: the module will be called voicebus. If unsure, say Y. config DAHDI_WCTDM24XXP tristate "Digium Wildcard VoiceBus analog card Support" depends on DAHDI && DAHDI_VOICEBUS default DAHDI ---help--- This driver provides support for the following Digium Wildcard products: * TDM410P (PCI/PCI-X) * AEX410 (PCI-E) * TDM800P (PCI/PCI-X) * AEX800 (PCI-E) * TDM2400P (PCI/PCI-X) * AEX2400 (PCI-E) To compile this driver as a module, choose M here: the module will be called wctdm24xxp. If unsure, say Y. config DAHDI_WCTE12XP tristate "Digium Wildcard VoiceBus digital card Support" depends on DAHDI && DAHDI_VOICEBUS default DAHDI ---help--- This driver provides support for the following Digium Wildcard products: * TE120P (PCI/PCI-X) * TE121 (PCI/PCI-X) * TE122 (PCI-E) To compile this driver as a module, choose M here: the module will be called wcte12xp. If unsure, say Y. config DAHDI_PCIRADIO tristate "PCI Radio Support" depends on DAHDI && PCI default DAHDI ---help--- To compile this driver as a module, choose M here: the module will be called pciradio. If unsure, say Y. config DAHDI_DUMMY tristate "Dummy (no hardware) Timing Support" depends on DAHDI default DAHDI ---help--- This module provides timing support for applications that use DAHDI conference mixing services, pseudo channels or for other purposes. To compile this driver as a module, choose M here: the module will be called dahdi_dummy. If unsure, say Y. config DAHDI_DYNAMIC tristate "Dynamic (virtual) Span Support" depends on DAHDI default DAHDI ---help--- This module provides support for virtual spans, which are emulated or provided using various technologies. To compile this driver as a module, choose M here: the module will be called dahdi_dynamic. If unsure, say Y. config DAHDI_DYNAMIC_ETH tristate "Ethernet (TDMoE) Span Support" depends on DAHDI && DAHDI_DYNAMIC default DAHDI ---help--- This module provides support for spans over Ethernet, using the TDMoE protocol. To compile this driver as a module, choose M here: the module will be called dahdi_dynamic_eth. If unsure, say Y. config DAHDI_DYNAMIC_LOC tristate "Local (loopback) Span Support" depends on DAHDI && DAHDI_DYNAMIC default DAHDI ---help--- This module provides support for spans in the local system, primarily used for looping and monitoring other spans. To compile this driver as a module, choose M here: the module will be called dahdi_dynamic_loc. If unsure, say Y. config DAHDI_TOR2 tristate "Tormenta2 quad-port T1/E1 Support" depends on DAHDI && PCI default DAHDI ---help--- To compile this driver as a module, choose M here: the module will be called tor2. If unsure, say Y. config DAHDI_WCFXO tristate "Digium Wildcard X100P Support" depends on DAHDI && PCI default DAHDI ---help--- To compile this driver as a module, choose M here: the module will be called wcfxo. If unsure, say Y. config DAHDI_WCT1XXP tristate "Digium Wildcard T100P Support" depends on DAHDI && PCI default DAHDI ---help--- To compile this driver as a module, choose M here: the module will be called wct1xxp. If unsure, say Y. config DAHDI_WCTE11XP tristate "Digium Wildcard TE110P Support" depends on DAHDI && PCI default DAHDI ---help--- To compile this driver as a module, choose M here: the module will be called wcte11xp. If unsure, say Y. source "drivers/dahdi/xpp/Kconfig" dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/0000755000175000017500000000000011202066033017577 5ustar maniacmaniacdahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/Makefile0000644000175000017500000000224510645765316021266 0ustar maniacmaniacCFLAGS=-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) dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/apilib/0000755000175000017500000000000011202066032021036 5ustar maniacmaniacdahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/apilib/largmath/0000755000175000017500000000000011202066032022635 5ustar maniacmaniacdahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/apilib/largmath/octapi_largmath.c0000644000175000017500000004215510700513330026146 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/apilib/llman/0000755000175000017500000000000011202066032022141 5ustar maniacmaniacdahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/apilib/llman/octapi_llman.c0000644000175000017500000026256110700513330024763 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 **********************************************/ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/apilib/llman/octapi_llman_private.h0000644000175000017500000001655610700513330026523 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__*/ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/apilib/bt/0000755000175000017500000000000011202066032021443 5ustar maniacmaniacdahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/apilib/bt/octapi_bt0_private.h0000644000175000017500000000644210700513330025400 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__*/ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/apilib/bt/octapi_bt0.c0000644000175000017500000011067610700513330023646 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/octasic-helper0000755000175000017500000000177310466370541022454 0ustar maniacmaniac#!/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 dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/0000755000175000017500000000000011202066033021222 5ustar maniacmaniacdahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/apilib/0000755000175000017500000000000011202066032022461 5ustar maniacmaniacdahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/apilib/octapi_bt0.h0000644000175000017500000000660410700513330024664 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__*/ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/apilib/octapi_llman.h0000644000175000017500000002226410700513330025302 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/apilib/octapi_largmath.h0000644000175000017500000000637010700513330025776 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/octosdependant.h0000644000175000017500000001110211026017756024414 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ File: octosdependant.h Copyright (c) 2001-2007 Octasic Inc. Description: This file is included to set target-specific constants. This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The OCT6100 GPL API is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the OCT6100 GPL API; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. $Octasic_Release: OCT612xAPI-01.00-PR49 $ $Octasic_Revision: 18 $ \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ #ifndef __OCTOSDEPENDANT_H__ #define __OCTOSDEPENDANT_H__ /*-------------------------------------------------------------------------- C language ----------------------------------------------------------------------------*/ #ifdef __cplusplus extern "C" { #endif /***************************************************************************** Known define values MSDEV: WIN32 == WINDOWS 32 bit app __WIN32__ == WINDOWS 32 bit app _Windows == WINDOWS 16 bit app _WINDOWS == Windows application .. not console _DLL == Dll Application _CONSOLE == Console Application .. no windows BORLANDC __TURBOC__ == Turbo Compiler __BORLANDC__ == Borland compiler __OS2__ == Borland OS2 compiler _Windows == Windows 16 bit app GCC Compiler __GNUC__ == GCC Compiler __unix__ == Unix system __vax__ == Unix system unix == Unix system vax == vax system TORNADO _VXWORKS_ == VXWORK ECOS/CYGWIN _ECOS_ == eCos SOLARIS _SOLARIS_ == Solaris *****************************************************************************/ /* Machine endian type */ #define OCT_MACH_LITTLE_ENDIAN 1 #define OCT_MACH_BIG_ENDIAN 2 /* Try to find current OCT_MACH_ENDIAN from compiler define values */ #if !defined( MACH_TYPE_BIG_ENDIAN ) && !defined( MACH_TYPE_LITTLE_ENDIAN ) /* Does GNU defines the endian ? */ #if defined(__GNU_C__) #if defined(_BIG_ENDIAN) || defined(__BIG_ENDIAN__) #define OCT_MACH_ENDIAN OCT_MACH_BIG_ENDIAN #elif defined(_LITTLE_ENDIAN) || defined(__LITTLE_ENDIAN__) #define OCT_MACH_ENDIAN OCT_MACH_LITTLE_ENDIAN #endif #endif /* Try with cpu type */ #if !defined(OCT_MACH_ENDIAN) /* Look for intel */ #if defined( _M_IX86 ) #define OCT_MACH_ENDIAN OCT_MACH_LITTLE_ENDIAN /* Look for PowerPC */ #elif defined( _M_MPPC ) || defined( _M_PPC ) || defined(PPC) || defined(__PPC) || defined(_ARCH_PPC) #define OCT_MACH_ENDIAN OCT_MACH_BIG_ENDIAN /* Look for Blackfin */ #elif defined( __bfin__ ) #define OCT_MACH_ENDIAN OCT_MACH_LITTLE_ENDIAN #elif defined( CPU ) #if CPU==PPC860 || CPU==SIMNT #define OCT_MACH_ENDIAN OCT_MACH_BIG_ENDIAN #else #define OCT_MACH_ENDIAN OCT_MACH_LITTLE_ENDIAN #endif #else #define OCT_MACH_ENDIAN OCT_MACH_LITTLE_ENDIAN #endif #endif #else #if defined( MACH_TYPE_BIG_ENDIAN ) #define OCT_MACH_ENDIAN OCT_MACH_BIG_ENDIAN #else #define OCT_MACH_ENDIAN OCT_MACH_LITTLE_ENDIAN #endif #endif /* Find system type if not already defined */ #if !defined( OCT_NTDRVENV ) && !defined( OCT_VXENV ) && !defined( OCT_WINENV ) #if defined( WIN32 ) || defined( __WIN32__ ) || defined( _WIN32_ ) || defined( WIN32S ) /* Verif if building a win32 driver */ #if ( defined( WIN32 ) && WIN32==100 ) #define OCT_NTDRVENV #else #define OCT_WINENV #endif #elif defined( _VXWORKS_ ) #define OCT_VXENV #elif defined( _ECOS_ ) #ifndef OCT_ECOSENV #define OCT_ECOSENV #endif /* OCT_ECOSENV */ #elif defined( _SOLARIS_ ) #define OCT_SOLARISENV #elif defined( _LINUX_ ) #define OCT_LINUXENV #else /* Unknown environment */ #define OCT_UNKNOWNENV #endif /* WIN env */ #endif /* Already defined */ #if defined( __KERNEL__ ) && defined( OCT_LINUXENV ) #define OCT_LINUXDRVENV #endif #ifdef _DEBUG #define OCT_OPT_USER_DEBUG #endif /*-------------------------------------------------------------------------- C language ----------------------------------------------------------------------------*/ #ifdef __cplusplus } #endif #endif /* __OCTOSDEPENDANT_H__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/digium_unused.h0000644000175000017500000003036110553760471024256 0ustar maniacmaniac/* 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 dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/octtype.h0000644000175000017500000000770011101704446023073 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ File: octtype.h Copyright (c) 2001-2007 Octasic Inc. Description: This file defines the base storage types. This file is part of the Octasic OCT6100 GPL API . The OCT6100 GPL API is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The OCT6100 GPL API is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the OCT6100 GPL API; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. $Octasic_Release: OCT612xAPI-01.00-PR49 $ $Octasic_Revision: 18 $ \*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ #ifndef __OCTTYPE_H__ #define __OCTTYPE_H__ /*-------------------------------------------------------------------------- C language ----------------------------------------------------------------------------*/ #ifdef __cplusplus extern "C" { #endif /*-------------------------------------------------------------------------- Include target-specific header if available ----------------------------------------------------------------------------*/ #if defined( OCT_NTDRVENV ) #include "octtypentdrv.h" /* All NT driver typedef */ #elif defined( OCT_WINENV ) #include "octtypewin.h" /* All Win32 typedef */ #elif defined( OCT_VXENV ) #include "octtypevx.h" /* All VxWorks typedef */ #else /*-------------------------------------------------------------------------- No target-specific header available ----------------------------------------------------------------------------*/ #ifdef SZ #undef SZ #endif /***************************** DEFINES *************************************/ /* 16-bit integer */ typedef unsigned short UINT16; typedef signed short INT16; typedef unsigned short *PUINT16; typedef signed short *PINT16; /* 8-bit integer */ typedef unsigned char UINT8; typedef signed char INT8; typedef signed char OCT_INT8; typedef unsigned char *PUINT8; typedef signed char *PINT8; /* 32 bit integer */ typedef unsigned int UINT32; typedef signed int INT32; typedef INT32 * PINT32; typedef UINT32 * PUINT32; /* Long integer */ typedef signed long LONG; typedef unsigned long ULONG; typedef long * PLONG; typedef unsigned long * PULONG; /* Short integer */ typedef short SHORT; typedef unsigned short USHORT; typedef short * PSHORT; typedef unsigned short *PUSHORT; /* 8-bit integer*/ typedef unsigned char BYTE; typedef BYTE * PBYTE; typedef unsigned char UCHAR; /* Character and strings */ typedef char CHAR; typedef CHAR SZ; typedef CHAR * PSZ; typedef CHAR * PCHAR; /* Double integers */ typedef double DOUBLE; typedef double * PDOUBLE; typedef float FLOAT; typedef float * PFLOAT; typedef void VOID; typedef void * PVOID; /* Booleans */ typedef int BOOL; typedef BOOL * PBOOL; /* Integers */ typedef int INT; typedef int * PINT; typedef unsigned int UINT; typedef unsigned int * PUINT; /* Define pseudo-keywords IN and OUT if not defined yet */ #ifndef IN #define IN /* IN param */ #endif #ifndef OUT #define OUT /* OUT param */ #endif /* LONG LONG */ #define LLONG signed long long #define PLLONG signed long long * #define ULLONG unsigned long long #define PULLONG unsigned long long * #ifndef OPT #define OPT /* OPT param */ #endif typedef PSZ * PPSZ; #include #endif /*-------------------------------------------------------------------------- C language ----------------------------------------------------------------------------*/ #ifdef __cplusplus } #endif #endif /* __OCTTYPE_H__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/octrpc/0000755000175000017500000000000011202066033022514 5ustar maniacmaniacdahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/octrpc/rpc_protocol.h0000644000175000017500000000773210700513330025402 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/octrpc/oct6100_rpc_protocol.h0000644000175000017500000003054610700513330026555 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/0000755000175000017500000000000011202066033023010 5ustar maniacmaniacdahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_mixer_pub.h0000644000175000017500000000507010700513330026330 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_conf_bridge_pub.h0000644000175000017500000001331710700513330027450 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_channel_inst.h0000644000175000017500000002266510700513330027014 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_tlv_inst.h0000644000175000017500000000451210700513330026200 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_apimi.h0000644000175000017500000000426610700513330025443 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_interrupts_inst.h0000644000175000017500000001054710700513330027617 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_defines.h0000644000175000017500000006024010700513330025753 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_phasing_tsst_pub.h0000644000175000017500000000505510700513330027715 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_playout_buf_inst.h0000644000175000017500000000557010700513330027731 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_chip_stats_pub.h0000644000175000017500000001026310700513330027345 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_adpcm_chan_inst.h0000644000175000017500000000460110700513330027447 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_phasing_tsst_inst.h0000644000175000017500000000441710700513330030105 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_adpcm_chan_pub.h0000644000175000017500000000540610700513330027264 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_debug_inst.h0000644000175000017500000000720010700513330026456 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_events_pub.h0000644000175000017500000000621510700513330026512 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_channel_pub.h0000644000175000017500000003313710700513330026621 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_errors.h0000644000175000017500000016600510700513330025660 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_chip_open_inst.h0000644000175000017500000003264110700513330027343 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_api.h0000644000175000017500000000475710700513330025122 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_remote_debug_inst.h0000644000175000017500000000443410700513330030037 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_tsst_inst.h0000644000175000017500000000374110700513330026373 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_mixer_inst.h0000644000175000017500000000476710700513330026533 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_tsi_cnct_pub.h0000644000175000017500000000475610700513330027024 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_events_inst.h0000644000175000017500000000425010700513330026676 0ustar maniacmaniac /*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_api_inst.h0000644000175000017500000000763310700513330026153 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_chip_stats_inst.h0000644000175000017500000000477210700513330027544 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_apiud.h0000644000175000017500000002152110700513330025437 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_remote_debug_pub.h0000644000175000017500000000427310700513330027651 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_conf_bridge_inst.h0000644000175000017500000000637510700513330027645 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_interrupts_pub.h0000644000175000017500000000600310700513330027420 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_chip_open_pub.h0000644000175000017500000001626010700513330027153 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_tone_detection_pub.h0000644000175000017500000000513710700513330030213 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_debug_pub.h0000644000175000017500000000474310700513330026300 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_playout_buf_pub.h0000644000175000017500000001656410700513330027547 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_tsi_cnct_inst.h0000644000175000017500000000441010700513330027176 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/oct6100api/oct6100_tone_detection_inst.h0000644000175000017500000000327010700513330030376 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/octtypevx.h0000644000175000017500000000617710700513330023452 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/octtypewin.h0000644000175000017500000000555510700513330023611 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/octmac.h0000644000175000017500000000666410700513330022654 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/include/octdef.h0000644000175000017500000000633710700513330022647 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/get_discards0000755000175000017500000000253510473710216022175 0ustar maniacmaniac#!/usr/bin/php dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/octdeviceapi/0000755000175000017500000000000011202066032022235 5ustar maniacmaniacdahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/octdeviceapi/oct6100api/0000755000175000017500000000000011202066032024023 5ustar maniacmaniacdahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_adpcm_chan_priv.h0000644000175000017500000001177310700513330030476 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_miscellaneous_priv.h0000644000175000017500000004410510700513330031257 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_tone_detection_priv.h0000644000175000017500000001001310700513330031406 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_events_priv.h0000644000175000017500000000602710700513330027721 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_channel_priv.h0000644000175000017500000004724110700513330030030 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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__ */ dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/0000755000175000017500000000000011202066032025750 5ustar maniacmaniac././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootdahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_phasing_tsst.cdahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_phasing_tsst0000644000175000017500000007641310700513330031570 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_user.c0000644000175000017500000003710310700513330030252 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_mixer.c0000644000175000017500000015774110700513330030433 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_debug.c0000644000175000017500000015042610700513330030366 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_tsi_cnct.c0000644000175000017500000010427010700513330031102 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootdahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_tone_detection.cdahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_tone_detecti0000644000175000017500000011354710700513330031530 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootdahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_playout_buf.cdahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_playout_buf.0000644000175000017500000035536710700513330031501 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootdahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_chip_stats.cdahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_chip_stats.c0000644000175000017500000004266110700513330031442 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_tsst.c0000644000175000017500000004356710700513330030304 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 ././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootdahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_conf_bridge.cdahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_conf_bridge.0000644000175000017500000110137110700513330031372 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootdahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_adpcm_chan.cdahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_adpcm_chan.c0000644000175000017500000013127510700513330031356 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_chip_open.c0000644000175000017500000070663710700513330031257 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootdahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_remote_debug.cdahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_remote_debug0000644000175000017500000016566510700513330031533 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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 dahdi-linux-2.2.0-rc4/drivers/dahdi/oct612x/octdeviceapi/oct6100api/oct6100_api/oct6100_tlv.c0000644000175000017500000021336410700513330030106 0ustar maniacmaniac/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*\ 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