[Pkg-voip-commits] r6477 - in /dahdi-linux/trunk: debian/README.Debian debian/changelog debian/copyright debian/patches/bri_dchan debian/patches/fix_xpp_test debian/patches/series debian/patches/udev debian/rules drivers/dahdi/dahdi_echocan_oslec.c drivers/dahdi/opvxa1200.c

tzafrir-guest at alioth.debian.org tzafrir-guest at alioth.debian.org
Mon Nov 17 15:30:17 UTC 2008


Author: tzafrir-guest
Date: Mon Nov 17 15:30:16 2008
New Revision: 6477

URL: http://svn.debian.org/wsvn/pkg-voip/?sc=1&rev=6477
Log:
* New upstream release: 2.1.0-RC3 .
* dahdi_echocan_oslec.c dropped: included upstream.
* Include a DAHDI version of the OpenVox analog driver opvxa1200.c .
* Patch fix_xpp_test: A bug fix. Already fixed upstream.
* Patch udev: Adapt udev rules to Debian.
* Adapt patch bri_dchan to newer version.
* Update the README.Debian .

Added:
    dahdi-linux/trunk/debian/patches/fix_xpp_test
    dahdi-linux/trunk/debian/patches/udev
Removed:
    dahdi-linux/trunk/drivers/dahdi/dahdi_echocan_oslec.c
Modified:
    dahdi-linux/trunk/debian/README.Debian
    dahdi-linux/trunk/debian/changelog
    dahdi-linux/trunk/debian/copyright
    dahdi-linux/trunk/debian/patches/bri_dchan
    dahdi-linux/trunk/debian/patches/series
    dahdi-linux/trunk/debian/rules
    dahdi-linux/trunk/drivers/dahdi/opvxa1200.c

Modified: dahdi-linux/trunk/debian/README.Debian
URL: http://svn.debian.org/wsvn/pkg-voip/dahdi-linux/trunk/debian/README.Debian?rev=6477&op=diff
==============================================================================
--- dahdi-linux/trunk/debian/README.Debian (original)
+++ dahdi-linux/trunk/debian/README.Debian Mon Nov 17 15:30:16 2008
@@ -30,53 +30,17 @@
 If you are using udev, zaptel devices will be created when kernel modules 
 are loaded by using modprobe, or devices are detected by hotplug at boot time.
 
-If you cannot access the zap/ctl device, check which user asterisk is 
-running as and add these permissions to your permissions file
-(i.e. /etc/udev/permissions.d/50-udev.permissions):
-# zaptel devices -- asterisk is expected to be part of 'dialout' group
-zap/*:root:dialout:660
-
-Note, however, that beginning with Sarge, the default udev settings should 
-include those lines.
+If you cannot access the dahdi/ctl device, check which user asterisk is 
+running as and set those permissions in /etc/udev/rules.d/dahdi.rules .
 
 
 Bristuff
 --------
-This version has the the bristuff patch and kernel modules. The bristuffed 
-modules require a bristuffed Asterisk to work. For the older asterisk 1.2 
-this is the package asterisk-bristuff . Current asterisk 1.4 packages 
-include  support for bristuff.
-
-
-FXOTune
--------
-FXOTune is a utility provided by Digium for fine-tuning parameters of the 
-FXO modules of their TDM cards and compatibles, as well as of those of the 
-Xorcom Astribank.
-
-This package includes the fxotune utility. It will also load configuration 
-from /etc/fxotune.conf if fxotune was used to tune the FXO modules. Note 
-that fxotune will not work with X100P and similar cards.
-
-
-/etc/zaptel.conf
-----------------
-A sample /etc/zaptel.conf is no longer installed by default. You should 
-generate it manually (or automatically with genzaptelconf) if and when
-you actually have zaptel hardware and installed a zaptel-modules package
-for your kernel version.
-
-
-Supported tone-zones
---------------------
-Zaptel is capable of playing ring tone, buy tone etc. for a large variety of
-countries. This is done using the loadzone and defaultzone settings in 
-zaptel.conf.  A list of tone-zones supported by zaptel and libtonezone is 
-included in the file tonezones.txt in the documentation directory. 
-
-Example section of zaptel.conf:
-loadzone=us,uk,de
-defaultzone=us
+This version includes the bri_dchan patch as adapted from the bristuff 
+distribution. It also includes kernel modules from the same distribution
+however those were not yet fully adapted to work with DAHDI and are not 
+built by default at the moment. Some work is needed to either adapt them
+or use the new wcb4xxp driver included with DAHDI.
 
 
 Echo Canceller
@@ -89,7 +53,7 @@
 
 The version of OSLEC included is currently one from the staging directory.
 This is done temporarily until that driver will find its way into the 
-mainline tree.
+mainline tree and to help test it.
 
 According to early tests by OSLEC users, the default Asterisk echo
 canceller size of 128 taps (16ms) should be good enough for most

Modified: dahdi-linux/trunk/debian/changelog
URL: http://svn.debian.org/wsvn/pkg-voip/dahdi-linux/trunk/debian/changelog?rev=6477&op=diff
==============================================================================
--- dahdi-linux/trunk/debian/changelog (original)
+++ dahdi-linux/trunk/debian/changelog Mon Nov 17 15:30:16 2008
@@ -1,4 +1,4 @@
-dahdi-linux (2.0.0~dfsg-1) UNRELEASED; urgency=low
+dahdi-linux (2.1.0~dfsg~rc3-1) UNRELEASED; urgency=low
 
   * Initial Release (Closes: #XXXXXX)
 

Modified: dahdi-linux/trunk/debian/copyright
URL: http://svn.debian.org/wsvn/pkg-voip/dahdi-linux/trunk/debian/copyright?rev=6477&op=diff
==============================================================================
--- dahdi-linux/trunk/debian/copyright (original)
+++ dahdi-linux/trunk/debian/copyright Mon Nov 17 15:30:16 2008
@@ -68,8 +68,7 @@
 * Modify from wctdm.c by MiaoLin<miaolin at openvox.com.cn>
 
 opvxa1200.c is available for download from 
-http://www.openvox.com.cn/members_downloads.php
-(requires no login. Does require javascript)
+http://www.openvox.com.cn/downloadsFile/a1200p-a800p_driver_with_dahdi.c
 
 wcopenpci.c is from the Voicetronix zaptel distribution at
 http://www.voicetronix.com/Downloads/asterisk/
@@ -77,21 +76,17 @@
 Copyright (C) 2005 - 2007, Voicetronix
 
 
-Files in oslec/ subdirectory and oslec patches:
-Part of the Open Source Line Echo Canceller (OSLEC) project:
-http://www.rowetel.com/ucasterisk/oslec.html
-Current version downloaded from the subversion repository at:
-http://svn.rowetel.com/software/oslec/trunk
+Patch oslec_kernelorg is based on the Linux Kernel distribution (see 
+README.Debian). Part of the Open Source Line Echo Canceller (OSLEC) project.
 
-oslec/echo.c: * Copyright (C) 2001, 2003 Steve Underwood, 2007 David Rowe
-oslec/oslec-ctrl-panel.sh:#  Copyright (C) 2007 David Rowe
-oslec/oslec.h:  Copyright (C) 2007 David Rowe
-oslec/oslec_wrap.c:  Copyright (C) 2007 David Rowe
-oslec/spandsp/fir.h: * Copyright (C) 2002 Steve Underwood
-oslec/spandsp/bit_operations.h: * Copyright (C) 2006 Steve Underwood
-oslec/spandsp/echo.h: * Copyright (C) 2001 Steve Underwood and 2007 David Rowe
+echo.c: * Copyright (C) 2001, 2003 Steve Underwood, 2007 David Rowe
+oslec.h:  Copyright (C) 2007 David Rowe
+oslec_wrap.c:  Copyright (C) 2007 David Rowe
+fir.h: * Copyright (C) 2002 Steve Underwood
+bit_operations.h: * Copyright (C) 2006 Steve Underwood
+echo.h: * Copyright (C) 2001 Steve Underwood and 2007 David Rowe
 
-oslec/spandsp/mmx.h:
+mmx.h:
 * mmx.h
  * Copyright (C) 1997-2001 H. Dietz and R. Fisher
  *

Modified: dahdi-linux/trunk/debian/patches/bri_dchan
URL: http://svn.debian.org/wsvn/pkg-voip/dahdi-linux/trunk/debian/patches/bri_dchan?rev=6477&op=diff
==============================================================================
--- dahdi-linux/trunk/debian/patches/bri_dchan (original)
+++ dahdi-linux/trunk/debian/patches/bri_dchan Mon Nov 17 15:30:16 2008
@@ -19,22 +19,24 @@
  	spinlock_t lock;
  	char name[40];
  	/* Specified by DAHDI */
