diff options
Diffstat (limited to 'xpp/xpp_zap.c')
-rw-r--r-- | xpp/xpp_zap.c | 987 |
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>"); |