build against the now-typedef-free dahdi/user.h, and remove some #ifdefs for features...
[asterisk/asterisk.git] / channels / chan_dahdi.c
index 669c44c..7222272 100644 (file)
@@ -58,7 +58,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include <sys/ioctl.h>
 #include <math.h>
 #include <ctype.h>
-#include "asterisk/dahdi.h"
+
+#include <dahdi/user.h>
+#include <dahdi/tonezone.h>
 
 #ifdef HAVE_PRI
 #include <libpri.h>
@@ -101,7 +103,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 #define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
 
-#ifdef DAHDI_SPANINFO_HAS_LINECONFIG
 static const char *lbostr[] = {
 "0 db (CSU)/0-133 feet (DSX-1)",
 "133-266 feet (DSX-1)",
@@ -112,7 +113,6 @@ static const char *lbostr[] = {
 "-15db (CSU)",
 "-22.5db (CSU)"
 };
-#endif
 
 /*! Global jitterbuffer configuration - by default, jb is disabled */
 static struct ast_jb_conf default_jbconf =
@@ -124,16 +124,6 @@ static struct ast_jb_conf default_jbconf =
 };
 static struct ast_jb_conf global_jbconf;
 
-#if !defined(DAHDI_SIG_EM_E1) || (defined(HAVE_PRI) && !defined(DAHDI_SIG_HARDHDLC))
-#error "Your DAHDI is too old.  Please update"
-#endif
-
-#ifndef DAHDI_TONEDETECT
-/* Work around older code with no tone detect */
-#define DAHDI_EVENT_DTMFDOWN 0
-#define DAHDI_EVENT_DTMFUP 0
-#endif
-
 /* define this to send PRI user-user information elements */
 #undef SUPPORT_USERUSER
 
@@ -240,6 +230,7 @@ static char parkinglot[AST_MAX_EXTENSION] = "";             /*!< Default parking lot for th
 
 /*! Run this script when the MWI state changes on an FXO line, if mwimonitor is enabled */
 static char mwimonitornotify[PATH_MAX] = "";
+static int  mwisend_rpas = 0;
 
 static char progzone[10] = "";
 
@@ -346,6 +337,8 @@ static int ringt_base = DEFAULT_RINGT;
 
 #define SS7_NAI_DYNAMIC                -1
 
