New signaling module to handle PRI/BRI operations in chan_dahdi
authorJeff Peeler <jpeeler@digium.com>
Thu, 25 Jun 2009 19:54:12 +0000 (19:54 +0000)
committerJeff Peeler <jpeeler@digium.com>
Thu, 25 Jun 2009 19:54:12 +0000 (19:54 +0000)
This merge splits the PRI/BRI signaling logic out of chan_dahdi.c into
sig_pri.c. Functionality in theory should not change (mostly). A few trivial
changes were made in sig_analog with verbose messages and commenting.

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@203304 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/Makefile
channels/chan_dahdi.c
channels/sig_analog.c
channels/sig_analog.h
channels/sig_pri.c [new file with mode: 0644]
channels/sig_pri.h [new file with mode: 0644]

index 6e03b22..b6c3b42 100644 (file)
@@ -69,7 +69,7 @@ dist-clean::
        rm -f h323/Makefile
 
 $(if $(filter chan_iax2,$(EMBEDDED_MODS)),modules.link,chan_iax2.so): iax2-parser.o iax2-provision.o
-$(if $(filter chan_dahdi,$(EMBEDDED_MODS)),modules.link,chan_dahdi.so): sig_analog.o
+$(if $(filter chan_dahdi,$(EMBEDDED_MODS)),modules.link,chan_dahdi.so): sig_analog.o sig_pri.o
 
 ifneq ($(filter chan_h323,$(EMBEDDED_MODS)),)
 modules.link: h323/libchanh323.a
index 344f56a..35cece3 100644 (file)
@@ -65,7 +65,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "sig_analog.h"
 
 #ifdef HAVE_PRI
-#include <libpri.h>
+#include "sig_pri.h"
 #endif
 
 #ifdef HAVE_SS7
@@ -346,58 +346,20 @@ static const char config[] = "chan_dahdi.conf";
 #define        SIG_SF_FEATDMF  (0x0400000 | DAHDI_SIG_SF)
 #define        SIG_SF_FEATB    (0x0800000 | DAHDI_SIG_SF)
 #define SIG_EM_E1      DAHDI_SIG_EM_E1
-#define SIG_GR303FXOKS (0x0100000 | DAHDI_SIG_FXOKS)
-#define SIG_GR303FXSKS (0x0100000 | DAHDI_SIG_FXSKS)
 
 #ifdef LOTS_OF_SPANS
 #define NUM_SPANS      DAHDI_MAX_SPANS
 #else
 #define NUM_SPANS              32
 #endif
-#define NUM_DCHANS             4       /*!< No more than 4 d-channels */
-#define MAX_CHANNELS   672             /*!< No more than a DS3 per trunk group */
 
 #define CHAN_PSEUDO    -2
 
-#define DCHAN_PROVISIONED (1 << 0)
-#define DCHAN_NOTINALARM  (1 << 1)
-#define DCHAN_UP          (1 << 2)
-
-#define DCHAN_AVAILABLE        (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
-
-/* Overlap dialing option types */
-#define DAHDI_OVERLAPDIAL_NONE 0
-#define DAHDI_OVERLAPDIAL_OUTGOING 1
-#define DAHDI_OVERLAPDIAL_INCOMING 2
-#define DAHDI_OVERLAPDIAL_BOTH (DAHDI_OVERLAPDIAL_INCOMING|DAHDI_OVERLAPDIAL_OUTGOING)
-
 #define CALLPROGRESS_PROGRESS          1
 #define CALLPROGRESS_FAX_OUTGOING      2
 #define CALLPROGRESS_FAX_INCOMING      4
 #define CALLPROGRESS_FAX               (CALLPROGRESS_FAX_INCOMING | CALLPROGRESS_FAX_OUTGOING)
 
-#ifdef HAVE_PRI_SERVICE_MESSAGES
-/*! \brief Persistent Service State */
-#define SRVST_DBKEY "service-state"
-/*! \brief The out-of-service SERVICE state */
-#define SRVST_TYPE_OOS "O"
-/*! \brief SRVST_INITIALIZED is used to indicate a channel being out-of-service 
- *  The SRVST_INITIALIZED is mostly used maintain backwards compatibility but also may
- *  mean that the channel has not yet received a RESTART message.  If a channel is
- *  out-of-service with this reason a RESTART message will result in the channel
- *  being put into service. */
-#define SRVST_INITIALIZED 0
-/*! \brief SRVST_NEAREND is used to indicate that the near end was put out-of-service */
-#define SRVST_NEAREND  (1 << 0)
-/*! \brief SRVST_FAREND is used to indicate that the far end was taken out-of-service */
-#define SRVST_FAREND   (1 << 1)
-/*! \brief SRVST_BOTH is used to indicate that both sides of the channel are out-of-service */
-#define SRVST_BOTH (SRVST_NEAREND | SRVST_FAREND)
-
-/*! \brief The AstDB family */
-static const char dahdi_db[] = "dahdi/registry";
-#endif
-
 static char defaultcic[64] = "";
 static char defaultozz[64] = "";
 
@@ -419,7 +381,6 @@ static int numbufs = 4;
 static int mwilevel = 512;
 
 #ifdef HAVE_PRI
-static struct ast_channel inuse;
 #ifdef PRI_GETSET_TIMERS
 static int pritimers[PRI_MAX_TIMERS];
 #endif
@@ -608,68 +569,13 @@ static int r2links_count = 0;
 
 #ifdef HAVE_PRI
 
-#define PVT_TO_CHANNEL(p) (((p)->prioffset) | ((p)->logicalspan << 8) | (p->pri->mastertrunkgroup ? 0x10000 : 0))
-#define PRI_CHANNEL(p) ((p) & 0xff)
-#define PRI_SPAN(p) (((p) >> 8) & 0xff)
-#define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
-
 struct dahdi_pri {
-       pthread_t master;                                               /*!< Thread of master */
-       ast_mutex_t lock;                                               /*!< Mutex */
-       char idleext[AST_MAX_EXTENSION];                                /*!< Where to idle extra calls */
-       char idlecontext[AST_MAX_CONTEXT];                              /*!< What context to use for idle */
-       char idledial[AST_MAX_EXTENSION];                               /*!< What to dial before dumping */
-       int minunused;                                                  /*!< Min # of channels to keep empty */
-       int minidle;                                                    /*!< Min # of "idling" calls to keep active */
-       int nodetype;                                                   /*!< Node type */
-       int switchtype;                                                 /*!< Type of switch to emulate */
-       int nsf;                                                        /*!< Network-Specific Facilities */
-       int dialplan;                                                   /*!< Dialing plan */
-       int localdialplan;                                              /*!< Local dialing plan */
-       char internationalprefix[10];                                   /*!< country access code ('00' for european dialplans) */
-       char nationalprefix[10];                                        /*!< area access code ('0' for european dialplans) */
-       char localprefix[20];                                           /*!< area access code + area code ('0'+area code for european dialplans) */
-       char privateprefix[20];                                         /*!< for private dialplans */
-       char unknownprefix[20];                                         /*!< for unknown dialplans */
        int dchannels[NUM_DCHANS];                                      /*!< What channel are the dchannels on */
-       int trunkgroup;                                                 /*!< What our trunkgroup is */
        int mastertrunkgroup;                                           /*!< What trunk group is our master */
        int prilogicalspan;                                             /*!< Logical span number within trunk group */
-       int numchans;                                                   /*!< Num of channels we represent */
-       int overlapdial;                                                /*!< In overlap dialing mode */
-       int qsigchannelmapping;                                         /*!< QSIG channel mapping type */
-       int discardremoteholdretrieval;                                 /*!< shall remote hold or remote retrieval notifications be discarded? */
-       int facilityenable;                                             /*!< Enable facility IEs */
-       struct pri *dchans[NUM_DCHANS];                                 /*!< Actual d-channels */
-       int dchanavail[NUM_DCHANS];                                     /*!< Whether each channel is available */
-       struct pri *pri;                                                /*!< Currently active D-channel */
-       /*! \brief TRUE if to dump PRI event info (Tested but never set) */
-       int debug;
-       int fds[NUM_DCHANS];                                            /*!< FD's for d-channels */
-       /*! \brief Value set but not used */
-       int offset;
-       /*! \brief Span number put into user output messages */
-       int span;
-       /*! \brief TRUE if span is being reset/restarted */
-       int resetting;
-       /*! \brief Current position during a reset (-1 if not started) */
-       int resetpos;
-#ifdef HAVE_PRI_SERVICE_MESSAGES
-       unsigned int enable_service_message_support:1;  /*!< enable SERVICE message support */
-#endif
-#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 */
-       /*! \brief ISDN signalling type (SIG_PRI, SIG_BRI, SIG_BRI_PTMP, etc...) */
-       int sig;
-       struct dahdi_pvt *pvts[MAX_CHANNELS];                           /*!< Member channel pvt structs */
-       struct dahdi_pvt *crvs;                                         /*!< Member CRV structs */
-       struct dahdi_pvt *crvend;                                               /*!< Pointer to end of CRV structs */
+       struct sig_pri_pri pri;
 };
 
-
 static struct dahdi_pri pris[NUM_SPANS];
 
 #if 0
@@ -678,11 +584,6 @@ static struct dahdi_pri pris[NUM_SPANS];
 #define DEFAULT_PRI_DEBUG 0
 #endif
 
-static inline void pri_rel(struct dahdi_pri *pri)
-{
-       ast_mutex_unlock(&pri->lock);
-}
-
 #else
 /*! Shut up the compiler */
 struct dahdi_pri;
@@ -1028,6 +929,11 @@ static struct dahdi_pvt {
         * \note Applies to SS7 channels.
         */
        unsigned int remotelyblocked:1;
+#if defined(HAVE_PRI)
+       struct sig_pri_pri *pri;
+       int prioffset;
+       int logicalspan;
+#endif
 #if defined(HAVE_PRI) || defined(HAVE_SS7)
        /*!
         * \brief XXX BOOLEAN Purpose???
@@ -1224,7 +1130,6 @@ static struct dahdi_pvt {
        struct timeval flashtime;                       /*!< Last flash-hook time */
        /*! \brief Opaque DSP configuration structure. */
        struct ast_dsp *dsp;
-       //int cref;                                     /*!< Call reference number (Not used) */
        /*! \brief DAHDI dial operation command struct for ioctl() call. */
        struct dahdi_dialoperation dop;
        int whichwink;                                  /*!< SIG_FEATDMF_TA Which wink are we on? */
@@ -1272,20 +1177,6 @@ static struct dahdi_pvt {
         * \note Set from the "sendcalleridafter" value read in from chan_dahdi.conf
         */
        int sendcalleridafter;
-#ifdef HAVE_PRI
-       /*! \brief DAHDI PRI control parameters */
-       struct dahdi_pri *pri;
-       /*! \brief XXX Purpose??? */
-       struct dahdi_pvt *bearer;
-       /*! \brief XXX Purpose??? */
-       struct dahdi_pvt *realcall;
-       /*! \brief Opaque libpri call control structure */
-       q931_call *call;
-       /*! \brief Channel number in span. */
-       int prioffset;
-       /*! \brief Logical span number within trunk group */
-       int logicalspan;
-#endif
        /*! \brief Current line interface polarity. POLARITY_IDLE, POLARITY_REV */
        int polarity;
        /*! \brief DSP feature flags: DSP_FEATURE_xxx */
@@ -1384,7 +1275,7 @@ static struct dahdi_chan_conf dahdi_chan_conf_default(void)
         */
        struct dahdi_chan_conf conf = {
 #ifdef HAVE_PRI
-               .pri = {
+               .pri.pri = {
                        .nsf = PRI_NSF_NONE,
                        .switchtype = PRI_SWITCH_NI2,
                        .dialplan = PRI_UNKNOWN + 1,
@@ -1535,11 +1426,7 @@ static const struct ast_channel_tech dahdi_tech = {
        .func_channel_write = dahdi_func_write,
 };
 
-#ifdef HAVE_PRI
-#define GET_CHANNEL(p) ((p)->bearer ? (p)->bearer->channel : p->channel)
-#else
 #define GET_CHANNEL(p) ((p)->channel)
-#endif
 
 static enum analog_sigtype dahdisig_to_analogsig(int sig)
 {
@@ -1847,7 +1734,7 @@ static int my_wink(void *pvt, enum analog_sub sub)
        return dahdi_wink(p, index);
 }
 
-static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri);
+static void wakeup_sub(struct dahdi_pvt *p, int a);
 
 static int reset_conf(struct dahdi_pvt *p);
 
@@ -2082,15 +1969,15 @@ static void my_swap_subchannels(void *pvt, enum analog_sub a, struct ast_channel
        p->subs[da].owner = ast_a;
        p->subs[db].owner = ast_b;
 
-       wakeup_sub(p, a, NULL);
-       wakeup_sub(p, b, NULL);
+       wakeup_sub(p, a);
+       wakeup_sub(p, b);
 
        return;
 }
 
 static struct ast_channel *dahdi_new(struct dahdi_pvt *, int, int, int, int, int);
 
-static struct ast_channel * my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub)
+static struct ast_channel *my_new_analog_ast_channel(void *pvt, int state, int startpbx, enum analog_sub sub)
 {
        struct dahdi_pvt *p = pvt;
        int dsub = analogsub_to_dahdisub(sub);
@@ -2098,6 +1985,50 @@ static struct ast_channel * my_new_analog_ast_channel(void *pvt, int state, int
        return dahdi_new(p, state, startpbx, dsub, 0, 0);
 }
 
+#if defined(HAVE_PRI) || defined(HAVE_SS7)
+static int dahdi_setlaw(int dfd, int law)
+{
+       int res;
+       res = ioctl(dfd, DAHDI_SETLAW, &law);
+       if (res)
+               return res;
+       return 0;
+}
+#endif
+
+#ifdef HAVE_PRI
+static struct ast_channel *my_new_pri_ast_channel(void *pvt, int state, int startpbx, enum sig_pri_law law, int transfercapability, char *exten)
+{
+       struct dahdi_pvt *p = pvt;
+       int audio;
+       int newlaw = -1;
+
+       /* Set to audio mode at this point */
+       audio = 1;
+       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &audio) == -1)
+               ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", p->channel, audio, strerror(errno));
+
+       if (law != SIG_PRI_DEFLAW) {
+               dahdi_setlaw(p->subs[SUB_REAL].dfd, (law == SIG_PRI_ULAW) ? DAHDI_LAW_MULAW : DAHDI_LAW_ALAW);
+       }
+
+       ast_copy_string(p->exten, exten, sizeof(p->exten));
+
+       switch (law) {
+               case SIG_PRI_DEFLAW:
+                       newlaw = 0;
+                       break;
+               case SIG_PRI_ALAW:
+                       newlaw = DAHDI_LAW_ALAW;
+                       break;
+               case SIG_PRI_ULAW:
+                       newlaw = DAHDI_LAW_MULAW;
+                       break;
+       }
+       return dahdi_new(p, state, startpbx, SUB_REAL, newlaw, transfercapability);
+}
+#endif
+
 static int unalloc_sub(struct dahdi_pvt *p, int x);
 
 static int my_unallocate_sub(void *pvt, enum analog_sub analogsub)
@@ -2333,6 +2264,92 @@ static int my_on_hook(void *pvt)
        return ioctl(p->subs[ANALOG_SUB_REAL].dfd, DAHDI_HOOK, &x);
 }
 
+#ifdef HAVE_PRI
+static void my_pri_fixup_chans(void *old_chan, void *new_chan)
+{
+       struct dahdi_pvt *old = old_chan;
+       struct dahdi_pvt *new = new_chan;
+       struct sig_pri_chan *pchan = new->sig_pvt;
+       struct sig_pri_pri *pri = pchan->pri;
+
+       new->owner = old->owner;
+       old->owner = NULL;
+       if (new->owner) {
+               char newname[AST_CHANNEL_NAME];
+               snprintf(newname, sizeof(newname), "DAHDI/%d:%d-%d", pri->trunkgroup, new->channel, 1);
+               ast_change_name(new->owner, newname);
+
+               new->owner->tech_pvt = new;
+               new->owner->fds[0] = new->subs[SUB_REAL].dfd;
+               new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
+               old->subs[SUB_REAL].owner = NULL;
+       }
+       /* Copy any DSP that may be present */
+       new->dsp = old->dsp;
+       new->dsp_features = old->dsp_features;
+       old->dsp = NULL;
+       old->dsp_features = 0;
+}
+
+static int sig_pri_tone_to_dahditone(enum analog_tone tone)
+{
+       switch (tone) {
+       case SIG_PRI_TONE_RINGTONE:
+               return DAHDI_TONE_RINGTONE;
+       case SIG_PRI_TONE_STUTTER:
+               return DAHDI_TONE_STUTTER;
+       case SIG_PRI_TONE_CONGESTION:
+               return DAHDI_TONE_CONGESTION;
+       case SIG_PRI_TONE_DIALTONE:
+               return DAHDI_TONE_DIALTONE;
+       case SIG_PRI_TONE_DIALRECALL:
+               return DAHDI_TONE_DIALRECALL;
+       case SIG_PRI_TONE_INFO:
+               return DAHDI_TONE_INFO;
+       case SIG_PRI_TONE_BUSY:
+               return DAHDI_TONE_BUSY;
+       default:
+               return -1;
+       }
+}
+
+static const char *event2str(int event);
+
+static void my_handle_dchan_exception(struct sig_pri_pri *pri, int index)
+{
+       int x, res;
+
+       res = ioctl(pri->fds[index], DAHDI_GETEVENT, &x);
+       if (x) {
+               ast_log(LOG_NOTICE, "PRI got event: %s (%d) on D-channel of span %d\n", event2str(x), x, pri->span);
+       }
+       /* Keep track of alarm state */ 
+       if (x == DAHDI_EVENT_ALARM) {
+               pri_event_alarm(pri, index, 0);
+       } else if (x == DAHDI_EVENT_NOALARM) {
+               pri_event_noalarm(pri, index, 0);
+       }
+}
+
+static int my_pri_play_tone(void *pvt, enum sig_pri_tone tone)
+{
+       struct dahdi_pvt *p = pvt;
+
+       return tone_zone_play_tone(p->subs[SUB_REAL].dfd, sig_pri_tone_to_dahditone(tone));
+}
+
+static struct sig_pri_callback dahdi_pri_callbacks =
+{
+       .handle_dchan_exception = my_handle_dchan_exception,
+       .play_tone = my_pri_play_tone,
+       .set_echocanceller = my_set_echocanceller,
+       .lock_private = my_lock_private,
+       .unlock_private = my_unlock_private,
+       .new_ast_channel = my_new_pri_ast_channel,
+       .fixup_chans = my_pri_fixup_chans,
+};
+#endif /* HAVE_PRI */
+
 /*!
  * \brief Send MWI state change
  *
@@ -2403,7 +2420,6 @@ static void my_handle_notify_message(struct ast_channel *chan, void *pvt, int ci
 }
 
 
-static const char *event2str(int event);
 
 static struct analog_callback dahdi_analog_callbacks =
 {
@@ -2448,24 +2464,6 @@ static struct analog_callback dahdi_analog_callbacks =
 
 static struct dahdi_pvt *round_robin[32];
 
-#if defined(HAVE_PRI)
-static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
-{
-       int res;
-       /* Grab the lock first */
-       do {
-               res = ast_mutex_trylock(&pri->lock);
-               if (res) {
-                       DEADLOCK_AVOIDANCE(&pvt->lock);
-               }
-       } while (res);
-       /* Then break the poll */
-       if (pri->master != AST_PTHREADT_NULL)
-               pthread_kill(pri->master, SIGURG);
-       return 0;
-}
-#endif /* defined(HAVE_PRI) */
-
 #if defined(HAVE_SS7)
 static inline void ss7_rel(struct dahdi_ss7 *ss7)
 {
@@ -2538,12 +2536,8 @@ static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nul
        return res;
 }
 
-static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
+static void wakeup_sub(struct dahdi_pvt *p, int a)
 {
-#ifdef HAVE_PRI
-       if (pri)
-               ast_mutex_unlock(&pri->lock);
-#endif
        for (;;) {
                if (p->subs[a].owner) {
                        if (ast_channel_trylock(p->subs[a].owner)) {
@@ -2556,36 +2550,18 @@ static void wakeup_sub(struct dahdi_pvt *p, int a, struct dahdi_pri *pri)
                } else
                        break;
        }
-#ifdef HAVE_PRI
-       if (pri)
-               ast_mutex_lock(&pri->lock);
-#endif
 }
 
 static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *data)
 {
-#ifdef HAVE_PRI
-       struct dahdi_pri *pri = (struct dahdi_pri*) data;
-#endif
 #ifdef HAVE_SS7
        struct dahdi_ss7 *ss7 = (struct dahdi_ss7*) data;
-#endif
-       /* We must unlock the PRI to avoid the possibility of a deadlock */
-#if defined(HAVE_PRI) || defined(HAVE_SS7)
+
        if (data) {
                switch (p->sig) {
-#ifdef HAVE_PRI
-               case SIG_BRI:
-               case SIG_BRI_PTMP:
-               case SIG_PRI:
-                       ast_mutex_unlock(&pri->lock);
-                       break;
-#endif
-#ifdef HAVE_SS7
                case SIG_SS7:
                        ast_mutex_unlock(&ss7->lock);
                        break;
-#endif
                default:
                        break;
                }
@@ -2603,21 +2579,12 @@ static void dahdi_queue_frame(struct dahdi_pvt *p, struct ast_frame *f, void *da
                } else
                        break;
        }
-#if defined(HAVE_PRI) || defined(HAVE_SS7)
+#if defined(HAVE_SS7)
        if (data) {
                switch (p->sig) {
-#ifdef HAVE_PRI
-               case SIG_BRI:
-               case SIG_BRI_PTMP:
-               case SIG_PRI:
-                       ast_mutex_lock(&pri->lock);
-                       break;
-#endif
-#ifdef HAVE_SS7
                case SIG_SS7:
                        ast_mutex_lock(&ss7->lock);
                        break;
-#endif
                default:
                        break;
                }
@@ -3107,8 +3074,8 @@ static void swap_subs(struct dahdi_pvt *p, int a, int b)
                ast_channel_set_fd(p->subs[a].owner, 0, p->subs[a].dfd);
        if (p->subs[b].owner)
                ast_channel_set_fd(p->subs[b].owner, 0, p->subs[b].dfd);
-       wakeup_sub(p, a, NULL);
-       wakeup_sub(p, b, NULL);
+       wakeup_sub(p, a);
+       wakeup_sub(p, b);
 }
 
 static int dahdi_open(char *fn)
@@ -3173,8 +3140,8 @@ static void dahdi_close_sub(struct dahdi_pvt *chan_pvt, int sub_num)
 #if defined(HAVE_PRI)
 static void dahdi_close_pri_fd(struct dahdi_pri *pri, int fd_num)
 {
-       dahdi_close(pri->fds[fd_num]);
-       pri->fds[fd_num] = -1;
+       dahdi_close(pri->pri.fds[fd_num]);
+       pri->pri.fds[fd_num] = -1;
 }
 #endif /* defined(HAVE_PRI) */
 
@@ -3271,6 +3238,7 @@ static int dahdi_digit_begin(struct ast_channel *chan, char digit)
        struct dahdi_pvt *pvt;
        int idx;
        int dtmf = -1;
+       int res;
 
        pvt = chan->tech_pvt;
 
@@ -3282,29 +3250,16 @@ static int dahdi_digit_begin(struct ast_channel *chan, char digit)
                goto out;
 
 #ifdef HAVE_PRI
-       if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
-                       && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
-               if (pvt->setup_ack) {
-                       if (!pri_grab(pvt, pvt->pri)) {
-                               pri_information(pvt->pri->pri, pvt->call, digit);
-                               pri_rel(pvt->pri);
-                       } else
-                               ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
-               } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
-                       int res;
-                       ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit);
-                       res = strlen(pvt->dialdest);
-                       pvt->dialdest[res++] = digit;
-                       pvt->dialdest[res] = '\0';
-               }
-               goto out;
+       if (pvt->sig == SIG_PRI || pvt->sig == SIG_BRI || pvt->sig == SIG_BRI_PTMP) {
+               res = sig_pri_digit_begin(pvt->sig_pvt, chan, digit);
+               if (!res)
+                       goto out;
        }
 #endif
        if ((dtmf = digit_to_dtmfindex(digit)) == -1)
                goto out;
 
        if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
