summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2008-01-10 18:12:27 +0000
committertzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2008-01-10 18:12:27 +0000
commit9899bafe997a4e020f302c99a6e025b4e8b25191 (patch)
tree8a108b05d0f319c95ba83f1d5984ae261572bebf
parent1d7d5b07325a186785b22abf09ff531dfc2edd54 (diff)
xpp.r5254:
* Improved polarity reversal hangups in FXO (r5194). Fixed false detection of polarity reversals. * Optimize xframe allocation, by not zeroing the whole memory (in get_xframe()). * Fixed erronous error message that appeared sometimes from fpga_load during USB renumeration. * Zaptel::Chans now provides battery() reporting for some FXO channels (Astribank FXO and wcfxo). git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.2@3643 5390a7c7-147a-4af0-8ec9-7488f05a26cb
-rw-r--r--xpp/.version2
-rw-r--r--xpp/Changelog_xpp12
-rw-r--r--xpp/Kbuild (renamed from xpp/Makefile)5
-rw-r--r--xpp/README.Astribank4
-rw-r--r--xpp/card_bri.c11
-rw-r--r--xpp/card_fxo.c99
-rw-r--r--xpp/card_global.c10
-rw-r--r--xpp/card_pri.c12
-rwxr-xr-xxpp/init_card_9_2928
-rw-r--r--xpp/utils/Makefile4
-rwxr-xr-xxpp/utils/astribank_hook18
-rw-r--r--xpp/utils/fpga_load.c30
-rwxr-xr-xxpp/utils/lszaptel18
-rwxr-xr-xxpp/utils/zapconf11
-rwxr-xr-xxpp/utils/zaptel_hardware4
-rw-r--r--xpp/utils/zconf/Zaptel.pm2
-rw-r--r--xpp/utils/zconf/Zaptel/Chans.pm102
-rw-r--r--xpp/utils/zconf/Zaptel/Config/Defaults.pm25
-rw-r--r--xpp/utils/zconf/Zaptel/Hardware/PCI.pm17
-rw-r--r--xpp/utils/zconf/Zaptel/Span.pm17
-rw-r--r--xpp/utils/zconf/Zaptel/Xpp/Line.pm59
-rw-r--r--xpp/utils/zconf/Zaptel/Xpp/Xpd.pm43
-rw-r--r--xpp/xbus-core.c41
-rw-r--r--xpp/xbus-pcm.c48
-rw-r--r--xpp/xdefs.h7
-rw-r--r--xpp/xframe_queue.c10
-rw-r--r--xpp/xpd.h13
-rw-r--r--xpp/xpp_usb.c4
-rw-r--r--xpp/xpp_zap.c21
-rw-r--r--xpp/xproto.c20
-rw-r--r--xpp/xproto.h17
-rw-r--r--xpp/zap_debug.c26
-rw-r--r--xpp/zap_debug.h17
33 files changed, 536 insertions, 221 deletions
diff --git a/xpp/.version b/xpp/.version
index 79b9063..d658f52 100644
--- a/xpp/.version
+++ b/xpp/.version
@@ -1 +1 @@
-trunk-r5178
+trunk-r5254
diff --git a/xpp/Changelog_xpp b/xpp/Changelog_xpp
index 9112826..31684e0 100644
--- a/xpp/Changelog_xpp
+++ b/xpp/Changelog_xpp
@@ -1,4 +1,14 @@
-Mon Dec 24 2007 Tzafrir Cohen <tzafrir.cohen@xorcom.com> - xpp.r5178
+Thu Jan 10 2008 Oron Peled <oron.peled@xorcom.com> - xpp.r5254
+ * Improved polarity reversal hangups in FXO (r5194).
+ Fixed false detection of polarity reversals.
+ * Optimize xframe allocation, by not zeroing the whole
+ memory (in get_xframe()).
+ * Fixed erronous error message that appeared sometimes
+ from fpga_load during USB renumeration.
+ * Zaptel::Chans now provides battery() reporting for some FXO
+ channels (Astribank FXO and wcfxo).
+
+Tue Dec 25 2007 Tzafrir Cohen <tzafrir.cohen@xorcom.com> - xpp.r5179
* xpd_pri: Basically ready.
* PCM synchronization changes:
- Each Astribank unit ticks independently. Each with its own PLL.
diff --git a/xpp/Makefile b/xpp/Kbuild
index bde055e..9ec225f 100644
--- a/xpp/Makefile
+++ b/xpp/Kbuild
@@ -30,7 +30,7 @@ ifneq (,$(HAS_BRISTUFF))
obj-m += xpd_bri.o
endif
-xpp-y += xbus-core.o xbus-sysfs.o xbus-pcm.o xframe_queue.o xpp_zap.o xproto.o card_global.o
+xpp-y += xbus-core.o xbus-sysfs.o xbus-pcm.o xframe_queue.o xpp_zap.o xproto.o card_global.o zap_debug.o
xpd_fxs-y += card_fxs.o
xpd_fxo-y += card_fxo.o
xpd_bri-y += card_bri.o
@@ -41,9 +41,6 @@ EXTRA_CFLAGS += -DDEBUG_SYNC_PARPORT
obj-m += parport_debug.o
endif
-ctags:
- ctags *.[ch]
-
# Handle versioning
XPP_VERSION_STR ?= $(shell if [ -r $(obj)/.version ]; then echo "\"`cat $(obj)/.version`\""; else echo '"Unknown"'; fi)
clean-files := xpp_version.h
diff --git a/xpp/README.Astribank b/xpp/README.Astribank
index c0b5a4c..342c6a9 100644
--- a/xpp/README.Astribank
+++ b/xpp/README.Astribank
@@ -821,8 +821,8 @@ for each Astribank (such as its connector string).
On each time an Astribank is initialized or destroyed a udev event is
generated. The rules from our sample udev rules file (xpp/utils/xpp.rules)
make that event run the script /usr/share/zaptel/astribank_hook with the
-parameter 'add' or 'remove'. Currently this script will just adjust the
-Astribank sync settings (by running xpp_sync).
+parameter 'add' or 'remove', if such script exists. An example script
+that just adjusts the Astribank sync settings is included in xpp/utils.
Registering in Zaptel
diff --git a/xpp/card_bri.c b/xpp/card_bri.c
index fb423a3..998d22a 100644
--- a/xpp/card_bri.c
+++ b/xpp/card_bri.c
@@ -151,7 +151,11 @@ typedef union {
)
#define BRI_BCHAN_SIGCAP ZT_SIG_CLEAR
-#define IS_NT(xpd) ((xpd)->type == XPD_TYPE_BRI_NT)
+#define IS_NT(xpd) ((xpd)->type == XPD_TYPE_BRI_NT)
+
+/* shift in PCM highway */
+#define SUBUNIT_PCM_SHIFT 4
+#define PCM_SHIFT(mask, sunit) ((mask) << (SUBUNIT_PCM_SHIFT * (sunit)))
/*---------------- BRI Protocol Commands ----------------------------------*/
@@ -723,7 +727,7 @@ static int BRI_card_zaptel_preregistration(xpd_t *xpd, bool on)
for(i = 0; i < MAX_SUBUNIT; i++) {
xpd_t *sub_xpd = xpd_byaddr(xbus, xpd->addr.unit, i);
if(sub_xpd) {
- tmp_pcm_mask |= (sub_xpd->wanted_pcm_mask << (SUBUNIT_PCM_SHIFT * i));
+ tmp_pcm_mask |= PCM_SHIFT(sub_xpd->wanted_pcm_mask, i);
line_count += 2;
}
}
@@ -1077,7 +1081,7 @@ static void BRI_card_pcm_fromspan(xbus_t *xbus, xpd_t *xpd, xpp_line_t wanted_li
pcm += ZT_CHUNKSIZE;
}
}
- pcm_mask |= (wanted_lines << SUBUNIT_PCM_SHIFT * subunit);
+ pcm_mask |= PCM_SHIFT(wanted_lines, subunit);
XPD_COUNTER(tmp_xpd, PCM_WRITE)++;
spin_unlock_irqrestore(&tmp_xpd->lock, flags);
}
@@ -1399,6 +1403,7 @@ static xproto_table_t PROTO_TABLE(BRI_TE) = {
.card_tick = BRI_card_tick,
.card_pcm_fromspan = BRI_card_pcm_fromspan,
.card_pcm_tospan = BRI_card_pcm_tospan,
+ .card_ioctl = BRI_card_ioctl,
.card_close = BRI_card_close,
.card_register_reply = BRI_card_register_reply,
diff --git a/xpp/card_fxo.c b/xpp/card_fxo.c
index 513cd5b..cbe953b 100644
--- a/xpp/card_fxo.c
+++ b/xpp/card_fxo.c
@@ -55,7 +55,6 @@ enum fxo_leds {
#define NUM_LEDS 1
#define DELAY_UNTIL_DIALTONE 3000
-#define POLREV_START 3 /* time after offhook to ignore polarity reversals (in ticks) */
#define POLREV_THRESHOLD 1000 /* minimum duration for polarity reversal detection (in ticks) */
#define BAT_THRESHOLD 3
#define BAT_DEBOUNCE 1000 /* compensate for battery voltage fluctuation (in ticks) */
@@ -105,11 +104,11 @@ struct FXO_priv_data {
#endif
struct proc_dir_entry *fxo_info;
uint poll_counter;
+ signed char battery_voltage[CHANNELS_PERXPD];
xpp_line_t battery;
ushort battery_debounce[CHANNELS_PERXPD];
xpp_line_t polarity;
ushort polarity_counter[CHANNELS_PERXPD];
- uint offhook_timestamp[CHANNELS_PERXPD];
ushort current_counter[CHANNELS_PERXPD];
xpp_line_t ledstate[NUM_LEDS]; /* 0 - OFF, 1 - ON */
xpp_line_t ledcontrol[NUM_LEDS]; /* 0 - OFF, 1 - ON */
@@ -280,7 +279,6 @@ static int do_sethook(xpd_t *xpd, int pos, bool to_offhook)
ret = DAA_DIRECT_REQUEST(xbus, xpd, pos, DAA_WRITE, DAA_REG_RING, value);
if(to_offhook) {
BIT_SET(xpd->offhook, pos);
- priv->offhook_timestamp[pos] = priv->poll_counter;
} else {
BIT_CLR(xpd->offhook, pos);
BIT_CLR(xpd->cid_on, pos);
@@ -709,14 +707,21 @@ HANDLER_DEF(FXO, SIG_CHANGED)
return 0;
}
+#ifndef ZT_GET_PARAMS_V1
+#define zt_alarm_channel(a,b) zt_qevent_lock(a,( (b)==ZT_ALARM_NONE )? \
+ ZT_EVENT_NOALARM : ZT_EVENT_ALARM)
+#endif
static void update_battery_status(xpd_t *xpd, byte data_low, lineno_t chipsel)
{
struct FXO_priv_data *priv;
byte bat = abs((signed char)data_low);
byte pol = IS_SET(data_low, 7);
+ int msec;
+
priv = xpd->priv;
BUG_ON(!priv);
+ priv->battery_voltage[chipsel] = data_low;
if(bat < BAT_THRESHOLD) {
/*
* Check for battery voltage fluctuations
@@ -725,12 +730,12 @@ static void update_battery_status(xpd_t *xpd, byte data_low, lineno_t chipsel)
int milliseconds;
milliseconds = priv->battery_debounce[chipsel]++ *
- poll_battery_interval;
+ poll_battery_interval;
if(milliseconds > BAT_DEBOUNCE) {
LINE_DBG(SIGNAL, xpd, chipsel, "BATTERY OFF voltage=%d\n", bat);
BIT_CLR(priv->battery, chipsel);
if(SPAN_REGISTERED(xpd))
- zt_qevent_lock(&xpd->chans[chipsel], ZT_EVENT_ALARM);
+ zt_alarm_channel(&xpd->chans[chipsel], ZT_ALARM_RED);
}
}
@@ -740,45 +745,47 @@ static void update_battery_status(xpd_t *xpd, byte data_low, lineno_t chipsel)
LINE_DBG(SIGNAL, xpd, chipsel, "BATTERY ON voltage=%d\n", bat);
BIT_SET(priv->battery, chipsel);
if(SPAN_REGISTERED(xpd))
- zt_qevent_lock(&xpd->chans[chipsel], ZT_EVENT_NOALARM);
+ zt_alarm_channel(&xpd->chans[chipsel], ZT_ALARM_NONE);
}
}
/*
* Handle reverse polarity
*/
- if (IS_SET(xpd->offhook, chipsel)) { /* Learn the current polarity */
- if (priv->poll_counter - priv->offhook_timestamp[chipsel] < POLREV_START) {
- priv->polarity_counter[chipsel] = 0;
- if (pol)
- BIT_SET(priv->polarity, chipsel);
- else
- BIT_CLR(priv->polarity, chipsel);
- } else if (IS_SET(priv->polarity, chipsel) != pol) { /* Polarity has reversed */
- int milliseconds;
-
- milliseconds = priv->polarity_counter[chipsel]++ * poll_battery_interval;
- if (milliseconds >= POLREV_THRESHOLD) {
- if (pol)
- BIT_SET(priv->polarity, chipsel);
- else
- BIT_CLR(priv->polarity, chipsel);
- priv->polarity_counter[chipsel] = 0;
- /* Inform Zaptel */
- LINE_DBG(SIGNAL, xpd, chipsel, "Send ZT_EVENT_POLARITY\n");
- zt_qevent_lock(&xpd->chans[chipsel], ZT_EVENT_POLARITY);
+ if(IS_SET(priv->polarity, chipsel) == pol) {
+ /* same, same, nothing to see here, move on */
+ priv->polarity_counter[chipsel] = 0;
+ return;
+ }
+ /*
+ * Track polarity reversals and debounce spikes.
+ * Only reversals with long duration count.
+ */
+ msec = priv->polarity_counter[chipsel]++ * poll_battery_interval;
+ if (msec >= POLREV_THRESHOLD) {
+ LINE_DBG(SIGNAL, xpd, chipsel, "Polarity is %s\n",
+ (pol)?"Positive":"Negative");
+ priv->polarity_counter[chipsel] = 0;
+ if (pol)
+ BIT_SET(priv->polarity, chipsel);
+ else
+ BIT_CLR(priv->polarity, chipsel);
+ /* polarity reversal during offhook should be reported to zaptel */
+ if(IS_SET(xpd->offhook, chipsel)) {
+ /* Inform Zaptel */
+ LINE_DBG(SIGNAL, xpd, chipsel, "Send ZT_EVENT_POLARITY\n");
+ zt_qevent_lock(&xpd->chans[chipsel], ZT_EVENT_POLARITY);
#if 0
- /*
- * These two lines hangup the channel (by sending a message to
- * the firmware), and inform Zaptel that the line has been hung-up.
- * They are not needed if Asterisk does the hangup after receiving
- * a notification from Zaptel (which is sent by the above zt_qevent_lock().
- * Asterisk does that if it has "hanguponpolarityswitch=1" in zapata.conf.
- */
- do_sethook(xpd, chipsel, 0);
- update_line_status(xpd, chipsel, 0);
- pcm_recompute(xpd, 0);
+ /*
+ * These two lines hangup the channel (by sending a message to
+ * the firmware), and inform Zaptel that the line has been hung-up.
+ * They are not needed if Asterisk does the hangup after receiving
+ * a notification from Zaptel (which is sent by the above zt_qevent_lock().
+ * Asterisk does that if it has "hanguponpolarityswitch=1" in zapata.conf.
+ */
+ do_sethook(xpd, chipsel, 0);
+ update_line_status(xpd, chipsel, 0);
+ pcm_recompute(xpd, 0);
#endif
- }
}
}
}
@@ -931,34 +938,38 @@ static int proc_fxo_info_read(char *page, char **start, off_t off, int count, in
len += sprintf(page + len, "\t%-17s: ", "Channel");
for_each_line(xpd, i) {
if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i))
- len += sprintf(page + len, "%2d ", i % 10);
+ len += sprintf(page + len, "%3d ", i % 10);
}
len += sprintf(page + len, "\n\t%-17s: ", "ledstate");
for_each_line(xpd, i) {
if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i))
- len += sprintf(page + len, "%2d ", IS_SET(priv->ledstate[LED_GREEN], i));
+ len += sprintf(page + len, "%3d ", IS_SET(priv->ledstate[LED_GREEN], i));
}
len += sprintf(page + len, "\n\t%-17s: ", "blinking");
for_each_line(xpd, i) {
if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i))
- len += sprintf(page + len, "%2d ", IS_BLINKING(priv,i,LED_GREEN));
+ len += sprintf(page + len, "%3d ", IS_BLINKING(priv,i,LED_GREEN));
}
len += sprintf(page + len, "\n\t%-17s: ", "battery");
for_each_line(xpd, i) {
- len += sprintf(page + len, "%2d ", IS_SET(priv->battery, i));
+ len += sprintf(page + len, "%3d ", IS_SET(priv->battery, i));
}
len += sprintf(page + len, "\n\t%-17s: ", "polarity");
for_each_line(xpd, i) {
- len += sprintf(page + len, "%2d ", IS_SET(priv->polarity, i));
+ len += sprintf(page + len, "%3d ", IS_SET(priv->polarity, i));
}
len += sprintf(page + len, "\n\t%-17s: ", "polarity_counter");
for_each_line(xpd, i) {
- len += sprintf(page + len, "%2d ", priv->polarity_counter[i]);
+ len += sprintf(page + len, "%3d ", priv->polarity_counter[i]);
+ }
+ len += sprintf(page + len, "\n\t%-17s: ", "battery_voltage");
+ for_each_line(xpd, i) {
+ len += sprintf(page + len, "%3d ", priv->battery_voltage[i]);
}
#ifdef WITH_METERING
len += sprintf(page + len, "\n\t%-17s: ", "metering");
for_each_line(xpd, i) {
- len += sprintf(page + len, "%2d ", priv->metering_count[i]);
+ len += sprintf(page + len, "%3d ", priv->metering_count[i]);
}
#endif
len += sprintf(page + len, "\n");
diff --git a/xpp/card_global.c b/xpp/card_global.c
index a2c4ac0..05f4008 100644
--- a/xpp/card_global.c
+++ b/xpp/card_global.c
@@ -78,7 +78,10 @@ int xpp_register_request(xbus_t *xbus, xpd_t *xpd,
regnum, subreg, data_low, data_high);
reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
reg_cmd->bytes = sizeof(*reg_cmd) - 1; // do not count the 'bytes' field
+ reg_cmd->eoframe = 0;
+ reg_cmd->multibyte = 0;
REG_FIELD(reg_cmd, chipsel) = chipsel;
+ REG_FIELD(reg_cmd, reserved) = 0; /* force reserved bits to 0 */
REG_FIELD(reg_cmd, read_request) = (writing) ? 0 : 1;
REG_FIELD(reg_cmd, do_subreg) = do_subreg;
REG_FIELD(reg_cmd, regnum) = regnum;
@@ -137,11 +140,10 @@ HANDLER_DEF(GLOBAL, DEV_DESC)
struct card_desc_struct *card_desc;
BUG_ON(!xbus);
- if((card_desc = kmalloc(sizeof(struct card_desc_struct), GFP_ATOMIC)) == NULL) {
+ if((card_desc = KZALLOC(sizeof(struct card_desc_struct), GFP_ATOMIC)) == NULL) {
XBUS_ERR(xbus, "Card description allocation failed.\n");
return -ENOMEM;
}
- memset(card_desc, 0, sizeof(struct card_desc_struct));
card_desc->magic = CARD_DESC_MAGIC;
INIT_LIST_HEAD(&card_desc->card_list);
card_desc->xbus = xbus;
@@ -168,7 +170,7 @@ HANDLER_DEF(GLOBAL, REGISTER_REPLY)
if(!xpd) {
XBUS_NOTICE(xbus, "%s: received %s for non-existing unit (%1d%1d)\n",
__FUNCTION__, cmd->name,
- XPACKET_ADDR(pack).unit, XPACKET_ADDR(pack).subunit);
+ XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack));
return -EPROTO;
}
return CALL_XMETHOD(card_register_reply, xbus, xpd, reg);
@@ -205,7 +207,7 @@ HANDLER_DEF(GLOBAL, ERROR_CODE)
return 0;
if(!xpd) {
snprintf(tmp_name, TMP_NAME_LEN, "%s(%1d%1d)", xbus->busname,
- XPACKET_ADDR(pack).unit, XPACKET_ADDR(pack).subunit);
+ XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack));
} else {
snprintf(tmp_name, TMP_NAME_LEN, "%s/%s", xbus->busname, xpd->xpdname);
}
diff --git a/xpp/card_pri.c b/xpp/card_pri.c
index c82eb6d..e055953 100644
--- a/xpp/card_pri.c
+++ b/xpp/card_pri.c
@@ -1214,8 +1214,16 @@ static void layer1_state(xpd_t *xpd, byte subunit, byte data_low)
if(!priv->layer1_up)
dchan_state(xpd, 0);
if(SPAN_REGISTERED(xpd) && xpd->span.alarms != alarms) {
- xpd->span.alarms = alarms;
- zt_alarm_notify(&xpd->span);
+ char str1[MAX_PROC_WRITE];
+ char str2[MAX_PROC_WRITE];
+
+ alarm2str(xpd->span.alarms, str1, sizeof(str1));
+ alarm2str(alarms, str2, sizeof(str2));
+ XPD_NOTICE(xpd, "Alarms: 0x%X (%s) => 0x%X (%s)\n",
+ xpd->span.alarms, str1,
+ alarms, str2);
+ xpd->span.alarms = alarms;
+ zt_alarm_notify(&xpd->span);
}
priv->reg_frs0 = data_low;
priv->layer1_replies++;
diff --git a/xpp/init_card_9_29 b/xpp/init_card_9_29
index 1e97877..dd3b0a5 100755
--- a/xpp/init_card_9_29
+++ b/xpp/init_card_9_29
@@ -126,23 +126,21 @@ sub set_defaults {
my @pri_specs;
my $match;
my $setup;
+ # For lab tests
+ my $labfile = "${0}.setup";
# Source default files
- foreach my $default_file ("${0}.setup", '/etc/default/zaptel', '/etc/sysconfig/zaptel') {
- next unless -r $default_file;
- my $setup_var = 'XPP_PRI_SETUP';
- my %source_defaults;
- my $setup_string;
- %source_defaults = Zaptel::Config::Defaults::do_source($default_file, $setup_var);
- last unless defined $source_defaults{$setup_var};
- $setup_string = $source_defaults{$setup_var};
- $setup_string =~ s/^\s+//; # trim
- $setup_string =~ s/\s+$//; # trim
- $setup_string =~ s/\s+/\n/g; # cannonical spaces
- logit "From $default_file: $setup_var=\n$setup_string\n";
- @pri_specs = split(/\s+/, $setup_string);
- last;
- }
+ $ENV{ZAPTEL_DEFAULTS} = "$labfile" if -r "$labfile";
+ my $setup_var = 'XPP_PRI_SETUP';
+ my $setup_string;
+ my ($default_file, %source_defaults) =
+ Zaptel::Config::Defaults::source_vars($setup_var);
+ $setup_string = $source_defaults{$setup_var};
+ $setup_string =~ s/^\s+//; # trim
+ $setup_string =~ s/\s+$//; # trim
+ $setup_string =~ s/\s+/\n/g; # cannonical spaces
+ logit "From $default_file: $setup_var=\n$setup_string\n";
+ @pri_specs = split(/\s+/, $setup_string);
push(@pri_specs, 'NUM/*=TE,E1'); # Fall back default (last)
logit "pri_specs: @pri_specs";
SPEC:
diff --git a/xpp/utils/Makefile b/xpp/utils/Makefile
index 7955b27..437b359 100644
--- a/xpp/utils/Makefile
+++ b/xpp/utils/Makefile
@@ -31,7 +31,6 @@ PERL_MODS := $(shell cd zconf; echo $(PERL_MODS_PAT))
XPD_FIRMWARE = $(wildcard ../firmwares/*.hex)
XPD_INIT_DATA = $(XPD_FIRMWARE) init_fxo_modes
XPD_INIT = $(wildcard ../init_card_?_*) ../calibrate_slics xpp_fxloader
-XPD_INIT_PERL = ../init_card_6_29 ../init_card_7_29 ../init_card_9_29
# Variables that should be defined above, but need sane defaults:
# FIXME: Are those values really sane?
@@ -82,7 +81,6 @@ install: all
$(INSTALL) -d $(DESTDIR)$(DATADIR)
$(INSTALL_DATA) $(XPD_INIT_DATA) $(DESTDIR)$(DATADIR)/
$(INSTALL) $(XPD_INIT) $(DESTDIR)$(DATADIR)/
- $(INSTALL) astribank_hook $(DESTDIR)$(DATADIR)/
$(INSTALL) -d $(DESTDIR)$(MANDIR)
$(INSTALL_DATA) $(MAN_INSTALL) $(DESTDIR)$(MANDIR)/
$(INSTALL) -d $(DESTDIR)$(HOTPLUG_USB_DIR)
@@ -130,7 +128,7 @@ wctdm_fxomodes.h: $(WCTDM)
init_fxo_modes: print_modes
./$< >$@
-perlcheck: $(PERL_SCRIPTS) $(XPD_INIT_PERL)
+perlcheck: $(PERL_SCRIPTS)
for i in $^; do perl -I./zconf -c $$i || exit 1; done
touch $@
diff --git a/xpp/utils/astribank_hook b/xpp/utils/astribank_hook
index 53d42f9..351cd93 100755
--- a/xpp/utils/astribank_hook
+++ b/xpp/utils/astribank_hook
@@ -1,14 +1,22 @@
#! /bin/sh
+# This is an example of an Astribank device hook. The xpp.rules file
+# calls /usr/share/zaptel/astribank_hook after a new Astribank is ready
+# and after and old Astribank device has been destroyed.
+#
+# This example script sets the sync source, and thus makes the call to
+# xpp_sync in the init.d script unnecessary.
+
set -e
-xpp_sync="/root/xortel/xpp_sync"
+xpp_sync="/usr/sbin/xpp_sync"
me=`basename $0`
INIT_DIR=`dirname $0`
XPP_BASE=/proc/xpp
export XPP_BASE
LOGGER="logger -s -t $me"
+XPP_SYNC='auto'
ZAPTEL_BOOT_DEBIAN=${ZAPTEL_BOOT_DEBIAN:-/etc/default/zaptel}
ZAPTEL_BOOT_FEDORA=${ZAPTEL_BOOT_FEDORA:-/etc/sysconfig/zaptel}
@@ -29,16 +37,14 @@ fi
## If you wish to trace this script:
#exec 2> "/tmp/astribank_hook_$XBUS_NAME"
-$LOGGER -p kern.info "$ACTION: $*"
-
-$LOGGER -p kern.info "Change Sync"
+$LOGGER -p kern.info "$ACTION: $*. Setting sync to $XPP_SYNC."
case "$ACTION" in
add)
- "$xpp_sync" auto
+ "$xpp_sync" $XPP_SYNC
;;
remove)
- "$xpp_sync" auto
+ "$xpp_sync" $XPP_SYNC
;;
*)
;;
diff --git a/xpp/utils/fpga_load.c b/xpp/utils/fpga_load.c
index 92e3c33..3d6bdbe 100644
--- a/xpp/utils/fpga_load.c
+++ b/xpp/utils/fpga_load.c
@@ -28,6 +28,7 @@ static const char rcsid[] = "$Id$";
static int verbose = LOG_WARNING;
static char *progname;
+static int disconnected = 0;
#define MAX_HEX_LINES 10000
#define PACKET_SIZE 512
@@ -238,18 +239,22 @@ int get_usb_string(char *buf, unsigned int len, uint16_t item, usb_dev_handle *h
return snprintf(buf, len, "%s", tmp);
}
-void my_usb_device_cleanup(struct my_usb_device *mydev, const struct astribank_type *abtype)
+void my_usb_device_cleanup(struct my_usb_device *mydev)
{
assert(mydev != NULL);
if(!mydev->handle) {
return; /* Nothing to do */
}
- if(usb_release_interface(mydev->handle, abtype->my_interface_num) != 0) {
- ERR("Releasing interface: usb: %s\n", usb_strerror());
+ if(!disconnected) {
+ if(usb_release_interface(mydev->handle, mydev->abtype->my_interface_num) != 0) {
+ ERR("Releasing interface: usb: %s\n", usb_strerror());
+ }
}
if(usb_close(mydev->handle) != 0) {
ERR("Closing device: usb: %s\n", usb_strerror());
}
+ disconnected = 1;
+ mydev->handle = NULL;
}
static void show_device_info(const struct my_usb_device *mydev)
@@ -295,8 +300,17 @@ int send_usb(const char *msg, struct my_usb_device *mydev, struct fpga_packet_he
}
ret = usb_bulk_write(mydev->handle, mydev->my_ep_out, p, len, timeout);
if(ret < 0) {
- ERR("bulk_write to endpoint 0x%x failed: %s\n", mydev->my_ep_out, usb_strerror());
- dump_packet("send_usb[ERR]", p, len);
+ /*
+ * If the device was gone, it may be the
+ * result of renumeration. Ignore it.
+ */
+ if(ret != -ENODEV) {
+ ERR("bulk_write to endpoint 0x%x failed: %s\n", mydev->my_ep_out, usb_strerror());
+ dump_packet("send_usb[ERR]", p, len);
+ } else {
+ disconnected = 1;
+ my_usb_device_cleanup(mydev);
+ }
return ret;
} else if(ret != len) {
ERR("bulk_write to endpoint 0x%x short write: %s\n", mydev->my_ep_out, usb_strerror());
@@ -611,8 +625,8 @@ int renumerate_device(struct my_usb_device *mydev, enum fpga_load_packet_types p
DBG("Renumerating with 0x%X\n", pt);
phead->header.op = pt;
ret = send_usb("renumerate[W]", mydev, phead, 1, TIMEOUT);
- if(ret < 0)
- return ret;
+ if(ret < 0 && ret != -ENODEV)
+ return ret;
#if 0
/*
* FIXME: we count on our USB firmware to reset the device... should we?
@@ -984,6 +998,6 @@ int main(int argc, char *argv[])
}
DBG("Exiting\n");
dev_err:
- my_usb_device_cleanup(&mydev, abtype);
+ my_usb_device_cleanup(&mydev);
return ret;
}
diff --git a/xpp/utils/lszaptel b/xpp/utils/lszaptel
index 3126c8a..a836d98 100755
--- a/xpp/utils/lszaptel
+++ b/xpp/utils/lszaptel
@@ -13,8 +13,20 @@ BEGIN { my $dir = dirname($0); unshift(@INC, "$dir", "$dir/zconf"); }
use Zaptel;
use Zaptel::Span;
+use Zaptel::Xpp;
+use Zaptel::Xpp::Xbus;
+use Zaptel::Xpp::Xpd;
+
+my @xbuses = Zaptel::Xpp::xbuses("SORT_CONNECTOR");
+my @xpds = map { $_->xpds } @xbuses;
foreach my $span (Zaptel::spans()) {
+ my $spanno = $span->num;
+ my $xpd = $span->xpd;
+ my @lines;
+ my $index = 0;
+
+ @lines = @{$xpd->lines} if defined $xpd;
printf "### Span %2d: %s %s\n", $span->num, $span->name, $span->description;
foreach my $chan ($span->chans()) {
my %type_map = (
@@ -22,7 +34,11 @@ foreach my $span (Zaptel::spans()) {
IN => 'Input'
);
my ($type) = map { $type_map{$_} or $_ } $chan->type || ("unknown");
- printf "%3d %-10s %-10s %s\n", $chan->num, $type, $chan->signalling, $chan->info;
+ my $batt = "";
+ $batt = "(battery)" if $chan->battery;
+ printf "%3d %-10s %-10s %s %s\n",
+ $chan->num, $type, $chan->signalling, $chan->info, $batt;
+ $index++;
}
}
diff --git a/xpp/utils/zapconf b/xpp/utils/zapconf
index 8ddbb81..dd6ab1f 100755
--- a/xpp/utils/zapconf
+++ b/xpp/utils/zapconf
@@ -502,16 +502,9 @@ sub gen_zapataconf($) {
}
sub set_defaults {
- my $zaptel_boot_debian = $ENV{ZAPTEL_BOOT_DEBIAN} || "/etc/default/zaptel";
- my $zaptel_boot_fedora = $ENV{ZAPTEL_BOOT_FEDORA} || "/etc/sysconfig/zaptel";
-
# Source default files
- my %source_defaults;
- foreach my $defaults ($zaptel_boot_debian, $zaptel_boot_fedora) {
- %source_defaults = Zaptel::Config::Defaults::do_source(
- $defaults, keys(%zaptel_default_vars))
- if -r $defaults;
- }
+ my ($default_file, %source_defaults) =
+ Zaptel::Config::Defaults::source_vars(keys(%zaptel_default_vars));
map_zaptel_defaults(%source_defaults);
# Fixups
foreach my $val (values %default_zaptel_signalling, values %default_zapata_signalling) {
diff --git a/xpp/utils/zaptel_hardware b/xpp/utils/zaptel_hardware
index a356f2c..004a44b 100755
--- a/xpp/utils/zaptel_hardware
+++ b/xpp/utils/zaptel_hardware
@@ -75,9 +75,9 @@ foreach my $dev ($hardware->device_list) {
my $loaded;
if($dev->is_astribank) {
$xbus = $dev->xbus;
- $loaded = $dev->loaded;
}
- die "driver should be '$driver' but is actually '$loaded'"
+ $loaded = $dev->loaded;
+ warn "driver should be '$driver' but is actually '$loaded'\n"
if defined($loaded) && $driver ne $loaded;
$driver = "$driver" . (($loaded) ? "+" : "-");
my $description = $dev->description || "";
diff --git a/xpp/utils/zconf/Zaptel.pm b/xpp/utils/zconf/Zaptel.pm
index e9d0529..a7e7d6c 100644
--- a/xpp/utils/zconf/Zaptel.pm
+++ b/xpp/utils/zconf/Zaptel.pm
@@ -14,7 +14,7 @@ use Zaptel::Span;
Zaptel - Perl interface to Zaptel information
-This package allows access from perl to information about Zaptel
+This package allows access from Perl to information about Zaptel
hardware and loaded Zaptel devices.
=head1 SYNOPSIS
diff --git a/xpp/utils/zconf/Zaptel/Chans.pm b/xpp/utils/zconf/Zaptel/Chans.pm
index 16ab1d5..b02bf24 100644
--- a/xpp/utils/zconf/Zaptel/Chans.pm
+++ b/xpp/utils/zconf/Zaptel/Chans.pm
@@ -10,31 +10,86 @@ package Zaptel::Chans;
use strict;
use Zaptel::Utils;
+=head1 NAME
+
+Zaptel::Chans - Perl interface to a Zaptel channel information
+
+This package allows access from perl to information about a Zaptel
+channel. It is part of the Zaptel Perl package.
+
+=head1 battery()
+
+Returns 1 if channel reports to have battery (A remote PBX connected to
+an FXO port), 0 if channel reports to not have battery and C<undef>
+otherwise.
+
+Currently only wcfxo and Astribank FXO modules report battery. For the
+rest of the channels
+
+=head1 fqn()
+
+(Fully Qualified Name) Returns the full "name" of the channel.
+
+=head1 index()
+
+Returns the number of this channel (in the span).
+
+=head1 num()
+
+Returns the number of this channel as a Zaptel channel.
+
+=head signalling()
+
+Returns the signalling set for this channel through /etc/zaptel.conf .
+This is always empty before ztcfg was run. And shows the "other" type
+for FXS and for FXO.
+
+=head1 span()
+
+Returns a reference to the span to which this channel belongs.
+
+=head1 type()
+
+Returns the type of the channel: 'FXS', 'FXO', 'EMPTY', etc.
+
+=cut
+
sub new($$$$$$) {
my $pack = shift or die "Wasn't called as a class method\n";
my $span = shift or die "Missing a span parameter\n";
+ my $index = shift;
my $line = shift or die "Missing an input line\n";
+ defined $index or die "Missing an index parameter\n";
+ my $self = {
+ 'SPAN' => $span,
+ 'INDEX' => $index,
+ };
+ bless $self, $pack;
my ($num, $fqn, $rest) = split(/\s+/, $line, 3);
$num or die "Missing a channel number parameter\n";
$fqn or die "Missing a channel fqn parameter\n";
my $signalling = '';
- if(defined $rest && ($rest =~ s/(\w+)//)) {
- $signalling = $1;
- }
my $info = '';
- if(defined $rest && ($rest =~ s/(.*)//)) {
- $info = $1;
+ if(defined $rest) {
+ if($rest =~ s/^\s*(\w+)\s*//) {
+ $signalling = $1;
+ }
+ if($rest =~ s/(.*)//) {
+ $info = $1;
+ }
}
- my $self = {};
- bless $self, $pack;
- $self->{SPAN} = $span;
$self->{NUM} = $num;
$self->{FQN} = $fqn;
$self->{SIGNALLING} = $signalling;
$self->{INFO} = $info;
my $type;
if($fqn =~ m|\bXPP_(\w+)/.*$|) {
- $type = $1; # One of our AB
+ $type = $1; # An Astribank
+ } elsif ($fqn =~ m{\bWCFXO/.*}) {
+ $type = "FXO"; # wcfxo - x100p and relatives.
+ # A single port card. The driver issue RED alarm when
+ # There's no better
+ $self->{BATTERY} = !($span->description =~ /\bRED\b/);
} elsif ($fqn =~ m{\bFXS/.*}) {
$type = "FXS"; # likely Rhino
} elsif ($fqn =~ m{\bFXO/.*}) {
@@ -69,6 +124,18 @@ sub new($$$$$$) {
return $self;
}
+=head1 probe_type()
+
+In the case of some cards, the information in /proc/zaptel is not good
+enough to tell the type of each channel. In this case an extra explicit
+probe is needed.
+
+Currently this is implemented by using some invocations of ztcfg(8).
+
+It may later be replaced by ztscan(8).
+
+=cut
+
my $ztcfg = $ENV{ZTCFG} || '/sbin/ztcfg';
sub probe_type($) {
my $self = shift;
@@ -100,4 +167,21 @@ sub probe_type($) {
return $type;
}
+sub battery($) {
+ my $self = shift or die;
+ my $span = $self->span or die;
+
+ return undef unless $self->type eq 'FXO';
+ return $self->{BATTERY} if defined $self->{BATTERY};
+
+ my $xpd = $span->xpd;
+ my $index = $self->index;
+ return undef if !$xpd;
+
+ # It's an XPD (FXO)
+ my @lines = @{$xpd->lines};
+ my $line = $lines[$index];
+ return $line->battery;
+}
+
1;
diff --git a/xpp/utils/zconf/Zaptel/Config/Defaults.pm b/xpp/utils/zconf/Zaptel/Config/Defaults.pm
index 05f4db3..1d11403 100644
--- a/xpp/utils/zconf/Zaptel/Config/Defaults.pm
+++ b/xpp/utils/zconf/Zaptel/Config/Defaults.pm
@@ -26,4 +26,29 @@ sub do_source($@) {
return %vars;
}
+sub source_vars {
+ my @vars = @_;
+ my $default_file;
+ my %system_files = (
+ "/etc/default/zaptel" => 'Debian and friends',
+ "/etc/sysconfig/zaptel" => 'Red Hat and friends',
+ );
+
+ if(defined $ENV{ZAPTEL_DEFAULTS}) {
+ $default_file = $ENV{ZAPTEL_DEFAULTS};
+ } else {
+ foreach my $f (keys %system_files) {
+ if(-r $f) {
+ if(defined $default_file) {
+ die "An '$f' collides with '$default_file'";
+ }
+ $default_file = $f;
+ }
+ }
+ }
+ die "No default_file" unless $default_file;
+ my %vars = Zaptel::Config::Defaults::do_source($default_file, @vars);
+ return ($default_file, %vars);
+}
+
1;
diff --git a/xpp/utils/zconf/Zaptel/Hardware/PCI.pm b/xpp/utils/zconf/Zaptel/Hardware/PCI.pm
index b1a6b67..45173d4 100644
--- a/xpp/utils/zconf/Zaptel/Hardware/PCI.pm
+++ b/xpp/utils/zconf/Zaptel/Hardware/PCI.pm
@@ -91,7 +91,9 @@ my %pci_ids = (
'1397:08b4/b556' => { DRIVER => 'qozap', DESCRIPTION => 'Junghanns DuoBRI ISDN card' },
'1397:08b4' => { DRIVER => 'qozap', DESCRIPTION => 'Junghanns QuadBRI ISDN card' },
'1397:16b8' => { DRIVER => 'qozap', DESCRIPTION => 'Junghanns OctoBRI ISDN card' },
+ '1397:30b1' => { DRIVER => 'cwain', DESCRIPTION => 'HFC-E1 ISDN E1 card' },
'1397:2bd0' => { DRIVER => 'zaphfc', DESCRIPTION => 'HFC-S ISDN BRI card' },
+ '1397:f001' => { DRIVER => 'ztgsm', DESCRIPTION => 'HFC-GSM Cologne Chips GSM' },
# Rhino cards (based on pci.ids)
'0b0b:0105' => { DRIVER => 'r1t1', DESCRIPTION => 'Rhino R1T1' },
@@ -159,8 +161,19 @@ sub scan_devices($) {
}
while(</sys/bus/pci/drivers/*/[0-9]*>) {
- m,([^/]+)/([^/]+)$,,;
- $pci_devs{$2}{LOADED} = $1;
+ m,^(.*?)/([^/]+)/([^/]+)$,;
+ my $prefix = $1;
+ my $drvname = $2;
+ my $id = $3;
+ my $l = readlink "$prefix/$drvname/module";
+ # Find the real module name (if we can).
+ if(defined $l) {
+ my $moduledir = "$prefix/$drvname/$l";
+ my $modname = $moduledir;
+ $modname =~ s:^.*/::;
+ $drvname = $modname;
+ }
+ $pci_devs{$id}{LOADED} = $drvname;
}
foreach (sort keys %pci_devs) {
my $dev = $pci_devs{$_};
diff --git a/xpp/utils/zconf/Zaptel/Span.pm b/xpp/utils/zconf/Zaptel/Span.pm
index f8e5f01..380dc7f 100644
--- a/xpp/utils/zconf/Zaptel/Span.pm
+++ b/xpp/utils/zconf/Zaptel/Span.pm
@@ -10,6 +10,7 @@ package Zaptel::Span;
use strict;
use Zaptel::Utils;
use Zaptel::Chans;
+use Zaptel::Xpp::Xpd;
my $proc_base = "/proc/zaptel";
@@ -50,6 +51,12 @@ sub new($$) {
my $self = { NUM => $num };
bless $self, $pack;
$self->{TYPE} = "UNKNOWN";
+ my @xpds = Zaptel::Xpp::Xpd::xpds_by_spanno;
+ my $xpd = $xpds[$num];
+ if(defined $xpd) {
+ die "Spanno mismatch: $xpd->spanno, $num" unless $xpd->spanno == $num;
+ $self->{XPD} = $xpd;
+ }
open(F, "$proc_base/$num") or die "Failed to open '$proc_base/$num\n";
my $head = <F>;
chomp $head;
@@ -92,16 +99,20 @@ sub new($$) {
$self->{IS_ZAPTEL_SYNC_MASTER} =
($self->{DESCRIPTION} =~ /\(MASTER\)/) ? 1 : 0;
$self->{CHANS} = [];
+ my @channels;
+ my $index = 0;
while(<F>) {
chomp;
s/^\s*//;
s/\s*$//;
next unless /\S/;
- my $c = Zaptel::Chans->new($self, $_);
- push(@{$self->{CHANS}}, $c);
+ my $c = Zaptel::Chans->new($self, $index, $_);
+ push(@channels, $c);
+ $index++;
}
close F;
-
+ @channels = sort { $a->num <=> $b->num } @channels;
+ $self->{CHANS} = \@channels;
$self->{YELLOW} = undef;
$self->{CRC4} = undef;
if($self->is_bri()) {
diff --git a/xpp/utils/zconf/Zaptel/Xpp/Line.pm b/xpp/utils/zconf/Zaptel/Xpp/Line.pm
new file mode 100644
index 0000000..e3e04f0
--- /dev/null
+++ b/xpp/utils/zconf/Zaptel/Xpp/Line.pm
@@ -0,0 +1,59 @@
+package Zaptel::Xpp::Line;
+#
+# Written by Oron Peled <oron@actcom.co.il>
+# Copyright (C) 2008, Xorcom
+# This program is free software; you can redistribute and/or
+# modify it under the same terms as Perl itself.
+#
+# $Id$
+#
+use strict;
+use Zaptel::Utils;
+
+my $proc_base = "/proc/xpp";
+
+sub new($$$) {
+ my $pack = shift or die "Wasn't called as a class method\n";
+ my $xpd = shift or die;
+ my $index = shift;
+ defined $index or die;
+ my $self = {};
+ bless $self, ref($xpd);
+ $self->{XPD} = $xpd;
+ $self->{INDEX} = $index;
+ return $self;
+}
+
+sub create_all($$) {
+ my $pack = shift or die "Wasn't called as a class method\n";
+ my $xpd = shift || die;
+ my $procdir = shift || die;
+ local $/ = "\n";
+ my @lines;
+ for(my $i = 0; $i < $xpd->{CHANNELS}; $i++) {
+ my $line = Zaptel::Xpp::Line->new($xpd, $i);
+ push(@lines, $line);
+ }
+ $xpd->{LINES} = \@lines;
+ my ($infofile) = glob "$procdir/*_info";
+ die "Failed globbing '$procdir/*_info'" unless defined $infofile;
+ my $type = $xpd->type;
+ open(F, "$infofile") || die "Failed opening '$infofile': $!";
+ while (<F>) {
+ chomp;
+ if($type eq 'FXO') {
+ if(s/^\s*battery\s*:\s*//) {
+ my @batt = split;
+ foreach my $l (@lines) {
+ die unless @batt;
+ $l->{BATTERY} = shift @batt;
+ }
+ die if @batt;
+ }
+ }
+ }
+ close F;
+}
+
+
+1;
diff --git a/xpp/utils/zconf/Zaptel/Xpp/Xpd.pm b/xpp/utils/zconf/Zaptel/Xpp/Xpd.pm
index c05cfdb..326aafd 100644
--- a/xpp/utils/zconf/Zaptel/Xpp/Xpd.pm
+++ b/xpp/utils/zconf/Zaptel/Xpp/Xpd.pm
@@ -9,6 +9,8 @@ package Zaptel::Xpp::Xpd;
#
use strict;
use Zaptel::Utils;
+use Zaptel::Xpp;
+use Zaptel::Xpp::Line;
my $proc_base = "/proc/xpp";
@@ -64,21 +66,15 @@ sub zt_registration($$) {
return $result;
}
-#
-# Backward compatibility for old drivers
-# before changeset:5119
-#
-# Newer drivers should directly have $xpd->spanno
-#
-sub spanno_of_xpd($) {
- my $xpd = shift || die;
-
- warn "Running on old driver. Keep going...\n";
- use Zaptel;
- my @spans = Zaptel::spans;
-
- my ($span) = grep { $_->name eq $xpd->fqn } @spans;
- return ($span) ? $span->num : 0;
+sub xpds_by_spanno() {
+ my @xbuses = Zaptel::Xpp::xbuses("SORT_CONNECTOR");
+ my @xpds = map { $_->xpds } @xbuses;
+ @xpds = grep { $_->spanno } @xpds;
+ @xpds = sort { $a->spanno <=> $b->spanno } @xpds;
+ my @spanno = map { $_->spanno } @xpds;
+ my @idx;
+ @idx[@spanno] = @xpds; # The spanno is the index now
+ return @idx;
}
sub new($$) {
@@ -92,8 +88,18 @@ sub new($$) {
local $/ = "\n";
open(F, "$procdir/summary") || die "Missing summary file in $procdir";
my $head = <F>;
- chomp $head;
- # "XPD-00 (BRI_TE ,card present, span 3)"
+ chomp $head; # "XPD-00 (BRI_TE ,card present, span 3)"
+ # The driver does not export the number of channels...
+ # Let's find it indirectly
+ while(<F>) {
+ chomp;
+ if(s/^\s*offhook\s*:\s*//) {
+ my @offhook = split;
+ @offhook || die "No channels in '$procdir/summary'";
+ $self->{CHANNELS} = @offhook;
+ last;
+ }
+ }
close F;
$head =~ s/^(XPD-(\d\d))\s+// || die;
$self->{ID} = $2;
@@ -105,13 +111,12 @@ sub new($$) {
#warn "Garbage in '$procdir/summary': rest='$rest'\n" if $rest;
if($span =~ s/span\s+(\d+)//) { # since changeset:5119
$self->{SPANNO} = $1;
- } else {
- $self->{SPANNO} = $self->spanno_of_xpd;
}
$self->{TYPE} = $type;
$self->{IS_BRI} = ($type =~ /BRI_(NT|TE)/);
$self->{IS_PRI} = ($type =~ /[ETJ]1_(NT|TE)/);
$self->{IS_DIGITAL} = ( $self->{IS_BRI} || $self->{IS_PRI} );
+ Zaptel::Xpp::Line->create_all($self, $procdir);
return $self;
}
diff --git a/xpp/xbus-core.c b/xpp/xbus-core.c
index 00acc3e..790c12a 100644
--- a/xpp/xbus-core.c
+++ b/xpp/xbus-core.c
@@ -282,11 +282,10 @@ static int debugfs_open(struct inode *inode, struct file *file)
XBUS_DBG(GENERAL, xbus, "\n");
if (xbus->debugfs_data)
return -EBUSY;
- d = kmalloc(sizeof(struct debugfs_data), GFP_KERNEL);
+ d = KZALLOC(sizeof(struct debugfs_data), GFP_KERNEL);
if (!d)
return -ENOMEM;
try_module_get(THIS_MODULE);
- memset(d, 0, sizeof(struct debugfs_data));
spin_lock_init(&d->lock);
d->xbus = xbus;
d->head = d->tail = 0;
@@ -463,7 +462,7 @@ void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe)
num, XPACKET_LEN(pack),
XPACKET_IS_PCM(pack), XPACKET_PCMSLOT(pack),
XPACKET_OP(pack),
- XPACKET_ADDR(pack).unit, XPACKET_ADDR(pack).subunit,
+ XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack),
pos);
dump_packet(" ", pack, print_dbg);
}
@@ -750,23 +749,6 @@ out:
return ret;
}
-#define REV(x,y) (10 * (x) + (y))
-static byte good_revs[] = {
- REV(2,9),
-};
-#undef REV
-
-static bool good_rev(byte rev)
-{
- int i;
-
- for(i = 0; i < ARRAY_SIZE(good_revs); i++) {
- if(good_revs[i] == rev)
- return 1;
- }
- return 0;
-}
-
/*
* This must be called from synchronous (non-interrupt) context
* it returns only when all XPD's on the bus are detected and
@@ -864,7 +846,7 @@ static void xbus_poll(void *data)
list_move_tail(card, &removal_list);
count_removed++;
} else if(!xpd && type != XPD_TYPE_NOMODULE) { /* card detection */
- if(!good_rev(card_desc->rev)) {
+ if(card_desc->rev != XPP_PROTOCOL_VERSION) {
XBUS_NOTICE(xbus, "XPD at %d%d: type=%d.%d has bad firmware revision %d.%d\n",
card_desc->xpd_addr.unit, card_desc->xpd_addr.subunit,
card_desc->type, card_desc->subtype,
@@ -999,8 +981,7 @@ static void poller_destroy(struct xbus_poller *poller)
poller->wq = NULL;
}
put_xbus(xbus);
- memset(poller, 0, sizeof(*poller));
- kfree(poller);
+ KZFREE(poller);
}
/*
@@ -1015,10 +996,9 @@ static struct xbus_poller *poller_new(xbus_t *xbus)
BUG_ON(xbus->busname[0] == '\0'); /* No name? */
BUG_ON(xbus->poller); /* Hmmm... overrun pollers? */
XBUS_DBG(DEVICES, xbus, "\n");
- poller = kmalloc(sizeof(*poller), GFP_KERNEL);
+ poller = KZALLOC(sizeof(*poller), GFP_KERNEL);
if(!poller)
goto err;
- memset(poller, 0, sizeof(*poller));
poller->xbus_num = xbus->num;
xbus->poller = poller;
/* poll related variables */
@@ -1153,12 +1133,11 @@ static xbus_t *xbus_alloc(void)
xbus_t *xbus;
int i;
- xbus = kmalloc(sizeof(xbus_t), GFP_KERNEL);
+ xbus = KZALLOC(sizeof(xbus_t), GFP_KERNEL);
if(!xbus) {
ERR("%s: out of memory\n", __FUNCTION__);
return NULL;
}
- memset(xbus, 0, sizeof(xbus_t));
spin_lock_irqsave(&xbuses_lock, flags);
for(i = 0; i < MAX_BUSES; i++)
if(xbuses_array[i].xbus == NULL)
@@ -1235,8 +1214,7 @@ static void xbus_free(xbus_t *xbus)
BUG_ON(refcount_xbus(num) != 0);
init_xbus(num, NULL);
spin_unlock_irqrestore(&xbuses_lock, flags);
- memset(xbus, 0, sizeof(*xbus));
- kfree(xbus);
+ KZFREE(xbus);
}
xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size, void *priv)
@@ -1706,10 +1684,9 @@ struct xbus_ops *transportops_get(xbus_t *xbus)
BUG_ON(!xbus);
atomic_inc(&xbus->transport.transport_refcount);
ops = xbus->transport.ops;
- if(!ops) {
+ if(!ops)
atomic_dec(&xbus->transport.transport_refcount);
- return NULL;
- }
+ /* fall through */
return ops;
}
diff --git a/xpp/xbus-pcm.c b/xpp/xbus-pcm.c
index eb63b11..0b1e5d1 100644
--- a/xpp/xbus-pcm.c
+++ b/xpp/xbus-pcm.c
@@ -40,6 +40,9 @@ extern int print_dbg;
#include "supress/ec_xpp.h"
DEF_PARM_BOOL(xpp_ec, 0, 0444, "Do we use our own (1) or Zaptel's (0) echo canceller");
#endif
+#ifdef OPTIMIZE_CHANMUTE
+DEF_PARM_BOOL(optimize_chanmute, 1, 0644, "Optimize by muting inactive channels");
+#endif
DEF_PARM(int, disable_pcm, 0, 0644, "Disable all PCM transmissions");
#ifdef DEBUG_PCMTX
@@ -542,7 +545,7 @@ static void do_ec(xpd_t *xpd)
#ifdef WITH_ECHO_SUPPRESSION
/* FIXME: need to Echo cancel double buffered data */
for (i = 0;i < xpd->span.channels; i++) {
- if(unlikely(IS_SET(xpd->digital_signalling, i))) /* Don't echo cancel PRI/BRI D-chans */
+ if(unlikely(IS_SET(xpd->digital_signalling, i))) /* Don't echo cancel BRI D-chans */
continue;
#ifdef XPP_EC_CHUNK
/* even if defined, parameterr xpp_ec can override at run-time */
@@ -646,7 +649,7 @@ static inline void pcm_frame_out(xbus_t *xbus, xframe_t *xframe)
do_gettimeofday(&now);
if(unlikely(disable_pcm || !TRANSPORT_RUNNING(xbus)))
goto dropit;
- if(XPACKET_ADDR((xpacket_t *)xframe->packets).sync_master) {
+ if(XPACKET_ADDR_SYNC((xpacket_t *)xframe->packets)) {
usec = usec_diff(&now, &xbus->last_tx_sync);
xbus->last_tx_sync = now;
/* ignore startup statistics */
@@ -728,8 +731,11 @@ void generic_card_pcm_tospan(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack)
for (i = 0; i < xpd->channels; i++) {
volatile u_char *r = xpd->span.chans[i].readchunk;
- if(!IS_SET(xpd->wanted_pcm_mask, i))
+ if(!IS_SET(xpd->wanted_pcm_mask, i)) {
+ if(IS_SET(xpd->silence_pcm, i))
+ memset((u_char *)r, 0x7F, ZT_CHUNKSIZE); // SILENCE
continue;
+ }
pcm_mask &= ~xpd->mute_dtmf;
if(IS_SET(pcm_mask, i)) {
// memset((u_char *)r, 0x5A, ZT_CHUNKSIZE); // DEBUG
@@ -788,7 +794,7 @@ static int copy_pcm_tospan(xbus_t *xbus, xframe_t *xframe)
}
goto out;
}
- xpd = xpd_byaddr(xbus, XPACKET_ADDR(pack).unit, XPACKET_ADDR(pack).subunit);
+ xpd = xpd_byaddr(xbus, XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack));
if(unlikely(!xpd)) {
static int rate_limit;
@@ -827,16 +833,22 @@ static void xbus_tick(xbus_t *xbus)
for(i = 0; i < MAX_XPDS; i++) {
xpd = xpd_of(xbus, i);
if(xpd && SPAN_REGISTERED(xpd)) {
+#ifdef OPTIMIZE_CHANMUTE
+ int j;
+ xpp_line_t xmit_mask = xpd->wanted_pcm_mask;
+
+ xmit_mask |= xpd->silence_pcm;
+ xmit_mask |= xpd->digital_signalling;
+ for_each_line(xpd, j) {
+ xpd->chans[j].chanmute = (optimize_chanmute)
+ ? !IS_SET(xmit_mask, j)
+ : 0;
+ }
+#endif
/*
* calls to zt_transmit should be out of spinlocks, as it may call back
* our hook setting methods.
*/
-#ifdef OPTIMIZE_CHANMUTE
- int j;
-
- for_each_line(xpd, j)
- xpd->chans[j].chanmute = !IS_SET(xpd->wanted_pcm_mask, j) && !IS_SET(xpd->digital_signalling, j);
-#endif
zt_transmit(&xpd->span);
}
}
@@ -873,7 +885,7 @@ static void xbus_tick(xbus_t *xbus)
XPACKET_INIT(pack, GLOBAL, PCM_WRITE, xpd->xbus_idx, 1, 0);
XPACKET_LEN(pack) = pcm_len;
if(!sent_sync_bit) {
- XPACKET_ADDR(pack).sync_master = 1;
+ XPACKET_ADDR_SYNC(pack) = 1;
sent_sync_bit = 1;
}
CALL_XMETHOD(card_pcm_fromspan, xbus, xpd, xpd->wanted_pcm_mask, pack);
@@ -889,7 +901,7 @@ static void xbus_tick(xbus_t *xbus)
i = atomic_read(&xbus->pcm_rx_counter) & 1;
while((xframe = xframe_dequeue(&xbus->pcm_tospan[i])) != NULL) {
copy_pcm_tospan(xbus, xframe);
- if(XPACKET_ADDR((xpacket_t *)xframe->packets).sync_master) {
+ if(XPACKET_ADDR_SYNC((xpacket_t *)xframe->packets)) {
struct timeval now;
unsigned long usec;
@@ -920,6 +932,7 @@ static void xbus_tick(xbus_t *xbus)
do_ec(xpd);
zt_receive(&xpd->span);
}
+ xpd->silence_pcm = 0; /* silence was injected */
xpd->timer_count = xbus->global_counter;
/*
* Must be called *after* tx/rx so
@@ -967,7 +980,7 @@ void xframe_receive_pcm(xbus_t *xbus, xframe_t *xframe)
* of the frame, regardless of the XPD that is sync master.
* FIXME: what about PRI split?
*/
- if(XPACKET_ADDR((xpacket_t *)xframe->packets).sync_master) {
+ if(XPACKET_ADDR_SYNC((xpacket_t *)xframe->packets)) {
do_tick(xbus, xframe->tv_received);
atomic_inc(&xbus->pcm_rx_counter);
} else
@@ -1050,11 +1063,6 @@ static int proc_sync_write(struct file *file, const char __user *buffer, unsigne
ERR("No bus %d exists\n", xbus_num);
return -ENXIO;
}
- if((xpd = xpd_of(xbus, 0)) == NULL) {
- XBUS_ERR(xbus, "No xpd 0 exists\n");
- put_xbus(xbus);
- return -ENXIO;
- }
update_sync_master(xbus);
put_xbus(xbus);
} else if(sscanf(buf, "QUERY=%d", &xbus_num) == 1) {
@@ -1101,6 +1109,10 @@ int xbus_pcm_init(struct proc_dir_entry *toplevel)
struct proc_dir_entry *ent;
#endif
+#ifdef OPTIMIZE_CHANMUTE
+ INFO("FEATURE: with CHANMUTE optimization (%sactivated)\n",
+ (optimize_chanmute)?"":"de");
+#endif
#ifdef WITH_ECHO_SUPPRESSION
INFO("FEATURE: with ECHO_SUPPRESSION\n");
#else
diff --git a/xpp/xdefs.h b/xpp/xdefs.h
index 1da9580..2aec497 100644
--- a/xpp/xdefs.h
+++ b/xpp/xdefs.h
@@ -77,7 +77,6 @@ struct list_head { struct list_head *next; struct list_head *prev; };
#define MAX_UNIT BIT(UNIT_BITS) /* 1 FXS + 3 FXS/FXO | 1 BRI + 3 FXS/FXO */
#define MAX_SUBUNIT BIT(SUBUNIT_BITS) /* 8 port BRI */
-#define SUBUNIT_PCM_SHIFT 4 /* shift in PCM highway */
/*
* Compile time sanity checks
@@ -109,6 +108,12 @@ typedef unsigned char byte;
#define KMEM_CACHE_T struct kmem_cache
#endif
+#define KZALLOC(size, gfp) my_kzalloc(size, gfp)
+#define KZFREE(p) do { \
+ memset((p), 0, sizeof(*(p))); \
+ kfree(p); \
+ } while(0);
+
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
typedef int bool;
#endif
diff --git a/xpp/xframe_queue.c b/xpp/xframe_queue.c
index abf9ee0..23dee0e 100644
--- a/xpp/xframe_queue.c
+++ b/xpp/xframe_queue.c
@@ -215,8 +215,16 @@ xframe_t *get_xframe(struct xframe_queue *q)
}
BUG_ON(xframe->xframe_magic != XFRAME_MAGIC);
atomic_set(&xframe->frame_len, 0);
+ xframe->first_free = xframe->packets;
do_gettimeofday(&xframe->tv_created);
- memset(xframe->packets, 0, xframe->frame_maxlen);
+ /*
+ * If later parts bother to correctly initialize their
+ * headers, there is no need to memset() the whole data.
+ *
+ * ticket:403
+ *
+ * memset(xframe->packets, 0, xframe->frame_maxlen);
+ */
//XBUS_INFO(xbus, "%s\n", __FUNCTION__);
return xframe;
}
diff --git a/xpp/xpd.h b/xpp/xpd.h
index 7c174f2..3187227 100644
--- a/xpp/xpd.h
+++ b/xpp/xpd.h
@@ -151,12 +151,13 @@ struct xpd {
xpp_line_t msg_waiting; /* Voice Mail Waiting Indication */
xpp_line_t digital_outputs; /* 0 - no, 1 - yes */
xpp_line_t digital_inputs; /* 0 - no, 1 - yes */
- xpp_line_t digital_signalling; /* PRI/BRI signalling channels */
+ xpp_line_t digital_signalling; /* BRI signalling channels */
uint timing_priority; /* from 'span' directives in zapata.conf */
/* maintained by card drivers */
uint pcm_len; /* allocation length of PCM packet (dynamic) */
xpp_line_t wanted_pcm_mask;
+ xpp_line_t silence_pcm; /* inject silence during next tick */
xpp_line_t mute_dtmf;
bool ringing[CHANNELS_PERXPD];
@@ -207,6 +208,16 @@ void xbus_flip_bit(xbus_t *xbus, unsigned int bitnum0, unsigned int bitnum1);
#define xbus_flip_bit(xbus, bitnum0, bitnum1)
#endif
+static inline void *my_kzalloc(size_t size, gfp_t flags)
+{
+ void *p;
+
+ p = kmalloc(size, flags);
+ if(p)
+ memset(p, 0, size);
+ return p;
+}
+
#endif
#endif /* XPD_H */
diff --git a/xpp/xpp_usb.c b/xpp/xpp_usb.c
index 73f351c..785e713 100644
--- a/xpp/xpp_usb.c
+++ b/xpp/xpp_usb.c
@@ -662,14 +662,12 @@ static int xusb_probe(struct usb_interface *interface, const struct usb_device_i
}
/* allocate memory for our device state and initialize it */
- xusb = kmalloc(sizeof(xusb_t), GFP_KERNEL);
+ xusb = KZALLOC(sizeof(xusb_t), GFP_KERNEL);
if (xusb == NULL) {
ERR("xpp_usb: Unable to allocate new xpp usb bus\n");
retval = -ENOMEM;
goto probe_failed;
}
- memset(xusb, 0, sizeof(xusb_t));
-
init_MUTEX (&xusb->sem);
atomic_set(&xusb->pending_writes, 0);
atomic_set(&xusb->pcm_tx_drops, 0);
diff --git a/xpp/xpp_zap.c b/xpp/xpp_zap.c
index db63095..edaedf9 100644
--- a/xpp/xpp_zap.c
+++ b/xpp/xpp_zap.c
@@ -152,8 +152,7 @@ static void xpd_free(xpd_t *xpd)
if(xpd->xproto)
xproto_put(xpd->xproto);
xpd->xproto = NULL;
- memset(xpd, 0, sizeof(*xpd));
- kfree(xpd);
+ KZFREE(xpd);
}
@@ -277,8 +276,7 @@ void card_detected(struct card_desc_struct *card_desc)
if(zap_autoreg)
zaptel_register_xpd(xpd);
out:
- memset(card_desc, 0, sizeof(struct card_desc_struct));
- kfree(card_desc);
+ KZFREE(card_desc);
return;
err:
xpd_free(xpd);
@@ -436,14 +434,12 @@ xpd_t *xpd_alloc(size_t privsize, const xproto_table_t *proto_table, int channel
goto err;
}
- if((xpd = kmalloc(alloc_size, GFP_KERNEL)) == NULL) {
+ if((xpd = KZALLOC(alloc_size, GFP_KERNEL)) == NULL) {
ERR("%s: type=%d: Unable to allocate memory\n",
__FUNCTION__, type);
goto err;
}
- memset(xpd, 0, alloc_size);
xpd->priv = (byte *)xpd + sizeof(xpd_t);
-
spin_lock_init(&xpd->lock);
xpd->xbus = NULL;
xpd->xbus_idx = -1;
@@ -553,6 +549,14 @@ void update_line_status(xpd_t *xpd, int pos, bool to_offhook)
BIT_CLR(xpd->offhook, pos);
BIT_CLR(xpd->cid_on, pos);
rxsig = ZT_RXSIG_ONHOOK;
+ /*
+ * To prevent latest PCM to stay in buffers
+ * indefinitely, mark this channel for a
+ * single silence transmittion.
+ *
+ * This bit will be cleared on the next tick.
+ */
+ BIT_SET(xpd->silence_pcm, pos);
}
/*
* We should not spinlock before calling zt_hooksig() as
@@ -993,9 +997,6 @@ int __init xpp_zap_init(void)
#else
INFO("FEATURE: without BRISTUFF support\n");
#endif
-#ifdef OPTIMIZE_CHANMUTE
- INFO("FEATURE: with CHANMUTE optimization\n");
-#endif
#ifdef CONFIG_PROC_FS
xpp_proc_toplevel = proc_mkdir(PROC_DIR, NULL);
if(!xpp_proc_toplevel) {
diff --git a/xpp/xproto.c b/xpp/xproto.c
index 83a66d8..d55949e 100644
--- a/xpp/xproto.c
+++ b/xpp/xproto.c
@@ -43,12 +43,6 @@ bool valid_xpd_addr(const struct xpd_addr *addr)
return ((addr->subunit & ~BITMASK(SUBUNIT_BITS)) == 0) && ((addr->unit & ~BITMASK(UNIT_BITS)) == 0);
}
-void xpd_set_addr(struct xpd_addr *addr, int xpd_num)
-{
- addr->unit = XBUS_UNIT(xpd_num);
- addr->subunit = XBUS_SUBUNIT(xpd_num);
-}
-
/*---------------- General Protocol Management ----------------------------*/
const xproto_entry_t *xproto_card_entry(const xproto_table_t *table, byte opcode)
@@ -145,13 +139,13 @@ int packet_process(xbus_t *xbus, xpacket_t *pack)
if(printk_ratelimit()) {
XBUS_NOTICE(xbus, "%s: from %d%d: bad address.\n",
__FUNCTION__,
- XPACKET_ADDR(pack).unit, XPACKET_ADDR(pack).subunit);
+ XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack));
dump_packet("packet_process -- bad address", pack, print_dbg);
}
goto out;
}
op = XPACKET_OP(pack);
- xpd = xpd_byaddr(xbus, XPACKET_ADDR(pack).unit, XPACKET_ADDR(pack).subunit);
+ xpd = xpd_byaddr(xbus, XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack));
/* XPD may be NULL (e.g: during bus polling */
xe = xproto_global_entry(op);
/*-------- Validations -----------*/
@@ -162,7 +156,7 @@ int packet_process(xbus_t *xbus, xpacket_t *pack)
if(printk_ratelimit()) {
XBUS_NOTICE(xbus, "%s: from %d%d opcode=0x%02X: no such global command.\n",
__FUNCTION__,
- XPACKET_ADDR(pack).unit, XPACKET_ADDR(pack).subunit, op);
+ XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack), op);
dump_packet("packet_process -- no such global command", pack, 1);
}
goto out;
@@ -263,6 +257,7 @@ int xframe_receive(xbus_t *xbus, xframe_t *xframe)
XBUS_NOTICE(xbus, "short xframe\n");
dump_xframe("short xframe", xbus, xframe);
}
+ FREE_RECV_XFRAME(xbus, xframe);
return -EPROTO;
}
if(!XBUS_GET(xbus)) {
@@ -299,9 +294,9 @@ void dump_packet(const char *msg, const xpacket_t *packet, bool print_dbg)
return;
printk(KERN_DEBUG "%s: XPD=%1X-%1X%c (0x%X) OP=0x%02X LEN=%d",
msg,
- XPACKET_ADDR(packet).unit,
- XPACKET_ADDR(packet).subunit,
- (XPACKET_ADDR(packet).sync_master)?'+':' ',
+ XPACKET_ADDR_UNIT(packet),
+ XPACKET_ADDR_SUBUNIT(packet),
+ (XPACKET_ADDR_SYNC(packet))?'+':' ',
*addr,
op,
XPACKET_LEN(packet));
@@ -444,7 +439,6 @@ EXPORT_SYMBOL(dump_reg_cmd);
EXPORT_SYMBOL(xframe_receive);
EXPORT_SYMBOL(notify_bad_xpd);
EXPORT_SYMBOL(valid_xpd_addr);
-EXPORT_SYMBOL(xpd_set_addr);
EXPORT_SYMBOL(xproto_global_entry);
EXPORT_SYMBOL(xproto_card_entry);
EXPORT_SYMBOL(xproto_name);
diff --git a/xpp/xproto.h b/xpp/xproto.h
index fbb6f16..f68fedf 100644
--- a/xpp/xproto.h
+++ b/xpp/xproto.h
@@ -29,6 +29,11 @@
#include <linux/proc_fs.h>
#include <zaptel.h>
+/*
+ * This must match the firmware protocol version
+ */
+#define XPP_PROTOCOL_VERSION 29
+
struct xpd_addr {
uint8_t unit:UNIT_BITS;
uint8_t subunit:SUBUNIT_BITS;
@@ -49,7 +54,12 @@ struct xpacket_header {
#define XPACKET_LEN(p) ((p)->head.packet_len)
#define XPACKET_IS_PCM(p) ((p)->head.is_pcm)
#define XPACKET_PCMSLOT(p) ((p)->head.pcmslot)
+#define XPACKET_RESERVED(p) ((p)->head.reserved)
#define XPACKET_ADDR(p) ((p)->head.addr)
+#define XPACKET_ADDR_UNIT(p) (XPACKET_ADDR(p).unit)
+#define XPACKET_ADDR_SUBUNIT(p) (XPACKET_ADDR(p).subunit)
+#define XPACKET_ADDR_SYNC(p) (XPACKET_ADDR(p).sync_master)
+#define XPACKET_ADDR_RESERVED(p) (XPACKET_ADDR(p).reserved)
#define PROTO_TABLE(n) n ## _protocol_table
@@ -75,7 +85,6 @@ typedef byte xpd_type_t;
#define PCM_CHUNKSIZE (CHANNELS_PERXPD * 8) /* samples of 8 bytes */
bool valid_xpd_addr(const struct xpd_addr *addr);
-void xpd_set_addr(struct xpd_addr *addr, int xpd_num);
#define XPROTO_NAME(card,op) card ## _ ## op
#define XPROTO_HANDLER(card,op) XPROTO_NAME(card,op ## _handler)
@@ -122,7 +131,11 @@ void xpd_set_addr(struct xpd_addr *addr, int xpd_num);
XPACKET_LEN(p) = RPACKET_SIZE(card,op); \
XPACKET_IS_PCM(p) = (pcm); \
XPACKET_PCMSLOT(p) = (pcmslot); \
- xpd_set_addr(&XPACKET_ADDR(p), (to)); \
+ XPACKET_RESERVED(p) = 0; \
+ XPACKET_ADDR_UNIT(p) = XBUS_UNIT(to); \
+ XPACKET_ADDR_SUBUNIT(p) = XBUS_SUBUNIT(to); \
+ XPACKET_ADDR_SYNC(p) = 0; \
+ XPACKET_ADDR_RESERVED(p) = 0; \
} while(0)
#define XFRAME_NEW_CMD(frm, p, xbus, card, op, to) \
diff --git a/xpp/zap_debug.c b/xpp/zap_debug.c
index 59eb0a8..bf54e62 100644
--- a/xpp/zap_debug.c
+++ b/xpp/zap_debug.c
@@ -30,6 +30,7 @@
#include <linux/module.h>
#include <zaptel.h>
#include "zap_debug.h"
+#include "xdefs.h"
static const char rcsid[] = "$Id$";
@@ -59,9 +60,32 @@ void dump_poll(int print_dbg, const char *msg, int poll)
for(i = 0; i < ARRAY_SIZE(poll_names); i++) {
if(poll & poll_names[i].value)
- DBG("%s: %s\n", msg, poll_names[i].name);
+ DBG(GENERAL, "%s: %s\n", msg, poll_names[i].name);
}
}
+void alarm2str(int alarm, char *buf, int buflen)
+{
+ char *p = buf;
+ int left = buflen;
+ int i;
+ int n;
+
+ if(!alarm) {
+ snprintf(buf, buflen, "NONE");
+ return;
+ }
+ memset(buf, 0, buflen);
+ for(i = 0; i < 8; i++) {
+ if(left && (alarm & BIT(i))) {
+ n = snprintf(p, left, "%s,", alarmbit2str(i));
+ p += n;
+ left -= n;
+ }
+ }
+ if(p > buf) /* kill last comma */
+ *(p - 1) = '\0';
+}
EXPORT_SYMBOL(dump_poll);
+EXPORT_SYMBOL(alarm2str);
diff --git a/xpp/zap_debug.h b/xpp/zap_debug.h
index ae5ee40..fb1ecc3 100644
--- a/xpp/zap_debug.h
+++ b/xpp/zap_debug.h
@@ -170,4 +170,21 @@ static inline char *sig2str(int sig)
return "Unconfigured";
}
+static inline char *alarmbit2str(int alarmbit)
+{
+ /* from zaptel.h */
+ switch(1 << alarmbit) {
+ case ZT_ALARM_NONE: return "NONE";
+ case ZT_ALARM_RECOVER: return "RECOVER";
+ case ZT_ALARM_LOOPBACK: return "LOOPBACK";
+ case ZT_ALARM_YELLOW: return "YELLOW";
+ case ZT_ALARM_RED: return "RED";
+ case ZT_ALARM_BLUE: return "BLUE";
+ case ZT_ALARM_NOTOPEN: return "NOTOPEN";
+ }
+ return "UNKNOWN";
+}
+
+void alarm2str(int alarm, char *buf, int buflen);
+
#endif /* ZAP_DEBUG_H */