+#define LINKSET_FLAG_EXPLICITACM (1 << 0)
+
 struct dahdi_ss7 {
        pthread_t master;                                               /*!< Thread of master */
        ast_mutex_t lock;
@@ -366,6 +359,7 @@ struct dahdi_ss7 {
        char unknownprefix[20];                                         /*!< for unknown dialplans */
        struct ss7 *ss7;
        struct dahdi_pvt *pvts[MAX_CHANNELS];                           /*!< Member channel pvt structs */
+       int flags;                                                      /*!< Linkset flags */
 };
 
 static struct dahdi_ss7 linksets[NUM_SPANS];
@@ -420,6 +414,9 @@ struct dahdi_pri {
        int span;
        int resetting;
        int resetpos;
+#ifdef HAVE_PRI_INBANDDISCONNECT
+       unsigned int inbanddisconnect:1;                                /*!< Should we support inband audio after receiving DISCONNECT? */
+#endif
        time_t lastreset;                                               /*!< time when unused channels were last reset */
        long resetinterval;                                             /*!< Interval (in seconds) for resetting unused channels */
        int sig;
@@ -490,7 +487,7 @@ struct dahdi_subchannel {
        unsigned int needunhold:1;
        unsigned int linear:1;
        unsigned int inthreeway:1;
-       DAHDI_CONFINFO curconf;
+       struct dahdi_confinfo curconf;
 };
 
 #define CONF_USER_REAL         (1 << 0)
@@ -511,6 +508,8 @@ static struct dahdi_pvt {
        struct dahdi_pvt *master;                               /*!< Master to us (we follow their conferencing) */
        int inconference;                               /*!< If our real should be in the conference */
        
+       int buf_no;                                     /*!< Number of buffers */
+       int buf_policy;                         /*!< Buffer policy */
        int sig;                                        /*!< Signalling style */
        int radio;                                      /*!< radio type */
        int outsigmod;                                  /*!< Outbound Signalling style (modifier) */
@@ -571,6 +570,7 @@ static struct dahdi_pvt {
        unsigned int mwimonitor_neon:1;                 /*!< monitor this FXO port for neon type MWI indication from other end */
        unsigned int mwimonitor_fsk:1;                  /*!< monitor this FXO port for fsk MWI indication from other end */
        unsigned int mwimonitoractive:1;                /*!< an MWI monitor thread is currently active */
+       unsigned int mwisendactive:1;                   /*!< a MWI message sending thread is active */
        /* Channel state or unavilability flags */
        unsigned int inservice:1;
        unsigned int locallyblocked:1;
@@ -649,7 +649,7 @@ static struct dahdi_pvt {
        struct timeval flashtime;                       /*!< Last flash-hook time */
        struct ast_dsp *dsp;
        int cref;                                       /*!< Call reference number */
-       DAHDI_DIAL_OPERATION dop;
+       struct dahdi_dialoperation dop;
        int whichwink;                                  /*!< SIG_FEATDMF_TA Which wink are we on? */
        char finaldial[64];
        char accountcode[AST_MAX_ACCOUNT_CODE];         /*!< Account code */
@@ -729,7 +729,7 @@ struct dahdi_chan_conf {
 #ifdef HAVE_SS7
        struct dahdi_ss7 ss7;
 #endif
-       DAHDI_PARAMS timing;
+       struct dahdi_params timing;
        int is_sig_auto; /*!< Use channel signalling from DAHDI? */
 
        char smdi_port[SMDI_MAX_FILENAME_LEN];
@@ -801,7 +801,10 @@ static struct dahdi_chan_conf dahdi_chan_conf_default(void) {
 
                        .polarityonanswerdelay = 600,
 
-                       .sendcalleridafter = DEFAULT_CIDRINGS
+                       .sendcalleridafter = DEFAULT_CIDRINGS,
+               
+                       .buf_policy = DAHDI_POLICY_IMMEDIATE,
+                       .buf_no = numbufs
                },
                .timing = {
                        .prewinktime = -1,
@@ -835,6 +838,7 @@ static int dahdi_indicate(struct ast_channel *chan, int condition, const void *d
 static int dahdi_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
 static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int datalen);
 static int dahdi_func_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len);
+static int handle_init_event(struct dahdi_pvt *i, int event);
 
 static const struct ast_channel_tech dahdi_tech = {
        .type = "DAHDI",
@@ -895,10 +899,7 @@ static inline int ss7_grab(struct dahdi_pvt *pvt, struct dahdi_ss7 *pri)
        do {
                res = ast_mutex_trylock(&pri->lock);
                if (res) {
-                       ast_mutex_unlock(&pvt->lock);
-                       /* Release the lock and try again */
-                       usleep(1);
-                       ast_mutex_lock(&pvt->lock);
+                       DEADLOCK_AVOIDANCE(&pvt->lock);
                }
        } while (res);
        /* Then break the poll */
@@ -928,6 +929,9 @@ static int cidrings[NUM_CADENCE_MAX] = {
        2,                                                                              /*!< Second spell */
 };
 
+/* ETSI EN300 659-1 specifies the ring pulse between 200 and 300 mS */
+static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
+
 #define ISTRUNK(p) ((p->sig == SIG_FXSLS) || (p->sig == SIG_FXSKS) || \
                        (p->sig == SIG_FXSGS) || (p->sig == SIG_PRI))
 
@@ -1138,7 +1142,7 @@ static int dahdi_setlinear(int zfd, int linear)
 
 static int alloc_sub(struct dahdi_pvt *p, int x)
 {
-       DAHDI_BUFFERINFO bi;
+       struct dahdi_bufferinfo bi;
        int res;
        if (p->subs[x].zfd >= 0) {
                ast_log(LOG_WARNING, "%s subchannel of %d already in use\n", subnames[x], p->channel);
@@ -1153,18 +1157,18 @@ static int alloc_sub(struct dahdi_pvt *p, int x)
 
        res = ioctl(p->subs[x].zfd, DAHDI_GET_BUFINFO, &bi);
        if (!res) {
-               bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
-               bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
-               bi.numbufs = numbufs;
+               bi.txbufpolicy = p->buf_policy;
+               bi.rxbufpolicy = p->buf_policy;
+               bi.numbufs = p->buf_no;
                res = ioctl(p->subs[x].zfd, DAHDI_SET_BUFINFO, &bi);
                if (res < 0) {
-                       ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d\n", x);
+                       ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", x, strerror(errno));
                }
        } else 
-               ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d\n", x);
+               ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", x, strerror(errno));
 
        if (ioctl(p->subs[x].zfd, DAHDI_CHANNO, &p->subs[x].chan) == 1) {
-               ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d\n", p->subs[x].zfd);
+               ast_log(LOG_WARNING, "Unable to get channel number for pseudo channel on FD %d: %s\n", p->subs[x].zfd, strerror(errno));
                dahdi_close(p->subs[x].zfd);
                p->subs[x].zfd = -1;
                return -1;
@@ -1248,7 +1252,7 @@ static int dahdi_digit_begin(struct ast_channel *chan, char digit)
 
        if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].zfd, DAHDI_SENDTONE, &dtmf)) {
                int res;
-               DAHDI_DIAL_OPERATION zo = {
+               struct dahdi_dialoperation zo = {
                        .op = DAHDI_DIAL_OP_APPEND,
                };
 
@@ -1256,7 +1260,7 @@ static int dahdi_digit_begin(struct ast_channel *chan, char digit)
                zo.dialstr[1] = digit;
                zo.dialstr[2] = '\0';
                if ((res = ioctl(pvt->subs[SUB_REAL].zfd, DAHDI_DIAL, &zo)))
-                       ast_log(LOG_WARNING, "Couldn't dial digit %c\n", digit);
+                       ast_log(LOG_WARNING, "Couldn't dial digit %c: %s\n", digit, strerror(errno));
                else
                        pvt->dialing = 1;
        } else {
@@ -1346,7 +1350,7 @@ static struct {
 static char *alarm2str(int alarm)
 {
        int x;
-       for (x = 0; x < sizeof(alarms) / sizeof(alarms[0]); x++) {
+       for (x = 0; x < ARRAY_LEN(alarms); x++) {
                if (alarms[x].alarm & alarm)
                        return alarms[x].name;
        }
@@ -1356,7 +1360,7 @@ static char *alarm2str(int alarm)
 static char *event2str(int event)
 {
        static char buf[256];
-       if ((event < (sizeof(events) / sizeof(events[0]))) && (event > -1))
+       if ((event < (ARRAY_LEN(events))) && (event > -1))
                return events[event];
        sprintf(buf, "Event %d", event); /* safe */
        return buf;
@@ -1444,7 +1448,7 @@ static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index,
 {
        /* If the conference already exists, and we're already in it
           don't bother doing anything */
-       DAHDI_CONFINFO zi;
+       struct dahdi_confinfo zi;
        
        memset(&zi, 0, sizeof(zi));
        zi.chan = 0;
@@ -1467,7 +1471,7 @@ static int conf_add(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index,
        if (c->zfd < 0)
                return 0;
        if (ioctl(c->zfd, DAHDI_SETCONF, &zi)) {
-               ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d\n", c->zfd, zi.confmode, zi.confno);
+               ast_log(LOG_WARNING, "Failed to add %d to conference %d/%d: %s\n", c->zfd, zi.confmode, zi.confno, strerror(errno));
                return -1;
        }
        if (slavechannel < 1) {
@@ -1491,7 +1495,7 @@ static int isourconf(struct dahdi_pvt *p, struct dahdi_subchannel *c)
 
 static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
 {
-       DAHDI_CONFINFO zi;
+       struct dahdi_confinfo zi;
        if (/* Can't delete if there's no zfd */
                (c->zfd < 0) ||
                /* Don't delete from the conference if it's not our conference */
@@ -1503,7 +1507,7 @@ static int conf_del(struct dahdi_pvt *p, struct dahdi_subchannel *c, int index)
        zi.confno = 0;
        zi.confmode = 0;
        if (ioctl(c->zfd, DAHDI_SETCONF, &zi)) {
-               ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d\n", c->zfd, c->curconf.confmode, c->curconf.confno);
+               ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d: %s\n", c->zfd, c->curconf.confmode, c->curconf.confno, strerror(errno));
                return -1;
        }
        ast_debug(1, "Removed %d from conference %d/%d\n", c->zfd, c->curconf.confmode, c->curconf.confno);
@@ -1557,13 +1561,13 @@ static int isslavenative(struct dahdi_pvt *p, struct dahdi_pvt **out)
 
 static int reset_conf(struct dahdi_pvt *p)
 {
-       DAHDI_CONFINFO zi;
+       struct dahdi_confinfo zi;
        memset(&zi, 0, sizeof(zi));
        p->confno = -1;
        memset(&p->subs[SUB_REAL].curconf, 0, sizeof(p->subs[SUB_REAL].curconf));
        if (p->subs[SUB_REAL].zfd > -1) {
                if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_SETCONF, &zi))
-                       ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d!\n", p->channel);
+                       ast_log(LOG_WARNING, "Failed to reset conferencing on channel %d: %s\n", p->channel, strerror(errno));
        }
        return 0;
 }
@@ -1665,7 +1669,7 @@ static void dahdi_train_ec(struct dahdi_pvt *p)
                x = p->echotraining;
                res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_ECHOTRAIN, &x);
                if (res)
-                       ast_log(LOG_WARNING, "Unable to request echo training on channel %d\n", p->channel);
+                       ast_log(LOG_WARNING, "Unable to request echo training on channel %d: %s\n", p->channel, strerror(errno));
                else
                        ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
        } else {
@@ -1683,7 +1687,7 @@ static void dahdi_disable_ec(struct dahdi_pvt *p)
                res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_ECHOCANCEL_PARAMS, &ecp);
 
                if (res)
-                       ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d\n", p->channel);
+                       ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d: %s\n", p->channel, strerror(errno));
                else
                        ast_debug(1, "Disabled echo cancellation on channel %d\n", p->channel);
        }
@@ -1699,7 +1703,7 @@ static void fill_txgain(struct dahdi_gains *g, float gain, int law)
 
        switch (law) {
        case DAHDI_LAW_ALAW:
-               for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
+               for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
                        if (gain) {
                                k = (int) (((float) AST_ALAW(j)) * linear_gain);
                                if (k > 32767) k = 32767;
@@ -1711,7 +1715,7 @@ static void fill_txgain(struct dahdi_gains *g, float gain, int law)
                }
                break;
        case DAHDI_LAW_MULAW:
-               for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
+               for (j = 0; j < ARRAY_LEN(g->txgain); j++) {
                        if (gain) {
                                k = (int) (((float) AST_MULAW(j)) * linear_gain);
                                if (k > 32767) k = 32767;
@@ -1733,7 +1737,7 @@ static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
 
        switch (law) {
        case DAHDI_LAW_ALAW:
-               for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
+               for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
                        if (gain) {
                                k = (int) (((float) AST_ALAW(j)) * linear_gain);
                                if (k > 32767) k = 32767;
@@ -1745,7 +1749,7 @@ static void fill_rxgain(struct dahdi_gains *g, float gain, int law)
                }
                break;
        case DAHDI_LAW_MULAW:
-               for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
+               for (j = 0; j < ARRAY_LEN(g->rxgain); j++) {
                        if (gain) {
                                k = (int) (((float) AST_MULAW(j)) * linear_gain);
                                if (k > 32767) k = 32767;
@@ -1851,7 +1855,7 @@ static inline int dahdi_confmute(struct dahdi_pvt *p, int muted)
                y = 1;
                res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_AUDIOMODE, &y);
                if (res)
-                       ast_log(LOG_WARNING, "Unable to set audio mode on '%d'\n", p->channel);
+                       ast_log(LOG_WARNING, "Unable to set audio mode on %d: %s\n", p->channel, strerror(errno));
        }
        res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_CONFMUTE, &x);
        if (res < 0)
@@ -2100,7 +2104,7 @@ static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
        x = DAHDI_FLUSH_READ | DAHDI_FLUSH_WRITE;
        res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_FLUSH, &x);
        if (res)
-               ast_log(LOG_WARNING, "Unable to flush input on channel %d\n", p->channel);
+               ast_log(LOG_WARNING, "Unable to flush input on channel %d: %s\n", p->channel, strerror(errno));
        p->outgoing = 1;
 
        set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain, p->txgain, p->law);
@@ -2134,11 +2138,11 @@ static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
                        /* Choose proper cadence */
                        if ((p->distinctivering > 0) && (p->distinctivering <= num_cadence)) {
                                if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_SETCADENCE, &cadences[p->distinctivering - 1]))
-                                       ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s'\n", p->distinctivering, ast->name);
+                                       ast_log(LOG_WARNING, "Unable to set distinctive ring cadence %d on '%s': %s\n", p->distinctivering, ast->name, strerror(errno));
                                p->cidrings = cidrings[p->distinctivering - 1];
                        } else {
                                if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_SETCADENCE, NULL))
-                                       ast_log(LOG_WARNING, "Unable to reset default ring on '%s'\n", ast->name);
+                                       ast_log(LOG_WARNING, "Unable to reset default ring on '%s': %s\n", ast->name, strerror(errno));
                                p->cidrings = p->sendcalleridafter;
                        }
 
@@ -2314,9 +2318,11 @@ static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
                        p->echobreak = 0;
                if (!res) {
                        if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_DIAL, &p->dop)) {
+                               int saveerr = errno;
+
                                x = DAHDI_ONHOOK;
                                ioctl(p->subs[SUB_REAL].zfd, DAHDI_HOOK, &x);
-                               ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(errno));
+                               ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
                                ast_mutex_unlock(&p->lock);
                                return -1;
                        }
@@ -2960,7 +2966,7 @@ static int dahdi_hangup(struct ast_channel *ast)
        struct dahdi_pvt *p = ast->tech_pvt;
        struct dahdi_pvt *tmp = NULL;
        struct dahdi_pvt *prev = NULL;
-       DAHDI_PARAMS par;
+       struct dahdi_params par;
 
        ast_debug(1, "dahdi_hangup(%s)\n", ast->name);
        if (!ast->tech_pvt) {
@@ -3126,7 +3132,7 @@ static int dahdi_hangup(struct ast_channel *ast)
                law = DAHDI_LAW_DEFAULT;
                res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_SETLAW, &law);
                if (res < 0) 
-                       ast_log(LOG_WARNING, "Unable to set law on channel %d to default\n", p->channel);
+                       ast_log(LOG_WARNING, "Unable to set law on channel %d to default: %s\n", p->channel, strerror(errno));
                /* Perform low level hangup if no owner left */
 #ifdef HAVE_SS7
                if (p->ss7) {
@@ -3548,7 +3554,7 @@ static int dahdi_setoption(struct ast_channel *chan, int option, void *data, int
                        x = 1;
                }
                if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_AUDIOMODE, &x) == -1)
-                       ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", p->channel, x);
+                       ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, x, strerror(errno));
                break;
        case AST_OPTION_OPRMODE:  /* Operator services mode */
                oprmode = (struct oprmode *) data;
@@ -3682,16 +3688,13 @@ static void dahdi_link(struct dahdi_pvt *slave, struct dahdi_pvt *master) {
 
 static void disable_dtmf_detect(struct dahdi_pvt *p)
 {
-#ifdef DAHDI_TONEDETECT
        int val;
-#endif
 
        p->ignoredtmf = 1;
 
-#ifdef DAHDI_TONEDETECT
        val = 0;
        ioctl(p->subs[SUB_REAL].zfd, DAHDI_TONEDETECT, &val);
-#endif         
+
        if (!p->hardwaredtmf && p->dsp) {
                p->dsp_features &= ~DSP_FEATURE_DIGIT_DETECT;
                ast_dsp_set_features(p->dsp, p->dsp_features);
@@ -3700,19 +3703,16 @@ static void disable_dtmf_detect(struct dahdi_pvt *p)
 
 static void enable_dtmf_detect(struct dahdi_pvt *p)
 {
-#ifdef DAHDI_TONEDETECT
        int val;
-#endif
 
        if (p->channel == CHAN_PSEUDO)
                return;
 
        p->ignoredtmf = 0;
 
-#ifdef DAHDI_TONEDETECT
        val = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
        ioctl(p->subs[SUB_REAL].zfd, DAHDI_TONEDETECT, &val);
-#endif         
+
        if (!p->hardwaredtmf && p->dsp) {
                p->dsp_features |= DSP_FEATURE_DIGIT_DETECT;
                ast_dsp_set_features(p->dsp, p->dsp_features);
@@ -3749,9 +3749,7 @@ static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_ch
 
        ast_channel_lock(c0);
        while (ast_channel_trylock(c1)) {
-               ast_channel_unlock(c0);
-               usleep(1);
-               ast_channel_lock(c0);
+               CHANNEL_DEADLOCK_AVOIDANCE(c0);
        }
 
        p0 = c0->tech_pvt;
@@ -3921,9 +3919,7 @@ static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_ch
                
                ast_channel_lock(c0);
                while (ast_channel_trylock(c1)) {
-                       ast_channel_unlock(c0);
-                       usleep(1);
-                       ast_channel_lock(c0);
+                       CHANNEL_DEADLOCK_AVOIDANCE(c0);
                }
 
                p0 = c0->tech_pvt;
@@ -4087,18 +4083,6 @@ static int attempt_transfer(struct dahdi_pvt *p)
                if (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_RING) {
                        tone_zone_play_tone(p->subs[SUB_THREEWAY].zfd, DAHDI_TONE_RINGTONE);
                }
-               if (p->subs[SUB_REAL].owner->cdr) {
-                       /* Move CDR from second channel to current one */
-                       p->subs[SUB_THREEWAY].owner->cdr =
-                               ast_cdr_append(p->subs[SUB_THREEWAY].owner->cdr, p->subs[SUB_REAL].owner->cdr);
-                       p->subs[SUB_REAL].owner->cdr = NULL;
-               }
-               if (ast_bridged_channel(p->subs[SUB_REAL].owner)->cdr) {
-                       /* Move CDR from second channel's bridge to current one */
-                       p->subs[SUB_THREEWAY].owner->cdr =
-                               ast_cdr_append(p->subs[SUB_THREEWAY].owner->cdr, ast_bridged_channel(p->subs[SUB_REAL].owner)->cdr);
-                       ast_bridged_channel(p->subs[SUB_REAL].owner)->cdr = NULL;
-               }
                 if (ast_channel_masquerade(p->subs[SUB_THREEWAY].owner, ast_bridged_channel(p->subs[SUB_REAL].owner))) {
                        ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
                                        ast_bridged_channel(p->subs[SUB_REAL].owner)->name, p->subs[SUB_THREEWAY].owner->name);
@@ -4115,18 +4099,6 @@ static int attempt_transfer(struct dahdi_pvt *p)
                if (p->subs[SUB_REAL].owner->_state == AST_STATE_RING) {
                        tone_zone_play_tone(p->subs[SUB_REAL].zfd, DAHDI_TONE_RINGTONE);
                }
-               if (p->subs[SUB_THREEWAY].owner->cdr) {
-                       /* Move CDR from second channel to current one */
-                       p->subs[SUB_REAL].owner->cdr = 
-                               ast_cdr_append(p->subs[SUB_REAL].owner->cdr, p->subs[SUB_THREEWAY].owner->cdr);
-                       p->subs[SUB_THREEWAY].owner->cdr = NULL;
-               }
-               if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->cdr) {
-                       /* Move CDR from second channel's bridge to current one */
-                       p->subs[SUB_REAL].owner->cdr = 
-                               ast_cdr_append(p->subs[SUB_REAL].owner->cdr, ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->cdr);
-                       ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->cdr = NULL;
-               }
                if (ast_channel_masquerade(p->subs[SUB_REAL].owner, ast_bridged_channel(p->subs[SUB_THREEWAY].owner))) {
                        ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
                                        ast_bridged_channel(p->subs[SUB_THREEWAY].owner)->name, p->subs[SUB_REAL].owner->name);
@@ -4149,13 +4121,13 @@ static int attempt_transfer(struct dahdi_pvt *p)
 
 static int check_for_conference(struct dahdi_pvt *p)
 {
-       DAHDI_CONFINFO ci;
+       struct dahdi_confinfo ci;
        /* Fine if we already have a master, etc */
        if (p->master || (p->confno > -1))
                return 0;
        memset(&ci, 0, sizeof(ci));
        if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_GETCONF, &ci)) {
-               ast_log(LOG_WARNING, "Failed to get conference info on channel %d\n", p->channel);
+               ast_log(LOG_WARNING, "Failed to get conference info on channel %d: %s\n", p->channel, strerror(errno));
                return 0;
        }
        /* If we have no master and don't have a confno, then 
@@ -4176,14 +4148,18 @@ static int check_for_conference(struct dahdi_pvt *p)
 static int get_alarms(struct dahdi_pvt *p)
 {
        int res;
-       DAHDI_SPANINFO zi;
+       struct dahdi_spaninfo zi;
        struct dahdi_params params;
 
        memset(&zi, 0, sizeof(zi));
        zi.spanno = p->span;
+
        if ((res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_SPANSTAT, &zi)) >= 0) {
                if (zi.alarms != DAHDI_ALARM_NONE)
                        return zi.alarms;
+       } else {
+               ast_log(LOG_WARNING, "Unable to determine alarm on channel %d: %s\n", p->channel, strerror(errno));
+               return 0;
        }
 
        /* No alarms on the span. Check for channel alarms. */
@@ -4248,6 +4224,17 @@ static void dahdi_handle_dtmfup(struct ast_channel *ast, int index, struct ast_f
        }
 }
                        
+static void handle_alarms(struct dahdi_pvt *p, int alarms)
+{
+       const char *alarm_str = alarm2str(alarms);
+
+       ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm_str);
+       manager_event(EVENT_FLAG_SYSTEM, "Alarm",
+                     "Alarm: %s\r\n"
+                     "Channel: %d\r\n",
+                     alarm_str, p->channel);
+}
+
 static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
 {
        int res, x;
@@ -4309,12 +4296,10 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
        }
 
        switch (res) {
-#ifdef DAHDI_EVENT_EC_DISABLED
                case DAHDI_EVENT_EC_DISABLED:
                        ast_verb(3, "Channel %d echo canceler disabled due to CED detection\n", p->channel);
                        p->echocanon = 0;
                        break;
-#endif
                case DAHDI_EVENT_BITSCHANGED:
                        ast_log(LOG_WARNING, "Recieved bits changed on %s signalling?\n", sig2str(p->sig));
                case DAHDI_EVENT_PULSE_START:
@@ -4326,7 +4311,7 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
                        if (p->inalarm) break;
                        if ((p->radio || (p->oprmode < 0))) break;
                        if (ioctl(p->subs[index].zfd,DAHDI_DIALING,&x) == -1) {
-                               ast_debug(1, "DAHDI_DIALING ioctl failed on %s\n",ast->name);
+                               ast_log(LOG_DEBUG, "DAHDI_DIALING ioctl failed on %s: %s\n",ast->name, strerror(errno));
                                return NULL;
                        }
                        if (!x) { /* if not still dialing in driver */
@@ -4397,11 +4382,7 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
 #endif
                        p->inalarm = 1;
                        res = get_alarms(p);
-                       ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", p->channel, alarm2str(res));
-                       manager_event(EVENT_FLAG_SYSTEM, "Alarm",
-                                                               "Alarm: %s\r\n"
-                                                               "Channel: %d\r\n",
-                                                               alarm2str(res), p->channel);
+                       handle_alarms(p, res);
 #ifdef HAVE_PRI
                        if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
                                /* fall through intentionally */
@@ -4463,14 +4444,12 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
                                                   the private structure -- not especially easy or clean */
                                                while (p->subs[SUB_THREEWAY].owner && ast_channel_trylock(p->subs[SUB_THREEWAY].owner)) {
                                                        /* Yuck, didn't get the lock on the 3-way, gotta release everything and re-grab! */
-                                                       ast_mutex_unlock(&p->lock);
-                                                       ast_channel_unlock(ast);
-                                                       usleep(1);
+                                                       DLA_UNLOCK(&p->lock);
+                                                       CHANNEL_DEADLOCK_AVOIDANCE(ast);
                                                        /* We can grab ast and p in that order, without worry.  We should make sure
                                                           nothing seriously bad has happened though like some sort of bizarre double
                                                           masquerade! */
-                                                       ast_channel_lock(ast);
-                                                       ast_mutex_lock(&p->lock);
+                                                       DLA_LOCK(&p->lock);
                                                        if (p->owner != ast) {
                                                                ast_log(LOG_WARNING, "This isn't good...\n");
                                                                return NULL;
@@ -4576,9 +4555,11 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
                                } else
                                        p->echobreak = 0;
                                if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_DIAL, &p->dop)) {
+                                       int saveerr = errno;
+
                                        x = DAHDI_ONHOOK;
                                        ioctl(p->subs[SUB_REAL].zfd, DAHDI_HOOK, &x);
-                                       ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(errno));
+                                       ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
                                        return NULL;
                                        }
                                p->dialing = 1;
@@ -4612,7 +4593,7 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
                                                /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
                                                res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_DIAL, &p->dop);
                                                if (res < 0) {
-                                                       ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
+                                                       ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
                                                        p->dop.dialstr[0] = '\0';
                                                        return NULL;
                                                } else {
@@ -4705,7 +4686,6 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
                                ast_log(LOG_WARNING, "Don't know how to handle ring/off hook for signalling %d\n", p->sig);
                        }
                        break;
-#ifdef DAHDI_EVENT_RINGBEGIN
                case DAHDI_EVENT_RINGBEGIN:
                        switch (p->sig) {
                        case SIG_FXSLS:
@@ -4717,7 +4697,6 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
                                break;
                        }
                        break;
-#endif                 
                case DAHDI_EVENT_RINGEROFF:
                        if (p->inalarm) break;
                        if ((p->radio || (p->oprmode < 0))) break;
@@ -4858,7 +4837,19 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
                                                        dahdi_enable_ec(p);
                                                        ast_hangup(chan);
                                                } else {
+                                                       struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
+                                                       int way3bridge = 0, cdr3way = 0;
+                                                       
+                                                       if (!other) {
+                                                               other = ast_bridged_channel(p->subs[SUB_REAL].owner);
+                                                       } else
+                                                               way3bridge = 1;
+                                                       
+                                                       if (p->subs[SUB_THREEWAY].owner->cdr)
+                                                               cdr3way = 1;
+                                                       
                                                        ast_verb(3, "Started three way call on channel %d\n", p->channel);
+
                                                        /* Start music on hold if appropriate */
                                                        if (ast_bridged_channel(p->subs[SUB_THREEWAY].owner)) {
                                                                ast_queue_control_data(p->subs[SUB_THREEWAY].owner, AST_CONTROL_HOLD,
@@ -4889,6 +4880,16 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
                                                if (((ast->pbx) || (ast->_state == AST_STATE_UP)) && 
                                                    (p->transfertobusy || (ast->_state != AST_STATE_BUSY))) {
                                                        int otherindex = SUB_THREEWAY;
+                                                       struct ast_channel *other = ast_bridged_channel(p->subs[SUB_THREEWAY].owner);
+                                                       int way3bridge = 0, cdr3way = 0;
+                                                       
+                                                       if (!other) {
+                                                               other = ast_bridged_channel(p->subs[SUB_REAL].owner);
+                                                       } else
+                                                               way3bridge = 1;
+                                                       
+                                                       if (p->subs[SUB_THREEWAY].owner->cdr)
+                                                               cdr3way = 1;
 
                                                        ast_verb(3, "Building conference on call on %s and %s\n", p->subs[SUB_THREEWAY].owner->name, p->subs[SUB_REAL].owner->name);
                                                        /* Put them in the threeway, and flip */
@@ -4965,7 +4966,7 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
                                if (!ast_strlen_zero(p->dop.dialstr)) {
                                        res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_DIAL, &p->dop);
                                        if (res < 0) {
-                                               ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
+                                               ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
                                                p->dop.dialstr[0] = '\0';
                                                return NULL;
                                        } else 
@@ -4994,7 +4995,7 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
                                if (!ast_strlen_zero(p->dop.dialstr)) {
                                        res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_DIAL, &p->dop);
                                        if (res < 0) {
-                                               ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
+                                               ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
                                                p->dop.dialstr[0] = '\0';
                                                return NULL;
                                        } else 
@@ -5190,10 +5191,11 @@ static struct ast_frame  *dahdi_read(struct ast_channel *ast)
        int index;
        void *readbuf;
        struct ast_frame *f;
-       
 
-       ast_mutex_lock(&p->lock);
-       
+       while (ast_mutex_trylock(&p->lock)) {
+               CHANNEL_DEADLOCK_AVOIDANCE(ast);
+       }
+
        index = dahdi_get_index(ast, p, 0);
        
        /* Hang up if we don't really exist */
@@ -5218,7 +5220,7 @@ static struct ast_frame  *dahdi_read(struct ast_channel *ast)
        /* make sure it sends initial key state as first frame */
        if ((p->radio || (p->oprmode < 0)) && (!p->firstradio))
        {
-               DAHDI_PARAMS ps;
+               struct dahdi_params ps;
 
                ps.channo = p->channel;
                if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_GET_PARAMS, &ps) < 0) {
@@ -5820,7 +5822,7 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb
        int features;
        struct ast_str *chan_name;
        struct ast_variable *v;
-       DAHDI_PARAMS ps;
+       struct dahdi_params ps;
        if (i->subs[index].owner) {
                ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
                return NULL;
@@ -5850,7 +5852,7 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb
        ps.channo = i->channel;
        res = ioctl(i->subs[SUB_REAL].zfd, DAHDI_GET_PARAMS, &ps);
        if (res) {
-               ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW\n");
+               ast_log(LOG_WARNING, "Unable to get parameters, assuming MULAW: %s\n", strerror(errno));
                ps.curlaw = DAHDI_LAW_MULAW;
        }
        if (ps.curlaw == DAHDI_LAW_ALAW)
@@ -5882,18 +5884,14 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb
                    (i->outgoing && (i->callprogress & CALLPROGRESS_FAX_OUTGOING))) {
                        features |= DSP_FEATURE_FAX_DETECT;
                }
-#ifdef DAHDI_TONEDETECT
                x = DAHDI_TONEDETECT_ON | DAHDI_TONEDETECT_MUTE;
                if (ioctl(i->subs[index].zfd, DAHDI_TONEDETECT, &x)) {
-#endif         
                        i->hardwaredtmf = 0;
                        features |= DSP_FEATURE_DIGIT_DETECT;
-#ifdef DAHDI_TONEDETECT
                } else if (NEED_MFDETECT(i)) {
                        i->hardwaredtmf = 1;
                        features |= DSP_FEATURE_DIGIT_DETECT;
                }
-#endif
        }
        if (features) {
                if (i->dsp) {
@@ -5904,12 +5902,13 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb
                        else
                                i->dsp = NULL;
                        if (i->dsp) {
-                               i->dsp_features = features & ~DSP_PROGRESS_TALK;
+                               i->dsp_features = features;
 #if defined(HAVE_PRI) || defined(HAVE_SS7)
                                /* We cannot do progress detection until receives PROGRESS message */
                                if (i->outgoing && ((i->sig == SIG_PRI) || (i->sig == SIG_BRI) || (i->sig == SIG_BRI_PTMP) || (i->sig == SIG_SS7))) {
                                        /* Remember requested DSP features, don't treat
                                           talking as ANSWER */
+                                       i->dsp_features = features & ~DSP_PROGRESS_TALK;
                                        features = 0;
                                }
 #endif
@@ -5986,7 +5985,7 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb
        /* Configure the new channel jb */
        ast_jb_configure(tmp, &global_jbconf);
 
-       ast_device_state_changed_literal(tmp->name);
+       ast_devstate_changed_literal(ast_state_chan2dev(state), tmp->name);
 
        for (v = i->vars ; v ; v = v->next)
                 pbx_builtin_setvar_helper(tmp, v->name, v->value);
@@ -6795,7 +6794,7 @@ static void *ss_thread(void *data)
                                        samples = 0;
 #if 1
                                        bump_gains(p);
-#endif                         
+#endif
                                        /* Take out of linear mode for Caller*ID processing */
                                        dahdi_setlinear(p->subs[index].zfd, 0);
                                        
@@ -6813,12 +6812,10 @@ static void *ss_thread(void *data)
                                                        ast_log(LOG_NOTICE, "Got event %d (%s)...\n", res, event2str(res));
 
                                                        if (p->cid_signalling == CID_SIG_V23_JP) {
-#ifdef DAHDI_EVENT_RINGBEGIN
                                                                if (res == DAHDI_EVENT_RINGBEGIN) {
                                                                        res = dahdi_set_hook(p->subs[SUB_REAL].zfd, DAHDI_OFFHOOK);
                                                                        usleep(1);
                                                                }
-#endif
                                                        } else {
                                                                res = 0;
                                                                break;
@@ -6875,7 +6872,11 @@ static void *ss_thread(void *data)
                                                        ast_hangup(chan);
                                                        return NULL;
                                                } 
-                                               f = ast_read(chan);
+                                               if (!(f = ast_read(chan))) {
+                                                       ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
+                                                       ast_hangup(chan);
+                                                       return NULL;
+                                               }
                                                ast_frfree(f);
                                                if (chan->_state == AST_STATE_RING ||
                                                    chan->_state == AST_STATE_RINGING) 
@@ -6888,7 +6889,7 @@ static void *ss_thread(void *data)
                                                len = 0;
                                                distMatches = 0;
                                                /* Clear the current ring data array so we dont have old data in it. */
-                                               for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
+                                               for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
                                                        curRingData[receivedRingT] = 0;
                                                receivedRingT = 0;
                                                counter = 0;
@@ -6919,7 +6920,7 @@ static void *ss_thread(void *data)
                                                                        break;
                                                                /* Increment the ringT counter so we can match it against
                                                                   values in chan_dahdi.conf for distinctive ring */
-                                                               if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
+                                                               if (++receivedRingT == ARRAY_LEN(curRingData))
                                                                        break;
                                                        } else if (i & DAHDI_IOMUX_READ) {
                                                                res = read(p->subs[index].zfd, buf, sizeof(buf));
@@ -7037,7 +7038,7 @@ static void *ss_thread(void *data)
                                len = 0;
                                distMatches = 0;
                                /* Clear the current ring data array so we dont have old data in it. */
-                               for (receivedRingT = 0; receivedRingT < (sizeof(curRingData) / sizeof(curRingData[0])); receivedRingT++)
+                               for (receivedRingT = 0; receivedRingT < ARRAY_LEN(curRingData); receivedRingT++)
                                        curRingData[receivedRingT] = 0;
                                receivedRingT = 0;
                                counter = 0;
@@ -7078,7 +7079,7 @@ static void *ss_thread(void *data)
                                                        break;
                                                /* Increment the ringT counter so we can match it against
                                                   values in chan_dahdi.conf for distinctive ring */
-                                               if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
+                                               if (++receivedRingT == ARRAY_LEN(curRingData))
                                                        break;
                                        } else if (i & DAHDI_IOMUX_READ) {
                                                res = read(p->subs[index].zfd, buf, sizeof(buf));
@@ -7139,7 +7140,7 @@ static void *ss_thread(void *data)
                                                                break;
                                                        /* Increment the ringT counter so we can match it against
                                                           values in chan_dahdi.conf for distinctive ring */
-                                                       if (++receivedRingT == (sizeof(curRingData) / sizeof(curRingData[0])))
+                                                       if (++receivedRingT == ARRAY_LEN(curRingData))
                                                                break;
                                                } else if (i & DAHDI_IOMUX_READ) {
                                                        res = read(p->subs[index].zfd, buf, sizeof(buf));
@@ -7222,6 +7223,18 @@ static void *ss_thread(void *data)
 
                if (cs)
                        callerid_free(cs);
+               /* If the CID had Message waiting payload, assume that this for MWI only and hangup the call */
+               if (flags & CID_MSGWAITING) {
+                       ast_log(LOG_NOTICE, "MWI: Channel %d message waiting!\n", p->channel);
+                       notify_message(p->mailbox, 1);
+                       ast_hangup(chan);
+                       return NULL;
+               } else if (flags & CID_NOMSGWAITING) {
+                       ast_log(LOG_NOTICE, "MWI: Channel %d no message waiting!\n", p->channel);
+                       notify_message(p->mailbox, 0);
+                       ast_hangup(chan);
+                       return NULL;
+               }
 
                ast_setstate(chan, AST_STATE_RING);
                chan->rings = 1;
@@ -7304,10 +7317,8 @@ static void *mwi_thread(void *data)
                        res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].zfd);
 
                        switch (res) {
-#ifdef HAVE_DAHDI_NEONMWI
                        case DAHDI_EVENT_NEONMWI_ACTIVE:
                        case DAHDI_EVENT_NEONMWI_INACTIVE:
-#endif
                        case DAHDI_EVENT_NONE:
                        case DAHDI_EVENT_BITSCHANGED:
                                break;
@@ -7320,11 +7331,7 @@ static void *mwi_thread(void *data)
                        case DAHDI_EVENT_ALARM:
                                mtd->pvt->inalarm = 1;
                                res = get_alarms(mtd->pvt);
-                               ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", mtd->pvt->channel, alarm2str(res));
-                               manager_event(EVENT_FLAG_SYSTEM, "Alarm",
-                                       "Alarm: %s\r\n"
-                                       "Channel: %d\r\n",
-                                       alarm2str(res), mtd->pvt->channel);
+                               handle_alarms(mtd->pvt, res);
                                break; /* What to do on channel alarm ???? -- fall thru intentionally?? */
                        default:
                                ast_log(LOG_NOTICE, "Got event %d (%s)...  Passing along to ss_thread\n", res, event2str(res));
@@ -7406,6 +7413,160 @@ quit_no_clean:
        return NULL;
 }
 
+/* States for sending MWI message
+ * First three states are required for send Ring Pulse Alert Signal 
+ */
+enum mwisend_states {
+       MWI_SEND_SA,
+ MWI_SEND_SA_WAIT,
+ MWI_SEND_PAUSE,
+ MWI_SEND_SPILL,
+ MWI_SEND_CLEANUP,
+ MWI_SEND_DONE
+};
+
+static void *mwi_send_thread(void *data)
+{
+       struct mwi_thread_data *mtd = data;
+       struct timeval timeout_basis, pause, now;
+       int x, i, res;
+       int num_read;
+       enum mwisend_states mwi_send_state = MWI_SEND_SPILL; /*Assume FSK only */
+
+       /* Determine how this spill is to be sent */
+       if(mwisend_rpas) {
+               mwi_send_state = MWI_SEND_SA;
+       }
+
+       gettimeofday(&timeout_basis, NULL);
+       
+       mtd->pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
+       if (!mtd->pvt->cidspill) {
+               mtd->pvt->mwisendactive = 0;
+               ast_free(mtd);
+               return NULL;
+       }
+       x = DAHDI_FLUSH_BOTH;
+       res = ioctl(mtd->pvt->subs[SUB_REAL].zfd, DAHDI_FLUSH, &x);
+       x = 3000;
+       ioctl(mtd->pvt->subs[SUB_REAL].zfd, DAHDI_ONHOOKTRANSFER, &x);
+       mtd->pvt->cidlen = vmwi_generate(mtd->pvt->cidspill, has_voicemail(mtd->pvt), CID_MWI_TYPE_MDMF_FULL,
+                                                                        AST_LAW(mtd->pvt), mtd->pvt->cid_name, mtd->pvt->cid_num, 0);
+       mtd->pvt->cidpos = 0;
+
+       while (MWI_SEND_DONE != mwi_send_state) {
+               num_read = 0;
+               gettimeofday(&now, NULL);
+               if ( 10 < (now.tv_sec - timeout_basis.tv_sec)) {
+                       ast_log(LOG_WARNING, "MWI Send TIMEOUT in state %d\n", mwi_send_state);
+                       goto quit;
+               }
+
+               i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
+               if ((res = ioctl(mtd->pvt->subs[SUB_REAL].zfd, DAHDI_IOMUX, &i))) {
+                       ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
+                       goto quit;
+               }
+
+               if (i & DAHDI_IOMUX_SIGEVENT) {
+                       /* If we get an event, screen out events that we do not act on.
+                       * Otherwise, let handle_init_event determine what is needed
+                       */
+                       res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].zfd);
+                       switch (res) {
+                               case DAHDI_EVENT_RINGEROFF:
+                                       if(mwi_send_state == MWI_SEND_SA_WAIT) {
+                                               if (dahdi_set_hook(mtd->pvt->subs[SUB_REAL].zfd, DAHDI_RINGOFF) ) {
+                                                       ast_log(LOG_WARNING, "Unable to finsh RP-AS: %s\n", strerror(errno));
+                                                       goto quit;
+                                               }
+                                               mwi_send_state = MWI_SEND_PAUSE;
+                                               gettimeofday(&pause, NULL);
+                                       }
+                                       break;
+                               case DAHDI_EVENT_RINGERON:
+                               case DAHDI_EVENT_HOOKCOMPLETE:
+                                       break;
+                               default:
+                                       /* Got to the default init event handler */
+                                       if (0 < handle_init_event(mtd->pvt, res)) {
+                                               /* I've spawned a thread, get out */
+                                               goto quit;
+                                       }
+                                       break;
+                       }
+               } else if (i & DAHDI_IOMUX_READ) {
+                       if ((num_read = read(mtd->pvt->subs[SUB_REAL].zfd, mtd->buf, sizeof(mtd->buf))) < 0) {
+                               if (errno != ELAST) {
+                                       ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
+                                       goto quit;
+                               }
+                               break;
+                       }
+               }
+               /* Perform mwi send action */
+               switch ( mwi_send_state) {
+                       case MWI_SEND_SA:
+                               /* Send the Ring Pulse Signal Alert */
+                               res = ioctl(mtd->pvt->subs[SUB_REAL].zfd, DAHDI_SETCADENCE, &AS_RP_cadence);
+                               if (res) {
+                                       ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
+                                       goto quit;
+                               }
+                               dahdi_set_hook(mtd->pvt->subs[SUB_REAL].zfd, DAHDI_RING);
+                               mwi_send_state = MWI_SEND_SA_WAIT;
+                               break;
+                               case MWI_SEND_SA_WAIT:  /* do nothing until I get RINGEROFF event */
+                                       break;
+                                       case MWI_SEND_PAUSE:  /* Wait between alert and spill - min of 500 mS*/
+                                               gettimeofday(&now, NULL);
+                                               if ((int)(now.tv_sec - pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pause.tv_usec > 500000) {
+                                                       mwi_send_state = MWI_SEND_SPILL;
+                                               }
+                                               break;
+                       case MWI_SEND_SPILL:
+                               /* We read some number of bytes.  Write an equal amount of data */
+                               if(0 < num_read) {
+                                       if (num_read > mtd->pvt->cidlen - mtd->pvt->cidpos)
+                                               num_read = mtd->pvt->cidlen - mtd->pvt->cidpos;
+                                       res = write(mtd->pvt->subs[SUB_REAL].zfd, mtd->pvt->cidspill + mtd->pvt->cidpos, num_read);
+                                       if (res > 0) {
+                                               mtd->pvt->cidpos += res;
+                                               if (mtd->pvt->cidpos >= mtd->pvt->cidlen) {
+                                                       ast_free(mtd->pvt->cidspill);
+                                                       mtd->pvt->cidspill = NULL;
+                                                       mtd->pvt->cidpos = 0;
+                                                       mtd->pvt->cidlen = 0;
+                                                       mwi_send_state = MWI_SEND_CLEANUP;
+                                               }
+                                       } else {
+                                               ast_log(LOG_WARNING, "MWI Send Write failed: %s\n", strerror(errno));
+                                               goto quit;
+                                       }
+                               }
+                               break;
+                       case MWI_SEND_CLEANUP:
+                               /* For now, do nothing */
+                               mwi_send_state = MWI_SEND_DONE;
+                               break;
+                       default:
+                               /* Should not get here, punt*/
+                               goto quit;
+                               break;
+               }
+       }
+quit:
+               if(mtd->pvt->cidspill) {
+       ast_free(mtd->pvt->cidspill);
+       mtd->pvt->cidspill = NULL;
+               }
+               mtd->pvt->mwisendactive = 0;
+               ast_free(mtd);
+
+               return NULL;
+}
+
+
 /* destroy a DAHDI channel, identified by its number */
 static int dahdi_destroy_channel_bynum(int channel)
 {
@@ -7424,9 +7585,11 @@ static int dahdi_destroy_channel_bynum(int channel)
        return RESULT_FAILURE;
 }
 
+/* returns < 0 = error, 0 event handled, >0 event handled and thread spawned */
 static int handle_init_event(struct dahdi_pvt *i, int event)
 {
        int res;
+       int thread_spawned = 0;
        pthread_t threadid;
        struct ast_channel *chan;
 
@@ -7480,6 +7643,8 @@ static int handle_init_event(struct dahdi_pvt *i, int event)
                                                if (res < 0)
                                                        ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
                                                ast_hangup(chan);
+                                       } else {
+                                               thread_spawned = 1;
                                        }
                                } else
                                        ast_log(LOG_WARNING, "Unable to create channel\n");
@@ -7505,22 +7670,26 @@ static int handle_init_event(struct dahdi_pvt *i, int event)
                case SIG_SF_FEATDMF:
                case SIG_SF_FEATB:
                case SIG_SF:
-                               /* Check for callerid, digits, etc */
-                               if (i->cid_start == CID_START_POLARITY_IN) {
-                                       chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
-                               } else {
-                                       chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
-                               }
-                               if (chan && ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
-                                       ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
-                                       res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, DAHDI_TONE_CONGESTION);
-                                       if (res < 0)
-                                               ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
-                                       ast_hangup(chan);
-                               } else if (!chan) {
-                                       ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
+                       /* Check for callerid, digits, etc */
+                       if (i->cid_start == CID_START_POLARITY_IN) {
+                               chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
+                       } else {
+                               chan = dahdi_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
+                       }
+
+                       if (!chan) {
+                               ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
+                       } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
+                               ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
+                               res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, DAHDI_TONE_CONGESTION);
+                               if (res < 0) {
+                                       ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", i->channel);
                                }
-                               break;
+                               ast_hangup(chan);
+                       } else  {
+                               thread_spawned = 1;
+                       }
+                       break;
                default:
                        ast_log(LOG_WARNING, "Don't know how to handle ring/answer with signalling %s on channel %d\n", sig2str(i->sig), i->channel);
                        res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, DAHDI_TONE_CONGESTION);
@@ -7538,11 +7707,7 @@ static int handle_init_event(struct dahdi_pvt *i, int event)
        case DAHDI_EVENT_ALARM:
                i->inalarm = 1;
                res = get_alarms(i);
-               ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", i->channel, alarm2str(res));
-               manager_event(EVENT_FLAG_SYSTEM, "Alarm",
-                       "Alarm: %s\r\n"
-                       "Channel: %d\r\n",
-                       alarm2str(res), i->channel);
+               handle_alarms(i, res);
                /* fall thru intentionally */
        case DAHDI_EVENT_ONHOOK:
                if (i->radio)
@@ -7615,8 +7780,12 @@ static int handle_init_event(struct dahdi_pvt *i, int event)
                                            "CID detection on channel %d\n",
                                            i->channel);
                                chan = dahdi_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
-                               if (chan && ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
+                               if (!chan) {
+                                       ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", i->channel);
+                               } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
                                        ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
+                               } else {
+                                       thread_spawned = 1;
                                }
                        }
                        break;
@@ -7632,7 +7801,6 @@ static int handle_init_event(struct dahdi_pvt *i, int event)
                                i->channel);
                dahdi_destroy_channel_bynum(i->channel);
                break;