-               int res;
                struct dahdi_dialoperation zo = {
                        .op = DAHDI_DIAL_OP_APPEND,
                };
@@ -3419,16 +3374,6 @@ static const char *event2str(int event)
        return buf;
 }
 
-#ifdef HAVE_PRI
-static char *dialplan2str(int dialplan)
-{
-       if (dialplan == -1 || dialplan == -2) {
-               return("Dynamically set dialplan in ISDN");
-       }
-       return (pri_plan2str(dialplan));
-}
-#endif
-
 static char *dahdi_sig2str(int sig)
 {
        static char buf[256];
@@ -3485,10 +3430,6 @@ static char *dahdi_sig2str(int sig)
                return "SF (Tone) with Feature Group D (MF)";
        case SIG_SF_FEATB:
                return "SF (Tone) with Feature Group B (MF)";
-       case SIG_GR303FXOKS:
-               return "GR-303 with FXOKS";
-       case SIG_GR303FXSKS:
-               return "GR-303 with FXSKS";
        case 0:
                return "Pseudo";
        default:
@@ -4119,12 +4060,11 @@ static unsigned char cid_pres2ss7screen(int cid_pres)
 static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
 {
        struct dahdi_pvt *p = ast->tech_pvt;
-       int x, res, idx,mysig;
-       char *c, *n, *l;
-#ifdef HAVE_PRI
-       char *s = NULL;
-#endif
+       int x, res, mysig;
        char dest[256]; /* must be same length as p->dialdest */
+#ifdef HAVE_SS7
+       char *c, *l;
+#endif
        ast_mutex_lock(&p->lock);
        ast_copy_string(dest, rdest, sizeof(dest));
        ast_copy_string(p->dialdest, rdest, sizeof(p->dialdest));
@@ -4154,6 +4094,20 @@ static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
        p->outgoing = 1;
 
        set_actual_gain(p->subs[SUB_REAL].dfd, 0, p->rxgain, p->txgain, p->law);
+       
+#ifdef HAVE_PRI
+       if (p->sig == SIG_PRI || p->sig == SIG_BRI || p->sig == SIG_BRI_PTMP) {
+               struct dahdi_params ps;
+               memset(&ps, 0, sizeof(ps));
+               if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &ps)) {
+                       ast_log(LOG_ERROR, "Could not get params\n");
+               }
+               res = sig_pri_call(p->sig_pvt, ast, rdest, timeout, (ps.curlaw == DAHDI_LAW_MULAW) ? PRI_LAYER_1_ULAW : PRI_LAYER_1_ALAW);
+               ast_mutex_unlock(&p->lock);
+               return res;
+       }
+#endif
+
        /* Set the ring cadence */
        mysig = p->sig;
        if (p->outsigmod > -1)
@@ -4176,7 +4130,7 @@ static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
                }
                break;
        }
-       
+
        /* If this is analog signalling we can exit here */
        if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
                p->callwaitrings = 0;
@@ -4185,271 +4139,52 @@ static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
                return res;
        }
 
+       mysig = p->sig;
+       if (p->outsigmod > -1)
+               mysig = p->outsigmod;
+
        switch (mysig) {
-       case SIG_FXOLS:
-       case SIG_FXOGS:
-       case SIG_FXOKS:
-               if (p->owner == ast) {
-                       /* Normal ring, on hook */
+       case 0:
+               /* Special pseudo -- automatically up*/
+               ast_setstate(ast, AST_STATE_UP);
+               break;
+       case SIG_BRI:
+       case SIG_BRI_PTMP:
+       case SIG_SS7:
+       case SIG_MFCR2:
+               /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
+               p->dialdest[0] = '\0';
+               p->dialing = 1;
+               break;
+       default:
+               ast_debug(1, "not yet implemented\n");
+               ast_mutex_unlock(&p->lock);
+               return -1;
+       }
+#ifdef HAVE_SS7
+       if (p->ss7) {
+               char ss7_called_nai;
+               int called_nai_strip;
+               char ss7_calling_nai;
+               int calling_nai_strip;
+               const char *charge_str = NULL;
+               const char *gen_address = NULL;
+               const char *gen_digits = NULL;
+               const char *gen_dig_type = NULL;
+               const char *gen_dig_scheme = NULL;
+               const char *gen_name = NULL;
+               const char *jip_digits = NULL;
+               const char *lspi_ident = NULL;
+               const char *rlt_flag = NULL;
+               const char *call_ref_id = NULL;
+               const char *call_ref_pc = NULL;
+               const char *send_far = NULL;
 
-                       /* Don't send audio while on hook, until the call is answered */
-                       p->dialing = 1;
-                       if (p->use_callerid) {
-                               /* Generate the Caller-ID spill if desired */
-                               if (p->cidspill) {
-                                       ast_log(LOG_WARNING, "cidspill already exists??\n");
-                                       ast_free(p->cidspill);
-                               }
-                               p->callwaitcas = 0;
-                               if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
-                                       p->cidlen = ast_callerid_generate(p->cidspill, ast->connected.id.name, ast->connected.id.number, AST_LAW(p));
-                                       p->cidpos = 0;
-                                       send_callerid(p);
-                               }
-                       }
-                       /* nick@dccinc.com 4/3/03 mods to allow for deferred dialing */
-                       c = strchr(dest, '/');
-                       if (c)
-                               c++;
-                       if (c && (strlen(c) < p->stripmsd)) {
-                               ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
-                               c = NULL;
-                       }
-                       if (c) {
-                               p->dop.op = DAHDI_DIAL_OP_REPLACE;
-                               snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
-                               ast_debug(1, "FXO: setup deferred dialstring: %s\n", c);
-                       } else {
-                               p->dop.dialstr[0] = '\0';
-                       }
-                       x = DAHDI_RING;
-                       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x) && (errno != EINPROGRESS)) {
-                               ast_log(LOG_WARNING, "Unable to ring phone: %s\n", strerror(errno));
-                               ast_mutex_unlock(&p->lock);
-                               return -1;
-                       }
-                       p->dialing = 1;
+               c = strchr(dest, '/');
+               if (c) {
+                       c++;
                } else {
-                       /* Call waiting call */
-                       p->callwaitrings = 0;
-                       if (ast->connected.id.number)
-                               ast_copy_string(p->callwait_num, ast->connected.id.number, sizeof(p->callwait_num));
-                       else
-                               p->callwait_num[0] = '\0';
-                       if (ast->connected.id.name)
-                               ast_copy_string(p->callwait_name, ast->connected.id.name, sizeof(p->callwait_name));
-                       else
-                               p->callwait_name[0] = '\0';
-                       /* Call waiting tone instead */
-                       if (dahdi_callwait(ast)) {
-                               ast_mutex_unlock(&p->lock);
-                               return -1;
-                       }
-                       /* Make ring-back */
-                       if (tone_zone_play_tone(p->subs[SUB_CALLWAIT].dfd, DAHDI_TONE_RINGTONE))
-                               ast_log(LOG_WARNING, "Unable to generate call-wait ring-back on channel %s\n", ast->name);
-               }
-               n = ast->connected.id.name;
-               l = ast->connected.id.number;
-               if (l)
-                       ast_copy_string(p->lastcid_num, l, sizeof(p->lastcid_num));
-               else
-                       p->lastcid_num[0] = '\0';
-               if (n)
-                       ast_copy_string(p->lastcid_name, n, sizeof(p->lastcid_name));
-               else
-                       p->lastcid_name[0] = '\0';
-               ast_setstate(ast, AST_STATE_RINGING);
-               idx = dahdi_get_index(ast, p, 0);
-               if (idx > -1) {
-                       p->subs[idx].needringing = 1;
-               }
-               break;
-       case SIG_FXSLS:
-       case SIG_FXSGS:
-       case SIG_FXSKS:
-       case SIG_EMWINK:
-       case SIG_EM:
-       case SIG_EM_E1:
-       case SIG_FEATD:
-       case SIG_FEATDMF:
-       case SIG_E911:
-       case SIG_FGC_CAMA:
-       case SIG_FGC_CAMAMF:
-       case SIG_FEATB:
-       case SIG_SFWINK:
-       case SIG_SF:
-       case SIG_SF_FEATD:
-       case SIG_SF_FEATDMF:
-       case SIG_FEATDMF_TA:
-       case SIG_SF_FEATB:
-               c = strchr(dest, '/');
-               if (c)
-                       c++;
-               else
-                       c = "";
-               if (strlen(c) < p->stripmsd) {
-                       ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
-                       ast_mutex_unlock(&p->lock);
-                       return -1;
-               }
-#ifdef HAVE_PRI
-               /* Start the trunk, if not GR-303 */
-               if (!p->pri) {
-#endif
-                       x = DAHDI_START;
-                       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
-                       if (res < 0) {
-                               if (errno != EINPROGRESS) {
-                                       ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
-                                       ast_mutex_unlock(&p->lock);
-                                       return -1;
-                               }
-                       }
-#ifdef HAVE_PRI
-               }
-#endif
-               ast_debug(1, "Dialing '%s'\n", c);
-               p->dop.op = DAHDI_DIAL_OP_REPLACE;
-
-               c += p->stripmsd;
-
-               switch (mysig) {
-               case SIG_FEATD:
-                       l = ast->connected.id.number;
-                       if (l)
-                               snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T*%s*%s*", l, c);
-                       else
-                               snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T**%s*", c);
-                       break;
-               case SIG_FEATDMF:
-                       l = ast->connected.id.number;
-                       if (l)
-                               snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*00%s#*%s#", l, c);
-                       else
-                               snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*02#*%s#", c);
-                       break;
-               case SIG_FEATDMF_TA:
-               {
-                       const char *cic, *ozz;
-
-                       /* If you have to go through a Tandem Access point you need to use this */
-                       ozz = pbx_builtin_getvar_helper(p->owner, "FEATDMF_OZZ");
-                       if (!ozz)
-                               ozz = defaultozz;
-                       cic = pbx_builtin_getvar_helper(p->owner, "FEATDMF_CIC");
-                       if (!cic)
-                               cic = defaultcic;
-                       if (!ozz || !cic) {
-                               ast_log(LOG_WARNING, "Unable to dial channel of type feature group D MF tandem access without CIC or OZZ set\n");
-                               ast_mutex_unlock(&p->lock);
-                               return -1;
-                       }
-                       snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s%s#", ozz, cic);
-                       snprintf(p->finaldial, sizeof(p->finaldial), "M*%s#", c);
-                       p->whichwink = 0;
-               }
-                       break;
-               case SIG_E911:
-                       ast_copy_string(p->dop.dialstr, "M*911#", sizeof(p->dop.dialstr));
-                       break;
-               case SIG_FGC_CAMA:
-                       snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%s", c);
-                       break;
-               case SIG_FGC_CAMAMF:
-               case SIG_FEATB:
-                       snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%s#", c);
-                       break;
-               default:
-                       if (p->pulse)
-                               snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "P%sw", c);
-                       else
-                               snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%sw", c);
-                       break;
-               }
-
-               if (p->echotraining && (strlen(p->dop.dialstr) > 4)) {
-                       memset(p->echorest, 'w', sizeof(p->echorest) - 1);
-                       strcpy(p->echorest + (p->echotraining / 400) + 1, p->dop.dialstr + strlen(p->dop.dialstr) - 2);
-                       p->echorest[sizeof(p->echorest) - 1] = '\0';
-                       p->echobreak = 1;
-                       p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
-               } else
-                       p->echobreak = 0;
-
-               /* waitfordialtone ? */
-#ifdef HAVE_PRI
-               if (!p->pri) {
-#endif
-                       if( p->waitfordialtone && CANPROGRESSDETECT(p) && p->dsp ) {
-                               ast_log(LOG_DEBUG, "Defer dialling for %dms or dialtone\n", p->waitfordialtone);
-                               gettimeofday(&p->waitingfordt,NULL);
-                               ast_setstate(ast, AST_STATE_OFFHOOK);
-                               break;
-                       }
-#ifdef HAVE_PRI
-               }
-#endif
-               if (!res) {
-                       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
-                               int saveerr = errno;
-
-                               x = DAHDI_ONHOOK;
-                               ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
-                               ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
-                               ast_mutex_unlock(&p->lock);
-                               return -1;
-                       }
-               } else
-                       ast_debug(1, "Deferring dialing...\n");
-
-               p->dialing = 1;
-               if (ast_strlen_zero(c))
-                       p->dialednone = 1;
-               ast_setstate(ast, AST_STATE_DIALING);
-               break;
-       case 0:
-               /* Special pseudo -- automatically up*/
-               ast_setstate(ast, AST_STATE_UP);
-               break;
-       case SIG_PRI:
-       case SIG_BRI:
-       case SIG_BRI_PTMP:
-       case SIG_SS7:
-       case SIG_MFCR2:
-               /* We'll get it in a moment -- but use dialdest to store pre-setup_ack digits */
-               p->dialdest[0] = '\0';
-               p->dialing = 1;
-               break;
-       default:
-               ast_debug(1, "not yet implemented\n");
-               ast_mutex_unlock(&p->lock);
-               return -1;
-       }
-#ifdef HAVE_SS7
-       if (p->ss7) {
-               char ss7_called_nai;
-               int called_nai_strip;
-               char ss7_calling_nai;
-               int calling_nai_strip;
-               const char *charge_str = NULL;
-               const char *gen_address = NULL;
-               const char *gen_digits = NULL;
-               const char *gen_dig_type = NULL;
-               const char *gen_dig_scheme = NULL;
-               const char *gen_name = NULL;
-               const char *jip_digits = NULL;
-               const char *lspi_ident = NULL;
-               const char *rlt_flag = NULL;
-               const char *call_ref_id = NULL;
-               const char *call_ref_pc = NULL;
-               const char *send_far = NULL;
-
-               c = strchr(dest, '/');
-               if (c) {
-                       c++;
-               } else {
-                       c = "";
+                       c = "";
                }
                if (strlen(c) < p->stripmsd) {
                        ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
@@ -4598,282 +4333,6 @@ static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
                ast_setstate(ast, AST_STATE_DIALING);
        }
 #endif /* HAVE_OPENR2 */
-#ifdef HAVE_PRI
-       if (p->pri) {
-               struct pri_sr *sr;
-#ifdef SUPPORT_USERUSER
-               const char *useruser;
-#endif
-               int pridialplan;
-               int dp_strip;
-               int prilocaldialplan;
-               int ldp_strip;
-               int exclusive;
-               const char *rr_str;
-               int redirect_reason;
-
-               c = strchr(dest, '/');
-               if (c) {
-                       c++;
-               } else {
-                       c = "";
-               }
-
-               l = NULL;
-               n = NULL;
-               if (!p->hidecallerid) {
-                       l = ast->connected.id.number;
-                       if (!p->hidecalleridname) {
-                               n = ast->connected.id.name;
-                       }
-               }
-
-               if (strlen(c) < p->stripmsd) {
-                       ast_log(LOG_WARNING, "Number '%s' is shorter than stripmsd (%d)\n", c, p->stripmsd);
-                       ast_mutex_unlock(&p->lock);
-                       return -1;
-               }
-               if (mysig != SIG_FXSKS) {
-                       p->dop.op = DAHDI_DIAL_OP_REPLACE;
-                       s = strchr(c + p->stripmsd, 'w');
-                       if (s) {
-                               if (strlen(s) > 1)
-                                       snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "T%s", s);
-                               else
-                                       p->dop.dialstr[0] = '\0';
-                               *s = '\0';
-                       } else {
-                               p->dop.dialstr[0] = '\0';
-                       }
-               }
-               if (pri_grab(p, p->pri)) {
-                       ast_log(LOG_WARNING, "Failed to grab PRI!\n");
-                       ast_mutex_unlock(&p->lock);
-                       return -1;
-               }
-               if (!(p->call = pri_new_call(p->pri->pri))) {
-                       ast_log(LOG_WARNING, "Unable to create call on channel %d\n", p->channel);
-                       pri_rel(p->pri);
-                       ast_mutex_unlock(&p->lock);
-                       return -1;
-               }
-               if (!(sr = pri_sr_new())) {
-                       ast_log(LOG_WARNING, "Failed to allocate setup request channel %d\n", p->channel);
-                       pri_rel(p->pri);
-                       ast_mutex_unlock(&p->lock);
-               }
-               if (p->bearer || (mysig == SIG_FXSKS)) {
-                       if (p->bearer) {
-                               ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
-                               p->bearer->call = p->call;
-                       } else
-                               ast_debug(1, "I'm being setup with no bearer right now...\n");
-
-                       pri_set_crv(p->pri->pri, p->call, p->channel, 0);
-               }
-               p->digital = IS_DIGITAL(ast->transfercapability);
-               /* Add support for exclusive override */
-               if (p->priexclusive)
-                       exclusive = 1;
-               else {
-               /* otherwise, traditional behavior */
-                       if (p->pri->nodetype == PRI_NETWORK)
-                               exclusive = 0;
-                       else
-                               exclusive = 1;
-               }
-
-               pri_sr_set_channel(sr, p->bearer ? PVT_TO_CHANNEL(p->bearer) : PVT_TO_CHANNEL(p), exclusive, 1);
-               pri_sr_set_bearer(sr, p->digital ? PRI_TRANS_CAP_DIGITAL : ast->transfercapability,
-                       (p->digital ? -1 :
-                               ((p->law == DAHDI_LAW_ALAW) ? PRI_LAYER_1_ALAW : PRI_LAYER_1_ULAW)));
-               if (p->pri->facilityenable)
-                       pri_facility_enable(p->pri->pri);
-
-               ast_verb(3, "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
-
-               dp_strip = 0;
-               pridialplan = p->pri->dialplan - 1;
-               if (pridialplan == -2 || pridialplan == -3) { /* compute dynamically */
-                       if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
-                               if (pridialplan == -2) {
-                                       dp_strip = strlen(p->pri->internationalprefix);
-                               }
-                               pridialplan = PRI_INTERNATIONAL_ISDN;
-                       } else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
-                               if (pridialplan == -2) {
-                                       dp_strip = strlen(p->pri->nationalprefix);
-                               }
-                               pridialplan = PRI_NATIONAL_ISDN;
-                       } else {
-                               pridialplan = PRI_LOCAL_ISDN;
-                       }
-               }
-               while (c[p->stripmsd] > '9' && c[p->stripmsd] != '*' && c[p->stripmsd] != '#') {
-                       switch (c[p->stripmsd]) {
-                       case 'U':
-                               pridialplan = (PRI_TON_UNKNOWN << 4) | (pridialplan & 0xf);
-                               break;
-                       case 'I':
-                               pridialplan = (PRI_TON_INTERNATIONAL << 4) | (pridialplan & 0xf);
-                               break;
-                       case 'N':
-                               pridialplan = (PRI_TON_NATIONAL << 4) | (pridialplan & 0xf);
-                               break;
-                       case 'L':
-                               pridialplan = (PRI_TON_NET_SPECIFIC << 4) | (pridialplan & 0xf);
-                               break;
-                       case 'S':
-                               pridialplan = (PRI_TON_SUBSCRIBER << 4) | (pridialplan & 0xf);
-                               break;
-                       case 'V':
-                               pridialplan = (PRI_TON_ABBREVIATED << 4) | (pridialplan & 0xf);
-                               break;
-                       case 'R':
-                               pridialplan = (PRI_TON_RESERVED << 4) | (pridialplan & 0xf);
-                               break;
-                       case 'u':
-                               pridialplan = PRI_NPI_UNKNOWN | (pridialplan & 0xf0);
-                               break;
-                       case 'e':
-                               pridialplan = PRI_NPI_E163_E164 | (pridialplan & 0xf0);
-                               break;
-                       case 'x':
-                               pridialplan = PRI_NPI_X121 | (pridialplan & 0xf0);
-                               break;
-                       case 'f':
-                               pridialplan = PRI_NPI_F69 | (pridialplan & 0xf0);
-                               break;
-                       case 'n':
-                               pridialplan = PRI_NPI_NATIONAL | (pridialplan & 0xf0);
-                               break;
-                       case 'p':
-                               pridialplan = PRI_NPI_PRIVATE | (pridialplan & 0xf0);
-                               break;
-                       case 'r':
-                               pridialplan = PRI_NPI_RESERVED | (pridialplan & 0xf0);
-                               break;
-                       default:
-                               if (isalpha(c[p->stripmsd])) {
-                                       ast_log(LOG_WARNING, "Unrecognized pridialplan %s modifier: %c\n",
-                                               c[p->stripmsd] > 'Z' ? "NPI" : "TON", c[p->stripmsd]);
-                               }
-                               break;
-                       }
-                       c++;
-               }
-               pri_sr_set_called(sr, c + p->stripmsd + dp_strip, pridialplan, s ? 1 : 0);
-
-               ldp_strip = 0;
-               prilocaldialplan = p->pri->localdialplan - 1;
-               if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) { /* compute dynamically */
-                       if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
-                               if (prilocaldialplan == -2) {
-                                       ldp_strip = strlen(p->pri->internationalprefix);
-                               }
-                               prilocaldialplan = PRI_INTERNATIONAL_ISDN;
-                       } else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
-                               if (prilocaldialplan == -2) {
-                                       ldp_strip = strlen(p->pri->nationalprefix);
-                               }
-                               prilocaldialplan = PRI_NATIONAL_ISDN;
-                       } else {
-                               prilocaldialplan = PRI_LOCAL_ISDN;
-                       }
-               }
-               if (l != NULL) {
-                       while (*l > '9' && *l != '*' && *l != '#') {
-                               switch (*l) {
-                               case 'U':
-                                       prilocaldialplan = (PRI_TON_UNKNOWN << 4) | (prilocaldialplan & 0xf);
-                                       break;
-                               case 'I':
-                                       prilocaldialplan = (PRI_TON_INTERNATIONAL << 4) | (prilocaldialplan & 0xf);
-                                       break;
-                               case 'N':
-                                       prilocaldialplan = (PRI_TON_NATIONAL << 4) | (prilocaldialplan & 0xf);
-                                       break;
-                               case 'L':
-                                       prilocaldialplan = (PRI_TON_NET_SPECIFIC << 4) | (prilocaldialplan & 0xf);
-                                       break;
-                               case 'S':
-                                       prilocaldialplan = (PRI_TON_SUBSCRIBER << 4) | (prilocaldialplan & 0xf);
-                                       break;
-                               case 'V':
-                                       prilocaldialplan = (PRI_TON_ABBREVIATED << 4) | (prilocaldialplan & 0xf);
-                                       break;
-                               case 'R':
-                                       prilocaldialplan = (PRI_TON_RESERVED << 4) | (prilocaldialplan & 0xf);
-                                       break;
-                               case 'u':
-                                       prilocaldialplan = PRI_NPI_UNKNOWN | (prilocaldialplan & 0xf0);
-                                       break;
-                               case 'e':
-                                       prilocaldialplan = PRI_NPI_E163_E164 | (prilocaldialplan & 0xf0);
-                                       break;
-                               case 'x':
-                                       prilocaldialplan = PRI_NPI_X121 | (prilocaldialplan & 0xf0);
-                                       break;
-                               case 'f':
-                                       prilocaldialplan = PRI_NPI_F69 | (prilocaldialplan & 0xf0);
-                                       break;
-                               case 'n':
-                                       prilocaldialplan = PRI_NPI_NATIONAL | (prilocaldialplan & 0xf0);
-                                       break;
-                               case 'p':
-                                       prilocaldialplan = PRI_NPI_PRIVATE | (prilocaldialplan & 0xf0);
-                                       break;
-                               case 'r':
-                                       prilocaldialplan = PRI_NPI_RESERVED | (prilocaldialplan & 0xf0);
-                                       break;
-                               default:
-                                       if (isalpha(*l)) {
-                                               ast_log(LOG_WARNING,
-                                                       "Unrecognized prilocaldialplan %s modifier: %c\n",
-                                                       *l > 'Z' ? "NPI" : "TON", *l);
-                                       }
-                                       break;
-                               }
-                               l++;
-                       }
-               }
-               pri_sr_set_caller(sr, l ? (l + ldp_strip) : NULL, n, prilocaldialplan,
-                       p->use_callingpres ? ast->connected.id.number_presentation : (l ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_NUMBER_NOT_AVAILABLE));
-               if ((rr_str = pbx_builtin_getvar_helper(ast, "PRIREDIRECTREASON"))) {
-                       if (!strcasecmp(rr_str, "UNKNOWN"))
-                               redirect_reason = 0;
-                       else if (!strcasecmp(rr_str, "BUSY"))
-                               redirect_reason = 1;
-                       else if (!strcasecmp(rr_str, "NO_REPLY"))
-                               redirect_reason = 2;
-                       else if (!strcasecmp(rr_str, "UNCONDITIONAL"))
-                               redirect_reason = 15;
-                       else
-                               redirect_reason = PRI_REDIR_UNCONDITIONAL;
-               } else
-                       redirect_reason = PRI_REDIR_UNCONDITIONAL;
-               pri_sr_set_redirecting(sr, ast->cid.cid_rdnis, p->pri->localdialplan - 1, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, redirect_reason);
-
-#ifdef SUPPORT_USERUSER
-               /* User-user info */
-               useruser = pbx_builtin_getvar_helper(p->owner, "USERUSERINFO");
-               if (useruser)
-                       pri_sr_set_useruser(sr, useruser);
-#endif
-
-               if (pri_setup(p->pri->pri, p->call, sr)) {
-                       ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
-                               c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
-                       pri_rel(p->pri);
-                       ast_mutex_unlock(&p->lock);
-                       pri_sr_free(sr);
-                       return -1;
-               }
-               pri_sr_free(sr);
-               ast_setstate(ast, AST_STATE_DIALING);
-               pri_rel(p->pri);
-       }
-#endif
        ast_mutex_unlock(&p->lock);
        return 0;
 }