-@@ -486,8 +493,15 @@ enum {
- 	DAHDI_FLAGBIT_LOOPED     = 18,
- 	DAHDI_FLAGBIT_MTP2       = 19,
-	DAHDI_FLAGBIT_HDLC56       = 20,
+@@ -486,6 +493,9 @@ enum {
+ 	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  */
 +#if defined(CONFIG_DAHDI_BRI_DCHANS)
-+	DAHDI_FLAGBIT_BRIDCHAN   = 21,
++	DAHDI_FLAGBIT_BRIDCHAN   = 21,	/*!< hardhdlc-like handling of the D channel */
 +#endif
  };
  
-+#if defined(CONFIG_DAHDI_BRI_DCHANS)
-+#define DAHDI_FLAG_BRIDCHAN		(1 << (int)DAHDI_FLAGBIT_BRIDCHAN)
-+#endif
-+
+ /* map flagbits to flag masks */
+@@ -500,6 +500,7 @@
+ #define DAHDI_FLAG_LOOPED	DAHDI_FLAG(LOOPED)
+ #define DAHDI_FLAG_MTP2		DAHDI_FLAG(MTP2)
+ #define DAHDI_FLAG_HDLC56	DAHDI_FLAG(HDLC56)
++#define DAHDI_FLAG_BRIDCHAN	DAHDI_FLAG(BRIDCHAN)
+ 
  struct dahdi_span {
  	spinlock_t lock;
- 	void *pvt;			/*!< Private stuff */
 --- a/drivers/dahdi/dahdi_config.h
 +++ b/drivers/dahdi/dahdi_config.h
 @@ -169,4 +169,10 @@

Added: dahdi-linux/trunk/debian/patches/fix_xpp_test
URL: http://svn.debian.org/wsvn/pkg-voip/dahdi-linux/trunk/debian/patches/fix_xpp_test?rev=6477&op=file
==============================================================================
--- dahdi-linux/trunk/debian/patches/fix_xpp_test (added)
+++ dahdi-linux/trunk/debian/patches/fix_xpp_test Mon Nov 17 15:30:16 2008
@@ -1,0 +1,16 @@
+Don't fail building if standard error is not a terminal.
+
+Already applied in upstream trunk and should hopefully be included in 
+dahdi-linux 2.1.0 .
+
+--- a/drivers/dahdi/xpp/init_card_2_30
++++ b/drivers/dahdi/xpp/init_card_2_30
+@@ -67,7 +67,7 @@ sub debug {
+ }
+ 
+ # Arrange for error logging
+-if (-t STDERR) {
++if (-t STDERR || $opts{v}) {
+ 	$unit_id = 'Interactive';
+ 	main::debug "Interactive startup";
+ } else {

Modified: dahdi-linux/trunk/debian/patches/series
URL: http://svn.debian.org/wsvn/pkg-voip/dahdi-linux/trunk/debian/patches/series?rev=6477&op=diff
==============================================================================
--- dahdi-linux/trunk/debian/patches/series (original)
+++ dahdi-linux/trunk/debian/patches/series Mon Nov 17 15:30:16 2008
@@ -19,3 +19,5 @@
 #staging-echo-remove-__cplusplus-macro-magic.patch
 #staging-echo-remove-annoying-end-of-function-markers.patch
 #staging-lindent-the-echo-driver.patch
+fix_xpp_test
+udev

Added: dahdi-linux/trunk/debian/patches/udev
URL: http://svn.debian.org/wsvn/pkg-voip/dahdi-linux/trunk/debian/patches/udev?rev=6477&op=file
==============================================================================
--- dahdi-linux/trunk/debian/patches/udev (added)
+++ dahdi-linux/trunk/debian/patches/udev Mon Nov 17 15:30:16 2008
@@ -1,0 +1,23 @@
+* Fix ownership in generated udev rules (Debian-specific)
+* Remove the rules to fix location of udev files. No longer needed.
+  (Should be part of upstream in a release or two)
+
+--- a/build_tools/genudevrules
++++ b/build_tools/genudevrules
+@@ -26,15 +26,6 @@ else
+ fi
+ 
+ cat <<EOF
+-# udev rules to generate the /dev/dahdi device files (if not yet provided 
+-# by your distribution):
+-KERNEL${match}"dahdictl", NAME="dahdi/ctl"
+-KERNEL${match}"dahditranscode", NAME="dahdi/transcode"
+-KERNEL${match}"dahditimer", NAME="dahdi/timer"
+-KERNEL${match}"dahdichannel", NAME="dahdi/channel"
+-KERNEL${match}"dahdipseudo", NAME="dahdi/pseudo"
+-KERNEL${match}"dahdi[0-9]*", NAME="dahdi/%n"
+-
+ # DAHDI devices with ownership/permissions for running as non-root
+-SUBSYSTEM${match}"dahdi",  OWNER="asterisk", GROUP="asterisk", MODE="0660"
++SUBSYSTEM${match}"dahdi",  GROUP="dialout", MODE="0660"
+ EOF

Modified: dahdi-linux/trunk/debian/rules
URL: http://svn.debian.org/wsvn/pkg-voip/dahdi-linux/trunk/debian/rules?rev=6477&op=diff
==============================================================================
--- dahdi-linux/trunk/debian/rules (original)
+++ dahdi-linux/trunk/debian/rules Mon Nov 17 15:30:16 2008
@@ -43,9 +43,9 @@
 # the generated headers as part of the source:
 GENERATED_SOURCES := include/dahdi/version.h
 
-#EXTRA_MODS=ds1x1f opvxa1200
+EXTRA_MODS=opvxa1200
 
-EXTRA_MODS=zaphfc qozap
+EXTRA_MODS=
 ifneq (,$(filter-out powerpc m68k armeb mips,$(shell dpkg-architecture -qDEB_HOST_ARCH)))
 EXTRA_MODS += wcopenpci
 endif
@@ -117,10 +117,8 @@
 	#   as the source tree is not there.
 	# FIXME: This will fail with an ugly warning on the clean of the
 	# modules build. However only fter the actuual clean.
-	# FIXME(2): 'make clean' currently fails if there's no kernel source.
-	# So clean manually. Should be fixed in 2.0.0 (final).
 	rm -f dahdi/include/version.h
-	#[ ! -f Makefile ] || $(MAKE) dist-clean || true
+	[ ! -f Makefile ] || $(MAKE) dist-clean || true
 	dh_clean
 
 TARPARDIR=$(CURDIR)/debian/tmp

Modified: dahdi-linux/trunk/drivers/dahdi/opvxa1200.c
URL: http://svn.debian.org/wsvn/pkg-voip/dahdi-linux/trunk/drivers/dahdi/opvxa1200.c?rev=6477&op=diff
==============================================================================
--- dahdi-linux/trunk/drivers/dahdi/opvxa1200.c (original)
+++ dahdi-linux/trunk/drivers/dahdi/opvxa1200.c Mon Nov 17 15:30:16 2008
@@ -1,5 +1,5 @@
 /*
- * OpenVox A1200P FXS/FXO Interface Driver for Zapata Telephony interface
+ * OpenVox A1200P FXS/FXO Interface Driver for DAHDI Telephony interface
  *
  * Modify from wctdm.c by MiaoLin<miaolin at openvox.com.cn>
  *
@@ -30,18 +30,43 @@
  * 	support firmware version 1.2, faster i/o operation, and better LED control.
  * 
  * Rev 0.12 patched to support new pci id 0x8519
+ * Rev 0.13 patched to remove the warning during compile under kernel 2.6.22 
+ * Rev 0.14 patched to remove the bug for ZAP_IRQ_SHARED , 3/9/2007 
+ * Rev 0.15 patched to support new pci ID 0X9532 by james.zhu, 23/10/2007
+ * Rev 0.16 support new pci id 0x9559 by Miao Lin 21/3/2008
+ * Rev 0.17 
+ *	patched a few bugs, 
+ *	add hwgain support.
+ *	fixed A800P version check
+ * Rev 1.4.9.2 
+ *		Only generate 8 channels for A800P
+ * 		Version number synced to zaptel distribution.
+ * Rev 1.4.9.2.a
+ *		Fixed freeregion.
+ * 		
+ * Rev 1.4.9.2.b
+ *    Add cid before first ring support.
+ *    New Paremeters:
+ *          	cidbeforering : set to 1 will cause the card enable cidbeforering function. default 0
+ * 		cidbuflen : length of cid buffer, in msec, default 3000 msec.
+ *              cidtimeout : time out of a ring, default 6000msec
+ *   	User must set cidstart=polarity in zapata.conf to use with this feature
+ * 		cidsignalling = signalling format send before 1st ring. most likely dtmf.
  * 
+ * Rev 1.4.9.2.c
+ * 	add driver parameter cidtimeout.
  * 
+ * Rev 1.4.9.2.d 
+ *  	add debug stuff to test fxs power alarm
+ *  
+ * Rev 1.4.11
+ *  	Support enhanced full scale tx/rx for FXO required by europe standard (Register 30, acim) (module parm fxofullscale)
+ *  
+ * Rev 1.4.12 2008/10/17
+ *      Fixed bug cause FXS module report fake power alarm.
+ *      Power alarm debug stuff removed.
  * 
- * 
- * 
- * 
- * 
- * 
- * 
- * 
- * 
- * 
+ * Rev 2.0 DAHDI 2008/10/17
  * 
  */
 
@@ -52,15 +77,15 @@
 #include <linux/errno.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
+#include <linux/moduleparam.h>
 #include <asm/io.h>
 #include "proslic.h"
-#include "wctdm.h"
-  
-//miaolin
-#include <linux/string.h>
-#include <asm/uaccess.h> // get_fs(), set_fs(), KERNEL_DS
-#include <linux/file.h> // fput()
-//miaolin
+   
+/* MiaoLin debug start */
+#include <linux/string.h>
+#include <asm/uaccess.h> 	/* get_fs(), set_fs(), KERNEL_DS */
+#include <linux/file.h> 	/* fput() */
+/* MiaoLin debug end */
   
 
 /*
@@ -137,114 +162,16 @@
 {43,66,"LOOP_CLOSE_TRES_LOW",0x1000},
 };
 
-static struct fxo_mode {
-	char *name;
-	/* FXO */
-	int ohs;
-	int ohs2;
-	int rz;
-	int rt;
-	int ilim;
-	int dcv;
-	int mini;
-	int acim;
-	int ring_osc;
-	int ring_x;
-} fxo_modes[] =
-{
-	{ "FCC", 0, 0, 0, 1, 0, 0x3, 0, 0, }, 	/* US, Canada */
-	{ "TBR21", 0, 0, 0, 0, 1, 0x3, 0, 0x2, 0x7e6c, 0x023a, },
-										/* Austria, Belgium, Denmark, Finland, France, Germany, 
-										   Greece, Iceland, Ireland, Italy, Luxembourg, Netherlands,
-										   Norway, Portugal, Spain, Sweden, Switzerland, and UK */
-	{ "ARGENTINA", 0, 0, 0, 0, 0, 0x3, 0, 0, },
-	{ "AUSTRALIA", 1, 0, 0, 0, 0, 0, 0x3, 0x3, },
-	{ "AUSTRIA", 0, 1, 0, 0, 1, 0x3, 0, 0x3, },
-	{ "BAHRAIN", 0, 0, 0, 0, 1, 0x3, 0, 0x2, },
-	{ "BELGIUM", 0, 1, 0, 0, 1, 0x3, 0, 0x2, },
-	{ "BRAZIL", 0, 0, 0, 0, 0, 0, 0x3, 0, },
-	{ "BULGARIA", 0, 0, 0, 0, 1, 0x3, 0x0, 0x3, },
-	{ "CANADA", 0, 0, 0, 0, 0, 0x3, 0, 0, },
-	{ "CHILE", 0, 0, 0, 0, 0, 0x3, 0, 0, },
-	{ "CHINA", 0, 0, 0, 0, 0, 0, 0x3, 0xf, },
-	{ "COLUMBIA", 0, 0, 0, 0, 0, 0x3, 0, 0, },
-	{ "CROATIA", 0, 0, 0, 0, 1, 0x3, 0, 0x2, },
-	{ "CYRPUS", 0, 0, 0, 0, 1, 0x3, 0, 0x2, },
-	{ "CZECH", 0, 0, 0, 0, 1, 0x3, 0, 0x2, },
-	{ "DENMARK", 0, 1, 0, 0, 1, 0x3, 0, 0x2, },
-	{ "ECUADOR", 0, 0, 0, 0, 0, 0x3, 0, 0, },
-	{ "EGYPT", 0, 0, 0, 0, 0, 0, 0x3, 0, },
-	{ "ELSALVADOR", 0, 0, 0, 0, 0, 0x3, 0, 0, },
-	{ "FINLAND", 0, 1, 0, 0, 1, 0x3, 0, 0x2, },
-	{ "FRANCE", 0, 1, 0, 0, 1, 0x3, 0, 0x2, },
-	{ "GERMANY", 0, 1, 0, 0, 1, 0x3, 0, 0x3, },
-	{ "GREECE", 0, 1, 0, 0, 1, 0x3, 0, 0x2, },
-	{ "GUAM", 0, 0, 0, 0, 0, 0x3, 0, 0, },
-	{ "HONGKONG", 0, 0, 0, 0, 0, 0x3, 0, 0, },
-	{ "HUNGARY", 0, 0, 0, 0, 0, 0x3, 0, 0, },
-	{ "ICELAND", 0, 1, 0, 0, 1, 0x3, 0, 0x2, },
-	{ "INDIA", 0, 0, 0, 0, 0, 0x3, 0, 0x4, },
-	{ "INDONESIA", 0, 0, 0, 0, 0, 0x3, 0, 0, },
-	{ "IRELAND", 0, 1, 0, 0, 1, 0x3, 0, 0x2, },
-	{ "ISRAEL", 0, 0, 0, 0, 1, 0x3, 0, 0x2, },
-	{ "ITALY", 0, 1, 0, 0, 1, 0x3, 0, 0x2, },
-	{ "JAPAN", 0, 0, 0, 0, 0, 0, 0x3, 0, },
-	{ "JORDAN", 0, 0, 0, 0, 0, 0, 0x3, 0, },
-	{ "KAZAKHSTAN", 0, 0, 0, 0, 0, 0x3, 0, },
-	{ "KUWAIT", 0, 0, 0, 0, 0, 0x3, 0, 0, },
-	{ "LATVIA", 0, 0, 0, 0, 1, 0x3, 0, 0x2, },
-	{ "LEBANON", 0, 0, 0, 0, 1, 0x3, 0, 0x2, },
-	{ "LUXEMBOURG", 0, 1, 0, 0, 1, 0x3, 0, 0x2, },
-	{ "MACAO", 0, 0, 0, 0, 0, 0x3, 0, 0, },
-	{ "MALAYSIA", 0, 0, 0, 0, 0, 0, 0x3, 0, },	/* Current loop >= 20ma */
-	{ "MALTA", 0, 0, 0, 0, 1, 0x3, 0, 0x2, },
-	{ "MEXICO", 0, 0, 0, 0, 0, 0x3, 0, 0, },
-	{ "MOROCCO", 0, 0, 0, 0, 1, 0x3, 0, 0x2, },
-	{ "NETHERLANDS", 0, 1, 0, 0, 1, 0x3, 0, 0x2, },
-	{ "NEWZEALAND", 0, 0, 0, 0, 0, 0x3, 0, 0x4, },
-	{ "NIGERIA", 0, 0, 0, 0, 0x1, 0x3, 0, 0x2, },
-	{ "NORWAY", 0, 1, 0, 0, 1, 0x3, 0, 0x2, },
-	{ "OMAN", 0, 0, 0, 0, 0, 0, 0x3, 0, },
-	{ "PAKISTAN", 0, 0, 0, 0, 0, 0, 0x3, 0, },
-	{ "PERU", 0, 0, 0, 0, 0, 0x3, 0, 0, },
-	{ "PHILIPPINES", 0, 0, 0, 0, 0, 0, 0x3, 0, },
-	{ "POLAND", 0, 0, 1, 1, 0, 0x3, 0, 0, },
-	{ "PORTUGAL", 0, 1, 0, 0, 1, 0x3, 0, 0x2, },
-	{ "ROMANIA", 0, 0, 0, 0, 0, 3, 0, 0, },
-	{ "RUSSIA", 0, 0, 0, 0, 0, 0, 0x3, 0, },
-	{ "SAUDIARABIA", 0, 0, 0, 0, 0, 0x3, 0, 0, },
-	{ "SINGAPORE", 0, 0, 0, 0, 0, 0x3, 0, 0, },
-	{ "SLOVAKIA", 0, 0, 0, 0, 0, 0x3, 0, 0x3, },
-	{ "SLOVENIA", 0, 0, 0, 0, 0, 0x3, 0, 0x2, },
-	{ "SOUTHAFRICA", 1, 0, 1, 0, 0, 0x3, 0, 0x3, },
-	{ "SOUTHKOREA", 0, 0, 0, 0, 0, 0x3, 0, 0, },
-	{ "SPAIN", 0, 1, 0, 0, 1, 0x3, 0, 0x2, },
-	{ "SWEDEN", 0, 1, 0, 0, 1, 0x3, 0, 0x2, },
-	{ "SWITZERLAND", 0, 1, 0, 0, 1, 0x3, 0, 0x2, },
-	{ "SYRIA", 0, 0, 0, 0, 0, 0, 0x3, 0, },
-	{ "TAIWAN", 0, 0, 0, 0, 0, 0, 0x3, 0, },
-	{ "THAILAND", 0, 0, 0, 0, 0, 0, 0x3, 0, },
-	{ "UAE", 0, 0, 0, 0, 0, 0x3, 0, 0, },
-	{ "UK", 0, 1, 0, 0, 1, 0x3, 0, 0x5, },
-	{ "USA", 0, 0, 0, 0, 0, 0x3, 0, 0, },
-	{ "YEMEN", 0, 0, 0, 0, 0, 0x3, 0, 0, },
-};
-
-#ifdef STANDALONE_ZAPATA
-#include "zaptel.h"
-#else
-#include <linux/zaptel.h>
-#endif
-
-#ifdef LINUX26
-#include <linux/moduleparam.h>
-#endif
+
+#include <dahdi/kernel.h>
+#include <dahdi/wctdm_user.h>
+
+#include "fxo_modes.h"
 
 #define NUM_FXO_REGS 60
 
 #define WC_MAX_IFACES 128
 
-#define DELAY	0x0	/* 30 = 15 cycles, 10 = 8 cycles, 0 = 3 cycles */
 #define WC_OFFSET	4	/* Offset between transmit and receive, in bytes. */
 #define WC_SYNCFLAG	0xca1ef1ac
 
@@ -292,12 +219,14 @@
 #define FLAG_WRITE	1
 #define FLAG_READ	2
 
+
+#define DEFAULT_RING_DEBOUNCE		64		/* Ringer Debounce (64 ms) */
+
 /* the constants below control the 'debounce' periods enforced by the
    check_hook routines; these routines are called once every 4 interrupts
    (the interrupt cycles around the four modules), so the periods are
    specified in _4 millisecond_ increments
 */
-#define RING_DEBOUNCE		4		/* Ringer Debounce (64 ms) */
 #define DEFAULT_BATT_DEBOUNCE	4		/* Battery debounce (64 ms) */
 #define POLARITY_DEBOUNCE 	4		/* Polarity debounce (64 ms) */
 #define DEFAULT_BATT_THRESH	3		/* Anything under this is "no battery" */
@@ -305,14 +234,24 @@
 #define OHT_TIMER		6000	/* How long after RING to retain OHT */
 
 #define FLAG_3215	(1 << 0)
-
-//modify by MiaoLin from 4 to 12;
-//#define NUM_CARDS 4
+#define FLAG_A800	(1 << 7)
+
+#define MAX_NUM_CARDS 12
 #define NUM_CARDS 12
-#define NUM_FLAG  4	//number of flag channels.
-
-// if you want to record the last 8 sec voice before the driver unload, uncomment it and rebuild.
-//#define TEST_LOG_INCOME_VOICE
+#define NUM_FLAG  4	/* number of flag channels. */
+
+
+enum cid_hook_state {
+	CID_STATE_IDLE = 0,
+	CID_STATE_RING_ON,
+	CID_STATE_RING_OFF,
+	CID_STATE_WAIT_RING_FINISH
+};
+
+/* if you want to record the last 8 sec voice before the driver unload, uncomment it and rebuild. */
+/* #define TEST_LOG_INCOME_VOICE */
+#define voc_buffer_size (8000*8)
+
 
 #define MAX_ALARMS 10
 
@@ -335,18 +274,16 @@
 	PROSLIC_POWER_WARNED,
 };
 
-#define voc_buffer_size (8000*8)
-
 struct wctdm {
 	struct pci_dev *dev;
 	char *variety;
-	struct zt_span span;
+	struct dahdi_span span;
 	unsigned char ios;
 	int usecount;
 	unsigned int intcount;
 	int dead;
 	int pos;
-	int flags[NUM_CARDS];
+	int flags[MAX_NUM_CARDS];
 	int freeregion;
 	int alt;
 	int curcard;
@@ -363,6 +300,7 @@
 			int ring;
 #else			
 			int wasringing;
+			int lastrdtx;
 #endif			
 			int ringdebounce;
 			int offhook;
@@ -384,12 +322,12 @@
 			int palarms;
 			struct calregs calregs;
 		} fxs;
-	} mod[NUM_CARDS];
+	} mod[MAX_NUM_CARDS];
 
 	/* Receive hook state and debouncing */
