[zaptel-commits] tzafrir: branch tzafrir/sync r2228 - /team/tzafrir/sync/xpp/

zaptel-commits at lists.digium.com zaptel-commits at lists.digium.com
Sun Feb 25 14:45:37 MST 2007


Author: tzafrir
Date: Sun Feb 25 15:45:36 2007
New Revision: 2228

URL: http://svn.digium.com/view/zaptel?view=rev&rev=2228
Log:
A version of the xpp driver that uses the sync method, amongst many 
other changes.

This version still only logs the lag and does not yet attempt to synchronize.

Modified:
    team/tzafrir/sync/xpp/card_fxo.c
    team/tzafrir/sync/xpp/card_fxs.c
    team/tzafrir/sync/xpp/card_global.c
    team/tzafrir/sync/xpp/xbus-core.c
    team/tzafrir/sync/xpp/xbus-core.h
    team/tzafrir/sync/xpp/xpd.h
    team/tzafrir/sync/xpp/xpp_usb.c
    team/tzafrir/sync/xpp/xpp_zap.c
    team/tzafrir/sync/xpp/xpp_zap.h
    team/tzafrir/sync/xpp/xproto.c
    team/tzafrir/sync/xpp/xproto.h

Modified: team/tzafrir/sync/xpp/card_fxo.c
URL: http://svn.digium.com/view/zaptel/team/tzafrir/sync/xpp/card_fxo.c?view=diff&rev=2228&r1=2227&r2=2228
==============================================================================
--- team/tzafrir/sync/xpp/card_fxo.c (original)
+++ team/tzafrir/sync/xpp/card_fxo.c Sun Feb 25 15:45:36 2007
@@ -417,6 +417,23 @@
 	return 0;
 }
 
+static int FXO_card_open(xpd_t *xpd, lineno_t chan)
+{
+	struct FXO_priv_data	*priv;
+
+	BUG_ON(!xpd);
+	priv = xpd->priv;
+	/*
+	 * We pretend to have battery. If this is really the case
+	 * than next calls to update_battery_status() won't change it.
+	 * If we don't have battery, than on the next calls to
+	 * update_battery_status() a battery_debounce[] cycle would start.
+	 * Than, if no-battery is persistent, asterisk would be notified.
+	 */
+	BIT_SET(priv->battery, chan);
+	return 0;
+}
+
 static void poll_battery(xbus_t *xbus, xpd_t *xpd)
 {
 	int	i;
@@ -634,13 +651,17 @@
 		if(IS_SET(priv->battery, chipsel) && priv->battery_debounce[chipsel]++ > BAT_DEBOUNCE) {
 			DBG("%s/%s/%d: BATTERY OFF voltage=%d\n", xpd->xbus->busname, xpd->xpdname, chipsel, bat);
 			BIT_CLR(priv->battery, chipsel);
-			update_line_status(xpd, chipsel, 0);
+			if(SPAN_REGISTERED(xpd))
+				zt_qevent_lock(&xpd->chans[chipsel], ZT_EVENT_ALARM);
+
 		}
 	} else {
 		priv->battery_debounce[chipsel] = 0;
 		if(!IS_SET(priv->battery, chipsel)) {
 			DBG("%s/%s/%d: BATTERY ON voltage=%d\n", xpd->xbus->busname, xpd->xpdname, chipsel, bat);
 			BIT_SET(priv->battery, chipsel);
+			if(SPAN_REGISTERED(xpd))
+				zt_qevent_lock(&xpd->chans[chipsel], ZT_EVENT_NOALARM);
 		}
 	}
 	/*
@@ -757,12 +778,11 @@
 		.card_hooksig	= FXO_card_hooksig,
 		.card_tick	= FXO_card_tick,
 		.card_ioctl	= FXO_card_ioctl,
+		.card_open	= FXO_card_open,
 
 		.RING		= XPROTO_CALLER(FXO, RING),
 		.RELAY_OUT	= XPROTO_CALLER(FXO, RELAY_OUT),
 		.XPD_STATE	= XPROTO_CALLER(FXO, XPD_STATE),
-
-		.SYNC_SOURCE	= XPROTO_CALLER(GLOBAL, SYNC_SOURCE),
 	},
 	.packet_is_valid = fxo_packet_is_valid,
 	.packet_dump = fxo_packet_dump,

Modified: team/tzafrir/sync/xpp/card_fxs.c
URL: http://svn.digium.com/view/zaptel/team/tzafrir/sync/xpp/card_fxs.c?view=diff&rev=2228&r1=2227&r2=2228
==============================================================================
--- team/tzafrir/sync/xpp/card_fxs.c (original)
+++ team/tzafrir/sync/xpp/card_fxs.c Sun Feb 25 15:45:36 2007
@@ -34,7 +34,8 @@
 static const char rcsid[] = "$Id$";
 
 DEF_PARM(int, print_dbg, 0, 0600, "Print DBG statements");	/* must be before zap_debug.h */
-DEF_PARM_BOOL(poll_digital_inputs, 1, 0600, "Poll Digital Inputs");	/* must be before zap_debug.h */
+DEF_PARM_BOOL(poll_digital_inputs, 1, 0600, "Poll Digital Inputs");
+DEF_PARM_BOOL(reversepolarity, 0, 0600, "Reverse Line Polarity");
 
 /* Signaling is opposite (fxo signalling for fxs card) */
 #if 1
@@ -69,6 +70,22 @@
 
 #define	VALID_CHIPSEL(x)	(((chipsel) >= 0 && (chipsel) <= 7) || (chipsel) == ALL_CHANS)
 
+/* Values of SLIC linefeed control register (0x40) */
+enum fxs_state {
+	FXS_LINE_OPEN		= 0x00,	/* Open */
+	FXS_LINE_ACTIVE		= 0x01,	/* Forward active */
+	FXS_LINE_OHTRANS	= 0x02,	/* Forward on-hook transmission */
+	FXS_LINE_TIPOPEN	= 0x03,	/* TIP open */
+	FXS_LINE_RING		= 0x04,	/* Ringing */
+	FXS_LINE_REV_ACTIVE	= 0x05,	/* Reverse active */
+	FXS_LINE_REV_OHTRANS	= 0x06,	/* Reverse on-hook transmission */
+	FXS_LINE_RING_OPEN	= 0x07	/* RING open */
+};
+
+#define	FXS_LINE_POL_ACTIVE	((reversepolarity) ? FXS_LINE_REV_ACTIVE : FXS_LINE_ACTIVE)
+#define	FXS_LINE_POL_OHTRANS	((reversepolarity) ? FXS_LINE_REV_OHTRANS : FXS_LINE_OHTRANS)
+
+
 /*---------------- FXS Protocol Commands ----------------------------------*/
 
 static /* 0x0F */ DECLARE_CMD(FXS, XPD_STATE, bool on);
