xpp: style - Run Lindent
* Here it is: KERNEL_STYLE="-npro -kr -i8 -ts8 -sob -l80 -ss -ncs -cp1" TYPEDEFS=' -T gfp_t -T __user -T u_char -T __u8 -T byte -T bool -T charp -T xusb_t -T xbus_t -T xpd_t -T xproto_table_t -T xproto_entry_t -T xframe_t -T xpacket_t -T reg_cmd_t ' indent $TYPEDEFS $KERNEL_STYLE \ --ignore-newlines \ --indent-label0 \ --no-space-after-function-call-names \ "$@" Signed-off-by: Oron Peled <oron.peled@xorcom.com> Acked-By: Tzafrir Cohen <tzafrir.cohen@xorcom.com> git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10428 a0bf4364-ded3-4de4-8d8a-66a801d63aff
This commit is contained in:
parent
97ad9f8d03
commit
a2a695c742
@ -40,8 +40,10 @@ static const char rcsid[] = "$Id$";
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static DEF_PARM(int, debug, 0, 0644, "Print DBG statements"); /* must be before dahdi_debug.h */
|
static DEF_PARM(int, debug, 0, 0644, "Print DBG statements"); /* must be before dahdi_debug.h */
|
||||||
static DEF_PARM(uint, poll_interval, 500, 0644, "Poll channel state interval in milliseconds (0 - disable)");
|
static DEF_PARM(uint, poll_interval, 500, 0644,
|
||||||
static DEF_PARM_BOOL(nt_keepalive, 1, 0644, "Force BRI_NT to keep trying connection");
|
"Poll channel state interval in milliseconds (0 - disable)");
|
||||||
|
static DEF_PARM_BOOL(nt_keepalive, 1, 0644,
|
||||||
|
"Force BRI_NT to keep trying connection");
|
||||||
|
|
||||||
enum xhfc_states {
|
enum xhfc_states {
|
||||||
ST_RESET = 0, /* G/F0 */
|
ST_RESET = 0, /* G/F0 */
|
||||||
@ -149,7 +151,8 @@ static int write_state_register(xpd_t *xpd, __u8 value);
|
|||||||
static bool bri_packet_is_valid(xpacket_t *pack);
|
static bool bri_packet_is_valid(xpacket_t *pack);
|
||||||
static void bri_packet_dump(const char *msg, xpacket_t *pack);
|
static void bri_packet_dump(const char *msg, xpacket_t *pack);
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
static int proc_bri_info_read(char *page, char **start, off_t off, int count, int *eof, void *data);
|
static int proc_bri_info_read(char *page, char **start, off_t off, int count,
|
||||||
|
int *eof, void *data);
|
||||||
#endif
|
#endif
|
||||||
static int bri_spanconfig(struct file *file, struct dahdi_span *span,
|
static int bri_spanconfig(struct file *file, struct dahdi_span *span,
|
||||||
struct dahdi_lineconfig *lc);
|
struct dahdi_lineconfig *lc);
|
||||||
@ -180,7 +183,6 @@ enum bri_led_names {
|
|||||||
#define NUM_LEDS 2
|
#define NUM_LEDS 2
|
||||||
#define LED_TICKS 100
|
#define LED_TICKS 100
|
||||||
|
|
||||||
|
|
||||||
struct bri_leds {
|
struct bri_leds {
|
||||||
__u8 state:2;
|
__u8 state:2;
|
||||||
__u8 led_sel:1; /* 0 - GREEN, 1 - RED */
|
__u8 led_sel:1; /* 0 - GREEN, 1 - RED */
|
||||||
@ -224,12 +226,11 @@ struct BRI_priv_data {
|
|||||||
|
|
||||||
static xproto_table_t PROTO_TABLE(BRI);
|
static xproto_table_t PROTO_TABLE(BRI);
|
||||||
|
|
||||||
|
|
||||||
DEF_RPACKET_DATA(BRI, SET_LED, /* Set one of the LED's */
|
DEF_RPACKET_DATA(BRI, SET_LED, /* Set one of the LED's */
|
||||||
struct bri_leds bri_leds;
|
struct bri_leds bri_leds;);
|
||||||
);
|
|
||||||
|
|
||||||
static /* 0x33 */ DECLARE_CMD(BRI, SET_LED, enum bri_led_names which_led, enum led_state to_led_state);
|
static /* 0x33 */ DECLARE_CMD(BRI, SET_LED, enum bri_led_names which_led,
|
||||||
|
enum led_state to_led_state);
|
||||||
|
|
||||||
#define DO_LED(xpd, which, tostate) \
|
#define DO_LED(xpd, which, tostate) \
|
||||||
CALL_PROTO(BRI, SET_LED, (xpd)->xbus, (xpd), (which), (tostate))
|
CALL_PROTO(BRI, SET_LED, (xpd)->xbus, (xpd), (which), (tostate))
|
||||||
@ -243,7 +244,8 @@ static void dump_hex_buf(xpd_t *xpd, char *msg, __u8 *buf, size_t len)
|
|||||||
|
|
||||||
debug_buf[0] = '\0';
|
debug_buf[0] = '\0';
|
||||||
for (i = 0; i < len && n < DEBUG_BUF_SIZE; i++)
|
for (i = 0; i < len && n < DEBUG_BUF_SIZE; i++)
|
||||||
n += snprintf(&debug_buf[n], DEBUG_BUF_SIZE - n, "%02X ", buf[i]);
|
n += snprintf(&debug_buf[n], DEBUG_BUF_SIZE - n, "%02X ",
|
||||||
|
buf[i]);
|
||||||
XPD_NOTICE(xpd, "%s[0..%zd]: %s%s\n", msg, len - 1, debug_buf,
|
XPD_NOTICE(xpd, "%s[0..%zd]: %s%s\n", msg, len - 1, debug_buf,
|
||||||
(n >= DEBUG_BUF_SIZE) ? "..." : "");
|
(n >= DEBUG_BUF_SIZE) ? "..." : "");
|
||||||
}
|
}
|
||||||
@ -275,14 +277,16 @@ static void dump_dchan_packet(xpd_t *xpd, bool transmit, __u8 *buf, int len)
|
|||||||
else
|
else
|
||||||
XPD_NOTICE(xpd, "Unknown frame type 0x%X\n", buf[0]);
|
XPD_NOTICE(xpd, "Unknown frame type 0x%X\n", buf[0]);
|
||||||
|
|
||||||
snprintf(msgbuf, MAX_PROC_WRITE, "D-Chan %s = (%c) ", direction, ftype);
|
snprintf(msgbuf, MAX_PROC_WRITE, "D-Chan %s = (%c) ", direction,
|
||||||
|
ftype);
|
||||||
} else {
|
} else {
|
||||||
snprintf(msgbuf, MAX_PROC_WRITE, "D-Chan %s = ", direction);
|
snprintf(msgbuf, MAX_PROC_WRITE, "D-Chan %s = ", direction);
|
||||||
}
|
}
|
||||||
dump_hex_buf(xpd, msgbuf, buf, len);
|
dump_hex_buf(xpd, msgbuf, buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_bri_timer(xpd_t *xpd, const char *name, int *bri_timer, int value)
|
static void set_bri_timer(xpd_t *xpd, const char *name, int *bri_timer,
|
||||||
|
int value)
|
||||||
{
|
{
|
||||||
if (value == HFC_TIMER_OFF)
|
if (value == HFC_TIMER_OFF)
|
||||||
XPD_DBG(SIGNAL, xpd, "Timer %s DISABLE\n", name);
|
XPD_DBG(SIGNAL, xpd, "Timer %s DISABLE\n", name);
|
||||||
@ -305,7 +309,8 @@ static void dchan_state(xpd_t *xpd, bool up)
|
|||||||
priv->dchan_alive = 1;
|
priv->dchan_alive = 1;
|
||||||
} else {
|
} else {
|
||||||
XPD_DBG(SIGNAL, xpd, "STATE CHANGE: D-Channel STOPPED\n");
|
XPD_DBG(SIGNAL, xpd, "STATE CHANGE: D-Channel STOPPED\n");
|
||||||
priv->dchan_rx_counter = priv->dchan_tx_counter = priv->dchan_rx_drops = 0;
|
priv->dchan_rx_counter = priv->dchan_tx_counter =
|
||||||
|
priv->dchan_rx_drops = 0;
|
||||||
priv->dchan_alive = 0;
|
priv->dchan_alive = 0;
|
||||||
priv->dchan_alive_ticks = 0;
|
priv->dchan_alive_ticks = 0;
|
||||||
}
|
}
|
||||||
@ -417,11 +422,11 @@ static void nt_activation(xpd_t *xpd, bool on)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* D-Chan receive
|
* D-Chan receive
|
||||||
*/
|
*/
|
||||||
static int bri_check_stat(xpd_t *xpd, struct dahdi_chan *dchan, __u8 *buf, int len)
|
static int bri_check_stat(xpd_t *xpd, struct dahdi_chan *dchan, __u8 *buf,
|
||||||
|
int len)
|
||||||
{
|
{
|
||||||
struct BRI_priv_data *priv;
|
struct BRI_priv_data *priv;
|
||||||
__u8 status;
|
__u8 status;
|
||||||
@ -522,7 +527,8 @@ static int send_dchan_frame(xpd_t *xpd, xframe_t *xframe, bool is_eof)
|
|||||||
priv = xpd->priv;
|
priv = xpd->priv;
|
||||||
if (!test_bit(HFC_L1_ACTIVATED, &priv->l1_flags)
|
if (!test_bit(HFC_L1_ACTIVATED, &priv->l1_flags)
|
||||||
&& !test_bit(HFC_L1_ACTIVATING, &priv->l1_flags)) {
|
&& !test_bit(HFC_L1_ACTIVATING, &priv->l1_flags)) {
|
||||||
XPD_DBG(SIGNAL, xpd, "Want to transmit: Kick D-Channel transmiter\n");
|
XPD_DBG(SIGNAL, xpd,
|
||||||
|
"Want to transmit: Kick D-Channel transmiter\n");
|
||||||
if (!IS_NT(xpd))
|
if (!IS_NT(xpd))
|
||||||
te_activation(xpd, 1);
|
te_activation(xpd, 1);
|
||||||
else
|
else
|
||||||
@ -545,8 +551,8 @@ static int send_dchan_frame(xpd_t *xpd, xframe_t *xframe, bool is_eof)
|
|||||||
/*
|
/*
|
||||||
* Fill a single multibyte REGISTER_REQUEST
|
* Fill a single multibyte REGISTER_REQUEST
|
||||||
*/
|
*/
|
||||||
static void fill_multibyte(xpd_t *xpd, xpacket_t *pack, bool eoframe,
|
static void fill_multibyte(xpd_t *xpd, xpacket_t *pack, bool eoframe, char *buf,
|
||||||
char *buf, int len)
|
int len)
|
||||||
{
|
{
|
||||||
reg_cmd_t *reg_cmd;
|
reg_cmd_t *reg_cmd;
|
||||||
char *p;
|
char *p;
|
||||||
@ -587,8 +593,8 @@ static int tx_dchan(xpd_t *xpd)
|
|||||||
BUG_ON(!priv);
|
BUG_ON(!priv);
|
||||||
if (atomic_read(&priv->hdlc_pending) == 0)
|
if (atomic_read(&priv->hdlc_pending) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
if (!SPAN_REGISTERED(xpd) ||
|
if (!SPAN_REGISTERED(xpd)
|
||||||
!(PHONEDEV(xpd).span.flags & DAHDI_FLAG_RUNNING))
|
|| !(PHONEDEV(xpd).span.flags & DAHDI_FLAG_RUNNING))
|
||||||
return 0;
|
return 0;
|
||||||
/* Allocate frame */
|
/* Allocate frame */
|
||||||
xframe = ALLOC_SEND_XFRAME(xpd->xbus);
|
xframe = ALLOC_SEND_XFRAME(xpd->xbus);
|
||||||
@ -609,8 +615,7 @@ static int tx_dchan(xpd_t *xpd)
|
|||||||
/*
|
/*
|
||||||
* A split. Send what we currently have.
|
* A split. Send what we currently have.
|
||||||
*/
|
*/
|
||||||
XPD_NOTICE(xpd,
|
XPD_NOTICE(xpd, "%s: xframe is full (%d packets)\n",
|
||||||
"%s: xframe is full (%d packets)\n",
|
|
||||||
__func__, packet_count);
|
__func__, packet_count);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -661,9 +666,12 @@ static int bri_proc_create(xbus_t *xbus, xpd_t *xpd)
|
|||||||
XPD_DBG(PROC, xpd, "\n");
|
XPD_DBG(PROC, xpd, "\n");
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
XPD_DBG(PROC, xpd, "Creating '%s'\n", PROC_BRI_INFO_FNAME);
|
XPD_DBG(PROC, xpd, "Creating '%s'\n", PROC_BRI_INFO_FNAME);
|
||||||
priv->bri_info = create_proc_read_entry(PROC_BRI_INFO_FNAME, 0444, xpd->proc_xpd_dir, proc_bri_info_read, xpd);
|
priv->bri_info =
|
||||||
|
create_proc_read_entry(PROC_BRI_INFO_FNAME, 0444, xpd->proc_xpd_dir,
|
||||||
|
proc_bri_info_read, xpd);
|
||||||
if (!priv->bri_info) {
|
if (!priv->bri_info) {
|
||||||
XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_BRI_INFO_FNAME);
|
XPD_ERR(xpd, "Failed to create proc file '%s'\n",
|
||||||
|
PROC_BRI_INFO_FNAME);
|
||||||
bri_proc_remove(xbus, xpd);
|
bri_proc_remove(xbus, xpd);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@ -672,8 +680,9 @@ static int bri_proc_create(xbus_t *xbus, xpd_t *xpd)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static xpd_t *BRI_card_new(xbus_t *xbus, int unit, int subunit, const xproto_table_t *proto_table,
|
static xpd_t *BRI_card_new(xbus_t *xbus, int unit, int subunit,
|
||||||
__u8 subtype, int subunits, int subunit_ports, bool to_phone)
|
const xproto_table_t *proto_table, __u8 subtype,
|
||||||
|
int subunits, int subunit_ports, bool to_phone)
|
||||||
{
|
{
|
||||||
xpd_t *xpd = NULL;
|
xpd_t *xpd = NULL;
|
||||||
int channels = min(3, CHANNELS_PERXPD);
|
int channels = min(3, CHANNELS_PERXPD);
|
||||||
@ -683,7 +692,9 @@ static xpd_t *BRI_card_new(xbus_t *xbus, int unit, int subunit, const xproto_tab
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
XBUS_DBG(GENERAL, xbus, "\n");
|
XBUS_DBG(GENERAL, xbus, "\n");
|
||||||
xpd = xpd_alloc(xbus, unit, subunit, subtype, subunits, sizeof(struct BRI_priv_data), proto_table, channels);
|
xpd =
|
||||||
|
xpd_alloc(xbus, unit, subunit, subtype, subunits,
|
||||||
|
sizeof(struct BRI_priv_data), proto_table, channels);
|
||||||
if (!xpd)
|
if (!xpd)
|
||||||
return NULL;
|
return NULL;
|
||||||
PHONEDEV(xpd).direction = (to_phone) ? TO_PHONE : TO_PSTN;
|
PHONEDEV(xpd).direction = (to_phone) ? TO_PHONE : TO_PSTN;
|
||||||
@ -766,8 +777,8 @@ static int BRI_card_dahdi_preregistration(xpd_t *xpd, bool on)
|
|||||||
|
|
||||||
XPD_DBG(GENERAL, xpd, "setting BRI channel %d\n", i);
|
XPD_DBG(GENERAL, xpd, "setting BRI channel %d\n", i);
|
||||||
snprintf(cur_chan->name, MAX_CHANNAME, "XPP_%s/%02d/%1d%1d/%d",
|
snprintf(cur_chan->name, MAX_CHANNAME, "XPP_%s/%02d/%1d%1d/%d",
|
||||||
xpd->type_name, xbus->num,
|
xpd->type_name, xbus->num, xpd->addr.unit,
|
||||||
xpd->addr.unit, xpd->addr.subunit, i);
|
xpd->addr.subunit, i);
|
||||||
cur_chan->chanpos = i + 1;
|
cur_chan->chanpos = i + 1;
|
||||||
cur_chan->pvt = xpd;
|
cur_chan->pvt = xpd;
|
||||||
if (i == 2) { /* D-CHAN */
|
if (i == 2) { /* D-CHAN */
|
||||||
@ -879,16 +890,20 @@ static void handle_bri_timers(xpd_t *xpd)
|
|||||||
if (IS_NT(xpd)) {
|
if (IS_NT(xpd)) {
|
||||||
if (priv->t1 > HFC_TIMER_OFF) {
|
if (priv->t1 > HFC_TIMER_OFF) {
|
||||||
if (--priv->t1 == 0) {
|
if (--priv->t1 == 0) {
|
||||||
set_bri_timer(xpd, "T1", &priv->t1, HFC_TIMER_OFF);
|
set_bri_timer(xpd, "T1", &priv->t1,
|
||||||
|
HFC_TIMER_OFF);
|
||||||
if (!nt_keepalive) {
|
if (!nt_keepalive) {
|
||||||
if (priv->state_register.bits.v_su_sta == ST_NT_ACTIVATING) { /* G2 */
|
if (priv->state_register.bits.v_su_sta == ST_NT_ACTIVATING) { /* G2 */
|
||||||
XPD_DBG(SIGNAL, xpd, "T1 Expired. Deactivate NT\n");
|
XPD_DBG(SIGNAL, xpd,
|
||||||
clear_bit(HFC_L1_ACTIVATING, &priv->l1_flags);
|
"T1 Expired. Deactivate NT\n");
|
||||||
|
clear_bit(HFC_L1_ACTIVATING,
|
||||||
|
&priv->l1_flags);
|
||||||
nt_activation(xpd, 0); /* Deactivate NT */
|
nt_activation(xpd, 0); /* Deactivate NT */
|
||||||
} else
|
} else
|
||||||
XPD_DBG(SIGNAL, xpd,
|
XPD_DBG(SIGNAL, xpd,
|
||||||
"T1 Expired. (state %d, ignored)\n",
|
"T1 Expired. (state %d, ignored)\n",
|
||||||
priv->state_register.bits.v_su_sta);
|
priv->state_register.
|
||||||
|
bits.v_su_sta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -896,8 +911,10 @@ static void handle_bri_timers(xpd_t *xpd)
|
|||||||
if (priv->t3 > HFC_TIMER_OFF) {
|
if (priv->t3 > HFC_TIMER_OFF) {
|
||||||
/* timer expired ? */
|
/* timer expired ? */
|
||||||
if (--priv->t3 == 0) {
|
if (--priv->t3 == 0) {
|
||||||
XPD_DBG(SIGNAL, xpd, "T3 expired. Deactivate TE\n");
|
XPD_DBG(SIGNAL, xpd,
|
||||||
set_bri_timer(xpd, "T3", &priv->t3, HFC_TIMER_OFF);
|
"T3 expired. Deactivate TE\n");
|
||||||
|
set_bri_timer(xpd, "T3", &priv->t3,
|
||||||
|
HFC_TIMER_OFF);
|
||||||
clear_bit(HFC_L1_ACTIVATING, &priv->l1_flags);
|
clear_bit(HFC_L1_ACTIVATING, &priv->l1_flags);
|
||||||
te_activation(xpd, 0); /* Deactivate TE */
|
te_activation(xpd, 0); /* Deactivate TE */
|
||||||
}
|
}
|
||||||
@ -920,8 +937,7 @@ static int BRI_card_tick(xbus_t *xbus, xpd_t *xpd)
|
|||||||
if (poll_interval != 0 && (priv->tick_counter % poll_interval) == 0) {
|
if (poll_interval != 0 && (priv->tick_counter % poll_interval) == 0) {
|
||||||
// XPD_DBG(GENERAL, xpd, "%d\n", priv->tick_counter);
|
// XPD_DBG(GENERAL, xpd, "%d\n", priv->tick_counter);
|
||||||
priv->poll_counter++;
|
priv->poll_counter++;
|
||||||
xpp_register_request(xbus, xpd,
|
xpp_register_request(xbus, xpd, BRI_PORT(xpd), /* portno */
|
||||||
BRI_PORT(xpd), /* portno */
|
|
||||||
0, /* writing */
|
0, /* writing */
|
||||||
A_SU_RD_STA, /* regnum */
|
A_SU_RD_STA, /* regnum */
|
||||||
0, /* do_subreg */
|
0, /* do_subreg */
|
||||||
@ -932,9 +948,9 @@ static int BRI_card_tick(xbus_t *xbus, xpd_t *xpd)
|
|||||||
0 /* should_reply */
|
0 /* should_reply */
|
||||||
);
|
);
|
||||||
|
|
||||||
if (IS_NT(xpd) && nt_keepalive &&
|
if (IS_NT(xpd) && nt_keepalive
|
||||||
!test_bit(HFC_L1_ACTIVATED, &priv->l1_flags) &&
|
&& !test_bit(HFC_L1_ACTIVATED, &priv->l1_flags)
|
||||||
!test_bit(HFC_L1_ACTIVATING, &priv->l1_flags)) {
|
&& !test_bit(HFC_L1_ACTIVATING, &priv->l1_flags)) {
|
||||||
XPD_DBG(SIGNAL, xpd, "Kick NT D-Channel\n");
|
XPD_DBG(SIGNAL, xpd, "Kick NT D-Channel\n");
|
||||||
nt_activation(xpd, 1);
|
nt_activation(xpd, 1);
|
||||||
}
|
}
|
||||||
@ -943,7 +959,9 @@ static int BRI_card_tick(xbus_t *xbus, xpd_t *xpd)
|
|||||||
priv->dchan_notx_ticks++;
|
priv->dchan_notx_ticks++;
|
||||||
priv->dchan_norx_ticks++;
|
priv->dchan_norx_ticks++;
|
||||||
priv->dchan_alive_ticks++;
|
priv->dchan_alive_ticks++;
|
||||||
if (priv->dchan_alive && (priv->dchan_notx_ticks > DCHAN_LOST || priv->dchan_norx_ticks > DCHAN_LOST)) {
|
if (priv->dchan_alive
|
||||||
|
&& (priv->dchan_notx_ticks > DCHAN_LOST
|
||||||
|
|| priv->dchan_norx_ticks > DCHAN_LOST)) {
|
||||||
/*
|
/*
|
||||||
* No tx_dchan() or rx_dchan() for many ticks
|
* No tx_dchan() or rx_dchan() for many ticks
|
||||||
* This D-Channel is probabelly dead.
|
* This D-Channel is probabelly dead.
|
||||||
@ -956,7 +974,8 @@ static int BRI_card_tick(xbus_t *xbus, xpd_t *xpd)
|
|||||||
/* Detect Layer1 disconnect */
|
/* Detect Layer1 disconnect */
|
||||||
if (priv->reg30_good && priv->reg30_ticks > poll_interval * REG30_LOST) {
|
if (priv->reg30_good && priv->reg30_ticks > poll_interval * REG30_LOST) {
|
||||||
/* No reply for 1/2 a second */
|
/* No reply for 1/2 a second */
|
||||||
XPD_ERR(xpd, "Lost state tracking for %d ticks\n", priv->reg30_ticks);
|
XPD_ERR(xpd, "Lost state tracking for %d ticks\n",
|
||||||
|
priv->reg30_ticks);
|
||||||
priv->reg30_good = 0;
|
priv->reg30_good = 0;
|
||||||
layer1_state(xpd, 0);
|
layer1_state(xpd, 0);
|
||||||
}
|
}
|
||||||
@ -968,7 +987,8 @@ static int BRI_card_tick(xbus_t *xbus, xpd_t *xpd)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int BRI_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long arg)
|
static int BRI_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd,
|
||||||
|
unsigned long arg)
|
||||||
{
|
{
|
||||||
BUG_ON(!xpd);
|
BUG_ON(!xpd);
|
||||||
if (!XBUS_IS(xpd->xbus, READY))
|
if (!XBUS_IS(xpd->xbus, READY))
|
||||||
@ -1043,14 +1063,10 @@ static int bri_spanconfig(struct file *file, struct dahdi_span *span,
|
|||||||
/* E1's can enable CRC checking */
|
/* E1's can enable CRC checking */
|
||||||
if (lc->lineconfig & DAHDI_CONFIG_CRC4)
|
if (lc->lineconfig & DAHDI_CONFIG_CRC4)
|
||||||
crcstr = "CRC4";
|
crcstr = "CRC4";
|
||||||
XPD_DBG(GENERAL, xpd, "[%s]: span=%d (%s) lbo=%d lineconfig=%s/%s/%s (0x%X) sync=%d\n",
|
XPD_DBG(GENERAL, xpd,
|
||||||
IS_NT(xpd)?"NT":"TE",
|
"[%s]: span=%d (%s) lbo=%d lineconfig=%s/%s/%s (0x%X) sync=%d\n",
|
||||||
lc->span,
|
IS_NT(xpd) ? "NT" : "TE", lc->span, lc->name, lc->lbo,
|
||||||
lc->name,
|
framingstr, codingstr, crcstr, lc->lineconfig, lc->sync);
|
||||||
lc->lbo,
|
|
||||||
framingstr, codingstr, crcstr,
|
|
||||||
lc->lineconfig,
|
|
||||||
lc->sync);
|
|
||||||
PHONEDEV(xpd).timing_priority = lc->sync;
|
PHONEDEV(xpd).timing_priority = lc->sync;
|
||||||
elect_syncer("BRI-spanconfig");
|
elect_syncer("BRI-spanconfig");
|
||||||
/*
|
/*
|
||||||
@ -1068,7 +1084,8 @@ static int bri_spanconfig(struct file *file, struct dahdi_span *span,
|
|||||||
static int bri_chanconfig(struct file *file, struct dahdi_chan *chan,
|
static int bri_chanconfig(struct file *file, struct dahdi_chan *chan,
|
||||||
int sigtype)
|
int sigtype)
|
||||||
{
|
{
|
||||||
DBG(GENERAL, "channel %d (%s) -> %s\n", chan->channo, chan->name, sig2str(sigtype));
|
DBG(GENERAL, "channel %d (%s) -> %s\n", chan->channo, chan->name,
|
||||||
|
sig2str(sigtype));
|
||||||
// FIXME: sanity checks:
|
// FIXME: sanity checks:
|
||||||
// - should be supported (within the sigcap)
|
// - should be supported (within the sigcap)
|
||||||
// - should not replace fxs <->fxo ??? (covered by previous?)
|
// - should not replace fxs <->fxo ??? (covered by previous?)
|
||||||
@ -1089,7 +1106,8 @@ static int bri_startup(struct file *file, struct dahdi_span *span)
|
|||||||
priv = xpd->priv;
|
priv = xpd->priv;
|
||||||
BUG_ON(!priv);
|
BUG_ON(!priv);
|
||||||
if (!XBUS_IS(xpd->xbus, READY)) {
|
if (!XBUS_IS(xpd->xbus, READY)) {
|
||||||
XPD_DBG(GENERAL, xpd, "Startup called by dahdi. No Hardware. Ignored\n");
|
XPD_DBG(GENERAL, xpd,
|
||||||
|
"Startup called by dahdi. No Hardware. Ignored\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
XPD_DBG(GENERAL, xpd, "STARTUP\n");
|
XPD_DBG(GENERAL, xpd, "STARTUP\n");
|
||||||
@ -1122,7 +1140,8 @@ static int bri_shutdown(struct dahdi_span *span)
|
|||||||
priv = xpd->priv;
|
priv = xpd->priv;
|
||||||
BUG_ON(!priv);
|
BUG_ON(!priv);
|
||||||
if (!XBUS_IS(xpd->xbus, READY)) {
|
if (!XBUS_IS(xpd->xbus, READY)) {
|
||||||
XPD_DBG(GENERAL, xpd, "Shutdown called by dahdi. No Hardware. Ignored\n");
|
XPD_DBG(GENERAL, xpd,
|
||||||
|
"Shutdown called by dahdi. No Hardware. Ignored\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
XPD_DBG(GENERAL, xpd, "SHUTDOWN\n");
|
XPD_DBG(GENERAL, xpd, "SHUTDOWN\n");
|
||||||
@ -1131,8 +1150,7 @@ static int bri_shutdown(struct dahdi_span *span)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void BRI_card_pcm_recompute(xpd_t *xpd,
|
static void BRI_card_pcm_recompute(xpd_t *xpd, xpp_line_t dont_care)
|
||||||
xpp_line_t dont_care)
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int line_count;
|
int line_count;
|
||||||
@ -1144,7 +1162,8 @@ static void BRI_card_pcm_recompute(xpd_t *xpd,
|
|||||||
BUG_ON(!xpd);
|
BUG_ON(!xpd);
|
||||||
main_xpd = xpd_byaddr(xpd->xbus, xpd->addr.unit, 0);
|
main_xpd = xpd_byaddr(xpd->xbus, xpd->addr.unit, 0);
|
||||||
if (!main_xpd) {
|
if (!main_xpd) {
|
||||||
XPD_DBG(DEVICES, xpd, "Unit 0 is already gone. Ignore request\n");
|
XPD_DBG(DEVICES, xpd,
|
||||||
|
"Unit 0 is already gone. Ignore request\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -1159,7 +1178,9 @@ static void BRI_card_pcm_recompute(xpd_t *xpd,
|
|||||||
|
|
||||||
if (sub_xpd) {
|
if (sub_xpd) {
|
||||||
xpp_line_t lines =
|
xpp_line_t lines =
|
||||||
PHONEDEV(sub_xpd).offhook_state & ~(PHONEDEV(sub_xpd).digital_signalling);
|
PHONEDEV(sub_xpd).
|
||||||
|
offhook_state & ~(PHONEDEV(sub_xpd).
|
||||||
|
digital_signalling);
|
||||||
|
|
||||||
if (lines) {
|
if (lines) {
|
||||||
pcm_mask |= PCM_SHIFT(lines, i);
|
pcm_mask |= PCM_SHIFT(lines, i);
|
||||||
@ -1183,8 +1204,8 @@ static void BRI_card_pcm_recompute(xpd_t *xpd,
|
|||||||
* The main unit account for all subunits (pcm_len and wanted_pcm_mask).
|
* The main unit account for all subunits (pcm_len and wanted_pcm_mask).
|
||||||
*/
|
*/
|
||||||
pcm_len = (line_count)
|
pcm_len = (line_count)
|
||||||
? RPACKET_HEADERSIZE + sizeof(xpp_line_t) + line_count * DAHDI_CHUNKSIZE
|
? RPACKET_HEADERSIZE + sizeof(xpp_line_t) +
|
||||||
: 0L;
|
line_count * DAHDI_CHUNKSIZE : 0L;
|
||||||
update_wanted_pcm_mask(main_xpd, pcm_mask, pcm_len);
|
update_wanted_pcm_mask(main_xpd, pcm_mask, pcm_len);
|
||||||
spin_unlock_irqrestore(&PHONEDEV(main_xpd).lock_recompute_pcm, flags);
|
spin_unlock_irqrestore(&PHONEDEV(main_xpd).lock_recompute_pcm, flags);
|
||||||
}
|
}
|
||||||
@ -1198,7 +1219,6 @@ static void BRI_card_pcm_fromspan(xpd_t *xpd, xpacket_t *pack)
|
|||||||
xpp_line_t pcm_mask = 0;
|
xpp_line_t pcm_mask = 0;
|
||||||
xpp_line_t wanted_lines;
|
xpp_line_t wanted_lines;
|
||||||
|
|
||||||
|
|
||||||
BUG_ON(!xpd);
|
BUG_ON(!xpd);
|
||||||
BUG_ON(!pack);
|
BUG_ON(!pack);
|
||||||
pcm = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, pcm);
|
pcm = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, pcm);
|
||||||
@ -1219,12 +1239,16 @@ static void BRI_card_pcm_fromspan(xpd_t *xpd, xpacket_t *pack)
|
|||||||
int channo = chan->channo;
|
int channo = chan->channo;
|
||||||
|
|
||||||
if (pcmtx >= 0 && pcmtx_chan == channo)
|
if (pcmtx >= 0 && pcmtx_chan == channo)
|
||||||
memset((u_char *)pcm, pcmtx, DAHDI_CHUNKSIZE);
|
memset((u_char *)pcm, pcmtx,
|
||||||
|
DAHDI_CHUNKSIZE);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
memcpy((u_char *)pcm, chan->writechunk, DAHDI_CHUNKSIZE);
|
memcpy((u_char *)pcm,
|
||||||
|
chan->writechunk,
|
||||||
|
DAHDI_CHUNKSIZE);
|
||||||
} else
|
} else
|
||||||
memset((u_char *)pcm, 0x7F, DAHDI_CHUNKSIZE);
|
memset((u_char *)pcm, 0x7F,
|
||||||
|
DAHDI_CHUNKSIZE);
|
||||||
pcm += DAHDI_CHUNKSIZE;
|
pcm += DAHDI_CHUNKSIZE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1252,13 +1276,15 @@ static void BRI_card_pcm_tospan(xpd_t *xpd, xpacket_t *pack)
|
|||||||
return;
|
return;
|
||||||
pcm = RPACKET_FIELD(pack, GLOBAL, PCM_READ, pcm);
|
pcm = RPACKET_FIELD(pack, GLOBAL, PCM_READ, pcm);
|
||||||
pcm_mask = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines);
|
pcm_mask = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines);
|
||||||
for (subunit = 0; subunit < MAX_SUBUNIT; subunit++, pcm_mask >>= SUBUNIT_PCM_SHIFT) {
|
for (subunit = 0; subunit < MAX_SUBUNIT;
|
||||||
|
subunit++, pcm_mask >>= SUBUNIT_PCM_SHIFT) {
|
||||||
xpd_t *tmp_xpd;
|
xpd_t *tmp_xpd;
|
||||||
|
|
||||||
if (!pcm_mask)
|
if (!pcm_mask)
|
||||||
break; /* optimize */
|
break; /* optimize */
|
||||||
tmp_xpd = xpd_byaddr(xpd->xbus, xpd->addr.unit, subunit);
|
tmp_xpd = xpd_byaddr(xpd->xbus, xpd->addr.unit, subunit);
|
||||||
if (!tmp_xpd || !tmp_xpd->card_present || !SPAN_REGISTERED(tmp_xpd))
|
if (!tmp_xpd || !tmp_xpd->card_present
|
||||||
|
|| !SPAN_REGISTERED(tmp_xpd))
|
||||||
continue;
|
continue;
|
||||||
spin_lock_irqsave(&tmp_xpd->lock, flags);
|
spin_lock_irqsave(&tmp_xpd->lock, flags);
|
||||||
for (i = 0; i < 2; i++) {
|
for (i = 0; i < 2; i++) {
|
||||||
@ -1319,7 +1345,8 @@ static int BRI_echocancel_setmask(xpd_t *xpd, xpp_line_t ec_mask)
|
|||||||
|
|
||||||
/*---------------- BRI: HOST COMMANDS -------------------------------------*/
|
/*---------------- BRI: HOST COMMANDS -------------------------------------*/
|
||||||
|
|
||||||
static /* 0x33 */ HOSTCMD(BRI, SET_LED, enum bri_led_names which_led, enum led_state to_led_state)
|
static /* 0x33 */ HOSTCMD(BRI, SET_LED, enum bri_led_names which_led,
|
||||||
|
enum led_state to_led_state)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
xframe_t *xframe;
|
xframe_t *xframe;
|
||||||
@ -1330,8 +1357,7 @@ static /* 0x33 */ HOSTCMD(BRI, SET_LED, enum bri_led_names which_led, enum led_s
|
|||||||
BUG_ON(!xbus);
|
BUG_ON(!xbus);
|
||||||
priv = xpd->priv;
|
priv = xpd->priv;
|
||||||
BUG_ON(!priv);
|
BUG_ON(!priv);
|
||||||
XPD_DBG(LEDS, xpd, "%s -> %d\n",
|
XPD_DBG(LEDS, xpd, "%s -> %d\n", (which_led) ? "RED" : "GREEN",
|
||||||
(which_led)?"RED":"GREEN",
|
|
||||||
to_led_state);
|
to_led_state);
|
||||||
XFRAME_NEW_CMD(xframe, pack, xbus, BRI, SET_LED, xpd->xbus_idx);
|
XFRAME_NEW_CMD(xframe, pack, xbus, BRI, SET_LED, xpd->xbus_idx);
|
||||||
bri_leds = &RPACKET_FIELD(pack, BRI, SET_LED, bri_leds);
|
bri_leds = &RPACKET_FIELD(pack, BRI, SET_LED, bri_leds);
|
||||||
@ -1348,8 +1374,7 @@ static int write_state_register(xpd_t *xpd, __u8 value)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
XPD_DBG(REGS, xpd, "value = 0x%02X\n", value);
|
XPD_DBG(REGS, xpd, "value = 0x%02X\n", value);
|
||||||
ret = xpp_register_request(xpd->xbus, xpd,
|
ret = xpp_register_request(xpd->xbus, xpd, BRI_PORT(xpd), /* portno */
|
||||||
BRI_PORT(xpd), /* portno */
|
|
||||||
1, /* writing */
|
1, /* writing */
|
||||||
A_SU_WR_STA, /* regnum */
|
A_SU_WR_STA, /* regnum */
|
||||||
0, /* do_subreg */
|
0, /* do_subreg */
|
||||||
@ -1384,11 +1409,8 @@ static void su_new_state(xpd_t *xpd, __u8 reg_x30)
|
|||||||
if (priv->state_register.bits.v_su_sta == new_state.bits.v_su_sta)
|
if (priv->state_register.bits.v_su_sta == new_state.bits.v_su_sta)
|
||||||
return; /* same same */
|
return; /* same same */
|
||||||
XPD_DBG(SIGNAL, xpd, "%02X ---> %02X (info0=%d) (%s%i)\n",
|
XPD_DBG(SIGNAL, xpd, "%02X ---> %02X (info0=%d) (%s%i)\n",
|
||||||
priv->state_register.reg,
|
priv->state_register.reg, reg_x30, new_state.bits.v_su_info0,
|
||||||
reg_x30,
|
IS_NT(xpd) ? "G" : "F", new_state.bits.v_su_sta);
|
||||||
new_state.bits.v_su_info0,
|
|
||||||
IS_NT(xpd)?"G":"F",
|
|
||||||
new_state.bits.v_su_sta);
|
|
||||||
if (!IS_NT(xpd)) {
|
if (!IS_NT(xpd)) {
|
||||||
switch (new_state.bits.v_su_sta) {
|
switch (new_state.bits.v_su_sta) {
|
||||||
case ST_TE_DEACTIVATED: /* F3 */
|
case ST_TE_DEACTIVATED: /* F3 */
|
||||||
@ -1421,7 +1443,8 @@ static void su_new_state(xpd_t *xpd, __u8 reg_x30)
|
|||||||
layer1_state(xpd, 0);
|
layer1_state(xpd, 0);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
XPD_NOTICE(xpd, "Bad TE state: %d\n", new_state.bits.v_su_sta);
|
XPD_NOTICE(xpd, "Bad TE state: %d\n",
|
||||||
|
new_state.bits.v_su_sta);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1453,7 +1476,8 @@ static void su_new_state(xpd_t *xpd, __u8 reg_x30)
|
|||||||
layer1_state(xpd, 0);
|
layer1_state(xpd, 0);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
XPD_NOTICE(xpd, "Bad NT state: %d\n", new_state.bits.v_su_sta);
|
XPD_NOTICE(xpd, "Bad NT state: %d\n",
|
||||||
|
new_state.bits.v_su_sta);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1485,11 +1509,13 @@ static int BRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
|||||||
BUG_ON(!priv);
|
BUG_ON(!priv);
|
||||||
if (REG_FIELD(info, do_subreg)) {
|
if (REG_FIELD(info, do_subreg)) {
|
||||||
XPD_DBG(REGS, xpd, "RI %02X %02X %02X\n",
|
XPD_DBG(REGS, xpd, "RI %02X %02X %02X\n",
|
||||||
REG_FIELD(info, regnum), REG_FIELD(info, subreg), REG_FIELD(info, data_low));
|
REG_FIELD(info, regnum), REG_FIELD(info, subreg),
|
||||||
|
REG_FIELD(info, data_low));
|
||||||
} else {
|
} else {
|
||||||
if (REG_FIELD(info, regnum) != A_SU_RD_STA)
|
if (REG_FIELD(info, regnum) != A_SU_RD_STA)
|
||||||
XPD_DBG(REGS, xpd, "RD %02X %02X\n",
|
XPD_DBG(REGS, xpd, "RD %02X %02X\n",
|
||||||
REG_FIELD(info, regnum), REG_FIELD(info, data_low));
|
REG_FIELD(info, regnum), REG_FIELD(info,
|
||||||
|
data_low));
|
||||||
else
|
else
|
||||||
XPD_DBG(REGS, xpd, "Got SU_RD_STA=%02X\n",
|
XPD_DBG(REGS, xpd, "Got SU_RD_STA=%02X\n",
|
||||||
REG_FIELD(info, data_low));
|
REG_FIELD(info, data_low));
|
||||||
@ -1501,7 +1527,8 @@ static int BRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
|||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
priv->dchan_rx_drops++;
|
priv->dchan_rx_drops++;
|
||||||
if (atomic_read(&PHONEDEV(xpd).open_counter) > 0)
|
if (atomic_read(&PHONEDEV(xpd).open_counter) > 0)
|
||||||
XPD_NOTICE(xpd, "Multibyte Drop: errno=%d\n", ret);
|
XPD_NOTICE(xpd, "Multibyte Drop: errno=%d\n",
|
||||||
|
ret);
|
||||||
}
|
}
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
@ -1510,10 +1537,11 @@ static int BRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Update /proc info only if reply relate to the last slic read request */
|
/* Update /proc info only if reply relate to the last slic read request */
|
||||||
if (
|
if (REG_FIELD(&xpd->requested_reply, regnum) == REG_FIELD(info, regnum)
|
||||||
REG_FIELD(&xpd->requested_reply, regnum) == REG_FIELD(info, regnum) &&
|
&& REG_FIELD(&xpd->requested_reply, do_subreg) == REG_FIELD(info,
|
||||||
REG_FIELD(&xpd->requested_reply, do_subreg) == REG_FIELD(info, do_subreg) &&
|
do_subreg)
|
||||||
REG_FIELD(&xpd->requested_reply, subreg) == REG_FIELD(info, subreg)) {
|
&& REG_FIELD(&xpd->requested_reply, subreg) == REG_FIELD(info,
|
||||||
|
subreg)) {
|
||||||
xpd->last_reply = *info;
|
xpd->last_reply = *info;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1566,18 +1594,12 @@ static const struct phoneops bri_phoneops = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static xproto_table_t PROTO_TABLE(BRI) = {
|
static xproto_table_t PROTO_TABLE(BRI) = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,.entries = {
|
||||||
.entries = {
|
|
||||||
/* Table Card Opcode */
|
/* Table Card Opcode */
|
||||||
},
|
},.name = "BRI", /* protocol name */
|
||||||
.name = "BRI", /* protocol name */
|
.ports_per_subunit = 1,.type = XPD_TYPE_BRI,.xops =
|
||||||
.ports_per_subunit = 1,
|
&bri_xops,.phoneops = &bri_phoneops,.packet_is_valid =
|
||||||
.type = XPD_TYPE_BRI,
|
bri_packet_is_valid,.packet_dump = bri_packet_dump,};
|
||||||
.xops = &bri_xops,
|
|
||||||
.phoneops = &bri_phoneops,
|
|
||||||
.packet_is_valid = bri_packet_is_valid,
|
|
||||||
.packet_dump = bri_packet_dump,
|
|
||||||
};
|
|
||||||
|
|
||||||
static bool bri_packet_is_valid(xpacket_t *pack)
|
static bool bri_packet_is_valid(xpacket_t *pack)
|
||||||
{
|
{
|
||||||
@ -1591,10 +1613,12 @@ static void bri_packet_dump(const char *msg, xpacket_t *pack)
|
|||||||
{
|
{
|
||||||
DBG(GENERAL, "%s\n", msg);
|
DBG(GENERAL, "%s\n", msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*------------------------- REGISTER Handling --------------------------*/
|
/*------------------------- REGISTER Handling --------------------------*/
|
||||||
|
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
static int proc_bri_info_read(char *page, char **start, off_t off, int count, int *eof, void *data)
|
static int proc_bri_info_read(char *page, char **start, off_t off, int count,
|
||||||
|
int *eof, void *data)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
@ -1609,11 +1633,16 @@ static int proc_bri_info_read(char *page, char **start, off_t off, int count, in
|
|||||||
BUG_ON(!priv);
|
BUG_ON(!priv);
|
||||||
len += sprintf(page + len, "%05d Layer 1: ", priv->poll_counter);
|
len += sprintf(page + len, "%05d Layer 1: ", priv->poll_counter);
|
||||||
if (priv->reg30_good) {
|
if (priv->reg30_good) {
|
||||||
len += sprintf(page + len, "%-5s ", (priv->layer1_up) ? "UP" : "DOWN");
|
len +=
|
||||||
len += sprintf(page + len, "%c%d %-15s -- fr_sync=%d t2_exp=%d info0=%d g2_g3=%d\n",
|
sprintf(page + len, "%-5s ",
|
||||||
|
(priv->layer1_up) ? "UP" : "DOWN");
|
||||||
|
len +=
|
||||||
|
sprintf(page + len,
|
||||||
|
"%c%d %-15s -- fr_sync=%d t2_exp=%d info0=%d g2_g3=%d\n",
|
||||||
IS_NT(xpd) ? 'G' : 'F',
|
IS_NT(xpd) ? 'G' : 'F',
|
||||||
priv->state_register.bits.v_su_sta,
|
priv->state_register.bits.v_su_sta,
|
||||||
xhfc_state_name(IS_NT(xpd), priv->state_register.bits.v_su_sta),
|
xhfc_state_name(IS_NT(xpd),
|
||||||
|
priv->state_register.bits.v_su_sta),
|
||||||
priv->state_register.bits.v_su_fr_sync,
|
priv->state_register.bits.v_su_fr_sync,
|
||||||
priv->state_register.bits.v_su_t2_exp,
|
priv->state_register.bits.v_su_t2_exp,
|
||||||
priv->state_register.bits.v_su_info0,
|
priv->state_register.bits.v_su_info0,
|
||||||
@ -1626,20 +1655,33 @@ static int proc_bri_info_read(char *page, char **start, off_t off, int count, in
|
|||||||
len += sprintf(page + len, "T3 Timer: %d\n", priv->t3);
|
len += sprintf(page + len, "T3 Timer: %d\n", priv->t3);
|
||||||
}
|
}
|
||||||
len += sprintf(page + len, "Tick Counter: %d\n", priv->tick_counter);
|
len += sprintf(page + len, "Tick Counter: %d\n", priv->tick_counter);
|
||||||
len += sprintf(page + len, "Last Poll Reply: %d ticks ago\n", priv->reg30_ticks);
|
len +=
|
||||||
|
sprintf(page + len, "Last Poll Reply: %d ticks ago\n",
|
||||||
|
priv->reg30_ticks);
|
||||||
len += sprintf(page + len, "reg30_good=%d\n", priv->reg30_good);
|
len += sprintf(page + len, "reg30_good=%d\n", priv->reg30_good);
|
||||||
len += sprintf(page + len, "D-Channel: TX=[%5d] RX=[%5d] BAD=[%5d] ",
|
len +=
|
||||||
priv->dchan_tx_counter, priv->dchan_rx_counter, priv->dchan_rx_drops);
|
sprintf(page + len, "D-Channel: TX=[%5d] RX=[%5d] BAD=[%5d] ",
|
||||||
|
priv->dchan_tx_counter, priv->dchan_rx_counter,
|
||||||
|
priv->dchan_rx_drops);
|
||||||
if (priv->dchan_alive) {
|
if (priv->dchan_alive) {
|
||||||
len += sprintf(page + len, "(alive %d K-ticks)\n",
|
len +=
|
||||||
|
sprintf(page + len, "(alive %d K-ticks)\n",
|
||||||
priv->dchan_alive_ticks / 1000);
|
priv->dchan_alive_ticks / 1000);
|
||||||
} else {
|
} else {
|
||||||
len += sprintf(page + len, "(dead)\n");
|
len += sprintf(page + len, "(dead)\n");
|
||||||
}
|
}
|
||||||
len += sprintf(page + len, "dchan_notx_ticks: %d\n", priv->dchan_notx_ticks);
|
len +=
|
||||||
len += sprintf(page + len, "dchan_norx_ticks: %d\n", priv->dchan_norx_ticks);
|
sprintf(page + len, "dchan_notx_ticks: %d\n",
|
||||||
len += sprintf(page + len, "LED: %-10s = %d\n", "GREEN", priv->ledstate[GREEN_LED]);
|
priv->dchan_notx_ticks);
|
||||||
len += sprintf(page + len, "LED: %-10s = %d\n", "RED", priv->ledstate[RED_LED]);
|
len +=
|
||||||
|
sprintf(page + len, "dchan_norx_ticks: %d\n",
|
||||||
|
priv->dchan_norx_ticks);
|
||||||
|
len +=
|
||||||
|
sprintf(page + len, "LED: %-10s = %d\n", "GREEN",
|
||||||
|
priv->ledstate[GREEN_LED]);
|
||||||
|
len +=
|
||||||
|
sprintf(page + len, "LED: %-10s = %d\n", "RED",
|
||||||
|
priv->ledstate[RED_LED]);
|
||||||
len += sprintf(page + len, "\nDCHAN:\n");
|
len += sprintf(page + len, "\nDCHAN:\n");
|
||||||
len += sprintf(page + len, "\n");
|
len += sprintf(page + len, "\n");
|
||||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||||
@ -1662,8 +1704,8 @@ static int bri_xpd_probe(struct device *dev)
|
|||||||
xpd = dev_to_xpd(dev);
|
xpd = dev_to_xpd(dev);
|
||||||
/* Is it our device? */
|
/* Is it our device? */
|
||||||
if (xpd->type != XPD_TYPE_BRI) {
|
if (xpd->type != XPD_TYPE_BRI) {
|
||||||
XPD_ERR(xpd, "drop suggestion for %s (%d)\n",
|
XPD_ERR(xpd, "drop suggestion for %s (%d)\n", dev_name(dev),
|
||||||
dev_name(dev), xpd->type);
|
xpd->type);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
XPD_DBG(DEVICES, xpd, "SYSFS\n");
|
XPD_DBG(DEVICES, xpd, "SYSFS\n");
|
||||||
@ -1687,8 +1729,7 @@ static struct xpd_driver bri_driver = {
|
|||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
#endif
|
#endif
|
||||||
.probe = bri_xpd_probe,
|
.probe = bri_xpd_probe,
|
||||||
.remove = bri_xpd_remove
|
.remove = bri_xpd_remove}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init card_bri_startup(void)
|
static int __init card_bri_startup(void)
|
||||||
|
@ -42,14 +42,9 @@ static DEF_PARM(int, debug, 0, 0644, "Print DBG statements");
|
|||||||
static bool echo_packet_is_valid(xpacket_t *pack);
|
static bool echo_packet_is_valid(xpacket_t *pack);
|
||||||
static void echo_packet_dump(const char *msg, xpacket_t *pack);
|
static void echo_packet_dump(const char *msg, xpacket_t *pack);
|
||||||
|
|
||||||
DEF_RPACKET_DATA(ECHO, SET,
|
DEF_RPACKET_DATA(ECHO, SET, __u8 timeslots[ECHO_TIMESLOTS];);
|
||||||
__u8 timeslots[ECHO_TIMESLOTS];
|
|
||||||
);
|
|
||||||
|
|
||||||
DEF_RPACKET_DATA(ECHO, SET_REPLY,
|
DEF_RPACKET_DATA(ECHO, SET_REPLY, __u8 status; __u8 reserved;);
|
||||||
__u8 status;
|
|
||||||
__u8 reserved;
|
|
||||||
);
|
|
||||||
|
|
||||||
struct ECHO_priv_data {
|
struct ECHO_priv_data {
|
||||||
};
|
};
|
||||||
@ -70,7 +65,8 @@ static xpd_t *ECHO_card_new(xbus_t *xbus, int unit, int subunit,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
XBUS_DBG(GENERAL, xbus, "\n");
|
XBUS_DBG(GENERAL, xbus, "\n");
|
||||||
xpd = xpd_alloc(xbus, unit, subunit, subtype, subunits,
|
xpd =
|
||||||
|
xpd_alloc(xbus, unit, subunit, subtype, subunits,
|
||||||
sizeof(struct ECHO_priv_data), proto_table, channels);
|
sizeof(struct ECHO_priv_data), proto_table, channels);
|
||||||
if (!xpd)
|
if (!xpd)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -122,19 +118,16 @@ static int ECHO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
|||||||
static int rate_limit;
|
static int rate_limit;
|
||||||
|
|
||||||
if ((rate_limit++ % 1003) < 5)
|
if ((rate_limit++ % 1003) < 5)
|
||||||
notify_bad_xpd(__func__, xbus, addr,
|
notify_bad_xpd(__func__, xbus, addr, orig_xpd->xpdname);
|
||||||
orig_xpd->xpdname);
|
|
||||||
return -EPROTO;
|
return -EPROTO;
|
||||||
}
|
}
|
||||||
spin_lock_irqsave(&xpd->lock, flags);
|
spin_lock_irqsave(&xpd->lock, flags);
|
||||||
/* Update /proc info only if reply related to last reg read request */
|
/* Update /proc info only if reply related to last reg read request */
|
||||||
if (
|
if (REG_FIELD(&xpd->requested_reply, regnum) == REG_FIELD(info, regnum)
|
||||||
REG_FIELD(&xpd->requested_reply, regnum) ==
|
&& REG_FIELD(&xpd->requested_reply, do_subreg) == REG_FIELD(info,
|
||||||
REG_FIELD(info, regnum) &&
|
do_subreg)
|
||||||
REG_FIELD(&xpd->requested_reply, do_subreg) ==
|
&& REG_FIELD(&xpd->requested_reply, subreg) == REG_FIELD(info,
|
||||||
REG_FIELD(info, do_subreg) &&
|
subreg)) {
|
||||||
REG_FIELD(&xpd->requested_reply, subreg) ==
|
|
||||||
REG_FIELD(info, subreg)) {
|
|
||||||
xpd->last_reply = *info;
|
xpd->last_reply = *info;
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||||
@ -236,10 +229,9 @@ static void ECHO_ec_dump(xbus_t *xbus)
|
|||||||
"EC-DUMP[%03d]: "
|
"EC-DUMP[%03d]: "
|
||||||
"0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X "
|
"0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X "
|
||||||
"0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n",
|
"0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n",
|
||||||
i,
|
i, ts[i + 0], ts[i + 1], ts[i + 2], ts[i + 3],
|
||||||
ts[i+0], ts[i+1], ts[i+2], ts[i+3], ts[i+4], ts[i+5],
|
ts[i + 4], ts[i + 5], ts[i + 6], ts[i + 7], ts[i + 8],
|
||||||
ts[i+6], ts[i+7],
|
ts[i + 9], ts[i + 10], ts[i + 11], ts[i + 12],
|
||||||
ts[i+8], ts[i+9], ts[i+10], ts[i+11], ts[i+12],
|
|
||||||
ts[i + 13], ts[i + 14], ts[i + 15]
|
ts[i + 13], ts[i + 14], ts[i + 15]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -279,19 +271,12 @@ static const struct echoops echoops = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static xproto_table_t PROTO_TABLE(ECHO) = {
|
static xproto_table_t PROTO_TABLE(ECHO) = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,.entries = {
|
||||||
.entries = {
|
|
||||||
/* Table Card Opcode */
|
/* Table Card Opcode */
|
||||||
XENTRY(ECHO, ECHO, SET_REPLY),
|
XENTRY(ECHO, ECHO, SET_REPLY),},.name = "ECHO",.ports_per_subunit =
|
||||||
},
|
1,.type = XPD_TYPE_ECHO,.xops = &echo_xops,.echoops =
|
||||||
.name = "ECHO",
|
&echoops,.packet_is_valid =
|
||||||
.ports_per_subunit = 1,
|
echo_packet_is_valid,.packet_dump = echo_packet_dump,};
|
||||||
.type = XPD_TYPE_ECHO,
|
|
||||||
.xops = &echo_xops,
|
|
||||||
.echoops = &echoops,
|
|
||||||
.packet_is_valid = echo_packet_is_valid,
|
|
||||||
.packet_dump = echo_packet_dump,
|
|
||||||
};
|
|
||||||
|
|
||||||
static bool echo_packet_is_valid(xpacket_t *pack)
|
static bool echo_packet_is_valid(xpacket_t *pack)
|
||||||
{
|
{
|
||||||
@ -315,8 +300,8 @@ static int echo_xpd_probe(struct device *dev)
|
|||||||
ec_xpd = dev_to_xpd(dev);
|
ec_xpd = dev_to_xpd(dev);
|
||||||
/* Is it our device? */
|
/* Is it our device? */
|
||||||
if (ec_xpd->type != XPD_TYPE_ECHO) {
|
if (ec_xpd->type != XPD_TYPE_ECHO) {
|
||||||
XPD_ERR(ec_xpd, "drop suggestion for %s (%d)\n",
|
XPD_ERR(ec_xpd, "drop suggestion for %s (%d)\n", dev_name(dev),
|
||||||
dev_name(dev), ec_xpd->type);
|
ec_xpd->type);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
XPD_DBG(DEVICES, ec_xpd, "SYSFS\n");
|
XPD_DBG(DEVICES, ec_xpd, "SYSFS\n");
|
||||||
@ -340,8 +325,7 @@ static struct xpd_driver echo_driver = {
|
|||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
#endif
|
#endif
|
||||||
.probe = echo_xpd_probe,
|
.probe = echo_xpd_probe,
|
||||||
.remove = echo_xpd_remove
|
.remove = echo_xpd_remove}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init card_echo_startup(void)
|
static int __init card_echo_startup(void)
|
||||||
|
@ -34,16 +34,24 @@
|
|||||||
static const char rcsid[] = "$Id$";
|
static const char rcsid[] = "$Id$";
|
||||||
|
|
||||||
static DEF_PARM(int, debug, 0, 0644, "Print DBG statements");
|
static DEF_PARM(int, debug, 0, 0644, "Print DBG statements");
|
||||||
static DEF_PARM(uint, poll_battery_interval, 500, 0644, "Poll battery interval in milliseconds (0 - disable)");
|
static DEF_PARM(uint, poll_battery_interval, 500, 0644,
|
||||||
|
"Poll battery interval in milliseconds (0 - disable)");
|
||||||
#ifdef WITH_METERING
|
#ifdef WITH_METERING
|
||||||
static DEF_PARM(uint, poll_metering_interval, 500, 0644, "Poll metering interval in milliseconds (0 - disable)");
|
static DEF_PARM(uint, poll_metering_interval, 500, 0644,
|
||||||
|
"Poll metering interval in milliseconds (0 - disable)");
|
||||||
#endif
|
#endif
|
||||||
static DEF_PARM(int, ring_debounce, 50, 0644, "Number of ticks to debounce a false RING indication");
|
static DEF_PARM(int, ring_debounce, 50, 0644,
|
||||||
static DEF_PARM(int, caller_id_style, 0, 0444, "Caller-Id detection style: 0 - [BELL], 1 - [ETSI_FSK], 2 - [ETSI_DTMF]");
|
"Number of ticks to debounce a false RING indication");
|
||||||
static DEF_PARM(int, power_denial_safezone, 650, 0644, "msec after offhook to ignore power-denial ( (0 - disable power-denial)");
|
static DEF_PARM(int, caller_id_style, 0, 0444,
|
||||||
static DEF_PARM(int, power_denial_minlen, 80, 0644, "Minimal detected power-denial length (msec) (0 - disable power-denial)");
|
"Caller-Id detection style: 0 - [BELL], 1 - [ETSI_FSK], 2 - [ETSI_DTMF]");
|
||||||
static DEF_PARM(uint, battery_threshold, 3, 0644, "Minimum voltage that shows there is battery");
|
static DEF_PARM(int, power_denial_safezone, 650, 0644,
|
||||||
static DEF_PARM(uint, battery_debounce, 1000, 0644, "Minimum interval (msec) for detection of battery off");
|
"msec after offhook to ignore power-denial ( (0 - disable power-denial)");
|
||||||
|
static DEF_PARM(int, power_denial_minlen, 80, 0644,
|
||||||
|
"Minimal detected power-denial length (msec) (0 - disable power-denial)");
|
||||||
|
static DEF_PARM(uint, battery_threshold, 3, 0644,
|
||||||
|
"Minimum voltage that shows there is battery");
|
||||||
|
static DEF_PARM(uint, battery_debounce, 1000, 0644,
|
||||||
|
"Minimum interval (msec) for detection of battery off");
|
||||||
|
|
||||||
enum cid_style {
|
enum cid_style {
|
||||||
CID_STYLE_BELL = 0, /* E.g: US (Bellcore) */
|
CID_STYLE_BELL = 0, /* E.g: US (Bellcore) */
|
||||||
@ -86,9 +94,11 @@ enum fxo_leds {
|
|||||||
static bool fxo_packet_is_valid(xpacket_t *pack);
|
static bool fxo_packet_is_valid(xpacket_t *pack);
|
||||||
static void fxo_packet_dump(const char *msg, xpacket_t *pack);
|
static void fxo_packet_dump(const char *msg, xpacket_t *pack);
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
static int proc_fxo_info_read(char *page, char **start, off_t off, int count, int *eof, void *data);
|
static int proc_fxo_info_read(char *page, char **start, off_t off, int count,
|
||||||
|
int *eof, void *data);
|
||||||
#ifdef WITH_METERING
|
#ifdef WITH_METERING
|
||||||
static int proc_xpd_metering_read(char *page, char **start, off_t off, int count, int *eof, void *data);
|
static int proc_xpd_metering_read(char *page, char **start, off_t off,
|
||||||
|
int count, int *eof, void *data);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
static void dahdi_report_battery(xpd_t *xpd, lineno_t chan);
|
static void dahdi_report_battery(xpd_t *xpd, lineno_t chan);
|
||||||
@ -170,9 +180,12 @@ struct FXO_priv_data {
|
|||||||
static const char *power2str(enum power_state pw)
|
static const char *power2str(enum power_state pw)
|
||||||
{
|
{
|
||||||
switch (pw) {
|
switch (pw) {
|
||||||
case POWER_UNKNOWN: return "UNKNOWN";
|
case POWER_UNKNOWN:
|
||||||
case POWER_OFF: return "OFF";
|
return "UNKNOWN";
|
||||||
case POWER_ON: return "ON";
|
case POWER_OFF:
|
||||||
|
return "OFF";
|
||||||
|
case POWER_ON:
|
||||||
|
return "ON";
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -183,8 +196,7 @@ static void power_change(xpd_t *xpd, int portno, enum power_state pw)
|
|||||||
|
|
||||||
priv = xpd->priv;
|
priv = xpd->priv;
|
||||||
LINE_DBG(SIGNAL, xpd, portno, "power: %s -> %s\n",
|
LINE_DBG(SIGNAL, xpd, portno, "power: %s -> %s\n",
|
||||||
power2str(priv->power[portno]),
|
power2str(priv->power[portno]), power2str(pw));
|
||||||
power2str(pw));
|
|
||||||
priv->power[portno] = pw;
|
priv->power[portno] = pw;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,7 +225,8 @@ static int do_led(xpd_t *xpd, lineno_t chan, __u8 which, bool on)
|
|||||||
xbus = xpd->xbus;
|
xbus = xpd->xbus;
|
||||||
priv = xpd->priv;
|
priv = xpd->priv;
|
||||||
which = which % NUM_LEDS;
|
which = which % NUM_LEDS;
|
||||||
if (IS_SET(PHONEDEV(xpd).digital_outputs, chan) || IS_SET(PHONEDEV(xpd).digital_inputs, chan))
|
if (IS_SET(PHONEDEV(xpd).digital_outputs, chan)
|
||||||
|
|| IS_SET(PHONEDEV(xpd).digital_inputs, chan))
|
||||||
goto out;
|
goto out;
|
||||||
if (chan == PORT_BROADCAST) {
|
if (chan == PORT_BROADCAST) {
|
||||||
priv->ledstate[which] = (on) ? ~0 : 0;
|
priv->ledstate[which] = (on) ? ~0 : 0;
|
||||||
@ -228,7 +241,8 @@ static int do_led(xpd_t *xpd, lineno_t chan, __u8 which, bool on)
|
|||||||
value |= ((BIT(5) | BIT(6) | BIT(7)) & ~led_register_mask[which]);
|
value |= ((BIT(5) | BIT(6) | BIT(7)) & ~led_register_mask[which]);
|
||||||
value |= (on) ? BIT(0) : 0;
|
value |= (on) ? BIT(0) : 0;
|
||||||
value |= (on) ? BIT(1) : 0;
|
value |= (on) ? BIT(1) : 0;
|
||||||
LINE_DBG(LEDS, xpd, chan, "LED: which=%d -- %s\n", which, (on) ? "on" : "off");
|
LINE_DBG(LEDS, xpd, chan, "LED: which=%d -- %s\n", which,
|
||||||
|
(on) ? "on" : "off");
|
||||||
ret = DAA_DIRECT_REQUEST(xbus, xpd, chan, DAA_WRITE, 0x20, value);
|
ret = DAA_DIRECT_REQUEST(xbus, xpd, chan, DAA_WRITE, 0x20, value);
|
||||||
out:
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
@ -249,7 +263,8 @@ static void handle_fxo_leds(xpd_t *xpd)
|
|||||||
timer_count = xpd->timer_count;
|
timer_count = xpd->timer_count;
|
||||||
for (color = 0; color < ARRAY_SIZE(colors); color++) {
|
for (color = 0; color < ARRAY_SIZE(colors); color++) {
|
||||||
for_each_line(xpd, i) {
|
for_each_line(xpd, i) {
|
||||||
if (IS_SET(PHONEDEV(xpd).digital_outputs, i) || IS_SET(PHONEDEV(xpd).digital_inputs, i))
|
if (IS_SET(PHONEDEV(xpd).digital_outputs, i)
|
||||||
|
|| IS_SET(PHONEDEV(xpd).digital_inputs, i))
|
||||||
continue;
|
continue;
|
||||||
if ((xpd->blink_mode & BIT(i)) || IS_BLINKING(priv, i, color)) { // Blinking
|
if ((xpd->blink_mode & BIT(i)) || IS_BLINKING(priv, i, color)) { // Blinking
|
||||||
int mod_value = LED_COUNTER(priv, i, color);
|
int mod_value = LED_COUNTER(priv, i, color);
|
||||||
@ -258,16 +273,21 @@ static void handle_fxo_leds(xpd_t *xpd)
|
|||||||
mod_value = DEFAULT_LED_PERIOD; /* safety value */
|
mod_value = DEFAULT_LED_PERIOD; /* safety value */
|
||||||
// led state is toggled
|
// led state is toggled
|
||||||
if ((timer_count % mod_value) == 0) {
|
if ((timer_count % mod_value) == 0) {
|
||||||
LINE_DBG(LEDS, xpd, i, "ledstate=%s\n", (IS_SET(priv->ledstate[color], i))?"ON":"OFF");
|
LINE_DBG(LEDS, xpd, i, "ledstate=%s\n",
|
||||||
|
(IS_SET
|
||||||
|
(priv->ledstate[color],
|
||||||
|
i)) ? "ON" : "OFF");
|
||||||
if (!IS_SET(priv->ledstate[color], i)) {
|
if (!IS_SET(priv->ledstate[color], i)) {
|
||||||
do_led(xpd, i, color, 1);
|
do_led(xpd, i, color, 1);
|
||||||
} else {
|
} else {
|
||||||
do_led(xpd, i, color, 0);
|
do_led(xpd, i, color, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (IS_SET(priv->ledcontrol[color], i) && !IS_SET(priv->ledstate[color], i)) {
|
} else if (IS_SET(priv->ledcontrol[color], i)
|
||||||
|
&& !IS_SET(priv->ledstate[color], i)) {
|
||||||
do_led(xpd, i, color, 1);
|
do_led(xpd, i, color, 1);
|
||||||
} else if (!IS_SET(priv->ledcontrol[color], i) && IS_SET(priv->ledstate[color], i)) {
|
} else if (!IS_SET(priv->ledcontrol[color], i)
|
||||||
|
&& IS_SET(priv->ledstate[color], i)) {
|
||||||
do_led(xpd, i, color, 0);
|
do_led(xpd, i, color, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -332,7 +352,8 @@ static int do_sethook(xpd_t *xpd, int pos, bool to_offhook)
|
|||||||
priv = xpd->priv;
|
priv = xpd->priv;
|
||||||
BUG_ON(!priv);
|
BUG_ON(!priv);
|
||||||
if (priv->battery[pos] != BATTERY_ON && to_offhook) {
|
if (priv->battery[pos] != BATTERY_ON && to_offhook) {
|
||||||
LINE_NOTICE(xpd, pos, "Cannot take offhook while battery is off!\n");
|
LINE_NOTICE(xpd, pos,
|
||||||
|
"Cannot take offhook while battery is off!\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
spin_lock_irqsave(&xpd->lock, flags);
|
spin_lock_irqsave(&xpd->lock, flags);
|
||||||
@ -340,12 +361,15 @@ static int do_sethook(xpd_t *xpd, int pos, bool to_offhook)
|
|||||||
value = REG_DAA_CONTROL1_ONHM; /* Bit 3 is for CID */
|
value = REG_DAA_CONTROL1_ONHM; /* Bit 3 is for CID */
|
||||||
if (to_offhook)
|
if (to_offhook)
|
||||||
value |= REG_DAA_CONTROL1_OH;
|
value |= REG_DAA_CONTROL1_OH;
|
||||||
LINE_DBG(SIGNAL, xpd, pos, "SETHOOK: value=0x%02X %s\n", value, (to_offhook)?"OFFHOOK":"ONHOOK");
|
LINE_DBG(SIGNAL, xpd, pos, "SETHOOK: value=0x%02X %s\n", value,
|
||||||
|
(to_offhook) ? "OFFHOOK" : "ONHOOK");
|
||||||
if (to_offhook)
|
if (to_offhook)
|
||||||
MARK_ON(priv, pos, LED_GREEN);
|
MARK_ON(priv, pos, LED_GREEN);
|
||||||
else
|
else
|
||||||
MARK_OFF(priv, pos, LED_GREEN);
|
MARK_OFF(priv, pos, LED_GREEN);
|
||||||
ret = DAA_DIRECT_REQUEST(xbus, xpd, pos, DAA_WRITE, REG_DAA_CONTROL1, value);
|
ret =
|
||||||
|
DAA_DIRECT_REQUEST(xbus, xpd, pos, DAA_WRITE, REG_DAA_CONTROL1,
|
||||||
|
value);
|
||||||
mark_offhook(xpd, pos, to_offhook);
|
mark_offhook(xpd, pos, to_offhook);
|
||||||
if (caller_id_style != CID_STYLE_ETSI_DTMF)
|
if (caller_id_style != CID_STYLE_ETSI_DTMF)
|
||||||
oht_pcm(xpd, pos, 0);
|
oht_pcm(xpd, pos, 0);
|
||||||
@ -400,19 +424,24 @@ static int fxo_proc_create(xbus_t *xbus, xpd_t *xpd)
|
|||||||
priv = xpd->priv;
|
priv = xpd->priv;
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
XPD_DBG(PROC, xpd, "Creating FXO_INFO file\n");
|
XPD_DBG(PROC, xpd, "Creating FXO_INFO file\n");
|
||||||
priv->fxo_info = create_proc_read_entry(PROC_FXO_INFO_FNAME, 0444, xpd->proc_xpd_dir, proc_fxo_info_read, xpd);
|
priv->fxo_info =
|
||||||
|
create_proc_read_entry(PROC_FXO_INFO_FNAME, 0444, xpd->proc_xpd_dir,
|
||||||
|
proc_fxo_info_read, xpd);
|
||||||
if (!priv->fxo_info) {
|
if (!priv->fxo_info) {
|
||||||
XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_FXO_INFO_FNAME);
|
XPD_ERR(xpd, "Failed to create proc file '%s'\n",
|
||||||
|
PROC_FXO_INFO_FNAME);
|
||||||
fxo_proc_remove(xbus, xpd);
|
fxo_proc_remove(xbus, xpd);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
SET_PROC_DIRENTRY_OWNER(priv->fxo_info);
|
SET_PROC_DIRENTRY_OWNER(priv->fxo_info);
|
||||||
#ifdef WITH_METERING
|
#ifdef WITH_METERING
|
||||||
XPD_DBG(PROC, xpd, "Creating Metering tone file\n");
|
XPD_DBG(PROC, xpd, "Creating Metering tone file\n");
|
||||||
priv->meteringfile = create_proc_read_entry(PROC_METERING_FNAME, 0444, xpd->proc_xpd_dir,
|
priv->meteringfile =
|
||||||
|
create_proc_read_entry(PROC_METERING_FNAME, 0444, xpd->proc_xpd_dir,
|
||||||
proc_xpd_metering_read, xpd);
|
proc_xpd_metering_read, xpd);
|
||||||
if (!priv->meteringfile) {
|
if (!priv->meteringfile) {
|
||||||
XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_METERING_FNAME);
|
XPD_ERR(xpd, "Failed to create proc file '%s'\n",
|
||||||
|
PROC_METERING_FNAME);
|
||||||
fxo_proc_remove(xbus, xpd);
|
fxo_proc_remove(xbus, xpd);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@ -422,8 +451,9 @@ static int fxo_proc_create(xbus_t *xbus, xpd_t *xpd)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static xpd_t *FXO_card_new(xbus_t *xbus, int unit, int subunit, const xproto_table_t *proto_table,
|
static xpd_t *FXO_card_new(xbus_t *xbus, int unit, int subunit,
|
||||||
__u8 subtype, int subunits, int subunit_ports, bool to_phone)
|
const xproto_table_t *proto_table, __u8 subtype,
|
||||||
|
int subunits, int subunit_ports, bool to_phone)
|
||||||
{
|
{
|
||||||
xpd_t *xpd = NULL;
|
xpd_t *xpd = NULL;
|
||||||
int channels;
|
int channels;
|
||||||
@ -438,7 +468,9 @@ static xpd_t *FXO_card_new(xbus_t *xbus, int unit, int subunit, const xproto_tab
|
|||||||
channels = min(2, subunit_ports);
|
channels = min(2, subunit_ports);
|
||||||
else
|
else
|
||||||
channels = min(8, subunit_ports);
|
channels = min(8, subunit_ports);
|
||||||
xpd = xpd_alloc(xbus, unit, subunit, subtype, subunits, sizeof(struct FXO_priv_data), proto_table, channels);
|
xpd =
|
||||||
|
xpd_alloc(xbus, unit, subunit, subtype, subunits,
|
||||||
|
sizeof(struct FXO_priv_data), proto_table, channels);
|
||||||
if (!xpd)
|
if (!xpd)
|
||||||
return NULL;
|
return NULL;
|
||||||
PHONEDEV(xpd).direction = TO_PSTN;
|
PHONEDEV(xpd).direction = TO_PSTN;
|
||||||
@ -589,11 +621,13 @@ static void dahdi_report_battery(xpd_t *xpd, lineno_t chan)
|
|||||||
break;
|
break;
|
||||||
case BATTERY_OFF:
|
case BATTERY_OFF:
|
||||||
LINE_DBG(SIGNAL, xpd, chan, "Send DAHDI_ALARM_RED\n");
|
LINE_DBG(SIGNAL, xpd, chan, "Send DAHDI_ALARM_RED\n");
|
||||||
dahdi_alarm_channel(XPD_CHAN(xpd, chan), DAHDI_ALARM_RED);
|
dahdi_alarm_channel(XPD_CHAN(xpd, chan),
|
||||||
|
DAHDI_ALARM_RED);
|
||||||
break;
|
break;
|
||||||
case BATTERY_ON:
|
case BATTERY_ON:
|
||||||
LINE_DBG(SIGNAL, xpd, chan, "Send DAHDI_ALARM_NONE\n");
|
LINE_DBG(SIGNAL, xpd, chan, "Send DAHDI_ALARM_NONE\n");
|
||||||
dahdi_alarm_channel(XPD_CHAN(xpd, chan), DAHDI_ALARM_NONE);
|
dahdi_alarm_channel(XPD_CHAN(xpd, chan),
|
||||||
|
DAHDI_ALARM_NONE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -621,7 +655,8 @@ static void poll_metering(xbus_t *xbus, xpd_t *xpd)
|
|||||||
|
|
||||||
for_each_line(xpd, i) {
|
for_each_line(xpd, i) {
|
||||||
if (IS_OFFHOOK(xpd, i))
|
if (IS_OFFHOOK(xpd, i))
|
||||||
DAA_DIRECT_REQUEST(xbus, xpd, i, DAA_READ, DAA_REG_METERING, 0);
|
DAA_DIRECT_REQUEST(xbus, xpd, i, DAA_READ,
|
||||||
|
DAA_REG_METERING, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -663,7 +698,8 @@ static void handle_fxo_power_denial(xpd_t *xpd)
|
|||||||
/*
|
/*
|
||||||
* Poll current, previous answers are meaningless
|
* Poll current, previous answers are meaningless
|
||||||
*/
|
*/
|
||||||
DAA_DIRECT_REQUEST(xpd->xbus, xpd, i, DAA_READ, DAA_REG_CURRENT, 0);
|
DAA_DIRECT_REQUEST(xpd->xbus, xpd, i, DAA_READ,
|
||||||
|
DAA_REG_CURRENT, 0);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -675,8 +711,10 @@ static void handle_fxo_power_denial(xpd_t *xpd)
|
|||||||
* detected it yet). This would cause false power denials.
|
* detected it yet). This would cause false power denials.
|
||||||
* So we just flag it and schedule more ticks to wait.
|
* So we just flag it and schedule more ticks to wait.
|
||||||
*/
|
*/
|
||||||
LINE_DBG(SIGNAL, xpd, i, "Possible Power Denial Hangup\n");
|
LINE_DBG(SIGNAL, xpd, i,
|
||||||
priv->power_denial_delay[i] = POWER_DENIAL_DELAY;
|
"Possible Power Denial Hangup\n");
|
||||||
|
priv->power_denial_delay[i] =
|
||||||
|
POWER_DENIAL_DELAY;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -688,7 +726,8 @@ static void handle_fxo_power_denial(xpd_t *xpd)
|
|||||||
*/
|
*/
|
||||||
priv->power_denial_delay[i]--;
|
priv->power_denial_delay[i]--;
|
||||||
if (priv->power_denial_delay[i] <= 0) {
|
if (priv->power_denial_delay[i] <= 0) {
|
||||||
LINE_DBG(SIGNAL, xpd, i, "Power Denial Hangup\n");
|
LINE_DBG(SIGNAL, xpd, i,
|
||||||
|
"Power Denial Hangup\n");
|
||||||
priv->power_denial_delay[i] = 0;
|
priv->power_denial_delay[i] = 0;
|
||||||
/*
|
/*
|
||||||
* Let Asterisk decide what to do
|
* Let Asterisk decide what to do
|
||||||
@ -726,7 +765,8 @@ static void check_etsi_dtmf(xpd_t *xpd)
|
|||||||
/* reset flags if it's been a while */
|
/* reset flags if it's been a while */
|
||||||
priv->cidtimer[portno] = timer_count;
|
priv->cidtimer[portno] = timer_count;
|
||||||
BIT_CLR(priv->cidfound, portno);
|
BIT_CLR(priv->cidfound, portno);
|
||||||
LINE_DBG(SIGNAL, xpd, portno, "Reset CID flag\n");
|
LINE_DBG(SIGNAL, xpd, portno,
|
||||||
|
"Reset CID flag\n");
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -740,8 +780,10 @@ static void check_etsi_dtmf(xpd_t *xpd)
|
|||||||
if (sample > 16000 || sample < -16000) {
|
if (sample > 16000 || sample < -16000) {
|
||||||
priv->cidtimer[portno] = timer_count;
|
priv->cidtimer[portno] = timer_count;
|
||||||
BIT_SET(priv->cidfound, portno);
|
BIT_SET(priv->cidfound, portno);
|
||||||
LINE_DBG(SIGNAL, xpd, portno, "Found DTMF CLIP (%d)\n", i);
|
LINE_DBG(SIGNAL, xpd, portno,
|
||||||
dahdi_qevent_lock(chan, DAHDI_EVENT_POLARITY);
|
"Found DTMF CLIP (%d)\n", i);
|
||||||
|
dahdi_qevent_lock(chan,
|
||||||
|
DAHDI_EVENT_POLARITY);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -756,10 +798,12 @@ static int FXO_card_tick(xbus_t *xbus, xpd_t *xpd)
|
|||||||
BUG_ON(!xpd);
|
BUG_ON(!xpd);
|
||||||
priv = xpd->priv;
|
priv = xpd->priv;
|
||||||
BUG_ON(!priv);
|
BUG_ON(!priv);
|
||||||
if (poll_battery_interval != 0 && (priv->poll_counter % poll_battery_interval) == 0)
|
if (poll_battery_interval != 0
|
||||||
|
&& (priv->poll_counter % poll_battery_interval) == 0)
|
||||||
poll_battery(xbus, xpd);
|
poll_battery(xbus, xpd);
|
||||||
#ifdef WITH_METERING
|
#ifdef WITH_METERING
|
||||||
if (poll_metering_interval != 0 && (priv->poll_counter % poll_metering_interval) == 0)
|
if (poll_metering_interval != 0
|
||||||
|
&& (priv->poll_counter % poll_metering_interval) == 0)
|
||||||
poll_metering(xbus, xpd);
|
poll_metering(xbus, xpd);
|
||||||
#endif
|
#endif
|
||||||
handle_fxo_leds(xpd);
|
handle_fxo_leds(xpd);
|
||||||
@ -777,9 +821,11 @@ static int FXO_card_tick(xbus_t *xbus, xpd_t *xpd)
|
|||||||
* We define the array size explicitly to track possible inconsistencies
|
* We define the array size explicitly to track possible inconsistencies
|
||||||
* if the struct is modified.
|
* if the struct is modified.
|
||||||
*/
|
*/
|
||||||
static const char echotune_regs[sizeof(struct wctdm_echo_coefs)] = {30, 45, 46, 47, 48, 49, 50, 51, 52};
|
static const char echotune_regs[sizeof(struct wctdm_echo_coefs)] =
|
||||||
|
{ 30, 45, 46, 47, 48, 49, 50, 51, 52 };
|
||||||
|
|
||||||
static int FXO_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long arg)
|
static int FXO_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd,
|
||||||
|
unsigned long arg)
|
||||||
{
|
{
|
||||||
int i, ret;
|
int i, ret;
|
||||||
unsigned char echotune_data[ARRAY_SIZE(echotune_regs)];
|
unsigned char echotune_data[ARRAY_SIZE(echotune_regs)];
|
||||||
@ -791,14 +837,20 @@ static int FXO_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long a
|
|||||||
case WCTDM_SET_ECHOTUNE:
|
case WCTDM_SET_ECHOTUNE:
|
||||||
XPD_DBG(GENERAL, xpd, "-- Setting echo registers: \n");
|
XPD_DBG(GENERAL, xpd, "-- Setting echo registers: \n");
|
||||||
/* first off: check if this span is fxs. If not: -EINVALID */
|
/* first off: check if this span is fxs. If not: -EINVALID */
|
||||||
if (copy_from_user(&echotune_data, (void __user *)arg, sizeof(echotune_data)))
|
if (copy_from_user
|
||||||
|
(&echotune_data, (void __user *)arg, sizeof(echotune_data)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(echotune_regs); i++) {
|
for (i = 0; i < ARRAY_SIZE(echotune_regs); i++) {
|
||||||
XPD_DBG(REGS, xpd, "Reg=0x%02X, data=0x%02X\n", echotune_regs[i], echotune_data[i]);
|
XPD_DBG(REGS, xpd, "Reg=0x%02X, data=0x%02X\n",
|
||||||
ret = DAA_DIRECT_REQUEST(xpd->xbus, xpd, pos, DAA_WRITE, echotune_regs[i], echotune_data[i]);
|
echotune_regs[i], echotune_data[i]);
|
||||||
|
ret =
|
||||||
|
DAA_DIRECT_REQUEST(xpd->xbus, xpd, pos, DAA_WRITE,
|
||||||
|
echotune_regs[i],
|
||||||
|
echotune_data[i]);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
LINE_NOTICE(xpd, pos, "Couldn't write %0x02X to register %0x02X\n",
|
LINE_NOTICE(xpd, pos,
|
||||||
|
"Couldn't write %0x02X to register %0x02X\n",
|
||||||
echotune_data[i], echotune_regs[i]);
|
echotune_data[i], echotune_regs[i]);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -828,8 +880,10 @@ static int FXO_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long a
|
|||||||
|
|
||||||
HANDLER_DEF(FXO, SIG_CHANGED)
|
HANDLER_DEF(FXO, SIG_CHANGED)
|
||||||
{
|
{
|
||||||
xpp_line_t sig_status = RPACKET_FIELD(pack, FXO, SIG_CHANGED, sig_status);
|
xpp_line_t sig_status =
|
||||||
xpp_line_t sig_toggles = RPACKET_FIELD(pack, FXO, SIG_CHANGED, sig_toggles);
|
RPACKET_FIELD(pack, FXO, SIG_CHANGED, sig_status);
|
||||||
|
xpp_line_t sig_toggles =
|
||||||
|
RPACKET_FIELD(pack, FXO, SIG_CHANGED, sig_toggles);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int i;
|
int i;
|
||||||
struct FXO_priv_data *priv;
|
struct FXO_priv_data *priv;
|
||||||
@ -840,7 +894,8 @@ HANDLER_DEF(FXO, SIG_CHANGED)
|
|||||||
}
|
}
|
||||||
priv = xpd->priv;
|
priv = xpd->priv;
|
||||||
BUG_ON(!priv);
|
BUG_ON(!priv);
|
||||||
XPD_DBG(SIGNAL, xpd, "(PSTN) sig_toggles=0x%04X sig_status=0x%04X\n", sig_toggles, sig_status);
|
XPD_DBG(SIGNAL, xpd, "(PSTN) sig_toggles=0x%04X sig_status=0x%04X\n",
|
||||||
|
sig_toggles, sig_status);
|
||||||
spin_lock_irqsave(&xpd->lock, flags);
|
spin_lock_irqsave(&xpd->lock, flags);
|
||||||
for_each_line(xpd, i) {
|
for_each_line(xpd, i) {
|
||||||
int debounce;
|
int debounce;
|
||||||
@ -851,18 +906,23 @@ HANDLER_DEF(FXO, SIG_CHANGED)
|
|||||||
* With poll_battery_interval==0 we cannot have BATTERY_OFF
|
* With poll_battery_interval==0 we cannot have BATTERY_OFF
|
||||||
* so we won't get here
|
* so we won't get here
|
||||||
*/
|
*/
|
||||||
LINE_NOTICE(xpd, i, "SIG_CHANGED while battery is off. Ignored.\n");
|
LINE_NOTICE(xpd, i,
|
||||||
|
"SIG_CHANGED while battery is off. Ignored.\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* First report false ring alarms */
|
/* First report false ring alarms */
|
||||||
debounce = atomic_read(&priv->ring_debounce[i]);
|
debounce = atomic_read(&priv->ring_debounce[i]);
|
||||||
if (debounce)
|
if (debounce)
|
||||||
LINE_NOTICE(xpd, i, "debounced false ring (only %d ticks)\n", debounce);
|
LINE_NOTICE(xpd, i,
|
||||||
|
"debounced false ring (only %d ticks)\n",
|
||||||
|
debounce);
|
||||||
/*
|
/*
|
||||||
* Now set a new ring alarm.
|
* Now set a new ring alarm.
|
||||||
* It will be checked in handle_fxo_ring()
|
* It will be checked in handle_fxo_ring()
|
||||||
*/
|
*/
|
||||||
debounce = (IS_SET(sig_status, i)) ? ring_debounce : -ring_debounce;
|
debounce =
|
||||||
|
(IS_SET(sig_status, i)) ? ring_debounce :
|
||||||
|
-ring_debounce;
|
||||||
atomic_set(&priv->ring_debounce[i], debounce);
|
atomic_set(&priv->ring_debounce[i], debounce);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -889,10 +949,12 @@ static void update_battery_voltage(xpd_t *xpd, __u8 data_low, xportno_t portno)
|
|||||||
if (priv->battery[portno] != BATTERY_OFF) {
|
if (priv->battery[portno] != BATTERY_OFF) {
|
||||||
int milliseconds;
|
int milliseconds;
|
||||||
|
|
||||||
milliseconds = priv->nobattery_debounce[portno]++ *
|
milliseconds =
|
||||||
|
priv->nobattery_debounce[portno]++ *
|
||||||
poll_battery_interval;
|
poll_battery_interval;
|
||||||
if (milliseconds > battery_debounce) {
|
if (milliseconds > battery_debounce) {
|
||||||
LINE_DBG(SIGNAL, xpd, portno, "BATTERY OFF voltage=%d\n", volts);
|
LINE_DBG(SIGNAL, xpd, portno,
|
||||||
|
"BATTERY OFF voltage=%d\n", volts);
|
||||||
priv->battery[portno] = BATTERY_OFF;
|
priv->battery[portno] = BATTERY_OFF;
|
||||||
dahdi_report_battery(xpd, portno);
|
dahdi_report_battery(xpd, portno);
|
||||||
/* What's the polarity ? */
|
/* What's the polarity ? */
|
||||||
@ -910,7 +972,8 @@ static void update_battery_voltage(xpd_t *xpd, __u8 data_low, xportno_t portno)
|
|||||||
} else {
|
} else {
|
||||||
priv->nobattery_debounce[portno] = 0;
|
priv->nobattery_debounce[portno] = 0;
|
||||||
if (priv->battery[portno] != BATTERY_ON) {
|
if (priv->battery[portno] != BATTERY_ON) {
|
||||||
LINE_DBG(SIGNAL, xpd, portno, "BATTERY ON voltage=%d\n", volts);
|
LINE_DBG(SIGNAL, xpd, portno, "BATTERY ON voltage=%d\n",
|
||||||
|
volts);
|
||||||
priv->battery[portno] = BATTERY_ON;
|
priv->battery[portno] = BATTERY_ON;
|
||||||
dahdi_report_battery(xpd, portno);
|
dahdi_report_battery(xpd, portno);
|
||||||
}
|
}
|
||||||
@ -972,8 +1035,10 @@ static void update_battery_voltage(xpd_t *xpd, __u8 data_low, xportno_t portno)
|
|||||||
oht_pcm(xpd, portno, 1); /* will be cleared on ring/offhook */
|
oht_pcm(xpd, portno, 1); /* will be cleared on ring/offhook */
|
||||||
if (SPAN_REGISTERED(xpd)) {
|
if (SPAN_REGISTERED(xpd)) {
|
||||||
LINE_DBG(SIGNAL, xpd, portno,
|
LINE_DBG(SIGNAL, xpd, portno,
|
||||||
"Send DAHDI_EVENT_POLARITY: %s\n", polname);
|
"Send DAHDI_EVENT_POLARITY: %s\n",
|
||||||
dahdi_qevent_lock(XPD_CHAN(xpd, portno), DAHDI_EVENT_POLARITY);
|
polname);
|
||||||
|
dahdi_qevent_lock(XPD_CHAN(xpd, portno),
|
||||||
|
DAHDI_EVENT_POLARITY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
priv->polarity[portno] = pol;
|
priv->polarity[portno] = pol;
|
||||||
@ -1038,8 +1103,8 @@ static void update_metering_state(xpd_t *xpd, __u8 data_low, lineno_t portno)
|
|||||||
BUG_ON(!priv);
|
BUG_ON(!priv);
|
||||||
old_metering_tone = IS_SET(priv->metering_tone_state, portno);
|
old_metering_tone = IS_SET(priv->metering_tone_state, portno);
|
||||||
LINE_DBG(SIGNAL, xpd, portno, "METERING: %s [dL=0x%X] (%d)\n",
|
LINE_DBG(SIGNAL, xpd, portno, "METERING: %s [dL=0x%X] (%d)\n",
|
||||||
(metering_tone) ? "ON" : "OFF",
|
(metering_tone) ? "ON" : "OFF", data_low,
|
||||||
data_low, priv->metering_count[portno]);
|
priv->metering_count[portno]);
|
||||||
if (metering_tone && !old_metering_tone) {
|
if (metering_tone && !old_metering_tone) {
|
||||||
/* Rising edge */
|
/* Rising edge */
|
||||||
priv->metering_count[portno]++;
|
priv->metering_count[portno]++;
|
||||||
@ -1049,7 +1114,8 @@ static void update_metering_state(xpd_t *xpd, __u8 data_low, lineno_t portno)
|
|||||||
if (metering_tone) {
|
if (metering_tone) {
|
||||||
/* Clear the BTD bit */
|
/* Clear the BTD bit */
|
||||||
data_low &= ~BTD_BIT;
|
data_low &= ~BTD_BIT;
|
||||||
DAA_DIRECT_REQUEST(xpd->xbus, xpd, portno, DAA_WRITE, DAA_REG_METERING, data_low);
|
DAA_DIRECT_REQUEST(xpd->xbus, xpd, portno, DAA_WRITE,
|
||||||
|
DAA_REG_METERING, data_low);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1076,15 +1142,14 @@ static int FXO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
LINE_DBG(REGS, xpd, portno, "%c reg_num=0x%X, dataL=0x%X dataH=0x%X\n",
|
LINE_DBG(REGS, xpd, portno, "%c reg_num=0x%X, dataL=0x%X dataH=0x%X\n",
|
||||||
((info->bytes == 3)?'I':'D'),
|
((info->bytes == 3) ? 'I' : 'D'), REG_FIELD(info, regnum),
|
||||||
REG_FIELD(info, regnum),
|
REG_FIELD(info, data_low), REG_FIELD(info, data_high));
|
||||||
REG_FIELD(info, data_low),
|
|
||||||
REG_FIELD(info, data_high));
|
|
||||||
/* Update /proc info only if reply relate to the last slic read request */
|
/* Update /proc info only if reply relate to the last slic read request */
|
||||||
if (
|
if (REG_FIELD(&xpd->requested_reply, regnum) == REG_FIELD(info, regnum)
|
||||||
REG_FIELD(&xpd->requested_reply, regnum) == REG_FIELD(info, regnum) &&
|
&& REG_FIELD(&xpd->requested_reply, do_subreg) == REG_FIELD(info,
|
||||||
REG_FIELD(&xpd->requested_reply, do_subreg) == REG_FIELD(info, do_subreg) &&
|
do_subreg)
|
||||||
REG_FIELD(&xpd->requested_reply, subreg) == REG_FIELD(info, subreg)) {
|
&& REG_FIELD(&xpd->requested_reply, subreg) == REG_FIELD(info,
|
||||||
|
subreg)) {
|
||||||
xpd->last_reply = *info;
|
xpd->last_reply = *info;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -1126,19 +1191,12 @@ static const struct phoneops fxo_phoneops = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static xproto_table_t PROTO_TABLE(FXO) = {
|
static xproto_table_t PROTO_TABLE(FXO) = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,.entries = {
|
||||||
.entries = {
|
|
||||||
/* Prototable Card Opcode */
|
/* Prototable Card Opcode */
|
||||||
XENTRY( FXO, FXO, SIG_CHANGED ),
|
XENTRY(FXO, FXO, SIG_CHANGED),},.name = "FXO", /* protocol name */
|
||||||
},
|
.ports_per_subunit = 8,.type = XPD_TYPE_FXO,.xops =
|
||||||
.name = "FXO", /* protocol name */
|
&fxo_xops,.phoneops = &fxo_phoneops,.packet_is_valid =
|
||||||
.ports_per_subunit = 8,
|
fxo_packet_is_valid,.packet_dump = fxo_packet_dump,};
|
||||||
.type = XPD_TYPE_FXO,
|
|
||||||
.xops = &fxo_xops,
|
|
||||||
.phoneops = &fxo_phoneops,
|
|
||||||
.packet_is_valid = fxo_packet_is_valid,
|
|
||||||
.packet_dump = fxo_packet_dump,
|
|
||||||
};
|
|
||||||
|
|
||||||
static bool fxo_packet_is_valid(xpacket_t *pack)
|
static bool fxo_packet_is_valid(xpacket_t *pack)
|
||||||
{
|
{
|
||||||
@ -1157,7 +1215,8 @@ static void fxo_packet_dump(const char *msg, xpacket_t *pack)
|
|||||||
/*------------------------- DAA Handling --------------------------*/
|
/*------------------------- DAA Handling --------------------------*/
|
||||||
|
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
static int proc_fxo_info_read(char *page, char **start, off_t off, int count, int *eof, void *data)
|
static int proc_fxo_info_read(char *page, char **start, off_t off, int count,
|
||||||
|
int *eof, void *data)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
@ -1172,21 +1231,26 @@ static int proc_fxo_info_read(char *page, char **start, off_t off, int count, in
|
|||||||
BUG_ON(!priv);
|
BUG_ON(!priv);
|
||||||
len += sprintf(page + len, "\t%-17s: ", "Channel");
|
len += sprintf(page + len, "\t%-17s: ", "Channel");
|
||||||
for_each_line(xpd, i) {
|
for_each_line(xpd, i) {
|
||||||
if (!IS_SET(PHONEDEV(xpd).digital_outputs, i) && !IS_SET(PHONEDEV(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, "%4d ", i % 10);
|
||||||
}
|
}
|
||||||
len += sprintf(page + len, "\nLeds:");
|
len += sprintf(page + len, "\nLeds:");
|
||||||
len += sprintf(page + len, "\n\t%-17s: ", "state");
|
len += sprintf(page + len, "\n\t%-17s: ", "state");
|
||||||
for_each_line(xpd, i) {
|
for_each_line(xpd, i) {
|
||||||
if (!IS_SET(PHONEDEV(xpd).digital_outputs, i) && !IS_SET(PHONEDEV(xpd).digital_inputs, i))
|
if (!IS_SET(PHONEDEV(xpd).digital_outputs, i)
|
||||||
len += sprintf(page + len, " %d%d ",
|
&& !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_GREEN], i),
|
||||||
IS_SET(priv->ledstate[LED_RED], i));
|
IS_SET(priv->ledstate[LED_RED], i));
|
||||||
}
|
}
|
||||||
len += sprintf(page + len, "\n\t%-17s: ", "blinking");
|
len += sprintf(page + len, "\n\t%-17s: ", "blinking");
|
||||||
for_each_line(xpd, i) {
|
for_each_line(xpd, i) {
|
||||||
if (!IS_SET(PHONEDEV(xpd).digital_outputs, i) && !IS_SET(PHONEDEV(xpd).digital_inputs, i))
|
if (!IS_SET(PHONEDEV(xpd).digital_outputs, i)
|
||||||
len += sprintf(page + len, " %d%d ",
|
&& !IS_SET(PHONEDEV(xpd).digital_inputs, i))
|
||||||
|
len +=
|
||||||
|
sprintf(page + len, " %d%d ",
|
||||||
IS_BLINKING(priv, i, LED_GREEN),
|
IS_BLINKING(priv, i, LED_GREEN),
|
||||||
IS_BLINKING(priv, i, LED_RED));
|
IS_BLINKING(priv, i, LED_RED));
|
||||||
}
|
}
|
||||||
@ -1248,7 +1312,8 @@ static int proc_fxo_info_read(char *page, char **start, off_t off, int count, in
|
|||||||
}
|
}
|
||||||
len += sprintf(page + len, "\n\t%-17s: ", "safezone");
|
len += sprintf(page + len, "\n\t%-17s: ", "safezone");
|
||||||
for_each_line(xpd, i) {
|
for_each_line(xpd, i) {
|
||||||
len += sprintf(page + len, "%4d ", priv->power_denial_safezone[i]);
|
len +=
|
||||||
|
sprintf(page + len, "%4d ", priv->power_denial_safezone[i]);
|
||||||
}
|
}
|
||||||
len += sprintf(page + len, "\n\t%-17s: ", "delay");
|
len += sprintf(page + len, "\n\t%-17s: ", "delay");
|
||||||
for_each_line(xpd, i) {
|
for_each_line(xpd, i) {
|
||||||
@ -1276,7 +1341,8 @@ static int proc_fxo_info_read(char *page, char **start, off_t off, int count, in
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_METERING
|
#ifdef WITH_METERING
|
||||||
static int proc_xpd_metering_read(char *page, char **start, off_t off, int count, int *eof, void *data)
|
static int proc_xpd_metering_read(char *page, char **start, off_t off,
|
||||||
|
int count, int *eof, void *data)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
@ -1291,8 +1357,8 @@ static int proc_xpd_metering_read(char *page, char **start, off_t off, int count
|
|||||||
spin_lock_irqsave(&xpd->lock, flags);
|
spin_lock_irqsave(&xpd->lock, flags);
|
||||||
len += sprintf(page + len, "# Chan\tMeter (since last read)\n");
|
len += sprintf(page + len, "# Chan\tMeter (since last read)\n");
|
||||||
for_each_line(xpd, i) {
|
for_each_line(xpd, i) {
|
||||||
len += sprintf(page + len, "%d\t%d\n",
|
len +=
|
||||||
i, priv->metering_count[i]);
|
sprintf(page + len, "%d\t%d\n", i, priv->metering_count[i]);
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||||
if (len <= off + count)
|
if (len <= off + count)
|
||||||
@ -1343,7 +1409,6 @@ static DEVICE_ATTR_READER(fxo_battery_show, dev, buf)
|
|||||||
|
|
||||||
static DEVICE_ATTR(fxo_battery, S_IRUGO, fxo_battery_show, NULL);
|
static DEVICE_ATTR(fxo_battery, S_IRUGO, fxo_battery_show, NULL);
|
||||||
|
|
||||||
|
|
||||||
static int fxo_xpd_probe(struct device *dev)
|
static int fxo_xpd_probe(struct device *dev)
|
||||||
{
|
{
|
||||||
xpd_t *xpd;
|
xpd_t *xpd;
|
||||||
@ -1352,14 +1417,15 @@ static int fxo_xpd_probe(struct device *dev)
|
|||||||
xpd = dev_to_xpd(dev);
|
xpd = dev_to_xpd(dev);
|
||||||
/* Is it our device? */
|
/* Is it our device? */
|
||||||
if (xpd->type != XPD_TYPE_FXO) {
|
if (xpd->type != XPD_TYPE_FXO) {
|
||||||
XPD_ERR(xpd, "drop suggestion for %s (%d)\n",
|
XPD_ERR(xpd, "drop suggestion for %s (%d)\n", dev_name(dev),
|
||||||
dev_name(dev), xpd->type);
|
xpd->type);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
XPD_DBG(DEVICES, xpd, "SYSFS\n");
|
XPD_DBG(DEVICES, xpd, "SYSFS\n");
|
||||||
ret = device_create_file(dev, &dev_attr_fxo_battery);
|
ret = device_create_file(dev, &dev_attr_fxo_battery);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
XPD_ERR(xpd, "%s: device_create_file(fxo_battery) failed: %d\n", __func__, ret);
|
XPD_ERR(xpd, "%s: device_create_file(fxo_battery) failed: %d\n",
|
||||||
|
__func__, ret);
|
||||||
goto fail_fxo_battery;
|
goto fail_fxo_battery;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -1385,8 +1451,7 @@ static struct xpd_driver fxo_driver = {
|
|||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
#endif
|
#endif
|
||||||
.probe = fxo_xpd_probe,
|
.probe = fxo_xpd_probe,
|
||||||
.remove = fxo_xpd_remove
|
.remove = fxo_xpd_remove}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init card_fxo_startup(void)
|
static int __init card_fxo_startup(void)
|
||||||
@ -1394,7 +1459,8 @@ static int __init card_fxo_startup(void)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (ring_debounce <= 0) {
|
if (ring_debounce <= 0) {
|
||||||
ERR("ring_debounce=%d. Must be positive number of ticks\n", ring_debounce);
|
ERR("ring_debounce=%d. Must be positive number of ticks\n",
|
||||||
|
ring_debounce);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if ((ret = xpd_driver_register(&fxo_driver.driver)) < 0)
|
if ((ret = xpd_driver_register(&fxo_driver.driver)) < 0)
|
||||||
|
@ -26,15 +26,12 @@
|
|||||||
|
|
||||||
enum fxo_opcodes {
|
enum fxo_opcodes {
|
||||||
XPROTO_NAME(FXO, SIG_CHANGED) = 0x06,
|
XPROTO_NAME(FXO, SIG_CHANGED) = 0x06,
|
||||||
/**/
|
/**/ XPROTO_NAME(FXO, DAA_WRITE) = 0x0F, /* Write to DAA */
|
||||||
XPROTO_NAME(FXO, DAA_WRITE) = 0x0F, /* Write to DAA */
|
|
||||||
XPROTO_NAME(FXO, CHAN_CID) = 0x0F, /* Write to DAA */
|
XPROTO_NAME(FXO, CHAN_CID) = 0x0F, /* Write to DAA */
|
||||||
XPROTO_NAME(FXO, LED) = 0x0F, /* Write to DAA */
|
XPROTO_NAME(FXO, LED) = 0x0F, /* Write to DAA */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
DEF_RPACKET_DATA(FXO, SIG_CHANGED, xpp_line_t sig_status; /* channels: lsb=1, msb=8 */
|
||||||
DEF_RPACKET_DATA(FXO, SIG_CHANGED,
|
|
||||||
xpp_line_t sig_status; /* channels: lsb=1, msb=8 */
|
|
||||||
xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */
|
xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -40,7 +40,8 @@ static DEF_PARM_BOOL(dtmf_detection, 1, 0644, "Do DTMF detection in hardware");
|
|||||||
static DEF_PARM(uint, poll_digital_inputs, 1000, 0644, "Poll Digital Inputs");
|
static DEF_PARM(uint, poll_digital_inputs, 1000, 0644, "Poll Digital Inputs");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static DEF_PARM_BOOL(vmwi_ioctl, 1, 0644, "Asterisk support VMWI notification via ioctl");
|
static DEF_PARM_BOOL(vmwi_ioctl, 1, 0644,
|
||||||
|
"Asterisk support VMWI notification via ioctl");
|
||||||
static DEF_PARM_BOOL(ring_trapez, 0, 0664, "Use trapezoid ring type");
|
static DEF_PARM_BOOL(ring_trapez, 0, 0664, "Use trapezoid ring type");
|
||||||
|
|
||||||
/* Signaling is opposite (fxo signalling for fxs card) */
|
/* Signaling is opposite (fxo signalling for fxs card) */
|
||||||
@ -108,9 +109,11 @@ enum fxs_state {
|
|||||||
static bool fxs_packet_is_valid(xpacket_t *pack);
|
static bool fxs_packet_is_valid(xpacket_t *pack);
|
||||||
static void fxs_packet_dump(const char *msg, xpacket_t *pack);
|
static void fxs_packet_dump(const char *msg, xpacket_t *pack);
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
static int proc_fxs_info_read(char *page, char **start, off_t off, int count, int *eof, void *data);
|
static int proc_fxs_info_read(char *page, char **start, off_t off, int count,
|
||||||
|
int *eof, void *data);
|
||||||
#ifdef WITH_METERING
|
#ifdef WITH_METERING
|
||||||
static int proc_xpd_metering_write(struct file *file, const char __user *buffer, unsigned long count, void *data);
|
static int proc_xpd_metering_write(struct file *file, const char __user *buffer,
|
||||||
|
unsigned long count, void *data);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
static void start_stop_vm_led(xbus_t *xbus, xpd_t *xpd, lineno_t pos);
|
static void start_stop_vm_led(xbus_t *xbus, xpd_t *xpd, lineno_t pos);
|
||||||
@ -157,7 +160,8 @@ struct FXS_priv_data {
|
|||||||
#define LED_BLINK_RING (1000/8) /* in ticks */
|
#define LED_BLINK_RING (1000/8) /* in ticks */
|
||||||
|
|
||||||
/*---------------- FXS: Static functions ----------------------------------*/
|
/*---------------- FXS: Static functions ----------------------------------*/
|
||||||
static int linefeed_control(xbus_t *xbus, xpd_t *xpd, lineno_t chan, enum fxs_state value)
|
static int linefeed_control(xbus_t *xbus, xpd_t *xpd, lineno_t chan,
|
||||||
|
enum fxs_state value)
|
||||||
{
|
{
|
||||||
struct FXS_priv_data *priv;
|
struct FXS_priv_data *priv;
|
||||||
|
|
||||||
@ -174,7 +178,8 @@ static int do_chan_power(xbus_t *xbus, xpd_t *xpd, lineno_t chan, bool on)
|
|||||||
BUG_ON(!xbus);
|
BUG_ON(!xbus);
|
||||||
BUG_ON(!xpd);
|
BUG_ON(!xpd);
|
||||||
LINE_DBG(SIGNAL, xpd, chan, "%s\n", (on) ? "up" : "down");
|
LINE_DBG(SIGNAL, xpd, chan, "%s\n", (on) ? "up" : "down");
|
||||||
return SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, REG_BATTERY, value);
|
return SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, REG_BATTERY,
|
||||||
|
value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vmwi_search(xpd_t *xpd, lineno_t pos, bool on)
|
static void vmwi_search(xpd_t *xpd, lineno_t pos, bool on)
|
||||||
@ -236,7 +241,8 @@ static int do_led(xpd_t *xpd, lineno_t chan, __u8 which, bool on)
|
|||||||
xbus = xpd->xbus;
|
xbus = xpd->xbus;
|
||||||
priv = xpd->priv;
|
priv = xpd->priv;
|
||||||
which = which % NUM_LEDS;
|
which = which % NUM_LEDS;
|
||||||
if (IS_SET(PHONEDEV(xpd).digital_outputs, chan) || IS_SET(PHONEDEV(xpd).digital_inputs, chan))
|
if (IS_SET(PHONEDEV(xpd).digital_outputs, chan)
|
||||||
|
|| IS_SET(PHONEDEV(xpd).digital_inputs, chan))
|
||||||
goto out;
|
goto out;
|
||||||
if (chan == PORT_BROADCAST) {
|
if (chan == PORT_BROADCAST) {
|
||||||
priv->ledstate[which] = (on) ? ~0 : 0;
|
priv->ledstate[which] = (on) ? ~0 : 0;
|
||||||
@ -247,13 +253,15 @@ static int do_led(xpd_t *xpd, lineno_t chan, __u8 which, bool on)
|
|||||||
BIT_CLR(priv->ledstate[which], chan);
|
BIT_CLR(priv->ledstate[which], chan);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LINE_DBG(LEDS, xpd, chan, "LED: which=%d -- %s\n", which, (on) ? "on" : "off");
|
LINE_DBG(LEDS, xpd, chan, "LED: which=%d -- %s\n", which,
|
||||||
|
(on) ? "on" : "off");
|
||||||
value = BIT(2) | BIT(3);
|
value = BIT(2) | BIT(3);
|
||||||
value |= ((BIT(5) | BIT(6) | BIT(7)) & ~led_register_mask[which]);
|
value |= ((BIT(5) | BIT(6) | BIT(7)) & ~led_register_mask[which]);
|
||||||
if (on)
|
if (on)
|
||||||
value |= led_register_vals[which];
|
value |= led_register_vals[which];
|
||||||
ret = SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE,
|
ret =
|
||||||
REG_DIGITAL_IOCTRL, value);
|
SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, REG_DIGITAL_IOCTRL,
|
||||||
|
value);
|
||||||
out:
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -271,7 +279,9 @@ static void handle_fxs_leds(xpd_t *xpd)
|
|||||||
timer_count = xpd->timer_count;
|
timer_count = xpd->timer_count;
|
||||||
for (color = 0; color < ARRAY_SIZE(colors); color++) {
|
for (color = 0; color < ARRAY_SIZE(colors); color++) {
|
||||||
for_each_line(xpd, i) {
|
for_each_line(xpd, i) {
|
||||||
if (IS_SET(PHONEDEV(xpd).digital_outputs | PHONEDEV(xpd).digital_inputs, i))
|
if (IS_SET
|
||||||
|
(PHONEDEV(xpd).digital_outputs | PHONEDEV(xpd).
|
||||||
|
digital_inputs, i))
|
||||||
continue;
|
continue;
|
||||||
if ((xpd->blink_mode & BIT(i)) || IS_BLINKING(priv, i, color)) { // Blinking
|
if ((xpd->blink_mode & BIT(i)) || IS_BLINKING(priv, i, color)) { // Blinking
|
||||||
int mod_value = LED_COUNTER(priv, i, color);
|
int mod_value = LED_COUNTER(priv, i, color);
|
||||||
@ -280,16 +290,25 @@ static void handle_fxs_leds(xpd_t *xpd)
|
|||||||
mod_value = DEFAULT_LED_PERIOD; /* safety value */
|
mod_value = DEFAULT_LED_PERIOD; /* safety value */
|
||||||
// led state is toggled
|
// led state is toggled
|
||||||
if ((timer_count % mod_value) == 0) {
|
if ((timer_count % mod_value) == 0) {
|
||||||
LINE_DBG(LEDS, xpd, i, "ledstate=%s\n", (IS_SET(priv->ledstate[color], i))?"ON":"OFF");
|
LINE_DBG(LEDS, xpd, i, "ledstate=%s\n",
|
||||||
|
(IS_SET
|
||||||
|
(priv->ledstate[color],
|
||||||
|
i)) ? "ON" : "OFF");
|
||||||
if (!IS_SET(priv->ledstate[color], i)) {
|
if (!IS_SET(priv->ledstate[color], i)) {
|
||||||
do_led(xpd, i, color, 1);
|
do_led(xpd, i, color, 1);
|
||||||
} else {
|
} else {
|
||||||
do_led(xpd, i, color, 0);
|
do_led(xpd, i, color, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (IS_SET(priv->ledcontrol[color] & ~priv->ledstate[color], i)) {
|
} else
|
||||||
|
if (IS_SET
|
||||||
|
(priv->ledcontrol[color] & ~priv->
|
||||||
|
ledstate[color], i)) {
|
||||||
do_led(xpd, i, color, 1);
|
do_led(xpd, i, color, 1);
|
||||||
} else if (IS_SET(~priv->ledcontrol[color] & priv->ledstate[color], i)) {
|
} else
|
||||||
|
if (IS_SET
|
||||||
|
(~priv->ledcontrol[color] & priv->
|
||||||
|
ledstate[color], i)) {
|
||||||
do_led(xpd, i, color, 0);
|
do_led(xpd, i, color, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,8 +335,10 @@ static int metering_gen(xpd_t *xpd, lineno_t chan, bool on)
|
|||||||
{
|
{
|
||||||
__u8 value = (on) ? 0x94 : 0x00;
|
__u8 value = (on) ? 0x94 : 0x00;
|
||||||
|
|
||||||
LINE_DBG(SIGNAL, xpd, chan, "METERING Generate: %s\n", (on)?"ON":"OFF");
|
LINE_DBG(SIGNAL, xpd, chan, "METERING Generate: %s\n",
|
||||||
return SLIC_DIRECT_REQUEST(xpd->xbus, xpd, chan, SLIC_WRITE, 0x23, value);
|
(on) ? "ON" : "OFF");
|
||||||
|
return SLIC_DIRECT_REQUEST(xpd->xbus, xpd, chan, SLIC_WRITE, 0x23,
|
||||||
|
value);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -355,18 +376,23 @@ static int fxs_proc_create(xbus_t *xbus, xpd_t *xpd)
|
|||||||
|
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
XPD_DBG(PROC, xpd, "Creating FXS_INFO file\n");
|
XPD_DBG(PROC, xpd, "Creating FXS_INFO file\n");
|
||||||
priv->fxs_info = create_proc_read_entry(PROC_FXS_INFO_FNAME, 0444, xpd->proc_xpd_dir, proc_fxs_info_read, xpd);
|
priv->fxs_info =
|
||||||
|
create_proc_read_entry(PROC_FXS_INFO_FNAME, 0444, xpd->proc_xpd_dir,
|
||||||
|
proc_fxs_info_read, xpd);
|
||||||
if (!priv->fxs_info) {
|
if (!priv->fxs_info) {
|
||||||
XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_FXS_INFO_FNAME);
|
XPD_ERR(xpd, "Failed to create proc file '%s'\n",
|
||||||
|
PROC_FXS_INFO_FNAME);
|
||||||
fxs_proc_remove(xbus, xpd);
|
fxs_proc_remove(xbus, xpd);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
SET_PROC_DIRENTRY_OWNER(priv->fxs_info);
|
SET_PROC_DIRENTRY_OWNER(priv->fxs_info);
|
||||||
#ifdef WITH_METERING
|
#ifdef WITH_METERING
|
||||||
XPD_DBG(PROC, xpd, "Creating Metering tone file\n");
|
XPD_DBG(PROC, xpd, "Creating Metering tone file\n");
|
||||||
priv->meteringfile = create_proc_entry(PROC_METERING_FNAME, 0200, xpd->proc_xpd_dir);
|
priv->meteringfile =
|
||||||
|
create_proc_entry(PROC_METERING_FNAME, 0200, xpd->proc_xpd_dir);
|
||||||
if (!priv->meteringfile) {
|
if (!priv->meteringfile) {
|
||||||
XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_METERING_FNAME);
|
XPD_ERR(xpd, "Failed to create proc file '%s'\n",
|
||||||
|
PROC_METERING_FNAME);
|
||||||
fxs_proc_remove(xbus, xpd);
|
fxs_proc_remove(xbus, xpd);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@ -379,8 +405,9 @@ static int fxs_proc_create(xbus_t *xbus, xpd_t *xpd)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static xpd_t *FXS_card_new(xbus_t *xbus, int unit, int subunit, const xproto_table_t *proto_table,
|
static xpd_t *FXS_card_new(xbus_t *xbus, int unit, int subunit,
|
||||||
__u8 subtype, int subunits, int subunit_ports, bool to_phone)
|
const xproto_table_t *proto_table, __u8 subtype,
|
||||||
|
int subunits, int subunit_ports, bool to_phone)
|
||||||
{
|
{
|
||||||
xpd_t *xpd = NULL;
|
xpd_t *xpd = NULL;
|
||||||
int channels;
|
int channels;
|
||||||
@ -407,7 +434,9 @@ static xpd_t *FXS_card_new(xbus_t *xbus, int unit, int subunit, const xproto_tab
|
|||||||
d_inputs = LINES_DIGI_INP;
|
d_inputs = LINES_DIGI_INP;
|
||||||
d_outputs = LINES_DIGI_OUT;
|
d_outputs = LINES_DIGI_OUT;
|
||||||
}
|
}
|
||||||
xpd = xpd_alloc(xbus, unit, subunit, subtype, subunits, sizeof(struct FXS_priv_data), proto_table, channels);
|
xpd =
|
||||||
|
xpd_alloc(xbus, unit, subunit, subtype, subunits,
|
||||||
|
sizeof(struct FXS_priv_data), proto_table, channels);
|
||||||
if (!xpd)
|
if (!xpd)
|
||||||
return NULL;
|
return NULL;
|
||||||
/* Initialize digital inputs/outputs */
|
/* Initialize digital inputs/outputs */
|
||||||
@ -476,9 +505,12 @@ static int FXS_card_init(xbus_t *xbus, xpd_t *xpd)
|
|||||||
* So we do this after the LEDs
|
* So we do this after the LEDs
|
||||||
*/
|
*/
|
||||||
for_each_line(xpd, i) {
|
for_each_line(xpd, i) {
|
||||||
if (IS_SET(PHONEDEV(xpd).digital_outputs | PHONEDEV(xpd).digital_inputs, i))
|
if (IS_SET
|
||||||
|
(PHONEDEV(xpd).digital_outputs | PHONEDEV(xpd).
|
||||||
|
digital_inputs, i))
|
||||||
continue;
|
continue;
|
||||||
SLIC_DIRECT_REQUEST(xbus, xpd, i, SLIC_READ, REG_LOOPCLOSURE, 0);
|
SLIC_DIRECT_REQUEST(xbus, xpd, i, SLIC_READ, REG_LOOPCLOSURE,
|
||||||
|
0);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
err:
|
err:
|
||||||
@ -513,14 +545,17 @@ static int FXS_card_dahdi_preregistration(xpd_t *xpd, bool on)
|
|||||||
|
|
||||||
XPD_DBG(GENERAL, xpd, "setting FXS channel %d\n", i);
|
XPD_DBG(GENERAL, xpd, "setting FXS channel %d\n", i);
|
||||||
if (IS_SET(PHONEDEV(xpd).digital_outputs, i)) {
|
if (IS_SET(PHONEDEV(xpd).digital_outputs, i)) {
|
||||||
snprintf(cur_chan->name, MAX_CHANNAME, "XPP_OUT/%02d/%1d%1d/%d",
|
snprintf(cur_chan->name, MAX_CHANNAME,
|
||||||
xbus->num, xpd->addr.unit, xpd->addr.subunit, i);
|
"XPP_OUT/%02d/%1d%1d/%d", xbus->num,
|
||||||
|
xpd->addr.unit, xpd->addr.subunit, i);
|
||||||
} else if (IS_SET(PHONEDEV(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",
|
snprintf(cur_chan->name, MAX_CHANNAME,
|
||||||
xbus->num, xpd->addr.unit, xpd->addr.subunit, i);
|
"XPP_IN/%02d/%1d%1d/%d", xbus->num,
|
||||||
|
xpd->addr.unit, xpd->addr.subunit, i);
|
||||||
} else {
|
} else {
|
||||||
snprintf(cur_chan->name, MAX_CHANNAME, "XPP_FXS/%02d/%1d%1d/%d",
|
snprintf(cur_chan->name, MAX_CHANNAME,
|
||||||
xbus->num, xpd->addr.unit, xpd->addr.subunit, i);
|
"XPP_FXS/%02d/%1d%1d/%d", xbus->num,
|
||||||
|
xpd->addr.unit, xpd->addr.subunit, i);
|
||||||
}
|
}
|
||||||
cur_chan->chanpos = i + 1;
|
cur_chan->chanpos = i + 1;
|
||||||
cur_chan->pvt = xpd;
|
cur_chan->pvt = xpd;
|
||||||
@ -590,54 +625,83 @@ static int set_vm_led_mode(xbus_t *xbus, xpd_t *xpd, int pos,
|
|||||||
/* A write to register 0x40 will now turn on/off the VM led */
|
/* A write to register 0x40 will now turn on/off the VM led */
|
||||||
LINE_DBG(SIGNAL, xpd, pos, "NEON\n");
|
LINE_DBG(SIGNAL, xpd, pos, "NEON\n");
|
||||||
BIT_SET(priv->neon_blinking, pos);
|
BIT_SET(priv->neon_blinking, pos);
|
||||||
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x16, 0xE8, 0x03);
|
ret +=
|
||||||
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x15, 0xEF, 0x7B);
|
SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x16,
|
||||||
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x14, 0x9F, 0x00);
|
0xE8, 0x03);
|
||||||
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x22, 0x19);
|
ret +=
|
||||||
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x30, 0xE0);
|
SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x15,
|
||||||
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x31, 0x01);
|
0xEF, 0x7B);
|
||||||
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x32, 0xF0);
|
ret +=
|
||||||
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x33, 0x05);
|
SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x14,
|
||||||
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x1D, 0x00, 0x46);
|
0x9F, 0x00);
|
||||||
|
ret +=
|
||||||
|
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x22, 0x19);
|
||||||
|
ret +=
|
||||||
|
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x30, 0xE0);
|
||||||
|
ret +=
|
||||||
|
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x31, 0x01);
|
||||||
|
ret +=
|
||||||
|
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x32, 0xF0);
|
||||||
|
ret +=
|
||||||
|
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x33, 0x05);
|
||||||
|
ret +=
|
||||||
|
SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x1D,
|
||||||
|
0x00, 0x46);
|
||||||
} else if (ring_trapez) {
|
} else if (ring_trapez) {
|
||||||
LINE_DBG(SIGNAL, xpd, pos, "RINGER: Trapez ring\n");
|
LINE_DBG(SIGNAL, xpd, pos, "RINGER: Trapez ring\n");
|
||||||
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos,
|
ret +=
|
||||||
SLIC_WRITE, 0x16, 0xC8, 0x00);
|
SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x16,
|
||||||
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos,
|
0xC8, 0x00);
|
||||||
SLIC_WRITE, 0x15, 0xAB, 0x5E);
|
ret +=
|
||||||
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos,
|
SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x15,
|
||||||
SLIC_WRITE, 0x14, 0x8C, 0x01);
|
0xAB, 0x5E);
|
||||||
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos,
|
ret +=
|
||||||
SLIC_WRITE, 0x22, 0x01);
|
SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x14,
|
||||||
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos,
|
0x8C, 0x01);
|
||||||
SLIC_WRITE, 0x4A, 0x34);
|
ret +=
|
||||||
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos,
|
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x22, 0x01);
|
||||||
SLIC_WRITE, 0x30, 0x00);
|
ret +=
|
||||||
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos,
|
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x4A, 0x34);
|
||||||
SLIC_WRITE, 0x31, 0x00);
|
ret +=
|
||||||
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos,
|
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x30, 0x00);
|
||||||
SLIC_WRITE, 0x32, 0x00);
|
ret +=
|
||||||
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos,
|
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x31, 0x00);
|
||||||
SLIC_WRITE, 0x33, 0x00);
|
ret +=
|
||||||
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos,
|
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x32, 0x00);
|
||||||
SLIC_WRITE, 0x1D, 0x00, 0x36);
|
ret +=
|
||||||
|
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x33, 0x00);
|
||||||
|
ret +=
|
||||||
|
SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x1D,
|
||||||
|
0x00, 0x36);
|
||||||
} else {
|
} else {
|
||||||
/* A write to register 0x40 will now turn on/off the ringer */
|
/* A write to register 0x40 will now turn on/off the ringer */
|
||||||
LINE_DBG(SIGNAL, xpd, pos, "RINGER\n");
|
LINE_DBG(SIGNAL, xpd, pos, "RINGER\n");
|
||||||
BIT_CLR(priv->neon_blinking, pos);
|
BIT_CLR(priv->neon_blinking, pos);
|
||||||
|
|
||||||
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x16, 0x00, 0x00);
|
ret +=
|
||||||
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x15, 0x77, 0x01);
|
SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x16,
|
||||||
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x14, 0xFD, 0x7E);
|
0x00, 0x00);
|
||||||
|
ret +=
|
||||||
|
SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x15,
|
||||||
|
0x77, 0x01);
|
||||||
|
ret +=
|
||||||
|
SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x14,
|
||||||
|
0xFD, 0x7E);
|
||||||
|
|
||||||
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x22, 0x00);
|
ret +=
|
||||||
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x30, 0x00);
|
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x22, 0x00);
|
||||||
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x31, 0x00);
|
ret +=
|
||||||
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x32, 0x00);
|
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x30, 0x00);
|
||||||
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x33, 0x00);
|
ret +=
|
||||||
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
|
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x31, 0x00);
|
||||||
0x4A, 0x34);/* High Vbat~ -82V[Dc] */
|
ret +=
|
||||||
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x1D, 0x00, 0x36);
|
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x32, 0x00);
|
||||||
|
ret +=
|
||||||
|
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x33, 0x00);
|
||||||
|
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x4A, 0x34); /* High Vbat~ -82V[Dc] */
|
||||||
|
ret +=
|
||||||
|
SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x1D,
|
||||||
|
0x00, 0x36);
|
||||||
}
|
}
|
||||||
return (ret ? -EPROTO : 0);
|
return (ret ? -EPROTO : 0);
|
||||||
}
|
}
|
||||||
@ -648,15 +712,17 @@ static void start_stop_vm_led(xbus_t *xbus, xpd_t *xpd, lineno_t pos)
|
|||||||
unsigned int msgs;
|
unsigned int msgs;
|
||||||
|
|
||||||
BUG_ON(!xpd);
|
BUG_ON(!xpd);
|
||||||
if (IS_SET(PHONEDEV(xpd).digital_outputs | PHONEDEV(xpd).digital_inputs, pos))
|
if (IS_SET
|
||||||
|
(PHONEDEV(xpd).digital_outputs | PHONEDEV(xpd).digital_inputs, pos))
|
||||||
return;
|
return;
|
||||||
priv = xpd->priv;
|
priv = xpd->priv;
|
||||||
msgs = PHONEDEV(xpd).msg_waiting[pos];
|
msgs = PHONEDEV(xpd).msg_waiting[pos];
|
||||||
LINE_DBG(SIGNAL, xpd, pos, "%s\n", (msgs) ? "ON" : "OFF");
|
LINE_DBG(SIGNAL, xpd, pos, "%s\n", (msgs) ? "ON" : "OFF");
|
||||||
set_vm_led_mode(xbus, xpd, pos, msgs);
|
set_vm_led_mode(xbus, xpd, pos, msgs);
|
||||||
do_chan_power(xbus, xpd, pos, msgs > 0);
|
do_chan_power(xbus, xpd, pos, msgs > 0);
|
||||||
linefeed_control(xbus, xpd, pos, (msgs > 0) ?
|
linefeed_control(xbus, xpd, pos,
|
||||||
FXS_LINE_RING : priv->idletxhookstate[pos]);
|
(msgs >
|
||||||
|
0) ? FXS_LINE_RING : priv->idletxhookstate[pos]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int relay_out(xpd_t *xpd, int pos, bool on)
|
static int relay_out(xpd_t *xpd, int pos, bool on)
|
||||||
@ -668,10 +734,12 @@ static int relay_out(xpd_t *xpd, int pos, bool on)
|
|||||||
BUG_ON(!xpd);
|
BUG_ON(!xpd);
|
||||||
/* map logical position to output port number (0/1) */
|
/* map logical position to output port number (0/1) */
|
||||||
which -= (xpd->subtype == 2) ? 6 : 8;
|
which -= (xpd->subtype == 2) ? 6 : 8;
|
||||||
LINE_DBG(SIGNAL, xpd, pos, "which=%d -- %s\n", which, (on) ? "on" : "off");
|
LINE_DBG(SIGNAL, xpd, pos, "which=%d -- %s\n", which,
|
||||||
|
(on) ? "on" : "off");
|
||||||
which = which % ARRAY_SIZE(relay_channels);
|
which = which % ARRAY_SIZE(relay_channels);
|
||||||
value = BIT(2) | BIT(3);
|
value = BIT(2) | BIT(3);
|
||||||
value |= ((BIT(5) | BIT(6) | BIT(7)) & ~led_register_mask[OUTPUT_RELAY]);
|
value |=
|
||||||
|
((BIT(5) | BIT(6) | BIT(7)) & ~led_register_mask[OUTPUT_RELAY]);
|
||||||
if (on)
|
if (on)
|
||||||
value |= led_register_vals[OUTPUT_RELAY];
|
value |= led_register_vals[OUTPUT_RELAY];
|
||||||
return SLIC_DIRECT_REQUEST(xpd->xbus, xpd, relay_channels[which],
|
return SLIC_DIRECT_REQUEST(xpd->xbus, xpd, relay_channels[which],
|
||||||
@ -714,7 +782,8 @@ static int FXS_card_hooksig(xpd_t *xpd, int pos, enum dahdi_txsig txsig)
|
|||||||
priv = xpd->priv;
|
priv = xpd->priv;
|
||||||
BUG_ON(PHONEDEV(xpd).direction != TO_PHONE);
|
BUG_ON(PHONEDEV(xpd).direction != TO_PHONE);
|
||||||
if (IS_SET(PHONEDEV(xpd).digital_inputs, pos)) {
|
if (IS_SET(PHONEDEV(xpd).digital_inputs, pos)) {
|
||||||
LINE_DBG(SIGNAL, xpd, pos, "Ignoring signal sent to digital input line\n");
|
LINE_DBG(SIGNAL, xpd, pos,
|
||||||
|
"Ignoring signal sent to digital input line\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (SPAN_REGISTERED(xpd))
|
if (SPAN_REGISTERED(xpd))
|
||||||
@ -730,7 +799,8 @@ static int FXS_card_hooksig(xpd_t *xpd, int pos, enum dahdi_txsig txsig)
|
|||||||
__do_mute_dtmf(xpd, pos, 0);
|
__do_mute_dtmf(xpd, pos, 0);
|
||||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||||
if (IS_SET(PHONEDEV(xpd).digital_outputs, pos)) {
|
if (IS_SET(PHONEDEV(xpd).digital_outputs, pos)) {
|
||||||
LINE_DBG(SIGNAL, xpd, pos, "%s -> digital output OFF\n", txsig2str(txsig));
|
LINE_DBG(SIGNAL, xpd, pos, "%s -> digital output OFF\n",
|
||||||
|
txsig2str(txsig));
|
||||||
ret = relay_out(xpd, pos, 0);
|
ret = relay_out(xpd, pos, 0);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -739,7 +809,8 @@ static int FXS_card_hooksig(xpd_t *xpd, int pos, enum dahdi_txsig txsig)
|
|||||||
* Restore state after KEWL hangup.
|
* Restore state after KEWL hangup.
|
||||||
*/
|
*/
|
||||||
LINE_DBG(SIGNAL, xpd, pos, "KEWL STOP\n");
|
LINE_DBG(SIGNAL, xpd, pos, "KEWL STOP\n");
|
||||||
linefeed_control(xpd->xbus, xpd, pos, FXS_LINE_POL_ACTIVE);
|
linefeed_control(xpd->xbus, xpd, pos,
|
||||||
|
FXS_LINE_POL_ACTIVE);
|
||||||
if (IS_OFFHOOK(xpd, pos))
|
if (IS_OFFHOOK(xpd, pos))
|
||||||
MARK_ON(priv, pos, LED_GREEN);
|
MARK_ON(priv, pos, LED_GREEN);
|
||||||
}
|
}
|
||||||
@ -763,7 +834,9 @@ static int FXS_card_hooksig(xpd_t *xpd, int pos, enum dahdi_txsig txsig)
|
|||||||
break;
|
break;
|
||||||
case DAHDI_TXSIG_OFFHOOK:
|
case DAHDI_TXSIG_OFFHOOK:
|
||||||
if (IS_SET(PHONEDEV(xpd).digital_outputs, pos)) {
|
if (IS_SET(PHONEDEV(xpd).digital_outputs, pos)) {
|
||||||
LINE_NOTICE(xpd, pos, "%s -> Is digital output. Ignored\n", txsig2str(txsig));
|
LINE_NOTICE(xpd, pos,
|
||||||
|
"%s -> Is digital output. Ignored\n",
|
||||||
|
txsig2str(txsig));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
txhook = priv->lasttxhook[pos];
|
txhook = priv->lasttxhook[pos];
|
||||||
@ -789,7 +862,8 @@ static int FXS_card_hooksig(xpd_t *xpd, int pos, enum dahdi_txsig txsig)
|
|||||||
oht_pcm(xpd, pos, 0);
|
oht_pcm(xpd, pos, 0);
|
||||||
vmwi_search(xpd, pos, 0);
|
vmwi_search(xpd, pos, 0);
|
||||||
if (IS_SET(PHONEDEV(xpd).digital_outputs, pos)) {
|
if (IS_SET(PHONEDEV(xpd).digital_outputs, pos)) {
|
||||||
LINE_DBG(SIGNAL, xpd, pos, "%s -> digital output ON\n", txsig2str(txsig));
|
LINE_DBG(SIGNAL, xpd, pos, "%s -> digital output ON\n",
|
||||||
|
txsig2str(txsig));
|
||||||
ret = relay_out(xpd, pos, 1);
|
ret = relay_out(xpd, pos, 1);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -797,15 +871,17 @@ static int FXS_card_hooksig(xpd_t *xpd, int pos, enum dahdi_txsig txsig)
|
|||||||
break;
|
break;
|
||||||
case DAHDI_TXSIG_KEWL:
|
case DAHDI_TXSIG_KEWL:
|
||||||
if (IS_SET(PHONEDEV(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));
|
LINE_DBG(SIGNAL, xpd, pos,
|
||||||
|
"%s -> Is digital output. Ignored\n",
|
||||||
|
txsig2str(txsig));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
linefeed_control(xpd->xbus, xpd, pos, FXS_LINE_OPEN);
|
linefeed_control(xpd->xbus, xpd, pos, FXS_LINE_OPEN);
|
||||||
MARK_OFF(priv, pos, LED_GREEN);
|
MARK_OFF(priv, pos, LED_GREEN);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
XPD_NOTICE(xpd, "%s: Can't set tx state to %s (%d)\n",
|
XPD_NOTICE(xpd, "%s: Can't set tx state to %s (%d)\n", __func__,
|
||||||
__func__, txsig2str(txsig), txsig);
|
txsig2str(txsig), txsig);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@ -815,21 +891,20 @@ static int set_vmwi(xpd_t *xpd, int pos, unsigned long arg)
|
|||||||
{
|
{
|
||||||
struct FXS_priv_data *priv;
|
struct FXS_priv_data *priv;
|
||||||
struct dahdi_vmwi_info vmwisetting;
|
struct dahdi_vmwi_info vmwisetting;
|
||||||
const int vmwi_flags = DAHDI_VMWI_LREV | DAHDI_VMWI_HVDC
|
const int vmwi_flags =
|
||||||
| DAHDI_VMWI_HVAC;
|
DAHDI_VMWI_LREV | DAHDI_VMWI_HVDC | DAHDI_VMWI_HVAC;
|
||||||
|
|
||||||
priv = xpd->priv;
|
priv = xpd->priv;
|
||||||
BUG_ON(!priv);
|
BUG_ON(!priv);
|
||||||
if (copy_from_user(&vmwisetting, (__user void *)arg,
|
if (copy_from_user
|
||||||
sizeof(vmwisetting)))
|
(&vmwisetting, (__user void *)arg, sizeof(vmwisetting)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if ((vmwisetting.vmwi_type & ~vmwi_flags) != 0) {
|
if ((vmwisetting.vmwi_type & ~vmwi_flags) != 0) {
|
||||||
LINE_NOTICE(xpd, pos, "Bad DAHDI_VMWI_CONFIG: 0x%X\n",
|
LINE_NOTICE(xpd, pos, "Bad DAHDI_VMWI_CONFIG: 0x%X\n",
|
||||||
vmwisetting.vmwi_type);
|
vmwisetting.vmwi_type);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
LINE_DBG(SIGNAL, xpd, pos,
|
LINE_DBG(SIGNAL, xpd, pos, "DAHDI_VMWI_CONFIG: 0x%X\n",
|
||||||
"DAHDI_VMWI_CONFIG: 0x%X\n",
|
|
||||||
vmwisetting.vmwi_type);
|
vmwisetting.vmwi_type);
|
||||||
if (VMWI_TYPE(priv, pos, LREV)) {
|
if (VMWI_TYPE(priv, pos, LREV)) {
|
||||||
LINE_NOTICE(xpd, pos,
|
LINE_NOTICE(xpd, pos,
|
||||||
@ -856,7 +931,8 @@ static int set_vmwi(xpd_t *xpd, int pos, unsigned long arg)
|
|||||||
* Private ioctl()
|
* Private ioctl()
|
||||||
* We don't need it now, since we detect vmwi via FSK patterns
|
* We don't need it now, since we detect vmwi via FSK patterns
|
||||||
*/
|
*/
|
||||||
static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long arg)
|
static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd,
|
||||||
|
unsigned long arg)
|
||||||
{
|
{
|
||||||
struct FXS_priv_data *priv;
|
struct FXS_priv_data *priv;
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
@ -871,8 +947,8 @@ static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long a
|
|||||||
if (!XBUS_IS(xbus, READY))
|
if (!XBUS_IS(xbus, READY))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
if (pos < 0 || pos >= PHONEDEV(xpd).channels) {
|
if (pos < 0 || pos >= PHONEDEV(xpd).channels) {
|
||||||
XPD_NOTICE(xpd, "Bad channel number %d in %s(), cmd=%u\n",
|
XPD_NOTICE(xpd, "Bad channel number %d in %s(), cmd=%u\n", pos,
|
||||||
pos, __func__, cmd);
|
__func__, cmd);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -880,17 +956,23 @@ static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long a
|
|||||||
case DAHDI_ONHOOKTRANSFER:
|
case DAHDI_ONHOOKTRANSFER:
|
||||||
if (get_user(val, (int __user *)arg))
|
if (get_user(val, (int __user *)arg))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
LINE_DBG(SIGNAL, xpd, pos, "DAHDI_ONHOOKTRANSFER (%d millis)\n", val);
|
LINE_DBG(SIGNAL, xpd, pos, "DAHDI_ONHOOKTRANSFER (%d millis)\n",
|
||||||
if (IS_SET(PHONEDEV(xpd).digital_inputs | PHONEDEV(xpd).digital_outputs, pos))
|
val);
|
||||||
|
if (IS_SET
|
||||||
|
(PHONEDEV(xpd).digital_inputs | PHONEDEV(xpd).
|
||||||
|
digital_outputs, pos))
|
||||||
return 0; /* Nothing to do */
|
return 0; /* Nothing to do */
|
||||||
oht_pcm(xpd, pos, 1); /* Get ready of VMWI FSK tones */
|
oht_pcm(xpd, pos, 1); /* Get ready of VMWI FSK tones */
|
||||||
if (priv->lasttxhook[pos] == FXS_LINE_POL_ACTIVE ||
|
if (priv->lasttxhook[pos] == FXS_LINE_POL_ACTIVE
|
||||||
IS_SET(priv->neon_blinking, pos)) {
|
|| IS_SET(priv->neon_blinking, pos)) {
|
||||||
priv->ohttimer[pos] = val;
|
priv->ohttimer[pos] = val;
|
||||||
priv->idletxhookstate[pos] = FXS_LINE_POL_OHTRANS;
|
priv->idletxhookstate[pos] = FXS_LINE_POL_OHTRANS;
|
||||||
vmwi_search(xpd, pos, 1);
|
vmwi_search(xpd, pos, 1);
|
||||||
CALL_PHONE_METHOD(card_pcm_recompute, xpd, priv->search_fsk_pattern);
|
CALL_PHONE_METHOD(card_pcm_recompute, xpd,
|
||||||
LINE_DBG(SIGNAL, xpd, pos, "Start OHT_TIMER. wanted_pcm_mask=0x%X\n", PHONEDEV(xpd).wanted_pcm_mask);
|
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))
|
if (VMWI_NEON(priv, pos) && !IS_OFFHOOK(xpd, pos))
|
||||||
start_stop_vm_led(xbus, xpd, pos);
|
start_stop_vm_led(xbus, xpd, pos);
|
||||||
@ -898,7 +980,8 @@ static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long a
|
|||||||
case DAHDI_TONEDETECT:
|
case DAHDI_TONEDETECT:
|
||||||
if (get_user(val, (int __user *)arg))
|
if (get_user(val, (int __user *)arg))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
LINE_DBG(SIGNAL, xpd, pos, "DAHDI_TONEDETECT: %s %s (dtmf_detection=%s)\n",
|
LINE_DBG(SIGNAL, xpd, pos,
|
||||||
|
"DAHDI_TONEDETECT: %s %s (dtmf_detection=%s)\n",
|
||||||
(val & DAHDI_TONEDETECT_ON) ? "ON" : "OFF",
|
(val & DAHDI_TONEDETECT_ON) ? "ON" : "OFF",
|
||||||
(val & DAHDI_TONEDETECT_MUTE) ? "MUTE" : "NO-MUTE",
|
(val & DAHDI_TONEDETECT_MUTE) ? "MUTE" : "NO-MUTE",
|
||||||
(dtmf_detection ? "YES" : "NO"));
|
(dtmf_detection ? "YES" : "NO"));
|
||||||
@ -906,7 +989,8 @@ static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long a
|
|||||||
spin_lock_irqsave(&xpd->lock, flags);
|
spin_lock_irqsave(&xpd->lock, flags);
|
||||||
if (IS_SET(priv->want_dtmf_events, pos)) {
|
if (IS_SET(priv->want_dtmf_events, pos)) {
|
||||||
/* Detection mode changed: Disable DTMF interrupts */
|
/* Detection mode changed: Disable DTMF interrupts */
|
||||||
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x17, 0);
|
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
|
||||||
|
0x17, 0);
|
||||||
}
|
}
|
||||||
BIT_CLR(priv->want_dtmf_events, pos);
|
BIT_CLR(priv->want_dtmf_events, pos);
|
||||||
BIT_CLR(priv->want_dtmf_mute, pos);
|
BIT_CLR(priv->want_dtmf_mute, pos);
|
||||||
@ -925,7 +1009,8 @@ static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long a
|
|||||||
/* Detection mode changed: Enable DTMF interrupts */
|
/* Detection mode changed: Enable DTMF interrupts */
|
||||||
LINE_DBG(SIGNAL, xpd, pos,
|
LINE_DBG(SIGNAL, xpd, pos,
|
||||||
"DAHDI_TONEDETECT: Enable Hardware DTMF\n");
|
"DAHDI_TONEDETECT: Enable Hardware DTMF\n");
|
||||||
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x17, 1);
|
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
|
||||||
|
0x17, 1);
|
||||||
}
|
}
|
||||||
BIT_SET(priv->want_dtmf_events, pos);
|
BIT_SET(priv->want_dtmf_events, pos);
|
||||||
} else {
|
} else {
|
||||||
@ -933,7 +1018,8 @@ static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long a
|
|||||||
/* Detection mode changed: Disable DTMF interrupts */
|
/* Detection mode changed: Disable DTMF interrupts */
|
||||||
LINE_DBG(SIGNAL, xpd, pos,
|
LINE_DBG(SIGNAL, xpd, pos,
|
||||||
"DAHDI_TONEDETECT: Disable Hardware DTMF\n");
|
"DAHDI_TONEDETECT: Disable Hardware DTMF\n");
|
||||||
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x17, 0);
|
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
|
||||||
|
0x17, 0);
|
||||||
}
|
}
|
||||||
BIT_CLR(priv->want_dtmf_events, pos);
|
BIT_CLR(priv->want_dtmf_events, pos);
|
||||||
}
|
}
|
||||||
@ -963,13 +1049,15 @@ static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long a
|
|||||||
* asterisk in wrong state (e.g: while ringing).
|
* asterisk in wrong state (e.g: while ringing).
|
||||||
* In these cases, silently ignore it.
|
* In these cases, silently ignore it.
|
||||||
*/
|
*/
|
||||||
if (priv->lasttxhook[pos] == FXS_LINE_RING || priv->lasttxhook[pos] == FXS_LINE_OPEN) {
|
if (priv->lasttxhook[pos] == FXS_LINE_RING
|
||||||
|
|| priv->lasttxhook[pos] == FXS_LINE_OPEN) {
|
||||||
LINE_DBG(SIGNAL, xpd, pos,
|
LINE_DBG(SIGNAL, xpd, pos,
|
||||||
"DAHDI_SETPOLARITY: %s Cannot change when lasttxhook=0x%X\n",
|
"DAHDI_SETPOLARITY: %s Cannot change when lasttxhook=0x%X\n",
|
||||||
(val) ? "ON" : "OFF", priv->lasttxhook[pos]);
|
(val) ? "ON" : "OFF", priv->lasttxhook[pos]);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
LINE_DBG(SIGNAL, xpd, pos, "DAHDI_SETPOLARITY: %s\n", (val)?"ON":"OFF");
|
LINE_DBG(SIGNAL, xpd, pos, "DAHDI_SETPOLARITY: %s\n",
|
||||||
|
(val) ? "ON" : "OFF");
|
||||||
if ((val && !reversepolarity) || (!val && reversepolarity))
|
if ((val && !reversepolarity) || (!val && reversepolarity))
|
||||||
priv->lasttxhook[pos] |= FXS_LINE_RING;
|
priv->lasttxhook[pos] |= FXS_LINE_RING;
|
||||||
else
|
else
|
||||||
@ -992,7 +1080,9 @@ static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long a
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* Digital inputs/outputs don't have VM leds */
|
/* Digital inputs/outputs don't have VM leds */
|
||||||
if (IS_SET(PHONEDEV(xpd).digital_inputs | PHONEDEV(xpd).digital_outputs, pos))
|
if (IS_SET
|
||||||
|
(PHONEDEV(xpd).digital_inputs | PHONEDEV(xpd).
|
||||||
|
digital_outputs, pos))
|
||||||
return 0;
|
return 0;
|
||||||
PHONEDEV(xpd).msg_waiting[pos] = val;
|
PHONEDEV(xpd).msg_waiting[pos] = val;
|
||||||
LINE_DBG(SIGNAL, xpd, pos, "DAHDI_VMWI: %s\n",
|
LINE_DBG(SIGNAL, xpd, pos, "DAHDI_VMWI: %s\n",
|
||||||
@ -1068,8 +1158,8 @@ static void handle_linefeed(xpd_t *xpd)
|
|||||||
priv = xpd->priv;
|
priv = xpd->priv;
|
||||||
BUG_ON(!priv);
|
BUG_ON(!priv);
|
||||||
for_each_line(xpd, i) {
|
for_each_line(xpd, i) {
|
||||||
if (priv->lasttxhook[i] == FXS_LINE_RING &&
|
if (priv->lasttxhook[i] == FXS_LINE_RING
|
||||||
!IS_SET(priv->neon_blinking, i)) {
|
&& !IS_SET(priv->neon_blinking, i)) {
|
||||||
/* RINGing, prepare for OHT */
|
/* RINGing, prepare for OHT */
|
||||||
priv->ohttimer[i] = OHT_TIMER;
|
priv->ohttimer[i] = OHT_TIMER;
|
||||||
priv->idletxhookstate[i] = FXS_LINE_POL_OHTRANS;
|
priv->idletxhookstate[i] = FXS_LINE_POL_OHTRANS;
|
||||||
@ -1077,13 +1167,18 @@ static void handle_linefeed(xpd_t *xpd)
|
|||||||
if (priv->ohttimer[i]) {
|
if (priv->ohttimer[i]) {
|
||||||
priv->ohttimer[i]--;
|
priv->ohttimer[i]--;
|
||||||
if (!priv->ohttimer[i]) {
|
if (!priv->ohttimer[i]) {
|
||||||
LINE_DBG(SIGNAL, xpd, i, "ohttimer expired\n");
|
LINE_DBG(SIGNAL, xpd, i,
|
||||||
priv->idletxhookstate[i] = FXS_LINE_POL_ACTIVE;
|
"ohttimer expired\n");
|
||||||
|
priv->idletxhookstate[i] =
|
||||||
|
FXS_LINE_POL_ACTIVE;
|
||||||
oht_pcm(xpd, i, 0);
|
oht_pcm(xpd, i, 0);
|
||||||
vmwi_search(xpd, i, 0);
|
vmwi_search(xpd, i, 0);
|
||||||
if (priv->lasttxhook[i] == FXS_LINE_POL_OHTRANS) {
|
if (priv->lasttxhook[i] ==
|
||||||
|
FXS_LINE_POL_OHTRANS) {
|
||||||
/* Apply the change if appropriate */
|
/* Apply the change if appropriate */
|
||||||
linefeed_control(xpd->xbus, xpd, i, FXS_LINE_POL_ACTIVE);
|
linefeed_control(xpd->xbus, xpd,
|
||||||
|
i,
|
||||||
|
FXS_LINE_POL_ACTIVE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1112,9 +1207,12 @@ static void detect_vmwi(xpd_t *xpd)
|
|||||||
{
|
{
|
||||||
struct FXS_priv_data *priv;
|
struct FXS_priv_data *priv;
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
static const __u8 FSK_COMMON_PATTERN[] = { 0xA8, 0x49, 0x22, 0x3B, 0x9F, 0xFF, 0x1F, 0xBB };
|
static const __u8 FSK_COMMON_PATTERN[] =
|
||||||
static const __u8 FSK_ON_PATTERN[] = { 0xA2, 0x2C, 0x1F, 0x2C, 0xBB, 0xA1, 0xA5, 0xFF };
|
{ 0xA8, 0x49, 0x22, 0x3B, 0x9F, 0xFF, 0x1F, 0xBB };
|
||||||
static const __u8 FSK_OFF_PATTERN[] = { 0xA2, 0x2C, 0x28, 0xA5, 0xB1, 0x21, 0x49, 0x9F };
|
static const __u8 FSK_ON_PATTERN[] =
|
||||||
|
{ 0xA2, 0x2C, 0x1F, 0x2C, 0xBB, 0xA1, 0xA5, 0xFF };
|
||||||
|
static const __u8 FSK_OFF_PATTERN[] =
|
||||||
|
{ 0xA2, 0x2C, 0x28, 0xA5, 0xB1, 0x21, 0x49, 0x9F };
|
||||||
int i;
|
int i;
|
||||||
xpp_line_t ignore_mask;
|
xpp_line_t ignore_mask;
|
||||||
|
|
||||||
@ -1123,11 +1221,10 @@ static void detect_vmwi(xpd_t *xpd)
|
|||||||
priv = xpd->priv;
|
priv = xpd->priv;
|
||||||
BUG_ON(!priv);
|
BUG_ON(!priv);
|
||||||
ignore_mask =
|
ignore_mask =
|
||||||
PHONEDEV(xpd).offhook_state |
|
PHONEDEV(xpd).offhook_state | ~(PHONEDEV(xpd).
|
||||||
~(PHONEDEV(xpd).oht_pcm_pass) |
|
oht_pcm_pass) | ~(priv->
|
||||||
~(priv->search_fsk_pattern) |
|
search_fsk_pattern)
|
||||||
PHONEDEV(xpd).digital_inputs |
|
| PHONEDEV(xpd).digital_inputs | PHONEDEV(xpd).digital_outputs;
|
||||||
PHONEDEV(xpd).digital_outputs;
|
|
||||||
for_each_line(xpd, i) {
|
for_each_line(xpd, i) {
|
||||||
struct dahdi_chan *chan = XPD_CHAN(xpd, i);
|
struct dahdi_chan *chan = XPD_CHAN(xpd, i);
|
||||||
__u8 *writechunk = chan->writechunk;
|
__u8 *writechunk = chan->writechunk;
|
||||||
@ -1147,17 +1244,26 @@ static void detect_vmwi(xpd_t *xpd)
|
|||||||
printk("\n");
|
printk("\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (unlikely(mem_equal(writechunk, FSK_COMMON_PATTERN, DAHDI_CHUNKSIZE))) {
|
if (unlikely
|
||||||
LINE_DBG(SIGNAL, xpd, i, "Found common FSK pattern. Start looking for ON/OFF patterns.\n");
|
(mem_equal
|
||||||
|
(writechunk, FSK_COMMON_PATTERN, DAHDI_CHUNKSIZE))) {
|
||||||
|
LINE_DBG(SIGNAL, xpd, i,
|
||||||
|
"Found common FSK pattern. Start looking for ON/OFF patterns.\n");
|
||||||
BIT_SET(priv->found_fsk_pattern, i);
|
BIT_SET(priv->found_fsk_pattern, i);
|
||||||
} else if (unlikely(IS_SET(priv->found_fsk_pattern, i))) {
|
} else if (unlikely(IS_SET(priv->found_fsk_pattern, i))) {
|
||||||
BIT_CLR(priv->found_fsk_pattern, i);
|
BIT_CLR(priv->found_fsk_pattern, i);
|
||||||
oht_pcm(xpd, i, 0);
|
oht_pcm(xpd, i, 0);
|
||||||
if (unlikely(mem_equal(writechunk, FSK_ON_PATTERN, DAHDI_CHUNKSIZE))) {
|
if (unlikely
|
||||||
|
(mem_equal
|
||||||
|
(writechunk, FSK_ON_PATTERN, DAHDI_CHUNKSIZE))) {
|
||||||
LINE_DBG(SIGNAL, xpd, i, "MSG WAITING ON\n");
|
LINE_DBG(SIGNAL, xpd, i, "MSG WAITING ON\n");
|
||||||
PHONEDEV(xpd).msg_waiting[i] = 1;
|
PHONEDEV(xpd).msg_waiting[i] = 1;
|
||||||
start_stop_vm_led(xbus, xpd, i);
|
start_stop_vm_led(xbus, xpd, i);
|
||||||
} else if (unlikely(mem_equal(writechunk, FSK_OFF_PATTERN, DAHDI_CHUNKSIZE))) {
|
} else
|
||||||
|
if (unlikely
|
||||||
|
(mem_equal
|
||||||
|
(writechunk, FSK_OFF_PATTERN,
|
||||||
|
DAHDI_CHUNKSIZE))) {
|
||||||
LINE_DBG(SIGNAL, xpd, i, "MSG WAITING OFF\n");
|
LINE_DBG(SIGNAL, xpd, i, "MSG WAITING OFF\n");
|
||||||
PHONEDEV(xpd).msg_waiting[i] = 0;
|
PHONEDEV(xpd).msg_waiting[i] = 0;
|
||||||
start_stop_vm_led(xbus, xpd, i);
|
start_stop_vm_led(xbus, xpd, i);
|
||||||
@ -1203,7 +1309,10 @@ static int FXS_card_tick(xbus_t *xbus, xpd_t *xpd)
|
|||||||
for_each_line(xpd, i) {
|
for_each_line(xpd, i) {
|
||||||
if (!IS_SET(priv->update_offhook_state, i))
|
if (!IS_SET(priv->update_offhook_state, i))
|
||||||
continue;
|
continue;
|
||||||
rxsig = IS_OFFHOOK(xpd, i) ? DAHDI_RXSIG_OFFHOOK : DAHDI_RXSIG_ONHOOK;
|
rxsig =
|
||||||
|
IS_OFFHOOK(xpd,
|
||||||
|
i) ? DAHDI_RXSIG_OFFHOOK :
|
||||||
|
DAHDI_RXSIG_ONHOOK;
|
||||||
notify_rxsig(xpd, i, rxsig); /* Notify after open() */
|
notify_rxsig(xpd, i, rxsig); /* Notify after open() */
|
||||||
BIT_CLR(priv->update_offhook_state, i);
|
BIT_CLR(priv->update_offhook_state, i);
|
||||||
}
|
}
|
||||||
@ -1222,7 +1331,8 @@ static int FXS_card_tick(xbus_t *xbus, xpd_t *xpd)
|
|||||||
/*
|
/*
|
||||||
* Should be called with spinlocked XPD
|
* Should be called with spinlocked XPD
|
||||||
*/
|
*/
|
||||||
static void process_hookstate(xpd_t *xpd, xpp_line_t offhook, xpp_line_t change_mask)
|
static void process_hookstate(xpd_t *xpd, xpp_line_t offhook,
|
||||||
|
xpp_line_t change_mask)
|
||||||
{
|
{
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
struct FXS_priv_data *priv;
|
struct FXS_priv_data *priv;
|
||||||
@ -1232,9 +1342,11 @@ static void process_hookstate(xpd_t *xpd, xpp_line_t offhook, xpp_line_t change_
|
|||||||
BUG_ON(PHONEDEV(xpd).direction != TO_PHONE);
|
BUG_ON(PHONEDEV(xpd).direction != TO_PHONE);
|
||||||
xbus = xpd->xbus;
|
xbus = xpd->xbus;
|
||||||
priv = xpd->priv;
|
priv = xpd->priv;
|
||||||
XPD_DBG(SIGNAL, xpd, "offhook=0x%X change_mask=0x%X\n", offhook, change_mask);
|
XPD_DBG(SIGNAL, xpd, "offhook=0x%X change_mask=0x%X\n", offhook,
|
||||||
|
change_mask);
|
||||||
for_each_line(xpd, i) {
|
for_each_line(xpd, i) {
|
||||||
if (IS_SET(PHONEDEV(xpd).digital_outputs, i) || IS_SET(PHONEDEV(xpd).digital_inputs, i))
|
if (IS_SET(PHONEDEV(xpd).digital_outputs, i)
|
||||||
|
|| IS_SET(PHONEDEV(xpd).digital_inputs, i))
|
||||||
continue;
|
continue;
|
||||||
if (IS_SET(change_mask, i)) {
|
if (IS_SET(change_mask, i)) {
|
||||||
PHONEDEV(xpd).ringing[i] = 0; /* No more ringing... */
|
PHONEDEV(xpd).ringing[i] = 0; /* No more ringing... */
|
||||||
@ -1246,7 +1358,8 @@ static void process_hookstate(xpd_t *xpd, xpp_line_t offhook, xpp_line_t change_
|
|||||||
* Reset our previous DTMF memories...
|
* Reset our previous DTMF memories...
|
||||||
*/
|
*/
|
||||||
BIT_CLR(priv->prev_key_down, i);
|
BIT_CLR(priv->prev_key_down, i);
|
||||||
priv->prev_key_time[i].tv_sec = priv->prev_key_time[i].tv_usec = 0L;
|
priv->prev_key_time[i].tv_sec =
|
||||||
|
priv->prev_key_time[i].tv_usec = 0L;
|
||||||
if (IS_SET(offhook, i)) {
|
if (IS_SET(offhook, i)) {
|
||||||
LINE_DBG(SIGNAL, xpd, i, "OFFHOOK\n");
|
LINE_DBG(SIGNAL, xpd, i, "OFFHOOK\n");
|
||||||
MARK_ON(priv, i, LED_GREEN);
|
MARK_ON(priv, i, LED_GREEN);
|
||||||
@ -1267,16 +1380,18 @@ static void process_hookstate(xpd_t *xpd, xpp_line_t offhook, xpp_line_t change_
|
|||||||
|
|
||||||
HANDLER_DEF(FXS, SIG_CHANGED)
|
HANDLER_DEF(FXS, SIG_CHANGED)
|
||||||
{
|
{
|
||||||
xpp_line_t sig_status = RPACKET_FIELD(pack, FXS, SIG_CHANGED, sig_status);
|
xpp_line_t sig_status =
|
||||||
xpp_line_t sig_toggles = RPACKET_FIELD(pack, FXS, SIG_CHANGED, sig_toggles);
|
RPACKET_FIELD(pack, FXS, SIG_CHANGED, sig_status);
|
||||||
|
xpp_line_t sig_toggles =
|
||||||
|
RPACKET_FIELD(pack, FXS, SIG_CHANGED, sig_toggles);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
BUG_ON(!xpd);
|
BUG_ON(!xpd);
|
||||||
BUG_ON(PHONEDEV(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);
|
XPD_DBG(SIGNAL, xpd, "(PHONE) sig_toggles=0x%04X sig_status=0x%04X\n",
|
||||||
|
sig_toggles, sig_status);
|
||||||
#if 0
|
#if 0
|
||||||
Is this needed?
|
Is this needed ? for_each_line(xpd, i) {
|
||||||
for_each_line(xpd, i) {
|
|
||||||
if (IS_SET(sig_toggles, i))
|
if (IS_SET(sig_toggles, i))
|
||||||
do_chan_power(xpd->xbus, xpd, BIT(i), 0); // Power down (prevent overheating!!!)
|
do_chan_power(xpd->xbus, xpd, BIT(i), 0); // Power down (prevent overheating!!!)
|
||||||
}
|
}
|
||||||
@ -1296,8 +1411,7 @@ static void process_digital_inputs(xpd_t *xpd, const reg_cmd_t *info)
|
|||||||
|
|
||||||
/* Sanity check */
|
/* Sanity check */
|
||||||
if (!PHONEDEV(xpd).digital_inputs) {
|
if (!PHONEDEV(xpd).digital_inputs) {
|
||||||
XPD_NOTICE(xpd,
|
XPD_NOTICE(xpd, "%s called without digital inputs. Ignored\n",
|
||||||
"%s called without digital inputs. Ignored\n",
|
|
||||||
__func__);
|
__func__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1363,10 +1477,8 @@ static void process_dtmf(xpd_t *xpd, uint portnum, __u8 val)
|
|||||||
priv->prev_key_time[portnum] = now;
|
priv->prev_key_time[portnum] = now;
|
||||||
LINE_DBG(SIGNAL, xpd, portnum,
|
LINE_DBG(SIGNAL, xpd, portnum,
|
||||||
"[%lu.%06lu] DTMF digit %-4s '%c' (val=%d, want_mute=%s want_event=%s, delta=%d msec)\n",
|
"[%lu.%06lu] DTMF digit %-4s '%c' (val=%d, want_mute=%s want_event=%s, delta=%d msec)\n",
|
||||||
now.tv_sec, now.tv_usec,
|
now.tv_sec, now.tv_usec, (key_down) ? "DOWN" : "UP", digit,
|
||||||
(key_down)?"DOWN":"UP", digit, val,
|
val, (want_mute) ? "yes" : "no", (want_event) ? "yes" : "no",
|
||||||
(want_mute) ? "yes" : "no",
|
|
||||||
(want_event) ? "yes" : "no",
|
|
||||||
msec);
|
msec);
|
||||||
/*
|
/*
|
||||||
* FIXME: we currently don't use the want_dtmf_mute until
|
* FIXME: we currently don't use the want_dtmf_mute until
|
||||||
@ -1378,7 +1490,8 @@ static void process_dtmf(xpd_t *xpd, uint portnum, __u8 val)
|
|||||||
else
|
else
|
||||||
__do_mute_dtmf(xpd, portnum, 0);
|
__do_mute_dtmf(xpd, portnum, 0);
|
||||||
if (want_event) {
|
if (want_event) {
|
||||||
int event = (key_down) ? DAHDI_EVENT_DTMFDOWN : DAHDI_EVENT_DTMFUP;
|
int event =
|
||||||
|
(key_down) ? DAHDI_EVENT_DTMFDOWN : DAHDI_EVENT_DTMFUP;
|
||||||
|
|
||||||
dahdi_qevent_lock(XPD_CHAN(xpd, portnum), event | digit);
|
dahdi_qevent_lock(XPD_CHAN(xpd, portnum), event | digit);
|
||||||
}
|
}
|
||||||
@ -1397,8 +1510,8 @@ static int FXS_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
|||||||
indirect = (REG_FIELD(info, regnum) == 0x1E);
|
indirect = (REG_FIELD(info, regnum) == 0x1E);
|
||||||
regnum = (indirect) ? REG_FIELD(info, subreg) : REG_FIELD(info, regnum);
|
regnum = (indirect) ? REG_FIELD(info, subreg) : REG_FIELD(info, regnum);
|
||||||
XPD_DBG(REGS, xpd, "%s reg_num=0x%X, dataL=0x%X dataH=0x%X\n",
|
XPD_DBG(REGS, xpd, "%s reg_num=0x%X, dataL=0x%X dataH=0x%X\n",
|
||||||
(indirect)?"I":"D",
|
(indirect) ? "I" : "D", regnum, REG_FIELD(info, data_low),
|
||||||
regnum, REG_FIELD(info, data_low), REG_FIELD(info, data_high));
|
REG_FIELD(info, data_high));
|
||||||
if (!indirect && regnum == REG_DTMF_DECODE) {
|
if (!indirect && regnum == REG_DTMF_DECODE) {
|
||||||
__u8 val = REG_FIELD(info, data_low);
|
__u8 val = REG_FIELD(info, data_low);
|
||||||
|
|
||||||
@ -1430,16 +1543,19 @@ static int FXS_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
#if 0
|
#if 0
|
||||||
XPD_NOTICE(xpd, "Spurious register reply(ignored): %s reg_num=0x%X, dataL=0x%X dataH=0x%X\n",
|
XPD_NOTICE(xpd,
|
||||||
(indirect)?"I":"D",
|
"Spurious register reply(ignored): %s reg_num=0x%X, dataL=0x%X dataH=0x%X\n",
|
||||||
regnum, REG_FIELD(info, data_low), REG_FIELD(info, data_high));
|
(indirect) ? "I" : "D", regnum, REG_FIELD(info,
|
||||||
|
data_low),
|
||||||
|
REG_FIELD(info, data_high));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
/* Update /proc info only if reply relate to the last slic read request */
|
/* Update /proc info only if reply relate to the last slic read request */
|
||||||
if (
|
if (REG_FIELD(&xpd->requested_reply, regnum) == REG_FIELD(info, regnum)
|
||||||
REG_FIELD(&xpd->requested_reply, regnum) == REG_FIELD(info, regnum) &&
|
&& REG_FIELD(&xpd->requested_reply, do_subreg) == REG_FIELD(info,
|
||||||
REG_FIELD(&xpd->requested_reply, do_subreg) == REG_FIELD(info, do_subreg) &&
|
do_subreg)
|
||||||
REG_FIELD(&xpd->requested_reply, subreg) == REG_FIELD(info, subreg)) {
|
&& REG_FIELD(&xpd->requested_reply, subreg) == REG_FIELD(info,
|
||||||
|
subreg)) {
|
||||||
xpd->last_reply = *info;
|
xpd->last_reply = *info;
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||||
@ -1478,19 +1594,12 @@ static const struct phoneops fxs_phoneops = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static xproto_table_t PROTO_TABLE(FXS) = {
|
static xproto_table_t PROTO_TABLE(FXS) = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,.entries = {
|
||||||
.entries = {
|
|
||||||
/* Prototable Card Opcode */
|
/* Prototable Card Opcode */
|
||||||
XENTRY( FXS, FXS, SIG_CHANGED ),
|
XENTRY(FXS, FXS, SIG_CHANGED),},.name = "FXS", /* protocol name */
|
||||||
},
|
.ports_per_subunit = 8,.type = XPD_TYPE_FXS,.xops =
|
||||||
.name = "FXS", /* protocol name */
|
&fxs_xops,.phoneops = &fxs_phoneops,.packet_is_valid =
|
||||||
.ports_per_subunit = 8,
|
fxs_packet_is_valid,.packet_dump = fxs_packet_dump,};
|
||||||
.type = XPD_TYPE_FXS,
|
|
||||||
.xops = &fxs_xops,
|
|
||||||
.phoneops = &fxs_phoneops,
|
|
||||||
.packet_is_valid = fxs_packet_is_valid,
|
|
||||||
.packet_dump = fxs_packet_dump,
|
|
||||||
};
|
|
||||||
|
|
||||||
static bool fxs_packet_is_valid(xpacket_t *pack)
|
static bool fxs_packet_is_valid(xpacket_t *pack)
|
||||||
{
|
{
|
||||||
@ -1509,7 +1618,8 @@ static void fxs_packet_dump(const char *msg, xpacket_t *pack)
|
|||||||
/*------------------------- SLIC Handling --------------------------*/
|
/*------------------------- SLIC Handling --------------------------*/
|
||||||
|
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
static int proc_fxs_info_read(char *page, char **start, off_t off, int count, int *eof, void *data)
|
static int proc_fxs_info_read(char *page, char **start, off_t off, int count,
|
||||||
|
int *eof, void *data)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
@ -1523,14 +1633,10 @@ static int proc_fxs_info_read(char *page, char **start, off_t off, int count, in
|
|||||||
spin_lock_irqsave(&xpd->lock, flags);
|
spin_lock_irqsave(&xpd->lock, flags);
|
||||||
priv = xpd->priv;
|
priv = xpd->priv;
|
||||||
BUG_ON(!priv);
|
BUG_ON(!priv);
|
||||||
len += sprintf(page + len, "%-8s %-10s %-10s %-10s %-10s %-10s\n",
|
len +=
|
||||||
"Channel",
|
sprintf(page + len, "%-8s %-10s %-10s %-10s %-10s %-10s\n",
|
||||||
"idletxhookstate",
|
"Channel", "idletxhookstate", "lasttxhook", "ohttimer",
|
||||||
"lasttxhook",
|
"neon_blinking", "search_fsk_pattern");
|
||||||
"ohttimer",
|
|
||||||
"neon_blinking",
|
|
||||||
"search_fsk_pattern"
|
|
||||||
);
|
|
||||||
for_each_line(xpd, i) {
|
for_each_line(xpd, i) {
|
||||||
char pref;
|
char pref;
|
||||||
|
|
||||||
@ -1540,12 +1646,10 @@ static int proc_fxs_info_read(char *page, char **start, off_t off, int count, in
|
|||||||
pref = 'I';
|
pref = 'I';
|
||||||
else
|
else
|
||||||
pref = ' ';
|
pref = ' ';
|
||||||
len += sprintf(page + len, "%c%7d %10d %10d %10d %10d %10d\n",
|
len +=
|
||||||
pref,
|
sprintf(page + len, "%c%7d %10d %10d %10d %10d %10d\n",
|
||||||
i,
|
pref, i, priv->idletxhookstate[i],
|
||||||
priv->idletxhookstate[i],
|
priv->lasttxhook[i], priv->ohttimer[i],
|
||||||
priv->lasttxhook[i],
|
|
||||||
priv->ohttimer[i],
|
|
||||||
IS_SET(priv->neon_blinking, i),
|
IS_SET(priv->neon_blinking, i),
|
||||||
IS_SET(priv->search_fsk_pattern, i)
|
IS_SET(priv->search_fsk_pattern, i)
|
||||||
);
|
);
|
||||||
@ -1555,18 +1659,27 @@ 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, "LED #%d", led);
|
||||||
len += sprintf(page + len, "\n\t%-17s: ", "ledstate");
|
len += sprintf(page + len, "\n\t%-17s: ", "ledstate");
|
||||||
for_each_line(xpd, i) {
|
for_each_line(xpd, i) {
|
||||||
if (!IS_SET(PHONEDEV(xpd).digital_outputs, i) && !IS_SET(PHONEDEV(xpd).digital_inputs, i))
|
if (!IS_SET(PHONEDEV(xpd).digital_outputs, i)
|
||||||
len += sprintf(page + len, "%d ", IS_SET(priv->ledstate[led], 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");
|
len += sprintf(page + len, "\n\t%-17s: ", "ledcontrol");
|
||||||
for_each_line(xpd, i) {
|
for_each_line(xpd, i) {
|
||||||
if (!IS_SET(PHONEDEV(xpd).digital_outputs, i) && !IS_SET(PHONEDEV(xpd).digital_inputs, i))
|
if (!IS_SET(PHONEDEV(xpd).digital_outputs, i)
|
||||||
len += sprintf(page + len, "%d ", IS_SET(priv->ledcontrol[led], 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");
|
len += sprintf(page + len, "\n\t%-17s: ", "led_counter");
|
||||||
for_each_line(xpd, i) {
|
for_each_line(xpd, i) {
|
||||||
if (!IS_SET(PHONEDEV(xpd).digital_outputs, i) && !IS_SET(PHONEDEV(xpd).digital_inputs, i))
|
if (!IS_SET(PHONEDEV(xpd).digital_outputs, i)
|
||||||
len += sprintf(page + len, "%d ", LED_COUNTER(priv,i,led));
|
&& !IS_SET(PHONEDEV(xpd).digital_inputs, i))
|
||||||
|
len +=
|
||||||
|
sprintf(page + len, "%d ",
|
||||||
|
LED_COUNTER(priv, i, led));
|
||||||
}
|
}
|
||||||
len += sprintf(page + len, "\n");
|
len += sprintf(page + len, "\n");
|
||||||
}
|
}
|
||||||
@ -1584,7 +1697,8 @@ static int proc_fxs_info_read(char *page, char **start, off_t off, int count, in
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_METERING
|
#ifdef WITH_METERING
|
||||||
static int proc_xpd_metering_write(struct file *file, const char __user *buffer, unsigned long count, void *data)
|
static int proc_xpd_metering_write(struct file *file, const char __user *buffer,
|
||||||
|
unsigned long count, void *data)
|
||||||
{
|
{
|
||||||
xpd_t *xpd = data;
|
xpd_t *xpd = data;
|
||||||
char buf[MAX_PROC_WRITE];
|
char buf[MAX_PROC_WRITE];
|
||||||
@ -1603,7 +1717,8 @@ static int proc_xpd_metering_write(struct file *file, const char __user *buffer,
|
|||||||
buf[count] = '\0';
|
buf[count] = '\0';
|
||||||
ret = sscanf(buf, "%d", &num);
|
ret = sscanf(buf, "%d", &num);
|
||||||
if (ret != 1) {
|
if (ret != 1) {
|
||||||
XPD_ERR(xpd, "Metering value should be number. Got '%s'\n", buf);
|
XPD_ERR(xpd, "Metering value should be number. Got '%s'\n",
|
||||||
|
buf);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
chan = num;
|
chan = num;
|
||||||
@ -1626,8 +1741,8 @@ static int fxs_xpd_probe(struct device *dev)
|
|||||||
xpd = dev_to_xpd(dev);
|
xpd = dev_to_xpd(dev);
|
||||||
/* Is it our device? */
|
/* Is it our device? */
|
||||||
if (xpd->type != XPD_TYPE_FXS) {
|
if (xpd->type != XPD_TYPE_FXS) {
|
||||||
XPD_ERR(xpd, "drop suggestion for %s (%d)\n",
|
XPD_ERR(xpd, "drop suggestion for %s (%d)\n", dev_name(dev),
|
||||||
dev_name(dev), xpd->type);
|
xpd->type);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
XPD_DBG(DEVICES, xpd, "SYSFS\n");
|
XPD_DBG(DEVICES, xpd, "SYSFS\n");
|
||||||
@ -1651,8 +1766,7 @@ static struct xpd_driver fxs_driver = {
|
|||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
#endif
|
#endif
|
||||||
.probe = fxs_xpd_probe,
|
.probe = fxs_xpd_probe,
|
||||||
.remove = fxs_xpd_remove
|
.remove = fxs_xpd_remove}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init card_fxs_startup(void)
|
static int __init card_fxs_startup(void)
|
||||||
|
@ -26,15 +26,12 @@
|
|||||||
|
|
||||||
enum fxs_opcodes {
|
enum fxs_opcodes {
|
||||||
XPROTO_NAME(FXS, SIG_CHANGED) = 0x06,
|
XPROTO_NAME(FXS, SIG_CHANGED) = 0x06,
|
||||||
/**/
|
/**/ XPROTO_NAME(FXS, CHAN_POWER) = 0x0F, /* Write to SLIC */
|
||||||
XPROTO_NAME(FXS, CHAN_POWER) = 0x0F, /* Write to SLIC */
|
|
||||||
XPROTO_NAME(FXS, CHAN_CID) = 0x0F, /* Write to SLIC */
|
XPROTO_NAME(FXS, CHAN_CID) = 0x0F, /* Write to SLIC */
|
||||||
XPROTO_NAME(FXS, LED) = 0x0F, /* Write to SLIC */
|
XPROTO_NAME(FXS, LED) = 0x0F, /* Write to SLIC */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
DEF_RPACKET_DATA(FXS, SIG_CHANGED, xpp_line_t sig_status; /* channels: lsb=1, msb=8 */
|
||||||
DEF_RPACKET_DATA(FXS, SIG_CHANGED,
|
|
||||||
xpp_line_t sig_status; /* channels: lsb=1, msb=8 */
|
|
||||||
xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */
|
xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -32,7 +32,8 @@
|
|||||||
|
|
||||||
static const char rcsid[] = "$Id$";
|
static const char rcsid[] = "$Id$";
|
||||||
|
|
||||||
DEF_PARM(charp,initdir, "/usr/share/dahdi", 0644, "The directory of card initialization scripts");
|
DEF_PARM(charp, initdir, "/usr/share/dahdi", 0644,
|
||||||
|
"The directory of card initialization scripts");
|
||||||
|
|
||||||
#define CHIP_REGISTERS "chipregs"
|
#define CHIP_REGISTERS "chipregs"
|
||||||
|
|
||||||
@ -40,8 +41,8 @@ extern int debug;
|
|||||||
|
|
||||||
/*---------------- GLOBAL PROC handling -----------------------------------*/
|
/*---------------- GLOBAL PROC handling -----------------------------------*/
|
||||||
|
|
||||||
static int send_magic_request(xbus_t *xbus,
|
static int send_magic_request(xbus_t *xbus, unsigned unit, xportno_t portno,
|
||||||
unsigned unit, xportno_t portno, bool eoftx)
|
bool eoftx)
|
||||||
{
|
{
|
||||||
xframe_t *xframe;
|
xframe_t *xframe;
|
||||||
xpacket_t *pack;
|
xpacket_t *pack;
|
||||||
@ -65,8 +66,8 @@ static int send_magic_request(xbus_t *xbus,
|
|||||||
dump_xframe(__func__, xbus, xframe, debug);
|
dump_xframe(__func__, xbus, xframe, debug);
|
||||||
ret = send_cmd_frame(xbus, xframe);
|
ret = send_cmd_frame(xbus, xframe);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
PORT_ERR(xbus, unit, portno,
|
PORT_ERR(xbus, unit, portno, "%s: failed sending xframe\n",
|
||||||
"%s: failed sending xframe\n", __func__);
|
__func__);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,7 +142,8 @@ static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
|
|||||||
addr_mode = argv[argno][1];
|
addr_mode = argv[argno][1];
|
||||||
switch (addr_mode) {
|
switch (addr_mode) {
|
||||||
case 'I':
|
case 'I':
|
||||||
XPD_NOTICE(xpd, "'I' is deprecated in register commands. Use 'S' instead.\n");
|
XPD_NOTICE(xpd,
|
||||||
|
"'I' is deprecated in register commands. Use 'S' instead.\n");
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case 'S':
|
case 'S':
|
||||||
do_subreg = 1;
|
do_subreg = 1;
|
||||||
@ -157,7 +159,8 @@ static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
|
|||||||
case 'm':
|
case 'm':
|
||||||
if (op != 'W') {
|
if (op != 'W') {
|
||||||
XPD_ERR(xpd,
|
XPD_ERR(xpd,
|
||||||
"Can use Multibyte (%c) only with op 'W'\n", addr_mode);
|
"Can use Multibyte (%c) only with op 'W'\n",
|
||||||
|
addr_mode);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
num_args--; /* No data low */
|
num_args--; /* No data low */
|
||||||
@ -185,7 +188,8 @@ static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
|
|||||||
addr_mode, argc - argno);
|
addr_mode, argc - argno);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
ret = send_magic_request(xpd->xbus, xpd->addr.unit, portno,
|
ret =
|
||||||
|
send_magic_request(xpd->xbus, xpd->addr.unit, portno,
|
||||||
addr_mode == 'm');
|
addr_mode == 'm');
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -209,7 +213,8 @@ static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
subreg = parse_hexbyte(argv[argno]);
|
subreg = parse_hexbyte(argv[argno]);
|
||||||
if (subreg < 0) {
|
if (subreg < 0) {
|
||||||
XPD_ERR(xpd, "Illegal subregister number '%s'\n", argv[argno]);
|
XPD_ERR(xpd, "Illegal subregister number '%s'\n",
|
||||||
|
argv[argno]);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
//XPD_DBG(REGS, xpd, "Subreg is %X\n", subreg);
|
//XPD_DBG(REGS, xpd, "Subreg is %X\n", subreg);
|
||||||
@ -223,7 +228,8 @@ static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
data_low = parse_hexbyte(argv[argno]);
|
data_low = parse_hexbyte(argv[argno]);
|
||||||
if (data_low < 0) {
|
if (data_low < 0) {
|
||||||
XPD_ERR(xpd, "Illegal data_low number '%s'\n", argv[argno]);
|
XPD_ERR(xpd, "Illegal data_low number '%s'\n",
|
||||||
|
argv[argno]);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
//XPD_DBG(REGS, xpd, "Data Low is %X\n", data_low);
|
//XPD_DBG(REGS, xpd, "Data Low is %X\n", data_low);
|
||||||
@ -238,7 +244,8 @@ static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
data_high = parse_hexbyte(argv[argno]);
|
data_high = parse_hexbyte(argv[argno]);
|
||||||
if (data_high < 0) {
|
if (data_high < 0) {
|
||||||
XPD_ERR(xpd, "Illegal data_high number '%s'\n", argv[argno]);
|
XPD_ERR(xpd, "Illegal data_high number '%s'\n",
|
||||||
|
argv[argno]);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
//XPD_DBG(REGS, xpd, "Data High is %X\n", data_high);
|
//XPD_DBG(REGS, xpd, "Data High is %X\n", data_high);
|
||||||
@ -246,26 +253,22 @@ static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
|
|||||||
} else
|
} else
|
||||||
data_high = 0;
|
data_high = 0;
|
||||||
if (argno < argc) {
|
if (argno < argc) {
|
||||||
XPD_ERR(xpd,
|
XPD_ERR(xpd, "Command contains an extra %d argument\n",
|
||||||
"Command contains an extra %d argument\n",
|
|
||||||
argc - argno);
|
argc - argno);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
XPD_DBG(REGS, xpd,
|
XPD_DBG(REGS, xpd, "portno=%d writing=%d regnum=%d do_subreg=%d subreg=%d dataL=%d do_datah=%d dataH=%d\n", portno, /* portno */
|
||||||
"portno=%d writing=%d regnum=%d do_subreg=%d subreg=%d dataL=%d do_datah=%d dataH=%d\n",
|
|
||||||
portno, /* portno */
|
|
||||||
writing, /* writing */
|
writing, /* writing */
|
||||||
regnum,
|
regnum, do_subreg, /* use subreg */
|
||||||
do_subreg, /* use subreg */
|
|
||||||
subreg, /* subreg */
|
subreg, /* subreg */
|
||||||
data_low,
|
data_low, do_datah, /* use data_high */
|
||||||
do_datah, /* use data_high*/
|
|
||||||
data_high);
|
data_high);
|
||||||
#endif
|
#endif
|
||||||
ret = xpp_register_request(xpd->xbus, xpd, portno,
|
ret =
|
||||||
writing, regnum, do_subreg, subreg,
|
xpp_register_request(xpd->xbus, xpd, portno, writing, regnum,
|
||||||
data_low, do_datah, data_high, 1);
|
do_subreg, subreg, data_low, do_datah,
|
||||||
|
data_high, 1);
|
||||||
out:
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -308,7 +311,8 @@ int parse_chip_command(xpd_t *xpd, char *cmdline)
|
|||||||
argv[i] = NULL;
|
argv[i] = NULL;
|
||||||
argc = i;
|
argc = i;
|
||||||
if (p) {
|
if (p) {
|
||||||
XPD_ERR(xpd, "Too many words (%d) to process. Last was '%s'\n", i, p);
|
XPD_ERR(xpd, "Too many words (%d) to process. Last was '%s'\n",
|
||||||
|
i, p);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (argc)
|
if (argc)
|
||||||
@ -349,7 +353,8 @@ static void global_packet_dump(const char *msg, xpacket_t *pack);
|
|||||||
|
|
||||||
int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
|
int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
|
||||||
bool writing, __u8 regnum, bool do_subreg, __u8 subreg,
|
bool writing, __u8 regnum, bool do_subreg, __u8 subreg,
|
||||||
__u8 data_low, bool do_datah, __u8 data_high, bool should_reply)
|
__u8 data_low, bool do_datah, __u8 data_high,
|
||||||
|
bool should_reply)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
xframe_t *xframe;
|
xframe_t *xframe;
|
||||||
@ -360,11 +365,11 @@ int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
|
|||||||
DBG(REGS, "NO XBUS\n");
|
DBG(REGS, "NO XBUS\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, REGISTER_REQUEST, xpd->xbus_idx);
|
XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, REGISTER_REQUEST,
|
||||||
|
xpd->xbus_idx);
|
||||||
LINE_DBG(REGS, xpd, portno, "%c%c %02X %02X %02X %02X\n",
|
LINE_DBG(REGS, xpd, portno, "%c%c %02X %02X %02X %02X\n",
|
||||||
(writing)?'W':'R',
|
(writing) ? 'W' : 'R', (do_subreg) ? 'S' : 'D', regnum, subreg,
|
||||||
(do_subreg)?'S':'D',
|
data_low, data_high);
|
||||||
regnum, subreg, data_low, data_high);
|
|
||||||
reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
|
reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
|
||||||
reg_cmd->bytes = sizeof(*reg_cmd) - 1; // do not count the 'bytes' field
|
reg_cmd->bytes = sizeof(*reg_cmd) - 1; // do not count the 'bytes' field
|
||||||
reg_cmd->is_multibyte = 0;
|
reg_cmd->is_multibyte = 0;
|
||||||
@ -387,7 +392,8 @@ int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
|
|||||||
if (should_reply)
|
if (should_reply)
|
||||||
xpd->requested_reply = *reg_cmd;
|
xpd->requested_reply = *reg_cmd;
|
||||||
if (debug & DBG_REGS) {
|
if (debug & DBG_REGS) {
|
||||||
dump_reg_cmd("REG_REQ", 1, xbus, xpd->addr.unit, reg_cmd->portnum, reg_cmd);
|
dump_reg_cmd("REG_REQ", 1, xbus, xpd->addr.unit,
|
||||||
|
reg_cmd->portnum, reg_cmd);
|
||||||
dump_packet("REG_REQ", pack, 1);
|
dump_packet("REG_REQ", pack, 1);
|
||||||
}
|
}
|
||||||
if (!xframe->usec_towait) { /* default processing time of SPI */
|
if (!xframe->usec_towait) { /* default processing time of SPI */
|
||||||
@ -443,8 +449,8 @@ HANDLER_DEF(GLOBAL, NULL_REPLY)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
HANDLER_DEF(GLOBAL, AB_DESCRIPTION) /* 0x08 */
|
HANDLER_DEF(GLOBAL, AB_DESCRIPTION)
|
||||||
{
|
{ /* 0x08 */
|
||||||
struct xbus_workqueue *worker;
|
struct xbus_workqueue *worker;
|
||||||
__u8 rev;
|
__u8 rev;
|
||||||
struct unit_descriptor *units;
|
struct unit_descriptor *units;
|
||||||
@ -473,8 +479,7 @@ HANDLER_DEF(GLOBAL, AB_DESCRIPTION) /* 0x08 */
|
|||||||
goto proto_err;
|
goto proto_err;
|
||||||
}
|
}
|
||||||
if (count_units <= 0) {
|
if (count_units <= 0) {
|
||||||
XBUS_NOTICE(xbus, "Empty astribank? (%d units)\n",
|
XBUS_NOTICE(xbus, "Empty astribank? (%d units)\n", count_units);
|
||||||
count_units);
|
|
||||||
ret = -EPROTO;
|
ret = -EPROTO;
|
||||||
goto proto_err;
|
goto proto_err;
|
||||||
}
|
}
|
||||||
@ -482,7 +487,8 @@ HANDLER_DEF(GLOBAL, AB_DESCRIPTION) /* 0x08 */
|
|||||||
ret = -EPROTO;
|
ret = -EPROTO;
|
||||||
goto proto_err;
|
goto proto_err;
|
||||||
}
|
}
|
||||||
XBUS_INFO(xbus, "DESCRIPTOR: %d cards, protocol revision %d\n", count_units, rev);
|
XBUS_INFO(xbus, "DESCRIPTOR: %d cards, protocol revision %d\n",
|
||||||
|
count_units, rev);
|
||||||
if (xbus_check_unique(xbus))
|
if (xbus_check_unique(xbus))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
xbus->revision = rev;
|
xbus->revision = rev;
|
||||||
@ -497,7 +503,9 @@ HANDLER_DEF(GLOBAL, AB_DESCRIPTION) /* 0x08 */
|
|||||||
struct card_desc_struct *card_desc;
|
struct card_desc_struct *card_desc;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if ((card_desc = KZALLOC(sizeof(struct card_desc_struct), GFP_ATOMIC)) == NULL) {
|
if ((card_desc =
|
||||||
|
KZALLOC(sizeof(struct card_desc_struct),
|
||||||
|
GFP_ATOMIC)) == NULL) {
|
||||||
XBUS_ERR(xbus, "Card description allocation failed.\n");
|
XBUS_ERR(xbus, "Card description allocation failed.\n");
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto out;
|
goto out;
|
||||||
@ -510,16 +518,14 @@ HANDLER_DEF(GLOBAL, AB_DESCRIPTION) /* 0x08 */
|
|||||||
card_desc->numchips = this_unit->numchips;
|
card_desc->numchips = this_unit->numchips;
|
||||||
card_desc->ports_per_chip = this_unit->ports_per_chip;
|
card_desc->ports_per_chip = this_unit->ports_per_chip;
|
||||||
card_desc->port_dir = this_unit->port_dir;
|
card_desc->port_dir = this_unit->port_dir;
|
||||||
card_desc->ports = card_desc->numchips * card_desc->ports_per_chip;
|
card_desc->ports =
|
||||||
XBUS_INFO(xbus, " CARD %d type=%d.%d ports=%d (%dx%d), port-dir=0x%02X\n",
|
card_desc->numchips * card_desc->ports_per_chip;
|
||||||
card_desc->xpd_addr.unit,
|
XBUS_INFO(xbus,
|
||||||
card_desc->type,
|
" CARD %d type=%d.%d ports=%d (%dx%d), port-dir=0x%02X\n",
|
||||||
card_desc->subtype,
|
card_desc->xpd_addr.unit, card_desc->type,
|
||||||
card_desc->ports,
|
card_desc->subtype, card_desc->ports,
|
||||||
card_desc->numchips,
|
card_desc->numchips, card_desc->ports_per_chip,
|
||||||
card_desc->ports_per_chip,
|
card_desc->port_dir);
|
||||||
card_desc->port_dir
|
|
||||||
);
|
|
||||||
spin_lock_irqsave(&worker->worker_lock, flags);
|
spin_lock_irqsave(&worker->worker_lock, flags);
|
||||||
worker->num_units++;
|
worker->num_units++;
|
||||||
XBUS_COUNTER(xbus, UNITS)++;
|
XBUS_COUNTER(xbus, UNITS)++;
|
||||||
@ -549,11 +555,13 @@ HANDLER_DEF(GLOBAL, REGISTER_REPLY)
|
|||||||
return -EPROTO;
|
return -EPROTO;
|
||||||
}
|
}
|
||||||
if (debug & DBG_REGS) {
|
if (debug & DBG_REGS) {
|
||||||
dump_reg_cmd("REG_REPLY", 0, xbus, xpd->addr.unit, reg->portnum, reg);
|
dump_reg_cmd("REG_REPLY", 0, xbus, xpd->addr.unit, reg->portnum,
|
||||||
|
reg);
|
||||||
dump_packet("REG_REPLY", pack, 1);
|
dump_packet("REG_REPLY", pack, 1);
|
||||||
}
|
}
|
||||||
if (!XMETHOD(card_register_reply, xpd)) {
|
if (!XMETHOD(card_register_reply, xpd)) {
|
||||||
XPD_ERR(xpd, "REGISTER_REPLY: without card_register_reply() method\n");
|
XPD_ERR(xpd,
|
||||||
|
"REGISTER_REPLY: without card_register_reply() method\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
return CALL_XMETHOD(card_register_reply, xpd, reg);
|
return CALL_XMETHOD(card_register_reply, xpd, reg);
|
||||||
@ -594,9 +602,11 @@ HANDLER_DEF(GLOBAL, ERROR_CODE)
|
|||||||
snprintf(tmp_name, TMP_NAME_LEN, "%s(%1d%1d)", xbus->busname,
|
snprintf(tmp_name, TMP_NAME_LEN, "%s(%1d%1d)", xbus->busname,
|
||||||
XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack));
|
XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack));
|
||||||
} else {
|
} else {
|
||||||
snprintf(tmp_name, TMP_NAME_LEN, "%s/%s", xbus->busname, xpd->xpdname);
|
snprintf(tmp_name, TMP_NAME_LEN, "%s/%s", xbus->busname,
|
||||||
|
xpd->xpdname);
|
||||||
}
|
}
|
||||||
NOTICE("%s: FIRMWARE %s: category=%d errorbits=0x%02X (rate_limit=%ld)\n",
|
NOTICE
|
||||||
|
("%s: FIRMWARE %s: category=%d errorbits=0x%02X (rate_limit=%ld)\n",
|
||||||
tmp_name, cmd->name, category_code, errorbits, rate_limit);
|
tmp_name, cmd->name, category_code, errorbits, rate_limit);
|
||||||
dump_packet("FIRMWARE: ", pack, 1);
|
dump_packet("FIRMWARE: ", pack, 1);
|
||||||
/*
|
/*
|
||||||
@ -605,20 +615,16 @@ HANDLER_DEF(GLOBAL, ERROR_CODE)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
xproto_table_t PROTO_TABLE(GLOBAL) = {
|
xproto_table_t PROTO_TABLE(GLOBAL) = {
|
||||||
.entries = {
|
.entries = {
|
||||||
/* Prototable Card Opcode */
|
/* Prototable Card Opcode */
|
||||||
XENTRY( GLOBAL, GLOBAL, NULL_REPLY ),
|
XENTRY(GLOBAL, GLOBAL, NULL_REPLY), XENTRY(GLOBAL, GLOBAL,
|
||||||
XENTRY( GLOBAL, GLOBAL, AB_DESCRIPTION ),
|
AB_DESCRIPTION),
|
||||||
XENTRY(GLOBAL, GLOBAL, SYNC_REPLY),
|
XENTRY(GLOBAL, GLOBAL, SYNC_REPLY),
|
||||||
XENTRY(GLOBAL, GLOBAL, ERROR_CODE),
|
XENTRY(GLOBAL, GLOBAL, ERROR_CODE),
|
||||||
XENTRY( GLOBAL, GLOBAL, REGISTER_REPLY ),
|
XENTRY(GLOBAL, GLOBAL, REGISTER_REPLY),},.name =
|
||||||
},
|
"GLOBAL",.packet_is_valid =
|
||||||
.name = "GLOBAL",
|
global_packet_is_valid,.packet_dump = global_packet_dump,};
|
||||||
.packet_is_valid = global_packet_is_valid,
|
|
||||||
.packet_dump = global_packet_dump,
|
|
||||||
};
|
|
||||||
|
|
||||||
static bool global_packet_is_valid(xpacket_t *pack)
|
static bool global_packet_is_valid(xpacket_t *pack)
|
||||||
{
|
{
|
||||||
@ -687,31 +693,38 @@ int run_initialize_registers(xpd_t *xpd)
|
|||||||
xpd_t *su = xpd_byaddr(xbus, xpd->addr.unit, i);
|
xpd_t *su = xpd_byaddr(xbus, xpd->addr.unit, i);
|
||||||
|
|
||||||
if (!su) {
|
if (!su) {
|
||||||
XPD_ERR(xpd,
|
XPD_ERR(xpd, "Have %d subunits, but not subunit #%d\n",
|
||||||
"Have %d subunits, but not subunit #%d\n",
|
|
||||||
xpd->subunits, i);
|
xpd->subunits, i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
direction_mask |= (PHONEDEV(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(busstr, MAX_ENV_STR, "XBUS_NAME=%s", xbus->busname);
|
||||||
snprintf(busnumstr, MAX_ENV_STR, "XBUS_NUMBER=%d", xbus->num);
|
snprintf(busnumstr, MAX_ENV_STR, "XBUS_NUMBER=%d", xbus->num);
|
||||||
snprintf(modelstr, MAX_ENV_STR, "XBUS_MODEL_STRING=%s", xbus->transport.model_string);
|
snprintf(modelstr, MAX_ENV_STR, "XBUS_MODEL_STRING=%s",
|
||||||
|
xbus->transport.model_string);
|
||||||
snprintf(unitstr, MAX_ENV_STR, "UNIT_NUMBER=%d", xpd->addr.unit);
|
snprintf(unitstr, MAX_ENV_STR, "UNIT_NUMBER=%d", xpd->addr.unit);
|
||||||
snprintf(typestr, MAX_ENV_STR, "UNIT_TYPE=%d", xpd->type);
|
snprintf(typestr, MAX_ENV_STR, "UNIT_TYPE=%d", xpd->type);
|
||||||
snprintf(subunitsstr, MAX_ENV_STR, "UNIT_SUBUNITS=%d", xpd->subunits);
|
snprintf(subunitsstr, MAX_ENV_STR, "UNIT_SUBUNITS=%d", xpd->subunits);
|
||||||
snprintf(directionstr, MAX_ENV_STR, "UNIT_SUBUNITS_DIR=%d", direction_mask);
|
snprintf(directionstr, MAX_ENV_STR, "UNIT_SUBUNITS_DIR=%d",
|
||||||
|
direction_mask);
|
||||||
snprintf(revstr, MAX_ENV_STR, "XBUS_REVISION=%d", xbus->revision);
|
snprintf(revstr, MAX_ENV_STR, "XBUS_REVISION=%d", xbus->revision);
|
||||||
snprintf(connectorstr, MAX_ENV_STR, "XBUS_CONNECTOR=%s", xbus->connector);
|
snprintf(connectorstr, MAX_ENV_STR, "XBUS_CONNECTOR=%s",
|
||||||
|
xbus->connector);
|
||||||
snprintf(xbuslabel, MAX_ENV_STR, "XBUS_LABEL=%s", xbus->label);
|
snprintf(xbuslabel, MAX_ENV_STR, "XBUS_LABEL=%s", xbus->label);
|
||||||
if (snprintf(init_card, MAX_PATH_STR, "%s/init_card_%d_%d",
|
if (snprintf
|
||||||
initdir, xpd->type, xbus->revision) > MAX_PATH_STR) {
|
(init_card, MAX_PATH_STR, "%s/init_card_%d_%d", initdir, xpd->type,
|
||||||
XPD_NOTICE(xpd, "Cannot initialize. pathname is longer than %d characters.\n", MAX_PATH_STR);
|
xbus->revision) > MAX_PATH_STR) {
|
||||||
|
XPD_NOTICE(xpd,
|
||||||
|
"Cannot initialize. pathname is longer than %d characters.\n",
|
||||||
|
MAX_PATH_STR);
|
||||||
ret = -E2BIG;
|
ret = -E2BIG;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if (!XBUS_IS(xbus, RECVD_DESC)) {
|
if (!XBUS_IS(xbus, RECVD_DESC)) {
|
||||||
XBUS_ERR(xbus, "Skipped register initialization. In state %s.\n",
|
XBUS_ERR(xbus,
|
||||||
|
"Skipped register initialization. In state %s.\n",
|
||||||
xbus_statename(XBUS_STATE(xbus)));
|
xbus_statename(XBUS_STATE(xbus)));
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto err;
|
goto err;
|
||||||
@ -725,15 +738,18 @@ int run_initialize_registers(xpd_t *xpd)
|
|||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
XPD_DBG(DEVICES, xpd, "'%s' finished OK\n", init_card);
|
XPD_DBG(DEVICES, xpd, "'%s' finished OK\n", init_card);
|
||||||
else if (ret < 0) {
|
else if (ret < 0) {
|
||||||
XPD_ERR(xpd, "Failed running '%s' (errno %d)\n", init_card, ret);
|
XPD_ERR(xpd, "Failed running '%s' (errno %d)\n", init_card,
|
||||||
|
ret);
|
||||||
} else {
|
} else {
|
||||||
__u8 exitval = ((unsigned)ret >> 8) & 0xFF;
|
__u8 exitval = ((unsigned)ret >> 8) & 0xFF;
|
||||||
__u8 sigval = ret & 0xFF;
|
__u8 sigval = ret & 0xFF;
|
||||||
|
|
||||||
if (!exitval) {
|
if (!exitval) {
|
||||||
XPD_ERR(xpd, "'%s' killed by signal %d\n", init_card, sigval);
|
XPD_ERR(xpd, "'%s' killed by signal %d\n", init_card,
|
||||||
|
sigval);
|
||||||
} else {
|
} else {
|
||||||
XPD_ERR(xpd, "'%s' aborted with exitval %d\n", init_card, exitval);
|
XPD_ERR(xpd, "'%s' aborted with exitval %d\n",
|
||||||
|
init_card, exitval);
|
||||||
}
|
}
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -30,14 +30,11 @@ enum global_opcodes {
|
|||||||
XPROTO_NAME(GLOBAL, AB_DESCRIPTION) = 0x08,
|
XPROTO_NAME(GLOBAL, AB_DESCRIPTION) = 0x08,
|
||||||
XPROTO_NAME(GLOBAL, REGISTER_REQUEST) = 0x0F,
|
XPROTO_NAME(GLOBAL, REGISTER_REQUEST) = 0x0F,
|
||||||
XPROTO_NAME(GLOBAL, REGISTER_REPLY) = 0x10,
|
XPROTO_NAME(GLOBAL, REGISTER_REPLY) = 0x10,
|
||||||
/**/
|
/**/ XPROTO_NAME(GLOBAL, PCM_WRITE) = 0x11,
|
||||||
XPROTO_NAME(GLOBAL, PCM_WRITE) = 0x11,
|
|
||||||
XPROTO_NAME(GLOBAL, PCM_READ) = 0x12,
|
XPROTO_NAME(GLOBAL, PCM_READ) = 0x12,
|
||||||
/**/
|
/**/ XPROTO_NAME(GLOBAL, SYNC_SOURCE) = 0x19,
|
||||||
XPROTO_NAME(GLOBAL, SYNC_SOURCE) = 0x19,
|
|
||||||
XPROTO_NAME(GLOBAL, SYNC_REPLY) = 0x1A,
|
XPROTO_NAME(GLOBAL, SYNC_REPLY) = 0x1A,
|
||||||
/**/
|
/**/ XPROTO_NAME(GLOBAL, ERROR_CODE) = 0x22,
|
||||||
XPROTO_NAME(GLOBAL, ERROR_CODE) = 0x22,
|
|
||||||
XPROTO_NAME(GLOBAL, RESET_SYNC_COUNTERS) = 0x23,
|
XPROTO_NAME(GLOBAL, RESET_SYNC_COUNTERS) = 0x23,
|
||||||
XPROTO_NAME(GLOBAL, NULL_REPLY) = 0xFE,
|
XPROTO_NAME(GLOBAL, NULL_REPLY) = 0xFE,
|
||||||
};
|
};
|
||||||
@ -56,45 +53,18 @@ struct unit_descriptor {
|
|||||||
#define NUM_UNITS 6
|
#define NUM_UNITS 6
|
||||||
|
|
||||||
DEF_RPACKET_DATA(GLOBAL, NULL_REPLY);
|
DEF_RPACKET_DATA(GLOBAL, NULL_REPLY);
|
||||||
DEF_RPACKET_DATA(GLOBAL, AB_REQUEST,
|
DEF_RPACKET_DATA(GLOBAL, AB_REQUEST, __u8 rev; __u8 reserved;);
|
||||||
__u8 rev;
|
DEF_RPACKET_DATA(GLOBAL, AB_DESCRIPTION, __u8 rev; __u8 reserved[3];
|
||||||
__u8 reserved;
|
struct unit_descriptor unit_descriptor[NUM_UNITS];);
|
||||||
);
|
DEF_RPACKET_DATA(GLOBAL, REGISTER_REQUEST, reg_cmd_t reg_cmd;);
|
||||||
DEF_RPACKET_DATA(GLOBAL, AB_DESCRIPTION,
|
DEF_RPACKET_DATA(GLOBAL, PCM_WRITE, xpp_line_t lines; __u8 pcm[PCM_CHUNKSIZE];);
|
||||||
__u8 rev;
|
DEF_RPACKET_DATA(GLOBAL, PCM_READ, xpp_line_t lines; __u8 pcm[PCM_CHUNKSIZE];);
|
||||||
__u8 reserved[3];
|
DEF_RPACKET_DATA(GLOBAL, SYNC_SOURCE, __u8 sync_mode; __u8 drift;);
|
||||||
struct unit_descriptor unit_descriptor[NUM_UNITS];
|
DEF_RPACKET_DATA(GLOBAL, SYNC_REPLY, __u8 sync_mode; __u8 drift;);
|
||||||
);
|
DEF_RPACKET_DATA(GLOBAL, REGISTER_REPLY, reg_cmd_t regcmd;);
|
||||||
DEF_RPACKET_DATA(GLOBAL, REGISTER_REQUEST,
|
DEF_RPACKET_DATA(GLOBAL, RESET_SYNC_COUNTERS, __u8 mask;);
|
||||||
reg_cmd_t reg_cmd;
|
DEF_RPACKET_DATA(GLOBAL, ERROR_CODE, __u8 category_code; __u8 errorbits;
|
||||||
);
|
__u8 bad_packet[0];);
|
||||||
DEF_RPACKET_DATA(GLOBAL, PCM_WRITE,
|
|
||||||
xpp_line_t lines;
|
|
||||||
__u8 pcm[PCM_CHUNKSIZE];
|
|
||||||
);
|
|
||||||
DEF_RPACKET_DATA(GLOBAL, PCM_READ,
|
|
||||||
xpp_line_t lines;
|
|
||||||
__u8 pcm[PCM_CHUNKSIZE];
|
|
||||||
);
|
|
||||||
DEF_RPACKET_DATA(GLOBAL, SYNC_SOURCE,
|
|
||||||
__u8 sync_mode;
|
|
||||||
__u8 drift;
|
|
||||||
);
|
|
||||||
DEF_RPACKET_DATA(GLOBAL, SYNC_REPLY,
|
|
||||||
__u8 sync_mode;
|
|
||||||
__u8 drift;
|
|
||||||
);
|
|
||||||
DEF_RPACKET_DATA(GLOBAL, REGISTER_REPLY,
|
|
||||||
reg_cmd_t regcmd;
|
|
||||||
);
|
|
||||||
DEF_RPACKET_DATA(GLOBAL, RESET_SYNC_COUNTERS,
|
|
||||||
__u8 mask;
|
|
||||||
);
|
|
||||||
DEF_RPACKET_DATA(GLOBAL, ERROR_CODE,
|
|
||||||
__u8 category_code;
|
|
||||||
__u8 errorbits;
|
|
||||||
__u8 bad_packet[0];
|
|
||||||
);
|
|
||||||
|
|
||||||
/* 0x07 */ DECLARE_CMD(GLOBAL, AB_REQUEST);
|
/* 0x07 */ DECLARE_CMD(GLOBAL, AB_REQUEST);
|
||||||
/* 0x19 */ DECLARE_CMD(GLOBAL, SYNC_SOURCE, enum sync_mode mode, int drift);
|
/* 0x19 */ DECLARE_CMD(GLOBAL, SYNC_SOURCE, enum sync_mode mode, int drift);
|
||||||
@ -102,7 +72,8 @@ DEF_RPACKET_DATA(GLOBAL, ERROR_CODE,
|
|||||||
|
|
||||||
int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
|
int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
|
||||||
bool writing, __u8 regnum, bool do_subreg, __u8 subreg,
|
bool writing, __u8 regnum, bool do_subreg, __u8 subreg,
|
||||||
__u8 data_low, bool do_datah, __u8 data_high, bool should_reply);
|
__u8 data_low, bool do_datah, __u8 data_high,
|
||||||
|
bool should_reply);
|
||||||
int send_multibyte_request(xbus_t *xbus, unsigned unit, xportno_t portno,
|
int send_multibyte_request(xbus_t *xbus, unsigned unit, xportno_t portno,
|
||||||
bool eoftx, __u8 *buf, unsigned len);
|
bool eoftx, __u8 *buf, unsigned len);
|
||||||
extern xproto_table_t PROTO_TABLE(GLOBAL);
|
extern xproto_table_t PROTO_TABLE(GLOBAL);
|
||||||
|
@ -36,7 +36,8 @@
|
|||||||
static const char rcsid[] = "$Id$";
|
static const char rcsid[] = "$Id$";
|
||||||
|
|
||||||
static DEF_PARM(int, debug, 0, 0644, "Print DBG statements"); /* must be before dahdi_debug.h */
|
static DEF_PARM(int, debug, 0, 0644, "Print DBG statements"); /* must be before dahdi_debug.h */
|
||||||
static DEF_PARM(uint, poll_interval, 500, 0644, "Poll channel state interval in milliseconds (0 - disable)");
|
static DEF_PARM(uint, poll_interval, 500, 0644,
|
||||||
|
"Poll channel state interval in milliseconds (0 - disable)");
|
||||||
|
|
||||||
#define PRI_LINES_BITMASK BITMASK(31)
|
#define PRI_LINES_BITMASK BITMASK(31)
|
||||||
#define PRI_SIGCAP ( \
|
#define PRI_SIGCAP ( \
|
||||||
@ -143,14 +144,12 @@ static int pri_linecompat(enum pri_protocol pri_protocol)
|
|||||||
[PRI_PROTO_0] = 0,
|
[PRI_PROTO_0] = 0,
|
||||||
[PRI_PROTO_E1] =
|
[PRI_PROTO_E1] =
|
||||||
/* coding */
|
/* coding */
|
||||||
DAHDI_CONFIG_CCS |
|
DAHDI_CONFIG_CCS | DAHDI_CONFIG_CRC4 |
|
||||||
DAHDI_CONFIG_CRC4 |
|
|
||||||
/* framing */
|
/* framing */
|
||||||
DAHDI_CONFIG_AMI | DAHDI_CONFIG_HDB3,
|
DAHDI_CONFIG_AMI | DAHDI_CONFIG_HDB3,
|
||||||
[PRI_PROTO_T1] =
|
[PRI_PROTO_T1] =
|
||||||
/* coding */
|
/* coding */
|
||||||
DAHDI_CONFIG_D4 |
|
DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF |
|
||||||
DAHDI_CONFIG_ESF |
|
|
||||||
/* framing */
|
/* framing */
|
||||||
DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS,
|
DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS,
|
||||||
[PRI_PROTO_J1] = 0
|
[PRI_PROTO_J1] = 0
|
||||||
@ -356,11 +355,10 @@ struct PRI_priv_data {
|
|||||||
static xproto_table_t PROTO_TABLE(PRI);
|
static xproto_table_t PROTO_TABLE(PRI);
|
||||||
|
|
||||||
DEF_RPACKET_DATA(PRI, SET_LED, /* Set one of the LED's */
|
DEF_RPACKET_DATA(PRI, SET_LED, /* Set one of the LED's */
|
||||||
struct pri_leds pri_leds;
|
struct pri_leds pri_leds;);
|
||||||
);
|
|
||||||
|
|
||||||
|
static /* 0x33 */ DECLARE_CMD(PRI, SET_LED, enum pri_led_selectors led_sel,
|
||||||
static /* 0x33 */ DECLARE_CMD(PRI, SET_LED, enum pri_led_selectors led_sel, enum pri_led_state to_led_state);
|
enum pri_led_state to_led_state);
|
||||||
|
|
||||||
#define DO_LED(xpd, which, tostate) \
|
#define DO_LED(xpd, which, tostate) \
|
||||||
CALL_PROTO(PRI, SET_LED, (xpd)->xbus, (xpd), (which), (tostate))
|
CALL_PROTO(PRI, SET_LED, (xpd)->xbus, (xpd), (which), (tostate))
|
||||||
@ -369,15 +367,11 @@ static /* 0x33 */ DECLARE_CMD(PRI, SET_LED, enum pri_led_selectors led_sel, enum
|
|||||||
|
|
||||||
static int query_subunit(xpd_t *xpd, __u8 regnum)
|
static int query_subunit(xpd_t *xpd, __u8 regnum)
|
||||||
{
|
{
|
||||||
XPD_DBG(REGS, xpd, "(%d%d): REG=0x%02X\n",
|
XPD_DBG(REGS, xpd, "(%d%d): REG=0x%02X\n", xpd->addr.unit,
|
||||||
xpd->addr.unit, xpd->addr.subunit,
|
xpd->addr.subunit, regnum);
|
||||||
regnum);
|
return xpp_register_request(xpd->xbus, xpd, PRI_PORT(xpd), /* portno */
|
||||||
return xpp_register_request(
|
|
||||||
xpd->xbus, xpd,
|
|
||||||
PRI_PORT(xpd), /* portno */
|
|
||||||
0, /* writing */
|
0, /* writing */
|
||||||
regnum,
|
regnum, 0, /* do_subreg */
|
||||||
0, /* do_subreg */
|
|
||||||
0, /* subreg */
|
0, /* subreg */
|
||||||
0, /* data_L */
|
0, /* data_L */
|
||||||
0, /* do_datah */
|
0, /* do_datah */
|
||||||
@ -386,18 +380,13 @@ static int query_subunit(xpd_t *xpd, __u8 regnum)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int write_subunit(xpd_t *xpd, __u8 regnum, __u8 val)
|
static int write_subunit(xpd_t *xpd, __u8 regnum, __u8 val)
|
||||||
{
|
{
|
||||||
XPD_DBG(REGS, xpd, "(%d%d): REG=0x%02X dataL=0x%02X\n",
|
XPD_DBG(REGS, xpd, "(%d%d): REG=0x%02X dataL=0x%02X\n", xpd->addr.unit,
|
||||||
xpd->addr.unit, xpd->addr.subunit,
|
xpd->addr.subunit, regnum, val);
|
||||||
regnum, val);
|
return xpp_register_request(xpd->xbus, xpd, PRI_PORT(xpd), /* portno */
|
||||||
return xpp_register_request(
|
|
||||||
xpd->xbus, xpd,
|
|
||||||
PRI_PORT(xpd), /* portno */
|
|
||||||
1, /* writing */
|
1, /* writing */
|
||||||
regnum,
|
regnum, 0, /* do_subreg */
|
||||||
0, /* do_subreg */
|
|
||||||
0, /* subreg */
|
0, /* subreg */
|
||||||
val, /* data_L */
|
val, /* data_L */
|
||||||
0, /* do_datah */
|
0, /* do_datah */
|
||||||
@ -408,15 +397,11 @@ static int write_subunit(xpd_t *xpd, __u8 regnum, __u8 val)
|
|||||||
|
|
||||||
static int pri_write_reg(xpd_t *xpd, int regnum, __u8 val)
|
static int pri_write_reg(xpd_t *xpd, int regnum, __u8 val)
|
||||||
{
|
{
|
||||||
XPD_DBG(REGS, xpd, "(%d%d): REG=0x%02X dataL=0x%02X\n",
|
XPD_DBG(REGS, xpd, "(%d%d): REG=0x%02X dataL=0x%02X\n", xpd->addr.unit,
|
||||||
xpd->addr.unit, xpd->addr.subunit,
|
xpd->addr.subunit, regnum, val);
|
||||||
regnum, val);
|
return xpp_register_request(xpd->xbus, xpd, 0, /* portno=0 */
|
||||||
return xpp_register_request(
|
|
||||||
xpd->xbus, xpd,
|
|
||||||
0, /* portno=0 */
|
|
||||||
1, /* writing */
|
1, /* writing */
|
||||||
regnum,
|
regnum, 0, /* do_subreg */
|
||||||
0, /* do_subreg */
|
|
||||||
0, /* subreg */
|
0, /* subreg */
|
||||||
val, /* data_L */
|
val, /* data_L */
|
||||||
0, /* do_datah */
|
0, /* do_datah */
|
||||||
@ -490,8 +475,8 @@ static int write_cas_reg(xpd_t *xpd, int rsnum, __u8 val)
|
|||||||
if (is_d4) {
|
if (is_d4) {
|
||||||
/* same data should be copied to RS7..12 in D4 only */
|
/* same data should be copied to RS7..12 in D4 only */
|
||||||
regnum = REG_RS7_E + rsnum;
|
regnum = REG_RS7_E + rsnum;
|
||||||
XPD_DBG(SIGNAL, xpd, "RBS(TX): reg=0x%X val=0x%02X\n",
|
XPD_DBG(SIGNAL, xpd, "RBS(TX): reg=0x%X val=0x%02X\n", regnum,
|
||||||
regnum, val);
|
val);
|
||||||
write_subunit(xpd, regnum, val);
|
write_subunit(xpd, regnum, val);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -503,16 +488,14 @@ static bool valid_pri_modes(const xpd_t *xpd)
|
|||||||
|
|
||||||
BUG_ON(!xpd);
|
BUG_ON(!xpd);
|
||||||
priv = xpd->priv;
|
priv = xpd->priv;
|
||||||
if (
|
if (priv->pri_protocol != PRI_PROTO_E1
|
||||||
priv->pri_protocol != PRI_PROTO_E1 &&
|
&& priv->pri_protocol != PRI_PROTO_T1
|
||||||
priv->pri_protocol != PRI_PROTO_T1 &&
|
&& priv->pri_protocol != PRI_PROTO_J1)
|
||||||
priv->pri_protocol != PRI_PROTO_J1)
|
|
||||||
return 0;
|
return 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PRI_card_pcm_recompute(xpd_t *xpd,
|
static void PRI_card_pcm_recompute(xpd_t *xpd, xpp_line_t pcm_mask)
|
||||||
xpp_line_t pcm_mask)
|
|
||||||
{
|
{
|
||||||
struct PRI_priv_data *priv;
|
struct PRI_priv_data *priv;
|
||||||
int i;
|
int i;
|
||||||
@ -546,8 +529,7 @@ static void PRI_card_pcm_recompute(xpd_t *xpd,
|
|||||||
}
|
}
|
||||||
pcm_len = (line_count)
|
pcm_len = (line_count)
|
||||||
? RPACKET_HEADERSIZE + sizeof(xpp_line_t) +
|
? RPACKET_HEADERSIZE + sizeof(xpp_line_t) +
|
||||||
line_count * DAHDI_CHUNKSIZE
|
line_count * DAHDI_CHUNKSIZE : 0L;
|
||||||
: 0L;
|
|
||||||
update_wanted_pcm_mask(xpd, pcm_mask, pcm_len);
|
update_wanted_pcm_mask(xpd, pcm_mask, pcm_len);
|
||||||
spin_unlock_irqrestore(&PHONEDEV(xpd).lock_recompute_pcm, flags);
|
spin_unlock_irqrestore(&PHONEDEV(xpd).lock_recompute_pcm, flags);
|
||||||
}
|
}
|
||||||
@ -571,12 +553,14 @@ static int set_pri_proto(xpd_t *xpd, enum pri_protocol set_proto)
|
|||||||
phonedev = &PHONEDEV(xpd);
|
phonedev = &PHONEDEV(xpd);
|
||||||
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &phonedev->span.flags)) {
|
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &phonedev->span.flags)) {
|
||||||
XPD_NOTICE(xpd, "%s: %s already assigned as span %d\n",
|
XPD_NOTICE(xpd, "%s: %s already assigned as span %d\n",
|
||||||
__func__, phonedev->span.name, phonedev->span.spanno);
|
__func__, phonedev->span.name,
|
||||||
|
phonedev->span.spanno);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
if (priv->pri_protocol != PRI_PROTO_0) {
|
if (priv->pri_protocol != PRI_PROTO_0) {
|
||||||
if (priv->pri_protocol == set_proto) {
|
if (priv->pri_protocol == set_proto) {
|
||||||
XPD_NOTICE(xpd, "Already in protocol %s. Ignored\n", pri_protocol_name(set_proto));
|
XPD_NOTICE(xpd, "Already in protocol %s. Ignored\n",
|
||||||
|
pri_protocol_name(set_proto));
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
XPD_INFO(xpd, "Switching from %s to %s\n",
|
XPD_INFO(xpd, "Switching from %s to %s\n",
|
||||||
@ -588,7 +572,8 @@ static int set_pri_proto(xpd_t *xpd, enum pri_protocol set_proto)
|
|||||||
case PRI_PROTO_E1:
|
case PRI_PROTO_E1:
|
||||||
deflaw = DAHDI_LAW_ALAW;
|
deflaw = DAHDI_LAW_ALAW;
|
||||||
dchan_num = 16;
|
dchan_num = 16;
|
||||||
default_lineconfig = DAHDI_CONFIG_CCS | DAHDI_CONFIG_CRC4 | DAHDI_CONFIG_HDB3;
|
default_lineconfig =
|
||||||
|
DAHDI_CONFIG_CCS | DAHDI_CONFIG_CRC4 | DAHDI_CONFIG_HDB3;
|
||||||
break;
|
break;
|
||||||
case PRI_PROTO_T1:
|
case PRI_PROTO_T1:
|
||||||
deflaw = DAHDI_LAW_MULAW;
|
deflaw = DAHDI_LAW_MULAW;
|
||||||
@ -605,8 +590,8 @@ static int set_pri_proto(xpd_t *xpd, enum pri_protocol set_proto)
|
|||||||
XPD_NOTICE(xpd, "J1 is not supported yet\n");
|
XPD_NOTICE(xpd, "J1 is not supported yet\n");
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
default:
|
default:
|
||||||
XPD_ERR(xpd, "%s: Unknown pri protocol = %d\n",
|
XPD_ERR(xpd, "%s: Unknown pri protocol = %d\n", __func__,
|
||||||
__func__, set_proto);
|
set_proto);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
priv->pri_protocol = set_proto;
|
priv->pri_protocol = set_proto;
|
||||||
@ -619,11 +604,8 @@ static int set_pri_proto(xpd_t *xpd, enum pri_protocol set_proto)
|
|||||||
priv->local_loopback = 0;
|
priv->local_loopback = 0;
|
||||||
xpd->type_name = type_name(priv->pri_protocol);
|
xpd->type_name = type_name(priv->pri_protocol);
|
||||||
XPD_DBG(GENERAL, xpd, "%s, channels=%d, dchan_num=%d, deflaw=%d\n",
|
XPD_DBG(GENERAL, xpd, "%s, channels=%d, dchan_num=%d, deflaw=%d\n",
|
||||||
pri_protocol_name(set_proto),
|
pri_protocol_name(set_proto), phonedev->channels,
|
||||||
phonedev->channels,
|
priv->dchan_num, priv->deflaw);
|
||||||
priv->dchan_num,
|
|
||||||
priv->deflaw
|
|
||||||
);
|
|
||||||
/*
|
/*
|
||||||
* Must set default now, so layer1 polling (Register REG_FRS0) would
|
* Must set default now, so layer1 polling (Register REG_FRS0) would
|
||||||
* give reliable results.
|
* give reliable results.
|
||||||
@ -652,7 +634,8 @@ static void dahdi_update_syncsrc(xpd_t *xpd)
|
|||||||
priv = subxpd->priv;
|
priv = subxpd->priv;
|
||||||
if (priv->clock_source && priv->alarms == 0) {
|
if (priv->clock_source && priv->alarms == 0) {
|
||||||
if (best_spanno)
|
if (best_spanno)
|
||||||
XPD_ERR(xpd, "Duplicate XPD's with clock_source=1\n");
|
XPD_ERR(xpd,
|
||||||
|
"Duplicate XPD's with clock_source=1\n");
|
||||||
best_spanno = PHONEDEV(subxpd).span.spanno;
|
best_spanno = PHONEDEV(subxpd).span.spanno;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -661,7 +644,8 @@ static void dahdi_update_syncsrc(xpd_t *xpd)
|
|||||||
if (!subxpd)
|
if (!subxpd)
|
||||||
continue;
|
continue;
|
||||||
if (PHONEDEV(subxpd).span.syncsrc == best_spanno)
|
if (PHONEDEV(subxpd).span.syncsrc == best_spanno)
|
||||||
XPD_DBG(SYNC, xpd, "Setting SyncSource to span %d\n", best_spanno);
|
XPD_DBG(SYNC, xpd, "Setting SyncSource to span %d\n",
|
||||||
|
best_spanno);
|
||||||
else
|
else
|
||||||
XPD_DBG(SYNC, xpd, "Slaving to span %d\n", best_spanno);
|
XPD_DBG(SYNC, xpd, "Slaving to span %d\n", best_spanno);
|
||||||
PHONEDEV(subxpd).span.syncsrc = best_spanno;
|
PHONEDEV(subxpd).span.syncsrc = best_spanno;
|
||||||
@ -695,22 +679,27 @@ static void set_clocking(xpd_t *xpd)
|
|||||||
priv = subxpd->priv;
|
priv = subxpd->priv;
|
||||||
if (priv->alarms != 0)
|
if (priv->alarms != 0)
|
||||||
continue;
|
continue;
|
||||||
if (PHONEDEV(subxpd).timing_priority > 0 && PHONEDEV(subxpd).timing_priority < best_subunit_prio) {
|
if (PHONEDEV(subxpd).timing_priority > 0
|
||||||
|
&& PHONEDEV(subxpd).timing_priority < best_subunit_prio) {
|
||||||
best_xpd = subxpd;
|
best_xpd = subxpd;
|
||||||
best_subunit = i;
|
best_subunit = i;
|
||||||
best_subunit_prio = PHONEDEV(subxpd).timing_priority;
|
best_subunit_prio = PHONEDEV(subxpd).timing_priority;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Now set it */
|
/* Now set it */
|
||||||
if (best_xpd && ((struct PRI_priv_data *)(best_xpd->priv))->clock_source == 0) {
|
if (best_xpd
|
||||||
|
&& ((struct PRI_priv_data *)(best_xpd->priv))->clock_source == 0) {
|
||||||
__u8 reg_pc_init[] = { VAL_PC_GPI, VAL_PC_GPI, VAL_PC_GPI };
|
__u8 reg_pc_init[] = { VAL_PC_GPI, VAL_PC_GPI, VAL_PC_GPI };
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(reg_pc_init); i++) {
|
for (i = 0; i < ARRAY_SIZE(reg_pc_init); i++) {
|
||||||
__u8 reg_pc = reg_pc_init[i];
|
__u8 reg_pc = reg_pc_init[i];
|
||||||
|
|
||||||
reg_pc |= (best_subunit & (1 << i)) ? VAL_PC_GPOH : VAL_PC_GPOL;
|
reg_pc |=
|
||||||
|
(best_subunit & (1 << i)) ? VAL_PC_GPOH :
|
||||||
|
VAL_PC_GPOL;
|
||||||
XPD_DBG(SYNC, best_xpd,
|
XPD_DBG(SYNC, best_xpd,
|
||||||
"ClockSource Set: PC%d=0x%02X\n", 2+i, reg_pc);
|
"ClockSource Set: PC%d=0x%02X\n", 2 + i,
|
||||||
|
reg_pc);
|
||||||
pri_write_reg(xpd, REG_PC2 + i, reg_pc);
|
pri_write_reg(xpd, REG_PC2 + i, reg_pc);
|
||||||
}
|
}
|
||||||
((struct PRI_priv_data *)(best_xpd->priv))->clock_source = 1;
|
((struct PRI_priv_data *)(best_xpd->priv))->clock_source = 1;
|
||||||
@ -781,7 +770,8 @@ static int set_localloop(xpd_t *xpd, bool localloop)
|
|||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
priv->local_loopback = localloop;
|
priv->local_loopback = localloop;
|
||||||
XPD_DBG(SIGNAL, xpd, "%s: %s\n", __func__, (localloop) ? "LOCALLOOP" : "NO");
|
XPD_DBG(SIGNAL, xpd, "%s: %s\n", __func__,
|
||||||
|
(localloop) ? "LOCALLOOP" : "NO");
|
||||||
set_master_mode(__func__, xpd);
|
set_master_mode(__func__, xpd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -793,15 +783,17 @@ static const struct {
|
|||||||
const int flags;
|
const int flags;
|
||||||
} valid_spanconfigs[sizeof(unsigned int) * 8] = {
|
} valid_spanconfigs[sizeof(unsigned int) * 8] = {
|
||||||
/* These apply to T1 */
|
/* These apply to T1 */
|
||||||
VALID_CONFIG(4, DAHDI_CONFIG_D4, "D4"),
|
VALID_CONFIG(4, DAHDI_CONFIG_D4, "D4"), VALID_CONFIG(5,
|
||||||
VALID_CONFIG(5, DAHDI_CONFIG_ESF, "ESF"),
|
DAHDI_CONFIG_ESF,
|
||||||
VALID_CONFIG(6, DAHDI_CONFIG_AMI, "AMI"),
|
"ESF"),
|
||||||
VALID_CONFIG(7, DAHDI_CONFIG_B8ZS, "B8ZS"),
|
VALID_CONFIG(6, DAHDI_CONFIG_AMI, "AMI"), VALID_CONFIG(7,
|
||||||
|
DAHDI_CONFIG_B8ZS,
|
||||||
|
"B8ZS"),
|
||||||
/* These apply to E1 */
|
/* These apply to E1 */
|
||||||
VALID_CONFIG(8, DAHDI_CONFIG_CCS, "CCS"),
|
VALID_CONFIG(8, DAHDI_CONFIG_CCS, "CCS"), VALID_CONFIG(9,
|
||||||
VALID_CONFIG(9, DAHDI_CONFIG_HDB3, "HDB3"),
|
DAHDI_CONFIG_HDB3,
|
||||||
VALID_CONFIG(10, DAHDI_CONFIG_CRC4, "CRC4"),
|
"HDB3"),
|
||||||
};
|
VALID_CONFIG(10, DAHDI_CONFIG_CRC4, "CRC4"),};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mark the lines as CLEAR or RBS signalling.
|
* Mark the lines as CLEAR or RBS signalling.
|
||||||
@ -829,9 +821,10 @@ static void set_rbslines(xpd_t *xpd, int channo)
|
|||||||
}
|
}
|
||||||
new_rbslines &= BITMASK(PHONEDEV(xpd).channels);
|
new_rbslines &= BITMASK(PHONEDEV(xpd).channels);
|
||||||
modified_lines = priv->rbslines ^ new_rbslines;
|
modified_lines = priv->rbslines ^ new_rbslines;
|
||||||
XPD_DBG(DEVICES, xpd, "RBSLINES-%d(%s): 0x%X\n",
|
XPD_DBG(DEVICES, xpd, "RBSLINES-%d(%s): 0x%X\n", channo,
|
||||||
channo, pri_protocol_name(priv->pri_protocol), new_rbslines);
|
pri_protocol_name(priv->pri_protocol), new_rbslines);
|
||||||
if ((priv->pri_protocol == PRI_PROTO_T1) || (priv->pri_protocol == PRI_PROTO_J1)) {
|
if ((priv->pri_protocol == PRI_PROTO_T1)
|
||||||
|
|| (priv->pri_protocol == PRI_PROTO_J1)) {
|
||||||
__u8 clear_lines = 0; /* Mark clear lines */
|
__u8 clear_lines = 0; /* Mark clear lines */
|
||||||
bool reg_changed = 0;
|
bool reg_changed = 0;
|
||||||
|
|
||||||
@ -847,10 +840,14 @@ static void set_rbslines(xpd_t *xpd, int channo)
|
|||||||
if (bitnum == 7) {
|
if (bitnum == 7) {
|
||||||
if (channo == 0 || reg_changed) {
|
if (channo == 0 || reg_changed) {
|
||||||
bytenum += REG_CCB1_T;
|
bytenum += REG_CCB1_T;
|
||||||
XPD_DBG(DEVICES, xpd, "RBS(%s): modified=0x%X rbslines=0x%X reg=0x%X clear_lines=0x%X\n",
|
XPD_DBG(DEVICES, xpd,
|
||||||
pri_protocol_name(priv->pri_protocol),
|
"RBS(%s): modified=0x%X rbslines=0x%X reg=0x%X clear_lines=0x%X\n",
|
||||||
modified_lines, new_rbslines, bytenum, clear_lines);
|
pri_protocol_name(priv->
|
||||||
write_subunit(xpd, bytenum, clear_lines);
|
pri_protocol),
|
||||||
|
modified_lines, new_rbslines,
|
||||||
|
bytenum, clear_lines);
|
||||||
|
write_subunit(xpd, bytenum,
|
||||||
|
clear_lines);
|
||||||
}
|
}
|
||||||
clear_lines = 0;
|
clear_lines = 0;
|
||||||
reg_changed = 0;
|
reg_changed = 0;
|
||||||
@ -920,8 +917,7 @@ static int pri_lineconfig(xpd_t *xpd, int lineconfig)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (flags && flags != BIT(i)) {
|
if (flags && flags != BIT(i)) {
|
||||||
ERR("%s: BUG: i=%d flags=0x%X\n",
|
ERR("%s: BUG: i=%d flags=0x%X\n", __func__, i, flags);
|
||||||
__func__, i, flags);
|
|
||||||
// BUG();
|
// BUG();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -951,7 +947,9 @@ static int pri_lineconfig(xpd_t *xpd, int lineconfig)
|
|||||||
/* framing first */
|
/* framing first */
|
||||||
if (lineconfig & DAHDI_CONFIG_B8ZS) {
|
if (lineconfig & DAHDI_CONFIG_B8ZS) {
|
||||||
framingstr = "B8ZS";
|
framingstr = "B8ZS";
|
||||||
fmr0 = REG_FMR0_E_XC1 | REG_FMR0_E_XC0 | REG_FMR0_E_RC1 | REG_FMR0_E_RC0;
|
fmr0 =
|
||||||
|
REG_FMR0_E_XC1 | REG_FMR0_E_XC0 | REG_FMR0_E_RC1 |
|
||||||
|
REG_FMR0_E_RC0;
|
||||||
} else if (lineconfig & DAHDI_CONFIG_AMI) {
|
} else if (lineconfig & DAHDI_CONFIG_AMI) {
|
||||||
framingstr = "AMI";
|
framingstr = "AMI";
|
||||||
fmr0 = REG_FMR0_E_XC1 | REG_FMR0_E_RC1;
|
fmr0 = REG_FMR0_E_XC1 | REG_FMR0_E_RC1;
|
||||||
@ -973,9 +971,12 @@ static int pri_lineconfig(xpd_t *xpd, int lineconfig)
|
|||||||
fmr0 |= REG_FMR0_E_RC0;
|
fmr0 |= REG_FMR0_E_RC0;
|
||||||
} else if (lineconfig & DAHDI_CONFIG_HDB3) {
|
} else if (lineconfig & DAHDI_CONFIG_HDB3) {
|
||||||
framingstr = "HDB3";
|
framingstr = "HDB3";
|
||||||
fmr0 = REG_FMR0_E_XC1 | REG_FMR0_E_XC0 | REG_FMR0_E_RC1 | REG_FMR0_E_RC0;
|
fmr0 =
|
||||||
|
REG_FMR0_E_XC1 | REG_FMR0_E_XC0 | REG_FMR0_E_RC1 |
|
||||||
|
REG_FMR0_E_RC0;
|
||||||
} else {
|
} else {
|
||||||
XPD_NOTICE(xpd, "Bad lineconfig. Not (B8ZS|AMI|HDB3). Ignored.\n");
|
XPD_NOTICE(xpd,
|
||||||
|
"Bad lineconfig. Not (B8ZS|AMI|HDB3). Ignored.\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
/* then coding */
|
/* then coding */
|
||||||
@ -1008,28 +1009,35 @@ static int pri_lineconfig(xpd_t *xpd, int lineconfig)
|
|||||||
fmr3 |= REG_FMR3_EXTIW;
|
fmr3 |= REG_FMR3_EXTIW;
|
||||||
}
|
}
|
||||||
XPD_DBG(GENERAL, xpd, "[%s] lineconfig=%s/%s/%s %s (0x%X)\n",
|
XPD_DBG(GENERAL, xpd, "[%s] lineconfig=%s/%s/%s %s (0x%X)\n",
|
||||||
(priv->clock_source)?"MASTER":"SLAVE",
|
(priv->clock_source) ? "MASTER" : "SLAVE", framingstr,
|
||||||
framingstr, codingstr, crcstr,
|
codingstr, crcstr,
|
||||||
(lineconfig & DAHDI_CONFIG_NOTOPEN) ? "YELLOW" : "",
|
(lineconfig & DAHDI_CONFIG_NOTOPEN) ? "YELLOW" : "",
|
||||||
lineconfig);
|
lineconfig);
|
||||||
set_reg_lim0(__func__, xpd);
|
set_reg_lim0(__func__, xpd);
|
||||||
XPD_DBG(GENERAL, xpd, "%s: fmr1(0x%02X) = 0x%02X\n", __func__, REG_FMR1, fmr1);
|
XPD_DBG(GENERAL, xpd, "%s: fmr1(0x%02X) = 0x%02X\n", __func__, REG_FMR1,
|
||||||
|
fmr1);
|
||||||
write_subunit(xpd, REG_FMR1, fmr1);
|
write_subunit(xpd, REG_FMR1, fmr1);
|
||||||
XPD_DBG(GENERAL, xpd, "%s: fmr2(0x%02X) = 0x%02X\n", __func__, REG_FMR2, fmr2);
|
XPD_DBG(GENERAL, xpd, "%s: fmr2(0x%02X) = 0x%02X\n", __func__, REG_FMR2,
|
||||||
|
fmr2);
|
||||||
write_subunit(xpd, REG_FMR2, fmr2);
|
write_subunit(xpd, REG_FMR2, fmr2);
|
||||||
XPD_DBG(GENERAL, xpd, "%s: fmr0(0x%02X) = 0x%02X\n", __func__, REG_FMR0, fmr0);
|
XPD_DBG(GENERAL, xpd, "%s: fmr0(0x%02X) = 0x%02X\n", __func__, REG_FMR0,
|
||||||
|
fmr0);
|
||||||
write_subunit(xpd, REG_FMR0, fmr0);
|
write_subunit(xpd, REG_FMR0, fmr0);
|
||||||
XPD_DBG(GENERAL, xpd, "%s: fmr4(0x%02X) = 0x%02X\n", __func__, REG_FMR4, fmr4);
|
XPD_DBG(GENERAL, xpd, "%s: fmr4(0x%02X) = 0x%02X\n", __func__, REG_FMR4,
|
||||||
|
fmr4);
|
||||||
write_subunit(xpd, REG_FMR4, fmr4);
|
write_subunit(xpd, REG_FMR4, fmr4);
|
||||||
if (fmr3) {
|
if (fmr3) {
|
||||||
XPD_DBG(GENERAL, xpd, "%s: fmr3(0x%02X) = 0x%02X\n", __func__, REG_FMR3, fmr3);
|
XPD_DBG(GENERAL, xpd, "%s: fmr3(0x%02X) = 0x%02X\n", __func__,
|
||||||
|
REG_FMR3, fmr3);
|
||||||
write_subunit(xpd, REG_FMR3, fmr3);
|
write_subunit(xpd, REG_FMR3, fmr3);
|
||||||
}
|
}
|
||||||
XPD_DBG(GENERAL, xpd, "%s: cmdr(0x%02X) = 0x%02X\n", __func__, REG_CMDR_E, cmdr);
|
XPD_DBG(GENERAL, xpd, "%s: cmdr(0x%02X) = 0x%02X\n", __func__,
|
||||||
|
REG_CMDR_E, cmdr);
|
||||||
write_subunit(xpd, REG_CMDR_E, cmdr);
|
write_subunit(xpd, REG_CMDR_E, cmdr);
|
||||||
#ifdef JAPANEZE_SUPPORT
|
#ifdef JAPANEZE_SUPPORT
|
||||||
if (rc0) {
|
if (rc0) {
|
||||||
XPD_DBG(GENERAL, xpd, "%s: rc0(0x%02X) = 0x%02X\n", __func__, REG_RC0, rc0);
|
XPD_DBG(GENERAL, xpd, "%s: rc0(0x%02X) = 0x%02X\n", __func__,
|
||||||
|
REG_RC0, rc0);
|
||||||
write_subunit(xpd, REG_RC0, rc0);
|
write_subunit(xpd, REG_RC0, rc0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1047,7 +1055,8 @@ static int pri_lineconfig(xpd_t *xpd, int lineconfig)
|
|||||||
}
|
}
|
||||||
xsp |= REG_XSP_E_CASEN; /* Same as REG_FMR5_T_EIBR for T1 */
|
xsp |= REG_XSP_E_CASEN; /* Same as REG_FMR5_T_EIBR for T1 */
|
||||||
}
|
}
|
||||||
XPD_DBG(GENERAL, xpd, "%s: xsp(0x%02X) = 0x%02X\n", __func__, REG_XSP_E, xsp);
|
XPD_DBG(GENERAL, xpd, "%s: xsp(0x%02X) = 0x%02X\n", __func__, REG_XSP_E,
|
||||||
|
xsp);
|
||||||
write_subunit(xpd, REG_XSP_E, xsp);
|
write_subunit(xpd, REG_XSP_E, xsp);
|
||||||
return 0;
|
return 0;
|
||||||
bad_lineconfig:
|
bad_lineconfig:
|
||||||
@ -1090,7 +1099,8 @@ static int pri_spanconfig(struct file *file, struct dahdi_span *span,
|
|||||||
* We currently ignore it also.
|
* We currently ignore it also.
|
||||||
*/
|
*/
|
||||||
XPD_DBG(GENERAL, xpd, "[%s] lbo=%d lineconfig=0x%X sync=%d\n",
|
XPD_DBG(GENERAL, xpd, "[%s] lbo=%d lineconfig=0x%X sync=%d\n",
|
||||||
(priv->clock_source)?"MASTER":"SLAVE", lc->lbo, lc->lineconfig, lc->sync);
|
(priv->clock_source) ? "MASTER" : "SLAVE", lc->lbo,
|
||||||
|
lc->lineconfig, lc->sync);
|
||||||
ret = pri_lineconfig(xpd, lc->lineconfig);
|
ret = pri_lineconfig(xpd, lc->lineconfig);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
span->lineconfig = lc->lineconfig;
|
span->lineconfig = lc->lineconfig;
|
||||||
@ -1109,13 +1119,15 @@ static int pri_spanconfig(struct file *file, struct dahdi_span *span,
|
|||||||
static int pri_chanconfig(struct file *file, struct dahdi_chan *chan,
|
static int pri_chanconfig(struct file *file, struct dahdi_chan *chan,
|
||||||
int sigtype)
|
int sigtype)
|
||||||
{
|
{
|
||||||
struct phonedev *phonedev = container_of(chan->span, struct phonedev, span);
|
struct phonedev *phonedev =
|
||||||
|
container_of(chan->span, struct phonedev, span);
|
||||||
xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
|
xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
|
||||||
struct PRI_priv_data *priv;
|
struct PRI_priv_data *priv;
|
||||||
|
|
||||||
BUG_ON(!xpd);
|
BUG_ON(!xpd);
|
||||||
priv = xpd->priv;
|
priv = xpd->priv;
|
||||||
DBG(GENERAL, "channel %d (%s) -> %s\n", chan->channo, chan->name, sig2str(sigtype));
|
DBG(GENERAL, "channel %d (%s) -> %s\n", chan->channo, chan->name,
|
||||||
|
sig2str(sigtype));
|
||||||
/*
|
/*
|
||||||
* Some bookkeeping to check if we have DChan defined or not
|
* Some bookkeeping to check if we have DChan defined or not
|
||||||
* FIXME: actually use this to prevent duplicate DChan definitions
|
* FIXME: actually use this to prevent duplicate DChan definitions
|
||||||
@ -1123,11 +1135,11 @@ static int pri_chanconfig(struct file *file, struct dahdi_chan *chan,
|
|||||||
*/
|
*/
|
||||||
if (is_sigtype_dchan(sigtype)) {
|
if (is_sigtype_dchan(sigtype)) {
|
||||||
if (VALID_DCHAN(priv) && DCHAN(priv) != chan->channo) {
|
if (VALID_DCHAN(priv) && DCHAN(priv) != chan->channo) {
|
||||||
ERR("channel %d (%s) marked DChan but also channel %d.\n",
|
ERR("channel %d (%s) marked DChan but also channel %d.\n", chan->channo, chan->name, DCHAN(priv));
|
||||||
chan->channo, chan->name, DCHAN(priv));
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
XPD_DBG(GENERAL, xpd, "channel %d (%s) marked as DChan\n", chan->channo, chan->name);
|
XPD_DBG(GENERAL, xpd, "channel %d (%s) marked as DChan\n",
|
||||||
|
chan->channo, chan->name);
|
||||||
SET_DCHAN(priv, chan->channo);
|
SET_DCHAN(priv, chan->channo);
|
||||||
/* In T1, we don't know before-hand */
|
/* In T1, we don't know before-hand */
|
||||||
if (priv->pri_protocol != PRI_PROTO_E1 && priv->is_cas != 0) {
|
if (priv->pri_protocol != PRI_PROTO_E1 && priv->is_cas != 0) {
|
||||||
@ -1135,7 +1147,9 @@ static int pri_chanconfig(struct file *file, struct dahdi_chan *chan,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (chan->channo == 1) {
|
if (chan->channo == 1) {
|
||||||
XPD_DBG(GENERAL, xpd, "channel %d (%s) marked a not DChan\n", chan->channo, chan->name);
|
XPD_DBG(GENERAL, xpd,
|
||||||
|
"channel %d (%s) marked a not DChan\n",
|
||||||
|
chan->channo, chan->name);
|
||||||
SET_DCHAN(priv, NO_DCHAN);
|
SET_DCHAN(priv, NO_DCHAN);
|
||||||
}
|
}
|
||||||
/* In T1, we don't know before-hand */
|
/* In T1, we don't know before-hand */
|
||||||
@ -1152,8 +1166,9 @@ static int pri_chanconfig(struct file *file, struct dahdi_chan *chan,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static xpd_t *PRI_card_new(xbus_t *xbus, int unit, int subunit, const xproto_table_t *proto_table,
|
static xpd_t *PRI_card_new(xbus_t *xbus, int unit, int subunit,
|
||||||
__u8 subtype, int subunits, int subunit_ports, bool to_phone)
|
const xproto_table_t *proto_table, __u8 subtype,
|
||||||
|
int subunits, int subunit_ports, bool to_phone)
|
||||||
{
|
{
|
||||||
xpd_t *xpd = NULL;
|
xpd_t *xpd = NULL;
|
||||||
struct PRI_priv_data *priv;
|
struct PRI_priv_data *priv;
|
||||||
@ -1164,7 +1179,9 @@ static xpd_t *PRI_card_new(xbus_t *xbus, int unit, int subunit, const xproto_tab
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
XBUS_DBG(GENERAL, xbus, "\n");
|
XBUS_DBG(GENERAL, xbus, "\n");
|
||||||
xpd = xpd_alloc(xbus, unit, subunit, subtype, subunits, sizeof(struct PRI_priv_data), proto_table, channels);
|
xpd =
|
||||||
|
xpd_alloc(xbus, unit, subunit, subtype, subunits,
|
||||||
|
sizeof(struct PRI_priv_data), proto_table, channels);
|
||||||
if (!xpd)
|
if (!xpd)
|
||||||
return NULL;
|
return NULL;
|
||||||
priv = xpd->priv;
|
priv = xpd->priv;
|
||||||
@ -1288,7 +1305,8 @@ static int apply_pri_protocol(xpd_t *xpd)
|
|||||||
XPD_DBG(GENERAL, xpd, "setting PRI channel %d (%s)\n", i,
|
XPD_DBG(GENERAL, xpd, "setting PRI channel %d (%s)\n", i,
|
||||||
(is_dchan) ? "DCHAN" : "CLEAR");
|
(is_dchan) ? "DCHAN" : "CLEAR");
|
||||||
snprintf(cur_chan->name, MAX_CHANNAME, "XPP_%s/%02d/%1d%1d/%d",
|
snprintf(cur_chan->name, MAX_CHANNAME, "XPP_%s/%02d/%1d%1d/%d",
|
||||||
xpd->type_name, xbus->num, xpd->addr.unit, xpd->addr.subunit, i);
|
xpd->type_name, xbus->num, xpd->addr.unit,
|
||||||
|
xpd->addr.subunit, i);
|
||||||
cur_chan->chanpos = i + 1;
|
cur_chan->chanpos = i + 1;
|
||||||
cur_chan->pvt = xpd;
|
cur_chan->pvt = xpd;
|
||||||
cur_chan->sigcap = PRI_SIGCAP;
|
cur_chan->sigcap = PRI_SIGCAP;
|
||||||
@ -1314,10 +1332,8 @@ static int PRI_card_dahdi_preregistration(xpd_t *xpd, bool on)
|
|||||||
priv = xpd->priv;
|
priv = xpd->priv;
|
||||||
BUG_ON(!xbus);
|
BUG_ON(!xbus);
|
||||||
XPD_DBG(GENERAL, xpd, "%s (proto=%s, channels=%d, deflaw=%d)\n",
|
XPD_DBG(GENERAL, xpd, "%s (proto=%s, channels=%d, deflaw=%d)\n",
|
||||||
(on)?"on":"off",
|
(on) ? "on" : "off", pri_protocol_name(priv->pri_protocol),
|
||||||
pri_protocol_name(priv->pri_protocol),
|
PHONEDEV(xpd).channels, priv->deflaw);
|
||||||
PHONEDEV(xpd).channels,
|
|
||||||
priv->deflaw);
|
|
||||||
if (!on) {
|
if (!on) {
|
||||||
/* Nothing to do yet */
|
/* Nothing to do yet */
|
||||||
return 0;
|
return 0;
|
||||||
@ -1357,7 +1373,8 @@ static void dchan_state(xpd_t *xpd, bool up)
|
|||||||
} else {
|
} else {
|
||||||
int d = PRI_DCHAN_IDX(priv);
|
int d = PRI_DCHAN_IDX(priv);
|
||||||
|
|
||||||
if (SPAN_REGISTERED(xpd) && d >= 0 && d < PHONEDEV(xpd).channels) {
|
if (SPAN_REGISTERED(xpd) && d >= 0
|
||||||
|
&& d < PHONEDEV(xpd).channels) {
|
||||||
__u8 *pcm;
|
__u8 *pcm;
|
||||||
|
|
||||||
pcm = (__u8 *)XPD_CHAN(xpd, d)->readchunk;
|
pcm = (__u8 *)XPD_CHAN(xpd, d)->readchunk;
|
||||||
@ -1455,8 +1472,7 @@ static int PRI_card_tick(xbus_t *xbus, xpd_t *xpd)
|
|||||||
/*
|
/*
|
||||||
* Poll layer1 status (cascade subunits)
|
* Poll layer1 status (cascade subunits)
|
||||||
*/
|
*/
|
||||||
if (poll_interval != 0 &&
|
if (poll_interval != 0 && ((xpd->timer_count % poll_interval) == 0)) {
|
||||||
((xpd->timer_count % poll_interval) == 0)) {
|
|
||||||
priv->poll_noreplies++;
|
priv->poll_noreplies++;
|
||||||
query_subunit(xpd, REG_FRS0);
|
query_subunit(xpd, REG_FRS0);
|
||||||
//query_subunit(xpd, REG_FRS1);
|
//query_subunit(xpd, REG_FRS1);
|
||||||
@ -1469,7 +1485,8 @@ static int PRI_card_tick(xbus_t *xbus, xpd_t *xpd)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int PRI_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long arg)
|
static int PRI_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd,
|
||||||
|
unsigned long arg)
|
||||||
{
|
{
|
||||||
struct dahdi_chan *chan;
|
struct dahdi_chan *chan;
|
||||||
|
|
||||||
@ -1487,8 +1504,8 @@ static int PRI_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long a
|
|||||||
*/
|
*/
|
||||||
case DAHDI_TONEDETECT:
|
case DAHDI_TONEDETECT:
|
||||||
LINE_DBG(SIGNAL, xpd, pos, "PRI: TONEDETECT (%s)\n",
|
LINE_DBG(SIGNAL, xpd, pos, "PRI: TONEDETECT (%s)\n",
|
||||||
(chan->flags & DAHDI_FLAG_AUDIO) ?
|
(chan->
|
||||||
"AUDIO" : "SILENCE");
|
flags & DAHDI_FLAG_AUDIO) ? "AUDIO" : "SILENCE");
|
||||||
return -ENOTTY;
|
return -ENOTTY;
|
||||||
case DAHDI_ONHOOKTRANSFER:
|
case DAHDI_ONHOOKTRANSFER:
|
||||||
LINE_DBG(SIGNAL, xpd, pos, "PRI: ONHOOKTRANSFER\n");
|
LINE_DBG(SIGNAL, xpd, pos, "PRI: ONHOOKTRANSFER\n");
|
||||||
@ -1530,7 +1547,8 @@ static int pri_startup(struct file *file, struct dahdi_span *span)
|
|||||||
priv = xpd->priv;
|
priv = xpd->priv;
|
||||||
BUG_ON(!priv);
|
BUG_ON(!priv);
|
||||||
if (!XBUS_IS(xpd->xbus, READY)) {
|
if (!XBUS_IS(xpd->xbus, READY)) {
|
||||||
XPD_DBG(GENERAL, xpd, "Startup called by dahdi. No Hardware. Ignored\n");
|
XPD_DBG(GENERAL, xpd,
|
||||||
|
"Startup called by dahdi. No Hardware. Ignored\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
XPD_DBG(GENERAL, xpd, "STARTUP\n");
|
XPD_DBG(GENERAL, xpd, "STARTUP\n");
|
||||||
@ -1554,7 +1572,8 @@ static int pri_shutdown(struct dahdi_span *span)
|
|||||||
priv = xpd->priv;
|
priv = xpd->priv;
|
||||||
BUG_ON(!priv);
|
BUG_ON(!priv);
|
||||||
if (!XBUS_IS(xpd->xbus, READY)) {
|
if (!XBUS_IS(xpd->xbus, READY)) {
|
||||||
XPD_DBG(GENERAL, xpd, "Shutdown called by dahdi. No Hardware. Ignored\n");
|
XPD_DBG(GENERAL, xpd,
|
||||||
|
"Shutdown called by dahdi. No Hardware. Ignored\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
XPD_DBG(GENERAL, xpd, "SHUTDOWN\n");
|
XPD_DBG(GENERAL, xpd, "SHUTDOWN\n");
|
||||||
@ -1576,7 +1595,8 @@ static int encode_rbsbits_e1(xpd_t *xpd, int pos, int bits)
|
|||||||
if (pos == 15)
|
if (pos == 15)
|
||||||
return 0; /* Don't write dchan in CAS */
|
return 0; /* Don't write dchan in CAS */
|
||||||
if (pos < 0 || pos > 31) {
|
if (pos < 0 || pos > 31) {
|
||||||
XPD_NOTICE(xpd, "%s: pos=%d out of range. Ignore\n", __func__, pos);
|
XPD_NOTICE(xpd, "%s: pos=%d out of range. Ignore\n", __func__,
|
||||||
|
pos);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (pos >= 16) {
|
if (pos >= 16) {
|
||||||
@ -1625,10 +1645,8 @@ static int encode_rbsbits_t1(xpd_t *xpd, int pos, int bits)
|
|||||||
val &= ~mask;
|
val &= ~mask;
|
||||||
val |= tx_bits;
|
val |= tx_bits;
|
||||||
LINE_DBG(SIGNAL, xpd, pos,
|
LINE_DBG(SIGNAL, xpd, pos,
|
||||||
"bits=0x%02X RS%02d(%s) offset=%d tx_bits=0x%02X\n",
|
"bits=0x%02X RS%02d(%s) offset=%d tx_bits=0x%02X\n", bits,
|
||||||
bits, rsnum+1,
|
rsnum + 1, (priv->is_esf) ? "esf" : "d4", offset, tx_bits);
|
||||||
(priv->is_esf) ? "esf" : "d4",
|
|
||||||
offset, tx_bits);
|
|
||||||
write_cas_reg(xpd, rsnum, val);
|
write_cas_reg(xpd, rsnum, val);
|
||||||
priv->dchan_tx_counter++;
|
priv->dchan_tx_counter++;
|
||||||
return 0;
|
return 0;
|
||||||
@ -1700,7 +1718,8 @@ static int pri_rbsbits(struct dahdi_chan *chan, int bits)
|
|||||||
if (encode_rbsbits_t1(xpd, pos, bits) < 0)
|
if (encode_rbsbits_t1(xpd, pos, bits) < 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
} else {
|
} else {
|
||||||
XPD_NOTICE(xpd, "%s: protocol %s is not supported yet with CAS\n",
|
XPD_NOTICE(xpd,
|
||||||
|
"%s: protocol %s is not supported yet with CAS\n",
|
||||||
__func__, pri_protocol_name(priv->pri_protocol));
|
__func__, pri_protocol_name(priv->pri_protocol));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@ -1757,13 +1776,17 @@ static void PRI_card_pcm_fromspan(xpd_t *xpd, xpacket_t *pack)
|
|||||||
int channo = XPD_CHAN(xpd, i)->channo;
|
int channo = XPD_CHAN(xpd, i)->channo;
|
||||||
|
|
||||||
if (pcmtx >= 0 && pcmtx_chan == channo)
|
if (pcmtx >= 0 && pcmtx_chan == channo)
|
||||||
memset((u_char *)pcm, pcmtx, DAHDI_CHUNKSIZE);
|
memset((u_char *)pcm, pcmtx,
|
||||||
|
DAHDI_CHUNKSIZE);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
memcpy((u_char *)pcm, chan->writechunk, DAHDI_CHUNKSIZE);
|
memcpy((u_char *)pcm, chan->writechunk,
|
||||||
|
DAHDI_CHUNKSIZE);
|
||||||
if (i == PRI_DCHAN_IDX(priv)) {
|
if (i == PRI_DCHAN_IDX(priv)) {
|
||||||
if (priv->dchan_tx_sample != chan->writechunk[0]) {
|
if (priv->dchan_tx_sample !=
|
||||||
priv->dchan_tx_sample = chan->writechunk[0];
|
chan->writechunk[0]) {
|
||||||
|
priv->dchan_tx_sample =
|
||||||
|
chan->writechunk[0];
|
||||||
priv->dchan_tx_counter++;
|
priv->dchan_tx_counter++;
|
||||||
} else if (chan->writechunk[0] == 0xFF)
|
} else if (chan->writechunk[0] == 0xFF)
|
||||||
dchan_state(xpd, 0);
|
dchan_state(xpd, 0);
|
||||||
@ -1771,7 +1794,8 @@ static void PRI_card_pcm_fromspan(xpd_t *xpd, xpacket_t *pack)
|
|||||||
chan->writechunk[0] = 0xFF; /* Clobber for next tick */
|
chan->writechunk[0] = 0xFF; /* Clobber for next tick */
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
memset((u_char *)pcm, DAHDI_XLAW(0, chan), DAHDI_CHUNKSIZE);
|
memset((u_char *)pcm, DAHDI_XLAW(0, chan),
|
||||||
|
DAHDI_CHUNKSIZE);
|
||||||
pcm += DAHDI_CHUNKSIZE;
|
pcm += DAHDI_CHUNKSIZE;
|
||||||
}
|
}
|
||||||
physical_chan++;
|
physical_chan++;
|
||||||
@ -1823,7 +1847,8 @@ static void PRI_card_pcm_tospan(xpd_t *xpd, xpacket_t *pack)
|
|||||||
if (logical_chan == PRI_DCHAN_IDX(priv) && !priv->is_cas) {
|
if (logical_chan == PRI_DCHAN_IDX(priv) && !priv->is_cas) {
|
||||||
if (priv->dchan_rx_sample != pcm[0]) {
|
if (priv->dchan_rx_sample != pcm[0]) {
|
||||||
if (debug & DBG_PCM) {
|
if (debug & DBG_PCM) {
|
||||||
XPD_INFO(xpd, "RX-D-Chan: prev=0x%X now=0x%X\n",
|
XPD_INFO(xpd,
|
||||||
|
"RX-D-Chan: prev=0x%X now=0x%X\n",
|
||||||
priv->dchan_rx_sample, pcm[0]);
|
priv->dchan_rx_sample, pcm[0]);
|
||||||
dump_packet("RX-D-Chan", pack, 1);
|
dump_packet("RX-D-Chan", pack, 1);
|
||||||
}
|
}
|
||||||
@ -1891,7 +1916,8 @@ static int PRI_echocancel_setmask(xpd_t *xpd, xpp_line_t ec_mask)
|
|||||||
|
|
||||||
/*---------------- PRI: HOST COMMANDS -------------------------------------*/
|
/*---------------- PRI: HOST COMMANDS -------------------------------------*/
|
||||||
|
|
||||||
static /* 0x33 */ HOSTCMD(PRI, SET_LED, enum pri_led_selectors led_sel, enum pri_led_state to_led_state)
|
static /* 0x33 */ HOSTCMD(PRI, SET_LED, enum pri_led_selectors led_sel,
|
||||||
|
enum pri_led_state to_led_state)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
xframe_t *xframe;
|
xframe_t *xframe;
|
||||||
@ -1963,8 +1989,7 @@ static void layer1_state(xpd_t *xpd, __u8 data_low)
|
|||||||
alarm2str(PHONEDEV(xpd).span.alarms, str1, sizeof(str1));
|
alarm2str(PHONEDEV(xpd).span.alarms, str1, sizeof(str1));
|
||||||
alarm2str(alarms, str2, sizeof(str2));
|
alarm2str(alarms, str2, sizeof(str2));
|
||||||
XPD_NOTICE(xpd, "Alarms: 0x%X (%s) => 0x%X (%s)\n",
|
XPD_NOTICE(xpd, "Alarms: 0x%X (%s) => 0x%X (%s)\n",
|
||||||
PHONEDEV(xpd).span.alarms, str1,
|
PHONEDEV(xpd).span.alarms, str1, alarms, str2);
|
||||||
alarms, str2);
|
|
||||||
if (priv->is_cas) {
|
if (priv->is_cas) {
|
||||||
if (alarms == DAHDI_ALARM_NONE)
|
if (alarms == DAHDI_ALARM_NONE)
|
||||||
send_oldbits(xpd);
|
send_oldbits(xpd);
|
||||||
@ -1978,7 +2003,8 @@ static void layer1_state(xpd_t *xpd, __u8 data_low)
|
|||||||
}
|
}
|
||||||
priv->reg_frs0 = data_low;
|
priv->reg_frs0 = data_low;
|
||||||
priv->layer1_replies++;
|
priv->layer1_replies++;
|
||||||
XPD_DBG(REGS, xpd, "subunit=%d data_low=0x%02X\n", xpd->addr.subunit, data_low);
|
XPD_DBG(REGS, xpd, "subunit=%d data_low=0x%02X\n", xpd->addr.subunit,
|
||||||
|
data_low);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int decode_cas_e1(xpd_t *xpd, __u8 regnum, __u8 data_low)
|
static int decode_cas_e1(xpd_t *xpd, __u8 regnum, __u8 data_low)
|
||||||
@ -1996,24 +2022,22 @@ static int decode_cas_e1(xpd_t *xpd, __u8 regnum, __u8 data_low)
|
|||||||
BUG_ON(priv->pri_protocol != PRI_PROTO_E1);
|
BUG_ON(priv->pri_protocol != PRI_PROTO_E1);
|
||||||
XPD_DBG(SIGNAL, xpd, "RBS: RX: data_low=0x%02X\n", data_low);
|
XPD_DBG(SIGNAL, xpd, "RBS: RX: data_low=0x%02X\n", data_low);
|
||||||
if (pos >= NUM_CAS_RS_E) {
|
if (pos >= NUM_CAS_RS_E) {
|
||||||
XPD_ERR(xpd, "%s: got bad pos=%d [0-%d]\n", __func__, pos, NUM_CAS_RS_E);
|
XPD_ERR(xpd, "%s: got bad pos=%d [0-%d]\n", __func__, pos,
|
||||||
|
NUM_CAS_RS_E);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (chan1 < 0 || chan1 > PHONEDEV(xpd).channels) {
|
if (chan1 < 0 || chan1 > PHONEDEV(xpd).channels) {
|
||||||
XPD_NOTICE(xpd, "%s: %s CAS: Bad chan1 number (%d)\n",
|
XPD_NOTICE(xpd, "%s: %s CAS: Bad chan1 number (%d)\n", __func__,
|
||||||
__func__,
|
pri_protocol_name(priv->pri_protocol), chan1);
|
||||||
pri_protocol_name(priv->pri_protocol),
|
|
||||||
chan1);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (chan2 < 0 || chan2 > PHONEDEV(xpd).channels) {
|
if (chan2 < 0 || chan2 > PHONEDEV(xpd).channels) {
|
||||||
XPD_NOTICE(xpd, "%s: %s CAS: Bad chan2 number (%d)\n",
|
XPD_NOTICE(xpd, "%s: %s CAS: Bad chan2 number (%d)\n", __func__,
|
||||||
__func__,
|
pri_protocol_name(priv->pri_protocol), chan2);
|
||||||
pri_protocol_name(priv->pri_protocol),
|
|
||||||
chan2);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
XPD_DBG(SIGNAL, xpd, "RBS: RX: RS%02d (channel %2d, channel %2d): 0x%02X -> 0x%02X\n",
|
XPD_DBG(SIGNAL, xpd,
|
||||||
|
"RBS: RX: RS%02d (channel %2d, channel %2d): 0x%02X -> 0x%02X\n",
|
||||||
rsnum, chan1 + 1, chan2 + 1, priv->cas_rs_e[pos], data_low);
|
rsnum, chan1 + 1, chan2 + 1, priv->cas_rs_e[pos], data_low);
|
||||||
if (SPAN_REGISTERED(xpd)) {
|
if (SPAN_REGISTERED(xpd)) {
|
||||||
dahdi_rbsbits(XPD_CHAN(xpd, chan1), val1);
|
dahdi_rbsbits(XPD_CHAN(xpd, chan1), val1);
|
||||||
@ -2044,11 +2068,9 @@ static int decode_cas_t1(xpd_t *xpd, __u8 regnum, __u8 data_low)
|
|||||||
rsnum = rsnum % 6; /* 2 identical banks of 6 registers */
|
rsnum = rsnum % 6; /* 2 identical banks of 6 registers */
|
||||||
chan_per_reg = CHAN_PER_REGS(priv);
|
chan_per_reg = CHAN_PER_REGS(priv);
|
||||||
width = 8 / chan_per_reg;
|
width = 8 / chan_per_reg;
|
||||||
XPD_DBG(SIGNAL, xpd,
|
XPD_DBG(SIGNAL, xpd, "RBS: RX(%s,%d): RS%02d data_low=0x%02X\n",
|
||||||
"RBS: RX(%s,%d): RS%02d data_low=0x%02X\n",
|
(priv->is_esf) ? "esf" : "d4", chan_per_reg, rsnum + 1,
|
||||||
(priv->is_esf) ? "esf" : "d4",
|
data_low);
|
||||||
chan_per_reg,
|
|
||||||
rsnum+1, data_low);
|
|
||||||
for (i = 0; i < chan_per_reg; i++) {
|
for (i = 0; i < chan_per_reg; i++) {
|
||||||
uint rxsig = (data_low >> (i * width)) & BITMASK(width);
|
uint rxsig = (data_low >> (i * width)) & BITMASK(width);
|
||||||
int pos;
|
int pos;
|
||||||
@ -2063,11 +2085,13 @@ static int decode_cas_t1(xpd_t *xpd, __u8 regnum, __u8 data_low)
|
|||||||
}
|
}
|
||||||
chan = XPD_CHAN(xpd, pos);
|
chan = XPD_CHAN(xpd, pos);
|
||||||
if (!chan) {
|
if (!chan) {
|
||||||
XPD_ERR(xpd, "%s: Null channel in pos=%d\n", __func__, pos);
|
XPD_ERR(xpd, "%s: Null channel in pos=%d\n", __func__,
|
||||||
|
pos);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (chan->rxsig != rxsig) {
|
if (chan->rxsig != rxsig) {
|
||||||
LINE_DBG(SIGNAL, xpd, pos, "i=%d rxsig=0x%02X\n", i, rxsig);
|
LINE_DBG(SIGNAL, xpd, pos, "i=%d rxsig=0x%02X\n", i,
|
||||||
|
rxsig);
|
||||||
dahdi_rbsbits(chan, rxsig);
|
dahdi_rbsbits(chan, rxsig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2097,7 +2121,8 @@ static void process_cas_dchan(xpd_t *xpd, __u8 regnum, __u8 data_low)
|
|||||||
static int rate_limit;
|
static int rate_limit;
|
||||||
|
|
||||||
if ((rate_limit++ % 10003) == 0)
|
if ((rate_limit++ % 10003) == 0)
|
||||||
XPD_DBG(SIGNAL, xpd, "RBS: RX: Span not registered. Ignore.\n");
|
XPD_DBG(SIGNAL, xpd,
|
||||||
|
"RBS: RX: Span not registered. Ignore.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (priv->pri_protocol == PRI_PROTO_E1) {
|
if (priv->pri_protocol == PRI_PROTO_E1) {
|
||||||
@ -2110,7 +2135,8 @@ static void process_cas_dchan(xpd_t *xpd, __u8 regnum, __u8 data_low)
|
|||||||
|
|
||||||
XPD_NOTICE(xpd,
|
XPD_NOTICE(xpd,
|
||||||
"%s: received register 0x%X in protocol %s. Ignore\n",
|
"%s: received register 0x%X in protocol %s. Ignore\n",
|
||||||
__func__, regnum, pri_protocol_name(priv->pri_protocol));
|
__func__, regnum,
|
||||||
|
pri_protocol_name(priv->pri_protocol));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (decode_cas_e1(xpd, regnum, data_low) < 0)
|
if (decode_cas_e1(xpd, regnum, data_low) < 0)
|
||||||
@ -2119,13 +2145,15 @@ static void process_cas_dchan(xpd_t *xpd, __u8 regnum, __u8 data_low)
|
|||||||
if (regnum > REG_RS12_E) {
|
if (regnum > REG_RS12_E) {
|
||||||
XPD_NOTICE(xpd,
|
XPD_NOTICE(xpd,
|
||||||
"%s: received register 0x%X in protocol %s. Ignore\n",
|
"%s: received register 0x%X in protocol %s. Ignore\n",
|
||||||
__func__, regnum, pri_protocol_name(priv->pri_protocol));
|
__func__, regnum,
|
||||||
|
pri_protocol_name(priv->pri_protocol));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (decode_cas_t1(xpd, regnum, data_low) < 0)
|
if (decode_cas_t1(xpd, regnum, data_low) < 0)
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
XPD_NOTICE(xpd, "%s: protocol %s is not supported yet with CAS\n",
|
XPD_NOTICE(xpd,
|
||||||
|
"%s: protocol %s is not supported yet with CAS\n",
|
||||||
__func__, pri_protocol_name(priv->pri_protocol));
|
__func__, pri_protocol_name(priv->pri_protocol));
|
||||||
}
|
}
|
||||||
priv->cas_replies++;
|
priv->cas_replies++;
|
||||||
@ -2172,10 +2200,11 @@ static int PRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Update /proc info only if reply relate to the last slic read request */
|
/* Update /proc info only if reply relate to the last slic read request */
|
||||||
if (
|
if (REG_FIELD(&xpd->requested_reply, regnum) == REG_FIELD(info, regnum)
|
||||||
REG_FIELD(&xpd->requested_reply, regnum) == REG_FIELD(info, regnum) &&
|
&& REG_FIELD(&xpd->requested_reply, do_subreg) == REG_FIELD(info,
|
||||||
REG_FIELD(&xpd->requested_reply, do_subreg) == REG_FIELD(info, do_subreg) &&
|
do_subreg)
|
||||||
REG_FIELD(&xpd->requested_reply, subreg) == REG_FIELD(info, subreg)) {
|
&& REG_FIELD(&xpd->requested_reply, subreg) == REG_FIELD(info,
|
||||||
|
subreg)) {
|
||||||
xpd->last_reply = *info;
|
xpd->last_reply = *info;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2214,18 +2243,12 @@ static const struct phoneops pri_phoneops = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static xproto_table_t PROTO_TABLE(PRI) = {
|
static xproto_table_t PROTO_TABLE(PRI) = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,.entries = {
|
||||||
.entries = {
|
|
||||||
/* Table Card Opcode */
|
/* Table Card Opcode */
|
||||||
},
|
},.name = "PRI", /* protocol name */
|
||||||
.name = "PRI", /* protocol name */
|
.ports_per_subunit = 1,.type = XPD_TYPE_PRI,.xops =
|
||||||
.ports_per_subunit = 1,
|
&pri_xops,.phoneops = &pri_phoneops,.packet_is_valid =
|
||||||
.type = XPD_TYPE_PRI,
|
pri_packet_is_valid,.packet_dump = pri_packet_dump,};
|
||||||
.xops = &pri_xops,
|
|
||||||
.phoneops = &pri_phoneops,
|
|
||||||
.packet_is_valid = pri_packet_is_valid,
|
|
||||||
.packet_dump = pri_packet_dump,
|
|
||||||
};
|
|
||||||
|
|
||||||
static bool pri_packet_is_valid(xpacket_t *pack)
|
static bool pri_packet_is_valid(xpacket_t *pack)
|
||||||
{
|
{
|
||||||
@ -2239,6 +2262,7 @@ static void pri_packet_dump(const char *msg, xpacket_t *pack)
|
|||||||
{
|
{
|
||||||
DBG(GENERAL, "%s\n", msg);
|
DBG(GENERAL, "%s\n", msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*------------------------- REGISTER Handling --------------------------*/
|
/*------------------------- REGISTER Handling --------------------------*/
|
||||||
|
|
||||||
/*------------------------- sysfs stuff --------------------------------*/
|
/*------------------------- sysfs stuff --------------------------------*/
|
||||||
@ -2313,8 +2337,7 @@ static DEVICE_ATTR_READER(pri_localloop_show, dev, buf)
|
|||||||
priv = xpd->priv;
|
priv = xpd->priv;
|
||||||
BUG_ON(!priv);
|
BUG_ON(!priv);
|
||||||
spin_lock_irqsave(&xpd->lock, flags);
|
spin_lock_irqsave(&xpd->lock, flags);
|
||||||
len += sprintf(buf, "%c\n",
|
len += sprintf(buf, "%c\n", (priv->local_loopback) ? 'Y' : 'N');
|
||||||
(priv->local_loopback) ? 'Y' : 'N');
|
|
||||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
@ -2351,7 +2374,8 @@ static DEVICE_ATTR_WRITER(pri_localloop_store, dev, buf, count)
|
|||||||
return (ret < 0) ? ret : count;
|
return (ret < 0) ? ret : count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEVICE_ATTR(pri_localloop, S_IRUGO | S_IWUSR, pri_localloop_show, pri_localloop_store);
|
static DEVICE_ATTR(pri_localloop, S_IRUGO | S_IWUSR, pri_localloop_show,
|
||||||
|
pri_localloop_store);
|
||||||
|
|
||||||
static DEVICE_ATTR_READER(pri_layer1_show, dev, buf)
|
static DEVICE_ATTR_READER(pri_layer1_show, dev, buf)
|
||||||
{
|
{
|
||||||
@ -2370,7 +2394,9 @@ static DEVICE_ATTR_READER(pri_layer1_show, dev, buf)
|
|||||||
if (priv->poll_noreplies > 1)
|
if (priv->poll_noreplies > 1)
|
||||||
len += sprintf(buf + len, "Unknown[%d]", priv->poll_noreplies);
|
len += sprintf(buf + len, "Unknown[%d]", priv->poll_noreplies);
|
||||||
else
|
else
|
||||||
len += sprintf(buf + len, "%-10s", ((priv->layer1_up) ? "UP" : "DOWN"));
|
len +=
|
||||||
|
sprintf(buf + len, "%-10s",
|
||||||
|
((priv->layer1_up) ? "UP" : "DOWN"));
|
||||||
len += sprintf(buf + len, "%d\n", priv->layer1_replies);
|
len += sprintf(buf + len, "%d\n", priv->layer1_replies);
|
||||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||||
return len;
|
return len;
|
||||||
@ -2388,10 +2414,10 @@ static DEVICE_ATTR_READER(pri_alarms_show, dev, buf)
|
|||||||
__u8 bits;
|
__u8 bits;
|
||||||
const char *name;
|
const char *name;
|
||||||
} alarm_types[] = {
|
} alarm_types[] = {
|
||||||
{ REG_FRS0_LOS, "RED" },
|
{
|
||||||
{ REG_FRS0_AIS, "BLUE" },
|
REG_FRS0_LOS, "RED"}, {
|
||||||
{ REG_FRS0_RRA, "YELLOW" },
|
REG_FRS0_AIS, "BLUE"}, {
|
||||||
};
|
REG_FRS0_RRA, "YELLOW"},};
|
||||||
|
|
||||||
BUG_ON(!dev);
|
BUG_ON(!dev);
|
||||||
xpd = dev_to_xpd(dev);
|
xpd = dev_to_xpd(dev);
|
||||||
@ -2407,7 +2433,9 @@ static DEVICE_ATTR_READER(pri_alarms_show, dev, buf)
|
|||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(alarm_types); i++) {
|
for (i = 0; i < ARRAY_SIZE(alarm_types); i++) {
|
||||||
if (priv->reg_frs0 & alarm_types[i].bits)
|
if (priv->reg_frs0 & alarm_types[i].bits)
|
||||||
len += sprintf(buf + len, "%s ", alarm_types[i].name);
|
len +=
|
||||||
|
sprintf(buf + len, "%s ",
|
||||||
|
alarm_types[i].name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
len += sprintf(buf + len, "\n");
|
len += sprintf(buf + len, "\n");
|
||||||
@ -2434,8 +2462,8 @@ static DEVICE_ATTR_READER(pri_cas_show, dev, buf)
|
|||||||
if (priv->is_cas) {
|
if (priv->is_cas) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
len += sprintf(buf + len,
|
len +=
|
||||||
"CAS: replies=%d\n", priv->cas_replies);
|
sprintf(buf + len, "CAS: replies=%d\n", priv->cas_replies);
|
||||||
len += sprintf(buf + len, " CAS-TS: ");
|
len += sprintf(buf + len, " CAS-TS: ");
|
||||||
for (i = 0; i < NUM_CAS_RS_E; i++) {
|
for (i = 0; i < NUM_CAS_RS_E; i++) {
|
||||||
len += sprintf(buf + len, " %02X", priv->cas_ts_e[i]);
|
len += sprintf(buf + len, " %02X", priv->cas_ts_e[i]);
|
||||||
@ -2467,11 +2495,14 @@ static DEVICE_ATTR_READER(pri_dchan_show, dev, buf)
|
|||||||
priv = xpd->priv;
|
priv = xpd->priv;
|
||||||
BUG_ON(!priv);
|
BUG_ON(!priv);
|
||||||
spin_lock_irqsave(&xpd->lock, flags);
|
spin_lock_irqsave(&xpd->lock, flags);
|
||||||
len += sprintf(buf + len, "D-Channel: TX=[%5d] (0x%02X) RX=[%5d] (0x%02X) ",
|
len +=
|
||||||
|
sprintf(buf + len,
|
||||||
|
"D-Channel: TX=[%5d] (0x%02X) RX=[%5d] (0x%02X) ",
|
||||||
priv->dchan_tx_counter, priv->dchan_tx_sample,
|
priv->dchan_tx_counter, priv->dchan_tx_sample,
|
||||||
priv->dchan_rx_counter, priv->dchan_rx_sample);
|
priv->dchan_rx_counter, priv->dchan_rx_sample);
|
||||||
if (priv->dchan_alive) {
|
if (priv->dchan_alive) {
|
||||||
len += sprintf(buf + len, "(alive %d K-ticks)\n",
|
len +=
|
||||||
|
sprintf(buf + len, "(alive %d K-ticks)\n",
|
||||||
priv->dchan_alive_ticks / 1000);
|
priv->dchan_alive_ticks / 1000);
|
||||||
} else {
|
} else {
|
||||||
len += sprintf(buf + len, "(dead)\n");
|
len += sprintf(buf + len, "(dead)\n");
|
||||||
@ -2496,7 +2527,9 @@ static DEVICE_ATTR_READER(pri_clocking_show, dev, buf)
|
|||||||
priv = xpd->priv;
|
priv = xpd->priv;
|
||||||
BUG_ON(!priv);
|
BUG_ON(!priv);
|
||||||
spin_lock_irqsave(&xpd->lock, flags);
|
spin_lock_irqsave(&xpd->lock, flags);
|
||||||
len += sprintf(buf + len, "%s\n", (priv->clock_source) ? "MASTER" : "SLAVE");
|
len +=
|
||||||
|
sprintf(buf + len, "%s\n",
|
||||||
|
(priv->clock_source) ? "MASTER" : "SLAVE");
|
||||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
@ -2511,44 +2544,54 @@ static int pri_xpd_probe(struct device *dev)
|
|||||||
xpd = dev_to_xpd(dev);
|
xpd = dev_to_xpd(dev);
|
||||||
/* Is it our device? */
|
/* Is it our device? */
|
||||||
if (xpd->type != XPD_TYPE_PRI) {
|
if (xpd->type != XPD_TYPE_PRI) {
|
||||||
XPD_ERR(xpd, "drop suggestion for %s (%d)\n",
|
XPD_ERR(xpd, "drop suggestion for %s (%d)\n", dev_name(dev),
|
||||||
dev_name(dev), xpd->type);
|
xpd->type);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
XPD_DBG(DEVICES, xpd, "SYSFS\n");
|
XPD_DBG(DEVICES, xpd, "SYSFS\n");
|
||||||
ret = device_create_file(dev, &dev_attr_pri_protocol);
|
ret = device_create_file(dev, &dev_attr_pri_protocol);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
XPD_ERR(xpd, "%s: device_create_file(pri_protocol) failed: %d\n", __func__, ret);
|
XPD_ERR(xpd,
|
||||||
|
"%s: device_create_file(pri_protocol) failed: %d\n",
|
||||||
|
__func__, ret);
|
||||||
goto fail_pri_protocol;
|
goto fail_pri_protocol;
|
||||||
}
|
}
|
||||||
ret = device_create_file(dev, &dev_attr_pri_localloop);
|
ret = device_create_file(dev, &dev_attr_pri_localloop);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
XPD_ERR(xpd, "%s: device_create_file(pri_localloop) failed: %d\n", __func__, ret);
|
XPD_ERR(xpd,
|
||||||
|
"%s: device_create_file(pri_localloop) failed: %d\n",
|
||||||
|
__func__, ret);
|
||||||
goto fail_pri_localloop;
|
goto fail_pri_localloop;
|
||||||
}
|
}
|
||||||
ret = device_create_file(dev, &dev_attr_pri_layer1);
|
ret = device_create_file(dev, &dev_attr_pri_layer1);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
XPD_ERR(xpd, "%s: device_create_file(pri_layer1) failed: %d\n", __func__, ret);
|
XPD_ERR(xpd, "%s: device_create_file(pri_layer1) failed: %d\n",
|
||||||
|
__func__, ret);
|
||||||
goto fail_pri_layer1;
|
goto fail_pri_layer1;
|
||||||
}
|
}
|
||||||
ret = device_create_file(dev, &dev_attr_pri_alarms);
|
ret = device_create_file(dev, &dev_attr_pri_alarms);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
XPD_ERR(xpd, "%s: device_create_file(pri_alarms) failed: %d\n", __func__, ret);
|
XPD_ERR(xpd, "%s: device_create_file(pri_alarms) failed: %d\n",
|
||||||
|
__func__, ret);
|
||||||
goto fail_pri_alarms;
|
goto fail_pri_alarms;
|
||||||
}
|
}
|
||||||
ret = device_create_file(dev, &dev_attr_pri_cas);
|
ret = device_create_file(dev, &dev_attr_pri_cas);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
XPD_ERR(xpd, "%s: device_create_file(pri_cas) failed: %d\n", __func__, ret);
|
XPD_ERR(xpd, "%s: device_create_file(pri_cas) failed: %d\n",
|
||||||
|
__func__, ret);
|
||||||
goto fail_pri_cas;
|
goto fail_pri_cas;
|
||||||
}
|
}
|
||||||
ret = device_create_file(dev, &dev_attr_pri_dchan);
|
ret = device_create_file(dev, &dev_attr_pri_dchan);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
XPD_ERR(xpd, "%s: device_create_file(pri_dchan) failed: %d\n", __func__, ret);
|
XPD_ERR(xpd, "%s: device_create_file(pri_dchan) failed: %d\n",
|
||||||
|
__func__, ret);
|
||||||
goto fail_pri_dchan;
|
goto fail_pri_dchan;
|
||||||
}
|
}
|
||||||
ret = device_create_file(dev, &dev_attr_pri_clocking);
|
ret = device_create_file(dev, &dev_attr_pri_clocking);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
XPD_ERR(xpd, "%s: device_create_file(pri_clocking) failed: %d\n", __func__, ret);
|
XPD_ERR(xpd,
|
||||||
|
"%s: device_create_file(pri_clocking) failed: %d\n",
|
||||||
|
__func__, ret);
|
||||||
goto fail_pri_clocking;
|
goto fail_pri_clocking;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -2592,8 +2635,7 @@ static struct xpd_driver pri_driver = {
|
|||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
#endif
|
#endif
|
||||||
.probe = pri_xpd_probe,
|
.probe = pri_xpd_probe,
|
||||||
.remove = pri_xpd_remove
|
.remove = pri_xpd_remove}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init card_pri_startup(void)
|
static int __init card_pri_startup(void)
|
||||||
|
@ -28,5 +28,4 @@ enum pri_opcodes {
|
|||||||
XPROTO_NAME(PRI, SET_LED) = 0x33,
|
XPROTO_NAME(PRI, SET_LED) = 0x33,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* CARD_PRI_H */
|
#endif /* CARD_PRI_H */
|
||||||
|
@ -39,19 +39,11 @@ static struct {
|
|||||||
int value;
|
int value;
|
||||||
char *name;
|
char *name;
|
||||||
} poll_names[] = {
|
} poll_names[] = {
|
||||||
P_(POLLIN),
|
P_(POLLIN), P_(POLLPRI), P_(POLLOUT), P_(POLLERR), P_(POLLHUP),
|
||||||
P_(POLLPRI),
|
P_(POLLNVAL), P_(POLLRDNORM), P_(POLLRDBAND), P_(POLLWRNORM),
|
||||||
P_(POLLOUT),
|
P_(POLLWRBAND), P_(POLLMSG), P_(POLLREMOVE)
|
||||||
P_(POLLERR),
|
|
||||||
P_(POLLHUP),
|
|
||||||
P_(POLLNVAL),
|
|
||||||
P_(POLLRDNORM),
|
|
||||||
P_(POLLRDBAND),
|
|
||||||
P_(POLLWRNORM),
|
|
||||||
P_(POLLWRBAND),
|
|
||||||
P_(POLLMSG),
|
|
||||||
P_(POLLREMOVE)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef P_
|
#undef P_
|
||||||
|
|
||||||
void dump_poll(int debug, const char *msg, int poll)
|
void dump_poll(int debug, const char *msg, int poll)
|
||||||
|
@ -95,11 +95,16 @@ void dump_poll(int debug, const char *msg, int poll);
|
|||||||
static inline char *rxsig2str(enum dahdi_rxsig sig)
|
static inline char *rxsig2str(enum dahdi_rxsig sig)
|
||||||
{
|
{
|
||||||
switch (sig) {
|
switch (sig) {
|
||||||
case DAHDI_RXSIG_ONHOOK: return "ONHOOK";
|
case DAHDI_RXSIG_ONHOOK:
|
||||||
case DAHDI_RXSIG_OFFHOOK: return "OFFHOOK";
|
return "ONHOOK";
|
||||||
case DAHDI_RXSIG_START: return "START";
|
case DAHDI_RXSIG_OFFHOOK:
|
||||||
case DAHDI_RXSIG_RING: return "RING";
|
return "OFFHOOK";
|
||||||
case DAHDI_RXSIG_INITIAL: return "INITIAL";
|
case DAHDI_RXSIG_START:
|
||||||
|
return "START";
|
||||||
|
case DAHDI_RXSIG_RING:
|
||||||
|
return "RING";
|
||||||
|
case DAHDI_RXSIG_INITIAL:
|
||||||
|
return "INITIAL";
|
||||||
}
|
}
|
||||||
return "Unknown rxsig";
|
return "Unknown rxsig";
|
||||||
}
|
}
|
||||||
@ -107,11 +112,16 @@ static inline char *rxsig2str(enum dahdi_rxsig sig)
|
|||||||
static inline char *txsig2str(enum dahdi_txsig sig)
|
static inline char *txsig2str(enum dahdi_txsig sig)
|
||||||
{
|
{
|
||||||
switch (sig) {
|
switch (sig) {
|
||||||
case DAHDI_TXSIG_ONHOOK: return "TXSIG_ONHOOK";
|
case DAHDI_TXSIG_ONHOOK:
|
||||||
case DAHDI_TXSIG_OFFHOOK: return "TXSIG_OFFHOOK";
|
return "TXSIG_ONHOOK";
|
||||||
case DAHDI_TXSIG_START: return "TXSIG_START";
|
case DAHDI_TXSIG_OFFHOOK:
|
||||||
case DAHDI_TXSIG_KEWL: return "TXSIG_KEWL"; /* Drop battery if possible */
|
return "TXSIG_OFFHOOK";
|
||||||
case DAHDI_TXSIG_TOTAL: break;
|
case DAHDI_TXSIG_START:
|
||||||
|
return "TXSIG_START";
|
||||||
|
case DAHDI_TXSIG_KEWL:
|
||||||
|
return "TXSIG_KEWL"; /* Drop battery if possible */
|
||||||
|
case DAHDI_TXSIG_TOTAL:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return "Unknown txsig";
|
return "Unknown txsig";
|
||||||
}
|
}
|
||||||
@ -119,24 +129,42 @@ static inline char *txsig2str(enum dahdi_txsig sig)
|
|||||||
static inline char *event2str(int event)
|
static inline char *event2str(int event)
|
||||||
{
|
{
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case DAHDI_EVENT_NONE: return "NONE";
|
case DAHDI_EVENT_NONE:
|
||||||
case DAHDI_EVENT_ONHOOK: return "ONHOOK";
|
return "NONE";
|
||||||
case DAHDI_EVENT_RINGOFFHOOK: return "RINGOFFHOOK";
|
case DAHDI_EVENT_ONHOOK:
|
||||||
case DAHDI_EVENT_WINKFLASH: return "WINKFLASH";
|
return "ONHOOK";
|
||||||
case DAHDI_EVENT_ALARM: return "ALARM";
|
case DAHDI_EVENT_RINGOFFHOOK:
|
||||||
case DAHDI_EVENT_NOALARM: return "NOALARM";
|
return "RINGOFFHOOK";
|
||||||
case DAHDI_EVENT_ABORT: return "ABORT";
|
case DAHDI_EVENT_WINKFLASH:
|
||||||
case DAHDI_EVENT_OVERRUN: return "OVERRUN";
|
return "WINKFLASH";
|
||||||
case DAHDI_EVENT_BADFCS: return "BADFCS";
|
case DAHDI_EVENT_ALARM:
|
||||||
case DAHDI_EVENT_DIALCOMPLETE: return "DIALCOMPLETE";
|
return "ALARM";
|
||||||
case DAHDI_EVENT_RINGERON: return "RINGERON";
|
case DAHDI_EVENT_NOALARM:
|
||||||
case DAHDI_EVENT_RINGEROFF: return "RINGEROFF";
|
return "NOALARM";
|
||||||
case DAHDI_EVENT_HOOKCOMPLETE: return "HOOKCOMPLETE";
|
case DAHDI_EVENT_ABORT:
|
||||||
case DAHDI_EVENT_BITSCHANGED: return "BITSCHANGED";
|
return "ABORT";
|
||||||
case DAHDI_EVENT_PULSE_START: return "PULSE_START";
|
case DAHDI_EVENT_OVERRUN:
|
||||||
case DAHDI_EVENT_TIMER_EXPIRED: return "TIMER_EXPIRED";
|
return "OVERRUN";
|
||||||
case DAHDI_EVENT_TIMER_PING: return "TIMER_PING";
|
case DAHDI_EVENT_BADFCS:
|
||||||
case DAHDI_EVENT_POLARITY: return "POLARITY";
|
return "BADFCS";
|
||||||
|
case DAHDI_EVENT_DIALCOMPLETE:
|
||||||
|
return "DIALCOMPLETE";
|
||||||
|
case DAHDI_EVENT_RINGERON:
|
||||||
|
return "RINGERON";
|
||||||
|
case DAHDI_EVENT_RINGEROFF:
|
||||||
|
return "RINGEROFF";
|
||||||
|
case DAHDI_EVENT_HOOKCOMPLETE:
|
||||||
|
return "HOOKCOMPLETE";
|
||||||
|
case DAHDI_EVENT_BITSCHANGED:
|
||||||
|
return "BITSCHANGED";
|
||||||
|
case DAHDI_EVENT_PULSE_START:
|
||||||
|
return "PULSE_START";
|
||||||
|
case DAHDI_EVENT_TIMER_EXPIRED:
|
||||||
|
return "TIMER_EXPIRED";
|
||||||
|
case DAHDI_EVENT_TIMER_PING:
|
||||||
|
return "TIMER_PING";
|
||||||
|
case DAHDI_EVENT_POLARITY:
|
||||||
|
return "POLARITY";
|
||||||
}
|
}
|
||||||
return "Unknown event";
|
return "Unknown event";
|
||||||
}
|
}
|
||||||
@ -144,13 +172,20 @@ static inline char *event2str(int event)
|
|||||||
static inline char *hookstate2str(int hookstate)
|
static inline char *hookstate2str(int hookstate)
|
||||||
{
|
{
|
||||||
switch (hookstate) {
|
switch (hookstate) {
|
||||||
case DAHDI_ONHOOK: return "DAHDI_ONHOOK";
|
case DAHDI_ONHOOK:
|
||||||
case DAHDI_START: return "DAHDI_START";
|
return "DAHDI_ONHOOK";
|
||||||
case DAHDI_OFFHOOK: return "DAHDI_OFFHOOK";
|
case DAHDI_START:
|
||||||
case DAHDI_WINK: return "DAHDI_WINK";
|
return "DAHDI_START";
|
||||||
case DAHDI_FLASH: return "DAHDI_FLASH";
|
case DAHDI_OFFHOOK:
|
||||||
case DAHDI_RING: return "DAHDI_RING";
|
return "DAHDI_OFFHOOK";
|
||||||
case DAHDI_RINGOFF: return "DAHDI_RINGOFF";
|
case DAHDI_WINK:
|
||||||
|
return "DAHDI_WINK";
|
||||||
|
case DAHDI_FLASH:
|
||||||
|
return "DAHDI_FLASH";
|
||||||
|
case DAHDI_RING:
|
||||||
|
return "DAHDI_RING";
|
||||||
|
case DAHDI_RINGOFF:
|
||||||
|
return "DAHDI_RINGOFF";
|
||||||
}
|
}
|
||||||
return "Unknown hookstate";
|
return "Unknown hookstate";
|
||||||
}
|
}
|
||||||
@ -159,23 +194,40 @@ static inline char *hookstate2str(int hookstate)
|
|||||||
static inline char *sig2str(int sig)
|
static inline char *sig2str(int sig)
|
||||||
{
|
{
|
||||||
switch (sig) {
|
switch (sig) {
|
||||||
case DAHDI_SIG_FXSLS: return "FXSLS";
|
case DAHDI_SIG_FXSLS:
|
||||||
case DAHDI_SIG_FXSKS: return "FXSKS";
|
return "FXSLS";
|
||||||
case DAHDI_SIG_FXSGS: return "FXSGS";
|
case DAHDI_SIG_FXSKS:
|
||||||
case DAHDI_SIG_FXOLS: return "FXOLS";
|
return "FXSKS";
|
||||||
case DAHDI_SIG_FXOKS: return "FXOKS";
|
case DAHDI_SIG_FXSGS:
|
||||||
case DAHDI_SIG_FXOGS: return "FXOGS";
|
return "FXSGS";
|
||||||
case DAHDI_SIG_EM: return "E&M";
|
case DAHDI_SIG_FXOLS:
|
||||||
case DAHDI_SIG_EM_E1: return "E&M-E1";
|
return "FXOLS";
|
||||||
case DAHDI_SIG_CLEAR: return "Clear";
|
case DAHDI_SIG_FXOKS:
|
||||||
case DAHDI_SIG_HDLCRAW: return "HDLCRAW";
|
return "FXOKS";
|
||||||
case DAHDI_SIG_HDLCFCS: return "HDLCFCS";
|
case DAHDI_SIG_FXOGS:
|
||||||
case DAHDI_SIG_HDLCNET: return "HDLCNET";
|
return "FXOGS";
|
||||||
case DAHDI_SIG_SLAVE: return "Slave";
|
case DAHDI_SIG_EM:
|
||||||
case DAHDI_SIG_CAS: return "CAS";
|
return "E&M";
|
||||||
case DAHDI_SIG_DACS: return "DACS";
|
case DAHDI_SIG_EM_E1:
|
||||||
case DAHDI_SIG_DACS_RBS: return "DACS+RBS";
|
return "E&M-E1";
|
||||||
case DAHDI_SIG_SF: return "SF (ToneOnly)";
|
case DAHDI_SIG_CLEAR:
|
||||||
|
return "Clear";
|
||||||
|
case DAHDI_SIG_HDLCRAW:
|
||||||
|
return "HDLCRAW";
|
||||||
|
case DAHDI_SIG_HDLCFCS:
|
||||||
|
return "HDLCFCS";
|
||||||
|
case DAHDI_SIG_HDLCNET:
|
||||||
|
return "HDLCNET";
|
||||||
|
case DAHDI_SIG_SLAVE:
|
||||||
|
return "Slave";
|
||||||
|
case DAHDI_SIG_CAS:
|
||||||
|
return "CAS";
|
||||||
|
case DAHDI_SIG_DACS:
|
||||||
|
return "DACS";
|
||||||
|
case DAHDI_SIG_DACS_RBS:
|
||||||
|
return "DACS+RBS";
|
||||||
|
case DAHDI_SIG_SF:
|
||||||
|
return "SF (ToneOnly)";
|
||||||
case DAHDI_SIG_NONE:
|
case DAHDI_SIG_NONE:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -186,13 +238,20 @@ static inline char *alarmbit2str(int alarmbit)
|
|||||||
{
|
{
|
||||||
/* from dahdi/kernel.h */
|
/* from dahdi/kernel.h */
|
||||||
switch (1 << alarmbit) {
|
switch (1 << alarmbit) {
|
||||||
case DAHDI_ALARM_NONE: return "NONE";
|
case DAHDI_ALARM_NONE:
|
||||||
case DAHDI_ALARM_RECOVER: return "RECOVER";
|
return "NONE";
|
||||||
case DAHDI_ALARM_LOOPBACK: return "LOOPBACK";
|
case DAHDI_ALARM_RECOVER:
|
||||||
case DAHDI_ALARM_YELLOW: return "YELLOW";
|
return "RECOVER";
|
||||||
case DAHDI_ALARM_RED: return "RED";
|
case DAHDI_ALARM_LOOPBACK:
|
||||||
case DAHDI_ALARM_BLUE: return "BLUE";
|
return "LOOPBACK";
|
||||||
case DAHDI_ALARM_NOTOPEN: return "NOTOPEN";
|
case DAHDI_ALARM_YELLOW:
|
||||||
|
return "YELLOW";
|
||||||
|
case DAHDI_ALARM_RED:
|
||||||
|
return "RED";
|
||||||
|
case DAHDI_ALARM_BLUE:
|
||||||
|
return "BLUE";
|
||||||
|
case DAHDI_ALARM_NOTOPEN:
|
||||||
|
return "NOTOPEN";
|
||||||
}
|
}
|
||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,9 @@ static int mmap_match(struct device *dev, struct device_driver *driver)
|
|||||||
{
|
{
|
||||||
return !strncmp(dev_name(dev), driver->name, strlen(driver->name));
|
return !strncmp(dev_name(dev), driver->name, strlen(driver->name));
|
||||||
}
|
}
|
||||||
static int mmap_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
|
|
||||||
|
static int mmap_uevent(struct device *dev, char **envp, int num_envp,
|
||||||
|
char *buffer, int buffer_size)
|
||||||
{
|
{
|
||||||
envp[0] = buffer;
|
envp[0] = buffer;
|
||||||
envp[1] = NULL;
|
envp[1] = NULL;
|
||||||
@ -33,8 +35,6 @@ static struct device mmap_bus = {
|
|||||||
.release = mmap_bus_release,
|
.release = mmap_bus_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int register_mmap_device(struct mmap_device *dev)
|
int register_mmap_device(struct mmap_device *dev)
|
||||||
{
|
{
|
||||||
dev->dev.bus = &mmap_bus_type;
|
dev->dev.bus = &mmap_bus_type;
|
||||||
@ -48,6 +48,7 @@ void unregister_mmap_device(struct mmap_device *dev)
|
|||||||
{
|
{
|
||||||
device_unregister(&dev->dev);
|
device_unregister(&dev->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(register_mmap_device);
|
EXPORT_SYMBOL(register_mmap_device);
|
||||||
EXPORT_SYMBOL(unregister_mmap_device);
|
EXPORT_SYMBOL(unregister_mmap_device);
|
||||||
|
|
||||||
@ -61,6 +62,7 @@ void unregister_mmap_driver(struct mmap_driver *driver)
|
|||||||
{
|
{
|
||||||
driver_unregister(&driver->driver);
|
driver_unregister(&driver->driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(register_mmap_driver);
|
EXPORT_SYMBOL(register_mmap_driver);
|
||||||
EXPORT_SYMBOL(unregister_mmap_driver);
|
EXPORT_SYMBOL(unregister_mmap_driver);
|
||||||
|
|
||||||
@ -84,6 +86,7 @@ void unregister_mmap_bus(void)
|
|||||||
device_unregister(&mmap_bus);
|
device_unregister(&mmap_bus);
|
||||||
bus_unregister(&mmap_bus_type);
|
bus_unregister(&mmap_bus_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(register_mmap_bus);
|
EXPORT_SYMBOL(register_mmap_bus);
|
||||||
EXPORT_SYMBOL(unregister_mmap_bus);
|
EXPORT_SYMBOL(unregister_mmap_bus);
|
||||||
|
|
||||||
|
@ -19,7 +19,9 @@
|
|||||||
#include "xframe_queue.h"
|
#include "xframe_queue.h"
|
||||||
|
|
||||||
/* Check at compile time that sizeof(xframe_t) is a multiple of 4 */
|
/* Check at compile time that sizeof(xframe_t) is a multiple of 4 */
|
||||||
typedef char sizeof_xframe_t_should_be_divisible_by_4[((sizeof(xframe_t) % 4) == 0) * 2 - 1];
|
typedef char
|
||||||
|
sizeof_xframe_t_should_be_divisible_by_4[((sizeof(xframe_t) % 4) ==
|
||||||
|
0) * 2 - 1];
|
||||||
|
|
||||||
#define ssync() __builtin_bfin_ssync()
|
#define ssync() __builtin_bfin_ssync()
|
||||||
|
|
||||||
@ -96,7 +98,8 @@ static void update_counter(struct counter *c, struct timeval *tv1)
|
|||||||
c->intr_min = diff;
|
c->intr_min = diff;
|
||||||
if (c->intr_max < diff)
|
if (c->intr_max < diff)
|
||||||
c->intr_max = diff;
|
c->intr_max = diff;
|
||||||
c->intr_avg = (c->intr_avg*c->intr_count + diff) / (c->intr_count+1);
|
c->intr_avg =
|
||||||
|
(c->intr_avg * c->intr_count + diff) / (c->intr_count + 1);
|
||||||
c->intr_count++;
|
c->intr_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,7 +167,8 @@ static irqreturn_t xpp_mmap_rx_irq(int irq, void *dev_id)
|
|||||||
/* Sanity check: length of first packet in frame should be no more than the frame length */
|
/* Sanity check: length of first packet in frame should be no more than the frame length */
|
||||||
if (((buf[0] | (buf[1] << 8)) & 0x3FF) > rxcnt) {
|
if (((buf[0] | (buf[1] << 8)) & 0x3FF) > rxcnt) {
|
||||||
if (printk_ratelimit()) {
|
if (printk_ratelimit()) {
|
||||||
ERR("Packet len=%d, frame len=%d\n", (buf[0] | (buf[1]<<8)) & 0x3FF, rxcnt);
|
ERR("Packet len=%d, frame len=%d\n",
|
||||||
|
(buf[0] | (buf[1] << 8)) & 0x3FF, rxcnt);
|
||||||
print_buffer("16 bytes of packet: ", buf, 16);
|
print_buffer("16 bytes of packet: ", buf, 16);
|
||||||
}
|
}
|
||||||
goto free;
|
goto free;
|
||||||
@ -258,7 +262,9 @@ static int xframe_send_common(xbus_t *xbus, xframe_t *xframe, bool pcm)
|
|||||||
if (pcm && pcm_in_pool_count >= 1) {
|
if (pcm && pcm_in_pool_count >= 1) {
|
||||||
static int rate_limit;
|
static int rate_limit;
|
||||||
if ((rate_limit++ % 1000) == 0)
|
if ((rate_limit++ % 1000) == 0)
|
||||||
XBUS_ERR(xbus, "Dropped PCM xframe (pcm_in_pool_count=%d).\n", pcm_in_pool_count);
|
XBUS_ERR(xbus,
|
||||||
|
"Dropped PCM xframe (pcm_in_pool_count=%d).\n",
|
||||||
|
pcm_in_pool_count);
|
||||||
FREE_SEND_XFRAME(xbus, xframe);
|
FREE_SEND_XFRAME(xbus, xframe);
|
||||||
pcm_dropped++;
|
pcm_dropped++;
|
||||||
} else {
|
} else {
|
||||||
@ -266,7 +272,8 @@ static int xframe_send_common(xbus_t *xbus, xframe_t *xframe, bool pcm)
|
|||||||
static int rate_limit;
|
static int rate_limit;
|
||||||
spin_unlock_irqrestore(&tx_ready_lock, flags);
|
spin_unlock_irqrestore(&tx_ready_lock, flags);
|
||||||
if ((rate_limit++ % 1000) == 0)
|
if ((rate_limit++ % 1000) == 0)
|
||||||
XBUS_ERR(xbus, "Dropped xframe. Cannot enqueue.\n");
|
XBUS_ERR(xbus,
|
||||||
|
"Dropped xframe. Cannot enqueue.\n");
|
||||||
FREE_SEND_XFRAME(xbus, xframe);
|
FREE_SEND_XFRAME(xbus, xframe);
|
||||||
return -E2BIG;
|
return -E2BIG;
|
||||||
}
|
}
|
||||||
@ -284,10 +291,12 @@ static xframe_t *alloc_xframe(xbus_t *xbus, gfp_t gfp_flags)
|
|||||||
if (!xframe) {
|
if (!xframe) {
|
||||||
static int rate_limit;
|
static int rate_limit;
|
||||||
if ((rate_limit++ % 1000) < 5)
|
if ((rate_limit++ % 1000) < 5)
|
||||||
XBUS_ERR(xbus, "frame allocation failed (%d)\n", rate_limit);
|
XBUS_ERR(xbus, "frame allocation failed (%d)\n",
|
||||||
|
rate_limit);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
xframe_init(xbus, xframe, ((__u8*)xframe) + sizeof(xframe_t), XFRAME_DATASIZE, xbus);
|
xframe_init(xbus, xframe, ((__u8 *)xframe) + sizeof(xframe_t),
|
||||||
|
XFRAME_DATASIZE, xbus);
|
||||||
return xframe;
|
return xframe;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,15 +327,11 @@ static int fill_proc_queue(char *p, struct xframe_queue *q)
|
|||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
len = sprintf(p,
|
len =
|
||||||
|
sprintf(p,
|
||||||
"%-15s: counts %3d, %3d, %3d worst %3d, overflows %3d worst_lag %02ld.%ld ms\n",
|
"%-15s: counts %3d, %3d, %3d worst %3d, overflows %3d worst_lag %02ld.%ld ms\n",
|
||||||
q->name,
|
q->name, q->steady_state_count, q->count, q->max_count,
|
||||||
q->steady_state_count,
|
q->worst_count, q->overflows, q->worst_lag_usec / 1000,
|
||||||
q->count,
|
|
||||||
q->max_count,
|
|
||||||
q->worst_count,
|
|
||||||
q->overflows,
|
|
||||||
q->worst_lag_usec / 1000,
|
|
||||||
q->worst_lag_usec % 1000);
|
q->worst_lag_usec % 1000);
|
||||||
xframe_queue_clearstats(q);
|
xframe_queue_clearstats(q);
|
||||||
return len;
|
return len;
|
||||||
@ -334,10 +339,12 @@ static int fill_proc_queue(char *p, struct xframe_queue *q)
|
|||||||
|
|
||||||
static int fill_proc_counter(char *p, struct counter *c)
|
static int fill_proc_counter(char *p, struct counter *c)
|
||||||
{
|
{
|
||||||
return sprintf(p, "min=%ld\nmax=%ld\navg=%ld\ncount=%ld\n", c->intr_min, c->intr_max, c->intr_avg, c->intr_count);
|
return sprintf(p, "min=%ld\nmax=%ld\navg=%ld\ncount=%ld\n", c->intr_min,
|
||||||
|
c->intr_max, c->intr_avg, c->intr_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int xpp_mmap_proc_read(char *page, char **start, off_t off, int count, int *eof, void *data)
|
static int xpp_mmap_proc_read(char *page, char **start, off_t off, int count,
|
||||||
|
int *eof, void *data)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
len += fill_proc_queue(page + len, &txpool);
|
len += fill_proc_queue(page + len, &txpool);
|
||||||
@ -363,7 +370,8 @@ static int xpp_mmap_proc_read(char *page, char **start, off_t off, int count, in
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int xpp_mmap_proc_write(struct file *file, const char __user *buffer, unsigned long count, void *data)
|
static int xpp_mmap_proc_write(struct file *file, const char __user *buffer,
|
||||||
|
unsigned long count, void *data)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
char *txchunk, *p, *endp;
|
char *txchunk, *p, *endp;
|
||||||
@ -379,8 +387,10 @@ static int xpp_mmap_proc_write(struct file *file, const char __user *buffer, uns
|
|||||||
|
|
||||||
while (*p) {
|
while (*p) {
|
||||||
unsigned long value;
|
unsigned long value;
|
||||||
while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++;
|
while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r')
|
||||||
if (*p == '\0') break;
|
p++;
|
||||||
|
if (*p == '\0')
|
||||||
|
break;
|
||||||
value = simple_strtoul(p, &endp, 16);
|
value = simple_strtoul(p, &endp, 16);
|
||||||
if (endp == p || value > 0xFF) {
|
if (endp == p || value > 0xFF) {
|
||||||
INFO("%s: Bad input\n", __func__);
|
INFO("%s: Bad input\n", __func__);
|
||||||
@ -414,7 +424,8 @@ static int __init xpp_mmap_load_fpga(u8 *data, size_t size)
|
|||||||
bfin_write_PORTGIO_DIR(bfin_read_PORTGIO_DIR() | DATA | NCONFIG | DCLK); //set data, nconfig and dclk to port out
|
bfin_write_PORTGIO_DIR(bfin_read_PORTGIO_DIR() | DATA | NCONFIG | DCLK); //set data, nconfig and dclk to port out
|
||||||
bfin_write_PORTG_FER(bfin_read_PORTG_FER() & ~(DATA | NCONFIG | DCLK));
|
bfin_write_PORTG_FER(bfin_read_PORTG_FER() & ~(DATA | NCONFIG | DCLK));
|
||||||
bfin_write_PORTGIO_DIR(bfin_read_PORTGIO_DIR() & ~(CONF_DONE | NSTATUS)); //set conf_done and nstatus to port in
|
bfin_write_PORTGIO_DIR(bfin_read_PORTGIO_DIR() & ~(CONF_DONE | NSTATUS)); //set conf_done and nstatus to port in
|
||||||
bfin_write_PORTGIO_INEN(bfin_read_PORTGIO_INEN() & ~(DATA | NCONFIG | DCLK));
|
bfin_write_PORTGIO_INEN(bfin_read_PORTGIO_INEN() &
|
||||||
|
~(DATA | NCONFIG | DCLK));
|
||||||
bfin_write_PORTGIO_INEN(bfin_read_PORTGIO_INEN() | CONF_DONE | NSTATUS);
|
bfin_write_PORTGIO_INEN(bfin_read_PORTGIO_INEN() | CONF_DONE | NSTATUS);
|
||||||
|
|
||||||
bfin_write_PORTGIO_CLEAR(NCONFIG); //reset fpga during configuration holds nCONFIG low
|
bfin_write_PORTGIO_CLEAR(NCONFIG); //reset fpga during configuration holds nCONFIG low
|
||||||
@ -456,8 +467,10 @@ static int __init xpp_mmap_load_fpga(u8 *data, size_t size)
|
|||||||
* to be used for debugging from now on.
|
* to be used for debugging from now on.
|
||||||
*/
|
*/
|
||||||
bfin_write_PORTGIO_DIR(bfin_read_PORTGIO_DIR() | DEBUG_GPIO1 | DEBUG_GPIO2); //set to port out
|
bfin_write_PORTGIO_DIR(bfin_read_PORTGIO_DIR() | DEBUG_GPIO1 | DEBUG_GPIO2); //set to port out
|
||||||
bfin_write_PORTG_FER(bfin_read_PORTG_FER() & ~(DEBUG_GPIO1 | DEBUG_GPIO2));
|
bfin_write_PORTG_FER(bfin_read_PORTG_FER() &
|
||||||
bfin_write_PORTGIO_INEN(bfin_read_PORTGIO_INEN() & ~(DEBUG_GPIO1 | DEBUG_GPIO2));
|
~(DEBUG_GPIO1 | DEBUG_GPIO2));
|
||||||
|
bfin_write_PORTGIO_INEN(bfin_read_PORTGIO_INEN() &
|
||||||
|
~(DEBUG_GPIO1 | DEBUG_GPIO2));
|
||||||
#endif
|
#endif
|
||||||
udelay(40); //tCD2UM - CONF_DONE high to user mode
|
udelay(40); //tCD2UM - CONF_DONE high to user mode
|
||||||
return 0;
|
return 0;
|
||||||
@ -476,7 +489,8 @@ static int __init xpp_mmap_load_firmware(void)
|
|||||||
{
|
{
|
||||||
const struct firmware *fw;
|
const struct firmware *fw;
|
||||||
int ret;
|
int ret;
|
||||||
if ((ret = request_firmware(&fw, "astribank.bin", &astribank_dev.dev)) < 0)
|
if ((ret =
|
||||||
|
request_firmware(&fw, "astribank.bin", &astribank_dev.dev)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
xpp_mmap_load_fpga(fw->data, fw->size);
|
xpp_mmap_load_fpga(fw->data, fw->size);
|
||||||
release_firmware(fw);
|
release_firmware(fw);
|
||||||
@ -499,11 +513,15 @@ static int __init xpp_mmap_init(void)
|
|||||||
goto fail_fw;
|
goto fail_fw;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = request_irq(FPGA_RX_IRQ, xpp_mmap_rx_irq, IRQF_TRIGGER_RISING, "xpp_mmap_rx", NULL)) < 0) {
|
if ((ret =
|
||||||
|
request_irq(FPGA_RX_IRQ, xpp_mmap_rx_irq, IRQF_TRIGGER_RISING,
|
||||||
|
"xpp_mmap_rx", NULL)) < 0) {
|
||||||
ERR("Unable to attach to RX interrupt %d\n", FPGA_RX_IRQ);
|
ERR("Unable to attach to RX interrupt %d\n", FPGA_RX_IRQ);
|
||||||
goto fail_irq_rx;
|
goto fail_irq_rx;
|
||||||
}
|
}
|
||||||
if ((ret = request_irq(FPGA_TX_IRQ, xpp_mmap_tx_irq, IRQF_TRIGGER_RISING, "xpp_mmap_tx", NULL)) < 0) {
|
if ((ret =
|
||||||
|
request_irq(FPGA_TX_IRQ, xpp_mmap_tx_irq, IRQF_TRIGGER_RISING,
|
||||||
|
"xpp_mmap_tx", NULL)) < 0) {
|
||||||
ERR("Unable to attach to TX interrupt %d\n", FPGA_TX_IRQ);
|
ERR("Unable to attach to TX interrupt %d\n", FPGA_TX_IRQ);
|
||||||
goto fail_irq_tx;
|
goto fail_irq_tx;
|
||||||
}
|
}
|
||||||
@ -513,9 +531,9 @@ static int __init xpp_mmap_init(void)
|
|||||||
}
|
}
|
||||||
outw(AS_BF_MODE, FPGA_BASE_ADDR + 4);
|
outw(AS_BF_MODE, FPGA_BASE_ADDR + 4);
|
||||||
|
|
||||||
xframe_cache = kmem_cache_create("xframe_cache",
|
xframe_cache =
|
||||||
sizeof(xframe_t) + XFRAME_DATASIZE,
|
kmem_cache_create("xframe_cache",
|
||||||
0, 0,
|
sizeof(xframe_t) + XFRAME_DATASIZE, 0, 0,
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)
|
||||||
NULL,
|
NULL,
|
||||||
#endif
|
#endif
|
||||||
@ -534,7 +552,9 @@ static int __init xpp_mmap_init(void)
|
|||||||
strncpy(global_xbus->label, "mmap:0", LABEL_SIZE);
|
strncpy(global_xbus->label, "mmap:0", LABEL_SIZE);
|
||||||
|
|
||||||
xframe_queue_init(&txpool, 10, 200, "mmap_txpool", global_xbus);
|
xframe_queue_init(&txpool, 10, 200, "mmap_txpool", global_xbus);
|
||||||
if (!(proc_entry = create_proc_entry("xpp_mmap", 0, global_xbus->proc_xbus_dir))) {
|
if (!
|
||||||
|
(proc_entry =
|
||||||
|
create_proc_entry("xpp_mmap", 0, global_xbus->proc_xbus_dir))) {
|
||||||
ERR("create_proc_entry() failed\n");
|
ERR("create_proc_entry() failed\n");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto fail_proc;
|
goto fail_proc;
|
||||||
|
@ -59,11 +59,13 @@ void flip_parport_bit(unsigned char bitnum)
|
|||||||
spin_unlock_irqrestore(&lock, flags);
|
spin_unlock_irqrestore(&lock, flags);
|
||||||
parport_write_data(debug_sync_parport, value);
|
parport_write_data(debug_sync_parport, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(flip_parport_bit);
|
EXPORT_SYMBOL(flip_parport_bit);
|
||||||
|
|
||||||
static void parport_attach(struct parport *port)
|
static void parport_attach(struct parport *port)
|
||||||
{
|
{
|
||||||
printk(KERN_INFO "%s: Using %s for debugging\n", THIS_MODULE->name, port->name);
|
printk(KERN_INFO "%s: Using %s for debugging\n", THIS_MODULE->name,
|
||||||
|
port->name);
|
||||||
if (debug_sync_parport) {
|
if (debug_sync_parport) {
|
||||||
printk(KERN_ERR "%s: Using %s, ignore new attachment %s\n",
|
printk(KERN_ERR "%s: Using %s, ignore new attachment %s\n",
|
||||||
THIS_MODULE->name, debug_sync_parport->name, port->name);
|
THIS_MODULE->name, debug_sync_parport->name, port->name);
|
||||||
|
@ -5,7 +5,8 @@ int main(int argc, char *argv[])
|
|||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < (sizeof(fxo_modes) / sizeof(struct fxo_mode)); i++) {
|
for (i = 0; i < (sizeof(fxo_modes) / sizeof(struct fxo_mode)); i++) {
|
||||||
if (fxo_modes[i].name == NULL) break;
|
if (fxo_modes[i].name == NULL)
|
||||||
|
break;
|
||||||
int reg16 = 0, reg26 = 0, reg30 = 0, reg31 = 0x20;
|
int reg16 = 0, reg26 = 0, reg30 = 0, reg31 = 0x20;
|
||||||
char ring_osc[BUFSIZ] = "", ring_x[BUFSIZ] = "";
|
char ring_osc[BUFSIZ] = "", ring_x[BUFSIZ] = "";
|
||||||
|
|
||||||
@ -22,11 +23,15 @@ int main(int argc, char *argv[])
|
|||||||
reg31 |= (fxo_modes[i].ohs2 << 3);
|
reg31 |= (fxo_modes[i].ohs2 << 3);
|
||||||
|
|
||||||
if (fxo_modes[i].ring_osc)
|
if (fxo_modes[i].ring_osc)
|
||||||
snprintf(ring_osc, BUFSIZ, "ring_osc=%04X", fxo_modes[i].ring_osc);
|
snprintf(ring_osc, BUFSIZ, "ring_osc=%04X",
|
||||||
|
fxo_modes[i].ring_osc);
|
||||||
if (fxo_modes[i].ring_x)
|
if (fxo_modes[i].ring_x)
|
||||||
snprintf(ring_x, BUFSIZ, "ring_x=%04X", fxo_modes[i].ring_x);
|
snprintf(ring_x, BUFSIZ, "ring_x=%04X",
|
||||||
printf("%-15s\treg16=%02X\treg26=%02X\treg30=%02X\treg31=%02X\t%s\t%s\n",
|
fxo_modes[i].ring_x);
|
||||||
fxo_modes[i].name, reg16, reg26, reg30, reg31, ring_osc, ring_x);
|
printf
|
||||||
|
("%-15s\treg16=%02X\treg26=%02X\treg30=%02X\treg31=%02X\t%s\t%s\n",
|
||||||
|
fxo_modes[i].name, reg16, reg26, reg30, reg31, ring_osc,
|
||||||
|
ring_x);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -52,22 +52,28 @@ static const char rcsid[] = "$Id$";
|
|||||||
#ifdef PROTOCOL_DEBUG
|
#ifdef PROTOCOL_DEBUG
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
#define PROC_XBUS_COMMAND "command"
|
#define PROC_XBUS_COMMAND "command"
|
||||||
static int proc_xbus_command_write(struct file *file, const char __user *buffer, unsigned long count, void *data);
|
static int proc_xbus_command_write(struct file *file, const char __user *buffer,
|
||||||
|
unsigned long count, void *data);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Command line parameters */
|
/* Command line parameters */
|
||||||
extern int debug;
|
extern int debug;
|
||||||
static DEF_PARM(uint, command_queue_length, 1500, 0444, "Maximal command queue length");
|
static DEF_PARM(uint, command_queue_length, 1500, 0444,
|
||||||
static DEF_PARM(uint, poll_timeout, 1000, 0644, "Timeout (in jiffies) waiting for units to reply");
|
"Maximal command queue length");
|
||||||
|
static DEF_PARM(uint, poll_timeout, 1000, 0644,
|
||||||
|
"Timeout (in jiffies) waiting for units to reply");
|
||||||
static DEF_PARM_BOOL(rx_tasklet, 0, 0644, "Use receive tasklets");
|
static DEF_PARM_BOOL(rx_tasklet, 0, 0644, "Use receive tasklets");
|
||||||
static DEF_PARM_BOOL(dahdi_autoreg, 0, 0644,
|
static DEF_PARM_BOOL(dahdi_autoreg, 0, 0644,
|
||||||
"Register devices automatically (1) or not (0)");
|
"Register devices automatically (1) or not (0)");
|
||||||
|
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
static int xbus_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data);
|
static int xbus_read_proc(char *page, char **start, off_t off, int count,
|
||||||
|
int *eof, void *data);
|
||||||
#endif
|
#endif
|
||||||
static void transport_init(xbus_t *xbus, struct xbus_ops *ops, ushort max_send_size, struct device *transport_device, void *priv);
|
static void transport_init(xbus_t *xbus, struct xbus_ops *ops,
|
||||||
|
ushort max_send_size,
|
||||||
|
struct device *transport_device, void *priv);
|
||||||
static void transport_destroy(xbus_t *xbus);
|
static void transport_destroy(xbus_t *xbus);
|
||||||
|
|
||||||
/* Data structures */
|
/* Data structures */
|
||||||
@ -105,8 +111,7 @@ int xbus_check_unique(xbus_t *xbus)
|
|||||||
if (xbus_old && xbus_old != xbus) {
|
if (xbus_old && xbus_old != xbus) {
|
||||||
XBUS_NOTICE(xbus_old,
|
XBUS_NOTICE(xbus_old,
|
||||||
"Duplicate LABEL='%s'. Leave %s unused. refcount_xbus=%d\n",
|
"Duplicate LABEL='%s'. Leave %s unused. refcount_xbus=%d\n",
|
||||||
xbus_old->label,
|
xbus_old->label, xbus->busname,
|
||||||
xbus->busname,
|
|
||||||
refcount_xbus(xbus_old));
|
refcount_xbus(xbus_old));
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
@ -119,14 +124,22 @@ int xbus_check_unique(xbus_t *xbus)
|
|||||||
const char *xbus_statename(enum xbus_state st)
|
const char *xbus_statename(enum xbus_state st)
|
||||||
{
|
{
|
||||||
switch (st) {
|
switch (st) {
|
||||||
case XBUS_STATE_START: return "START";
|
case XBUS_STATE_START:
|
||||||
case XBUS_STATE_IDLE: return "IDLE";
|
return "START";
|
||||||
case XBUS_STATE_SENT_REQUEST: return "SENT_REQUEST";
|
case XBUS_STATE_IDLE:
|
||||||
case XBUS_STATE_RECVD_DESC: return "RECVD_DESC";
|
return "IDLE";
|
||||||
case XBUS_STATE_READY: return "READY";
|
case XBUS_STATE_SENT_REQUEST:
|
||||||
case XBUS_STATE_DEACTIVATING: return "DEACTIVATING";
|
return "SENT_REQUEST";
|
||||||
case XBUS_STATE_DEACTIVATED: return "DEACTIVATED";
|
case XBUS_STATE_RECVD_DESC:
|
||||||
case XBUS_STATE_FAIL: return "FAIL";
|
return "RECVD_DESC";
|
||||||
|
case XBUS_STATE_READY:
|
||||||
|
return "READY";
|
||||||
|
case XBUS_STATE_DEACTIVATING:
|
||||||
|
return "DEACTIVATING";
|
||||||
|
case XBUS_STATE_DEACTIVATED:
|
||||||
|
return "DEACTIVATED";
|
||||||
|
case XBUS_STATE_FAIL:
|
||||||
|
return "FAIL";
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -191,8 +204,8 @@ xbus_t *get_xbus(const char *msg, uint num)
|
|||||||
xbus = xbus_num(num);
|
xbus = xbus_num(num);
|
||||||
if (xbus != NULL) {
|
if (xbus != NULL) {
|
||||||
kref_get(&xbus->kref);
|
kref_get(&xbus->kref);
|
||||||
XBUS_DBG(DEVICES, xbus, "%s: refcount_xbus=%d\n",
|
XBUS_DBG(DEVICES, xbus, "%s: refcount_xbus=%d\n", msg,
|
||||||
msg, refcount_xbus(xbus));
|
refcount_xbus(xbus));
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&xbuses_lock, flags);
|
spin_unlock_irqrestore(&xbuses_lock, flags);
|
||||||
return xbus;
|
return xbus;
|
||||||
@ -200,8 +213,8 @@ xbus_t *get_xbus(const char *msg, uint num)
|
|||||||
|
|
||||||
void put_xbus(const char *msg, xbus_t *xbus)
|
void put_xbus(const char *msg, xbus_t *xbus)
|
||||||
{
|
{
|
||||||
XBUS_DBG(DEVICES, xbus, "%s: refcount_xbus=%d\n",
|
XBUS_DBG(DEVICES, xbus, "%s: refcount_xbus=%d\n", msg,
|
||||||
msg, refcount_xbus(xbus));
|
refcount_xbus(xbus));
|
||||||
kref_put(&xbus->kref, xbus_destroy);
|
kref_put(&xbus->kref, xbus_destroy);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,7 +227,8 @@ int refcount_xbus(xbus_t *xbus)
|
|||||||
|
|
||||||
/*------------------------- Frame Handling ------------------------*/
|
/*------------------------- Frame Handling ------------------------*/
|
||||||
|
|
||||||
void xframe_init(xbus_t *xbus, xframe_t *xframe, void *buf, size_t maxsize, void *priv)
|
void xframe_init(xbus_t *xbus, xframe_t *xframe, void *buf, size_t maxsize,
|
||||||
|
void *priv)
|
||||||
{
|
{
|
||||||
memset(xframe, 0, sizeof(*xframe));
|
memset(xframe, 0, sizeof(*xframe));
|
||||||
INIT_LIST_HEAD(&xframe->frame_list);
|
INIT_LIST_HEAD(&xframe->frame_list);
|
||||||
@ -260,7 +274,8 @@ static void do_hexdump(const char msg[], __u8 *data, uint16_t len)
|
|||||||
DBG(ANY, "%s: %3d> %02X\n", msg, i, data[i]);
|
DBG(ANY, "%s: %3d> %02X\n", msg, i, data[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe, int debug)
|
void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe,
|
||||||
|
int debug)
|
||||||
{
|
{
|
||||||
const uint16_t frm_len = XFRAME_LEN(xframe);
|
const uint16_t frm_len = XFRAME_LEN(xframe);
|
||||||
xpacket_t *pack;
|
xpacket_t *pack;
|
||||||
@ -271,15 +286,16 @@ void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe, i
|
|||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if (xframe->xframe_magic != XFRAME_MAGIC) {
|
if (xframe->xframe_magic != XFRAME_MAGIC) {
|
||||||
XBUS_ERR(xbus, "%s: bad xframe_magic %lX\n",
|
XBUS_ERR(xbus, "%s: bad xframe_magic %lX\n", __func__,
|
||||||
__func__, xframe->xframe_magic);
|
xframe->xframe_magic);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
spin_lock_irqsave(&serialize_dump_xframe, flags);
|
spin_lock_irqsave(&serialize_dump_xframe, flags);
|
||||||
do {
|
do {
|
||||||
if (pos >= xbus->transport.max_send_size) {
|
if (pos >= xbus->transport.max_send_size) {
|
||||||
if (printk_ratelimit()) {
|
if (printk_ratelimit()) {
|
||||||
XBUS_NOTICE(xbus, "%s: xframe overflow (%d bytes)\n",
|
XBUS_NOTICE(xbus,
|
||||||
|
"%s: xframe overflow (%d bytes)\n",
|
||||||
msg, frm_len);
|
msg, frm_len);
|
||||||
do_hexdump(msg, xframe->packets, frm_len);
|
do_hexdump(msg, xframe->packets, frm_len);
|
||||||
}
|
}
|
||||||
@ -287,7 +303,8 @@ void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe, i
|
|||||||
}
|
}
|
||||||
if (pos > frm_len) {
|
if (pos > frm_len) {
|
||||||
if (printk_ratelimit()) {
|
if (printk_ratelimit()) {
|
||||||
XBUS_NOTICE(xbus, "%s: packet overflow pos=%d frame_len=%d\n",
|
XBUS_NOTICE(xbus,
|
||||||
|
"%s: packet overflow pos=%d frame_len=%d\n",
|
||||||
msg, pos, frm_len);
|
msg, pos, frm_len);
|
||||||
do_hexdump(msg, xframe->packets, frm_len);
|
do_hexdump(msg, xframe->packets, frm_len);
|
||||||
}
|
}
|
||||||
@ -296,8 +313,10 @@ void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe, i
|
|||||||
pack = (xpacket_t *)&xframe->packets[pos];
|
pack = (xpacket_t *)&xframe->packets[pos];
|
||||||
if (XPACKET_LEN(pack) <= 0) {
|
if (XPACKET_LEN(pack) <= 0) {
|
||||||
if (printk_ratelimit()) {
|
if (printk_ratelimit()) {
|
||||||
XBUS_NOTICE(xbus, "%s: xframe -- bad packet_len=%d pos=%d frame_len=%d\n",
|
XBUS_NOTICE(xbus,
|
||||||
msg, XPACKET_LEN(pack), pos, frm_len);
|
"%s: xframe -- bad packet_len=%d pos=%d frame_len=%d\n",
|
||||||
|
msg, XPACKET_LEN(pack), pos,
|
||||||
|
frm_len);
|
||||||
do_hexdump(msg, xframe->packets, frm_len);
|
do_hexdump(msg, xframe->packets, frm_len);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -305,7 +324,8 @@ void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe, i
|
|||||||
nextpos = pos + XPACKET_LEN(pack);
|
nextpos = pos + XPACKET_LEN(pack);
|
||||||
if (nextpos > frm_len) {
|
if (nextpos > frm_len) {
|
||||||
if (printk_ratelimit()) {
|
if (printk_ratelimit()) {
|
||||||
XBUS_NOTICE(xbus, "%s: packet overflow nextpos=%d frame_len=%d\n",
|
XBUS_NOTICE(xbus,
|
||||||
|
"%s: packet overflow nextpos=%d frame_len=%d\n",
|
||||||
msg, nextpos, frm_len);
|
msg, nextpos, frm_len);
|
||||||
do_hexdump(msg, xframe->packets, frm_len);
|
do_hexdump(msg, xframe->packets, frm_len);
|
||||||
}
|
}
|
||||||
@ -314,8 +334,8 @@ void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe, i
|
|||||||
do_print = 0;
|
do_print = 0;
|
||||||
if (debug == DBG_ANY)
|
if (debug == DBG_ANY)
|
||||||
do_print = 1;
|
do_print = 1;
|
||||||
else if (XPACKET_OP(pack) != XPROTO_NAME(GLOBAL, PCM_READ) &&
|
else if (XPACKET_OP(pack) != XPROTO_NAME(GLOBAL, PCM_READ)
|
||||||
XPACKET_OP(pack) != XPROTO_NAME(GLOBAL, PCM_WRITE))
|
&& XPACKET_OP(pack) != XPROTO_NAME(GLOBAL, PCM_WRITE))
|
||||||
do_print = 1;
|
do_print = 1;
|
||||||
else if (debug & DBG_PCM) {
|
else if (debug & DBG_PCM) {
|
||||||
static int rate_limit;
|
static int rate_limit;
|
||||||
@ -326,17 +346,15 @@ void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe, i
|
|||||||
if (do_print) {
|
if (do_print) {
|
||||||
if (num == 1) {
|
if (num == 1) {
|
||||||
XBUS_DBG(ANY, xbus, "%s: frame_len=%d. %s\n",
|
XBUS_DBG(ANY, xbus, "%s: frame_len=%d. %s\n",
|
||||||
msg, frm_len,
|
msg, frm_len, (XPACKET_IS_PCM(pack))
|
||||||
(XPACKET_IS_PCM(pack))
|
? "(IS_PCM)" : "");
|
||||||
? "(IS_PCM)"
|
|
||||||
: "");
|
|
||||||
}
|
}
|
||||||
XBUS_DBG(ANY, xbus, " %3d. DATALEN=%d pcm=%d slot=%d OP=0x%02X XPD-%d%d (pos=%d)\n",
|
XBUS_DBG(ANY, xbus,
|
||||||
num, XPACKET_LEN(pack),
|
" %3d. DATALEN=%d pcm=%d slot=%d OP=0x%02X XPD-%d%d (pos=%d)\n",
|
||||||
XPACKET_IS_PCM(pack), XPACKET_PCMSLOT(pack),
|
num, XPACKET_LEN(pack), XPACKET_IS_PCM(pack),
|
||||||
XPACKET_OP(pack),
|
XPACKET_PCMSLOT(pack), XPACKET_OP(pack),
|
||||||
XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack),
|
XPACKET_ADDR_UNIT(pack),
|
||||||
pos);
|
XPACKET_ADDR_SUBUNIT(pack), pos);
|
||||||
dump_packet(" ", pack, debug);
|
dump_packet(" ", pack, debug);
|
||||||
}
|
}
|
||||||
num++;
|
num++;
|
||||||
@ -360,7 +378,8 @@ int send_pcm_frame(xbus_t *xbus, xframe_t *xframe)
|
|||||||
|
|
||||||
BUG_ON(!xframe);
|
BUG_ON(!xframe);
|
||||||
if (!XBUS_IS(xbus, READY)) {
|
if (!XBUS_IS(xbus, READY)) {
|
||||||
XBUS_ERR(xbus, "Dropped a pcm frame -- hardware is not ready.\n");
|
XBUS_ERR(xbus,
|
||||||
|
"Dropped a pcm frame -- hardware is not ready.\n");
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@ -386,7 +405,8 @@ static int really_send_cmd_frame(xbus_t *xbus, xframe_t *xframe)
|
|||||||
BUG_ON(!xframe);
|
BUG_ON(!xframe);
|
||||||
BUG_ON(xframe->xframe_magic != XFRAME_MAGIC);
|
BUG_ON(xframe->xframe_magic != XFRAME_MAGIC);
|
||||||
if (!XBUS_FLAGS(xbus, CONNECTED)) {
|
if (!XBUS_FLAGS(xbus, CONNECTED)) {
|
||||||
XBUS_ERR(xbus, "Dropped command before sending -- hardware deactivated.\n");
|
XBUS_ERR(xbus,
|
||||||
|
"Dropped command before sending -- hardware deactivated.\n");
|
||||||
dump_xframe("Dropped", xbus, xframe, DBG_ANY);
|
dump_xframe("Dropped", xbus, xframe, DBG_ANY);
|
||||||
FREE_SEND_XFRAME(xbus, xframe);
|
FREE_SEND_XFRAME(xbus, xframe);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
@ -451,8 +471,10 @@ static int xbus_command_queue_waitempty(xbus_t *xbus)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
XBUS_DBG(DEVICES, xbus, "Waiting for command_queue to empty\n");
|
XBUS_DBG(DEVICES, xbus, "Waiting for command_queue to empty\n");
|
||||||
ret = wait_event_interruptible(xbus->command_queue_empty,
|
ret =
|
||||||
xframe_queue_count(&xbus->command_queue) == 0);
|
wait_event_interruptible(xbus->command_queue_empty,
|
||||||
|
xframe_queue_count(&xbus->command_queue) ==
|
||||||
|
0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
XBUS_ERR(xbus, "waiting for command_queue interrupted!!!\n");
|
XBUS_ERR(xbus, "waiting for command_queue interrupted!!!\n");
|
||||||
}
|
}
|
||||||
@ -464,10 +486,10 @@ int send_cmd_frame(xbus_t *xbus, xframe_t *xframe)
|
|||||||
static int rate_limit;
|
static int rate_limit;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
|
||||||
BUG_ON(xframe->xframe_magic != XFRAME_MAGIC);
|
BUG_ON(xframe->xframe_magic != XFRAME_MAGIC);
|
||||||
if (!XBUS_FLAGS(xbus, CONNECTED)) {
|
if (!XBUS_FLAGS(xbus, CONNECTED)) {
|
||||||
XBUS_ERR(xbus, "Dropped command before queueing -- hardware deactivated.\n");
|
XBUS_ERR(xbus,
|
||||||
|
"Dropped command before queueing -- hardware deactivated.\n");
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@ -502,7 +524,9 @@ static void xframe_enqueue_recv(xbus_t *xbus, xframe_t *xframe)
|
|||||||
static int rate_limit;
|
static int rate_limit;
|
||||||
|
|
||||||
if ((rate_limit++ % 1003) == 0)
|
if ((rate_limit++ % 1003) == 0)
|
||||||
XBUS_ERR(xbus, "Failed to enqueue for receive_tasklet (%d)\n", rate_limit);
|
XBUS_ERR(xbus,
|
||||||
|
"Failed to enqueue for receive_tasklet (%d)\n",
|
||||||
|
rate_limit);
|
||||||
FREE_RECV_XFRAME(xbus, xframe); /* return to receive_pool */
|
FREE_RECV_XFRAME(xbus, xframe); /* return to receive_pool */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -569,8 +593,8 @@ int xbus_xpd_bind(xbus_t *xbus, xpd_t *xpd, int unit, int subunit)
|
|||||||
if (xbus->xpds[xpd_num] != NULL) {
|
if (xbus->xpds[xpd_num] != NULL) {
|
||||||
xpd_t *other = xbus->xpds[xpd_num];
|
xpd_t *other = xbus->xpds[xpd_num];
|
||||||
|
|
||||||
XBUS_ERR(xbus, "xpd_num=%d is occupied by %p (%s)\n",
|
XBUS_ERR(xbus, "xpd_num=%d is occupied by %p (%s)\n", xpd_num,
|
||||||
xpd_num, other, other->xpdname);
|
other, other->xpdname);
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
snprintf(xpd->xpdname, XPD_NAMELEN, "XPD-%1d%1d", unit, subunit);
|
snprintf(xpd->xpdname, XPD_NAMELEN, "XPD-%1d%1d", unit, subunit);
|
||||||
@ -599,7 +623,8 @@ int xbus_xpd_unbind(xbus_t *xbus, xpd_t *xpd)
|
|||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
if (xbus->xpds[xpd_num] == NULL) {
|
if (xbus->xpds[xpd_num] == NULL) {
|
||||||
XBUS_ERR(xbus, "%s: slot xpd_num=%d is empty\n", __func__, xpd_num);
|
XBUS_ERR(xbus, "%s: slot xpd_num=%d is empty\n", __func__,
|
||||||
|
xpd_num);
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
if (xbus->xpds[xpd_num] != xpd) {
|
if (xbus->xpds[xpd_num] != xpd) {
|
||||||
@ -618,13 +643,8 @@ int xbus_xpd_unbind(xbus_t *xbus, xpd_t *xpd)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int new_card(xbus_t *xbus,
|
static int new_card(xbus_t *xbus, int unit, __u8 type, __u8 subtype,
|
||||||
int unit,
|
__u8 numchips, __u8 ports_per_chip, __u8 ports,
|
||||||
__u8 type,
|
|
||||||
__u8 subtype,
|
|
||||||
__u8 numchips,
|
|
||||||
__u8 ports_per_chip,
|
|
||||||
__u8 ports,
|
|
||||||
__u8 port_dir)
|
__u8 port_dir)
|
||||||
{
|
{
|
||||||
const xproto_table_t *proto_table;
|
const xproto_table_t *proto_table;
|
||||||
@ -654,18 +674,13 @@ static int new_card(xbus_t *xbus,
|
|||||||
xbus->echo_state.xpd_idx = XPD_IDX(unit, 0);
|
xbus->echo_state.xpd_idx = XPD_IDX(unit, 0);
|
||||||
}
|
}
|
||||||
remaining_ports = ports;
|
remaining_ports = ports;
|
||||||
subunits = (ports + proto_table->ports_per_subunit - 1) /
|
subunits =
|
||||||
proto_table->ports_per_subunit;
|
(ports + proto_table->ports_per_subunit -
|
||||||
XBUS_DBG(DEVICES, xbus, "CARD %d type=%d.%d ports=%d (%dx%d), %d subunits, port-dir=0x%02X\n",
|
1) / proto_table->ports_per_subunit;
|
||||||
unit,
|
XBUS_DBG(DEVICES, xbus,
|
||||||
type,
|
"CARD %d type=%d.%d ports=%d (%dx%d), %d subunits, port-dir=0x%02X\n",
|
||||||
subtype,
|
unit, type, subtype, ports, numchips, ports_per_chip, subunits,
|
||||||
ports,
|
port_dir);
|
||||||
numchips,
|
|
||||||
ports_per_chip,
|
|
||||||
subunits,
|
|
||||||
port_dir
|
|
||||||
);
|
|
||||||
if (type == XPD_TYPE_PRI || type == XPD_TYPE_BRI)
|
if (type == XPD_TYPE_PRI || type == XPD_TYPE_BRI)
|
||||||
xbus->quirks.has_digital_span = 1;
|
xbus->quirks.has_digital_span = 1;
|
||||||
if (type == XPD_TYPE_FXO)
|
if (type == XPD_TYPE_FXO)
|
||||||
@ -680,31 +695,26 @@ static int new_card(xbus_t *xbus,
|
|||||||
if (subunit_ports <= 0) {
|
if (subunit_ports <= 0) {
|
||||||
XBUS_NOTICE(xbus,
|
XBUS_NOTICE(xbus,
|
||||||
"Subunit XPD=%d%d without ports (%d of %d)\n",
|
"Subunit XPD=%d%d without ports (%d of %d)\n",
|
||||||
unit,
|
unit, i, subunit_ports, ports);
|
||||||
i,
|
|
||||||
subunit_ports,
|
|
||||||
ports);
|
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (!XBUS_IS(xbus, RECVD_DESC)) {
|
if (!XBUS_IS(xbus, RECVD_DESC)) {
|
||||||
XBUS_NOTICE(xbus,
|
XBUS_NOTICE(xbus,
|
||||||
"Cannot create XPD=%d%d in state %s\n",
|
"Cannot create XPD=%d%d in state %s\n",
|
||||||
unit,
|
unit, i, xbus_statename(XBUS_STATE(xbus)));
|
||||||
i,
|
|
||||||
xbus_statename(XBUS_STATE(xbus)));
|
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
XBUS_DBG(DEVICES, xbus, "Creating XPD=%d%d type=%d.%d (%d ports)\n",
|
XBUS_DBG(DEVICES, xbus,
|
||||||
unit,
|
"Creating XPD=%d%d type=%d.%d (%d ports)\n", unit, i,
|
||||||
i,
|
type, subtype, subunit_ports);
|
||||||
type,
|
ret =
|
||||||
subtype, subunit_ports);
|
create_xpd(xbus, proto_table, unit, i, type, subtype,
|
||||||
ret = create_xpd(xbus, proto_table, unit, i, type, subtype, subunits, subunit_ports, port_dir);
|
subunits, subunit_ports, port_dir);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
XBUS_ERR(xbus, "Creation of XPD=%d%d failed %d\n",
|
XBUS_ERR(xbus, "Creation of XPD=%d%d failed %d\n", unit,
|
||||||
unit, i, ret);
|
i, ret);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
xbus->worker.num_units_initialized++;
|
xbus->worker.num_units_initialized++;
|
||||||
@ -845,8 +855,7 @@ static int xbus_initialize(xbus_t *xbus)
|
|||||||
int res = 0;
|
int res = 0;
|
||||||
|
|
||||||
do_gettimeofday(&time_start);
|
do_gettimeofday(&time_start);
|
||||||
XBUS_DBG(DEVICES, xbus, "refcount_xbus=%d\n",
|
XBUS_DBG(DEVICES, xbus, "refcount_xbus=%d\n", refcount_xbus(xbus));
|
||||||
refcount_xbus(xbus));
|
|
||||||
if (xbus_aquire_xpds(xbus) < 0) /* Until end of initialization */
|
if (xbus_aquire_xpds(xbus) < 0) /* Until end of initialization */
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
for (unit = 0; unit < MAX_UNIT; unit++) {
|
for (unit = 0; unit < MAX_UNIT; unit++) {
|
||||||
@ -856,12 +865,13 @@ static int xbus_initialize(xbus_t *xbus)
|
|||||||
if (!XBUS_IS(xbus, RECVD_DESC)) {
|
if (!XBUS_IS(xbus, RECVD_DESC)) {
|
||||||
XBUS_NOTICE(xbus,
|
XBUS_NOTICE(xbus,
|
||||||
"Cannot initialize UNIT=%d in state %s\n",
|
"Cannot initialize UNIT=%d in state %s\n",
|
||||||
unit,
|
unit, xbus_statename(XBUS_STATE(xbus)));
|
||||||
xbus_statename(XBUS_STATE(xbus)));
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if (run_initialize_registers(xpd) < 0) {
|
if (run_initialize_registers(xpd) < 0) {
|
||||||
XBUS_ERR(xbus, "Register Initialization of card #%d failed\n", unit);
|
XBUS_ERR(xbus,
|
||||||
|
"Register Initialization of card #%d failed\n",
|
||||||
|
unit);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
for (subunit = 0; subunit < MAX_SUBUNIT; subunit++) {
|
for (subunit = 0; subunit < MAX_SUBUNIT; subunit++) {
|
||||||
@ -885,7 +895,8 @@ static int xbus_initialize(xbus_t *xbus)
|
|||||||
do_gettimeofday(&time_end);
|
do_gettimeofday(&time_end);
|
||||||
timediff = usec_diff(&time_end, &time_start);
|
timediff = usec_diff(&time_end, &time_start);
|
||||||
timediff /= 1000 * 100;
|
timediff /= 1000 * 100;
|
||||||
XBUS_INFO(xbus, "Initialized in %ld.%1ld sec\n", timediff/10, timediff%10);
|
XBUS_INFO(xbus, "Initialized in %ld.%1ld sec\n", timediff / 10,
|
||||||
|
timediff % 10);
|
||||||
out:
|
out:
|
||||||
xbus_release_xpds(xbus); /* Initialization done/failed */
|
xbus_release_xpds(xbus); /* Initialization done/failed */
|
||||||
return res;
|
return res;
|
||||||
@ -1000,7 +1011,8 @@ void xbus_unregister_dahdi_device(xbus_t *xbus)
|
|||||||
}
|
}
|
||||||
if (xbus->ddev) {
|
if (xbus->ddev) {
|
||||||
dahdi_unregister_device(xbus->ddev);
|
dahdi_unregister_device(xbus->ddev);
|
||||||
XBUS_NOTICE(xbus, "%s: finished dahdi_unregister_device()\n", __func__);
|
XBUS_NOTICE(xbus, "%s: finished dahdi_unregister_device()\n",
|
||||||
|
__func__);
|
||||||
xbus_free_ddev(xbus);
|
xbus_free_ddev(xbus);
|
||||||
}
|
}
|
||||||
for (i = 0; i < MAX_XPDS; i++) {
|
for (i = 0; i < MAX_XPDS; i++) {
|
||||||
@ -1017,7 +1029,8 @@ void xbus_unregister_dahdi_device(xbus_t *xbus)
|
|||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
|
||||||
static void xbus_populate(struct work_struct *work)
|
static void xbus_populate(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct xbus_workqueue *worker = container_of(work, struct xbus_workqueue, xpds_init_work);
|
struct xbus_workqueue *worker =
|
||||||
|
container_of(work, struct xbus_workqueue, xpds_init_work);
|
||||||
#else
|
#else
|
||||||
void xbus_populate(void *data)
|
void xbus_populate(void *data)
|
||||||
{
|
{
|
||||||
@ -1034,19 +1047,17 @@ void xbus_populate(void *data)
|
|||||||
XBUS_DBG(DEVICES, xbus, "Entering %s\n", __func__);
|
XBUS_DBG(DEVICES, xbus, "Entering %s\n", __func__);
|
||||||
spin_lock_irqsave(&worker->worker_lock, flags);
|
spin_lock_irqsave(&worker->worker_lock, flags);
|
||||||
list_for_each_safe(card, next_card, &worker->card_list) {
|
list_for_each_safe(card, next_card, &worker->card_list) {
|
||||||
struct card_desc_struct *card_desc = list_entry(card, struct card_desc_struct, card_list);
|
struct card_desc_struct *card_desc =
|
||||||
|
list_entry(card, struct card_desc_struct, card_list);
|
||||||
|
|
||||||
list_del(card);
|
list_del(card);
|
||||||
BUG_ON(card_desc->magic != CARD_DESC_MAGIC);
|
BUG_ON(card_desc->magic != CARD_DESC_MAGIC);
|
||||||
/* Release/Reacquire locks around blocking calls */
|
/* Release/Reacquire locks around blocking calls */
|
||||||
spin_unlock_irqrestore(&xbus->worker.worker_lock, flags);
|
spin_unlock_irqrestore(&xbus->worker.worker_lock, flags);
|
||||||
ret = new_card(xbus,
|
ret =
|
||||||
card_desc->xpd_addr.unit,
|
new_card(xbus, card_desc->xpd_addr.unit, card_desc->type,
|
||||||
card_desc->type,
|
card_desc->subtype, card_desc->numchips,
|
||||||
card_desc->subtype,
|
card_desc->ports_per_chip, card_desc->ports,
|
||||||
card_desc->numchips,
|
|
||||||
card_desc->ports_per_chip,
|
|
||||||
card_desc->ports,
|
|
||||||
card_desc->port_dir);
|
card_desc->port_dir);
|
||||||
spin_lock_irqsave(&xbus->worker.worker_lock, flags);
|
spin_lock_irqsave(&xbus->worker.worker_lock, flags);
|
||||||
KZFREE(card_desc);
|
KZFREE(card_desc);
|
||||||
@ -1055,12 +1066,14 @@ void xbus_populate(void *data)
|
|||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&worker->worker_lock, flags);
|
spin_unlock_irqrestore(&worker->worker_lock, flags);
|
||||||
if (xbus_initialize(xbus) < 0) {
|
if (xbus_initialize(xbus) < 0) {
|
||||||
XBUS_NOTICE(xbus, "Initialization failed. Leave unused. refcount_xbus=%d\n",
|
XBUS_NOTICE(xbus,
|
||||||
|
"Initialization failed. Leave unused. refcount_xbus=%d\n",
|
||||||
refcount_xbus(xbus));
|
refcount_xbus(xbus));
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
if (!xbus_setstate(xbus, XBUS_STATE_READY)) {
|
if (!xbus_setstate(xbus, XBUS_STATE_READY)) {
|
||||||
XBUS_NOTICE(xbus, "Illegal transition. Leave unused. refcount_xbus=%d\n",
|
XBUS_NOTICE(xbus,
|
||||||
|
"Illegal transition. Leave unused. refcount_xbus=%d\n",
|
||||||
refcount_xbus(xbus));
|
refcount_xbus(xbus));
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
@ -1096,7 +1109,8 @@ int xbus_process_worker(xbus_t *xbus)
|
|||||||
}
|
}
|
||||||
worker = &xbus->worker;
|
worker = &xbus->worker;
|
||||||
if (down_trylock(&worker->running_initialization)) {
|
if (down_trylock(&worker->running_initialization)) {
|
||||||
ERR("%s: xbus is disconnected -- skip initialization\n", __func__);
|
ERR("%s: xbus is disconnected -- skip initialization\n",
|
||||||
|
__func__);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
XBUS_DBG(DEVICES, xbus, "\n");
|
XBUS_DBG(DEVICES, xbus, "\n");
|
||||||
@ -1129,12 +1143,13 @@ static void worker_reset(xbus_t *xbus)
|
|||||||
name = (xbus) ? xbus->busname : "detached";
|
name = (xbus) ? xbus->busname : "detached";
|
||||||
DBG(DEVICES, "%s\n", name);
|
DBG(DEVICES, "%s\n", name);
|
||||||
if (!worker->xpds_init_done) {
|
if (!worker->xpds_init_done) {
|
||||||
NOTICE("%s: worker(%s)->xpds_init_done=%d\n",
|
NOTICE("%s: worker(%s)->xpds_init_done=%d\n", __func__, name,
|
||||||
__func__, name, worker->xpds_init_done);
|
worker->xpds_init_done);
|
||||||
}
|
}
|
||||||
spin_lock_irqsave(&worker->worker_lock, flags);
|
spin_lock_irqsave(&worker->worker_lock, flags);
|
||||||
list_for_each_safe(card, next_card, &worker->card_list) {
|
list_for_each_safe(card, next_card, &worker->card_list) {
|
||||||
struct card_desc_struct *card_desc = list_entry(card, struct card_desc_struct, card_list);
|
struct card_desc_struct *card_desc =
|
||||||
|
list_entry(card, struct card_desc_struct, card_list);
|
||||||
|
|
||||||
BUG_ON(card_desc->magic != CARD_DESC_MAGIC);
|
BUG_ON(card_desc->magic != CARD_DESC_MAGIC);
|
||||||
list_del(card);
|
list_del(card);
|
||||||
@ -1215,8 +1230,7 @@ bool xbus_setflags(xbus_t *xbus, int flagbit, bool on)
|
|||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&xbus->transport.state_lock, flags);
|
spin_lock_irqsave(&xbus->transport.state_lock, flags);
|
||||||
XBUS_DBG(DEVICES, xbus, "%s flag %d\n",
|
XBUS_DBG(DEVICES, xbus, "%s flag %d\n", (on) ? "Set" : "Clear",
|
||||||
(on) ? "Set" : "Clear",
|
|
||||||
flagbit);
|
flagbit);
|
||||||
if (on)
|
if (on)
|
||||||
set_bit(flagbit, &(xbus->transport.transport_flags));
|
set_bit(flagbit, &(xbus->transport.transport_flags));
|
||||||
@ -1243,13 +1257,11 @@ bool xbus_setstate(xbus_t *xbus, enum xbus_state newstate)
|
|||||||
case XBUS_STATE_START:
|
case XBUS_STATE_START:
|
||||||
goto bad_state;
|
goto bad_state;
|
||||||
case XBUS_STATE_IDLE:
|
case XBUS_STATE_IDLE:
|
||||||
if (!XBUS_IS(xbus, START) &&
|
if (!XBUS_IS(xbus, START) && !XBUS_IS(xbus, DEACTIVATED))
|
||||||
!XBUS_IS(xbus, DEACTIVATED))
|
|
||||||
goto bad_state;
|
goto bad_state;
|
||||||
break;
|
break;
|
||||||
case XBUS_STATE_SENT_REQUEST:
|
case XBUS_STATE_SENT_REQUEST:
|
||||||
if (!XBUS_IS(xbus, IDLE) &&
|
if (!XBUS_IS(xbus, IDLE) && !XBUS_IS(xbus, SENT_REQUEST))
|
||||||
!XBUS_IS(xbus, SENT_REQUEST))
|
|
||||||
goto bad_state;
|
goto bad_state;
|
||||||
break;
|
break;
|
||||||
case XBUS_STATE_RECVD_DESC:
|
case XBUS_STATE_RECVD_DESC:
|
||||||
@ -1282,10 +1294,10 @@ bool xbus_setstate(xbus_t *xbus, enum xbus_state newstate)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
/* All good */
|
/* All good */
|
||||||
XBUS_DBG(DEVICES, xbus, "%s -> %s\n",
|
XBUS_DBG(DEVICES, xbus, "%s -> %s\n", xbus_statename(XBUS_STATE(xbus)),
|
||||||
xbus_statename(XBUS_STATE(xbus)),
|
|
||||||
xbus_statename(newstate));
|
xbus_statename(newstate));
|
||||||
if (xbus->transport.xbus_state == XBUS_STATE_READY && newstate != XBUS_STATE_READY)
|
if (xbus->transport.xbus_state == XBUS_STATE_READY
|
||||||
|
&& newstate != XBUS_STATE_READY)
|
||||||
state_flip = -1; /* We became bad */
|
state_flip = -1; /* We became bad */
|
||||||
xbus->transport.xbus_state = newstate;
|
xbus->transport.xbus_state = newstate;
|
||||||
ret = 1;
|
ret = 1;
|
||||||
@ -1299,8 +1311,7 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
bad_state:
|
bad_state:
|
||||||
XBUS_NOTICE(xbus, "Bad state transition %s -> %s ignored.\n",
|
XBUS_NOTICE(xbus, "Bad state transition %s -> %s ignored.\n",
|
||||||
xbus_statename(XBUS_STATE(xbus)),
|
xbus_statename(XBUS_STATE(xbus)), xbus_statename(newstate));
|
||||||
xbus_statename(newstate));
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1408,7 +1419,6 @@ out:
|
|||||||
return xbus;
|
return xbus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xbus_free(xbus_t *xbus)
|
void xbus_free(xbus_t *xbus)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
@ -1425,14 +1435,18 @@ void xbus_free(xbus_t *xbus)
|
|||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
if (xbus->proc_xbus_dir) {
|
if (xbus->proc_xbus_dir) {
|
||||||
if (xbus->proc_xbus_summary) {
|
if (xbus->proc_xbus_summary) {
|
||||||
XBUS_DBG(PROC, xbus, "Removing proc '%s'\n", PROC_XBUS_SUMMARY);
|
XBUS_DBG(PROC, xbus, "Removing proc '%s'\n",
|
||||||
remove_proc_entry(PROC_XBUS_SUMMARY, xbus->proc_xbus_dir);
|
PROC_XBUS_SUMMARY);
|
||||||
|
remove_proc_entry(PROC_XBUS_SUMMARY,
|
||||||
|
xbus->proc_xbus_dir);
|
||||||
xbus->proc_xbus_summary = NULL;
|
xbus->proc_xbus_summary = NULL;
|
||||||
}
|
}
|
||||||
#ifdef PROTOCOL_DEBUG
|
#ifdef PROTOCOL_DEBUG
|
||||||
if (xbus->proc_xbus_command) {
|
if (xbus->proc_xbus_command) {
|
||||||
XBUS_DBG(PROC, xbus, "Removing proc '%s'\n", PROC_XBUS_COMMAND);
|
XBUS_DBG(PROC, xbus, "Removing proc '%s'\n",
|
||||||
remove_proc_entry(PROC_XBUS_COMMAND, xbus->proc_xbus_dir);
|
PROC_XBUS_COMMAND);
|
||||||
|
remove_proc_entry(PROC_XBUS_COMMAND,
|
||||||
|
xbus->proc_xbus_dir);
|
||||||
xbus->proc_xbus_command = NULL;
|
xbus->proc_xbus_command = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1448,7 +1462,8 @@ void xbus_free(xbus_t *xbus)
|
|||||||
KZFREE(xbus);
|
KZFREE(xbus);
|
||||||
}
|
}
|
||||||
|
|
||||||
xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size, struct device *transport_device, void *priv)
|
xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size,
|
||||||
|
struct device *transport_device, void *priv)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
xbus_t *xbus = NULL;
|
xbus_t *xbus = NULL;
|
||||||
@ -1494,20 +1509,23 @@ xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size, struct device *tran
|
|||||||
err = -EIO;
|
err = -EIO;
|
||||||
goto nobus;
|
goto nobus;
|
||||||
}
|
}
|
||||||
xbus->proc_xbus_summary = create_proc_read_entry(PROC_XBUS_SUMMARY,
|
xbus->proc_xbus_summary =
|
||||||
0444, xbus->proc_xbus_dir,
|
create_proc_read_entry(PROC_XBUS_SUMMARY, 0444, xbus->proc_xbus_dir,
|
||||||
xbus_read_proc,
|
xbus_read_proc,
|
||||||
(void *)((unsigned long)(xbus->num)));
|
(void *)((unsigned long)(xbus->num)));
|
||||||
if (!xbus->proc_xbus_summary) {
|
if (!xbus->proc_xbus_summary) {
|
||||||
XBUS_ERR(xbus, "Failed to create proc file '%s'\n", PROC_XBUS_SUMMARY);
|
XBUS_ERR(xbus, "Failed to create proc file '%s'\n",
|
||||||
|
PROC_XBUS_SUMMARY);
|
||||||
err = -EIO;
|
err = -EIO;
|
||||||
goto nobus;
|
goto nobus;
|
||||||
}
|
}
|
||||||
SET_PROC_DIRENTRY_OWNER(xbus->proc_xbus_summary);
|
SET_PROC_DIRENTRY_OWNER(xbus->proc_xbus_summary);
|
||||||
#ifdef PROTOCOL_DEBUG
|
#ifdef PROTOCOL_DEBUG
|
||||||
xbus->proc_xbus_command = create_proc_entry(PROC_XBUS_COMMAND, 0200, xbus->proc_xbus_dir);
|
xbus->proc_xbus_command =
|
||||||
|
create_proc_entry(PROC_XBUS_COMMAND, 0200, xbus->proc_xbus_dir);
|
||||||
if (!xbus->proc_xbus_command) {
|
if (!xbus->proc_xbus_command) {
|
||||||
XBUS_ERR(xbus, "Failed to create proc file '%s'\n", PROC_XBUS_COMMAND);
|
XBUS_ERR(xbus, "Failed to create proc file '%s'\n",
|
||||||
|
PROC_XBUS_COMMAND);
|
||||||
err = -EIO;
|
err = -EIO;
|
||||||
goto nobus;
|
goto nobus;
|
||||||
}
|
}
|
||||||
@ -1516,12 +1534,14 @@ xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size, struct device *tran
|
|||||||
SET_PROC_DIRENTRY_OWNER(xbus->proc_xbus_command);
|
SET_PROC_DIRENTRY_OWNER(xbus->proc_xbus_command);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
xframe_queue_init(&xbus->command_queue, 10, command_queue_length, "command_queue", xbus);
|
xframe_queue_init(&xbus->command_queue, 10, command_queue_length,
|
||||||
|
"command_queue", xbus);
|
||||||
xframe_queue_init(&xbus->receive_queue, 10, 50, "receive_queue", xbus);
|
xframe_queue_init(&xbus->receive_queue, 10, 50, "receive_queue", xbus);
|
||||||
xframe_queue_init(&xbus->send_pool, 10, 100, "send_pool", xbus);
|
xframe_queue_init(&xbus->send_pool, 10, 100, "send_pool", xbus);
|
||||||
xframe_queue_init(&xbus->receive_pool, 10, 50, "receive_pool", xbus);
|
xframe_queue_init(&xbus->receive_pool, 10, 50, "receive_pool", xbus);
|
||||||
xframe_queue_init(&xbus->pcm_tospan, 5, 10, "pcm_tospan", xbus);
|
xframe_queue_init(&xbus->pcm_tospan, 5, 10, "pcm_tospan", xbus);
|
||||||
tasklet_init(&xbus->receive_tasklet, receive_tasklet_func, (unsigned long)xbus);
|
tasklet_init(&xbus->receive_tasklet, receive_tasklet_func,
|
||||||
|
(unsigned long)xbus);
|
||||||
/*
|
/*
|
||||||
* Create worker after /proc/XBUS-?? so the directory exists
|
* Create worker after /proc/XBUS-?? so the directory exists
|
||||||
* before /proc/XBUS-??/waitfor_xpds tries to get created.
|
* before /proc/XBUS-??/waitfor_xpds tries to get created.
|
||||||
@ -1588,11 +1608,11 @@ int waitfor_xpds(xbus_t *xbus, char *buf)
|
|||||||
}
|
}
|
||||||
XBUS_DBG(DEVICES, xbus,
|
XBUS_DBG(DEVICES, xbus,
|
||||||
"Waiting for card init of %d XPD's max %d seconds (%p)\n",
|
"Waiting for card init of %d XPD's max %d seconds (%p)\n",
|
||||||
worker->num_units,
|
worker->num_units, INITIALIZATION_TIMEOUT / HZ,
|
||||||
INITIALIZATION_TIMEOUT/HZ,
|
|
||||||
&worker->wait_for_xpd_initialization);
|
&worker->wait_for_xpd_initialization);
|
||||||
ret = wait_event_interruptible_timeout(
|
ret =
|
||||||
worker->wait_for_xpd_initialization,
|
wait_event_interruptible_timeout(worker->
|
||||||
|
wait_for_xpd_initialization,
|
||||||
xpds_done(xbus),
|
xpds_done(xbus),
|
||||||
INITIALIZATION_TIMEOUT);
|
INITIALIZATION_TIMEOUT);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
@ -1612,8 +1632,8 @@ int waitfor_xpds(xbus_t *xbus, char *buf)
|
|||||||
len += sprintf(buf, "FAILED: %s\n", xbus->busname);
|
len += sprintf(buf, "FAILED: %s\n", xbus->busname);
|
||||||
} else {
|
} else {
|
||||||
spin_lock_irqsave(&xbus->lock, flags);
|
spin_lock_irqsave(&xbus->lock, flags);
|
||||||
len += sprintf(buf, "XPDS_READY: %s: %d/%d\n",
|
len +=
|
||||||
xbus->busname,
|
sprintf(buf, "XPDS_READY: %s: %d/%d\n", xbus->busname,
|
||||||
worker->num_units_initialized, worker->num_units);
|
worker->num_units_initialized, worker->num_units);
|
||||||
spin_unlock_irqrestore(&xbus->lock, flags);
|
spin_unlock_irqrestore(&xbus->lock, flags);
|
||||||
}
|
}
|
||||||
@ -1628,21 +1648,18 @@ static int xbus_fill_proc_queue(char *p, struct xframe_queue *q)
|
|||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
len = sprintf(p,
|
len =
|
||||||
|
sprintf(p,
|
||||||
"%-15s: counts %3d, %3d, %3d worst %3d, overflows %3d worst_lag %02ld.%ld ms\n",
|
"%-15s: counts %3d, %3d, %3d worst %3d, overflows %3d worst_lag %02ld.%ld ms\n",
|
||||||
q->name,
|
q->name, q->steady_state_count, q->count, q->max_count,
|
||||||
q->steady_state_count,
|
q->worst_count, q->overflows, q->worst_lag_usec / 1000,
|
||||||
q->count,
|
|
||||||
q->max_count,
|
|
||||||
q->worst_count,
|
|
||||||
q->overflows,
|
|
||||||
q->worst_lag_usec / 1000,
|
|
||||||
q->worst_lag_usec % 1000);
|
q->worst_lag_usec % 1000);
|
||||||
xframe_queue_clearstats(q);
|
xframe_queue_clearstats(q);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int xbus_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
|
static int xbus_read_proc(char *page, char **start, off_t off, int count,
|
||||||
|
int *eof, void *data)
|
||||||
{
|
{
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
@ -1654,12 +1671,10 @@ static int xbus_read_proc(char *page, char **start, off_t off, int count, int *e
|
|||||||
goto out;
|
goto out;
|
||||||
spin_lock_irqsave(&xbus->lock, flags);
|
spin_lock_irqsave(&xbus->lock, flags);
|
||||||
|
|
||||||
len += sprintf(page + len, "%s: CONNECTOR=%s LABEL=[%s] STATUS=%s\n",
|
len +=
|
||||||
xbus->busname,
|
sprintf(page + len, "%s: CONNECTOR=%s LABEL=[%s] STATUS=%s\n",
|
||||||
xbus->connector,
|
xbus->busname, xbus->connector, xbus->label,
|
||||||
xbus->label,
|
(XBUS_FLAGS(xbus, CONNECTED)) ? "connected" : "missing");
|
||||||
(XBUS_FLAGS(xbus, CONNECTED)) ? "connected" : "missing"
|
|
||||||
);
|
|
||||||
len += xbus_fill_proc_queue(page + len, &xbus->send_pool);
|
len += xbus_fill_proc_queue(page + len, &xbus->send_pool);
|
||||||
len += xbus_fill_proc_queue(page + len, &xbus->receive_pool);
|
len += xbus_fill_proc_queue(page + len, &xbus->receive_pool);
|
||||||
len += xbus_fill_proc_queue(page + len, &xbus->command_queue);
|
len += xbus_fill_proc_queue(page + len, &xbus->command_queue);
|
||||||
@ -1671,32 +1686,41 @@ static int xbus_read_proc(char *page, char **start, off_t off, int count, int *e
|
|||||||
len += sprintf(page + len, "%5d ", xbus->cpu_rcv_intr[i]);
|
len += sprintf(page + len, "%5d ", xbus->cpu_rcv_intr[i]);
|
||||||
len += sprintf(page + len, "\ncpu_rcv_tasklet: ");
|
len += sprintf(page + len, "\ncpu_rcv_tasklet: ");
|
||||||
for_each_online_cpu(i)
|
for_each_online_cpu(i)
|
||||||
len += sprintf(page + len, "%5d ", xbus->cpu_rcv_tasklet[i]);
|
len +=
|
||||||
|
sprintf(page + len, "%5d ", xbus->cpu_rcv_tasklet[i]);
|
||||||
len += sprintf(page + len, "\n");
|
len += sprintf(page + len, "\n");
|
||||||
}
|
}
|
||||||
len += sprintf(page + len, "self_ticking: %d (last_tick at %ld)\n",
|
len +=
|
||||||
|
sprintf(page + len, "self_ticking: %d (last_tick at %ld)\n",
|
||||||
xbus->self_ticking, xbus->ticker.last_sample.tv.tv_sec);
|
xbus->self_ticking, xbus->ticker.last_sample.tv.tv_sec);
|
||||||
len += sprintf(page + len, "command_tick: %d\n", xbus->command_tick_counter);
|
len +=
|
||||||
|
sprintf(page + len, "command_tick: %d\n",
|
||||||
|
xbus->command_tick_counter);
|
||||||
len += sprintf(page + len, "usec_nosend: %d\n", xbus->usec_nosend);
|
len += sprintf(page + len, "usec_nosend: %d\n", xbus->usec_nosend);
|
||||||
len += sprintf(page + len, "xbus: pcm_rx_counter = %d, frag = %d\n",
|
len +=
|
||||||
|
sprintf(page + len, "xbus: pcm_rx_counter = %d, frag = %d\n",
|
||||||
atomic_read(&xbus->pcm_rx_counter), xbus->xbus_frag_count);
|
atomic_read(&xbus->pcm_rx_counter), xbus->xbus_frag_count);
|
||||||
len += sprintf(page + len, "max_rx_process = %2ld.%ld ms\n",
|
len +=
|
||||||
xbus->max_rx_process / 1000,
|
sprintf(page + len, "max_rx_process = %2ld.%ld ms\n",
|
||||||
xbus->max_rx_process % 1000);
|
xbus->max_rx_process / 1000, xbus->max_rx_process % 1000);
|
||||||
xbus->max_rx_process = 0;
|
xbus->max_rx_process = 0;
|
||||||
len += sprintf(page + len, "\nTRANSPORT: max_send_size=%d refcount=%d\n",
|
len +=
|
||||||
|
sprintf(page + len, "\nTRANSPORT: max_send_size=%d refcount=%d\n",
|
||||||
MAX_SEND_SIZE(xbus),
|
MAX_SEND_SIZE(xbus),
|
||||||
atomic_read(&xbus->transport.transport_refcount)
|
atomic_read(&xbus->transport.transport_refcount)
|
||||||
);
|
);
|
||||||
len += sprintf(page + len, "PCM Metrices:\n");
|
len += sprintf(page + len, "PCM Metrices:\n");
|
||||||
len += sprintf(page + len, "\tPCM TX: min=%ld max=%ld\n",
|
len +=
|
||||||
|
sprintf(page + len, "\tPCM TX: min=%ld max=%ld\n",
|
||||||
xbus->min_tx_sync, xbus->max_tx_sync);
|
xbus->min_tx_sync, xbus->max_tx_sync);
|
||||||
len += sprintf(page + len, "\tPCM RX: min=%ld max=%ld\n",
|
len +=
|
||||||
|
sprintf(page + len, "\tPCM RX: min=%ld max=%ld\n",
|
||||||
xbus->min_rx_sync, xbus->max_rx_sync);
|
xbus->min_rx_sync, xbus->max_rx_sync);
|
||||||
len += sprintf(page + len, "COUNTERS:\n");
|
len += sprintf(page + len, "COUNTERS:\n");
|
||||||
for (i = 0; i < XBUS_COUNTER_MAX; i++) {
|
for (i = 0; i < XBUS_COUNTER_MAX; i++) {
|
||||||
len += sprintf(page + len, "\t%-15s = %d\n",
|
len +=
|
||||||
xbus_counters[i].name, xbus->counters[i]);
|
sprintf(page + len, "\t%-15s = %d\n", xbus_counters[i].name,
|
||||||
|
xbus->counters[i]);
|
||||||
}
|
}
|
||||||
len += sprintf(page + len, "<-- len=%d\n", len);
|
len += sprintf(page + len, "<-- len=%d\n", len);
|
||||||
spin_unlock_irqrestore(&xbus->lock, flags);
|
spin_unlock_irqrestore(&xbus->lock, flags);
|
||||||
@ -1715,7 +1739,8 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PROTOCOL_DEBUG
|
#ifdef PROTOCOL_DEBUG
|
||||||
static int proc_xbus_command_write(struct file *file, const char __user *buffer, unsigned long count, void *data)
|
static int proc_xbus_command_write(struct file *file, const char __user *buffer,
|
||||||
|
unsigned long count, void *data)
|
||||||
{
|
{
|
||||||
char *buf;
|
char *buf;
|
||||||
xbus_t *xbus = data;
|
xbus_t *xbus = data;
|
||||||
@ -1728,7 +1753,8 @@ static int proc_xbus_command_write(struct file *file, const char __user *buffer,
|
|||||||
const size_t max_text = max_len * 3 + 10;
|
const size_t max_text = max_len * 3 + 10;
|
||||||
|
|
||||||
if (count > max_text) {
|
if (count > max_text) {
|
||||||
XBUS_ERR(xbus, "%s: line too long (%ld > %zd)\n", __func__, count, max_len);
|
XBUS_ERR(xbus, "%s: line too long (%ld > %zd)\n", __func__,
|
||||||
|
count, max_len);
|
||||||
return -EFBIG;
|
return -EFBIG;
|
||||||
}
|
}
|
||||||
/* 3 bytes per hex-digit and space */
|
/* 3 bytes per hex-digit and space */
|
||||||
@ -1756,7 +1782,8 @@ static int proc_xbus_command_write(struct file *file, const char __user *buffer,
|
|||||||
if (!(*p))
|
if (!(*p))
|
||||||
break;
|
break;
|
||||||
if (!isxdigit(*p)) {
|
if (!isxdigit(*p)) {
|
||||||
XBUS_ERR(xbus, "%s: bad hex value ASCII='0x%X' at position %ld\n",
|
XBUS_ERR(xbus,
|
||||||
|
"%s: bad hex value ASCII='0x%X' at position %ld\n",
|
||||||
__func__, *p, (long)(p - buf));
|
__func__, *p, (long)(p - buf));
|
||||||
count = -EINVAL;
|
count = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
@ -1767,13 +1794,15 @@ static int proc_xbus_command_write(struct file *file, const char __user *buffer,
|
|||||||
if (isxdigit(*p))
|
if (isxdigit(*p))
|
||||||
hexdigit[1] = *p++;
|
hexdigit[1] = *p++;
|
||||||
if (sscanf(hexdigit, "%2X", &val) != 1) {
|
if (sscanf(hexdigit, "%2X", &val) != 1) {
|
||||||
XBUS_ERR(xbus, "%s: bad hex value '%s' at position %ld\n",
|
XBUS_ERR(xbus,
|
||||||
|
"%s: bad hex value '%s' at position %ld\n",
|
||||||
__func__, hexdigit, (long)(p - buf));
|
__func__, hexdigit, (long)(p - buf));
|
||||||
count = -EINVAL;
|
count = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
*q++ = val;
|
*q++ = val;
|
||||||
XBUS_DBG(GENERAL, xbus, "%3zd> '%s' val=%d\n", q - pack_start, hexdigit, val);
|
XBUS_DBG(GENERAL, xbus, "%3zd> '%s' val=%d\n", q - pack_start,
|
||||||
|
hexdigit, val);
|
||||||
}
|
}
|
||||||
len = q - pack_start;
|
len = q - pack_start;
|
||||||
xframe = ALLOC_SEND_XFRAME(xbus);
|
xframe = ALLOC_SEND_XFRAME(xbus);
|
||||||
@ -1793,8 +1822,8 @@ out:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int read_proc_xbuses(char *page, char **start, off_t off, int count,
|
||||||
static int read_proc_xbuses(char *page, char **start, off_t off, int count, int *eof, void *data)
|
int *eof, void *data)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
int i;
|
int i;
|
||||||
@ -1803,12 +1832,12 @@ static int read_proc_xbuses(char *page, char **start, off_t off, int count, int
|
|||||||
xbus_t *xbus = get_xbus(__func__, i);
|
xbus_t *xbus = get_xbus(__func__, i);
|
||||||
|
|
||||||
if (xbus) {
|
if (xbus) {
|
||||||
len += sprintf(page + len, "%s: CONNECTOR=%s LABEL=[%s] STATUS=%s\n",
|
len +=
|
||||||
xbus->busname,
|
sprintf(page + len,
|
||||||
xbus->connector,
|
"%s: CONNECTOR=%s LABEL=[%s] STATUS=%s\n",
|
||||||
xbus->label,
|
xbus->busname, xbus->connector, xbus->label,
|
||||||
(XBUS_FLAGS(xbus, CONNECTED)) ? "connected" : "missing"
|
(XBUS_FLAGS(xbus, CONNECTED)) ? "connected"
|
||||||
);
|
: "missing");
|
||||||
put_xbus(__func__, xbus);
|
put_xbus(__func__, xbus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1828,7 +1857,9 @@ static int read_proc_xbuses(char *page, char **start, off_t off, int count, int
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void transport_init(xbus_t *xbus, struct xbus_ops *ops, ushort max_send_size, struct device *transport_device, void *priv)
|
static void transport_init(xbus_t *xbus, struct xbus_ops *ops,
|
||||||
|
ushort max_send_size,
|
||||||
|
struct device *transport_device, void *priv)
|
||||||
{
|
{
|
||||||
BUG_ON(!xbus);
|
BUG_ON(!xbus);
|
||||||
BUG_ON(!ops);
|
BUG_ON(!ops);
|
||||||
@ -1855,10 +1886,13 @@ static void transport_destroy(xbus_t *xbus)
|
|||||||
BUG_ON(!xbus);
|
BUG_ON(!xbus);
|
||||||
XBUS_DBG(DEVICES, xbus, "Waiting... (transport_refcount=%d)\n",
|
XBUS_DBG(DEVICES, xbus, "Waiting... (transport_refcount=%d)\n",
|
||||||
atomic_read(&xbus->transport.transport_refcount));
|
atomic_read(&xbus->transport.transport_refcount));
|
||||||
ret = wait_event_interruptible(xbus->transport.transport_unused,
|
ret =
|
||||||
atomic_read(&xbus->transport.transport_refcount) == 0);
|
wait_event_interruptible(xbus->transport.transport_unused,
|
||||||
|
atomic_read(&xbus->transport.
|
||||||
|
transport_refcount) == 0);
|
||||||
if (ret)
|
if (ret)
|
||||||
XBUS_ERR(xbus, "Waiting for transport_refcount interrupted!!!\n");
|
XBUS_ERR(xbus,
|
||||||
|
"Waiting for transport_refcount interrupted!!!\n");
|
||||||
xbus->transport.ops = NULL;
|
xbus->transport.ops = NULL;
|
||||||
xbus->transport.priv = NULL;
|
xbus->transport.priv = NULL;
|
||||||
}
|
}
|
||||||
@ -1909,7 +1943,9 @@ int __init xbus_core_init(void)
|
|||||||
INFO("FEATURE: with PROTOCOL_DEBUG\n");
|
INFO("FEATURE: with PROTOCOL_DEBUG\n");
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
proc_xbuses = create_proc_read_entry(PROC_XBUSES, 0444, xpp_proc_toplevel, read_proc_xbuses, NULL);
|
proc_xbuses =
|
||||||
|
create_proc_read_entry(PROC_XBUSES, 0444, xpp_proc_toplevel,
|
||||||
|
read_proc_xbuses, NULL);
|
||||||
if (!proc_xbuses) {
|
if (!proc_xbuses) {
|
||||||
ERR("Failed to create proc file %s\n", PROC_XBUSES);
|
ERR("Failed to create proc file %s\n", PROC_XBUSES);
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
@ -1925,7 +1961,6 @@ err:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void xbus_core_shutdown(void)
|
void xbus_core_shutdown(void)
|
||||||
{
|
{
|
||||||
xbus_core_cleanup();
|
xbus_core_cleanup();
|
||||||
|
@ -69,17 +69,9 @@ enum {
|
|||||||
static struct xbus_counters {
|
static struct xbus_counters {
|
||||||
char *name;
|
char *name;
|
||||||
} xbus_counters[] = {
|
} xbus_counters[] = {
|
||||||
C_(UNITS),
|
C_(UNITS), C_(TX_XFRAME_PCM), C_(RX_XFRAME_PCM), C_(TX_PACK_PCM),
|
||||||
C_(TX_XFRAME_PCM),
|
C_(RX_PACK_PCM), C_(TX_BYTES), C_(RX_BYTES),
|
||||||
C_(RX_XFRAME_PCM),
|
C_(TX_PCM_FRAG), C_(RX_CMD), C_(TX_CMD),};
|
||||||
C_(TX_PACK_PCM),
|
|
||||||
C_(RX_PACK_PCM),
|
|
||||||
C_(TX_BYTES),
|
|
||||||
C_(RX_BYTES),
|
|
||||||
C_(TX_PCM_FRAG),
|
|
||||||
C_(RX_CMD),
|
|
||||||
C_(TX_CMD),
|
|
||||||
};
|
|
||||||
|
|
||||||
#undef C_
|
#undef C_
|
||||||
|
|
||||||
@ -294,7 +286,8 @@ struct xframe {
|
|||||||
void *priv;
|
void *priv;
|
||||||
};
|
};
|
||||||
|
|
||||||
void xframe_init(xbus_t *xbus, xframe_t *xframe, void *buf, size_t maxsize, void *priv);
|
void xframe_init(xbus_t *xbus, xframe_t *xframe, void *buf, size_t maxsize,
|
||||||
|
void *priv);
|
||||||
|
|
||||||
#define XFRAME_LEN(frame) atomic_read(&(frame)->frame_len)
|
#define XFRAME_LEN(frame) atomic_read(&(frame)->frame_len)
|
||||||
|
|
||||||
@ -302,7 +295,8 @@ int xbus_core_init(void); /* Initializer */
|
|||||||
void xbus_core_shutdown(void); /* Terminator */
|
void xbus_core_shutdown(void); /* Terminator */
|
||||||
|
|
||||||
/* Frame handling */
|
/* Frame handling */
|
||||||
void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe, int debug);
|
void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe,
|
||||||
|
int debug);
|
||||||
int send_cmd_frame(xbus_t *xbus, xframe_t *xframe);
|
int send_cmd_frame(xbus_t *xbus, xframe_t *xframe);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -325,7 +319,8 @@ xpd_t *xpd_byaddr(const xbus_t *xbus, uint unit, uint subunit);
|
|||||||
int xbus_check_unique(xbus_t *xbus);
|
int xbus_check_unique(xbus_t *xbus);
|
||||||
bool xbus_setstate(xbus_t *xbus, enum xbus_state newstate);
|
bool xbus_setstate(xbus_t *xbus, enum xbus_state newstate);
|
||||||
bool xbus_setflags(xbus_t *xbus, int flagbit, bool on);
|
bool xbus_setflags(xbus_t *xbus, int flagbit, bool on);
|
||||||
xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size, struct device *transport_device, void *priv);
|
xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size,
|
||||||
|
struct device *transport_device, void *priv);
|
||||||
void xbus_free(xbus_t *xbus);
|
void xbus_free(xbus_t *xbus);
|
||||||
int xbus_connect(xbus_t *xbus);
|
int xbus_connect(xbus_t *xbus);
|
||||||
int xbus_activate(xbus_t *xbus);
|
int xbus_activate(xbus_t *xbus);
|
||||||
@ -370,4 +365,3 @@ enum kobject_action {
|
|||||||
void astribank_uevent_send(xbus_t *xbus, enum kobject_action act);
|
void astribank_uevent_send(xbus_t *xbus, enum kobject_action act);
|
||||||
|
|
||||||
#endif /* XBUS_CORE_H */
|
#endif /* XBUS_CORE_H */
|
||||||
|
|
||||||
|
@ -37,15 +37,18 @@ static const char rcsid[] = "$Id$";
|
|||||||
|
|
||||||
extern int debug;
|
extern int debug;
|
||||||
#ifdef OPTIMIZE_CHANMUTE
|
#ifdef OPTIMIZE_CHANMUTE
|
||||||
static DEF_PARM_BOOL(optimize_chanmute, 1, 0644, "Optimize by muting inactive channels");
|
static DEF_PARM_BOOL(optimize_chanmute, 1, 0644,
|
||||||
|
"Optimize by muting inactive channels");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static DEF_PARM(int, disable_pcm, 0, 0644, "Disable all PCM transmissions");
|
static DEF_PARM(int, disable_pcm, 0, 0644, "Disable all PCM transmissions");
|
||||||
#ifdef DEBUG_PCMTX
|
#ifdef DEBUG_PCMTX
|
||||||
DEF_PARM(int, pcmtx, -1, 0644, "Forced PCM value to transmit (negative to disable)");
|
DEF_PARM(int, pcmtx, -1, 0644,
|
||||||
|
"Forced PCM value to transmit (negative to disable)");
|
||||||
DEF_PARM(int, pcmtx_chan, 0, 0644, "channel to force PCM value");
|
DEF_PARM(int, pcmtx_chan, 0, 0644, "channel to force PCM value");
|
||||||
#endif
|
#endif
|
||||||
static DEF_PARM_BOOL(disable_pll_sync, 0, 0644, "Disable automatic adjustment of AB clocks");
|
static DEF_PARM_BOOL(disable_pll_sync, 0, 0644,
|
||||||
|
"Disable automatic adjustment of AB clocks");
|
||||||
|
|
||||||
static xbus_t *syncer; /* current syncer */
|
static xbus_t *syncer; /* current syncer */
|
||||||
static atomic_t xpp_tick_counter = ATOMIC_INIT(0);
|
static atomic_t xpp_tick_counter = ATOMIC_INIT(0);
|
||||||
@ -118,8 +121,8 @@ static int xpp_ticker_step(struct xpp_ticker *ticker, const struct timeval *t)
|
|||||||
spin_lock_irqsave(&ticker->lock, flags);
|
spin_lock_irqsave(&ticker->lock, flags);
|
||||||
ticker->last_sample.tv = *t;
|
ticker->last_sample.tv = *t;
|
||||||
if ((ticker->count % ticker->cycle) == ticker->cycle - 1) { /* rate adjust */
|
if ((ticker->count % ticker->cycle) == ticker->cycle - 1) { /* rate adjust */
|
||||||
usec = (long)usec_diff(
|
usec =
|
||||||
&ticker->last_sample.tv,
|
(long)usec_diff(&ticker->last_sample.tv,
|
||||||
&ticker->first_sample.tv);
|
&ticker->first_sample.tv);
|
||||||
ticker->first_sample = ticker->last_sample;
|
ticker->first_sample = ticker->last_sample;
|
||||||
ticker->tick_period = usec / ticker->cycle;
|
ticker->tick_period = usec / ticker->cycle;
|
||||||
@ -194,7 +197,8 @@ static void xpp_drift_step(xbus_t *xbus, const struct timeval *tv)
|
|||||||
* Do we need to be synchronized and is there an established reference
|
* Do we need to be synchronized and is there an established reference
|
||||||
* ticker (another Astribank or another DAHDI device) already?
|
* ticker (another Astribank or another DAHDI device) already?
|
||||||
*/
|
*/
|
||||||
if (ref_ticker && ref_ticker != &xbus->ticker && syncer && xbus->sync_mode == SYNC_MODE_PLL) {
|
if (ref_ticker && ref_ticker != &xbus->ticker && syncer
|
||||||
|
&& xbus->sync_mode == SYNC_MODE_PLL) {
|
||||||
int new_delta_tick = ticker->count - ref_ticker->count;
|
int new_delta_tick = ticker->count - ref_ticker->count;
|
||||||
int lost_ticks = new_delta_tick - di->delta_tick;
|
int lost_ticks = new_delta_tick - di->delta_tick;
|
||||||
long usec_delta;
|
long usec_delta;
|
||||||
@ -224,22 +228,26 @@ static void xpp_drift_step(xbus_t *xbus, const struct timeval *tv)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Sample a delta */
|
/* Sample a delta */
|
||||||
usec_delta = (long)usec_diff(
|
usec_delta =
|
||||||
&ticker->last_sample.tv,
|
(long)usec_diff(&ticker->last_sample.tv,
|
||||||
&ref_ticker->last_sample.tv);
|
&ref_ticker->last_sample.tv);
|
||||||
sample_tick(xbus, usec_delta);
|
sample_tick(xbus, usec_delta);
|
||||||
if ((ticker->count % SYNC_CYCLE) > (SYNC_CYCLE - SYNC_CYCLE_SAMPLE))
|
if ((ticker->count % SYNC_CYCLE) >
|
||||||
|
(SYNC_CYCLE - SYNC_CYCLE_SAMPLE))
|
||||||
di->delta_sum += usec_delta;
|
di->delta_sum += usec_delta;
|
||||||
|
|
||||||
if ((ticker->count % SYNC_CYCLE) == 0) {
|
if ((ticker->count % SYNC_CYCLE) == 0) {
|
||||||
/*
|
/*
|
||||||
* Full sampling cycle passed. Let's calculate
|
* Full sampling cycle passed. Let's calculate
|
||||||
*/
|
*/
|
||||||
int offset = di->delta_sum / SYNC_CYCLE_SAMPLE - SYNC_CENTER;
|
int offset =
|
||||||
|
di->delta_sum / SYNC_CYCLE_SAMPLE -
|
||||||
|
SYNC_CENTER;
|
||||||
int offset_prev = di->offset_prev;
|
int offset_prev = di->offset_prev;
|
||||||
int speed = xbus->sync_adjustment;
|
int speed = xbus->sync_adjustment;
|
||||||
int fix = 0;
|
int fix = 0;
|
||||||
int best_speed = (di->max_speed + di->min_speed) >> 1;
|
int best_speed =
|
||||||
|
(di->max_speed + di->min_speed) >> 1;
|
||||||
|
|
||||||
if (offset > 0 && offset < SYNC_DELTA) {
|
if (offset > 0 && offset < SYNC_DELTA) {
|
||||||
speed = best_speed - 1;
|
speed = best_speed - 1;
|
||||||
@ -268,16 +276,22 @@ static void xpp_drift_step(xbus_t *xbus, const struct timeval *tv)
|
|||||||
if (offset < di->offset_min)
|
if (offset < di->offset_min)
|
||||||
di->offset_min = offset;
|
di->offset_min = offset;
|
||||||
|
|
||||||
XBUS_DBG(SYNC, xbus, "offset: %d, min_speed=%d, max_speed=%d, usec_delta(last)=%ld\n",
|
XBUS_DBG(SYNC, xbus,
|
||||||
offset_prev, di->min_speed, di->max_speed, usec_delta);
|
"offset: %d, min_speed=%d, max_speed=%d, usec_delta(last)=%ld\n",
|
||||||
XBUS_DBG(SYNC, xbus, "ADJ: speed=%d (best_speed=%d) fix=%d\n",
|
offset_prev, di->min_speed,
|
||||||
|
di->max_speed, usec_delta);
|
||||||
|
XBUS_DBG(SYNC, xbus,
|
||||||
|
"ADJ: speed=%d (best_speed=%d) fix=%d\n",
|
||||||
speed, best_speed, fix);
|
speed, best_speed, fix);
|
||||||
xbus->sync_adjustment_offset = speed;
|
xbus->sync_adjustment_offset = speed;
|
||||||
if (xbus != syncer && xbus->sync_adjustment != speed)
|
if (xbus != syncer
|
||||||
|
&& xbus->sync_adjustment != speed)
|
||||||
send_drift(xbus, speed);
|
send_drift(xbus, speed);
|
||||||
di->sync_inaccuracy = abs(offset) + abs(di->offset_range) / 2;
|
di->sync_inaccuracy =
|
||||||
|
abs(offset) + abs(di->offset_range) / 2;
|
||||||
if (ticker->count >= SYNC_CYCLE * SYNC_CONVERGE) {
|
if (ticker->count >= SYNC_CYCLE * SYNC_CONVERGE) {
|
||||||
di->offset_range = di->offset_max - di->offset_min;
|
di->offset_range =
|
||||||
|
di->offset_max - di->offset_min;
|
||||||
di->offset_min = INT_MAX;
|
di->offset_min = INT_MAX;
|
||||||
di->offset_max = -INT_MAX;
|
di->offset_max = -INT_MAX;
|
||||||
if (di->max_speed > best_speed)
|
if (di->max_speed > best_speed)
|
||||||
@ -379,7 +393,8 @@ void got_new_syncer(xbus_t *xbus, enum sync_mode mode, int drift)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
XBUS_DBG(SYNC, xbus, "Mode %s (%d), drift=%d (pcm_rx_counter=%d)\n",
|
XBUS_DBG(SYNC, xbus, "Mode %s (%d), drift=%d (pcm_rx_counter=%d)\n",
|
||||||
sync_mode_name(mode), mode, drift, atomic_read(&xbus->pcm_rx_counter));
|
sync_mode_name(mode), mode, drift,
|
||||||
|
atomic_read(&xbus->pcm_rx_counter));
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case SYNC_MODE_AB:
|
case SYNC_MODE_AB:
|
||||||
xbus->sync_mode = mode;
|
xbus->sync_mode = mode;
|
||||||
@ -456,7 +471,8 @@ static void reset_sync_counters(void)
|
|||||||
"Dropped packet. Is shutting down.\n");
|
"Dropped packet. Is shutting down.\n");
|
||||||
} else {
|
} else {
|
||||||
/* Reset sync LEDs once in a while */
|
/* Reset sync LEDs once in a while */
|
||||||
CALL_PROTO(GLOBAL, RESET_SYNC_COUNTERS, xbus, NULL);
|
CALL_PROTO(GLOBAL, RESET_SYNC_COUNTERS, xbus,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
put_xbus(__func__, xbus);
|
put_xbus(__func__, xbus);
|
||||||
@ -474,11 +490,13 @@ static void send_drift(xbus_t *xbus, int drift)
|
|||||||
msg = "up";
|
msg = "up";
|
||||||
else
|
else
|
||||||
msg = "down";
|
msg = "down";
|
||||||
XBUS_DBG(SYNC, xbus, "%sDRIFT adjust %s (%d) (last update %ld seconds ago)\n",
|
XBUS_DBG(SYNC, xbus,
|
||||||
(disable_pll_sync) ? "Fake " : "",
|
"%sDRIFT adjust %s (%d) (last update %ld seconds ago)\n",
|
||||||
msg, drift, now.tv_sec - xbus->pll_updated_at);
|
(disable_pll_sync) ? "Fake " : "", msg, drift,
|
||||||
|
now.tv_sec - xbus->pll_updated_at);
|
||||||
if (!disable_pll_sync)
|
if (!disable_pll_sync)
|
||||||
CALL_PROTO(GLOBAL, SYNC_SOURCE, xbus, NULL, SYNC_MODE_PLL, drift);
|
CALL_PROTO(GLOBAL, SYNC_SOURCE, xbus, NULL, SYNC_MODE_PLL,
|
||||||
|
drift);
|
||||||
xbus->pll_updated_at = now.tv_sec;
|
xbus->pll_updated_at = now.tv_sec;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -512,7 +530,8 @@ void dahdi_sync_tick(struct dahdi_span *span, int is_master)
|
|||||||
static int rate_limit;
|
static int rate_limit;
|
||||||
|
|
||||||
if ((rate_limit++ % 10003) == 0)
|
if ((rate_limit++ % 10003) == 0)
|
||||||
XPD_NOTICE(xpd, "Is a DAHDI sync master: ignore sync from DAHDI\n");
|
XPD_NOTICE(xpd,
|
||||||
|
"Is a DAHDI sync master: ignore sync from DAHDI\n");
|
||||||
goto noop;
|
goto noop;
|
||||||
}
|
}
|
||||||
/* Now we know for sure someone else is dahdi sync master */
|
/* Now we know for sure someone else is dahdi sync master */
|
||||||
@ -556,8 +575,7 @@ static void update_sync_master(xbus_t *new_syncer, bool force_dahdi)
|
|||||||
WARN_ON(new_syncer && force_dahdi); /* Ambigous */
|
WARN_ON(new_syncer && force_dahdi); /* Ambigous */
|
||||||
force_dahdi_sync = force_dahdi;
|
force_dahdi_sync = force_dahdi;
|
||||||
msg = (force_dahdi_sync) ? "DAHDI" : "NO-SYNC";
|
msg = (force_dahdi_sync) ? "DAHDI" : "NO-SYNC";
|
||||||
DBG(SYNC, "%s => %s\n",
|
DBG(SYNC, "%s => %s\n", (syncer) ? syncer->busname : msg,
|
||||||
(syncer) ? syncer->busname : msg,
|
|
||||||
(new_syncer) ? new_syncer->busname : msg);
|
(new_syncer) ? new_syncer->busname : msg);
|
||||||
/*
|
/*
|
||||||
* This global locking protects:
|
* This global locking protects:
|
||||||
@ -598,7 +616,8 @@ static void update_sync_master(xbus_t *new_syncer, bool force_dahdi)
|
|||||||
xbus_request_sync(xbus,
|
xbus_request_sync(xbus,
|
||||||
xbus->sync_mode_default);
|
xbus->sync_mode_default);
|
||||||
else
|
else
|
||||||
XBUS_DBG(SYNC, xbus, "Not self_ticking yet. Ignore\n");
|
XBUS_DBG(SYNC, xbus,
|
||||||
|
"Not self_ticking yet. Ignore\n");
|
||||||
}
|
}
|
||||||
put_xbus(__func__, xbus);
|
put_xbus(__func__, xbus);
|
||||||
}
|
}
|
||||||
@ -628,9 +647,12 @@ void elect_syncer(const char *msg)
|
|||||||
xpd_t *xpd = xpd_of(xbus, j);
|
xpd_t *xpd = xpd_of(xbus, j);
|
||||||
int prio;
|
int prio;
|
||||||
|
|
||||||
if (!xpd || !xpd->card_present || !IS_PHONEDEV(xpd))
|
if (!xpd || !xpd->card_present
|
||||||
|
|| !IS_PHONEDEV(xpd))
|
||||||
continue;
|
continue;
|
||||||
prio = CALL_PHONE_METHOD(card_timing_priority, xpd);
|
prio =
|
||||||
|
CALL_PHONE_METHOD(card_timing_priority,
|
||||||
|
xpd);
|
||||||
if (prio < 0) {
|
if (prio < 0) {
|
||||||
DBG(SYNC, "%s/%s: skip sync\n",
|
DBG(SYNC, "%s/%s: skip sync\n",
|
||||||
xbus->busname, xpd->xpdname);
|
xbus->busname, xpd->xpdname);
|
||||||
@ -646,7 +668,8 @@ void elect_syncer(const char *msg)
|
|||||||
}
|
}
|
||||||
if (best_xpd) {
|
if (best_xpd) {
|
||||||
the_xbus = best_xpd->xbus;
|
the_xbus = best_xpd->xbus;
|
||||||
XPD_DBG(SYNC, best_xpd, "%s: elected with priority %d\n", msg, timing_priority);
|
XPD_DBG(SYNC, best_xpd, "%s: elected with priority %d\n", msg,
|
||||||
|
timing_priority);
|
||||||
} else if (the_xbus) {
|
} else if (the_xbus) {
|
||||||
XBUS_DBG(SYNC, the_xbus, "%s: elected\n", msg);
|
XBUS_DBG(SYNC, the_xbus, "%s: elected\n", msg);
|
||||||
} else {
|
} else {
|
||||||
@ -705,8 +728,8 @@ void generic_card_pcm_recompute(xpd_t *xpd, xpp_line_t pcm_mask)
|
|||||||
line_count = 1;
|
line_count = 1;
|
||||||
}
|
}
|
||||||
pcm_len = (line_count)
|
pcm_len = (line_count)
|
||||||
? RPACKET_HEADERSIZE + sizeof(xpp_line_t) + line_count * DAHDI_CHUNKSIZE
|
? RPACKET_HEADERSIZE + sizeof(xpp_line_t) +
|
||||||
: 0L;
|
line_count * DAHDI_CHUNKSIZE : 0L;
|
||||||
update_wanted_pcm_mask(xpd, pcm_mask, pcm_len);
|
update_wanted_pcm_mask(xpd, pcm_mask, pcm_len);
|
||||||
spin_unlock_irqrestore(&PHONEDEV(xpd).lock_recompute_pcm, flags);
|
spin_unlock_irqrestore(&PHONEDEV(xpd).lock_recompute_pcm, flags);
|
||||||
}
|
}
|
||||||
@ -748,9 +771,12 @@ static void do_ec(xpd_t *xpd)
|
|||||||
continue;
|
continue;
|
||||||
if (!IS_SET(PHONEDEV(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;
|
continue;
|
||||||
dahdi_ec_chunk(chan, chan->readchunk, PHONEDEV(xpd).ec_chunk2[i]);
|
dahdi_ec_chunk(chan, chan->readchunk,
|
||||||
memcpy(PHONEDEV(xpd).ec_chunk2[i], PHONEDEV(xpd).ec_chunk1[i], DAHDI_CHUNKSIZE);
|
PHONEDEV(xpd).ec_chunk2[i]);
|
||||||
memcpy(PHONEDEV(xpd).ec_chunk1[i], chan->writechunk, DAHDI_CHUNKSIZE);
|
memcpy(PHONEDEV(xpd).ec_chunk2[i], PHONEDEV(xpd).ec_chunk1[i],
|
||||||
|
DAHDI_CHUNKSIZE);
|
||||||
|
memcpy(PHONEDEV(xpd).ec_chunk1[i], chan->writechunk,
|
||||||
|
DAHDI_CHUNKSIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -799,7 +825,8 @@ static bool pcm_valid(xpd_t *xpd, xpacket_t *pack)
|
|||||||
|
|
||||||
XPD_COUNTER(xpd, RECV_ERRORS)++;
|
XPD_COUNTER(xpd, RECV_ERRORS)++;
|
||||||
if ((rate_limit++ % 1000) <= 10) {
|
if ((rate_limit++ % 1000) <= 10) {
|
||||||
XPD_ERR(xpd, "BAD PCM REPLY: packet_len=%d (should be %d), count=%d\n",
|
XPD_ERR(xpd,
|
||||||
|
"BAD PCM REPLY: packet_len=%d (should be %d), count=%d\n",
|
||||||
XPACKET_LEN(pack), good_len, count);
|
XPACKET_LEN(pack), good_len, count);
|
||||||
dump_packet("BAD PCM REPLY", pack, 1);
|
dump_packet("BAD PCM REPLY", pack, 1);
|
||||||
}
|
}
|
||||||
@ -808,8 +835,6 @@ static bool pcm_valid(xpd_t *xpd, xpacket_t *pack)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static inline void pcm_frame_out(xbus_t *xbus, xframe_t *xframe)
|
static inline void pcm_frame_out(xbus_t *xbus, xframe_t *xframe)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
@ -824,12 +849,14 @@ static inline void pcm_frame_out(xbus_t *xbus, xframe_t *xframe)
|
|||||||
usec = usec_diff(&now, &xbus->last_tx_sync);
|
usec = usec_diff(&now, &xbus->last_tx_sync);
|
||||||
xbus->last_tx_sync = now;
|
xbus->last_tx_sync = now;
|
||||||
/* ignore startup statistics */
|
/* ignore startup statistics */
|
||||||
if (likely(atomic_read(&xbus->pcm_rx_counter) > BIG_TICK_INTERVAL)) {
|
if (likely
|
||||||
|
(atomic_read(&xbus->pcm_rx_counter) > BIG_TICK_INTERVAL)) {
|
||||||
if (abs(usec - 1000) > TICK_TOLERANCE) {
|
if (abs(usec - 1000) > TICK_TOLERANCE) {
|
||||||
static int rate_limit;
|
static int rate_limit;
|
||||||
|
|
||||||
if ((rate_limit++ % 5003) == 0)
|
if ((rate_limit++ % 5003) == 0)
|
||||||
XBUS_DBG(SYNC, xbus, "Bad PCM TX timing(%d): usec=%ld.\n",
|
XBUS_DBG(SYNC, xbus,
|
||||||
|
"Bad PCM TX timing(%d): usec=%ld.\n",
|
||||||
rate_limit, usec);
|
rate_limit, usec);
|
||||||
}
|
}
|
||||||
if (usec > xbus->max_tx_sync)
|
if (usec > xbus->max_tx_sync)
|
||||||
@ -876,10 +903,12 @@ void generic_card_pcm_fromspan(xpd_t *xpd, xpacket_t *pack)
|
|||||||
int channo = chan->channo;
|
int channo = chan->channo;
|
||||||
|
|
||||||
if (pcmtx >= 0 && pcmtx_chan == channo)
|
if (pcmtx >= 0 && pcmtx_chan == channo)
|
||||||
memset((u_char *)pcm, pcmtx, DAHDI_CHUNKSIZE);
|
memset((u_char *)pcm, pcmtx,
|
||||||
|
DAHDI_CHUNKSIZE);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
memcpy((u_char *)pcm, chan->writechunk, DAHDI_CHUNKSIZE);
|
memcpy((u_char *)pcm, chan->writechunk,
|
||||||
|
DAHDI_CHUNKSIZE);
|
||||||
} else
|
} else
|
||||||
memset((u_char *)pcm, 0x7F, DAHDI_CHUNKSIZE);
|
memset((u_char *)pcm, 0x7F, DAHDI_CHUNKSIZE);
|
||||||
pcm += DAHDI_CHUNKSIZE;
|
pcm += DAHDI_CHUNKSIZE;
|
||||||
@ -915,7 +944,10 @@ void generic_card_pcm_tospan(xpd_t *xpd, xpacket_t *pack)
|
|||||||
/* We have and want real data */
|
/* We have and want real data */
|
||||||
// memset((u_char *)r, 0x5A, DAHDI_CHUNKSIZE); // DEBUG
|
// memset((u_char *)r, 0x5A, DAHDI_CHUNKSIZE); // DEBUG
|
||||||
memcpy((u_char *)r, pcm, DAHDI_CHUNKSIZE);
|
memcpy((u_char *)r, pcm, DAHDI_CHUNKSIZE);
|
||||||
} else if (IS_SET(PHONEDEV(xpd).wanted_pcm_mask | PHONEDEV(xpd).silence_pcm, i)) {
|
} else
|
||||||
|
if (IS_SET
|
||||||
|
(PHONEDEV(xpd).wanted_pcm_mask | PHONEDEV(xpd).
|
||||||
|
silence_pcm, i)) {
|
||||||
/* Inject SILENCE */
|
/* Inject SILENCE */
|
||||||
memset((u_char *)r, 0x7F, DAHDI_CHUNKSIZE);
|
memset((u_char *)r, 0x7F, DAHDI_CHUNKSIZE);
|
||||||
if (IS_SET(PHONEDEV(xpd).silence_pcm, i)) {
|
if (IS_SET(PHONEDEV(xpd).silence_pcm, i)) {
|
||||||
@ -923,8 +955,10 @@ void generic_card_pcm_tospan(xpd_t *xpd, xpacket_t *pack)
|
|||||||
* This will clear the EC buffers until next tick
|
* This will clear the EC buffers until next tick
|
||||||
* So we don't have noise residues from the past.
|
* So we don't have noise residues from the past.
|
||||||
*/
|
*/
|
||||||
memset(PHONEDEV(xpd).ec_chunk2[i], 0x7F, DAHDI_CHUNKSIZE);
|
memset(PHONEDEV(xpd).ec_chunk2[i], 0x7F,
|
||||||
memset(PHONEDEV(xpd).ec_chunk1[i], 0x7F, DAHDI_CHUNKSIZE);
|
DAHDI_CHUNKSIZE);
|
||||||
|
memset(PHONEDEV(xpd).ec_chunk1[i], 0x7F,
|
||||||
|
DAHDI_CHUNKSIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (got_data)
|
if (got_data)
|
||||||
@ -939,6 +973,7 @@ int generic_echocancel_timeslot(xpd_t *xpd, int pos)
|
|||||||
{
|
{
|
||||||
return xpd->addr.unit * 32 + pos;
|
return xpd->addr.unit * 32 + pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(generic_echocancel_timeslot);
|
EXPORT_SYMBOL(generic_echocancel_timeslot);
|
||||||
|
|
||||||
int generic_echocancel_setmask(xpd_t *xpd, xpp_line_t ec_mask)
|
int generic_echocancel_setmask(xpd_t *xpd, xpp_line_t ec_mask)
|
||||||
@ -959,6 +994,7 @@ int generic_echocancel_setmask(xpd_t *xpd, xpp_line_t ec_mask)
|
|||||||
CALL_EC_METHOD(ec_update, xpd->xbus, xpd->xbus);
|
CALL_EC_METHOD(ec_update, xpd->xbus, xpd->xbus);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(generic_echocancel_setmask);
|
EXPORT_SYMBOL(generic_echocancel_setmask);
|
||||||
|
|
||||||
static int copy_pcm_tospan(xbus_t *xbus, xframe_t *xframe)
|
static int copy_pcm_tospan(xbus_t *xbus, xframe_t *xframe)
|
||||||
@ -988,7 +1024,8 @@ static int copy_pcm_tospan(xbus_t *xbus, xframe_t *xframe)
|
|||||||
XBUS_NOTICE(xbus,
|
XBUS_NOTICE(xbus,
|
||||||
"%s: Non-PCM packet within a PCM xframe. (%d)\n",
|
"%s: Non-PCM packet within a PCM xframe. (%d)\n",
|
||||||
__func__, rate_limit);
|
__func__, rate_limit);
|
||||||
dump_xframe("In PCM xframe", xbus, xframe, debug);
|
dump_xframe("In PCM xframe", xbus, xframe,
|
||||||
|
debug);
|
||||||
}
|
}
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -1004,13 +1041,18 @@ static int copy_pcm_tospan(xbus_t *xbus, xframe_t *xframe)
|
|||||||
}
|
}
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
xpd = xpd_byaddr(xbus, XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack));
|
xpd =
|
||||||
|
xpd_byaddr(xbus, XPACKET_ADDR_UNIT(pack),
|
||||||
|
XPACKET_ADDR_SUBUNIT(pack));
|
||||||
if (unlikely(!xpd)) {
|
if (unlikely(!xpd)) {
|
||||||
static int rate_limit;
|
static int rate_limit;
|
||||||
|
|
||||||
if ((rate_limit++ % 1003) == 0) {
|
if ((rate_limit++ % 1003) == 0) {
|
||||||
notify_bad_xpd(__func__, xbus, XPACKET_ADDR(pack), "RECEIVE PCM");
|
notify_bad_xpd(__func__, xbus,
|
||||||
dump_xframe("Unknown XPD addr", xbus, xframe, debug);
|
XPACKET_ADDR(pack),
|
||||||
|
"RECEIVE PCM");
|
||||||
|
dump_xframe("Unknown XPD addr", xbus, xframe,
|
||||||
|
debug);
|
||||||
}
|
}
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -1083,23 +1125,28 @@ static void xbus_tick(xbus_t *xbus)
|
|||||||
if (xframe && !pack) { /* FULL frame */
|
if (xframe && !pack) { /* FULL frame */
|
||||||
pcm_frame_out(xbus, xframe);
|
pcm_frame_out(xbus, xframe);
|
||||||
xframe = NULL;
|
xframe = NULL;
|
||||||
XBUS_COUNTER(xbus, TX_PCM_FRAG)++;
|
XBUS_COUNTER(xbus,
|
||||||
|
TX_PCM_FRAG)++;
|
||||||
}
|
}
|
||||||
if (!xframe) { /* Alloc frame */
|
if (!xframe) { /* Alloc frame */
|
||||||
xframe = ALLOC_SEND_XFRAME(xbus);
|
xframe =
|
||||||
|
ALLOC_SEND_XFRAME(xbus);
|
||||||
if (!xframe) {
|
if (!xframe) {
|
||||||
static int rate_limit;
|
static int rate_limit;
|
||||||
|
|
||||||
if ((rate_limit++ % 3001) == 0)
|
if ((rate_limit++ %
|
||||||
|
3001) == 0)
|
||||||
XBUS_ERR(xbus,
|
XBUS_ERR(xbus,
|
||||||
"%s: failed to allocate new xframe\n",
|
"%s: failed to allocate new xframe\n",
|
||||||
__func__);
|
__func__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pack = xframe_next_packet(xframe, pcm_len);
|
pack =
|
||||||
|
xframe_next_packet(xframe, pcm_len);
|
||||||
} while (!pack);
|
} while (!pack);
|
||||||
XPACKET_INIT(pack, GLOBAL, PCM_WRITE, xpd->xbus_idx, 1, 0);
|
XPACKET_INIT(pack, GLOBAL, PCM_WRITE,
|
||||||
|
xpd->xbus_idx, 1, 0);
|
||||||
XPACKET_LEN(pack) = pcm_len;
|
XPACKET_LEN(pack) = pcm_len;
|
||||||
if (!sent_sync_bit) {
|
if (!sent_sync_bit) {
|
||||||
XPACKET_ADDR_SYNC(pack) = 1;
|
XPACKET_ADDR_SYNC(pack) = 1;
|
||||||
@ -1125,12 +1172,15 @@ static void xbus_tick(xbus_t *xbus)
|
|||||||
usec = usec_diff(&now, &xbus->last_rx_sync);
|
usec = usec_diff(&now, &xbus->last_rx_sync);
|
||||||
xbus->last_rx_sync = now;
|
xbus->last_rx_sync = now;
|
||||||
/* ignore startup statistics */
|
/* ignore startup statistics */
|
||||||
if (likely(atomic_read(&xbus->pcm_rx_counter) > BIG_TICK_INTERVAL)) {
|
if (likely
|
||||||
|
(atomic_read(&xbus->pcm_rx_counter) >
|
||||||
|
BIG_TICK_INTERVAL)) {
|
||||||
if (abs(usec - 1000) > TICK_TOLERANCE) {
|
if (abs(usec - 1000) > TICK_TOLERANCE) {
|
||||||
static int rate_limit;
|
static int rate_limit;
|
||||||
|
|
||||||
if ((rate_limit++ % 5003) == 0)
|
if ((rate_limit++ % 5003) == 0)
|
||||||
XBUS_DBG(SYNC, xbus, "Bad PCM RX timing(%d): usec=%ld.\n",
|
XBUS_DBG(SYNC, xbus,
|
||||||
|
"Bad PCM RX timing(%d): usec=%ld.\n",
|
||||||
rate_limit, usec);
|
rate_limit, usec);
|
||||||
}
|
}
|
||||||
if (usec > xbus->max_rx_sync)
|
if (usec > xbus->max_rx_sync)
|
||||||
@ -1238,7 +1288,8 @@ int fill_sync_string(char *buf, size_t count)
|
|||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
if (!syncer) {
|
if (!syncer) {
|
||||||
len += snprintf(buf, count, "%s\n",
|
len +=
|
||||||
|
snprintf(buf, count, "%s\n",
|
||||||
(force_dahdi_sync) ? "DAHDI" : "NO-SYNC");
|
(force_dahdi_sync) ? "DAHDI" : "NO-SYNC");
|
||||||
} else
|
} else
|
||||||
len += snprintf(buf, count, "SYNC=%02d\n", syncer->num);
|
len += snprintf(buf, count, "SYNC=%02d\n", syncer->num);
|
||||||
@ -1267,7 +1318,6 @@ void xbus_pcm_shutdown(void)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EXPORT_SYMBOL(xbus_request_sync);
|
EXPORT_SYMBOL(xbus_request_sync);
|
||||||
EXPORT_SYMBOL(got_new_syncer);
|
EXPORT_SYMBOL(got_new_syncer);
|
||||||
EXPORT_SYMBOL(elect_syncer);
|
EXPORT_SYMBOL(elect_syncer);
|
||||||
@ -1283,4 +1333,3 @@ EXPORT_SYMBOL(generic_timing_priority);
|
|||||||
EXPORT_SYMBOL(pcmtx);
|
EXPORT_SYMBOL(pcmtx);
|
||||||
EXPORT_SYMBOL(pcmtx_chan);
|
EXPORT_SYMBOL(pcmtx_chan);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -88,7 +88,8 @@ struct xpp_drift {
|
|||||||
|
|
||||||
void xpp_drift_init(xbus_t *xbus);
|
void xpp_drift_init(xbus_t *xbus);
|
||||||
|
|
||||||
static inline long usec_diff(const struct timeval *tv1, const struct timeval *tv2)
|
static inline long usec_diff(const struct timeval *tv1,
|
||||||
|
const struct timeval *tv2)
|
||||||
{
|
{
|
||||||
long diff_sec;
|
long diff_sec;
|
||||||
long diff_usec;
|
long diff_usec;
|
||||||
@ -98,7 +99,6 @@ static inline long usec_diff(const struct timeval *tv1, const struct timeval *tv
|
|||||||
return diff_sec * 1000000 + diff_usec;
|
return diff_sec * 1000000 + diff_usec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int xbus_pcm_init(void *top);
|
int xbus_pcm_init(void *top);
|
||||||
void xbus_pcm_shutdown(void);
|
void xbus_pcm_shutdown(void);
|
||||||
int send_pcm_frame(xbus_t *xbus, xframe_t *xframe);
|
int send_pcm_frame(xbus_t *xbus, xframe_t *xframe);
|
||||||
@ -133,4 +133,3 @@ extern int pcmtx_chan;
|
|||||||
#endif /* __KERNEL__ */
|
#endif /* __KERNEL__ */
|
||||||
|
|
||||||
#endif /* XBUS_PCM_H */
|
#endif /* XBUS_PCM_H */
|
||||||
|
|
||||||
|
@ -52,7 +52,8 @@ static ssize_t sync_show(struct device_driver *driver, char *buf)
|
|||||||
return fill_sync_string(buf, PAGE_SIZE);
|
return fill_sync_string(buf, PAGE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t sync_store(struct device_driver *driver, const char *buf, size_t count)
|
static ssize_t sync_store(struct device_driver *driver, const char *buf,
|
||||||
|
size_t count)
|
||||||
{
|
{
|
||||||
/* DBG(SYNC, "%s\n", buf); */
|
/* DBG(SYNC, "%s\n", buf); */
|
||||||
return exec_sync_command(buf, count);
|
return exec_sync_command(buf, count);
|
||||||
@ -71,8 +72,7 @@ static DEVICE_ATTR_READER(xbus_state_show, dev, buf)
|
|||||||
|
|
||||||
xbus = dev_to_xbus(dev);
|
xbus = dev_to_xbus(dev);
|
||||||
ret = XBUS_STATE(xbus);
|
ret = XBUS_STATE(xbus);
|
||||||
ret = snprintf(buf, PAGE_SIZE, "%s (%d)\n",
|
ret = snprintf(buf, PAGE_SIZE, "%s (%d)\n", xbus_statename(ret), ret);
|
||||||
xbus_statename(ret), ret);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,9 +87,9 @@ static DEVICE_ATTR_WRITER(xbus_state_store, dev, buf, count)
|
|||||||
else if (XBUS_IS(xbus, IDLE) && strncmp(buf, "start", 5) == 0)
|
else if (XBUS_IS(xbus, IDLE) && strncmp(buf, "start", 5) == 0)
|
||||||
xbus_activate(xbus);
|
xbus_activate(xbus);
|
||||||
else {
|
else {
|
||||||
XBUS_NOTICE(xbus, "%s: Illegal action %s in state %s. Ignored.\n",
|
XBUS_NOTICE(xbus,
|
||||||
__func__, buf,
|
"%s: Illegal action %s in state %s. Ignored.\n",
|
||||||
xbus_statename(XBUS_STATE(xbus)));
|
__func__, buf, xbus_statename(XBUS_STATE(xbus)));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
@ -101,7 +101,9 @@ static DEVICE_ATTR_READER(status_show, dev, buf)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
xbus = dev_to_xbus(dev);
|
xbus = dev_to_xbus(dev);
|
||||||
ret = snprintf(buf, PAGE_SIZE, "%s\n", (XBUS_FLAGS(xbus, CONNECTED))?"connected":"missing");
|
ret =
|
||||||
|
snprintf(buf, PAGE_SIZE, "%s\n",
|
||||||
|
(XBUS_FLAGS(xbus, CONNECTED)) ? "connected" : "missing");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,16 +117,19 @@ static DEVICE_ATTR_READER(timing_show, dev, buf)
|
|||||||
do_gettimeofday(&now);
|
do_gettimeofday(&now);
|
||||||
xbus = dev_to_xbus(dev);
|
xbus = dev_to_xbus(dev);
|
||||||
driftinfo = &xbus->drift;
|
driftinfo = &xbus->drift;
|
||||||
len += snprintf(buf + len, PAGE_SIZE - len, "%-3s", sync_mode_name(xbus->sync_mode));
|
len +=
|
||||||
|
snprintf(buf + len, PAGE_SIZE - len, "%-3s",
|
||||||
|
sync_mode_name(xbus->sync_mode));
|
||||||
if (xbus->sync_mode == SYNC_MODE_PLL) {
|
if (xbus->sync_mode == SYNC_MODE_PLL) {
|
||||||
len += snprintf(buf + len, PAGE_SIZE - len,
|
len +=
|
||||||
" %5d: lost (%4d,%4d) : ",
|
snprintf(buf + len, PAGE_SIZE - len,
|
||||||
xbus->ticker.cycle,
|
" %5d: lost (%4d,%4d) : ", xbus->ticker.cycle,
|
||||||
driftinfo->lost_ticks, driftinfo->lost_tick_count);
|
driftinfo->lost_ticks, driftinfo->lost_tick_count);
|
||||||
len += snprintf(buf + len, PAGE_SIZE - len,
|
len +=
|
||||||
"DRIFT %3d %ld sec ago",
|
snprintf(buf + len, PAGE_SIZE - len,
|
||||||
xbus->sync_adjustment,
|
"DRIFT %3d %ld sec ago", xbus->sync_adjustment,
|
||||||
(xbus->pll_updated_at == 0) ? 0 : now.tv_sec - xbus->pll_updated_at);
|
(xbus->pll_updated_at ==
|
||||||
|
0) ? 0 : now.tv_sec - xbus->pll_updated_at);
|
||||||
}
|
}
|
||||||
len += snprintf(buf + len, PAGE_SIZE - len, "\n");
|
len += snprintf(buf + len, PAGE_SIZE - len, "\n");
|
||||||
return len;
|
return len;
|
||||||
@ -151,7 +156,9 @@ static DEVICE_ATTR_READER(samples_show, dev, buf)
|
|||||||
for (i = 0; i < SAMPLE_SIZE; i++) {
|
for (i = 0; i < SAMPLE_SIZE; i++) {
|
||||||
if (len > PAGE_SIZE - 20)
|
if (len > PAGE_SIZE - 20)
|
||||||
break;
|
break;
|
||||||
len += snprintf(buf + len, PAGE_SIZE - len, "%d\n", xbus->sample_ticks[i]);
|
len +=
|
||||||
|
snprintf(buf + len, PAGE_SIZE - len, "%d\n",
|
||||||
|
xbus->sample_ticks[i]);
|
||||||
}
|
}
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
@ -239,25 +246,38 @@ static DEVICE_ATTR_READER(driftinfo_show, dev, buf)
|
|||||||
hours = minutes / 60;
|
hours = minutes / 60;
|
||||||
minutes = minutes % 60;
|
minutes = minutes % 60;
|
||||||
#define SHOW(ptr,item) len += snprintf(buf + len, PAGE_SIZE - len, "%-15s: %8d\n", #item, (ptr)->item)
|
#define SHOW(ptr,item) len += snprintf(buf + len, PAGE_SIZE - len, "%-15s: %8d\n", #item, (ptr)->item)
|
||||||
len += snprintf(buf + len, PAGE_SIZE - len, "%-15s: %8d (was %d:%02d:%02d ago)\n",
|
len +=
|
||||||
"lost_ticks", di->lost_ticks, hours, minutes, seconds);
|
snprintf(buf + len, PAGE_SIZE - len,
|
||||||
|
"%-15s: %8d (was %d:%02d:%02d ago)\n", "lost_ticks",
|
||||||
|
di->lost_ticks, hours, minutes, seconds);
|
||||||
speed_range = abs(di->max_speed - di->min_speed);
|
speed_range = abs(di->max_speed - di->min_speed);
|
||||||
uframes_inaccuracy = di->sync_inaccuracy / 125;
|
uframes_inaccuracy = di->sync_inaccuracy / 125;
|
||||||
len += snprintf(buf + len, PAGE_SIZE - len, "%-15s: %8d ",
|
len +=
|
||||||
"instability", speed_range + uframes_inaccuracy);
|
snprintf(buf + len, PAGE_SIZE - len, "%-15s: %8d ", "instability",
|
||||||
|
speed_range + uframes_inaccuracy);
|
||||||
if (xbus->sync_mode == SYNC_MODE_AB) {
|
if (xbus->sync_mode == SYNC_MODE_AB) {
|
||||||
buf[len++] = '-';
|
buf[len++] = '-';
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; len < PAGE_SIZE - 1 && i < speed_range + uframes_inaccuracy; i++)
|
for (i = 0;
|
||||||
|
len < PAGE_SIZE - 1
|
||||||
|
&& i < speed_range + uframes_inaccuracy; i++)
|
||||||
buf[len++] = '#';
|
buf[len++] = '#';
|
||||||
}
|
}
|
||||||
buf[len++] = '\n';
|
buf[len++] = '\n';
|
||||||
len += snprintf(buf + len, PAGE_SIZE - len, "%-15s: %8d (uframes)\n", "inaccuracy", uframes_inaccuracy);
|
len +=
|
||||||
len += snprintf(buf + len, PAGE_SIZE - len, "%-15s: %8d\n", "speed_range", speed_range);
|
snprintf(buf + len, PAGE_SIZE - len, "%-15s: %8d (uframes)\n",
|
||||||
|
"inaccuracy", uframes_inaccuracy);
|
||||||
|
len +=
|
||||||
|
snprintf(buf + len, PAGE_SIZE - len, "%-15s: %8d\n", "speed_range",
|
||||||
|
speed_range);
|
||||||
SHOW(xbus, sync_adjustment);
|
SHOW(xbus, sync_adjustment);
|
||||||
len += snprintf(buf + len, PAGE_SIZE - len, "%-15s: %8d\n", "offset (usec)", di->offset_prev);
|
len +=
|
||||||
|
snprintf(buf + len, PAGE_SIZE - len, "%-15s: %8d\n",
|
||||||
|
"offset (usec)", di->offset_prev);
|
||||||
SHOW(di, offset_range);
|
SHOW(di, offset_range);
|
||||||
len += snprintf(buf + len, PAGE_SIZE - len, "%-15s: %8d\n", "best_speed", (di->max_speed + di->min_speed) / 2);
|
len +=
|
||||||
|
snprintf(buf + len, PAGE_SIZE - len, "%-15s: %8d\n", "best_speed",
|
||||||
|
(di->max_speed + di->min_speed) / 2);
|
||||||
SHOW(di, min_speed);
|
SHOW(di, min_speed);
|
||||||
SHOW(di, max_speed);
|
SHOW(di, max_speed);
|
||||||
SHOW(ticker, cycle);
|
SHOW(ticker, cycle);
|
||||||
@ -301,14 +321,14 @@ static struct device_attribute xbus_dev_attrs[] = {
|
|||||||
__ATTR_RO(waitfor_xpds),
|
__ATTR_RO(waitfor_xpds),
|
||||||
__ATTR_RO(driftinfo),
|
__ATTR_RO(driftinfo),
|
||||||
__ATTR(cls, S_IWUSR, NULL, cls_store),
|
__ATTR(cls, S_IWUSR, NULL, cls_store),
|
||||||
__ATTR(xbus_state, S_IRUGO | S_IWUSR, xbus_state_show, xbus_state_store),
|
__ATTR(xbus_state, S_IRUGO | S_IWUSR, xbus_state_show,
|
||||||
|
xbus_state_store),
|
||||||
#ifdef SAMPLE_TICKS
|
#ifdef SAMPLE_TICKS
|
||||||
__ATTR(samples, S_IWUSR | S_IRUGO, samples_show, samples_store),
|
__ATTR(samples, S_IWUSR | S_IRUGO, samples_show, samples_store),
|
||||||
#endif
|
#endif
|
||||||
__ATTR_NULL,
|
__ATTR_NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static int astribank_match(struct device *dev, struct device_driver *driver)
|
static int astribank_match(struct device *dev, struct device_driver *driver)
|
||||||
{
|
{
|
||||||
DBG(DEVICES, "SYSFS MATCH: dev->bus_id = %s, driver->name = %s\n",
|
DBG(DEVICES, "SYSFS MATCH: dev->bus_id = %s, driver->name = %s\n",
|
||||||
@ -317,7 +337,8 @@ static int astribank_match(struct device *dev, struct device_driver *driver)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef OLD_HOTPLUG_SUPPORT
|
#ifdef OLD_HOTPLUG_SUPPORT
|
||||||
static int astribank_hotplug(struct device *dev, char **envp, int envnum, char *buff, int bufsize)
|
static int astribank_hotplug(struct device *dev, char **envp, int envnum,
|
||||||
|
char *buff, int bufsize)
|
||||||
{
|
{
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
|
|
||||||
@ -349,7 +370,8 @@ static int astribank_hotplug(struct device *dev, char **envp, int envnum, char *
|
|||||||
return err; \
|
return err; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static int astribank_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
|
static int astribank_uevent(struct device *dev, char **envp, int num_envp,
|
||||||
|
char *buffer, int buffer_size)
|
||||||
{
|
{
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -429,7 +451,8 @@ static void astribank_release(struct device *dev)
|
|||||||
XBUS_ERR(xbus, "Try to release CONNECTED device.\n");
|
XBUS_ERR(xbus, "Try to release CONNECTED device.\n");
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
if (!XBUS_IS(xbus, IDLE) && !XBUS_IS(xbus, FAIL) && !XBUS_IS(xbus, DEACTIVATED)) {
|
if (!XBUS_IS(xbus, IDLE) && !XBUS_IS(xbus, FAIL)
|
||||||
|
&& !XBUS_IS(xbus, DEACTIVATED)) {
|
||||||
XBUS_ERR(xbus, "Try to release in state %s\n",
|
XBUS_ERR(xbus, "Try to release in state %s\n",
|
||||||
xbus_statename(XBUS_STATE(xbus)));
|
xbus_statename(XBUS_STATE(xbus)));
|
||||||
BUG();
|
BUG();
|
||||||
@ -495,7 +518,9 @@ static DEVICE_ATTR_READER(chipregs_show, dev, buf)
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
spin_lock_irqsave(&xpd->lock, flags);
|
spin_lock_irqsave(&xpd->lock, flags);
|
||||||
regs = &xpd->last_reply;
|
regs = &xpd->last_reply;
|
||||||
len += sprintf(buf + len, "# Writing bad data into this file may damage your hardware!\n");
|
len +=
|
||||||
|
sprintf(buf + len,
|
||||||
|
"# Writing bad data into this file may damage your hardware!\n");
|
||||||
len += sprintf(buf + len, "# Consult firmware docs first\n");
|
len += sprintf(buf + len, "# Consult firmware docs first\n");
|
||||||
len += sprintf(buf + len, "#\n");
|
len += sprintf(buf + len, "#\n");
|
||||||
do_datah = REG_FIELD(regs, do_datah) ? 1 : 0;
|
do_datah = REG_FIELD(regs, do_datah) ? 1 : 0;
|
||||||
@ -505,19 +530,22 @@ static DEVICE_ATTR_READER(chipregs_show, dev, buf)
|
|||||||
} else
|
} else
|
||||||
datah_str[0] = '\0';
|
datah_str[0] = '\0';
|
||||||
if (REG_FIELD(regs, do_subreg)) {
|
if (REG_FIELD(regs, do_subreg)) {
|
||||||
len += sprintf(buf + len, "#CH\tOP\tReg.\tSub\tDL%s\n",
|
len +=
|
||||||
|
sprintf(buf + len, "#CH\tOP\tReg.\tSub\tDL%s\n",
|
||||||
(do_datah) ? "\tDH" : "");
|
(do_datah) ? "\tDH" : "");
|
||||||
len += sprintf(buf + len, "%2d\tRS\t%02X\t%02X\t%02X%s\n",
|
len +=
|
||||||
regs->portnum,
|
sprintf(buf + len, "%2d\tRS\t%02X\t%02X\t%02X%s\n",
|
||||||
REG_FIELD(regs, regnum), REG_FIELD(regs, subreg),
|
regs->portnum, REG_FIELD(regs, regnum),
|
||||||
REG_FIELD(regs, data_low), datah_str);
|
REG_FIELD(regs, subreg), REG_FIELD(regs, data_low),
|
||||||
|
datah_str);
|
||||||
} else {
|
} else {
|
||||||
len += sprintf(buf + len, "#CH\tOP\tReg.\tDL%s\n",
|
len +=
|
||||||
|
sprintf(buf + len, "#CH\tOP\tReg.\tDL%s\n",
|
||||||
(do_datah) ? "\tDH" : "");
|
(do_datah) ? "\tDH" : "");
|
||||||
len += sprintf(buf + len, "%2d\tRD\t%02X\t%02X%s\n",
|
len +=
|
||||||
regs->portnum,
|
sprintf(buf + len, "%2d\tRD\t%02X\t%02X%s\n", regs->portnum,
|
||||||
REG_FIELD(regs, regnum),
|
REG_FIELD(regs, regnum), REG_FIELD(regs, data_low),
|
||||||
REG_FIELD(regs, data_low), datah_str);
|
datah_str);
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||||
return len;
|
return len;
|
||||||
@ -541,14 +569,17 @@ static DEVICE_ATTR_WRITER(chipregs_store, dev, buf, count)
|
|||||||
i = strcspn(p, "\r\n");
|
i = strcspn(p, "\r\n");
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
if (i >= MAX_PROC_WRITE) {
|
if (i >= MAX_PROC_WRITE) {
|
||||||
XPD_NOTICE(xpd, "Command too long (%d chars)\n", i);
|
XPD_NOTICE(xpd, "Command too long (%d chars)\n",
|
||||||
|
i);
|
||||||
return -E2BIG;
|
return -E2BIG;
|
||||||
}
|
}
|
||||||
memcpy(tmp, p, i);
|
memcpy(tmp, p, i);
|
||||||
tmp[i] = '\0';
|
tmp[i] = '\0';
|
||||||
ret = parse_chip_command(xpd, tmp);
|
ret = parse_chip_command(xpd, tmp);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
XPD_NOTICE(xpd, "Failed writing command: '%s'\n", tmp);
|
XPD_NOTICE(xpd,
|
||||||
|
"Failed writing command: '%s'\n",
|
||||||
|
tmp);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -608,7 +639,9 @@ static DEVICE_ATTR_READER(span_show, dev, buf)
|
|||||||
if (!xpd)
|
if (!xpd)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
spin_lock_irqsave(&xpd->lock, flags);
|
spin_lock_irqsave(&xpd->lock, flags);
|
||||||
len += sprintf(buf, "%d\n", SPAN_REGISTERED(xpd) ? PHONEDEV(xpd).span.spanno : 0);
|
len +=
|
||||||
|
sprintf(buf, "%d\n",
|
||||||
|
SPAN_REGISTERED(xpd) ? PHONEDEV(xpd).span.spanno : 0);
|
||||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
@ -632,8 +665,7 @@ static DEVICE_ATTR_WRITER(span_store, dev, buf, count)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (!XBUS_IS(xpd->xbus, READY))
|
if (!XBUS_IS(xpd->xbus, READY))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
XPD_DBG(DEVICES, xpd,
|
XPD_DBG(DEVICES, xpd, "%s -- deprecated (should use pinned-spans)\n",
|
||||||
"%s -- deprecated (should use pinned-spans)\n",
|
|
||||||
(dahdi_reg) ? "register" : "unregister");
|
(dahdi_reg) ? "register" : "unregister");
|
||||||
if (xbus_is_registered(xpd->xbus)) {
|
if (xbus_is_registered(xpd->xbus)) {
|
||||||
if (dahdi_reg) {
|
if (dahdi_reg) {
|
||||||
@ -725,11 +757,13 @@ static int xpd_match(struct device *dev, struct device_driver *driver)
|
|||||||
xpd_driver = driver_to_xpd_driver(driver);
|
xpd_driver = driver_to_xpd_driver(driver);
|
||||||
xpd = dev_to_xpd(dev);
|
xpd = dev_to_xpd(dev);
|
||||||
if (xpd_driver->type != xpd->type) {
|
if (xpd_driver->type != xpd->type) {
|
||||||
XPD_DBG(DEVICES, xpd, "SYSFS match fail: xpd->type = %d, xpd_driver->type = %d\n",
|
XPD_DBG(DEVICES, xpd,
|
||||||
|
"SYSFS match fail: xpd->type = %d, xpd_driver->type = %d\n",
|
||||||
xpd->type, xpd_driver->type);
|
xpd->type, xpd_driver->type);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
XPD_DBG(DEVICES, xpd, "SYSFS MATCH: type=%d dev->bus_id = %s, driver->name = %s\n",
|
XPD_DBG(DEVICES, xpd,
|
||||||
|
"SYSFS MATCH: type=%d dev->bus_id = %s, driver->name = %s\n",
|
||||||
xpd->type, dev_name(dev), driver->name);
|
xpd->type, dev_name(dev), driver->name);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -758,8 +792,8 @@ int xpd_driver_register(struct device_driver *driver)
|
|||||||
DBG(DEVICES, "%s\n", driver->name);
|
DBG(DEVICES, "%s\n", driver->name);
|
||||||
driver->bus = &xpd_type;
|
driver->bus = &xpd_type;
|
||||||
if ((ret = driver_register(driver)) < 0) {
|
if ((ret = driver_register(driver)) < 0) {
|
||||||
ERR("%s: driver_register(%s) failed. Error number %d",
|
ERR("%s: driver_register(%s) failed. Error number %d", __func__,
|
||||||
__func__, driver->name, ret);
|
driver->name, ret);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -905,12 +939,12 @@ int echocancel_xpd(xpd_t *xpd, int on)
|
|||||||
|
|
||||||
ret = device_create_file(&xpd->xpd_dev, &dev_attr_echocancel);
|
ret = device_create_file(&xpd->xpd_dev, &dev_attr_echocancel);
|
||||||
if (ret)
|
if (ret)
|
||||||
XPD_ERR(xpd,
|
XPD_ERR(xpd, "%s: device_create_file(echocancel) failed: %d\n",
|
||||||
"%s: device_create_file(echocancel) failed: %d\n",
|
|
||||||
__func__, ret);
|
__func__, ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(echocancel_xpd);
|
EXPORT_SYMBOL(echocancel_xpd);
|
||||||
|
|
||||||
/*--------- Sysfs Device handling ----*/
|
/*--------- Sysfs Device handling ----*/
|
||||||
@ -940,11 +974,12 @@ int xbus_sysfs_transport_create(xbus_t *xbus)
|
|||||||
XBUS_ERR(xbus, "%s: Missing transport_device\n", __func__);
|
XBUS_ERR(xbus, "%s: Missing transport_device\n", __func__);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
ret = sysfs_create_link(&astribank->kobj, &transport_device->kobj,
|
ret =
|
||||||
|
sysfs_create_link(&astribank->kobj, &transport_device->kobj,
|
||||||
"transport");
|
"transport");
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
XBUS_ERR(xbus, "%s: sysfs_create_link failed: %d\n",
|
XBUS_ERR(xbus, "%s: sysfs_create_link failed: %d\n", __func__,
|
||||||
__func__, ret);
|
ret);
|
||||||
dev_set_drvdata(astribank, NULL);
|
dev_set_drvdata(astribank, NULL);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@ -979,7 +1014,8 @@ int xbus_sysfs_create(xbus_t *xbus)
|
|||||||
astribank->release = astribank_release;
|
astribank->release = astribank_release;
|
||||||
ret = device_register(astribank);
|
ret = device_register(astribank);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
XBUS_ERR(xbus, "%s: device_register failed: %d\n", __func__, ret);
|
XBUS_ERR(xbus, "%s: device_register failed: %d\n", __func__,
|
||||||
|
ret);
|
||||||
dev_set_drvdata(astribank, NULL);
|
dev_set_drvdata(astribank, NULL);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@ -991,18 +1027,18 @@ int __init xpp_driver_init(void)
|
|||||||
|
|
||||||
DBG(DEVICES, "SYSFS\n");
|
DBG(DEVICES, "SYSFS\n");
|
||||||
if ((ret = bus_register(&toplevel_bus_type)) < 0) {
|
if ((ret = bus_register(&toplevel_bus_type)) < 0) {
|
||||||
ERR("%s: bus_register(%s) failed. Error number %d",
|
ERR("%s: bus_register(%s) failed. Error number %d", __func__,
|
||||||
__func__, toplevel_bus_type.name, ret);
|
toplevel_bus_type.name, ret);
|
||||||
goto failed_toplevel;
|
goto failed_toplevel;
|
||||||
}
|
}
|
||||||
if ((ret = driver_register(&xpp_driver)) < 0) {
|
if ((ret = driver_register(&xpp_driver)) < 0) {
|
||||||
ERR("%s: driver_register(%s) failed. Error number %d",
|
ERR("%s: driver_register(%s) failed. Error number %d", __func__,
|
||||||
__func__, xpp_driver.name, ret);
|
xpp_driver.name, ret);
|
||||||
goto failed_xpp_driver;
|
goto failed_xpp_driver;
|
||||||
}
|
}
|
||||||
if ((ret = bus_register(&xpd_type)) < 0) {
|
if ((ret = bus_register(&xpd_type)) < 0) {
|
||||||
ERR("%s: bus_register(%s) failed. Error number %d",
|
ERR("%s: bus_register(%s) failed. Error number %d", __func__,
|
||||||
__func__, xpd_type.name, ret);
|
xpd_type.name, ret);
|
||||||
goto failed_xpd_bus;
|
goto failed_xpd_bus;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -45,7 +45,10 @@ typedef uint32_t __u32;
|
|||||||
#define ERR(fmt, ...) printf("ERR: " fmt, ## __VA_ARGS__)
|
#define ERR(fmt, ...) printf("ERR: " fmt, ## __VA_ARGS__)
|
||||||
#define __user
|
#define __user
|
||||||
|
|
||||||
struct list_head { struct list_head *next; struct list_head *prev; };
|
struct list_head {
|
||||||
|
struct list_head *next;
|
||||||
|
struct list_head *prev;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -7,7 +7,8 @@ extern int debug;
|
|||||||
static xframe_t *transport_alloc_xframe(xbus_t *xbus, gfp_t gfp_flags);
|
static xframe_t *transport_alloc_xframe(xbus_t *xbus, gfp_t gfp_flags);
|
||||||
static void transport_free_xframe(xbus_t *xbus, xframe_t *xframe);
|
static void transport_free_xframe(xbus_t *xbus, xframe_t *xframe);
|
||||||
|
|
||||||
void xframe_queue_init(struct xframe_queue *q, unsigned int steady_state_count, unsigned int max_count, const char *name, void *priv)
|
void xframe_queue_init(struct xframe_queue *q, unsigned int steady_state_count,
|
||||||
|
unsigned int max_count, const char *name, void *priv)
|
||||||
{
|
{
|
||||||
memset(q, 0, sizeof(*q));
|
memset(q, 0, sizeof(*q));
|
||||||
spin_lock_init(&q->lock);
|
spin_lock_init(&q->lock);
|
||||||
@ -34,8 +35,7 @@ static void __xframe_dump_queue(struct xframe_queue *q)
|
|||||||
|
|
||||||
do_gettimeofday(&now);
|
do_gettimeofday(&now);
|
||||||
printk(KERN_DEBUG "%s: dump queue '%s' (first packet in each frame)\n",
|
printk(KERN_DEBUG "%s: dump queue '%s' (first packet in each frame)\n",
|
||||||
THIS_MODULE->name,
|
THIS_MODULE->name, q->name);
|
||||||
q->name);
|
|
||||||
list_for_each_entry_reverse(xframe, &q->head, frame_list) {
|
list_for_each_entry_reverse(xframe, &q->head, frame_list) {
|
||||||
xpacket_t *pack = (xpacket_t *)&xframe->packets[0];
|
xpacket_t *pack = (xpacket_t *)&xframe->packets[0];
|
||||||
long usec = usec_diff(&now, &xframe->tv_queued);
|
long usec = usec_diff(&now, &xframe->tv_queued);
|
||||||
@ -57,13 +57,10 @@ static bool __xframe_enqueue(struct xframe_queue *q, xframe_t *xframe)
|
|||||||
if (q->count >= q->max_count) {
|
if (q->count >= q->max_count) {
|
||||||
q->overflows++;
|
q->overflows++;
|
||||||
if ((overflow_cnt++ % 1000) < 5) {
|
if ((overflow_cnt++ % 1000) < 5) {
|
||||||
NOTICE("Overflow of %-15s: counts %3d, %3d, %3d worst %3d, overflows %3d worst_lag %02ld.%ld ms\n",
|
NOTICE
|
||||||
q->name,
|
("Overflow of %-15s: counts %3d, %3d, %3d worst %3d, overflows %3d worst_lag %02ld.%ld ms\n",
|
||||||
q->steady_state_count,
|
q->name, q->steady_state_count, q->count,
|
||||||
q->count,
|
q->max_count, q->worst_count, q->overflows,
|
||||||
q->max_count,
|
|
||||||
q->worst_count,
|
|
||||||
q->overflows,
|
|
||||||
q->worst_lag_usec / 1000,
|
q->worst_lag_usec / 1000,
|
||||||
q->worst_lag_usec % 1000);
|
q->worst_lag_usec % 1000);
|
||||||
__xframe_dump_queue(q);
|
__xframe_dump_queue(q);
|
||||||
@ -105,8 +102,10 @@ static xframe_t *__xframe_dequeue(struct xframe_queue *q)
|
|||||||
frm = list_entry(h, xframe_t, frame_list);
|
frm = list_entry(h, xframe_t, frame_list);
|
||||||
do_gettimeofday(&now);
|
do_gettimeofday(&now);
|
||||||
usec_lag =
|
usec_lag =
|
||||||
(now.tv_sec - frm->tv_queued.tv_sec)*1000*1000 +
|
(now.tv_sec - frm->tv_queued.tv_sec) * 1000 * 1000 + (now.tv_usec -
|
||||||
(now.tv_usec - frm->tv_queued.tv_usec);
|
frm->
|
||||||
|
tv_queued.
|
||||||
|
tv_usec);
|
||||||
if (q->worst_lag_usec < usec_lag)
|
if (q->worst_lag_usec < usec_lag)
|
||||||
q->worst_lag_usec = usec_lag;
|
q->worst_lag_usec = usec_lag;
|
||||||
out:
|
out:
|
||||||
@ -123,6 +122,7 @@ xframe_t *xframe_dequeue(struct xframe_queue *q)
|
|||||||
spin_unlock_irqrestore(&q->lock, flags);
|
spin_unlock_irqrestore(&q->lock, flags);
|
||||||
return frm;
|
return frm;
|
||||||
}
|
}
|
||||||
|
|
||||||
void xframe_queue_disable(struct xframe_queue *q, bool disabled)
|
void xframe_queue_disable(struct xframe_queue *q, bool disabled)
|
||||||
{
|
{
|
||||||
q->disabled = disabled;
|
q->disabled = disabled;
|
||||||
@ -139,7 +139,8 @@ void xframe_queue_clear(struct xframe_queue *q)
|
|||||||
transport_free_xframe(xbus, xframe);
|
transport_free_xframe(xbus, xframe);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
XBUS_DBG(DEVICES, xbus, "%s: finished queue clear (%d items)\n", q->name, i);
|
XBUS_DBG(DEVICES, xbus, "%s: finished queue clear (%d items)\n",
|
||||||
|
q->name, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint xframe_queue_count(struct xframe_queue *q)
|
uint xframe_queue_count(struct xframe_queue *q)
|
||||||
@ -214,14 +215,16 @@ static bool xframe_queue_adjust(struct xframe_queue *q)
|
|||||||
static int rate_limit;
|
static int rate_limit;
|
||||||
|
|
||||||
if ((rate_limit++ % 3001) == 0)
|
if ((rate_limit++ % 3001) == 0)
|
||||||
XBUS_ERR(xbus, "%s: failed frame allocation\n", q->name);
|
XBUS_ERR(xbus, "%s: failed frame allocation\n",
|
||||||
|
q->name);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (!__xframe_enqueue(q, xframe)) {
|
if (!__xframe_enqueue(q, xframe)) {
|
||||||
static int rate_limit;
|
static int rate_limit;
|
||||||
|
|
||||||
if ((rate_limit++ % 3001) == 0)
|
if ((rate_limit++ % 3001) == 0)
|
||||||
XBUS_ERR(xbus, "%s: failed enqueueing frame\n", q->name);
|
XBUS_ERR(xbus, "%s: failed enqueueing frame\n",
|
||||||
|
q->name);
|
||||||
transport_free_xframe(xbus, xframe);
|
transport_free_xframe(xbus, xframe);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -233,7 +236,8 @@ static bool xframe_queue_adjust(struct xframe_queue *q)
|
|||||||
static int rate_limit;
|
static int rate_limit;
|
||||||
|
|
||||||
if ((rate_limit++ % 3001) == 0)
|
if ((rate_limit++ % 3001) == 0)
|
||||||
XBUS_ERR(xbus, "%s: failed dequeueing frame\n", q->name);
|
XBUS_ERR(xbus, "%s: failed dequeueing frame\n",
|
||||||
|
q->name);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
transport_free_xframe(xbus, xframe);
|
transport_free_xframe(xbus, xframe);
|
||||||
@ -258,7 +262,8 @@ xframe_t *get_xframe(struct xframe_queue *q)
|
|||||||
static int rate_limit;
|
static int rate_limit;
|
||||||
|
|
||||||
if ((rate_limit++ % 3001) == 0)
|
if ((rate_limit++ % 3001) == 0)
|
||||||
XBUS_ERR(xbus, "%s STILL EMPTY (%d)\n", q->name, rate_limit);
|
XBUS_ERR(xbus, "%s STILL EMPTY (%d)\n", q->name,
|
||||||
|
rate_limit);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
BUG_ON(xframe->xframe_magic != XFRAME_MAGIC);
|
BUG_ON(xframe->xframe_magic != XFRAME_MAGIC);
|
||||||
@ -294,7 +299,6 @@ void put_xframe(struct xframe_queue *q, xframe_t *xframe)
|
|||||||
xframe_queue_adjust(q);
|
xframe_queue_adjust(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EXPORT_SYMBOL(xframe_queue_init);
|
EXPORT_SYMBOL(xframe_queue_init);
|
||||||
EXPORT_SYMBOL(xframe_queue_clearstats);
|
EXPORT_SYMBOL(xframe_queue_clearstats);
|
||||||
EXPORT_SYMBOL(xframe_enqueue);
|
EXPORT_SYMBOL(xframe_enqueue);
|
||||||
|
@ -22,9 +22,8 @@ struct xframe_queue {
|
|||||||
unsigned long worst_lag_usec; /* since xframe creation */
|
unsigned long worst_lag_usec; /* since xframe creation */
|
||||||
};
|
};
|
||||||
|
|
||||||
void xframe_queue_init(struct xframe_queue *q,
|
void xframe_queue_init(struct xframe_queue *q, unsigned int steady_state_count,
|
||||||
unsigned int steady_state_count, unsigned int max_count,
|
unsigned int max_count, const char *name, void *priv);
|
||||||
const char *name, void *priv);
|
|
||||||
__must_check bool xframe_enqueue(struct xframe_queue *q, xframe_t *xframe);
|
__must_check bool xframe_enqueue(struct xframe_queue *q, xframe_t *xframe);
|
||||||
__must_check xframe_t *xframe_dequeue(struct xframe_queue *q);
|
__must_check xframe_t *xframe_dequeue(struct xframe_queue *q);
|
||||||
void xframe_queue_clearstats(struct xframe_queue *q);
|
void xframe_queue_clearstats(struct xframe_queue *q);
|
||||||
|
@ -122,10 +122,7 @@ enum {
|
|||||||
static struct xpd_counters {
|
static struct xpd_counters {
|
||||||
char *name;
|
char *name;
|
||||||
} xpd_counters[] = {
|
} xpd_counters[] = {
|
||||||
C_(PCM_READ),
|
C_(PCM_READ), C_(PCM_WRITE), C_(RECV_ERRORS),};
|
||||||
C_(PCM_WRITE),
|
|
||||||
C_(RECV_ERRORS),
|
|
||||||
};
|
|
||||||
|
|
||||||
#undef C_
|
#undef C_
|
||||||
|
|
||||||
|
@ -57,7 +57,8 @@ struct proc_dir_entry *xpp_proc_toplevel = NULL;
|
|||||||
#define DELAY_UNTIL_DIALTONE 3000
|
#define DELAY_UNTIL_DIALTONE 3000
|
||||||
|
|
||||||
DEF_PARM(int, debug, 0, 0644, "Print DBG statements");
|
DEF_PARM(int, debug, 0, 0644, "Print DBG statements");
|
||||||
static DEF_PARM_BOOL(prefmaster, 0, 0644, "Do we want to be dahdi preferred sync master");
|
static DEF_PARM_BOOL(prefmaster, 0, 0644,
|
||||||
|
"Do we want to be dahdi preferred sync master");
|
||||||
// DEF_ARRAY(int, pcmtx, 4, 0, "Forced PCM values to transmit");
|
// DEF_ARRAY(int, pcmtx, 4, 0, "Forced PCM values to transmit");
|
||||||
|
|
||||||
#include "dahdi_debug.h"
|
#include "dahdi_debug.h"
|
||||||
@ -75,6 +76,7 @@ static void phonedev_cleanup(xpd_t *xpd);
|
|||||||
* echo "3,5" > /sys/module/xpp/parameters/parport_xbuses
|
* echo "3,5" > /sys/module/xpp/parameters/parport_xbuses
|
||||||
*/
|
*/
|
||||||
static int parport_xbuses[2] = { 0, 1 };
|
static int parport_xbuses[2] = { 0, 1 };
|
||||||
|
|
||||||
unsigned int parport_xbuses_num_values;
|
unsigned int parport_xbuses_num_values;
|
||||||
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 9)
|
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 9)
|
||||||
module_param_array(parport_xbuses, int, &parport_xbuses_num_values, 0577);
|
module_param_array(parport_xbuses, int, &parport_xbuses_num_values, 0577);
|
||||||
@ -97,6 +99,7 @@ void xbus_flip_bit(xbus_t *xbus, unsigned int bitnum0, unsigned int bitnum1)
|
|||||||
if (num == parport_xbuses[1])
|
if (num == parport_xbuses[1])
|
||||||
flip_parport_bit(bitnum1);
|
flip_parport_bit(bitnum1);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(xbus_flip_bit);
|
EXPORT_SYMBOL(xbus_flip_bit);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -108,7 +111,8 @@ int total_registered_spans(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
static int xpd_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data);
|
static int xpd_read_proc(char *page, char **start, off_t off, int count,
|
||||||
|
int *eof, void *data);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*------------------------- XPD Management -------------------------*/
|
/*------------------------- XPD Management -------------------------*/
|
||||||
@ -134,16 +138,14 @@ int refcount_xpd(xpd_t *xpd)
|
|||||||
|
|
||||||
xpd_t *get_xpd(const char *msg, xpd_t *xpd)
|
xpd_t *get_xpd(const char *msg, xpd_t *xpd)
|
||||||
{
|
{
|
||||||
XPD_DBG(DEVICES, xpd, "%s: refcount_xpd=%d\n",
|
XPD_DBG(DEVICES, xpd, "%s: refcount_xpd=%d\n", msg, refcount_xpd(xpd));
|
||||||
msg, refcount_xpd(xpd));
|
|
||||||
kref_get(&xpd->kref);
|
kref_get(&xpd->kref);
|
||||||
return xpd;
|
return xpd;
|
||||||
}
|
}
|
||||||
|
|
||||||
void put_xpd(const char *msg, xpd_t *xpd)
|
void put_xpd(const char *msg, xpd_t *xpd)
|
||||||
{
|
{
|
||||||
XPD_DBG(DEVICES, xpd, "%s: refcount_xpd=%d\n",
|
XPD_DBG(DEVICES, xpd, "%s: refcount_xpd=%d\n", msg, refcount_xpd(xpd));
|
||||||
msg, refcount_xpd(xpd));
|
|
||||||
kref_put(&xpd->kref, xpd_destroy);
|
kref_put(&xpd->kref, xpd_destroy);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,7 +154,8 @@ static void xpd_proc_remove(xbus_t *xbus, xpd_t *xpd)
|
|||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
if (xpd->proc_xpd_dir) {
|
if (xpd->proc_xpd_dir) {
|
||||||
if (xpd->proc_xpd_summary) {
|
if (xpd->proc_xpd_summary) {
|
||||||
XPD_DBG(PROC, xpd, "Removing proc '%s'\n", PROC_XPD_SUMMARY);
|
XPD_DBG(PROC, xpd, "Removing proc '%s'\n",
|
||||||
|
PROC_XPD_SUMMARY);
|
||||||
remove_proc_entry(PROC_XPD_SUMMARY, xpd->proc_xpd_dir);
|
remove_proc_entry(PROC_XPD_SUMMARY, xpd->proc_xpd_dir);
|
||||||
xpd->proc_xpd_summary = NULL;
|
xpd->proc_xpd_summary = NULL;
|
||||||
}
|
}
|
||||||
@ -173,10 +176,12 @@ static int xpd_proc_create(xbus_t *xbus, xpd_t *xpd)
|
|||||||
XPD_ERR(xpd, "Failed to create proc directory\n");
|
XPD_ERR(xpd, "Failed to create proc directory\n");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
xpd->proc_xpd_summary = create_proc_read_entry(PROC_XPD_SUMMARY, 0444, xpd->proc_xpd_dir,
|
xpd->proc_xpd_summary =
|
||||||
|
create_proc_read_entry(PROC_XPD_SUMMARY, 0444, xpd->proc_xpd_dir,
|
||||||
xpd_read_proc, xpd);
|
xpd_read_proc, xpd);
|
||||||
if (!xpd->proc_xpd_summary) {
|
if (!xpd->proc_xpd_summary) {
|
||||||
XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_XPD_SUMMARY);
|
XPD_ERR(xpd, "Failed to create proc file '%s'\n",
|
||||||
|
PROC_XPD_SUMMARY);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
SET_PROC_DIRENTRY_OWNER(xpd->proc_xpd_summary);
|
SET_PROC_DIRENTRY_OWNER(xpd->proc_xpd_summary);
|
||||||
@ -217,14 +222,9 @@ void xpd_free(xpd_t *xpd)
|
|||||||
* Synchronous part of XPD detection.
|
* Synchronous part of XPD detection.
|
||||||
* Called from new_card()
|
* Called from new_card()
|
||||||
*/
|
*/
|
||||||
int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table,
|
int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table, int unit,
|
||||||
int unit,
|
int subunit, __u8 type, __u8 subtype, int subunits,
|
||||||
int subunit,
|
int subunit_ports, __u8 port_dir)
|
||||||
__u8 type,
|
|
||||||
__u8 subtype,
|
|
||||||
int subunits,
|
|
||||||
int subunit_ports,
|
|
||||||
__u8 port_dir)
|
|
||||||
{
|
{
|
||||||
xpd_t *xpd = NULL;
|
xpd_t *xpd = NULL;
|
||||||
bool to_phone;
|
bool to_phone;
|
||||||
@ -234,8 +234,7 @@ int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table,
|
|||||||
BUG_ON(!xbus);
|
BUG_ON(!xbus);
|
||||||
xpd = xpd_byaddr(xbus, unit, subunit);
|
xpd = xpd_byaddr(xbus, unit, subunit);
|
||||||
if (xpd) {
|
if (xpd) {
|
||||||
XPD_NOTICE(xpd, "XPD at %d%d already exists\n",
|
XPD_NOTICE(xpd, "XPD at %d%d already exists\n", unit, subunit);
|
||||||
unit, subunit);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (subunit_ports <= 0 || subunit_ports > CHANNELS_PERXPD) {
|
if (subunit_ports <= 0 || subunit_ports > CHANNELS_PERXPD) {
|
||||||
@ -243,10 +242,14 @@ int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table,
|
|||||||
subunit_ports, unit, subunit);
|
subunit_ports, unit, subunit);
|
||||||
return 0;
|
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) {
|
if (!xpd) {
|
||||||
XBUS_NOTICE(xbus, "card_new(%d,%d,%d,%d,%d) failed. Ignored.\n",
|
XBUS_NOTICE(xbus, "card_new(%d,%d,%d,%d,%d) failed. Ignored.\n",
|
||||||
unit, subunit, proto_table->type, subtype, to_phone);
|
unit, subunit, proto_table->type, subtype,
|
||||||
|
to_phone);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -263,7 +266,8 @@ int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table,
|
|||||||
* @eof TODO: figure out procfs
|
* @eof TODO: figure out procfs
|
||||||
* @data an xbus_t pointer with the bus data.
|
* @data an xbus_t pointer with the bus data.
|
||||||
*/
|
*/
|
||||||
static int xpd_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
|
static int xpd_read_proc(char *page, char **start, off_t off, int count,
|
||||||
|
int *eof, void *data)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
xpd_t *xpd = data;
|
xpd_t *xpd = data;
|
||||||
@ -272,34 +276,45 @@ static int xpd_read_proc(char *page, char **start, off_t off, int count, int *eo
|
|||||||
if (!xpd)
|
if (!xpd)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
len += sprintf(page + len, "%s (%s, card %s, span %d)\n"
|
len +=
|
||||||
"timing_priority: %d\n"
|
sprintf(page + len,
|
||||||
"timer_count: %d span->mainttimer=%d\n"
|
"%s (%s, card %s, span %d)\n" "timing_priority: %d\n"
|
||||||
,
|
"timer_count: %d span->mainttimer=%d\n", xpd->xpdname,
|
||||||
xpd->xpdname, xpd->type_name,
|
xpd->type_name, (xpd->card_present) ? "present" : "missing",
|
||||||
(xpd->card_present) ? "present" : "missing",
|
|
||||||
(SPAN_REGISTERED(xpd)) ? PHONEDEV(xpd).span.spanno : 0,
|
(SPAN_REGISTERED(xpd)) ? PHONEDEV(xpd).span.spanno : 0,
|
||||||
PHONEDEV(xpd).timing_priority,
|
PHONEDEV(xpd).timing_priority, xpd->timer_count,
|
||||||
xpd->timer_count, PHONEDEV(xpd).span.mainttimer
|
PHONEDEV(xpd).span.mainttimer);
|
||||||
);
|
len +=
|
||||||
len += sprintf(page + len, "xpd_state: %s (%d)\n",
|
sprintf(page + len, "xpd_state: %s (%d)\n",
|
||||||
xpd_statename(xpd->xpd_state), xpd->xpd_state);
|
xpd_statename(xpd->xpd_state), xpd->xpd_state);
|
||||||
len += sprintf(page + len, "open_counter=%d refcount=%d\n",
|
len +=
|
||||||
atomic_read(&PHONEDEV(xpd).open_counter), refcount_xpd(xpd));
|
sprintf(page + len, "open_counter=%d refcount=%d\n",
|
||||||
len += sprintf(page + len, "Address: U=%d S=%d\n", xpd->addr.unit, xpd->addr.subunit);
|
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, "Subunits: %d\n", xpd->subunits);
|
||||||
len += sprintf(page + len, "Type: %d.%d\n\n", xpd->type, xpd->subtype);
|
len += sprintf(page + len, "Type: %d.%d\n\n", xpd->type, xpd->subtype);
|
||||||
len += sprintf(page + len, "pcm_len=%d\n\n", PHONEDEV(xpd).pcm_len);
|
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 +=
|
||||||
len += sprintf(page + len, "mute_dtmf=0x%04X\n\n", PHONEDEV(xpd).mute_dtmf);
|
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, "STATES:");
|
||||||
len += sprintf(page + len, "\n\t%-17s: ", "output_relays");
|
len += sprintf(page + len, "\n\t%-17s: ", "output_relays");
|
||||||
for_each_line(xpd, i) {
|
for_each_line(xpd, i) {
|
||||||
len += sprintf(page + len, "%d ", IS_SET(PHONEDEV(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");
|
len += sprintf(page + len, "\n\t%-17s: ", "input_relays");
|
||||||
for_each_line(xpd, i) {
|
for_each_line(xpd, i) {
|
||||||
len += sprintf(page + len, "%d ", IS_SET(PHONEDEV(xpd).digital_inputs, i));
|
len +=
|
||||||
|
sprintf(page + len, "%d ",
|
||||||
|
IS_SET(PHONEDEV(xpd).digital_inputs, i));
|
||||||
}
|
}
|
||||||
len += sprintf(page + len, "\n\t%-17s: ", "offhook");
|
len += sprintf(page + len, "\n\t%-17s: ", "offhook");
|
||||||
for_each_line(xpd, i) {
|
for_each_line(xpd, i) {
|
||||||
@ -307,7 +322,9 @@ 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");
|
len += sprintf(page + len, "\n\t%-17s: ", "oht_pcm_pass");
|
||||||
for_each_line(xpd, i) {
|
for_each_line(xpd, i) {
|
||||||
len += sprintf(page + len, "%d ", IS_SET(PHONEDEV(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");
|
len += sprintf(page + len, "\n\t%-17s: ", "msg_waiting");
|
||||||
for_each_line(xpd, i) {
|
for_each_line(xpd, i) {
|
||||||
@ -319,11 +336,14 @@ static int xpd_read_proc(char *page, char **start, off_t off, int count, int *eo
|
|||||||
}
|
}
|
||||||
len += sprintf(page + len, "\n\t%-17s: ", "no_pcm");
|
len += sprintf(page + len, "\n\t%-17s: ", "no_pcm");
|
||||||
for_each_line(xpd, i) {
|
for_each_line(xpd, i) {
|
||||||
len += sprintf(page + len, "%d ", IS_SET(PHONEDEV(xpd).no_pcm, i));
|
len +=
|
||||||
|
sprintf(page + len, "%d ", IS_SET(PHONEDEV(xpd).no_pcm, i));
|
||||||
}
|
}
|
||||||
#if 1
|
#if 1
|
||||||
if (SPAN_REGISTERED(xpd)) {
|
if (SPAN_REGISTERED(xpd)) {
|
||||||
len += sprintf(page + len, "\nPCM:\n | [readchunk] | [writechunk] | W D");
|
len +=
|
||||||
|
sprintf(page + len,
|
||||||
|
"\nPCM:\n | [readchunk] | [writechunk] | W D");
|
||||||
for_each_line(xpd, i) {
|
for_each_line(xpd, i) {
|
||||||
struct dahdi_chan *chan = XPD_CHAN(xpd, i);
|
struct dahdi_chan *chan = XPD_CHAN(xpd, i);
|
||||||
__u8 rchunk[DAHDI_CHUNKSIZE];
|
__u8 rchunk[DAHDI_CHUNKSIZE];
|
||||||
@ -350,10 +370,14 @@ static int xpd_read_proc(char *page, char **start, off_t off, int count, int *eo
|
|||||||
for (j = 0; j < DAHDI_CHUNKSIZE; j++) {
|
for (j = 0; j < DAHDI_CHUNKSIZE; j++) {
|
||||||
len += sprintf(page + len, "%02X ", wchunk[j]);
|
len += sprintf(page + len, "%02X ", wchunk[j]);
|
||||||
}
|
}
|
||||||
len += sprintf(page + len, " | %c",
|
len +=
|
||||||
(IS_SET(PHONEDEV(xpd).wanted_pcm_mask, i))?'+':' ');
|
sprintf(page + len, " | %c",
|
||||||
len += sprintf(page + len, " %c",
|
(IS_SET(PHONEDEV(xpd).wanted_pcm_mask, i)) ?
|
||||||
(IS_SET(PHONEDEV(xpd).mute_dtmf, i))?'-':' ');
|
'+' : ' ');
|
||||||
|
len +=
|
||||||
|
sprintf(page + len, " %c",
|
||||||
|
(IS_SET(PHONEDEV(xpd).mute_dtmf, i)) ? '-' :
|
||||||
|
' ');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -362,13 +386,17 @@ static int xpd_read_proc(char *page, char **start, off_t off, int count, int *eo
|
|||||||
len += sprintf(page + len, "\nSignalling:\n");
|
len += sprintf(page + len, "\nSignalling:\n");
|
||||||
for_each_line(xpd, i) {
|
for_each_line(xpd, i) {
|
||||||
struct dahdi_chan *chan = XPD_CHAN(xpd, i);
|
struct dahdi_chan *chan = XPD_CHAN(xpd, i);
|
||||||
len += sprintf(page + len, "\t%2d> sigcap=0x%04X sig=0x%04X\n", i, chan->sigcap, chan->sig);
|
len +=
|
||||||
|
sprintf(page + len,
|
||||||
|
"\t%2d> sigcap=0x%04X sig=0x%04X\n", i,
|
||||||
|
chan->sigcap, chan->sig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
len += sprintf(page + len, "\nCOUNTERS:\n");
|
len += sprintf(page + len, "\nCOUNTERS:\n");
|
||||||
for (i = 0; i < XPD_COUNTER_MAX; i++) {
|
for (i = 0; i < XPD_COUNTER_MAX; i++) {
|
||||||
len += sprintf(page + len, "\t\t%-20s = %d\n",
|
len +=
|
||||||
|
sprintf(page + len, "\t\t%-20s = %d\n",
|
||||||
xpd_counters[i].name, xpd->counters[i]);
|
xpd_counters[i].name, xpd->counters[i]);
|
||||||
}
|
}
|
||||||
len += sprintf(page + len, "<-- len=%d\n", len);
|
len += sprintf(page + len, "<-- len=%d\n", len);
|
||||||
@ -390,10 +418,14 @@ out:
|
|||||||
const char *xpd_statename(enum xpd_state st)
|
const char *xpd_statename(enum xpd_state st)
|
||||||
{
|
{
|
||||||
switch (st) {
|
switch (st) {
|
||||||
case XPD_STATE_START: return "START";
|
case XPD_STATE_START:
|
||||||
case XPD_STATE_INIT_REGS: return "INIT_REGS";
|
return "START";
|
||||||
case XPD_STATE_READY: return "READY";
|
case XPD_STATE_INIT_REGS:
|
||||||
case XPD_STATE_NOHW: return "NOHW";
|
return "INIT_REGS";
|
||||||
|
case XPD_STATE_READY:
|
||||||
|
return "READY";
|
||||||
|
case XPD_STATE_NOHW:
|
||||||
|
return "NOHW";
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -435,14 +467,12 @@ bool xpd_setstate(xpd_t *xpd, enum xpd_state newstate)
|
|||||||
xpd->xpd_state = newstate;
|
xpd->xpd_state = newstate;
|
||||||
return 1;
|
return 1;
|
||||||
badstate:
|
badstate:
|
||||||
XPD_NOTICE(xpd, "%s: cannot transition: %s (%d) -> %s (%d)\n",
|
XPD_NOTICE(xpd, "%s: cannot transition: %s (%d) -> %s (%d)\n", __func__,
|
||||||
__func__,
|
|
||||||
xpd_statename(xpd->xpd_state), xpd->xpd_state,
|
xpd_statename(xpd->xpd_state), xpd->xpd_state,
|
||||||
xpd_statename(newstate), newstate);
|
xpd_statename(newstate), newstate);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Cleanup/initialize phonedev
|
* Cleanup/initialize phonedev
|
||||||
*/
|
*/
|
||||||
@ -460,7 +490,8 @@ static void phonedev_cleanup(xpd_t *xpd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__must_check static int phonedev_init(xpd_t *xpd, const xproto_table_t *proto_table,
|
__must_check static int phonedev_init(xpd_t *xpd,
|
||||||
|
const xproto_table_t *proto_table,
|
||||||
int channels, xpp_line_t no_pcm)
|
int channels, xpp_line_t no_pcm)
|
||||||
{
|
{
|
||||||
struct phonedev *phonedev = &PHONEDEV(xpd);
|
struct phonedev *phonedev = &PHONEDEV(xpd);
|
||||||
@ -476,12 +507,14 @@ __must_check static int phonedev_init(xpd_t *xpd, const xproto_table_t *proto_ta
|
|||||||
atomic_set(&phonedev->dahdi_registered, 0);
|
atomic_set(&phonedev->dahdi_registered, 0);
|
||||||
atomic_set(&phonedev->open_counter, 0);
|
atomic_set(&phonedev->open_counter, 0);
|
||||||
for (x = 0; x < phonedev->channels; x++) {
|
for (x = 0; x < phonedev->channels; x++) {
|
||||||
if (!(phonedev->chans[x] = KZALLOC(sizeof(*(phonedev->chans[x])), GFP_KERNEL))) {
|
if (!
|
||||||
|
(phonedev->chans[x] =
|
||||||
|
KZALLOC(sizeof(*(phonedev->chans[x])), GFP_KERNEL))) {
|
||||||
ERR("%s: Unable to allocate channel %d\n", __func__, x);
|
ERR("%s: Unable to allocate channel %d\n", __func__, x);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
phonedev->ec[x] = KZALLOC(sizeof(*(phonedev->ec[x])),
|
phonedev->ec[x] =
|
||||||
GFP_KERNEL);
|
KZALLOC(sizeof(*(phonedev->ec[x])), GFP_KERNEL);
|
||||||
if (!phonedev->ec[x]) {
|
if (!phonedev->ec[x]) {
|
||||||
ERR("%s: Unable to allocate ec state %d\n", __func__,
|
ERR("%s: Unable to allocate ec state %d\n", __func__,
|
||||||
x);
|
x);
|
||||||
@ -498,10 +531,9 @@ err:
|
|||||||
* xpd_alloc - Allocator for new XPD's
|
* xpd_alloc - Allocator for new XPD's
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
__must_check xpd_t *xpd_alloc(xbus_t *xbus,
|
__must_check xpd_t *xpd_alloc(xbus_t *xbus, int unit, int subunit, int subtype,
|
||||||
int unit, int subunit,
|
int subunits, size_t privsize,
|
||||||
int subtype, int subunits,
|
const xproto_table_t *proto_table, int channels)
|
||||||
size_t privsize, const xproto_table_t *proto_table, int channels)
|
|
||||||
{
|
{
|
||||||
xpd_t *xpd = NULL;
|
xpd_t *xpd = NULL;
|
||||||
size_t alloc_size = sizeof(xpd_t) + privsize;
|
size_t alloc_size = sizeof(xpd_t) + privsize;
|
||||||
@ -509,11 +541,11 @@ __must_check xpd_t *xpd_alloc(xbus_t *xbus,
|
|||||||
xpp_line_t no_pcm = 0;
|
xpp_line_t no_pcm = 0;
|
||||||
|
|
||||||
BUG_ON(!proto_table);
|
BUG_ON(!proto_table);
|
||||||
XBUS_DBG(DEVICES, xbus, "type=%d channels=%d (alloc_size=%zd)\n",
|
XBUS_DBG(DEVICES, xbus, "type=%d channels=%d (alloc_size=%zd)\n", type,
|
||||||
type, channels, alloc_size);
|
channels, alloc_size);
|
||||||
if (channels > CHANNELS_PERXPD) {
|
if (channels > CHANNELS_PERXPD) {
|
||||||
XBUS_ERR(xbus, "%s: type=%d: too many channels %d\n",
|
XBUS_ERR(xbus, "%s: type=%d: too many channels %d\n", __func__,
|
||||||
__func__, type, channels);
|
type, channels);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -535,8 +567,11 @@ __must_check xpd_t *xpd_alloc(xbus_t *xbus,
|
|||||||
|
|
||||||
/* For USB-1 disable some channels */
|
/* For USB-1 disable some channels */
|
||||||
if (MAX_SEND_SIZE(xbus) < RPACKET_SIZE(GLOBAL, PCM_WRITE)) {
|
if (MAX_SEND_SIZE(xbus) < RPACKET_SIZE(GLOBAL, PCM_WRITE)) {
|
||||||
no_pcm = 0x7F | PHONEDEV(xpd).digital_outputs | PHONEDEV(xpd).digital_inputs;
|
no_pcm =
|
||||||
XBUS_NOTICE(xbus, "max xframe size = %d, disabling some PCM channels. no_pcm=0x%04X\n",
|
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), PHONEDEV(xpd).no_pcm);
|
MAX_SEND_SIZE(xbus), PHONEDEV(xpd).no_pcm);
|
||||||
}
|
}
|
||||||
if (phonedev_init(xpd, proto_table, channels, no_pcm) < 0)
|
if (phonedev_init(xpd, proto_table, channels, no_pcm) < 0)
|
||||||
@ -589,7 +624,8 @@ void update_xpd_status(xpd_t *xpd, int alarm_flag)
|
|||||||
}
|
}
|
||||||
if (span->alarms == alarm_flag)
|
if (span->alarms == alarm_flag)
|
||||||
return;
|
return;
|
||||||
XPD_DBG(GENERAL, xpd, "Update XPD alarms: %s -> %02X\n", PHONEDEV(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;
|
span->alarms = alarm_flag;
|
||||||
dahdi_alarm_notify(span);
|
dahdi_alarm_notify(span);
|
||||||
}
|
}
|
||||||
@ -661,14 +697,14 @@ void hookstate_changed(xpd_t *xpd, int pos, bool to_offhook)
|
|||||||
*/
|
*/
|
||||||
BIT_SET(PHONEDEV(xpd).silence_pcm, pos);
|
BIT_SET(PHONEDEV(xpd).silence_pcm, pos);
|
||||||
}
|
}
|
||||||
notify_rxsig(xpd, pos, (to_offhook) ? DAHDI_RXSIG_OFFHOOK : DAHDI_RXSIG_ONHOOK);
|
notify_rxsig(xpd, pos,
|
||||||
|
(to_offhook) ? DAHDI_RXSIG_OFFHOOK : DAHDI_RXSIG_ONHOOK);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define XPP_MAX_LEN 512
|
#define XPP_MAX_LEN 512
|
||||||
|
|
||||||
/*------------------------- Dahdi Interfaces -----------------------*/
|
/*------------------------- Dahdi Interfaces -----------------------*/
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called from dahdi with spinlock held on chan. Must not call back
|
* Called from dahdi with spinlock held on chan. Must not call back
|
||||||
* dahdi functions.
|
* dahdi functions.
|
||||||
@ -701,9 +737,8 @@ int xpp_open(struct dahdi_chan *chan)
|
|||||||
}
|
}
|
||||||
spin_lock_irqsave(&xbus->lock, flags);
|
spin_lock_irqsave(&xbus->lock, flags);
|
||||||
atomic_inc(&PHONEDEV(xpd).open_counter);
|
atomic_inc(&PHONEDEV(xpd).open_counter);
|
||||||
LINE_DBG(DEVICES, xpd, pos, "%s[%d]: open_counter=%d\n",
|
LINE_DBG(DEVICES, xpd, pos, "%s[%d]: open_counter=%d\n", current->comm,
|
||||||
current->comm, current->pid,
|
current->pid, atomic_read(&PHONEDEV(xpd).open_counter));
|
||||||
atomic_read(&PHONEDEV(xpd).open_counter));
|
|
||||||
spin_unlock_irqrestore(&xbus->lock, flags);
|
spin_unlock_irqrestore(&xbus->lock, flags);
|
||||||
if (PHONE_METHOD(card_open, xpd))
|
if (PHONE_METHOD(card_open, xpd))
|
||||||
CALL_PHONE_METHOD(card_open, xpd, pos);
|
CALL_PHONE_METHOD(card_open, xpd, pos);
|
||||||
@ -721,9 +756,8 @@ int xpp_close(struct dahdi_chan *chan)
|
|||||||
spin_unlock_irqrestore(&xbus->lock, flags);
|
spin_unlock_irqrestore(&xbus->lock, flags);
|
||||||
if (PHONE_METHOD(card_close, xpd))
|
if (PHONE_METHOD(card_close, xpd))
|
||||||
CALL_PHONE_METHOD(card_close, xpd, pos);
|
CALL_PHONE_METHOD(card_close, xpd, pos);
|
||||||
LINE_DBG(DEVICES, xpd, pos, "%s[%d]: open_counter=%d\n",
|
LINE_DBG(DEVICES, xpd, pos, "%s[%d]: open_counter=%d\n", current->comm,
|
||||||
current->comm, current->pid,
|
current->pid, atomic_read(&PHONEDEV(xpd).open_counter));
|
||||||
atomic_read(&PHONEDEV(xpd).open_counter));
|
|
||||||
atomic_dec(&PHONEDEV(xpd).open_counter); /* from xpp_open() */
|
atomic_dec(&PHONEDEV(xpd).open_counter); /* from xpp_open() */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -756,7 +790,8 @@ int xpp_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long arg)
|
|||||||
default:
|
default:
|
||||||
/* Some span-specific commands before we give up: */
|
/* Some span-specific commands before we give up: */
|
||||||
if (PHONE_METHOD(card_ioctl, xpd)) {
|
if (PHONE_METHOD(card_ioctl, xpd)) {
|
||||||
return CALL_PHONE_METHOD(card_ioctl, xpd, pos, cmd, arg);
|
return CALL_PHONE_METHOD(card_ioctl, xpd, pos, cmd,
|
||||||
|
arg);
|
||||||
}
|
}
|
||||||
report_bad_ioctl(THIS_MODULE->name, xpd, pos, cmd);
|
report_bad_ioctl(THIS_MODULE->name, xpd, pos, cmd);
|
||||||
return -ENOTTY;
|
return -ENOTTY;
|
||||||
@ -783,9 +818,11 @@ int xpp_hooksig(struct dahdi_chan *chan, enum dahdi_txsig txsig)
|
|||||||
}
|
}
|
||||||
xbus = xpd->xbus;
|
xbus = xpd->xbus;
|
||||||
BUG_ON(!xbus);
|
BUG_ON(!xbus);
|
||||||
DBG(SIGNAL, "Setting %s to %s (%d)\n", chan->name, txsig2str(txsig), txsig);
|
DBG(SIGNAL, "Setting %s to %s (%d)\n", chan->name, txsig2str(txsig),
|
||||||
|
txsig);
|
||||||
return CALL_PHONE_METHOD(card_hooksig, xpd, pos, txsig);
|
return CALL_PHONE_METHOD(card_hooksig, xpd, pos, txsig);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(xpp_hooksig);
|
EXPORT_SYMBOL(xpp_hooksig);
|
||||||
|
|
||||||
/* Req: Set the requested chunk size. This is the unit in which you must
|
/* Req: Set the requested chunk size. This is the unit in which you must
|
||||||
@ -893,16 +930,13 @@ const char *xpp_echocan_name(const struct dahdi_chan *chan)
|
|||||||
* quirks and limitations
|
* quirks and limitations
|
||||||
*/
|
*/
|
||||||
if (xbus->quirks.has_fxo) {
|
if (xbus->quirks.has_fxo) {
|
||||||
if (
|
if (xbus->quirks.has_digital_span && xpd->type == XPD_TYPE_FXO) {
|
||||||
xbus->quirks.has_digital_span &&
|
|
||||||
xpd->type == XPD_TYPE_FXO) {
|
|
||||||
LINE_NOTICE(xpd, pos,
|
LINE_NOTICE(xpd, pos,
|
||||||
"quirk: give up HWEC on FXO: "
|
"quirk: give up HWEC on FXO: "
|
||||||
"AB has digital span\n");
|
"AB has digital span\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
} else if (
|
} else if (xbus->sync_mode != SYNC_MODE_AB
|
||||||
xbus->sync_mode != SYNC_MODE_AB &&
|
&& xpd->type == XPD_TYPE_FXS) {
|
||||||
xpd->type == XPD_TYPE_FXS) {
|
|
||||||
LINE_NOTICE(xpd, pos,
|
LINE_NOTICE(xpd, pos,
|
||||||
"quirk: give up HWEC on FXS: "
|
"quirk: give up HWEC on FXS: "
|
||||||
"AB has FXO and is sync slave\n");
|
"AB has FXO and is sync slave\n");
|
||||||
@ -911,10 +945,10 @@ const char *xpp_echocan_name(const struct dahdi_chan *chan)
|
|||||||
}
|
}
|
||||||
return "XPP";
|
return "XPP";
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(xpp_echocan_name);
|
EXPORT_SYMBOL(xpp_echocan_name);
|
||||||
|
|
||||||
int xpp_echocan_create(struct dahdi_chan *chan,
|
int xpp_echocan_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
|
||||||
struct dahdi_echocanparams *ecp,
|
|
||||||
struct dahdi_echocanparam *p,
|
struct dahdi_echocanparam *p,
|
||||||
struct dahdi_echocan_state **ec)
|
struct dahdi_echocan_state **ec)
|
||||||
{
|
{
|
||||||
@ -942,6 +976,7 @@ int xpp_echocan_create(struct dahdi_chan *chan,
|
|||||||
CALL_EC_METHOD(ec_update, xbus, xbus);
|
CALL_EC_METHOD(ec_update, xbus, xbus);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(xpp_echocan_create);
|
EXPORT_SYMBOL(xpp_echocan_create);
|
||||||
|
|
||||||
void xpp_span_assigned(struct dahdi_span *span)
|
void xpp_span_assigned(struct dahdi_span *span)
|
||||||
@ -955,6 +990,7 @@ void xpp_span_assigned(struct dahdi_span *span)
|
|||||||
dahdi_alarm_notify(&phonedev->span);
|
dahdi_alarm_notify(&phonedev->span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(xpp_span_assigned);
|
EXPORT_SYMBOL(xpp_span_assigned);
|
||||||
|
|
||||||
static const struct dahdi_span_ops xpp_span_ops = {
|
static const struct dahdi_span_ops xpp_span_ops = {
|
||||||
@ -984,7 +1020,8 @@ void xpd_set_spanname(xpd_t *xpd)
|
|||||||
{
|
{
|
||||||
struct dahdi_span *span = &PHONEDEV(xpd).span;
|
struct dahdi_span *span = &PHONEDEV(xpd).span;
|
||||||
|
|
||||||
snprintf(span->name, MAX_SPANNAME, "%s/%s", xpd->xbus->busname, xpd->xpdname);
|
snprintf(span->name, MAX_SPANNAME, "%s/%s", xpd->xbus->busname,
|
||||||
|
xpd->xpdname);
|
||||||
/*
|
/*
|
||||||
* The "Xorcom XPD" is a prefix in one of the regexes we
|
* The "Xorcom XPD" is a prefix in one of the regexes we
|
||||||
* use in our dahdi_genconf to match for PRI cards.
|
* use in our dahdi_genconf to match for PRI cards.
|
||||||
@ -994,6 +1031,7 @@ void xpd_set_spanname(xpd_t *xpd)
|
|||||||
snprintf(span->desc, MAX_SPANDESC, "Xorcom XPD [%s].%d: %s",
|
snprintf(span->desc, MAX_SPANDESC, "Xorcom XPD [%s].%d: %s",
|
||||||
xpd->xbus->label, span->offset + 1, xpd->type_name);
|
xpd->xbus->label, span->offset + 1, xpd->type_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(xpd_set_spanname);
|
EXPORT_SYMBOL(xpd_set_spanname);
|
||||||
|
|
||||||
static void xpd_init_span(xpd_t *xpd, unsigned offset, int cn)
|
static void xpd_init_span(xpd_t *xpd, unsigned offset, int cn)
|
||||||
@ -1093,9 +1131,11 @@ void xpd_dahdi_preunregister(xpd_t *xpd)
|
|||||||
int j;
|
int j;
|
||||||
|
|
||||||
dahdi_alarm_notify(&PHONEDEV(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");
|
XPD_DBG(DEVICES, xpd,
|
||||||
|
"Queuing DAHDI_EVENT_REMOVED on all channels to ask user to release them\n");
|
||||||
for (j = 0; j < PHONEDEV(xpd).span.channels; j++) {
|
for (j = 0; j < PHONEDEV(xpd).span.channels; j++) {
|
||||||
dahdi_qevent_lock(XPD_CHAN(xpd, j), DAHDI_EVENT_REMOVED);
|
dahdi_qevent_lock(XPD_CHAN(xpd, j),
|
||||||
|
DAHDI_EVENT_REMOVED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1128,8 +1168,8 @@ static int __init xpp_dahdi_init(void)
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
void *top = NULL;
|
void *top = NULL;
|
||||||
|
|
||||||
INFO("revision %s MAX_XPDS=%d (%d*%d)\n", XPP_VERSION,
|
INFO("revision %s MAX_XPDS=%d (%d*%d)\n", XPP_VERSION, MAX_XPDS,
|
||||||
MAX_XPDS, MAX_UNIT, MAX_SUBUNIT);
|
MAX_UNIT, MAX_SUBUNIT);
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
xpp_proc_toplevel = proc_mkdir(PROC_DIR, NULL);
|
xpp_proc_toplevel = proc_mkdir(PROC_DIR, NULL);
|
||||||
if (!xpp_proc_toplevel) {
|
if (!xpp_proc_toplevel) {
|
||||||
|
@ -30,15 +30,17 @@ int xpd_dahdi_preregister(xpd_t *xpd, unsigned offset);
|
|||||||
int xpd_dahdi_postregister(xpd_t *xpd);
|
int xpd_dahdi_postregister(xpd_t *xpd);
|
||||||
void xpd_dahdi_preunregister(xpd_t *xpd);
|
void xpd_dahdi_preunregister(xpd_t *xpd);
|
||||||
void xpd_dahdi_postunregister(xpd_t *xpd);
|
void xpd_dahdi_postunregister(xpd_t *xpd);
|
||||||
int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table,
|
int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table, int unit,
|
||||||
int unit, int subunit, __u8 type, __u8 subtype, int subunits, int subunit_ports, __u8 port_dir);
|
int subunit, __u8 type, __u8 subtype, int subunits,
|
||||||
xpd_t *xpd_alloc(xbus_t *xbus, int unit, int subunit, int subtype, int subunits, size_t privsize, const xproto_table_t *proto_table, int channels);
|
int subunit_ports, __u8 port_dir);
|
||||||
|
xpd_t *xpd_alloc(xbus_t *xbus, int unit, int subunit, int subtype, int subunits,
|
||||||
|
size_t privsize, const xproto_table_t *proto_table,
|
||||||
|
int channels);
|
||||||
void xpd_free(xpd_t *xpd);
|
void xpd_free(xpd_t *xpd);
|
||||||
void xpd_remove(xpd_t *xpd);
|
void xpd_remove(xpd_t *xpd);
|
||||||
void update_xpd_status(xpd_t *xpd, int alarm_flag);
|
void update_xpd_status(xpd_t *xpd, int alarm_flag);
|
||||||
const char *xpp_echocan_name(const struct dahdi_chan *chan);
|
const char *xpp_echocan_name(const struct dahdi_chan *chan);
|
||||||
int xpp_echocan_create(struct dahdi_chan *chan,
|
int xpp_echocan_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
|
||||||
struct dahdi_echocanparams *ecp,
|
|
||||||
struct dahdi_echocanparam *p,
|
struct dahdi_echocanparam *p,
|
||||||
struct dahdi_echocan_state **ec);
|
struct dahdi_echocan_state **ec);
|
||||||
void hookstate_changed(xpd_t *xpd, int pos, bool good);
|
void hookstate_changed(xpd_t *xpd, int pos, bool good);
|
||||||
|
@ -47,11 +47,11 @@ static const char rcsid[] = "$Id$";
|
|||||||
static DEF_PARM(int, debug, 0, 0644, "Print DBG statements"); /* must be before dahdi_debug.h */
|
static DEF_PARM(int, debug, 0, 0644, "Print DBG statements"); /* must be before dahdi_debug.h */
|
||||||
static DEF_PARM(int, usb1, 0, 0644, "Allow using USB 1.1 interfaces");
|
static DEF_PARM(int, usb1, 0, 0644, "Allow using USB 1.1 interfaces");
|
||||||
static DEF_PARM(uint, tx_sluggish, 2000, 0644, "A sluggish transmit (usec)");
|
static DEF_PARM(uint, tx_sluggish, 2000, 0644, "A sluggish transmit (usec)");
|
||||||
static DEF_PARM(uint, drop_pcm_after, 6, 0644, "Number of consecutive tx_sluggish to drop a PCM frame");
|
static DEF_PARM(uint, drop_pcm_after, 6, 0644,
|
||||||
|
"Number of consecutive tx_sluggish to drop a PCM frame");
|
||||||
|
|
||||||
#include "dahdi_debug.h"
|
#include "dahdi_debug.h"
|
||||||
|
|
||||||
|
|
||||||
#define XUSB_PRINTK(level, xusb, fmt, ...) \
|
#define XUSB_PRINTK(level, xusb, fmt, ...) \
|
||||||
printk(KERN_ ## level "%s-%s: xusb-%d (%s) [%s]: " fmt, #level, \
|
printk(KERN_ ## level "%s-%s: xusb-%d (%s) [%s]: " fmt, #level, \
|
||||||
THIS_MODULE->name, (xusb)->index, xusb->path, xusb->serial, ## __VA_ARGS__)
|
THIS_MODULE->name, (xusb)->index, xusb->path, xusb->serial, ## __VA_ARGS__)
|
||||||
@ -154,12 +154,8 @@ enum {
|
|||||||
static struct xusb_counters {
|
static struct xusb_counters {
|
||||||
char *name;
|
char *name;
|
||||||
} xusb_counters[] = {
|
} xusb_counters[] = {
|
||||||
C_(RX_FRAMES),
|
C_(RX_FRAMES), C_(TX_FRAMES), C_(RX_ERRORS), C_(TX_ERRORS),
|
||||||
C_(TX_FRAMES),
|
C_(RCV_ZERO_LEN),};
|
||||||
C_(RX_ERRORS),
|
|
||||||
C_(TX_ERRORS),
|
|
||||||
C_(RCV_ZERO_LEN),
|
|
||||||
};
|
|
||||||
|
|
||||||
#undef C_
|
#undef C_
|
||||||
|
|
||||||
@ -243,8 +239,8 @@ struct xusb {
|
|||||||
|
|
||||||
static DEFINE_SPINLOCK(xusb_lock);
|
static DEFINE_SPINLOCK(xusb_lock);
|
||||||
static xusb_t *xusb_array[MAX_BUSES] = { };
|
static xusb_t *xusb_array[MAX_BUSES] = { };
|
||||||
static unsigned bus_count;
|
|
||||||
|
|
||||||
|
static unsigned bus_count;
|
||||||
|
|
||||||
/* prevent races between open() and disconnect() */
|
/* prevent races between open() and disconnect() */
|
||||||
static DEFINE_SEMAPHORE(disconnect_sem);
|
static DEFINE_SEMAPHORE(disconnect_sem);
|
||||||
@ -263,10 +259,12 @@ static DEFINE_SEMAPHORE(disconnect_sem);
|
|||||||
|
|
||||||
static void xpp_send_callback(USB_PASS_CB(urb));
|
static void xpp_send_callback(USB_PASS_CB(urb));
|
||||||
static void xpp_receive_callback(USB_PASS_CB(urb));
|
static void xpp_receive_callback(USB_PASS_CB(urb));
|
||||||
static int xusb_probe (struct usb_interface *interface, const struct usb_device_id *id);
|
static int xusb_probe(struct usb_interface *interface,
|
||||||
|
const struct usb_device_id *id);
|
||||||
static void xusb_disconnect(struct usb_interface *interface);
|
static void xusb_disconnect(struct usb_interface *interface);
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
static int xusb_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data);
|
static int xusb_read_proc(char *page, char **start, off_t off, int count,
|
||||||
|
int *eof, void *data);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*------------------------------------------------------------------*/
|
/*------------------------------------------------------------------*/
|
||||||
@ -288,7 +286,8 @@ static void uframe_recompute(struct uframe *uframe, enum xusb_dir dir)
|
|||||||
: usb_sndbulkpipe(udev, epnum);
|
: usb_sndbulkpipe(udev, epnum);
|
||||||
|
|
||||||
BUG_ON(uframe->uframe_magic != UFRAME_MAGIC);
|
BUG_ON(uframe->uframe_magic != UFRAME_MAGIC);
|
||||||
usb_fill_bulk_urb(urb, udev, pipe, uframe->transfer_buffer, uframe->transfer_buffer_length, urb_cb, uframe);
|
usb_fill_bulk_urb(urb, udev, pipe, uframe->transfer_buffer,
|
||||||
|
uframe->transfer_buffer_length, urb_cb, uframe);
|
||||||
urb->transfer_flags = (URB_NO_TRANSFER_DMA_MAP | URB_ASYNC_UNLINK);
|
urb->transfer_flags = (URB_NO_TRANSFER_DMA_MAP | URB_ASYNC_UNLINK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,21 +305,27 @@ static xframe_t *alloc_xframe(xbus_t *xbus, gfp_t gfp_flags)
|
|||||||
if (!xusb->present) {
|
if (!xusb->present) {
|
||||||
if ((rate_limit++ % 1003) == 0)
|
if ((rate_limit++ % 1003) == 0)
|
||||||
XUSB_ERR(xusb,
|
XUSB_ERR(xusb,
|
||||||
"abort allocations during device disconnect (%d)\n", rate_limit);
|
"abort allocations during device disconnect (%d)\n",
|
||||||
|
rate_limit);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
size = min(xusb->endpoints[XUSB_SEND].max_size, xusb->endpoints[XUSB_RECV].max_size);
|
size =
|
||||||
|
min(xusb->endpoints[XUSB_SEND].max_size,
|
||||||
|
xusb->endpoints[XUSB_RECV].max_size);
|
||||||
uframe = kmem_cache_alloc(xusb_cache, gfp_flags);
|
uframe = kmem_cache_alloc(xusb_cache, gfp_flags);
|
||||||
if (!uframe) {
|
if (!uframe) {
|
||||||
if ((rate_limit++ % 1003) == 0)
|
if ((rate_limit++ % 1003) == 0)
|
||||||
XUSB_ERR(xusb, "frame allocation failed (%d)\n", rate_limit);
|
XUSB_ERR(xusb, "frame allocation failed (%d)\n",
|
||||||
|
rate_limit);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
usb_init_urb(&uframe->urb);
|
usb_init_urb(&uframe->urb);
|
||||||
p = usb_alloc_coherent(xusb->udev, size, gfp_flags, &uframe->urb.transfer_dma);
|
p = usb_alloc_coherent(xusb->udev, size, gfp_flags,
|
||||||
|
&uframe->urb.transfer_dma);
|
||||||
if (!p) {
|
if (!p) {
|
||||||
if ((rate_limit++ % 1003) == 0)
|
if ((rate_limit++ % 1003) == 0)
|
||||||
XUSB_ERR(xusb, "buffer allocation failed (%d)\n", rate_limit);
|
XUSB_ERR(xusb, "buffer allocation failed (%d)\n",
|
||||||
|
rate_limit);
|
||||||
kmem_cache_free(xusb_cache, uframe);
|
kmem_cache_free(xusb_cache, uframe);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -328,7 +333,8 @@ static xframe_t *alloc_xframe(xbus_t *xbus, gfp_t gfp_flags)
|
|||||||
uframe->transfer_buffer_length = size;
|
uframe->transfer_buffer_length = size;
|
||||||
uframe->transfer_buffer = p;
|
uframe->transfer_buffer = p;
|
||||||
uframe->xusb = xusb;
|
uframe->xusb = xusb;
|
||||||
xframe_init(xbus, &uframe->xframe, uframe->transfer_buffer, uframe->transfer_buffer_length, uframe);
|
xframe_init(xbus, &uframe->xframe, uframe->transfer_buffer,
|
||||||
|
uframe->transfer_buffer_length, uframe);
|
||||||
return &uframe->xframe;
|
return &uframe->xframe;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -340,8 +346,7 @@ static void free_xframe(xbus_t *xbus, xframe_t *xframe)
|
|||||||
BUG_ON(xbus->transport.priv != uframe->xusb);
|
BUG_ON(xbus->transport.priv != uframe->xusb);
|
||||||
//XUSB_INFO(uframe->xusb, "frame_free\n");
|
//XUSB_INFO(uframe->xusb, "frame_free\n");
|
||||||
usb_free_coherent(urb->dev, uframe->transfer_buffer_length,
|
usb_free_coherent(urb->dev, uframe->transfer_buffer_length,
|
||||||
urb->transfer_buffer,
|
urb->transfer_buffer, urb->transfer_dma);
|
||||||
urb->transfer_dma);
|
|
||||||
memset(uframe, 0, sizeof(*uframe));
|
memset(uframe, 0, sizeof(*uframe));
|
||||||
kmem_cache_free(xusb_cache, uframe);
|
kmem_cache_free(xusb_cache, uframe);
|
||||||
}
|
}
|
||||||
@ -367,7 +372,8 @@ static int do_send_xframe(xbus_t *xbus, xframe_t *xframe)
|
|||||||
|
|
||||||
if ((rate_limit++ % 1003) == 0)
|
if ((rate_limit++ % 1003) == 0)
|
||||||
XUSB_ERR(xusb,
|
XUSB_ERR(xusb,
|
||||||
"abort do_send_xframe during device disconnect (%d)\n", rate_limit);
|
"abort do_send_xframe during device disconnect (%d)\n",
|
||||||
|
rate_limit);
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
@ -490,12 +496,9 @@ static const struct xusb_model_info {
|
|||||||
struct xusb_endpoint out;
|
struct xusb_endpoint out;
|
||||||
} model_table[] = {
|
} model_table[] = {
|
||||||
[MODEL_FPGA_XPD] = {
|
[MODEL_FPGA_XPD] = {
|
||||||
.iface_num = 0,
|
.iface_num = 0,.in = {
|
||||||
.in = { .ep_addr = 0x86 },
|
.ep_addr = 0x86},.out = {
|
||||||
.out = { .ep_addr = 0x02 },
|
.ep_addr = 0x02},.desc = "FPGA_XPD"},};
|
||||||
.desc = "FPGA_XPD"
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
/* table of devices that work with this driver */
|
/* table of devices that work with this driver */
|
||||||
static const struct usb_device_id xusb_table[] = {
|
static const struct usb_device_id xusb_table[] = {
|
||||||
@ -508,7 +511,6 @@ static const struct usb_device_id xusb_table [] = {
|
|||||||
|
|
||||||
MODULE_DEVICE_TABLE(usb, xusb_table);
|
MODULE_DEVICE_TABLE(usb, xusb_table);
|
||||||
|
|
||||||
|
|
||||||
/* usb specific object needed to register this driver with the usb subsystem */
|
/* usb specific object needed to register this driver with the usb subsystem */
|
||||||
static struct usb_driver xusb_driver = {
|
static struct usb_driver xusb_driver = {
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
|
||||||
@ -568,17 +570,20 @@ static struct usb_class_driver xusb_class = {
|
|||||||
*/
|
*/
|
||||||
static int check_usb1(struct usb_endpoint_descriptor *endpoint)
|
static int check_usb1(struct usb_endpoint_descriptor *endpoint)
|
||||||
{
|
{
|
||||||
const char *msg = (usb_pipein(endpoint->bEndpointAddress))?"input":"output";
|
const char *msg =
|
||||||
|
(usb_pipein(endpoint->bEndpointAddress)) ? "input" : "output";
|
||||||
|
|
||||||
if (endpoint->wMaxPacketSize >= sizeof(xpacket_t))
|
if (endpoint->wMaxPacketSize >= sizeof(xpacket_t))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (usb1) {
|
if (usb1) {
|
||||||
NOTICE("USB1 endpoint detected: USB %s endpoint 0x%X support only wMaxPacketSize=%d.\n",
|
NOTICE
|
||||||
|
("USB1 endpoint detected: USB %s endpoint 0x%X support only wMaxPacketSize=%d.\n",
|
||||||
msg, endpoint->bEndpointAddress, endpoint->wMaxPacketSize);
|
msg, endpoint->bEndpointAddress, endpoint->wMaxPacketSize);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
NOTICE("USB1 endpoint detected. Device disabled. To enable: usb1=1, and read docs. (%s, endpoint %d, size %d).\n",
|
NOTICE
|
||||||
|
("USB1 endpoint detected. Device disabled. To enable: usb1=1, and read docs. (%s, endpoint %d, size %d).\n",
|
||||||
msg, endpoint->bEndpointAddress, endpoint->wMaxPacketSize);
|
msg, endpoint->bEndpointAddress, endpoint->wMaxPacketSize);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -588,7 +593,8 @@ static int check_usb1(struct usb_endpoint_descriptor *endpoint)
|
|||||||
* check out the endpoints
|
* check out the endpoints
|
||||||
* FIXME: Should be simplified (above 2.6.10) to use usb_dev->ep_in[0..16] and usb_dev->ep_out[0..16]
|
* FIXME: Should be simplified (above 2.6.10) to use usb_dev->ep_in[0..16] and usb_dev->ep_out[0..16]
|
||||||
*/
|
*/
|
||||||
static int set_endpoints(xusb_t *xusb, struct usb_host_interface *iface_desc, struct xusb_model_info *model_info)
|
static int set_endpoints(xusb_t *xusb, struct usb_host_interface *iface_desc,
|
||||||
|
struct xusb_model_info *model_info)
|
||||||
{
|
{
|
||||||
struct usb_endpoint_descriptor *endpoint;
|
struct usb_endpoint_descriptor *endpoint;
|
||||||
struct xusb_endpoint *xusb_ep;
|
struct xusb_endpoint *xusb_ep;
|
||||||
@ -602,7 +608,8 @@ static int set_endpoints(xusb_t *xusb, struct usb_host_interface *iface_desc, st
|
|||||||
ep_addr = endpoint->bEndpointAddress;
|
ep_addr = endpoint->bEndpointAddress;
|
||||||
|
|
||||||
if (!BULK_ENDPOINT(endpoint)) {
|
if (!BULK_ENDPOINT(endpoint)) {
|
||||||
DBG(DEVICES, "endpoint 0x%x is not bulk: mbAttributes=0x%X\n",
|
DBG(DEVICES,
|
||||||
|
"endpoint 0x%x is not bulk: mbAttributes=0x%X\n",
|
||||||
ep_addr, endpoint->bmAttributes);
|
ep_addr, endpoint->bmAttributes);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -626,11 +633,14 @@ static int set_endpoints(xusb_t *xusb, struct usb_host_interface *iface_desc, st
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!xusb->endpoints[XUSB_RECV].ep_addr || !xusb->endpoints[XUSB_SEND].ep_addr) {
|
if (!xusb->endpoints[XUSB_RECV].ep_addr
|
||||||
|
|| !xusb->endpoints[XUSB_SEND].ep_addr) {
|
||||||
XUSB_ERR(xusb, "Couldn't find bulk-in or bulk-out endpoints\n");
|
XUSB_ERR(xusb, "Couldn't find bulk-in or bulk-out endpoints\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
DBG(DEVICES, "in=0x%02X out=0x%02X\n", xusb->endpoints[XUSB_RECV].ep_addr, xusb->endpoints[XUSB_SEND].ep_addr);
|
DBG(DEVICES, "in=0x%02X out=0x%02X\n",
|
||||||
|
xusb->endpoints[XUSB_RECV].ep_addr,
|
||||||
|
xusb->endpoints[XUSB_SEND].ep_addr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -651,12 +661,15 @@ static int set_endpoints(xusb_t *xusb, struct usb_host_interface *iface_desc, st
|
|||||||
* Called by the usb core when a new device is connected that it thinks
|
* Called by the usb core when a new device is connected that it thinks
|
||||||
* this driver might be interested in.
|
* this driver might be interested in.
|
||||||
*/
|
*/
|
||||||
static int xusb_probe(struct usb_interface *interface, const struct usb_device_id *id)
|
static int xusb_probe(struct usb_interface *interface,
|
||||||
|
const struct usb_device_id *id)
|
||||||
{
|
{
|
||||||
struct usb_device *udev = interface_to_usbdev(interface);
|
struct usb_device *udev = interface_to_usbdev(interface);
|
||||||
struct usb_host_interface *iface_desc = usb_altnum_to_altsetting(interface, 0);
|
struct usb_host_interface *iface_desc =
|
||||||
|
usb_altnum_to_altsetting(interface, 0);
|
||||||
xusb_t *xusb = NULL;
|
xusb_t *xusb = NULL;
|
||||||
struct xusb_model_info *model_info = (struct xusb_model_info*)id->driver_info;
|
struct xusb_model_info *model_info =
|
||||||
|
(struct xusb_model_info *)id->driver_info;
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
struct proc_dir_entry *procsummary = NULL;
|
struct proc_dir_entry *procsummary = NULL;
|
||||||
#endif
|
#endif
|
||||||
@ -713,8 +726,8 @@ static int xusb_probe(struct usb_interface *interface, const struct usb_device_i
|
|||||||
USB_GET_STRING(udev, iProduct, xusb->product);
|
USB_GET_STRING(udev, iProduct, xusb->product);
|
||||||
USB_GET_IFACE_NAME(udev, iface_desc, xusb->interface_name);
|
USB_GET_IFACE_NAME(udev, iface_desc, xusb->interface_name);
|
||||||
#endif
|
#endif
|
||||||
INFO("XUSB: %s -- %s -- %s\n",
|
INFO("XUSB: %s -- %s -- %s\n", xusb->manufacturer, xusb->product,
|
||||||
xusb->manufacturer, xusb->product, xusb->interface_name);
|
xusb->interface_name);
|
||||||
|
|
||||||
/* allow device read, write and ioctl */
|
/* allow device read, write and ioctl */
|
||||||
xusb->present = 1;
|
xusb->present = 1;
|
||||||
@ -732,16 +745,18 @@ static int xusb_probe(struct usb_interface *interface, const struct usb_device_i
|
|||||||
|
|
||||||
/* let the user know what node this device is now attached to */
|
/* let the user know what node this device is now attached to */
|
||||||
DBG(DEVICES, "USB XPP device now attached to minor %d\n", xusb->minor);
|
DBG(DEVICES, "USB XPP device now attached to minor %d\n", xusb->minor);
|
||||||
xbus = xbus_new(&xusb_ops, min(xusb->endpoints[XUSB_SEND].max_size, xusb->endpoints[XUSB_RECV].max_size), &udev->dev, xusb);
|
xbus =
|
||||||
|
xbus_new(&xusb_ops,
|
||||||
|
min(xusb->endpoints[XUSB_SEND].max_size,
|
||||||
|
xusb->endpoints[XUSB_RECV].max_size), &udev->dev,
|
||||||
|
xusb);
|
||||||
if (!xbus) {
|
if (!xbus) {
|
||||||
retval = -ENOMEM;
|
retval = -ENOMEM;
|
||||||
goto probe_failed;
|
goto probe_failed;
|
||||||
}
|
}
|
||||||
snprintf(xbus->transport.model_string,
|
snprintf(xbus->transport.model_string,
|
||||||
ARRAY_SIZE(xbus->transport.model_string),
|
ARRAY_SIZE(xbus->transport.model_string), "usb:%04x/%04x/%x",
|
||||||
"usb:%04x/%04x/%x",
|
udev->descriptor.idVendor, udev->descriptor.idProduct,
|
||||||
udev->descriptor.idVendor,
|
|
||||||
udev->descriptor.idProduct,
|
|
||||||
udev->descriptor.bcdDevice);
|
udev->descriptor.bcdDevice);
|
||||||
spin_lock_irqsave(&xusb_lock, flags);
|
spin_lock_irqsave(&xusb_lock, flags);
|
||||||
for (i = 0; i < MAX_BUSES; i++) {
|
for (i = 0; i < MAX_BUSES; i++) {
|
||||||
@ -763,11 +778,14 @@ static int xusb_probe(struct usb_interface *interface, const struct usb_device_i
|
|||||||
XUSB_DBG(DEVICES, xusb, "GOT XPP USB BUS: %s\n", xbus->connector);
|
XUSB_DBG(DEVICES, xusb, "GOT XPP USB BUS: %s\n", xbus->connector);
|
||||||
|
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
DBG(PROC, "Creating proc entry " PROC_USBXPP_SUMMARY " in bus proc dir.\n");
|
DBG(PROC,
|
||||||
procsummary = create_proc_read_entry(PROC_USBXPP_SUMMARY, 0444, xbus->proc_xbus_dir,
|
"Creating proc entry " PROC_USBXPP_SUMMARY " in bus proc dir.\n");
|
||||||
xusb_read_proc, xusb);
|
procsummary =
|
||||||
|
create_proc_read_entry(PROC_USBXPP_SUMMARY, 0444,
|
||||||
|
xbus->proc_xbus_dir, xusb_read_proc, xusb);
|
||||||
if (!procsummary) {
|
if (!procsummary) {
|
||||||
XBUS_ERR(xbus, "Failed to create proc file '%s'\n", PROC_USBXPP_SUMMARY);
|
XBUS_ERR(xbus, "Failed to create proc file '%s'\n",
|
||||||
|
PROC_USBXPP_SUMMARY);
|
||||||
// FIXME: better error handling
|
// FIXME: better error handling
|
||||||
retval = -EIO;
|
retval = -EIO;
|
||||||
goto probe_failed;
|
goto probe_failed;
|
||||||
@ -795,8 +813,11 @@ probe_failed:
|
|||||||
if (xbus) {
|
if (xbus) {
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
if (procsummary) {
|
if (procsummary) {
|
||||||
XBUS_DBG(PROC, xbus, "Remove proc_entry: " PROC_USBXPP_SUMMARY "\n");
|
XBUS_DBG(PROC, xbus,
|
||||||
remove_proc_entry(PROC_USBXPP_SUMMARY, xbus->proc_xbus_dir);
|
"Remove proc_entry: " PROC_USBXPP_SUMMARY
|
||||||
|
"\n");
|
||||||
|
remove_proc_entry(PROC_USBXPP_SUMMARY,
|
||||||
|
xbus->proc_xbus_dir);
|
||||||
procsummary = NULL;
|
procsummary = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -819,12 +840,14 @@ probe_failed:
|
|||||||
*/
|
*/
|
||||||
static void xusb_disconnect(struct usb_interface *interface)
|
static void xusb_disconnect(struct usb_interface *interface)
|
||||||
{
|
{
|
||||||
struct usb_host_interface *iface_desc = usb_altnum_to_altsetting(interface, 0);
|
struct usb_host_interface *iface_desc =
|
||||||
|
usb_altnum_to_altsetting(interface, 0);
|
||||||
xusb_t *xusb;
|
xusb_t *xusb;
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
DBG(DEVICES, "CALLED on interface #%d\n", iface_desc->desc.bInterfaceNumber);
|
DBG(DEVICES, "CALLED on interface #%d\n",
|
||||||
|
iface_desc->desc.bInterfaceNumber);
|
||||||
/* prevent races with open() */
|
/* prevent races with open() */
|
||||||
down(&disconnect_sem);
|
down(&disconnect_sem);
|
||||||
|
|
||||||
@ -843,7 +866,8 @@ static void xusb_disconnect(struct usb_interface *interface)
|
|||||||
|
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
if (xbus->proc_xbus_dir) {
|
if (xbus->proc_xbus_dir) {
|
||||||
XBUS_DBG(PROC, xbus, "Remove proc_entry: " PROC_USBXPP_SUMMARY "\n");
|
XBUS_DBG(PROC, xbus,
|
||||||
|
"Remove proc_entry: " PROC_USBXPP_SUMMARY "\n");
|
||||||
remove_proc_entry(PROC_USBXPP_SUMMARY, xbus->proc_xbus_dir);
|
remove_proc_entry(PROC_USBXPP_SUMMARY, xbus->proc_xbus_dir);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -874,7 +898,8 @@ static void xpp_send_callback(USB_PASS_CB(urb))
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!xbus) {
|
if (!xbus) {
|
||||||
XUSB_ERR(xusb, "Sent URB does not belong to a valid xbus anymore...\n");
|
XUSB_ERR(xusb,
|
||||||
|
"Sent URB does not belong to a valid xbus anymore...\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//flip_parport_bit(6);
|
//flip_parport_bit(6);
|
||||||
@ -904,7 +929,8 @@ static void xpp_send_callback(USB_PASS_CB(urb))
|
|||||||
} else
|
} else
|
||||||
xusb->sluggish_debounce = 0;
|
xusb->sluggish_debounce = 0;
|
||||||
/* sync/async unlink faults aren't errors */
|
/* sync/async unlink faults aren't errors */
|
||||||
if (urb->status && !(urb->status == -ENOENT || urb->status == -ECONNRESET)) {
|
if (urb->status
|
||||||
|
&& !(urb->status == -ENOENT || urb->status == -ECONNRESET)) {
|
||||||
static int rate_limit;
|
static int rate_limit;
|
||||||
if ((rate_limit++ % 1000) < 10) {
|
if ((rate_limit++ % 1000) < 10) {
|
||||||
XUSB_ERR(xusb,
|
XUSB_ERR(xusb,
|
||||||
@ -933,7 +959,8 @@ static void xpp_receive_callback(USB_PASS_CB(urb))
|
|||||||
do_gettimeofday(&now);
|
do_gettimeofday(&now);
|
||||||
atomic_dec(&xusb->pending_reads);
|
atomic_dec(&xusb->pending_reads);
|
||||||
if (!xbus) {
|
if (!xbus) {
|
||||||
XUSB_ERR(xusb, "Received URB does not belong to a valid xbus anymore...\n");
|
XUSB_ERR(xusb,
|
||||||
|
"Received URB does not belong to a valid xbus anymore...\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!xusb->present) {
|
if (!xusb->present) {
|
||||||
@ -941,7 +968,8 @@ static void xpp_receive_callback(USB_PASS_CB(urb))
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if (urb->status) {
|
if (urb->status) {
|
||||||
DBG(GENERAL, "nonzero read bulk status received: %d\n", urb->status);
|
DBG(GENERAL, "nonzero read bulk status received: %d\n",
|
||||||
|
urb->status);
|
||||||
XUSB_COUNTER(xusb, RX_ERRORS)++;
|
XUSB_COUNTER(xusb, RX_ERRORS)++;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@ -950,7 +978,8 @@ static void xpp_receive_callback(USB_PASS_CB(urb))
|
|||||||
static int rate_limit;
|
static int rate_limit;
|
||||||
|
|
||||||
if ((rate_limit++ % 5003) == 0)
|
if ((rate_limit++ % 5003) == 0)
|
||||||
XUSB_NOTICE(xusb, "Received a zero length URBs (%d)\n", rate_limit);
|
XUSB_NOTICE(xusb, "Received a zero length URBs (%d)\n",
|
||||||
|
rate_limit);
|
||||||
XUSB_COUNTER(xusb, RCV_ZERO_LEN)++;
|
XUSB_COUNTER(xusb, RCV_ZERO_LEN)++;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@ -971,7 +1000,6 @@ err:
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*------------------------- Initialization -------------------------*/
|
/*------------------------- Initialization -------------------------*/
|
||||||
|
|
||||||
static void xpp_usb_cleanup(void)
|
static void xpp_usb_cleanup(void)
|
||||||
@ -988,8 +1016,8 @@ static int __init xpp_usb_init(void)
|
|||||||
//xusb_t *xusb;
|
//xusb_t *xusb;
|
||||||
|
|
||||||
INFO("revision %s\n", XPP_VERSION);
|
INFO("revision %s\n", XPP_VERSION);
|
||||||
xusb_cache = kmem_cache_create("xusb_cache",
|
xusb_cache =
|
||||||
sizeof(xframe_t) + XFRAME_DATASIZE,
|
kmem_cache_create("xusb_cache", sizeof(xframe_t) + XFRAME_DATASIZE,
|
||||||
#if (LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 22)) && defined(CONFIG_SLUB)
|
#if (LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 22)) && defined(CONFIG_SLUB)
|
||||||
0, SLAB_STORE_USER,
|
0, SLAB_STORE_USER,
|
||||||
#else
|
#else
|
||||||
@ -1016,7 +1044,6 @@ failure:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void __exit xpp_usb_shutdown(void)
|
static void __exit xpp_usb_shutdown(void)
|
||||||
{
|
{
|
||||||
DBG(GENERAL, "\n");
|
DBG(GENERAL, "\n");
|
||||||
@ -1025,11 +1052,10 @@ static void __exit xpp_usb_shutdown(void)
|
|||||||
xpp_usb_cleanup();
|
xpp_usb_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
|
|
||||||
static int xusb_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
|
static int xusb_read_proc(char *page, char **start, off_t off, int count,
|
||||||
|
int *eof, void *data)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
@ -1043,46 +1069,57 @@ static int xusb_read_proc(char *page, char **start, off_t off, int count, int *e
|
|||||||
goto out;
|
goto out;
|
||||||
// TODO: probably needs a per-xusb lock:
|
// TODO: probably needs a per-xusb lock:
|
||||||
spin_lock_irqsave(&xusb_lock, flags);
|
spin_lock_irqsave(&xusb_lock, flags);
|
||||||
len += sprintf(page + len, "Device: %03d/%03d\n",
|
len +=
|
||||||
xusb->udev->bus->busnum,
|
sprintf(page + len, "Device: %03d/%03d\n", xusb->udev->bus->busnum,
|
||||||
xusb->udev->devnum
|
xusb->udev->devnum);
|
||||||
);
|
len +=
|
||||||
len += sprintf(page + len, "USB: manufacturer=%s\n", xusb->manufacturer);
|
sprintf(page + len, "USB: manufacturer=%s\n", xusb->manufacturer);
|
||||||
len += sprintf(page + len, "USB: product=%s\n", xusb->product);
|
len += sprintf(page + len, "USB: product=%s\n", xusb->product);
|
||||||
len += sprintf(page + len, "USB: serial=%s\n", xusb->serial);
|
len += sprintf(page + len, "USB: serial=%s\n", xusb->serial);
|
||||||
len += sprintf(page + len, "Minor: %d\nModel Info: %s\n",
|
len +=
|
||||||
xusb->minor, xusb->model_info->desc);
|
sprintf(page + len, "Minor: %d\nModel Info: %s\n", xusb->minor,
|
||||||
len += sprintf(page + len, "Endpoints:\n"
|
xusb->model_info->desc);
|
||||||
"\tIn: 0x%02X - Size: %d)\n"
|
len +=
|
||||||
|
sprintf(page + len,
|
||||||
|
"Endpoints:\n" "\tIn: 0x%02X - Size: %d)\n"
|
||||||
"\tOut: 0x%02X - Size: %d)\n",
|
"\tOut: 0x%02X - Size: %d)\n",
|
||||||
xusb->endpoints[XUSB_RECV].ep_addr,
|
xusb->endpoints[XUSB_RECV].ep_addr,
|
||||||
xusb->endpoints[XUSB_RECV].max_size,
|
xusb->endpoints[XUSB_RECV].max_size,
|
||||||
xusb->endpoints[XUSB_SEND].ep_addr,
|
xusb->endpoints[XUSB_SEND].ep_addr,
|
||||||
xusb->endpoints[XUSB_SEND].max_size
|
xusb->endpoints[XUSB_SEND].max_size);
|
||||||
);
|
len +=
|
||||||
len += sprintf(page + len, "\npending_writes=%d\n", atomic_read(&xusb->pending_writes));
|
sprintf(page + len, "\npending_writes=%d\n",
|
||||||
len += sprintf(page + len, "pending_reads=%d\n", atomic_read(&xusb->pending_reads));
|
atomic_read(&xusb->pending_writes));
|
||||||
|
len +=
|
||||||
|
sprintf(page + len, "pending_reads=%d\n",
|
||||||
|
atomic_read(&xusb->pending_reads));
|
||||||
len += sprintf(page + len, "max_tx_delay=%d\n", xusb->max_tx_delay);
|
len += sprintf(page + len, "max_tx_delay=%d\n", xusb->max_tx_delay);
|
||||||
xusb->max_tx_delay = 0;
|
xusb->max_tx_delay = 0;
|
||||||
#ifdef DEBUG_PCM_TIMING
|
#ifdef DEBUG_PCM_TIMING
|
||||||
len += sprintf(page + len, "\nstamp_last_pcm_read=%lld accumulate_diff=%lld\n", stamp_last_pcm_read, accumulate_diff);
|
len +=
|
||||||
|
sprintf(page + len,
|
||||||
|
"\nstamp_last_pcm_read=%lld accumulate_diff=%lld\n",
|
||||||
|
stamp_last_pcm_read, accumulate_diff);
|
||||||
#endif
|
#endif
|
||||||
memcpy(usb_tx_delay, xusb->usb_tx_delay, sizeof(usb_tx_delay));
|
memcpy(usb_tx_delay, xusb->usb_tx_delay, sizeof(usb_tx_delay));
|
||||||
len += sprintf(page + len, "usb_tx_delay[%d,%d,%d]: ",
|
len +=
|
||||||
USEC_BUCKET, BUCKET_START, NUM_BUCKETS);
|
sprintf(page + len, "usb_tx_delay[%d,%d,%d]: ", USEC_BUCKET,
|
||||||
|
BUCKET_START, NUM_BUCKETS);
|
||||||
for (i = BUCKET_START; i < NUM_BUCKETS; i++) {
|
for (i = BUCKET_START; i < NUM_BUCKETS; i++) {
|
||||||
len += sprintf(page + len, "%6d ",
|
len += sprintf(page + len, "%6d ", usb_tx_delay[i]);
|
||||||
usb_tx_delay[i]);
|
|
||||||
if (i == mark_limit)
|
if (i == mark_limit)
|
||||||
len += sprintf(page + len, "| ");
|
len += sprintf(page + len, "| ");
|
||||||
}
|
}
|
||||||
len += sprintf(page + len, "\nPCM_TX_DROPS: %5d (sluggish: %d)\n",
|
len +=
|
||||||
|
sprintf(page + len, "\nPCM_TX_DROPS: %5d (sluggish: %d)\n",
|
||||||
atomic_read(&xusb->pcm_tx_drops),
|
atomic_read(&xusb->pcm_tx_drops),
|
||||||
atomic_read(&xusb->usb_sluggish_count)
|
atomic_read(&xusb->usb_sluggish_count)
|
||||||
);
|
);
|
||||||
len += sprintf(page + len, "\nCOUNTERS:\n");
|
len += sprintf(page + len, "\nCOUNTERS:\n");
|
||||||
for (i = 0; i < XUSB_COUNTER_MAX; i++) {
|
for (i = 0; i < XUSB_COUNTER_MAX; i++) {
|
||||||
len += sprintf(page + len, "\t%-15s = %d\n", xusb_counters[i].name, xusb->counters[i]);
|
len +=
|
||||||
|
sprintf(page + len, "\t%-15s = %d\n", xusb_counters[i].name,
|
||||||
|
xusb->counters[i]);
|
||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
len += sprintf(page + len, "<-- len=%d\n", len);
|
len += sprintf(page + len, "<-- len=%d\n", len);
|
||||||
@ -1103,8 +1140,6 @@ out:
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
MODULE_DESCRIPTION("XPP USB Transport Driver");
|
MODULE_DESCRIPTION("XPP USB Transport Driver");
|
||||||
MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");
|
MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
@ -40,12 +40,14 @@ static const xproto_table_t *xprotocol_tables[XPD_TYPE_NOMODULE];
|
|||||||
|
|
||||||
bool valid_xpd_addr(const struct xpd_addr *addr)
|
bool valid_xpd_addr(const struct xpd_addr *addr)
|
||||||
{
|
{
|
||||||
return ((addr->subunit & ~BITMASK(SUBUNIT_BITS)) == 0) && ((addr->unit & ~BITMASK(UNIT_BITS)) == 0);
|
return ((addr->subunit & ~BITMASK(SUBUNIT_BITS)) == 0)
|
||||||
|
&& ((addr->unit & ~BITMASK(UNIT_BITS)) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*---------------- General Protocol Management ----------------------------*/
|
/*---------------- General Protocol Management ----------------------------*/
|
||||||
|
|
||||||
const xproto_entry_t *xproto_card_entry(const xproto_table_t *table, __u8 opcode)
|
const xproto_entry_t *xproto_card_entry(const xproto_table_t *table,
|
||||||
|
__u8 opcode)
|
||||||
{
|
{
|
||||||
const xproto_entry_t *xe;
|
const xproto_entry_t *xe;
|
||||||
|
|
||||||
@ -85,7 +87,8 @@ const xproto_table_t *xproto_get(xpd_type_t cardtype)
|
|||||||
if (!xtable) { /* Try to load the relevant module */
|
if (!xtable) { /* Try to load the relevant module */
|
||||||
int ret = request_module(XPD_TYPE_PREFIX "%d", cardtype);
|
int ret = request_module(XPD_TYPE_PREFIX "%d", cardtype);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
NOTICE("%s: Failed to load module for type=%d. exit status=%d.\n",
|
NOTICE
|
||||||
|
("%s: Failed to load module for type=%d. exit status=%d.\n",
|
||||||
__func__, cardtype, ret);
|
__func__, cardtype, ret);
|
||||||
/* Drop through: we may be lucky... */
|
/* Drop through: we may be lucky... */
|
||||||
}
|
}
|
||||||
@ -94,10 +97,12 @@ const xproto_table_t *xproto_get(xpd_type_t cardtype)
|
|||||||
if (xtable) {
|
if (xtable) {
|
||||||
BUG_ON(!xtable->owner);
|
BUG_ON(!xtable->owner);
|
||||||
#ifdef CONFIG_MODULE_UNLOAD
|
#ifdef CONFIG_MODULE_UNLOAD
|
||||||
DBG(GENERAL, "%s refcount was %d\n", xtable->name, module_refcount(xtable->owner));
|
DBG(GENERAL, "%s refcount was %d\n", xtable->name,
|
||||||
|
module_refcount(xtable->owner));
|
||||||
#endif
|
#endif
|
||||||
if (!try_module_get(xtable->owner)) {
|
if (!try_module_get(xtable->owner)) {
|
||||||
ERR("%s: try_module_get for %s failed.\n", __func__, xtable->name);
|
ERR("%s: try_module_get for %s failed.\n", __func__,
|
||||||
|
xtable->name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,7 +113,8 @@ void xproto_put(const xproto_table_t *xtable)
|
|||||||
{
|
{
|
||||||
BUG_ON(!xtable);
|
BUG_ON(!xtable);
|
||||||
#ifdef CONFIG_MODULE_UNLOAD
|
#ifdef CONFIG_MODULE_UNLOAD
|
||||||
DBG(GENERAL, "%s refcount was %d\n", xtable->name, module_refcount(xtable->owner));
|
DBG(GENERAL, "%s refcount was %d\n", xtable->name,
|
||||||
|
module_refcount(xtable->owner));
|
||||||
BUG_ON(module_refcount(xtable->owner) <= 0);
|
BUG_ON(module_refcount(xtable->owner) <= 0);
|
||||||
#endif
|
#endif
|
||||||
module_put(xtable->owner);
|
module_put(xtable->owner);
|
||||||
@ -123,10 +129,11 @@ xproto_handler_t xproto_card_handler(const xproto_table_t *table, __u8 opcode)
|
|||||||
return xe->handler;
|
return xe->handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
void notify_bad_xpd(const char *funcname, xbus_t *xbus, const struct xpd_addr addr, const char *msg)
|
void notify_bad_xpd(const char *funcname, xbus_t *xbus,
|
||||||
|
const struct xpd_addr addr, const char *msg)
|
||||||
{
|
{
|
||||||
XBUS_NOTICE(xbus, "%s: non-existing address (%1d%1d): %s\n",
|
XBUS_NOTICE(xbus, "%s: non-existing address (%1d%1d): %s\n", funcname,
|
||||||
funcname, addr.unit, addr.subunit, msg);
|
addr.unit, addr.subunit, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int packet_process(xbus_t *xbus, xpacket_t *pack)
|
static int packet_process(xbus_t *xbus, xpacket_t *pack)
|
||||||
@ -142,14 +149,17 @@ static int packet_process(xbus_t *xbus, xpacket_t *pack)
|
|||||||
if (!valid_xpd_addr(&XPACKET_ADDR(pack))) {
|
if (!valid_xpd_addr(&XPACKET_ADDR(pack))) {
|
||||||
if (printk_ratelimit()) {
|
if (printk_ratelimit()) {
|
||||||
XBUS_NOTICE(xbus, "%s: from %d%d: bad address.\n",
|
XBUS_NOTICE(xbus, "%s: from %d%d: bad address.\n",
|
||||||
__func__,
|
__func__, XPACKET_ADDR_UNIT(pack),
|
||||||
XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack));
|
XPACKET_ADDR_SUBUNIT(pack));
|
||||||
dump_packet("packet_process -- bad address", pack, debug);
|
dump_packet("packet_process -- bad address", pack,
|
||||||
|
debug);
|
||||||
}
|
}
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
op = XPACKET_OP(pack);
|
op = XPACKET_OP(pack);
|
||||||
xpd = xpd_byaddr(xbus, XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack));
|
xpd =
|
||||||
|
xpd_byaddr(xbus, XPACKET_ADDR_UNIT(pack),
|
||||||
|
XPACKET_ADDR_SUBUNIT(pack));
|
||||||
/* XPD may be NULL (e.g: during bus polling */
|
/* XPD may be NULL (e.g: during bus polling */
|
||||||
xe = xproto_global_entry(op);
|
xe = xproto_global_entry(op);
|
||||||
/*-------- Validations -----------*/
|
/*-------- Validations -----------*/
|
||||||
@ -158,28 +168,32 @@ static int packet_process(xbus_t *xbus, xpacket_t *pack)
|
|||||||
|
|
||||||
if (!xpd) {
|
if (!xpd) {
|
||||||
if (printk_ratelimit()) {
|
if (printk_ratelimit()) {
|
||||||
XBUS_NOTICE(xbus, "%s: from %d%d opcode=0x%02X: no such global command.\n",
|
XBUS_NOTICE(xbus,
|
||||||
__func__,
|
"%s: from %d%d opcode=0x%02X: no such global command.\n",
|
||||||
XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack), op);
|
__func__, XPACKET_ADDR_UNIT(pack),
|
||||||
dump_packet("packet_process -- no such global command", pack, 1);
|
XPACKET_ADDR_SUBUNIT(pack), op);
|
||||||
|
dump_packet
|
||||||
|
("packet_process -- no such global command",
|
||||||
|
pack, 1);
|
||||||
}
|
}
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
xtable = xproto_table(xpd->type);
|
xtable = xproto_table(xpd->type);
|
||||||
if (!xtable) {
|
if (!xtable) {
|
||||||
if (printk_ratelimit())
|
if (printk_ratelimit())
|
||||||
XPD_ERR(xpd, "%s: no protocol table (type=%d)\n",
|
XPD_ERR(xpd,
|
||||||
__func__,
|
"%s: no protocol table (type=%d)\n",
|
||||||
xpd->type);
|
__func__, xpd->type);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
xe = xproto_card_entry(xtable, op);
|
xe = xproto_card_entry(xtable, op);
|
||||||
if (!xe) {
|
if (!xe) {
|
||||||
if (printk_ratelimit()) {
|
if (printk_ratelimit()) {
|
||||||
XPD_NOTICE(xpd, "%s: bad command (type=%d,opcode=0x%x)\n",
|
XPD_NOTICE(xpd,
|
||||||
__func__,
|
"%s: bad command (type=%d,opcode=0x%x)\n",
|
||||||
xpd->type, op);
|
__func__, xpd->type, op);
|
||||||
dump_packet("packet_process -- bad command", pack, 1);
|
dump_packet("packet_process -- bad command",
|
||||||
|
pack, 1);
|
||||||
}
|
}
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -190,7 +204,8 @@ static int packet_process(xbus_t *xbus, xpacket_t *pack)
|
|||||||
if (printk_ratelimit()) {
|
if (printk_ratelimit()) {
|
||||||
ERR("xpp: %s: wrong size %d for opcode=0x%02X\n",
|
ERR("xpp: %s: wrong size %d for opcode=0x%02X\n",
|
||||||
__func__, XPACKET_LEN(pack), op);
|
__func__, XPACKET_LEN(pack), op);
|
||||||
dump_packet("packet_process -- wrong size", pack, debug);
|
dump_packet("packet_process -- wrong size", pack,
|
||||||
|
debug);
|
||||||
}
|
}
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -223,8 +238,10 @@ static int xframe_receive_cmd(xbus_t *xbus, xframe_t *xframe)
|
|||||||
static int rate_limit;
|
static int rate_limit;
|
||||||
|
|
||||||
if ((rate_limit++ % 1003) == 0) {
|
if ((rate_limit++ % 1003) == 0) {
|
||||||
XBUS_DBG(GENERAL, xbus, "A PCM packet within a Non-PCM xframe\n");
|
XBUS_DBG(GENERAL, xbus,
|
||||||
dump_xframe("In Non-PCM xframe", xbus, xframe, debug);
|
"A PCM packet within a Non-PCM xframe\n");
|
||||||
|
dump_xframe("In Non-PCM xframe", xbus, xframe,
|
||||||
|
debug);
|
||||||
}
|
}
|
||||||
ret = -EPROTO;
|
ret = -EPROTO;
|
||||||
goto out;
|
goto out;
|
||||||
@ -234,7 +251,8 @@ static int xframe_receive_cmd(xbus_t *xbus, xframe_t *xframe)
|
|||||||
static int rate_limit;
|
static int rate_limit;
|
||||||
|
|
||||||
if ((rate_limit++ % 1003) == 0) {
|
if ((rate_limit++ % 1003) == 0) {
|
||||||
XBUS_NOTICE(xbus, "Invalid packet length %d\n", len);
|
XBUS_NOTICE(xbus, "Invalid packet length %d\n",
|
||||||
|
len);
|
||||||
dump_xframe("BAD LENGTH", xbus, xframe, debug);
|
dump_xframe("BAD LENGTH", xbus, xframe, debug);
|
||||||
}
|
}
|
||||||
ret = -EPROTO;
|
ret = -EPROTO;
|
||||||
@ -285,8 +303,9 @@ int xframe_receive(xbus_t *xbus, xframe_t *xframe)
|
|||||||
}
|
}
|
||||||
/* Calculate total processing time */
|
/* Calculate total processing time */
|
||||||
do_gettimeofday(&now);
|
do_gettimeofday(&now);
|
||||||
usec = (now.tv_sec - tv_received.tv_sec) * 1000000 +
|
usec =
|
||||||
now.tv_usec - tv_received.tv_usec;
|
(now.tv_sec - tv_received.tv_sec) * 1000000 + now.tv_usec -
|
||||||
|
tv_received.tv_usec;
|
||||||
if (usec > xbus->max_rx_process)
|
if (usec > xbus->max_rx_process)
|
||||||
xbus->max_rx_process = usec;
|
xbus->max_rx_process = usec;
|
||||||
return ret;
|
return ret;
|
||||||
@ -302,13 +321,9 @@ void dump_packet(const char *msg, const xpacket_t *packet, bool debug)
|
|||||||
|
|
||||||
if (!debug)
|
if (!debug)
|
||||||
return;
|
return;
|
||||||
printk(KERN_DEBUG "%s: XPD=%1X-%1X%c (0x%X) OP=0x%02X LEN=%d",
|
printk(KERN_DEBUG "%s: XPD=%1X-%1X%c (0x%X) OP=0x%02X LEN=%d", msg,
|
||||||
msg,
|
XPACKET_ADDR_UNIT(packet), XPACKET_ADDR_SUBUNIT(packet),
|
||||||
XPACKET_ADDR_UNIT(packet),
|
(XPACKET_ADDR_SYNC(packet)) ? '+' : ' ', *addr, op,
|
||||||
XPACKET_ADDR_SUBUNIT(packet),
|
|
||||||
(XPACKET_ADDR_SYNC(packet))?'+':' ',
|
|
||||||
*addr,
|
|
||||||
op,
|
|
||||||
XPACKET_LEN(packet));
|
XPACKET_LEN(packet));
|
||||||
#if VERBOSE_DEBUG
|
#if VERBOSE_DEBUG
|
||||||
{
|
{
|
||||||
@ -321,11 +336,9 @@ void dump_packet(const char *msg, const xpacket_t *packet, bool debug)
|
|||||||
|
|
||||||
if (i >= sizeof(xpacket_t)) {
|
if (i >= sizeof(xpacket_t)) {
|
||||||
if (limiter < ERR_REPORT_LIMIT) {
|
if (limiter < ERR_REPORT_LIMIT) {
|
||||||
ERR("%s: length overflow i=%d > sizeof(xpacket_t)=%lu\n",
|
ERR("%s: length overflow i=%d > sizeof(xpacket_t)=%lu\n", __func__, i + 1, (long)sizeof(xpacket_t));
|
||||||
__func__, i+1, (long)sizeof(xpacket_t));
|
|
||||||
} else if (limiter == ERR_REPORT_LIMIT) {
|
} else if (limiter == ERR_REPORT_LIMIT) {
|
||||||
ERR("%s: error packet #%d... squelsh reports.\n",
|
ERR("%s: error packet #%d... squelsh reports.\n", __func__, limiter);
|
||||||
__func__, limiter);
|
|
||||||
}
|
}
|
||||||
limiter++;
|
limiter++;
|
||||||
break;
|
break;
|
||||||
@ -338,8 +351,8 @@ void dump_packet(const char *msg, const xpacket_t *packet, bool debug)
|
|||||||
printk("\n");
|
printk("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump_reg_cmd(const char msg[], bool writing, xbus_t *xbus,
|
void dump_reg_cmd(const char msg[], bool writing, xbus_t *xbus, __u8 unit,
|
||||||
__u8 unit, xportno_t port, const reg_cmd_t *regcmd)
|
xportno_t port, const reg_cmd_t *regcmd)
|
||||||
{
|
{
|
||||||
char action;
|
char action;
|
||||||
char modifier;
|
char modifier;
|
||||||
@ -348,8 +361,9 @@ void dump_reg_cmd(const char msg[], bool writing, xbus_t *xbus,
|
|||||||
char data_buf[MAX_PROC_WRITE];
|
char data_buf[MAX_PROC_WRITE];
|
||||||
|
|
||||||
if (regcmd->bytes > sizeof(*regcmd) - 1) { /* The size byte is not included */
|
if (regcmd->bytes > sizeof(*regcmd) - 1) { /* The size byte is not included */
|
||||||
PORT_NOTICE(xbus, unit, port, "%s: %s: Too long: regcmd->bytes = %d\n",
|
PORT_NOTICE(xbus, unit, port,
|
||||||
__func__, msg, regcmd->bytes);
|
"%s: %s: Too long: regcmd->bytes = %d\n", __func__,
|
||||||
|
msg, regcmd->bytes);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (regcmd->is_multibyte) {
|
if (regcmd->is_multibyte) {
|
||||||
@ -361,27 +375,27 @@ void dump_reg_cmd(const char msg[], bool writing, xbus_t *xbus,
|
|||||||
|
|
||||||
buf[0] = '\0';
|
buf[0] = '\0';
|
||||||
for (i = 0; i < len && n < MAX_PROC_WRITE; i++)
|
for (i = 0; i < len && n < MAX_PROC_WRITE; i++)
|
||||||
n += snprintf(&buf[n], MAX_PROC_WRITE - n, "%02X ", p[i]);
|
n += snprintf(&buf[n], MAX_PROC_WRITE - n, "%02X ",
|
||||||
|
p[i]);
|
||||||
PORT_DBG(REGS, xbus, unit, port,
|
PORT_DBG(REGS, xbus, unit, port,
|
||||||
"UNIT-%d PORT-%d: Multibyte(eoframe=%d) %s[0..%zd]: %s%s\n",
|
"UNIT-%d PORT-%d: Multibyte(eoframe=%d) %s[0..%zd]: %s%s\n",
|
||||||
unit, port, regcmd->eoframe,
|
unit, port, regcmd->eoframe, msg, len - 1, buf,
|
||||||
msg, len-1, buf, (n >= MAX_PROC_WRITE)?"...":"");
|
(n >= MAX_PROC_WRITE) ? "..." : "");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (regcmd->bytes != sizeof(*regcmd) - 1) { /* The size byte is not included */
|
if (regcmd->bytes != sizeof(*regcmd) - 1) { /* The size byte is not included */
|
||||||
PORT_NOTICE(xbus, unit, port, "%s: %s: Wrong size: regcmd->bytes = %d\n",
|
PORT_NOTICE(xbus, unit, port,
|
||||||
|
"%s: %s: Wrong size: regcmd->bytes = %d\n",
|
||||||
__func__, msg, regcmd->bytes);
|
__func__, msg, regcmd->bytes);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
snprintf(port_buf, MAX_PROC_WRITE, "%d%s",
|
snprintf(port_buf, MAX_PROC_WRITE, "%d%s", regcmd->portnum,
|
||||||
regcmd->portnum,
|
|
||||||
(REG_FIELD(regcmd, all_ports_broadcast)) ? "*" : "");
|
(REG_FIELD(regcmd, all_ports_broadcast)) ? "*" : "");
|
||||||
action = (REG_FIELD(regcmd, read_request)) ? 'R' : 'W';
|
action = (REG_FIELD(regcmd, read_request)) ? 'R' : 'W';
|
||||||
modifier = 'D';
|
modifier = 'D';
|
||||||
if (REG_FIELD(regcmd, do_subreg)) {
|
if (REG_FIELD(regcmd, do_subreg)) {
|
||||||
snprintf(reg_buf, MAX_PROC_WRITE, "%02X %02X",
|
snprintf(reg_buf, MAX_PROC_WRITE, "%02X %02X",
|
||||||
REG_FIELD(regcmd, regnum),
|
REG_FIELD(regcmd, regnum), REG_FIELD(regcmd, subreg));
|
||||||
REG_FIELD(regcmd, subreg));
|
|
||||||
modifier = 'S';
|
modifier = 'S';
|
||||||
} else {
|
} else {
|
||||||
snprintf(reg_buf, MAX_PROC_WRITE, "%02X",
|
snprintf(reg_buf, MAX_PROC_WRITE, "%02X",
|
||||||
@ -391,16 +405,15 @@ void dump_reg_cmd(const char msg[], bool writing, xbus_t *xbus,
|
|||||||
data_buf[0] = '\0';
|
data_buf[0] = '\0';
|
||||||
} else if (REG_FIELD(regcmd, do_datah)) {
|
} else if (REG_FIELD(regcmd, do_datah)) {
|
||||||
snprintf(data_buf, MAX_PROC_WRITE, "%02X %02X",
|
snprintf(data_buf, MAX_PROC_WRITE, "%02X %02X",
|
||||||
REG_FIELD(regcmd, data_low),
|
REG_FIELD(regcmd, data_low), REG_FIELD(regcmd,
|
||||||
REG_FIELD(regcmd, data_high));
|
data_high));
|
||||||
modifier = 'I';
|
modifier = 'I';
|
||||||
} else {
|
} else {
|
||||||
snprintf(data_buf, MAX_PROC_WRITE, "%02X",
|
snprintf(data_buf, MAX_PROC_WRITE, "%02X",
|
||||||
REG_FIELD(regcmd, data_low));
|
REG_FIELD(regcmd, data_low));
|
||||||
}
|
}
|
||||||
PORT_DBG(REGS, xbus, unit, port, "%s: %s %c%c %s %s\n",
|
PORT_DBG(REGS, xbus, unit, port, "%s: %s %c%c %s %s\n", msg, port_buf,
|
||||||
msg, port_buf, action, modifier,
|
action, modifier, reg_buf, data_buf);
|
||||||
reg_buf, data_buf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *xproto_name(xpd_type_t xpd_type)
|
const char *xproto_name(xpd_type_t xpd_type)
|
||||||
@ -442,7 +455,8 @@ int xproto_register(const xproto_table_t *proto_table)
|
|||||||
}
|
}
|
||||||
DBG(GENERAL, "%s (%d)\n", name, type);
|
DBG(GENERAL, "%s (%d)\n", name, type);
|
||||||
if (xprotocol_tables[type])
|
if (xprotocol_tables[type])
|
||||||
NOTICE("%s: overriding registration of %s (%d)\n", __func__, name, type);
|
NOTICE("%s: overriding registration of %s (%d)\n", __func__,
|
||||||
|
name, type);
|
||||||
xops = proto_table->xops;
|
xops = proto_table->xops;
|
||||||
CHECK_XOP(xops, card_new);
|
CHECK_XOP(xops, card_new);
|
||||||
CHECK_XOP(xops, card_init);
|
CHECK_XOP(xops, card_init);
|
||||||
@ -481,7 +495,8 @@ void xproto_unregister(const xproto_table_t *proto_table)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!xprotocol_tables[type])
|
if (!xprotocol_tables[type])
|
||||||
NOTICE("%s: xproto type %s (%d) is already unregistered\n", __func__, name, type);
|
NOTICE("%s: xproto type %s (%d) is already unregistered\n",
|
||||||
|
__func__, name, type);
|
||||||
xprotocol_tables[type] = NULL;
|
xprotocol_tables[type] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,15 +200,13 @@ typedef struct reg_cmd {
|
|||||||
typedef struct xproto_entry xproto_entry_t;
|
typedef struct xproto_entry xproto_entry_t;
|
||||||
typedef struct xproto_table xproto_table_t;
|
typedef struct xproto_table xproto_table_t;
|
||||||
|
|
||||||
typedef int (*xproto_handler_t)(
|
typedef int (*xproto_handler_t) (xbus_t *xbus, xpd_t *xpd,
|
||||||
xbus_t *xbus,
|
const xproto_entry_t *cmd, xpacket_t *pack);
|
||||||
xpd_t *xpd,
|
|
||||||
const xproto_entry_t *cmd,
|
|
||||||
xpacket_t *pack);
|
|
||||||
|
|
||||||
const xproto_table_t *xproto_get(xpd_type_t cardtype);
|
const xproto_table_t *xproto_get(xpd_type_t cardtype);
|
||||||
void xproto_put(const xproto_table_t *xtable);
|
void xproto_put(const xproto_table_t *xtable);
|
||||||
const xproto_entry_t *xproto_card_entry(const xproto_table_t *table, __u8 opcode);
|
const xproto_entry_t *xproto_card_entry(const xproto_table_t *table,
|
||||||
|
__u8 opcode);
|
||||||
xproto_handler_t xproto_card_handler(const xproto_table_t *table, __u8 opcode);
|
xproto_handler_t xproto_card_handler(const xproto_table_t *table, __u8 opcode);
|
||||||
|
|
||||||
const xproto_entry_t *xproto_global_entry(__u8 opcode);
|
const xproto_entry_t *xproto_global_entry(__u8 opcode);
|
||||||
@ -240,7 +238,8 @@ struct phoneops {
|
|||||||
int (*card_dahdi_preregistration) (xpd_t *xpd, bool on);
|
int (*card_dahdi_preregistration) (xpd_t *xpd, bool on);
|
||||||
int (*card_dahdi_postregistration) (xpd_t *xpd, bool on);
|
int (*card_dahdi_postregistration) (xpd_t *xpd, bool on);
|
||||||
int (*card_hooksig) (xpd_t *xpd, int pos, enum dahdi_txsig txsig);
|
int (*card_hooksig) (xpd_t *xpd, int pos, enum dahdi_txsig txsig);
|
||||||
int (*card_ioctl)(xpd_t *xpd, int pos, unsigned int cmd, unsigned long arg);
|
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_open) (xpd_t *xpd, lineno_t pos);
|
||||||
int (*card_close) (xpd_t *xpd, lineno_t pos);
|
int (*card_close) (xpd_t *xpd, lineno_t pos);
|
||||||
int (*card_state) (xpd_t *xpd, bool on);
|
int (*card_state) (xpd_t *xpd, bool on);
|
||||||
@ -282,7 +281,6 @@ struct xproto_table {
|
|||||||
#include "card_bri.h"
|
#include "card_bri.h"
|
||||||
#include "card_pri.h"
|
#include "card_pri.h"
|
||||||
|
|
||||||
|
|
||||||
#define MEMBER(card, op) RPACKET_TYPE(card, op) RPACKET_NAME(card, op)
|
#define MEMBER(card, op) RPACKET_TYPE(card, op) RPACKET_NAME(card, op)
|
||||||
|
|
||||||
struct xpacket {
|
struct xpacket {
|
||||||
@ -303,9 +301,11 @@ struct xpacket {
|
|||||||
} PACKED;
|
} PACKED;
|
||||||
|
|
||||||
void dump_packet(const char *msg, const xpacket_t *packet, bool debug);
|
void dump_packet(const char *msg, const xpacket_t *packet, bool debug);
|
||||||
void dump_reg_cmd(const char msg[], bool writing, xbus_t *xbus, __u8 unit, xportno_t port, const reg_cmd_t *regcmd);
|
void dump_reg_cmd(const char msg[], bool writing, xbus_t *xbus, __u8 unit,
|
||||||
|
xportno_t port, const reg_cmd_t *regcmd);
|
||||||
int xframe_receive(xbus_t *xbus, xframe_t *xframe);
|
int xframe_receive(xbus_t *xbus, xframe_t *xframe);
|
||||||
void notify_bad_xpd(const char *funcname, xbus_t *xbus, const struct xpd_addr addr, const char *msg);
|
void notify_bad_xpd(const char *funcname, xbus_t *xbus,
|
||||||
|
const struct xpd_addr addr, const char *msg);
|
||||||
int xproto_register(const xproto_table_t *proto_table);
|
int xproto_register(const xproto_table_t *proto_table);
|
||||||
void xproto_unregister(const xproto_table_t *proto_table);
|
void xproto_unregister(const xproto_table_t *proto_table);
|
||||||
const xproto_entry_t *xproto_global_entry(__u8 opcode);
|
const xproto_entry_t *xproto_global_entry(__u8 opcode);
|
||||||
|
Loading…
Reference in New Issue
Block a user