-	int modtype[NUM_CARDS];
-	unsigned char reg0shadow[NUM_CARDS];
-	unsigned char reg1shadow[NUM_CARDS];
+	int modtype[MAX_NUM_CARDS];
+	unsigned char reg0shadow[MAX_NUM_CARDS];
+	unsigned char reg1shadow[MAX_NUM_CARDS];
 
 	unsigned long ioaddr;
 	unsigned long mem_region;	/* 32 bit Region allocated to tiger320 */
@@ -400,26 +338,36 @@
 	dma_addr_t	writedma;
 	volatile unsigned char *writechunk;					/* Double-word aligned write memory */
 	volatile unsigned char *readchunk;					/* Double-word aligned read memory */
-	struct zt_chan chans[NUM_CARDS];
+	/*struct dahdi_chan chans[MAX_NUM_CARDS];*/
+	struct dahdi_chan _chans[NUM_CARDS];
+	struct dahdi_chan *chans[NUM_CARDS];
+
 
 #ifdef TEST_LOG_INCOME_VOICE	
-	//unsigned char tempo[NUM_CARDS + NUM_FLAG];
-	char * voc_buf[NUM_CARDS + NUM_FLAG];
-	int voc_ptr[NUM_CARDS + NUM_FLAG];
+	char * voc_buf[MAX_NUM_CARDS + NUM_FLAG];
+	int voc_ptr[MAX_NUM_CARDS + NUM_FLAG];
 #endif
-	//int offset;
 	int lastchan;
 	unsigned short ledstate;
 	unsigned char fwversion;
+	int max_cards;
+	char *card_name;
+	
+	char *cid_history_buf[MAX_NUM_CARDS];
+	int	 cid_history_ptr[MAX_NUM_CARDS];
+	int  cid_history_clone_cnt[MAX_NUM_CARDS];
+	enum cid_hook_state cid_state[MAX_NUM_CARDS];
 };
 
+char* A1200P_Name = "A1200P";
+char* A800P_Name  = "A800P";
 
 struct wctdm_desc {
 	char *name;
 	int flags;
 };
 
-static struct wctdm_desc wctdme = { "OpenVox A1200P", 0 };
+static struct wctdm_desc wctdme = { "OpenVox A1200P/A800P", 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];
@@ -428,18 +376,30 @@
 
 static int battdebounce = DEFAULT_BATT_DEBOUNCE;
 static int battthresh = DEFAULT_BATT_THRESH;
+static int ringdebounce = DEFAULT_RING_DEBOUNCE;
+static int fwringdetect = 0;
 static int debug = 0;
-//static int debug = 1;
 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 spibyhw = 1;			// MiaoLin add;
+static int fastpickup = 0;
+static int fxotxgain = 0;
+static int fxorxgain = 0;
+static int fxstxgain = 0;
+static int fxsrxgain = 0;
+/* special h/w control command */
+static int spibyhw = 1;
 static int usememio = 1;
+static int cidbeforering = 0;
+static int cidbuflen = 3000;	/* in msec, default 3000 */
+static int cidtimeout = 6*1000;	/* in msec, default 6000 */
+static int fxofullscale = 0;	/* fxo full scale tx/rx, register 30, acim */
 
 static int wctdm_init_proslic(struct wctdm *wc, int card, int fast , int manual, int sane);
 
@@ -452,7 +412,7 @@
 	wc->ledstate |= (onoff<<card);
 	c = (inb(wc->ioaddr + WC_AUXD)&~BIT_LED_CLK)|BIT_LED_DATA;
 	outb( c,  wc->ioaddr + WC_AUXD);
-	for(i=NUM_CARDS-1; i>=0; i--)
+	for(i=MAX_NUM_CARDS-1; i>=0; i--)
 	{
 		if(wc->ledstate & (0x0001<<i))
 			if(wc->fwversion == 0x11)
@@ -477,68 +437,35 @@
 	int x, y, chan_offset, pos;
 	volatile unsigned char *txbuf;
 	
-	if (ints & 0x04 /*0x01*/) 
+	if (ints & /*0x01*/ 0x04) 
 		/* Write is at interrupt address.  Start writing from normal offset */
 		txbuf = wc->writechunk;
 	else 
-		txbuf = wc->writechunk + ZT_CHUNKSIZE * (NUM_CARDS+NUM_FLAG);
+		txbuf = wc->writechunk + DAHDI_CHUNKSIZE * (MAX_NUM_CARDS+NUM_FLAG);
 		
 	/* Calculate Transmission */
-	zt_transmit(&wc->span);
+	dahdi_transmit(&wc->span);
 	
 	if(wc->lastchan == -1)	// not in sync.
 		return;
 	
-	chan_offset = (wc->lastchan*4 + 4 ) % (NUM_CARDS+NUM_FLAG);
-
-	//for (x=0;x<wc->offset;x++)
-	//	txbuf[x] = wc->tempo[x];
-	for (y=0;y<ZT_CHUNKSIZE;y++) {
+	chan_offset = (wc->lastchan*4 + 4 ) % (MAX_NUM_CARDS+NUM_FLAG);
+
+	for (y=0;y<DAHDI_CHUNKSIZE;y++) {
 #ifdef __BIG_ENDIAN
 	// operation pending...
 #else
-		//for (x=0;x<(NUM_CARDS+NUM_FLAG);x++) {
-		//	pos = y * (NUM_CARDS+NUM_FLAG) + chanmap[(x+chan_offset)&0x0f] + wc->offset;
-		//	/* Put channel number as outgoing data */
-		//	if (pos < (NUM_CARDS+NUM_FLAG) * ZT_CHUNKSIZE)
-		//		txbuf[pos] = wc->chans[x].writechunk[y];
-		//	else
-		//		wc->tempo[pos - (NUM_CARDS+NUM_FLAG) * ZT_CHUNKSIZE] = wc->chans[x].writechunk[y];
-		//}
-		//printk("\n");
-		for (x=0;x<(NUM_CARDS+NUM_FLAG);x++) {
-			pos = y * (NUM_CARDS+NUM_FLAG) + ((x + chan_offset + NUM_CARDS+NUM_FLAG  /*+ wc->offset*/ - WC_OFFSET)&0x0f);
-			if(x<NUM_CARDS)
-				txbuf[pos] = wc->chans[x].writechunk[y]; 
+		for (x=0;x<(MAX_NUM_CARDS+NUM_FLAG);x++) {
+			pos = y * (MAX_NUM_CARDS+NUM_FLAG) + ((x + chan_offset + MAX_NUM_CARDS+NUM_FLAG - WC_OFFSET)&0x0f);
+			if(x<wc->max_cards/*MAX_NUM_CARDS*/)
+				txbuf[pos] = wc->chans[x]->writechunk[y]; 
 			else
 				txbuf[pos] = 0; 
-			//if(x==2)
-			//	txbuf[pos] = 0x55;//trans_count;
-			//else
-			//	txbuf[pos] = 0;
-		}
-
-		/*for (x=0;x<(NUM_CARDS+NUM_FLAG);x++) {
-			pos = y * (NUM_CARDS+NUM_FLAG) + x + chan_offset + wc->offset - WC_OFFSET;
-			if ( pos<(NUM_CARDS+NUM_FLAG)*ZT_CHUNKSIZE )
-			{	
-				if(x<NUM_CARDS)
-					txbuf[pos] = wc->chans[x].writechunk[y]; 
-				else
-					txbuf[pos] = 0; 
-			}
-			else
-			{
-				if(x<NUM_CARDS)
-					wc->tempo[pos - (NUM_CARDS+NUM_FLAG) * ZT_CHUNKSIZE] = wc->chans[x].writechunk[y]; 
-				else
-					wc->tempo[pos - (NUM_CARDS+NUM_FLAG) * ZT_CHUNKSIZE] = 0; 
-			}
-		}*/
+		}
 #endif
 	}
-
-}
+}
+
 
 #ifdef AUDIO_RINGCHECK
 static inline void ring_check(struct wctdm *wc, int card)