@@ -86,13 +103,18 @@
 #define	PROC_FXS_INFO_FNAME	"fxs_info"
 
 struct FXS_priv_data {
-	struct proc_dir_entry		*regfile;
-	struct proc_dir_entry		*fxs_info;
-	xpp_line_t			ledstate[NUM_LEDS];	/* 0 - OFF, 1 - ON */
-	xpp_line_t			ledcontrol[NUM_LEDS];	/* 0 - OFF, 1 - ON */
-	xpp_line_t			found_fsk_pattern;
-	xpp_line_t			msg_waiting;
-	int				led_counter[NUM_LEDS][CHANNELS_PERXPD];
+	struct proc_dir_entry	*regfile;
+	struct proc_dir_entry	*fxs_info;
+	xpp_line_t		ledstate[NUM_LEDS];	/* 0 - OFF, 1 - ON */
+	xpp_line_t		ledcontrol[NUM_LEDS];	/* 0 - OFF, 1 - ON */
+	xpp_line_t		found_fsk_pattern;
+	xpp_line_t		msg_waiting;
+	xpp_line_t		update_offhook_state;
+	int			led_counter[NUM_LEDS][CHANNELS_PERXPD];
+	int			ohttimer[CHANNELS_PERXPD];
+#define OHT_TIMER		6000	/* How long after RING to retain OHT */
+	enum fxs_state		idletxhookstate[CHANNELS_PERXPD];	/* IDLE changing hook state */
+	enum fxs_state		lasttxhook[CHANNELS_PERXPD];
 };
 
 /*
@@ -108,6 +130,16 @@
 #define	LED_BLINK_RING			(1000/8)	/* in ticks */
 
 /*---------------- FXS: Static functions ----------------------------------*/
+static int linefeed_control(xbus_t *xbus, xpd_t *xpd, lineno_t chan, enum fxs_state value)
+{
+	struct FXS_priv_data	*priv;
+
+	priv = xpd->priv;
+	DBG("%s/%s/%d: value=0x%02X\n", xbus->busname, xpd->xpdname, chan, value);
+	priv->lasttxhook[chan] = value;
+	return SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, 0x40, value);
+}
+
 static int do_chan_power(xbus_t *xbus, xpd_t *xpd, lineno_t chan, bool on)
 {
 	int		value = (on) ? 0x06 : 0x00;
@@ -223,20 +255,19 @@
 	}
 }
 
-static int do_callerid(xbus_t *xbus, xpd_t *xpd, lineno_t chan)
-{
-	int		ret = 0;
-	int		i;
-
-	BUG_ON(!xbus);
-	BUG_ON(!xpd);
-	DBG("%s/%s/%d:\n", xbus->busname, xpd->xpdname, chan);
-	ret = SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, 0x40, FXS_LINE_CID);
-	for_each_line(xpd, i)
-		xpd->lasttxhook[i] = FXS_LINE_CID;
-	return ret;
-}
-
+static void restore_leds(xpd_t *xpd)
+{
+	struct FXS_priv_data	*priv;
+	int			i;
+
+	priv = xpd->priv;
+	for_each_line(xpd, i) {
+		if(IS_SET(xpd->offhook, i))
+			MARK_ON(priv, i, LED_GREEN);
+		else
+			MARK_OFF(priv, i, LED_GREEN);
+	}
+}
 
 /*---------------- FXS: Methods -------------------------------------------*/
 
@@ -310,6 +341,9 @@
 	priv->regfile->read_proc = proc_xpd_register_read;
 	priv->regfile->data = xpd;
 #endif
+	for_each_line(xpd, i) {
+		priv->idletxhookstate[i] = FXS_LINE_POL_ACTIVE;
+	}
 	ret = run_initialize_registers(xpd);
 	if(ret < 0)
 		goto err;
@@ -333,6 +367,7 @@
 		do_led(xpd, i, LED_GREEN, 0);
 		msleep(50);
 	}
+	restore_leds(xpd);
 	return 0;
 err:
 	clean_proc(xbus, xpd);
@@ -404,19 +439,26 @@
 		MARK_OFF(priv, i, LED_RED);
 		msleep(2);
 	}