-#ifdef HAVE_DAHDI_NEONMWI
        case DAHDI_EVENT_NEONMWI_ACTIVE:
                if (i->mwimonitor_neon) {
                        notify_message(i->mailbox, 1);
@@ -7645,9 +7813,8 @@ static int handle_init_event(struct dahdi_pvt *i, int event)
                        ast_log(LOG_NOTICE, "NEON MWI cleared for channel %d, mailbox %s\n", i->channel, i->mailbox);
                }
                break;
-#endif
        }
-       return 0;
+       return thread_spawned;
 }
 
 static void *do_monitor(void *data)
@@ -7692,7 +7859,7 @@ static void *do_monitor(void *data)
                i = iflist;
                while (i) {
                        if ((i->subs[SUB_REAL].zfd > -1) && i->sig && (!i->radio)) {
-                               if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive) {
+                               if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive && !i->mwisendactive) {
                                        /* This needs to be watched, as it lacks an owner */
                                        pfds[count].fd = i->subs[SUB_REAL].zfd;
                                        pfds[count].events = POLLPRI;
@@ -7732,29 +7899,31 @@ static void *do_monitor(void *data)
                                if (!found && ((i == last) || ((i == iflist) && !last))) {
                                        last = i;
                                        if (last) {
-                                               if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
-                                                       (last->sig & __DAHDI_SIG_FXO)) {
+                                               if (!last->mwisendactive &&      last->sig & __DAHDI_SIG_FXO) {
                                                        res = has_voicemail(last);
                                                        if (last->msgstate != res) {
-                                                               int x;
-                                                               ast_debug(1, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
-#ifdef DAHDI_VMWI
+
+                                                               /* This channel has a new voicemail state,
+                                                               * initiate a thread to send an MWI message
+                                                               */
+                                                               pthread_attr_t attr;
+                                                               pthread_t threadid;
+                                                               struct mwi_thread_data *mtd;
                                                                res2 = ioctl(last->subs[SUB_REAL].zfd, DAHDI_VMWI, res);
-                                                               if (res2)
-                                                                       ast_log(LOG_DEBUG, "Unable to control message waiting led on channel %d\n", last->channel);
-#endif
-                                                               x = DAHDI_FLUSH_BOTH;
-                                                               res2 = ioctl(last->subs[SUB_REAL].zfd, DAHDI_FLUSH, &x);
-                                                               if (res2)
-                                                                       ast_log(LOG_WARNING, "Unable to flush input on channel %d\n", last->channel);
-                                                               if ((last->cidspill = ast_calloc(1, MAX_CALLERID_SIZE))) {
-                                                                       /* Turn on on hook transfer for 4 seconds */
-                                                                       x = 4000;
-                                                                       ioctl(last->subs[SUB_REAL].zfd, DAHDI_ONHOOKTRANSFER, &x);
-                                                                       last->cidlen = vmwi_generate(last->cidspill, res, 1, AST_LAW(last));
-                                                                       last->cidpos = 0;
+                                                               if (res2) {
+                                                                       ast_log(LOG_DEBUG, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
+                                                               }
+                                                               pthread_attr_init(&attr);
+                                                               pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+                                                               if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
                                                                        last->msgstate = res;
-                                                                       last->onhooktime = thispass;
+                                                                       mtd->pvt = last;
+                                                                       last->mwisendactive = 1;
+                                                                       if (ast_pthread_create_background(&threadid, &attr, mwi_send_thread, mtd)) {
+                                                                               ast_log(LOG_WARNING, "Unable to start mwi send thread on channel %d\n", last->channel);
+                                                                               ast_free(mtd);
+                                                                               last->mwisendactive = 0;
+                                                                       }
                                                                }
                                                                found ++;
                                                        }
@@ -7816,23 +7985,6 @@ static void *do_monitor(void *data)
                                                                        i->mwimonitoractive = 1;
                                                                }
                                                        }
-                                               } else if (i->cidspill) {
-                                                       /* We read some number of bytes.  Write an equal amount of data */
-                                                       if (res > i->cidlen - i->cidpos) 
-                                                               res = i->cidlen - i->cidpos;
-                                                       res2 = write(i->subs[SUB_REAL].zfd, i->cidspill + i->cidpos, res);
-                                                       if (res2 > 0) {
-                                                               i->cidpos += res2;
-                                                               if (i->cidpos >= i->cidlen) {
-                                                                       free(i->cidspill);
-                                                                       i->cidspill = 0;
-                                                                       i->cidpos = 0;
-                                                                       i->cidlen = 0;
-                                                               }
-                                                       } else {
-                                                               ast_log(LOG_WARNING, "Write failed: %s\n", strerror(errno));
-                                                               i->msgstate = -1;
-                                                       }
                                                }
                                        } else {
                                                ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
@@ -7915,11 +8067,19 @@ static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spa
                        ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
                        *span = -1;
                } else {
-                       if (si->totalchans == 31) { /* if it's an E1 */
+                       if (si->totalchans == 31) {
+                               /* E1 */
                                pris[*span].dchannels[0] = 16 + offset;
-                       } else { /* T1 or BRI: D Channel is the last Channel */
-                               pris[*span].dchannels[0] = 
-                                       si->totalchans + offset;
+                       } else if (si->totalchans == 24) {
+                               /* T1 or J1 */
+                               pris[*span].dchannels[0] = 24 + offset;
+                       } else if (si->totalchans == 3) {
+                               /* BRI */
+                               pris[*span].dchannels[0] = 3 + offset;
+                       } else {
+                               ast_log(LOG_WARNING, "Unable to use span %d, since the D-channel cannot be located (unexpected span size of %d channels)\n", *span, si->totalchans);
+                               *span = -1;
+                               return 0;
                        }
                        pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
                        pris[*span].offset = offset;
@@ -7932,7 +8092,7 @@ static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spa
 static int pri_create_trunkgroup(int trunkgroup, int *channels)
 {
        struct dahdi_spaninfo si;
-       DAHDI_PARAMS p;
+       struct dahdi_params p;
        int fd;
        int span;
        int ospan=0;
@@ -7964,7 +8124,7 @@ static int pri_create_trunkgroup(int trunkgroup, int *channels)
                        return -1;
                }
                if (ioctl(fd, DAHDI_SPANSTAT, &si)) {
-                       ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d)\n", channels[y], p.spanno);
+                       ast_log(LOG_WARNING, "Failed go get span information on channel %d (span %d): %s\n", channels[y], p.spanno, strerror(errno));
                        dahdi_close(fd);
                        return -1;
                }
@@ -8045,10 +8205,7 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
        /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
        struct dahdi_pvt *tmp = NULL, *tmp2,  *prev = NULL;
        char fn[80];
-#if 1
        struct dahdi_bufferinfo bi;
-#endif
-       struct dahdi_spaninfo si;
 
        int res;
        int span = 0;
@@ -8056,7 +8213,7 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
        int x;
        struct dahdi_pvt **wlist;
        struct dahdi_pvt **wend;
-       DAHDI_PARAMS p;
+       struct dahdi_params p;
 
        wlist = &iflist;
        wend = &ifend;
@@ -8115,14 +8272,14 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
                                memset(&p, 0, sizeof(p));
                                res = ioctl(tmp->subs[SUB_REAL].zfd, DAHDI_GET_PARAMS, &p);
                                if (res < 0) {
-                                       ast_log(LOG_ERROR, "Unable to get parameters\n");
+                                       ast_log(LOG_ERROR, "Unable to get parameters: %s\n", strerror(errno));
                                        destroy_dahdi_pvt(&tmp);
                                        return NULL;
                                }
                                if (conf->is_sig_auto)
                                        chan_sig = sigtype_to_signalling(p.sigtype);
-                               if (p.sigtype != (conf->chan.sig & 0x3ffff)) {
-                                       ast_log(LOG_ERROR, "Signalling requested on channel %d is %s but line is in %s signalling\n", channel, sig2str(conf->chan.sig), sig2str(p.sigtype));
+                               if (p.sigtype != (chan_sig & 0x3ffff)) {
+                                       ast_log(LOG_ERROR, "Signalling requested on channel %d is %s but line is in %s signalling\n", channel, sig2str(chan_sig), sig2str(p.sigtype));
                                        destroy_dahdi_pvt(&tmp);
                                        return NULL;
                                }
@@ -8178,13 +8335,13 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
                        }
 #endif
 #ifdef HAVE_PRI
-                       if ((conf->chan.sig == SIG_PRI) || (conf->chan.sig == SIG_BRI) || (conf->chan.sig == SIG_BRI_PTMP) || (conf->chan.sig == SIG_GR303FXOKS) || (conf->chan.sig == SIG_GR303FXSKS)) {
+                       if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
                                int offset;
                                int myswitchtype;
                                int matchesdchan;
                                int x,y;
                                offset = 0;
-                               if (((conf->chan.sig == SIG_PRI) || (conf->chan.sig == SIG_BRI) || (conf->chan.sig == SIG_BRI_PTMP)) 
+                               if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP)) 
                                                && ioctl(tmp->subs[SUB_REAL].zfd, DAHDI_AUDIOMODE, &offset)) {
                                        ast_log(LOG_ERROR, "Unable to set clear mode on clear channel %d of span %d: %s\n", channel, p.spanno, strerror(errno));
                                        destroy_dahdi_pvt(&tmp);
@@ -8195,6 +8352,7 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
                                        destroy_dahdi_pvt(&tmp);
                                        return NULL;
                                } else {
+                                       struct dahdi_spaninfo si;
                                        si.spanno = 0;
                                        if (ioctl(tmp->subs[SUB_REAL].zfd,DAHDI_SPANSTAT,&si) == -1) {
                                                ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
@@ -8209,9 +8367,9 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
                                                destroy_dahdi_pvt(&tmp);
                                                return NULL;
                                        }
-                                       if ((conf->chan.sig == SIG_PRI) ||
-                                                       (conf->chan.sig == SIG_BRI) ||
-                                                       (conf->chan.sig == SIG_BRI_PTMP))
+                                       if ((chan_sig == SIG_PRI) ||
+                                                       (chan_sig == SIG_BRI) ||
+                                                       (chan_sig == SIG_BRI_PTMP))
                                                myswitchtype = conf->pri.switchtype;
                                        else
                                                myswitchtype = PRI_SWITCH_GR303_TMC;
@@ -8269,7 +8427,7 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
                                                        return NULL;
                                                }
 
-                                               pris[span].sig = conf->chan.sig;
+                                               pris[span].sig = chan_sig;
                                                pris[span].nodetype = conf->pri.nodetype;
                                                pris[span].switchtype = myswitchtype;
                                                pris[span].nsf = conf->pri.nsf;
@@ -8279,6 +8437,9 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
                                                pris[span].minunused = conf->pri.minunused;
                                                pris[span].minidle = conf->pri.minidle;
                                                pris[span].overlapdial = conf->pri.overlapdial;
+#ifdef HAVE_PRI_INBANDDISCONNECT
+                                               pris[span].inbanddisconnect = conf->pri.inbanddisconnect;
+#endif
                                                pris[span].facilityenable = conf->pri.facilityenable;
                                                ast_copy_string(pris[span].idledial, conf->pri.idledial, sizeof(pris[span].idledial));
                                                ast_copy_string(pris[span].idleext, conf->pri.idleext, sizeof(pris[span].idleext));
@@ -8365,7 +8526,7 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
                {
                        res = ioctl(tmp->subs[SUB_REAL].zfd, DAHDI_SET_PARAMS, &p);
                        if (res < 0) {
-                               ast_log(LOG_ERROR, "Unable to set parameters\n");
+                               ast_log(LOG_ERROR, "Unable to set parameters: %s\n", strerror(errno));
                                destroy_dahdi_pvt(&tmp);
                                return NULL;
                        }
@@ -8375,20 +8536,20 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
                        memset(&bi, 0, sizeof(bi));
                        res = ioctl(tmp->subs[SUB_REAL].zfd, DAHDI_GET_BUFINFO, &bi);
                        if (!res) {
-                               bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
-                               bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
-                               bi.numbufs = numbufs;
+                               bi.txbufpolicy = conf->chan.buf_policy;
+                               bi.rxbufpolicy = conf->chan.buf_policy;
+                               bi.numbufs = conf->chan.buf_no;
                                res = ioctl(tmp->subs[SUB_REAL].zfd, DAHDI_SET_BUFINFO, &bi);
                                if (res < 0) {
-                                       ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d\n", channel);
+                                       ast_log(LOG_WARNING, "Unable to set buffer policy on channel %d: %s\n", channel, strerror(errno));
                                }
                        } else
-                               ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d\n", channel);
+                               ast_log(LOG_WARNING, "Unable to check buffer policy on channel %d: %s\n", channel, strerror(errno));
                }
 #endif
                tmp->immediate = conf->chan.immediate;
                tmp->transfertobusy = conf->chan.transfertobusy;
-               if (conf->chan.sig & __DAHDI_SIG_FXS) {
+               if (chan_sig & __DAHDI_SIG_FXS) {
                        tmp->mwimonitor_fsk = conf->chan.mwimonitor_fsk;
                        tmp->mwimonitor_neon = conf->chan.mwimonitor_neon;
                }
@@ -8526,16 +8687,11 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
                        /* the dchannel is down so put the channel in alarm */
                        if (tmp->pri && !pri_is_up(tmp->pri))
                                tmp->inalarm = 1;
-                       else
-                               tmp->inalarm = 0;
 #endif                         
-                       memset(&si, 0, sizeof(si));
-                       if (ioctl(tmp->subs[SUB_REAL].zfd,DAHDI_SPANSTAT,&si) == -1) {
-                               ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
-                               destroy_dahdi_pvt(&tmp);
-                               return NULL;
+                       if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
+                               tmp->inalarm = 1;
+                               handle_alarms(tmp, res);
                        }
-                       if (si.alarms) tmp->inalarm = 1;
                }
 
                tmp->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
@@ -8544,7 +8700,7 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
                tmp->sendcalleridafter = conf->chan.sendcalleridafter;
                if (!here) {
                        tmp->locallyblocked = tmp->remotelyblocked = 0;
-                       if ((conf->chan.sig == SIG_PRI) || (conf->chan.sig == SIG_BRI) || (conf->chan.sig == SIG_BRI_PTMP) || (conf->chan.sig == SIG_SS7))
+                       if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7))
                                tmp->inservice = 0;
                        else /* We default to in service on protocols that don't have a reset */
                                tmp->inservice = 1;
@@ -8600,7 +8756,7 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
 {
        int res;
-       DAHDI_PARAMS par;
+       struct dahdi_params par;
 
        /* First, check group matching */
        if (groupmatch) {
@@ -8662,7 +8818,7 @@ static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t g
                                par.rxisoffhook = 0;
                        }
                        if (res) {
-                               ast_log(LOG_WARNING, "Unable to check hook state on channel %d\n", p->channel);
+                               ast_log(LOG_WARNING, "Unable to check hook state on channel %d: %s\n", p->channel, strerror(errno));
                        } else if ((p->sig == SIG_FXSKS) || (p->sig == SIG_FXSGS)) {
                                /* When "onhook" that means no battery on the line, and thus
                                  it is out of service..., if it's on a TDM card... If it's a channel
@@ -8672,11 +8828,7 @@ static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t g
                                if (par.rxisoffhook)
                                        return 1;
                                else
-#ifdef DAHDI_CHECK_HOOKSTATE
                                        return 0;
-#else
-                                       return 1;
-#endif
                        } else if (par.rxisoffhook) {
                                ast_debug(1, "Channel %d off hook, can't use\n", p->channel);
                                /* Not available when the other end is off hook */
@@ -8716,7 +8868,7 @@ static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t g
 static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
 {
        struct dahdi_pvt *p;
-       DAHDI_BUFFERINFO bi;
+       struct dahdi_bufferinfo bi;
        int res;
        
        if ((p = ast_malloc(sizeof(*p)))) {
@@ -8731,15 +8883,15 @@ static struct dahdi_pvt *chandup(struct dahdi_pvt *src)
                }
                res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_GET_BUFINFO, &bi);
                if (!res) {
-                       bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
-                       bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
-                       bi.numbufs = numbufs;
+                       bi.txbufpolicy = src->buf_policy;
+                       bi.rxbufpolicy = src->buf_policy;
+                       bi.numbufs = src->buf_no;
                        res = ioctl(p->subs[SUB_REAL].zfd, DAHDI_SET_BUFINFO, &bi);
                        if (res < 0) {
-                               ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel\n");
+                               ast_log(LOG_WARNING, "Unable to set buffer policy on dup channel: %s\n", strerror(errno));
                        }
                } else
-                       ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel\n");
+                       ast_log(LOG_WARNING, "Unable to check buffer policy on dup channel: %s\n", strerror(errno));
        }
        p->destroy = 1;
        p->next = iflist;
@@ -9110,7 +9262,7 @@ static void dahdi_loopback(struct dahdi_pvt *p, int enable)
 {
        if (p->loopedback != enable) {
                if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_LOOPBACK, &enable)) {
-                       ast_log(LOG_WARNING, "Unable to set loopback on channel %d\n", p->channel);
+                       ast_log(LOG_WARNING, "Unable to set loopback on channel %d: %s\n", p->channel, strerror(errno));
                        return;
                }
                p->loopedback = enable;
@@ -9127,7 +9279,7 @@ static void ss7_start_call(struct dahdi_pvt *p, struct dahdi_ss7 *linkset)
        char tmp[256];
 
        if (ioctl(p->subs[SUB_REAL].zfd, DAHDI_AUDIOMODE, &law) == -1)
-               ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", p->channel, law);
+               ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, law, strerror(errno));
        
        if (linkset->type == SS7_ITU)
                law = DAHDI_LAW_ALAW;
@@ -9138,8 +9290,10 @@ static void ss7_start_call(struct dahdi_pvt *p, struct dahdi_ss7 *linkset)
        if (res < 0) 
                ast_log(LOG_WARNING, "Unable to set law on channel %d\n", p->channel);
        
-       p->proceeding = 1;
-       isup_acm(ss7, p->ss7call);
+       if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) {
+               p->proceeding = 1;
+               isup_acm(ss7, p->ss7call);
+       }
 
        ast_mutex_unlock(&linkset->lock);
        c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0);