@@ -4994,14 +4453,13 @@ static void destroy_all_channels(void)
        ast_mutex_unlock(&iflock);
 }
 
-#if defined(HAVE_PRI)
+#ifdef HAVE_PRI
 static char *dahdi_send_keypad_facility_app = "DAHDISendKeypadFacility";
 
-static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *data)
+static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char *digits)
 {
        /* Data will be our digit string */
        struct dahdi_pvt *p;
-       const char *digits = data;
 
        if (ast_strlen_zero(digits)) {
                ast_debug(1, "No digit string sent to application!\n");
@@ -5015,24 +4473,7 @@ static int dahdi_send_keypad_facility_exec(struct ast_channel *chan, const char
                return -1;
        }
 
-       ast_mutex_lock(&p->lock);
-
-       if (!p->pri || !p->call) {
-               ast_debug(1, "Unable to find pri or call on channel!\n");
-               ast_mutex_unlock(&p->lock);
-               return -1;
-       }
-
-       if (!pri_grab(p, p->pri)) {
-               pri_keypad_facility(p->pri->pri, p->call, digits);
-               pri_rel(p->pri);
-       } else {
-               ast_debug(1, "Unable to grab pri to send keypad facility!\n");
-               ast_mutex_unlock(&p->lock);
-               return -1;
-       }
-
-       ast_mutex_unlock(&p->lock);
+       pri_send_keypad_facility_exec(p->sig_pvt, digits);
 
        return 0;
 }
@@ -5084,126 +4525,12 @@ static int dahdi_send_callrerouting_facility_exec(struct ast_channel *chan, cons
                args.reason = NULL;
        }
 
-       ast_mutex_lock(&p->lock);
+       pri_send_callrerouting_facility_exec(p->sig_pvt, chan->_state, args.destination, args.original, args.reason);
 
-       if (!p->pri || !p->call) {
-               ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
-               ast_mutex_unlock(&p->lock);
-               return -1;
-       }
-
-       switch (p->sig) {
-       case SIG_PRI:
-               if (!pri_grab(p, p->pri)) {
-                       if (chan->_state == AST_STATE_RING) {
-                               res = pri_callrerouting_facility(p->pri->pri, p->call, args.destination, args.original, args.reason);
-                       }
-                       pri_rel(p->pri);
-               } else {
-                       ast_log(LOG_DEBUG, "Unable to grab pri to send callrerouting facility on span %d!\n", p->span);
-                       ast_mutex_unlock(&p->lock);
-                       return -1;
-               }
-               break;
-       }
-
-       ast_mutex_unlock(&p->lock);
-
-       return res;
-}
-#endif /* defined(HAVE_PRI_PROG_W_CAUSE) */
-#endif /* defined(HAVE_PRI) */
-
-#if defined(HAVE_PRI)
-static int pri_is_up(struct dahdi_pri *pri)
-{
-       int x;
-       for (x = 0; x < NUM_DCHANS; x++) {
-               if (pri->dchanavail[x] == DCHAN_AVAILABLE)
-                       return 1;
-       }
-       return 0;
-}
-#endif /* defined(HAVE_PRI) */
-
-#if defined(HAVE_PRI)
-static int pri_assign_bearer(struct dahdi_pvt *crv, struct dahdi_pri *pri, struct dahdi_pvt *bearer)
-{
-       bearer->owner = &inuse;
-       bearer->realcall = crv;
-       crv->subs[SUB_REAL].dfd = bearer->subs[SUB_REAL].dfd;
-       if (crv->subs[SUB_REAL].owner)
-               ast_channel_set_fd(crv->subs[SUB_REAL].owner, 0, crv->subs[SUB_REAL].dfd);
-       crv->bearer = bearer;
-       crv->call = bearer->call;
-       crv->pri = pri;
-       return 0;
-}
-#endif /* defined(HAVE_PRI) */
-
-#if defined(HAVE_PRI)
-static char *pri_order(int level)
-{
-       switch (level) {
-       case 0:
-               return "Primary";
-       case 1:
-               return "Secondary";
-       case 2:
-               return "Tertiary";
-       case 3:
-               return "Quaternary";
-       default:
-               return "<Unknown>";
-       }
-}
-#endif /* defined(HAVE_PRI) */
-
-#if defined(HAVE_PRI)
-/* Returns fd of the active dchan */
-static int pri_active_dchan_fd(struct dahdi_pri *pri)
-{
-       int x = -1;
-
-       for (x = 0; x < NUM_DCHANS; x++) {
-               if ((pri->dchans[x] == pri->pri))
-                       break;
-       }
-
-       return pri->fds[x];
-}
-#endif /* defined(HAVE_PRI) */
-
-#if defined(HAVE_PRI)
-static int pri_find_dchan(struct dahdi_pri *pri)
-{
-       int oldslot = -1;
-       struct pri *old;
-       int newslot = -1;
-       int x;
-       old = pri->pri;
-       for (x = 0; x < NUM_DCHANS; x++) {
-               if ((pri->dchanavail[x] == DCHAN_AVAILABLE) && (newslot < 0))
-                       newslot = x;
-               if (pri->dchans[x] == old) {
-                       oldslot = x;
-               }
-       }
-       if (newslot < 0) {
-               newslot = 0;
-               /* This is annoying to see on non persistent layer 2 connections.  Let's not complain in that case */
-               if (pri->sig != SIG_BRI_PTMP) {
-                       ast_log(LOG_WARNING, "No D-channels available!  Using Primary channel %d as D-channel anyway!\n",
-                               pri->dchannels[newslot]);
-               }
-       }
-       if (old && (oldslot != newslot))
-               ast_log(LOG_NOTICE, "Switching from from d-channel %d to channel %d!\n",
-                       pri->dchannels[oldslot], pri->dchannels[newslot]);
-       pri->pri = pri->dchans[newslot];
-       return 0;
-}
-#endif /* defined(HAVE_PRI) */
+       return res;
+}
+#endif /* defined(HAVE_PRI_PROG_W_CAUSE) */
+#endif /* defined(HAVE_PRI) */
 
 #if defined(HAVE_OPENR2)
 static const char * const dahdi_accept_r2_call_app = "DAHDIAcceptR2Call";
@@ -5350,8 +4677,8 @@ static openr2_call_disconnect_cause_t dahdi_ast_cause_to_r2_cause(int cause)
 
 static int dahdi_hangup(struct ast_channel *ast)
 {
-       int res;
-       int idx,x, law;
+       int res = 0;
+       int idx,x;
        /*static int restore_gains(struct dahdi_pvt *p);*/
        struct dahdi_pvt *p = ast->tech_pvt;
        struct dahdi_pvt *tmp = NULL;
@@ -5396,7 +4723,32 @@ static int dahdi_hangup(struct ast_channel *ast)
 
        idx = dahdi_get_index(ast, p, 1);
 
-       if ((p->sig == SIG_PRI) || (p->sig == SIG_SS7) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
+#ifdef HAVE_PRI
+       if (p->sig == SIG_PRI || p->sig == SIG_BRI || p->sig == SIG_BRI_PTMP) {
+               int law;
+               x = 1;
+               ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
+               dahdi_confmute(p, 0);
+               restore_gains(p);
+               if (p->dsp) {
+                       ast_dsp_free(p->dsp);
+                       p->dsp = NULL;
+               }
+               dahdi_setlinear(p->subs[SUB_REAL].dfd, 0);
+               law = DAHDI_LAW_DEFAULT;
+               res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
+               if (p->sig)
+                       dahdi_disable_ec(p);
+               update_conf(p);
+               reset_conf(p);
+               sig_pri_hangup(p->sig_pvt, ast);
+               p->subs[SUB_REAL].owner = NULL;
+               p->owner = NULL;
+               goto hangup_out;
+       }
+#endif
+
+       if (p->sig == SIG_SS7) {
                x = 1;
                ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
        }
@@ -5563,8 +4915,6 @@ static int dahdi_hangup(struct ast_channel *ast)
                        p->bufferoverrideinuse = 0;
                }
 
-               law = DAHDI_LAW_DEFAULT;
-               res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_SETLAW, &law);
                if (res < 0)
                        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 */
@@ -5608,59 +4958,6 @@ static int dahdi_hangup(struct ast_channel *ast)
                        dahdi_r2_update_monitor_count(p->mfcr2, 1);
                }
 #endif
-#ifdef HAVE_PRI
-               if (p->pri) {
-#ifdef SUPPORT_USERUSER
-                       const char *useruser = pbx_builtin_getvar_helper(ast,"USERUSERINFO");
-#endif
-
-                       /* Make sure we have a call (or REALLY have a call in the case of a PRI) */
-                       if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
-                               if (!pri_grab(p, p->pri)) {
-                                       if (p->alreadyhungup) {
-                                               ast_debug(1, "Already hungup...  Calling hangup once, and clearing call\n");
-
-#ifdef SUPPORT_USERUSER
-                                               pri_call_set_useruser(p->call, useruser);
-#endif
-
-                                               pri_hangup(p->pri->pri, p->call, -1);
-                                               p->call = NULL;
-                                               if (p->bearer)
-                                                       p->bearer->call = NULL;
-                                       } else {
-                                               const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
-                                               int icause = ast->hangupcause ? ast->hangupcause : -1;
-                                               ast_debug(1, "Not yet hungup...  Calling hangup once with icause, and clearing call\n");
-
-#ifdef SUPPORT_USERUSER
-                                               pri_call_set_useruser(p->call, useruser);
-#endif
-
-                                               p->alreadyhungup = 1;
-                                               if (p->bearer)
-                                                       p->bearer->alreadyhungup = 1;
-                                               if (cause) {
-                                                       if (atoi(cause))
-                                                               icause = atoi(cause);
-                                               }
-                                               pri_hangup(p->pri->pri, p->call, icause);
-                                       }
-                                       if (res < 0)
-                                               ast_log(LOG_WARNING, "pri_disconnect failed\n");
-                                       pri_rel(p->pri);
-                               } else {
-                                       ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
-                                       res = -1;
-                               }
-                       } else {
-                               if (p->bearer)
-                                       ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
-                               p->call = NULL;
-                               res = 0;
-                       }
-               }
-#endif
                if (p->sig && ((p->sig != SIG_PRI) && (p->sig != SIG_SS7)
                        && (p->sig != SIG_BRI)
                        && (p->sig != SIG_BRI_PTMP))
@@ -5719,20 +5016,6 @@ static int dahdi_hangup(struct ast_channel *ast)
                        x = 0;
                        ast_channel_setoption(ast,AST_OPTION_AUDIO_MODE,&x,sizeof(char),0);
                }
-#ifdef HAVE_PRI
-               if (p->bearer) {
-                       ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel);
-                       /* Free up the bearer channel as well, and
-                          don't use its file descriptor anymore */
-                       update_conf(p->bearer);
-                       reset_conf(p->bearer);
-                       p->bearer->owner = NULL;
-                       p->bearer->realcall = NULL;
-                       p->bearer = NULL;
-                       p->subs[SUB_REAL].dfd = -1;
-                       p->pri = NULL;
-               }
-#endif
                if (num_restart_pending == 0)
                        restart_monitor();
        }
@@ -5778,7 +5061,6 @@ static int dahdi_answer(struct ast_channel *ast)
        struct dahdi_pvt *p = ast->tech_pvt;
        int res = 0;
        int idx;
-       int oldstate = ast->_state;
        ast_setstate(ast, AST_STATE_UP);
        ast_mutex_lock(&p->lock);
        idx = dahdi_get_index(ast, p, 0);
@@ -5795,68 +5077,15 @@ static int dahdi_answer(struct ast_channel *ast)
                ast_mutex_unlock(&p->lock);
                return res;
        }