+	restore_leds(xpd);
 	return 0;
 }
 
 int FXS_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, zt_txsig_t txsig)
 {
-	int		ret = 0;
+	struct FXS_priv_data	*priv;
+	int			ret = 0;
+	struct zt_chan		*chan = NULL;
+	enum fxs_state		txhook;
 
 	DBG("%s/%s/%d: %s\n", xbus->busname, xpd->xpdname, pos, txsig2str(txsig));
+	priv = xpd->priv;
 	BUG_ON(xpd->direction != TO_PHONE);
 	if (IS_SET(xpd->digital_inputs, pos)) {
 		DBG("Ignoring signal sent to digital input line\n");
 		return 0;
 	}
+	if(SPAN_REGISTERED(xpd))
+		chan = &xpd->span.chans[pos];
 	switch(txsig) {
 		case ZT_TXSIG_ONHOOK:
 			xpd->ringing[pos] = 0;
@@ -426,41 +468,54 @@
 				ret = CALL_XMETHOD(RELAY_OUT, xpd->xbus, xpd, pos-8, 0);
 				return ret;
 			}
+			if (priv->lasttxhook[pos] == FXS_LINE_OPEN) {
+				/*
+				 * Restore state after KEWL hangup.
+				 */
+				DBG("%s/%s/%d: KEWL STOP\n",
+						xbus->busname, xpd->xpdname, pos);
+				linefeed_control(xbus, xpd, pos, FXS_LINE_POL_ACTIVE);
+				if(IS_SET(xpd->offhook, pos))
+					MARK_ON(priv, pos, LED_GREEN);
+			}
 			ret = CALL_XMETHOD(RING, xbus, xpd, pos, 0);			// RING off
 			if (!IS_SET(xpd->offhook, pos))
 				start_stop_vm_led(xbus, xpd, pos);
-#if 0
-			switch(chan->sig) {
-				case ZT_SIG_EM:
-				case ZT_SIG_FXOKS:
-				case ZT_SIG_FXOLS:
-					xpd->lasttxhook[pos] = xpd->idletxhookstate[pos];
-					break;
-				case ZT_SIG_FXOGS:
-					xpd->lasttxhook[pos] = FXS_LINE_TIPOPEN;
-					break;
+			txhook = priv->lasttxhook[pos];
+			if(chan) {
+				switch(chan->sig) {
+					case ZT_SIG_EM:
+					case ZT_SIG_FXOKS:
+					case ZT_SIG_FXOLS:
+						txhook = priv->idletxhookstate[pos];
+						break;
+					case ZT_SIG_FXOGS:
+						txhook = FXS_LINE_TIPOPEN;
+						break;
+				}
 			}
-#endif
+			ret = linefeed_control(xbus, xpd, pos, txhook);
 			break;
 		case ZT_TXSIG_OFFHOOK:
+			txhook = priv->lasttxhook[pos];
 			if(xpd->ringing[pos]) {
 				BIT_SET(xpd->cid_on, pos);
-				ret = do_callerid(xpd->xbus, xpd, pos);		// CALLER ID
+				txhook = FXS_LINE_OHTRANS;
 			}
 			xpd->ringing[pos] = 0;
-#if 0
-			switch(chan->sig) {
-				case ZT_SIG_EM:
-					xpd->lasttxhook[pos] = FXS_LINE_REV_ACTIVE;
-					break;
-				default:
-					xpd->lasttxhook[pos] = xpd->idletxhookstate[pos];
-					break;
+			if(chan) {
+				switch(chan->sig) {
+					case ZT_SIG_EM:
+						txhook = FXS_LINE_POL_ACTIVE;
+						break;
+					default:
+						txhook = priv->idletxhookstate[pos];
+						break;
+				}
 			}
-#endif
+			ret = linefeed_control(xbus, xpd, pos, txhook);
 			break;
 		case ZT_TXSIG_START:
-			xpd->lasttxhook[pos] = FXS_LINE_RING;
 			xpd->ringing[pos] = 1;
 			BIT_CLR(xpd->cid_on, pos);
 			if(IS_SET(xpd->digital_outputs, pos)) {
@@ -471,7 +526,9 @@
 			ret = CALL_XMETHOD(RING, xbus, xpd, pos, 1);			// RING on
 			break;
 		case ZT_TXSIG_KEWL:
-			xpd->lasttxhook[pos] = FXS_LINE_DISABLED;
+			DBG("%s/%s/%d: KEWL START\n", xbus->busname, xpd->xpdname, pos);
+			linefeed_control(xbus, xpd, pos, FXS_LINE_OPEN);
+			MARK_OFF(priv, pos, LED_GREEN);
 			break;
 		default:
 			NOTICE("%s: Can't set tx state to %s (%d)\n", __FUNCTION__, txsig2str(txsig), txsig);
@@ -553,32 +610,68 @@
 
 static void start_stop_vm_led(xbus_t *xbus, xpd_t *xpd, lineno_t pos)
 {
+	struct FXS_priv_data	*priv;
 	bool		on;
 
+	BUG_ON(!xpd);
 	if (IS_SET(xpd->digital_outputs | xpd->digital_inputs, pos))
 		return;
+	priv = xpd->priv;
 	on = IS_SET(((struct FXS_priv_data *)xpd->priv)->msg_waiting, pos);
 	DBG("%s/%s/%d %s\n", xbus->busname, xpd->xpdname, pos, (on)?"ON":"OFF");
 	set_vm_led_mode(xbus, xpd, pos, on);
 	do_chan_power(xbus, xpd, pos, on);
-	SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x40, (on) ? 0x04 : 0x01);
+	linefeed_control(xbus, xpd, pos, (on) ? FXS_LINE_RING : priv->idletxhookstate[pos]);
 }
 
 static int FXS_chan_onhooktransfer(xbus_t *xbus, xpd_t *xpd, lineno_t chan, int millies)
 {
-	int	ret = 0;
-
-	BUG_ON(!xpd);
+	struct FXS_priv_data	*priv;
+	int			ret = 0;
+
+	BUG_ON(!xpd);
+	priv = xpd->priv;
 	BUG_ON(chan == ALL_CHANS);
 	DBG("%s/%s/%d: (%d millies)\n", xbus->busname, xpd->xpdname, chan, millies);
-	xpd->ohttimer[chan] = millies << 3;
-	xpd->idletxhookstate[chan] = FXS_LINE_CID;	/* OHT mode when idle */
-	if (xpd->lasttxhook[chan] == FXS_LINE_ENABLED) {
+	priv->ohttimer[chan] = millies;
+	priv->idletxhookstate[chan] = FXS_LINE_POL_OHTRANS;	/* OHT mode when idle */
+	if (priv->lasttxhook[chan] == FXS_LINE_POL_ACTIVE) {
 		/* Apply the change if appropriate */
-		ret = do_callerid(xpd->xbus, xpd, chan);		// CALLER ID
+		ret = linefeed_control(xbus, xpd, chan, FXS_LINE_OHTRANS);
 	}
 	start_stop_vm_led(xbus, xpd, chan);
 	return ret;
+}
+
+static int FXS_card_open(xpd_t *xpd, lineno_t chan)
+{
+	struct FXS_priv_data	*priv;
+	bool			is_offhook;
+
+	BUG_ON(!xpd);
+	priv = xpd->priv;
+	is_offhook = IS_SET(xpd->offhook, chan);
+	DBG("%s/%s:%d (is %shook)\n", xpd->xbus->busname, xpd->xpdname,
+			chan, (is_offhook)?"off":"on");
+	/*
+	 * Delegate updating zaptel to FXS_card_tick():
+	 *   The problem is that zt_hooksig() is spinlocking the channel and
+	 *   we are called by zaptel with the spinlock already held on the
+	 *   same channel.
+	 */
+	BIT_SET(priv->update_offhook_state, chan);
+	return 0;
+}
+
+static int FXS_card_close(xpd_t *xpd, lineno_t chan)
+{
+	struct FXS_priv_data	*priv;
+
+	BUG_ON(!xpd);
+	DBG("%s/%s:%d\n", xpd->xbus->busname, xpd->xpdname, chan);
+	priv = xpd->priv;
+	priv->idletxhookstate[chan] = FXS_LINE_POL_ACTIVE;
+	return 0;
 }
 
 /*
@@ -600,6 +693,36 @@
 		byte	pos = input_channels[i];
 
 		SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_READ, 0x06, 0);
+	}
+}
+
+void handle_linefeed(xpd_t *xpd)
+{
+	struct FXS_priv_data	*priv;
+	int			i;
+
+	BUG_ON(!xpd);
+	priv = xpd->priv;
+	BUG_ON(!priv);
+	for_each_line(xpd, i) {
+		if (priv->lasttxhook[i] == FXS_LINE_RING) {
+			/* RINGing, prepare for OHT */
+			priv->ohttimer[i] = OHT_TIMER;
+			priv->idletxhookstate[i] = FXS_LINE_POL_OHTRANS;
+		} else {
+			if (priv->ohttimer[i]) {
+				priv->ohttimer[i]--;
+				if (!priv->ohttimer[i]) {
+					priv->idletxhookstate[i] = FXS_LINE_POL_ACTIVE;
+					if (priv->lasttxhook[i] == FXS_LINE_POL_OHTRANS) {
+						enum fxs_state	txhook = FXS_LINE_POL_ACTIVE;
+						/* Apply the change if appropriate */
+						BIT_CLR(xpd->cid_on, i);
+						linefeed_control(xpd->xbus, xpd, i, txhook);
+					}
+				}
+			}
+		}
 	}
 }
 
@@ -678,6 +801,28 @@
 	}
 #endif
 	handle_fxs_leds(xpd);
+	handle_linefeed(xpd);
+	if(priv->update_offhook_state) {	/* set in FXS_card_open() */
+		int	i;
+
+		for_each_line(xpd, i) {
+			if(!IS_SET(priv->update_offhook_state, i))
+				continue;
+			/*
+			 * Update LEDs and zaptel with current state of line.
+			 */
+			if(IS_SET(xpd->offhook, i)) {
+				NOTICE("%s/%s/%d: Already offhook during open. OK.\n",
+						xbus->busname, xpd->xpdname, i);
+				MARK_ON(priv, i, LED_GREEN);
+				update_line_status(xpd, i, 1);
+			} else {
+				MARK_OFF(priv, i, LED_GREEN);
+				update_line_status(xpd, i, 0);
+			}
+			BIT_CLR(priv->update_offhook_state, i);
+		}
+	}
 #ifndef	VMWI_IOCTL
 	if(SPAN_REGISTERED(xpd))
 		detect_vmwi(xpd);