@@ -9378,7 +9532,10 @@ static void *ss7_linkset(void *data)
                                }
                                break;
                        case MTP2_LINK_UP:
-                               ast_debug(1, "MTP2 link up\n");
+                               ast_verbose("MTP2 link up (SLC %d)\n", e->gen.data);
+                               break;
+                       case MTP2_LINK_DOWN:
+                               ast_log(LOG_WARNING, "MTP2 link down (SLC %d)\n", e->gen.data);
                                break;
                        case ISUP_EVENT_CPG:
                                chanpos = ss7_find_cic(linkset, e->cpg.cic, e->cpg.opc);
@@ -9835,7 +9992,7 @@ static int pri_find_principle(struct dahdi_pri *pri, int channel)
        int x;
        int span = PRI_SPAN(channel);
        int spanfd;
-       DAHDI_PARAMS param;
+       struct dahdi_params param;
        int principle = -1;
        int explicit = PRI_EXPLICIT(channel);
        channel = PRI_CHANNEL(channel);
@@ -10629,7 +10786,7 @@ static void *pri_dchannel(void *vpri)
                                                        /* Set to audio mode at this point */
                                                        law = 1;
                                                        if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].zfd, DAHDI_AUDIOMODE, &law) == -1)
-                                                               ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", pri->pvts[chanpos]->channel, law);
+                                                               ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
                                                }
                                                if (e->ring.layer1 == PRI_LAYER_1_ALAW)
                                                        law = DAHDI_LAW_ALAW;