@@ -547,10 +474,10 @@
 	short sample;
 	if (wc->modtype[card] != MOD_TYPE_FXO)
 		return;
-	wc->mod[card].fxo.pegtimer += ZT_CHUNKSIZE;
-	for (x=0;x<ZT_CHUNKSIZE;x++) {
+	wc->mod[card].fxo.pegtimer += DAHDI_CHUNKSIZE;
+	for (x=0;x<DAHDI_CHUNKSIZE;x++) {
 		/* Look for pegging to indicate ringing */
-		sample = ZT_XLAW(wc->chans[card].readchunk[x], (&(wc->chans[card])));
+		sample = DAHDI_XLAW(wc->chans[card].readchunk[x], (&(wc->chans[card])));
 		if ((sample > 10000) && (wc->mod[card].fxo.peg != 1)) {
 			if (debug > 1) printk("High peg!\n");
 			if ((wc->mod[card].fxo.pegtimer < PEGTIME) && (wc->mod[card].fxo.pegtimer > MINPEGTIME))
@@ -578,14 +505,14 @@
 			if (debug)
 				printk("RING on %d/%d!\n", wc->span.spanno, card + 1);
 			if (!wc->mod[card].fxo.offhook)
-				zt_hooksig(&wc->chans[card], ZT_RXSIG_RING);
+				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("NO RING on %d/%d!\n", wc->span.spanno, card + 1);
-			zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK);
+			dahdi_hooksig(&wc->chans[card], DAHDI_RXSIG_OFFHOOK);
 			wc->mod[card].fxo.ring = 0;
 		}
 	}
@@ -599,23 +526,15 @@
 	int x, y, chan_offset;
 
 
-	if (ints & /*0x08*/0x04)
+	if (ints & 0x08/*0x04*/)
 		/* Read is at interrupt address.  Valid data is available at normal offset */
 		rxbuf = wc->readchunk;
 	else
-		rxbuf = wc->readchunk + ZT_CHUNKSIZE * (NUM_CARDS+NUM_FLAG);
-
-	//search for the flag channel
+		rxbuf = wc->readchunk + DAHDI_CHUNKSIZE * (MAX_NUM_CARDS+NUM_FLAG);
+
 	for(x=0; x<4; x++)
-	{
-		//printk("0x%08x ", *(int*)(rxbuf+x*4));
 		if(  *(int*)(rxbuf+x*4) == WC_SYNCFLAG)
-		{
-			//printk(" found at %d ", x);	
 			break;
-		}
-	}
-	
 	if(x==4)
 	{
 		printk("buffer sync misseed!\n");
@@ -624,39 +543,86 @@
 	}
 	else if(wc->lastchan != x)
 	{
-		
 		printk("buffer re-sync occur from %d to %d\n", wc->lastchan, x);
 		wc->lastchan = x;
 	}
-	chan_offset = (wc->lastchan*4 + 4 ) % (NUM_CARDS+NUM_FLAG);
-
-	for (x=0;x<ZT_CHUNKSIZE;x++) {
+	chan_offset = (wc->lastchan*4 + 4 ) % (MAX_NUM_CARDS+NUM_FLAG);
+
+	for (x=0;x<DAHDI_CHUNKSIZE;x++) {
 #ifdef __BIG_ENDIAN
 	// operation pending...
 #else
-		for (y=0;y<NUM_CARDS;y++) { 
+		for (y=0;y<wc->max_cards/*MAX_NUM_CARDS*/;y++) { 
 			if (wc->cardflag & (1 << y))
-				wc->chans[y].readchunk[x] = rxbuf[(NUM_CARDS+NUM_FLAG) * x + ((y + chan_offset ) & 0x0f)];
+				wc->chans[y]->readchunk[x] = rxbuf[(MAX_NUM_CARDS+NUM_FLAG) * x + ((y + chan_offset ) & 0x0f)];
 #ifdef TEST_LOG_INCOME_VOICE
-			wc->voc_buf[y][wc->voc_ptr[y]] = rxbuf[(NUM_CARDS+NUM_FLAG) * x + ((y + chan_offset) & 0x0f)];
+			wc->voc_buf[y][wc->voc_ptr[y]] = rxbuf[(MAX_NUM_CARDS+NUM_FLAG) * x + ((y + chan_offset) & 0x0f)];
 			wc->voc_ptr[y]++;
 			if(wc->voc_ptr[y] >= voc_buffer_size)
 				wc->voc_ptr[y] = 0;
 #endif		
 		}
-
 #endif
 	}
+	
+	if(cidbeforering)
+	{
+		for(x=0; x<wc->max_cards; x++)
+		{
+			if (wc->modtype[wc->chans[x]->chanpos - 1] == MOD_TYPE_FXO)
+				if(wc->mod[wc->chans[x]->chanpos - 1].fxo.offhook == 0)
+				{
+					/*unsigned int *p_readchunk, *p_cid_history;
+					
+					p_readchunk = (unsigned int*)wc->chans[x].readchunk;
+					p_cid_history = (unsigned int*)(wc->cid_history_buf[x] + wc->cid_history_ptr[x]);*/
+					
+					if(wc->cid_state[x] == CID_STATE_IDLE)	/* we need copy data to the cid voice buffer */
+					{
+						memcpy(wc->cid_history_buf[x] + wc->cid_history_ptr[x], wc->chans[x]->readchunk, DAHDI_CHUNKSIZE);
+						wc->cid_history_ptr[x] = (wc->cid_history_ptr[x] + DAHDI_CHUNKSIZE)%(cidbuflen * DAHDI_MAX_CHUNKSIZE);
+					}
+					else if (wc->cid_state[x] == CID_STATE_RING_ON)
+						wc->cid_history_clone_cnt[x] = cidbuflen;
+					else if (wc->cid_state[x] == CID_STATE_RING_OFF)
+					{ 
+						if(wc->cid_history_clone_cnt[x])
+						{	
+							memcpy(wc->chans[x]->readchunk, wc->cid_history_buf[x] + wc->cid_history_ptr[x], DAHDI_MAX_CHUNKSIZE);
+							wc->cid_history_clone_cnt[x]--;
+							wc->cid_history_ptr[x] = (wc->cid_history_ptr[x] + DAHDI_MAX_CHUNKSIZE)%(cidbuflen * DAHDI_MAX_CHUNKSIZE);
+						}
+						else
+						{
+							wc->cid_state[x] = CID_STATE_WAIT_RING_FINISH;
+							wc->cid_history_clone_cnt[x] = cidtimeout; /* wait 6 sec, if no ring, return to idle */
+						}
+					}
+					else if(wc->cid_state[x] == CID_STATE_WAIT_RING_FINISH)
+					{
+						if(wc->cid_history_clone_cnt[x] > 0)
+							wc->cid_history_clone_cnt[x]--;
+						else
+						{
+							wc->cid_state[x] = CID_STATE_IDLE;
+							wc->cid_history_ptr[x] = 0;
+							wc->cid_history_clone_cnt[x] = 0;
+						}
+					}
+				}
+		}		
+	}
+	
 #ifdef AUDIO_RINGCHECK
-	for (x=0;x<wc->cards;x++)
+	for (x=0;x<wc->max_cards;x++)
 		ring_check(wc, x);
 #endif		
 	/* XXX We're wasting 8 taps.  We should get closer :( */
-	for (x = 0; x < NUM_CARDS; x++) {
+	for (x = 0; x < wc->max_cards/*MAX_NUM_CARDS*/; x++) {
 		if (wc->cardflag & (1 << x))
-			zt_ec_chunk(&wc->chans[x], wc->chans[x].readchunk, wc->chans[x].writechunk);
-	}
-	zt_receive(&wc->span);
+			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);
@@ -1003,6 +969,10 @@
 	int res;
 	/* Check loopback */
 	res = wc->reg1shadow[card];
+	
+	if (!res && (res != wc->mod[card].fxs.lasttxhook))     // read real state from register   By wx
+		res=wctdm_getreg(wc, card, 64);
+	
 	if (!res && (res != wc->mod[card].fxs.lasttxhook)) {
 		res = wctdm_getreg(wc, card, 8);
 		if (res) {
@@ -1049,30 +1019,101 @@
 		return;
 #ifndef AUDIO_RINGCHECK
 	if (!wc->mod[card].fxo.offhook) {
-		res = wc->reg0shadow[card];
-		if ((res & 0x60) && wc->mod[card].fxo.battery) {
-			wc->mod[card].fxo.ringdebounce += (ZT_CHUNKSIZE * 16);
-			if (wc->mod[card].fxo.ringdebounce >= ZT_CHUNKSIZE * 64) {
-				if (!wc->mod[card].fxo.wasringing) {
-					wc->mod[card].fxo.wasringing = 1;
-					zt_hooksig(&wc->chans[card], ZT_RXSIG_RING);
-					if (debug)
-						printk("RING on %d/%d!\n", wc->span.spanno, card + 1);
+		if (fwringdetect) {
+			res = wc->reg0shadow[card] & 0x60;
+			if (wc->mod[card].fxo.ringdebounce--) {
+				if (res && (res != wc->mod[card].fxo.lastrdtx) && (wc->mod[card].fxo.battery == 1)) {
+					if (!wc->mod[card].fxo.wasringing) {
+						wc->mod[card].fxo.wasringing = 1;
+						if (debug)
+							printk("RING on %d/%d!\n", wc->span.spanno, card + 1);
+						if(cidbeforering)
+						{
+							if(wc->cid_state[card] == CID_STATE_IDLE)
+								wc->cid_state[card] = CID_STATE_RING_ON;
+							else
+								dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_RING);
+						}
+						else
+							dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_RING);
+					}
+					wc->mod[card].fxo.lastrdtx = res;
+					wc->mod[card].fxo.ringdebounce = 10;
+				} else if (!res) {
+					if ((wc->mod[card].fxo.ringdebounce == 0) && wc->mod[card].fxo.wasringing) {
+						wc->mod[card].fxo.wasringing = 0;
+						if (debug)
+							printk("NO RING on %d/%d!\n", wc->span.spanno, card + 1);
+						if(cidbeforering)
+						{
+							if(wc->cid_state[card] == CID_STATE_RING_ON)
+							{
+								dahdi_qevent_lock(wc->chans[card], DAHDI_EVENT_POLARITY);
+								wc->cid_state[card] = CID_STATE_RING_OFF;
+							}
+							else 
+							{
+								if(wc->cid_state[card] == CID_STATE_WAIT_RING_FINISH)
+									wc->cid_history_clone_cnt[card] = cidtimeout;
+								dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_OFFHOOK);
+							}
+						}
+						else
+							dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_OFFHOOK);
+					}
 				}
-				wc->mod[card].fxo.ringdebounce = ZT_CHUNKSIZE * 64;
+			} else if (res && (wc->mod[card].fxo.battery == 1)) {
+				wc->mod[card].fxo.lastrdtx = res;
+				wc->mod[card].fxo.ringdebounce = 10;
 			}
 		} else {
-			wc->mod[card].fxo.ringdebounce -= ZT_CHUNKSIZE * 4;
-			if (wc->mod[card].fxo.ringdebounce <= 0) {
-				if (wc->mod[card].fxo.wasringing) {
-					wc->mod[card].fxo.wasringing = 0;
-					zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK);
-					if (debug)
-						printk("NO RING on %d/%d!\n", wc->span.spanno, card + 1);
+			res = wc->reg0shadow[card];
+			if ((res & 0x60) && (wc->mod[card].fxo.battery == 1)) {
+				wc->mod[card].fxo.ringdebounce += (DAHDI_CHUNKSIZE * 16);
+				if (wc->mod[card].fxo.ringdebounce >= DAHDI_CHUNKSIZE * ringdebounce) {
+					if (!wc->mod[card].fxo.wasringing) {
+						wc->mod[card].fxo.wasringing = 1;
+						if(cidbeforering)
+						{
+							if(wc->cid_state[card] == CID_STATE_IDLE)
+								wc->cid_state[card] = CID_STATE_RING_ON;
+							else
+								dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_RING);
+						}
+						else
+							dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_RING);
+						if (debug)
+							printk("RING on %d/%d!\n", wc->span.spanno, card + 1);
+					}
+					wc->mod[card].fxo.ringdebounce = DAHDI_CHUNKSIZE * ringdebounce;
 				}
-				wc->mod[card].fxo.ringdebounce = 0;
+			} else {
+				wc->mod[card].fxo.ringdebounce -= DAHDI_CHUNKSIZE * 4;
+				if (wc->mod[card].fxo.ringdebounce <= 0) {
+					if (wc->mod[card].fxo.wasringing) {
+						wc->mod[card].fxo.wasringing = 0;
+						if(cidbeforering)
+						{
+							if(wc->cid_state[card] == CID_STATE_RING_ON)
+							{
+								dahdi_qevent_lock(wc->chans[card], DAHDI_EVENT_POLARITY);
+								wc->cid_state[card] = CID_STATE_RING_OFF;
+							}
+							else 
+							{
+								if(wc->cid_state[card] == CID_STATE_WAIT_RING_FINISH)
+									wc->cid_history_clone_cnt[card] = cidtimeout;
+								dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_OFFHOOK);
+							}
+						}
+						else
+							dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_OFFHOOK);
+						if (debug)
+							printk("NO RING on %d/%d!\n", wc->span.spanno, card + 1);
+					}
+					wc->mod[card].fxo.ringdebounce = 0;
+				}
 			}
-				
 		}
 	}
 #endif