@@ -721,9 +866,8 @@
 
 static /* 0x0F */ HOSTCMD(FXS, XPD_STATE, bool on)
 {
-	int		ret = 0;
 	int		i;
-	enum fxs_state	value = (on) ? 0x01 : 0x00;
+	enum fxs_state	value = (on) ? FXS_LINE_POL_ACTIVE : FXS_LINE_OPEN;
 	unsigned long		flags;
 	struct FXS_priv_data	*priv;
 
@@ -732,23 +876,22 @@
 	priv = xpd->priv;
 	spin_lock_irqsave(&xpd->lock, flags);
 	DBG("%s/%s: %s\n", xbus->busname, xpd->xpdname, (on) ? "on" : "off");
-	ret = SLIC_DIRECT_REQUEST(xbus, xpd, ALL_CHANS, SLIC_WRITE, 0x40, value);
 	for_each_line(xpd, i)
-		xpd->lasttxhook[i] = value;
+		linefeed_control(xbus, xpd, i, value);
 	if(on) {
 		MARK_ON(priv, ALL_CHANS, LED_GREEN);
 	} else {
 		MARK_OFF(priv, ALL_CHANS, LED_GREEN);
 	}
 	spin_unlock_irqrestore(&xpd->lock, flags);
-	return ret;
+	return 0;
 }
 
 static /* 0x0F */ HOSTCMD(FXS, RING, lineno_t chan, bool on)
 {
 	int			ret = 0;
 	struct FXS_priv_data	*priv;
-	enum fxs_state		value = (on) ? 0x04 : 0x01;
+	enum fxs_state		value = (on) ? FXS_LINE_RING : FXS_LINE_POL_ACTIVE;
 
 	BUG_ON(!xbus);
 	BUG_ON(!xpd);
@@ -756,8 +899,7 @@
 	priv = xpd->priv;
 	set_vm_led_mode(xbus, xpd, chan, 0);
 	do_chan_power(xbus, xpd, chan, on);		// Power up (for ring)
-	ret = SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, 0x40, value);
-	xpd->lasttxhook[chan] = value;
+	ret = linefeed_control(xbus, xpd, chan, value);
 	if(on) {
 		MARK_BLINK(priv, chan, LED_GREEN, LED_BLINK_RING);
 	} else {
@@ -819,7 +961,6 @@
 				DBG("%s/%s/%d: ONHOOK\n", xbus->busname, xpd->xpdname, i);
 				MARK_OFF(priv, i, LED_GREEN);
 				update_line_status(xpd, i, 0);
-				start_stop_vm_led(xbus, xpd, i);
 			}
 		}
 	}
@@ -910,6 +1051,8 @@
 		.card_hooksig	= FXS_card_hooksig,
 		.card_tick	= FXS_card_tick,
 		.chan_onhooktransfer = FXS_chan_onhooktransfer,
+		.card_open	= FXS_card_open,
+		.card_close	= FXS_card_close,
 #ifdef	VMWI_IOCTL
 		.card_ioctl	= FXS_card_ioctl,
 #endif
@@ -917,8 +1060,6 @@
 		.RING		= XPROTO_CALLER(FXS, RING),
 		.RELAY_OUT	= XPROTO_CALLER(FXS, RELAY_OUT),
 		.XPD_STATE	= XPROTO_CALLER(FXS, XPD_STATE),
-
-		.SYNC_SOURCE	= XPROTO_CALLER(GLOBAL, SYNC_SOURCE),
 	},
 	.packet_is_valid = fxs_packet_is_valid,
 	.packet_dump = fxs_packet_dump,
@@ -954,10 +1095,28 @@
 	spin_lock_irqsave(&xpd->lock, flags);
 	priv = xpd->priv;
 	BUG_ON(!priv);
-	len += sprintf(page + len, "\t%-17s: ", "Channel");
+	len += sprintf(page + len, "%-8s %-10s %-10s %-10s\n",
+			"Channel",
+			"idletxhookstate",
+			"lasttxhook",
+			"ohttimer"
+			);
 	for_each_line(xpd, i) {
-		if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i))
-			len += sprintf(page + len, "%d ", i % 10);
+		char	pref;
+
+		if(IS_SET(xpd->digital_outputs, i))
+			pref = 'O';
+		else if(IS_SET(xpd->digital_inputs, i))
+			pref = 'I';
+		else
+			pref = ' ';
+		len += sprintf(page + len, "%c%7d %10d %10d %10d\n",
+				pref,
+				i,
+				priv->idletxhookstate[i],
+				priv->lasttxhook[i],
+				priv->ohttimer[i]
+			      );
 	}
 	len += sprintf(page + len, "\n");
 	for(led = 0; led < NUM_LEDS; led++) {

Modified: team/tzafrir/sync/xpp/card_global.c
URL: http://svn.digium.com/view/zaptel/team/tzafrir/sync/xpp/card_global.c?view=diff&rev=2228&r1=2227&r2=2228
==============================================================================
--- team/tzafrir/sync/xpp/card_global.c (original)
+++ team/tzafrir/sync/xpp/card_global.c Sun Feb 25 15:45:36 2007
@@ -59,6 +59,9 @@
 	return ret;
 }
 
+/*
+ * The XPD parameter is totaly ignored by the driver and firmware as well.
+ */
 /* 0x19 */ HOSTCMD(GLOBAL, SYNC_SOURCE, bool setit, bool is_master)
 {
 	xframe_t	*xframe;
@@ -66,14 +69,14 @@
 	byte		mask = 0;
 
 	BUG_ON(!xbus);
-	BUG_ON(!xpd);
 	if(is_master)
 		mask |= BIT(0);
 	if(!setit)
 		mask |= BIT(1);
-	DBG("SYNC_SOURCE %s setit=%s is_master=%s (mask=0x%X)\n",
-			xpd->xpdname, (setit)?"yes":"no", (is_master)?"yes":"no", mask);
-	XFRAME_NEW(xframe, pack, xbus, GLOBAL, SYNC_SOURCE, xpd->id);
+	DBG("%s: setit=%s is_master=%s\n",
+			xbus->busname,
+			(setit)?"yes":"no", (is_master)?"yes":"no");
+	XFRAME_NEW(xframe, pack, xbus, GLOBAL, SYNC_SOURCE, 0);
 	RPACKET_FIELD(pack, GLOBAL, SYNC_SOURCE, mask) = mask;
 	xframe_send(xbus, xframe);
 	return 0;
@@ -94,7 +97,6 @@
 	xpp_line_t		line_status = RPACKET_FIELD(pack, GLOBAL, DEV_DESC, line_status);
 	xpd_addr_t		xpd_addr = RPACKET_FIELD(pack, GLOBAL, DEV_DESC, addr);
 	struct card_desc_struct	*card_desc;
-	unsigned long		flags;
 
 	BUG_ON(!xbus);
 	if((card_desc = kmalloc(sizeof(struct card_desc_struct), GFP_ATOMIC)) == NULL) {
@@ -108,22 +110,10 @@
 	card_desc->type = type;
 	card_desc->rev = rev;
 	card_desc->xpd_addr = xpd_addr;
+	card_desc->line_status = line_status;
 	DBG("%s: xpd=%d-%d type=%d rev=%d line_status=0x%04X\n",
 			xbus->busname, xpd_addr.unit, xpd_addr.subunit, type, rev, line_status);
-	spin_lock_irqsave(&xbus->lock, flags);
-	if(type == XPD_TYPE_NOMODULE)
-		XBUS_COUNTER(xbus, DEV_DESC_EMPTY)++;
-	else
-		XBUS_COUNTER(xbus, DEV_DESC_FULL)++;
-	atomic_inc(&xbus->count_poll_answers);
-	list_add_tail(&card_desc->card_list, &xbus->poll_results);
-	spin_unlock_irqrestore(&xbus->lock, flags);
-	/*
-	 * wake_up only after exiting our critical section.
-	 * We suspect that otherwise a spinlock nesting may occur
-	 * and cause a panic (if spinlock debugging is compiled in).
-	 */
-	wake_up(&xbus->wait_for_polls);
+	xbus_poller_notify(xbus, card_desc);
 	return 0;
 }
 
@@ -219,8 +209,11 @@
 		NOTICE("%s: received %s for non-existing xpd: addr=0x%02X\n", __FUNCTION__, cmd->name, xpd_num);
 		return -EPROTO;
 	}