-
-       switch (p->sig) {
-       case SIG_FXSLS:
-       case SIG_FXSGS:
-       case SIG_FXSKS:
-               p->ringt = 0;
-               /* Fall through */
-       case SIG_EM:
-       case SIG_EM_E1:
-       case SIG_EMWINK:
-       case SIG_FEATD:
-       case SIG_FEATDMF:
-       case SIG_FEATDMF_TA:
-       case SIG_E911:
-       case SIG_FGC_CAMA:
-       case SIG_FGC_CAMAMF:
-       case SIG_FEATB:
-       case SIG_SF:
-       case SIG_SFWINK:
-       case SIG_SF_FEATD:
-       case SIG_SF_FEATDMF:
-       case SIG_SF_FEATB:
-       case SIG_FXOLS:
-       case SIG_FXOGS:
-       case SIG_FXOKS:
-               /* Pick up the line */
-               ast_debug(1, "Took %s off hook\n", ast->name);
-               if (p->hanguponpolarityswitch) {
-                       p->polaritydelaytv = ast_tvnow();
-               }
-               res = dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
-               tone_zone_play_tone(p->subs[idx].dfd, -1);
-               p->dialing = 0;
-               if ((idx == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
-                       if (oldstate == AST_STATE_RINGING) {
-                               ast_debug(1, "Finally swapping real and threeway\n");
-                               tone_zone_play_tone(p->subs[SUB_THREEWAY].dfd, -1);
-                               swap_subs(p, SUB_THREEWAY, SUB_REAL);
-                               p->owner = p->subs[SUB_REAL].owner;
-                       }
-               }
-               if (p->sig & __DAHDI_SIG_FXS) {
-                       dahdi_enable_ec(p);
-                       dahdi_train_ec(p);
-               }
-               break;
 #ifdef HAVE_PRI
-       case SIG_BRI:
-       case SIG_BRI_PTMP:
-       case SIG_PRI:
-               /* Send a pri acknowledge */
-               if (!pri_grab(p, p->pri)) {
-                       p->proceeding = 1;
-                       p->dialing = 0;
-                       res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
-                       pri_rel(p->pri);
-               } else {
-                       ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
-                       res = -1;
-               }
-               break;
+       if (p->sig == SIG_PRI || p->sig == SIG_BRI || p->sig == SIG_BRI_PTMP) {
+               res = sig_pri_answer(p->sig_pvt, ast);
+               ast_mutex_unlock(&p->lock);
+               return res;
+       }
 #endif
+
+       switch (p->sig) {
 #ifdef HAVE_SS7
        case SIG_SS7:
                if (!ss7_grab(p, p->ss7)) {
@@ -6605,8 +5834,8 @@ static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_ch
                }
 
 #ifdef PRI_2BCT
-               q931c0 = p0->call;
-               q931c1 = p1->call;
+               q931c0 = ((struct sig_pri_chan *)(p0->sig_pvt))->call;
+               q931c1 = ((struct sig_pri_chan *)(p1->sig_pvt))->call;
                if (p0->transfer && p1->transfer
                        && q931c0 && q931c1
                        && !triedtopribridge) {
@@ -6961,7 +6190,7 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
                p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
                ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
 #ifdef HAVE_PRI
-               if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
+               if (!((struct sig_pri_chan *)(p->sig_pvt))->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
                        /* absorb event */
                } else {
 #endif
@@ -7084,28 +6313,13 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
                break;
        case DAHDI_EVENT_ALARM:
 #ifdef HAVE_PRI
-               if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
-                       if (!p->pri || !p->pri->pri || (pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0)) {
-                               /* T309 is not enabled : hangup calls when alarm occurs */
-                               if (p->call) {
-                                       if (p->pri && p->pri->pri) {
-                                               if (!pri_grab(p, p->pri)) {
-                                                       pri_hangup(p->pri->pri, p->call, -1);
-                                                       pri_destroycall(p->pri->pri, p->call);
-                                                       p->call = NULL;
-                                                       pri_rel(p->pri);
-                                               } else
-                                                       ast_log(LOG_WARNING, "Failed to grab PRI!\n");
-                                       } else
-                                               ast_log(LOG_WARNING, "The PRI Call has not been destroyed\n");
-                               }
+                       if (p->sig == SIG_PRI || p->sig == SIG_BRI || p->sig == SIG_BRI_PTMP) {
+                               sig_pri_chan_alarm_notify(p->sig_pvt, 0);
+
+                       } else {
                                if (p->owner)
                                        p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
                        }
-               }
-               if (p->bearer)
-                       p->bearer->inalarm = 1;
-               else
 #endif
                p->inalarm = 1;
                res = get_alarms(p);
@@ -7430,28 +6644,15 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
                        break;
                }
                break;
-       case DAHDI_EVENT_RINGEROFF:
-               if (p->inalarm) break;
-               if ((p->radio || (p->oprmode < 0))) break;
-               ast->rings++;
-               if ((ast->rings > p->cidrings) && (p->cidspill)) {
-                       ast_log(LOG_WARNING, "Didn't finish Caller-ID spill.  Cancelling.\n");
-                       ast_free(p->cidspill);
-                       p->cidspill = NULL;
-                       p->callwaitcas = 0;
-               }
-               p->subs[idx].f.frametype = AST_FRAME_CONTROL;
-               p->subs[idx].f.subclass = AST_CONTROL_RINGING;
-               break;
        case DAHDI_EVENT_RINGERON:
                break;
        case DAHDI_EVENT_NOALARM:
-               p->inalarm = 0;
 #ifdef HAVE_PRI
-               /* Extremely unlikely but just in case */
-               if (p->bearer)
-                       p->bearer->inalarm = 0;
+               if (p->sig == SIG_PRI || p->sig == SIG_BRI || p->sig == SIG_BRI_PTMP) {
+                       sig_pri_chan_alarm_notify(p->sig_pvt, 1);
+               }
 #endif
+               p->inalarm = 0;
                ast_log(LOG_NOTICE, "Alarm cleared on channel %d\n", p->channel);
                manager_event(EVENT_FLAG_SYSTEM, "AlarmClear",
                                                        "Channel: %d\r\n", p->channel);
@@ -7803,12 +7004,11 @@ winkflashdone:
 
 static struct ast_frame *__dahdi_exception(struct ast_channel *ast)
 {
-       struct dahdi_pvt *p = ast->tech_pvt;
        int res;
-       int usedindex=-1;
        int idx;
        struct ast_frame *f;
-
+       int usedindex = -1;
+       struct dahdi_pvt *p = ast->tech_pvt;
 
        idx = dahdi_get_index(ast, p, 1);
 
@@ -8217,7 +7417,7 @@ static struct ast_frame *dahdi_read(struct ast_channel *ast)
                                }
                        } else if (f->frametype == AST_FRAME_DTMF) {
 #ifdef HAVE_PRI
-                               if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri &&
+                               if (!((struct sig_pri_chan *)(p->sig_pvt))->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri &&
                                        ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) ||
                                        (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
                                        /* Don't accept in-band DTMF when in overlap dial mode */
@@ -8401,51 +7601,19 @@ static int dahdi_indicate(struct ast_channel *chan, int condition, const void *d
                return 0;
        }
 #endif
+#ifdef HAVE_PRI
+       if (p->sig == SIG_PRI || p->sig == SIG_BRI || p->sig == SIG_BRI_PTMP) {
+               res = sig_pri_indicate(p->sig_pvt, chan, condition, data, datalen);
+               ast_mutex_unlock(&p->lock);
+               return res;
+       }
+#endif
        if (idx == SUB_REAL) {
                switch (condition) {
                case AST_CONTROL_BUSY:
-#ifdef HAVE_PRI
-                       if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
-                               chan->hangupcause = AST_CAUSE_USER_BUSY;
-                               chan->_softhangup |= AST_SOFTHANGUP_DEV;
-                               res = 0;
-                       } else if (!p->progress &&
-                                       ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
-                                       && p->pri && !p->outgoing) {
-                               if (p->pri->pri) {
-                                       if (!pri_grab(p, p->pri)) {
-#ifdef HAVE_PRI_PROG_W_CAUSE
-                                               pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, PRI_CAUSE_USER_BUSY); /* cause = 17 */
-#else
-                                               pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
-#endif
-                                               pri_rel(p->pri);
-                                       }
-                                       else
-                                               ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
-                               }
-                               p->progress = 1;
-                               res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
-                       } else
-#endif
-                               res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
+                       res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
                        break;
                case AST_CONTROL_RINGING:
-#ifdef HAVE_PRI
-                       if ((!p->alerting) && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
-                                       && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
-                               if (p->pri->pri) {
-                                       if (!pri_grab(p, p->pri)) {
-                                               pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
-                                               pri_rel(p->pri);
-                                       }
-                                       else
-                                               ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
-                               }
-                               p->alerting = 1;
-                       }
-
-#endif
 #ifdef HAVE_SS7
                        if ((!p->alerting) && (p->sig == SIG_SS7) && p->ss7 && !p->outgoing && (chan->_state != AST_STATE_UP)) {
                                if (p->ss7->ss7) {
@@ -8473,21 +7641,6 @@ static int dahdi_indicate(struct ast_channel *chan, int condition, const void *d
                        break;
                case AST_CONTROL_PROCEEDING:
                        ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
-#ifdef HAVE_PRI
-                       if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
-                                       && p->pri && !p->outgoing) {
-                               if (p->pri->pri) {
-                                       if (!pri_grab(p, p->pri)) {
-                                               pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
-                                               pri_rel(p->pri);
-                                       }
-                                       else
-                                               ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
-                               }
-                               p->proceeding = 1;
-                               p->dialing = 0;
-                       }
-#endif
 #ifdef HAVE_SS7
                        /* This IF sends the FAR for an answered ALEG call */
                        if (chan->_state == AST_STATE_UP && (p->rlt != 1) && (p->sig == SIG_SS7)){
@@ -8510,25 +7663,6 @@ static int dahdi_indicate(struct ast_channel *chan, int condition, const void *d
                        break;
                case AST_CONTROL_PROGRESS:
                        ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
-#ifdef HAVE_PRI
-                       p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */
-                       if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
-                                       && p->pri && !p->outgoing) {
-                               if (p->pri->pri) {
-                                       if (!pri_grab(p, p->pri)) {
-#ifdef HAVE_PRI_PROG_W_CAUSE
-                                               pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, -1);  /* no cause at all */
-#else
-                                               pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
-#endif
-                                               pri_rel(p->pri);
-                                       }
-                                       else
-                                               ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
-                               }
-                               p->progress = 1;
-                       }
-#endif
 #ifdef HAVE_SS7
                        if (!p->progress && p->sig==SIG_SS7 && p->ss7 && !p->outgoing) {
                                if (p->ss7->ss7) {
@@ -8547,53 +7681,12 @@ static int dahdi_indicate(struct ast_channel *chan, int condition, const void *d
                        break;
                case AST_CONTROL_CONGESTION:
                        chan->hangupcause = AST_CAUSE_CONGESTION;
-#ifdef HAVE_PRI
-                       if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
-                               chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
-                               chan->_softhangup |= AST_SOFTHANGUP_DEV;
-                               res = 0;
-                       } else if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
-                                       && p->pri && !p->outgoing) {
-                               if (p->pri) {
-                                       if (!pri_grab(p, p->pri)) {
-#ifdef HAVE_PRI_PROG_W_CAUSE
-                                               pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, PRI_CAUSE_SWITCH_CONGESTION); /* cause = 42 */
-#else
-                                               pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
-#endif
-                                               pri_rel(p->pri);
-                                       } else
-                                               ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
-                               }
-                               p->progress = 1;
-                               res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
-                       } else
-#endif
-                               res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
                        break;
                case AST_CONTROL_HOLD:
-#ifdef HAVE_PRI
-                       if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
-                               if (!pri_grab(p, p->pri)) {
-                                       res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_HOLD);
-                                       pri_rel(p->pri);
-                               } else
-                                               ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
-                       } else
-#endif
-                               ast_moh_start(chan, data, p->mohinterpret);
+                       ast_moh_start(chan, data, p->mohinterpret);
                        break;
                case AST_CONTROL_UNHOLD:
-#ifdef HAVE_PRI
-                       if (p->pri && !strcasecmp(p->mohinterpret, "passthrough")) {
-                               if (!pri_grab(p, p->pri)) {
-                                       res = pri_notify(p->pri->pri, p->call, p->prioffset, PRI_NOTIFY_REMOTE_RETRIEVAL);
-                                       pri_rel(p->pri);
-                               } else
-                                               ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
-                       } else
-#endif
-                               ast_moh_stop(chan);
+                       ast_moh_stop(chan);
                        break;
                case AST_CONTROL_RADIO_KEY:
                        if (p->radio)
@@ -8648,11 +7741,6 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb
        y = 1;
        chan_name = ast_str_alloca(32);
        do {
-#ifdef HAVE_PRI
-               if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
-                       ast_str_set(&chan_name, 0, "%d:%d-%d", i->pri->trunkgroup, i->channel, y);
-               else
-#endif
                if (i->channel == CHAN_PSEUDO)
                        ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
                else
@@ -8724,9 +7812,9 @@ static struct ast_channel *dahdi_new(struct dahdi_pvt *i, int state, int startpb
                                i->dsp = NULL;
                        if (i->dsp) {
                                i->dsp_features = features;
-#if defined(HAVE_PRI) || defined(HAVE_SS7)
+#if 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))) {
+                               if (i->outgoing && (i->sig == SIG_SS7)) {
                                        /* Remember requested DSP features, don't treat
                                           talking as ANSWER */
                                        i->dsp_features = features & ~DSP_PROGRESS_TALK;
@@ -8937,62 +8025,6 @@ static void *analog_ss_thread(void *data)
        if (p->dsp)
                ast_dsp_digitreset(p->dsp);
        switch (p->sig) {
-#ifdef HAVE_PRI
-       case SIG_PRI:
-       case SIG_BRI:
-       case SIG_BRI_PTMP:
-               /* Now loop looking for an extension */
-               ast_copy_string(exten, p->exten, sizeof(exten));
-               len = strlen(exten);
-               res = 0;
-               while ((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
-                       if (len && !ast_ignore_pattern(chan->context, exten))
-                               tone_zone_play_tone(p->subs[idx].dfd, -1);
-                       else
-                               tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_DIALTONE);
-                       if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num))
-                               timeout = matchdigittimeout;
-                       else
-                               timeout = gendigittimeout;
-                       res = ast_waitfordigit(chan, timeout);
-                       if (res < 0) {
-                               ast_debug(1, "waitfordigit returned < 0...\n");
-                               ast_hangup(chan);
-                               goto quit;
-                       } else if (res) {
-                               exten[len++] = res;
-                               exten[len] = '\0';
-                       } else
-                               break;
-               }
-               /* if no extension was received ('unspecified') on overlap call, use the 's' extension */
-               if (ast_strlen_zero(exten)) {
-                       ast_verb(3, "Going to extension s|1 because of empty extension received on overlap call\n");
-                       exten[0] = 's';
-                       exten[1] = '\0';
-               }
-               tone_zone_play_tone(p->subs[idx].dfd, -1);
-               if (ast_exists_extension(chan, chan->context, exten, 1, p->cid_num)) {
-                       /* Start the real PBX */
-                       ast_copy_string(chan->exten, exten, sizeof(chan->exten));
-                       if (p->dsp) ast_dsp_digitreset(p->dsp);
-                       dahdi_enable_ec(p);
-                       ast_setstate(chan, AST_STATE_RING);
-                       res = ast_pbx_run(chan);
-                       if (res) {
-                               ast_log(LOG_WARNING, "PBX exited non-zero!\n");
-                       }
-               } else {
-                       ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
-                       chan->hangupcause = AST_CAUSE_UNALLOCATED;
-                       ast_hangup(chan);
-                       p->exten[0] = '\0';
-                       /* Since we send release complete here, we won't get one */
-                       p->call = NULL;
-               }
-               goto quit;
-               break;
-#endif
        case SIG_FEATD:
        case SIG_FEATDMF:
        case SIG_FEATDMF_TA:
@@ -9517,37 +8549,6 @@ static void *analog_ss_thread(void *data)
        case SIG_FXSLS:
        case SIG_FXSGS:
        case SIG_FXSKS:
-#ifdef HAVE_PRI
-               if (p->pri) {
-                       /* This is a GR-303 trunk actually.  Wait for the first ring... */
-                       struct ast_frame *f;
-                       int res;
-                       time_t start;
-
-                       time(&start);
-                       ast_setstate(chan, AST_STATE_RING);
-                       while (time(NULL) < start + 3) {
-                               res = ast_waitfor(chan, 1000);
-                               if (res) {
-                                       f = ast_read(chan);
-                                       if (!f) {
-                                               ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
-                                               ast_hangup(chan);
-                                               goto quit;
-                                       } else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
-                                               res = 1;
-                                       } else
-                                               res = 0;
-                                       ast_frfree(f);
-                                       if (res) {
-                                               ast_debug(1, "Got ring!\n");
-                                               res = 0;
-                                               break;
-                                       }
-                               }
-                       }
-               }
-#endif
                /* check for SMDI messages */
                if (p->use_smdi && p->smdi_iface) {
                        smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT);
@@ -10598,12 +9599,6 @@ static int handle_init_event(struct dahdi_pvt *i, int event)
                case SIG_FXSLS:
                case SIG_FXSGS:
                case SIG_FXSKS:
-               case SIG_GR303FXSKS:
-                       dahdi_disable_ec(i);
-                       res = tone_zone_play_tone(i->subs[SUB_REAL].dfd, -1);
-                       dahdi_set_hook(i->subs[SUB_REAL].dfd, DAHDI_ONHOOK);
-                       break;
-               case SIG_GR303FXOKS:
                case SIG_FXOKS:
                        dahdi_disable_ec(i);
                        /* Diddle the battery for the zhone */
@@ -10946,7 +9941,7 @@ static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spa
        if (trunkgroup) {
                /* Select a specific trunk group */
                for (x = 0; x < NUM_SPANS; x++) {
-                       if (pris[x].trunkgroup == trunkgroup) {
+                       if (pris[x].pri.trunkgroup == trunkgroup) {
                                *span = x;
                                return 0;
                        }
@@ -10954,8 +9949,8 @@ static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spa
                ast_log(LOG_WARNING, "Channel %d on span %d configured to use nonexistent trunk group %d\n", channel, *span, trunkgroup);
                *span = -1;
        } else {
-               if (pris[*span].trunkgroup) {
-                       ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].trunkgroup);
+               if (pris[*span].pri.trunkgroup) {
+                       ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is trunk group %d (please use spanmap)\n", *span, pris[*span].pri.trunkgroup);
                        *span = -1;
                } else if (pris[*span].mastertrunkgroup) {
                        ast_log(LOG_WARNING, "Unable to use span %d implicitly since it is already part of trunk group %d\n", *span, pris[*span].mastertrunkgroup);
@@ -10975,9 +9970,7 @@ static int pri_resolve_span(int *span, int channel, int offset, struct dahdi_spa
                                *span = -1;
                                return 0;
                        }
-                       pris[*span].dchanavail[0] |= DCHAN_PROVISIONED;
-                       pris[*span].offset = offset;
-                       pris[*span].span = *span + 1;
+                       pris[*span].pri.span = *span + 1;
                }
        }
        return 0;
@@ -10994,7 +9987,7 @@ static int pri_create_trunkgroup(int trunkgroup, int *channels)
        int ospan=0;
        int x,y;
        for (x = 0; x < NUM_SPANS; x++) {
-               if (pris[x].trunkgroup == trunkgroup) {
+               if (pris[x].pri.trunkgroup == trunkgroup) {
                        ast_log(LOG_WARNING, "Trunk group %d already exists on span %d, Primary d-channel %d\n", trunkgroup, x + 1, pris[x].dchannels[0]);
                        return -1;
                }
@@ -11025,24 +10018,22 @@ static int pri_create_trunkgroup(int trunkgroup, int *channels)
                        return -1;
                }
                span = p.spanno - 1;
-               if (pris[span].trunkgroup) {
-                       ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].trunkgroup);
+               if (pris[span].pri.trunkgroup) {
+                       ast_log(LOG_WARNING, "Span %d is already provisioned for trunk group %d\n", span + 1, pris[span].pri.trunkgroup);
                        close(fd);
                        return -1;
                }
-               if (pris[span].pvts[0]) {
+               if (pris[span].pri.pvts[0]) {
                        ast_log(LOG_WARNING, "Span %d is already provisioned with channels (implicit PRI maybe?)\n", span + 1);
                        close(fd);
                        return -1;
                }
                if (!y) {
-                       pris[span].trunkgroup = trunkgroup;
-                       pris[span].offset = channels[y] - p.chanpos;
+                       pris[span].pri.trunkgroup = trunkgroup;
                        ospan = span;
                }
                pris[ospan].dchannels[y] = channels[y];
-               pris[ospan].dchanavail[y] |= DCHAN_PROVISIONED;
-               pris[span].span = span + 1;
+               pris[span].pri.span = span + 1;
                close(fd);
        }
        return 0;
@@ -11197,7 +10188,7 @@ static int sigtype_to_signalling(int sigtype)
        return sigtype;
 }
 
-static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, struct dahdi_pri *pri, int reloading)
+static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, int reloading)
 {
        /* Make a dahdi_pvt structure for this interface (or CRV if "pri" is specified) */
        struct dahdi_pvt *tmp = NULL, *tmp2, *prev = NULL;
@@ -11212,17 +10203,14 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
        struct dahdi_pvt **wend;
        struct analog_pvt *analog_p = NULL;
        struct dahdi_params p;
+#ifdef HAVE_PRI
+       struct dahdi_spaninfo si;
+       struct sig_pri_chan *pchan = NULL;
+#endif
 
        wlist = &iflist;
        wend = &ifend;
 
-#ifdef HAVE_PRI
-       if (pri) {
-               wlist = &pri->crvs;
-               wend = &pri->crvend;
-       }
-#endif
-
        tmp2 = *wlist;
        prev = NULL;
 
@@ -11255,7 +10243,7 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
        if (tmp) {
                int chan_sig = conf->chan.sig;
                if (!here) {
-                       if ((channel != CHAN_PSEUDO) && !pri) {
+                       if ((channel != CHAN_PSEUDO)) {
                                int count = 0;
                                snprintf(fn, sizeof(fn), "%d", channel);
                                /* Open non-blocking */
@@ -11399,14 +10387,13 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
                        }
 #endif
 #ifdef HAVE_PRI
-                       if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_GR303FXOKS) || (chan_sig == SIG_GR303FXSKS)) {
+                       if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP)) {
                                int offset;
-                               int myswitchtype;
                                int matchesdchan;
                                int x,y;
+                               int myswitchtype = 0;
                                offset = 0;
-                               if (((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP))
-                                               && ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &offset)) {
+                               if (ioctl(tmp->subs[SUB_REAL].dfd, 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);
                                        return NULL;
@@ -11416,7 +10403,6 @@ 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].dfd,DAHDI_SPANSTAT,&si) == -1) {
                                                ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
@@ -11431,12 +10417,7 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
                                                destroy_dahdi_pvt(&tmp);
                                                return NULL;
                                        }
-                                       if ((chan_sig == SIG_PRI) ||
-                                                       (chan_sig == SIG_BRI) ||
-                                                       (chan_sig == SIG_BRI_PTMP))
-                                               myswitchtype = conf->pri.switchtype;
-                                       else
-                                               myswitchtype = PRI_SWITCH_GR303_TMC;
+                                       myswitchtype = conf->pri.pri.switchtype;
                                        /* Make sure this isn't a d-channel */
                                        matchesdchan=0;
                                        for (x = 0; x < NUM_SPANS; x++) {
@@ -11448,85 +10429,92 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
                                                }
                                        }
                                        if (!matchesdchan) {
-                                               if (pris[span].nodetype && (pris[span].nodetype != conf->pri.nodetype)) {
-                                                       ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].nodetype));
+                                               if (pris[span].pri.nodetype && (pris[span].pri.nodetype != conf->pri.pri.nodetype)) {
+                                                       ast_log(LOG_ERROR, "Span %d is already a %s node\n", span + 1, pri_node2str(pris[span].pri.nodetype));
                                                        destroy_dahdi_pvt(&tmp);
                                                        return NULL;
                                                }
-                                               if (pris[span].switchtype && (pris[span].switchtype != myswitchtype)) {
-                                                       ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].switchtype));
+                                               if (pris[span].pri.switchtype && (pris[span].pri.switchtype != myswitchtype)) {
+                                                       ast_log(LOG_ERROR, "Span %d is already a %s switch\n", span + 1, pri_switch2str(pris[span].pri.switchtype));
                                                        destroy_dahdi_pvt(&tmp);
                                                        return NULL;
                                                }
-                                               if ((pris[span].dialplan) && (pris[span].dialplan != conf->pri.dialplan)) {
-                                                       ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, dialplan2str(pris[span].dialplan));
+                                               if ((pris[span].pri.dialplan) && (pris[span].pri.dialplan != conf->pri.pri.dialplan)) {
+                                                       ast_log(LOG_ERROR, "Span %d is already a %s dialing plan\n", span + 1, pris[span].pri.dialplan == -1 ? "Dynamically set dialplan in ISDN" : pri_plan2str(pris[span].pri.dialplan));
                                                        destroy_dahdi_pvt(&tmp);
                                                        return NULL;
                                                }
-                                               if (!ast_strlen_zero(pris[span].idledial) && strcmp(pris[span].idledial, conf->pri.idledial)) {
-                                                       ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.idledial);
+                                               if (!ast_strlen_zero(pris[span].pri.idledial) && strcmp(pris[span].pri.idledial, conf->pri.pri.idledial)) {
+                                                       ast_log(LOG_ERROR, "Span %d already has idledial '%s'.\n", span + 1, conf->pri.pri.idledial);
                                                        destroy_dahdi_pvt(&tmp);
                                                        return NULL;
                                                }
-                                               if (!ast_strlen_zero(pris[span].idleext) && strcmp(pris[span].idleext, conf->pri.idleext)) {
-                                                       ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.idleext);
+                                               if (!ast_strlen_zero(pris[span].pri.idleext) && strcmp(pris[span].pri.idleext, conf->pri.pri.idleext)) {
+                                                       ast_log(LOG_ERROR, "Span %d already has idleext '%s'.\n", span + 1, conf->pri.pri.idleext);
                                                        destroy_dahdi_pvt(&tmp);
                                                        return NULL;
                                                }
-                                               if (pris[span].minunused && (pris[span].minunused != conf->pri.minunused)) {
-                                                       ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.minunused);
+                                               if (pris[span].pri.minunused && (pris[span].pri.minunused != conf->pri.pri.minunused)) {
+                                                       ast_log(LOG_ERROR, "Span %d already has minunused of %d.\n", span + 1, conf->pri.pri.minunused);
                                                        destroy_dahdi_pvt(&tmp);
                                                        return NULL;
                                                }
-                                               if (pris[span].minidle && (pris[span].minidle != conf->pri.minidle)) {
-                                                       ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.minidle);
+                                               if (pris[span].pri.minidle && (pris[span].pri.minidle != conf->pri.pri.minidle)) {
+                                                       ast_log(LOG_ERROR, "Span %d already has minidle of %d.\n", span + 1, conf->pri.pri.minidle);
                                                        destroy_dahdi_pvt(&tmp);
                                                        return NULL;
                                                }
-                                               if (pris[span].numchans >= MAX_CHANNELS) {
+                                               if (pris[span].pri.numchans >= MAX_CHANNELS) {
                                                        ast_log(LOG_ERROR, "Unable to add channel %d: Too many channels in trunk group %d!\n", channel,
-                                                               pris[span].trunkgroup);
+                                                               pris[span].pri.trunkgroup);
                                                        destroy_dahdi_pvt(&tmp);
                                                        return NULL;
                                                }
 
-                                               pris[span].sig = chan_sig;
-                                               pris[span].nodetype = conf->pri.nodetype;
-                                               pris[span].switchtype = myswitchtype;
-                                               pris[span].nsf = conf->pri.nsf;
-                                               pris[span].dialplan = conf->pri.dialplan;
-                                               pris[span].localdialplan = conf->pri.localdialplan;
-                                               pris[span].pvts[pris[span].numchans++] = tmp;
-                                               pris[span].minunused = conf->pri.minunused;
-                                               pris[span].minidle = conf->pri.minidle;
-                                               pris[span].overlapdial = conf->pri.overlapdial;
-                                               pris[span].qsigchannelmapping = conf->pri.qsigchannelmapping;
-                                               pris[span].discardremoteholdretrieval = conf->pri.discardremoteholdretrieval;
+                                               ast_debug(4, "Adding callbacks %p to chan %d\n", &dahdi_pri_callbacks, tmp->channel);
+                                               pchan = sig_pri_chan_new(tmp, &dahdi_pri_callbacks, &pris[span].pri, tmp->logicalspan, p.chanpos);
+                                               if (!pchan) {
+                                                       destroy_dahdi_pvt(&tmp);
+                                                       return NULL;
+                                               }
+                                               tmp->sig_pvt = pchan;
+                                               tmp->pri = &pris[span].pri;
+
+                                               pris[span].pri.sig = chan_sig;
+                                               pris[span].pri.nodetype = conf->pri.pri.nodetype;
+                                               pris[span].pri.switchtype = myswitchtype;
+                                               pris[span].pri.nsf = conf->pri.pri.nsf;
+                                               pris[span].pri.dialplan = conf->pri.pri.dialplan;
+                                               pris[span].pri.localdialplan = conf->pri.pri.localdialplan;
+                                               pris[span].pri.pvts[pris[span].pri.numchans++] = tmp->sig_pvt;
+                                               pris[span].pri.minunused = conf->pri.pri.minunused;
+                                               pris[span].pri.minidle = conf->pri.pri.minidle;
+                                               pris[span].pri.overlapdial = conf->pri.pri.overlapdial;
+                                               pris[span].pri.qsigchannelmapping = conf->pri.pri.qsigchannelmapping;
+                                               pris[span].pri.discardremoteholdretrieval = conf->pri.pri.discardremoteholdretrieval;
 #ifdef HAVE_PRI_SERVICE_MESSAGES
-                                               pris[span].enable_service_message_support = conf->pri.enable_service_message_support;
+                                               pris[span].pri.enable_service_message_support = conf->pri.pri.enable_service_message_support;
 #endif
 #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));
-                                               ast_copy_string(pris[span].internationalprefix, conf->pri.internationalprefix, sizeof(pris[span].internationalprefix));
-                                               ast_copy_string(pris[span].nationalprefix, conf->pri.nationalprefix, sizeof(pris[span].nationalprefix));
-                                               ast_copy_string(pris[span].localprefix, conf->pri.localprefix, sizeof(pris[span].localprefix));
-                                               ast_copy_string(pris[span].privateprefix, conf->pri.privateprefix, sizeof(pris[span].privateprefix));
-                                               ast_copy_string(pris[span].unknownprefix, conf->pri.unknownprefix, sizeof(pris[span].unknownprefix));
-                                               pris[span].resetinterval = conf->pri.resetinterval;
-
-                                               tmp->pri = &pris[span];
+                                               pris[span].pri.inbanddisconnect = conf->pri.pri.inbanddisconnect;
+#endif
+                                               pris[span].pri.facilityenable = conf->pri.pri.facilityenable;
+                                               ast_copy_string(pris[span].pri.idledial, conf->pri.pri.idledial, sizeof(pris[span].pri.idledial));
+                                               ast_copy_string(pris[span].pri.idleext, conf->pri.pri.idleext, sizeof(pris[span].pri.idleext));
+                                               ast_copy_string(pris[span].pri.internationalprefix, conf->pri.pri.internationalprefix, sizeof(pris[span].pri.internationalprefix));
+                                               ast_copy_string(pris[span].pri.nationalprefix, conf->pri.pri.nationalprefix, sizeof(pris[span].pri.nationalprefix));
+                                               ast_copy_string(pris[span].pri.localprefix, conf->pri.pri.localprefix, sizeof(pris[span].pri.localprefix));
+                                               ast_copy_string(pris[span].pri.privateprefix, conf->pri.pri.privateprefix, sizeof(pris[span].pri.privateprefix));
+                                               ast_copy_string(pris[span].pri.unknownprefix, conf->pri.pri.unknownprefix, sizeof(pris[span].pri.unknownprefix));
+                                               pris[span].pri.resetinterval = conf->pri.pri.resetinterval;
+
                                                if (si.spanno != span + 1) { /* in another trunkgroup */
-                                                       tmp->prioffset = pris[span].numchans;
+                                                       tmp->prioffset = pris[span].pri.numchans;
                                                } else {
                                                        tmp->prioffset = p.chanpos;
                                                }
-                                               tmp->call = NULL;
                                        } else {
-                                               ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", offset);
+                                               ast_log(LOG_ERROR, "Channel %d is reserved for D-channel.\n", p.chanpos);
                                                destroy_dahdi_pvt(&tmp);
                                                return NULL;
                                        }
