[zaptel-commits] tzafrir: branch 1.4 r4590 - /branches/1.4/kernel/xpp/
SVN commits to the Zaptel project
zaptel-commits at lists.digium.com
Sun Nov 30 06:10:03 CST 2008
Author: tzafrir
Date: Sun Nov 30 06:10:03 2008
New Revision: 4590
URL: http://svn.digium.com/view/zaptel?view=rev&rev=4590
Log:
xpp: PCM changes and related bugfixes.
* Power-denial signalling is now sent to Zaptel to decide if we're LS or
KS (and not hang up ourselves always).
* Fix card_fxo's caller_id_style=1 (FSK).
* Macro XPD_CHAN: s/xpd->chans[i]/XPD_CHAN(xpd, i)/ to reduce diff from DAHDI.
Modified:
branches/1.4/kernel/xpp/.version
branches/1.4/kernel/xpp/card_bri.c
branches/1.4/kernel/xpp/card_fxo.c
branches/1.4/kernel/xpp/card_fxs.c
branches/1.4/kernel/xpp/card_pri.c
branches/1.4/kernel/xpp/xbus-pcm.c
branches/1.4/kernel/xpp/xbus-pcm.h
branches/1.4/kernel/xpp/xpd.h
branches/1.4/kernel/xpp/xpp_zap.c
branches/1.4/kernel/xpp/xpp_zap.h
branches/1.4/kernel/xpp/xproto.c
branches/1.4/kernel/xpp/xproto.h
Modified: branches/1.4/kernel/xpp/.version
URL: http://svn.digium.com/view/zaptel/branches/1.4/kernel/xpp/.version?view=diff&rev=4590&r1=4589&r2=4590
==============================================================================
--- branches/1.4/kernel/xpp/.version (original)
+++ branches/1.4/kernel/xpp/.version Sun Nov 30 06:10:03 2008
@@ -1,1 +1,1 @@
-trunk-r6058
+branch-rel-6171-r6408
Modified: branches/1.4/kernel/xpp/card_bri.c
URL: http://svn.digium.com/view/zaptel/branches/1.4/kernel/xpp/card_bri.c?view=diff&rev=4590&r1=4589&r2=4590
==============================================================================
--- branches/1.4/kernel/xpp/card_bri.c (original)
+++ branches/1.4/kernel/xpp/card_bri.c Sun Nov 30 06:10:03 2008
@@ -208,7 +208,6 @@
bool reg30_good;
uint reg30_ticks;
bool layer1_up;
- xpp_line_t card_pcm_mask;
/*
* D-Chan: buffers + extra state info.
@@ -460,8 +459,8 @@
#ifdef XPP_DEBUGFS
xbus_log(xbus, xpd, 0, regcmd, sizeof(reg_cmd_t)); /* 0 = RX */
#endif
- dchan = &xpd->span.chans[2];
- if(!IS_SET(xpd->offhook, 2)) { /* D-chan is used? */
+ dchan = XPD_CHAN(xpd, 2);
+ if(!IS_OFFHOOK(xpd, 2)) { /* D-chan is used? */
static int rate_limit;
if((rate_limit++ % 1000) == 0)
@@ -534,7 +533,7 @@
BUG_ON(!priv);
if(!SPAN_REGISTERED(xpd) || !(xpd->span.flags & ZT_FLAG_RUNNING))
return 0;
- dchan = &xpd->chans[2];
+ dchan = XPD_CHAN(xpd, 2);
len = dchan->bytes2transmit; /* dchan's hdlc package len */
eoframe = dchan->eoftx; /* dchan's end of frame */
dchan->bytes2transmit = 0;
@@ -659,9 +658,6 @@
{
xbus_t *xbus;
struct BRI_priv_data *priv;
- xpp_line_t tmp_pcm_mask;
- int tmp_pcm_len;
- unsigned long flags;
int i;
BUG_ON(!xpd);
@@ -680,7 +676,7 @@
xpd->span.deflaw = ZT_LAW_ALAW;
BIT_SET(xpd->digital_signalling, 2); /* D-Channel */
for_each_line(xpd, i) {
- struct zt_chan *cur_chan = &xpd->chans[i];
+ struct zt_chan *cur_chan = XPD_CHAN(xpd, i);
XPD_DBG(GENERAL, xpd, "setting BRI channel %d\n", i);
snprintf(cur_chan->name, MAX_CHANNAME, "XPP_%s/%02d/%1d%1d/%d",
@@ -705,35 +701,11 @@
} else
cur_chan->sigcap = BRI_BCHAN_SIGCAP;
}
- xpd->offhook = BIT(0) | BIT(1); /* 2*bchan */
-
- /*
- * Compute PCM lentgh and mask
- * We know all cards have been initialized until now
- */
- tmp_pcm_mask = 0;
- if(xpd->addr.subunit == 0) {
- int line_count = 0;
-
- for(i = 0; i < MAX_SUBUNIT; i++) {
- xpd_t *sub_xpd = xpd_byaddr(xbus, xpd->addr.unit, i);
- if(sub_xpd) {
- tmp_pcm_mask |= PCM_SHIFT(sub_xpd->wanted_pcm_mask, i);
- line_count += 2;
- }
- }
- tmp_pcm_len = RPACKET_HEADERSIZE + sizeof(xpp_line_t) + line_count * ZT_CHUNKSIZE;
- } else
- tmp_pcm_len = 0;
- spin_lock_irqsave(&xpd->lock, flags);
- xpd->pcm_len = tmp_pcm_len;
- xpd->wanted_pcm_mask = xpd->offhook;
- priv->card_pcm_mask = tmp_pcm_mask;
+ CALL_XMETHOD(card_pcm_recompute, xbus, xpd, 0);
xpd->span.spanconfig = bri_spanconfig;
xpd->span.chanconfig = bri_chanconfig;
xpd->span.startup = bri_startup;
xpd->span.shutdown = bri_shutdown;
- spin_unlock_irqrestore(&xpd->lock, flags);
return 0;
}
@@ -943,15 +915,38 @@
return 0;
}
+static int BRI_card_open(xpd_t *xpd, lineno_t pos)
+{
+ struct BRI_priv_data *priv;
+
+ BUG_ON(!xpd);
+ priv = xpd->priv;
+ if(pos == 2) {
+ LINE_DBG(SIGNAL, xpd, pos, "OFFHOOK the whole span\n");
+ BIT_SET(xpd->offhook_state, 0);
+ BIT_SET(xpd->offhook_state, 1);
+ BIT_SET(xpd->offhook_state, 2);
+ CALL_XMETHOD(card_pcm_recompute, xpd->xbus, xpd, 0);
+ }
+ return 0;
+}
+
static int BRI_card_close(xpd_t *xpd, lineno_t pos)
{
- struct zt_chan *chan = &xpd->span.chans[pos];
+ struct zt_chan *chan = XPD_CHAN(xpd, pos);
/* Clear D-Channel pending data */
chan->bytes2receive = 0;
chan->eofrx = 0;
chan->bytes2transmit = 0;
chan->eoftx = 0;
+ if(pos == 2) {
+ LINE_DBG(SIGNAL, xpd, pos, "ONHOOK the whole span\n");
+ BIT_CLR(xpd->offhook_state, 0);
+ BIT_CLR(xpd->offhook_state, 1);
+ BIT_CLR(xpd->offhook_state, 2);
+ CALL_XMETHOD(card_pcm_recompute, xpd->xbus, xpd, 0);
+ }
return 0;
}
@@ -1031,7 +1026,7 @@
// Turn on all channels
CALL_XMETHOD(XPD_STATE, xpd->xbus, xpd, 1);
if(SPAN_REGISTERED(xpd)) {
- dchan = &span->chans[2];
+ dchan = XPD_CHAN(xpd, 2);
span->flags |= ZT_FLAG_RUNNING;
/*
* Zaptel (wrongly) assume that D-Channel need HDLC decoding
@@ -1066,14 +1061,74 @@
return 0;
}
-static void BRI_card_pcm_fromspan(xbus_t *xbus, xpd_t *xpd, xpp_line_t wanted_lines, xpacket_t *pack)
+void BRI_card_pcm_recompute(xbus_t *xbus, xpd_t *xpd, xpp_line_t dont_care)
+{
+ int i;
+ int line_count;
+ xpp_line_t pcm_mask;
+ xpd_t *main_xpd;
+ unsigned long flags;
+
+ BUG_ON(!xpd);
+ main_xpd = xpd_byaddr(xbus, xpd->addr.unit, 0);
+ if(!main_xpd) {
+ XPD_DBG(DEVICES, xpd, "Unit 0 is already gone. Ignore request\n");
+ return;
+ }
+ /*
+ * We calculate all subunits, so use the main lock
+ * as a mutex for the whole operation.
+ */
+ spin_lock_irqsave(&main_xpd->lock_recompute_pcm, flags);
+ line_count = 0;
+ pcm_mask = 0;
+ for(i = 0; i < MAX_SUBUNIT; i++) {
+ xpd_t *sub_xpd = xpd_byaddr(xbus, main_xpd->addr.unit, i);
+
+ if(sub_xpd) {
+ xpp_line_t lines =
+ sub_xpd->offhook_state & ~sub_xpd->digital_signalling;
+
+ if(lines) {
+ pcm_mask |= PCM_SHIFT(lines, i);
+ line_count += 2;
+ }
+ /* subunits have fake pcm_len and wanted_pcm_mask */
+ if(i > 0) {
+ sub_xpd->pcm_len = 0;
+ sub_xpd->wanted_pcm_mask = lines;
+ }
+ }
+ }
+ /*
+ * FIXME: Workaround a bug in sync code of the Astribank.
+ * Send dummy PCM for sync.
+ */
+ if(main_xpd->addr.unit == 0 && line_count == 0) {
+ pcm_mask = BIT(0);
+ line_count = 1;
+ }
+ /*
+ * The main unit account for all subunits (pcm_len and wanted_pcm_mask).
+ */
+ main_xpd->pcm_len = (line_count)
+ ? RPACKET_HEADERSIZE + sizeof(xpp_line_t) + line_count * ZT_CHUNKSIZE
+ : 0L;
+ main_xpd->wanted_pcm_mask = pcm_mask;
+ XPD_DBG(SIGNAL, main_xpd, "pcm_len=%d wanted_pcm_mask=0x%X (%s)\n",
+ main_xpd->pcm_len, main_xpd->wanted_pcm_mask,
+ xpd->xpdname);
+ spin_unlock_irqrestore(&main_xpd->lock_recompute_pcm, flags);
+}
+
+static void BRI_card_pcm_fromspan(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack)
{
byte *pcm;
- struct zt_chan *chans;
unsigned long flags;
int i;
int subunit;
xpp_line_t pcm_mask = 0;
+ xpp_line_t wanted_lines;
BUG_ON(!xbus);
@@ -1087,18 +1142,20 @@
if(!tmp_xpd || !tmp_xpd->card_present)
continue;
spin_lock_irqsave(&tmp_xpd->lock, flags);
- chans = tmp_xpd->span.chans;
+ wanted_lines = tmp_xpd->wanted_pcm_mask;
for_each_line(tmp_xpd, i) {
+ struct zt_chan *chan = XPD_CHAN(tmp_xpd, i);
+
if(IS_SET(wanted_lines, i)) {
if(SPAN_REGISTERED(tmp_xpd)) {
#ifdef DEBUG_PCMTX
- int channo = tmp_xpd->span.chans[i].channo;
+ int channo = chan->channo;
if(pcmtx >= 0 && pcmtx_chan == channo)
memset((u_char *)pcm, pcmtx, ZT_CHUNKSIZE);
else
#endif
- memcpy((u_char *)pcm, chans[i].writechunk, ZT_CHUNKSIZE);
+ memcpy((u_char *)pcm, chan->writechunk, ZT_CHUNKSIZE);
} else
memset((u_char *)pcm, 0x7F, ZT_CHUNKSIZE);
pcm += ZT_CHUNKSIZE;
@@ -1142,7 +1199,7 @@
volatile u_char *r;
if(IS_SET(tmp_mask, i)) {
- r = tmp_xpd->span.chans[i].readchunk;
+ r = XPD_CHAN(tmp_xpd, i)->readchunk;
// memset((u_char *)r, 0x5A, ZT_CHUNKSIZE); // DEBUG
memcpy((u_char *)r, pcm, ZT_CHUNKSIZE);
pcm += ZT_CHUNKSIZE;
@@ -1395,9 +1452,11 @@
.card_zaptel_postregistration = BRI_card_zaptel_postregistration,
.card_hooksig = BRI_card_hooksig,
.card_tick = BRI_card_tick,
+ .card_pcm_recompute = BRI_card_pcm_recompute,
.card_pcm_fromspan = BRI_card_pcm_fromspan,
.card_pcm_tospan = BRI_card_pcm_tospan,
.card_ioctl = BRI_card_ioctl,
+ .card_open = BRI_card_open,
.card_close = BRI_card_close,
.card_register_reply = BRI_card_register_reply,
Modified: branches/1.4/kernel/xpp/card_fxo.c
URL: http://svn.digium.com/view/zaptel/branches/1.4/kernel/xpp/card_fxo.c?view=diff&rev=4590&r1=4589&r2=4590
==============================================================================
--- branches/1.4/kernel/xpp/card_fxo.c (original)
+++ branches/1.4/kernel/xpp/card_fxo.c Sun Nov 30 06:10:03 2008
@@ -175,6 +175,27 @@
/*---------------- FXO: Static functions ----------------------------------*/
+static const char *power2str(enum power_state pw)
+{
+ switch(pw) {
+ case POWER_UNKNOWN: return "UNKOWN";
+ case POWER_OFF: return "OFF";
+ case POWER_ON: return "ON";
+ }
+ return NULL;
+}
+
+static void power_change(xpd_t *xpd, int portno, enum power_state pw)
+{
+ struct FXO_priv_data *priv;
+
+ priv = xpd->priv;
+ LINE_DBG(SIGNAL, xpd, portno, "power: %s -> %s\n",
+ power2str(priv->power[portno]),
+ power2str(pw));
+ priv->power[portno] = pw;
+}
+
static void reset_battery_readings(xpd_t *xpd, lineno_t pos)
{
struct FXO_priv_data *priv = xpd->priv;
@@ -265,30 +286,15 @@
static void update_zap_ring(xpd_t *xpd, int pos, bool on)
{
- zt_rxsig_t rxsig;
-
- BUG_ON(!xpd);
- if(on) {
- if(caller_id_style == CID_STYLE_BELL) {
- LINE_DBG(SIGNAL, xpd, pos, "Caller-ID PCM: off\n");
- BIT_CLR(xpd->cid_on, pos);
- }
- rxsig = ZT_RXSIG_RING;
- } else {
- if(caller_id_style == CID_STYLE_BELL) {
- LINE_DBG(SIGNAL, xpd, pos, "Caller-ID PCM: on\n");
- BIT_SET(xpd->cid_on, pos);
- }
- rxsig = ZT_RXSIG_OFFHOOK;
- }
- pcm_recompute(xpd, 0);
+ BUG_ON(!xpd);
+ if(caller_id_style == CID_STYLE_BELL)
+ oht_pcm(xpd, pos, !on);
/*
* We should not spinlock before calling zt_hooksig() as
* it may call back into our xpp_hooksig() and cause
* a nested spinlock scenario
*/
- if(SPAN_REGISTERED(xpd))
- zt_hooksig(&xpd->chans[pos], rxsig);
+ notify_rxsig(xpd, pos, (on) ? ZT_RXSIG_RING : ZT_RXSIG_OFFHOOK);
}
static void mark_ring(xpd_t *xpd, lineno_t pos, bool on, bool update_zap)
@@ -349,15 +355,9 @@
else
MARK_OFF(priv, pos, LED_GREEN);
ret = DAA_DIRECT_REQUEST(xbus, xpd, pos, DAA_WRITE, REG_DAA_CONTROL1, value);
- if(to_offhook) {
- BIT_SET(xpd->offhook, pos);
- } else {
- BIT_CLR(xpd->offhook, pos);
- }
- if(caller_id_style != CID_STYLE_ETSI_DTMF) {
- LINE_DBG(SIGNAL, xpd, pos, "Caller-ID PCM: off\n");
- BIT_CLR(xpd->cid_on, pos);
- }
+ mark_offhook(xpd, pos, to_offhook);
+ if(caller_id_style != CID_STYLE_ETSI_DTMF)
+ oht_pcm(xpd, pos, 0);
#ifdef WITH_METERING
priv->metering_count[pos] = 0;
priv->metering_tone_state = 0L;
@@ -366,7 +366,7 @@
reset_battery_readings(xpd, pos); /* unstable during hook changes */
priv->power_denial_safezone[pos] = (to_offhook) ? POWER_DENIAL_SAFEZONE : 0;
if(!to_offhook)
- priv->power[pos] = POWER_UNKNOWN;
+ power_change(xpd, pos, POWER_UNKNOWN);
priv->cidtimer[pos] = xpd->timer_count;
spin_unlock_irqrestore(&xpd->lock, flags);
return ret;
@@ -469,10 +469,11 @@
for_each_line(xpd, i) {
do_sethook(xpd, i, 0);
priv->polarity[i] = POL_UNKNOWN; /* will be updated on next battery sample */
+ priv->polarity_debounce[i] = 0;
priv->battery[i] = BATTERY_UNKNOWN; /* will be updated on next battery sample */
priv->power[i] = POWER_UNKNOWN; /* will be updated on next battery sample */
if(caller_id_style == CID_STYLE_ETSI_DTMF)
- BIT_SET(xpd->cid_on, i);
+ oht_pcm(xpd, i, 1);
}
XPD_DBG(GENERAL, xpd, "done\n");
for_each_line(xpd, i) {
@@ -486,7 +487,7 @@
do_led(xpd, i, LED_GREEN, 0);
msleep(50);
}
- pcm_recompute(xpd, 0);
+ CALL_XMETHOD(card_pcm_recompute, xbus, xpd, 0);
return 0;
}
@@ -519,7 +520,7 @@
xpd->span.spantype = "FXO";
#endif
for_each_line(xpd, i) {
- struct zt_chan *cur_chan = &xpd->chans[i];
+ struct zt_chan *cur_chan = XPD_CHAN(xpd, i);
XPD_DBG(GENERAL, xpd, "setting FXO channel %d\n", i);
snprintf(cur_chan->name, MAX_CHANNAME, "XPP_FXO/%02d/%1d%1d/%d",
@@ -585,7 +586,6 @@
txsig2str(txsig), txsig);
return -EINVAL;
}
- pcm_recompute(xpd, 0);
return ret;
}
@@ -602,11 +602,11 @@
break;
case BATTERY_OFF:
LINE_DBG(SIGNAL, xpd, chan, "Send ZT_ALARM_RED\n");
- zt_alarm_channel(&xpd->chans[chan], ZT_ALARM_RED);
+ zt_alarm_channel(XPD_CHAN(xpd, chan), ZT_ALARM_RED);
break;
case BATTERY_ON:
LINE_DBG(SIGNAL, xpd, chan, "Send ZT_ALARM_NONE\n");
- zt_alarm_channel(&xpd->chans[chan], ZT_ALARM_NONE);
+ zt_alarm_channel(XPD_CHAN(xpd, chan), ZT_ALARM_NONE);
break;
}
}
@@ -636,7 +636,7 @@
int i;
for_each_line(xpd, i) {
- if (IS_SET(xpd->offhook, i))
+ if (IS_OFFHOOK(xpd, i))
DAA_DIRECT_REQUEST(xbus, xpd, i, DAA_READ, DAA_REG_METERING, 0);
}
}
@@ -689,7 +689,7 @@
DAA_DIRECT_REQUEST(xpd->xbus, xpd, i, DAA_READ, DAA_REG_CURRENT, 0);
}
}
- if(IS_SET(priv->maybe_power_denial, i) && !xpd->ringing[i] && IS_SET(xpd->offhook, i)) {
+ if(IS_SET(priv->maybe_power_denial, i) && !xpd->ringing[i] && IS_OFFHOOK(xpd, i)) {
/*
* Ring detection by the firmware takes some time.
* Therefore we delay our decision until we are
@@ -700,9 +700,10 @@
LINE_DBG(SIGNAL, xpd, i, "Power Denial Hangup\n");
priv->power_denial_delay[i] = 0;
BIT_CLR(priv->maybe_power_denial, i);
- do_sethook(xpd, i, 0);
- update_line_status(xpd, i, 0);
- pcm_recompute(xpd, 0);
+ /*
+ * Let Asterisk decide what to do
+ */
+ notify_rxsig(xpd, i, ZT_RXSIG_ONHOOK);
}
} else {
priv->power_denial_delay[i] = 0;
@@ -731,7 +732,7 @@
timer_count = xpd->timer_count;
for_each_line(xpd, portno) {
/* Skip offhook and ringing ports */
- if(IS_SET(xpd->offhook, portno) || xpd->ringing[portno])
+ if(IS_OFFHOOK(xpd, portno) || xpd->ringing[portno])
continue;
if(IS_SET(priv->cidfound, portno)) {
if(timer_count > priv->cidtimer[portno] + 4000) {
@@ -743,7 +744,7 @@
continue;
}
if(timer_count > priv->cidtimer[portno] + 400) {
- struct zt_chan *chan = &xpd->span.chans[portno];
+ struct zt_chan *chan = XPD_CHAN(xpd, portno);
int sample;
int i;
@@ -922,8 +923,11 @@
priv->battery[portno] = BATTERY_OFF;
if(SPAN_REGISTERED(xpd))
zap_report_battery(xpd, portno);
- priv->polarity[portno] = POL_UNKNOWN; /* What's the polarity ? */
- priv->power[portno] = POWER_UNKNOWN; /* What's the current ? */
+ /* What's the polarity ? */
+ priv->polarity[portno] = POL_UNKNOWN;
+ priv->polarity_debounce[portno] = 0;
+ /* What's the current ? */
+ power_change(xpd, portno, POWER_UNKNOWN);
/*
* Stop further processing for now
*/
@@ -976,7 +980,7 @@
msec = priv->polarity_debounce[portno]++ * poll_battery_interval;
if (msec >= POLREV_THRESHOLD) {
priv->polarity_debounce[portno] = 0;
- if(pol != POL_UNKNOWN) {
+ if(pol != POL_UNKNOWN && priv->polarity[portno] != POL_UNKNOWN) {
char *polname = NULL;
if(pol == POL_POSITIVE)
@@ -993,14 +997,12 @@
* 2. In some countries used to report caller-id during onhook
* but before first ring.
*/
- if(caller_id_style == CID_STYLE_ETSI_FSK) {
- LINE_DBG(SIGNAL, xpd, portno, "Caller-ID PCM: on\n");
- BIT_SET(xpd->cid_on, portno); /* will be cleared on ring/offhook */
- }
+ if(caller_id_style == CID_STYLE_ETSI_FSK)
+ oht_pcm(xpd, portno, 1); /* will be cleared on ring/offhook */
if(SPAN_REGISTERED(xpd)) {
LINE_DBG(SIGNAL, xpd, portno,
"Send ZT_EVENT_POLARITY: %s\n", polname);
- zt_qevent_lock(&xpd->chans[portno], ZT_EVENT_POLARITY);
+ zt_qevent_lock(XPD_CHAN(xpd, portno), ZT_EVENT_POLARITY);
}
}
priv->polarity[portno] = pol;
@@ -1024,7 +1026,7 @@
* During ringing, current is not stable.
* During onhook there should not be current anyway.
*/
- if(xpd->ringing[portno] || !IS_SET(xpd->offhook, portno))
+ if(xpd->ringing[portno] || !IS_OFFHOOK(xpd, portno))
goto ignore_it;
/*
* Power denial with no battery voltage is meaningless
@@ -1036,15 +1038,16 @@
goto ignore_it;
if(data_low < POWER_DENIAL_CURRENT) {
if(priv->power[portno] == POWER_ON) {
- LINE_DBG(SIGNAL, xpd, portno, "power: ON -> OFF\n");
- priv->power[portno] = POWER_OFF;
+ power_change(xpd, portno, POWER_OFF);
priv->power_denial_minimum[portno] = POWER_DENIAL_TIME;
}
} else {
- LINE_DBG(SIGNAL, xpd, portno, "power: ON\n");
- priv->power[portno] = POWER_ON;
- priv->power_denial_minimum[portno] = 0;
- update_line_status(xpd, portno, 1);
+ if(priv->power[portno] != POWER_ON) {
+ power_change(xpd, portno, POWER_ON);
+ priv->power_denial_minimum[portno] = 0;
+ /* We are now OFFHOOK */
+ hookstate_changed(xpd, portno, 1);
+ }
}
return;
ignore_it:
@@ -1135,6 +1138,7 @@
.card_zaptel_postregistration = FXO_card_zaptel_postregistration,
.card_hooksig = FXO_card_hooksig,
.card_tick = FXO_card_tick,
+ .card_pcm_recompute = generic_card_pcm_recompute,
.card_pcm_fromspan = generic_card_pcm_fromspan,
.card_pcm_tospan = generic_card_pcm_tospan,
.card_ioctl = FXO_card_ioctl,
Modified: branches/1.4/kernel/xpp/card_fxs.c
URL: http://svn.digium.com/view/zaptel/branches/1.4/kernel/xpp/card_fxs.c?view=diff&rev=4590&r1=4589&r2=4590
==============================================================================
--- branches/1.4/kernel/xpp/card_fxs.c (original)
+++ branches/1.4/kernel/xpp/card_fxs.c Sun Nov 30 06:10:03 2008
@@ -172,6 +172,21 @@
BUG_ON(!xpd);
LINE_DBG(SIGNAL, xpd, chan, "%s\n", (on) ? "up" : "down");
return SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, REG_BATTERY, value);
+}
+
+static void vmwi_search(xpd_t *xpd, lineno_t pos, bool on)
+{
+ struct FXS_priv_data *priv;
+
+ priv = xpd->priv;
+ BUG_ON(!xpd);
+ if(vmwineon && on) {
+ LINE_DBG(SIGNAL, xpd, pos, "START\n");
+ BIT_SET(priv->search_fsk_pattern, pos);
+ } else {
+ LINE_DBG(SIGNAL, xpd, pos, "STOP\n");
+ BIT_CLR(priv->search_fsk_pattern, pos);
+ }
}
/*
@@ -286,7 +301,7 @@
priv = xpd->priv;
for_each_line(xpd, i) {
- if(IS_SET(xpd->offhook, i))
+ if(IS_OFFHOOK(xpd, i))
MARK_ON(priv, i, LED_GREEN);
else
MARK_OFF(priv, i, LED_GREEN);
@@ -438,7 +453,7 @@
msleep(50);
}
restore_leds(xpd);
- pcm_recompute(xpd, 0);
+ CALL_XMETHOD(card_pcm_recompute, xbus, xpd, 0);
/*
* We should query our offhook state long enough time after we
* set the linefeed_control()
@@ -483,7 +498,7 @@
xpd->span.spantype = "FXS";
#endif
for_each_line(xpd, i) {
- struct zt_chan *cur_chan = &xpd->chans[i];
+ struct zt_chan *cur_chan = XPD_CHAN(xpd, i);
XPD_DBG(GENERAL, xpd, "setting FXS channel %d\n", i);
if(IS_SET(xpd->digital_outputs, i)) {
@@ -540,19 +555,18 @@
BIT_SET(xpd->mute_dtmf, pos);
else
BIT_CLR(xpd->mute_dtmf, pos);
-}
-
-static int set_vm_led_mode(xbus_t *xbus, xpd_t *xpd, int pos, int on)
+ CALL_XMETHOD(card_pcm_recompute, xpd->xbus, xpd, 0); /* already spinlocked */
+}
+
+static int set_vm_led_mode(xbus_t *xbus, xpd_t *xpd, int pos, bool msg_waiting)
{
int ret = 0;
BUG_ON(!xbus);
BUG_ON(!xpd);
- LINE_DBG(SIGNAL, xpd, pos, "%s%s\n", (on)?"ON":"OFF", (vmwineon)?"":" (Ignored)");
- if (!vmwineon)
- return 0;
- if (on) {
+ if (vmwineon && msg_waiting) {
/* A write to register 0x40 will now turn on/off the VM led */
+ LINE_DBG(SIGNAL, xpd, pos, "NEON\n");
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x16, 0xE8, 0x03);
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x15, 0xEF, 0x7B);
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x14, 0x9F, 0x00);
@@ -565,6 +579,7 @@
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x1D, 0x00, 0x46);
} else {
/* A write to register 0x40 will now turn on/off the ringer */
+ LINE_DBG(SIGNAL, xpd, pos, "RINGER\n");
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x16, 0x00, 0x00);
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x15, 0x60, 0x01);
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x14, 0xF0, 0x7E);
@@ -576,7 +591,6 @@
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x33, 0x00);
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x1D, 0x00, 0x36);
}
-
return (ret ? -EPROTO : 0);
}
@@ -586,7 +600,7 @@
bool on;
BUG_ON(!xpd);
- if (!vmwineon || IS_SET(xpd->digital_outputs | xpd->digital_inputs, pos))
+ if (IS_SET(xpd->digital_outputs | xpd->digital_inputs, pos))
return;
priv = xpd->priv;
on = IS_SET(xpd->msg_waiting, pos);
@@ -655,17 +669,16 @@
return 0;
}
if(SPAN_REGISTERED(xpd))
- chan = &xpd->span.chans[pos];
+ chan = XPD_CHAN(xpd, pos);
switch(txsig) {
case ZT_TXSIG_ONHOOK:
spin_lock_irqsave(&xpd->lock, flags);
xpd->ringing[pos] = 0;
- BIT_CLR(xpd->cid_on, pos);
- BIT_CLR(priv->search_fsk_pattern, pos);
+ oht_pcm(xpd, pos, 0);
+ vmwi_search(xpd, pos, 0);
BIT_CLR(priv->want_dtmf_events, pos);
BIT_CLR(priv->want_dtmf_mute, pos);
__do_mute_dtmf(xpd, pos, 0);
- __pcm_recompute(xpd, 0); /* already spinlocked */
spin_unlock_irqrestore(&xpd->lock, flags);
if(IS_SET(xpd->digital_outputs, pos)) {
LINE_DBG(SIGNAL, xpd, pos, "%s -> digital output OFF\n", txsig2str(txsig));
@@ -678,11 +691,11 @@
*/
LINE_DBG(SIGNAL, xpd, pos, "KEWL STOP\n");
linefeed_control(xbus, xpd, pos, FXS_LINE_POL_ACTIVE);
- if(IS_SET(xpd->offhook, pos))
+ if(IS_OFFHOOK(xpd, pos))
MARK_ON(priv, pos, LED_GREEN);
}
ret = send_ring(xpd, pos, 0); // RING off
- if (!IS_SET(xpd->offhook, pos))
+ if (!IS_OFFHOOK(xpd, pos))
start_stop_vm_led(xbus, xpd, pos);
txhook = priv->lasttxhook[pos];
if(chan) {
@@ -706,8 +719,7 @@
}
txhook = priv->lasttxhook[pos];
if(xpd->ringing[pos]) {
- BIT_SET(xpd->cid_on, pos);
- pcm_recompute(xpd, 0);
+ oht_pcm(xpd, pos, 1);
txhook = FXS_LINE_OHTRANS;
}
xpd->ringing[pos] = 0;
@@ -725,9 +737,8 @@
break;
case ZT_TXSIG_START:
xpd->ringing[pos] = 1;
- BIT_CLR(xpd->cid_on, pos);
- BIT_CLR(priv->search_fsk_pattern, pos);
- pcm_recompute(xpd, 0);
+ oht_pcm(xpd, pos, 0);
+ vmwi_search(xpd, pos, 0);
if(IS_SET(xpd->digital_outputs, pos)) {
LINE_DBG(SIGNAL, xpd, pos, "%s -> digital output ON\n", txsig2str(txsig));
ret = relay_out(xpd, pos, 1);
@@ -782,14 +793,15 @@
LINE_DBG(SIGNAL, xpd, pos, "ZT_ONHOOKTRANSFER (%d millis)\n", val);
if (IS_SET(xpd->digital_inputs | xpd->digital_outputs, pos))
return 0; /* Nothing to do */
- BIT_CLR(xpd->cid_on, pos);
+ oht_pcm(xpd, pos, 1); /* Get ready of VMWI FSK tones */
if(priv->lasttxhook[pos] == FXS_LINE_POL_ACTIVE) {
- priv->ohttimer[pos] = OHT_TIMER;
+ priv->ohttimer[pos] = val;
priv->idletxhookstate[pos] = FXS_LINE_POL_OHTRANS;
- BIT_SET(priv->search_fsk_pattern, pos);
- pcm_recompute(xpd, priv->search_fsk_pattern);
- }
- if(!IS_SET(xpd->offhook, pos))
+ vmwi_search(xpd, pos, 1);
+ CALL_XMETHOD(card_pcm_recompute, xbus, xpd, priv->search_fsk_pattern);
+ LINE_DBG(SIGNAL, xpd, pos, "Start OHT_TIMER. wanted_pcm_mask=0x%X\n", xpd->wanted_pcm_mask);
+ }
+ if(vmwineon && !IS_OFFHOOK(xpd, pos))
start_stop_vm_led(xbus, xpd, pos);
return 0;
case ZT_TONEDETECT:
@@ -808,7 +820,6 @@
BIT_CLR(priv->want_dtmf_events, pos);
BIT_CLR(priv->want_dtmf_mute, pos);
__do_mute_dtmf(xpd, pos, 0);
- __pcm_recompute(xpd, 0); /* already spinlocked */
spin_unlock_irqrestore(&xpd->lock, flags);
return -ENOTTY;
}
@@ -840,7 +851,6 @@
} else {
BIT_CLR(priv->want_dtmf_mute, pos);
__do_mute_dtmf(xpd, pos, 0);
- __pcm_recompute(xpd, 0);
}
spin_unlock_irqrestore(&xpd->lock, flags);
return 0;
@@ -886,12 +896,10 @@
static int FXS_card_open(xpd_t *xpd, lineno_t chan)
{
struct FXS_priv_data *priv;
- bool is_offhook;
-
- BUG_ON(!xpd);
- priv = xpd->priv;
- is_offhook = IS_SET(xpd->offhook, chan);
- if(is_offhook)
+
+ BUG_ON(!xpd);
+ priv = xpd->priv;
+ if(IS_OFFHOOK(xpd, chan))
LINE_NOTICE(xpd, chan, "Already offhook during open. OK.\n");
else
LINE_DBG(SIGNAL, xpd, chan, "is onhook\n");
@@ -957,10 +965,10 @@
if (priv->ohttimer[i]) {
priv->ohttimer[i]--;
if (!priv->ohttimer[i]) {
+ LINE_DBG(SIGNAL, xpd, i, "ohttimer expired\n");
priv->idletxhookstate[i] = FXS_LINE_POL_ACTIVE;
- BIT_CLR(xpd->cid_on, i);
- BIT_CLR(priv->search_fsk_pattern, i);
- pcm_recompute(xpd, 0);
+ oht_pcm(xpd, i, 0);
+ vmwi_search(xpd, i, 0);
if (priv->lasttxhook[i] == FXS_LINE_POL_OHTRANS) {
/* Apply the change if appropriate */
linefeed_control(xpd->xbus, xpd, i, FXS_LINE_POL_ACTIVE);
@@ -996,16 +1004,23 @@
static const byte FSK_ON_PATTERN[] = { 0xA2, 0x2C, 0x1F, 0x2C, 0xBB, 0xA1, 0xA5, 0xFF };
static const byte FSK_OFF_PATTERN[] = { 0xA2, 0x2C, 0x28, 0xA5, 0xB1, 0x21, 0x49, 0x9F };
int i;
+ xpp_line_t ignore_mask;
BUG_ON(!xpd);
xbus = xpd->xbus;
priv = xpd->priv;
BUG_ON(!priv);
+ ignore_mask =
+ xpd->offhook_state |
+ ~xpd->oht_pcm_pass |
+ ~priv->search_fsk_pattern |
+ xpd->digital_inputs |
+ xpd->digital_outputs;
for_each_line(xpd, i) {
- struct zt_chan *chan = &xpd->span.chans[i];
+ struct zt_chan *chan = XPD_CHAN(xpd, i);
byte *writechunk = chan->writechunk;
- if(IS_SET(xpd->offhook | xpd->cid_on | xpd->digital_inputs | xpd->digital_outputs, i))
+ if(IS_SET(ignore_mask, i))
continue;
#if 0
if(writechunk[0] != 0x7F && writechunk[0] != 0) {
@@ -1020,10 +1035,12 @@
printk("\n");
}
#endif
- if(unlikely(mem_equal(writechunk, FSK_COMMON_PATTERN, ZT_CHUNKSIZE)))
+ if(unlikely(mem_equal(writechunk, FSK_COMMON_PATTERN, ZT_CHUNKSIZE))) {
+ LINE_DBG(SIGNAL, xpd, i, "Found common FSK pattern. Start looking for ON/OFF patterns.\n");
BIT_SET(priv->found_fsk_pattern, i);
- else if(unlikely(IS_SET(priv->found_fsk_pattern, i))) {
+ } else if(unlikely(IS_SET(priv->found_fsk_pattern, i))) {
BIT_CLR(priv->found_fsk_pattern, i);
+ oht_pcm(xpd, i, 0);
if(unlikely(mem_equal(writechunk, FSK_ON_PATTERN, ZT_CHUNKSIZE))) {
LINE_DBG(SIGNAL, xpd, i, "MSG WAITING ON\n");
BIT_SET(xpd->msg_waiting, i);
@@ -1060,25 +1077,27 @@
#endif
handle_fxs_leds(xpd);
handle_linefeed(xpd);
- if(priv->update_offhook_state) { /* set in FXS_card_open() */
- int i;
+ /*
+ * Hack alert (FIXME):
+ * Asterisk did FXS_card_open() and we wanted to report
+ * offhook state. However, the channel is spinlocked by zaptel
+ * so we marked it in the priv->update_offhook_state mask and
+ * now we take care of notification to zaptel and Asterisk
+ */
+ if(priv->update_offhook_state) {
+ zt_rxsig_t rxsig;
+ int i;
for_each_line(xpd, i) {
if(!IS_SET(priv->update_offhook_state, i))
continue;
- /*
- * Update zaptel with current state of line.
- */
- if(IS_SET(xpd->offhook, i)) {
- update_line_status(xpd, i, 1);
- } else {
- update_line_status(xpd, i, 0);
- }
+ rxsig = IS_OFFHOOK(xpd, i) ? ZT_RXSIG_OFFHOOK : ZT_RXSIG_ONHOOK;
+ notify_rxsig(xpd, i, rxsig); /* Notify after open() */
BIT_CLR(priv->update_offhook_state, i);
}
}
if(SPAN_REGISTERED(xpd)) {
- if(vmwineon && !vmwi_ioctl)
+ if(vmwineon && !vmwi_ioctl && priv->search_fsk_pattern)
detect_vmwi(xpd); /* Detect via FSK modulation */
}
return 0;
@@ -1127,11 +1146,11 @@
if(IS_SET(offhook, i)) {
LINE_DBG(SIGNAL, xpd, i, "OFFHOOK\n");
MARK_ON(priv, i, LED_GREEN);
- update_line_status(xpd, i, 1);
+ hookstate_changed(xpd, i, 1);
} else {
LINE_DBG(SIGNAL, xpd, i, "ONHOOK\n");
MARK_OFF(priv, i, LED_GREEN);
- update_line_status(xpd, i, 0);
+ hookstate_changed(xpd, i, 0);
}
/*
* Must switch to low power. In high power, an ONHOOK
@@ -1140,7 +1159,6 @@
do_chan_power(xbus, xpd, i, 0);
}
}
- __pcm_recompute(xpd, 0); /* in a spinlock */
}
HANDLER_DEF(FXS, SIG_CHANGED)
@@ -1182,12 +1200,12 @@
BIT_CLR(lines, channo);
BIT_SET(lines, newchanno);
xpd->ringing[newchanno] = 0; // Stop ringing. No leds for digital inputs.
- if(offhook && !IS_SET(xpd->offhook, newchanno)) { // OFFHOOK
+ if(offhook && !IS_OFFHOOK(xpd, newchanno)) { // OFFHOOK
LINE_DBG(SIGNAL, xpd, newchanno, "OFFHOOK\n");
- update_line_status(xpd, newchanno, 1);
- } else if(!offhook && IS_SET(xpd->offhook, newchanno)) { // ONHOOK
+ hookstate_changed(xpd, newchanno, 1);
+ } else if(!offhook && IS_OFFHOOK(xpd, newchanno)) { // ONHOOK
LINE_DBG(SIGNAL, xpd, newchanno, "ONHOOK\n");
- update_line_status(xpd, newchanno, 0);
+ hookstate_changed(xpd, newchanno, 0);
}
}
}
@@ -1253,11 +1271,10 @@
__do_mute_dtmf(xpd, portnum, 1);
else
__do_mute_dtmf(xpd, portnum, 0);
- __pcm_recompute(xpd, 0); /* XPD is locked */
if(want_event) {
int event = (key_down) ? ZT_EVENT_DTMFDOWN : ZT_EVENT_DTMFUP;
- zt_qevent_lock(&xpd->chans[portnum], event | digit);
+ zt_qevent_lock(XPD_CHAN(xpd, portnum), event | digit);
}
}
@@ -1334,6 +1351,7 @@
.card_zaptel_postregistration = FXS_card_zaptel_postregistration,
.card_hooksig = FXS_card_hooksig,
.card_tick = FXS_card_tick,
+ .card_pcm_recompute = generic_card_pcm_recompute,
.card_pcm_fromspan = generic_card_pcm_fromspan,
.card_pcm_tospan = generic_card_pcm_tospan,
.card_open = FXS_card_open,
Modified: branches/1.4/kernel/xpp/card_pri.c
URL: http://svn.digium.com/view/zaptel/branches/1.4/kernel/xpp/card_pri.c?view=diff&rev=4590&r1=4589&r2=4590
==============================================================================
--- branches/1.4/kernel/xpp/card_pri.c (original)
+++ branches/1.4/kernel/xpp/card_pri.c Sun Nov 30 06:10:03 2008
@@ -1037,7 +1037,7 @@
xpd->span.linecompat = pri_linecompat(priv->pri_protocol);
xpd->span.deflaw = priv->deflaw;
for_each_line(xpd, i) {
- struct zt_chan *cur_chan = &xpd->chans[i];
+ struct zt_chan *cur_chan = XPD_CHAN(xpd, i);
bool is_dchan = i == PRI_DCHAN_IDX(priv);
XPD_DBG(GENERAL, xpd, "setting PRI channel %d (%s)\n", i,
@@ -1053,7 +1053,7 @@
} else
cur_chan->sigcap = PRI_BCHAN_SIGCAP;
}
- xpd->offhook = xpd->wanted_pcm_mask;
+ xpd->offhook_state = xpd->wanted_pcm_mask;
xpd->span.spanconfig = pri_spanconfig;
xpd->span.chanconfig = pri_chanconfig;
xpd->span.startup = pri_startup;
@@ -1102,9 +1102,9 @@
if(SPAN_REGISTERED(xpd) && d >= 0 && d < xpd->channels) {
byte *pcm;
- pcm = (byte *)xpd->span.chans[d].readchunk;
+ pcm = (byte *)XPD_CHAN(xpd, d)->readchunk;
pcm[0] = 0x00;
- pcm = (byte *)xpd->span.chans[d].writechunk;
+ pcm = (byte *)XPD_CHAN(xpd, d)->writechunk;
pcm[0] = 0x00;
}
XPD_DBG(SIGNAL, xpd, "STATE CHANGE: D-Channel STOPPED\n");
@@ -1233,7 +1233,7 @@
static int PRI_card_close(xpd_t *xpd, lineno_t pos)
{
- //struct zt_chan *chan = &xpd->span.chans[pos];
+ //struct zt_chan *chan = XPD_CHAN(xpd, pos);
dchan_state(xpd, 0);
return 0;
}
@@ -1342,13 +1342,13 @@
* send 31 channels to the device, but they should be called 1-31 rather
* than 0-30 .
*/
-static void PRI_card_pcm_fromspan(xbus_t *xbus, xpd_t *xpd, xpp_line_t lines, xpacket_t *pack)
+static void PRI_card_pcm_fromspan(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack)
{
struct PRI_priv_data *priv;
byte *pcm;
- struct zt_chan *chans;
unsigned long flags;
int i;
+ xpp_line_t wanted_lines;
int physical_chan;
int physical_mask = 0;
@@ -1359,9 +1359,11 @@
BUG_ON(!priv);
pcm = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, pcm);
spin_lock_irqsave(&xpd->lock, flags);
- chans = xpd->span.chans;
+ wanted_lines = xpd->wanted_pcm_mask;
physical_chan = 0;
for_each_line(xpd, i) {
+ struct zt_chan *chan = XPD_CHAN(xpd, i);
+
if(priv->pri_protocol == PRI_PROTO_E1) {
/* In E1 - Only 0'th channel is unused */
if(i == 0) {
@@ -1373,28 +1375,28 @@
physical_chan++;
}
}
- if(IS_SET(lines, i)) {
+ if(IS_SET(wanted_lines, i)) {
physical_mask |= BIT(physical_chan);
if(SPAN_REGISTERED(xpd)) {
#ifdef DEBUG_PCMTX
- int channo = xpd->span.chans[i].channo;
+ int channo = XPD_CHAN(xpd, i)->channo;
if(pcmtx >= 0 && pcmtx_chan == channo)
memset((u_char *)pcm, pcmtx, ZT_CHUNKSIZE);
else
#endif
- memcpy((u_char *)pcm, chans[i].writechunk, ZT_CHUNKSIZE);
+ memcpy((u_char *)pcm, chan->writechunk, ZT_CHUNKSIZE);
if(i == PRI_DCHAN_IDX(priv)) {
- if(priv->dchan_tx_sample != chans[i].writechunk[0]) {
- priv->dchan_tx_sample = chans[i].writechunk[0];
+ if(priv->dchan_tx_sample != chan->writechunk[0]) {
+ priv->dchan_tx_sample = chan->writechunk[0];
priv->dchan_tx_counter++;
- } else if(chans[i].writechunk[0] == 0xFF)
+ } else if(chan->writechunk[0] == 0xFF)
dchan_state(xpd, 0);
else
- chans[i].writechunk[0] = 0xFF; /* Clobber for next tick */
+ chan->writechunk[0] = 0xFF; /* Clobber for next tick */
}
} else
- memset((u_char *)pcm, ZT_XLAW(0, (&chans[i])), ZT_CHUNKSIZE);
+ memset((u_char *)pcm, ZT_XLAW(0, chan), ZT_CHUNKSIZE);
pcm += ZT_CHUNKSIZE;
}
physical_chan++;
@@ -1418,7 +1420,6 @@
{
struct PRI_priv_data *priv;
byte *pcm;
- struct zt_chan *chans;
xpp_line_t physical_mask;
unsigned long flags;
int i;
@@ -1431,7 +1432,6 @@
pcm = RPACKET_FIELD(pack, GLOBAL, PCM_READ, pcm);
physical_mask = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines);
spin_lock_irqsave(&xpd->lock, flags);
- chans = xpd->span.chans;
logical_chan = 0;
for (i = 0; i < CHANNELS_PERXPD; i++) {
volatile u_char *r;
@@ -1458,9 +1458,8 @@
dchan_state(xpd, 0);
}
if(IS_SET(physical_mask, i)) {
- r = chans[logical_chan].readchunk;
+ r = XPD_CHAN(xpd, logical_chan)->readchunk;
// memset((u_char *)r, 0x5A, ZT_CHUNKSIZE); // DEBUG
- // fill_beep((u_char *)r, 1, 1); // DEBUG: BEEP
memcpy((u_char *)r, pcm, ZT_CHUNKSIZE);
pcm += ZT_CHUNKSIZE;
}
@@ -1576,9 +1575,9 @@
rsnum, chan1+1, chan2+1, priv->cas_rs_e[pos], data_low);
if(SPAN_REGISTERED(xpd)) {
if(old1 != new1)
- zt_rbsbits(&xpd->span.chans[chan1], new1);
+ zt_rbsbits(XPD_CHAN(xpd, chan1), new1);
if(old2 != new2)
- zt_rbsbits(&xpd->span.chans[chan2], new2);
+ zt_rbsbits(XPD_CHAN(xpd, chan2), new2);
}
priv->dchan_rx_counter++;
priv->cas_rs_e[pos] = data_low;
@@ -1657,6 +1656,7 @@
.card_zaptel_postregistration = PRI_card_zaptel_postregistration,
.card_hooksig = PRI_card_hooksig,
.card_tick = PRI_card_tick,
+ .card_pcm_recompute = generic_card_pcm_recompute,
.card_pcm_fromspan = PRI_card_pcm_fromspan,
.card_pcm_tospan = PRI_card_pcm_tospan,
.card_ioctl = PRI_card_ioctl,
Modified: branches/1.4/kernel/xpp/xbus-pcm.c
URL: http://svn.digium.com/view/zaptel/branches/1.4/kernel/xpp/xbus-pcm.c?view=diff&rev=4590&r1=4589&r2=4590
==============================================================================
--- branches/1.4/kernel/xpp/xbus-pcm.c (original)
+++ branches/1.4/kernel/xpp/xbus-pcm.c Sun Nov 30 06:10:03 2008
@@ -580,19 +580,18 @@
* This function is used by FXS/FXO. The pcm_mask argument signifies
* channels which should be *added* to the automatic calculation.
* Normally, this argument is 0.
- *
- * The caller should spinlock the XPD before calling it.
*/
-void __pcm_recompute(xpd_t *xpd, xpp_line_t pcm_mask)
+void generic_card_pcm_recompute(xbus_t *xbus, xpd_t *xpd, xpp_line_t pcm_mask)
{
int i;
int line_count = 0;
-
- XPD_DBG(SIGNAL, xpd, "pcm_mask=0x%X\n", pcm_mask);
+ unsigned long flags;
+
+ spin_lock_irqsave(&xpd->lock_recompute_pcm, flags);
+ //XPD_DBG(SIGNAL, xpd, "pcm_mask=0x%X\n", pcm_mask);
/* Add/remove all the trivial cases */
- pcm_mask |= xpd->offhook;
- pcm_mask |= xpd->cid_on;
- pcm_mask &= ~xpd->digital_signalling; /* No PCM in D-Channels */
+ pcm_mask |= xpd->offhook_state;
+ pcm_mask |= xpd->oht_pcm_pass;
pcm_mask &= ~xpd->digital_inputs;
pcm_mask &= ~xpd->digital_outputs;
for_each_line(xpd, i)
@@ -610,18 +609,9 @@
? RPACKET_HEADERSIZE + sizeof(xpp_line_t) + line_count * ZT_CHUNKSIZE
: 0L;
xpd->wanted_pcm_mask = pcm_mask;
-}
-
-/*
- * A spinlocked version of __pcm_recompute()
- */
-void pcm_recompute(xpd_t *xpd, xpp_line_t pcm_mask)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&xpd->lock, flags);
- __pcm_recompute(xpd, pcm_mask);
- spin_unlock_irqrestore(&xpd->lock, flags);
+ XPD_DBG(SIGNAL, xpd, "pcm_len=%d wanted_pcm_mask=0x%X\n",
+ xpd->pcm_len, xpd->wanted_pcm_mask);
+ spin_unlock_irqrestore(&xpd->lock_recompute_pcm, flags);
}
void fill_beep(u_char *buf, int num, int duration)
@@ -676,11 +666,12 @@
static void do_ec(xpd_t *xpd)
{
#ifdef WITH_ECHO_SUPPRESSION
- struct zt_chan *chans = xpd->span.chans;
int i;
/* FIXME: need to Echo cancel double buffered data */
for (i = 0;i < xpd->span.channels; i++) {
+ struct zt_chan *chan = XPD_CHAN(xpd, i);
+
if(unlikely(IS_SET(xpd->digital_signalling, i))) /* Don't echo cancel BRI D-chans */
continue;
if(!IS_SET(xpd->wanted_pcm_mask, i)) /* No ec for unwanted PCM */
@@ -688,12 +679,12 @@
#ifdef XPP_EC_CHUNK
/* even if defined, parameterr xpp_ec can override at run-time */
if (xpp_ec)
- xpp_ec_chunk(&chans[i], chans[i].readchunk, xpd->ec_chunk2[i]);
+ xpp_ec_chunk(chan, chan->readchunk, xpd->ec_chunk2[i]);
else
#endif
- zt_ec_chunk(&chans[i], chans[i].readchunk, xpd->ec_chunk2[i]);
+ zt_ec_chunk(chan, chan->readchunk, xpd->ec_chunk2[i]);
memcpy(xpd->ec_chunk2[i], xpd->ec_chunk1[i], ZT_CHUNKSIZE);
- memcpy(xpd->ec_chunk1[i], chans[i].writechunk, ZT_CHUNKSIZE);
+ memcpy(xpd->ec_chunk1[i], chan->writechunk, ZT_CHUNKSIZE);
}
#endif
}
@@ -821,31 +812,33 @@
* Generic implementations of card_pcmfromspan()/card_pcmtospan()
* For FXS/FXO
*/
-void generic_card_pcm_fromspan(xbus_t *xbus, xpd_t *xpd, xpp_line_t lines, xpacket_t *pack)
+void generic_card_pcm_fromspan(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack)
{
byte *pcm;
- struct zt_chan *chans;
unsigned long flags;
+ xpp_line_t wanted_lines;
int i;
BUG_ON(!xbus);
BUG_ON(!xpd);
BUG_ON(!pack);
- RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines) = lines;
+ wanted_lines = xpd->wanted_pcm_mask;
+ RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines) = wanted_lines;
pcm = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, pcm);
spin_lock_irqsave(&xpd->lock, flags);
- chans = xpd->span.chans;
for (i = 0; i < xpd->channels; i++) {
- if(IS_SET(lines, i)) {
+ struct zt_chan *chan = XPD_CHAN(xpd, i);
+
+ if(IS_SET(wanted_lines, i)) {
if(SPAN_REGISTERED(xpd)) {
#ifdef DEBUG_PCMTX
- int channo = xpd->span.chans[i].channo;
+ int channo = chan->channo;
if(pcmtx >= 0 && pcmtx_chan == channo)
memset((u_char *)pcm, pcmtx, ZT_CHUNKSIZE);
else
#endif
- memcpy((u_char *)pcm, chans[i].writechunk, ZT_CHUNKSIZE);
+ memcpy((u_char *)pcm, chan->writechunk, ZT_CHUNKSIZE);
} else
memset((u_char *)pcm, 0x7F, ZT_CHUNKSIZE);
pcm += ZT_CHUNKSIZE;
@@ -874,7 +867,7 @@
if(!SPAN_REGISTERED(xpd))
goto out;
for (i = 0; i < xpd->channels; i++) {
- volatile u_char *r = xpd->span.chans[i].readchunk;
+ volatile u_char *r = XPD_CHAN(xpd, i)->readchunk;
bool got_data = IS_SET(pcm_mask, i);
if(got_data && !IS_SET(pcm_mute, i)) {
@@ -974,7 +967,6 @@
xpd_t *xpd;
xframe_t *xframe = NULL;
[... 410 lines stripped ...]
More information about the zaptel-commits
mailing list