-	DBG("%s/%s: SYNC_REPLY: 0x%X %s\n", xpd->xbus->busname, xpd->xpdname,
-			mask, (setit) ? "SET SYNC MASTER" : "");
+	DBG("%s/%s: mask=0x%X %s\n",
+			xpd->xbus->busname, xpd->xpdname,
+			mask,
+			(setit) ? "SET SYNC MASTER" : "");
+	dump_packet("SYNC_REPLY", pack, 1);
 	return 0;
 }
 

Modified: team/tzafrir/sync/xpp/xbus-core.c
URL: http://svn.digium.com/view/zaptel/team/tzafrir/sync/xpp/xbus-core.c?view=diff&rev=2228&r1=2227&r2=2228
==============================================================================
--- team/tzafrir/sync/xpp/xbus-core.c (original)
+++ team/tzafrir/sync/xpp/xbus-core.c Sun Feb 25 15:45:36 2007
@@ -32,6 +32,7 @@
 #ifdef	PROTOCOL_DEBUG
 #include <linux/ctype.h>
 #endif
+#include <linux/workqueue.h>
 #include <linux/device.h>
 #include <linux/delay.h>	/* for msleep() to debug */
 #include "xpd.h"
@@ -77,7 +78,6 @@
 static int xbus_read_waitfor_xpds(char *page, char **start, off_t off, int count, int *eof, void *data);
 
 /* Data structures */
-struct workqueue_struct		*xpp_worker = NULL;
 static spinlock_t		xbuses_lock = SPIN_LOCK_UNLOCKED;
 static xbus_t			*xbuses_array[MAX_BUSES] = {};
 static int			bus_count = 0;
@@ -264,15 +264,22 @@
 /*
  * Return pointer to next packet slot in the frame
  * or NULL if the frame is full.
+ *
+ * FIXME: we do not use atomic_add_return() because kernel-2.6.8
+ *        does not have it. This make this code a little racy,
+ *        but we currently call xframe_next_packet() only in the
+ *        PCM loop (xbus_tick() etc.)
  */
 xpacket_t *xframe_next_packet(xframe_t *frm, int len)
 {
-	int newlen = atomic_add_return(len, &frm->frame_len);
+	int newlen = atomic_read(&frm->frame_len);
+
+	newlen += len;
 //	DBG("len=%d, newlen=%d, frm->frame_len=%d\n", len, newlen, XFRAME_LEN(frm));
 	if (newlen > XFRAME_DATASIZE) {
-		atomic_sub(len, &frm->frame_len);
 		return NULL;
 	}
+	atomic_add(len, &frm->frame_len);
 	return (xpacket_t *)(frm->packets + newlen - len);
 }
 
