From 9899bafe997a4e020f302c99a6e025b4e8b25191 Mon Sep 17 00:00:00 2001 From: tzafrir Date: Thu, 10 Jan 2008 18:12:27 +0000 Subject: 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 --- xpp/.version | 2 +- xpp/Changelog_xpp | 12 +++- xpp/Kbuild | 58 +++++++++++++++++ xpp/Makefile | 61 ------------------ xpp/README.Astribank | 4 +- xpp/card_bri.c | 11 +++- xpp/card_fxo.c | 99 ++++++++++++++++------------- xpp/card_global.c | 10 +-- xpp/card_pri.c | 12 +++- xpp/init_card_9_29 | 28 ++++---- xpp/utils/Makefile | 4 +- xpp/utils/astribank_hook | 18 ++++-- xpp/utils/fpga_load.c | 30 ++++++--- xpp/utils/lszaptel | 18 +++++- xpp/utils/zapconf | 11 +--- xpp/utils/zaptel_hardware | 4 +- xpp/utils/zconf/Zaptel.pm | 2 +- xpp/utils/zconf/Zaptel/Chans.pm | 102 +++++++++++++++++++++++++++--- xpp/utils/zconf/Zaptel/Config/Defaults.pm | 25 ++++++++ xpp/utils/zconf/Zaptel/Hardware/PCI.pm | 17 ++++- xpp/utils/zconf/Zaptel/Span.pm | 17 ++++- xpp/utils/zconf/Zaptel/Xpp/Line.pm | 59 +++++++++++++++++ xpp/utils/zconf/Zaptel/Xpp/Xpd.pm | 43 +++++++------ xpp/xbus-core.c | 41 +++--------- xpp/xbus-pcm.c | 48 ++++++++------ xpp/xdefs.h | 7 +- xpp/xframe_queue.c | 10 ++- xpp/xpd.h | 13 +++- xpp/xpp_usb.c | 4 +- xpp/xpp_zap.c | 21 +++--- xpp/xproto.c | 20 ++---- xpp/xproto.h | 17 ++++- xpp/zap_debug.c | 26 +++++++- xpp/zap_debug.h | 17 +++++ 34 files changed, 593 insertions(+), 278 deletions(-) create mode 100644 xpp/Kbuild delete mode 100644 xpp/Makefile create mode 100644 xpp/utils/zconf/Zaptel/Xpp/Line.pm 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 - xpp.r5178 +Thu Jan 10 2008 Oron Peled - 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 - xpp.r5179 * xpd_pri: Basically ready. * PCM synchronization changes: - Each Astribank unit ticks independently. Each with its own PLL. diff --git a/xpp/Kbuild b/xpp/Kbuild new file mode 100644 index 0000000..9ec225f --- /dev/null +++ b/xpp/Kbuild @@ -0,0 +1,58 @@ +ifdef SUBDIRS + ZAPTEL_DIR = $(SUBDIRS) +else + ZAPTEL_DIR = $(M) +endif + +EXTRA_CFLAGS = $(XPP_LOCAL_CFLAGS) \ + -I$(ZAPTEL_DIR) \ + -DDEBUG \ + -DPOLL_DIGITAL_INPUTS \ + -DWITH_ECHO_SUPPRESSION \ + -DDEBUG_PCMTX \ + -DPROTOCOL_DEBUG \ + -g + # + +ifneq (,$(shell grep -w echo_can_state_t $(ZAPTEL_DIR)/zaptel.h)) +EXTRA_CFLAGS += -DZAPTEL_EC_TYPEDEF +endif + +obj-m += xpp.o xpd_fxs.o xpd_fxo.o xpd_pri.o + +HAS_BRISTUFF := $(shell cpp $(CPPFLAGS) -dM $(ZAPTEL_DIR)/zconfig.h | sed -n 's/^.*CONFIG_ZAPATA_BRI_DCHANS/y/p') + +# Build only supported modules +ifneq (,$(filter y m,$(CONFIG_USB))) +obj-m += xpp_usb.o +endif +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 zap_debug.o +xpd_fxs-y += card_fxs.o +xpd_fxo-y += card_fxo.o +xpd_bri-y += card_bri.o +xpd_pri-y += card_pri.o + +ifeq (y,$(PARPORT_DEBUG)) +EXTRA_CFLAGS += -DDEBUG_SYNC_PARPORT +obj-m += parport_debug.o +endif + +# Handle versioning +XPP_VERSION_STR ?= $(shell if [ -r $(obj)/.version ]; then echo "\"`cat $(obj)/.version`\""; else echo '"Unknown"'; fi) +clean-files := xpp_version.h + +$(obj)/card_fxs.o $(obj)/card_fxo.o $(obj)/card_bri.o $(obj)/card_pri.o $(obj)/xpp_usb.o $(obj)/xpp.o: $(obj)/xpp_version.h + +$(obj)/xpp_version.h: FORCE + $(Q)echo '#define XPP_VERSION $(XPP_VERSION_STR)' > $@.tmp + $(Q)if cmp -s $@.tmp $@ ; then echo; else \ + mv $@.tmp $@ ; \ + fi + $(Q)rm -f $@.tmp + +.PHONY: FORCE +FORCE: diff --git a/xpp/Makefile b/xpp/Makefile deleted file mode 100644 index bde055e..0000000 --- a/xpp/Makefile +++ /dev/null @@ -1,61 +0,0 @@ -ifdef SUBDIRS - ZAPTEL_DIR = $(SUBDIRS) -else - ZAPTEL_DIR = $(M) -endif - -EXTRA_CFLAGS = $(XPP_LOCAL_CFLAGS) \ - -I$(ZAPTEL_DIR) \ - -DDEBUG \ - -DPOLL_DIGITAL_INPUTS \ - -DWITH_ECHO_SUPPRESSION \ - -DDEBUG_PCMTX \ - -DPROTOCOL_DEBUG \ - -g - # - -ifneq (,$(shell grep -w echo_can_state_t $(ZAPTEL_DIR)/zaptel.h)) -EXTRA_CFLAGS += -DZAPTEL_EC_TYPEDEF -endif - -obj-m += xpp.o xpd_fxs.o xpd_fxo.o xpd_pri.o - -HAS_BRISTUFF := $(shell cpp $(CPPFLAGS) -dM $(ZAPTEL_DIR)/zconfig.h | sed -n 's/^.*CONFIG_ZAPATA_BRI_DCHANS/y/p') - -# Build only supported modules -ifneq (,$(filter y m,$(CONFIG_USB))) -obj-m += xpp_usb.o -endif -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 -xpd_fxs-y += card_fxs.o -xpd_fxo-y += card_fxo.o -xpd_bri-y += card_bri.o -xpd_pri-y += card_pri.o - -ifeq (y,$(PARPORT_DEBUG)) -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 - -$(obj)/card_fxs.o $(obj)/card_fxo.o $(obj)/card_bri.o $(obj)/card_pri.o $(obj)/xpp_usb.o $(obj)/xpp.o: $(obj)/xpp_version.h - -$(obj)/xpp_version.h: FORCE - $(Q)echo '#define XPP_VERSION $(XPP_VERSION_STR)' > $@.tmp - $(Q)if cmp -s $@.tmp $@ ; then echo; else \ - mv $@.tmp $@ ; \ - fi - $(Q)rm -f $@.tmp - -.PHONY: FORCE -FORCE: 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 +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() { - 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 = ; 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() { 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 +# 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 () { + 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 = ; - 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() { + 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 #include +/* + * 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 #include #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 */ -- cgit v1.2.3