@@ -10944,7 +11101,7 @@ static void *pri_dchannel(void *vpri)
                                                        /* Send any "w" waited stuff */
                                                        res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].zfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
                                                        if (res < 0) {
-                                                               ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", pri->pvts[chanpos]->channel);
+                                                               ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
                                                                pri->pvts[chanpos]->dop.dialstr[0] = '\0';
                                                        } else
                                                                ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
@@ -11243,8 +11400,8 @@ static void *pri_dchannel(void *vpri)
 static int start_pri(struct dahdi_pri *pri)
 {
        int res, x;
-       DAHDI_PARAMS p;
-       DAHDI_BUFFERINFO bi;
+       struct dahdi_params p;
+       struct dahdi_bufferinfo bi;
        struct dahdi_spaninfo si;
        int i;
        
@@ -11267,7 +11424,7 @@ static int start_pri(struct dahdi_pri *pri)
                if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC)) {
                        dahdi_close(pri->fds[i]);
                        pri->fds[i] = -1;
-                       ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.  See /etc/dahdi.conf\n", x);
+                       ast_log(LOG_ERROR, "D-channel %d is not in HDLC/FCS mode.\n", x);
                        return -1;
                }
                memset(&si, 0, sizeof(si));
@@ -11286,7 +11443,7 @@ static int start_pri(struct dahdi_pri *pri)
                bi.numbufs = 32;
                bi.bufsize = 1024;
                if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