@@ -1089,7 +1130,7 @@
 	if (abs(b) < battthresh) {
 		wc->mod[card].fxo.nobatttimer++;
 #if 0
-		if (wc->mod[card].fxo.battery)
+		if (wc->mod[card].fxo.battery == 1)
 			printk("Battery loss: %d (%d debounce)\n", b, wc->mod[card].fxo.battdebounce);
 #endif
 		if (wc->mod[card].fxo.battery && !wc->mod[card].fxo.battdebounce) {
@@ -1098,7 +1139,7 @@
 			wc->mod[card].fxo.battery =  0;
 #ifdef	JAPAN
 			if ((!wc->ohdebounce) && wc->offhook) {
-				zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK);
+				dahdi_hooksig(&wc->chans[card], DAHDI_RXSIG_ONHOOK);
 				if (debug)
 					printk("Signalled On Hook\n");
 #ifdef	ZERO_BATT_RING
@@ -1106,30 +1147,32 @@
 #endif
 			}
 #else
-			zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK);
+			dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_ONHOOK);
+			dahdi_alarm_channel(wc->chans[card], DAHDI_ALARM_NONE);
 #endif
 			wc->mod[card].fxo.battdebounce = battdebounce;
 		} else if (!wc->mod[card].fxo.battery)
 			wc->mod[card].fxo.battdebounce = battdebounce;
 	} else if (abs(b) > battthresh) {
-		if (!wc->mod[card].fxo.battery && !wc->mod[card].fxo.battdebounce) {
+		if ((wc->mod[card].fxo.battery < 1)&& !wc->mod[card].fxo.battdebounce) {
 			if (debug)
 				printk("BATTERY on %d/%d (%s)!\n", wc->span.spanno, card + 1, 
 					(b < 0) ? "-" : "+");			    
 #ifdef	ZERO_BATT_RING
 			if (wc->onhook) {
 				wc->onhook = 0;
-				zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK);
+				dahdi_hooksig(&wc->chans[card], DAHDI_RXSIG_OFFHOOK);
 				if (debug)
 					printk("Signalled Off Hook\n");
 			}
 #else
-			zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK);
+			dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_OFFHOOK);
+			dahdi_alarm_channel(wc->chans[card], DAHDI_ALARM_NONE);
 #endif
 			wc->mod[card].fxo.battery = 1;
 			wc->mod[card].fxo.nobatttimer = 0;
 			wc->mod[card].fxo.battdebounce = battdebounce;
-		} else if (wc->mod[card].fxo.battery)
+		} else if (wc->mod[card].fxo.battery == 1)
 			wc->mod[card].fxo.battdebounce = battdebounce;
 
 		if (wc->mod[card].fxo.lastpol >= 0) {
@@ -1159,7 +1202,7 @@
 				       wc->mod[card].fxo.polarity, 
 				       wc->mod[card].fxo.lastpol);
 				if (wc->mod[card].fxo.polarity)
-				    zt_qevent_lock(&wc->chans[card], ZT_EVENT_POLARITY);
+				    dahdi_qevent_lock(wc->chans[card], DAHDI_EVENT_POLARITY);
 				wc->mod[card].fxo.polarity = wc->mod[card].fxo.lastpol;
 		    }
 		}
@@ -1184,7 +1227,7 @@
 #endif
 	} else {
 		if (wc->mod[card].fxs.debounce > 0) {
-			wc->mod[card].fxs.debounce-= 16 * ZT_CHUNKSIZE;
+			wc->mod[card].fxs.debounce-= 16 * DAHDI_CHUNKSIZE;
 #if 0
 			printk("Sustaining hook %d, %d\n", hook, wc->mod[card].fxs.debounce);
 #endif
@@ -1200,7 +1243,7 @@
 				if (debug)
 #endif				
 					printk("opvxa1200: Card %d Going off hook\n", card);
-				zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK);
+				dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_OFFHOOK);
 				if (robust)
 					wctdm_init_proslic(wc, card, 1, 0, 1);
 				wc->mod[card].fxs.oldrxhook = 1;
@@ -1211,7 +1254,7 @@
 				if (debug)
 #endif				
 					printk("opvxa1200: Card %d Going on hook\n", card);
-				zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK);
+				dahdi_hooksig(wc->chans[card], DAHDI_RXSIG_ONHOOK);
 				wc->mod[card].fxs.oldrxhook = 0;
 			}
 		}
@@ -1219,7 +1262,7 @@
 	wc->mod[card].fxs.lastrxhook = hook;
 }
 
-ZAP_IRQ_HANDLER(wctdm_interrupt)
+DAHDI_IRQ_HANDLER(wctdm_interrupt)
 {
 	struct wctdm *wc = dev_id;
 	unsigned char ints;
@@ -1227,36 +1270,25 @@
 	int mode;
 
 	ints = inb(wc->ioaddr + WC_INTSTAT);
+
+	if (!ints)
+		return IRQ_NONE;
+
 	outb(ints, wc->ioaddr + WC_INTSTAT);
-
-	if (!ints)
-#ifdef LINUX26
-		return IRQ_NONE;
-#else
-		return;
-#endif		
-
+	
 	if (ints & 0x10) {
 		/* Stop DMA, wait for watchdog */
 		printk("TDM PCI Master abort\n");
 		wctdm_stop_dma(wc);
-#ifdef LINUX26
 		return IRQ_RETVAL(1);
-#else
-		return;
-#endif		
 	}
 	
 	if (ints & 0x20) {
 		printk("PCI Target abort\n");
-#ifdef LINUX26
 		return IRQ_RETVAL(1);
-#else
-		return;
-#endif		
-	}
-
-	for (x=0;x<4*3;x++) {
+	}
+
+	for (x=0;x<wc->max_cards/*4*3*/;x++) {
 		if (wc->cardflag & (1 << x) &&
 		    (wc->modtype[x] == MOD_TYPE_FXS)) {
 			if (wc->mod[x].fxs.lasttxhook == 0x4) {
@@ -1268,13 +1300,13 @@
 					wc->mod[x].fxs.idletxhookstate = 0x2; 
 			} else {
 				if (wc->mod[x].fxs.ohttimer) {
-					wc->mod[x].fxs.ohttimer-= ZT_CHUNKSIZE;
+					wc->mod[x].fxs.ohttimer-= DAHDI_CHUNKSIZE;
 					if (!wc->mod[x].fxs.ohttimer) {
 						if (reversepolarity)
 							wc->mod[x].fxs.idletxhookstate = 0x5;	/* Switch to active */
 						else
 							wc->mod[x].fxs.idletxhookstate = 0x1;
-						if ((wc->mod[x].fxs.lasttxhook == 0x2) || (wc->mod[x].fxs.lasttxhook = 0x6)) {
+						if ((wc->mod[x].fxs.lasttxhook == 0x2) || (wc->mod[x].fxs.lasttxhook == 0x6)) {
 							/* Apply the change if appropriate */
 							if (reversepolarity) 
 								wc->mod[x].fxs.lasttxhook = 0x5;
@@ -1292,7 +1324,7 @@
 		wc->intcount++;
 		z = wc->intcount & 0x3;
 		mode = wc->intcount & 0xc;
-		for(y=0; y<3; y++)
+		for(y=0; y<wc->max_cards/4/*3*/; y++)
 		{
 			x = z + y*4;
 			if (wc->cardflag & (1 << x ) ) 
@@ -1322,7 +1354,7 @@
 						wctdm_proslic_check_hook(wc, x);
 						if (!(wc->intcount & 0xf0))
 							wctdm_proslic_recheck_sanity(wc, x);
-						} else if (wc->modtype[x] == MOD_TYPE_FXO) {
+					} else if (wc->modtype[x] == MOD_TYPE_FXO) {
 						wctdm_voicedaa_check_hook(wc, x);
 					}
 					break;
@@ -1331,7 +1363,7 @@
 		}
 		if (!(wc->intcount % 10000)) {
 			/* Accept an alarm once per 10 seconds */
-			for (x=0;x<4*3;x++) 
+			for (x=0;x<wc->max_cards/*4*3*/;x++) 
 				if (wc->modtype[x] == MOD_TYPE_FXS) {
 					if (wc->mod[x].fxs.palarms)
 						wc->mod[x].fxs.palarms--;
@@ -1340,10 +1372,9 @@
 		wctdm_receiveprep(wc, ints);
 		wctdm_transmitprep(wc, ints);
 	}
-#ifdef LINUX26
+
 	return IRQ_RETVAL(1);
-#endif		
-	
+
 }
 
 static int wctdm_voicedaa_insane(struct wctdm *wc, int card)
@@ -1381,10 +1412,10 @@
 		printk("ProSLIC 3210 version %d is too old\n", blah & 0xf);
 		return -1;
 	}
-	if ((blah & 0xf) == 2) {
-		/* ProSLIC 3215, not a 3210 */
+	if (wctdm_getreg(wc, card, 1) & 0x80)
+	/* ProSLIC 3215, not a 3210 */
 		wc->flags[card] |= FLAG_3215;
-	}
+	
 	blah = wctdm_getreg(wc, card, 8);
 	if (blah != 0x2) {
 		printk("ProSLIC on module %d insane (1) %d should be 2\n", card, blah);
@@ -1630,12 +1661,56 @@
 	while(jiffies < newjiffies);
 }
 
+/*********************************************************************
+ * Set the hwgain on the analog modules
+ *
+ * card = the card position for this module (0-23)
+ * gain = gain in dB x10 (e.g. -3.5dB  would be gain=-35)
+ * tx = (0 for rx; 1 for tx)
+ *
+ *******************************************************************/
+static int wctdm_set_hwgain(struct wctdm *wc, int card, __s32 gain, __u32 tx)
+{
+	if (!(wc->modtype[card] == MOD_TYPE_FXO)) {
+		printk("Cannot adjust gain.  Unsupported module type!\n");
+		return -1;
+	}
+	if (tx) {
+		if (debug)
+			printk("setting FXO tx gain for card=%d to %d\n", card, gain);
+		if (gain >=  -150 && gain <= 0) {
+			wctdm_setreg(wc, card, 38, 16 + (gain/-10));
+			wctdm_setreg(wc, card, 40, 16 + (-gain%10));
+		} else if (gain <= 120 && gain > 0) {
+			wctdm_setreg(wc, card, 38, gain/10);
+			wctdm_setreg(wc, card, 40, (gain%10));
+		} else {
+			printk("FXO tx gain is out of range (%d)\n", gain);
+			return -1;
+		}
+	} else { /* rx */
+		if (debug)
+			printk("setting FXO rx gain for card=%d to %d\n", card, gain);
+		if (gain >=  -150 && gain <= 0) {
+			wctdm_setreg(wc, card, 39, 16+ (gain/-10));
+			wctdm_setreg(wc, card, 41, 16 + (-gain%10));
+		} else if (gain <= 120 && gain > 0) {
+			wctdm_setreg(wc, card, 39, gain/10);
+			wctdm_setreg(wc, card, 41, (gain%10));
+		} else {
+			printk("FXO rx gain is out of range (%d)\n", gain);
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
 static int wctdm_init_voicedaa(struct wctdm *wc, int card, int fast, int manual, int sane)
 {
 	unsigned char reg16=0, reg26=0, reg30=0, reg31=0;
 	long newjiffies;
 	wc->modtype[card] = MOD_TYPE_FXO;
-	
 	/* Sanity check the ProSLIC */
 	reset_spi(wc, card);
 	if (!sane && wctdm_voicedaa_insane(wc, card))
@@ -1658,6 +1733,16 @@
 	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 */
@@ -1666,12 +1751,16 @@
 	reg26 |= (fxo_modes[_opermode].ilim << 1);
 	wctdm_setreg(wc, card, 26, reg26);
 
-	/* Set AC Impedence */
-	reg30 = (fxo_modes[_opermode].acim);
+	/* Set AC Impedence */ 
+	reg30 = (fxofullscale==1) ? (fxo_modes[_opermode].acim|0x10) :  (fxo_modes[_opermode].acim);
 	wctdm_setreg(wc, card, 30, reg30);
 
 	/* Misc. DAA parameters */
-	reg31 = 0xa3;
+	if (fastpickup)
+		reg31 = 0xb3;
+	else
+		reg31 = 0xa3;
+
 	reg31 |= (fxo_modes[_opermode].ohs2 << 3);
 	wctdm_setreg(wc, card, 31, reg31);
 
@@ -1685,6 +1774,9 @@
 	/* 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;
@@ -1702,11 +1794,21 @@
 	/* Enable on-hook line monitor */
 	wctdm_setreg(wc, card, 5, 0x08);
 
+	/* Take values for fxotxgain and fxorxgain and apply them to module */
+	wctdm_set_hwgain(wc, card, fxotxgain, 1);
+	wctdm_set_hwgain(wc, card, fxorxgain, 0);
+
 	/* NZ -- crank the tx gain up by 7 dB */
 	if (!strcmp(fxo_modes[_opermode].name, "NEWZEALAND")) {
 		printk("Adjusting gain\n");
-		wctdm_setreg(wc, card, 38, 0x7);
-	}
+		wctdm_set_hwgain(wc, card, 7, 1);
+	}
+
+	if(debug)
+		printk("DEBUG fxotxgain:%i.%i fxorxgain:%i.%i\n", (wctdm_getreg(wc, card, 38)/16)?-(wctdm_getreg(wc, card, 38) - 16) : wctdm_getreg(wc, card, 38), (wctdm_getreg(wc, card, 40)/16)? -(wctdm_getreg(wc, card, 40) - 16):wctdm_getreg(wc, card, 40), (wctdm_getreg(wc, card, 39)/16)? -(wctdm_getreg(wc, card, 39) - 16) : wctdm_getreg(wc, card, 39),(wctdm_getreg(wc, card, 41)/16)?-(wctdm_getreg(wc, card, 41) - 16):wctdm_getreg(wc, card, 41));
+
+	/* battery state still unknown */
+	wc->mod[card].fxo.battery = -1;
 
 	return 0;
 		
@@ -1716,20 +1818,19 @@
 {
 
 	unsigned short tmp[5];
-	unsigned char r19;
+	unsigned char r19, r9;
 	int x;
 	int fxsmode=0;
 
+	/* Sanity check the ProSLIC */
+	if (!sane && wctdm_proslic_insane(wc, card))
+		return -2;
 
 	/* By default, don't send on hook */
 	if (reversepolarity)
 		wc->mod[card].fxs.idletxhookstate = 5;
 	else
 		wc->mod[card].fxs.idletxhookstate = 1;
-
-	/* Sanity check the ProSLIC */
-	if (!sane && wctdm_proslic_insane(wc, card))
-		return -2;
 		
 	if (sane) {
 		/* Make sure we turn off the DC->DC converter to prevent anything from blowing up */
@@ -1752,7 +1853,8 @@
 
 	/* Disable automatic VBat switching for safety to prevent
 	   Q7 from accidently turning on and burning out. */
-	wctdm_setreg(wc, card, 67, 0x17);
+	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);
@@ -1849,9 +1951,7 @@
     	wctdm_setreg(wc, card, 1, 0x20);
     else
     	wctdm_setreg(wc, card, 1, 0x28);
- 	// U-Law 8-bit interface
-	
-    //printk("set card %d to %d\n", card, (3-(card%4)) * 8 + (card/4) * 64);
+  // U-Law 8-bit interface
     wctdm_setreg(wc, card, 2, (3-(card%4)) * 8 + (card/4) * 64);    // 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%4)) * 8 + (card/4) * 64);    // Rx Start count low byte  0
@@ -1885,31 +1985,83 @@
     wctdm_setreg(wc, card, 1, 0x08);
 #endif
 
-	/* Beef up Ringing voltage to 89V */
-	if (boostringer) {
-		if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x1d1)) 
-			return -1;
-		printk("Boosting ringinger on slot %d (89V peak)\n", card + 1);
-	} else if (lowpower) {
-		if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x108)) 
-			return -1;
-		printk("Reducing ring power on slot %d (50V peak)\n", card + 1);
-	}
+	if (fastringer) {
+		/* Speed up Ringer */
+		wctdm_proslic_setreg_indirect(wc, card, 20, 0x7e6d);
+		wctdm_proslic_setreg_indirect(wc, card, 21, 0x01b9);
+		/* Beef up Ringing voltage to 89V */
+		if (boostringer) {
+			wctdm_setreg(wc, card, 74, 0x3f);
+			if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x247)) 
+				return -1;
+			printk("Boosting fast ringer on slot %d (89V peak)\n", card + 1);
+		} else if (lowpower) {
+			if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x14b)) 
+				return -1;
+			printk("Reducing fast ring power on slot %d (50V peak)\n", card + 1);
+		} else
+			printk("Speeding up ringer on slot %d (25Hz)\n", card + 1);
+	} else {
+		/* Beef up Ringing voltage to 89V */
+		if (boostringer) {
+			wctdm_setreg(wc, card, 74, 0x3f);
+			if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x1d1)) 
+				return -1;
+			printk("Boosting ringer on slot %d (89V peak)\n", card + 1);
+		} else if (lowpower) {
+			if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x108)) 
+				return -1;
+			printk("Reducing ring power on slot %d (50V peak)\n", card + 1);
+		}
+	}
+
+	if(fxstxgain || fxsrxgain) {
+		r9 = wctdm_getreg(wc, card, 9);
+		switch (fxstxgain) {
+		
+			case 35:
+				r9+=8;
+				break;
+			case -35:
+				r9+=4;
+				break;
+			case 0: 
+				break;
+		}
+	
+		switch (fxsrxgain) {
+			
+			case 35:
+				r9+=2;
+				break;
+			case -35:
+				r9+=1;
+				break;
+			case 0:
+				break;
+		}
+		wctdm_setreg(wc,card,9,r9);
+	}
+
+	if(debug)
+		printk("DEBUG: fxstxgain:%s fxsrxgain:%s\n",((wctdm_getreg(wc, card, 9)/8) == 1)?"3.5":(((wctdm_getreg(wc,card,9)/4) == 1)?"-3.5":"0.0"),((wctdm_getreg(wc, card, 9)/2) == 1)?"3.5":((wctdm_getreg(wc,card,9)%2)?"-3.5":"0.0"));
+
 	wctdm_setreg(wc, card, 64, 0x01);
 	return 0;
 }
 
 
