summaryrefslogtreecommitdiff
path: root/xpp/xpp_zap.c
diff options
context:
space:
mode:
Diffstat (limited to 'xpp/xpp_zap.c')
-rw-r--r--xpp/xpp_zap.c987
1 files changed, 87 insertions, 900 deletions
diff --git a/xpp/xpp_zap.c b/xpp/xpp_zap.c
index aabc236..db63095 100644
--- a/xpp/xpp_zap.c
+++ b/xpp/xpp_zap.c
@@ -49,72 +49,20 @@ static const char rcsid[] = "$Id$";
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *xpp_proc_toplevel = NULL;
#define PROC_DIR "xpp"
-#define PROC_SYNC "sync"
#define PROC_XPD_ZTREGISTER "zt_registration"
#define PROC_XPD_BLINK "blink"
#define PROC_XPD_SUMMARY "summary"
#endif
#define MAX_QUEUE_LEN 10000
-#define SAMPLE_TICKS 10000
#define DELAY_UNTIL_DIALTONE 3000
-static struct timer_list xpp_timer;
-static xpd_t *sync_master = NULL; // Start with host based sync
-static unsigned int xpp_timer_count = 0;
-static unsigned int xpp_last_jiffies = 0;
-
-#ifdef ZAPTEL_SYNC_TICK
-static unsigned int zaptel_tick_count = 0;
-/*
- * Statistics variables
- */
-static struct timeval ticked_zaptel;
-static struct timeval ticked_xpp;
-static long usec_lag_curr; /* current: zaptel - xpp */
-static long sigma_lag; /* sum of lags over SYNC_ADJ_INTERVAL */
-static long average_lag; /* average of lags over SYNC_ADJ_INTERVAL */
-static bool zaptel_is_ticking;
-static bool have_sync_mastership;
-static unsigned int sync_tick_nomaster;
-
-#define ZAPTEL_BIG_LAG 2000 /* usec */
-
-#define SYNC_ADJ_MIN (-30) /* minimal firmware drift unit */
-#define SYNC_ADJ_MAX 30 /* maximal firmware drift unit */
-#define SYNC_ADJ_INTERVAL 5000 /* minimum interval between fixes (usec) */
-#define SYNC_ADJ_FACTOR 30 /* sigma usec/drift_unit */
-
-DEF_PARM_BOOL(sync_tick_active, 1, 0644, "Measure via zaptel sync_tick() method");
-
-#endif
-
-
-DEF_PARM_BOOL(pcm_tasklet, 0, 0644, "Handle PCM in a tasklet (lower interrupt load)");
-#define PCM_TASKLET_DEPRECATION "\n" \
- "====================================================================\n" \
- "CONFIGURATION ERROR: 'pcm_tasklet' module parameter is deprecated!!!\n" \
- "====================================================================\n"
-
-DEF_PARM(int, disable_pcm, 0, 0644, "Disable all PCM transmissions");
DEF_PARM(int, print_dbg, 0, 0644, "Print DBG statements");
DEF_PARM_BOOL(zap_autoreg, 0, 0644, "Register spans automatically (1) or not (0)");
DEF_PARM_BOOL(prefmaster, 0, 0644, "Do we want to be zaptel preferred sync master");
-#ifdef XPP_EC_CHUNK
-DEF_PARM_BOOL(xpp_ec, 0, 0444, "Do we use our own (1) or Zaptel's (0) echo canceller");
-#else
-static int xpp_ec = 0;
-#endif
-#ifdef DEBUG_PCMTX
-DEF_PARM(int, pcmtx, -1, 0644, "Forced PCM value to transmit (negative to disable)");
-DEF_PARM(int, pcmtx_chan, 0, 0644, "channel to force PCM value");
-#endif
// DEF_ARRAY(int, pcmtx, 4, 0, "Forced PCM values to transmit");
#include "zap_debug.h"
-#ifdef XPP_EC_CHUNK
-#include "supress/ec_xpp.h"
-#endif
#ifdef DEBUG_SYNC_PARPORT
/*
@@ -152,14 +100,15 @@ void xbus_flip_bit(xbus_t *xbus, unsigned int bitnum0, unsigned int bitnum1)
EXPORT_SYMBOL(xbus_flip_bit);
#endif
-#ifdef ZAPTEL_SYNC_TICK
-static void send_drift(int drift);
-#endif
-static void xpp_tick(unsigned long param);
+static atomic_t num_registered_spans = ATOMIC_INIT(0);
+
+int total_registered_spans(void)
+{
+ return atomic_read(&num_registered_spans);
+}
+
static int zaptel_register_xpd(xpd_t *xpd);
static int zaptel_unregister_xpd(xpd_t *xpd);
-static void xpp_receiveprep(xpd_t *xpd);
-static void do_ec(xpd_t *xpd);
static int xpd_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data);
static int proc_xpd_ztregister_read(char *page, char **start, off_t off, int count, int *eof, void *data);
static int proc_xpd_ztregister_write(struct file *file, const char __user *buffer, unsigned long count, void *data);
@@ -167,434 +116,6 @@ static int proc_xpd_blink_read(char *page, char **start, off_t off, int count, i
static int proc_xpd_blink_write(struct file *file, const char __user *buffer, unsigned long count, void *data);
static void xpd_free(xpd_t *xpd);
-static void external_sync(xbus_t *the_xbus)
-{
- int i;
-
- DBG(SYNC, "%s\n", (the_xbus) ? the_xbus->busname : "HOST");
- // Shut all down
- for(i = 0; i < MAX_BUSES; i++) {
- xbus_t *xbus = xbus_of(i);
- if(!xbus)
- continue;
- if (!xbus->hardware_exists)
- continue;
- CALL_PROTO(GLOBAL, SYNC_SOURCE, xbus, NULL, SYNC_MODE_HOST, 0);
- }
- if(the_xbus)
- CALL_PROTO(GLOBAL, SYNC_SOURCE, the_xbus, NULL, SYNC_MODE_AB, 0);
-}
-
-/*
- * Change sync_master. May block. Cannot be called from atomic context
- */
-static void sync_master_is(const char *msg, xbus_t *xbus)
-{
- xpd_t *xpd = (xbus)? xpd_of(xbus, 0) : NULL;
-
- if(xbus && !xpd) {
- XBUS_NOTICE(xbus, "Cannot set sync master (has no XPD #0).\n");
- xbus = NULL; /* Fallback to HOST */
- }
- DBG(SYNC, "SYNC MASTER CHANGING(%s): %s => %s\n",
- msg,
- (sync_master) ? sync_master->xbus->busname : "HOST",
- (xbus) ? xbus->busname : "HOST");
- /* First stop all generators */
- if(!sync_master)
- del_timer_sync(&xpp_timer);
- /* Now set a new master */
- sync_master = xpd;
- if(sync_master) { // XPD
- external_sync(xbus);
- } else { // HOST
- external_sync(NULL);
- if(!timer_pending(&xpp_timer)) {
- xpp_timer.function = xpp_tick;
- xpp_timer.data = 0;
- xpp_timer.expires = jiffies + 1; /* Must be 1KHz rate */
- add_timer(&xpp_timer);
- }
- }
-}
-
-void elect_syncer(const char *msg)
-{
- int i;
- int j;
- uint timing_priority = 0;
- xpd_t *best_xpd = NULL;
-
- for(i = 0; i < MAX_BUSES; i++) {
- xbus_t *xbus = xbus_of(i);
- if(!xbus)
- continue;
- if (!xbus->hardware_exists)
- continue;
- for(j = 0; j < MAX_XPDS; j++) {
- xpd_t *xpd = xpd_of(xbus, j);
-
- if(!xpd)
- continue;
- if(SPAN_REGISTERED(xpd)) {
- if(xpd->timing_priority > timing_priority) {
- timing_priority = xpd->timing_priority;
- best_xpd = xpd;
- }
- }
- }
- }
- if(!best_xpd) {
- DBG(GENERAL, "%s: elected HOST\n", msg);
- sync_master_is(msg, NULL);
- } else if(!sync_master || (timing_priority > sync_master->timing_priority)) {
- XPD_DBG(GENERAL, best_xpd, "%s: elected with priority %d\n", msg, timing_priority);
- sync_master_is(msg, best_xpd->xbus);
- }
-}
-
-static inline void send_pcm_frame(xbus_t *xbus, xframe_t *xframe)
-{
- unsigned long flags;
- struct timeval now;
- unsigned long sec_diff;
- unsigned long usec_diff;
-
- spin_lock_irqsave(&xbus->lock, flags);
- do_gettimeofday(&now);
- if(unlikely(disable_pcm || !xbus->hardware_exists))
- goto dropit;
- sec_diff = now.tv_sec - xbus->last_tx_sync.tv_sec;
- usec_diff = sec_diff * 1000000 + (now.tv_usec - xbus->last_tx_sync.tv_usec);
- if(unlikely(abs(sec_diff) > 2)) {
- XBUS_DBG(SYNC, xbus, "PCM TX timing restart (sec_diff=%ld)\n", sec_diff);
- xbus->last_tx_sync = now;
- goto dropit;
- }
- if(abs(usec_diff - 1000) > TICK_TOLERANCE) {
- static int rate_limit;
-
- if((rate_limit++ % 5003) == 0)
- XBUS_DBG(SYNC, xbus, "Bad PCM TX timing(%d): usec_diff=%ld.\n",
- rate_limit, usec_diff);
- }
- if(usec_diff > xbus->max_tx_sync)
- xbus->max_tx_sync = usec_diff;
- if(usec_diff < xbus->min_tx_sync)
- xbus->min_tx_sync = usec_diff;
- spin_unlock_irqrestore(&xbus->lock, flags);
- /* OK, really send it */
- if(print_dbg & DBG_PCM )
- dump_xframe("TX_XFRAME_PCM", xbus, xframe);
- xframe_send(xbus, xframe);
- XBUS_COUNTER(xbus, TX_XFRAME_PCM)++;
- xbus->last_tx_sync = now;
- return;
-dropit:
- spin_unlock_irqrestore(&xbus->lock, flags);
- xbus->ops->xframe_free(xbus, xframe);
-}
-
-/*
- * Generic implementations of card_pcmfromspan()/card_pcmtospan()
- * For FXS/FXO
- */
-void generic_card_pcm_fromspan(xbus_t *xbus, xpd_t *xpd, xpp_line_t lines, xpacket_t *pack)
-{
- byte *pcm;
- struct zt_chan *chans;
- unsigned long flags;
- int i;
-
- BUG_ON(!xbus);
- BUG_ON(!xpd);
- BUG_ON(!pack);
- RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines) = lines;
- pcm = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, pcm);
- spin_lock_irqsave(&xpd->lock, flags);
- chans = xpd->span.chans;
- for (i = 0; i < xpd->channels; i++) {
- if(IS_SET(lines, i)) {
- if(SPAN_REGISTERED(xpd)) {
-#ifdef DEBUG_PCMTX
- if(pcmtx >= 0 && pcmtx_chan == i)
- memset((u_char *)pcm, pcmtx, ZT_CHUNKSIZE);
- else
-#endif
- memcpy((u_char *)pcm, chans[i].writechunk, ZT_CHUNKSIZE);
- // fill_beep((u_char *)pcm, xpd->addr.subunit, 2);
- } else
- memset((u_char *)pcm, 0x7F, ZT_CHUNKSIZE);
- pcm += ZT_CHUNKSIZE;
- }
- }
- XPD_COUNTER(xpd, PCM_WRITE)++;
- spin_unlock_irqrestore(&xpd->lock, flags);
-}
-
-void generic_card_pcm_tospan(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack)
-{
- volatile u_char *r;
- byte *pcm;
- xpp_line_t pcm_mask;
- unsigned long flags;
- int i;
-
- pcm = RPACKET_FIELD(pack, GLOBAL, PCM_READ, pcm);
- pcm_mask = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines);
- spin_lock_irqsave(&xpd->lock, flags);
- if (xpd->timer_count & 1)
- r = xpd->readchunk; /* First part */
- else
- r = xpd->readchunk + ZT_CHUNKSIZE * CHANNELS_PERXPD;
- for (i = 0; i < CHANNELS_PERXPD; i++, r += ZT_CHUNKSIZE) {
- /*
- * We don't copy signalling buffers (they may be
- * longer than ZT_CHUNKSIZE).
- */
- if(IS_SET(pcm_mask, i)) {
- // memset((u_char *)r, 0x5A, ZT_CHUNKSIZE); // DEBUG
- // fill_beep((u_char *)r, 1, 1); // DEBUG: BEEP
- memcpy((u_char *)r, pcm, ZT_CHUNKSIZE);
- pcm += ZT_CHUNKSIZE;
- }
- }
- XPD_COUNTER(xpd, PCM_READ)++;
- spin_unlock_irqrestore(&xpd->lock, flags);
-}
-
-static void xbus_tick(xbus_t *xbus)
-{
- int i;
- xpd_t *xpd;
- xframe_t *xframe = NULL;
- xpacket_t *pack = NULL;
- size_t pcm_len;
- bool sent_sync_bit = 0;
-
- /*
- * Update zaptel
- */
- for(i = 0; i < MAX_XPDS; i++) {
- xpd = xpd_of(xbus, i);
- if(xpd && SPAN_REGISTERED(xpd)) {
- /*
- * 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);
- }
- }
- /*
- * Fill xframes
- */
- for(i = 0; i < MAX_XPDS; i++) {
- if((xpd = xpd_of(xbus, i)) == NULL)
- continue;
- pcm_len = xpd->pcm_len;
- if(SPAN_REGISTERED(xpd)) {
- if(pcm_len && xpd->card_present) {
- do {
- // pack = NULL; /* FORCE single packet frames */
- if(xframe && !pack) { /* FULL frame */
- send_pcm_frame(xbus, xframe);
- xframe = NULL;
- XBUS_COUNTER(xbus, TX_PCM_FRAG)++;
- }
- if(!xframe) { /* Alloc frame */
- xframe = xbus->ops->xframe_new(xbus, GFP_ATOMIC);
- if (!xframe) {
- XBUS_ERR(xbus, "%s: failed to allocate new xframe\n", __FUNCTION__);
- return;
- }
- }
- pack = xframe_next_packet(xframe, pcm_len);
- } while(!pack);
- XPACKET_INIT(pack, GLOBAL, PCM_WRITE, xpd->xbus_idx);
- XPACKET_LEN(pack) = pcm_len;
- XPACKET_IS_PCM(pack) = 1;
- if(!sent_sync_bit) {
- XPACKET_ADDR(pack).sync_master = 1;
- sent_sync_bit = 1;
- }
- CALL_XMETHOD(card_pcm_fromspan, xbus, xpd, xpd->wanted_pcm_mask, pack);
- XBUS_COUNTER(xbus, TX_PACK_PCM)++;
- }
- }
- }
- if(xframe) /* clean any leftovers */
- send_pcm_frame(xbus, xframe);
- /*
- * Receive PCM
- */
- for(i = 0; i < MAX_XPDS; i++) {
- xpd = xpd_of(xbus, i);
- if(!xpd || !xpd->card_present)
- continue;
- if(SPAN_REGISTERED(xpd))
- xpp_receiveprep(xpd);
- xpd->timer_count = xpp_timer_count;
- /*
- * Must be called *after* tx/rx so
- * D-Chan counters may be cleared
- */
- CALL_XMETHOD(card_tick, xbus, xpd);
- }
-#ifdef ZAPTEL_SYNC_TICK
- if(xbus->sync_adjustment != xbus->sync_adjustment_offset)
- send_drift(xbus->sync_adjustment_offset);
-#endif
-}
-
-void xpp_tick(unsigned long param)
-{
- xbus_t *xbus;
- int i;
-
-#ifdef ZAPTEL_SYNC_TICK
- flip_parport_bit(3);
- do_gettimeofday(&ticked_xpp);
-#endif
- if(!sync_master) /* Called from timer */
- mod_timer(&xpp_timer, jiffies + 1); /* Must be 1KHz rate */
- /* Statistics */
- if((xpp_timer_count % SAMPLE_TICKS) == 0) {
- xpp_last_jiffies = jiffies;
- }
- xpp_timer_count++;
- for(i = 0; i < MAX_BUSES; i++) {
- xbus = xbus_of(i);
- if(!xbus)
- continue;
- if (!xbus->hardware_exists)
- continue;
- if(!down_read_trylock(&xbus->in_use)) {
- XBUS_DBG(GENERAL, xbus, "Dropped packet. Is in_use\n");
- continue;
- }
- /* Reset sync LEDs once in a while */
- if((xpp_timer_count % 10000) == 0)
- CALL_PROTO(GLOBAL, RESET_SYNC_COUNTERS, xbus, NULL);
- if(atomic_dec_and_test(&xbus->pcm_nesting)) {
- xbus_tick(xbus);
- } else {
- XBUS_ERR(xbus, "NESTING ATTEMPT: %d\n", atomic_read(&xbus->pcm_nesting));
- }
- atomic_inc(&xbus->pcm_nesting);
- up_read(&xbus->in_use);
- }
-}
-
-void got_sync_from(xpd_t *xpd)
-{
- xbus_t *xbus;
-
- xbus = xpd->xbus;
- if(xpd != sync_master) {
- static int rate_limit;
-
- if((rate_limit++ % 1003) == 0)
- XPD_DBG(SYNC, xpd, "is not SYNC master. Go away! (%d)\n", rate_limit);
- return;
- }
- xpp_tick(0L);
-}
-
-#ifdef ZAPTEL_SYNC_TICK
-static void send_drift(int drift)
-{
- struct timeval now;
- const char *msg;
- xbus_t *xbus;
-
- BUG_ON(!sync_master);
- xbus = sync_master->xbus;
- BUG_ON(drift < SYNC_ADJ_MIN || drift > SYNC_ADJ_MAX);
- do_gettimeofday(&now);
- if(drift == 0)
- msg = "stop";
- else if(drift > 0)
- msg = "up";
- else
- msg = "down";
- XBUS_DBG(SYNC, xbus, "DRIFT adjust %s (%d) (last update %ld seconds ago)\n",
- msg, drift, now.tv_sec - xbus->pll_updated_at);
- CALL_PROTO(GLOBAL, SYNC_SOURCE, xbus, NULL, SYNC_MODE_PLL, drift);
- xbus->pll_updated_at = now.tv_sec;
-}
-
-int zaptel_sync_tick(struct zt_span *span, int is_master)
-{
- xpd_t *xpd = span->pvt;
- int offset;
-
- if(!sync_tick_active)
- goto noop;
- /*
- * Detect if any of our spans is zaptel sync master
- */
- if(is_master) {
- sync_tick_nomaster = 0; /* Yes */
- have_sync_mastership = 1;
- }
- if(sync_tick_nomaster < MAX_BUSES * MAX_XPDS) {
- sync_tick_nomaster++; /* Maybe */
- goto noop;
- }
- /* Now we know for sure someone else is zaptel sync master */
- have_sync_mastership = 0;
- BUG_ON(!xpd);
- /*
- * Calculate only if:
- * - HOST sync (for information only)
- * - Called for the sync_master (the function is called
- * for each span, so we don't want to do it multiple times).
- */
- if(sync_master && sync_master != xpd)
- return 0;
- zaptel_tick_count++;
- zaptel_is_ticking = 1;
- flip_parport_bit(1);
- do_gettimeofday(&ticked_zaptel);
- usec_lag_curr =
- (ticked_zaptel.tv_sec - ticked_xpp.tv_sec)*1000*1000 +
- (ticked_zaptel.tv_usec - ticked_xpp.tv_usec);
- if(unlikely(usec_lag_curr > ZAPTEL_BIG_LAG)) {
- static int rate_limit;
-
- if((rate_limit++ % 1003) == 0)
- DBG(SYNC, "Big lag of Xpp ticks relative to zaptel ticks: %ld\n", usec_lag_curr);
- }
- sigma_lag += usec_lag_curr;
- if((zaptel_tick_count % SYNC_ADJ_INTERVAL) == 0) {
- average_lag = sigma_lag / SYNC_ADJ_INTERVAL;
- sigma_lag = 0;
- if(sync_master == xpd) {
- xbus_t *xbus = sync_master->xbus;
-
- /* Calculate required fix */
- offset = (average_lag - 500) / SYNC_ADJ_FACTOR;
- if(offset < SYNC_ADJ_MIN)
- offset = SYNC_ADJ_MIN;
- if(offset > SYNC_ADJ_MAX)
- offset = SYNC_ADJ_MAX;
- xbus->sync_adjustment_offset = offset;
- }
- }
- return 0;
-noop:
- zaptel_is_ticking = 0;
- sigma_lag = 0;
- return 0; /* No auto sync from zaptel */
-}
-#endif
-
static void xpd_free(xpd_t *xpd)
{
xbus_t *xbus = NULL;
@@ -604,7 +125,7 @@ static void xpd_free(xpd_t *xpd)
xbus = xpd->xbus;
if(!xbus)
return;
- XPD_DBG(GENERAL, xpd, "\n");
+ XPD_DBG(DEVICES, xpd, "\n");
#ifdef CONFIG_PROC_FS
if(xpd->proc_xpd_dir) {
if(xpd->proc_xpd_summary) {
@@ -628,12 +149,10 @@ static void xpd_free(xpd_t *xpd)
}
#endif
xbus_unregister_xpd(xbus, xpd);
- if(xpd->readchunk)
- kfree((void *)xpd->readchunk);
- xpd->readchunk = NULL;
if(xpd->xproto)
xproto_put(xpd->xproto);
xpd->xproto = NULL;
+ memset(xpd, 0, sizeof(*xpd));
kfree(xpd);
}
@@ -659,7 +178,7 @@ void card_detected(struct card_desc_struct *card_desc)
BUG_ON(!card_desc);
BUG_ON(card_desc->magic != CARD_DESC_MAGIC);
- xbus = card_desc->xbus;
+ xbus = card_desc->xbus; /* refcount held by xbus_poll() */
type = card_desc->type;
subtype = card_desc->subtype;
unit = card_desc->xpd_addr.unit;
@@ -706,13 +225,13 @@ void card_detected(struct card_desc_struct *card_desc)
xpd->offhook = card_desc->line_status;
/* For USB-1 disable some channels */
- if(xbus->max_xframe_size < RPACKET_SIZE(GLOBAL, PCM_WRITE)) {
+ if(MAX_SEND_SIZE(xbus) < RPACKET_SIZE(GLOBAL, PCM_WRITE)) {
xpp_line_t no_pcm;
no_pcm = 0x7F | xpd->digital_outputs | xpd->digital_inputs;
xpd->no_pcm = no_pcm;
XBUS_NOTICE(xbus, "max xframe size = %d, disabling some PCM channels. no_pcm=0x%04X\n",
- xbus->max_xframe_size, xpd->no_pcm);
+ MAX_SEND_SIZE(xbus), xpd->no_pcm);
}
xbus_register_xpd(xbus, xpd);
#ifdef CONFIG_PROC_FS
@@ -750,13 +269,8 @@ void card_detected(struct card_desc_struct *card_desc)
#endif
if(CALL_XMETHOD(card_init, xbus, xpd) < 0)
goto err;
- CALL_XMETHOD(XPD_STATE, xbus, xpd, 0); /* Turn off all channels */
- CALL_PROTO(GLOBAL, SYNC_SOURCE, xbus, NULL, SYNC_MODE_HOST, 0); /* Not a SYNC master (yet) */
+ //CALL_XMETHOD(XPD_STATE, xbus, xpd, 0); /* Turn off all channels */
xpd->card_present = 1;
- if(xbus->last_tx_sync.tv_sec == 0 && xbus->last_tx_sync.tv_usec == 0) {
- do_gettimeofday(&xbus->last_tx_sync); /* start timing ticks */
- xbus->last_rx_sync = xbus->last_tx_sync;
- }
CALL_XMETHOD(XPD_STATE, xbus, xpd, 1); /* Turn on all channels */
XPD_INFO(xpd, "Initialized: %s\n", xpd->type_name);
@@ -794,13 +308,14 @@ static int xpd_read_proc(char *page, char **start, off_t off, int count, int *eo
goto out;
xbus = xpd->xbus;
- len += sprintf(page + len, "%s (%s ,card %s, span %s) %s\n"
+ len += sprintf(page + len, "%s (%s ,card %s, span %d)\n"
+ "timing_priority: %d\n"
"timer_count: %d span->mainttimer=%d\n"
,
xpd->xpdname, xpd->type_name,
(xpd->card_present) ? "present" : "missing",
- (SPAN_REGISTERED(xpd)) ? "registered" : "NOT registered",
- (xpd == sync_master) ? "SYNC MASTER" : "SYNC SLAVE",
+ (SPAN_REGISTERED(xpd)) ? xpd->span.spanno : 0,
+ xpd->timing_priority,
xpd->timer_count, xpd->span.mainttimer
);
len += sprintf(page + len, "Address: U=%d S=%d\n", xpd->addr.unit, xpd->addr.subunit);
@@ -854,11 +369,7 @@ static int xpd_read_proc(char *page, char **start, off_t off, int count, int *eo
continue;
if(IS_SET(xpd->digital_signalling, i))
continue;
-#if 1
rp = chans[i].readchunk;
-#else
- rp = (byte *)xpd->readchunk + (ZT_CHUNKSIZE * i);
-#endif
wp = chans[i].writechunk;
memcpy(rchunk, rp, ZT_CHUNKSIZE);
memcpy(wchunk, wp, ZT_CHUNKSIZE);
@@ -917,7 +428,8 @@ xpd_t *xpd_alloc(size_t privsize, const xproto_table_t *proto_table, int channel
size_t alloc_size = sizeof(xpd_t) + privsize;
int type = proto_table->type;
- DBG(GENERAL, "type=%d channels=%d\n", type, channels);
+ DBG(DEVICES, "type=%d channels=%d (alloc_size=%d)\n",
+ type, channels, alloc_size);
if(channels > CHANNELS_PERXPD) {
ERR("%s: type=%d: too many channels %d\n",
__FUNCTION__, type, channels);
@@ -953,20 +465,11 @@ xpd_t *xpd_alloc(size_t privsize, const xproto_table_t *proto_table, int channel
ERR("%s: Unable to allocate channels\n", __FUNCTION__);
goto err;
}
- alloc_size = ZT_MAX_CHUNKSIZE * CHANNELS_PERXPD * 2; /* Double Buffer */
- if((xpd->readchunk = kmalloc(alloc_size, GFP_KERNEL)) == NULL) {
- ERR("%s: Unable to allocate memory for readchunk\n", __FUNCTION__);
- goto err;
- }
- /* Initialize read buffers to all blank data */
- memset((void *)xpd->readchunk, 0, alloc_size);
return xpd;
err:
if(xpd) {
if(xpd->chans)
kfree((void *)xpd->chans);
- if(xpd->readchunk)
- kfree((void *)xpd->readchunk);
kfree(xpd);
}
return NULL;
@@ -985,14 +488,8 @@ void xpd_disconnect(xpd_t *xpd)
BUG_ON(!xpd);
- // TODO: elect a new sync master
- if(sync_master == xpd) {
- sync_master_is("DISCONNECT", NULL);
- elect_syncer("DISCONNECT");
- }
-
spin_lock_irqsave(&xpd->lock, flags);
- XPD_DBG(GENERAL, xpd, "(%p)\n", xpd->xproto);
+ XPD_DBG(DEVICES, xpd, "(%p)\n", xpd->xproto);
if(!xpd->card_present) /* Multiple reports */
goto out;
xpd->card_present = 0;
@@ -1001,7 +498,7 @@ void xpd_disconnect(xpd_t *xpd)
update_xpd_status(xpd, ZT_ALARM_NOTOPEN);
/* TODO: Should this be done before releasing the spinlock? */
- XPD_DBG(GENERAL, xpd, "Queuing ZT_EVENT_REMOVED on all channels to ask user to release them\n");
+ XPD_DBG(DEVICES, xpd, "Queuing ZT_EVENT_REMOVED on all channels to ask user to release them\n");
for (i=0; i<xpd->span.channels; i++)
zt_qevent_lock(&xpd->chans[i],ZT_EVENT_REMOVED);
}
@@ -1062,130 +559,12 @@ void update_line_status(xpd_t *xpd, int pos, bool to_offhook)
* it may call back into our xpp_hooksig() and cause
* a nested spinlock scenario
*/
- LINE_DBG(GENERAL, xpd, pos, "rxsig=%s\n", (rxsig == ZT_RXSIG_ONHOOK) ? "ONHOOK" : "OFFHOOK");
+ LINE_DBG(SIGNAL, xpd, pos, "rxsig=%s\n", (rxsig == ZT_RXSIG_ONHOOK) ? "ONHOOK" : "OFFHOOK");
if(SPAN_REGISTERED(xpd))
zt_hooksig(&xpd->chans[pos], rxsig);
}
#ifdef CONFIG_PROC_FS
-
-int proc_sync_read(char *page, char **start, off_t off, int count, int *eof, void *data)
-{
- int len = 0;
- unsigned int xpp_timer_rate;
- unsigned int jiffies_now;
-
- len += sprintf(page + len, "# To modify sync source write into this file:\n");
- len += sprintf(page + len, "# HOST - For host based sync\n");
- len += sprintf(page + len, "# SYNC=nn - XBUS-nn provide sync\n");
- len += sprintf(page + len, "# QUERY=nn - Query XBUS-nn for sync information (DEBUG)\n");
- if(!sync_master)
- len += sprintf(page + len, "HOST\n");
- else {
- len += sprintf(page + len, "SYNC=%02d\n", sync_master->xbus->num);
- len += sprintf(page + len, "PLL DRIFT=%d\n",
- sync_master->xbus->sync_adjustment);
- }
-#ifdef ZAPTEL_SYNC_TICK
- if(sync_tick_active) {
- if(!zaptel_is_ticking) {
- len += sprintf(page + len,
- "Zaptel Reference Sync Not activated\n");
- goto noextsync;
- }
- len += sprintf(page + len, "Zaptel Reference Sync (%s):\n",
- (have_sync_mastership)?"xpp":"external");
- len += sprintf(page + len, "\tzaptel_tick: #%d\n", zaptel_tick_count);
- len += sprintf(page + len, "\ttick - zaptel_tick = %d\n",
- xpp_timer_count - zaptel_tick_count);
- len += sprintf(page + len, "\t%-19s: %5ld (usec)\n",
- "current lag", usec_lag_curr);
- len += sprintf(page + len, "\t%-19s: %5ld (usec)\n",
- "average lag", average_lag);
- if(sync_master) {
- struct timeval now;
- xbus_t *xbus = sync_master->xbus;
-
- do_gettimeofday(&now);
- len += sprintf(page + len, "\t%-19s: %5ld seconds ago\n",
- "PLL updated",
- (xbus->pll_updated_at == 0) ? 0 : now.tv_sec - xbus->pll_updated_at);
- len += sprintf(page + len, "\t%-19s: %5d\n",
- "offset",
- xbus->sync_adjustment_offset);
- }
- }
-noextsync:
-#endif
- len += sprintf(page + len, "\ntick: #%d\n", xpp_timer_count);
- xpp_timer_rate = 0;
- jiffies_now = jiffies;
- if(jiffies_now - xpp_last_jiffies > 0) {
- unsigned long delta = (jiffies_now - xpp_last_jiffies);
- xpp_timer_rate = (xpp_timer_count % SAMPLE_TICKS) * HZ / delta;
- len += sprintf(page + len, "tick rate: %4d/second (SAMPLE_TICKS=%d)\n", xpp_timer_rate, SAMPLE_TICKS);
- }
- if(pcm_tasklet)
- len += sprintf(page + len, PCM_TASKLET_DEPRECATION);
- if (len <= off+count)
- *eof = 1;
- *start = page + off;
- len -= off;
- if (len > count)
- len = count;
- if (len < 0)
- len = 0;
- return len;
-}
-
-static int proc_sync_write(struct file *file, const char __user *buffer, unsigned long count, void *data)
-{
- char buf[MAX_PROC_WRITE];
- int xbus_num;
- int xpd_num;
- xbus_t *xbus;
-
- // DBG(SYNC, "%s: count=%ld\n", __FUNCTION__, count);
- if(count >= MAX_PROC_WRITE)
- return -EINVAL;
- if(copy_from_user(buf, buffer, count))
- return -EFAULT;
- buf[count] = '\0';
- if(strncmp("HOST", buf, 4) == 0) {
- sync_master_is("PROC", NULL);
- } else if(sscanf(buf, "SYNC=%d", &xbus_num) == 1) {
- DBG(SYNC, "SYNC=%d\n", xbus_num);
- if((xbus = xbus_of(xbus_num)) == NULL) {
- ERR("No bus %d exists\n", xbus_num);
- return -ENXIO;
- }
- sync_master_is("PROC", xbus);
- } else if(sscanf(buf, "QUERY=%d", &xbus_num) == 1) {
- DBG(SYNC, "QUERY=%d\n", xbus_num);
- if((xbus = xbus_of(xbus_num)) == NULL) {
- ERR("No bus %d exists\n", xbus_num);
- return -ENXIO;
- }
- CALL_PROTO(GLOBAL, SYNC_SOURCE, xbus, NULL, SYNC_MODE_QUERY, 0);
- } else if(sscanf(buf, "%d %d", &xbus_num, &xpd_num) == 2) {
- NOTICE("Using deprecated syntax to update /proc/%s/%s\n",
- PROC_DIR, PROC_SYNC);
- if(xpd_num != 0) {
- ERR("Currently can only set sync for XPD #0\n");
- return -EINVAL;
- }
- if((xbus = xbus_of(xbus_num)) == NULL) {
- ERR("No bus %d exists\n", xbus_num);
- return -ENXIO;
- }
- sync_master_is("PROC", xbus);
- } else {
- ERR("%s: cannot parse '%s'\n", __FUNCTION__, buf);
- count = -EINVAL;
- }
- return count;
-}
-
int proc_xpd_ztregister_read(char *page, char **start, off_t off, int count, int *eof, void *data)
{
int len = 0;
@@ -1195,7 +574,7 @@ int proc_xpd_ztregister_read(char *page, char **start, off_t off, int count, int
BUG_ON(!xpd);
spin_lock_irqsave(&xpd->lock, flags);
- len += sprintf(page + len, "%d\n", SPAN_REGISTERED(xpd));
+ len += sprintf(page + len, "%d\n", SPAN_REGISTERED(xpd) ? xpd->span.spanno : 0);
spin_unlock_irqrestore(&xpd->lock, flags);
if (len <= off+count)
*eof = 1;
@@ -1282,151 +661,6 @@ static int proc_xpd_blink_write(struct file *file, const char __user *buffer, un
/*------------------------- Zaptel Interfaces ----------------------*/
-void pcm_recompute(xpd_t *xpd, xpp_line_t pcm_mask)
-{
- int i;
- int line_count = 0;
- unsigned long flags;
-
- pcm_mask &= ~xpd->digital_signalling; /* without D-Channel */
- pcm_mask &= ~xpd->digital_inputs;
- pcm_mask &= ~xpd->digital_outputs;
- for_each_line(xpd, i)
- if(IS_SET(pcm_mask, i))
- line_count++;
- /*
- * FIXME: Workaround a bug in sync code of the Astribank.
- * Send dummy PCM for sync.
- */
- if(xpd->addr.unit == 0 && pcm_mask == 0) {
- pcm_mask = BIT(0);
- line_count = 1;
- }
- spin_lock_irqsave(&xpd->lock, flags);
- xpd->pcm_len = (line_count)
- ? RPACKET_HEADERSIZE + sizeof(xpp_line_t) + line_count * ZT_CHUNKSIZE
- : 0L;
- xpd->wanted_pcm_mask = pcm_mask;
- spin_unlock_irqrestore(&xpd->lock, flags);
-}
-
-void fill_beep(u_char *buf, int num, int duration)
-{
- bool alternate = (duration) ? (jiffies/(duration*1000)) & 0x1 : 0;
- int which;
- u_char *snd;
-
- /*
- * debug tones
- */
- static u_char beep[] = {
- 0x7F, 0xBE, 0xD8, 0xBE, 0x80, 0x41, 0x24, 0x41, /* Dima */
- 0x67, 0x90, 0x89, 0x90, 0xFF, 0x10, 0x09, 0x10, /* Izzy */
- };
- static u_char beep_alt[] = {
- 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, /* silence */
- };
- if(alternate) {
- which = num % ARRAY_SIZE(beep_alt);
- snd = &beep_alt[which];
- } else {
- which = num % ARRAY_SIZE(beep);
- snd = &beep[which];
- }
- memcpy(buf, snd, ZT_CHUNKSIZE);
-}
-
-#ifdef XPP_EC_CHUNK
-/*
- * Taken from zaptel.c
- */
-static inline void xpp_ec_chunk(struct zt_chan *chan, unsigned char *rxchunk, const unsigned char *txchunk)
-{
- int16_t rxlin;
- int x;
- unsigned long flags;
-
- /* Perform echo cancellation on a chunk if necessary */
- if (!chan->ec)
- return;
- spin_lock_irqsave(&chan->lock, flags);
- for (x=0;x<ZT_CHUNKSIZE;x++) {
- rxlin = ZT_XLAW(rxchunk[x], chan);
- rxlin = xpp_echo_can_update(chan->ec, ZT_XLAW(txchunk[x], chan), rxlin);
- rxchunk[x] = ZT_LIN2X((int)rxlin, chan);
- }
- spin_unlock_irqrestore(&chan->lock, flags);
-}
-#endif
-
-static void do_ec(xpd_t *xpd)
-{
- struct zt_chan *chans = xpd->span.chans;
- int i;
-
-#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 */
- continue;
-#ifdef XPP_EC_CHUNK
- /* even if defined, parameterr xpp_ec can override at run-time */
- if (xpp_ec)
- xpp_ec_chunk(&chans[i], chans[i].readchunk, xpd->ec_chunk2[i]);
- else
-#endif
- zt_ec_chunk(&chans[i], chans[i].readchunk, xpd->ec_chunk2[i]);
- memcpy(xpd->ec_chunk2[i], xpd->ec_chunk1[i], ZT_CHUNKSIZE);
- memcpy(xpd->ec_chunk1[i], chans[i].writechunk, ZT_CHUNKSIZE);
- }
-#endif
-}
-
-
-
-static void xpp_receiveprep(xpd_t *xpd)
-{
- volatile u_char *readchunk;
- int i;
- int channels = xpd->channels;
- struct zt_chan *chans = xpd->span.chans;
- unsigned long flags;
-
- spin_lock_irqsave(&xpd->lock, flags);
- // if((xpd->timer_count % 1000) == 0)
- // XPD_DBG(GENERAL, xpd, "%d\n", xpd->timer_count);
-
- if (xpd->timer_count & 1) {
- /* First part */
- readchunk = xpd->readchunk;
- } else {
- readchunk = xpd->readchunk + ZT_CHUNKSIZE * CHANNELS_PERXPD;
- }
-
- for (i = 0; i < channels; i++, readchunk += ZT_CHUNKSIZE) {
- /*
- * We don't copy signalling buffers (they may be
- * longer than ZT_CHUNKSIZE).
- */
- if(unlikely(IS_SET(xpd->digital_signalling, i)))
- continue;
- if(!IS_SET(xpd->mute_dtmf, i) &&
- (IS_SET(xpd->offhook, i) || IS_SET(xpd->cid_on, i) || IS_BRI(xpd))) {
- // memset((u_char *)readchunk, 0x5A, ZT_CHUNKSIZE); // DEBUG
- // fill_beep((u_char *)readchunk, 1, 1); // DEBUG: BEEP
- memcpy(chans[i].readchunk, (u_char *)readchunk, ZT_CHUNKSIZE);
- } else {
- memset(chans[i].readchunk, 0x7F, ZT_CHUNKSIZE); // SILENCE
- }
- }
- spin_unlock_irqrestore(&xpd->lock, flags);
- /*
- * This should be out of spinlocks, as it may call back our hook setting
- * methods
- */
- do_ec(xpd);
- zt_receive(&xpd->span);
-}
/*
* Called from zaptel with spinlock held on chan. Must not call back
@@ -1434,17 +668,41 @@ static void xpp_receiveprep(xpd_t *xpd)
*/
int xpp_open(struct zt_chan *chan)
{
+#if 0
xpd_t *xpd = chan->pvt;
xbus_t *xbus = xpd->xbus;
int pos = chan->chanpos - 1;
unsigned long flags;
+#else
+ xpd_t *xpd;
+ xbus_t *xbus;
+ int pos;
+ unsigned long flags;
+
+ if (!chan) {
+ NOTICE("open called on a null chan\n");
+ return -EINVAL;
+ }
+ xpd = chan->pvt;
+ if (!xpd) {
+ NOTICE("open called on a chan with no pvt (xpd)\n");
+ return -EINVAL;
+ }
+ xbus = xpd->xbus;
+ if (!xbus) {
+ NOTICE("open called on a chan with no xbus\n");
+ return -EINVAL;
+ }
+ pos = chan->chanpos - 1;
+#endif
spin_lock_irqsave(&xbus->lock, flags);
- xbus->open_counter++;
+ atomic_inc(&xbus->xbus_ref_count);
atomic_inc(&xpd->open_counter);
if(IS_SET(xpd->digital_signalling, pos)) /* D-chan offhook */
BIT_SET(xpd->offhook, pos);
- DBG(GENERAL, "chan=%d (open_counter=%d)\n", pos, xbus->open_counter);
+ DBG(DEVICES, "chan=%d (xbus_ref_count=%d)\n",
+ pos, atomic_read(&xbus->xbus_ref_count));
spin_unlock_irqrestore(&xbus->lock, flags);
if(xpd->xops->card_open)
xpd->xops->card_open(xpd, pos);
@@ -1457,45 +715,48 @@ int xpp_close(struct zt_chan *chan)
xbus_t *xbus = xpd->xbus;
int pos = chan->chanpos - 1;
unsigned long flags;
- bool should_remove = 0;
spin_lock_irqsave(&xbus->lock, flags);
- xbus->open_counter--;
atomic_dec(&xpd->open_counter);
- if (!xbus->hardware_exists && xbus->open_counter == 0)
- should_remove = 1;
if(IS_SET(xpd->digital_signalling, pos)) /* D-chan onhook */
BIT_CLR(xpd->offhook, pos);
spin_unlock_irqrestore(&xbus->lock, flags);
if(xpd->xops->card_close)
xpd->xops->card_close(xpd, pos);
- DBG(GENERAL, "chan=%d (open_counter=%d, should_remove=%d)\n", pos, xbus->open_counter, should_remove);
- if(should_remove) {
- XBUS_DBG(GENERAL, xbus, "Going to remove\n");
+ XPD_DBG(GENERAL, xpd, "pid=%d: chan=%d (xbus_ref_count=%d)\n",
+ current->pid, pos, atomic_read(&xbus->xbus_ref_count));
+ if(atomic_dec_and_test(&xbus->xbus_ref_count))
xbus_remove(xbus);
- }
return 0;
}
+void report_bad_ioctl(const char *msg, xpd_t *xpd, int pos, unsigned int cmd)
+{
+ XPD_NOTICE(xpd, "%s: Bad ioctl\n", msg);
+ XPD_NOTICE(xpd, "ENOTTY: chan=%d cmd=0x%x\n", pos, cmd);
+ XPD_NOTICE(xpd, " IOC_TYPE=0x%02X\n", _IOC_TYPE(cmd));
+ XPD_NOTICE(xpd, " IOC_DIR=0x%02X\n", _IOC_DIR(cmd));
+ XPD_NOTICE(xpd, " IOC_NR=%d\n", _IOC_NR(cmd));
+ XPD_NOTICE(xpd, " IOC_SIZE=0x%02X\n", _IOC_SIZE(cmd));
+}
+
int xpp_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long arg)
{
xpd_t *xpd = chan->pvt;
int pos = chan->chanpos - 1;
- int ret = 0;
+ if(!xpd) {
+ ERR("%s: channel in pos %d, was already closed. Ignore.\n",
+ __FUNCTION__, pos);
+ return -ENODEV;
+ }
switch (cmd) {
default:
/* Some span-specific commands before we give up: */
if (xpd->xops->card_ioctl != NULL) {
- ret = xpd->xops->card_ioctl(xpd, pos, cmd, arg);
- if (ret != -ENOTTY)
- return ret;
+ return xpd->xops->card_ioctl(xpd, pos, cmd, arg);
}
- XPD_DBG(GENERAL, xpd, "ENOTTY: chan=%d cmd=0x%x\n", pos, cmd);
- XPD_DBG(GENERAL, xpd, " IOC_TYPE=0x%02X\n", _IOC_TYPE(cmd));
- XPD_DBG(GENERAL, xpd, " IOC_DIR=0x%02X\n", _IOC_DIR(cmd));
- XPD_DBG(GENERAL, xpd, " IOC_NR=0x%02X\n", _IOC_NR(cmd));
- XPD_DBG(GENERAL, xpd, " IOC_SIZE=0x%02X\n", _IOC_SIZE(cmd));
+ report_bad_ioctl(THIS_MODULE->name, xpd, pos, cmd);
return -ENOTTY;
}
return 0;
@@ -1507,10 +768,14 @@ static int xpp_hooksig(struct zt_chan *chan, zt_txsig_t txsig)
xbus_t *xbus;
int pos = chan->chanpos - 1;
- BUG_ON(!xpd);
+ if(!xpd) {
+ ERR("%s: channel in pos %d, was already closed. Ignore.\n",
+ __FUNCTION__, pos);
+ return -ENODEV;
+ }
xbus = xpd->xbus;
BUG_ON(!xbus);
- DBG(GENERAL, "Setting %s to %s (%d)\n", chan->name, txsig2str(txsig), txsig);
+ DBG(SIGNAL, "Setting %s to %s (%d)\n", chan->name, txsig2str(txsig), txsig);
return CALL_XMETHOD(card_hooksig, xbus, xpd, pos, txsig);
}
@@ -1527,7 +792,6 @@ int xpp_maint(struct zt_span *span, int cmd)
char loopback_data[] = "THE-QUICK-BROWN-FOX-JUMPED-OVER-THE-LAZY-DOG";
#endif
- BUG_ON(!xpd);
DBG(GENERAL, "span->mainttimer=%d\n", span->mainttimer);
switch(cmd) {
case ZT_MAINT_NONE:
@@ -1559,51 +823,6 @@ int xpp_maint(struct zt_span *span, int cmd)
return ret;
}
-#if 0
-/* Okay, now we get to the signalling. You have several options: */
-
-/* Option 1: If you're a T1 like interface, you can just provide a
- rbsbits function and we'll assert robbed bits for you. Be sure to
- set the ZT_FLAG_RBS in this case. */
-
-/* Opt: If the span uses A/B bits, set them here */
-int (*rbsbits)(struct zt_chan *chan, int bits);
-
-/* Option 2: If you don't know about sig bits, but do have their
- equivalents (i.e. you can disconnect battery, detect off hook,
- generate ring, etc directly) then you can just specify a
- sethook function, and we'll call you with appropriate hook states
- to set. Still set the ZT_FLAG_RBS in this case as well */
-int (*hooksig)(struct zt_chan *chan, zt_txsig_t hookstate);
-
-/* Option 3: If you can't use sig bits, you can write a function
- which handles the individual hook states */
-int (*sethook)(struct zt_chan *chan, int hookstate);
-#endif
-
-static int xpp_echocan(struct zt_chan *chan, int len)
-{
-#ifdef XPP_EC_CHUNK
- if(len == 0) { /* shut down */
- /* zaptel calls this also during channel initialization */
- if(chan->ec) {
- xpp_echo_can_free(chan->ec);
- }
- return 0;
- }
- if(chan->ec) {
- ERR("%s: Trying to override an existing EC (%p)\n", __FUNCTION__, chan->ec);
- return -EINVAL;
- }
- chan->ec = xpp_echo_can_create(len, 0);
- if(!chan->ec) {
- ERR("%s: Failed creating xpp EC (len=%d)\n", __FUNCTION__, len);
- return -EINVAL;
- }
-#endif
- return 0;
-}
-
#ifdef CONFIG_ZAPTEL_WATCHDOG
/*
* If the watchdog detects no received data, it will call the
@@ -1653,10 +872,8 @@ static int zaptel_unregister_xpd(xpd_t *xpd)
if(xpd->card_present)
xpd->xops->card_zaptel_preregistration(xpd, 0);
atomic_dec(&xpd->zt_registered);
+ atomic_dec(&num_registered_spans);
zt_unregister(&xpd->span);
-#ifdef ZAPTEL_SYNC_TICK
- zaptel_is_ticking = 0;
-#endif
if(xpd->card_present)
xpd->xops->card_zaptel_postregistration(xpd, 0);
return 0;
@@ -1678,13 +895,13 @@ static int zaptel_register_xpd(xpd_t *xpd)
return -EEXIST;
}
cn = xpd->channels;
- XPD_DBG(GENERAL, xpd, "Initializing span: %d channels.\n", cn);
+ XPD_DBG(DEVICES, xpd, "Initializing span: %d channels.\n", cn);
memset(xpd->chans, 0, sizeof(struct zt_chan)*cn);
memset(&xpd->span, 0, sizeof(struct zt_span));
span = &xpd->span;
snprintf(span->name, MAX_SPANNAME, "%s/%s", xbus->busname, xpd->xpdname);
- span->deflaw = ZT_LAW_MULAW;
+ span->deflaw = ZT_LAW_MULAW; /* default, may be overriden by card_* drivers */
init_waitqueue_head(&span->maintq);
span->pvt = xpd;
span->channels = cn;
@@ -1713,6 +930,7 @@ static int zaptel_register_xpd(xpd_t *xpd)
XPD_ERR(xpd, "Failed to zt_register span\n");
return -ENODEV;
}
+ atomic_inc(&num_registered_spans);
atomic_inc(&xpd->zt_registered);
xpd->xops->card_zaptel_postregistration(xpd, 1);
/*
@@ -1755,11 +973,7 @@ static int xpp_zap_write_proc(struct file *file, const char __user *buffer, unsi
static void do_cleanup(void)
{
- if(timer_pending(&xpp_timer))
- del_timer_sync(&xpp_timer);
#ifdef CONFIG_PROC_FS
- DBG(GENERAL, "Removing '%s' from proc\n", PROC_SYNC);
- remove_proc_entry(PROC_SYNC, xpp_proc_toplevel);
if(xpp_proc_toplevel) {
DBG(GENERAL, "Removing '%s' from proc\n", PROC_DIR);
remove_proc_entry(PROC_DIR, NULL);
@@ -1771,29 +985,14 @@ static void do_cleanup(void)
int __init xpp_zap_init(void)
{
int ret = 0;
- struct proc_dir_entry *ent;
INFO("revision %s MAX_XPDS=%d (%d*%d)\n", XPP_VERSION,
MAX_XPDS, MAX_UNIT, MAX_SUBUNIT);
-#ifdef WITH_ECHO_SUPPRESSION
- INFO("FEATURE: with ECHO_SUPPRESSION\n");
-#else
- INFO("FEATURE: without ECHO_SUPPRESSION\n");
-#endif
- if (xpp_ec)
- INFO("FEATURE: with XPP_EC_CHUNK\n");
- else
- INFO("FEATURE: without XPP_EC_CHUNK\n");
#ifdef CONFIG_ZAPATA_BRI_DCHANS
INFO("FEATURE: with BRISTUFF support\n");
#else
INFO("FEATURE: without BRISTUFF support\n");
#endif
-#ifdef ZAPTEL_SYNC_TICK
- INFO("FEATURE: with sync_tick() from ZAPTEL\n");
-#else
- INFO("FEATURE: without sync_tick() from ZAPTEL\n");
-#endif
#ifdef OPTIMIZE_CHANMUTE
INFO("FEATURE: with CHANMUTE optimization\n");
#endif
@@ -1803,27 +1002,18 @@ int __init xpp_zap_init(void)
ret = -EIO;
goto err;
}
-
- ent = create_proc_entry(PROC_SYNC, 0644, xpp_proc_toplevel);
- if(!ent) {
- ret = -EFAULT;
- goto err;
- }
- ent->read_proc = proc_sync_read;
- ent->write_proc = proc_sync_write;
- ent->data = NULL;
#endif
ret = xbus_core_init();
if(ret) {
ERR("xbus_core_init failed (%d)\n", ret);
goto err;
}
-
- /* Only timer init. We add it only *after* zt_register */
- init_timer(&xpp_timer);
- sync_master_is("INIT", NULL); /* Internal ticking */
- if(pcm_tasklet)
- ERR(PCM_TASKLET_DEPRECATION);
+ ret = xbus_pcm_init(xpp_proc_toplevel);
+ if(ret) {
+ ERR("xbus_pcm_init failed (%d)\n", ret);
+ xbus_core_shutdown();
+ goto err;
+ }
return 0;
err:
do_cleanup();
@@ -1832,6 +1022,7 @@ err:
void __exit xpp_zap_cleanup(void)
{
+ xbus_pcm_shutdown();
xbus_core_shutdown();
do_cleanup();
}
@@ -1840,17 +1031,13 @@ EXPORT_SYMBOL(print_dbg);
EXPORT_SYMBOL(card_detected);
EXPORT_SYMBOL(xpd_alloc);
EXPORT_SYMBOL(xpd_disconnect);
-EXPORT_SYMBOL(pcm_recompute);
-EXPORT_SYMBOL(generic_card_pcm_fromspan);
-EXPORT_SYMBOL(generic_card_pcm_tospan);
EXPORT_SYMBOL(update_xpd_status);
EXPORT_SYMBOL(update_line_status);
-EXPORT_SYMBOL(fill_beep);
EXPORT_SYMBOL(xpp_open);
EXPORT_SYMBOL(xpp_close);
EXPORT_SYMBOL(xpp_ioctl);
EXPORT_SYMBOL(xpp_maint);
-EXPORT_SYMBOL(elect_syncer);
+EXPORT_SYMBOL(report_bad_ioctl);
MODULE_DESCRIPTION("XPP Zaptel Driver");
MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");