-                       ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d\n", x);
+                       ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
                        dahdi_close(pri->fds[i]);
                        pri->fds[i] = -1;
                        return -1;
@@ -11305,6 +11462,9 @@ static int start_pri(struct dahdi_pri *pri)
                if (pri->switchtype == PRI_SWITCH_GR303_TMC)
                        pri->overlapdial |= DAHDI_OVERLAPDIAL_BOTH;
                pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)?1:0);
+#ifdef HAVE_PRI_INBANDDISCONNECT
+               pri_set_inbanddisconnect(pri->dchans[i], pri->inbanddisconnect);
+#endif
                /* Enslave to master if appropriate */
                if (i)
                        pri_enslave(pri->dchans[0], pri->dchans[i]);
@@ -11724,24 +11884,6 @@ static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_
        return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
 }
 
-static char *handle_cli_zap_destroy_channel_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
-       switch (cmd) {
-       case CLI_INIT:
-               e->command = "zap destroy channel";
-               e->usage = 
-                       "Usage: zap destroy channel <chan num>\n"
-                       "       DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
-               return NULL;
-       case CLI_GENERATE:
-               return NULL;
-       case CLI_HANDLER:
-               return dahdi_destroy_channel(e, cmd, a);
-       }
-
-       return CLI_FAILURE;
-}
-
 static int setup_dahdi(int reload);
 static int dahdi_restart(void)
 {
@@ -11782,27 +11924,6 @@ static char *dahdi_restart_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_
        return CLI_SUCCESS;
 }
 
-static char *handle_cli_zap_restart_cmd_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
-       switch (cmd) {
-       case CLI_INIT:
-               e->command = "zap restart";
-               e->usage = 
-                       "Usage: zap restart\n"
-                       "       Restarts the zap channels: destroys them all and then\n"
-                       "       re-reads them from chan_dahdi.conf.\n"
-                       "       Note that this will STOP any running CALL on zap channels.\n"
-                       "";
-               return NULL;
-       case CLI_GENERATE:
-               return NULL;
-       case CLI_HANDLER:
-               return dahdi_restart_cmd(e, cmd, a);
-       }
-
-       return CLI_FAILURE;
-}
-
 static int action_dahdirestart(struct mansession *s, const struct message *m)
 {
        if (dahdi_restart() != 0) {
@@ -11937,31 +12058,12 @@ static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cl
 #undef FORMAT2
 }
 
-static char *handle_cli_zap_show_channels_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
-       switch (cmd) {
-    case CLI_INIT:
-        e->command = "zap show channels [trunkgroup|group|context]";
-        e->usage =
-            "Usage: zap show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
-            "   Shows a list of available channels with optional filtering\n"
-            "   <group> must be a number between 0 and 63\n";
-        return NULL;
-    case CLI_GENERATE:
-        return NULL;
-       case CLI_HANDLER:
-               return dahdi_show_channels(e, cmd, a);
-    }
-
-       return CLI_FAILURE;
-}
-
 static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        int channel;
        struct dahdi_pvt *tmp = NULL;
-       DAHDI_CONFINFO ci;
-       DAHDI_PARAMS ps;
+       struct dahdi_confinfo ci;
+       struct dahdi_params ps;
        int x;
        ast_mutex_t *lock;
        struct dahdi_pvt *start;
@@ -12111,13 +12213,11 @@ static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli
                                if (!ioctl(tmp->subs[SUB_REAL].zfd, DAHDI_GETCONF, &ci)) {
                                        ast_cli(a->fd, "Actual Confinfo: Num/%d, Mode/0x%04x\n", ci.confno, ci.confmode);
                                }
-#ifdef DAHDI_GETCONFMUTE
                                if (!ioctl(tmp->subs[SUB_REAL].zfd, DAHDI_GETCONFMUTE, &x)) {
                                        ast_cli(a->fd, "Actual Confmute: %s\n", x ? "Yes" : "No");
                                }
-#endif
                                if (ioctl(tmp->subs[SUB_REAL].zfd, DAHDI_GET_PARAMS, &ps) < 0) {
-                                       ast_log(LOG_WARNING, "Failed to get parameters on channel %d\n", tmp->channel);
+                                       ast_log(LOG_WARNING, "Failed to get parameters on channel %d: %s\n", tmp->channel, strerror(errno));
                                } else {
                                        ast_cli(a->fd, "Hookstate (FXS only): %s\n", ps.rxisoffhook ? "Offhook" : "Onhook");
                                }
@@ -12133,24 +12233,6 @@ static char *dahdi_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli
        return CLI_FAILURE;
 }
 