@@ -11536,6 +10524,8 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
                        }
 #endif
                } else {
+                       /* already exists in interface list */
+                       ast_log(LOG_WARNING, "Attempt to configure channel %d with signaling %s ignored because it is already configured to be %s.\n", tmp->channel, dahdi_sig2str(chan_sig), dahdi_sig2str(tmp->sig));
                        chan_sig = tmp->sig;
                        if (tmp->subs[SUB_REAL].dfd > -1) {
                                memset(&p, 0, sizeof(p));
@@ -11786,13 +10776,25 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
                        }
                        ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SETTONEZONE,&tmp->tonezone);
 #ifdef HAVE_PRI
-                       /* the dchannel is down so put the channel in alarm */
-                       if (tmp->pri && !pri_is_up(tmp->pri))
-                               tmp->inalarm = 1;
+                       memset(&si, 0, sizeof(si));
+                       if (ioctl(tmp->subs[SUB_REAL].dfd,DAHDI_SPANSTAT,&si) == -1) {
+                               ast_log(LOG_ERROR, "Unable to get span status: %s\n", strerror(errno));
+                               destroy_dahdi_pvt(&tmp);
+                               return NULL;
+                       }
 #endif
                        if ((res = get_alarms(tmp)) != DAHDI_ALARM_NONE) {
-                               tmp->inalarm = 1;
-                               handle_alarms(tmp, res);
+                       /* the dchannel is down so put the channel in alarm */
+#ifdef HAVE_PRI
+                               if (tmp->sig == SIG_PRI || tmp->sig == SIG_BRI || tmp->sig == SIG_BRI_PTMP)
+                                       sig_pri_chan_alarm_notify(tmp->sig_pvt, si.alarms);
+                               else {
+#endif
+                                       tmp->inalarm = 1;
+                                       handle_alarms(tmp, res);
+#ifdef HAVE_PRI
+                               }
+#endif
                        }
                }
 
@@ -11800,6 +10802,7 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
                tmp->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
                tmp->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
                tmp->sendcalleridafter = conf->chan.sendcalleridafter;
+
                if (!here) {
                        tmp->locallyblocked = tmp->remotelyblocked = 0;
                        if ((chan_sig == SIG_PRI) || (chan_sig == SIG_BRI) || (chan_sig == SIG_BRI_PTMP) || (chan_sig == SIG_SS7)) {
@@ -11821,38 +10824,56 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
                        }
                }
 
-               analog_p = tmp->sig_pvt;
-               if (analog_p) {
-                       analog_p->channel = tmp->channel;
-                       analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
-                       analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
-                       analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
-                       analog_p->sendcalleridafter = conf->chan.sendcalleridafter;
-                       analog_p->permcallwaiting = 1;
-                       analog_p->callreturn = conf->chan.callreturn;
-                       analog_p->cancallforward = conf->chan.cancallforward;
-                       analog_p->canpark = conf->chan.canpark;
-                       analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
-                       analog_p->immediate = conf->chan.immediate;
-                       analog_p->permhidecallerid = conf->chan.permhidecallerid;
-                       analog_p->pulse = conf->chan.pulse;
-                       analog_p->threewaycalling = conf->chan.threewaycalling;
-                       analog_p->transfer = conf->chan.transfer;
-                       analog_p->transfertobusy = conf->chan.transfertobusy;
-                       analog_p->use_callerid = conf->chan.use_callerid;
-                       analog_p->outsigmod = ANALOG_SIG_NONE;
-                       analog_p->echotraining = conf->chan.echotraining;
-                       analog_p->cid_signalling = conf->chan.cid_signalling;
-                       analog_p->stripmsd = conf->chan.stripmsd;
-                       analog_p->cid_start = ANALOG_CID_START_RING;
-                       tmp->callwaitingcallerid = analog_p->callwaitingcallerid = 1;
-
-                       ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
-                       ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
-                       ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
-
-                       analog_config_complete(analog_p);
+               if (tmp->sig != SIG_PRI && tmp->sig != SIG_BRI && tmp->sig != SIG_BRI_PTMP) {
+                       analog_p = tmp->sig_pvt;
+                       if (analog_p) {
+                               analog_p->channel = tmp->channel;
+                               analog_p->polarityonanswerdelay = conf->chan.polarityonanswerdelay;
+                               analog_p->answeronpolarityswitch = conf->chan.answeronpolarityswitch;
+                               analog_p->hanguponpolarityswitch = conf->chan.hanguponpolarityswitch;
+                               analog_p->sendcalleridafter = conf->chan.sendcalleridafter;
+                               analog_p->permcallwaiting = 1;
+                               analog_p->callreturn = conf->chan.callreturn;
+                               analog_p->cancallforward = conf->chan.cancallforward;
+                               analog_p->canpark = conf->chan.canpark;
+                               analog_p->dahditrcallerid = conf->chan.dahditrcallerid;
+                               analog_p->immediate = conf->chan.immediate;
+                               analog_p->permhidecallerid = conf->chan.permhidecallerid;
+                               analog_p->pulse = conf->chan.pulse;
+                               analog_p->threewaycalling = conf->chan.threewaycalling;
+                               analog_p->transfer = conf->chan.transfer;
+                               analog_p->transfertobusy = conf->chan.transfertobusy;
+                               analog_p->use_callerid = conf->chan.use_callerid;
+                               analog_p->outsigmod = ANALOG_SIG_NONE;
+                               analog_p->echotraining = conf->chan.echotraining;
+                               analog_p->cid_signalling = conf->chan.cid_signalling;
+                               analog_p->stripmsd = conf->chan.stripmsd;
+                               analog_p->cid_start = ANALOG_CID_START_RING;
+                               tmp->callwaitingcallerid = analog_p->callwaitingcallerid = 1;
+       
+                               ast_copy_string(analog_p->mohsuggest, conf->chan.mohsuggest, sizeof(analog_p->mohsuggest));
+                               ast_copy_string(analog_p->cid_num, conf->chan.cid_num, sizeof(analog_p->cid_num));
+                               ast_copy_string(analog_p->cid_name, conf->chan.cid_name, sizeof(analog_p->cid_name));
+
+                               analog_config_complete(analog_p);
+                       }
+               } 
+#ifdef HAVE_PRI
+               else if (pchan != NULL) {
+                       pchan->channel = tmp->channel;
+                       pchan->hidecallerid = tmp->hidecallerid;
+                       pchan->hidecalleridname = tmp->hidecalleridname;
+                       pchan->immediate = tmp->immediate;
+                       pchan->inalarm = tmp->inalarm;
+                       pchan->priexclusive = tmp->priexclusive;
+                       pchan->priindication_oob = tmp->priindication_oob;
+                       pchan->use_callerid = tmp->use_callerid;
+                       pchan->use_callingpres = tmp->use_callingpres;
+                       ast_copy_string(pchan->context, tmp->context, sizeof(pchan->context));
+                       ast_copy_string(pchan->mohinterpret, tmp->mohinterpret, sizeof(pchan->mohinterpret));
+                       pchan->stripmsd = tmp->stripmsd;
                }
+#endif
        }
        if (tmp && !here) {
                /* nothing on the iflist */
@@ -11903,9 +10924,6 @@ 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 *reason, int *channelmatched, int *groupmatched)
 {
-       int res;
-       struct dahdi_params par;
-
        /* First, check group matching */
        if (groupmatch) {
                if ((p->group & groupmatch) != groupmatch)
@@ -11919,50 +10937,18 @@ static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t g
                *channelmatched = 1;
        }
 
-       if (analog_lib_handles(p->sig, p->radio, p->oprmode))
-               return analog_available(p->sig_pvt, channelmatch, groupmatch, reason, channelmatched, groupmatched);
-
-       /* We're at least busy at this point */
-       if (reason) {
-               if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
-                       *reason = AST_CAUSE_BUSY;
-       }
-       /* If do not disturb, definitely not */
-       if (p->dnd)
-               return 0;
-       /* If guard time, definitely not */
-       if (p->guardtime && (time(NULL) < p->guardtime))
+       if (p->inalarm)
                return 0;
 
-       if (p->locallyblocked || p->remotelyblocked)
-               return 0;
+       if (analog_lib_handles(p->sig, p->radio, p->oprmode))
+               return analog_available(p->sig_pvt, channelmatch, groupmatch, reason, channelmatched, groupmatched);
 
-       /* If no owner definitely available */
-       if (!p->owner) {
 #ifdef HAVE_PRI
-               /* Trust PRI */
-               if (p->pri) {
-#ifdef HAVE_PRI_SERVICE_MESSAGES
-                       char db_chan_name[20], db_answer[5], state;
-                       int why = 0;
-                                               
-                       snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, p->span, p->channel);
-                       if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
-                               sscanf(db_answer, "%c:%d", &state, &why);
-                       }
-                       if ((p->resetting || p->call) || (why)) {
-                               if (why) {
-                                       *reason = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
-                               }
-#else
-                       if (p->resetting || p->call) {
-#endif
-                               return 0;
-                       } else {
-                               return 1;
-                       }
-               }
+       if (p->sig == SIG_PRI || p->sig == SIG_BRI || p->sig == SIG_BRI_PTMP) {
+               return sig_pri_available(p->sig_pvt, channelmatch, groupmatch, reason, channelmatched, groupmatched);
+       }
 #endif
+
 #ifdef HAVE_SS7
                /* Trust SS7 */
                if (p->ss7) {
@@ -11981,69 +10967,8 @@ static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t g
                                return 1;
                }
 #endif
-               if (!(p->radio || (p->oprmode < 0)))
-               {
-                       if (!p->sig || (p->sig == SIG_FXSLS))
-                               return 1;
-                       /* Check hook state */
-                       if (p->subs[SUB_REAL].dfd > -1) {
-                               memset(&par, 0, sizeof(par));
-                               res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_GET_PARAMS, &par);
-                       } else {
-                               /* Assume not off hook on CVRS */
-                               res = 0;
-                               par.rxisoffhook = 0;
-                       }
-                       if (res) {
-                               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
-                                 bank, there is no telling... */
-                               if (par.rxbits > -1)
-                                       return 1;
-                               if (par.rxisoffhook)
-                                       return 1;
-                               else
-                                       return 0;
-                       } 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 */
-#ifdef DAHDI_CHECK_HOOKSTATE
-                               return 0;
-#else
-                               return 1;
-#endif
-                       }
-               }
-               return 1;
-       }
-
-       /* If it's not an FXO, forget about call wait */
-       if ((p->sig != SIG_FXOKS) && (p->sig != SIG_FXOLS) && (p->sig != SIG_FXOGS))
-               return 0;
 