-static int wctdm_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data)
+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 ZT_ONHOOKTRANSFER:
+	case DAHDI_ONHOOKTRANSFER:
 		if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS)
 			return -EINVAL;
 		if (get_user(x, (int *)data))
@@ -1919,7 +2071,7 @@
 			wc->mod[chan->chanpos - 1].fxs.idletxhookstate = 0x6;	/* OHT mode when idle */
 		else
 			wc->mod[chan->chanpos - 1].fxs.idletxhookstate = 0x2;
-		if (wc->mod[chan->chanpos - 1].fxs.lasttxhook == 0x1) {
+		if (wc->mod[chan->chanpos - 1].fxs.lasttxhook == 0x1 || wc->mod[chan->chanpos - 1].fxs.lasttxhook == 0x5) {
 				/* Apply the change if appropriate */
 				if (reversepolarity)
 					wc->mod[chan->chanpos - 1].fxs.lasttxhook = 0x6;
@@ -1928,7 +2080,7 @@
 				wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mod[chan->chanpos - 1].fxs.lasttxhook);
 		}
 		break;
-	case ZT_SETPOLARITY:
+	case DAHDI_SETPOLARITY:
 		if (get_user(x, (int *)data))
 			return -EFAULT;
 		if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS)
@@ -1993,7 +2145,7 @@
 
 		if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) {
 			/* Set the ACIM register */
-			wctdm_setreg(wc, chan->chanpos - 1, 30, echoregs.acim);
+			wctdm_setreg(wc, chan->chanpos - 1, 30, (fxofullscale==1) ? (echoregs.acim|0x10) : echoregs.acim);
 
 			/* Set the digital echo canceller registers */
 			wctdm_setreg(wc, chan->chanpos - 1, 45, echoregs.coef1);
@@ -2013,6 +2165,16 @@
 
 		}
 		break;
+	case DAHDI_SET_HWGAIN:
+		if (copy_from_user(&hwgain, (struct dahdi_hwgain*) data, sizeof(hwgain)))
+			return -EFAULT;
+
+		wctdm_set_hwgain(wc, chan->chanpos-1, hwgain.newgain, hwgain.tx);
+
+		if (debug)
+			printk("Setting hwgain on channel %d to %d for %s direction\n", 
+				chan->chanpos-1, hwgain.newgain, hwgain.tx ? "tx" : "rx");
+		break;
 	default:
 		return -ENOTTY;
 	}
@@ -2020,7 +2182,7 @@
 
 }
 
-static int wctdm_open(struct zt_chan *chan)
+static int wctdm_open(struct dahdi_chan *chan)
 {
 	struct wctdm *wc = chan->pvt;
 	if (!(wc->cardflag & (1 << (chan->chanpos - 1))))
@@ -2028,30 +2190,27 @@
 	if (wc->dead)
 		return -ENODEV;
 	wc->usecount++;
-#ifndef LINUX26
-	MOD_INC_USE_COUNT;
-#else
+
+	/*MOD_INC_USE_COUNT; */
 	try_module_get(THIS_MODULE);
-#endif	
 	return 0;
 }
 
-static int wctdm_watchdog(struct zt_span *span, int event)
+static int wctdm_watchdog(struct dahdi_span *span, int event)
 {
 	printk("opvxa1200: Restarting DMA\n");
 	wctdm_restart_dma(span->pvt);
 	return 0;
 }
 
-static int wctdm_close(struct zt_chan *chan)
+static int wctdm_close(struct dahdi_chan *chan)
 {
 	struct wctdm *wc = chan->pvt;
 	wc->usecount--;
-#ifndef LINUX26
-	MOD_DEC_USE_COUNT;
-#else
+
+	/*MOD_DEC_USE_COUNT;*/
 	module_put(THIS_MODULE);
-#endif
+
 	if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) {
 		if (reversepolarity)
 			wc->mod[chan->chanpos - 1].fxs.idletxhookstate = 5;
@@ -2064,19 +2223,26 @@
 	return 0;
 }
 
-static int wctdm_hooksig(struct zt_chan *chan, zt_txsig_t txsig)
+static int wctdm_hooksig(struct dahdi_chan *chan, enum dahdi_txsig txsig)
 {
 	struct wctdm *wc = chan->pvt;
 	int reg=0;
 	if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) {
 		/* XXX Enable hooksig for FXO XXX */
 		switch(txsig) {
-		case ZT_TXSIG_START:
-		case ZT_TXSIG_OFFHOOK:
+		case DAHDI_TXSIG_START:
+		case DAHDI_TXSIG_OFFHOOK:
 			wc->mod[chan->chanpos - 1].fxo.offhook = 1;
 			wctdm_setreg(wc, chan->chanpos - 1, 5, 0x9);
+			if(cidbeforering)
+			{
+				wc->cid_state[chan->chanpos - 1] = CID_STATE_IDLE;
+				wc->cid_history_clone_cnt[chan->chanpos - 1] = 0;
+				wc->cid_history_ptr[chan->chanpos - 1] = 0;
+				memset(wc->cid_history_buf[chan->chanpos - 1], DAHDI_LIN2X(0, chan), cidbuflen * DAHDI_MAX_CHUNKSIZE);
+			}
 			break;
-		case ZT_TXSIG_ONHOOK:
+		case DAHDI_TXSIG_ONHOOK:
 			wc->mod[chan->chanpos - 1].fxo.offhook = 0;
 			wctdm_setreg(wc, chan->chanpos - 1, 5, 0x8);
 			break;
@@ -2085,21 +2251,21 @@
 		}
 	} else {
 		switch(txsig) {
-		case ZT_TXSIG_ONHOOK:
+		case DAHDI_TXSIG_ONHOOK:
 			switch(chan->sig) {
-			case ZT_SIG_EM:
-			case ZT_SIG_FXOKS:
-			case ZT_SIG_FXOLS:
+			case DAHDI_SIG_EM:
+			case DAHDI_SIG_FXOKS:
+			case DAHDI_SIG_FXOLS:
 				wc->mod[chan->chanpos-1].fxs.lasttxhook = wc->mod[chan->chanpos-1].fxs.idletxhookstate;
 				break;
-			case ZT_SIG_FXOGS:
+			case DAHDI_SIG_FXOGS:
 				wc->mod[chan->chanpos-1].fxs.lasttxhook = 3;
 				break;
 			}
 			break;
-		case ZT_TXSIG_OFFHOOK:
+		case DAHDI_TXSIG_OFFHOOK:
 			switch(chan->sig) {
-			case ZT_SIG_EM:
+			case DAHDI_SIG_EM:
 				wc->mod[chan->chanpos-1].fxs.lasttxhook = 5;
 				break;
 			default:
@@ -2107,10 +2273,10 @@
 				break;
 			}
 			break;
-		case ZT_TXSIG_START:
+		case DAHDI_TXSIG_START:
 			wc->mod[chan->chanpos-1].fxs.lasttxhook = 4;
 			break;
-		case ZT_TXSIG_KEWL:
+		case DAHDI_TXSIG_KEWL:
 			wc->mod[chan->chanpos-1].fxs.lasttxhook = 0;
 			break;
 		default:
@@ -2132,31 +2298,50 @@
 
 	/* Zapata stuff */
 	sprintf(wc->span.name, "OPVXA1200/%d", wc->pos);
-	sprintf(wc->span.desc, "%s Board %d", wc->variety, wc->pos + 1);
+	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 = "OpenVox";
+	strncpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype) - 1);
 	if (alawoverride) {
 		printk("ALAW override parameter detected.  Device will be operating in ALAW\n");
-		wc->span.deflaw = ZT_LAW_ALAW;
+		wc->span.deflaw = DAHDI_LAW_ALAW;
 	} else