-static char *handle_cli_zap_show_channel_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
-       switch (cmd) {
-       case CLI_INIT:
-               e->command = "zap show channel";
-               e->usage = 
-                       "Usage: zap show channel <chan num>\n"
-                       "       Detailed information about a given channel\n";
-               return NULL;
-       case CLI_GENERATE:
-               return NULL;    
-       case CLI_HANDLER:
-               return dahdi_show_channel(e, cmd, a);
-       }
-
-       return CLI_FAILURE;
-}
-
 static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        int i, j;
@@ -12187,40 +12269,17 @@ static char *handle_dahdi_show_cadences(struct ast_cli_entry *e, int cmd, struct
        return CLI_SUCCESS;
 }
 
-static char *handle_cli_zap_show_cadences_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
-       switch(cmd) {
-       case CLI_INIT:
-               e->command = "zap show cadences";
-               e->usage = 
-                       "Usage: zap show cadences\n"
-                       "               Shows all cadences currently defined\n";
-               return NULL;
-       case CLI_GENERATE:
-               return NULL;
-       case CLI_HANDLER:
-               return handle_dahdi_show_cadences(e, cmd, a);
-       }
-
-       return CLI_FAILURE;
-}
-
 /* Based on irqmiss.c */
 static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) 
 {
-#ifdef DAHDI_SPANINFO_HAS_LINECONFIG
        #define FORMAT "%-40.40s %-7.7s %-6d %-6d %-6d %-3.3s %-4.4s %-8.8s %s\n"
        #define FORMAT2 "%-40.40s %-7.7s %-6.6s %-6.6s %-6.6s %-3.3s %-4.4s %-8.8s %s\n"
-#else
-       #define FORMAT "%-40.40s %-10.10s %-10d %-10d %-10d\n"
-       #define FORMAT2 "%-40.40s %-10.10s %-10.10s %-10.10s %-10.10s\n"
-#endif
        int span;
        int res;
        char alarms[50];
 
        int ctl;
-       DAHDI_SPANINFO s;
+       struct dahdi_spaninfo s;
 
        switch (cmd) {
        case CLI_INIT:
@@ -12237,11 +12296,7 @@ static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_
                ast_cli(a->fd, "No DAHDI found. Unable to open /dev/dahdi/ctl: %s\n", strerror(errno));
                return CLI_FAILURE;
        }
-       ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4"
-#ifdef DAHDI_SPANINFO_HAS_LINECONFIG
-                       , "Framing", "Coding", "Options", "LBO"
-#endif
-               );
+       ast_cli(a->fd, FORMAT2, "Description", "Alarms", "IRQ", "bpviol", "CRC4", "Framing", "Coding", "Options", "LBO");
 
        for (span = 1; span < DAHDI_MAX_SPANS; ++span) {
                s.spanno = span;
@@ -12277,7 +12332,6 @@ static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_
                }
 
                ast_cli(a->fd, FORMAT, s.desc, alarms, s.irqmisses, s.bpvcount, s.crc4count
-#ifdef DAHDI_SPANINFO_HAS_LINECONFIG
                                , s.lineconfig & DAHDI_CONFIG_D4 ? "D4" :
                                  s.lineconfig & DAHDI_CONFIG_ESF ? "ESF" :
                                  s.lineconfig & DAHDI_CONFIG_CCS ? "CCS" :
@@ -12289,7 +12343,6 @@ static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_
                                , s.lineconfig & DAHDI_CONFIG_CRC4 ?
                                  s.lineconfig & DAHDI_CONFIG_NOTOPEN ? "CRC4/YEL" : "CRC4" : "YEL"
                                , lbostr[s.lbo]
-#endif
                        );
        }
        close(ctl);
@@ -12299,24 +12352,6 @@ static char *dahdi_show_status(struct ast_cli_entry *e, int cmd, struct ast_cli_
 #undef FORMAT2
 }
 
-static char *handle_cli_zap_show_status_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
-       switch (cmd) {
-       case CLI_INIT:
-               e->command = "zap show status";
-               e->usage = 
-                       "Usage: zap show status\n"
-                       "       Shows a list of zap cards with status\n";
-               return NULL;
-       case CLI_GENERATE:
-               return NULL;    
-       case CLI_HANDLER:
-               return dahdi_show_status(e, cmd, a);
-       }
-
-       return CLI_FAILURE;
-}
-
 static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        int pseudo_fd = -1;
@@ -12341,7 +12376,7 @@ static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli
        strcpy(vi.echo_canceller, "Unknown");
 
        if (ioctl(pseudo_fd, DAHDI_GETVERSION, &vi))
-               ast_cli(a->fd, "Failed to get version from control file.\n");
+               ast_cli(a->fd, "Failed to get DAHDI version: %s\n", strerror(errno));
        else
                ast_cli(a->fd, "DAHDI Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
 
@@ -12350,24 +12385,6 @@ static char *dahdi_show_version(struct ast_cli_entry *e, int cmd, struct ast_cli
        return CLI_SUCCESS;
 }
 
-static char *handle_cli_zap_show_version_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
-       switch (cmd) {
-       case CLI_INIT:
-               e->command = "zap show version";
-               e->usage = 
-                       "Usage: zap show version\n"
-                       "       Shows the zap version in use\n";
-               return NULL;
-       case CLI_GENERATE:
-               return NULL;
-       case CLI_HANDLER:
-               return dahdi_show_version(e, cmd, a);
-       }
-
-       return CLI_FAILURE;
-}
-
 static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        int channel;
@@ -12418,7 +12435,7 @@ static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_a
                hwgain.newgain = gain;
                hwgain.tx = tx;
                if (ioctl(tmp->subs[SUB_REAL].zfd, DAHDI_SET_HWGAIN, &hwgain) < 0) {
-                       ast_cli(a->fd, "Unable to set the hardware gain for channel %d\n", channel);
+                       ast_cli(a->fd, "Unable to set the hardware gain for channel %d: %s\n", channel, strerror(errno));
                        ast_mutex_unlock(&iflock);
                        return CLI_FAILURE;
                }
@@ -12437,29 +12454,6 @@ static char *dahdi_set_hwgain(struct ast_cli_entry *e, int cmd, struct ast_cli_a
 
 }
 
-static char *handle_cli_zap_set_hwgain_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
-       switch (cmd) {
-       case CLI_INIT:
-               e->command = "zap set hwgain";
-               e->usage = 
-                       "Usage: zap set hwgain <rx|tx> <chan#> <gain>\n"
-                       "       Sets the hardware gain on a a given channel, overriding the\n"
-                       "   value provided at module loadtime, whether the channel is in\n"
-                       "   use or not.  Changes take effect immediately.\n"
-                       "   <rx|tx> which direction do you want to change (relative to our module)\n"
-                       "   <chan num> is the channel number relative to the device\n"
-                       "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
-               return NULL;
-       case CLI_GENERATE:
-               return NULL;    
-       case CLI_HANDLER:
-               return dahdi_set_hwgain(e, cmd, a);
-       }
-
-       return CLI_FAILURE;
-}
-
 static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        int channel;
@@ -12534,29 +12528,6 @@ static char *dahdi_set_swgain(struct ast_cli_entry *e, int cmd, struct ast_cli_a
 
 }
 
-static char *handle_cli_zap_set_swgain_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
-       switch (cmd) {
-       case CLI_INIT:
-               e->command = "zap set swgain";
-               e->usage = 
-                       "Usage: zap set swgain <rx|tx> <chan#> <gain>\n"
-                       "       Sets the software gain on a a given channel, overriding the\n"
-                       "   value provided at module loadtime, whether the channel is in\n"
-                       "   use or not.  Changes take effect immediately.\n"
-                       "   <rx|tx> which direction do you want to change (relative to our module)\n"
-                       "   <chan num> is the channel number relative to the device\n"
-                       "   <gain> is the gain in dB (e.g. -3.5 for -3.5dB)\n";
-               return NULL;
-       case CLI_GENERATE:
-               return NULL;    
-       case CLI_HANDLER:
-               return dahdi_set_swgain(e, cmd, a);
-       }
-
-       return CLI_FAILURE;
-}
-
 static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        int channel;
@@ -12614,50 +12585,17 @@ static char *dahdi_set_dnd(struct ast_cli_entry *e, int cmd, struct ast_cli_args
        return CLI_SUCCESS;
 }
 
-static char *handle_cli_zap_set_dnd_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
-{
-       switch (cmd) {
-       case CLI_INIT:
-               e->command = "zap set dnd";
-               e->usage = 
-                       "Usage: zap set dnd <chan#> <on|off>\n"
-                       "   Sets/resets DND (Do Not Disturb) mode on a channel.\n"
-                       "   Changes take effect immediately.\n"
-                       "   <chan num> is the channel number\n"
-                       "   <on|off> Enable or disable DND mode?\n"
-                       ;
-               return NULL;
-       case CLI_GENERATE:
-               return NULL;
-       case CLI_HANDLER:
-               return dahdi_set_dnd(e, cmd, a);
-       }
-
-       return CLI_FAILURE;
-}
-
-static struct ast_cli_entry cli_zap_show_cadences_deprecated = AST_CLI_DEFINE(handle_cli_zap_show_cadences_deprecated, "List cadences");
-static struct ast_cli_entry cli_zap_show_channels_deprecated = AST_CLI_DEFINE(handle_cli_zap_show_channels_deprecated, "Show active channels");
-static struct ast_cli_entry cli_zap_show_channel_deprecated = AST_CLI_DEFINE(handle_cli_zap_show_channel_deprecated, "Show information on a channel");
-static struct ast_cli_entry cli_zap_destroy_channel_deprecated = AST_CLI_DEFINE(handle_cli_zap_destroy_channel_deprecated, "Destroy a channel");
-static struct ast_cli_entry cli_zap_restart_cmd_deprecated = AST_CLI_DEFINE(handle_cli_zap_restart_cmd_deprecated, "Fully restart channels");
-static struct ast_cli_entry cli_zap_show_status_deprecated = AST_CLI_DEFINE(handle_cli_zap_show_status_deprecated, "Show all cards status");
-static struct ast_cli_entry cli_zap_show_version_deprecated = AST_CLI_DEFINE(handle_cli_zap_show_version_deprecated, "Show DAHDI version in use");
-static struct ast_cli_entry cli_zap_set_hwgain_deprecated = AST_CLI_DEFINE(handle_cli_zap_set_hwgain_deprecated, "Set hardware gain on a channel");
-static struct ast_cli_entry cli_zap_set_swgain_deprecated = AST_CLI_DEFINE(handle_cli_zap_set_swgain_deprecated, "Set software gain on a channel");
-static struct ast_cli_entry cli_zap_set_dnd_deprecated = AST_CLI_DEFINE(handle_cli_zap_set_dnd_deprecated, "Set software gain on a channel");
-
 static struct ast_cli_entry dahdi_cli[] = {
-       AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences", .deprecate_cmd = &cli_zap_show_cadences_deprecated),
-       AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels", .deprecate_cmd = &cli_zap_show_channels_deprecated),
-       AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel", .deprecate_cmd = &cli_zap_show_channel_deprecated),
-       AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel", .deprecate_cmd = &cli_zap_destroy_channel_deprecated),
-       AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels", .deprecate_cmd = &cli_zap_restart_cmd_deprecated),
-       AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status", .deprecate_cmd = &cli_zap_show_status_deprecated),
-       AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use", .deprecate_cmd = &cli_zap_show_version_deprecated),
-       AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel", .deprecate_cmd = &cli_zap_set_hwgain_deprecated),
-       AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel", .deprecate_cmd = &cli_zap_set_swgain_deprecated),
-       AST_CLI_DEFINE(dahdi_set_dnd, "Set software gain on a channel", .deprecate_cmd = &cli_zap_set_dnd_deprecated),
+       AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
+       AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
+       AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
+       AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
+       AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
+       AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
+       AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
+       AST_CLI_DEFINE(dahdi_set_hwgain, "Set hardware gain on a channel"),
+       AST_CLI_DEFINE(dahdi_set_swgain, "Set software gain on a channel"),
+       AST_CLI_DEFINE(dahdi_set_dnd, "Set software gain on a channel"),
 };
 
 #define TRANSFER       0
@@ -12975,8 +12913,8 @@ static int linkset_addsigchan(int sigchan)
        struct dahdi_ss7 *link;
        int res;
        int curfd;
-       DAHDI_PARAMS p;
-       DAHDI_BUFFERINFO bi;
+       struct dahdi_params p;
+       struct dahdi_bufferinfo bi;
        struct dahdi_spaninfo si;
 
 
@@ -13032,7 +12970,7 @@ static int linkset_addsigchan(int sigchan)
                if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) {
                        dahdi_close(link->fds[curfd]);
                        link->fds[curfd] = -1;
-                       ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.  See /etc/dahdi.conf\n", sigchan);
+                       ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
                        return -1;
                }
 
@@ -13042,13 +12980,17 @@ static int linkset_addsigchan(int sigchan)
                bi.bufsize = 512;
 
                if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
-                       ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d\n", sigchan);
+                       ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno));
                        dahdi_close(link->fds[curfd]);
                        link->fds[curfd] = -1;
                        return -1;
                }
 