-       if (!p->callwaiting) {
-               /* If they don't have call waiting enabled, then for sure they're unavailable at this point */
-               return 0;
-       }
-
-       if (p->subs[SUB_CALLWAIT].dfd > -1) {
-               /* If there is already a call waiting call, then we can't take a second one */
-               return 0;
-       }
-
-       if ((p->owner->_state != AST_STATE_UP) &&
-               ((p->owner->_state != AST_STATE_RINGING) || p->outgoing)) {
-               /* If the current call is not up, then don't allow the call */
-               return 0;
-       }
-       if ((p->subs[SUB_THREEWAY].owner) && (!p->subs[SUB_THREEWAY].inthreeway)) {
-               /* Can't take a call wait when the three way calling hasn't been merged yet. */
-               return 0;
-       }
-       /* We're cool */
-       return 1;
+       return 0;
 }
 
 /* This function can *ONLY* be used for copying pseudo (CHAN_PSEUDO) private
@@ -12087,33 +11012,6 @@ static struct dahdi_pvt *duplicate_pseudo(struct dahdi_pvt *src)
        return p;
 }
 
-#if defined(HAVE_PRI)
-static int pri_find_empty_chan(struct dahdi_pri *pri, int backwards)
-{
-       int x;
-       if (backwards)
-               x = pri->numchans;
-       else
-               x = 0;
-       for (;;) {
-               if (backwards && (x < 0))
-                       break;
-               if (!backwards && (x >= pri->numchans))
-                       break;
-               if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
-                       ast_debug(1, "Found empty available channel %d/%d\n",
-                               pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
-                       return x;
-               }
-               if (backwards)
-                       x--;
-               else
-                       x++;
-       }
-       return -1;
-}
-#endif /* defined(HAVE_PRI) */
-
 static struct ast_channel *dahdi_request(const char *type, int format, void *data, int *cause)
 {
        ast_group_t groupmatch = 0;
@@ -12129,12 +11027,6 @@ static struct ast_channel *dahdi_request(const char *type, int format, void *dat
        char opt=0;
        int res=0, y=0;
        int backwards = 0;
-#ifdef HAVE_PRI
-       int crv;
-       int bearer = -1;
-       int trunkgroup;
-       struct dahdi_pri *pri=NULL;
-#endif
        struct dahdi_pvt *exitpvt, *start, *end;
        ast_mutex_t *lock;
        int channelmatched = 0;
@@ -12208,30 +11100,6 @@ static struct ast_channel *dahdi_request(const char *type, int format, void *dat
                        x = CHAN_PSEUDO;
                        channelmatch = x;
                }
-#ifdef HAVE_PRI
-               else if ((res = sscanf(s, "%d:%d%c%d", &trunkgroup, &crv, &opt, &y)) > 1) {
-                       if ((trunkgroup < 1) || (crv < 1)) {
-                               ast_log(LOG_WARNING, "Unable to determine trunk group and CRV for data %s\n", (char *)data);
-                               return NULL;
-                       }
-                       res--;
-                       for (x = 0; x < NUM_SPANS; x++) {
-                               if (pris[x].trunkgroup == trunkgroup) {
-                                       pri = pris + x;
-                                       lock = &pri->lock;
-                                       start = pri->crvs;
-                                       end = pri->crvend;
-                                       break;
-                               }
-                       }
-                       if (!pri) {
-                               ast_log(LOG_WARNING, "Unable to find trunk group %d\n", trunkgroup);
-                               return NULL;
-                       }
-                       channelmatch = crv;
-                       p = pris[x].crvs;
-               }
-#endif
                else if ((res = sscanf(s, "%d%c%d", &x, &opt, &y)) < 1) {
                        ast_log(LOG_WARNING, "Unable to determine channel for data %s\n", (char *)data);
                        return NULL;
@@ -12251,34 +11119,8 @@ static struct ast_channel *dahdi_request(const char *type, int format, void *dat
 
                if (p && available(p, channelmatch, groupmatch, &unavailreason, &channelmatched, &groupmatched)) {
                        ast_debug(1, "Using channel %d\n", p->channel);
-                       if (p->inalarm)
-                               goto next;
 
                        callwait = (p->owner != NULL);
-#ifdef HAVE_PRI
-                       if (pri && (p->subs[SUB_REAL].dfd < 0)) {
-                               if (p->sig != SIG_FXSKS) {
-                                       /* Gotta find an actual channel to use for this
-                                          CRV if this isn't a callwait */
-                                       bearer = pri_find_empty_chan(pri, 0);
-                                       if (bearer < 0) {
-                                               ast_log(LOG_NOTICE, "Out of bearer channels on span %d for call to CRV %d:%d\n", pri->span, trunkgroup, crv);
-                                               p = NULL;
-                                               break;
-                                       }
-                                       pri_assign_bearer(p, pri, pri->pvts[bearer]);
-                               } else {
-                                       if (alloc_sub(p, 0)) {
-                                               ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
-                                               p = NULL;
-                                               break;
-                                       } else
-                                               ast_debug(1, "Allocated placeholder pseudo channel\n");
-
-                                       p->pri = pri;
-                               }
-                       }
-#endif
 #ifdef HAVE_OPENR2
                        if (p->mfcr2) {
                                ast_mutex_lock(&p->lock);
@@ -12307,14 +11149,16 @@ static struct ast_channel *dahdi_request(const char *type, int format, void *dat
                        p->outgoing = 1;
                        if (analog_lib_handles(p->sig, p->radio, p->oprmode)) {
                                tmp = analog_request(p->sig_pvt, &callwait);
-                       } else
-                               tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
+                       } 
 #ifdef HAVE_PRI
-                       if (p->bearer) {
-                               /* Log owner to bearer channel, too */
-                               p->bearer->owner = tmp;
+                       else if (p->sig == SIG_PRI || p->sig == SIG_BRI || p->sig == SIG_BRI_PTMP) {
+                               tmp = sig_pri_request(p->sig_pvt, SIG_PRI_DEFLAW);
                        }
-#endif
+#endif   
+                       else {
+                               tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
+                       }
+
                        /* Make special notes */
                        if (res > 1) {
                                if (opt == 'c') {
@@ -12340,7 +11184,6 @@ static struct ast_channel *dahdi_request(const char *type, int format, void *dat
                                tmp->cdrflags |= AST_CDR_CALLWAIT;
                        break;
                }
-next:
                if (backwards) {
                        p = p->prev;
                        if (!p)
@@ -12370,17 +11213,6 @@ next:
        return tmp;
 }
 
-#if defined(HAVE_PRI) || defined(HAVE_SS7)
-static int dahdi_setlaw(int dfd, int law)
-{
-       int res;
-       res = ioctl(dfd, DAHDI_SETLAW, &law);
-       if (res)
-               return res;
-       return 0;
-}
-#endif /* defined(HAVE_PRI) || defined(HAVE_SS7) */
-
 #if defined(HAVE_SS7)
 static int ss7_find_cic(struct dahdi_ss7 *linkset, int cic, unsigned int dpc)
 {
@@ -13087,7 +11919,7 @@ static void *ss7_linkset(void *data)
                                ast_mutex_lock(&p->lock);
                                p->remotelyblocked = 1;
                                p->inservice = 0;
-                               ast_mutex_unlock(&p->lock);                     //doesn't require a SS7 acknowledgement
+                               ast_mutex_unlock(&p->lock);                     /* doesn't require a SS7 acknowledgement */
                                break;
                        case ISUP_EVENT_BLO:
                                chanpos = ss7_find_cic(linkset, e->blo.cic, e->blo.opc);
@@ -13314,1613 +12146,110 @@ static void *mfcr2_monitor(void *data)
 #endif /* HAVE_OPENR2 */
 
 #if defined(HAVE_PRI)
-static struct dahdi_pvt *pri_find_crv(struct dahdi_pri *pri, int crv)
-{
-       struct dahdi_pvt *p;
-       p = pri->crvs;
-       while (p) {
-               if (p->channel == crv)
-                       return p;
-               p = p->next;
-       }
-       return NULL;
-}
-#endif /* defined(HAVE_PRI) */
-
-#if defined(HAVE_PRI)
-static int pri_find_principle(struct dahdi_pri *pri, int channel)
-{
-       int x;
-       int span = PRI_SPAN(channel);
-       int spanfd;
-       struct dahdi_params param;
-       int principle = -1;
-       int explicit = PRI_EXPLICIT(channel);
-       channel = PRI_CHANNEL(channel);
-
-       if (!explicit) {
-               spanfd = pri_active_dchan_fd(pri);
-               memset(&param, 0, sizeof(param));
-               if (ioctl(spanfd, DAHDI_GET_PARAMS, &param))
-                       return -1;
-               span = pris[param.spanno - 1].prilogicalspan;
-       }
-
-       for (x = 0; x < pri->numchans; x++) {
-               if (pri->pvts[x] && (pri->pvts[x]->prioffset == channel) && (pri->pvts[x]->logicalspan == span)) {
-                       principle = x;
-                       break;
-               }
-       }
-
-       return principle;
-}
-#endif /* defined(HAVE_PRI) */
-
-#if defined(HAVE_PRI)
-static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *c)
-{
-       int x;
-       struct dahdi_pvt *crv;
-       if (!c) {
-               if (principle < 0)
-                       return -1;
-               return principle;
-       }
-       if ((principle > -1) &&
-               (principle < pri->numchans) &&
-               (pri->pvts[principle]) &&
-               (pri->pvts[principle]->call == c))
-               return principle;
-       /* First, check for other bearers */
-       for (x = 0; x < pri->numchans; x++) {
-               if (!pri->pvts[x])
-                       continue;
-               if (pri->pvts[x]->call == c) {
-                       /* Found our call */
-                       if (principle != x) {
-                               struct dahdi_pvt *new = pri->pvts[principle], *old = pri->pvts[x];
-
-                               ast_verb(3, "Moving call from channel %d to channel %d\n",
-                                        old->channel, new->channel);
-                               if (new->owner) {
-                                       ast_log(LOG_WARNING, "Can't fix up channel from %d to %d because %d is already in use\n",
-                                               old->channel, new->channel, new->channel);
-                                       return -1;
-                               }
-                               /* Fix it all up now */
-                               new->owner = old->owner;
-                               old->owner = NULL;
-                               if (new->owner) {
-                                       char newname[AST_CHANNEL_NAME];
-
-                                       snprintf(newname, sizeof(newname),
-                                               "DAHDI/%d:%d-%d", pri->trunkgroup, new->channel, 1);
-
-                                       ast_change_name(new->owner, newname);
-
-                                       new->owner->tech_pvt = new;
-                                       ast_channel_set_fd(new->owner, 0, new->subs[SUB_REAL].dfd);
-                                       new->subs[SUB_REAL].owner = old->subs[SUB_REAL].owner;
-                                       old->subs[SUB_REAL].owner = NULL;
-                               } else
-                                       ast_log(LOG_WARNING, "Whoa, there's no  owner, and we're having to fix up channel %d to channel %d\n", old->channel, new->channel);
-                               new->call = old->call;
-                               old->call = NULL;
-
-                               /* Copy any DSP that may be present */
-                               new->dsp = old->dsp;
-                               new->dsp_features = old->dsp_features;
-                               old->dsp = NULL;
-                               old->dsp_features = 0;
-                       }
-                       return principle;
-               }
-       }
-       /* Now check for a CRV with no bearer */
-       crv = pri->crvs;
-       while (crv) {
-               if (crv->call == c) {
-                       /* This is our match...  Perform some basic checks */
-                       if (crv->bearer)
-                               ast_log(LOG_WARNING, "Trying to fix up call which already has a bearer which isn't the one we think it is\n");
-                       else if (pri->pvts[principle]->owner)
-                               ast_log(LOG_WARNING, "Tring to fix up a call to a bearer which already has an owner!\n");
-                       else {
-                               /* Looks good.  Drop the pseudo channel now, clear up the assignment, and
-                                  wakeup the potential sleeper */
-                               dahdi_close_sub(crv, SUB_REAL);
-                               pri->pvts[principle]->call = crv->call;
-                               pri_assign_bearer(crv, pri, pri->pvts[principle]);
-                               ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n",
-                                       pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
-                                       pri->trunkgroup, crv->channel);
-                               wakeup_sub(crv, SUB_REAL, pri);
-                       }
-                       return principle;
-               }
-               crv = crv->next;
-       }
-       ast_log(LOG_WARNING, "Call specified, but not found?\n");
-       return -1;
-}
-#endif /* defined(HAVE_PRI) */
-
-#if defined(HAVE_PRI)
-static void *do_idle_thread(void *vchan)
-{
-       struct ast_channel *chan = vchan;
-       struct dahdi_pvt *pvt = chan->tech_pvt;
-       struct ast_frame *f;
-       char ex[80];
-       /* Wait up to 30 seconds for an answer */
-       int newms, ms = 30000;
-       ast_verb(3, "Initiating idle call on channel %s\n", chan->name);
-       snprintf(ex, sizeof(ex), "%d/%s", pvt->channel, pvt->pri->idledial);
-       if (ast_call(chan, ex, 0)) {
-               ast_log(LOG_WARNING, "Idle dial failed on '%s' to '%s'\n", chan->name, ex);
-               ast_hangup(chan);
-               return NULL;
-       }
-       while ((newms = ast_waitfor(chan, ms)) > 0) {
-               f = ast_read(chan);
-               if (!f) {
-                       /* Got hangup */
-                       break;
-               }
-               if (f->frametype == AST_FRAME_CONTROL) {
-                       switch (f->subclass) {
-                       case AST_CONTROL_ANSWER:
-                               /* Launch the PBX */
-                               ast_copy_string(chan->exten, pvt->pri->idleext, sizeof(chan->exten));
-                               ast_copy_string(chan->context, pvt->pri->idlecontext, sizeof(chan->context));
-                               chan->priority = 1;
-                               ast_verb(4, "Idle channel '%s' answered, sending to %s@%s\n", chan->name, chan->exten, chan->context);
-                               ast_pbx_run(chan);
-                               /* It's already hungup, return immediately */
-                               return NULL;
-                       case AST_CONTROL_BUSY:
-                               ast_verb(4, "Idle channel '%s' busy, waiting...\n", chan->name);
-                               break;
-                       case AST_CONTROL_CONGESTION:
-                               ast_verb(4, "Idle channel '%s' congested, waiting...\n", chan->name);
-                               break;
-                       };
-               }
-               ast_frfree(f);
-               ms = newms;
-       }
-       /* Hangup the channel since nothing happend */
-       ast_hangup(chan);
-       return NULL;
-}
-#endif /* defined(HAVE_PRI) */
-
-#if defined(HAVE_PRI)
 #ifndef PRI_RESTART
 #error "Upgrade your libpri"
 #endif
-static void dahdi_pri_message(struct pri *pri, char *s)
-{
-       int x, y;
-       int dchan = -1, span = -1;
-       int dchancount = 0;
-
-       if (pri) {
-               for (x = 0; x < NUM_SPANS; x++) {
-                       for (y = 0; y < NUM_DCHANS; y++) {
-                               if (pris[x].dchans[y])
-                                       dchancount++;
-
-                               if (pris[x].dchans[y] == pri)
-                                       dchan = y;
-                       }
-                       if (dchan >= 0) {
-                               span = x;
-                               break;
-                       }
-                       dchancount = 0;
-               }
-               if (dchancount > 1 && (span > -1))
-                       ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
-               else
-                       ast_verbose("%s", s);
-       } else
-               ast_verbose("%s", s);
-
-       ast_mutex_lock(&pridebugfdlock);
-
-       if (pridebugfd >= 0) {
-               if (write(pridebugfd, s, strlen(s)) < 0) {
-                       ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
-               }
-       }
-
-       ast_mutex_unlock(&pridebugfdlock);
-}
-#endif /* defined(HAVE_PRI) */
-
-#if defined(HAVE_PRI)
-static void dahdi_pri_error(struct pri *pri, char *s)
-{
-       int x, y;
-       int dchan = -1, span = -1;
-       int dchancount = 0;
-
-       if (pri) {
-               for (x = 0; x < NUM_SPANS; x++) {
-                       for (y = 0; y < NUM_DCHANS; y++) {
-                               if (pris[x].dchans[y])
-                                       dchancount++;
-
-                               if (pris[x].dchans[y] == pri)
-                                       dchan = y;
-                       }
-                       if (dchan >= 0) {
-                               span = x;
-                               break;
-                       }
-                       dchancount = 0;
-               }
-               if ((dchancount > 1) && (span > -1))
-                       ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
-               else
-                       ast_log(LOG_ERROR, "%s", s);
-       } else
-               ast_log(LOG_ERROR, "%s", s);
-
-       ast_mutex_lock(&pridebugfdlock);
-
-       if (pridebugfd >= 0) {
-               if (write(pridebugfd, s, strlen(s)) < 0) {
-                       ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
-               }
-       }
-
-       ast_mutex_unlock(&pridebugfdlock);
-}
-#endif /* defined(HAVE_PRI) */
-
-#if defined(HAVE_PRI)
-static int pri_check_restart(struct dahdi_pri *pri)
-{
-#ifdef HAVE_PRI_SERVICE_MESSAGES
-tryanotherpos:
-#endif
-       do {
-               pri->resetpos++;
-       } while ((pri->resetpos < pri->numchans) &&
-               (!pri->pvts[pri->resetpos] ||
-               pri->pvts[pri->resetpos]->call ||
-               pri->pvts[pri->resetpos]->resetting));
-       if (pri->resetpos < pri->numchans) {
-#ifdef HAVE_PRI_SERVICE_MESSAGES
-               char db_chan_name[20], db_answer[5], state;
-               int why;
-
-               /* check if the channel is out of service */
-               ast_mutex_lock(&pri->pvts[pri->resetpos]->lock);
-               snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, pri->pvts[pri->resetpos]->span, pri->pvts[pri->resetpos]->channel);
-               ast_mutex_unlock(&pri->pvts[pri->resetpos]->lock);
-
-               /* if so, try next channel */
-               if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
-                       sscanf(db_answer, "%c:%d", &state, &why);
-                       if (why) {
-                               ast_log(LOG_NOTICE, "span '%d' channel '%d' out-of-service (reason: %s), not sending RESTART\n", pri->span,
-                               pri->pvts[pri->resetpos]->channel, (why & SRVST_FAREND) ? (why & SRVST_NEAREND) ? "both ends" : "far end" : "near end");
-                               goto tryanotherpos;
-                       }
-               }
-#endif
-
-               /* Mark the channel as resetting and restart it */
-               pri->pvts[pri->resetpos]->resetting = 1;
-               pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[pri->resetpos]));
-       } else {
-               pri->resetting = 0;
-               time(&pri->lastreset);
-       }
-       return 0;
-}
-#endif /* defined(HAVE_PRI) */
-
-#if defined(HAVE_PRI)
-static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
-{
-       int x;
-       int redo;
-       ast_mutex_unlock(&pri->lock);
-       ast_mutex_lock(&p->lock);
-       do {
-               redo = 0;
-               for (x = 0; x < 3; x++) {
-                       while (p->subs[x].owner && ast_channel_trylock(p->subs[x].owner)) {
-                               redo++;
-                               DEADLOCK_AVOIDANCE(&p->lock);
-                       }
-                       if (p->subs[x].owner) {
-                               ast_queue_hangup_with_cause(p->subs[x].owner, AST_CAUSE_PRE_EMPTED);
-                               ast_channel_unlock(p->subs[x].owner);
-                       }
-               }
-       } while (redo);
-       ast_mutex_unlock(&p->lock);
-       ast_mutex_lock(&pri->lock);
-       return 0;
-}
-#endif /* defined(HAVE_PRI) */
-
-#if defined(HAVE_PRI)
-static char * redirectingreason2str(int redirectingreason)
-{
-       switch (redirectingreason) {
-       case 0:
-               return "UNKNOWN";
-       case 1:
-               return "BUSY";
-       case 2:
-               return "NO_REPLY";
-       case 0xF:
-               return "UNCONDITIONAL";
-       default:
-               return "NOREDIRECT";
-       }
-}
-#endif /* defined(HAVE_PRI) */
-
-#if defined(HAVE_PRI)
-static void apply_plan_to_number(char *buf, size_t size, const struct dahdi_pri *pri, const char *number, const int plan)
-{
-       if (pri->dialplan == -2) { /* autodetect the TON but leave the number untouched */
-               snprintf(buf, size, "%s", number);
-               return;
-       }
-       if (ast_strlen_zero(number)) { /* make sure a number exists so prefix isn't placed on an empty string */
-               if (size) {
-                       *buf = '\0';
-               }
-               return;
-       }
-       switch (plan) {
-       case PRI_INTERNATIONAL_ISDN:            /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
-               snprintf(buf, size, "%s%s", pri->internationalprefix, number);
-               break;
-       case PRI_NATIONAL_ISDN:                 /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
-               snprintf(buf, size, "%s%s", pri->nationalprefix, number);
-               break;
-       case PRI_LOCAL_ISDN:                    /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
-               snprintf(buf, size, "%s%s", pri->localprefix, number);
-               break;
-       case PRI_PRIVATE:                       /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
-               snprintf(buf, size, "%s%s", pri->privateprefix, number);
-               break;
-       case PRI_UNKNOWN:                       /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
-               snprintf(buf, size, "%s%s", pri->unknownprefix, number);
-               break;
-       default:                                /* other Q.931 dialplan => don't twiddle with callingnum */
-               snprintf(buf, size, "%s", number);
-               break;
-       }
-}
-#endif /* defined(HAVE_PRI) */
-
-#if defined(HAVE_PRI)
-static void *pri_dchannel(void *vpri)
-{
-       struct dahdi_pri *pri = vpri;
-       pri_event *e;
-       struct pollfd fds[NUM_DCHANS];
-       int res;
-       int chanpos = 0;
-       int x;
-       int haveidles;
-       int activeidles;
-       int nextidle = -1;
-       struct ast_channel *c;
-       struct timeval tv, lowest, *next;
-       struct timeval lastidle = ast_tvnow();
-       int doidling=0;
-       char *cc;
-       char idlen[80];
-       struct ast_channel *idle;
-       pthread_t p;
-       time_t t;
-       int i, which=-1;
-       int numdchans;
-       int cause=0;
-       struct dahdi_pvt *crv;
-       pthread_t threadid;
-       char ani2str[6];
-       char plancallingnum[256];
-       char plancallingani[256];
-       char calledtonstr[10];
-
-       pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
-
-       gettimeofday(&lastidle, NULL);
-       if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
-               /* Need to do idle dialing, check to be sure though */
-               cc = strchr(pri->idleext, '@');
-               if (cc) {
-                       *cc = '\0';
-                       cc++;
-                       ast_copy_string(pri->idlecontext, cc, sizeof(pri->idlecontext));
-#if 0
-                       /* Extensions may not be loaded yet */
-                       if (!ast_exists_extension(NULL, pri->idlecontext, pri->idleext, 1, NULL))
-                               ast_log(LOG_WARNING, "Extension '%s @ %s' does not exist\n", pri->idleext, pri->idlecontext);
-                       else
-#endif
-                               doidling = 1;
-               } else
-                       ast_log(LOG_WARNING, "Idle dial string '%s' lacks '@context'\n", pri->idleext);
-       }
-       for (;;) {
-               for (i = 0; i < NUM_DCHANS; i++) {
-                       if (!pri->dchannels[i])
-                               break;
-                       fds[i].fd = pri->fds[i];
-                       fds[i].events = POLLIN | POLLPRI;
-                       fds[i].revents = 0;
-               }
-               numdchans = i;
-               time(&t);
-               ast_mutex_lock(&pri->lock);
-               if ((pri->switchtype != PRI_SWITCH_GR303_TMC) && (pri->sig != SIG_BRI_PTMP) && (pri->resetinterval > 0)) {
-                       if (pri->resetting && pri_is_up(pri)) {
-                               if (pri->resetpos < 0)
-                                       pri_check_restart(pri);
-                       } else {
-                               if (!pri->resetting     && (t - pri->lastreset) >= pri->resetinterval) {
-                                       pri->resetting = 1;
-                                       pri->resetpos = -1;
-                               }
-                       }
-               }
-               /* Look for any idle channels if appropriate */
-               if (doidling && pri_is_up(pri)) {
-                       nextidle = -1;
-                       haveidles = 0;
-                       activeidles = 0;
-                       for (x = pri->numchans; x >= 0; x--) {
-                               if (pri->pvts[x] && !pri->pvts[x]->owner &&
-                                       !pri->pvts[x]->call) {
-                                       if (haveidles < pri->minunused) {
-                                               haveidles++;
-                                       } else if (!pri->pvts[x]->resetting) {
-                                               nextidle = x;
-                                               break;
-                                       }
-                               } else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
-                                       activeidles++;
-                       }
-                       if (nextidle > -1) {
-                               if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
-                                       /* Don't create a new idle call more than once per second */
-                                       snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
-                                       idle = dahdi_request("DAHDI", AST_FORMAT_ULAW, idlen, &cause);
-                                       if (idle) {
-                                               pri->pvts[nextidle]->isidlecall = 1;
-                                               if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
-                                                       ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
-                                                       dahdi_hangup(idle);
-                                               }
-                                       } else
-                                               ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
-                                       lastidle = ast_tvnow();
-                               }
-                       } else if ((haveidles < pri->minunused) &&
-                               (activeidles > pri->minidle)) {
-                               /* Mark something for hangup if there is something
-                                  that can be hungup */
-                               for (x = pri->numchans; x >= 0; x--) {
-                                       /* find a candidate channel */
-                                       if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
-                                               pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-                                               haveidles++;
-                                               /* Stop if we have enough idle channels or
-                                                 can't spare any more active idle ones */
-                                               if ((haveidles >= pri->minunused) ||
-                                                       (activeidles <= pri->minidle))
-                                                       break;
-                                       }
-                               }
-                       }
-               }
-               /* Start with reasonable max */
-               lowest = ast_tv(60, 0);
-               for (i = 0; i < NUM_DCHANS; i++) {
-                       /* Find lowest available d-channel */
-                       if (!pri->dchannels[i])
-                               break;
-                       if ((next = pri_schedule_next(pri->dchans[i]))) {
-                               /* We need relative time here */
-                               tv = ast_tvsub(*next, ast_tvnow());
-                               if (tv.tv_sec < 0) {
-                                       tv = ast_tv(0,0);
-                               }
-                               if (doidling || pri->resetting) {
-                                       if (tv.tv_sec > 1) {
-                                               tv = ast_tv(1, 0);
-                                       }
-                               } else {
-                                       if (tv.tv_sec > 60) {
-                                               tv = ast_tv(60, 0);
-                                       }
-                               }
-                       } else if (doidling || pri->resetting) {
-                               /* Make sure we stop at least once per second if we're
-                                  monitoring idle channels */
-                               tv = ast_tv(1,0);
-                       } else {
-                               /* Don't poll for more than 60 seconds */
-                               tv = ast_tv(60, 0);
-                       }
-                       if (!i || ast_tvcmp(tv, lowest) < 0) {
-                               lowest = tv;
-                       }
-               }
-               ast_mutex_unlock(&pri->lock);
-
-               pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
-               pthread_testcancel();
-               e = NULL;
-               res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
-               pthread_testcancel();
-               pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
-
-               ast_mutex_lock(&pri->lock);
-               if (!res) {
-                       for (which = 0; which < NUM_DCHANS; which++) {
-                               if (!pri->dchans[which])
-                                       break;
-                               /* Just a timeout, run the scheduler */
-                               e = pri_schedule_run(pri->dchans[which]);
-                               if (e)
-                                       break;
-                       }
-               } else if (res > -1) {
-                       for (which = 0; which < NUM_DCHANS; which++) {
-                               if (!pri->dchans[which])
-                                       break;
-                               if (fds[which].revents & POLLPRI) {
-                                       /* Check for an event */
-                                       x = 0;
-                                       res = ioctl(pri->fds[which], DAHDI_GETEVENT, &x);
-                                       if (x) {
-                                               ast_log(LOG_NOTICE, "PRI got event: %s (%d) on %s D-channel of span %d\n", event2str(x), x, pri_order(which), pri->span);
-                                               manager_event(EVENT_FLAG_SYSTEM, "PRIEvent",
-                                                       "PRIEvent: %s\r\n"
-                                                       "PRIEventCode: %d\r\n"
-                                                       "D-channel: %s\r\n"
-                                                       "Span: %d\r\n",
-                                                       event2str(x),
-                                                       x,
-                                                       pri_order(which),
-                                                       pri->span
-                                                       );
-                                       }
-                                       /* Keep track of alarm state */
-                                       if (x == DAHDI_EVENT_ALARM) {
-                                               pri->dchanavail[which] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
-                                               pri_find_dchan(pri);
-                                       } else if (x == DAHDI_EVENT_NOALARM) {
-                                               pri->dchanavail[which] |= DCHAN_NOTINALARM;
-                                               pri_restart(pri->dchans[which]);
-                                       }
-
-                                       ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
-                               } else if (fds[which].revents & POLLIN) {
-                                       e = pri_check_event(pri->dchans[which]);
-                               }
-                               if (e)
-                                       break;
-                       }
-               } else if (errno != EINTR)
-                       ast_log(LOG_WARNING, "pri_event returned error %d (%s)\n", errno, strerror(errno));
-
-               if (e) {
-                       if (pri->debug)
-                               pri_dump_event(pri->dchans[which], e);
-
-                       if (e->e != PRI_EVENT_DCHAN_DOWN) {
-                               if (!(pri->dchanavail[which] & DCHAN_UP)) {
-                                       ast_verb(2, "%s D-Channel on span %d up\n", pri_order(which), pri->span);
-                               }
-                               pri->dchanavail[which] |= DCHAN_UP;
-                       } else if (pri->sig != SIG_BRI_PTMP) {
-                               if (pri->dchanavail[which] & DCHAN_UP) {
-                                       ast_verb(2, "%s D-Channel on span %d down\n", pri_order(which), pri->span);
-                               }
-                               pri->dchanavail[which] &= ~DCHAN_UP;
-                       }
-
-                       if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
-                               /* Must be an NFAS group that has the secondary dchan active */
-                               pri->pri = pri->dchans[which];
-
-                       switch (e->e) {
-                       case PRI_EVENT_DCHAN_UP:
-                               if (!pri->pri) pri_find_dchan(pri);
-
-                               /* Note presense of D-channel */
-                               time(&pri->lastreset);
-
-                               /* Restart in 5 seconds */
-                               if (pri->resetinterval > -1) {
-                                       pri->lastreset -= pri->resetinterval;
-                                       pri->lastreset += 5;
-                               }
-                               pri->resetting = 0;
-                               /* Take the channels from inalarm condition */
-                               for (i = 0; i < pri->numchans; i++)
-                                       if (pri->pvts[i]) {
-                                               pri->pvts[i]->inalarm = 0;
-                                       }
-                               break;
-                       case PRI_EVENT_DCHAN_DOWN:
-                               pri_find_dchan(pri);
-                               if (!pri_is_up(pri)) {
-                                       pri->resetting = 0;
-                                       /* Hangup active channels and put them in alarm mode */
-                                       for (i = 0; i < pri->numchans; i++) {
-                                               struct dahdi_pvt *p = pri->pvts[i];
-                                               if (p) {
-                                                       if (!p->pri || !p->pri->pri || pri_get_timer(p->pri->pri, PRI_TIMER_T309) < 0) {
-                                                               /* T309 is not enabled : hangup calls when alarm occurs */
-                                                               if (p->call) {
-                                                                       if (p->pri && p->pri->pri) {
-                                                                               pri_hangup(p->pri->pri, p->call, -1);
-                                                                               pri_destroycall(p->pri->pri, p->call);
-                                                                               p->call = NULL;
-                                                                       } else
-                                                                               ast_log(LOG_WARNING, "The PRI Call have not been destroyed\n");
-                                                               }
-                                                               if (p->realcall) {
-                                                                       pri_hangup_all(p->realcall, pri);
-                                                               } else if (p->owner)
-                                                                       p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-                                                       }
-                                                       /* For PTMP connections with non persistent layer 2 we want
-                                                        * to *not* declare inalarm unless there actually is an alarm */
-                                                       if (p->sig != SIG_BRI_PTMP) {
-                                                               p->inalarm = 1;
-                                                       }
-                                               }
-                                       }
-                               }
-                               break;
-                       case PRI_EVENT_RESTART:
-                               if (e->restart.channel > -1) {
-                                       chanpos = pri_find_principle(pri, e->restart.channel);
-                                       if (chanpos < 0)
-                                               ast_log(LOG_WARNING, "Restart requested on odd/unavailable channel number %d/%d on span %d\n",
-                                                       PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
-                                       else {
-#ifdef HAVE_PRI_SERVICE_MESSAGES
-                                               char db_chan_name[20], db_answer[5], state;
-                                               int why, skipit = 0;
-                                               
-                                               ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                               snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, pri->pvts[chanpos]->span, pri->pvts[chanpos]->channel);
-                                               ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-
-                                               if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
-                                                       sscanf(db_answer, "%c:%d", &state, &why);
-                                                       if (why) {
-                                                               ast_log(LOG_NOTICE, "span '%d' channel '%d' out-of-service (reason: %s), ignoring RESTART\n", pri->span,
-                                                                       e->restart.channel, (why & SRVST_FAREND) ? (why & SRVST_NEAREND) ? "both ends" : "far end" : "near end");
-                                                               skipit = 1;
-                                                       } else {
-                                                               ast_db_del(db_chan_name, SRVST_DBKEY);
-                                                       }
-                                               }
-                                               if (!skipit) {
-#endif
-                                                       ast_verb(3, "B-channel %d/%d restarted on span %d\n",
-                                                                       PRI_SPAN(e->restart.channel), PRI_CHANNEL(e->restart.channel), pri->span);
-                                                       ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                                       if (pri->pvts[chanpos]->call) {
-                                                               pri_destroycall(pri->pri, pri->pvts[chanpos]->call);
-                                                               pri->pvts[chanpos]->call = NULL;
-                                                       }
-#ifdef HAVE_PRI_SERVICE_MESSAGES
-                                               }
-#endif
-                                               /* Force soft hangup if appropriate */
-                                               if (pri->pvts[chanpos]->realcall)
-                                                       pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
-                                               else if (pri->pvts[chanpos]->owner)
-                                                       pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-                                               ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                                       }
-                               } else {
-                                       ast_verb(3, "Restart on requested on entire span %d\n", pri->span);
-                                       for (x = 0; x < pri->numchans; x++)
-                                               if (pri->pvts[x]) {
-                                                       ast_mutex_lock(&pri->pvts[x]->lock);
-                                                       if (pri->pvts[x]->call) {
-                                                               pri_destroycall(pri->pri, pri->pvts[x]->call);
-                                                               pri->pvts[x]->call = NULL;
-                                                       }
-                                                       if (pri->pvts[chanpos]->realcall)
-                                                               pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
-                                                       else if (pri->pvts[x]->owner)
-                                                               pri->pvts[x]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-                                                       ast_mutex_unlock(&pri->pvts[x]->lock);
-                                               }
-                               }
-                               break;
-                       case PRI_EVENT_KEYPAD_DIGIT:
-                               chanpos = pri_find_principle(pri, e->digit.channel);
-                               if (chanpos < 0) {
-                                       ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n",
-                                               PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
-                               } else {
-                                       chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
-                                       if (chanpos > -1) {
-                                               ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                               /* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
-                                               if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
-                                                       /* how to do that */
-                                                       int digitlen = strlen(e->digit.digits);
-                                                       char digit;
-                                                       int i;
-                                                       for (i = 0; i < digitlen; i++) {
-                                                               digit = e->digit.digits[i];
-                                                               {
-                                                                       struct ast_frame f = { AST_FRAME_DTMF, digit, };
-                                                                       dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
-                                                               }
-                                                       }
-                                               }
-                                               ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                                       }
-                               }
-                               break;
-
-                       case PRI_EVENT_INFO_RECEIVED:
-                               chanpos = pri_find_principle(pri, e->ring.channel);
-                               if (chanpos < 0) {
-                                       ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n",
-                                               PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
-                               } else {
-                                       chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
-                                       if (chanpos > -1) {
-                                               ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                               /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
-                                               if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
-                                                       /* how to do that */
-                                                       int digitlen = strlen(e->ring.callednum);
-                                                       char digit;
-                                                       int i;
-                                                       for (i = 0; i < digitlen; i++) {
-                                                               digit = e->ring.callednum[i];
-                                                               {
-                                                                       struct ast_frame f = { AST_FRAME_DTMF, digit, };
-                                                                       dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
-                                                               }
-                                                       }
-                                               }
-                                               ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                                       }
-                               }
-                               break;
-#ifdef HAVE_PRI_SERVICE_MESSAGES
-                       case PRI_EVENT_SERVICE:
-                               chanpos = pri_find_principle(pri, e->service.channel);
-                               if (chanpos < 0) {
-                                       ast_log(LOG_WARNING, "Received service change status %d on unconfigured channel %d/%d span %d\n",
-                                               e->service_ack.changestatus, PRI_SPAN(e->service_ack.channel), PRI_CHANNEL(e->service_ack.channel), pri->span);
-                               } else {
-                                       char db_chan_name[20], db_answer[5], state;
-                                       int ch, why = -1;
-
-                                       ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                       ch = pri->pvts[chanpos]->channel;
-                                       ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                                       
-                                       snprintf(db_chan_name, sizeof(db_chan_name), "%s/%d:%d", dahdi_db, pri->pvts[chanpos]->span, ch);
-                                       if (!ast_db_get(db_chan_name, SRVST_DBKEY, db_answer, sizeof(db_answer))) {
-                                               sscanf(db_answer, "%c:%d", &state, &why);
-                                               ast_db_del(db_chan_name, SRVST_DBKEY);
-                                       }
-                                       switch (e->service.changestatus) {
-                                       case 0: /* in-service */
-                                               if (why > -1) {
-                                                       if (why & SRVST_NEAREND) {
-                                                               snprintf(db_answer, sizeof(db_answer), "%s:%d", SRVST_TYPE_OOS, SRVST_NEAREND);
-                                                               ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
-                                                               ast_debug(2, "channel '%d' service state { near: out-of-service,  far: in-service }\n", ch);
-                                                       }
-                                               }
-                                               break;
-                                       case 2: /* out-of-service */
-                                               if (why == -1) {
-                                                       why = SRVST_FAREND;
-                                               } else {
-                                                       why |= SRVST_FAREND;
-                                               }
-                                               snprintf(db_answer, sizeof(db_answer), "%s:%d", SRVST_TYPE_OOS, why);
-                                               ast_db_put(db_chan_name, SRVST_DBKEY, db_answer);
-                                               break;
-                                       default:
-                                               ast_log(LOG_ERROR, "Huh?  changestatus is: %d\n", e->service.changestatus);
-                                       }
-                                       ast_log(LOG_NOTICE, "Channel %d/%d span %d (logical: %d) received a change of service message, status '%d'\n",
-                                               PRI_SPAN(e->service.channel), PRI_CHANNEL(e->service.channel), pri->span, ch, e->service.changestatus);
-                               }
-                               break;
-                       case PRI_EVENT_SERVICE_ACK:
-                               chanpos = pri_find_principle(pri, e->service_ack.channel);
-                               if (chanpos < 0) {
-                                       ast_log(LOG_WARNING, "Received service acknowledge change status '%d' on unconfigured channel %d/%d span %d\n",
-                                               e->service_ack.changestatus, PRI_SPAN(e->service_ack.channel), PRI_CHANNEL(e->service_ack.channel), pri->span);
-                               } else {
-                                       ast_debug(2, "Channel %d/%d span %d received a change os service acknowledgement message, status '%d'\n",
-                                               PRI_SPAN(e->service_ack.channel), PRI_CHANNEL(e->service_ack.channel), pri->span, e->service_ack.changestatus);
-                               }
-                               break;
-#endif
-                       case PRI_EVENT_RING:
-                               crv = NULL;
-                               if (e->ring.channel == -1)
-                                       chanpos = pri_find_empty_chan(pri, 1);
-                               else
-                                       chanpos = pri_find_principle(pri, e->ring.channel);
-                               /* if no channel specified find one empty */
-                               if (chanpos < 0) {
-                                       ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n",
-                                               PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
-                               } else {
-                                       ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                       if (pri->pvts[chanpos]->owner) {
-                                               if (pri->pvts[chanpos]->call == e->ring.call) {
-                                                       ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n",
-                                                               PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
-                                                       ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                                                       break;
-                                               } else {
-                                                       /* This is where we handle initial glare */
-                                                       ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d.  Attempting to renegotiate channel.\n",
-                                                       PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
-                                                       ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                                                       chanpos = -1;
-                                               }
-                                       }
-                                       if (chanpos > -1)
-                                               ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                               }
-                               if ((chanpos < 0) && (e->ring.flexible))
-                                       chanpos = pri_find_empty_chan(pri, 1);
-                               if (chanpos > -1) {
-                                       ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                       if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
-                                               /* Should be safe to lock CRV AFAIK while bearer is still locked */
-                                               crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
-                                               if (crv)
-                                                       ast_mutex_lock(&crv->lock);
-                                               if (!crv || crv->owner) {
-                                                       pri->pvts[chanpos]->call = NULL;
-                                                       if (crv) {
-                                                               if (crv->owner)
-                                                                       crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-                                                               ast_log(LOG_WARNING, "Call received for busy CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
-                                                       } else
-                                                               ast_log(LOG_NOTICE, "Call received for unconfigured CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
-                                                       pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
-                                                       if (crv)
-                                                               ast_mutex_unlock(&crv->lock);
-                                                       ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                                                       break;
-                                               }
-                                       }
-                                       pri->pvts[chanpos]->call = e->ring.call;
-                                       apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
-                                       if (pri->pvts[chanpos]->use_callerid) {
-                                               ast_shrink_phone_number(plancallingnum);
-                                               ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
-#ifdef PRI_ANI
-                                               if (!ast_strlen_zero(e->ring.callingani)) {
-                                                       apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
-                                                       ast_shrink_phone_number(plancallingani);
-                                                       ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
-                                               } else {
-                                                       pri->pvts[chanpos]->cid_ani[0] = '\0';
-                                               }
-#endif
-                                               ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
-                                               pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
-                                       } else {
-                                               pri->pvts[chanpos]->cid_num[0] = '\0';
-                                               pri->pvts[chanpos]->cid_ani[0] = '\0';
-                                               pri->pvts[chanpos]->cid_name[0] = '\0';
-                                               pri->pvts[chanpos]->cid_ton = 0;
-                                       }
-                                       apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
-                                               e->ring.redirectingnum, e->ring.callingplanrdnis);
-                                       /* If immediate=yes go to s|1 */
-                                       if (pri->pvts[chanpos]->immediate) {
-                                               ast_verb(3, "Going to extension s|1 because of immediate=yes\n");
-                                               pri->pvts[chanpos]->exten[0] = 's';
-                                               pri->pvts[chanpos]->exten[1] = '\0';
-                                       }
-                                       /* Get called number */
-                                       else if (!ast_strlen_zero(e->ring.callednum)) {
-                                               ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
-                                               ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
-                                       } else if (pri->overlapdial)
-                                               pri->pvts[chanpos]->exten[0] = '\0';
-                                       else {
-                                               /* Some PRI circuits are set up to send _no_ digits.  Handle them as 's'. */
-                                               pri->pvts[chanpos]->exten[0] = 's';
-                                               pri->pvts[chanpos]->exten[1] = '\0';
-                                       }
-                                       /* Set DNID on all incoming calls -- even immediate */
-                                       if (!ast_strlen_zero(e->ring.callednum))
-                                               ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
-                                       /* No number yet, but received "sending complete"? */
-                                       if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
-                                               ast_verb(3, "Going to extension s|1 because of Complete received\n");
-                                               pri->pvts[chanpos]->exten[0] = 's';
-                                               pri->pvts[chanpos]->exten[1] = '\0';
-                                       }
-                                       /* Make sure extension exists (or in overlap dial mode, can exist) */
-                                       if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
-                                               ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
-                                               /* Setup law */
-                                               int law;
-                                               if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
-                                                       /* Set to audio mode at this point */
-                                                       law = 1;
-                                                       if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
-                                                               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;
-                                               else
-                                                       law = DAHDI_LAW_MULAW;
-                                               res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
-                                               if (res < 0)
-                                                       ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
-                                               res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
-                                               if (res < 0)
-                                                       ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
-                                               if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
-                                                       /* Just announce proceeding */
-                                                       pri->pvts[chanpos]->proceeding = 1;
-                                                       pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
-                                               } else {
-                                                       if (pri->switchtype != PRI_SWITCH_GR303_TMC)
-                                                               pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
-                                                       else
-                                                               pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
-                                               }
-                                               /* Get the use_callingpres state */
-                                               pri->pvts[chanpos]->callingpres = e->ring.callingpres;
-
-                                               /* Start PBX */
-                                               if (!e->ring.complete && (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
-                                                       /* Release the PRI lock while we create the channel */
-                                                       ast_mutex_unlock(&pri->lock);
-                                                       if (crv) {
-                                                               /* Set bearer and such */
-                                                               pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
-                                                               c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
-                                                               pri->pvts[chanpos]->owner = &inuse;
-                                                               ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
-                                                       } else {
-                                                               c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
-                                                       }
-
-                                                       ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-
-                                                       if (!ast_strlen_zero(e->ring.callingsubaddr)) {
-                                                               pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
-                                                       }
-                                                       if (e->ring.ani2 >= 0) {
-                                                               snprintf(ani2str, 5, "%.2d", e->ring.ani2);
-                                                               pbx_builtin_setvar_helper(c, "ANI2", ani2str);
-                                                               pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
-                                                       }
-
-#ifdef SUPPORT_USERUSER
-                                                       if (!ast_strlen_zero(e->ring.useruserinfo)) {
-                                                               pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
-                                                       }
-#endif
-
-                                                       snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
-                                                       pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
-                                                       if (e->ring.redirectingreason >= 0)
-                                                               pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
-
-                                                       ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                                       ast_mutex_lock(&pri->lock);
-                                                       if (c && !ast_pthread_create_detached(&threadid, NULL, analog_ss_thread, c)) {
-                                                               ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
-                                                                               plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
-                                                                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
-                                                       } else {
-                                                               ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
-                                                                       pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
-                                                               if (c)
-                                                                       ast_hangup(c);
-                                                               else {
-                                                                       pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
-                                                                       pri->pvts[chanpos]->call = NULL;
-                                                               }
-                                                       }
-                                               } else {
-                                                       ast_mutex_unlock(&pri->lock);
-                                                       /* Release PRI lock while we create the channel */
-                                                       c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype);
-                                                       if (c) {
-                                                               char calledtonstr[10];
-
-                                                               ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-
-                                                               if (e->ring.ani2 >= 0) {
-                                                                       snprintf(ani2str, 5, "%d", e->ring.ani2);
-                                                                       pbx_builtin_setvar_helper(c, "ANI2", ani2str);
-                                                                       pri->pvts[chanpos]->cid_ani2 = e->ring.ani2;
-                                                               }
-
-#ifdef SUPPORT_USERUSER
-                                                               if (!ast_strlen_zero(e->ring.useruserinfo)) {
-                                                                       pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
-                                                               }
-#endif
-
-                                                               if (e->ring.redirectingreason >= 0)
-                                                                       pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
-
-                                                               snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
-                                                               pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
-
-                                                               ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                                               ast_mutex_lock(&pri->lock);
-
-                                                               ast_verb(3, "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
-                                                                               plancallingnum, pri->pvts[chanpos]->exten,
-                                                                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
-
-                                                               dahdi_enable_ec(pri->pvts[chanpos]);
-                                                       } else {
-
-                                                               ast_mutex_lock(&pri->lock);
-
-                                                               ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
-                                                                       pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
-                                                               pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
-                                                               pri->pvts[chanpos]->call = NULL;
-                                                       }
-                                               }
-                                       } else {
-                                               ast_verb(3, "Extension '%s' in context '%s' from '%s' does not exist.  Rejecting call on channel %d/%d, span %d\n",
-                                                               pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan,
-                                                                       pri->pvts[chanpos]->prioffset, pri->span);
-                                               pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
-                                               pri->pvts[chanpos]->call = NULL;
-                                               pri->pvts[chanpos]->exten[0] = '\0';
-                                       }
-                                       if (crv)
-                                               ast_mutex_unlock(&crv->lock);
-                                       ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                               } else {
-                                       if (e->ring.flexible)
-                                               pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
-                                       else
-                                               pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
-                               }
-                               break;
-                       case PRI_EVENT_RINGING:
-                               chanpos = pri_find_principle(pri, e->ringing.channel);
-                               if (chanpos < 0) {
-                                       ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n",
-                                               PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
-                               } else {
-                                       chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
-                                       if (chanpos < 0) {
-                                               ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n",
-                                                       PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
-                                       } else {
-                                               ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                               if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
-                                                       dahdi_enable_ec(pri->pvts[chanpos]);
-                                                       pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
-                                                       pri->pvts[chanpos]->alerting = 1;
-                                               } else
-                                                       ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n");
-
-                                               if (
-#ifdef PRI_PROGRESS_MASK
-                                                       e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE
-#else
-                                                       e->ringing.progress == 8
-#endif
-                                                       ) {
-                                                       /* Now we can do call progress detection */
-                                                       if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
-                                                               /* RINGING detection isn't required because we got ALERTING signal */
-                                                               ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
-                                                               pri->pvts[chanpos]->dsp_features = 0;
-                                                       }
-                                               }
-
-#ifdef SUPPORT_USERUSER
-                                               if (!ast_strlen_zero(e->ringing.useruserinfo)) {
-                                                       struct ast_channel *owner = pri->pvts[chanpos]->owner;
-                                                       ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                                                       pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
-                                                       ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                               }
-#endif
-
-                                               ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                                       }
-                               }
-                               break;
-                       case PRI_EVENT_PROGRESS:
-                               /* Get chan value if e->e is not PRI_EVNT_RINGING */
-                               chanpos = pri_find_principle(pri, e->proceeding.channel);
-                               if (chanpos > -1) {
-                                       if ((!pri->pvts[chanpos]->progress)
-#ifdef PRI_PROGRESS_MASK
-                                               || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
-#else
-                                               || (e->proceeding.progress == 8)
-#endif
-                                               ) {
-                                               struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
-
-                                               if (e->proceeding.cause > -1) {
-                                                       ast_verb(3, "PROGRESS with cause code %d received\n", e->proceeding.cause);
-
-                                                       /* Work around broken, out of spec USER_BUSY cause in a progress message */
-                                                       if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
-                                                               if (pri->pvts[chanpos]->owner) {
-                                                                       ast_verb(3, "PROGRESS with 'user busy' received, signalling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
-
-                                                                       pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
-                                                                       f.subclass = AST_CONTROL_BUSY;
-                                                               }
-                                                       }
-                                               }
-
-                                               ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                               ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
-                                                       pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
-                                               dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
-                                               if (
-#ifdef PRI_PROGRESS_MASK
-                                                       e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
-#else
-                                                       e->proceeding.progress == 8
-#endif
-                                                       ) {
-                                                       /* Now we can do call progress detection */
-                                                       if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
-                                                               ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
-                                                               pri->pvts[chanpos]->dsp_features = 0;
-                                                       }
-                                                       /* Bring voice path up */
-                                                       f.subclass = AST_CONTROL_PROGRESS;
-                                                       dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
-                                               }
-                                               pri->pvts[chanpos]->progress = 1;
-                                               pri->pvts[chanpos]->dialing = 0;
-                                               ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                                       }
-                               }
-                               break;
-                       case PRI_EVENT_PROCEEDING:
-                               chanpos = pri_find_principle(pri, e->proceeding.channel);
-                               if (chanpos > -1) {
-                                       if (!pri->pvts[chanpos]->proceeding) {
-                                               struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
-
-                                               ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                               ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
-                                                       pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
-                                               dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
-                                               if (
-#ifdef PRI_PROGRESS_MASK
-                                                       e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
-#else
-                                                       e->proceeding.progress == 8
-#endif
-                                                       ) {
-                                                       /* Now we can do call progress detection */
-                                                       if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
-                                                               ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
-                                                               pri->pvts[chanpos]->dsp_features = 0;
-                                                       }
-                                                       /* Bring voice path up */
-                                                       f.subclass = AST_CONTROL_PROGRESS;
-                                                       dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
-                                               }
-                                               pri->pvts[chanpos]->proceeding = 1;
-                                               pri->pvts[chanpos]->dialing = 0;
-                                               ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                                       }
-                               }
-                               break;
-                       case PRI_EVENT_FACNAME:
-                               chanpos = pri_find_principle(pri, e->facname.channel);
-                               if (chanpos < 0) {
-                                       ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n",
-                                               PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
-                               } else {
-                                       chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
-                                       if (chanpos < 0) {
-                                               ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n",
-                                                       PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
-                                       } else {
-                                               /* Re-use *69 field for PRI */
-                                               ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                               ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
-                                               ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
-                                               pri->pvts[chanpos]->subs[SUB_REAL].needcallerid =1;
-                                               dahdi_enable_ec(pri->pvts[chanpos]);
-                                               ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                                       }
-                               }
-                               break;
-                       case PRI_EVENT_ANSWER:
-                               chanpos = pri_find_principle(pri, e->answer.channel);
-                               if (chanpos < 0) {
-                                       ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n",
-                                               PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
-                               } else {
-                                       chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
-                                       if (chanpos < 0) {
-                                               ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n",
-                                                       PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
-                                       } else {
-                                               ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                               /* Now we can do call progress detection */
-
-                                               /* We changed this so it turns on the DSP no matter what... progress or no progress.
-                                                * By this time, we need DTMF detection and other features that were previously disabled
-                                                * -- Matt F */
-                                               if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
-                                                       ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
-                                                       pri->pvts[chanpos]->dsp_features = 0;
-                                               }
-                                               if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
-                                                       ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n");
-                                                       x = DAHDI_START;
-                                                       res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
-                                                       if (res < 0) {
-                                                               if (errno != EINPROGRESS) {
-                                                                       ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
-                                                               }
-                                                       }
-                                               } else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
-                                                       pri->pvts[chanpos]->dialing = 1;
-                                                       /* Send any "w" waited stuff */
-                                                       res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
-                                                       if (res < 0) {
-                                                               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);
-
-                                                       pri->pvts[chanpos]->dop.dialstr[0] = '\0';
-                                               } else if (pri->pvts[chanpos]->confirmanswer) {
-                                                       ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
-                                               } else {
-                                                       pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
-                                                       /* Enable echo cancellation if it's not on already */
-                                                       dahdi_enable_ec(pri->pvts[chanpos]);
-                                               }
-
-#ifdef SUPPORT_USERUSER
-                                               if (!ast_strlen_zero(e->answer.useruserinfo)) {
-                                                       struct ast_channel *owner = pri->pvts[chanpos]->owner;
-                                                       ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                                                       pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
-                                                       ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                               }
-#endif
-
-                                               ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                                       }
-                               }
-                               break;
-                       case PRI_EVENT_HANGUP:
-                               chanpos = pri_find_principle(pri, e->hangup.channel);
-                               if (chanpos < 0) {
-                                       ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n",
-                                               PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-                               } else {
-                                       chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
-                                       if (chanpos > -1) {
-                                               ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                               if (!pri->pvts[chanpos]->alreadyhungup) {
-                                                       /* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
-                                                       pri->pvts[chanpos]->alreadyhungup = 1;
-                                                       if (pri->pvts[chanpos]->realcall)
-                                                               pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
-                                                       else if (pri->pvts[chanpos]->owner) {
-                                                               /* Queue a BUSY instead of a hangup if our cause is appropriate */
-                                                               pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
-                                                               if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
-                                                                       pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-                                                               else {
-                                                                       switch (e->hangup.cause) {
-                                                                       case PRI_CAUSE_USER_BUSY:
-                                                                               pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
-                                                                               break;
-                                                                       case PRI_CAUSE_CALL_REJECTED:
-                                                                       case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
-                                                                       case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
-                                                                       case PRI_CAUSE_SWITCH_CONGESTION:
-                                                                       case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
-                                                                       case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
-                                                                               pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
-                                                                               break;
-                                                                       default:
-                                                                               pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-                                                                       }
-                                                               }
-                                                       }
-                                                       ast_verb(3, "Channel %d/%d, span %d got hangup, cause %d\n",
-                                                                       pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
-                                               } else {
-                                                       pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
-                                                       pri->pvts[chanpos]->call = NULL;
-                                               }
-                                               if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
-                                                       ast_verb(3, "Forcing restart of channel %d/%d on span %d since channel reported in use\n",
-                                                                       PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-                                                       pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
-                                                       pri->pvts[chanpos]->resetting = 1;
-                                               }
-                                               if (e->hangup.aoc_units > -1)
-                                                       ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
-                                                                       pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
-
-#ifdef SUPPORT_USERUSER
-                                               if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
-                                                       struct ast_channel *owner = pri->pvts[chanpos]->owner;
-                                                       ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                                                       pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
-                                                       ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                               }
-#endif
+static void dahdi_pri_message(struct pri *pri, char *s)
+{
+       int x, y;
+       int dchan = -1, span = -1, dchancount = 0;
 
-                                               ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                                       } else {
-                                               ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n",
-                                                       PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-                                       }
-                               }
+       if (pri) {
+               for (x = 0; x < NUM_SPANS; x++) {
+                       for (y = 0; y < NUM_DCHANS; y++) {
+                               if (pris[x].pri.dchans[y])
+                                       dchancount++;
+
+                               if (pris[x].pri.dchans[y] == pri)
+                                       dchan = y;
+                       }
+                       if (dchan >= 0) {
+                               span = x;
                                break;
-#ifndef PRI_EVENT_HANGUP_REQ
-#error please update libpri
-#endif
-                       case PRI_EVENT_HANGUP_REQ:
-                               chanpos = pri_find_principle(pri, e->hangup.channel);
-                               if (chanpos < 0) {
-                                       ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n",
-                                               PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-                               } else {
-                                       chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
-                                       if (chanpos > -1) {
-                                               ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                               if (pri->pvts[chanpos]->realcall)
-                                                       pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
-                                               else if (pri->pvts[chanpos]->owner) {
-                                                       pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
-                                                       if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
-                                                               pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-                                                       else {
-                                                               switch (e->hangup.cause) {
-                                                               case PRI_CAUSE_USER_BUSY:
-                                                                       pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
-                                                                       break;
-                                                               case PRI_CAUSE_CALL_REJECTED:
-                                                               case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
-                                                               case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
-                                                               case PRI_CAUSE_SWITCH_CONGESTION:
-                                                               case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
-                                                               case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
-                                                                       pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
-                                                                       break;
-                                                               default:
-                                                                       pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-                                                                       break;
-                                                               }
-                                                       }
-                                                       ast_verb(3, "Channel %d/%d, span %d got hangup request, cause %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span, e->hangup.cause);
-                                                       if (e->hangup.aoc_units > -1)
-                                                               ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
-                                                                               pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
-                                               } else {
-                                                       pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
-                                                       pri->pvts[chanpos]->call = NULL;
-                                               }
-                                               if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
-                                                       ast_verb(3, "Forcing restart of channel %d/%d span %d since channel reported in use\n",
-                                                                       PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-                                                       pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
-                                                       pri->pvts[chanpos]->resetting = 1;
-                                               }
+                       }
+                       dchancount = 0;
+               }
+               if (dchancount > 1 && (span > -1))
+                       ast_verbose("[Span %d D-Channel %d]%s", span, dchan, s);
+               else
+                       ast_verbose("%s", s);
+       } else
+               ast_verbose("%s", s);
 
-#ifdef SUPPORT_USERUSER
-                                               if (!ast_strlen_zero(e->hangup.useruserinfo)) {
-                                                       struct ast_channel *owner = pri->pvts[chanpos]->owner;
-                                                       ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                                                       pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
-                                                       ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                               }
-#endif
+       ast_mutex_lock(&pridebugfdlock);
 
-                                               ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                                       } else {
-                                               ast_log(LOG_WARNING, "Hangup REQ on bad channel %d/%d on span %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-                                       }
-                               }
-                               break;
-                       case PRI_EVENT_HANGUP_ACK:
-                               chanpos = pri_find_principle(pri, e->hangup.channel);
-                               if (chanpos < 0) {
-                                       ast_log(LOG_WARNING, "Hangup ACK requested on unconfigured channel number %d/%d span %d\n",
-                                               PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-                               } else {
-                                       chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
-                                       if (chanpos > -1) {
-                                               ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                               pri->pvts[chanpos]->call = NULL;
-                                               pri->pvts[chanpos]->resetting = 0;
-                                               if (pri->pvts[chanpos]->owner) {
-                                                       ast_verb(3, "Channel %d/%d, span %d got hangup ACK\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-                                               }
+       if (pridebugfd >= 0) {
+               if (write(pridebugfd, s, strlen(s)) < 0) {
+                       ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
+               }
+       }
 
-#ifdef SUPPORT_USERUSER
-                                               if (!ast_strlen_zero(e->hangup.useruserinfo)) {
-                                                       struct ast_channel *owner = pri->pvts[chanpos]->owner;
-                                                       ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                                                       pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
-                                                       ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                               }
-#endif
+       ast_mutex_unlock(&pridebugfdlock);
+}
+#endif /* defined(HAVE_PRI) */
 
-                                               ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                                       }
-                               }
-                               break;
-                       case PRI_EVENT_CONFIG_ERR:
-                               ast_log(LOG_WARNING, "PRI Error on span %d: %s\n", pri->trunkgroup, e->err.err);
-                               break;
-                       case PRI_EVENT_RESTART_ACK:
-                               chanpos = pri_find_principle(pri, e->restartack.channel);
-                               if (chanpos < 0) {
-                                       /* Sometime switches (e.g. I421 / British Telecom) don't give us the
-                                          channel number, so we have to figure it out...  This must be why
-                                          everybody resets exactly a channel at a time. */
-                                       for (x = 0; x < pri->numchans; x++) {
-                                               if (pri->pvts[x] && pri->pvts[x]->resetting) {
-                                                       chanpos = x;
-                                                       ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                                       ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
-                                                               pri->pvts[chanpos]->prioffset, pri->span);
-                                                       if (pri->pvts[chanpos]->realcall)
-                                                               pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
-                                                       else if (pri->pvts[chanpos]->owner) {
-                                                               ast_log(LOG_WARNING, "Got restart ack on channel %d/%d with owner on span %d\n", pri->pvts[chanpos]->logicalspan,
-                                                                       pri->pvts[chanpos]->prioffset, pri->span);
-                                                               pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-                                                       }
-                                                       pri->pvts[chanpos]->resetting = 0;
-                                                       ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
-                                                                       pri->pvts[chanpos]->prioffset, pri->span);
-                                                       ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                                                       if (pri->resetting)
-                                                               pri_check_restart(pri);
-                                                       break;
-                                               }
-                                       }
-                                       if (chanpos < 0) {
-                                               ast_log(LOG_WARNING, "Restart ACK requested on strange channel %d/%d span %d\n",
-                                                       PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
-                                       }
-                               } else {
-                                       if (pri->pvts[chanpos]) {
-                                               ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                               if (pri->pvts[chanpos]->realcall)
-                                                       pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
-                                               else if (pri->pvts[chanpos]->owner) {
-                                                       ast_log(LOG_WARNING, "Got restart ack on channel %d/%d span %d with owner\n",
-                                                               PRI_SPAN(e->restartack.channel), PRI_CHANNEL(e->restartack.channel), pri->span);
-                                                       pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-                                               }
-                                               pri->pvts[chanpos]->resetting = 0;
-                                               pri->pvts[chanpos]->inservice = 1;
-                                               ast_verb(3, "B-channel %d/%d successfully restarted on span %d\n", pri->pvts[chanpos]->logicalspan,
-                                                                       pri->pvts[chanpos]->prioffset, pri->span);
-                                               ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                                               if (pri->resetting)
-                                                       pri_check_restart(pri);
-                                       }
-                               }
-                               break;
-                       case PRI_EVENT_SETUP_ACK:
-                               chanpos = pri_find_principle(pri, e->setup_ack.channel);
-                               if (chanpos < 0) {
-                                       ast_log(LOG_WARNING, "Received SETUP_ACKNOWLEDGE on unconfigured channel %d/%d span %d\n",
-                                               PRI_SPAN(e->setup_ack.channel), PRI_CHANNEL(e->setup_ack.channel), pri->span);
-                               } else {
-                                       chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
-                                       if (chanpos > -1) {
-                                               ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                               pri->pvts[chanpos]->setup_ack = 1;
-                                               /* Send any queued digits */
-                                               for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
-                                                       ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
-                                                       pri_information(pri->pri, pri->pvts[chanpos]->call,
-                                                               pri->pvts[chanpos]->dialdest[x]);
-                                               }
-                                               ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                                       } else
-                                               ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);
-                               }
-                               break;
-                       case PRI_EVENT_NOTIFY:
-                               chanpos = pri_find_principle(pri, e->notify.channel);
-                               if (chanpos < 0) {
-                                       ast_log(LOG_WARNING, "Received NOTIFY on unconfigured channel %d/%d span %d\n",
-                                               PRI_SPAN(e->notify.channel), PRI_CHANNEL(e->notify.channel), pri->span);
-                               } else if (!pri->discardremoteholdretrieval) {
-                                       struct ast_frame f = { AST_FRAME_CONTROL, };
-                                       ast_mutex_lock(&pri->pvts[chanpos]->lock);
-                                       switch (e->notify.info) {
-                                       case PRI_NOTIFY_REMOTE_HOLD:
-                                               f.subclass = AST_CONTROL_HOLD;
-                                               dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
-                                               break;
-                                       case PRI_NOTIFY_REMOTE_RETRIEVAL:
-                                               f.subclass = AST_CONTROL_UNHOLD;
-                                               dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
-                                               break;
-                                       }
-                                       ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-                               }
+#if defined(HAVE_PRI)
+static void dahdi_pri_error(struct pri *pri, char *s)
+{
+       int x, y;
+       int dchan = -1, span = -1;
+       int dchancount = 0;
+
+       if (pri) {
+               for (x = 0; x < NUM_SPANS; x++) {
+                       for (y = 0; y < NUM_DCHANS; y++) {
+                               if (pris[x].pri.dchans[y])
+                                       dchancount++;
+
+                               if (pris[x].pri.dchans[y] == pri)
+                                       dchan = y;
+                       }
+                       if (dchan >= 0) {
+                               span = x;
                                break;
-                       default:
-                               ast_debug(1, "Event: %d\n", e->e);
                        }
+                       dchancount = 0;
+               }
+               if ((dchancount > 1) && (span > -1))
+                       ast_log(LOG_ERROR, "[Span %d D-Channel %d] PRI: %s", span, dchan, s);
+               else
+                       ast_log(LOG_ERROR, "%s", s);
+       } else
+               ast_log(LOG_ERROR, "%s", s);
+
+       ast_mutex_lock(&pridebugfdlock);
+
+       if (pridebugfd >= 0) {
+               if (write(pridebugfd, s, strlen(s)) < 0) {
+                       ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
                }
-               ast_mutex_unlock(&pri->lock);
        }
-       /* Never reached */
-       return NULL;
+
+       ast_mutex_unlock(&pridebugfdlock);
 }
 #endif /* defined(HAVE_PRI) */
 
-#if defined(HAVE_PRI)
-static int start_pri(struct dahdi_pri *pri)
+#ifdef HAVE_PRI
+static int prepare_pri(struct dahdi_pri *pri)
 {
-       int res, x;
+       int i, res, x;
        struct dahdi_params p;
        struct dahdi_bufferinfo bi;
        struct dahdi_spaninfo si;
-       int i;
+
+       pri->pri.calls = &dahdi_pri_callbacks;
 
        for (i = 0; i < NUM_DCHANS; i++) {
                if (!pri->dchannels[i])
                        break;
-               pri->fds[i] = open("/dev/dahdi/channel", O_RDWR);
+               pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
                x = pri->dchannels[i];
-               if ((pri->fds[i] < 0) || (ioctl(pri->fds[i],DAHDI_SPECIFY,&x) == -1)) {
+               if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
                        ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
                        return -1;
                }
                memset(&p, 0, sizeof(p));
-               res = ioctl(pri->fds[i], DAHDI_GET_PARAMS, &p);
+               res = ioctl(pri->pri.fds[i], DAHDI_GET_PARAMS, &p);
                if (res) {
                        dahdi_close_pri_fd(pri, i);
                        ast_log(LOG_ERROR, "Unable to get parameters for D-channel %d (%s)\n", x, strerror(errno));
@@ -14932,85 +12261,31 @@ static int start_pri(struct dahdi_pri *pri)
                        return -1;
                }
                memset(&si, 0, sizeof(si));
-               res = ioctl(pri->fds[i], DAHDI_SPANSTAT, &si);
+               res = ioctl(pri->pri.fds[i], DAHDI_SPANSTAT, &si);
                if (res) {
                        dahdi_close_pri_fd(pri, i);
                        ast_log(LOG_ERROR, "Unable to get span state for D-channel %d (%s)\n", x, strerror(errno));
                }
-               if (!si.alarms)
-                       pri->dchanavail[i] |= DCHAN_NOTINALARM;
-               else
-                       pri->dchanavail[i] &= ~DCHAN_NOTINALARM;
+               if (!si.alarms) {
+                       pri_event_noalarm(&pri->pri, i, 1);
+               } else {
+                       pri_event_alarm(&pri->pri, i, 1);
+               }
                memset(&bi, 0, sizeof(bi));
                bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
                bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
                bi.numbufs = 32;
                bi.bufsize = 1024;
-               if (ioctl(pri->fds[i], DAHDI_SET_BUFINFO, &bi)) {
+               if (ioctl(pri->pri.fds[i], DAHDI_SET_BUFINFO, &bi)) {
                        ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", x, strerror(errno));
                        dahdi_close_pri_fd(pri, i);
                        return -1;
                }
-               switch (pri->sig) {
-               case SIG_BRI:
-                       pri->dchans[i] = pri_new_bri(pri->fds[i], 1, pri->nodetype, pri->switchtype);
-                       break;
-               case SIG_BRI_PTMP:
-                       pri->dchans[i] = pri_new_bri(pri->fds[i], 0, pri->nodetype, pri->switchtype);
-                       break;
-               default:
-                       pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
-#ifdef HAVE_PRI_SERVICE_MESSAGES
-                               if (pri->enable_service_message_support) {
-                                       pri_set_service_message_support(pri->dchans[i], 1);
-                               }
-#endif
-                       break;
-               }
-               /* Force overlap dial if we're doing GR-303! */
-               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_PROG_W_CAUSE
-               pri_set_chan_mapping_logical(pri->dchans[i], pri->qsigchannelmapping == DAHDI_CHAN_MAPPING_LOGICAL);
-#endif
-#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]);
-               if (!pri->dchans[i]) {
-                       dahdi_close_pri_fd(pri, i);
-                       ast_log(LOG_ERROR, "Unable to create PRI structure\n");
-                       return -1;
-               }
-               pri_set_debug(pri->dchans[i], DEFAULT_PRI_DEBUG);
-               pri_set_nsf(pri->dchans[i], pri->nsf);
-#ifdef PRI_GETSET_TIMERS
-               for (x = 0; x < PRI_MAX_TIMERS; x++) {
-                       if (pritimers[x] != 0)
-                               pri_set_timer(pri->dchans[i], x, pritimers[x]);
-               }
-#endif
-       }
-       /* Assume primary is the one we use */
-       pri->pri = pri->dchans[0];
-       pri->resetpos = -1;
-       if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) {
-               for (i = 0; i < NUM_DCHANS; i++) {
-                       if (!pri->dchannels[i])
-                               break;
-                       dahdi_close_pri_fd(pri, i);
-               }
-               ast_log(LOG_ERROR, "Unable to spawn D-channel: %s\n", strerror(errno));
-               return -1;
+               pri->pri.dchan_logical_span[i] = pris[p.spanno - 1].prilogicalspan;
        }
        return 0;
 }
-#endif /* defined(HAVE_PRI) */
 
-#if defined(HAVE_PRI)
 static char *complete_span_helper(const char *line, const char *word, int pos, int state, int rpos)
 {
        int which, span;
@@ -15020,7 +12295,7 @@ static char *complete_span_helper(const char *line, const char *word, int pos, i
                return ret;
 
        for (which = span = 0; span < NUM_SPANS; span++) {
-               if (pris[span].pri && ++which > state) {
+               if (pris[span].pri.pri && ++which > state) {
                        if (asprintf(&ret, "%d", span + 1) < 0) {       /* user indexes start from 1 */
                                ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
                        }
@@ -15029,9 +12304,7 @@ static char *complete_span_helper(const char *line, const char *word, int pos, i
        }
        return ret;
 }
-#endif /* defined(HAVE_PRI) */
 
-#if defined(HAVE_PRI)
 static char *complete_span_4(const char *line, const char *word, int pos, int state)
 {
        return complete_span_helper(line,word,pos,state,3);
@@ -15108,27 +12381,27 @@ static char *handle_pri_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_a
                ast_cli(a->fd, "Invalid span %s.  Should be a number %d to %d\n", a->argv[5], 1, NUM_SPANS);
                return CLI_SUCCESS;
        }
-       if (!pris[span-1].pri) {
+       if (!pris[span-1].pri.pri) {
                ast_cli(a->fd, "No PRI running on span %d\n", span);
                return CLI_SUCCESS;
        }
        for (x = 0; x < NUM_DCHANS; x++) {
-               if (pris[span-1].dchans[x]) {
+               if (pris[span-1].pri.dchans[x]) {
                        if (level == 1) {
-                               pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
+                               pri_set_debug(pris[span-1].pri.dchans[x], PRI_DEBUG_APDU |
                                        PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
                                        PRI_DEBUG_Q921_STATE);
                                ast_cli(a->fd, "Enabled debugging on span %d\n", span);
                        } else if (level == 0) {
-                               pri_set_debug(pris[span-1].dchans[x], 0);
-                               //close the file if it's set
+                               pri_set_debug(pris[span-1].pri.dchans[x], 0);
+                               /* close the file if it's set */
                                ast_mutex_lock(&pridebugfdlock);
                                close(pridebugfd);
                                pridebugfd = -1;
                                ast_cli(a->fd, "PRI debug output to file disabled\n");
                                ast_mutex_unlock(&pridebugfdlock);
                        } else {
-                               pri_set_debug(pris[span-1].dchans[x], PRI_DEBUG_APDU |
+                               pri_set_debug(pris[span-1].pri.dchans[x], PRI_DEBUG_APDU |
                                        PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE |
                                        PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE);
                                ast_cli(a->fd, "Enabled debugging on span %d\n", span);
@@ -15165,14 +12438,13 @@ static char *handle_pri_service_generic(struct ast_cli_entry *e, int cmd, struct