xpp: prepare for phonedev refactor
* Allow having XPDs that represent a device that is not a span. * Refactor all span related data from 'struct xpd' to 'struct phonedev' * Refactor span related methods into 'phonedev->phoneops' * Refactor phone related initialization into phonedev_init()/phonedev_cleanup() Signed-off-by: Oron Peled <oron@actcom.co.il> Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com> git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@9704 a0bf4364-ded3-4de4-8d8a-66a801d63aff
This commit is contained in:
committed by
Tzafrir Cohen
parent
dd73a1c778
commit
af702dafff
@@ -147,7 +147,7 @@ typedef union {
|
||||
#endif
|
||||
#define BRI_BCHAN_SIGCAP (DAHDI_SIG_CLEAR | DAHDI_SIG_DACS)
|
||||
|
||||
#define IS_NT(xpd) ((xpd)->direction == TO_PHONE)
|
||||
#define IS_NT(xpd) (PHONEDEV(xpd).direction == TO_PHONE)
|
||||
#define BRI_PORT(xpd) ((xpd)->addr.subunit)
|
||||
|
||||
/* shift in PCM highway */
|
||||
@@ -732,7 +732,7 @@ static int tx_dchan(xpd_t *xpd)
|
||||
if(atomic_read(&priv->hdlc_pending) == 0)
|
||||
return 0;
|
||||
#endif
|
||||
if(!SPAN_REGISTERED(xpd) || !(xpd->span.flags & DAHDI_FLAG_RUNNING))
|
||||
if(!SPAN_REGISTERED(xpd) || !(PHONEDEV(xpd).span.flags & DAHDI_FLAG_RUNNING))
|
||||
return 0;
|
||||
dchan = XPD_CHAN(xpd, 2);
|
||||
len = ARRAY_SIZE(priv->dchan_tbuf);
|
||||
@@ -748,7 +748,7 @@ static int tx_dchan(xpd_t *xpd)
|
||||
}
|
||||
if(!test_bit(HFC_L1_ACTIVATED, &priv->l1_flags) && !test_bit(HFC_L1_ACTIVATING, &priv->l1_flags)) {
|
||||
XPD_DBG(SIGNAL, xpd, "Want to transmit: Kick D-Channel transmiter\n");
|
||||
if(xpd->direction == TO_PSTN)
|
||||
if(! IS_NT(xpd))
|
||||
te_activation(xpd, 1);
|
||||
else
|
||||
nt_activation(xpd, 1);
|
||||
@@ -825,7 +825,7 @@ static xpd_t *BRI_card_new(xbus_t *xbus, int unit, int subunit, const xproto_tab
|
||||
xpd = xpd_alloc(xbus, unit, subunit, subtype, subunits, sizeof(struct BRI_priv_data), proto_table, channels);
|
||||
if(!xpd)
|
||||
return NULL;
|
||||
xpd->direction = (to_phone) ? TO_PHONE : TO_PSTN;
|
||||
PHONEDEV(xpd).direction = (to_phone) ? TO_PHONE : TO_PSTN;
|
||||
xpd->type_name = (to_phone) ? "BRI_NT" : "BRI_TE";
|
||||
if(bri_proc_create(xbus, xpd) < 0)
|
||||
goto err;
|
||||
@@ -898,10 +898,10 @@ static int BRI_card_dahdi_preregistration(xpd_t *xpd, bool on)
|
||||
/* Nothing to do yet */
|
||||
return 0;
|
||||
}
|
||||
xpd->span.spantype = "BRI";
|
||||
xpd->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_CCS;
|
||||
xpd->span.deflaw = DAHDI_LAW_ALAW;
|
||||
BIT_SET(xpd->digital_signalling, 2); /* D-Channel */
|
||||
PHONEDEV(xpd).span.spantype = "BRI";
|
||||
PHONEDEV(xpd).span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_CCS;
|
||||
PHONEDEV(xpd).span.deflaw = DAHDI_LAW_ALAW;
|
||||
BIT_SET(PHONEDEV(xpd).digital_signalling, 2); /* D-Channel */
|
||||
for_each_line(xpd, i) {
|
||||
struct dahdi_chan *cur_chan = XPD_CHAN(xpd, i);
|
||||
|
||||
@@ -932,8 +932,8 @@ static int BRI_card_dahdi_preregistration(xpd_t *xpd, bool on)
|
||||
cur_chan->sigcap = BRI_BCHAN_SIGCAP;
|
||||
}
|
||||
}
|
||||
CALL_XMETHOD(card_pcm_recompute, xbus, xpd, 0);
|
||||
xpd->span.ops = &BRI_span_ops;
|
||||
PHONE_METHOD(xpd, card_pcm_recompute)(xpd->xbus, xpd, 0);
|
||||
PHONEDEV(xpd).span.ops = &BRI_span_ops;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1151,10 +1151,10 @@ static int BRI_card_open(xpd_t *xpd, lineno_t pos)
|
||||
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);
|
||||
BIT_SET(PHONEDEV(xpd).offhook_state, 0);
|
||||
BIT_SET(PHONEDEV(xpd).offhook_state, 1);
|
||||
BIT_SET(PHONEDEV(xpd).offhook_state, 2);
|
||||
PHONE_METHOD(xpd, card_pcm_recompute)(xpd->xbus, xpd, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1173,10 +1173,10 @@ static int BRI_card_close(xpd_t *xpd, lineno_t pos)
|
||||
#endif
|
||||
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);
|
||||
BIT_CLR(PHONEDEV(xpd).offhook_state, 0);
|
||||
BIT_CLR(PHONEDEV(xpd).offhook_state, 1);
|
||||
BIT_CLR(PHONEDEV(xpd).offhook_state, 2);
|
||||
PHONE_METHOD(xpd, card_pcm_recompute)(xpd->xbus, xpd, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1186,7 +1186,8 @@ static int BRI_card_close(xpd_t *xpd, lineno_t pos)
|
||||
*/
|
||||
static int bri_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc)
|
||||
{
|
||||
xpd_t *xpd = container_of(span, struct xpd, span);
|
||||
struct phonedev *phonedev = container_of(span, struct phonedev, span);
|
||||
xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
|
||||
const char *framingstr = "";
|
||||
const char *codingstr = "";
|
||||
const char *crcstr = "";
|
||||
@@ -1242,7 +1243,8 @@ static int bri_chanconfig(struct dahdi_chan *chan, int sigtype)
|
||||
*/
|
||||
static int bri_startup(struct dahdi_span *span)
|
||||
{
|
||||
xpd_t *xpd = container_of(span, struct xpd, span);
|
||||
struct phonedev *phonedev = container_of(span, struct phonedev, span);
|
||||
xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
|
||||
struct BRI_priv_data *priv;
|
||||
struct dahdi_chan *dchan;
|
||||
|
||||
@@ -1255,7 +1257,7 @@ static int bri_startup(struct dahdi_span *span)
|
||||
}
|
||||
XPD_DBG(GENERAL, xpd, "STARTUP\n");
|
||||
// Turn on all channels
|
||||
CALL_XMETHOD(XPD_STATE, xpd->xbus, xpd, 1);
|
||||
PHONE_METHOD(xpd, XPD_STATE)(xpd->xbus, xpd, 1);
|
||||
if(SPAN_REGISTERED(xpd)) {
|
||||
dchan = XPD_CHAN(xpd, 2);
|
||||
span->flags |= DAHDI_FLAG_RUNNING;
|
||||
@@ -1278,7 +1280,8 @@ static int bri_startup(struct dahdi_span *span)
|
||||
*/
|
||||
static int bri_shutdown(struct dahdi_span *span)
|
||||
{
|
||||
xpd_t *xpd = container_of(span, struct xpd, span);
|
||||
struct phonedev *phonedev = container_of(span, struct phonedev, span);
|
||||
xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
|
||||
struct BRI_priv_data *priv;
|
||||
|
||||
BUG_ON(!xpd);
|
||||
@@ -1290,7 +1293,7 @@ static int bri_shutdown(struct dahdi_span *span)
|
||||
}
|
||||
XPD_DBG(GENERAL, xpd, "SHUTDOWN\n");
|
||||
// Turn off all channels
|
||||
CALL_XMETHOD(XPD_STATE, xpd->xbus, xpd, 0);
|
||||
PHONE_METHOD(xpd, XPD_STATE)(xpd->xbus, xpd, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1314,7 +1317,7 @@ static void BRI_card_pcm_recompute(xbus_t *xbus, xpd_t *xpd,
|
||||
* 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);
|
||||
spin_lock_irqsave(&PHONEDEV(main_xpd).lock_recompute_pcm, flags);
|
||||
line_count = 0;
|
||||
pcm_mask = 0;
|
||||
for(i = 0; i < MAX_SUBUNIT; i++) {
|
||||
@@ -1322,7 +1325,7 @@ static void BRI_card_pcm_recompute(xbus_t *xbus, xpd_t *xpd,
|
||||
|
||||
if(sub_xpd) {
|
||||
xpp_line_t lines =
|
||||
sub_xpd->offhook_state & ~sub_xpd->digital_signalling;
|
||||
PHONEDEV(sub_xpd).offhook_state & ~(PHONEDEV(sub_xpd).digital_signalling);
|
||||
|
||||
if(lines) {
|
||||
pcm_mask |= PCM_SHIFT(lines, i);
|
||||
@@ -1349,7 +1352,7 @@ static void BRI_card_pcm_recompute(xbus_t *xbus, xpd_t *xpd,
|
||||
? RPACKET_HEADERSIZE + sizeof(xpp_line_t) + line_count * DAHDI_CHUNKSIZE
|
||||
: 0L;
|
||||
update_wanted_pcm_mask(main_xpd, pcm_mask, pcm_len);
|
||||
spin_unlock_irqrestore(&main_xpd->lock_recompute_pcm, flags);
|
||||
spin_unlock_irqrestore(&PHONEDEV(main_xpd).lock_recompute_pcm, flags);
|
||||
}
|
||||
|
||||
static void BRI_card_pcm_fromspan(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack)
|
||||
@@ -1373,7 +1376,7 @@ static void BRI_card_pcm_fromspan(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack)
|
||||
if(!tmp_xpd || !tmp_xpd->card_present)
|
||||
continue;
|
||||
spin_lock_irqsave(&tmp_xpd->lock, flags);
|
||||
wanted_lines = tmp_xpd->wanted_pcm_mask;
|
||||
wanted_lines = PHONEDEV(tmp_xpd).wanted_pcm_mask;
|
||||
for_each_line(tmp_xpd, i) {
|
||||
struct dahdi_chan *chan = XPD_CHAN(tmp_xpd, i);
|
||||
|
||||
@@ -1452,7 +1455,7 @@ static /* 0x0F */ HOSTCMD(BRI, XPD_STATE, bool on)
|
||||
XPD_DBG(GENERAL, xpd, "%s\n", (on)?"ON":"OFF");
|
||||
if(on) {
|
||||
if(!test_bit(HFC_L1_ACTIVATED, &priv->l1_flags)) {
|
||||
if(xpd->direction == TO_PSTN)
|
||||
if( ! IS_NT(xpd))
|
||||
te_activation(xpd, 1);
|
||||
else
|
||||
nt_activation(xpd, 1);
|
||||
@@ -1645,7 +1648,7 @@ static int BRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
||||
ret = rx_dchan(xpd, info);
|
||||
if (ret < 0) {
|
||||
priv->dchan_rx_drops++;
|
||||
if(atomic_read(&xpd->open_counter) > 0)
|
||||
if(atomic_read(&PHONEDEV(xpd).open_counter) > 0)
|
||||
XPD_NOTICE(xpd, "Multibyte Drop: errno=%d\n", ret);
|
||||
}
|
||||
goto end;
|
||||
@@ -1667,6 +1670,29 @@ end:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct xops bri_xops = {
|
||||
.card_new = BRI_card_new,
|
||||
.card_init = BRI_card_init,
|
||||
.card_remove = BRI_card_remove,
|
||||
.card_tick = BRI_card_tick,
|
||||
.card_register_reply = BRI_card_register_reply,
|
||||
};
|
||||
|
||||
static const struct phoneops bri_phoneops = {
|
||||
.card_dahdi_preregistration = BRI_card_dahdi_preregistration,
|
||||
.card_dahdi_postregistration = BRI_card_dahdi_postregistration,
|
||||
.card_hooksig = BRI_card_hooksig,
|
||||
.card_pcm_recompute = BRI_card_pcm_recompute,
|
||||
.card_pcm_fromspan = BRI_card_pcm_fromspan,
|
||||
.card_pcm_tospan = BRI_card_pcm_tospan,
|
||||
.card_timing_priority = generic_timing_priority,
|
||||
.card_ioctl = BRI_card_ioctl,
|
||||
.card_open = BRI_card_open,
|
||||
.card_close = BRI_card_close,
|
||||
|
||||
.XPD_STATE = XPROTO_CALLER(BRI, XPD_STATE),
|
||||
};
|
||||
|
||||
static xproto_table_t PROTO_TABLE(BRI) = {
|
||||
.owner = THIS_MODULE,
|
||||
.entries = {
|
||||
@@ -1675,25 +1701,8 @@ static xproto_table_t PROTO_TABLE(BRI) = {
|
||||
.name = "BRI", /* protocol name */
|
||||
.ports_per_subunit = 1,
|
||||
.type = XPD_TYPE_BRI,
|
||||
.xops = {
|
||||
.card_new = BRI_card_new,
|
||||
.card_init = BRI_card_init,
|
||||
.card_remove = BRI_card_remove,
|
||||
.card_dahdi_preregistration = BRI_card_dahdi_preregistration,
|
||||
.card_dahdi_postregistration = BRI_card_dahdi_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_timing_priority = generic_timing_priority,
|
||||
.card_ioctl = BRI_card_ioctl,
|
||||
.card_open = BRI_card_open,
|
||||
.card_close = BRI_card_close,
|
||||
.card_register_reply = BRI_card_register_reply,
|
||||
|
||||
.XPD_STATE = XPROTO_CALLER(BRI, XPD_STATE),
|
||||
},
|
||||
.xops = &bri_xops,
|
||||
.phoneops = &bri_phoneops,
|
||||
.packet_is_valid = bri_packet_is_valid,
|
||||
.packet_dump = bri_packet_dump,
|
||||
};
|
||||
|
||||
@@ -215,7 +215,7 @@ static int do_led(xpd_t *xpd, lineno_t chan, byte which, bool on)
|
||||
xbus = xpd->xbus;
|
||||
priv = xpd->priv;
|
||||
which = which % NUM_LEDS;
|
||||
if(IS_SET(xpd->digital_outputs, chan) || IS_SET(xpd->digital_inputs, chan))
|
||||
if(IS_SET(PHONEDEV(xpd).digital_outputs, chan) || IS_SET(PHONEDEV(xpd).digital_inputs, chan))
|
||||
goto out;
|
||||
if(chan == PORT_BROADCAST) {
|
||||
priv->ledstate[which] = (on) ? ~0 : 0;
|
||||
@@ -251,7 +251,7 @@ static void handle_fxo_leds(xpd_t *xpd)
|
||||
timer_count = xpd->timer_count;
|
||||
for(color = 0; color < ARRAY_SIZE(colors); color++) {
|
||||
for_each_line(xpd, i) {
|
||||
if(IS_SET(xpd->digital_outputs, i) || IS_SET(xpd->digital_inputs, i))
|
||||
if(IS_SET(PHONEDEV(xpd).digital_outputs, i) || IS_SET(PHONEDEV(xpd).digital_inputs, i))
|
||||
continue;
|
||||
if((xpd->blink_mode & BIT(i)) || IS_BLINKING(priv, i, color)) { // Blinking
|
||||
int mod_value = LED_COUNTER(priv, i, color);
|
||||
@@ -302,16 +302,16 @@ static void mark_ring(xpd_t *xpd, lineno_t pos, bool on, bool update_dahdi)
|
||||
* due to voltage fluctuations.
|
||||
*/
|
||||
reset_battery_readings(xpd, pos);
|
||||
if(on && !xpd->ringing[pos]) {
|
||||
if(on && !PHONEDEV(xpd).ringing[pos]) {
|
||||
LINE_DBG(SIGNAL, xpd, pos, "START\n");
|
||||
xpd->ringing[pos] = 1;
|
||||
PHONEDEV(xpd).ringing[pos] = 1;
|
||||
priv->cidtimer[pos] = xpd->timer_count;
|
||||
MARK_BLINK(priv, pos, LED_GREEN, LED_BLINK_RING);
|
||||
if(update_dahdi)
|
||||
update_dahdi_ring(xpd, pos, on);
|
||||
} else if(!on && xpd->ringing[pos]) {
|
||||
} else if(!on && PHONEDEV(xpd).ringing[pos]) {
|
||||
LINE_DBG(SIGNAL, xpd, pos, "STOP\n");
|
||||
xpd->ringing[pos] = 0;
|
||||
PHONEDEV(xpd).ringing[pos] = 0;
|
||||
priv->cidtimer[pos] = xpd->timer_count;
|
||||
if(IS_BLINKING(priv, pos, LED_GREEN))
|
||||
MARK_BLINK(priv, pos, LED_GREEN, 0);
|
||||
@@ -329,7 +329,7 @@ static int do_sethook(xpd_t *xpd, int pos, bool to_offhook)
|
||||
byte value;
|
||||
|
||||
BUG_ON(!xpd);
|
||||
BUG_ON(xpd->direction == TO_PHONE); // We can SETHOOK state only on PSTN
|
||||
BUG_ON(PHONEDEV(xpd).direction == TO_PHONE); // We can SETHOOK state only on PSTN
|
||||
xbus = xpd->xbus;
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
@@ -443,7 +443,7 @@ static xpd_t *FXO_card_new(xbus_t *xbus, int unit, int subunit, const xproto_tab
|
||||
xpd = xpd_alloc(xbus, unit, subunit, subtype, subunits, sizeof(struct FXO_priv_data), proto_table, channels);
|
||||
if(!xpd)
|
||||
return NULL;
|
||||
xpd->direction = TO_PSTN;
|
||||
PHONEDEV(xpd).direction = TO_PSTN;
|
||||
xpd->type_name = "FXO";
|
||||
if(fxo_proc_create(xbus, xpd) < 0)
|
||||
goto err;
|
||||
@@ -482,7 +482,7 @@ static int FXO_card_init(xbus_t *xbus, xpd_t *xpd)
|
||||
do_led(xpd, i, LED_GREEN, 0);
|
||||
msleep(50);
|
||||
}
|
||||
CALL_XMETHOD(card_pcm_recompute, xbus, xpd, 0);
|
||||
PHONE_METHOD(xpd, card_pcm_recompute)(xbus, xpd, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -511,6 +511,7 @@ static int FXO_card_dahdi_preregistration(xpd_t *xpd, bool on)
|
||||
BUG_ON(!priv);
|
||||
timer_count = xpd->timer_count;
|
||||
XPD_DBG(GENERAL, xpd, "%s\n", (on)?"ON":"OFF");
|
||||
PHONEDEV(xpd).span.spantype = "FXO";
|
||||
for_each_line(xpd, i) {
|
||||
struct dahdi_chan *cur_chan = XPD_CHAN(xpd, i);
|
||||
|
||||
@@ -562,7 +563,7 @@ static int FXO_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, enum dahdi_txsig
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
LINE_DBG(SIGNAL, xpd, pos, "%s\n", txsig2str(txsig));
|
||||
BUG_ON(xpd->direction != TO_PSTN);
|
||||
BUG_ON(PHONEDEV(xpd).direction != TO_PSTN);
|
||||
/* XXX Enable hooksig for FXO XXX */
|
||||
switch(txsig) {
|
||||
case DAHDI_TXSIG_START:
|
||||
@@ -661,7 +662,7 @@ static void handle_fxo_power_denial(xpd_t *xpd)
|
||||
return; /* Ignore power denials */
|
||||
priv = xpd->priv;
|
||||
for_each_line(xpd, i) {
|
||||
if(xpd->ringing[i] || !IS_OFFHOOK(xpd, i)) {
|
||||
if(PHONEDEV(xpd).ringing[i] || !IS_OFFHOOK(xpd, i)) {
|
||||
priv->power_denial_delay[i] = 0;
|
||||
continue;
|
||||
}
|
||||
@@ -726,7 +727,7 @@ static void check_etsi_dtmf(xpd_t *xpd)
|
||||
timer_count = xpd->timer_count;
|
||||
for_each_line(xpd, portno) {
|
||||
/* Skip offhook and ringing ports */
|
||||
if(IS_OFFHOOK(xpd, portno) || xpd->ringing[portno])
|
||||
if(IS_OFFHOOK(xpd, portno) || PHONEDEV(xpd).ringing[portno])
|
||||
continue;
|
||||
if(IS_SET(priv->cidfound, portno)) {
|
||||
if(timer_count > priv->cidtimer[portno] + 4000) {
|
||||
@@ -900,7 +901,7 @@ static void update_battery_voltage(xpd_t *xpd, byte data_low, xportno_t portno)
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
priv->battery_voltage[portno] = volts;
|
||||
if(xpd->ringing[portno])
|
||||
if(PHONEDEV(xpd).ringing[portno])
|
||||
goto ignore_reading; /* ring voltage create false alarms */
|
||||
if(abs(volts) < battery_threshold) {
|
||||
/*
|
||||
@@ -1017,7 +1018,7 @@ static void update_battery_current(xpd_t *xpd, byte data_low, xportno_t portno)
|
||||
* During ringing, current is not stable.
|
||||
* During onhook there should not be current anyway.
|
||||
*/
|
||||
if(xpd->ringing[portno] || !IS_OFFHOOK(xpd, portno))
|
||||
if(PHONEDEV(xpd).ringing[portno] || !IS_OFFHOOK(xpd, portno))
|
||||
goto ignore_it;
|
||||
/*
|
||||
* Power denial with no battery voltage is meaningless
|
||||
@@ -1110,6 +1111,27 @@ static int FXO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct xops fxo_xops = {
|
||||
.card_new = FXO_card_new,
|
||||
.card_init = FXO_card_init,
|
||||
.card_remove = FXO_card_remove,
|
||||
.card_tick = FXO_card_tick,
|
||||
.card_register_reply = FXO_card_register_reply,
|
||||
};
|
||||
|
||||
static const struct phoneops fxo_phoneops = {
|
||||
.card_dahdi_preregistration = FXO_card_dahdi_preregistration,
|
||||
.card_dahdi_postregistration = FXO_card_dahdi_postregistration,
|
||||
.card_hooksig = FXO_card_hooksig,
|
||||
.card_pcm_recompute = generic_card_pcm_recompute,
|
||||
.card_pcm_fromspan = generic_card_pcm_fromspan,
|
||||
.card_pcm_tospan = generic_card_pcm_tospan,
|
||||
.card_timing_priority = generic_timing_priority,
|
||||
.card_ioctl = FXO_card_ioctl,
|
||||
.card_open = FXO_card_open,
|
||||
|
||||
.XPD_STATE = XPROTO_CALLER(FXO, XPD_STATE),
|
||||
};
|
||||
|
||||
static xproto_table_t PROTO_TABLE(FXO) = {
|
||||
.owner = THIS_MODULE,
|
||||
@@ -1120,24 +1142,8 @@ static xproto_table_t PROTO_TABLE(FXO) = {
|
||||
.name = "FXO", /* protocol name */
|
||||
.ports_per_subunit = 8,
|
||||
.type = XPD_TYPE_FXO,
|
||||
.xops = {
|
||||
.card_new = FXO_card_new,
|
||||
.card_init = FXO_card_init,
|
||||
.card_remove = FXO_card_remove,
|
||||
.card_dahdi_preregistration = FXO_card_dahdi_preregistration,
|
||||
.card_dahdi_postregistration = FXO_card_dahdi_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_timing_priority = generic_timing_priority,
|
||||
.card_ioctl = FXO_card_ioctl,
|
||||
.card_open = FXO_card_open,
|
||||
.card_register_reply = FXO_card_register_reply,
|
||||
|
||||
.XPD_STATE = XPROTO_CALLER(FXO, XPD_STATE),
|
||||
},
|
||||
.xops = &fxo_xops,
|
||||
.phoneops = &fxo_phoneops,
|
||||
.packet_is_valid = fxo_packet_is_valid,
|
||||
.packet_dump = fxo_packet_dump,
|
||||
};
|
||||
@@ -1174,20 +1180,20 @@ static int proc_fxo_info_read(char *page, char **start, off_t off, int count, in
|
||||
BUG_ON(!priv);
|
||||
len += sprintf(page + len, "\t%-17s: ", "Channel");
|
||||
for_each_line(xpd, i) {
|
||||
if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i))
|
||||
if(!IS_SET(PHONEDEV(xpd).digital_outputs, i) && !IS_SET(PHONEDEV(xpd).digital_inputs, i))
|
||||
len += sprintf(page + len, "%4d ", i % 10);
|
||||
}
|
||||
len += sprintf(page + len, "\nLeds:");
|
||||
len += sprintf(page + len, "\n\t%-17s: ", "state");
|
||||
for_each_line(xpd, i) {
|
||||
if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i))
|
||||
if(!IS_SET(PHONEDEV(xpd).digital_outputs, i) && !IS_SET(PHONEDEV(xpd).digital_inputs, i))
|
||||
len += sprintf(page + len, " %d%d ",
|
||||
IS_SET(priv->ledstate[LED_GREEN], i),
|
||||
IS_SET(priv->ledstate[LED_RED], i));
|
||||
}
|
||||
len += sprintf(page + len, "\n\t%-17s: ", "blinking");
|
||||
for_each_line(xpd, i) {
|
||||
if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i))
|
||||
if(!IS_SET(PHONEDEV(xpd).digital_outputs, i) && !IS_SET(PHONEDEV(xpd).digital_inputs, i))
|
||||
len += sprintf(page + len, " %d%d ",
|
||||
IS_BLINKING(priv,i,LED_GREEN),
|
||||
IS_BLINKING(priv,i,LED_RED));
|
||||
|
||||
@@ -236,7 +236,7 @@ static int do_led(xpd_t *xpd, lineno_t chan, byte which, bool on)
|
||||
xbus = xpd->xbus;
|
||||
priv = xpd->priv;
|
||||
which = which % NUM_LEDS;
|
||||
if(IS_SET(xpd->digital_outputs, chan) || IS_SET(xpd->digital_inputs, chan))
|
||||
if(IS_SET(PHONEDEV(xpd).digital_outputs, chan) || IS_SET(PHONEDEV(xpd).digital_inputs, chan))
|
||||
goto out;
|
||||
if(chan == PORT_BROADCAST) {
|
||||
priv->ledstate[which] = (on) ? ~0 : 0;
|
||||
@@ -271,7 +271,7 @@ static void handle_fxs_leds(xpd_t *xpd)
|
||||
timer_count = xpd->timer_count;
|
||||
for(color = 0; color < ARRAY_SIZE(colors); color++) {
|
||||
for_each_line(xpd, i) {
|
||||
if(IS_SET(xpd->digital_outputs | xpd->digital_inputs, i))
|
||||
if(IS_SET(PHONEDEV(xpd).digital_outputs | PHONEDEV(xpd).digital_inputs, i))
|
||||
continue;
|
||||
if((xpd->blink_mode & BIT(i)) || IS_BLINKING(priv, i, color)) { // Blinking
|
||||
int mod_value = LED_COUNTER(priv, i, color);
|
||||
@@ -406,10 +406,10 @@ static xpd_t *FXS_card_new(xbus_t *xbus, int unit, int subunit, const xproto_tab
|
||||
return NULL;
|
||||
if(unit == 0) {
|
||||
XBUS_DBG(GENERAL, xbus, "First XPD detected. Initialize digital outputs/inputs\n");
|
||||
xpd->digital_outputs = BITMASK(LINES_DIGI_OUT) << regular_channels;
|
||||
xpd->digital_inputs = BITMASK(LINES_DIGI_INP) << (regular_channels + LINES_DIGI_OUT);
|
||||
PHONEDEV(xpd).digital_outputs = BITMASK(LINES_DIGI_OUT) << regular_channels;
|
||||
PHONEDEV(xpd).digital_inputs = BITMASK(LINES_DIGI_INP) << (regular_channels + LINES_DIGI_OUT);
|
||||
}
|
||||
xpd->direction = TO_PHONE;
|
||||
PHONEDEV(xpd).direction = TO_PHONE;
|
||||
xpd->type_name = "FXS";
|
||||
if(fxs_proc_create(xbus, xpd) < 0)
|
||||
goto err;
|
||||
@@ -455,14 +455,14 @@ static int FXS_card_init(xbus_t *xbus, xpd_t *xpd)
|
||||
msleep(50);
|
||||
}
|
||||
restore_leds(xpd);
|
||||
CALL_XMETHOD(card_pcm_recompute, xbus, xpd, 0);
|
||||
PHONE_METHOD(xpd, card_pcm_recompute)(xbus, xpd, 0);
|
||||
/*
|
||||
* We should query our offhook state long enough time after we
|
||||
* set the linefeed_control()
|
||||
* So we do this after the LEDs
|
||||
*/
|
||||
for_each_line(xpd, i) {
|
||||
if(IS_SET(xpd->digital_outputs | xpd->digital_inputs, i))
|
||||
if(IS_SET(PHONEDEV(xpd).digital_outputs | PHONEDEV(xpd).digital_inputs, i))
|
||||
continue;
|
||||
SLIC_DIRECT_REQUEST(xbus, xpd, i, SLIC_READ, REG_LOOPCLOSURE, 0);
|
||||
}
|
||||
@@ -496,15 +496,15 @@ static int FXS_card_dahdi_preregistration(xpd_t *xpd, bool on)
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
XPD_DBG(GENERAL, xpd, "%s\n", (on)?"on":"off");
|
||||
xpd->span.spantype = "FXS";
|
||||
PHONEDEV(xpd).span.spantype = "FXS";
|
||||
for_each_line(xpd, i) {
|
||||
struct dahdi_chan *cur_chan = XPD_CHAN(xpd, i);
|
||||
|
||||
XPD_DBG(GENERAL, xpd, "setting FXS channel %d\n", i);
|
||||
if(IS_SET(xpd->digital_outputs, i)) {
|
||||
if(IS_SET(PHONEDEV(xpd).digital_outputs, i)) {
|
||||
snprintf(cur_chan->name, MAX_CHANNAME, "XPP_OUT/%02d/%1d%1d/%d",
|
||||
xbus->num, xpd->addr.unit, xpd->addr.subunit, i);
|
||||
} else if(IS_SET(xpd->digital_inputs, i)) {
|
||||
} else if(IS_SET(PHONEDEV(xpd).digital_inputs, i)) {
|
||||
snprintf(cur_chan->name, MAX_CHANNAME, "XPP_IN/%02d/%1d%1d/%d",
|
||||
xbus->num, xpd->addr.unit, xpd->addr.subunit, i);
|
||||
} else {
|
||||
@@ -556,10 +556,10 @@ static void __do_mute_dtmf(xpd_t *xpd, int pos, bool muteit)
|
||||
{
|
||||
LINE_DBG(SIGNAL, xpd, pos, "%s\n", (muteit) ? "MUTE" : "UNMUTE");
|
||||
if(muteit)
|
||||
BIT_SET(xpd->mute_dtmf, pos);
|
||||
BIT_SET(PHONEDEV(xpd).mute_dtmf, pos);
|
||||
else
|
||||
BIT_CLR(xpd->mute_dtmf, pos);
|
||||
CALL_XMETHOD(card_pcm_recompute, xpd->xbus, xpd, 0); /* already spinlocked */
|
||||
BIT_CLR(PHONEDEV(xpd).mute_dtmf, pos);
|
||||
PHONE_METHOD(xpd, card_pcm_recompute)(xpd->xbus, xpd, 0); /* already spinlocked */
|
||||
}
|
||||
|
||||
static int set_vm_led_mode(xbus_t *xbus, xpd_t *xpd, int pos,
|
||||
@@ -607,10 +607,10 @@ static void start_stop_vm_led(xbus_t *xbus, xpd_t *xpd, lineno_t pos)
|
||||
unsigned int msgs;
|
||||
|
||||
BUG_ON(!xpd);
|
||||
if (IS_SET(xpd->digital_outputs | xpd->digital_inputs, pos))
|
||||
if (IS_SET(PHONEDEV(xpd).digital_outputs | PHONEDEV(xpd).digital_inputs, pos))
|
||||
return;
|
||||
priv = xpd->priv;
|
||||
msgs = xpd->msg_waiting[pos];
|
||||
msgs = PHONEDEV(xpd).msg_waiting[pos];
|
||||
LINE_DBG(SIGNAL, xpd, pos, "%s\n", (msgs) ? "ON" : "OFF");
|
||||
set_vm_led_mode(xbus, xpd, pos, msgs);
|
||||
do_chan_power(xbus, xpd, pos, msgs > 0);
|
||||
@@ -671,8 +671,8 @@ static int FXS_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, enum dahdi_txsig
|
||||
|
||||
LINE_DBG(SIGNAL, xpd, pos, "%s\n", txsig2str(txsig));
|
||||
priv = xpd->priv;
|
||||
BUG_ON(xpd->direction != TO_PHONE);
|
||||
if (IS_SET(xpd->digital_inputs, pos)) {
|
||||
BUG_ON(PHONEDEV(xpd).direction != TO_PHONE);
|
||||
if (IS_SET(PHONEDEV(xpd).digital_inputs, pos)) {
|
||||
LINE_DBG(SIGNAL, xpd, pos, "Ignoring signal sent to digital input line\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -681,14 +681,14 @@ static int FXS_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, enum dahdi_txsig
|
||||
switch(txsig) {
|
||||
case DAHDI_TXSIG_ONHOOK:
|
||||
spin_lock_irqsave(&xpd->lock, flags);
|
||||
xpd->ringing[pos] = 0;
|
||||
PHONEDEV(xpd).ringing[pos] = 0;
|
||||
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);
|
||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||
if(IS_SET(xpd->digital_outputs, pos)) {
|
||||
if(IS_SET(PHONEDEV(xpd).digital_outputs, pos)) {
|
||||
LINE_DBG(SIGNAL, xpd, pos, "%s -> digital output OFF\n", txsig2str(txsig));
|
||||
ret = relay_out(xpd, pos, 0);
|
||||
return ret;
|
||||
@@ -721,16 +721,16 @@ static int FXS_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, enum dahdi_txsig
|
||||
ret = linefeed_control(xbus, xpd, pos, txhook);
|
||||
break;
|
||||
case DAHDI_TXSIG_OFFHOOK:
|
||||
if(IS_SET(xpd->digital_outputs, pos)) {
|
||||
if(IS_SET(PHONEDEV(xpd).digital_outputs, pos)) {
|
||||
LINE_NOTICE(xpd, pos, "%s -> Is digital output. Ignored\n", txsig2str(txsig));
|
||||
return -EINVAL;
|
||||
}
|
||||
txhook = priv->lasttxhook[pos];
|
||||
if(xpd->ringing[pos]) {
|
||||
if(PHONEDEV(xpd).ringing[pos]) {
|
||||
oht_pcm(xpd, pos, 1);
|
||||
txhook = FXS_LINE_OHTRANS;
|
||||
}
|
||||
xpd->ringing[pos] = 0;
|
||||
PHONEDEV(xpd).ringing[pos] = 0;
|
||||
if(chan) {
|
||||
switch(chan->sig) {
|
||||
case DAHDI_SIG_EM:
|
||||
@@ -744,10 +744,10 @@ static int FXS_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, enum dahdi_txsig
|
||||
ret = linefeed_control(xbus, xpd, pos, txhook);
|
||||
break;
|
||||
case DAHDI_TXSIG_START:
|
||||
xpd->ringing[pos] = 1;
|
||||
PHONEDEV(xpd).ringing[pos] = 1;
|
||||
oht_pcm(xpd, pos, 0);
|
||||
vmwi_search(xpd, pos, 0);
|
||||
if(IS_SET(xpd->digital_outputs, pos)) {
|
||||
if(IS_SET(PHONEDEV(xpd).digital_outputs, pos)) {
|
||||
LINE_DBG(SIGNAL, xpd, pos, "%s -> digital output ON\n", txsig2str(txsig));
|
||||
ret = relay_out(xpd, pos, 1);
|
||||
return ret;
|
||||
@@ -755,7 +755,7 @@ static int FXS_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, enum dahdi_txsig
|
||||
ret = send_ring(xpd, pos, 1); // RING on
|
||||
break;
|
||||
case DAHDI_TXSIG_KEWL:
|
||||
if(IS_SET(xpd->digital_outputs, pos)) {
|
||||
if(IS_SET(PHONEDEV(xpd).digital_outputs, pos)) {
|
||||
LINE_DBG(SIGNAL, xpd, pos, "%s -> Is digital output. Ignored\n", txsig2str(txsig));
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -807,7 +807,7 @@ static int set_vmwi(xpd_t *xpd, int pos, unsigned long arg)
|
||||
; /* Disable VMWI */
|
||||
}
|
||||
priv->vmwisetting[pos] = vmwisetting;
|
||||
set_vm_led_mode(xpd->xbus, xpd, pos, xpd->msg_waiting[pos]);
|
||||
set_vm_led_mode(xpd->xbus, xpd, pos, PHONEDEV(xpd).msg_waiting[pos]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -829,7 +829,7 @@ static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long a
|
||||
BUG_ON(!xbus);
|
||||
if(!XBUS_IS(xbus, READY))
|
||||
return -ENODEV;
|
||||
if (pos < 0 || pos >= xpd->channels) {
|
||||
if (pos < 0 || pos >= PHONEDEV(xpd).channels) {
|
||||
XPD_NOTICE(xpd, "Bad channel number %d in %s(), cmd=%u\n",
|
||||
pos, __FUNCTION__, cmd);
|
||||
return -EINVAL;
|
||||
@@ -840,15 +840,15 @@ static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long a
|
||||
if (get_user(val, (int __user *)arg))
|
||||
return -EFAULT;
|
||||
LINE_DBG(SIGNAL, xpd, pos, "DAHDI_ONHOOKTRANSFER (%d millis)\n", val);
|
||||
if (IS_SET(xpd->digital_inputs | xpd->digital_outputs, pos))
|
||||
if (IS_SET(PHONEDEV(xpd).digital_inputs | PHONEDEV(xpd).digital_outputs, pos))
|
||||
return 0; /* Nothing to do */
|
||||
oht_pcm(xpd, pos, 1); /* Get ready of VMWI FSK tones */
|
||||
if(priv->lasttxhook[pos] == FXS_LINE_POL_ACTIVE) {
|
||||
priv->ohttimer[pos] = val;
|
||||
priv->idletxhookstate[pos] = FXS_LINE_POL_OHTRANS;
|
||||
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);
|
||||
PHONE_METHOD(xpd, card_pcm_recompute)(xbus, xpd, priv->search_fsk_pattern);
|
||||
LINE_DBG(SIGNAL, xpd, pos, "Start OHT_TIMER. wanted_pcm_mask=0x%X\n", PHONEDEV(xpd).wanted_pcm_mask);
|
||||
}
|
||||
if (VMWI_NEON(priv, pos) && !IS_OFFHOOK(xpd, pos))
|
||||
start_stop_vm_led(xbus, xpd, pos);
|
||||
@@ -935,9 +935,9 @@ static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long a
|
||||
return 0;
|
||||
}
|
||||
/* Digital inputs/outputs don't have VM leds */
|
||||
if (IS_SET(xpd->digital_inputs | xpd->digital_outputs, pos))
|
||||
if (IS_SET(PHONEDEV(xpd).digital_inputs | PHONEDEV(xpd).digital_outputs, pos))
|
||||
return 0;
|
||||
xpd->msg_waiting[pos] = val;
|
||||
PHONEDEV(xpd).msg_waiting[pos] = val;
|
||||
LINE_DBG(SIGNAL, xpd, pos, "DAHDI_VMWI: %s\n",
|
||||
(val) ? "yes" : "no");
|
||||
return 0;
|
||||
@@ -1065,11 +1065,11 @@ static void detect_vmwi(xpd_t *xpd)
|
||||
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;
|
||||
PHONEDEV(xpd).offhook_state |
|
||||
~(PHONEDEV(xpd).oht_pcm_pass) |
|
||||
~(priv->search_fsk_pattern) |
|
||||
PHONEDEV(xpd).digital_inputs |
|
||||
PHONEDEV(xpd).digital_outputs;
|
||||
for_each_line(xpd, i) {
|
||||
struct dahdi_chan *chan = XPD_CHAN(xpd, i);
|
||||
byte *writechunk = chan->writechunk;
|
||||
@@ -1097,11 +1097,11 @@ static void detect_vmwi(xpd_t *xpd)
|
||||
oht_pcm(xpd, i, 0);
|
||||
if(unlikely(mem_equal(writechunk, FSK_ON_PATTERN, DAHDI_CHUNKSIZE))) {
|
||||
LINE_DBG(SIGNAL, xpd, i, "MSG WAITING ON\n");
|
||||
xpd->msg_waiting[i] = 1;
|
||||
PHONEDEV(xpd).msg_waiting[i] = 1;
|
||||
start_stop_vm_led(xbus, xpd, i);
|
||||
} else if(unlikely(mem_equal(writechunk, FSK_OFF_PATTERN, DAHDI_CHUNKSIZE))) {
|
||||
LINE_DBG(SIGNAL, xpd, i, "MSG WAITING OFF\n");
|
||||
xpd->msg_waiting[i] = 0;
|
||||
PHONEDEV(xpd).msg_waiting[i] = 0;
|
||||
start_stop_vm_led(xbus, xpd, i);
|
||||
} else {
|
||||
int j;
|
||||
@@ -1179,15 +1179,15 @@ static void process_hookstate(xpd_t *xpd, xpp_line_t offhook, xpp_line_t change_
|
||||
int i;
|
||||
|
||||
BUG_ON(!xpd);
|
||||
BUG_ON(xpd->direction != TO_PHONE);
|
||||
BUG_ON(PHONEDEV(xpd).direction != TO_PHONE);
|
||||
xbus = xpd->xbus;
|
||||
priv = xpd->priv;
|
||||
XPD_DBG(SIGNAL, xpd, "offhook=0x%X change_mask=0x%X\n", offhook, change_mask);
|
||||
for_each_line(xpd, i) {
|
||||
if(IS_SET(xpd->digital_outputs, i) || IS_SET(xpd->digital_inputs, i))
|
||||
if(IS_SET(PHONEDEV(xpd).digital_outputs, i) || IS_SET(PHONEDEV(xpd).digital_inputs, i))
|
||||
continue;
|
||||
if(IS_SET(change_mask, i)) {
|
||||
xpd->ringing[i] = 0; /* No more ringing... */
|
||||
PHONEDEV(xpd).ringing[i] = 0; /* No more ringing... */
|
||||
#ifdef WITH_METERING
|
||||
metering_gen(xpd, i, 0); /* Stop metering... */
|
||||
#endif
|
||||
@@ -1222,7 +1222,7 @@ HANDLER_DEF(FXS, SIG_CHANGED)
|
||||
unsigned long flags;
|
||||
|
||||
BUG_ON(!xpd);
|
||||
BUG_ON(xpd->direction != TO_PHONE);
|
||||
BUG_ON(PHONEDEV(xpd).direction != TO_PHONE);
|
||||
XPD_DBG(SIGNAL, xpd, "(PHONE) sig_toggles=0x%04X sig_status=0x%04X\n", sig_toggles, sig_status);
|
||||
#if 0
|
||||
Is this needed?
|
||||
@@ -1250,10 +1250,10 @@ static void process_digital_inputs(xpd_t *xpd, const reg_cmd_t *info)
|
||||
int newchanno;
|
||||
|
||||
if(IS_SET(lines, channo)) {
|
||||
newchanno = xpd->channels - LINES_DIGI_INP + i;
|
||||
newchanno = PHONEDEV(xpd).channels - LINES_DIGI_INP + i;
|
||||
BIT_CLR(lines, channo);
|
||||
BIT_SET(lines, newchanno);
|
||||
xpd->ringing[newchanno] = 0; // Stop ringing. No leds for digital inputs.
|
||||
PHONEDEV(xpd).ringing[newchanno] = 0; // Stop ringing. No leds for digital inputs.
|
||||
if(offhook && !IS_OFFHOOK(xpd, newchanno)) { // OFFHOOK
|
||||
LINE_DBG(SIGNAL, xpd, newchanno, "OFFHOOK\n");
|
||||
hookstate_changed(xpd, newchanno, 1);
|
||||
@@ -1394,6 +1394,29 @@ static int FXS_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct xops fxs_xops = {
|
||||
.card_new = FXS_card_new,
|
||||
.card_init = FXS_card_init,
|
||||
.card_remove = FXS_card_remove,
|
||||
.card_tick = FXS_card_tick,
|
||||
.card_register_reply = FXS_card_register_reply,
|
||||
};
|
||||
|
||||
static const struct phoneops fxs_phoneops = {
|
||||
.card_dahdi_preregistration = FXS_card_dahdi_preregistration,
|
||||
.card_dahdi_postregistration = FXS_card_dahdi_postregistration,
|
||||
.card_hooksig = FXS_card_hooksig,
|
||||
.card_pcm_recompute = generic_card_pcm_recompute,
|
||||
.card_pcm_fromspan = generic_card_pcm_fromspan,
|
||||
.card_pcm_tospan = generic_card_pcm_tospan,
|
||||
.card_timing_priority = generic_timing_priority,
|
||||
.card_open = FXS_card_open,
|
||||
.card_close = FXS_card_close,
|
||||
.card_ioctl = FXS_card_ioctl,
|
||||
|
||||
.XPD_STATE = XPROTO_CALLER(FXS, XPD_STATE),
|
||||
};
|
||||
|
||||
static xproto_table_t PROTO_TABLE(FXS) = {
|
||||
.owner = THIS_MODULE,
|
||||
.entries = {
|
||||
@@ -1403,25 +1426,8 @@ static xproto_table_t PROTO_TABLE(FXS) = {
|
||||
.name = "FXS", /* protocol name */
|
||||
.ports_per_subunit = 8,
|
||||
.type = XPD_TYPE_FXS,
|
||||
.xops = {
|
||||
.card_new = FXS_card_new,
|
||||
.card_init = FXS_card_init,
|
||||
.card_remove = FXS_card_remove,
|
||||
.card_dahdi_preregistration = FXS_card_dahdi_preregistration,
|
||||
.card_dahdi_postregistration = FXS_card_dahdi_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_timing_priority = generic_timing_priority,
|
||||
.card_open = FXS_card_open,
|
||||
.card_close = FXS_card_close,
|
||||
.card_ioctl = FXS_card_ioctl,
|
||||
.card_register_reply = FXS_card_register_reply,
|
||||
|
||||
.XPD_STATE = XPROTO_CALLER(FXS, XPD_STATE),
|
||||
},
|
||||
.xops = &fxs_xops,
|
||||
.phoneops = &fxs_phoneops,
|
||||
.packet_is_valid = fxs_packet_is_valid,
|
||||
.packet_dump = fxs_packet_dump,
|
||||
};
|
||||
@@ -1466,9 +1472,9 @@ static int proc_fxs_info_read(char *page, char **start, off_t off, int count, in
|
||||
for_each_line(xpd, i) {
|
||||
char pref;
|
||||
|
||||
if(IS_SET(xpd->digital_outputs, i))
|
||||
if(IS_SET(PHONEDEV(xpd).digital_outputs, i))
|
||||
pref = 'O';
|
||||
else if(IS_SET(xpd->digital_inputs, i))
|
||||
else if(IS_SET(PHONEDEV(xpd).digital_inputs, i))
|
||||
pref = 'I';
|
||||
else
|
||||
pref = ' ';
|
||||
@@ -1485,17 +1491,17 @@ static int proc_fxs_info_read(char *page, char **start, off_t off, int count, in
|
||||
len += sprintf(page + len, "LED #%d", led);
|
||||
len += sprintf(page + len, "\n\t%-17s: ", "ledstate");
|
||||
for_each_line(xpd, i) {
|
||||
if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i))
|
||||
if(!IS_SET(PHONEDEV(xpd).digital_outputs, i) && !IS_SET(PHONEDEV(xpd).digital_inputs, i))
|
||||
len += sprintf(page + len, "%d ", IS_SET(priv->ledstate[led], i));
|
||||
}
|
||||
len += sprintf(page + len, "\n\t%-17s: ", "ledcontrol");
|
||||
for_each_line(xpd, i) {
|
||||
if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i))
|
||||
if(!IS_SET(PHONEDEV(xpd).digital_outputs, i) && !IS_SET(PHONEDEV(xpd).digital_inputs, i))
|
||||
len += sprintf(page + len, "%d ", IS_SET(priv->ledcontrol[led], i));
|
||||
}
|
||||
len += sprintf(page + len, "\n\t%-17s: ", "led_counter");
|
||||
for_each_line(xpd, i) {
|
||||
if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i))
|
||||
if(!IS_SET(PHONEDEV(xpd).digital_outputs, i) && !IS_SET(PHONEDEV(xpd).digital_inputs, i))
|
||||
len += sprintf(page + len, "%d ", LED_COUNTER(priv,i,led));
|
||||
}
|
||||
len += sprintf(page + len, "\n");
|
||||
|
||||
@@ -820,7 +820,7 @@ int run_initialize_registers(xpd_t *xpd)
|
||||
xpd->subunits, i);
|
||||
continue;
|
||||
}
|
||||
direction_mask |= (su->direction == TO_PHONE) ? BIT(i) : 0;
|
||||
direction_mask |= (PHONEDEV(su).direction == TO_PHONE) ? BIT(i) : 0;
|
||||
}
|
||||
snprintf(busstr, MAX_ENV_STR, "XBUS_NAME=%s", xbus->busname);
|
||||
snprintf(busnumstr, MAX_ENV_STR, "XBUS_NUMBER=%d", xbus->num);
|
||||
|
||||
@@ -563,10 +563,10 @@ static void PRI_card_pcm_recompute(xbus_t *xbus, xpd_t *xpd,
|
||||
|
||||
BUG_ON(!xpd);
|
||||
priv = xpd->priv;
|
||||
spin_lock_irqsave(&xpd->lock_recompute_pcm, flags);
|
||||
spin_lock_irqsave(&PHONEDEV(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_state;
|
||||
pcm_mask |= PHONEDEV(xpd).offhook_state;
|
||||
for_each_line(xpd, i)
|
||||
if (IS_SET(pcm_mask, i))
|
||||
line_count++;
|
||||
@@ -590,7 +590,7 @@ static void PRI_card_pcm_recompute(xbus_t *xbus, xpd_t *xpd,
|
||||
line_count * DAHDI_CHUNKSIZE
|
||||
: 0L;
|
||||
update_wanted_pcm_mask(xpd, pcm_mask, pcm_len);
|
||||
spin_unlock_irqrestore(&xpd->lock_recompute_pcm, flags);
|
||||
spin_unlock_irqrestore(&PHONEDEV(xpd).lock_recompute_pcm, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -610,7 +610,7 @@ static int set_pri_proto(xpd_t *xpd, enum pri_protocol set_proto)
|
||||
priv = xpd->priv;
|
||||
if(SPAN_REGISTERED(xpd)) {
|
||||
XPD_NOTICE(xpd, "Registered as span %d. Cannot do setup pri protocol (%s)\n",
|
||||
xpd->span.spanno, __FUNCTION__);
|
||||
PHONEDEV(xpd).span.spanno, __FUNCTION__);
|
||||
return -EBUSY;
|
||||
}
|
||||
if(priv->pri_protocol != PRI_PROTO_0) {
|
||||
@@ -650,16 +650,16 @@ static int set_pri_proto(xpd_t *xpd, enum pri_protocol set_proto)
|
||||
}
|
||||
priv->pri_protocol = set_proto;
|
||||
priv->is_cas = -1;
|
||||
xpd->channels = pri_num_channels(set_proto);
|
||||
xpd->offhook_state = BITMASK(xpd->channels);
|
||||
CALL_XMETHOD(card_pcm_recompute, xpd->xbus, xpd, 0);
|
||||
PHONEDEV(xpd).channels = pri_num_channels(set_proto);
|
||||
PHONEDEV(xpd).offhook_state = BITMASK(PHONEDEV(xpd).channels);
|
||||
PHONE_METHOD(xpd, card_pcm_recompute)(xpd->xbus, xpd, 0);
|
||||
priv->deflaw = deflaw;
|
||||
priv->dchan_num = dchan_num;
|
||||
priv->local_loopback = 0;
|
||||
xpd->type_name = type_name(priv->pri_protocol);
|
||||
XPD_DBG(GENERAL, xpd, "%s, channels=%d, dchan_num=%d, deflaw=%d\n",
|
||||
pri_protocol_name(set_proto),
|
||||
xpd->channels,
|
||||
PHONEDEV(xpd).channels,
|
||||
priv->dchan_num,
|
||||
priv->deflaw
|
||||
);
|
||||
@@ -692,18 +692,18 @@ static void dahdi_update_syncsrc(xpd_t *xpd)
|
||||
if(priv->clock_source && priv->alarms == 0) {
|
||||
if(best_spanno)
|
||||
XPD_ERR(xpd, "Duplicate XPD's with clock_source=1\n");
|
||||
best_spanno = subxpd->span.spanno;
|
||||
best_spanno = PHONEDEV(subxpd).span.spanno;
|
||||
}
|
||||
}
|
||||
for(i = 0; i < MAX_SLAVES; i++) {
|
||||
subxpd = xpd_byaddr(xpd->xbus, xpd->addr.unit, i);
|
||||
if(!subxpd)
|
||||
continue;
|
||||
if(subxpd->span.syncsrc == best_spanno)
|
||||
if(PHONEDEV(subxpd).span.syncsrc == best_spanno)
|
||||
XPD_DBG(SYNC, xpd, "Setting SyncSource to span %d\n", best_spanno);
|
||||
else
|
||||
XPD_DBG(SYNC, xpd, "Slaving to span %d\n", best_spanno);
|
||||
subxpd->span.syncsrc = best_spanno;
|
||||
PHONEDEV(subxpd).span.syncsrc = best_spanno;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -734,10 +734,10 @@ static void set_clocking(xpd_t *xpd)
|
||||
priv = subxpd->priv;
|
||||
if(priv->alarms != 0)
|
||||
continue;
|
||||
if(subxpd->timing_priority > 0 && subxpd->timing_priority < best_subunit_prio) {
|
||||
if(PHONEDEV(subxpd).timing_priority > 0 && PHONEDEV(subxpd).timing_priority < best_subunit_prio) {
|
||||
best_xpd = subxpd;
|
||||
best_subunit = i;
|
||||
best_subunit_prio = subxpd->timing_priority;
|
||||
best_subunit_prio = PHONEDEV(subxpd).timing_priority;
|
||||
}
|
||||
}
|
||||
/* Now set it */
|
||||
@@ -779,7 +779,7 @@ static void set_reg_lim0(const char *msg, xpd_t *xpd)
|
||||
BUG_ON(!xpd);
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
is_master_mode = xpd->timing_priority == 0;
|
||||
is_master_mode = PHONEDEV(xpd).timing_priority == 0;
|
||||
localloop = priv->local_loopback;
|
||||
lim0 |= (localloop) ? REG_LIM0_LL : 0;
|
||||
if(is_master_mode)
|
||||
@@ -819,7 +819,7 @@ static int set_localloop(xpd_t *xpd, bool localloop)
|
||||
priv = xpd->priv;
|
||||
if(SPAN_REGISTERED(xpd)) {
|
||||
XPD_NOTICE(xpd, "Registered as span %d. Cannot do %s\n",
|
||||
xpd->span.spanno, __FUNCTION__);
|
||||
PHONEDEV(xpd).span.spanno, __FUNCTION__);
|
||||
return -EBUSY;
|
||||
}
|
||||
priv->local_loopback = localloop;
|
||||
@@ -869,7 +869,7 @@ static void set_rbslines(xpd_t *xpd, int channo)
|
||||
else
|
||||
BIT_SET(new_rbslines, i);
|
||||
}
|
||||
new_rbslines &= BITMASK(xpd->channels);
|
||||
new_rbslines &= BITMASK(PHONEDEV(xpd).channels);
|
||||
modified_lines = priv->rbslines ^ new_rbslines;
|
||||
XPD_DBG(DEVICES, xpd, "RBSLINES-%d(%s): 0x%X\n",
|
||||
channo, pri_protocol_name(priv->pri_protocol), new_rbslines);
|
||||
@@ -1037,7 +1037,7 @@ static int pri_lineconfig(xpd_t *xpd, int lineconfig)
|
||||
force_cas = 1;
|
||||
set_mode_cas(xpd, 1);
|
||||
}
|
||||
CALL_XMETHOD(card_pcm_recompute, xpd->xbus, xpd, 0);
|
||||
PHONE_METHOD(xpd, card_pcm_recompute)(xpd->xbus, xpd, 0);
|
||||
/*
|
||||
* E1's can enable CRC checking
|
||||
* CRC4 is legal only for E1, and it is checked by pri_linecompat()
|
||||
@@ -1092,15 +1092,16 @@ bad_lineconfig:
|
||||
|
||||
static int pri_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc)
|
||||
{
|
||||
xpd_t *xpd = container_of(span, struct xpd, span);
|
||||
struct phonedev *phonedev = container_of(span, struct phonedev, span);
|
||||
xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
|
||||
struct PRI_priv_data *priv;
|
||||
int ret;
|
||||
|
||||
BUG_ON(!xpd);
|
||||
priv = xpd->priv;
|
||||
if(lc->span != xpd->span.spanno) {
|
||||
if(lc->span != PHONEDEV(xpd).span.spanno) {
|
||||
XPD_ERR(xpd, "I am span %d but got spanconfig for span %d\n",
|
||||
xpd->span.spanno, lc->span);
|
||||
PHONEDEV(xpd).span.spanno, lc->span);
|
||||
return -EINVAL;
|
||||
}
|
||||
/*
|
||||
@@ -1112,7 +1113,7 @@ static int pri_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc)
|
||||
ret = pri_lineconfig(xpd, lc->lineconfig);
|
||||
if(!ret) {
|
||||
span->lineconfig = lc->lineconfig;
|
||||
xpd->timing_priority = lc->sync;
|
||||
PHONEDEV(xpd).timing_priority = lc->sync;
|
||||
set_master_mode("spanconfig", xpd);
|
||||
elect_syncer("PRI-master_mode");
|
||||
}
|
||||
@@ -1126,7 +1127,8 @@ static int pri_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc)
|
||||
*/
|
||||
static int pri_chanconfig(struct dahdi_chan *chan, int sigtype)
|
||||
{
|
||||
xpd_t *xpd = container_of(chan->span, struct xpd, span);
|
||||
struct phonedev *phonedev = container_of(chan->span, struct phonedev, span);
|
||||
xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
|
||||
struct PRI_priv_data *priv;
|
||||
|
||||
BUG_ON(!xpd);
|
||||
@@ -1158,7 +1160,7 @@ static int pri_chanconfig(struct dahdi_chan *chan, int sigtype)
|
||||
if(priv->pri_protocol != PRI_PROTO_E1 && priv->is_cas != 1)
|
||||
set_mode_cas(xpd, 1);
|
||||
}
|
||||
if(xpd->span.flags & DAHDI_FLAG_RUNNING) {
|
||||
if(PHONEDEV(xpd).span.flags & DAHDI_FLAG_RUNNING) {
|
||||
XPD_DBG(DEVICES, xpd, "Span is RUNNING. Updating rbslines.\n");
|
||||
set_rbslines(xpd, chan->channo);
|
||||
}
|
||||
@@ -1227,9 +1229,9 @@ static int PRI_card_init(xbus_t *xbus, xpd_t *xpd)
|
||||
goto err;
|
||||
}
|
||||
xpd->type_name = type_name(priv->pri_protocol);
|
||||
xpd->direction = TO_PSTN;
|
||||
PHONEDEV(xpd).direction = TO_PSTN;
|
||||
XPD_DBG(DEVICES, xpd, "%s\n", xpd->type_name);
|
||||
xpd->timing_priority = 1; /* High priority SLAVE */
|
||||
PHONEDEV(xpd).timing_priority = 1; /* High priority SLAVE */
|
||||
set_master_mode(__FUNCTION__, xpd);
|
||||
for(ret = 0; ret < NUM_LEDS; ret++) {
|
||||
DO_LED(xpd, ret, PRI_LED_ON);
|
||||
@@ -1308,15 +1310,15 @@ static int PRI_card_dahdi_preregistration(xpd_t *xpd, bool on)
|
||||
XPD_DBG(GENERAL, xpd, "%s (proto=%s, channels=%d, deflaw=%d)\n",
|
||||
(on)?"on":"off",
|
||||
pri_protocol_name(priv->pri_protocol),
|
||||
xpd->channels,
|
||||
PHONEDEV(xpd).channels,
|
||||
priv->deflaw);
|
||||
if(!on) {
|
||||
/* Nothing to do yet */
|
||||
return 0;
|
||||
}
|
||||
xpd->span.spantype = pri_protocol_name(priv->pri_protocol);
|
||||
xpd->span.linecompat = pri_linecompat(priv->pri_protocol);
|
||||
xpd->span.deflaw = priv->deflaw;
|
||||
PHONEDEV(xpd).span.spantype = pri_protocol_name(priv->pri_protocol);
|
||||
PHONEDEV(xpd).span.linecompat = pri_linecompat(priv->pri_protocol);
|
||||
PHONEDEV(xpd).span.deflaw = priv->deflaw;
|
||||
for_each_line(xpd, i) {
|
||||
struct dahdi_chan *cur_chan = XPD_CHAN(xpd, i);
|
||||
bool is_dchan = i == PRI_DCHAN_IDX(priv);
|
||||
@@ -1333,8 +1335,8 @@ static int PRI_card_dahdi_preregistration(xpd_t *xpd, bool on)
|
||||
cur_chan->flags &= ~DAHDI_FLAG_HDLC;
|
||||
}
|
||||
}
|
||||
xpd->offhook_state = xpd->wanted_pcm_mask;
|
||||
xpd->span.ops = &PRI_span_ops;
|
||||
PHONEDEV(xpd).offhook_state = PHONEDEV(xpd).wanted_pcm_mask;
|
||||
PHONEDEV(xpd).span.ops = &PRI_span_ops;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1372,7 +1374,7 @@ static void dchan_state(xpd_t *xpd, bool up)
|
||||
} else {
|
||||
int d = PRI_DCHAN_IDX(priv);
|
||||
|
||||
if(SPAN_REGISTERED(xpd) && d >= 0 && d < xpd->channels) {
|
||||
if(SPAN_REGISTERED(xpd) && d >= 0 && d < PHONEDEV(xpd).channels) {
|
||||
byte *pcm;
|
||||
|
||||
pcm = (byte *)XPD_CHAN(xpd, d)->readchunk;
|
||||
@@ -1406,7 +1408,7 @@ static void handle_leds(xbus_t *xbus, xpd_t *xpd)
|
||||
BUG_ON(!xpd);
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
if(xpd->timing_priority == 0) {
|
||||
if(PHONEDEV(xpd).timing_priority == 0) {
|
||||
which_led = TOP_RED_LED;
|
||||
other_led = BOTTOM_GREEN_LED;
|
||||
} else {
|
||||
@@ -1530,7 +1532,8 @@ static int PRI_card_close(xpd_t *xpd, lineno_t pos)
|
||||
*/
|
||||
static int pri_startup(struct dahdi_span *span)
|
||||
{
|
||||
xpd_t *xpd = container_of(span, struct xpd, span);
|
||||
struct phonedev *phonedev = container_of(span, struct phonedev, span);
|
||||
xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
|
||||
struct PRI_priv_data *priv;
|
||||
|
||||
BUG_ON(!xpd);
|
||||
@@ -1542,7 +1545,7 @@ static int pri_startup(struct dahdi_span *span)
|
||||
}
|
||||
XPD_DBG(GENERAL, xpd, "STARTUP\n");
|
||||
// Turn on all channels
|
||||
CALL_XMETHOD(XPD_STATE, xpd->xbus, xpd, 1);
|
||||
PHONE_METHOD(xpd, XPD_STATE)(xpd->xbus, xpd, 1);
|
||||
set_rbslines(xpd, 0);
|
||||
write_subunit(xpd, REG_XPM2, 0x00);
|
||||
return 0;
|
||||
@@ -1553,7 +1556,8 @@ static int pri_startup(struct dahdi_span *span)
|
||||
*/
|
||||
static int pri_shutdown(struct dahdi_span *span)
|
||||
{
|
||||
xpd_t *xpd = container_of(span, struct xpd, span);
|
||||
struct phonedev *phonedev = container_of(span, struct phonedev, span);
|
||||
xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
|
||||
struct PRI_priv_data *priv;
|
||||
|
||||
BUG_ON(!xpd);
|
||||
@@ -1565,7 +1569,7 @@ static int pri_shutdown(struct dahdi_span *span)
|
||||
}
|
||||
XPD_DBG(GENERAL, xpd, "SHUTDOWN\n");
|
||||
// Turn off all channels
|
||||
CALL_XMETHOD(XPD_STATE, xpd->xbus, xpd, 0);
|
||||
PHONE_METHOD(xpd, XPD_STATE)(xpd->xbus, xpd, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1614,7 +1618,7 @@ static int encode_rbsbits_t1(xpd_t *xpd, int pos, int bits)
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
BUG_ON(priv->pri_protocol != PRI_PROTO_T1);
|
||||
if(pos < 0 || pos >= xpd->channels) {
|
||||
if(pos < 0 || pos >= PHONEDEV(xpd).channels) {
|
||||
XPD_ERR(xpd, "%s: Bad pos=%d\n", __FUNCTION__, pos);
|
||||
return 0;
|
||||
}
|
||||
@@ -1741,7 +1745,7 @@ static void PRI_card_pcm_fromspan(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack)
|
||||
BUG_ON(!priv);
|
||||
pcm = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, pcm);
|
||||
spin_lock_irqsave(&xpd->lock, flags);
|
||||
wanted_lines = xpd->wanted_pcm_mask;
|
||||
wanted_lines = PHONEDEV(xpd).wanted_pcm_mask;
|
||||
physical_chan = 0;
|
||||
for_each_line(xpd, i) {
|
||||
struct dahdi_chan *chan = XPD_CHAN(xpd, i);
|
||||
@@ -1858,7 +1862,7 @@ int PRI_timing_priority(xbus_t *xbus, xpd_t *xpd)
|
||||
priv = xpd->priv;
|
||||
BUG_ON(!priv);
|
||||
if (priv->layer1_up)
|
||||
return xpd->timing_priority;
|
||||
return PHONEDEV(xpd).timing_priority;
|
||||
XPD_DBG(SYNC, xpd, "No timing priority (no layer1)\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
@@ -1937,24 +1941,24 @@ static void layer1_state(xpd_t *xpd, byte data_low)
|
||||
query_subunit(xpd, regbase + i);
|
||||
}
|
||||
|
||||
if(SPAN_REGISTERED(xpd) && xpd->span.alarms != alarms) {
|
||||
if(SPAN_REGISTERED(xpd) && PHONEDEV(xpd).span.alarms != alarms) {
|
||||
char str1[MAX_PROC_WRITE];
|
||||
char str2[MAX_PROC_WRITE];
|
||||
|
||||
alarm2str(xpd->span.alarms, str1, sizeof(str1));
|
||||
alarm2str(PHONEDEV(xpd).span.alarms, str1, sizeof(str1));
|
||||
alarm2str(alarms, str2, sizeof(str2));
|
||||
XPD_NOTICE(xpd, "Alarms: 0x%X (%s) => 0x%X (%s)\n",
|
||||
xpd->span.alarms, str1,
|
||||
PHONEDEV(xpd).span.alarms, str1,
|
||||
alarms, str2);
|
||||
if (priv->is_cas) {
|
||||
if (alarms == DAHDI_ALARM_NONE)
|
||||
send_oldbits(xpd);
|
||||
else if (xpd->span.alarms == DAHDI_ALARM_NONE)
|
||||
else if (PHONEDEV(xpd).span.alarms == DAHDI_ALARM_NONE)
|
||||
send_idlebits(xpd, 1);
|
||||
}
|
||||
xpd->span.alarms = alarms;
|
||||
PHONEDEV(xpd).span.alarms = alarms;
|
||||
elect_syncer("LAYER1");
|
||||
dahdi_alarm_notify(&xpd->span);
|
||||
dahdi_alarm_notify(&PHONEDEV(xpd).span);
|
||||
set_clocking(xpd);
|
||||
}
|
||||
priv->reg_frs0 = data_low;
|
||||
@@ -1980,14 +1984,14 @@ static int decode_cas_e1(xpd_t *xpd, byte regnum, byte data_low)
|
||||
XPD_ERR(xpd, "%s: got bad pos=%d [0-%d]\n", __FUNCTION__, pos, NUM_CAS_RS_E);
|
||||
return -EINVAL;
|
||||
}
|
||||
if(chan1 < 0 || chan1 > xpd->channels) {
|
||||
if(chan1 < 0 || chan1 > PHONEDEV(xpd).channels) {
|
||||
XPD_NOTICE(xpd, "%s: %s CAS: Bad chan1 number (%d)\n",
|
||||
__FUNCTION__,
|
||||
pri_protocol_name(priv->pri_protocol),
|
||||
chan1);
|
||||
return -EINVAL;
|
||||
}
|
||||
if(chan2 < 0 || chan2 > xpd->channels) {
|
||||
if(chan2 < 0 || chan2 > PHONEDEV(xpd).channels) {
|
||||
XPD_NOTICE(xpd, "%s: %s CAS: Bad chan2 number (%d)\n",
|
||||
__FUNCTION__,
|
||||
pri_protocol_name(priv->pri_protocol),
|
||||
@@ -2038,7 +2042,7 @@ static int decode_cas_t1(xpd_t *xpd, byte regnum, byte data_low)
|
||||
if (!priv->is_esf)
|
||||
rxsig <<= 2;
|
||||
pos = rsnum * chan_per_reg + chan_per_reg - i - 1;
|
||||
if(pos < 0 || pos >= xpd->channels) {
|
||||
if(pos < 0 || pos >= PHONEDEV(xpd).channels) {
|
||||
XPD_ERR(xpd, "%s: Bad pos=%d\n", __FUNCTION__, pos);
|
||||
continue;
|
||||
}
|
||||
@@ -2165,6 +2169,27 @@ end:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct xops pri_xops = {
|
||||
.card_new = PRI_card_new,
|
||||
.card_init = PRI_card_init,
|
||||
.card_remove = PRI_card_remove,
|
||||
.card_tick = PRI_card_tick,
|
||||
.card_register_reply = PRI_card_register_reply,
|
||||
};
|
||||
|
||||
static const struct phoneops pri_phoneops = {
|
||||
.card_dahdi_preregistration = PRI_card_dahdi_preregistration,
|
||||
.card_dahdi_postregistration = PRI_card_dahdi_postregistration,
|
||||
.card_pcm_recompute = PRI_card_pcm_recompute,
|
||||
.card_pcm_fromspan = PRI_card_pcm_fromspan,
|
||||
.card_pcm_tospan = PRI_card_pcm_tospan,
|
||||
.card_timing_priority = PRI_timing_priority,
|
||||
.card_ioctl = PRI_card_ioctl,
|
||||
.card_close = PRI_card_close,
|
||||
|
||||
.XPD_STATE = XPROTO_CALLER(PRI, XPD_STATE),
|
||||
};
|
||||
|
||||
static xproto_table_t PROTO_TABLE(PRI) = {
|
||||
.owner = THIS_MODULE,
|
||||
.entries = {
|
||||
@@ -2173,23 +2198,8 @@ static xproto_table_t PROTO_TABLE(PRI) = {
|
||||
.name = "PRI", /* protocol name */
|
||||
.ports_per_subunit = 1,
|
||||
.type = XPD_TYPE_PRI,
|
||||
.xops = {
|
||||
.card_new = PRI_card_new,
|
||||
.card_init = PRI_card_init,
|
||||
.card_remove = PRI_card_remove,
|
||||
.card_dahdi_preregistration = PRI_card_dahdi_preregistration,
|
||||
.card_dahdi_postregistration = PRI_card_dahdi_postregistration,
|
||||
.card_tick = PRI_card_tick,
|
||||
.card_pcm_recompute = PRI_card_pcm_recompute,
|
||||
.card_pcm_fromspan = PRI_card_pcm_fromspan,
|
||||
.card_pcm_tospan = PRI_card_pcm_tospan,
|
||||
.card_timing_priority = PRI_timing_priority,
|
||||
.card_ioctl = PRI_card_ioctl,
|
||||
.card_close = PRI_card_close,
|
||||
.card_register_reply = PRI_card_register_reply,
|
||||
|
||||
.XPD_STATE = XPROTO_CALLER(PRI, XPD_STATE),
|
||||
},
|
||||
.xops = &pri_xops,
|
||||
.phoneops = &pri_phoneops,
|
||||
.packet_is_valid = pri_packet_is_valid,
|
||||
.packet_dump = pri_packet_dump,
|
||||
};
|
||||
|
||||
@@ -784,7 +784,6 @@ static int new_card(xbus_t *xbus,
|
||||
byte port_dir)
|
||||
{
|
||||
const xproto_table_t *proto_table;
|
||||
const xops_t *xops;
|
||||
int i;
|
||||
int subunits;
|
||||
int ret = 0;
|
||||
@@ -810,8 +809,7 @@ static int new_card(xbus_t *xbus,
|
||||
subunits,
|
||||
port_dir
|
||||
);
|
||||
xops = &proto_table->xops;
|
||||
BUG_ON(!xops);
|
||||
BUG_ON(!proto_table->phoneops);
|
||||
xbus->worker.num_units += subunits - 1;
|
||||
for(i = 0; i < subunits; i++) {
|
||||
int subunit_ports = proto_table->ports_per_subunit;
|
||||
@@ -915,7 +913,7 @@ static int xpd_initialize(xpd_t *xpd)
|
||||
}
|
||||
//CALL_XMETHOD(XPD_STATE, xpd->xbus, xpd, 0); /* Turn off all channels */
|
||||
xpd->card_present = 1;
|
||||
CALL_XMETHOD(XPD_STATE, xpd->xbus, xpd, 1); /* Turn on all channels */
|
||||
PHONE_METHOD(xpd, XPD_STATE)(xpd->xbus, xpd, 1); /* Turn on all channels */
|
||||
if(!xpd_setstate(xpd, XPD_STATE_READY)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -496,7 +496,8 @@ static void global_tick(void)
|
||||
#ifdef DAHDI_SYNC_TICK
|
||||
void dahdi_sync_tick(struct dahdi_span *span, int is_master)
|
||||
{
|
||||
xpd_t *xpd = container_of(span, struct xpd, span);
|
||||
struct phonedev *phonedev = container_of(span, struct phonedev, span);
|
||||
xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
|
||||
static int redundant_ticks; /* for extra spans */
|
||||
struct timeval now;
|
||||
|
||||
@@ -629,8 +630,7 @@ void elect_syncer(const char *msg)
|
||||
|
||||
if(!xpd || !xpd->card_present)
|
||||
continue;
|
||||
prio = CALL_XMETHOD(card_timing_priority,
|
||||
xbus, xpd);
|
||||
prio = PHONE_METHOD(xpd, card_timing_priority)(xbus, xpd);
|
||||
if (prio < 0) {
|
||||
DBG(SYNC, "%s/%s: skip sync\n",
|
||||
xbus->busname, xpd->xpdname);
|
||||
@@ -668,10 +668,10 @@ void elect_syncer(const char *msg)
|
||||
*/
|
||||
void update_wanted_pcm_mask(xpd_t *xpd, xpp_line_t new_mask, uint new_pcm_len)
|
||||
{
|
||||
xpd->pcm_len = new_pcm_len;
|
||||
xpd->wanted_pcm_mask = new_mask;
|
||||
PHONEDEV(xpd).pcm_len = new_pcm_len;
|
||||
PHONEDEV(xpd).wanted_pcm_mask = new_mask;
|
||||
XPD_DBG(SIGNAL, xpd, "pcm_len=%d wanted_pcm_mask=0x%X\n",
|
||||
xpd->pcm_len, xpd->wanted_pcm_mask);
|
||||
PHONEDEV(xpd).pcm_len, PHONEDEV(xpd).wanted_pcm_mask);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -686,13 +686,13 @@ void generic_card_pcm_recompute(xbus_t *xbus, xpd_t *xpd, xpp_line_t pcm_mask)
|
||||
unsigned long flags;
|
||||
uint pcm_len;
|
||||
|
||||
spin_lock_irqsave(&xpd->lock_recompute_pcm, flags);
|
||||
spin_lock_irqsave(&PHONEDEV(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_state;
|
||||
pcm_mask |= xpd->oht_pcm_pass;
|
||||
pcm_mask &= ~xpd->digital_inputs;
|
||||
pcm_mask &= ~xpd->digital_outputs;
|
||||
pcm_mask |= PHONEDEV(xpd).offhook_state;
|
||||
pcm_mask |= PHONEDEV(xpd).oht_pcm_pass;
|
||||
pcm_mask &= ~(PHONEDEV(xpd).digital_inputs);
|
||||
pcm_mask &= ~(PHONEDEV(xpd).digital_outputs);
|
||||
for_each_line(xpd, i)
|
||||
if(IS_SET(pcm_mask, i))
|
||||
line_count++;
|
||||
@@ -708,7 +708,7 @@ void generic_card_pcm_recompute(xbus_t *xbus, xpd_t *xpd, xpp_line_t pcm_mask)
|
||||
? RPACKET_HEADERSIZE + sizeof(xpp_line_t) + line_count * DAHDI_CHUNKSIZE
|
||||
: 0L;
|
||||
update_wanted_pcm_mask(xpd, pcm_mask, pcm_len);
|
||||
spin_unlock_irqrestore(&xpd->lock_recompute_pcm, flags);
|
||||
spin_unlock_irqrestore(&PHONEDEV(xpd).lock_recompute_pcm, flags);
|
||||
}
|
||||
|
||||
void fill_beep(u_char *buf, int num, int duration)
|
||||
@@ -741,16 +741,16 @@ static void do_ec(xpd_t *xpd)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0;i < xpd->span.channels; i++) {
|
||||
for (i = 0;i < PHONEDEV(xpd).span.channels; i++) {
|
||||
struct dahdi_chan *chan = XPD_CHAN(xpd, i);
|
||||
|
||||
if(unlikely(IS_SET(xpd->digital_signalling, i))) /* Don't echo cancel BRI D-chans */
|
||||
if(unlikely(IS_SET(PHONEDEV(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 */
|
||||
if(!IS_SET(PHONEDEV(xpd).wanted_pcm_mask, i)) /* No ec for unwanted PCM */
|
||||
continue;
|
||||
dahdi_ec_chunk(chan, chan->readchunk, xpd->ec_chunk2[i]);
|
||||
memcpy(xpd->ec_chunk2[i], xpd->ec_chunk1[i], DAHDI_CHUNKSIZE);
|
||||
memcpy(xpd->ec_chunk1[i], chan->writechunk, DAHDI_CHUNKSIZE);
|
||||
dahdi_ec_chunk(chan, chan->readchunk, PHONEDEV(xpd).ec_chunk2[i]);
|
||||
memcpy(PHONEDEV(xpd).ec_chunk2[i], PHONEDEV(xpd).ec_chunk1[i], DAHDI_CHUNKSIZE);
|
||||
memcpy(PHONEDEV(xpd).ec_chunk1[i], chan->writechunk, DAHDI_CHUNKSIZE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -864,11 +864,11 @@ void generic_card_pcm_fromspan(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack)
|
||||
BUG_ON(!xbus);
|
||||
BUG_ON(!xpd);
|
||||
BUG_ON(!pack);
|
||||
wanted_lines = xpd->wanted_pcm_mask;
|
||||
wanted_lines = PHONEDEV(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);
|
||||
for (i = 0; i < xpd->channels; i++) {
|
||||
for (i = 0; i < PHONEDEV(xpd).channels; i++) {
|
||||
struct dahdi_chan *chan = XPD_CHAN(xpd, i);
|
||||
|
||||
if(IS_SET(wanted_lines, i)) {
|
||||
@@ -904,11 +904,11 @@ void generic_card_pcm_tospan(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack)
|
||||
/*
|
||||
* Calculate the channels we want to mute
|
||||
*/
|
||||
pcm_mute = ~xpd->wanted_pcm_mask;
|
||||
pcm_mute |= xpd->mute_dtmf | xpd->silence_pcm;
|
||||
pcm_mute = ~(PHONEDEV(xpd).wanted_pcm_mask);
|
||||
pcm_mute |= PHONEDEV(xpd).mute_dtmf | PHONEDEV(xpd).silence_pcm;
|
||||
if(!SPAN_REGISTERED(xpd))
|
||||
goto out;
|
||||
for (i = 0; i < xpd->channels; i++) {
|
||||
for (i = 0; i < PHONEDEV(xpd).channels; i++) {
|
||||
volatile u_char *r = XPD_CHAN(xpd, i)->readchunk;
|
||||
bool got_data = IS_SET(pcm_mask, i);
|
||||
|
||||
@@ -916,16 +916,16 @@ void generic_card_pcm_tospan(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack)
|
||||
/* We have and want real data */
|
||||
// memset((u_char *)r, 0x5A, DAHDI_CHUNKSIZE); // DEBUG
|
||||
memcpy((u_char *)r, pcm, DAHDI_CHUNKSIZE);
|
||||
} else if(IS_SET(xpd->wanted_pcm_mask | xpd->silence_pcm, i)) {
|
||||
} else if(IS_SET(PHONEDEV(xpd).wanted_pcm_mask | PHONEDEV(xpd).silence_pcm, i)) {
|
||||
/* Inject SILENCE */
|
||||
memset((u_char *)r, 0x7F, DAHDI_CHUNKSIZE);
|
||||
if(IS_SET(xpd->silence_pcm, i)) {
|
||||
if(IS_SET(PHONEDEV(xpd).silence_pcm, i)) {
|
||||
/*
|
||||
* This will clear the EC buffers until next tick
|
||||
* So we don't have noise residues from the past.
|
||||
*/
|
||||
memset(xpd->ec_chunk2[i], 0x7F, DAHDI_CHUNKSIZE);
|
||||
memset(xpd->ec_chunk1[i], 0x7F, DAHDI_CHUNKSIZE);
|
||||
memset(PHONEDEV(xpd).ec_chunk2[i], 0x7F, DAHDI_CHUNKSIZE);
|
||||
memset(PHONEDEV(xpd).ec_chunk1[i], 0x7F, DAHDI_CHUNKSIZE);
|
||||
}
|
||||
}
|
||||
if(got_data)
|
||||
@@ -993,7 +993,7 @@ static int copy_pcm_tospan(xbus_t *xbus, xframe_t *xframe)
|
||||
goto out;
|
||||
if(SPAN_REGISTERED(xpd)) {
|
||||
XBUS_COUNTER(xbus, RX_PACK_PCM)++;
|
||||
CALL_XMETHOD(card_pcm_tospan, xbus, xpd, pack);
|
||||
PHONE_METHOD(xpd, card_pcm_tospan)(xbus, xpd, pack);
|
||||
}
|
||||
} while(p < xframe_end);
|
||||
ret = 0; /* all good */
|
||||
@@ -1005,7 +1005,7 @@ out:
|
||||
|
||||
int generic_timing_priority(xbus_t *xbus, xpd_t *xpd)
|
||||
{
|
||||
return xpd->timing_priority;
|
||||
return PHONEDEV(xpd).timing_priority;
|
||||
}
|
||||
|
||||
static void xbus_tick(xbus_t *xbus)
|
||||
@@ -1024,10 +1024,10 @@ static void xbus_tick(xbus_t *xbus)
|
||||
if(xpd && SPAN_REGISTERED(xpd)) {
|
||||
#ifdef OPTIMIZE_CHANMUTE
|
||||
int j;
|
||||
xpp_line_t xmit_mask = xpd->wanted_pcm_mask;
|
||||
xpp_line_t xmit_mask = PHONEDEV(xpd).wanted_pcm_mask;
|
||||
|
||||
xmit_mask |= xpd->silence_pcm;
|
||||
xmit_mask |= xpd->digital_signalling;
|
||||
xmit_mask |= PHONEDEV(xpd).silence_pcm;
|
||||
xmit_mask |= PHONEDEV(xpd).digital_signalling;
|
||||
for_each_line(xpd, j) {
|
||||
XPD_CHAN(xpd, j)->chanmute = (optimize_chanmute)
|
||||
? !IS_SET(xmit_mask, j)
|
||||
@@ -1038,7 +1038,7 @@ static void xbus_tick(xbus_t *xbus)
|
||||
* calls to dahdi_transmit should be out of spinlocks, as it may call back
|
||||
* our hook setting methods.
|
||||
*/
|
||||
dahdi_transmit(&xpd->span);
|
||||
dahdi_transmit(&PHONEDEV(xpd).span);
|
||||
}
|
||||
}
|
||||
/*
|
||||
@@ -1049,7 +1049,7 @@ static void xbus_tick(xbus_t *xbus)
|
||||
|
||||
if((xpd = xpd_of(xbus, i)) == NULL)
|
||||
continue;
|
||||
pcm_len = xpd->pcm_len;
|
||||
pcm_len = PHONEDEV(xpd).pcm_len;
|
||||
if(SPAN_REGISTERED(xpd)) {
|
||||
if(pcm_len && xpd->card_present) {
|
||||
do {
|
||||
@@ -1079,7 +1079,7 @@ static void xbus_tick(xbus_t *xbus)
|
||||
XPACKET_ADDR_SYNC(pack) = 1;
|
||||
sent_sync_bit = 1;
|
||||
}
|
||||
CALL_XMETHOD(card_pcm_fromspan, xbus, xpd, pack);
|
||||
PHONE_METHOD(xpd, card_pcm_fromspan)(xbus, xpd, pack);
|
||||
XBUS_COUNTER(xbus, TX_PACK_PCM)++;
|
||||
}
|
||||
}
|
||||
@@ -1120,9 +1120,9 @@ static void xbus_tick(xbus_t *xbus)
|
||||
continue;
|
||||
if(SPAN_REGISTERED(xpd)) {
|
||||
do_ec(xpd);
|
||||
dahdi_receive(&xpd->span);
|
||||
dahdi_receive(&PHONEDEV(xpd).span);
|
||||
}
|
||||
xpd->silence_pcm = 0; /* silence was injected */
|
||||
PHONEDEV(xpd).silence_pcm = 0; /* silence was injected */
|
||||
xpd->timer_count = xbus->global_counter;
|
||||
/*
|
||||
* Must be called *after* tx/rx so
|
||||
|
||||
@@ -621,7 +621,7 @@ static DEVICE_ATTR_READER(span_show, dev, buf)
|
||||
if(!xpd)
|
||||
return -ENODEV;
|
||||
spin_lock_irqsave(&xpd->lock, flags);
|
||||
len += sprintf(buf, "%d\n", SPAN_REGISTERED(xpd) ? xpd->span.spanno : 0);
|
||||
len += sprintf(buf, "%d\n", SPAN_REGISTERED(xpd) ? PHONEDEV(xpd).span.spanno : 0);
|
||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||
return len;
|
||||
}
|
||||
@@ -693,7 +693,7 @@ static DEVICE_ATTR_READER(timing_priority_show, dev, buf)
|
||||
if(!xpd)
|
||||
return -ENODEV;
|
||||
spin_lock_irqsave(&xpd->lock, flags);
|
||||
len += sprintf(buf + len, "%d\n", xpd->timing_priority);
|
||||
len += sprintf(buf + len, "%d\n", PHONEDEV(xpd).timing_priority);
|
||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -159,7 +159,6 @@ typedef struct xbus xbus_t;
|
||||
typedef struct xpd xpd_t;
|
||||
typedef struct xframe xframe_t;
|
||||
typedef struct xpacket xpacket_t;
|
||||
typedef struct xops xops_t;
|
||||
typedef __u32 xpp_line_t; /* at most 31 lines for E1 */
|
||||
typedef byte lineno_t;
|
||||
typedef byte xportno_t;
|
||||
|
||||
@@ -149,21 +149,15 @@ enum xpd_state {
|
||||
bool xpd_setstate(xpd_t *xpd, enum xpd_state newstate);
|
||||
const char *xpd_statename(enum xpd_state st);
|
||||
|
||||
/*
|
||||
* An XPD is a single Xorcom Protocol Device
|
||||
*/
|
||||
struct xpd {
|
||||
char xpdname[XPD_NAMELEN];
|
||||
#define PHONEDEV(xpd) ((xpd)->phonedev)
|
||||
|
||||
struct phonedev {
|
||||
const struct phoneops *phoneops; /* Card level operations */
|
||||
struct dahdi_span span;
|
||||
struct dahdi_chan *chans[32];
|
||||
#define XPD_CHAN(xpd,chan) ((xpd)->chans[(chan)])
|
||||
|
||||
#define XPD_CHAN(xpd,chan) (PHONEDEV(xpd).chans[(chan)])
|
||||
int channels;
|
||||
xpd_type_t type;
|
||||
const char *type_name;
|
||||
byte subtype;
|
||||
xpd_direction_t direction; /* TO_PHONE, TO_PSTN */
|
||||
int subunits; /* all siblings */
|
||||
xpp_line_t no_pcm; /* Temporary: disable PCM (for USB-1) */
|
||||
xpp_line_t offhook_state; /* Actual chip state: 0 - ONHOOK, 1 - OFHOOK */
|
||||
xpp_line_t oht_pcm_pass; /* Transfer on-hook PCM */
|
||||
@@ -174,12 +168,6 @@ struct xpd {
|
||||
xpp_line_t digital_signalling; /* BRI signalling channels */
|
||||
uint timing_priority; /* from 'span' directives in chan_dahdi.conf */
|
||||
|
||||
enum xpd_state xpd_state;
|
||||
struct device xpd_dev;
|
||||
#define dev_to_xpd(dev) container_of(dev, struct xpd, xpd_dev)
|
||||
struct kref kref;
|
||||
#define kref_to_xpd(k) container_of(k, struct xpd, kref)
|
||||
|
||||
/* Assure atomicity of changes to pcm_len and wanted_pcm_mask */
|
||||
spinlock_t lock_recompute_pcm;
|
||||
/* maintained by card drivers */
|
||||
@@ -190,11 +178,35 @@ struct xpd {
|
||||
|
||||
bool ringing[CHANNELS_PERXPD];
|
||||
|
||||
atomic_t dahdi_registered; /* Am I fully registered with dahdi */
|
||||
atomic_t open_counter; /* Number of open channels */
|
||||
|
||||
/* Echo cancelation */
|
||||
u_char ec_chunk1[CHANNELS_PERXPD][DAHDI_CHUNKSIZE];
|
||||
u_char ec_chunk2[CHANNELS_PERXPD][DAHDI_CHUNKSIZE];
|
||||
};
|
||||
|
||||
/*
|
||||
* An XPD is a single Xorcom Protocol Device
|
||||
*/
|
||||
struct xpd {
|
||||
char xpdname[XPD_NAMELEN];
|
||||
struct phonedev phonedev;
|
||||
|
||||
const struct xops *xops;
|
||||
xpd_type_t type;
|
||||
const char *type_name;
|
||||
byte subtype;
|
||||
int subunits; /* all siblings */
|
||||
enum xpd_state xpd_state;
|
||||
struct device xpd_dev;
|
||||
#define dev_to_xpd(dev) container_of(dev, struct xpd, xpd_dev)
|
||||
struct kref kref;
|
||||
#define kref_to_xpd(k) container_of(k, struct xpd, kref)
|
||||
|
||||
xbus_t *xbus; /* The XBUS we are connected to */
|
||||
|
||||
spinlock_t lock;
|
||||
atomic_t dahdi_registered; /* Am I fully registered with dahdi */
|
||||
atomic_t open_counter; /* Number of open channels */
|
||||
|
||||
int flags;
|
||||
unsigned long blink_mode; /* bitmask of blinking ports */
|
||||
@@ -213,7 +225,6 @@ struct xpd {
|
||||
int counters[XPD_COUNTER_MAX];
|
||||
|
||||
const xproto_table_t *xproto; /* Card level protocol table */
|
||||
const xops_t *xops; /* Card level operations */
|
||||
void *priv; /* Card level private data */
|
||||
bool card_present;
|
||||
reg_cmd_t requested_reply;
|
||||
@@ -224,12 +235,9 @@ struct xpd {
|
||||
struct xpd_addr addr;
|
||||
struct list_head xpd_list;
|
||||
unsigned int timer_count;
|
||||
/* Echo cancelation */
|
||||
u_char ec_chunk1[CHANNELS_PERXPD][DAHDI_CHUNKSIZE];
|
||||
u_char ec_chunk2[CHANNELS_PERXPD][DAHDI_CHUNKSIZE];
|
||||
};
|
||||
|
||||
#define for_each_line(xpd,i) for((i) = 0; (i) < (xpd)->channels; (i)++)
|
||||
#define for_each_line(xpd,i) for((i) = 0; (i) < PHONEDEV(xpd).channels; (i)++)
|
||||
#define IS_BRI(xpd) ((xpd)->type == XPD_TYPE_BRI)
|
||||
#define TICK_TOLERANCE 500 /* usec */
|
||||
|
||||
|
||||
@@ -251,9 +251,9 @@ void xpd_free(xpd_t *xpd)
|
||||
XPD_DBG(DEVICES, xpd, "\n");
|
||||
xpd_proc_remove(xbus, xpd);
|
||||
xbus_xpd_unbind(xbus, xpd);
|
||||
for (x = 0; x < xpd->channels; x++) {
|
||||
if (xpd->chans[x])
|
||||
KZFREE(xpd->chans[x]);
|
||||
for (x = 0; x < PHONEDEV(xpd).channels; x++) {
|
||||
if (PHONEDEV(xpd).chans[x])
|
||||
KZFREE(PHONEDEV(xpd).chans[x]);
|
||||
}
|
||||
KZFREE(xpd);
|
||||
DBG(DEVICES, "refcount_xbus=%d\n", refcount_xbus(xbus));
|
||||
@@ -293,7 +293,7 @@ int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table,
|
||||
subunit_ports, unit, subunit);
|
||||
return 0;
|
||||
}
|
||||
xpd = proto_table->xops.card_new(xbus, unit, subunit, proto_table, subtype, subunits, subunit_ports, to_phone);
|
||||
xpd = proto_table->xops->card_new(xbus, unit, subunit, proto_table, subtype, subunits, subunit_ports, to_phone);
|
||||
if(!xpd) {
|
||||
XBUS_NOTICE(xbus, "card_new(%d,%d,%d,%d,%d) failed. Ignored.\n",
|
||||
unit, subunit, proto_table->type, subtype, to_phone);
|
||||
@@ -337,28 +337,28 @@ static int xpd_read_proc(char *page, char **start, off_t off, int count, int *eo
|
||||
,
|
||||
xpd->xpdname, xpd->type_name,
|
||||
(xpd->card_present) ? "present" : "missing",
|
||||
(SPAN_REGISTERED(xpd)) ? xpd->span.spanno : 0,
|
||||
xpd->timing_priority,
|
||||
xpd->timer_count, xpd->span.mainttimer
|
||||
(SPAN_REGISTERED(xpd)) ? PHONEDEV(xpd).span.spanno : 0,
|
||||
PHONEDEV(xpd).timing_priority,
|
||||
xpd->timer_count, PHONEDEV(xpd).span.mainttimer
|
||||
);
|
||||
len += sprintf(page + len, "xpd_state: %s (%d)\n",
|
||||
xpd_statename(xpd->xpd_state), xpd->xpd_state);
|
||||
len += sprintf(page + len, "open_counter=%d refcount=%d\n",
|
||||
atomic_read(&xpd->open_counter), refcount_xpd(xpd));
|
||||
atomic_read(&PHONEDEV(xpd).open_counter), refcount_xpd(xpd));
|
||||
len += sprintf(page + len, "Address: U=%d S=%d\n", xpd->addr.unit, xpd->addr.subunit);
|
||||
len += sprintf(page + len, "Subunits: %d\n", xpd->subunits);
|
||||
len += sprintf(page + len, "Type: %d.%d\n\n", xpd->type, xpd->subtype);
|
||||
len += sprintf(page + len, "pcm_len=%d\n\n", xpd->pcm_len);
|
||||
len += sprintf(page + len, "wanted_pcm_mask=0x%04X\n\n", xpd->wanted_pcm_mask);
|
||||
len += sprintf(page + len, "mute_dtmf=0x%04X\n\n", xpd->mute_dtmf);
|
||||
len += sprintf(page + len, "pcm_len=%d\n\n", PHONEDEV(xpd).pcm_len);
|
||||
len += sprintf(page + len, "wanted_pcm_mask=0x%04X\n\n", PHONEDEV(xpd).wanted_pcm_mask);
|
||||
len += sprintf(page + len, "mute_dtmf=0x%04X\n\n", PHONEDEV(xpd).mute_dtmf);
|
||||
len += sprintf(page + len, "STATES:");
|
||||
len += sprintf(page + len, "\n\t%-17s: ", "output_relays");
|
||||
for_each_line(xpd, i) {
|
||||
len += sprintf(page + len, "%d ", IS_SET(xpd->digital_outputs, i));
|
||||
len += sprintf(page + len, "%d ", IS_SET(PHONEDEV(xpd).digital_outputs, i));
|
||||
}
|
||||
len += sprintf(page + len, "\n\t%-17s: ", "input_relays");
|
||||
for_each_line(xpd, i) {
|
||||
len += sprintf(page + len, "%d ", IS_SET(xpd->digital_inputs, i));
|
||||
len += sprintf(page + len, "%d ", IS_SET(PHONEDEV(xpd).digital_inputs, i));
|
||||
}
|
||||
len += sprintf(page + len, "\n\t%-17s: ", "offhook");
|
||||
for_each_line(xpd, i) {
|
||||
@@ -366,19 +366,19 @@ static int xpd_read_proc(char *page, char **start, off_t off, int count, int *eo
|
||||
}
|
||||
len += sprintf(page + len, "\n\t%-17s: ", "oht_pcm_pass");
|
||||
for_each_line(xpd, i) {
|
||||
len += sprintf(page + len, "%d ", IS_SET(xpd->oht_pcm_pass, i));
|
||||
len += sprintf(page + len, "%d ", IS_SET(PHONEDEV(xpd).oht_pcm_pass, i));
|
||||
}
|
||||
len += sprintf(page + len, "\n\t%-17s: ", "msg_waiting");
|
||||
for_each_line(xpd, i) {
|
||||
len += sprintf(page + len, "%d ", xpd->msg_waiting[i]);
|
||||
len += sprintf(page + len, "%d ", PHONEDEV(xpd).msg_waiting[i]);
|
||||
}
|
||||
len += sprintf(page + len, "\n\t%-17s: ", "ringing");
|
||||
for_each_line(xpd, i) {
|
||||
len += sprintf(page + len, "%d ", xpd->ringing[i]);
|
||||
len += sprintf(page + len, "%d ", PHONEDEV(xpd).ringing[i]);
|
||||
}
|
||||
len += sprintf(page + len, "\n\t%-17s: ", "no_pcm");
|
||||
for_each_line(xpd, i) {
|
||||
len += sprintf(page + len, "%d ", IS_SET(xpd->no_pcm, i));
|
||||
len += sprintf(page + len, "%d ", IS_SET(PHONEDEV(xpd).no_pcm, i));
|
||||
}
|
||||
#if 1
|
||||
if(SPAN_REGISTERED(xpd)) {
|
||||
@@ -391,11 +391,11 @@ static int xpd_read_proc(char *page, char **start, off_t off, int count, int *eo
|
||||
byte *wp;
|
||||
int j;
|
||||
|
||||
if(IS_SET(xpd->digital_outputs, i))
|
||||
if(IS_SET(PHONEDEV(xpd).digital_outputs, i))
|
||||
continue;
|
||||
if(IS_SET(xpd->digital_inputs, i))
|
||||
if(IS_SET(PHONEDEV(xpd).digital_inputs, i))
|
||||
continue;
|
||||
if(IS_SET(xpd->digital_signalling, i))
|
||||
if(IS_SET(PHONEDEV(xpd).digital_signalling, i))
|
||||
continue;
|
||||
rp = chan->readchunk;
|
||||
wp = chan->writechunk;
|
||||
@@ -410,9 +410,9 @@ static int xpd_read_proc(char *page, char **start, off_t off, int count, int *eo
|
||||
len += sprintf(page + len, "%02X ", wchunk[j]);
|
||||
}
|
||||
len += sprintf(page + len, " | %c",
|
||||
(IS_SET(xpd->wanted_pcm_mask, i))?'+':' ');
|
||||
(IS_SET(PHONEDEV(xpd).wanted_pcm_mask, i))?'+':' ');
|
||||
len += sprintf(page + len, " %c",
|
||||
(IS_SET(xpd->mute_dtmf, i))?'-':' ');
|
||||
(IS_SET(PHONEDEV(xpd).mute_dtmf, i))?'-':' ');
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -502,6 +502,48 @@ badstate:
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Cleanup/initialize phonedev
|
||||
*/
|
||||
static void phonedev_cleanup(xpd_t *xpd)
|
||||
{
|
||||
struct phonedev *phonedev = &PHONEDEV(xpd);
|
||||
unsigned int x;
|
||||
|
||||
for (x = 0; x < phonedev->channels; x++) {
|
||||
if (phonedev->chans[x]) {
|
||||
kfree(phonedev->chans[x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__must_check static int phonedev_init(xpd_t *xpd, const xproto_table_t *proto_table,
|
||||
int channels, xpp_line_t no_pcm)
|
||||
{
|
||||
struct phonedev *phonedev = &PHONEDEV(xpd);
|
||||
unsigned int x;
|
||||
|
||||
spin_lock_init(&phonedev->lock_recompute_pcm);
|
||||
phonedev->channels = channels;
|
||||
phonedev->no_pcm = no_pcm;
|
||||
phonedev->offhook_state = 0x0; /* ONHOOK */
|
||||
phonedev->phoneops = proto_table->phoneops;
|
||||
phonedev->digital_outputs = 0;
|
||||
phonedev->digital_inputs = 0;
|
||||
atomic_set(&phonedev->dahdi_registered, 0);
|
||||
atomic_set(&phonedev->open_counter, 0);
|
||||
for (x = 0; x < phonedev->channels; x++) {
|
||||
if (!(phonedev->chans[x] = kmalloc(sizeof(*(phonedev->chans[x])), GFP_KERNEL))) {
|
||||
ERR("%s: Unable to allocate channel %d\n", __FUNCTION__, x);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
err:
|
||||
phonedev_cleanup(xpd);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* xpd_alloc - Allocator for new XPD's
|
||||
*
|
||||
@@ -514,7 +556,7 @@ __must_check xpd_t *xpd_alloc(xbus_t *xbus,
|
||||
xpd_t *xpd = NULL;
|
||||
size_t alloc_size = sizeof(xpd_t) + privsize;
|
||||
int type = proto_table->type;
|
||||
unsigned int x;
|
||||
xpp_line_t no_pcm = 0;
|
||||
|
||||
BUG_ON(!proto_table);
|
||||
XBUS_DBG(DEVICES, xbus, "type=%d channels=%d (alloc_size=%zd)\n",
|
||||
@@ -532,38 +574,23 @@ __must_check xpd_t *xpd_alloc(xbus_t *xbus,
|
||||
}
|
||||
xpd->priv = (byte *)xpd + sizeof(xpd_t);
|
||||
spin_lock_init(&xpd->lock);
|
||||
spin_lock_init(&xpd->lock_recompute_pcm);
|
||||
xpd->channels = channels;
|
||||
xpd->card_present = 0;
|
||||
xpd->offhook_state = 0x0; /* ONHOOK */
|
||||
xpd->type = proto_table->type;
|
||||
xpd->xproto = proto_table;
|
||||
xpd->xops = &proto_table->xops;
|
||||
xpd->digital_outputs = 0;
|
||||
xpd->digital_inputs = 0;
|
||||
xpd->xops = proto_table->xops;
|
||||
xpd->xpd_state = XPD_STATE_START;
|
||||
xpd->subtype = subtype;
|
||||
xpd->subunits = subunits;
|
||||
|
||||
atomic_set(&xpd->dahdi_registered, 0);
|
||||
atomic_set(&xpd->open_counter, 0);
|
||||
kref_init(&xpd->kref);
|
||||
|
||||
/* For USB-1 disable some channels */
|
||||
if(MAX_SEND_SIZE(xbus) < RPACKET_SIZE(GLOBAL, PCM_WRITE)) {
|
||||
xpp_line_t no_pcm;
|
||||
|
||||
no_pcm = 0x7F | xpd->digital_outputs | xpd->digital_inputs;
|
||||
xpd->no_pcm = no_pcm;
|
||||
no_pcm = 0x7F | PHONEDEV(xpd).digital_outputs | PHONEDEV(xpd).digital_inputs;
|
||||
XBUS_NOTICE(xbus, "max xframe size = %d, disabling some PCM channels. no_pcm=0x%04X\n",
|
||||
MAX_SEND_SIZE(xbus), xpd->no_pcm);
|
||||
}
|
||||
for (x = 0; x < xpd->channels; x++) {
|
||||
if (!(xpd->chans[x] = kmalloc(sizeof(*xpd->chans[x]), GFP_KERNEL))) {
|
||||
ERR("%s: Unable to allocate channel %d\n", __FUNCTION__, x);
|
||||
goto err;
|
||||
}
|
||||
MAX_SEND_SIZE(xbus), PHONEDEV(xpd).no_pcm);
|
||||
}
|
||||
if (phonedev_init(xpd, proto_table, channels, no_pcm) < 0)
|
||||
goto err;
|
||||
xbus_xpd_bind(xbus, xpd, unit, subunit);
|
||||
if(xpd_proc_create(xbus, xpd) < 0)
|
||||
goto err;
|
||||
@@ -577,11 +604,7 @@ __must_check xpd_t *xpd_alloc(xbus_t *xbus,
|
||||
err:
|
||||
if(xpd) {
|
||||
xpd_proc_remove(xbus, xpd);
|
||||
for (x = 0; x < xpd->channels; x++) {
|
||||
if (xpd->chans[x]) {
|
||||
kfree(xpd->chans[x]);
|
||||
}
|
||||
}
|
||||
phonedev_cleanup(xpd);
|
||||
KZFREE(xpd);
|
||||
}
|
||||
return NULL;
|
||||
@@ -606,7 +629,7 @@ void xbus_request_removal(xbus_t *xbus)
|
||||
spin_lock_irqsave(&xpd->lock, flags);
|
||||
xpd->card_present = 0;
|
||||
xpd_setstate(xpd, XPD_STATE_NOHW);
|
||||
xpd->span.alarms = DAHDI_ALARM_NOTOPEN;
|
||||
PHONEDEV(xpd).span.alarms = DAHDI_ALARM_NOTOPEN;
|
||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||
}
|
||||
}
|
||||
@@ -617,9 +640,9 @@ void xbus_request_removal(xbus_t *xbus)
|
||||
if(SPAN_REGISTERED(xpd)) {
|
||||
int j;
|
||||
|
||||
dahdi_alarm_notify(&xpd->span);
|
||||
dahdi_alarm_notify(&PHONEDEV(xpd).span);
|
||||
XPD_DBG(DEVICES, xpd, "Queuing DAHDI_EVENT_REMOVED on all channels to ask user to release them\n");
|
||||
for (j=0; j<xpd->span.channels; j++) {
|
||||
for (j=0; j<PHONEDEV(xpd).span.channels; j++) {
|
||||
dahdi_qevent_lock(XPD_CHAN(xpd, j),DAHDI_EVENT_REMOVED);
|
||||
}
|
||||
}
|
||||
@@ -644,7 +667,7 @@ void xpd_remove(xpd_t *xpd)
|
||||
|
||||
void update_xpd_status(xpd_t *xpd, int alarm_flag)
|
||||
{
|
||||
struct dahdi_span *span = &xpd->span;
|
||||
struct dahdi_span *span = &PHONEDEV(xpd).span;
|
||||
|
||||
if(!SPAN_REGISTERED(xpd)) {
|
||||
// XPD_NOTICE(xpd, "%s: XPD is not registered. Skipping.\n", __FUNCTION__);
|
||||
@@ -660,7 +683,7 @@ void update_xpd_status(xpd_t *xpd, int alarm_flag)
|
||||
}
|
||||
if(span->alarms == alarm_flag)
|
||||
return;
|
||||
XPD_DBG(GENERAL, xpd, "Update XPD alarms: %s -> %02X\n", xpd->span.name, alarm_flag);
|
||||
XPD_DBG(GENERAL, xpd, "Update XPD alarms: %s -> %02X\n", PHONEDEV(xpd).span.name, alarm_flag);
|
||||
span->alarms = alarm_flag;
|
||||
dahdi_alarm_notify(span);
|
||||
}
|
||||
@@ -674,12 +697,12 @@ void oht_pcm(xpd_t *xpd, int pos, bool pass)
|
||||
{
|
||||
if(pass) {
|
||||
LINE_DBG(SIGNAL, xpd, pos, "OHT PCM: pass\n");
|
||||
BIT_SET(xpd->oht_pcm_pass, pos);
|
||||
BIT_SET(PHONEDEV(xpd).oht_pcm_pass, pos);
|
||||
} else {
|
||||
LINE_DBG(SIGNAL, xpd, pos, "OHT PCM: block\n");
|
||||
BIT_CLR(xpd->oht_pcm_pass, pos);
|
||||
BIT_CLR(PHONEDEV(xpd).oht_pcm_pass, pos);
|
||||
}
|
||||
CALL_XMETHOD(card_pcm_recompute, xpd->xbus, xpd, 0);
|
||||
PHONE_METHOD(xpd, card_pcm_recompute)(xpd->xbus, xpd, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -689,12 +712,12 @@ void mark_offhook(xpd_t *xpd, int pos, bool to_offhook)
|
||||
{
|
||||
if(to_offhook) {
|
||||
LINE_DBG(SIGNAL, xpd, pos, "OFFHOOK\n");
|
||||
BIT_SET(xpd->offhook_state, pos);
|
||||
BIT_SET(PHONEDEV(xpd).offhook_state, pos);
|
||||
} else {
|
||||
LINE_DBG(SIGNAL, xpd, pos, "ONHOOK\n");
|
||||
BIT_CLR(xpd->offhook_state, pos);
|
||||
BIT_CLR(PHONEDEV(xpd).offhook_state, pos);
|
||||
}
|
||||
CALL_XMETHOD(card_pcm_recompute, xpd->xbus, xpd, 0);
|
||||
PHONE_METHOD(xpd, card_pcm_recompute)(xpd->xbus, xpd, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -730,7 +753,7 @@ void hookstate_changed(xpd_t *xpd, int pos, bool to_offhook)
|
||||
*
|
||||
* This bit will be cleared on the next tick.
|
||||
*/
|
||||
BIT_SET(xpd->silence_pcm, pos);
|
||||
BIT_SET(PHONEDEV(xpd).silence_pcm, pos);
|
||||
}
|
||||
notify_rxsig(xpd, pos, (to_offhook) ? DAHDI_RXSIG_OFFHOOK : DAHDI_RXSIG_ONHOOK);
|
||||
}
|
||||
@@ -879,13 +902,13 @@ int xpp_open(struct dahdi_chan *chan)
|
||||
return -ENODEV;
|
||||
}
|
||||
spin_lock_irqsave(&xbus->lock, flags);
|
||||
atomic_inc(&xpd->open_counter);
|
||||
atomic_inc(&PHONEDEV(xpd).open_counter);
|
||||
LINE_DBG(DEVICES, xpd, pos, "%s[%d]: open_counter=%d\n",
|
||||
current->comm, current->pid,
|
||||
atomic_read(&xpd->open_counter));
|
||||
atomic_read(&PHONEDEV(xpd).open_counter));
|
||||
spin_unlock_irqrestore(&xbus->lock, flags);
|
||||
if(xpd->xops->card_open)
|
||||
xpd->xops->card_open(xpd, pos);
|
||||
if(PHONE_METHOD(xpd, card_open))
|
||||
PHONE_METHOD(xpd, card_open)(xpd, pos);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -898,12 +921,12 @@ int xpp_close(struct dahdi_chan *chan)
|
||||
|
||||
spin_lock_irqsave(&xbus->lock, flags);
|
||||
spin_unlock_irqrestore(&xbus->lock, flags);
|
||||
if(xpd->xops->card_close)
|
||||
xpd->xops->card_close(xpd, pos);
|
||||
if(PHONE_METHOD(xpd, card_close))
|
||||
PHONE_METHOD(xpd, card_close)(xpd, pos);
|
||||
LINE_DBG(DEVICES, xpd, pos, "%s[%d]: open_counter=%d\n",
|
||||
current->comm, current->pid,
|
||||
atomic_read(&xpd->open_counter));
|
||||
atomic_dec(&xpd->open_counter); /* from xpp_open() */
|
||||
atomic_read(&PHONEDEV(xpd).open_counter));
|
||||
atomic_dec(&PHONEDEV(xpd).open_counter); /* from xpp_open() */
|
||||
put_xpd(__FUNCTION__, xpd); /* from xpp_open() */
|
||||
return 0;
|
||||
}
|
||||
@@ -935,8 +958,8 @@ int xpp_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long arg)
|
||||
switch (cmd) {
|
||||
default:
|
||||
/* Some span-specific commands before we give up: */
|
||||
if (xpd->xops->card_ioctl != NULL) {
|
||||
return xpd->xops->card_ioctl(xpd, pos, cmd, arg);
|
||||
if (PHONE_METHOD(xpd, card_ioctl)) {
|
||||
return PHONE_METHOD(xpd, card_ioctl)(xpd, pos, cmd, arg);
|
||||
}
|
||||
report_bad_ioctl(THIS_MODULE->name, xpd, pos, cmd);
|
||||
return -ENOTTY;
|
||||
@@ -955,7 +978,7 @@ int xpp_hooksig(struct dahdi_chan *chan, enum dahdi_txsig txsig)
|
||||
__FUNCTION__, pos);
|
||||
return -ENODEV;
|
||||
}
|
||||
if(!xpd->xops->card_hooksig) {
|
||||
if(!PHONE_METHOD(xpd, card_hooksig)) {
|
||||
LINE_ERR(xpd, pos,
|
||||
"%s: No hooksig method for this channel. Ignore.\n",
|
||||
__FUNCTION__);
|
||||
@@ -964,7 +987,7 @@ int xpp_hooksig(struct dahdi_chan *chan, enum dahdi_txsig txsig)
|
||||
xbus = xpd->xbus;
|
||||
BUG_ON(!xbus);
|
||||
DBG(SIGNAL, "Setting %s to %s (%d)\n", chan->name, txsig2str(txsig), txsig);
|
||||
return CALL_XMETHOD(card_hooksig, xbus, xpd, pos, txsig);
|
||||
return PHONE_METHOD(xpd, card_hooksig)(xbus, xpd, pos, txsig);
|
||||
}
|
||||
EXPORT_SYMBOL(xpp_hooksig);
|
||||
|
||||
@@ -975,7 +998,8 @@ int xpp_setchunksize(struct dahdi_span *span, int chunksize);
|
||||
/* Enable maintenance modes */
|
||||
int xpp_maint(struct dahdi_span *span, int cmd)
|
||||
{
|
||||
xpd_t *xpd = container_of(span, struct xpd, span);
|
||||
struct phonedev *phonedev = container_of(span, struct phonedev, span);
|
||||
xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
|
||||
int ret = 0;
|
||||
#if 0
|
||||
char loopback_data[] = "THE-QUICK-BROWN-FOX-JUMPED-OVER-THE-LAZY-DOG";
|
||||
@@ -1049,20 +1073,20 @@ int dahdi_unregister_xpd(xpd_t *xpd)
|
||||
}
|
||||
update_xpd_status(xpd, DAHDI_ALARM_NOTOPEN);
|
||||
/* We should now have only a ref from the xbus (from create_xpd()) */
|
||||
if(atomic_read(&xpd->open_counter)) {
|
||||
XPD_NOTICE(xpd, "Busy (open_counter=%d). Skipping.\n", atomic_read(&xpd->open_counter));
|
||||
if(atomic_read(&PHONEDEV(xpd).open_counter)) {
|
||||
XPD_NOTICE(xpd, "Busy (open_counter=%d). Skipping.\n", atomic_read(&PHONEDEV(xpd).open_counter));
|
||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
mdelay(2); // FIXME: This is to give chance for transmit/receiveprep to finish.
|
||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||
if(xpd->card_present)
|
||||
xpd->xops->card_dahdi_preregistration(xpd, 0);
|
||||
atomic_dec(&xpd->dahdi_registered);
|
||||
PHONE_METHOD(xpd, card_dahdi_preregistration)(xpd, 0);
|
||||
atomic_dec(&PHONEDEV(xpd).dahdi_registered);
|
||||
atomic_dec(&num_registered_spans);
|
||||
dahdi_unregister(&xpd->span);
|
||||
dahdi_unregister(&PHONEDEV(xpd).span);
|
||||
if(xpd->card_present)
|
||||
xpd->xops->card_dahdi_postregistration(xpd, 0);
|
||||
PHONE_METHOD(xpd, card_dahdi_postregistration)(xpd, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1089,32 +1113,30 @@ int dahdi_register_xpd(xpd_t *xpd)
|
||||
xbus_t *xbus;
|
||||
int cn;
|
||||
int i;
|
||||
const xops_t *xops;
|
||||
|
||||
BUG_ON(!xpd);
|
||||
|
||||
xops = xpd->xops;
|
||||
xbus = xpd->xbus;
|
||||
|
||||
if (SPAN_REGISTERED(xpd)) {
|
||||
XPD_ERR(xpd, "Already registered\n");
|
||||
return -EEXIST;
|
||||
}
|
||||
cn = xpd->channels;
|
||||
cn = PHONEDEV(xpd).channels;
|
||||
XPD_DBG(DEVICES, xpd, "Initializing span: %d channels.\n", cn);
|
||||
memset(&xpd->span, 0, sizeof(struct dahdi_span));
|
||||
memset(&PHONEDEV(xpd).span, 0, sizeof(struct dahdi_span));
|
||||
for(i = 0; i < cn; i++) {
|
||||
memset(XPD_CHAN(xpd, i), 0, sizeof(struct dahdi_chan));
|
||||
}
|
||||
|
||||
span = &xpd->span;
|
||||
span = &PHONEDEV(xpd).span;
|
||||
snprintf(span->name, MAX_SPANNAME, "%s/%s", xbus->busname, xpd->xpdname);
|
||||
span->deflaw = DAHDI_LAW_MULAW; /* default, may be overriden by card_* drivers */
|
||||
span->channels = cn;
|
||||
span->chans = xpd->chans;
|
||||
span->chans = PHONEDEV(xpd).chans;
|
||||
|
||||
span->flags = DAHDI_FLAG_RBS;
|
||||
if(xops->card_hooksig)
|
||||
if(PHONEDEV(xpd).phoneops->card_hooksig)
|
||||
span->ops = &xpp_rbs_span_ops; /* Only with RBS bits */
|
||||
else
|
||||
span->ops = &xpp_span_ops;
|
||||
@@ -1152,17 +1174,17 @@ int dahdi_register_xpd(xpd_t *xpd)
|
||||
*/
|
||||
span->irq = 0;
|
||||
|
||||
snprintf(xpd->span.desc, MAX_SPANDESC, "Xorcom XPD #%02d/%1d%1d: %s",
|
||||
snprintf(PHONEDEV(xpd).span.desc, MAX_SPANDESC, "Xorcom XPD #%02d/%1d%1d: %s",
|
||||
xbus->num, xpd->addr.unit, xpd->addr.subunit, xpd->type_name);
|
||||
XPD_DBG(GENERAL, xpd, "Registering span '%s'\n", xpd->span.desc);
|
||||
xpd->xops->card_dahdi_preregistration(xpd, 1);
|
||||
if(dahdi_register(&xpd->span, prefmaster)) {
|
||||
XPD_DBG(GENERAL, xpd, "Registering span '%s'\n", PHONEDEV(xpd).span.desc);
|
||||
PHONE_METHOD(xpd, card_dahdi_preregistration)(xpd, 1);
|
||||
if(dahdi_register(&PHONEDEV(xpd).span, prefmaster)) {
|
||||
XPD_ERR(xpd, "Failed to dahdi_register span\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
atomic_inc(&num_registered_spans);
|
||||
atomic_inc(&xpd->dahdi_registered);
|
||||
xpd->xops->card_dahdi_postregistration(xpd, 1);
|
||||
atomic_inc(&PHONEDEV(xpd).dahdi_registered);
|
||||
PHONE_METHOD(xpd, card_dahdi_postregistration)(xpd, 1);
|
||||
/*
|
||||
* Update dahdi about our state:
|
||||
* - Since asterisk didn't open the channel yet,
|
||||
|
||||
@@ -45,7 +45,7 @@ void report_bad_ioctl(const char *msg, xpd_t *xpd, int pos, unsigned int cmd);
|
||||
int total_registered_spans(void);
|
||||
void oht_pcm(xpd_t *xpd, int pos, bool pass);
|
||||
void mark_offhook(xpd_t *xpd, int pos, bool to_offhook);
|
||||
#define IS_OFFHOOK(xpd,pos) IS_SET((xpd)->offhook_state, (pos))
|
||||
#define IS_OFFHOOK(xpd,pos) IS_SET((xpd)->phonedev.offhook_state, (pos))
|
||||
void notify_rxsig(xpd_t *xpd, int pos, enum dahdi_rxsig rxsig);
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
@@ -54,6 +54,6 @@ void notify_rxsig(xpd_t *xpd, int pos, enum dahdi_rxsig rxsig);
|
||||
extern struct proc_dir_entry *xpp_proc_toplevel;
|
||||
#endif
|
||||
|
||||
#define SPAN_REGISTERED(xpd) atomic_read(&(xpd)->dahdi_registered)
|
||||
#define SPAN_REGISTERED(xpd) atomic_read(&PHONEDEV(xpd).dahdi_registered)
|
||||
|
||||
#endif /* XPP_DAHDI_H */
|
||||
|
||||
@@ -414,7 +414,7 @@ const char *xproto_name(xpd_type_t xpd_type)
|
||||
return proto_table->name;
|
||||
}
|
||||
|
||||
#define CHECK_XOP(f) \
|
||||
#define CHECK_XOP(xops, f) \
|
||||
if(!(xops)->f) { \
|
||||
ERR("%s: missing xmethod %s [%s (%d)]\n", __FUNCTION__, #f, name, type); \
|
||||
return -EINVAL; \
|
||||
@@ -422,9 +422,9 @@ const char *xproto_name(xpd_type_t xpd_type)
|
||||
|
||||
int xproto_register(const xproto_table_t *proto_table)
|
||||
{
|
||||
int type;
|
||||
const char *name;
|
||||
const xops_t *xops;
|
||||
int type;
|
||||
const char *name;
|
||||
const struct xops *xops;
|
||||
|
||||
BUG_ON(!proto_table);
|
||||
type = proto_table->type;
|
||||
@@ -436,11 +436,13 @@ int xproto_register(const xproto_table_t *proto_table)
|
||||
DBG(GENERAL, "%s (%d)\n", name, type);
|
||||
if(xprotocol_tables[type])
|
||||
NOTICE("%s: overriding registration of %s (%d)\n", __FUNCTION__, name, type);
|
||||
xops = &proto_table->xops;
|
||||
CHECK_XOP(card_new);
|
||||
CHECK_XOP(card_init);
|
||||
CHECK_XOP(card_remove);
|
||||
CHECK_XOP(card_tick);
|
||||
xops = proto_table->xops;
|
||||
CHECK_XOP(xops, card_new);
|
||||
CHECK_XOP(xops, card_init);
|
||||
CHECK_XOP(xops, card_remove);
|
||||
CHECK_XOP(xops, card_tick);
|
||||
#if 0
|
||||
/* FIXME: check PHONE_METHOD() */
|
||||
CHECK_XOP(card_pcm_recompute);
|
||||
CHECK_XOP(card_pcm_fromspan);
|
||||
CHECK_XOP(card_pcm_tospan);
|
||||
@@ -449,6 +451,7 @@ int xproto_register(const xproto_table_t *proto_table)
|
||||
// CHECK_XOP(card_ioctl); // optional method -- call after testing
|
||||
CHECK_XOP(card_register_reply);
|
||||
CHECK_XOP(XPD_STATE);
|
||||
#endif
|
||||
|
||||
xprotocol_tables[type] = proto_table;
|
||||
return 0;
|
||||
|
||||
@@ -216,13 +216,9 @@ xproto_handler_t xproto_global_handler(byte opcode);
|
||||
#define CALL_XMETHOD(name, xbus, xpd, ...) \
|
||||
(xpd)->xops->name(xbus, xpd, ## __VA_ARGS__ )
|
||||
|
||||
struct xops {
|
||||
xpd_t *(*card_new)(xbus_t *xbus, int unit, int subunit,
|
||||
const xproto_table_t *proto_table, byte subtype,
|
||||
int subunits, int subunit_ports, bool to_phone);
|
||||
int (*card_init)(xbus_t *xbus, xpd_t *xpd);
|
||||
int (*card_remove)(xbus_t *xbus, xpd_t *xpd);
|
||||
int (*card_tick)(xbus_t *xbus, xpd_t *xpd);
|
||||
#define PHONE_METHOD(xpd, name) PHONEDEV(xpd).phoneops->name
|
||||
|
||||
struct phoneops {
|
||||
void (*card_pcm_recompute)(xbus_t *xbus, xpd_t *xpd, xpp_line_t pcm_mask);
|
||||
void (*card_pcm_fromspan)(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack);
|
||||
void (*card_pcm_tospan)(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack);
|
||||
@@ -233,11 +229,20 @@ struct xops {
|
||||
int (*card_ioctl)(xpd_t *xpd, int pos, unsigned int cmd, unsigned long arg);
|
||||
int (*card_open)(xpd_t *xpd, lineno_t pos);
|
||||
int (*card_close)(xpd_t *xpd, lineno_t pos);
|
||||
int (*card_register_reply)(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *reg);
|
||||
|
||||
int (*XPD_STATE)(xbus_t *xbus, xpd_t *xpd, bool on);
|
||||
};
|
||||
|
||||
struct xops {
|
||||
xpd_t *(*card_new)(xbus_t *xbus, int unit, int subunit,
|
||||
const xproto_table_t *proto_table, byte subtype,
|
||||
int subunits, int subunit_ports, bool to_phone);
|
||||
int (*card_init)(xbus_t *xbus, xpd_t *xpd);
|
||||
int (*card_remove)(xbus_t *xbus, xpd_t *xpd);
|
||||
int (*card_tick)(xbus_t *xbus, xpd_t *xpd);
|
||||
int (*card_register_reply)(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *reg);
|
||||
};
|
||||
|
||||
struct xproto_entry {
|
||||
xproto_handler_t handler;
|
||||
int datalen;
|
||||
@@ -246,9 +251,11 @@ struct xproto_entry {
|
||||
};
|
||||
|
||||
struct xproto_table {
|
||||
struct module *owner;
|
||||
xproto_entry_t entries[256]; /* Indexed by opcode */
|
||||
xops_t xops;
|
||||
struct module *owner;
|
||||
xproto_entry_t entries[256]; /* Indexed by opcode */
|
||||
const struct xops *xops; /* Card level operations */
|
||||
const struct phoneops *phoneops; /* DAHDI operations */
|
||||
//const struct echoops *echo;
|
||||
xpd_type_t type;
|
||||
byte ports_per_subunit;
|
||||
const char *name;
|
||||
|
||||
Reference in New Issue
Block a user