-               ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDI, link->fds[curfd]);
+               if (p.sigtype == DAHDI_SIG_MTP2)
+                       ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd]);
+               else
+                       ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd]);
+
                link->numsigchans++;
 
                memset(&si, 0, sizeof(si));
@@ -13208,6 +13150,51 @@ static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_c
        else
                ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
 
+       /* Break poll on the linkset so it sends our messages */
+       pthread_kill(linksets[linkset-1].master, SIGURG);
+
+       return CLI_SUCCESS;
+}
+
+static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+       int linkset;
+       int i;
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "ss7 block linkset";
+               e->usage = 
+                       "Usage: ss7 block linkset <linkset number>\n"
+                       "       Sends a remote blocking request for all CICs on the given linkset\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
+       }
+       if (a->argc == 4)
+               linkset = atoi(a->argv[3]);
+       else
+               return CLI_SHOWUSAGE;
+
+       if ((linkset < 1) || (linkset > NUM_SPANS)) {
+               ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
+               return CLI_SUCCESS;
+       }
+
+       if (!linksets[linkset-1].ss7) {
+               ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
+               return CLI_SUCCESS;
+       }
+
+       for (i = 0; i < linksets[linkset-1].numchans; i++) {
+               ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
+               ast_mutex_lock(&linksets[linkset-1].lock);
+               isup_blo(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
+               ast_mutex_unlock(&linksets[linkset-1].lock);
+       }
+
+       /* Break poll on the linkset so it sends our messages */
+       pthread_kill(linksets[linkset-1].master, SIGURG);
+
        return CLI_SUCCESS;
 }
 
@@ -13261,6 +13248,53 @@ static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast
 
        if (blocked > 0)
                ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
+
+       /* Break poll on the linkset so it sends our messages */
+       pthread_kill(linksets[linkset-1].master, SIGURG);
+
+       return CLI_SUCCESS;
+}
+
+static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+       int linkset;
+       int i;
+       switch (cmd) {
+       case CLI_INIT:
+               e->command = "ss7 unblock linkset";
+               e->usage = 
+                       "Usage: ss7 unblock linkset <linkset number>\n"
+                       "       Sends a remote unblocking request for all CICs on the specified linkset\n";
+               return NULL;
+       case CLI_GENERATE:
+               return NULL;
+       }
+
+       if (a->argc == 4)
+               linkset = atoi(a->argv[3]);
+       else
+               return CLI_SHOWUSAGE;
+
+       if ((linkset < 1) || (linkset > NUM_SPANS)) {
+               ast_cli(a->fd, "Invalid linkset %s.  Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
+               return CLI_SUCCESS;
+       }
+
+       if (!linksets[linkset-1].ss7) {
+               ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
+               return CLI_SUCCESS;
+       }
+
+       for (i = 0; i < linksets[linkset-1].numchans; i++) {
+               ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].pvts[i]->cic);
+               ast_mutex_lock(&linksets[linkset-1].lock);
+               isup_ubl(linksets[linkset-1].ss7, linksets[linkset-1].pvts[i]->cic, linksets[linkset-1].pvts[i]->dpc);
+               ast_mutex_unlock(&linksets[linkset-1].lock);
+       }
+
+       /* Break poll on the linkset so it sends our messages */
+       pthread_kill(linksets[linkset-1].master, SIGURG);
+
        return CLI_SUCCESS;
 }
 
@@ -13316,8 +13350,10 @@ static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli
 static struct ast_cli_entry dahdi_ss7_cli[] = {
        AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"), 
        AST_CLI_DEFINE(handle_ss7_no_debug, "Disables SS7 debugging on a linkset"), 
-       AST_CLI_DEFINE(handle_ss7_block_cic, "Disables SS7 debugging on a linkset"),
-       AST_CLI_DEFINE(handle_ss7_unblock_cic, "Disables SS7 debugging on a linkset"),
+       AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
+       AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
+       AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
+       AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
        AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
        AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
 };
@@ -13438,7 +13474,7 @@ static void process_echocancel(struct dahdi_chan_conf *confp, const char *data,
        unsigned int param_count;
        unsigned int x;
 
-       if (!(param_count = ast_app_separate_args(parse, ',', params, sizeof(params) / sizeof(params[0]))))
+       if (!(param_count = ast_app_separate_args(parse, ',', params, ARRAY_LEN(params))))
                return;
 
        memset(&confp->chan.echocancel, 0, sizeof(confp->chan.echocancel));
@@ -13490,7 +13526,6 @@ static void process_echocancel(struct dahdi_chan_conf *confp, const char *data,
 static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct ast_variable *v, int reload, int options)
 {
        struct dahdi_pvt *tmp;
-       const char *ringc; /* temporary string for parsing the dring number. */
        int y;
        int found_pseudo = 0;
        char dahdichan[MAX_CHANLIST_LEN] = {};
@@ -13516,6 +13551,26 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
                        iscrv = !strcasecmp(v->name, "crv");
                        if (build_channels(confp, iscrv, v->value, reload, v->lineno, &found_pseudo))
                                        return -1;
+               } else if (!strcasecmp(v->name, "buffers")) {
+                       int res;
+                       char policy[8] = "";
+                       res = sscanf(v->value, "%d,%s", &confp->chan.buf_no, policy);
+                       if (res != 2) {
+                               ast_log(LOG_WARNING, "Parsing buffers option data failed, using defaults.\n");
+                               confp->chan.buf_no = numbufs;
+                               continue;
+                       }
+                       if (confp->chan.buf_no < 0)
+                               confp->chan.buf_no = numbufs;
+                       if (!strcasecmp(policy, "full")) {
+                               confp->chan.buf_policy = DAHDI_POLICY_WHEN_FULL;
+                       } else if (!strcasecmp(policy, "half")) {
+                               confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE /*HALF_FULL*/;
+                       } else if (!strcasecmp(policy, "immediate")) {
+                               confp->chan.buf_policy = DAHDI_POLICY_IMMEDIATE;
+                       } else {
+                               ast_log(LOG_WARNING, "Invalid policy name given (%s).\n", policy);
+                       }
                } else if (!strcasecmp(v->name, "dahdichan")) {
                        ast_copy_string(dahdichan, v->value, sizeof(dahdichan));
                } else if (!strcasecmp(v->name, "usedistinctiveringdetection")) {
@@ -13535,14 +13590,11 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
                } else if (!strcasecmp(v->name, "dring3range")) {
                        confp->chan.drings.ringnum[2].range = atoi(v->value);
                } else if (!strcasecmp(v->name, "dring1")) {
-                       ringc = v->value;
-                       sscanf(ringc, "%d,%d,%d", &confp->chan.drings.ringnum[0].ring[0], &confp->chan.drings.ringnum[0].ring[1], &confp->chan.drings.ringnum[0].ring[2]);
+                       sscanf(v->value, "%d,%d,%d", &confp->chan.drings.ringnum[0].ring[0], &confp->chan.drings.ringnum[0].ring[1], &confp->chan.drings.ringnum[0].ring[2]);
                } else if (!strcasecmp(v->name, "dring2")) {
-                       ringc = v->value;
-                       sscanf(ringc,"%d,%d,%d", &confp->chan.drings.ringnum[1].ring[0], &confp->chan.drings.ringnum[1].ring[1], &confp->chan.drings.ringnum[1].ring[2]);
+                       sscanf(v->value,"%d,%d,%d", &confp->chan.drings.ringnum[1].ring[0], &confp->chan.drings.ringnum[1].ring[1], &confp->chan.drings.ringnum[1].ring[2]);
                } else if (!strcasecmp(v->name, "dring3")) {
-                       ringc = v->value;
-                       sscanf(ringc, "%d,%d,%d", &confp->chan.drings.ringnum[2].ring[0], &confp->chan.drings.ringnum[2].ring[1], &confp->chan.drings.ringnum[2].ring[2]);
+                       sscanf(v->value, "%d,%d,%d", &confp->chan.drings.ringnum[2].ring[0], &confp->chan.drings.ringnum[2].ring[1], &confp->chan.drings.ringnum[2].ring[2]);
                } else if (!strcasecmp(v->name, "usecallerid")) {
                        confp->chan.use_callerid = ast_true(v->value);
                } else if (!strcasecmp(v->name, "cidsignalling")) {
@@ -13745,7 +13797,13 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
                        confp->chan.sendcalleridafter = atoi(v->value);
                } else if (!strcasecmp(v->name, "mwimonitornotify")) {
                        ast_copy_string(mwimonitornotify, v->value, sizeof(mwimonitornotify));
-               } else if (!reload){ 
+               } else if (!strcasecmp(v->name, "mwisendtype")) {
+                       if (!strcasecmp(v->value, "rpas")) { /* Ring Pulse Alert Signal */
+                               mwisend_rpas = 1;
+                       } else {
+                               mwisend_rpas = 0;
+                       }
+               } else if (!reload){
                         if (!strcasecmp(v->name, "signalling") || !strcasecmp(v->name, "signaling")) {
                                int orig_radio = confp->chan.radio;
                                int orig_outsigmod = confp->chan.outsigmod;
@@ -14026,6 +14084,10 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
                                } else {
                                        confp->pri.overlapdial = DAHDI_OVERLAPDIAL_NONE;
                                }
+#ifdef HAVE_PRI_INBANDDISCONNECT
+                       } else if (!strcasecmp(v->name, "inbanddisconnect")) {
+                               confp->pri.inbanddisconnect = ast_true(v->value);
+#endif
                        } else if (!strcasecmp(v->name, "pritimer")) {
 #ifdef PRI_GETSET_TIMERS
                                char tmp[20], *timerc, *c = tmp;
@@ -14116,6 +14178,17 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
                                res = linkset_addsigchan(sigchan);
                                if (res < 0)
                                        return -1;
+
+                       } else if (!strcasecmp(v->name, "ss7_explicitacm")) {
+                               struct dahdi_ss7 *link;
+                               link = ss7_resolve_linkset(cur_linkset);
+                               if (!link) {
+                                       ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
+                                       return -1;
+                               }
+                               if (ast_true(v->value))
+                                       link->flags |= LINKSET_FLAG_EXPLICITACM;
+
 #endif /* HAVE_SS7 */
                        } else if (!strcasecmp(v->name, "cadence")) {
                                /* setup to scan our argument */
@@ -14234,7 +14307,7 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
                                        dps.dtmf_tonelen = dps.mfv1_tonelen = toneduration;
                                        res = ioctl(ctlfd, DAHDI_SET_DIALPARAMS, &dps);
                                        if (res < 0) {
-                                               ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d.\n", toneduration, v->lineno);
+                                               ast_log(LOG_ERROR, "Invalid tone duration: %d ms at line %d: %s\n", toneduration, v->lineno, strerror(errno));
                                                return -1;
                                        }
                                }
@@ -14382,7 +14455,7 @@ static int setup_dahdi(int reload)
        mwimonitornotify[0] = '\0';
 
        v = ast_variable_browse(cfg, "channels");
-       if ((res = process_dahdi(&base_conf, v, reload, 0))) {
+       if ((res = process_dahdi(&base_conf, "", v, reload, 0))) {
                ast_mutex_unlock(&iflock);
                ast_config_destroy(cfg);
                if (ucfg) {
@@ -14405,7 +14478,7 @@ static int setup_dahdi(int reload)
 
                memcpy(&conf, &base_conf, sizeof(conf));
 
-               if ((res = process_dahdi(&conf, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
+               if ((res = process_dahdi(&conf, cat, ast_variable_browse(cfg, cat), reload, PROC_DAHDI_OPT_NOCHAN))) {
                        ast_mutex_unlock(&iflock);
                        ast_config_destroy(cfg);
                        if (ucfg) {
@@ -14525,7 +14598,7 @@ static int load_module(void)
        ast_cli_register_multiple(dahdi_pri_cli, sizeof(dahdi_pri_cli) / sizeof(struct ast_cli_entry));
 #endif 
 #ifdef HAVE_SS7
-       ast_cli_register_multiple(dahdi_ss7_cli, sizeof(dahdi_ss7_cli) / sizeof(dahdi_ss7_cli[0]));
+       ast_cli_register_multiple(dahdi_ss7_cli, ARRAY_LEN(dahdi_ss7_cli));
 #endif
 
        ast_cli_register_multiple(dahdi_cli, sizeof(dahdi_cli) / sizeof(struct ast_cli_entry));
@@ -14658,11 +14731,19 @@ static int reload(void)
  * AST_MODULE_INFO(, , "DAHDI Telephony"
  */
 
-#ifdef DAHDI_PRI
+#ifdef HAVE_PRI
+#ifdef HAVE_SS7
+#define tdesc "DAHDI Telephony w/PRI & SS7"
+#else
 #define tdesc "DAHDI Telephony w/PRI"
+#endif
+#else
+#ifdef HAVE_SS7
+#define tdesc "DAHDI Telephony w/SS7"
 #else
 #define tdesc "DAHDI Telephony"
 #endif
+#endif
 
 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, tdesc,
                .load = load_module,