@@ -435,13 +442,12 @@
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
 static void xbus_poll(struct work_struct *work)
 {
-	xbus_t			*xbus = container_of(work, xbus_t, xpds_init_work);
+	struct xbus_poller	*poller = container_of(work, struct xbus_poller, xpds_init_work);
 #else
 static void xbus_poll(void *data)
 {
-	xbus_t			*xbus = data;
-#endif
-
+	struct xbus_poller	*poller = data;
+#endif
 	int			id;
 	int			ret = 0;
 	unsigned long		flags;
@@ -451,7 +457,11 @@
 	struct list_head	additions_list;
 	int			count_removed;
 	int			count_added;
-
+	xbus_t			*xbus;
+
+	BUG_ON(!poller);
+	xbus = poller->xbus;
+	BUG_ON(!xbus);
 	if(!down_read_trylock(&xbus->in_use)) {
 		ERR("%s is being removed...\n", xbus->busname);
 		return;
@@ -459,6 +469,7 @@
 	msleep(2);	/* roundtrip for older polls */
 	spin_lock_irqsave(&xbus->lock, flags);
 	DBG("%s\n", xbus->busname);
+	poller->is_polling = 1;
 
 	/*
 	 * Send out the polls
@@ -481,7 +492,7 @@
 	 * Wait for replies
 	 */
 	DBG("%s: Polled %d XPD's. Waiting for replies max %d jiffies\n", xbus->busname, MAX_XPDS, poll_timeout);
-	ret = wait_event_interruptible_timeout(xbus->wait_for_polls, atomic_read(&xbus->count_poll_answers) >= MAX_XPDS, poll_timeout);
+	ret = wait_event_interruptible_timeout(poller->wait_for_polls, atomic_read(&poller->count_poll_answers) >= MAX_XPDS, poll_timeout);
 	if(ret == 0) {
 		ERR("%s: Poll timeout. Continuing anyway.\n", xbus->busname);
 		/*
@@ -500,7 +511,7 @@
 	INIT_LIST_HEAD(&additions_list);
 	count_removed = 0;
 	count_added = 0;
-	list_for_each_safe(card, next_card, &xbus->poll_results) {
+	list_for_each_safe(card, next_card, &poller->poll_results) {
 		struct card_desc_struct	*card_desc = list_entry(card, struct card_desc_struct, card_list);
 		byte			type = card_desc->type;
 		xpd_t			*xpd;
@@ -523,7 +534,7 @@
 	 * We set this *after* poll is finished, so wait_for_xpd_initialization can
 	 * tell we already know how many units we have.
 	 */
-	atomic_set(&xbus->count_xpds_to_initialize, count_added);
+	atomic_set(&poller->count_xpds_to_initialize, count_added);
 	spin_unlock_irqrestore(&xbus->lock, flags);
 	INFO("%s: Poll results: removals=%d additions=%d\n", xbus->busname, count_removed, count_added);
 	/*
@@ -548,39 +559,144 @@
 		list_del(card);
 		/* FIXME: card_detected() should have a return value for count_xpds_initialized */
 		card_detected(card_desc);
-		atomic_inc(&xbus->count_xpds_initialized);
-	}
-	wake_up(&xbus->wait_for_xpd_initialization);
+		atomic_inc(&poller->count_xpds_initialized);
+	}
+	wake_up(&poller->wait_for_xpd_initialization);
 out:
+	poller->is_polling = 0;
 	up_read(&xbus->in_use);
 	return;
 }
 
+void xbus_poller_notify(xbus_t *xbus, struct card_desc_struct *card_desc)
+{
+	struct xbus_poller	*poller;
+	unsigned long		flags;
+
+	BUG_ON(!xbus);
+	poller = xbus->poller;
+	BUG_ON(!poller);
+	if(!poller->is_polling) {
+		NOTICE("%s: %d-%d replied not during poll. Ignore\n",
+				xbus->busname,
+				card_desc->xpd_addr.unit,
+				card_desc->xpd_addr.subunit);
+		kfree(card_desc);
+		return;
+	}
+	spin_lock_irqsave(&xbus->lock, flags);
+	if(card_desc->type == XPD_TYPE_NOMODULE)
+		XBUS_COUNTER(xbus, DEV_DESC_EMPTY)++;
+	else
+		XBUS_COUNTER(xbus, DEV_DESC_FULL)++;
+	atomic_inc(&poller->count_poll_answers);
+	list_add_tail(&card_desc->card_list, &poller->poll_results);
+	spin_unlock_irqrestore(&xbus->lock, flags);
+	/*
+	 * wake_up only after exiting our critical section.
+	 * We suspect that otherwise a spinlock nesting may occur
+	 * and cause a panic (if spinlock debugging is compiled in).
+	 */
+	wake_up(&poller->wait_for_polls);
+	return;
+}
+
+static void poller_destroy(struct xbus_poller *poller)
+{
+	if(!poller)
+		return;
+	if(poller->xbus) {
+		DBG("%s: detach poller\n", poller->xbus->busname);
+		poller->xbus->poller = NULL;
+	}
+	if (poller->wq) {
+		DBG("%s: destroy workqueue\n", poller->xbus->busname);
+		flush_workqueue(poller->wq);
+		destroy_workqueue(poller->wq);
+		poller->wq = NULL;
+	}
+	kfree(poller);
+}
+
+/*
+ * Allocate a poller for the xbus including the nessessary workqueue.
+ * May call blocking operations, but only briefly (as we are called
+ * from xbus_new() which is called from khubd.
+ */
+static struct xbus_poller *poller_new(xbus_t *xbus)
+{
+	struct xbus_poller	*poller;
+
+	BUG_ON(xbus->busname[0] == '\0');	/* No name? */
+	BUG_ON(xbus->poller);			/* Hmmm... overrun pollers? */
+	DBG("%s\n", xbus->busname);
+	poller = kmalloc(sizeof(*poller), SLAB_KERNEL);
+	if(!poller)
+		goto err;
+	memset(poller, 0, sizeof(*poller));
+	poller->xbus = xbus;
+	xbus->poller = poller;
+	/* poll related variables */
+	atomic_set(&poller->count_poll_answers, 0);
+	atomic_set(&poller->count_xpds_to_initialize, 0);
+	atomic_set(&poller->count_xpds_initialized, 0);
+	INIT_LIST_HEAD(&poller->poll_results);
+	init_waitqueue_head(&poller->wait_for_polls);
+	init_waitqueue_head(&poller->wait_for_xpd_initialization);
+	poller->wq = create_singlethread_workqueue(xbus->busname);
+	if(!poller->wq) {
+		ERR("%s: Failed to create poller workqueue.\n", xbus->busname);
+		goto err;
+	}
+	return poller;
+err:
+	poller_destroy(poller);
+	return NULL;
+}
+
+/*
+ * Sends an xbus_poll() work to the poller workqueue of the given xbus.
+ */
+static int poller_dispatch(xbus_t *xbus)
+{
+	struct xbus_poller	*poller = xbus->poller;
+
+	if(!poller) {
+		ERR("%s: missing poller\n", xbus->busname);
+		return 0;
+	}
+	/* Initialize the work. (adapt to kernel API changes). */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
+	INIT_WORK(&poller->xpds_init_work, xbus_poll);
+#else
+	INIT_WORK(&poller->xpds_init_work, xbus_poll, poller);
+#endif
+	/* Now send it */
+	if(!queue_work(poller->wq, &poller->xpds_init_work)) {
+		ERR("%s: Failed to queue xpd initialization work\n",
+				xbus->busname);
+		return 0;
+	}
+	return 1;
+}
 
 void xbus_activate(xbus_t *xbus)
 {
-	xbus_ops_t *ops;
+	xbus_ops_t		*ops;
+	struct xbus_poller	*poller;
 
 	BUG_ON(!xbus);
 	ops = xbus->ops;
 	BUG_ON(!ops);
+	poller = xbus->poller;
+	BUG_ON(!poller);
 	/* Sanity checks */
 	BUG_ON(!ops->xframe_send);
 	BUG_ON(!ops->xframe_new || !ops->xframe_free);
 	xbus->hardware_exists = 1;
 	DBG("Activating: %s\n", xbus->busname);
-
 	/* Poll it */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
-	INIT_WORK(&xbus->xpds_init_work, xbus_poll);
-#else
-	INIT_WORK(&xbus->xpds_init_work, xbus_poll, xbus);
-#endif
-
-	if(!queue_work(xpp_worker, &xbus->xpds_init_work)) {
-		ERR("Failed to queue xpd initialization work\n");
-		/* FIXME: need to return error */
-	}
+	poller_dispatch(xbus);
 }
 
 void xbus_disconnect(xbus_t *xbus)
@@ -685,6 +801,7 @@
 	device_remove_file(&xbus->the_bus, &dev_attr_status);
 	device_remove_file(&xbus->the_bus, &dev_attr_connector);
 	device_unregister(&xbus->the_bus);
+	poller_destroy(xbus->poller);
 	kfree(xbus);
 }
 
@@ -697,17 +814,16 @@
 	DBG("%s\n", xbus->busname);
 }
 
