List Info

Thread: sruffell: branch 1.4 r4096 - in /branches/1.4: doc/ kernel/ kernel/wctdm24xxp...




sruffell: branch 1.4 r4096 - in /branches/1.4: doc/ kernel/ kernel/wctdm24xxp...
user name
2008-03-27 16:17:46
Author: sruffell
Date: Thu Mar 27 16:17:46 2008
New Revision: 4096

URL: http://svn.digium.com/view/zaptel?view=rev&rev=4096
Log:
- Updated wctdm24xxp and wcte12xp driver which are now more
tolerant of
  systems which do not exhibit good real-time
characteristics.
- Bringing in improvements to battery alarm generation that
was on kpflemings
  battery_alarms branch. (Issue #12099)

Added:
    branches/1.4/kernel/fxo_modes.h
      - copied unchanged from r4094,
team/sruffell/voicebus/kernel/fxo_modes.h
    branches/1.4/kernel/voicebus.c
      - copied unchanged from r4094,
team/sruffell/voicebus/kernel/voicebus.c
    branches/1.4/kernel/voicebus.h
      - copied unchanged from r4094,
team/sruffell/voicebus/kernel/voicebus.h
Modified:
    branches/1.4/doc/module-parameters.txt
    branches/1.4/kernel/wctdm.c
    branches/1.4/kernel/wctdm24xxp/Kbuild
    branches/1.4/kernel/wctdm24xxp/base.c
    branches/1.4/kernel/wctdm24xxp/wctdm24xxp.h
    branches/1.4/kernel/wcte12xp/Kbuild
    branches/1.4/kernel/wcte12xp/base.c
    branches/1.4/kernel/wcte12xp/vpmadt032.c
    branches/1.4/kernel/wcte12xp/wcte12xp.h
    branches/1.4/kernel/zaptel-base.c

Modified: branches/1.4/doc/module-parameters.txt
URL: http://svn.digium.com/view/zaptel/branches/1.4/doc/mo
dule-parameters.txt?view=diff&rev=4096&r1=4095&r
2=4096
============================================================
==================
--- branches/1.4/doc/module-parameters.txt (original)
+++ branches/1.4/doc/module-parameters.txt Thu Mar 27
16:17:46 2008
 -2,6
+2,7 
 
 (Note: this list is woefully incomplete, but is a starting
point and
 will be improved as time permits.)
+
 
  --- VPMADT032 Parameters ---
 
 -42,3
+43,15 
 	When vpmnlptype is 'Suppress', this value indicates the
 	relative energy level decrease that should be applied to
the
 	echo signal).
+
+ --- General Module Parameters ---
+
+latency - 3 to 32, defaults to 3
+
+	For the wctdm24xxp and wcte12xp drivers.  Specifies the
amount of
+	latency the driver inserts into the voice conversation. 
On systems
+	that are unable to service the interrupt in a timely
manner,
+	increasing the latency can increase module init time since
the driver
+	will not have to dynamically grow the latency during
initialization.
+	However, the latency in the driver does add to the overall
latency of
+	any voice conversation.

Modified: branches/1.4/kernel/wctdm.c
URL: http
://svn.digium.com/view/zaptel/branches/1.4/kernel/wctdm.c?vi
ew=diff&rev=4096&r1=4095&r2=4096
============================================================
==================
--- branches/1.4/kernel/wctdm.c (original)
+++ branches/1.4/kernel/wctdm.c Thu Mar 27 16:17:46 2008
 -108,100
+108,9 
 {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, },
-};
-
 #include "zaptel.h"
+
+#include "fxo_modes.h"
 
 #ifdef LINUX26
 #include <linux/moduleparam.h>
 -249,14
+158,7 
 
 #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 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" */
+#define POLARITY_DEBOUNCE 	64		/* Polarity debounce (64 ms)
*/
 
 #define OHT_TIMER		6000	/* How long after RING to retain
OHT */
 
 -283,6
+185,12 
 	PROSLIC_POWER_UNKNOWN = 0,
 	PROSLIC_POWER_ON,
 	PROSLIC_POWER_WARNED,