-		wc->span.deflaw = ZT_LAW_MULAW;
-	for (x = 0; x < NUM_CARDS; x++) {
-		sprintf(wc->chans[x].name, "OPVXA1200/%d/%d", wc->pos, x);
-		wc->chans[x].sigcap = ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_SF | ZT_SIG_EM | ZT_SIG_CLEAR;
-		wc->chans[x].sigcap |= ZT_SIG_FXSKS | ZT_SIG_FXSLS | ZT_SIG_SF | ZT_SIG_CLEAR;
-		wc->chans[x].chanpos = x+1;
-		wc->chans[x].pvt = wc;
+		wc->span.deflaw = DAHDI_LAW_MULAW;
+		
+	x = __wctdm_getcreg(wc, WC_VER);
+	wc->fwversion = x;
+	if( x & FLAG_A800)
+	{
+		wc->card_name = A800P_Name;
+		wc->max_cards = 8;
+	}
+	else
+	{
+		wc->card_name = A1200P_Name;
+		wc->max_cards = 12;
+	}
+		
+	for (x = 0; x < wc->max_cards/*MAX_NUM_CARDS*/; x++) {
+		sprintf(wc->chans[x]->name, "OPVXA1200/%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.channels = wc->max_cards;	/*MAX_NUM_CARDS;*/
 	wc->span.hooksig = wctdm_hooksig;
+	wc->span.irq = wc->dev->irq;
 	wc->span.open = wctdm_open;
 	wc->span.close = wctdm_close;
-	wc->span.flags = ZT_FLAG_RBS;
+	wc->span.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 (zt_register(&wc->span, 0)) {
+	if (dahdi_register(&wc->span, 0)) {
 		printk("Unable to register span with zaptel\n");
 		return -1;
 	}
@@ -2166,13 +2351,16 @@
 static void wctdm_post_initialize(struct wctdm *wc)
 {
 	int x;
+
 	/* Finalize signalling  */
-	for (x = 0; x < NUM_CARDS; x++) {
+	for (x = 0; x < wc->max_cards/*MAX_NUM_CARDS*/; x++) {
 		if (wc->cardflag & (1 << x)) {
 			if (wc->modtype[x] == MOD_TYPE_FXO)
-				wc->chans[x].sigcap = ZT_SIG_FXSKS | ZT_SIG_FXSLS | ZT_SIG_SF | ZT_SIG_CLEAR;
+				wc->chans[x]->sigcap = DAHDI_SIG_FXSKS | DAHDI_SIG_FXSLS | DAHDI_SIG_SF | DAHDI_SIG_CLEAR;
 			else
-				wc->chans[x].sigcap = ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_SF | ZT_SIG_EM | ZT_SIG_CLEAR;
+				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;
 		}
 	}
 }
@@ -2205,7 +2393,18 @@
 	x=inb(wc->ioaddr + WC_CNTL);
 	ver = __wctdm_getcreg(wc, WC_VER);
 	wc->fwversion = ver;
-	printk("OpenVox A1200P version: %01x.%01x\n", ver>>4, ver&0x0f);
+	/*if( ver & FLAG_A800)
+	{
+		wc->card_name = A800P_Name;
+		wc->max_cards = 8;
+	}
+	else
+	{
+		wc->card_name = A1200P_Name;
+		wc->max_cards = 12;
+	}*/
+	printk("OpenVox %s version: %01x.%01x\n", wc->card_name, (ver&(~FLAG_A800))>>4, ver&0x0f);
+	
 	failed = 0;
 	if (ver != 0x00) {
 		for (x=0;x<16;x++) {
@@ -2219,9 +2418,9 @@
 		}
 
 		if (!failed) {
-			printk("OpenVox A1200P passed register test\n");
+			printk("OpenVox %s passed register test\n", wc->card_name);
 		} else {
-			printk("OpenVox A1200P failed register test\n");
+			printk("OpenVox %s failed register test\n", wc->card_name);
 			return -1;
 		}
 	} else {
@@ -2243,8 +2442,8 @@
 	/* Set all to outputs except AUX 5, which is an input */
 	outb(0xdf, wc->ioaddr + WC_AUXC);
 
-	/* Select alternate function for AUX0 *///MiaoLin modify it to normal io line.
-	//outb(0x4, wc->ioaddr + WC_AUXFUNC);
+	/* Select alternate function for AUX0 */  /* Useless in OpenVox by MiaoLin. */
+	/* outb(0x4, wc->ioaddr + WC_AUXFUNC); */
 	
 	/* Wait 1/4 of a sec */
 	wait_just_a_bit(HZ/4);
@@ -2255,24 +2454,22 @@
 	wctdm_set_led(wc, 0, 0);
 	
 	/* Make sure serial port and DMA are out of reset */
-	outb(inb(wc->ioaddr + WC_CNTL) & 0xf9, WC_CNTL);
+	outb(inb(wc->ioaddr + WC_CNTL) & 0xf9, wc->ioaddr + WC_CNTL);
 	
 	/* Configure serial port for MSB->LSB operation */
-	//outb(0xc1, wc->ioaddr + WC_SERCTL);
 	outb(0xc1, wc->ioaddr + WC_SERCTL);
 
 	/* Delay FSC by 0 so it's properly aligned */
-	//outb(0x0, wc->ioaddr + WC_FSCDELAY);
-	outb(0x01, wc->ioaddr + WC_FSCDELAY);
+	outb(0x01, wc->ioaddr + WC_FSCDELAY);  /* Modify to 1 by MiaoLin */
 
 	/* Setup DMA Addresses */
 	outl(wc->writedma,                    wc->ioaddr + WC_DMAWS);		/* Write start */
-	outl(wc->writedma + ZT_CHUNKSIZE * 4 * 4 - 4, wc->ioaddr + WC_DMAWI);		/* Middle (interrupt) */
-	outl(wc->writedma + ZT_CHUNKSIZE * 8 * 4 - 4, wc->ioaddr + WC_DMAWE);			/* End */
+	outl(wc->writedma + DAHDI_CHUNKSIZE * 4 * 4 - 4, wc->ioaddr + WC_DMAWI);		/* Middle (interrupt) */
+	outl(wc->writedma + DAHDI_CHUNKSIZE * 8 * 4 - 4, wc->ioaddr + WC_DMAWE);			/* End */
 	
 	outl(wc->readdma,                    	 wc->ioaddr + WC_DMARS);	/* Read start */
-	outl(wc->readdma + ZT_CHUNKSIZE * 4 * 4 - 4, 	 wc->ioaddr + WC_DMARI);	/* Middle (interrupt) */
-	outl(wc->readdma + ZT_CHUNKSIZE * 8 * 4 - 4, wc->ioaddr + WC_DMARE);	/* End */
+	outl(wc->readdma + DAHDI_CHUNKSIZE * 4 * 4 - 4, 	 wc->ioaddr + WC_DMARI);	/* Middle (interrupt) */
+	outl(wc->readdma + DAHDI_CHUNKSIZE * 8 * 4 - 4, wc->ioaddr + WC_DMARE);	/* End */
 	
 	/* Clear interrupts */
 	outb(0xff, wc->ioaddr + WC_INTSTAT);
@@ -2280,7 +2477,7 @@
 	/* Wait 1/4 of a second more */
 	wait_just_a_bit(HZ/4);
 
-	for (x = 0; x < NUM_CARDS; x++) {
+	for (x = 0; x < wc->max_cards/*MAX_NUM_CARDS*/; x++) {
 		int sane=0,ret=0,readi=0;
 #if 1
 		/* Init with Auto Calibration */
@@ -2309,6 +2506,7 @@
 					printk("Module %d: Installed -- MANUAL FXS\n",x);
 				} else {
 					printk("Module %d: FAILED FXS (%s)\n", x, fxshonormode ? fxo_modes[_opermode].name : "FCC");
+					wc->chans[x]->sigcap = __DAHDI_SIG_FXO | DAHDI_SIG_BROKEN;
 				} 
 			} else if (!(ret = wctdm_init_voicedaa(wc, x, 0, 0, sane))) {
 				wc->cardflag |= (1 << x);
@@ -2323,7 +2521,7 @@
 	/* Return error if nothing initialized okay. */
 	if (!wc->cardflag && !timingonly)
 		return -1;
-	//__wctdm_setcreg(wc, WC_SYNC, (wc->cardflag << 1) | 0x1);
+	/*__wctdm_setcreg(wc, WC_SYNC, (wc->cardflag << 1) | 0x1); */  /* removed by MiaoLin */
 	return 0;
 }
 
@@ -2333,7 +2531,7 @@
 	outb(0xff, wc->ioaddr + WC_INTSTAT);
 
 	/* Enable interrupts (we care about all of them) */
-	outb(0x3c /*0x3f*/, wc->ioaddr + WC_MASK0);
+	outb(0x3c, wc->ioaddr + WC_MASK0);
 	/* No external interrupts */
 	outb(0x00, wc->ioaddr + WC_MASK1);
 }
@@ -2400,12 +2598,15 @@
 		if (wc) {
 			int cardcount = 0;
 			
-			//wc->offset = 12;	// miaolin add.
-			wc->lastchan = -1;	// first channel offset = -1;
+			wc->lastchan = -1;	/* first channel offset = -1; */
 			wc->ledstate = 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);
@@ -2415,7 +2616,7 @@
 			wc->dev = pdev;
 			wc->pos = x;
 			wc->variety = d->name;
-			for (y=0;y<NUM_CARDS;y++)
+			for (y=0;y<MAX_NUM_CARDS;y++)
 				wc->flags[y] = d->flags;
 			/* Keep track of whether we need to free the region */
 			if (request_region(wc->ioaddr, 0xff, "opvxa1200")) 
@@ -2428,12 +2629,12 @@
 
 			/* Allocate enough memory for two zt chunks, receive and transmit.  Each sample uses
 			   8 bits.  */
-			wc->writechunk = pci_alloc_consistent(pdev, ZT_MAX_CHUNKSIZE * (NUM_CARDS+NUM_FLAG) * 2 * 2, &wc->writedma);
+			wc->writechunk = pci_alloc_consistent(pdev, DAHDI_MAX_CHUNKSIZE * (MAX_NUM_CARDS+NUM_FLAG) * 2 * 2, &wc->writedma);
 			if (!wc->writechunk) {
 				printk("opvxa1200: Unable to allocate DMA-able memory\n");
 				if (wc->freeregion & 0x01)
 					release_region(wc->ioaddr, 0xff);
-				if (wc->freeregion & 0x02);
+				if (wc->freeregion & 0x02)
 				{
 					release_mem_region(wc->mem_region, wc->mem_len);
 					iounmap((void *)wc->mem32);
@@ -2441,8 +2642,8 @@
 				return -ENOMEM;
 			}
 
-			wc->readchunk = wc->writechunk + ZT_MAX_CHUNKSIZE * (NUM_CARDS+NUM_FLAG) * 2;	/* in bytes */
-			wc->readdma = wc->writedma + ZT_MAX_CHUNKSIZE * (NUM_CARDS+NUM_FLAG) * 2;	/* in bytes */
+			wc->readchunk = wc->writechunk + DAHDI_MAX_CHUNKSIZE * (MAX_NUM_CARDS+NUM_FLAG) * 2;	/* in bytes */
+			wc->readdma = wc->writedma + DAHDI_MAX_CHUNKSIZE * (MAX_NUM_CARDS+NUM_FLAG) * 2;	/* in bytes */
 			
 			if (wctdm_initialize(wc)) {
 				printk("opvxa1200: Unable to intialize FXS\n");
@@ -2453,14 +2654,11 @@
 				free_irq(pdev->irq, wc);
 				if (wc->freeregion & 0x01)
 					release_region(wc->ioaddr, 0xff);
-				if (wc->freeregion & 0x02);
+				if (wc->freeregion & 0x02)
 				{
 					release_mem_region(wc->mem_region, wc->mem_len);
 					iounmap((void *)wc->mem32);
 				}
-				pci_free_consistent(pdev,  ZT_MAX_CHUNKSIZE * (NUM_CARDS+NUM_FLAG) * 2 * 2, (void *)wc->writechunk, wc->writedma);
-				kfree(wc);
-				return -EIO;
 			}
 
 			/* Enable bus mastering */
@@ -2469,21 +2667,21 @@
 			/* Keep track of which device we are */
 			pci_set_drvdata(pdev, wc);
 
-			if (request_irq(pdev->irq, wctdm_interrupt, ZAP_IRQ_SHARED, "opvxa1200", wc)) {
+
+			if (request_irq(pdev->irq, wctdm_interrupt, DAHDI_IRQ_SHARED, "opvxa1200", wc)) {
 				printk("opvxa1200: Unable to request IRQ %d\n", pdev->irq);
 				if (wc->freeregion & 0x01)
 					release_region(wc->ioaddr, 0xff);
-				if (wc->freeregion & 0x02);
+				if (wc->freeregion & 0x02)
 				{
 					release_mem_region(wc->mem_region, wc->mem_len);
 					iounmap((void *)wc->mem32);
 				}
-				pci_free_consistent(pdev,  ZT_MAX_CHUNKSIZE * (NUM_CARDS+NUM_FLAG) * 2 * 2, (void *)wc->writechunk, wc->writedma);
+				pci_free_consistent(pdev,  DAHDI_MAX_CHUNKSIZE * (MAX_NUM_CARDS+NUM_FLAG) * 2 * 2, (void *)wc->writechunk, wc->writedma);
 				pci_set_drvdata(pdev, NULL);
 				kfree(wc);
 				return -EIO;
 			}
-
 
 			if (wctdm_hardware_init(wc)) {
 				unsigned char x;
@@ -2495,43 +2693,59 @@
 				free_irq(pdev->irq, wc);
 				if (wc->freeregion & 0x01)
 					release_region(wc->ioaddr, 0xff);
-				if (wc->freeregion & 0x02);
+				if (wc->freeregion & 0x02)
 				{
 					release_mem_region(wc->mem_region, wc->mem_len);
 					iounmap((void *)wc->mem32);
 				}
-				pci_free_consistent(pdev,  ZT_MAX_CHUNKSIZE * (NUM_CARDS+NUM_FLAG) * 2 * 2, (void *)wc->writechunk, wc->writedma);
+				pci_free_consistent(pdev,  DAHDI_MAX_CHUNKSIZE * (MAX_NUM_CARDS+NUM_FLAG) * 2 * 2, (void *)wc->writechunk, wc->writedma);
 				pci_set_drvdata(pdev, NULL);
-				zt_unregister(&wc->span);
+				dahdi_unregister(&wc->span);
 				kfree(wc);
 				return -EIO;
 
 			}
 
 #ifdef TEST_LOG_INCOME_VOICE
-			for(i=0; i<NUM_CARDS+NUM_FLAG; i++)
+			for(x=0; x<MAX_NUM_CARDS+NUM_FLAG; x++)
 			{
-				wc->voc_buf[i] = kmalloc(voc_buffer_size, GFP_KERNEL);
-				wc->voc_ptr[i] = 0;
+				wc->voc_buf[x] = kmalloc(voc_buffer_size, GFP_KERNEL);
+				wc->voc_ptr[x] = 0;
 			}
 #endif
+
+			if(cidbeforering) 
+			{		
+				int len = cidbuflen * DAHDI_MAX_CHUNKSIZE;
+				if(debug)
+					printk("cidbeforering support enabled, length is %d msec\n", cidbuflen);
+				for (x = 0; x < wc->max_cards/*MAX_NUM_CARDS*/; x++) 
+				{
+					wc->cid_history_buf[x] = kmalloc(len, GFP_KERNEL);
+					wc->cid_history_ptr[x] = 0;
+					wc->cid_history_clone_cnt[x] = 0;
+					wc->cid_state[x] = CID_STATE_IDLE;
+				}
+			}
 			
 			wctdm_post_initialize(wc);
 
 			/* Enable interrupts */
 			wctdm_enable_interrupts(wc);
 			/* Initialize Write/Buffers to all blank data */
-			memset((void *)wc->writechunk,0, ZT_MAX_CHUNKSIZE * (NUM_CARDS+NUM_FLAG) * 2 * 2);
+			memset((void *)wc->writechunk,0, DAHDI_MAX_CHUNKSIZE * (MAX_NUM_CARDS+NUM_FLAG) * 2 * 2);
 
 			/* Start DMA */
 			wctdm_start_dma(wc);
 
-			for (x = 0; x < NUM_CARDS; x++) {
+			for (x = 0; x < wc->max_cards/*MAX_NUM_CARDS*/; x++) {
 				if (wc->cardflag & (1 << x))
 					cardcount++;
 			}
 
-			printk("Found a OpenVox A1200P: Version %01x.%01x (%d modules)\n", wc->fwversion>>4, wc->fwversion&0x0f, cardcount);
+			printk("Found aa OpenVox %s: Version %x.%x (%d modules)\n", wc->card_name, (wc->fwversion&(~FLAG_A800))>>4, wc->fwversion&0x0f, cardcount);
+			if(debug)
+				printk("OpenVox %s debug On\n", wc->card_name);
 			
 			res = 0;
 		} else
@@ -2543,49 +2757,56 @@
 static void wctdm_release(struct wctdm *wc)
 {
 #ifdef TEST_LOG_INCOME_VOICE
-	struct file * f = NULL;
+	struct file * f = NULL;
 	mm_segment_t orig_fs;
 	int i;
-	char fname[20];
+	char fname[20];
 #endif
 	
-	zt_unregister(&wc->span);
+	dahdi_unregister(&wc->span);
 	if (wc->freeregion & 0x01)
 		release_region(wc->ioaddr, 0xff);
-	if (wc->freeregion & 0x02);
+	if (wc->freeregion & 0x02)
 	{
 		release_mem_region(wc->mem_region, wc->mem_len);
 		iounmap((void *)wc->mem32);
 	}
 	
 #ifdef TEST_LOG_INCOME_VOICE
-	for(i=0; i<NUM_CARDS + NUM_FLAG; i++)
+	for(i=0; i<MAX_NUM_CARDS + NUM_FLAG; i++)
 	{
 		sprintf(fname, "//usr//%d.pcm", i); 
-		f = filp_open(fname, O_RDWR|O_CREAT, 00);
-	
-		if (!f || !f->f_op || !f->f_op->read)
+		f = filp_open(fname, O_RDWR|O_CREAT, 00);
+	
+		if (!f || !f->f_op || !f->f_op->read)
 		{
 			printk("WARNING: File (read) object is a null pointer!!!\n");
 			continue;
-		}
-	
-		f->f_pos = 0;
-		
-		orig_fs = get_fs();
-		set_fs(KERNEL_DS); 
-		
+		}
+	
+		f->f_pos = 0;
+		
+		orig_fs = get_fs();
+		set_fs(KERNEL_DS); 
+		
 		if(wc->voc_buf[i])
 		{
 			f->f_op->write(f, wc->voc_buf[i], voc_buffer_size, &f->f_pos);
 			kfree(wc->voc_buf[i]);
-		}
-		
-		set_fs(orig_fs); 
+		}
+		
+		set_fs(orig_fs); 
 		fput(f);
 	}
-#endif
- 
+#endif
+ 
+	if(cidbeforering) 
+	{
+		int x;
+		for (x = 0; x < wc->max_cards/*MAX_NUM_CARDS*/; x++) 
+			kfree(wc->cid_history_buf[x]);
+	}
+ 
 	kfree(wc);
 	printk("Freed a OpenVox A1200 card\n");
 }
@@ -2603,7 +2824,7 @@
 		wctdm_disable_interrupts(wc);
 		
 		/* Immediately free resources */
-		pci_free_consistent(pdev,  ZT_MAX_CHUNKSIZE * (NUM_CARDS+NUM_FLAG) * 2 * 2, (void *)wc->writechunk, wc->writedma);
+		pci_free_consistent(pdev,  DAHDI_MAX_CHUNKSIZE * (MAX_NUM_CARDS+NUM_FLAG) * 2 * 2, (void *)wc->writechunk, wc->writedma);
 		free_irq(pdev->irq, wc);
 
 		/* Reset PCI chip and registers */
@@ -2627,7 +2848,10 @@
 	{ 0xe159, 0x0001, 0x9100, PCI_ANY_ID, 0, 0, (unsigned long) &wctdme },
 	{ 0xe159, 0x0001, 0x9519, PCI_ANY_ID, 0, 0, (unsigned long) &wctdme },
 	{ 0xe159, 0x0001, 0x95D9, PCI_ANY_ID, 0, 0, (unsigned long) &wctdme },
+	{ 0xe159, 0x0001, 0x9500, PCI_ANY_ID, 0, 0, (unsigned long) &wctdme },
+	{ 0xe159, 0x0001, 0x9532, PCI_ANY_ID, 0, 0, (unsigned long) &wctdme }, 
 	{ 0xe159, 0x0001, 0x8519, PCI_ANY_ID, 0, 0, (unsigned long) &wctdme },
+	{ 0xe159, 0x0001, 0x9559, PCI_ANY_ID, 0, 0, (unsigned long) &wctdme },
 	{ 0 }
 };
 
@@ -2636,11 +2860,7 @@
 static struct pci_driver wctdm_driver = {
 	name: 	"opvxa1200",
 	probe: 	wctdm_init_one,
-#ifdef LINUX26
 	remove:	__devexit_p(wctdm_remove_one),
-#else
-	remove:	wctdm_remove_one,
-#endif
 	suspend: NULL,
 	resume:	NULL,
 	id_table: wctdm_pci_tbl,
@@ -2663,8 +2883,12 @@
 		printk("Note this option is CASE SENSITIVE!\n");
 		return -ENODEV;
 	}
-
-	res = zap_pci_module(&wctdm_driver);
+	if (!strcmp(fxo_modes[_opermode].name, "AUSTRALIA")) {
+		boostringer=1;
+		fxshonormode=1;
+	}
+
+	res = dahdi_pci_module(&wctdm_driver);
 	if (res)
 		return -ENODEV;
 	return 0;
@@ -2675,7 +2899,6 @@
 	pci_unregister_driver(&wctdm_driver);
 }
 
-#ifdef LINUX26
 module_param(debug, int, 0600);
 module_param(loopcurrent, int, 0600);
 module_param(reversepolarity, int, 0600);
@@ -2685,34 +2908,29 @@
 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, int, 0600);
 module_param(battthresh, int, 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_param(spibyhw, int, 0600);
 module_param(usememio, int, 0600);
-#else
-MODULE_PARM(debug, "i");
-MODULE_PARM(loopcurrent, "i");
-MODULE_PARM(reversepolarity, "i");
-MODULE_PARM(robust, "i");
-MODULE_PARM(_opermode, "i");
-MODULE_PARM(opermode, "s");
-MODULE_PARM(timingonly, "i");
-MODULE_PARM(lowpower, "i");
-MODULE_PARM(boostringer, "i");
-MODULE_PARM(fxshonormode, "i");
-MODULE_PARM(battdebounce, "i");
-MODULE_PARM(battthresh, "i");
-MODULE_PARM(alawoverride, "i");
-MODULE_PARM(spibyhw, "i");
-MODULE_PARM(usememio, "i");
-#endif
-MODULE_DESCRIPTION("OpenVox A1200 Zaptel Driver");
+module_param(cidbeforering, int, 0600);
+module_param(cidbuflen, int, 0600);
+module_param(cidtimeout, int, 0600);
+module_param(fxofullscale, int, 0600);
+
+
+MODULE_DESCRIPTION("OpenVox A1200 Driver");
 MODULE_AUTHOR("MiaoLin <miaolin at openvox.com.cn>");
-#ifdef MODULE_LICENSE
-MODULE_LICENSE("GPL");
-#endif
+MODULE_LICENSE("GPL v2");
 
 module_init(wctdm_init);
 module_exit(wctdm_cleanup);




More information about the Pkg-voip-commits mailing list