-
 xbus_t *xbus_new(xbus_ops_t *ops)
 {
-	int		err;
-	xbus_t		*xbus = NULL;
+	int			err;
+	xbus_t			*xbus = NULL;
+	struct xbus_poller	*poller;
 
 	BUG_ON(!ops);
 	xbus = xbus_alloc();
 	if(!xbus)
 		return NULL;
-
 	/* Init data structures */
 	spin_lock_init(&xbus->lock);
 	snprintf(xbus->busname, XBUS_NAMELEN, "XBUS-%02d", xbus->num);
@@ -715,14 +831,13 @@
 	init_waitqueue_head(&xbus->packet_cache_empty);
 	atomic_set(&xbus->packet_counter, 0);
 
-	/* poll related variables */
-	atomic_set(&xbus->count_poll_answers, 0);
-	atomic_set(&xbus->count_xpds_to_initialize, 0);
-	atomic_set(&xbus->count_xpds_initialized, 0);
-	INIT_LIST_HEAD(&xbus->poll_results);
-	init_waitqueue_head(&xbus->wait_for_polls);
-	init_waitqueue_head(&xbus->wait_for_xpd_initialization);
 	xbus->num_xpds = 0;
+	poller = poller_new(xbus);
+	if(!poller) {
+		ERR("Failed to allocate poller\n");
+		xbus_free(xbus);
+		return NULL;
+	}
 
 	init_rwsem(&xbus->in_use);
 	xbus_reset_counters(xbus);
@@ -866,14 +981,16 @@
 #if CONFIG_PROC_FS
 static int xbus_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
 {
-	int len = 0;
-	unsigned long flags;
-	xbus_t	*xbus = data;
-	int i;
+	xbus_t			*xbus = data;
+	struct xbus_poller	*poller;
+	unsigned long		flags;
+	int			len = 0;
+	int			i;
 
 	if(!xbus)
 		goto out;
 	spin_lock_irqsave(&xbus->lock, flags);
+	poller = xbus->poller;
 
 	len += sprintf(page + len, "%s: CONNECTOR=%s STATUS=%s bus_type=%d\n",
 			xbus->busname,
@@ -882,10 +999,10 @@
 			xbus->bus_type
 		      );
 	len += sprintf(page + len, "POLLS: %d/%d\n",
-			atomic_read(&xbus->count_poll_answers), MAX_XPDS);
+			atomic_read(&poller->count_poll_answers), MAX_XPDS);
 	len += sprintf(page + len, "XPDS_READY: %d/%d\n",
-			atomic_read(&xbus->count_xpds_initialized),
-			atomic_read(&xbus->count_xpds_to_initialize));
+			atomic_read(&poller->count_xpds_initialized),
+			atomic_read(&poller->count_xpds_to_initialize));
 	len += sprintf(page + len, "\nmax_packet_size=%d open_counter=%d packet_count=%d\n",
 			xbus->max_packet_size,
 			xbus->open_counter,
@@ -916,10 +1033,12 @@
 	int		len = 0;
 	unsigned long	flags;
 	xbus_t		*xbus = data;
+	struct xbus_poller	*poller;
 	int		ret;
 
 	if(!xbus)
 		goto out;
+	poller = xbus->poller;
 	DBG("%s: Waiting for card initialization of %d XPD's max %d seconds\n", xbus->busname, MAX_XPDS, INITIALIZATION_TIMEOUT/HZ);
 	/*
 	 * xbus_poll sets count_xpds_to_initialize only when polling is finished.
@@ -927,9 +1046,9 @@
 	 *   - It is none zero -- meaning we already have the poll results.
 	 *   - And all units have finished initialization.
 	 */
-	ret = wait_event_interruptible_timeout(xbus->wait_for_xpd_initialization,
-			atomic_read(&xbus->count_xpds_to_initialize) &&
-			atomic_read(&xbus->count_xpds_initialized) >= atomic_read(&xbus->count_xpds_to_initialize),
+	ret = wait_event_interruptible_timeout(poller->wait_for_xpd_initialization,
+			atomic_read(&poller->count_xpds_to_initialize) &&
+			atomic_read(&poller->count_xpds_initialized) >= atomic_read(&poller->count_xpds_to_initialize),
 			INITIALIZATION_TIMEOUT);
 	if(ret == 0) {
 		ERR("%s: Card Initialization Timeout\n", xbus->busname);
@@ -942,8 +1061,8 @@
 	spin_lock_irqsave(&xbus->lock, flags);
 	len += sprintf(page + len, "XPDS_READY: %s: %d/%d\n",
 			xbus->busname,
-			atomic_read(&xbus->count_xpds_initialized),
-			atomic_read(&xbus->count_xpds_to_initialize));
+			atomic_read(&poller->count_xpds_initialized),
+			atomic_read(&poller->count_xpds_to_initialize));
 	spin_unlock_irqrestore(&xbus->lock, flags);
 out:
 	if (len <= off+count)
@@ -1105,11 +1224,6 @@
 
 static void xbus_core_cleanup(void)
 {
-	if (xpp_worker) {
-		flush_workqueue(xpp_worker);
-		destroy_workqueue(xpp_worker);
-		xpp_worker = NULL;
-	}
 #ifdef	XPP_DEBUGFS
 	if(debugfs_root) {
 		DBG("Removing xpp from debugfs\n");
@@ -1143,12 +1257,6 @@
 			NULL, NULL);
 	if(!xframes_cache) {
 		return -ENOMEM;
-	}
-	xpp_worker = create_singlethread_workqueue("xppworker");
-	if(!xpp_worker) {
-		ERR("Failed to create card detector workqueue.\n");
-		ret = -ENOMEM;
-		goto err;
 	}
 #ifdef CONFIG_PROC_FS
 	proc_xbuses = create_proc_read_entry(PROC_XBUSES, 0444, xpp_proc_toplevel, read_proc_xbuses, NULL);
@@ -1201,6 +1309,7 @@
 EXPORT_SYMBOL(xbus_reset_counters);
 EXPORT_SYMBOL(xframe_next_packet);
 EXPORT_SYMBOL(dump_xframe);
+EXPORT_SYMBOL(xbus_poller_notify);
 #ifdef XPP_DEBUGFS
 EXPORT_SYMBOL(xbus_log);
 #endif

Modified: team/tzafrir/sync/xpp/xbus-core.h
URL: http://svn.digium.com/view/zaptel/team/tzafrir/sync/xpp/xbus-core.h?view=diff&rev=2228&r1=2227&r2=2228
==============================================================================
--- team/tzafrir/sync/xpp/xbus-core.h (original)
+++ team/tzafrir/sync/xpp/xbus-core.h Sun Feb 25 15:45:36 2007
@@ -61,6 +61,7 @@
 void xbus_activate(xbus_t *xbus);
 void xbus_disconnect(xbus_t *xbus);
 
+void xbus_poller_notify(xbus_t *xbus, struct card_desc_struct *card_desc);
 void xbus_reset_counters(xbus_t *xbus);
 
 int xbus_register_xpd(xbus_t *xbus, xpd_t *xpd);

Modified: team/tzafrir/sync/xpp/xpd.h
URL: http://svn.digium.com/view/zaptel/team/tzafrir/sync/xpp/xpd.h?view=diff&rev=2228&r1=2227&r2=2228
==============================================================================
--- team/tzafrir/sync/xpp/xpd.h (original)
+++ team/tzafrir/sync/xpp/xpd.h Sun Feb 25 15:45:36 2007
@@ -155,12 +155,34 @@
 	byte			rev;		/* Revision number */
 	byte			type;		/* LSB: 1 - to_phone, 0 - to_line */
 	xpd_addr_t		xpd_addr;
+	xpp_line_t		line_status;	/* Initial line status (offhook) */
 };
 
 #ifdef XPP_DEBUGFS
 /* definition in xbus-core.c */
 struct debugfs_data;
 #endif
+
+/*
+ * Encapsulate all poll related data of a single xbus.
+ */
+struct xbus_poller {
+	/*
+	 * Bus scanning
+	 */
+	xbus_t			*xbus;
+	struct workqueue_struct	*wq;
+	bool			is_polling;
+	atomic_t		count_poll_answers;
+	struct list_head	poll_results;
+	wait_queue_head_t	wait_for_polls;
+
+	struct work_struct	xpds_init_work;
+
+	atomic_t		count_xpds_to_initialize;
+	atomic_t		count_xpds_initialized;
+	wait_queue_head_t	wait_for_xpd_initialization;
+};
 
 /*
  * An xbus is a transport layer for Xorcom Protocol commands
@@ -186,18 +208,7 @@
 	atomic_t		packet_counter;		/* Allocated packets */
 	wait_queue_head_t	packet_cache_empty;
 
-	/*
-	 * Bus scanning
-	 */
-	atomic_t		count_poll_answers;
-	struct list_head	poll_results;
-	wait_queue_head_t	wait_for_polls;
-
-	struct work_struct	xpds_init_work;
-
-	atomic_t		count_xpds_to_initialize;
-	atomic_t		count_xpds_initialized;
-	wait_queue_head_t	wait_for_xpd_initialization;
+	struct xbus_poller	*poller;
 
 	struct	rw_semaphore	in_use;
 	int			num_xpds;
@@ -254,16 +265,6 @@
 #undef C_
 
 #define	XPD_COUNTER_MAX	(sizeof(xpd_counters)/sizeof(xpd_counters[0]))
-
-/* Values of SLIC register 0x40 */
-enum fxs_state {
-	FXS_LINE_DISABLED	= 0x00,
-	FXS_LINE_ENABLED	= 0x01,
-	FXS_LINE_CID		= 0x02,
-	FXS_LINE_TIPOPEN	= 0x03,	/* For GroundStart signalling */
-	FXS_LINE_RING		= 0x04,
-	FXS_LINE_REV_ACTIVE	= 0x05
-};
 
 /*
  * An XPD is a single Xorcom Protocol Device
@@ -285,10 +286,6 @@
 
 	bool		ringing[CHANNELS_PERXPD];
 
-	enum fxs_state	lasttxhook[CHANNELS_PERXPD];
-	int		idletxhookstate[CHANNELS_PERXPD];	/* IDLE changing hook state */
-	int		ohttimer[CHANNELS_PERXPD];
-
 	xbus_t *xbus;			/* The XBUS we are connected to */
 
 	spinlock_t	lock;

Modified: team/tzafrir/sync/xpp/xpp_usb.c
URL: http://svn.digium.com/view/zaptel/team/tzafrir/sync/xpp/xpp_usb.c?view=diff&rev=2228&r1=2227&r2=2228
==============================================================================
--- team/tzafrir/sync/xpp/xpp_usb.c (original)
+++ team/tzafrir/sync/xpp/xpp_usb.c Sun Feb 25 15:45:36 2007
@@ -266,8 +266,9 @@
 	if(atomic_read(&xusb->pending_writes) > MAX_PENDING_WRITES) {
 		static	int rate_limit;
 
-		if((rate_limit++ % 1000) < 10)
-			ERR("%s: %s: more than %d pending writes. Dropping.\n", __FUNCTION__, xbus->busname, MAX_PENDING_WRITES);
+		if((rate_limit++ % 5000) == 0)
+			ERR("%s: %s: more than %d pending writes (%d). Dropping.\n",
+					__FUNCTION__, xbus->busname, MAX_PENDING_WRITES, rate_limit);
 		ret = -ENODEV;
 		goto freepack;
 	}

Modified: team/tzafrir/sync/xpp/xpp_zap.c
URL: http://svn.digium.com/view/zaptel/team/tzafrir/sync/xpp/xpp_zap.c?view=diff&rev=2228&r1=2227&r2=2228
==============================================================================
--- team/tzafrir/sync/xpp/xpp_zap.c (original)
+++ team/tzafrir/sync/xpp/xpp_zap.c Sun Feb 25 15:45:36 2007
@@ -63,11 +63,30 @@
 static unsigned int		xpp_timer_count = 0;
 static unsigned int		xpp_last_jiffies = 0;
 
+#ifdef	ZAPTEL_SYNC_TICK
+/*
+ * Statistics variables
+ */
+static struct timeval		ticked_zaptel;
+static struct timeval		ticked_xpp;
+static long			usec_lag_curr;	/* current: zaptel - xpp */
+static long			usec_lag_prev;	/* previous: zaptel - xpp */
+static long			usec_delta;	/* previous - current */
+static long			usec_sigma;	/* sum of deltas */
+static long			status_cleared_at;
+static long			since_status_clear;
+static bool			zaptel_is_ticking;
+
+DEF_PARM_BOOL(sync_tick_active, 1, 0600, "Measure via zaptel sync_tick() method");
+
+static void sync_status_clear(void);
+#endif
+
 
 DEF_PARM_BOOL(pcm_tasklet, 0, 0600, "Handle PCM in a tasklet (lower interrupt load)");
 DEF_PARM(int, disable_pcm, 0, 0600, "Disable all PCM transmissions");
 DEF_PARM(int, print_dbg, 0, 0600, "Print DBG statements");
-DEF_PARM_BOOL(zap_autoreg, 1, 0600, "Register spans automatically (1) or not (0)");
+DEF_PARM_BOOL(zap_autoreg, 0, 0600, "Register spans automatically (1) or not (0)");
 DEF_PARM_BOOL(prefmaster, 1, 0600, "Do we want to be zaptel preferred sync master");
 #ifdef	XPP_EC_CHUNK
 DEF_PARM_BOOL(xpp_ec, 1, 0400, "Do we use our own (1) or Zaptel's (0) echo canceller");
@@ -96,11 +115,11 @@
 static DECLARE_TASKLET(tasklet_tick, xpp_tick, 0L);
 static atomic_t		missed_ticks = ATOMIC_INIT(0);	/* In pcm_tasklet mode */
 
-static void external_sync(xpd_t *the_xpd)
-{
-	int	i, j;
-
-	DBG("SYNC %s\n", (the_xpd)?"Astribanks":"HOST");
+static void external_sync(xbus_t *the_xbus)
+{
+	int	i;
+
+	DBG("%s\n", (the_xbus) ? the_xbus->busname : "HOST");
 	// Shut all down
 	for(i = 0; i < MAX_BUSES; i++) {
 		xbus_t	*xbus = xbus_of(i);
@@ -108,25 +127,27 @@
 			continue;
 		if (!xbus->hardware_exists)
 			continue;
-		for(j = 0; j < MAX_XPDS; j++) {
-			xpd_t	*xpd = xpd_of(xbus, j);
-			if(xpd) {
-				CALL_XMETHOD(SYNC_SOURCE, xbus, xpd, 1, 0);
-			}
-		}
-	}
-	if(the_xpd)
-		CALL_XMETHOD(SYNC_SOURCE, the_xpd->xbus, the_xpd, 1, 1);
+		CALL_PROTO(GLOBAL, SYNC_SOURCE, xbus, NULL, 1, 0);
+	}
+	if(the_xbus)
+		CALL_PROTO(GLOBAL, SYNC_SOURCE, the_xbus, NULL, 1, 1);
 }
 
 /*
  * Change sync_master. May block. Cannot be called from atomic context
  */
-void sync_master_is(xpd_t *xpd)
-{
-	DBG("SYNC MASTER CHANGED: %s => %s\n",
-			(sync_master) ? sync_master->xpdname : "HOST",
-			(xpd) ? xpd->xpdname : "HOST");
+static void sync_master_is(xbus_t *xbus)
+{
+	xpd_t	*xpd = (xbus)? xpd_of(xbus, 0) : NULL;
+
+	if(xbus && !xpd) {
+		NOTICE("Cannot set sync master to %s (has no XPD #0).\n",
+				xbus->busname);
+		xbus = NULL;	/* Fallback to HOST */
+	}
+	DBG("SYNC MASTER CHANGING: %s => %s\n",
+			(sync_master) ? sync_master->xbus->busname : "HOST",
+			(xbus) ? xbus->busname : "HOST");
 	/* First stop all generators */

[... 397 lines stripped ...]


More information about the zaptel-commits mailing list