+};
+
+enum battery_state {
+	BATTERY_UNKNOWN = 0,
+	BATTERY_PRESENT,
+	BATTERY_LOST,
 };
 
 struct wctdm {
 -303,7
+211,7 
 	spinlock_t lock;
 
 	union {
-		struct {
+		struct fxo {
 #ifdef AUDIO_RINGCHECK
 			unsigned int pegtimer;
 			int pegcount;
 -315,14
+223,14 
 #endif			
 			int ringdebounce;
 			int offhook;
-			int battdebounce;
-			int nobatttimer;
-			int battery;
+			unsigned int battdebounce;
+			unsigned int battalarm;
+			enum battery_state battery;
 		        int lastpol;
 		        int polarity;
 		        int polaritydebounce;
 		} fxo;
-		struct {
+		struct fxs {
 			int oldrxhook;
 			int debouncehook;
 			int lastrxhook;
 -364,8
+272,9 
 
 static void wctdm_release(struct wctdm *wc);
 
-static int battdebounce = DEFAULT_BATT_DEBOUNCE;
-static int battthresh = DEFAULT_BATT_THRESH;
+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;
 -834,11
+743,15 
 
 static inline void wctdm_voicedaa_check_hook(struct wctdm
*wc, int card)
 {
+#define MS_PER_CHECK_HOOK 16
+
 #ifndef AUDIO_RINGCHECK
 	unsigned char res;
 #endif	
 	signed char b;
 	int poopy = 0;
+	struct fxo *fxo = &wc->mod[card].fxo;
+
 	/* Try to track issues that plague slot one FXO's */
 	b = wc->reg0shadow[card];
 	if ((b & 0x2) || !(b & 0x8)) {
 -848,7
+761,7 
 		poopy++;
 	}
 	b &= 0x9b;
-	if (wc->mod[card].fxo.offhook) {
+	if (fxo->offhook) {
 		if (b != 0x9)
 			wctdm_setreg(wc, card, 5, 0x9);
 	} else {
 -857,150
+770,182 
 	}
 	if (poopy)
 		return;
-#ifndef AUDIO_RINGCHECK
-	if (!wc->mod[card].fxo.offhook) {
+	if (!fxo->offhook) {
 		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 (fxo->ringdebounce--) {
+				if (res && (res != fxo->lastrdtx)
&&
+				    (fxo->battery == BATTERY_PRESENT)) {
+					if (!fxo->wasringing) {
+						fxo->wasringing = 1;
 						if (debug)
 							printk("RING on %d/%d!n",
wc->span.spanno, card + 1);
 						zt_hooksig(&wc->chans[card], ZT_RXSIG_RING);
 					}
-					wc->mod[card].fxo.lastrdtx = res;
-					wc->mod[card].fxo.ringdebounce = 10;
+					fxo->lastrdtx = res;
+					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 ((fxo->ringdebounce == 0) &&
fxo->wasringing) {
+						fxo->wasringing = 0;
 						if (debug)
 							printk("NO RING on %d/%d!n",
wc->span.spanno, card + 1);
 						zt_hooksig(&wc->chans[card],
ZT_RXSIG_OFFHOOK);
 					}
 				}
-			} else if (res && (wc->mod[card].fxo.battery
== 1)) {
-				wc->mod[card].fxo.lastrdtx = res;
-				wc->mod[card].fxo.ringdebounce = 10;
+			} else if (res && (fxo->battery ==
BATTERY_PRESENT)) {
+				fxo->lastrdtx = res;
+				fxo->ringdebounce = 10;
 			}
 		} else {
 			res = wc->reg0shadow[card];
-			if ((res & 0x60) &&
(wc->mod[card].fxo.battery == 1)) {
-				wc->mod[card].fxo.ringdebounce += (ZT_CHUNKSIZE *
16);
-				if (wc->mod[card].fxo.ringdebounce >=
ZT_CHUNKSIZE * ringdebounce) {
-					if (!wc->mod[card].fxo.wasringing) {
-						wc->mod[card].fxo.wasringing = 1;
+			if ((res & 0x60) && (fxo->battery ==
BATTERY_PRESENT)) {
+				fxo->ringdebounce += (ZT_CHUNKSIZE * 16);
+				if (fxo->ringdebounce >= ZT_CHUNKSIZE *
ringdebounce) {
+					if (!fxo->wasringing) {
+						fxo->wasringing = 1;
 						zt_hooksig(&wc->chans[card], ZT_RXSIG_RING);
 						if (debug)
 							printk("RING on %d/%d!n",
wc->span.spanno, card + 1);
 					}
-					wc->mod[card].fxo.ringdebounce = ZT_CHUNKSIZE *
ringdebounce;
+					fxo->ringdebounce = ZT_CHUNKSIZE * ringdebounce;
 				}
 			} 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;
+				fxo->ringdebounce -= ZT_CHUNKSIZE * 4;
+				if (fxo->ringdebounce <= 0) {
+					if (fxo->wasringing) {
+						fxo->wasringing = 0;
 						zt_hooksig(&wc->chans[card],
ZT_RXSIG_OFFHOOK);
 						if (debug)
 							printk("NO RING on %d/%d!n",
wc->span.spanno, card + 1);
 					}
-					wc->mod[card].fxo.ringdebounce = 0;
+					fxo->ringdebounce = 0;
 				}
 			}
 		}
 	}
+
+	b = wc->reg1shadow[card];
+
+	if (abs(b) < battthresh) {
+		/* possible existing states:
+		   battery lost, no debounce timer
+		   battery lost, debounce timer (going to battery
present)
+		   battery present or unknown, no debounce timer
+		   battery present or unknown, debounce timer (going to
battery lost)
+		*/
+
+		if (fxo->battery == BATTERY_LOST) {
+			if (fxo->battdebounce) {
+				/* we were going to BATTERY_PRESENT, but battery was
lost again,
+				   so clear the debounce timer */
+				fxo->battdebounce = 0;
+			}
+		} else {
+			if (fxo->battdebounce) {
+				/* going to BATTERY_LOST, see if we are there yet */
+				if (--fxo->battdebounce == 0) {
+					fxo->battery = BATTERY_LOST;
+					if (debug)
+						printk("NO BATTERY on %d/%d!n",
wc->span.spanno, card + 1);
+#ifdef	JAPAN
+					if (!wc->ohdebounce && wc->offhook) {
+						zt_hooksig(&wc->chans[card],
ZT_RXSIG_ONHOOK);
+						if (debug)
+							printk("Signalled On Hookn");
+#ifdef	ZERO_BATT_RING
+						wc->onhook++;
 #endif
-	b = wc->reg1shadow[card];
-#if 0 
-	{
-		static int count = 0;
-		if (!(count++ % 100)) {
-			printk("Card %d: Voltage: %d  Debounce %dn",
card + 1, 
-			       b, wc->mod[card].fxo.battdebounce);
-		}
-	}
-#endif	
-	if (abs(b) < battthresh) {
-		wc->mod[card].fxo.nobatttimer++;
-#if 0
-		if (wc->mod[card].fxo.battery == 1)
-			printk("Battery loss: %d (%d debounce)n", b,
wc->mod[card].fxo.battdebounce);
+					}
+#else
+					zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK);
+					/* set the alarm timer, taking into account that part
of its time
+					   period has already passed while debouncing occurred
*/
+					fxo->battalarm = (battalarm - battdebounce) /
MS_PER_CHECK_HOOK;
 #endif
-		if (wc->mod[card].fxo.battery &&
!wc->mod[card].fxo.battdebounce) {
-			if (debug)
-				printk("NO BATTERY on %d/%d!n",
wc->span.spanno, card + 1);
-			wc->mod[card].fxo.battery =  0;
-#ifdef	JAPAN
-			if ((!wc->ohdebounce) && wc->offhook) {
-				zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK);
-				if (debug)
-					printk("Signalled On Hookn");
+				}
+			} else {
+				/* start the debounce timer to verify that battery has
been lost */
+				fxo->battdebounce = battdebounce /
MS_PER_CHECK_HOOK;
+			}
+		}
+	} else {
+		/* possible existing states:
+		   battery lost or unknown, no debounce timer
+		   battery lost or unknown, debounce timer (going to
battery present)
+		   battery present, no debounce timer
+		   battery present, debounce timer (going to battery
lost)
+		*/
+
+		if (fxo->battery == BATTERY_PRESENT) {
+			if (fxo->battdebounce) {
+				/* we were going to BATTERY_LOST, but battery appeared
again,
+				   so clear the debounce timer */
+				fxo->battdebounce = 0;
+			}
+		} else {
+			if (fxo->battdebounce) {
+				/* going to BATTERY_PRESENT, see if we are there yet
*/
+				if (--fxo->battdebounce == 0) {
+					fxo->battery = BATTERY_PRESENT;
+					if (debug)
+						printk("BATTERY on %d/%d (%s)!n",
wc->span.spanno, card + 1, 
+						       (b < 0) ? "-" :
"+");			    
 #ifdef	ZERO_BATT_RING
-				wc->onhook++;
+					if (wc->onhook) {
+						wc->onhook = 0;
+						zt_hooksig(&wc->chans[card],
ZT_RXSIG_OFFHOOK);
+						if (debug)
+							printk("Signalled Off Hookn");
+					}
+#else
+					zt_hooksig(&wc->chans[card],
ZT_RXSIG_OFFHOOK);
 #endif
+					/* set the alarm timer, taking into account that part
of its time
+					   period has already passed while debouncing occurred
*/
+					fxo->battalarm = (battalarm - battdebounce) /
MS_PER_CHECK_HOOK;
+				}
+			} else {
+				/* start the debounce timer to verify that battery has
appeared */
+				fxo->battdebounce = battdebounce /
MS_PER_CHECK_HOOK;
 			}
-#else
-			zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK);
-			zt_alarm_channel(&wc->chans[card],
ZT_ALARM_RED);
-#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 < 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);
-				if (debug)
-					printk("Signalled Off Hookn");
+		}
+
+		if (fxo->lastpol >= 0) {
+			if (b < 0) {
+				fxo->lastpol = -1;
+				fxo->polaritydebounce = POLARITY_DEBOUNCE /
MS_PER_CHECK_HOOK;
 			}
-#else
-			zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK);
-			zt_alarm_channel(&wc->chans[card],
ZT_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 == 1)
-			wc->mod[card].fxo.battdebounce = battdebounce;
-
-		if (wc->mod[card].fxo.lastpol >= 0) {
-		    if (b < 0) {
-			wc->mod[card].fxo.lastpol = -1;
-			wc->mod[card].fxo.polaritydebounce =
POLARITY_DEBOUNCE;
-		    }
 		} 
-		if (wc->mod[card].fxo.lastpol <= 0) {
-		    if (b > 0) {
-			wc->mod[card].fxo.lastpol = 1;
-			wc->mod[card].fxo.polaritydebounce =
POLARITY_DEBOUNCE;
-		    }
-		}
-	} else {
-		/* It's something else... */
-		wc->mod[card].fxo.battdebounce = battdebounce;
-	}
-	if (wc->mod[card].fxo.battdebounce)
-		wc->mod[card].fxo.battdebounce--;
-	if (wc->mod[card].fxo.polaritydebounce) {
-	        wc->mod[card].fxo.polaritydebounce--;
-		if (wc->mod[card].fxo.polaritydebounce < 1) {
-		    if (wc->mod[card].fxo.lastpol !=
wc->mod[card].fxo.polarity) {
+		if (fxo->lastpol <= 0) {
+			if (b > 0) {
+				fxo->lastpol = 1;
+				fxo->polaritydebounce = POLARITY_DEBOUNCE /
MS_PER_CHECK_HOOK;
+			}
+		}
+	}
+
+	if (fxo->battalarm) {
+		if (--fxo->battalarm == 0) {
+			/* the alarm timer has expired, so update the battery
alarm state
+			   for this channel */
+			zt_alarm_channel(&wc->chans[card],
fxo->battery ? ZT_ALARM_NONE : ZT_ALARM_RED);
+		}
+	}
+
+	if (fxo->polaritydebounce) {
+		if (--fxo->polaritydebounce == 0) {
+		    if (fxo->lastpol != fxo->polarity) {
 				if (debug)
 					printk("%lu Polarity reversed (%d ->
%d)n", jiffies, 
-				       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);
-				wc->mod[card].fxo.polarity =
wc->mod[card].fxo.lastpol;
+				       fxo->polarity, 
+				       fxo->lastpol);
+				if (fxo->polarity)
+					zt_qevent_lock(&wc->chans[card],
ZT_EVENT_POLARITY);
+				fxo->polarity = fxo->lastpol;
 		    }
 		}
 	}
+#undef MS_PER_CHECK_HOOK
 }
 
 static inline void wctdm_proslic_check_hook(struct wctdm
*wc, int card)
 -1607,9
+1552,6 
 	if(debug)
 		printk("DEBUG fxotxgain:%i.%i
fxorxgain:%i.%in", (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;
 		
 }
 -2514,7
+2456,8 
 {
 	int res;
 	int x;
-	for (x=0;x<(sizeof(fxo_modes) / sizeof(fxo_modes[0]));
x++) {
+
+	for (x = 0; x < (sizeof(fxo_modes) /
sizeof(fxo_modes[0])); x++) {
 		if (!strcmp(fxo_modes[x].name, opermode))
 			break;
 	}
 -2522,16
+2465,30 
 		_opermode = x;
 	} else {
 		printk("Invalid/unknown operating mode '%s'
specified.  Please choose one of:n", opermode);
-		for (x=0;x<sizeof(fxo_modes) / sizeof(fxo_modes[0]);
x++)
+		for (x = 0; x < sizeof(fxo_modes) /
sizeof(fxo_modes[0]); x++)
 			printk("  %sn", fxo_modes[x].name);
 		printk("Note this option is CASE
SENSITIVE!n");
 		return -ENODEV;
 	}
-	if (!strcmp(fxo_modes[_opermode].name,
"AUSTRALIA")) {
-		boostringer=1;
-		fxshonormode=1;
-	}
-	
+
+	if (!strcmp(opermode, "AUSTRALIA")) {
+		boostringer = 1;
+		fxshonormode = 1;
+	}
+
+	/* for the voicedaa_check_hook defaults, if the user has
not overridden
+	   them by specifying them as module parameters, then get
the values
+	   from the selected operating mode
+	*/
+	if (battdebounce == 0) {
+		battdebounce = fxo_modes[_opermode].battdebounce;
+	}
+	if (battalarm == 0) {
+		battalarm = fxo_modes[_opermode].battalarm;
+	}
+	if (battthresh == 0) {
+		battthresh = fxo_modes[_opermode].battthresh;
+	}
 
 	res = zap_pci_module(&wctdm_driver);
 	if (res)
 -2549,15
+2506,15 
 module_param(loopcurrent, int, 0600);
 module_param(reversepolarity, int, 0600);
 module_param(robust, int, 0600);
-module_param(_opermode, 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, int, 0600);
-module_param(battthresh, 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);
 -2571,7
+2528,6 
 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");
 -2579,6
+2535,7 
 MODULE_PARM(fastringer, "i");
 MODULE_PARM(fxshonormode, "i");
 MODULE_PARM(battdebounce, "i");
+MODULE_PARM(battalarm, "i");
 MODULE_PARM(battthresh, "i");
 MODULE_PARM(ringdebounce, "i");
 MODULE_PARM(fwringdetect, "i");

Modified: branches/1.4/kernel/wctdm24xxp/Kbuild
URL: http://svn.digium.com/view/zaptel/branches/1.4/kernel/
wctdm24xxp/Kbuild?view=diff&rev=4096&r1=4095&r2=
4096
============================================================
==================
--- branches/1.4/kernel/wctdm24xxp/Kbuild (original)
+++ branches/1.4/kernel/wctdm24xxp/Kbuild Thu Mar 27
16:17:46 2008
 -8,7
+8,7 
   EXTRA_CFLAGS+=-DHOTPLUG_FIRMWARE
 endif
 
-wctdm24xxp-objs := base.o GpakCust.o GpakApi.o
+wctdm24xxp-objs := base.o GpakCust.o GpakApi.o
../voicebus.o
 
 ifneq ($(HOTPLUG_FIRMWARE),yes)
 wctdm24xxp-objs += $(FIRM_DIR)/zaptel-fw-vpmadt032.o

Modified: branches/1.4/kernel/wctdm24xxp/base.c
URL: http://svn.digium.com/view/zaptel/branches/1.4/kernel/
wctdm24xxp/base.c?view=diff&rev=4096&r1=4095&r2=
4096
============================================================
==================
--- branches/1.4/kernel/wctdm24xxp/base.c (original)
+++ branches/1.4/kernel/wctdm24xxp/base.c Thu Mar 27
16:17:46 2008
 -4,7
+4,7 
  * Written by Mark Spencer <marksterdigium.com>
  * Support for TDM800P and VPM150M by Matthew Fredrickson
<creslindigium.com>
  *
- * Copyright (C) 2005,2006, Digium, Inc.
+ * Copyright (C) 2005 - 2008 Digium, Inc.
  * All rights reserved.
  *
  * Sections for QRV cards written by Jim Dixon <jimlambdatel.com>
 -146,101
+146,10 
    enable for normal operation! */
 /* #define PAQ_DEBUG */
 
-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, },
-};
-
 #define DEBUG_CARD (1 << 0)
 #define DEBUG_ECHOCAN (1 << 1)
+
+#include "fxo_modes.h"
 
 struct wctdm_desc {
 	char *name;
 -262,8
+171,9 
 static void wctdm_release(struct wctdm *wc);
 
 static int fxovoltage = 0;
-static int battdebounce = DEFAULT_BATT_DEBOUNCE;
-static int battthresh = DEFAULT_BATT_THRESH;
+static unsigned int battdebounce;
+static unsigned int battalarm;
+static unsigned int battthresh;
 static int debug = 0;
 static int robust = 0;
 static int lowpower = 0;
 -281,6
+191,7 
 static int nativebridge = 0;
 static int ringdebounce = DEFAULT_RING_DEBOUNCE;
 static int fwringdetect = 0;
+static int latency = VOICEBUS_DEFAULT_LATENCY;
 #ifdef VPM_SUPPORT
 static int vpmsupport = 1;
 static int vpmdtmfsupport = 0;
 -746,29
+657,26 
 	}
 }
 
-static inline void wctdm_transmitprep(struct wctdm *wc, int
dbl)
-{
-	volatile unsigned char *writechunk;
+static inline void wctdm_transmitprep(struct wctdm *wc,
unsigned char *writechunk)
+{
 	int x,y;
 
-	dbl = dbl % 2;
-
-	writechunk = (volatile unsigned char
*)(wc->writechunk);
-	if (dbl) 
-		/* Write is at interrupt address.  Start writing from
normal offset */
-		writechunk += SFRAME_SIZE;
-
 	/* Calculate Transmission */
-	zt_transmit(&wc->span);
+	if (likely(wc->initialized)) {
+		zt_transmit(&wc->span);
+	}
 
 	for (x=0;x<ZT_CHUNKSIZE;x++) {
 		/* Send a sample, as a 32-bit word */
 		for (y=0;y < wc->cards;y++) {
-			if (!x)
+			if (!x) {
 				cmd_checkisr(wc, y);
-
-			if (y < wc->type)
-				writechunk[y] = wc->chans[y].writechunk[x];
+			}
+
+			if (likely(wc->initialized)) {
+				if (y < wc->type)
+					writechunk[y] = wc->chans[y].writechunk[x];
+			}
 			cmd_dequeue(wc, writechunk, y, x);
 		}
 #ifdef VPM_SUPPORT
 -776,8
+684,9 
 			wc->blinktimer++;
 		if (wc->vpm) {
 			for (y=24;y<28;y++) {
-				if (!x)
+				if (!x) {
 					cmd_checkisr(wc, y);
+				}
 				cmd_dequeue(wc, writechunk, y, x);
 			}
 #ifdef FANCY_ECHOCAN
 -808,24
+717,6 
 	}
 }
 
-static inline void __wctdm_setctl(struct wctdm *wc,
unsigned int addr, unsigned int val)
-{
-	outl(val, wc->iobase + addr);
-}
-
-static inline unsigned int __wctdm_getctl(struct wctdm *wc,
unsigned int addr)
-{
-	return inl(wc->iobase + addr);
-}
-
-static inline void wctdm_setctl(struct wctdm *wc, unsigned
int addr, unsigned int val)
-{
-	unsigned long flags;
-	spin_lock_irqsave(&wc->reglock, flags);
-	__wctdm_setctl(wc, addr, val);
-	spin_unlock_irqrestore(&wc->reglock, flags);
-}
-
 static inline int wctdm_setreg_full(struct wctdm *wc, int
card, int addr, int val, int inisr)
 {
 	unsigned long flags;
 -900,96
+791,6 
 		}
 	} while (hit > -1);
 	return ret;
-}
-
-static inline unsigned int wctdm_getctl(struct wctdm *wc,
unsigned int addr)
-{
-	unsigned long flags;
-	unsigned int val;
-	spin_lock_irqsave(&wc->reglock, flags);
-	val = __wctdm_getctl(wc, addr);
-	spin_unlock_irqrestore(&wc->reglock, flags);
-	return val;
-}
-
-static inline int __wctdm_sdi_clk(struct wctdm *wc)
-{
-	unsigned int ret;
-	wc->sdi &= ~SDI_CLK;
-	__wctdm_setctl(wc, 0x0048, wc->sdi);
-	ret = __wctdm_getctl(wc, 0x0048);
-	wc->sdi |= SDI_CLK;
-	__wctdm_setctl(wc, 0x0048, wc->sdi);
-	return ret & SDI_DIN;
-}
-
-static inline void __wctdm_sdi_sendbits(struct wctdm *wc,
unsigned int bits, int count)
-{
-	wc->sdi &= ~SDI_DREAD;
-	__wctdm_setctl(wc, 0x0048, wc->sdi);
-	while(count--) {
-		if (bits & (1 << count))
-			wc->sdi |= SDI_DOUT;
-		else
-			wc->sdi &= ~SDI_DOUT;
-		__wctdm_sdi_clk(wc);
-	}
-}
-
-static inline unsigned int __wctdm_sdi_recvbits(struct
wctdm *wc, int count)
-{
-	unsigned int bits=0;
-	wc->sdi |= SDI_DREAD;
-	__wctdm_setctl(wc, 0x0048, wc->sdi);
-	while(count--) {
-		bits <<= 1;
-		if (__wctdm_sdi_clk(wc))
-			bits |= 1;
-		else
-			bits &= ~1;
-	}
-	return bits;
-}
-
-static inline void __wctdm_setsdi(struct wctdm *wc,
unsigned char addr, unsigned short value)
-{
-	unsigned int bits;
-	/* Send preamble */
-	bits = 0xffffffff;
-	__wctdm_sdi_sendbits(wc, bits, 32);
-	bits = (0x5 << 12) | (1 << 7) | (addr <<
2) | 0x2;
-	__wctdm_sdi_sendbits(wc, bits, 16);
-	__wctdm_sdi_sendbits(wc, value, 16);
-	
-}
-
-static inline unsigned short __wctdm_getsdi(struct wctdm
*wc, unsigned char addr)
-{
-	unsigned int bits;
-	/* Send preamble */
-	bits = 0xffffffff;
-	__wctdm_sdi_sendbits(wc, bits, 32);
-	bits = (0x6 << 10) | (1 << 5) | (addr);
-	__wctdm_sdi_sendbits(wc, bits, 14);
-	return __wctdm_sdi_recvbits(wc, 18);
-}
-
-static inline void wctdm_setsdi(struct wctdm *wc, unsigned
char addr, unsigned short value)
-{
-	unsigned long flags;
-	spin_lock_irqsave(&wc->reglock, flags);
-	__wctdm_setsdi(wc, addr, value);
-	spin_unlock_irqrestore(&wc->reglock, flags);
-}
-
-static inline unsigned short wctdm_getsdi(struct wctdm *wc,
unsigned char addr)
-{
-	unsigned long flags;
-	unsigned short val;
-	spin_lock_irqsave(&wc->reglock, flags);
-	val = __wctdm_getsdi(wc, addr);
-	spin_unlock_irqrestore(&wc->reglock, flags);
-	return val;
 }
 
 #ifdef VPM_SUPPORT
 -1039,17
+840,13 
 #endif
 }
 
-static inline void wctdm_receiveprep(struct wctdm *wc, int
dbl)
-{
-	volatile unsigned char *readchunk;
+static inline void wctdm_receiveprep(struct wctdm *wc,
unsigned char *readchunk)
+{
 	int x,y;
 	unsigned char expected;
 
-	dbl = dbl % 2;
-
-	readchunk = (volatile unsigned char *)wc->readchunk;
-	if (dbl)
-		readchunk += SFRAME_SIZE;
+	BUG_ON(NULL == readchunk);
+
 	for (x=0;x<ZT_CHUNKSIZE;x++) {
 		if (x < ZT_CHUNKSIZE - 1) {
 			expected = wc->rxident+1;
 -1060,9
+857,11 
 			}
 		}
 		for (y=0;y < wc->cards;y++) {
-			if (y < wc->type) {
-				wc->chans[y].readchunk[x] = readchunk[y];
-			}
+			if (likely(wc->initialized)) {
+				if (y < wc->type) {
+					wc->chans[y].readchunk[x] = readchunk[y];
+				}
+			}	
 			cmd_decifer(wc, readchunk, y);
 		}
 #ifdef VPM_SUPPORT
 -1072,25
+871,20 
 		} else if (wc->vpm150m)
 			cmd_decifer_vpm150m(wc, readchunk);
 #endif
-#if 0
-		if (cmddesc < 1024) {
-			printk("RC Result: %02xn",
readchunk[EFRAME_SIZE+1]);
-		}
-#endif		
+
 		readchunk += (EFRAME_SIZE + EFRAME_GAP);
 	}
 	/* XXX We're wasting 8 taps.  We should get closer :( */
-	for (x=0;x<wc->type;x++) {
-		if (wc->cardflag & (1 << x))
-			zt_ec_chunk(&wc->chans[x],
wc->chans[x].readchunk, wc->chans[x].writechunk);
-	}
-	zt_receive(&wc->span);
+	if (likely(wc->initialized)) {
+		for (x=0;x<wc->type;x++) {
+			if (wc->cardflag & (1 << x))
+				zt_ec_chunk(&wc->chans[x],
wc->chans[x].readchunk, wc->chans[x].writechunk);
+		}
+		zt_receive(&wc->span);
+	}
 	/* Wake up anyone sleeping to read/write a new register
*/
 	wake_up_interruptible(&wc->regq);
 }
-
-static void wctdm_stop_dma(struct wctdm *wc);
-static void wctdm_restart_dma(struct wctdm *wc);
 
 static int wait_access(struct wctdm *wc, int card)
 {

-1330,160 +1124,206 
 
 static inline void wctdm_voicedaa_check_hook(struct wctdm
*wc, int card)
 {
+#define MS_PER_CHECK_HOOK 1
+
 	unsigned char res;
 	signed char b;
+	struct fxo *fxo = &wc->mods[card].fxo;
+
 	/* Try to track issues that plague slot one FXO's */
 	b = wc->cmdq[card].isrshadow[0];	/* Hook/Ring state */
 	b &= 0x9b;
-	if (wc->mods[card].fxo.offhook) {
+	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 (!wc->mods[card].fxo.offhook) {
+	if (!fxo->offhook) {
 		if (fwringdetect) {
 			res =  wc->cmdq[card].isrshadow[0] & 0x60;
-			if (wc->mods[card].fxo.ringdebounce--) {
-				if (res && (res !=
wc->mods[card].fxo.lastrdtx) &&
(wc->mods[card].fxo.battery == 1)) {
-					if (!wc->mods[card].fxo.wasringing) {
-						wc->mods[card].fxo.wasringing = 1;
+			if (fxo->ringdebounce--) {
+				if (res && (res != fxo->lastrdtx) &&
(fxo->battery == 1)) {
+					if (!fxo->wasringing) {
+						fxo->wasringing = 1;
 						if (debug)
 							printk("RING on %d/%d!n",
wc->span.spanno, card + 1);
 						zt_hooksig(&wc->chans[card], ZT_RXSIG_RING);
 					}
-					wc->mods[card].fxo.lastrdtx = res;
-					wc->mods[card].fxo.ringdebounce = 10;
+					fxo->lastrdtx = res;
+					fxo->ringdebounce = 10;
 				} else if (!res) {
-					if ((wc->mods[card].fxo.ringdebounce == 0)
&& wc->mods[card].fxo.wasringing) {
-						wc->mods[card].fxo.wasringing = 0;
+					if ((fxo->ringdebounce == 0) &&
fxo->wasringing) {
+						fxo->wasringing = 0;
 						if (debug)
 							printk("NO RING on %d/%d!n",
wc->span.spanno, card + 1);
 						zt_hooksig(&wc->chans[card],
ZT_RXSIG_OFFHOOK);
 					}
 				}
-			} else if (res && (wc->mods[card].fxo.battery
== 1)) {
-				wc->mods[card].fxo.lastrdtx = res;
-				wc->mods[card].fxo.ringdebounce = 10;
+			} else if (res && (fxo->battery ==
BATTERY_PRESENT)) {
+				fxo->lastrdtx = res;
+				fxo->ringdebounce = 10;
 			}
 		} else {
 			res =  wc->cmdq[card].isrshadow[0];
-			if ((res & 0x60) &&
(wc->mods[card].fxo.battery == 1)) {
-				wc->mods[card].fxo.ringdebounce += (ZT_CHUNKSIZE *
16);
-				if (wc->mods[card].fxo.ringdebounce >=
ZT_CHUNKSIZE * ringdebounce) {
-					if (!wc->mods[card].fxo.wasringing) {
-						wc->mods[card].fxo.wasringing = 1;
+			if ((res & 0x60) && (fxo->battery ==
BATTERY_PRESENT)) {
+				fxo->ringdebounce += (ZT_CHUNKSIZE * 16);
+				if (fxo->ringdebounce >= ZT_CHUNKSIZE *
ringdebounce) {
+					if (!fxo->wasringing) {
+						fxo->wasringing = 1;
 						zt_hooksig(&wc->chans[card], ZT_RXSIG_RING);
 						if (debug)
 							printk("RING on %d/%d!n",
wc->span.spanno, card + 1);
 					}
-					wc->mods[card].fxo.ringdebounce = ZT_CHUNKSIZE *
ringdebounce;
+					fxo->ringdebounce = ZT_CHUNKSIZE * ringdebounce;
 				}
 			} else {
-				wc->mods[card].fxo.ringdebounce -= ZT_CHUNKSIZE *
4;
-				if (wc->mods[card].fxo.ringdebounce <= 0) {
-					if (wc->mods[card].fxo.wasringing) {
-						wc->mods[card].fxo.wasringing = 0;
+				fxo->ringdebounce -= ZT_CHUNKSIZE * 4;
+				if (fxo->ringdebounce <= 0) {
+					if (fxo->wasringing) {
+						fxo->wasringing = 0;
 						zt_hooksig(&wc->chans[card],
ZT_RXSIG_OFFHOOK);
 						if (debug)
 							printk("NO RING on %d/%d!n",
wc->span.spanno, card + 1);
 					}
-					wc->mods[card].fxo.ringdebounce = 0;
+					fxo->ringdebounce = 0;
 				}
 					
 			}
 		}
 	}
+
 	b = wc->cmdq[card].isrshadow[1]; /* Voltage */
 
 	if (fxovoltage) {
 		if (!(wc->intcount % 100)) {
 			printk("Port %d: Voltage: %d  Debounce %dn",
card + 1, 
-			       b, wc->mods[card].fxo.battdebounce);
+			       b, fxo->battdebounce);
 		}
 	}
 
 	if (abs(b) < battthresh) {
-		wc->mods[card].fxo.nobatttimer++;
-#if 0
-		if (wc->mods[card].fxo.battery == 1)
-			printk("Battery loss: %d (%d debounce)n", b,
wc->mods[card].fxo.battdebounce);
-#endif
-		if (wc->mods[card].fxo.battery &&
!wc->mods[card].fxo.battdebounce) {
-			if (debug & DEBUG_CARD)
-				printk("NO BATTERY on %d/%d!n",
wc->span.spanno, card + 1);
-			wc->mods[card].fxo.battery =  0;
+		/* possible existing states:
+		   battery lost, no debounce timer
+		   battery lost, debounce timer (going to battery
present)
+		   battery present or unknown, no debounce timer
+		   battery present or unknown, debounce timer (going to
battery lost)
+		*/
+
+		if (fxo->battery == BATTERY_LOST) {
+			if (fxo->battdebounce) {
+				/* we were going to BATTERY_PRESENT, but battery was
lost again,
+				   so clear the debounce timer */
+				fxo->battdebounce = 0;
+			}
+		} else {
+			if (fxo->battdebounce) {
+				/* going to BATTERY_LOST, see if we are there yet */
+				if (--fxo->battdebounce == 0) {
+					fxo->battery = BATTERY_LOST;
+					if (debug)
+						printk("NO BATTERY on %d/%d!n",
wc->span.spanno, card + 1);
 #ifdef	JAPAN
-			if ((!wc->ohdebounce) && wc->offhook) {
-				zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK);
-				if (debug & DEBUG_CARD)
-					printk("Signalled On Hookn");
+					if (!wc->ohdebounce && wc->offhook) {
+						zt_hooksig(&wc->chans[card],
ZT_RXSIG_ONHOOK);
+						if (debug)
+							printk("Signalled On Hookn");
 #ifdef	ZERO_BATT_RING
-				wc->onhook++;
-#endif
-			}
+						wc->onhook++;
+#endif
+					}
 #else
-			zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK);
-			zt_alarm_channel(&wc->chans[card],
ZT_ALARM_RED);
-#endif
-			wc->mods[card].fxo.battdebounce = battdebounce;
-		} else if (!wc->mods[card].fxo.battery)
-			wc->mods[card].fxo.battdebounce = battdebounce;
-	} else if (abs(b) > battthresh) {
-		if ((wc->mods[card].fxo.battery < 1) &&
!wc->mods[card].fxo.battdebounce) {
-			if (debug & DEBUG_CARD)
-				printk("BATTERY on %d/%d (%s)!n",
wc->span.spanno, card + 1, 
-					(b < 0) ? "-" : "+");			    
+					zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK);
+					/* set the alarm timer, taking into account that part
of its time
+					   period has already passed while debouncing occurred
*/
+					fxo->battalarm = (battalarm - battdebounce) /
MS_PER_CHECK_HOOK;
+#endif
+				}
+			} else {
+				/* start the debounce timer to verify that battery has
been lost */
+				fxo->battdebounce = battdebounce /
MS_PER_CHECK_HOOK;
+			}
+		}
+	} else {
+		/* possible existing states:
+		   battery lost or unknown, no debounce timer
+		   battery lost or unknown, debounce timer (going to
battery present)
+		   battery present, no debounce timer
+		   battery present, debounce timer (going to battery
lost)
+		*/
+
+		if (fxo->battery == BATTERY_PRESENT) {
+			if (fxo->battdebounce) {

[... 2206 lines stripped ...]

_______________________________________________
--Bandwidth and Colocation Provided by http://www.api-digital.c
om--

zaptel-commits mailing list
To UNSUBSCRIBE or update options visit:
   http://lists.digium.com/mailman/listinfo/zaptel-commits

[1]

about | contact  Other archives ( Real Estate discussion Medical topics )