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
File diff suppressed because it is too large
Load Diff
@ -25,7 +25,7 @@
|
|||||||
#include "xpd.h"
|
#include "xpd.h"
|
||||||
|
|
||||||
enum bri_opcodes {
|
enum bri_opcodes {
|
||||||
XPROTO_NAME(BRI, SET_LED) = 0x33,
|
XPROTO_NAME(BRI, SET_LED) = 0x33,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* CARD_BRI_H */
|
#endif /* CARD_BRI_H */
|
||||||
|
@ -42,25 +42,20 @@ 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 {
|
||||||
};
|
};
|
||||||
|
|
||||||
static xproto_table_t PROTO_TABLE(ECHO);
|
static xproto_table_t PROTO_TABLE(ECHO);
|
||||||
|
|
||||||
/*---------------- ECHO: Methods -------------------------------------------*/
|
/*---------------- ECHO: Methods -------------------------------------------*/
|
||||||
|
|
||||||
static xpd_t *ECHO_card_new(xbus_t *xbus, int unit, int subunit,
|
static xpd_t *ECHO_card_new(xbus_t *xbus, int unit, int subunit,
|
||||||
const xproto_table_t *proto_table, __u8 subtype,
|
const xproto_table_t *proto_table, __u8 subtype,
|
||||||
int subunits, int subunit_ports, bool to_phone)
|
int subunits, int subunit_ports, bool to_phone)
|
||||||
{
|
{
|
||||||
xpd_t *xpd = NULL;
|
xpd_t *xpd = NULL;
|
||||||
int channels = 0;
|
int channels = 0;
|
||||||
@ -70,8 +65,9 @@ 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 =
|
||||||
sizeof(struct ECHO_priv_data), proto_table, channels);
|
xpd_alloc(xbus, unit, subunit, subtype, subunits,
|
||||||
|
sizeof(struct ECHO_priv_data), proto_table, channels);
|
||||||
if (!xpd)
|
if (!xpd)
|
||||||
return NULL;
|
return NULL;
|
||||||
xpd->type_name = "ECHO";
|
xpd->type_name = "ECHO";
|
||||||
@ -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);
|
||||||
@ -198,7 +191,7 @@ static int ECHO_ec_set(xpd_t *xpd, int pos, bool on)
|
|||||||
ts[ts_number] &= ~ts_mask;
|
ts[ts_number] &= ~ts_mask;
|
||||||
}
|
}
|
||||||
LINE_DBG(GENERAL, xpd, pos, "%s = %d -- ts_number=%d ts_mask=0x%X\n",
|
LINE_DBG(GENERAL, xpd, pos, "%s = %d -- ts_number=%d ts_mask=0x%X\n",
|
||||||
__func__, on, ts_number, ts_mask);
|
__func__, on, ts_number, ts_mask);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,7 +213,7 @@ static int ECHO_ec_get(xpd_t *xpd, int pos)
|
|||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
LINE_DBG(GENERAL, xpd, pos, "ec_get=%d -- ts_number=%d ts_mask=0x%X\n",
|
LINE_DBG(GENERAL, xpd, pos, "ec_get=%d -- ts_number=%d ts_mask=0x%X\n",
|
||||||
is_on, ts_number, ts_mask);
|
is_on, ts_number, ts_mask);
|
||||||
#endif
|
#endif
|
||||||
return is_on;
|
return is_on;
|
||||||
}
|
}
|
||||||
@ -233,15 +226,14 @@ static void ECHO_ec_dump(xbus_t *xbus)
|
|||||||
ts = xbus->echo_state.timeslots;
|
ts = xbus->echo_state.timeslots;
|
||||||
for (i = 0; i + 15 < ECHO_TIMESLOTS; i += 16) {
|
for (i = 0; i + 15 < ECHO_TIMESLOTS; i += 16) {
|
||||||
XBUS_DBG(GENERAL, xbus,
|
XBUS_DBG(GENERAL, 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]
|
);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,7 +247,7 @@ static int ECHO_ec_update(xbus_t *xbus)
|
|||||||
/*---------------- ECHO: Astribank Reply Handlers --------------------------*/
|
/*---------------- ECHO: Astribank Reply Handlers --------------------------*/
|
||||||
HANDLER_DEF(ECHO, SET_REPLY)
|
HANDLER_DEF(ECHO, SET_REPLY)
|
||||||
{
|
{
|
||||||
__u8 status;
|
__u8 status;
|
||||||
|
|
||||||
BUG_ON(!xpd);
|
BUG_ON(!xpd);
|
||||||
status = RPACKET_FIELD(pack, ECHO, SET_REPLY, status);
|
status = RPACKET_FIELD(pack, ECHO, SET_REPLY, status);
|
||||||
@ -263,39 +255,32 @@ HANDLER_DEF(ECHO, SET_REPLY)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct xops echo_xops = {
|
static const struct xops echo_xops = {
|
||||||
.card_new = ECHO_card_new,
|
.card_new = ECHO_card_new,
|
||||||
.card_init = ECHO_card_init,
|
.card_init = ECHO_card_init,
|
||||||
.card_remove = ECHO_card_remove,
|
.card_remove = ECHO_card_remove,
|
||||||
.card_tick = ECHO_card_tick,
|
.card_tick = ECHO_card_tick,
|
||||||
.card_register_reply = ECHO_card_register_reply,
|
.card_register_reply = ECHO_card_register_reply,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct echoops echoops = {
|
static const struct echoops echoops = {
|
||||||
.ec_set = ECHO_ec_set,
|
.ec_set = ECHO_ec_set,
|
||||||
.ec_get = ECHO_ec_get,
|
.ec_get = ECHO_ec_get,
|
||||||
.ec_update = ECHO_ec_update,
|
.ec_update = ECHO_ec_update,
|
||||||
.ec_dump = ECHO_ec_dump,
|
.ec_dump = ECHO_ec_dump,
|
||||||
};
|
};
|
||||||
|
|
||||||
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),},.name = "ECHO",.ports_per_subunit =
|
||||||
XENTRY(ECHO, ECHO, SET_REPLY),
|
1,.type = XPD_TYPE_ECHO,.xops = &echo_xops,.echoops =
|
||||||
},
|
&echoops,.packet_is_valid =
|
||||||
.name = "ECHO",
|
echo_packet_is_valid,.packet_dump = echo_packet_dump,};
|
||||||
.ports_per_subunit = 1,
|
|
||||||
.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)
|
||||||
{
|
{
|
||||||
const xproto_entry_t *xe = NULL;
|
const xproto_entry_t *xe = NULL;
|
||||||
// DBG(GENERAL, "\n");
|
// DBG(GENERAL, "\n");
|
||||||
xe = xproto_card_entry(&PROTO_TABLE(ECHO), XPACKET_OP(pack));
|
xe = xproto_card_entry(&PROTO_TABLE(ECHO), XPACKET_OP(pack));
|
||||||
return xe != NULL;
|
return xe != NULL;
|
||||||
@ -309,14 +294,14 @@ static void echo_packet_dump(const char *msg, xpacket_t *pack)
|
|||||||
/*------------------------- sysfs stuff --------------------------------*/
|
/*------------------------- sysfs stuff --------------------------------*/
|
||||||
static int echo_xpd_probe(struct device *dev)
|
static int echo_xpd_probe(struct device *dev)
|
||||||
{
|
{
|
||||||
xpd_t *ec_xpd;
|
xpd_t *ec_xpd;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
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");
|
||||||
@ -325,23 +310,22 @@ static int echo_xpd_probe(struct device *dev)
|
|||||||
|
|
||||||
static int echo_xpd_remove(struct device *dev)
|
static int echo_xpd_remove(struct device *dev)
|
||||||
{
|
{
|
||||||
xpd_t *ec_xpd;
|
xpd_t *ec_xpd;
|
||||||
|
|
||||||
ec_xpd = dev_to_xpd(dev);
|
ec_xpd = dev_to_xpd(dev);
|
||||||
XPD_DBG(DEVICES, ec_xpd, "SYSFS\n");
|
XPD_DBG(DEVICES, ec_xpd, "SYSFS\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct xpd_driver echo_driver = {
|
static struct xpd_driver echo_driver = {
|
||||||
.type = XPD_TYPE_ECHO,
|
.type = XPD_TYPE_ECHO,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "echo",
|
.name = "echo",
|
||||||
#ifndef OLD_HOTPLUG_SUPPORT
|
#ifndef OLD_HOTPLUG_SUPPORT
|
||||||
.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)
|
||||||
|
@ -24,8 +24,8 @@
|
|||||||
#include "xpd.h"
|
#include "xpd.h"
|
||||||
|
|
||||||
enum echo_opcodes {
|
enum echo_opcodes {
|
||||||
XPROTO_NAME(ECHO, SET) = 0x39,
|
XPROTO_NAME(ECHO, SET) = 0x39,
|
||||||
XPROTO_NAME(ECHO, SET_REPLY) = 0x3A,
|
XPROTO_NAME(ECHO, SET_REPLY) = 0x3A,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* CARD_ECHO_H */
|
#endif /* CARD_ECHO_H */
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -25,17 +25,14 @@
|
|||||||
#include "xpd.h"
|
#include "xpd.h"
|
||||||
|
|
||||||
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 */
|
||||||
|
xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */
|
||||||
|
);
|
||||||
|
|
||||||
DEF_RPACKET_DATA(FXO, SIG_CHANGED,
|
#endif /* CARD_FXO_H */
|
||||||
xpp_line_t sig_status; /* channels: lsb=1, msb=8 */
|
|
||||||
xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */
|
|
||||||
);
|
|
||||||
|
|
||||||
#endif /* CARD_FXO_H */
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -25,17 +25,14 @@
|
|||||||
#include "xpd.h"
|
#include "xpd.h"
|
||||||
|
|
||||||
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 */
|
||||||
|
xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */
|
||||||
|
);
|
||||||
|
|
||||||
DEF_RPACKET_DATA(FXS, SIG_CHANGED,
|
#endif /* CARD_FXS_H */
|
||||||
xpp_line_t sig_status; /* channels: lsb=1, msb=8 */
|
|
||||||
xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */
|
|
||||||
);
|
|
||||||
|
|
||||||
#endif /* CARD_FXS_H */
|
|
||||||
|
@ -32,21 +32,22 @@
|
|||||||
|
|
||||||
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"
|
||||||
|
|
||||||
extern int debug;
|
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;
|
||||||
reg_cmd_t *reg_cmd;
|
reg_cmd_t *reg_cmd;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Zero length multibyte is legal and has special meaning for the
|
* Zero length multibyte is legal and has special meaning for the
|
||||||
@ -65,15 +66,15 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_hexbyte(const char *buf)
|
static int parse_hexbyte(const char *buf)
|
||||||
{
|
{
|
||||||
char *endp;
|
char *endp;
|
||||||
unsigned val;
|
unsigned val;
|
||||||
|
|
||||||
val = simple_strtoul(buf, &endp, 16);
|
val = simple_strtoul(buf, &endp, 16);
|
||||||
if (*endp != '\0' || val > 0xFF)
|
if (*endp != '\0' || val > 0xFF)
|
||||||
@ -83,26 +84,26 @@ static int parse_hexbyte(const char *buf)
|
|||||||
|
|
||||||
static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
|
static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int argno;
|
int argno;
|
||||||
char num_args;
|
char num_args;
|
||||||
int portno;
|
int portno;
|
||||||
bool writing;
|
bool writing;
|
||||||
int op; /* [W]rite, [R]ead */
|
int op; /* [W]rite, [R]ead */
|
||||||
int addr_mode; /* [D]irect, [I]ndirect, [Mm]ulti */
|
int addr_mode; /* [D]irect, [I]ndirect, [Mm]ulti */
|
||||||
bool do_subreg = 0;
|
bool do_subreg = 0;
|
||||||
int regnum;
|
int regnum;
|
||||||
int subreg;
|
int subreg;
|
||||||
int data_low;
|
int data_low;
|
||||||
bool do_datah;
|
bool do_datah;
|
||||||
int data_high;
|
int data_high;
|
||||||
int ret = -EBADR;
|
int ret = -EBADR;
|
||||||
|
|
||||||
num_args = 2; /* port + operation */
|
num_args = 2; /* port + operation */
|
||||||
if (argc < num_args) {
|
if (argc < num_args) {
|
||||||
XPD_ERR(xpd, "Not enough arguments (%d)\n", argc);
|
XPD_ERR(xpd, "Not enough arguments (%d)\n", argc);
|
||||||
XPD_ERR(xpd,
|
XPD_ERR(xpd,
|
||||||
"Any Command is composed of at least %d words (got only %d)\n",
|
"Any Command is composed of at least %d words (got only %d)\n",
|
||||||
num_args, argc);
|
num_args, argc);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
/* Process the arguments */
|
/* Process the arguments */
|
||||||
@ -125,47 +126,49 @@ static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
op = argv[argno][0];
|
op = argv[argno][0];
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case 'W':
|
case 'W':
|
||||||
writing = 1;
|
writing = 1;
|
||||||
num_args++; /* data low */
|
num_args++; /* data low */
|
||||||
//XPD_DBG(REGS, xpd, "WRITING\n");
|
//XPD_DBG(REGS, xpd, "WRITING\n");
|
||||||
break;
|
break;
|
||||||
case 'R':
|
case 'R':
|
||||||
writing = 0;
|
writing = 0;
|
||||||
//XPD_DBG(REGS, xpd, "READING\n");
|
//XPD_DBG(REGS, xpd, "READING\n");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
XPD_ERR(xpd, "Unknown operation type '%c'\n", op);
|
XPD_ERR(xpd, "Unknown operation type '%c'\n", op);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
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,
|
||||||
/* fall through */
|
"'I' is deprecated in register commands. Use 'S' instead.\n");
|
||||||
case 'S':
|
/* fall through */
|
||||||
do_subreg = 1;
|
case 'S':
|
||||||
num_args += 2; /* register + subreg */
|
do_subreg = 1;
|
||||||
//XPD_DBG(REGS, xpd, "SUBREG\n");
|
num_args += 2; /* register + subreg */
|
||||||
break;
|
//XPD_DBG(REGS, xpd, "SUBREG\n");
|
||||||
case 'D':
|
break;
|
||||||
do_subreg = 0;
|
case 'D':
|
||||||
num_args++; /* register */
|
do_subreg = 0;
|
||||||
//XPD_DBG(REGS, xpd, "DIRECT\n");
|
num_args++; /* register */
|
||||||
break;
|
//XPD_DBG(REGS, xpd, "DIRECT\n");
|
||||||
case 'M':
|
break;
|
||||||
case 'm':
|
case 'M':
|
||||||
if (op != 'W') {
|
case 'm':
|
||||||
XPD_ERR(xpd,
|
if (op != 'W') {
|
||||||
"Can use Multibyte (%c) only with op 'W'\n", addr_mode);
|
XPD_ERR(xpd,
|
||||||
goto out;
|
"Can use Multibyte (%c) only with op 'W'\n",
|
||||||
}
|
addr_mode);
|
||||||
num_args--; /* No data low */
|
|
||||||
//XPD_DBG(REGS, xpd, "Multibyte (%c)\n", addr_mode);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
XPD_ERR(xpd, "Unknown addressing type '%c'\n", addr_mode);
|
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
|
num_args--; /* No data low */
|
||||||
|
//XPD_DBG(REGS, xpd, "Multibyte (%c)\n", addr_mode);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
XPD_ERR(xpd, "Unknown addressing type '%c'\n", addr_mode);
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
if (argv[argno][2] != '\0') {
|
if (argv[argno][2] != '\0') {
|
||||||
XPD_ERR(xpd, "Bad operation field '%s'\n", argv[argno]);
|
XPD_ERR(xpd, "Bad operation field '%s'\n", argv[argno]);
|
||||||
@ -173,20 +176,21 @@ static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
if (argc < num_args) {
|
if (argc < num_args) {
|
||||||
XPD_ERR(xpd,
|
XPD_ERR(xpd,
|
||||||
"Command \"%s\" is composed of at least %d words (got only %d)\n",
|
"Command \"%s\" is composed of at least %d words (got only %d)\n",
|
||||||
argv[argno], num_args, argc);
|
argv[argno], num_args, argc);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
argno++;
|
argno++;
|
||||||
if (addr_mode == 'M' || addr_mode == 'm') {
|
if (addr_mode == 'M' || addr_mode == 'm') {
|
||||||
if (argno < argc) {
|
if (argno < argc) {
|
||||||
XPD_ERR(xpd,
|
XPD_ERR(xpd,
|
||||||
"Magic-Multibyte(%c) with %d extra arguments\n",
|
"Magic-Multibyte(%c) with %d extra arguments\n",
|
||||||
addr_mode, argc - argno);
|
addr_mode, argc - argno);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
ret = send_magic_request(xpd->xbus, xpd->addr.unit, portno,
|
ret =
|
||||||
addr_mode == 'm');
|
send_magic_request(xpd->xbus, xpd->addr.unit, portno,
|
||||||
|
addr_mode == 'm');
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
/* Normal (non-Magic) register commands */
|
/* Normal (non-Magic) register commands */
|
||||||
@ -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,41 +253,37 @@ 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",
|
writing, /* writing */
|
||||||
portno, /* portno */
|
regnum, do_subreg, /* use subreg */
|
||||||
writing, /* writing */
|
subreg, /* subreg */
|
||||||
regnum,
|
data_low, do_datah, /* use data_high */
|
||||||
do_subreg, /* use subreg */
|
data_high);
|
||||||
subreg, /* subreg */
|
|
||||||
data_low,
|
|
||||||
do_datah, /* use 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
int parse_chip_command(xpd_t *xpd, char *cmdline)
|
int parse_chip_command(xpd_t *xpd, char *cmdline)
|
||||||
{
|
{
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
int ret = -EBADR;
|
int ret = -EBADR;
|
||||||
__u8 buf[MAX_PROC_WRITE];
|
__u8 buf[MAX_PROC_WRITE];
|
||||||
char *str;
|
char *str;
|
||||||
char *p;
|
char *p;
|
||||||
static const int MAX_ARGS = 10;
|
static const int MAX_ARGS = 10;
|
||||||
char *argv[MAX_ARGS + 1];
|
char *argv[MAX_ARGS + 1];
|
||||||
int argc;
|
int argc;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
BUG_ON(!xpd);
|
BUG_ON(!xpd);
|
||||||
xbus = xpd->xbus;
|
xbus = xpd->xbus;
|
||||||
@ -295,10 +298,10 @@ int parse_chip_command(xpd_t *xpd, char *cmdline)
|
|||||||
*p = '\0';
|
*p = '\0';
|
||||||
if ((p = strchr(buf, ';')) != NULL) /* Truncate comments */
|
if ((p = strchr(buf, ';')) != NULL) /* Truncate comments */
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
for (p = buf; *p && (*p == ' ' || *p == '\t'); p++) /* Trim leading whitespace */
|
for (p = buf; *p && (*p == ' ' || *p == '\t'); p++) /* Trim leading whitespace */
|
||||||
;
|
;
|
||||||
str = p;
|
str = p;
|
||||||
for (i = 0; (p = strsep(&str, " \t")) != NULL && i < MAX_ARGS; ) {
|
for (i = 0; (p = strsep(&str, " \t")) != NULL && i < MAX_ARGS;) {
|
||||||
if (*p != '\0') {
|
if (*p != '\0') {
|
||||||
argv[i] = p;
|
argv[i] = p;
|
||||||
// XPD_DBG(REGS, xpd, "ARG %d = '%s'\n", i, p);
|
// XPD_DBG(REGS, xpd, "ARG %d = '%s'\n", i, p);
|
||||||
@ -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)
|
||||||
@ -328,9 +332,9 @@ static void global_packet_dump(const char *msg, xpacket_t *pack);
|
|||||||
|
|
||||||
/* 0x07 */ HOSTCMD(GLOBAL, AB_REQUEST)
|
/* 0x07 */ HOSTCMD(GLOBAL, AB_REQUEST)
|
||||||
{
|
{
|
||||||
int ret = -ENODEV;
|
int ret = -ENODEV;
|
||||||
xframe_t *xframe;
|
xframe_t *xframe;
|
||||||
xpacket_t *pack;
|
xpacket_t *pack;
|
||||||
|
|
||||||
if (!xbus) {
|
if (!xbus) {
|
||||||
DBG(DEVICES, "NO XBUS\n");
|
DBG(DEVICES, "NO XBUS\n");
|
||||||
@ -348,23 +352,24 @@ 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;
|
||||||
xpacket_t *pack;
|
xpacket_t *pack;
|
||||||
reg_cmd_t *reg_cmd;
|
reg_cmd_t *reg_cmd;
|
||||||
|
|
||||||
if (!xbus) {
|
if (!xbus) {
|
||||||
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 */
|
||||||
@ -405,9 +411,9 @@ int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
|
|||||||
*/
|
*/
|
||||||
/* 0x19 */ HOSTCMD(GLOBAL, SYNC_SOURCE, enum sync_mode mode, int drift)
|
/* 0x19 */ HOSTCMD(GLOBAL, SYNC_SOURCE, enum sync_mode mode, int drift)
|
||||||
{
|
{
|
||||||
xframe_t *xframe;
|
xframe_t *xframe;
|
||||||
xpacket_t *pack;
|
xpacket_t *pack;
|
||||||
const char *mode_name;
|
const char *mode_name;
|
||||||
|
|
||||||
BUG_ON(!xbus);
|
BUG_ON(!xbus);
|
||||||
if ((mode_name = sync_mode_name(mode)) == NULL) {
|
if ((mode_name = sync_mode_name(mode)) == NULL) {
|
||||||
@ -424,8 +430,8 @@ int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
|
|||||||
|
|
||||||
/* 0x23 */ HOSTCMD(GLOBAL, RESET_SYNC_COUNTERS)
|
/* 0x23 */ HOSTCMD(GLOBAL, RESET_SYNC_COUNTERS)
|
||||||
{
|
{
|
||||||
xframe_t *xframe;
|
xframe_t *xframe;
|
||||||
xpacket_t *pack;
|
xpacket_t *pack;
|
||||||
|
|
||||||
BUG_ON(!xbus);
|
BUG_ON(!xbus);
|
||||||
//XBUS_DBG(SYNC, xbus, "\n");
|
//XBUS_DBG(SYNC, xbus, "\n");
|
||||||
@ -443,14 +449,14 @@ 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;
|
||||||
int count_units;
|
int count_units;
|
||||||
int i;
|
int i;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (!xbus) {
|
if (!xbus) {
|
||||||
NOTICE("%s: xbus is gone!!!\n", __func__);
|
NOTICE("%s: xbus is gone!!!\n", __func__);
|
||||||
@ -462,19 +468,18 @@ HANDLER_DEF(GLOBAL, AB_DESCRIPTION) /* 0x08 */
|
|||||||
count_units /= sizeof(*units);
|
count_units /= sizeof(*units);
|
||||||
if (rev != XPP_PROTOCOL_VERSION) {
|
if (rev != XPP_PROTOCOL_VERSION) {
|
||||||
XBUS_NOTICE(xbus, "Bad protocol version %d (should be %d)\n",
|
XBUS_NOTICE(xbus, "Bad protocol version %d (should be %d)\n",
|
||||||
rev, XPP_PROTOCOL_VERSION);
|
rev, XPP_PROTOCOL_VERSION);
|
||||||
ret = -EPROTO;
|
ret = -EPROTO;
|
||||||
goto proto_err;
|
goto proto_err;
|
||||||
}
|
}
|
||||||
if (count_units > NUM_UNITS) {
|
if (count_units > NUM_UNITS) {
|
||||||
XBUS_NOTICE(xbus, "Too many units %d (should be %d)\n",
|
XBUS_NOTICE(xbus, "Too many units %d (should be %d)\n",
|
||||||
count_units, NUM_UNITS);
|
count_units, NUM_UNITS);
|
||||||
ret = -EPROTO;
|
ret = -EPROTO;
|
||||||
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;
|
||||||
@ -493,11 +499,13 @@ HANDLER_DEF(GLOBAL, AB_DESCRIPTION) /* 0x08 */
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
for (i = 0; i < count_units; i++) {
|
for (i = 0; i < count_units; i++) {
|
||||||
struct unit_descriptor *this_unit = &units[i];
|
struct unit_descriptor *this_unit = &units[i];
|
||||||
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)++;
|
||||||
@ -539,21 +545,23 @@ out:
|
|||||||
|
|
||||||
HANDLER_DEF(GLOBAL, REGISTER_REPLY)
|
HANDLER_DEF(GLOBAL, REGISTER_REPLY)
|
||||||
{
|
{
|
||||||
reg_cmd_t *reg = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REPLY, regcmd);
|
reg_cmd_t *reg = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REPLY, regcmd);
|
||||||
|
|
||||||
if (!xpd) {
|
if (!xpd) {
|
||||||
static int rate_limit;
|
static int rate_limit;
|
||||||
|
|
||||||
if ((rate_limit++ % 1003) < 5)
|
if ((rate_limit++ % 1003) < 5)
|
||||||
notify_bad_xpd(__func__, xbus, XPACKET_ADDR(pack), "");
|
notify_bad_xpd(__func__, xbus, XPACKET_ADDR(pack), "");
|
||||||
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);
|
||||||
@ -561,9 +569,9 @@ HANDLER_DEF(GLOBAL, REGISTER_REPLY)
|
|||||||
|
|
||||||
HANDLER_DEF(GLOBAL, SYNC_REPLY)
|
HANDLER_DEF(GLOBAL, SYNC_REPLY)
|
||||||
{
|
{
|
||||||
__u8 mode = RPACKET_FIELD(pack, GLOBAL, SYNC_REPLY, sync_mode);
|
__u8 mode = RPACKET_FIELD(pack, GLOBAL, SYNC_REPLY, sync_mode);
|
||||||
__u8 drift = RPACKET_FIELD(pack, GLOBAL, SYNC_REPLY, drift);
|
__u8 drift = RPACKET_FIELD(pack, GLOBAL, SYNC_REPLY, drift);
|
||||||
const char *mode_name;
|
const char *mode_name;
|
||||||
|
|
||||||
BUG_ON(!xbus);
|
BUG_ON(!xbus);
|
||||||
if ((mode_name = sync_mode_name(mode)) == NULL) {
|
if ((mode_name = sync_mode_name(mode)) == NULL) {
|
||||||
@ -580,10 +588,10 @@ HANDLER_DEF(GLOBAL, SYNC_REPLY)
|
|||||||
|
|
||||||
HANDLER_DEF(GLOBAL, ERROR_CODE)
|
HANDLER_DEF(GLOBAL, ERROR_CODE)
|
||||||
{
|
{
|
||||||
char tmp_name[TMP_NAME_LEN];
|
char tmp_name[TMP_NAME_LEN];
|
||||||
static long rate_limit;
|
static long rate_limit;
|
||||||
__u8 category_code;
|
__u8 category_code;
|
||||||
__u8 errorbits;
|
__u8 errorbits;
|
||||||
|
|
||||||
BUG_ON(!xbus);
|
BUG_ON(!xbus);
|
||||||
if ((rate_limit++ % 5003) > 200)
|
if ((rate_limit++ % 5003) > 200)
|
||||||
@ -592,12 +600,14 @@ HANDLER_DEF(GLOBAL, ERROR_CODE)
|
|||||||
errorbits = RPACKET_FIELD(pack, GLOBAL, ERROR_CODE, errorbits);
|
errorbits = RPACKET_FIELD(pack, GLOBAL, ERROR_CODE, errorbits);
|
||||||
if (!xpd) {
|
if (!xpd) {
|
||||||
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
|
||||||
tmp_name, cmd->name, category_code, errorbits, rate_limit);
|
("%s: FIRMWARE %s: category=%d errorbits=0x%02X (rate_limit=%ld)\n",
|
||||||
|
tmp_name, cmd->name, category_code, errorbits, rate_limit);
|
||||||
dump_packet("FIRMWARE: ", pack, 1);
|
dump_packet("FIRMWARE: ", pack, 1);
|
||||||
/*
|
/*
|
||||||
* FIXME: Should implement an error recovery plan
|
* FIXME: Should implement an error recovery plan
|
||||||
@ -605,24 +615,20 @@ 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)
|
||||||
{
|
{
|
||||||
const xproto_entry_t *xe;
|
const xproto_entry_t *xe;
|
||||||
|
|
||||||
//DBG(GENERAL, "\n");
|
//DBG(GENERAL, "\n");
|
||||||
xe = xproto_global_entry(XPACKET_OP(pack));
|
xe = xproto_global_entry(XPACKET_OP(pack));
|
||||||
@ -638,26 +644,26 @@ static void global_packet_dump(const char *msg, xpacket_t *pack)
|
|||||||
|
|
||||||
int run_initialize_registers(xpd_t *xpd)
|
int run_initialize_registers(xpd_t *xpd)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
char busstr[MAX_ENV_STR];
|
char busstr[MAX_ENV_STR];
|
||||||
char busnumstr[MAX_ENV_STR];
|
char busnumstr[MAX_ENV_STR];
|
||||||
char modelstr[MAX_ENV_STR];
|
char modelstr[MAX_ENV_STR];
|
||||||
char unitstr[MAX_ENV_STR];
|
char unitstr[MAX_ENV_STR];
|
||||||
char subunitsstr[MAX_ENV_STR];
|
char subunitsstr[MAX_ENV_STR];
|
||||||
char typestr[MAX_ENV_STR];
|
char typestr[MAX_ENV_STR];
|
||||||
char directionstr[MAX_ENV_STR];
|
char directionstr[MAX_ENV_STR];
|
||||||
char revstr[MAX_ENV_STR];
|
char revstr[MAX_ENV_STR];
|
||||||
char connectorstr[MAX_ENV_STR];
|
char connectorstr[MAX_ENV_STR];
|
||||||
char xbuslabel[MAX_ENV_STR];
|
char xbuslabel[MAX_ENV_STR];
|
||||||
char init_card[MAX_PATH_STR];
|
char init_card[MAX_PATH_STR];
|
||||||
__u8 direction_mask;
|
__u8 direction_mask;
|
||||||
int i;
|
int i;
|
||||||
char *argv[] = {
|
char *argv[] = {
|
||||||
init_card,
|
init_card,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
char *envp[] = {
|
char *envp[] = {
|
||||||
busstr,
|
busstr,
|
||||||
busnumstr,
|
busnumstr,
|
||||||
modelstr,
|
modelstr,
|
||||||
@ -684,40 +690,47 @@ int run_initialize_registers(xpd_t *xpd)
|
|||||||
}
|
}
|
||||||
direction_mask = 0;
|
direction_mask = 0;
|
||||||
for (i = 0; i < xpd->subunits; i++) {
|
for (i = 0; i < xpd->subunits; i++) {
|
||||||
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,
|
||||||
xbus_statename(XBUS_STATE(xbus)));
|
"Skipped register initialization. In state %s.\n",
|
||||||
|
xbus_statename(XBUS_STATE(xbus)));
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
XPD_DBG(DEVICES, xpd, "running '%s' for type=%d revision=%d\n",
|
XPD_DBG(DEVICES, xpd, "running '%s' for type=%d revision=%d\n",
|
||||||
init_card, xpd->type, xbus->revision);
|
init_card, xpd->type, xbus->revision);
|
||||||
ret = call_usermodehelper(init_card, argv, envp, 1);
|
ret = call_usermodehelper(init_card, argv, envp, 1);
|
||||||
/*
|
/*
|
||||||
* Carefully report results
|
* Carefully report results
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -26,88 +26,59 @@
|
|||||||
#include "xbus-pcm.h"
|
#include "xbus-pcm.h"
|
||||||
|
|
||||||
enum global_opcodes {
|
enum global_opcodes {
|
||||||
XPROTO_NAME(GLOBAL, AB_REQUEST) = 0x07,
|
XPROTO_NAME(GLOBAL, AB_REQUEST) = 0x07,
|
||||||
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_REPLY) = 0x1A,
|
||||||
XPROTO_NAME(GLOBAL, SYNC_SOURCE) = 0x19,
|
/**/ XPROTO_NAME(GLOBAL, ERROR_CODE) = 0x22,
|
||||||
XPROTO_NAME(GLOBAL, SYNC_REPLY) = 0x1A,
|
XPROTO_NAME(GLOBAL, RESET_SYNC_COUNTERS) = 0x23,
|
||||||
/**/
|
XPROTO_NAME(GLOBAL, NULL_REPLY) = 0xFE,
|
||||||
XPROTO_NAME(GLOBAL, ERROR_CODE) = 0x22,
|
|
||||||
XPROTO_NAME(GLOBAL, RESET_SYNC_COUNTERS) = 0x23,
|
|
||||||
XPROTO_NAME(GLOBAL, NULL_REPLY) = 0xFE,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct unit_descriptor {
|
struct unit_descriptor {
|
||||||
struct xpd_addr addr;
|
struct xpd_addr addr;
|
||||||
__u8 subtype:4;
|
__u8 subtype:4;
|
||||||
__u8 type:4;
|
__u8 type:4;
|
||||||
__u8 numchips;
|
__u8 numchips;
|
||||||
__u8 ports_per_chip;
|
__u8 ports_per_chip;
|
||||||
__u8 port_dir; /* bitmask: 0 - PSTN, 1 - PHONE */
|
__u8 port_dir; /* bitmask: 0 - PSTN, 1 - PHONE */
|
||||||
__u8 reserved[2];
|
__u8 reserved[2];
|
||||||
struct xpd_addr ec_addr;
|
struct xpd_addr ec_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#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);
|
||||||
/* 0x23 */ DECLARE_CMD(GLOBAL, RESET_SYNC_COUNTERS);
|
/* 0x23 */ DECLARE_CMD(GLOBAL, RESET_SYNC_COUNTERS);
|
||||||
|
|
||||||
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);
|
||||||
int run_initialize_registers(xpd_t *xpd);
|
int run_initialize_registers(xpd_t *xpd);
|
||||||
int parse_chip_command(xpd_t *xpd, char *cmdline);
|
int parse_chip_command(xpd_t *xpd, char *cmdline);
|
||||||
extern charp initdir;
|
extern charp initdir;
|
||||||
|
|
||||||
#endif /* CARD_GLOBAL_H */
|
#endif /* CARD_GLOBAL_H */
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -25,8 +25,7 @@
|
|||||||
#include "xpd.h"
|
#include "xpd.h"
|
||||||
|
|
||||||
enum pri_opcodes {
|
enum pri_opcodes {
|
||||||
XPROTO_NAME(PRI, SET_LED) = 0x33,
|
XPROTO_NAME(PRI, SET_LED) = 0x33,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif /* CARD_PRI_H */
|
||||||
#endif /* CARD_PRI_H */
|
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
|
||||||
# warning "This module is tested only with 2.6 kernels"
|
#warning "This module is tested only with 2.6 kernels"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
@ -35,28 +35,20 @@
|
|||||||
static const char rcsid[] = "$Id$";
|
static const char rcsid[] = "$Id$";
|
||||||
|
|
||||||
#define P_(x) [ x ] = { .value = x, .name = #x, }
|
#define P_(x) [ x ] = { .value = x, .name = #x, }
|
||||||
static struct {
|
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)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(poll_names); i++) {
|
for (i = 0; i < ARRAY_SIZE(poll_names); i++) {
|
||||||
if (poll & poll_names[i].value)
|
if (poll & poll_names[i].value)
|
||||||
@ -66,10 +58,10 @@ void dump_poll(int debug, const char *msg, int poll)
|
|||||||
|
|
||||||
void alarm2str(int alarm, char *buf, int buflen)
|
void alarm2str(int alarm, char *buf, int buflen)
|
||||||
{
|
{
|
||||||
char *p = buf;
|
char *p = buf;
|
||||||
int left = buflen;
|
int left = buflen;
|
||||||
int i;
|
int i;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
if (!alarm) {
|
if (!alarm) {
|
||||||
snprintf(buf, buflen, "NONE");
|
snprintf(buf, buflen, "NONE");
|
||||||
@ -83,7 +75,7 @@ void alarm2str(int alarm, char *buf, int buflen)
|
|||||||
left -= n;
|
left -= n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (p > buf) /* kill last comma */
|
if (p > buf) /* kill last comma */
|
||||||
*(p - 1) = '\0';
|
*(p - 1) = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,25 +194,42 @@ 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:
|
||||||
case DAHDI_SIG_NONE:
|
return "Clear";
|
||||||
break;
|
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:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return "Unconfigured";
|
return "Unconfigured";
|
||||||
}
|
}
|
||||||
@ -186,17 +238,24 @@ 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";
|
||||||
}
|
}
|
||||||
|
|
||||||
void alarm2str(int alarm, char *buf, int buflen);
|
void alarm2str(int alarm, char *buf, int buflen);
|
||||||
|
|
||||||
#endif /* DAHDI_DEBUG_H */
|
#endif /* DAHDI_DEBUG_H */
|
||||||
|
@ -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,11 +19,13 @@
|
|||||||
#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()
|
||||||
|
|
||||||
//#define AB_IN_BUF PF5
|
//#define AB_IN_BUF PF5
|
||||||
/* firmware pins */
|
/* firmware pins */
|
||||||
#define DATA PG8
|
#define DATA PG8
|
||||||
#define NCONFIG PG9
|
#define NCONFIG PG9
|
||||||
@ -39,7 +41,7 @@ typedef char sizeof_xframe_t_should_be_divisible_by_4[((sizeof(xframe_t) % 4) ==
|
|||||||
#define DEBUG_GPIO1 CONF_DONE
|
#define DEBUG_GPIO1 CONF_DONE
|
||||||
#define DEBUG_GPIO2 NSTATUS
|
#define DEBUG_GPIO2 NSTATUS
|
||||||
|
|
||||||
static int rx_intr_counter;
|
static int rx_intr_counter;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define FPGA_RX_IRQ IRQ_PF7
|
#define FPGA_RX_IRQ IRQ_PF7
|
||||||
@ -49,9 +51,9 @@ static int rx_intr_counter;
|
|||||||
#define END_OF_FRAME 0x0001
|
#define END_OF_FRAME 0x0001
|
||||||
#define GET_LEN 0x0002
|
#define GET_LEN 0x0002
|
||||||
#define START_RD_BURST 0x0008
|
#define START_RD_BURST 0x0008
|
||||||
#define AS_BF_MODE 0x0010 //stand alone Astribank without USB (Asterisk BlackFin Mode)
|
#define AS_BF_MODE 0x0010 //stand alone Astribank without USB (Asterisk BlackFin Mode)
|
||||||
#define EC_BF_MODE 0x0020 //all data between Astribank and USB routed thru BF(EchoCanceler BlackFin Mode)
|
#define EC_BF_MODE 0x0020 //all data between Astribank and USB routed thru BF(EchoCanceler BlackFin Mode)
|
||||||
#define NO_BF_MODE 0x0040 //Astribank worke with USB only (no BlackFin Mode)
|
#define NO_BF_MODE 0x0040 //Astribank worke with USB only (no BlackFin Mode)
|
||||||
#define SET_XA_DIR 0x0080
|
#define SET_XA_DIR 0x0080
|
||||||
#define GET_XPD_STS 0x0100
|
#define GET_XPD_STS 0x0100
|
||||||
#define GET_CHECKSUM 0x0200
|
#define GET_CHECKSUM 0x0200
|
||||||
@ -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++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,18 +156,19 @@ static irqreturn_t xpp_mmap_rx_irq(int irq, void *dev_id)
|
|||||||
outw(START_RD_BURST, FPGA_BASE_ADDR + 4);
|
outw(START_RD_BURST, FPGA_BASE_ADDR + 4);
|
||||||
insw((unsigned long)FPGA_BASE_ADDR, buf, rxcnt / 2);
|
insw((unsigned long)FPGA_BASE_ADDR, buf, rxcnt / 2);
|
||||||
#if 0
|
#if 0
|
||||||
for (count = 0; count < rxcnt; count+=2) {
|
for (count = 0; count < rxcnt; count += 2) {
|
||||||
unsigned short v = inw(FPGA_BASE_ADDR);
|
unsigned short v = inw(FPGA_BASE_ADDR);
|
||||||
buf[count] = v & 0xFF;
|
buf[count] = v & 0xFF;
|
||||||
buf[count+1] = v >> 8;
|
buf[count + 1] = v >> 8;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (rxcnt & 1)
|
if (rxcnt & 1)
|
||||||
buf[rxcnt-1] = inw(FPGA_BASE_ADDR);
|
buf[rxcnt - 1] = inw(FPGA_BASE_ADDR);
|
||||||
/* 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;
|
||||||
@ -199,7 +203,7 @@ static void send_buffer(unsigned char *buf, unsigned long len)
|
|||||||
print_buffer("Sent: ", buf, len);
|
print_buffer("Sent: ", buf, len);
|
||||||
outsw((unsigned long)FPGA_BASE_ADDR, buf, len / 2);
|
outsw((unsigned long)FPGA_BASE_ADDR, buf, len / 2);
|
||||||
if (len & 1)
|
if (len & 1)
|
||||||
outw((unsigned short)buf[len-1], FPGA_BASE_ADDR);
|
outw((unsigned short)buf[len - 1], FPGA_BASE_ADDR);
|
||||||
outw(END_OF_FRAME, FPGA_BASE_ADDR + 4);
|
outw(END_OF_FRAME, FPGA_BASE_ADDR + 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,28 +325,26 @@ static struct xbus_ops xmmap_ops = {
|
|||||||
|
|
||||||
static int fill_proc_queue(char *p, struct xframe_queue *q)
|
static int fill_proc_queue(char *p, struct xframe_queue *q)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
len = sprintf(p,
|
len =
|
||||||
"%-15s: counts %3d, %3d, %3d worst %3d, overflows %3d worst_lag %02ld.%ld ms\n",
|
sprintf(p,
|
||||||
q->name,
|
"%-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->max_count,
|
||||||
q->count,
|
q->worst_count, q->overflows, q->worst_lag_usec / 1000,
|
||||||
q->max_count,
|
q->worst_lag_usec % 1000);
|
||||||
q->worst_count,
|
|
||||||
q->overflows,
|
|
||||||
q->worst_lag_usec / 1000,
|
|
||||||
q->worst_lag_usec % 1000);
|
|
||||||
xframe_queue_clearstats(q);
|
xframe_queue_clearstats(q);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
@ -347,7 +354,7 @@ static int xpp_mmap_proc_read(char *page, char **start, off_t off, int count, in
|
|||||||
len += fill_proc_counter(page + len, &rx_counter);
|
len += fill_proc_counter(page + len, &rx_counter);
|
||||||
len += sprintf(page + len, "\ntx_counter:\n");
|
len += sprintf(page + len, "\ntx_counter:\n");
|
||||||
len += fill_proc_counter(page + len, &tx_counter);
|
len += fill_proc_counter(page + len, &tx_counter);
|
||||||
if (len <= off+count) {
|
if (len <= off + count) {
|
||||||
*eof = 1;
|
*eof = 1;
|
||||||
tx_counter.intr_min = rx_counter.intr_min = INT_MAX;
|
tx_counter.intr_min = rx_counter.intr_min = INT_MAX;
|
||||||
tx_counter.intr_max = rx_counter.intr_max = 0;
|
tx_counter.intr_max = rx_counter.intr_max = 0;
|
||||||
@ -363,14 +370,15 @@ 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;
|
||||||
|
|
||||||
if (count >= XFRAME_DATASIZE*3+10)
|
if (count >= XFRAME_DATASIZE * 3 + 10)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
p = txchunk = kmalloc(count+1, GFP_KERNEL);
|
p = txchunk = kmalloc(count + 1, GFP_KERNEL);
|
||||||
if (copy_from_user(txchunk, buffer, count)) {
|
if (copy_from_user(txchunk, buffer, count)) {
|
||||||
count = -EFAULT;
|
count = -EFAULT;
|
||||||
goto out;
|
goto out;
|
||||||
@ -379,13 +387,15 @@ 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__);
|
||||||
count = -EINVAL;
|
count = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
p = endp;
|
p = endp;
|
||||||
txchunk[i++] = (char)value;
|
txchunk[i++] = (char)value;
|
||||||
@ -399,8 +409,8 @@ out:
|
|||||||
static struct mmap_driver astribank_driver = {
|
static struct mmap_driver astribank_driver = {
|
||||||
.module = THIS_MODULE,
|
.module = THIS_MODULE,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "xpp_mmap",
|
.name = "xpp_mmap",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct mmap_device astribank_dev = {
|
static struct mmap_device astribank_dev = {
|
||||||
@ -408,42 +418,43 @@ static struct mmap_device astribank_dev = {
|
|||||||
.driver = &astribank_driver,
|
.driver = &astribank_driver,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init xpp_mmap_load_fpga(u8 *data, size_t size)
|
static int __init xpp_mmap_load_fpga(u8 * data, size_t size)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
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
|
||||||
udelay(40); //Tcfg ~40us delay
|
udelay(40); //Tcfg ~40us delay
|
||||||
bfin_write_PORTGIO_SET(NCONFIG); //transition nCONFIG to high - reset end.
|
bfin_write_PORTGIO_SET(NCONFIG); //transition nCONFIG to high - reset end.
|
||||||
udelay(40); //Tcf2ck ~40us delay
|
udelay(40); //Tcf2ck ~40us delay
|
||||||
if (!(bfin_read_PORTGIO() & NSTATUS))
|
if (!(bfin_read_PORTGIO() & NSTATUS))
|
||||||
return -EIO; //report reset faill - Tcf2st1 pass
|
return -EIO; //report reset faill - Tcf2st1 pass
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
if (!(bfin_read_PORTGIO() & CONF_DONE))
|
if (!(bfin_read_PORTGIO() & CONF_DONE))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
#endif
|
#endif
|
||||||
bfin_write_PORTGIO_CLEAR(DCLK);
|
bfin_write_PORTGIO_CLEAR(DCLK);
|
||||||
for (i=0; i<size; i++) { // loop EP2OUT buffer data to FPGA
|
for (i = 0; i < size; i++) { // loop EP2OUT buffer data to FPGA
|
||||||
int j;
|
int j;
|
||||||
u8 __u8 = data[i];
|
u8 __u8 = data[i];
|
||||||
for (j=0; j<8; j++) //send the configuration data through the DATA0 pin one bit at a time.
|
for (j = 0; j < 8; j++) //send the configuration data through the DATA0 pin one bit at a time.
|
||||||
{
|
{
|
||||||
if (__u8 & 1)
|
if (__u8 &1)
|
||||||
bfin_write_PORTGIO_SET(DATA);
|
bfin_write_PORTGIO_SET(DATA);
|
||||||
else
|
else
|
||||||
bfin_write_PORTGIO_CLEAR(DATA);
|
bfin_write_PORTGIO_CLEAR(DATA);
|
||||||
__u8 >>= 1;
|
__u8 >>=1;
|
||||||
bfin_write_PORTGIO_SET(DCLK);
|
bfin_write_PORTGIO_SET(DCLK);
|
||||||
bfin_write_PORTGIO_CLEAR(DCLK);
|
bfin_write_PORTGIO_CLEAR(DCLK);
|
||||||
}
|
}
|
||||||
if (!(bfin_read_PORTGIO() & NSTATUS))
|
if (!(bfin_read_PORTGIO() & NSTATUS))
|
||||||
return -EIO; //check the nSTATUS
|
return -EIO; //check the nSTATUS
|
||||||
}
|
}
|
||||||
bfin_write_PORTGIO_CLEAR(DATA);
|
bfin_write_PORTGIO_CLEAR(DATA);
|
||||||
udelay(1);
|
udelay(1);
|
||||||
@ -455,20 +466,22 @@ static int __init xpp_mmap_load_fpga(u8 *data, size_t size)
|
|||||||
* some pins that were used only during initialization
|
* some pins that were used only during initialization
|
||||||
* 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit xpp_mmap_unload_fpga(void)
|
static void __exit xpp_mmap_unload_fpga(void)
|
||||||
{
|
{
|
||||||
bfin_write_PORTGIO_CLEAR(NCONFIG); //reset fpga during configuration holds nCONFIG low
|
bfin_write_PORTGIO_CLEAR(NCONFIG); //reset fpga during configuration holds nCONFIG low
|
||||||
udelay(40); //Tcfg ~40us delay
|
udelay(40); //Tcfg ~40us delay
|
||||||
bfin_write_PORTGIO_DIR(bfin_read_PORTGIO_DIR() & ~( DATA | NCONFIG | DCLK)); //disable output pin
|
bfin_write_PORTGIO_DIR(bfin_read_PORTGIO_DIR() & ~(DATA | NCONFIG | DCLK)); //disable output pin
|
||||||
bfin_write_PORTGIO_INEN(bfin_read_PORTGIO_INEN() & ~( CONF_DONE | NSTATUS));//disable input buffer
|
bfin_write_PORTGIO_INEN(bfin_read_PORTGIO_INEN() & ~(CONF_DONE | NSTATUS)); //disable input buffer
|
||||||
INFO("FPGA Firmware unloaded\n");
|
INFO("FPGA Firmware unloaded\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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,27 +513,31 @@ 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;
|
||||||
}
|
}
|
||||||
if (!request_region((resource_size_t)FPGA_BASE_ADDR, 8, "xpp_mmap")) {
|
if (!request_region((resource_size_t) FPGA_BASE_ADDR, 8, "xpp_mmap")) {
|
||||||
ERR("Unable to request memory region at %p\n", FPGA_BASE_ADDR);
|
ERR("Unable to request memory region at %p\n", FPGA_BASE_ADDR);
|
||||||
goto fail_region;
|
goto fail_region;
|
||||||
}
|
}
|
||||||
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
|
||||||
NULL);
|
NULL);
|
||||||
if (!xframe_cache) {
|
if (!xframe_cache) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto fail_cache;
|
goto fail_cache;
|
||||||
@ -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;
|
||||||
@ -552,7 +572,7 @@ fail_proc:
|
|||||||
fail_xbus:
|
fail_xbus:
|
||||||
kmem_cache_destroy(xframe_cache);
|
kmem_cache_destroy(xframe_cache);
|
||||||
fail_cache:
|
fail_cache:
|
||||||
release_region((resource_size_t)FPGA_BASE_ADDR, 8);
|
release_region((resource_size_t) FPGA_BASE_ADDR, 8);
|
||||||
fail_region:
|
fail_region:
|
||||||
free_irq(FPGA_TX_IRQ, NULL);
|
free_irq(FPGA_TX_IRQ, NULL);
|
||||||
fail_irq_tx:
|
fail_irq_tx:
|
||||||
@ -579,7 +599,7 @@ static void __exit xpp_mmap_exit(void)
|
|||||||
xbus_disconnect(xbus);
|
xbus_disconnect(xbus);
|
||||||
kmem_cache_destroy(xframe_cache);
|
kmem_cache_destroy(xframe_cache);
|
||||||
|
|
||||||
release_region((resource_size_t)FPGA_BASE_ADDR, 8);
|
release_region((resource_size_t) FPGA_BASE_ADDR, 8);
|
||||||
free_irq(FPGA_RX_IRQ, NULL);
|
free_irq(FPGA_RX_IRQ, NULL);
|
||||||
free_irq(FPGA_TX_IRQ, NULL);
|
free_irq(FPGA_TX_IRQ, NULL);
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
|
||||||
# warning "This module is tested only with 2.6 kernels"
|
#warning "This module is tested only with 2.6 kernels"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
@ -30,21 +30,21 @@
|
|||||||
#include <linux/parport.h>
|
#include <linux/parport.h>
|
||||||
#include "parport_debug.h"
|
#include "parport_debug.h"
|
||||||
|
|
||||||
static struct parport *debug_sync_parport;
|
static struct parport *debug_sync_parport;
|
||||||
static int parport_toggles[8]; /* 8 bit flip-flop */
|
static int parport_toggles[8]; /* 8 bit flip-flop */
|
||||||
|
|
||||||
void flip_parport_bit(unsigned char bitnum)
|
void flip_parport_bit(unsigned char bitnum)
|
||||||
{
|
{
|
||||||
static unsigned char last_value;
|
static unsigned char last_value;
|
||||||
DEFINE_SPINLOCK(lock);
|
DEFINE_SPINLOCK(lock);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned char mask;
|
unsigned char mask;
|
||||||
unsigned char value;
|
unsigned char value;
|
||||||
|
|
||||||
if (!debug_sync_parport) {
|
if (!debug_sync_parport) {
|
||||||
if (printk_ratelimit()) {
|
if (printk_ratelimit()) {
|
||||||
printk(KERN_NOTICE "%s: no debug parallel port\n",
|
printk(KERN_NOTICE "%s: no debug parallel port\n",
|
||||||
THIS_MODULE->name);
|
THIS_MODULE->name);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -59,14 +59,16 @@ 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);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
parport_get_port(port);
|
parport_get_port(port);
|
||||||
@ -78,14 +80,14 @@ static void parport_detach(struct parport *port)
|
|||||||
printk(KERN_INFO "%s: Releasing %s\n", THIS_MODULE->name, port->name);
|
printk(KERN_INFO "%s: Releasing %s\n", THIS_MODULE->name, port->name);
|
||||||
if (debug_sync_parport != port) {
|
if (debug_sync_parport != port) {
|
||||||
printk(KERN_ERR "%s: Using %s, ignore new detachment %s\n",
|
printk(KERN_ERR "%s: Using %s, ignore new detachment %s\n",
|
||||||
THIS_MODULE->name, debug_sync_parport->name, port->name);
|
THIS_MODULE->name, debug_sync_parport->name, port->name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
parport_put_port(debug_sync_parport);
|
parport_put_port(debug_sync_parport);
|
||||||
debug_sync_parport = NULL;
|
debug_sync_parport = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct parport_driver debug_parport_driver = {
|
static struct parport_driver debug_parport_driver = {
|
||||||
.name = "parport_debug",
|
.name = "parport_debug",
|
||||||
.attach = parport_attach,
|
.attach = parport_attach,
|
||||||
.detach = parport_detach,
|
.detach = parport_detach,
|
||||||
@ -93,7 +95,7 @@ static struct parport_driver debug_parport_driver = {
|
|||||||
|
|
||||||
int __init parallel_dbg_init(void)
|
int __init parallel_dbg_init(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = parport_register_driver(&debug_parport_driver);
|
ret = parport_register_driver(&debug_parport_driver);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -28,4 +28,4 @@ void flip_parport_bit(unsigned char bitnum);
|
|||||||
#define flip_parport_bit(bitnum)
|
#define flip_parport_bit(bitnum)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* PARPORT_DEBUG_H */
|
#endif /* PARPORT_DEBUG_H */
|
||||||
|
@ -4,10 +4,11 @@ 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)
|
||||||
int reg16=0, reg26=0, reg30=0, reg31=0x20;
|
break;
|
||||||
char ring_osc[BUFSIZ]="", ring_x[BUFSIZ] = "";
|
int reg16 = 0, reg26 = 0, reg30 = 0, reg31 = 0x20;
|
||||||
|
char ring_osc[BUFSIZ] = "", ring_x[BUFSIZ] = "";
|
||||||
|
|
||||||
reg16 |= (fxo_modes[i].ohs << 6);
|
reg16 |= (fxo_modes[i].ohs << 6);
|
||||||
reg16 |= (fxo_modes[i].rz << 1);
|
reg16 |= (fxo_modes[i].rz << 1);
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -39,10 +39,10 @@ struct xbus_workqueue;
|
|||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
struct xbus_ops {
|
struct xbus_ops {
|
||||||
int (*xframe_send_pcm)(xbus_t *xbus, xframe_t *xframe);
|
int (*xframe_send_pcm) (xbus_t *xbus, xframe_t *xframe);
|
||||||
int (*xframe_send_cmd)(xbus_t *xbus, xframe_t *xframe);
|
int (*xframe_send_cmd) (xbus_t *xbus, xframe_t *xframe);
|
||||||
xframe_t *(*alloc_xframe)(xbus_t *xbus, gfp_t gfp_flags);
|
xframe_t *(*alloc_xframe) (xbus_t *xbus, gfp_t gfp_flags);
|
||||||
void (*free_xframe)(xbus_t *xbus, xframe_t *xframe);
|
void (*free_xframe) (xbus_t *xbus, xframe_t *xframe);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -67,19 +67,11 @@ enum {
|
|||||||
|
|
||||||
/* yucky, make an instance so we can size it... */
|
/* yucky, make an instance so we can size it... */
|
||||||
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_
|
||||||
|
|
||||||
@ -99,17 +91,17 @@ enum xbus_state {
|
|||||||
const char *xbus_statename(enum xbus_state st);
|
const char *xbus_statename(enum xbus_state st);
|
||||||
|
|
||||||
struct xbus_transport {
|
struct xbus_transport {
|
||||||
struct xbus_ops *ops;
|
struct xbus_ops *ops;
|
||||||
void *priv;
|
void *priv;
|
||||||
struct device *transport_device;
|
struct device *transport_device;
|
||||||
ushort max_send_size;
|
ushort max_send_size;
|
||||||
enum xbus_state xbus_state;
|
enum xbus_state xbus_state;
|
||||||
unsigned long transport_flags;
|
unsigned long transport_flags;
|
||||||
spinlock_t state_lock;
|
spinlock_t state_lock;
|
||||||
atomic_t transport_refcount;
|
atomic_t transport_refcount;
|
||||||
wait_queue_head_t transport_unused;
|
wait_queue_head_t transport_unused;
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
char model_string[MAX_ENV_STR];
|
char model_string[MAX_ENV_STR];
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_SEND_SIZE(xbus) ((xbus)->transport.max_send_size)
|
#define MAX_SEND_SIZE(xbus) ((xbus)->transport.max_send_size)
|
||||||
@ -127,15 +119,15 @@ void transportops_put(xbus_t *xbus);
|
|||||||
* Encapsulate all poll related data of a single xbus.
|
* Encapsulate all poll related data of a single xbus.
|
||||||
*/
|
*/
|
||||||
struct xbus_workqueue {
|
struct xbus_workqueue {
|
||||||
struct workqueue_struct *wq;
|
struct workqueue_struct *wq;
|
||||||
struct work_struct xpds_init_work;
|
struct work_struct xpds_init_work;
|
||||||
bool xpds_init_done;
|
bool xpds_init_done;
|
||||||
struct list_head card_list;
|
struct list_head card_list;
|
||||||
int num_units;
|
int num_units;
|
||||||
int num_units_initialized;
|
int num_units_initialized;
|
||||||
wait_queue_head_t wait_for_xpd_initialization;
|
wait_queue_head_t wait_for_xpd_initialization;
|
||||||
spinlock_t worker_lock;
|
spinlock_t worker_lock;
|
||||||
struct semaphore running_initialization;
|
struct semaphore running_initialization;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -152,10 +144,10 @@ void put_xframe(struct xframe_queue *q, xframe_t *xframe);
|
|||||||
#define FREE_SEND_XFRAME(xbus, xframe) put_xframe(&(xbus)->send_pool, (xframe))
|
#define FREE_SEND_XFRAME(xbus, xframe) put_xframe(&(xbus)->send_pool, (xframe))
|
||||||
#define FREE_RECV_XFRAME(xbus, xframe) put_xframe(&(xbus)->receive_pool, (xframe))
|
#define FREE_RECV_XFRAME(xbus, xframe) put_xframe(&(xbus)->receive_pool, (xframe))
|
||||||
|
|
||||||
xbus_t *xbus_num(uint num);
|
xbus_t *xbus_num(uint num);
|
||||||
xbus_t *get_xbus(const char *msg, uint num);
|
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);
|
||||||
int refcount_xbus(xbus_t *xbus);
|
int refcount_xbus(xbus_t *xbus);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Echo canceller related data
|
* Echo canceller related data
|
||||||
@ -163,17 +155,17 @@ int refcount_xbus(xbus_t *xbus);
|
|||||||
#define ECHO_TIMESLOTS 128
|
#define ECHO_TIMESLOTS 128
|
||||||
|
|
||||||
struct echoops {
|
struct echoops {
|
||||||
int (*ec_set)(xpd_t *xpd, int pos, bool on);
|
int (*ec_set) (xpd_t *xpd, int pos, bool on);
|
||||||
int (*ec_get)(xpd_t *xpd, int pos);
|
int (*ec_get) (xpd_t *xpd, int pos);
|
||||||
int (*ec_update)(xbus_t *xbus);
|
int (*ec_update) (xbus_t *xbus);
|
||||||
void (*ec_dump)(xbus_t *xbus);
|
void (*ec_dump) (xbus_t *xbus);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct xbus_echo_state {
|
struct xbus_echo_state {
|
||||||
const struct echoops *echoops;
|
const struct echoops *echoops;
|
||||||
__u8 timeslots[ECHO_TIMESLOTS];
|
__u8 timeslots[ECHO_TIMESLOTS];
|
||||||
int xpd_idx;
|
int xpd_idx;
|
||||||
struct device_attribute *da[MAX_XPDS];
|
struct device_attribute *da[MAX_XPDS];
|
||||||
};
|
};
|
||||||
#define ECHOOPS(xbus) ((xbus)->echo_state.echoops)
|
#define ECHOOPS(xbus) ((xbus)->echo_state.echoops)
|
||||||
#define EC_METHOD(name, xbus) (ECHOOPS(xbus)->name)
|
#define EC_METHOD(name, xbus) (ECHOOPS(xbus)->name)
|
||||||
@ -183,126 +175,128 @@ struct xbus_echo_state {
|
|||||||
* An xbus is a transport layer for Xorcom Protocol commands
|
* An xbus is a transport layer for Xorcom Protocol commands
|
||||||
*/
|
*/
|
||||||
struct xbus {
|
struct xbus {
|
||||||
char busname[XBUS_NAMELEN]; /* set by xbus_new() */
|
char busname[XBUS_NAMELEN]; /* set by xbus_new() */
|
||||||
|
|
||||||
/* low-level bus drivers set these 2 fields */
|
/* low-level bus drivers set these 2 fields */
|
||||||
char connector[XBUS_DESCLEN];
|
char connector[XBUS_DESCLEN];
|
||||||
char label[LABEL_SIZE];
|
char label[LABEL_SIZE];
|
||||||
__u8 revision; /* Protocol revision */
|
__u8 revision; /* Protocol revision */
|
||||||
struct xbus_transport transport;
|
struct xbus_transport transport;
|
||||||
struct dahdi_device *ddev;
|
struct dahdi_device *ddev;
|
||||||
|
|
||||||
int num;
|
int num;
|
||||||
struct xpd *xpds[MAX_XPDS];
|
struct xpd *xpds[MAX_XPDS];
|
||||||
struct xbus_echo_state echo_state;
|
struct xbus_echo_state echo_state;
|
||||||
|
|
||||||
int command_tick_counter;
|
int command_tick_counter;
|
||||||
int usec_nosend; /* Firmware flow control */
|
int usec_nosend; /* Firmware flow control */
|
||||||
struct xframe_queue command_queue;
|
struct xframe_queue command_queue;
|
||||||
wait_queue_head_t command_queue_empty;
|
wait_queue_head_t command_queue_empty;
|
||||||
|
|
||||||
struct xframe_queue send_pool; /* empty xframes for send */
|
struct xframe_queue send_pool; /* empty xframes for send */
|
||||||
struct xframe_queue receive_pool; /* empty xframes for receive */
|
struct xframe_queue receive_pool; /* empty xframes for receive */
|
||||||
|
|
||||||
/* tasklet processing */
|
/* tasklet processing */
|
||||||
struct xframe_queue receive_queue;
|
struct xframe_queue receive_queue;
|
||||||
struct tasklet_struct receive_tasklet;
|
struct tasklet_struct receive_tasklet;
|
||||||
int cpu_rcv_intr[NR_CPUS];
|
int cpu_rcv_intr[NR_CPUS];
|
||||||
int cpu_rcv_tasklet[NR_CPUS];
|
int cpu_rcv_tasklet[NR_CPUS];
|
||||||
|
|
||||||
struct quirks {
|
struct quirks {
|
||||||
unsigned int has_fxo:1;
|
unsigned int has_fxo:1;
|
||||||
unsigned int has_digital_span:1;
|
unsigned int has_digital_span:1;
|
||||||
} quirks;
|
} quirks;
|
||||||
bool self_ticking;
|
bool self_ticking;
|
||||||
enum sync_mode sync_mode;
|
enum sync_mode sync_mode;
|
||||||
/* Managed by low-level drivers: */
|
/* Managed by low-level drivers: */
|
||||||
enum sync_mode sync_mode_default;
|
enum sync_mode sync_mode_default;
|
||||||
struct timer_list command_timer;
|
struct timer_list command_timer;
|
||||||
unsigned int xbus_frag_count;
|
unsigned int xbus_frag_count;
|
||||||
struct xframe_queue pcm_tospan;
|
struct xframe_queue pcm_tospan;
|
||||||
|
|
||||||
struct xpp_ticker ticker; /* for tick rate */
|
struct xpp_ticker ticker; /* for tick rate */
|
||||||
struct xpp_drift drift; /* for tick offset */
|
struct xpp_drift drift; /* for tick offset */
|
||||||
|
|
||||||
atomic_t pcm_rx_counter;
|
atomic_t pcm_rx_counter;
|
||||||
unsigned int global_counter;
|
unsigned int global_counter;
|
||||||
|
|
||||||
/* Device-Model */
|
/* Device-Model */
|
||||||
struct device astribank;
|
struct device astribank;
|
||||||
#define dev_to_xbus(dev) container_of(dev, struct xbus, astribank)
|
#define dev_to_xbus(dev) container_of(dev, struct xbus, astribank)
|
||||||
struct kref kref;
|
struct kref kref;
|
||||||
#define kref_to_xbus(k) container_of(k, struct xbus, kref)
|
#define kref_to_xbus(k) container_of(k, struct xbus, kref)
|
||||||
|
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
|
|
||||||
/* PCM metrics */
|
/* PCM metrics */
|
||||||
struct timeval last_tx_sync;
|
struct timeval last_tx_sync;
|
||||||
struct timeval last_rx_sync;
|
struct timeval last_rx_sync;
|
||||||
unsigned long max_tx_sync;
|
unsigned long max_tx_sync;
|
||||||
unsigned long min_tx_sync;
|
unsigned long min_tx_sync;
|
||||||
unsigned long max_rx_sync;
|
unsigned long max_rx_sync;
|
||||||
unsigned long min_rx_sync;
|
unsigned long min_rx_sync;
|
||||||
unsigned long max_rx_process; /* packet processing time (usec) */
|
unsigned long max_rx_process; /* packet processing time (usec) */
|
||||||
#ifdef SAMPLE_TICKS
|
#ifdef SAMPLE_TICKS
|
||||||
#define SAMPLE_SIZE 1000
|
#define SAMPLE_SIZE 1000
|
||||||
int sample_ticks[SAMPLE_SIZE];
|
int sample_ticks[SAMPLE_SIZE];
|
||||||
bool sample_running;
|
bool sample_running;
|
||||||
int sample_pos;
|
int sample_pos;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct xbus_workqueue worker;
|
struct xbus_workqueue worker;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sync adjustment
|
* Sync adjustment
|
||||||
*/
|
*/
|
||||||
int sync_adjustment;
|
int sync_adjustment;
|
||||||
int sync_adjustment_offset;
|
int sync_adjustment_offset;
|
||||||
long pll_updated_at;
|
long pll_updated_at;
|
||||||
|
|
||||||
atomic_t num_xpds;
|
atomic_t num_xpds;
|
||||||
|
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
struct proc_dir_entry *proc_xbus_dir;
|
struct proc_dir_entry *proc_xbus_dir;
|
||||||
struct proc_dir_entry *proc_xbus_summary;
|
struct proc_dir_entry *proc_xbus_summary;
|
||||||
#ifdef PROTOCOL_DEBUG
|
#ifdef PROTOCOL_DEBUG
|
||||||
struct proc_dir_entry *proc_xbus_command;
|
struct proc_dir_entry *proc_xbus_command;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* statistics */
|
/* statistics */
|
||||||
int counters[XBUS_COUNTER_MAX];
|
int counters[XBUS_COUNTER_MAX];
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define XFRAME_MAGIC 123456L
|
#define XFRAME_MAGIC 123456L
|
||||||
|
|
||||||
struct xframe {
|
struct xframe {
|
||||||
unsigned long xframe_magic;
|
unsigned long xframe_magic;
|
||||||
struct list_head frame_list;
|
struct list_head frame_list;
|
||||||
atomic_t frame_len;
|
atomic_t frame_len;
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
struct timeval tv_created;
|
struct timeval tv_created;
|
||||||
struct timeval tv_queued;
|
struct timeval tv_queued;
|
||||||
struct timeval tv_submitted;
|
struct timeval tv_submitted;
|
||||||
struct timeval tv_received;
|
struct timeval tv_received;
|
||||||
/* filled by transport layer */
|
/* filled by transport layer */
|
||||||
size_t frame_maxlen;
|
size_t frame_maxlen;
|
||||||
__u8 *packets; /* max XFRAME_DATASIZE */
|
__u8 *packets; /* max XFRAME_DATASIZE */
|
||||||
__u8 *first_free;
|
__u8 *first_free;
|
||||||
int usec_towait; /* prevent overflowing AB */
|
int usec_towait; /* prevent overflowing AB */
|
||||||
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)
|
||||||
|
|
||||||
int xbus_core_init(void); /* Initializer */
|
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);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -320,39 +314,40 @@ xpacket_t *xframe_next_packet(xframe_t *xframe, int len);
|
|||||||
#define XBUS_UNIT(idx) ((idx) / MAX_SUBUNIT)
|
#define XBUS_UNIT(idx) ((idx) / MAX_SUBUNIT)
|
||||||
#define XBUS_SUBUNIT(idx) ((idx) % MAX_SUBUNIT)
|
#define XBUS_SUBUNIT(idx) ((idx) % MAX_SUBUNIT)
|
||||||
|
|
||||||
xpd_t *xpd_of(const xbus_t *xbus, int xpd_num);
|
xpd_t *xpd_of(const xbus_t *xbus, int xpd_num);
|
||||||
xpd_t *xpd_byaddr(const xbus_t *xbus, uint unit, uint subunit);
|
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,
|
||||||
void xbus_free(xbus_t *xbus);
|
struct device *transport_device, void *priv);
|
||||||
int xbus_connect(xbus_t *xbus);
|
void xbus_free(xbus_t *xbus);
|
||||||
int xbus_activate(xbus_t *xbus);
|
int xbus_connect(xbus_t *xbus);
|
||||||
void xbus_deactivate(xbus_t *xbus);
|
int xbus_activate(xbus_t *xbus);
|
||||||
void xbus_disconnect(xbus_t *xbus);
|
void xbus_deactivate(xbus_t *xbus);
|
||||||
void xbus_receive_xframe(xbus_t *xbus, xframe_t *xframe);
|
void xbus_disconnect(xbus_t *xbus);
|
||||||
int xbus_process_worker(xbus_t *xbus);
|
void xbus_receive_xframe(xbus_t *xbus, xframe_t *xframe);
|
||||||
int waitfor_xpds(xbus_t *xbus, char *buf);
|
int xbus_process_worker(xbus_t *xbus);
|
||||||
|
int waitfor_xpds(xbus_t *xbus, char *buf);
|
||||||
|
|
||||||
int xbus_xpd_bind(xbus_t *xbus, xpd_t *xpd, int unit, int subunit);
|
int xbus_xpd_bind(xbus_t *xbus, xpd_t *xpd, int unit, int subunit);
|
||||||
int xbus_xpd_unbind(xbus_t *xbus, xpd_t *xpd);
|
int xbus_xpd_unbind(xbus_t *xbus, xpd_t *xpd);
|
||||||
|
|
||||||
/* sysfs */
|
/* sysfs */
|
||||||
int xpd_device_register(xbus_t *xbus, xpd_t *xpd);
|
int xpd_device_register(xbus_t *xbus, xpd_t *xpd);
|
||||||
void xpd_device_unregister(xpd_t *xpd);
|
void xpd_device_unregister(xpd_t *xpd);
|
||||||
int echocancel_xpd(xpd_t *xpd, int on);
|
int echocancel_xpd(xpd_t *xpd, int on);
|
||||||
|
|
||||||
int xbus_is_registered(xbus_t *xbus);
|
int xbus_is_registered(xbus_t *xbus);
|
||||||
int xbus_register_dahdi_device(xbus_t *xbus);
|
int xbus_register_dahdi_device(xbus_t *xbus);
|
||||||
void xbus_unregister_dahdi_device(xbus_t *xbus);
|
void xbus_unregister_dahdi_device(xbus_t *xbus);
|
||||||
|
|
||||||
int xpp_driver_init(void);
|
int xpp_driver_init(void);
|
||||||
void xpp_driver_exit(void);
|
void xpp_driver_exit(void);
|
||||||
int xbus_sysfs_transport_create(xbus_t *xbus);
|
int xbus_sysfs_transport_create(xbus_t *xbus);
|
||||||
void xbus_sysfs_transport_remove(xbus_t *xbus);
|
void xbus_sysfs_transport_remove(xbus_t *xbus);
|
||||||
int xbus_sysfs_create(xbus_t *xbus);
|
int xbus_sysfs_create(xbus_t *xbus);
|
||||||
void xbus_sysfs_remove(xbus_t *xbus);
|
void xbus_sysfs_remove(xbus_t *xbus);
|
||||||
|
|
||||||
#ifdef OLD_HOTPLUG_SUPPORT_269
|
#ifdef OLD_HOTPLUG_SUPPORT_269
|
||||||
/* Copy from new kernels lib/kobject_uevent.c */
|
/* Copy from new kernels lib/kobject_uevent.c */
|
||||||
@ -367,7 +362,6 @@ enum kobject_action {
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
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 */
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -33,10 +33,10 @@
|
|||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
enum sync_mode {
|
enum sync_mode {
|
||||||
SYNC_MODE_NONE = 0x00,
|
SYNC_MODE_NONE = 0x00,
|
||||||
SYNC_MODE_AB = 0x01, /* Astribank sync */
|
SYNC_MODE_AB = 0x01, /* Astribank sync */
|
||||||
SYNC_MODE_PLL = 0x03, /* Adjust XPD's PLL according to HOST */
|
SYNC_MODE_PLL = 0x03, /* Adjust XPD's PLL according to HOST */
|
||||||
SYNC_MODE_QUERY = 0x80,
|
SYNC_MODE_QUERY = 0x80,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -46,7 +46,7 @@ enum sync_mode {
|
|||||||
* time representations.
|
* time representations.
|
||||||
*/
|
*/
|
||||||
struct xpp_timestamp {
|
struct xpp_timestamp {
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -58,12 +58,12 @@ struct xpp_timestamp {
|
|||||||
* from other dahdi devices).
|
* from other dahdi devices).
|
||||||
*/
|
*/
|
||||||
struct xpp_ticker { /* for rate calculation */
|
struct xpp_ticker { /* for rate calculation */
|
||||||
int count;
|
int count;
|
||||||
int cycle;
|
int cycle;
|
||||||
struct xpp_timestamp first_sample;
|
struct xpp_timestamp first_sample;
|
||||||
struct xpp_timestamp last_sample;
|
struct xpp_timestamp last_sample;
|
||||||
int tick_period; /* usec/tick */
|
int tick_period; /* usec/tick */
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -71,66 +71,65 @@ struct xpp_ticker { /* for rate calculation */
|
|||||||
* xbus ticker to a reference ticker.
|
* xbus ticker to a reference ticker.
|
||||||
*/
|
*/
|
||||||
struct xpp_drift {
|
struct xpp_drift {
|
||||||
int delta_tick; /* from ref_ticker */
|
int delta_tick; /* from ref_ticker */
|
||||||
int lost_ticks; /* occurances */
|
int lost_ticks; /* occurances */
|
||||||
int lost_tick_count;
|
int lost_tick_count;
|
||||||
int sync_inaccuracy;
|
int sync_inaccuracy;
|
||||||
struct xpp_timestamp last_lost_tick;
|
struct xpp_timestamp last_lost_tick;
|
||||||
long delta_sum;
|
long delta_sum;
|
||||||
int offset_prev;
|
int offset_prev;
|
||||||
int offset_range;
|
int offset_range;
|
||||||
int offset_min;
|
int offset_min;
|
||||||
int offset_max;
|
int offset_max;
|
||||||
int min_speed;
|
int min_speed;
|
||||||
int max_speed;
|
int max_speed;
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
diff_sec = tv1->tv_sec - tv2->tv_sec;
|
diff_sec = tv1->tv_sec - tv2->tv_sec;
|
||||||
diff_usec = tv1->tv_usec - tv2->tv_usec;
|
diff_usec = tv1->tv_usec - tv2->tv_usec;
|
||||||
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);
|
void pcm_recompute(xpd_t *xpd, xpp_line_t tmp_pcm_mask);
|
||||||
void pcm_recompute(xpd_t *xpd, xpp_line_t tmp_pcm_mask);
|
void xframe_receive_pcm(xbus_t *xbus, xframe_t *xframe);
|
||||||
void xframe_receive_pcm(xbus_t *xbus, xframe_t *xframe);
|
void update_wanted_pcm_mask(xpd_t *xpd, xpp_line_t new_mask, uint new_pcm_len);
|
||||||
void update_wanted_pcm_mask(xpd_t *xpd, xpp_line_t new_mask, uint new_pcm_len);
|
void generic_card_pcm_recompute(xpd_t *xpd, xpp_line_t pcm_mask);
|
||||||
void generic_card_pcm_recompute(xpd_t *xpd, xpp_line_t pcm_mask);
|
void generic_card_pcm_fromspan(xpd_t *xpd, xpacket_t *pack);
|
||||||
void generic_card_pcm_fromspan(xpd_t *xpd, xpacket_t *pack);
|
void generic_card_pcm_tospan(xpd_t *xpd, xpacket_t *pack);
|
||||||
void generic_card_pcm_tospan(xpd_t *xpd, xpacket_t *pack);
|
int generic_timing_priority(xpd_t *xpd);
|
||||||
int generic_timing_priority(xpd_t *xpd);
|
int generic_echocancel_timeslot(xpd_t *xpd, int pos);
|
||||||
int generic_echocancel_timeslot(xpd_t *xpd, int pos);
|
int generic_echocancel_setmask(xpd_t *xpd, xpp_line_t ec_mask);
|
||||||
int generic_echocancel_setmask(xpd_t *xpd, xpp_line_t ec_mask);
|
void fill_beep(u_char *buf, int num, int duration);
|
||||||
void fill_beep(u_char *buf, int num, int duration);
|
const char *sync_mode_name(enum sync_mode mode);
|
||||||
const char *sync_mode_name(enum sync_mode mode);
|
void xbus_set_command_timer(xbus_t *xbus, bool on);
|
||||||
void xbus_set_command_timer(xbus_t *xbus, bool on);
|
void xbus_request_sync(xbus_t *xbus, enum sync_mode mode);
|
||||||
void xbus_request_sync(xbus_t *xbus, enum sync_mode mode);
|
void got_new_syncer(xbus_t *xbus, enum sync_mode mode, int drift);
|
||||||
void got_new_syncer(xbus_t *xbus, enum sync_mode mode, int drift);
|
int xbus_command_queue_tick(xbus_t *xbus);
|
||||||
int xbus_command_queue_tick(xbus_t *xbus);
|
void xbus_reset_counters(xbus_t *xbus);
|
||||||
void xbus_reset_counters(xbus_t *xbus);
|
void elect_syncer(const char *msg);
|
||||||
void elect_syncer(const char *msg);
|
int exec_sync_command(const char *buf, size_t count);
|
||||||
int exec_sync_command(const char *buf, size_t count);
|
int fill_sync_string(char *buf, size_t count);
|
||||||
int fill_sync_string(char *buf, size_t count);
|
|
||||||
#ifdef DAHDI_SYNC_TICK
|
#ifdef DAHDI_SYNC_TICK
|
||||||
void dahdi_sync_tick(struct dahdi_span *span, int is_master);
|
void dahdi_sync_tick(struct dahdi_span *span, int is_master);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG_PCMTX
|
#ifdef DEBUG_PCMTX
|
||||||
extern int pcmtx;
|
extern int pcmtx;
|
||||||
extern int pcmtx_chan;
|
extern int pcmtx_chan;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* __KERNEL__ */
|
#endif /* __KERNEL__ */
|
||||||
|
|
||||||
#endif /* XBUS_PCM_H */
|
|
||||||
|
|
||||||
|
#endif /* XBUS_PCM_H */
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
|
||||||
# warning "This module is tested only with 2.6 kernels"
|
#warning "This module is tested only with 2.6 kernels"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.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);
|
||||||
@ -66,19 +67,18 @@ static struct driver_attribute xpp_attrs[] = {
|
|||||||
/*--------- Sysfs Bus handling ----*/
|
/*--------- Sysfs Bus handling ----*/
|
||||||
static DEVICE_ATTR_READER(xbus_state_show, dev, buf)
|
static DEVICE_ATTR_READER(xbus_state_show, dev, buf)
|
||||||
{
|
{
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEVICE_ATTR_WRITER(xbus_state_store, dev, buf, count)
|
static DEVICE_ATTR_WRITER(xbus_state_store, dev, buf, count)
|
||||||
{
|
{
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
|
|
||||||
xbus = dev_to_xbus(dev);
|
xbus = dev_to_xbus(dev);
|
||||||
XBUS_DBG(GENERAL, xbus, "%s\n", buf);
|
XBUS_DBG(GENERAL, xbus, "%s\n", buf);
|
||||||
@ -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;
|
||||||
@ -97,34 +97,39 @@ static DEVICE_ATTR_WRITER(xbus_state_store, dev, buf, count)
|
|||||||
|
|
||||||
static DEVICE_ATTR_READER(status_show, dev, buf)
|
static DEVICE_ATTR_READER(status_show, dev, buf)
|
||||||
{
|
{
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEVICE_ATTR_READER(timing_show, dev, buf)
|
static DEVICE_ATTR_READER(timing_show, dev, buf)
|
||||||
{
|
{
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
struct xpp_drift *driftinfo;
|
struct xpp_drift *driftinfo;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
|
|
||||||
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;
|
||||||
@ -141,9 +146,9 @@ static DEVICE_ATTR_READER(timing_show, dev, buf)
|
|||||||
*/
|
*/
|
||||||
static DEVICE_ATTR_READER(samples_show, dev, buf)
|
static DEVICE_ATTR_READER(samples_show, dev, buf)
|
||||||
{
|
{
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
xbus = dev_to_xbus(dev);
|
xbus = dev_to_xbus(dev);
|
||||||
if (xbus->sample_running)
|
if (xbus->sample_running)
|
||||||
@ -151,14 +156,16 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEVICE_ATTR_WRITER(samples_store, dev, buf, count)
|
static DEVICE_ATTR_WRITER(samples_store, dev, buf, count)
|
||||||
{
|
{
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
|
|
||||||
xbus = dev_to_xbus(dev);
|
xbus = dev_to_xbus(dev);
|
||||||
if (xbus->sample_running)
|
if (xbus->sample_running)
|
||||||
@ -175,8 +182,8 @@ static DEVICE_ATTR_WRITER(samples_store, dev, buf, count)
|
|||||||
*/
|
*/
|
||||||
static DEVICE_ATTR_WRITER(cls_store, dev, buf, count)
|
static DEVICE_ATTR_WRITER(cls_store, dev, buf, count)
|
||||||
{
|
{
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
struct xpp_drift *driftinfo;
|
struct xpp_drift *driftinfo;
|
||||||
|
|
||||||
xbus = dev_to_xbus(dev);
|
xbus = dev_to_xbus(dev);
|
||||||
driftinfo = &xbus->drift;
|
driftinfo = &xbus->drift;
|
||||||
@ -194,8 +201,8 @@ static DEVICE_ATTR_WRITER(cls_store, dev, buf, count)
|
|||||||
|
|
||||||
static DEVICE_ATTR_READER(waitfor_xpds_show, dev, buf)
|
static DEVICE_ATTR_READER(waitfor_xpds_show, dev, buf)
|
||||||
{
|
{
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
xbus = dev_to_xbus(dev);
|
xbus = dev_to_xbus(dev);
|
||||||
len = waitfor_xpds(xbus, buf);
|
len = waitfor_xpds(xbus, buf);
|
||||||
@ -204,8 +211,8 @@ static DEVICE_ATTR_READER(waitfor_xpds_show, dev, buf)
|
|||||||
|
|
||||||
static DEVICE_ATTR_READER(refcount_xbus_show, dev, buf)
|
static DEVICE_ATTR_READER(refcount_xbus_show, dev, buf)
|
||||||
{
|
{
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
xbus = dev_to_xbus(dev);
|
xbus = dev_to_xbus(dev);
|
||||||
len = sprintf(buf, "%d\n", refcount_xbus(xbus));
|
len = sprintf(buf, "%d\n", refcount_xbus(xbus));
|
||||||
@ -214,17 +221,17 @@ static DEVICE_ATTR_READER(refcount_xbus_show, dev, buf)
|
|||||||
|
|
||||||
static DEVICE_ATTR_READER(driftinfo_show, dev, buf)
|
static DEVICE_ATTR_READER(driftinfo_show, dev, buf)
|
||||||
{
|
{
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
struct xpp_drift *di;
|
struct xpp_drift *di;
|
||||||
struct xpp_ticker *ticker;
|
struct xpp_ticker *ticker;
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
int hours;
|
int hours;
|
||||||
int minutes;
|
int minutes;
|
||||||
int seconds;
|
int seconds;
|
||||||
int speed_range;
|
int speed_range;
|
||||||
int uframes_inaccuracy;
|
int uframes_inaccuracy;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
xbus = dev_to_xbus(dev);
|
xbus = dev_to_xbus(dev);
|
||||||
di = &xbus->drift;
|
di = &xbus->drift;
|
||||||
@ -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);
|
||||||
@ -293,33 +313,34 @@ xbus_attr(connector, "%s\n");
|
|||||||
xbus_attr(label, "%s\n");
|
xbus_attr(label, "%s\n");
|
||||||
|
|
||||||
static struct device_attribute xbus_dev_attrs[] = {
|
static struct device_attribute xbus_dev_attrs[] = {
|
||||||
__ATTR_RO(connector),
|
__ATTR_RO(connector),
|
||||||
__ATTR_RO(label),
|
__ATTR_RO(label),
|
||||||
__ATTR_RO(status),
|
__ATTR_RO(status),
|
||||||
__ATTR_RO(timing),
|
__ATTR_RO(timing),
|
||||||
__ATTR_RO(refcount_xbus),
|
__ATTR_RO(refcount_xbus),
|
||||||
__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",
|
||||||
dev_name(dev), driver->name);
|
dev_name(dev), driver->name);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#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;
|
||||||
|
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
@ -349,12 +370,13 @@ 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;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
extern char *initdir;
|
extern char *initdir;
|
||||||
|
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
@ -375,8 +397,8 @@ static int astribank_uevent(struct device *dev, char **envp, int num_envp, char
|
|||||||
|
|
||||||
static int astribank_uevent(struct device *dev, struct kobj_uevent_env *kenv)
|
static int astribank_uevent(struct device *dev, struct kobj_uevent_env *kenv)
|
||||||
{
|
{
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
extern char *initdir;
|
extern char *initdir;
|
||||||
|
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
@ -388,27 +410,27 @@ static int astribank_uevent(struct device *dev, struct kobj_uevent_env *kenv)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* OLD_HOTPLUG_SUPPORT */
|
#endif /* OLD_HOTPLUG_SUPPORT */
|
||||||
|
|
||||||
void astribank_uevent_send(xbus_t *xbus, enum kobject_action act)
|
void astribank_uevent_send(xbus_t *xbus, enum kobject_action act)
|
||||||
{
|
{
|
||||||
struct kobject *kobj;
|
struct kobject *kobj;
|
||||||
|
|
||||||
kobj = &xbus->astribank.kobj;
|
kobj = &xbus->astribank.kobj;
|
||||||
XBUS_DBG(DEVICES, xbus, "SYFS bus_id=%s action=%d\n",
|
XBUS_DBG(DEVICES, xbus, "SYFS bus_id=%s action=%d\n",
|
||||||
dev_name(&xbus->astribank), act);
|
dev_name(&xbus->astribank), act);
|
||||||
|
|
||||||
#if defined(OLD_HOTPLUG_SUPPORT_269)
|
#if defined(OLD_HOTPLUG_SUPPORT_269)
|
||||||
{
|
{
|
||||||
/* Copy from new kernels lib/kobject_uevent.c */
|
/* Copy from new kernels lib/kobject_uevent.c */
|
||||||
static const char *str[] = {
|
static const char *str[] = {
|
||||||
[KOBJ_ADD] "add",
|
[KOBJ_ADD] "add",
|
||||||
[KOBJ_REMOVE] "remove",
|
[KOBJ_REMOVE] "remove",
|
||||||
[KOBJ_CHANGE] "change",
|
[KOBJ_CHANGE] "change",
|
||||||
[KOBJ_MOUNT] "mount",
|
[KOBJ_MOUNT] "mount",
|
||||||
[KOBJ_UMOUNT] "umount",
|
[KOBJ_UMOUNT] "umount",
|
||||||
[KOBJ_OFFLINE] "offline",
|
[KOBJ_OFFLINE] "offline",
|
||||||
[KOBJ_ONLINE] "online"
|
[KOBJ_ONLINE] "online"
|
||||||
};
|
};
|
||||||
kobject_hotplug(str[act], kobj);
|
kobject_hotplug(str[act], kobj);
|
||||||
}
|
}
|
||||||
@ -421,7 +443,7 @@ void astribank_uevent_send(xbus_t *xbus, enum kobject_action act)
|
|||||||
|
|
||||||
static void astribank_release(struct device *dev)
|
static void astribank_release(struct device *dev)
|
||||||
{
|
{
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
|
|
||||||
BUG_ON(!dev);
|
BUG_ON(!dev);
|
||||||
xbus = dev_to_xbus(dev);
|
xbus = dev_to_xbus(dev);
|
||||||
@ -429,9 +451,10 @@ 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();
|
||||||
}
|
}
|
||||||
XBUS_INFO(xbus, "[%s] Astribank Release\n", xbus->label);
|
XBUS_INFO(xbus, "[%s] Astribank Release\n", xbus->label);
|
||||||
@ -439,20 +462,20 @@ static void astribank_release(struct device *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct bus_type toplevel_bus_type = {
|
static struct bus_type toplevel_bus_type = {
|
||||||
.name = "astribanks",
|
.name = "astribanks",
|
||||||
.match = astribank_match,
|
.match = astribank_match,
|
||||||
#ifdef OLD_HOTPLUG_SUPPORT
|
#ifdef OLD_HOTPLUG_SUPPORT
|
||||||
.hotplug = astribank_hotplug,
|
.hotplug = astribank_hotplug,
|
||||||
#else
|
#else
|
||||||
.uevent = astribank_uevent,
|
.uevent = astribank_uevent,
|
||||||
#endif
|
#endif
|
||||||
.dev_attrs = xbus_dev_attrs,
|
.dev_attrs = xbus_dev_attrs,
|
||||||
.drv_attrs = xpp_attrs,
|
.drv_attrs = xpp_attrs,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int astribank_probe(struct device *dev)
|
static int astribank_probe(struct device *dev)
|
||||||
{
|
{
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
|
|
||||||
xbus = dev_to_xbus(dev);
|
xbus = dev_to_xbus(dev);
|
||||||
XBUS_DBG(DEVICES, xbus, "SYSFS\n");
|
XBUS_DBG(DEVICES, xbus, "SYSFS\n");
|
||||||
@ -461,7 +484,7 @@ static int astribank_probe(struct device *dev)
|
|||||||
|
|
||||||
static int astribank_remove(struct device *dev)
|
static int astribank_remove(struct device *dev)
|
||||||
{
|
{
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
|
|
||||||
xbus = dev_to_xbus(dev);
|
xbus = dev_to_xbus(dev);
|
||||||
XBUS_INFO(xbus, "[%s] Atribank Remove\n", xbus->label);
|
XBUS_INFO(xbus, "[%s] Atribank Remove\n", xbus->label);
|
||||||
@ -469,12 +492,12 @@ static int astribank_remove(struct device *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct device_driver xpp_driver = {
|
static struct device_driver xpp_driver = {
|
||||||
.name = "xppdrv",
|
.name = "xppdrv",
|
||||||
.bus = &toplevel_bus_type,
|
.bus = &toplevel_bus_type,
|
||||||
.probe = astribank_probe,
|
.probe = astribank_probe,
|
||||||
.remove = astribank_remove,
|
.remove = astribank_remove,
|
||||||
#ifndef OLD_HOTPLUG_SUPPORT
|
#ifndef OLD_HOTPLUG_SUPPORT
|
||||||
.owner = THIS_MODULE
|
.owner = THIS_MODULE
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -482,12 +505,12 @@ static struct device_driver xpp_driver = {
|
|||||||
|
|
||||||
static DEVICE_ATTR_READER(chipregs_show, dev, buf)
|
static DEVICE_ATTR_READER(chipregs_show, dev, buf)
|
||||||
{
|
{
|
||||||
xpd_t *xpd;
|
xpd_t *xpd;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
reg_cmd_t *regs;
|
reg_cmd_t *regs;
|
||||||
bool do_datah;
|
bool do_datah;
|
||||||
char datah_str[50];
|
char datah_str[50];
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
BUG_ON(!dev);
|
BUG_ON(!dev);
|
||||||
xpd = dev_to_xpd(dev);
|
xpd = dev_to_xpd(dev);
|
||||||
@ -495,29 +518,34 @@ 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;
|
||||||
if (do_datah) {
|
if (do_datah) {
|
||||||
snprintf(datah_str, ARRAY_SIZE(datah_str), "\t%02X",
|
snprintf(datah_str, ARRAY_SIZE(datah_str), "\t%02X",
|
||||||
REG_FIELD(regs, data_high));
|
REG_FIELD(regs, data_high));
|
||||||
} 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 +=
|
||||||
(do_datah) ? "\tDH" : "");
|
sprintf(buf + len, "#CH\tOP\tReg.\tSub\tDL%s\n",
|
||||||
len += sprintf(buf + len, "%2d\tRS\t%02X\t%02X\t%02X%s\n",
|
(do_datah) ? "\tDH" : "");
|
||||||
regs->portnum,
|
len +=
|
||||||
REG_FIELD(regs, regnum), REG_FIELD(regs, subreg),
|
sprintf(buf + len, "%2d\tRS\t%02X\t%02X\t%02X%s\n",
|
||||||
REG_FIELD(regs, data_low), datah_str);
|
regs->portnum, REG_FIELD(regs, regnum),
|
||||||
|
REG_FIELD(regs, subreg), REG_FIELD(regs, data_low),
|
||||||
|
datah_str);
|
||||||
} else {
|
} else {
|
||||||
len += sprintf(buf + len, "#CH\tOP\tReg.\tDL%s\n",
|
len +=
|
||||||
(do_datah) ? "\tDH" : "");
|
sprintf(buf + len, "#CH\tOP\tReg.\tDL%s\n",
|
||||||
len += sprintf(buf + len, "%2d\tRD\t%02X\t%02X%s\n",
|
(do_datah) ? "\tDH" : "");
|
||||||
regs->portnum,
|
len +=
|
||||||
REG_FIELD(regs, regnum),
|
sprintf(buf + len, "%2d\tRD\t%02X\t%02X%s\n", regs->portnum,
|
||||||
REG_FIELD(regs, data_low), datah_str);
|
REG_FIELD(regs, regnum), REG_FIELD(regs, data_low),
|
||||||
|
datah_str);
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&xpd->lock, flags);
|
spin_unlock_irqrestore(&xpd->lock, flags);
|
||||||
return len;
|
return len;
|
||||||
@ -525,11 +553,11 @@ static DEVICE_ATTR_READER(chipregs_show, dev, buf)
|
|||||||
|
|
||||||
static DEVICE_ATTR_WRITER(chipregs_store, dev, buf, count)
|
static DEVICE_ATTR_WRITER(chipregs_store, dev, buf, count)
|
||||||
{
|
{
|
||||||
xpd_t *xpd;
|
xpd_t *xpd;
|
||||||
const char *p;
|
const char *p;
|
||||||
char tmp[MAX_PROC_WRITE];
|
char tmp[MAX_PROC_WRITE];
|
||||||
int i;
|
int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
BUG_ON(!dev);
|
BUG_ON(!dev);
|
||||||
xpd = dev_to_xpd(dev);
|
xpd = dev_to_xpd(dev);
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -562,9 +593,9 @@ static DEVICE_ATTR_WRITER(chipregs_store, dev, buf, count)
|
|||||||
|
|
||||||
static DEVICE_ATTR_READER(blink_show, dev, buf)
|
static DEVICE_ATTR_READER(blink_show, dev, buf)
|
||||||
{
|
{
|
||||||
xpd_t *xpd;
|
xpd_t *xpd;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
BUG_ON(!dev);
|
BUG_ON(!dev);
|
||||||
xpd = dev_to_xpd(dev);
|
xpd = dev_to_xpd(dev);
|
||||||
@ -578,9 +609,9 @@ static DEVICE_ATTR_READER(blink_show, dev, buf)
|
|||||||
|
|
||||||
static DEVICE_ATTR_WRITER(blink_store, dev, buf, count)
|
static DEVICE_ATTR_WRITER(blink_store, dev, buf, count)
|
||||||
{
|
{
|
||||||
xpd_t *xpd;
|
xpd_t *xpd;
|
||||||
char *endp;
|
char *endp;
|
||||||
unsigned long blink;
|
unsigned long blink;
|
||||||
|
|
||||||
BUG_ON(!dev);
|
BUG_ON(!dev);
|
||||||
xpd = dev_to_xpd(dev);
|
xpd = dev_to_xpd(dev);
|
||||||
@ -599,16 +630,18 @@ static DEVICE_ATTR_WRITER(blink_store, dev, buf, count)
|
|||||||
|
|
||||||
static DEVICE_ATTR_READER(span_show, dev, buf)
|
static DEVICE_ATTR_READER(span_show, dev, buf)
|
||||||
{
|
{
|
||||||
xpd_t *xpd;
|
xpd_t *xpd;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
BUG_ON(!dev);
|
BUG_ON(!dev);
|
||||||
xpd = dev_to_xpd(dev);
|
xpd = dev_to_xpd(dev);
|
||||||
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;
|
||||||
}
|
}
|
||||||
@ -619,9 +652,9 @@ static DEVICE_ATTR_READER(span_show, dev, buf)
|
|||||||
*/
|
*/
|
||||||
static DEVICE_ATTR_WRITER(span_store, dev, buf, count)
|
static DEVICE_ATTR_WRITER(span_store, dev, buf, count)
|
||||||
{
|
{
|
||||||
xpd_t *xpd;
|
xpd_t *xpd;
|
||||||
int dahdi_reg;
|
int dahdi_reg;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
BUG_ON(!dev);
|
BUG_ON(!dev);
|
||||||
xpd = dev_to_xpd(dev);
|
xpd = dev_to_xpd(dev);
|
||||||
@ -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) {
|
||||||
@ -657,8 +689,8 @@ static DEVICE_ATTR_WRITER(span_store, dev, buf, count)
|
|||||||
|
|
||||||
static DEVICE_ATTR_READER(type_show, dev, buf)
|
static DEVICE_ATTR_READER(type_show, dev, buf)
|
||||||
{
|
{
|
||||||
xpd_t *xpd;
|
xpd_t *xpd;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
BUG_ON(!dev);
|
BUG_ON(!dev);
|
||||||
xpd = dev_to_xpd(dev);
|
xpd = dev_to_xpd(dev);
|
||||||
@ -670,9 +702,9 @@ static DEVICE_ATTR_READER(type_show, dev, buf)
|
|||||||
|
|
||||||
static DEVICE_ATTR_READER(offhook_show, dev, buf)
|
static DEVICE_ATTR_READER(offhook_show, dev, buf)
|
||||||
{
|
{
|
||||||
xpd_t *xpd;
|
xpd_t *xpd;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
BUG_ON(!dev);
|
BUG_ON(!dev);
|
||||||
xpd = dev_to_xpd(dev);
|
xpd = dev_to_xpd(dev);
|
||||||
@ -682,7 +714,7 @@ static DEVICE_ATTR_READER(offhook_show, dev, buf)
|
|||||||
len += sprintf(buf + len, "%d ", IS_OFFHOOK(xpd, i));
|
len += sprintf(buf + len, "%d ", IS_OFFHOOK(xpd, i));
|
||||||
}
|
}
|
||||||
if (len) {
|
if (len) {
|
||||||
len--; /* backout last space */
|
len--; /* backout last space */
|
||||||
}
|
}
|
||||||
len += sprintf(buf + len, "\n");
|
len += sprintf(buf + len, "\n");
|
||||||
return len;
|
return len;
|
||||||
@ -690,9 +722,9 @@ static DEVICE_ATTR_READER(offhook_show, dev, buf)
|
|||||||
|
|
||||||
static DEVICE_ATTR_READER(timing_priority_show, dev, buf)
|
static DEVICE_ATTR_READER(timing_priority_show, dev, buf)
|
||||||
{
|
{
|
||||||
xpd_t *xpd;
|
xpd_t *xpd;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
BUG_ON(!dev);
|
BUG_ON(!dev);
|
||||||
xpd = dev_to_xpd(dev);
|
xpd = dev_to_xpd(dev);
|
||||||
@ -706,8 +738,8 @@ static DEVICE_ATTR_READER(timing_priority_show, dev, buf)
|
|||||||
|
|
||||||
static DEVICE_ATTR_READER(refcount_xpd_show, dev, buf)
|
static DEVICE_ATTR_READER(refcount_xpd_show, dev, buf)
|
||||||
{
|
{
|
||||||
xpd_t *xpd;
|
xpd_t *xpd;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
BUG_ON(!dev);
|
BUG_ON(!dev);
|
||||||
xpd = dev_to_xpd(dev);
|
xpd = dev_to_xpd(dev);
|
||||||
@ -719,47 +751,49 @@ static DEVICE_ATTR_READER(refcount_xpd_show, dev, buf)
|
|||||||
|
|
||||||
static int xpd_match(struct device *dev, struct device_driver *driver)
|
static int xpd_match(struct device *dev, struct device_driver *driver)
|
||||||
{
|
{
|
||||||
struct xpd_driver *xpd_driver;
|
struct xpd_driver *xpd_driver;
|
||||||
xpd_t *xpd;
|
xpd_t *xpd;
|
||||||
|
|
||||||
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,
|
||||||
xpd->type, xpd_driver->type);
|
"SYSFS match fail: xpd->type = %d, xpd_driver->type = %d\n",
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct device_attribute xpd_dev_attrs[] = {
|
static struct device_attribute xpd_dev_attrs[] = {
|
||||||
__ATTR(chipregs, S_IRUGO | S_IWUSR, chipregs_show, chipregs_store),
|
__ATTR(chipregs, S_IRUGO | S_IWUSR, chipregs_show, chipregs_store),
|
||||||
__ATTR(blink, S_IRUGO | S_IWUSR, blink_show, blink_store),
|
__ATTR(blink, S_IRUGO | S_IWUSR, blink_show, blink_store),
|
||||||
__ATTR(span, S_IRUGO | S_IWUSR, span_show, span_store),
|
__ATTR(span, S_IRUGO | S_IWUSR, span_show, span_store),
|
||||||
__ATTR_RO(type),
|
__ATTR_RO(type),
|
||||||
__ATTR_RO(offhook),
|
__ATTR_RO(offhook),
|
||||||
__ATTR_RO(timing_priority),
|
__ATTR_RO(timing_priority),
|
||||||
__ATTR_RO(refcount_xpd),
|
__ATTR_RO(refcount_xpd),
|
||||||
__ATTR_NULL,
|
__ATTR_NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct bus_type xpd_type = {
|
static struct bus_type xpd_type = {
|
||||||
.name = "xpds",
|
.name = "xpds",
|
||||||
.match = xpd_match,
|
.match = xpd_match,
|
||||||
.dev_attrs = xpd_dev_attrs,
|
.dev_attrs = xpd_dev_attrs,
|
||||||
};
|
};
|
||||||
|
|
||||||
int xpd_driver_register(struct device_driver *driver)
|
int xpd_driver_register(struct device_driver *driver)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
@ -772,7 +806,7 @@ void xpd_driver_unregister(struct device_driver *driver)
|
|||||||
|
|
||||||
static void xpd_release(struct device *dev)
|
static void xpd_release(struct device *dev)
|
||||||
{
|
{
|
||||||
xpd_t *xpd;
|
xpd_t *xpd;
|
||||||
|
|
||||||
BUG_ON(!dev);
|
BUG_ON(!dev);
|
||||||
xpd = dev_to_xpd(dev);
|
xpd = dev_to_xpd(dev);
|
||||||
@ -782,14 +816,14 @@ static void xpd_release(struct device *dev)
|
|||||||
|
|
||||||
int xpd_device_register(xbus_t *xbus, xpd_t *xpd)
|
int xpd_device_register(xbus_t *xbus, xpd_t *xpd)
|
||||||
{
|
{
|
||||||
struct device *dev = &xpd->xpd_dev;
|
struct device *dev = &xpd->xpd_dev;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
XPD_DBG(DEVICES, xpd, "SYSFS\n");
|
XPD_DBG(DEVICES, xpd, "SYSFS\n");
|
||||||
dev->bus = &xpd_type;
|
dev->bus = &xpd_type;
|
||||||
dev->parent = &xbus->astribank;
|
dev->parent = &xbus->astribank;
|
||||||
dev_set_name(dev, "%02d:%1x:%1x", xbus->num, xpd->addr.unit,
|
dev_set_name(dev, "%02d:%1x:%1x", xbus->num, xpd->addr.unit,
|
||||||
xpd->addr.subunit);
|
xpd->addr.subunit);
|
||||||
dev_set_drvdata(dev, xpd);
|
dev_set_drvdata(dev, xpd);
|
||||||
dev->release = xpd_release;
|
dev->release = xpd_release;
|
||||||
ret = device_register(dev);
|
ret = device_register(dev);
|
||||||
@ -802,8 +836,8 @@ int xpd_device_register(xbus_t *xbus, xpd_t *xpd)
|
|||||||
|
|
||||||
void xpd_device_unregister(xpd_t *xpd)
|
void xpd_device_unregister(xpd_t *xpd)
|
||||||
{
|
{
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
|
|
||||||
xbus = xpd->xbus;
|
xbus = xpd->xbus;
|
||||||
BUG_ON(!xbus);
|
BUG_ON(!xbus);
|
||||||
@ -890,8 +924,8 @@ static DEVICE_ATTR_WRITER(echocancel_store, dev, buf, count)
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEVICE_ATTR(echocancel, S_IRUGO | S_IWUSR, echocancel_show,
|
static DEVICE_ATTR(echocancel, S_IRUGO | S_IWUSR, echocancel_show,
|
||||||
echocancel_store);
|
echocancel_store);
|
||||||
|
|
||||||
int echocancel_xpd(xpd_t *xpd, int on)
|
int echocancel_xpd(xpd_t *xpd, int on)
|
||||||
{
|
{
|
||||||
@ -905,19 +939,19 @@ 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 ----*/
|
||||||
|
|
||||||
void xbus_sysfs_transport_remove(xbus_t *xbus)
|
void xbus_sysfs_transport_remove(xbus_t *xbus)
|
||||||
{
|
{
|
||||||
struct device *astribank;
|
struct device *astribank;
|
||||||
|
|
||||||
BUG_ON(!xbus);
|
BUG_ON(!xbus);
|
||||||
XBUS_DBG(DEVICES, xbus, "\n");
|
XBUS_DBG(DEVICES, xbus, "\n");
|
||||||
@ -927,9 +961,9 @@ void xbus_sysfs_transport_remove(xbus_t *xbus)
|
|||||||
|
|
||||||
int xbus_sysfs_transport_create(xbus_t *xbus)
|
int xbus_sysfs_transport_create(xbus_t *xbus)
|
||||||
{
|
{
|
||||||
struct device *astribank;
|
struct device *astribank;
|
||||||
struct device *transport_device;
|
struct device *transport_device;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
BUG_ON(!xbus);
|
BUG_ON(!xbus);
|
||||||
XBUS_DBG(DEVICES, xbus, "\n");
|
XBUS_DBG(DEVICES, xbus, "\n");
|
||||||
@ -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 =
|
||||||
"transport");
|
sysfs_create_link(&astribank->kobj, &transport_device->kobj,
|
||||||
|
"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;
|
||||||
@ -952,7 +987,7 @@ int xbus_sysfs_transport_create(xbus_t *xbus)
|
|||||||
|
|
||||||
void xbus_sysfs_remove(xbus_t *xbus)
|
void xbus_sysfs_remove(xbus_t *xbus)
|
||||||
{
|
{
|
||||||
struct device *astribank;
|
struct device *astribank;
|
||||||
|
|
||||||
BUG_ON(!xbus);
|
BUG_ON(!xbus);
|
||||||
XBUS_DBG(DEVICES, xbus, "\n");
|
XBUS_DBG(DEVICES, xbus, "\n");
|
||||||
@ -966,8 +1001,8 @@ void xbus_sysfs_remove(xbus_t *xbus)
|
|||||||
|
|
||||||
int xbus_sysfs_create(xbus_t *xbus)
|
int xbus_sysfs_create(xbus_t *xbus)
|
||||||
{
|
{
|
||||||
struct device *astribank;
|
struct device *astribank;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
BUG_ON(!xbus);
|
BUG_ON(!xbus);
|
||||||
astribank = &xbus->astribank;
|
astribank = &xbus->astribank;
|
||||||
@ -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;
|
||||||
@ -987,22 +1023,22 @@ int xbus_sysfs_create(xbus_t *xbus)
|
|||||||
|
|
||||||
int __init xpp_driver_init(void)
|
int __init xpp_driver_init(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
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;
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
/* This is to enable user-space programs to include this. */
|
/* This is to enable user-space programs to include this. */
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
typedef uint8_t __u8;
|
typedef uint8_t __u8;
|
||||||
typedef uint32_t __u32;
|
typedef uint32_t __u32;
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -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
|
||||||
|
|
||||||
@ -53,7 +56,7 @@ struct list_head { struct list_head *next; struct list_head *prev; };
|
|||||||
|
|
||||||
#define ALL_LINES ((lineno_t)-1)
|
#define ALL_LINES ((lineno_t)-1)
|
||||||
|
|
||||||
#ifndef BIT /* added in 2.6.24 */
|
#ifndef BIT /* added in 2.6.24 */
|
||||||
#define BIT(i) (1UL << (i))
|
#define BIT(i) (1UL << (i))
|
||||||
#endif
|
#endif
|
||||||
#define BIT_SET(x, i) ((x) |= BIT(i))
|
#define BIT_SET(x, i) ((x) |= BIT(i))
|
||||||
@ -95,10 +98,10 @@ struct list_head { struct list_head *next; struct list_head *prev; };
|
|||||||
|
|
||||||
#define VALID_XPD_NUM(x) ((x) < MAX_XPDS && (x) >= 0)
|
#define VALID_XPD_NUM(x) ((x) < MAX_XPDS && (x) >= 0)
|
||||||
|
|
||||||
#define CHAN_BITS 5 /* 0-31 for E1 */
|
#define CHAN_BITS 5 /* 0-31 for E1 */
|
||||||
|
|
||||||
typedef char *charp;
|
typedef char *charp;
|
||||||
typedef unsigned char byte;
|
typedef unsigned char byte;
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
/* Kernel versions... */
|
/* Kernel versions... */
|
||||||
@ -121,7 +124,7 @@ typedef unsigned char byte;
|
|||||||
#define OLD_HOTPLUG_SUPPORT // for older kernels
|
#define OLD_HOTPLUG_SUPPORT // for older kernels
|
||||||
#endif
|
#endif
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
|
||||||
#define OLD_HOTPLUG_SUPPORT_269// for way older kernels
|
#define OLD_HOTPLUG_SUPPORT_269 // for way older kernels
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
|
||||||
@ -149,20 +152,20 @@ typedef unsigned char byte;
|
|||||||
* same linux-2.6-net-infrastructure-updates-to-mac80211-iwl4965.patch
|
* same linux-2.6-net-infrastructure-updates-to-mac80211-iwl4965.patch
|
||||||
* as is the bool typedef. */
|
* as is the bool typedef. */
|
||||||
#if LINUX_VERSION_CODE != KERNEL_VERSION(2, 6, 18) || ! defined(hex_asc)
|
#if LINUX_VERSION_CODE != KERNEL_VERSION(2, 6, 18) || ! defined(hex_asc)
|
||||||
typedef int bool;
|
typedef int bool;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
typedef int bool;
|
typedef int bool;
|
||||||
#endif
|
#endif
|
||||||
typedef struct xbus xbus_t;
|
typedef struct xbus xbus_t;
|
||||||
typedef struct xpd xpd_t;
|
typedef struct xpd xpd_t;
|
||||||
typedef struct xframe xframe_t;
|
typedef struct xframe xframe_t;
|
||||||
typedef struct xpacket xpacket_t;
|
typedef struct xpacket xpacket_t;
|
||||||
typedef __u32 xpp_line_t; /* at most 31 lines for E1 */
|
typedef __u32 xpp_line_t; /* at most 31 lines for E1 */
|
||||||
typedef byte lineno_t;
|
typedef byte lineno_t;
|
||||||
typedef byte xportno_t;
|
typedef byte xportno_t;
|
||||||
|
|
||||||
#define PORT_BROADCAST 255
|
#define PORT_BROADCAST 255
|
||||||
|
|
||||||
#endif /* XDEFS_H */
|
#endif /* XDEFS_H */
|
||||||
|
@ -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);
|
||||||
@ -21,34 +22,33 @@ void xframe_queue_init(struct xframe_queue *q, unsigned int steady_state_count,
|
|||||||
void xframe_queue_clearstats(struct xframe_queue *q)
|
void xframe_queue_clearstats(struct xframe_queue *q)
|
||||||
{
|
{
|
||||||
q->worst_count = 0;
|
q->worst_count = 0;
|
||||||
//q->overflows = 0; /* Never clear overflows */
|
//q->overflows = 0; /* Never clear overflows */
|
||||||
q->worst_lag_usec = 0L;
|
q->worst_lag_usec = 0L;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __xframe_dump_queue(struct xframe_queue *q)
|
static void __xframe_dump_queue(struct xframe_queue *q)
|
||||||
{
|
{
|
||||||
xframe_t *xframe;
|
xframe_t *xframe;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
char prefix[30];
|
char prefix[30];
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
|
|
||||||
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);
|
||||||
snprintf(prefix, ARRAY_SIZE(prefix), " %3d> %5ld.%03ld msec",
|
snprintf(prefix, ARRAY_SIZE(prefix), " %3d> %5ld.%03ld msec",
|
||||||
i++, usec / 1000, usec % 1000);
|
i++, usec / 1000, usec % 1000);
|
||||||
dump_packet(prefix, pack, 1);
|
dump_packet(prefix, pack, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool __xframe_enqueue(struct xframe_queue *q, xframe_t *xframe)
|
static bool __xframe_enqueue(struct xframe_queue *q, xframe_t *xframe)
|
||||||
{
|
{
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
static int overflow_cnt;
|
static int overflow_cnt;
|
||||||
|
|
||||||
if (unlikely(q->disabled)) {
|
if (unlikely(q->disabled)) {
|
||||||
ret = 0;
|
ret = 0;
|
||||||
@ -57,15 +57,12 @@ 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_lag_usec / 1000,
|
||||||
q->worst_count,
|
q->worst_lag_usec % 1000);
|
||||||
q->overflows,
|
|
||||||
q->worst_lag_usec / 1000,
|
|
||||||
q->worst_lag_usec % 1000);
|
|
||||||
__xframe_dump_queue(q);
|
__xframe_dump_queue(q);
|
||||||
}
|
}
|
||||||
ret = 0;
|
ret = 0;
|
||||||
@ -81,8 +78,8 @@ out:
|
|||||||
|
|
||||||
bool xframe_enqueue(struct xframe_queue *q, xframe_t *xframe)
|
bool xframe_enqueue(struct xframe_queue *q, xframe_t *xframe)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
spin_lock_irqsave(&q->lock, flags);
|
spin_lock_irqsave(&q->lock, flags);
|
||||||
ret = __xframe_enqueue(q, xframe);
|
ret = __xframe_enqueue(q, xframe);
|
||||||
@ -92,10 +89,10 @@ bool xframe_enqueue(struct xframe_queue *q, xframe_t *xframe)
|
|||||||
|
|
||||||
static xframe_t *__xframe_dequeue(struct xframe_queue *q)
|
static xframe_t *__xframe_dequeue(struct xframe_queue *q)
|
||||||
{
|
{
|
||||||
xframe_t *frm = NULL;
|
xframe_t *frm = NULL;
|
||||||
struct list_head *h;
|
struct list_head *h;
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
unsigned long usec_lag;
|
unsigned long usec_lag;
|
||||||
|
|
||||||
if (list_empty(&q->head))
|
if (list_empty(&q->head))
|
||||||
goto out;
|
goto out;
|
||||||
@ -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:
|
||||||
@ -115,14 +114,15 @@ out:
|
|||||||
|
|
||||||
xframe_t *xframe_dequeue(struct xframe_queue *q)
|
xframe_t *xframe_dequeue(struct xframe_queue *q)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
xframe_t *frm;
|
xframe_t *frm;
|
||||||
|
|
||||||
spin_lock_irqsave(&q->lock, flags);
|
spin_lock_irqsave(&q->lock, flags);
|
||||||
frm = __xframe_dequeue(q);
|
frm = __xframe_dequeue(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;
|
||||||
@ -130,16 +130,17 @@ void xframe_queue_disable(struct xframe_queue *q, bool disabled)
|
|||||||
|
|
||||||
void xframe_queue_clear(struct xframe_queue *q)
|
void xframe_queue_clear(struct xframe_queue *q)
|
||||||
{
|
{
|
||||||
xframe_t *xframe;
|
xframe_t *xframe;
|
||||||
xbus_t *xbus = q->priv;
|
xbus_t *xbus = q->priv;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
xframe_queue_disable(q, 1);
|
xframe_queue_disable(q, 1);
|
||||||
while ((xframe = xframe_dequeue(q)) != NULL) {
|
while ((xframe = xframe_dequeue(q)) != NULL) {
|
||||||
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)
|
||||||
@ -151,9 +152,9 @@ uint xframe_queue_count(struct xframe_queue *q)
|
|||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
struct xbus_ops *ops;
|
struct xbus_ops *ops;
|
||||||
xframe_t *xframe;
|
xframe_t *xframe;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
BUG_ON(!xbus);
|
BUG_ON(!xbus);
|
||||||
ops = transportops_get(xbus);
|
ops = transportops_get(xbus);
|
||||||
@ -169,8 +170,8 @@ static xframe_t *transport_alloc_xframe(xbus_t *xbus, gfp_t gfp_flags)
|
|||||||
|
|
||||||
if ((rate_limit++ % 3001) == 0)
|
if ((rate_limit++ % 3001) == 0)
|
||||||
XBUS_ERR(xbus,
|
XBUS_ERR(xbus,
|
||||||
"Failed xframe allocation from transport (%d)\n",
|
"Failed xframe allocation from transport (%d)\n",
|
||||||
rate_limit);
|
rate_limit);
|
||||||
transportops_put(xbus);
|
transportops_put(xbus);
|
||||||
/* fall through */
|
/* fall through */
|
||||||
}
|
}
|
||||||
@ -180,8 +181,8 @@ 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)
|
||||||
{
|
{
|
||||||
struct xbus_ops *ops;
|
struct xbus_ops *ops;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
BUG_ON(!xbus);
|
BUG_ON(!xbus);
|
||||||
ops = xbus->transport.ops;
|
ops = xbus->transport.ops;
|
||||||
@ -195,11 +196,11 @@ static void transport_free_xframe(xbus_t *xbus, xframe_t *xframe)
|
|||||||
|
|
||||||
static bool xframe_queue_adjust(struct xframe_queue *q)
|
static bool xframe_queue_adjust(struct xframe_queue *q)
|
||||||
{
|
{
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
xframe_t *xframe;
|
xframe_t *xframe;
|
||||||
int delta;
|
int delta;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
BUG_ON(!q);
|
BUG_ON(!q);
|
||||||
xbus = q->priv;
|
xbus = q->priv;
|
||||||
@ -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);
|
||||||
@ -246,8 +250,8 @@ out:
|
|||||||
|
|
||||||
xframe_t *get_xframe(struct xframe_queue *q)
|
xframe_t *get_xframe(struct xframe_queue *q)
|
||||||
{
|
{
|
||||||
xframe_t *xframe;
|
xframe_t *xframe;
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
|
|
||||||
BUG_ON(!q);
|
BUG_ON(!q);
|
||||||
xbus = (xbus_t *)q->priv;
|
xbus = (xbus_t *)q->priv;
|
||||||
@ -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);
|
||||||
@ -279,7 +284,7 @@ xframe_t *get_xframe(struct xframe_queue *q)
|
|||||||
|
|
||||||
void put_xframe(struct xframe_queue *q, xframe_t *xframe)
|
void put_xframe(struct xframe_queue *q, xframe_t *xframe)
|
||||||
{
|
{
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
|
|
||||||
BUG_ON(!q);
|
BUG_ON(!q);
|
||||||
xbus = (xbus_t *)q->priv;
|
xbus = (xbus_t *)q->priv;
|
||||||
@ -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);
|
||||||
|
@ -8,23 +8,22 @@
|
|||||||
#define XFRAME_QUEUE_MARGIN 10
|
#define XFRAME_QUEUE_MARGIN 10
|
||||||
|
|
||||||
struct xframe_queue {
|
struct xframe_queue {
|
||||||
struct list_head head;
|
struct list_head head;
|
||||||
bool disabled;
|
bool disabled;
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
unsigned int max_count;
|
unsigned int max_count;
|
||||||
unsigned int steady_state_count;
|
unsigned int steady_state_count;
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
const char *name;
|
const char *name;
|
||||||
void *priv;
|
void *priv;
|
||||||
/* statistics */
|
/* statistics */
|
||||||
unsigned int worst_count;
|
unsigned int worst_count;
|
||||||
unsigned int overflows;
|
unsigned int overflows;
|
||||||
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);
|
||||||
@ -32,4 +31,4 @@ void xframe_queue_disable(struct xframe_queue *q, bool disabled);
|
|||||||
void xframe_queue_clear(struct xframe_queue *q);
|
void xframe_queue_clear(struct xframe_queue *q);
|
||||||
uint xframe_queue_count(struct xframe_queue *q);
|
uint xframe_queue_count(struct xframe_queue *q);
|
||||||
|
|
||||||
#endif /* XFRAME_QUEUE_ */
|
#endif /* XFRAME_QUEUE_ */
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
#include <asm/semaphore.h>
|
#include <asm/semaphore.h>
|
||||||
#endif
|
#endif
|
||||||
#include <linux/moduleparam.h>
|
#include <linux/moduleparam.h>
|
||||||
#endif /* __KERNEL__ */
|
#endif /* __KERNEL__ */
|
||||||
|
|
||||||
#include <dahdi/kernel.h>
|
#include <dahdi/kernel.h>
|
||||||
|
|
||||||
@ -45,7 +45,7 @@
|
|||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
|
||||||
/* also added in RHEL kernels with the OpenInfiniband backport: */
|
/* also added in RHEL kernels with the OpenInfiniband backport: */
|
||||||
#if LINUX_VERSION_CODE != KERNEL_VERSION(2, 6, 9) || !defined(DEFINE_SPINLOCK)
|
#if LINUX_VERSION_CODE != KERNEL_VERSION(2, 6, 9) || !defined(DEFINE_SPINLOCK)
|
||||||
typedef unsigned gfp_t; /* Added in 2.6.14 */
|
typedef unsigned gfp_t; /* Added in 2.6.14 */
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -81,21 +81,21 @@ typedef unsigned gfp_t; /* Added in 2.6.14 */
|
|||||||
module_param_array(name, type, &name ## _num_values, 0644); \
|
module_param_array(name, type, &name ## _num_values, 0644); \
|
||||||
MODULE_PARM_DESC(name, desc " ( 1-" __MODULE_STRING(count) ")")
|
MODULE_PARM_DESC(name, desc " ( 1-" __MODULE_STRING(count) ")")
|
||||||
#endif
|
#endif
|
||||||
#endif // __KERNEL__
|
#endif // __KERNEL__
|
||||||
|
|
||||||
#define CARD_DESC_MAGIC 0xca9dde5c
|
#define CARD_DESC_MAGIC 0xca9dde5c
|
||||||
|
|
||||||
struct card_desc_struct {
|
struct card_desc_struct {
|
||||||
struct list_head card_list;
|
struct list_head card_list;
|
||||||
u32 magic;
|
u32 magic;
|
||||||
__u8 type; /* LSB: 1 - to_phone, 0 - to_line */
|
__u8 type; /* LSB: 1 - to_phone, 0 - to_line */
|
||||||
__u8 subtype;
|
__u8 subtype;
|
||||||
struct xpd_addr xpd_addr;
|
struct xpd_addr xpd_addr;
|
||||||
__u8 numchips;
|
__u8 numchips;
|
||||||
__u8 ports_per_chip;
|
__u8 ports_per_chip;
|
||||||
__u8 ports;
|
__u8 ports;
|
||||||
__u8 port_dir;
|
__u8 port_dir;
|
||||||
struct xpd_addr ec_addr; /* echo canceler address */
|
struct xpd_addr ec_addr; /* echo canceler address */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum xpd_direction {
|
typedef enum xpd_direction {
|
||||||
@ -120,12 +120,9 @@ enum {
|
|||||||
|
|
||||||
/* yucky, make an instance so we can size it... */
|
/* yucky, make an instance so we can size it... */
|
||||||
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_
|
||||||
|
|
||||||
@ -138,43 +135,43 @@ enum xpd_state {
|
|||||||
XPD_STATE_NOHW,
|
XPD_STATE_NOHW,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool xpd_setstate(xpd_t *xpd, enum xpd_state newstate);
|
bool xpd_setstate(xpd_t *xpd, enum xpd_state newstate);
|
||||||
const char *xpd_statename(enum xpd_state st);
|
const char *xpd_statename(enum xpd_state st);
|
||||||
|
|
||||||
#define PHONEDEV(xpd) ((xpd)->phonedev)
|
#define PHONEDEV(xpd) ((xpd)->phonedev)
|
||||||
#define IS_PHONEDEV(xpd) (PHONEDEV(xpd).phoneops)
|
#define IS_PHONEDEV(xpd) (PHONEDEV(xpd).phoneops)
|
||||||
|
|
||||||
struct phonedev {
|
struct phonedev {
|
||||||
const struct phoneops *phoneops; /* Card level operations */
|
const struct phoneops *phoneops; /* Card level operations */
|
||||||
struct dahdi_span span;
|
struct dahdi_span span;
|
||||||
struct dahdi_chan *chans[32];
|
struct dahdi_chan *chans[32];
|
||||||
#define XPD_CHAN(xpd, chan) (PHONEDEV(xpd).chans[(chan)])
|
#define XPD_CHAN(xpd, chan) (PHONEDEV(xpd).chans[(chan)])
|
||||||
struct dahdi_echocan_state *ec[32];
|
struct dahdi_echocan_state *ec[32];
|
||||||
|
|
||||||
int channels;
|
int channels;
|
||||||
xpd_direction_t direction; /* TO_PHONE, TO_PSTN */
|
xpd_direction_t direction; /* TO_PHONE, TO_PSTN */
|
||||||
xpp_line_t no_pcm; /* Temporary: disable PCM (for USB-1) */
|
xpp_line_t no_pcm; /* Temporary: disable PCM (for USB-1) */
|
||||||
xpp_line_t offhook_state; /* Actual chip state: 0 - ONHOOK, 1 - OFHOOK */
|
xpp_line_t offhook_state; /* Actual chip state: 0 - ONHOOK, 1 - OFHOOK */
|
||||||
xpp_line_t oht_pcm_pass; /* Transfer on-hook PCM */
|
xpp_line_t oht_pcm_pass; /* Transfer on-hook PCM */
|
||||||
/* Voice Mail Waiting Indication: */
|
/* Voice Mail Waiting Indication: */
|
||||||
unsigned int msg_waiting[CHANNELS_PERXPD];
|
unsigned int msg_waiting[CHANNELS_PERXPD];
|
||||||
xpp_line_t digital_outputs; /* 0 - no, 1 - yes */
|
xpp_line_t digital_outputs; /* 0 - no, 1 - yes */
|
||||||
xpp_line_t digital_inputs; /* 0 - no, 1 - yes */
|
xpp_line_t digital_inputs; /* 0 - no, 1 - yes */
|
||||||
xpp_line_t digital_signalling; /* BRI signalling channels */
|
xpp_line_t digital_signalling; /* BRI signalling channels */
|
||||||
uint timing_priority; /* from 'span' directives in chan_dahdi.conf */
|
uint timing_priority; /* from 'span' directives in chan_dahdi.conf */
|
||||||
|
|
||||||
/* Assure atomicity of changes to pcm_len and wanted_pcm_mask */
|
/* Assure atomicity of changes to pcm_len and wanted_pcm_mask */
|
||||||
spinlock_t lock_recompute_pcm;
|
spinlock_t lock_recompute_pcm;
|
||||||
/* maintained by card drivers */
|
/* maintained by card drivers */
|
||||||
uint pcm_len; /* allocation length of PCM packet (dynamic) */
|
uint pcm_len; /* allocation length of PCM packet (dynamic) */
|
||||||
xpp_line_t wanted_pcm_mask;
|
xpp_line_t wanted_pcm_mask;
|
||||||
xpp_line_t silence_pcm; /* inject silence during next tick */
|
xpp_line_t silence_pcm; /* inject silence during next tick */
|
||||||
xpp_line_t mute_dtmf;
|
xpp_line_t mute_dtmf;
|
||||||
|
|
||||||
bool ringing[CHANNELS_PERXPD];
|
bool ringing[CHANNELS_PERXPD];
|
||||||
|
|
||||||
atomic_t dahdi_registered; /* Am I fully registered with dahdi */
|
atomic_t dahdi_registered; /* Am I fully registered with dahdi */
|
||||||
atomic_t open_counter; /* Number of open channels */
|
atomic_t open_counter; /* Number of open channels */
|
||||||
|
|
||||||
/* Echo cancelation */
|
/* Echo cancelation */
|
||||||
u_char ec_chunk1[CHANNELS_PERXPD][DAHDI_CHUNKSIZE];
|
u_char ec_chunk1[CHANNELS_PERXPD][DAHDI_CHUNKSIZE];
|
||||||
@ -186,51 +183,51 @@ struct phonedev {
|
|||||||
*/
|
*/
|
||||||
struct xpd {
|
struct xpd {
|
||||||
char xpdname[XPD_NAMELEN];
|
char xpdname[XPD_NAMELEN];
|
||||||
struct phonedev phonedev;
|
struct phonedev phonedev;
|
||||||
|
|
||||||
const struct xops *xops;
|
const struct xops *xops;
|
||||||
xpd_type_t type;
|
xpd_type_t type;
|
||||||
const char *type_name;
|
const char *type_name;
|
||||||
__u8 subtype;
|
__u8 subtype;
|
||||||
int subunits; /* all siblings */
|
int subunits; /* all siblings */
|
||||||
enum xpd_state xpd_state;
|
enum xpd_state xpd_state;
|
||||||
struct device xpd_dev;
|
struct device xpd_dev;
|
||||||
#define dev_to_xpd(dev) container_of(dev, struct xpd, xpd_dev)
|
#define dev_to_xpd(dev) container_of(dev, struct xpd, xpd_dev)
|
||||||
struct kref kref;
|
struct kref kref;
|
||||||
#define kref_to_xpd(k) container_of(k, struct xpd, kref)
|
#define kref_to_xpd(k) container_of(k, struct xpd, kref)
|
||||||
|
|
||||||
xbus_t *xbus; /* The XBUS we are connected to */
|
xbus_t *xbus; /* The XBUS we are connected to */
|
||||||
struct device *echocancel;
|
struct device *echocancel;
|
||||||
|
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
|
|
||||||
int flags;
|
int flags;
|
||||||
unsigned long blink_mode; /* bitmask of blinking ports */
|
unsigned long blink_mode; /* bitmask of blinking ports */
|
||||||
#define DEFAULT_LED_PERIOD (1000/8) /* in tick */
|
#define DEFAULT_LED_PERIOD (1000/8) /* in tick */
|
||||||
|
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
struct proc_dir_entry *proc_xpd_dir;
|
struct proc_dir_entry *proc_xpd_dir;
|
||||||
struct proc_dir_entry *proc_xpd_summary;
|
struct proc_dir_entry *proc_xpd_summary;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int counters[XPD_COUNTER_MAX];
|
int counters[XPD_COUNTER_MAX];
|
||||||
|
|
||||||
const xproto_table_t *xproto; /* Card level protocol table */
|
const xproto_table_t *xproto; /* Card level protocol table */
|
||||||
void *priv; /* Card level private data */
|
void *priv; /* Card level private data */
|
||||||
bool card_present;
|
bool card_present;
|
||||||
reg_cmd_t requested_reply;
|
reg_cmd_t requested_reply;
|
||||||
reg_cmd_t last_reply;
|
reg_cmd_t last_reply;
|
||||||
|
|
||||||
unsigned long last_response; /* in jiffies */
|
unsigned long last_response; /* in jiffies */
|
||||||
unsigned xbus_idx; /* index in xbus->xpds[] */
|
unsigned xbus_idx; /* index in xbus->xpds[] */
|
||||||
struct xpd_addr addr;
|
struct xpd_addr addr;
|
||||||
struct list_head xpd_list;
|
struct list_head xpd_list;
|
||||||
unsigned int timer_count;
|
unsigned int timer_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define for_each_line(xpd, i) for ((i) = 0; (i) < PHONEDEV(xpd).channels; (i)++)
|
#define for_each_line(xpd, i) for ((i) = 0; (i) < PHONEDEV(xpd).channels; (i)++)
|
||||||
#define IS_BRI(xpd) ((xpd)->type == XPD_TYPE_BRI)
|
#define IS_BRI(xpd) ((xpd)->type == XPD_TYPE_BRI)
|
||||||
#define TICK_TOLERANCE 500 /* usec */
|
#define TICK_TOLERANCE 500 /* usec */
|
||||||
|
|
||||||
#ifdef DEBUG_SYNC_PARPORT
|
#ifdef DEBUG_SYNC_PARPORT
|
||||||
void xbus_flip_bit(xbus_t *xbus, unsigned int bitnum0, unsigned int bitnum1);
|
void xbus_flip_bit(xbus_t *xbus, unsigned int bitnum0, unsigned int bitnum1);
|
||||||
@ -240,7 +237,7 @@ void xbus_flip_bit(xbus_t *xbus, unsigned int bitnum0, unsigned int bitnum1);
|
|||||||
|
|
||||||
static inline void *my_kzalloc(size_t size, gfp_t flags)
|
static inline void *my_kzalloc(size_t size, gfp_t flags)
|
||||||
{
|
{
|
||||||
void *p;
|
void *p;
|
||||||
|
|
||||||
p = kmalloc(size, flags);
|
p = kmalloc(size, flags);
|
||||||
if (p)
|
if (p)
|
||||||
@ -249,18 +246,18 @@ static inline void *my_kzalloc(size_t size, gfp_t flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct xpd_driver {
|
struct xpd_driver {
|
||||||
xpd_type_t type;
|
xpd_type_t type;
|
||||||
|
|
||||||
struct device_driver driver;
|
struct device_driver driver;
|
||||||
#define driver_to_xpd_driver(driver) container_of(driver, struct xpd_driver, driver)
|
#define driver_to_xpd_driver(driver) container_of(driver, struct xpd_driver, driver)
|
||||||
};
|
};
|
||||||
|
|
||||||
int xpd_driver_register(struct device_driver *driver);
|
int xpd_driver_register(struct device_driver *driver);
|
||||||
void xpd_driver_unregister(struct device_driver *driver);
|
void xpd_driver_unregister(struct device_driver *driver);
|
||||||
xpd_t *get_xpd(const char *msg, xpd_t *xpd);
|
xpd_t *get_xpd(const char *msg, xpd_t *xpd);
|
||||||
void put_xpd(const char *msg, xpd_t *xpd);
|
void put_xpd(const char *msg, xpd_t *xpd);
|
||||||
int refcount_xpd(xpd_t *xpd);
|
int refcount_xpd(xpd_t *xpd);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* XPD_H */
|
#endif /* XPD_H */
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
|
||||||
# warning "This module is tested only with 2.6 kernels"
|
#warning "This module is tested only with 2.6 kernels"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
@ -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);
|
||||||
@ -90,13 +92,14 @@ MODULE_PARM_DESC(parport_xbuses, "Id's of xbuses to sample (1-2)");
|
|||||||
*/
|
*/
|
||||||
void xbus_flip_bit(xbus_t *xbus, unsigned int bitnum0, unsigned int bitnum1)
|
void xbus_flip_bit(xbus_t *xbus, unsigned int bitnum0, unsigned int bitnum1)
|
||||||
{
|
{
|
||||||
int num = xbus->num;
|
int num = xbus->num;
|
||||||
|
|
||||||
if (num == parport_xbuses[0])
|
if (num == parport_xbuses[0])
|
||||||
flip_parport_bit(bitnum0);
|
flip_parport_bit(bitnum0);
|
||||||
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 -------------------------*/
|
||||||
@ -118,7 +122,7 @@ static int xpd_read_proc(char *page, char **start, off_t off, int count, int *eo
|
|||||||
*/
|
*/
|
||||||
static void xpd_destroy(struct kref *kref)
|
static void xpd_destroy(struct kref *kref)
|
||||||
{
|
{
|
||||||
xpd_t *xpd;
|
xpd_t *xpd;
|
||||||
|
|
||||||
xpd = kref_to_xpd(kref);
|
xpd = kref_to_xpd(kref);
|
||||||
XPD_DBG(DEVICES, xpd, "%s\n", __func__);
|
XPD_DBG(DEVICES, xpd, "%s\n", __func__);
|
||||||
@ -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,12 +154,13 @@ 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;
|
||||||
}
|
}
|
||||||
XPD_DBG(PROC, xpd, "Removing %s/%s proc directory\n",
|
XPD_DBG(PROC, xpd, "Removing %s/%s proc directory\n",
|
||||||
xbus->busname, xpd->xpdname);
|
xbus->busname, xpd->xpdname);
|
||||||
remove_proc_entry(xpd->xpdname, xbus->proc_xbus_dir);
|
remove_proc_entry(xpd->xpdname, xbus->proc_xbus_dir);
|
||||||
xpd->proc_xpd_dir = NULL;
|
xpd->proc_xpd_dir = 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 =
|
||||||
xpd_read_proc, xpd);
|
create_proc_read_entry(PROC_XPD_SUMMARY, 0444, xpd->proc_xpd_dir,
|
||||||
|
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);
|
||||||
@ -191,7 +196,7 @@ err:
|
|||||||
|
|
||||||
void xpd_free(xpd_t *xpd)
|
void xpd_free(xpd_t *xpd)
|
||||||
{
|
{
|
||||||
xbus_t *xbus = NULL;
|
xbus_t *xbus = NULL;
|
||||||
|
|
||||||
if (!xpd)
|
if (!xpd)
|
||||||
return;
|
return;
|
||||||
@ -210,43 +215,41 @@ void xpd_free(xpd_t *xpd)
|
|||||||
/*
|
/*
|
||||||
* This must be last, so the xbus cannot be released before the xpd
|
* This must be last, so the xbus cannot be released before the xpd
|
||||||
*/
|
*/
|
||||||
put_xbus(__func__, xbus); /* was taken in xpd_alloc() */
|
put_xbus(__func__, xbus); /* was taken in xpd_alloc() */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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;
|
||||||
|
|
||||||
BUG_ON(type == XPD_TYPE_NOMODULE);
|
BUG_ON(type == XPD_TYPE_NOMODULE);
|
||||||
to_phone = BIT(subunit) & port_dir;
|
to_phone = BIT(subunit) & port_dir;
|
||||||
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) {
|
||||||
XBUS_NOTICE(xbus, "Illegal number of ports %d for XPD %d%d\n",
|
XBUS_NOTICE(xbus, "Illegal number of ports %d for XPD %d%d\n",
|
||||||
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,43 +266,55 @@ 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;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
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, xpd->timer_count,
|
||||||
PHONEDEV(xpd).timing_priority,
|
PHONEDEV(xpd).span.mainttimer);
|
||||||
xpd->timer_count, PHONEDEV(xpd).span.mainttimer
|
len +=
|
||||||
);
|
sprintf(page + len, "xpd_state: %s (%d)\n",
|
||||||
len += 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 +=
|
||||||
len += sprintf(page + len, "open_counter=%d refcount=%d\n",
|
sprintf(page + len, "open_counter=%d refcount=%d\n",
|
||||||
atomic_read(&PHONEDEV(xpd).open_counter), refcount_xpd(xpd));
|
atomic_read(&PHONEDEV(xpd).open_counter),
|
||||||
len += sprintf(page + len, "Address: U=%d S=%d\n", xpd->addr.unit, xpd->addr.subunit);
|
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,17 +336,20 @@ 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];
|
||||||
__u8 wchunk[DAHDI_CHUNKSIZE];
|
__u8 wchunk[DAHDI_CHUNKSIZE];
|
||||||
__u8 *rp;
|
__u8 *rp;
|
||||||
__u8 *wp;
|
__u8 *wp;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
if (IS_SET(PHONEDEV(xpd).digital_outputs, i))
|
if (IS_SET(PHONEDEV(xpd).digital_outputs, i))
|
||||||
@ -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,18 +386,22 @@ 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 +=
|
||||||
xpd_counters[i].name, xpd->counters[i]);
|
sprintf(page + len, "\t\t%-20s = %d\n",
|
||||||
|
xpd_counters[i].name, xpd->counters[i]);
|
||||||
}
|
}
|
||||||
len += sprintf(page + len, "<-- len=%d\n", len);
|
len += sprintf(page + len, "<-- len=%d\n", len);
|
||||||
out:
|
out:
|
||||||
if (len <= off+count)
|
if (len <= off + count)
|
||||||
*eof = 1;
|
*eof = 1;
|
||||||
*start = page + off;
|
*start = page + off;
|
||||||
len -= off;
|
len -= off;
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
@ -412,8 +444,8 @@ bool xpd_setstate(xpd_t *xpd, enum xpd_state newstate)
|
|||||||
goto badstate;
|
goto badstate;
|
||||||
if (xpd->addr.subunit != 0) {
|
if (xpd->addr.subunit != 0) {
|
||||||
XPD_NOTICE(xpd,
|
XPD_NOTICE(xpd,
|
||||||
"%s: Moving to %s allowed only for subunit 0\n",
|
"%s: Moving to %s allowed only for subunit 0\n",
|
||||||
__func__, xpd_statename(newstate));
|
__func__, xpd_statename(newstate));
|
||||||
goto badstate;
|
goto badstate;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -435,21 +467,19 @@ 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
|
||||||
*/
|
*/
|
||||||
static void phonedev_cleanup(xpd_t *xpd)
|
static void phonedev_cleanup(xpd_t *xpd)
|
||||||
{
|
{
|
||||||
struct phonedev *phonedev = &PHONEDEV(xpd);
|
struct phonedev *phonedev = &PHONEDEV(xpd);
|
||||||
unsigned int x;
|
unsigned int x;
|
||||||
|
|
||||||
for (x = 0; x < phonedev->channels; x++) {
|
for (x = 0; x < phonedev->channels; x++) {
|
||||||
if (phonedev->chans[x]) {
|
if (phonedev->chans[x]) {
|
||||||
@ -460,11 +490,12 @@ 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,
|
||||||
int channels, xpp_line_t no_pcm)
|
const xproto_table_t *proto_table,
|
||||||
|
int channels, xpp_line_t no_pcm)
|
||||||
{
|
{
|
||||||
struct phonedev *phonedev = &PHONEDEV(xpd);
|
struct phonedev *phonedev = &PHONEDEV(xpd);
|
||||||
unsigned int x;
|
unsigned int x;
|
||||||
|
|
||||||
spin_lock_init(&phonedev->lock_recompute_pcm);
|
spin_lock_init(&phonedev->lock_recompute_pcm);
|
||||||
phonedev->channels = channels;
|
phonedev->channels = channels;
|
||||||
@ -476,15 +507,17 @@ __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);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -498,28 +531,27 @@ 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;
|
||||||
int type = proto_table->type;
|
int type = proto_table->type;
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((xpd = KZALLOC(alloc_size, GFP_KERNEL)) == NULL) {
|
if ((xpd = KZALLOC(alloc_size, GFP_KERNEL)) == NULL) {
|
||||||
XBUS_ERR(xbus, "%s: type=%d: Unable to allocate memory\n",
|
XBUS_ERR(xbus, "%s: type=%d: Unable to allocate memory\n",
|
||||||
__func__, type);
|
__func__, type);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
xpd->priv = (__u8 *)xpd + sizeof(xpd_t);
|
xpd->priv = (__u8 *)xpd + sizeof(xpd_t);
|
||||||
@ -535,9 +567,12 @@ __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).
|
||||||
MAX_SEND_SIZE(xbus), PHONEDEV(xpd).no_pcm);
|
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);
|
||||||
}
|
}
|
||||||
if (phonedev_init(xpd, proto_table, channels, no_pcm) < 0)
|
if (phonedev_init(xpd, proto_table, channels, no_pcm) < 0)
|
||||||
goto err;
|
goto err;
|
||||||
@ -549,7 +584,7 @@ __must_check xpd_t *xpd_alloc(xbus_t *xbus,
|
|||||||
* is removed in xpd_free()
|
* is removed in xpd_free()
|
||||||
*/
|
*/
|
||||||
xbus = get_xbus(__func__, xbus->num); /* returned in xpd_free() */
|
xbus = get_xbus(__func__, xbus->num); /* returned in xpd_free() */
|
||||||
xproto_get(type); /* will be returned in xpd_free() */
|
xproto_get(type); /* will be returned in xpd_free() */
|
||||||
return xpd;
|
return xpd;
|
||||||
err:
|
err:
|
||||||
if (xpd) {
|
if (xpd) {
|
||||||
@ -580,16 +615,17 @@ void update_xpd_status(xpd_t *xpd, int alarm_flag)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (alarm_flag) {
|
switch (alarm_flag) {
|
||||||
case DAHDI_ALARM_NONE:
|
case DAHDI_ALARM_NONE:
|
||||||
xpd->last_response = jiffies;
|
xpd->last_response = jiffies;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// Nothing
|
// Nothing
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
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,24 +697,24 @@ 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.
|
||||||
*/
|
*/
|
||||||
int xpp_open(struct dahdi_chan *chan)
|
int xpp_open(struct dahdi_chan *chan)
|
||||||
{
|
{
|
||||||
xpd_t *xpd;
|
xpd_t *xpd;
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
int pos;
|
int pos;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
if (!chan) {
|
if (!chan) {
|
||||||
NOTICE("open called on a null chan\n");
|
NOTICE("open called on a null chan\n");
|
||||||
@ -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);
|
||||||
@ -712,25 +747,24 @@ int xpp_open(struct dahdi_chan *chan)
|
|||||||
|
|
||||||
int xpp_close(struct dahdi_chan *chan)
|
int xpp_close(struct dahdi_chan *chan)
|
||||||
{
|
{
|
||||||
xpd_t *xpd = chan->pvt;
|
xpd_t *xpd = chan->pvt;
|
||||||
xbus_t *xbus = xpd->xbus;
|
xbus_t *xbus = xpd->xbus;
|
||||||
int pos = chan->chanpos - 1;
|
int pos = chan->chanpos - 1;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
spin_lock_irqsave(&xbus->lock, flags);
|
spin_lock_irqsave(&xbus->lock, flags);
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
void report_bad_ioctl(const char *msg, xpd_t *xpd, int pos, unsigned int cmd)
|
void report_bad_ioctl(const char *msg, xpd_t *xpd, int pos, unsigned int cmd)
|
||||||
{
|
{
|
||||||
char *extra_msg = "";
|
char *extra_msg = "";
|
||||||
|
|
||||||
if (_IOC_TYPE(cmd) == 'J')
|
if (_IOC_TYPE(cmd) == 'J')
|
||||||
extra_msg = " (for old ZAPTEL)";
|
extra_msg = " (for old ZAPTEL)";
|
||||||
@ -744,48 +778,51 @@ void report_bad_ioctl(const char *msg, xpd_t *xpd, int pos, unsigned int cmd)
|
|||||||
|
|
||||||
int xpp_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long arg)
|
int xpp_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
xpd_t *xpd = chan->pvt;
|
xpd_t *xpd = chan->pvt;
|
||||||
int pos = chan->chanpos - 1;
|
int pos = chan->chanpos - 1;
|
||||||
|
|
||||||
if (!xpd) {
|
if (!xpd) {
|
||||||
ERR("%s: channel in pos %d, was already closed. Ignore.\n",
|
ERR("%s: channel in pos %d, was already closed. Ignore.\n",
|
||||||
__func__, pos);
|
__func__, pos);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
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);
|
}
|
||||||
return -ENOTTY;
|
report_bad_ioctl(THIS_MODULE->name, xpd, pos, cmd);
|
||||||
|
return -ENOTTY;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int xpp_hooksig(struct dahdi_chan *chan, enum dahdi_txsig txsig)
|
int xpp_hooksig(struct dahdi_chan *chan, enum dahdi_txsig txsig)
|
||||||
{
|
{
|
||||||
xpd_t *xpd = chan->pvt;
|
xpd_t *xpd = chan->pvt;
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
int pos = chan->chanpos - 1;
|
int pos = chan->chanpos - 1;
|
||||||
|
|
||||||
if (!xpd) {
|
if (!xpd) {
|
||||||
ERR("%s: channel in pos %d, was already closed. Ignore.\n",
|
ERR("%s: channel in pos %d, was already closed. Ignore.\n",
|
||||||
__func__, pos);
|
__func__, pos);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
if (!PHONE_METHOD(card_hooksig, xpd)) {
|
if (!PHONE_METHOD(card_hooksig, xpd)) {
|
||||||
LINE_ERR(xpd, pos,
|
LINE_ERR(xpd, pos,
|
||||||
"%s: No hooksig method for this channel. Ignore.\n",
|
"%s: No hooksig method for this channel. Ignore.\n",
|
||||||
__func__);
|
__func__);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
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
|
||||||
@ -795,34 +832,34 @@ int xpp_setchunksize(struct dahdi_span *span, int chunksize);
|
|||||||
/* Enable maintenance modes */
|
/* Enable maintenance modes */
|
||||||
int xpp_maint(struct dahdi_span *span, int cmd)
|
int xpp_maint(struct dahdi_span *span, int cmd)
|
||||||
{
|
{
|
||||||
struct phonedev *phonedev = container_of(span, struct phonedev, span);
|
struct phonedev *phonedev = container_of(span, struct phonedev, span);
|
||||||
xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
|
xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
#if 0
|
#if 0
|
||||||
char loopback_data[] = "THE-QUICK-BROWN-FOX-JUMPED-OVER-THE-LAZY-DOG";
|
char loopback_data[] = "THE-QUICK-BROWN-FOX-JUMPED-OVER-THE-LAZY-DOG";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DBG(GENERAL, "span->mainttimer=%d\n", span->mainttimer);
|
DBG(GENERAL, "span->mainttimer=%d\n", span->mainttimer);
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case DAHDI_MAINT_NONE:
|
case DAHDI_MAINT_NONE:
|
||||||
INFO("XXX Turn off local and remote loops XXX\n");
|
INFO("XXX Turn off local and remote loops XXX\n");
|
||||||
break;
|
break;
|
||||||
case DAHDI_MAINT_LOCALLOOP:
|
case DAHDI_MAINT_LOCALLOOP:
|
||||||
INFO("XXX Turn on local loopback XXX\n");
|
INFO("XXX Turn on local loopback XXX\n");
|
||||||
break;
|
break;
|
||||||
case DAHDI_MAINT_REMOTELOOP:
|
case DAHDI_MAINT_REMOTELOOP:
|
||||||
INFO("XXX Turn on remote loopback XXX\n");
|
INFO("XXX Turn on remote loopback XXX\n");
|
||||||
break;
|
break;
|
||||||
case DAHDI_MAINT_LOOPUP:
|
case DAHDI_MAINT_LOOPUP:
|
||||||
INFO("XXX Send loopup code XXX\n");
|
INFO("XXX Send loopup code XXX\n");
|
||||||
break;
|
break;
|
||||||
case DAHDI_MAINT_LOOPDOWN:
|
case DAHDI_MAINT_LOOPDOWN:
|
||||||
INFO("XXX Send loopdown code XXX\n");
|
INFO("XXX Send loopdown code XXX\n");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ERR("XPP: Unknown maint command: %d\n", cmd);
|
ERR("XPP: Unknown maint command: %d\n", cmd);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (span->mainttimer || span->maintstat)
|
if (span->mainttimer || span->maintstat)
|
||||||
update_xpd_status(xpd, DAHDI_ALARM_LOOPBACK);
|
update_xpd_status(xpd, DAHDI_ALARM_LOOPBACK);
|
||||||
@ -836,7 +873,7 @@ int xpp_maint(struct dahdi_span *span, int cmd)
|
|||||||
*/
|
*/
|
||||||
static int xpp_watchdog(struct dahdi_span *span, int cause)
|
static int xpp_watchdog(struct dahdi_span *span, int cause)
|
||||||
{
|
{
|
||||||
static int rate_limit;
|
static int rate_limit;
|
||||||
|
|
||||||
if ((rate_limit++ % 1000) == 0)
|
if ((rate_limit++ % 1000) == 0)
|
||||||
DBG(GENERAL, "\n");
|
DBG(GENERAL, "\n");
|
||||||
@ -848,12 +885,12 @@ static int xpp_watchdog(struct dahdi_span *span, int cause)
|
|||||||
* Hardware Echo Canceller management
|
* Hardware Echo Canceller management
|
||||||
*/
|
*/
|
||||||
static void echocan_free(struct dahdi_chan *chan,
|
static void echocan_free(struct dahdi_chan *chan,
|
||||||
struct dahdi_echocan_state *ec)
|
struct dahdi_echocan_state *ec)
|
||||||
{
|
{
|
||||||
xpd_t *xpd;
|
xpd_t *xpd;
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
int pos = chan->chanpos - 1;
|
int pos = chan->chanpos - 1;
|
||||||
const struct echoops *echoops;
|
const struct echoops *echoops;
|
||||||
|
|
||||||
xpd = chan->pvt;
|
xpd = chan->pvt;
|
||||||
xbus = xpd->xbus;
|
xbus = xpd->xbus;
|
||||||
@ -875,9 +912,9 @@ static const struct dahdi_echocan_ops xpp_ec_ops = {
|
|||||||
|
|
||||||
const char *xpp_echocan_name(const struct dahdi_chan *chan)
|
const char *xpp_echocan_name(const struct dahdi_chan *chan)
|
||||||
{
|
{
|
||||||
xpd_t *xpd;
|
xpd_t *xpd;
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
int pos;
|
int pos;
|
||||||
|
|
||||||
if (!chan) {
|
if (!chan) {
|
||||||
NOTICE("%s(NULL)\n", __func__);
|
NOTICE("%s(NULL)\n", __func__);
|
||||||
@ -893,37 +930,34 @@ 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");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
xpd_t *xpd;
|
xpd_t *xpd;
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
int pos;
|
int pos;
|
||||||
struct phonedev *phonedev;
|
struct phonedev *phonedev;
|
||||||
const struct echoops *echoops;
|
const struct echoops *echoops;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
xpd = chan->pvt;
|
xpd = chan->pvt;
|
||||||
xbus = xpd->xbus;
|
xbus = xpd->xbus;
|
||||||
@ -937,17 +971,18 @@ int xpp_echocan_create(struct dahdi_chan *chan,
|
|||||||
(*ec)->features = xpp_ec_features;
|
(*ec)->features = xpp_ec_features;
|
||||||
xpd = get_xpd(__func__, xpd); /* Returned in echocan_free() */
|
xpd = get_xpd(__func__, xpd); /* Returned in echocan_free() */
|
||||||
LINE_DBG(GENERAL, xpd, pos, "(tap=%d, param_count=%d)\n",
|
LINE_DBG(GENERAL, xpd, pos, "(tap=%d, param_count=%d)\n",
|
||||||
ecp->tap_length, ecp->param_count);
|
ecp->tap_length, ecp->param_count);
|
||||||
ret = CALL_EC_METHOD(ec_set, xbus, xpd, pos, 1);
|
ret = CALL_EC_METHOD(ec_set, xbus, xpd, pos, 1);
|
||||||
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)
|
||||||
{
|
{
|
||||||
struct phonedev *phonedev = container_of(span, struct phonedev, span);
|
struct phonedev *phonedev = container_of(span, struct phonedev, span);
|
||||||
xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
|
xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
|
||||||
|
|
||||||
XPD_INFO(xpd, "Span assigned: %d\n", span->spanno);
|
XPD_INFO(xpd, "Span assigned: %d\n", span->spanno);
|
||||||
if (xpd->card_present) {
|
if (xpd->card_present) {
|
||||||
@ -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.
|
||||||
@ -992,14 +1029,15 @@ void xpd_set_spanname(xpd_t *xpd)
|
|||||||
* this horseshit.
|
* this horseshit.
|
||||||
*/
|
*/
|
||||||
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)
|
||||||
{
|
{
|
||||||
struct dahdi_span *span;
|
struct dahdi_span *span;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
memset(&PHONEDEV(xpd).span, 0, sizeof(struct dahdi_span));
|
memset(&PHONEDEV(xpd).span, 0, sizeof(struct dahdi_span));
|
||||||
for (i = 0; i < cn; i++)
|
for (i = 0; i < cn; i++)
|
||||||
@ -1022,9 +1060,9 @@ static void xpd_init_span(xpd_t *xpd, unsigned offset, int cn)
|
|||||||
|
|
||||||
int xpd_dahdi_preregister(xpd_t *xpd, unsigned offset)
|
int xpd_dahdi_preregister(xpd_t *xpd, unsigned offset)
|
||||||
{
|
{
|
||||||
xbus_t *xbus;
|
xbus_t *xbus;
|
||||||
int cn;
|
int cn;
|
||||||
struct phonedev *phonedev;
|
struct phonedev *phonedev;
|
||||||
|
|
||||||
BUG_ON(!xpd);
|
BUG_ON(!xpd);
|
||||||
|
|
||||||
@ -1052,7 +1090,7 @@ int xpd_dahdi_preregister(xpd_t *xpd, unsigned offset)
|
|||||||
|
|
||||||
int xpd_dahdi_postregister(xpd_t *xpd)
|
int xpd_dahdi_postregister(xpd_t *xpd)
|
||||||
{
|
{
|
||||||
int cn;
|
int cn;
|
||||||
|
|
||||||
atomic_inc(&num_registered_spans);
|
atomic_inc(&num_registered_spans);
|
||||||
atomic_inc(&PHONEDEV(xpd).dahdi_registered);
|
atomic_inc(&PHONEDEV(xpd).dahdi_registered);
|
||||||
@ -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,
|
||||||
for (j=0; j<PHONEDEV(xpd).span.channels; j++) {
|
"Queuing DAHDI_EVENT_REMOVED on all channels to ask user to release them\n");
|
||||||
dahdi_qevent_lock(XPD_CHAN(xpd, j), DAHDI_EVENT_REMOVED);
|
for (j = 0; j < PHONEDEV(xpd).span.channels; j++) {
|
||||||
|
dahdi_qevent_lock(XPD_CHAN(xpd, j),
|
||||||
|
DAHDI_EVENT_REMOVED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1125,11 +1165,11 @@ static void do_cleanup(void)
|
|||||||
|
|
||||||
static int __init xpp_dahdi_init(void)
|
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,17 +30,19 @@ 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);
|
||||||
int xpp_open(struct dahdi_chan *chan);
|
int xpp_open(struct dahdi_chan *chan);
|
||||||
int xpp_close(struct dahdi_chan *chan);
|
int xpp_close(struct dahdi_chan *chan);
|
||||||
@ -58,9 +60,9 @@ void notify_rxsig(xpd_t *xpd, int pos, enum dahdi_rxsig rxsig);
|
|||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
#include <linux/proc_fs.h>
|
#include <linux/proc_fs.h>
|
||||||
|
|
||||||
extern struct proc_dir_entry *xpp_proc_toplevel;
|
extern struct proc_dir_entry *xpp_proc_toplevel;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SPAN_REGISTERED(xpd) atomic_read(&PHONEDEV(xpd).dahdi_registered)
|
#define SPAN_REGISTERED(xpd) atomic_read(&PHONEDEV(xpd).dahdi_registered)
|
||||||
|
|
||||||
#endif /* XPP_DAHDI_H */
|
#endif /* XPP_DAHDI_H */
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
static const char rcsid[] = "$Id$";
|
static const char rcsid[] = "$Id$";
|
||||||
|
|
||||||
extern int debug;
|
extern int debug;
|
||||||
|
|
||||||
static const xproto_table_t *xprotocol_tables[XPD_TYPE_NOMODULE];
|
static const xproto_table_t *xprotocol_tables[XPD_TYPE_NOMODULE];
|
||||||
|
|
||||||
@ -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;
|
||||||
|
|
||||||
@ -82,11 +84,12 @@ const xproto_table_t *xproto_get(xpd_type_t cardtype)
|
|||||||
if (cardtype >= XPD_TYPE_NOMODULE)
|
if (cardtype >= XPD_TYPE_NOMODULE)
|
||||||
return NULL;
|
return NULL;
|
||||||
xtable = xprotocol_tables[cardtype];
|
xtable = xprotocol_tables[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
|
||||||
__func__, cardtype, ret);
|
("%s: Failed to load module for type=%d. exit status=%d.\n",
|
||||||
|
__func__, cardtype, ret);
|
||||||
/* Drop through: we may be lucky... */
|
/* Drop through: we may be lucky... */
|
||||||
}
|
}
|
||||||
xtable = xprotocol_tables[cardtype];
|
xtable = xprotocol_tables[cardtype];
|
||||||
@ -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,33 +129,37 @@ 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)
|
||||||
{
|
{
|
||||||
__u8 op;
|
__u8 op;
|
||||||
const xproto_entry_t *xe;
|
const xproto_entry_t *xe;
|
||||||
xproto_handler_t handler;
|
xproto_handler_t handler;
|
||||||
xproto_table_t *table;
|
xproto_table_t *table;
|
||||||
xpd_t *xpd;
|
xpd_t *xpd;
|
||||||
int ret = -EPROTO;
|
int ret = -EPROTO;
|
||||||
|
|
||||||
BUG_ON(!pack);
|
BUG_ON(!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;
|
||||||
}
|
}
|
||||||
@ -189,12 +203,13 @@ static int packet_process(xbus_t *xbus, xpacket_t *pack)
|
|||||||
if (!table->packet_is_valid(pack)) {
|
if (!table->packet_is_valid(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;
|
||||||
}
|
}
|
||||||
ret = 0; /* All well */
|
ret = 0; /* All well */
|
||||||
handler = xe->handler;
|
handler = xe->handler;
|
||||||
BUG_ON(!handler);
|
BUG_ON(!handler);
|
||||||
XBUS_COUNTER(xbus, RX_BYTES) += XPACKET_LEN(pack);
|
XBUS_COUNTER(xbus, RX_BYTES) += XPACKET_LEN(pack);
|
||||||
@ -205,11 +220,11 @@ out:
|
|||||||
|
|
||||||
static int xframe_receive_cmd(xbus_t *xbus, xframe_t *xframe)
|
static int xframe_receive_cmd(xbus_t *xbus, xframe_t *xframe)
|
||||||
{
|
{
|
||||||
__u8 *xframe_end;
|
__u8 *xframe_end;
|
||||||
xpacket_t *pack;
|
xpacket_t *pack;
|
||||||
__u8 *p;
|
__u8 *p;
|
||||||
int len;
|
int len;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (debug & DBG_COMMANDS)
|
if (debug & DBG_COMMANDS)
|
||||||
dump_xframe("RX-CMD", xbus, xframe, DBG_ANY);
|
dump_xframe("RX-CMD", xbus, xframe, DBG_ANY);
|
||||||
@ -220,21 +235,24 @@ static int xframe_receive_cmd(xbus_t *xbus, xframe_t *xframe)
|
|||||||
len = XPACKET_LEN(pack);
|
len = XPACKET_LEN(pack);
|
||||||
/* Sanity checks */
|
/* Sanity checks */
|
||||||
if (unlikely(XPACKET_OP(pack) == XPROTO_NAME(GLOBAL, PCM_READ))) {
|
if (unlikely(XPACKET_OP(pack) == XPROTO_NAME(GLOBAL, PCM_READ))) {
|
||||||
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;
|
||||||
}
|
}
|
||||||
p += len;
|
p += len;
|
||||||
if (p > xframe_end || len < RPACKET_HEADERSIZE) {
|
if (p > xframe_end || len < RPACKET_HEADERSIZE) {
|
||||||
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;
|
||||||
@ -251,13 +269,13 @@ out:
|
|||||||
|
|
||||||
int xframe_receive(xbus_t *xbus, xframe_t *xframe)
|
int xframe_receive(xbus_t *xbus, xframe_t *xframe)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
struct timeval tv_received;
|
struct timeval tv_received;
|
||||||
int usec;
|
int usec;
|
||||||
|
|
||||||
if (XFRAME_LEN(xframe) < RPACKET_HEADERSIZE) {
|
if (XFRAME_LEN(xframe) < RPACKET_HEADERSIZE) {
|
||||||
static int rate_limit;
|
static int rate_limit;
|
||||||
|
|
||||||
if ((rate_limit++ % 1003) == 0) {
|
if ((rate_limit++ % 1003) == 0) {
|
||||||
XBUS_NOTICE(xbus, "short xframe\n");
|
XBUS_NOTICE(xbus, "short xframe\n");
|
||||||
@ -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;
|
||||||
@ -297,23 +316,19 @@ int xframe_receive(xbus_t *xbus, xframe_t *xframe)
|
|||||||
|
|
||||||
void dump_packet(const char *msg, const xpacket_t *packet, bool debug)
|
void dump_packet(const char *msg, const xpacket_t *packet, bool debug)
|
||||||
{
|
{
|
||||||
__u8 op = XPACKET_OP(packet);
|
__u8 op = XPACKET_OP(packet);
|
||||||
__u8 *addr = (__u8 *)&XPACKET_ADDR(packet);
|
__u8 *addr = (__u8 *)&XPACKET_ADDR(packet);
|
||||||
|
|
||||||
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_LEN(packet));
|
||||||
(XPACKET_ADDR_SYNC(packet))?'+':' ',
|
|
||||||
*addr,
|
|
||||||
op,
|
|
||||||
XPACKET_LEN(packet));
|
|
||||||
#if VERBOSE_DEBUG
|
#if VERBOSE_DEBUG
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
__u8 *p = (__u8 *)packet;
|
__u8 *p = (__u8 *)packet;
|
||||||
|
|
||||||
printk(" BYTES: ");
|
printk(" BYTES: ");
|
||||||
for (i = 0; i < XPACKET_LEN(packet); i++) {
|
for (i = 0; i < XPACKET_LEN(packet); i++) {
|
||||||
@ -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,74 +351,74 @@ 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;
|
||||||
char port_buf[MAX_PROC_WRITE];
|
char port_buf[MAX_PROC_WRITE];
|
||||||
char reg_buf[MAX_PROC_WRITE];
|
char reg_buf[MAX_PROC_WRITE];
|
||||||
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) {
|
||||||
char buf[MAX_PROC_WRITE + 1];
|
char buf[MAX_PROC_WRITE + 1];
|
||||||
int i;
|
int i;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
size_t len = regcmd->bytes;
|
size_t len = regcmd->bytes;
|
||||||
const __u8 *p = REG_XDATA(regcmd);
|
const __u8 *p = REG_XDATA(regcmd);
|
||||||
|
|
||||||
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,
|
||||||
__func__, msg, regcmd->bytes);
|
"%s: %s: Wrong size: regcmd->bytes = %d\n",
|
||||||
|
__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",
|
||||||
REG_FIELD(regcmd, regnum));
|
REG_FIELD(regcmd, regnum));
|
||||||
}
|
}
|
||||||
if (REG_FIELD(regcmd, read_request)) {
|
if (REG_FIELD(regcmd, read_request)) {
|
||||||
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)
|
||||||
{
|
{
|
||||||
const xproto_table_t *proto_table;
|
const xproto_table_t *proto_table;
|
||||||
|
|
||||||
BUG_ON(xpd_type >= XPD_TYPE_NOMODULE);
|
BUG_ON(xpd_type >= XPD_TYPE_NOMODULE);
|
||||||
proto_table = xprotocol_tables[xpd_type];
|
proto_table = xprotocol_tables[xpd_type];
|
||||||
@ -428,10 +441,10 @@ const char *xproto_name(xpd_type_t xpd_type)
|
|||||||
|
|
||||||
int xproto_register(const xproto_table_t *proto_table)
|
int xproto_register(const xproto_table_t *proto_table)
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
const char *name;
|
const char *name;
|
||||||
const struct xops *xops;
|
const struct xops *xops;
|
||||||
const struct phoneops *phoneops;
|
const struct phoneops *phoneops;
|
||||||
|
|
||||||
BUG_ON(!proto_table);
|
BUG_ON(!proto_table);
|
||||||
type = proto_table->type;
|
type = proto_table->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);
|
||||||
@ -460,7 +474,7 @@ int xproto_register(const xproto_table_t *proto_table)
|
|||||||
CHECK_PHONEOP(phoneops, card_dahdi_preregistration);
|
CHECK_PHONEOP(phoneops, card_dahdi_preregistration);
|
||||||
CHECK_PHONEOP(phoneops, card_dahdi_postregistration);
|
CHECK_PHONEOP(phoneops, card_dahdi_postregistration);
|
||||||
/* optional method -- call after testing: */
|
/* optional method -- call after testing: */
|
||||||
/*CHECK_PHONEOP(phoneops, card_ioctl);*/
|
/*CHECK_PHONEOP(phoneops, card_ioctl); */
|
||||||
}
|
}
|
||||||
|
|
||||||
xprotocol_tables[type] = proto_table;
|
xprotocol_tables[type] = proto_table;
|
||||||
@ -469,8 +483,8 @@ 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)
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
BUG_ON(!proto_table);
|
BUG_ON(!proto_table);
|
||||||
type = proto_table->type;
|
type = proto_table->type;
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,10 +35,10 @@
|
|||||||
#define XPP_PROTOCOL_VERSION 30
|
#define XPP_PROTOCOL_VERSION 30
|
||||||
|
|
||||||
struct xpd_addr {
|
struct xpd_addr {
|
||||||
uint8_t subunit:SUBUNIT_BITS;
|
uint8_t subunit:SUBUNIT_BITS;
|
||||||
uint8_t reserved:1;
|
uint8_t reserved:1;
|
||||||
uint8_t unit:UNIT_BITS;
|
uint8_t unit:UNIT_BITS;
|
||||||
uint8_t sync_master:1;
|
uint8_t sync_master:1;
|
||||||
} PACKED;
|
} PACKED;
|
||||||
|
|
||||||
#define MKADDR(p, u, s) do { \
|
#define MKADDR(p, u, s) do { \
|
||||||
@ -48,12 +48,12 @@ struct xpd_addr {
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
struct xpacket_header {
|
struct xpacket_header {
|
||||||
uint16_t packet_len:10;
|
uint16_t packet_len:10;
|
||||||
uint16_t reserved:1;
|
uint16_t reserved:1;
|
||||||
uint16_t is_pcm:1;
|
uint16_t is_pcm:1;
|
||||||
uint16_t pcmslot:4;
|
uint16_t pcmslot:4;
|
||||||
uint8_t opcode;
|
uint8_t opcode;
|
||||||
struct xpd_addr addr;
|
struct xpd_addr addr;
|
||||||
} PACKED;
|
} PACKED;
|
||||||
|
|
||||||
#define XPACKET_OP(p) ((p)->head.opcode)
|
#define XPACKET_OP(p) ((p)->head.opcode)
|
||||||
@ -81,7 +81,7 @@ struct xpacket_header {
|
|||||||
#define XPD_TYPE_ECHO 5 // Octasic echo canceller
|
#define XPD_TYPE_ECHO 5 // Octasic echo canceller
|
||||||
#define XPD_TYPE_NOMODULE 7
|
#define XPD_TYPE_NOMODULE 7
|
||||||
|
|
||||||
typedef byte xpd_type_t;
|
typedef byte xpd_type_t;
|
||||||
|
|
||||||
#define XPD_TYPE_PREFIX "xpd-type-"
|
#define XPD_TYPE_PREFIX "xpd-type-"
|
||||||
|
|
||||||
@ -167,25 +167,25 @@ bool valid_xpd_addr(const struct xpd_addr *addr);
|
|||||||
#define MULTIBYTE_MAX_LEN 5 /* FPGA firmware limitation */
|
#define MULTIBYTE_MAX_LEN 5 /* FPGA firmware limitation */
|
||||||
|
|
||||||
typedef struct reg_cmd {
|
typedef struct reg_cmd {
|
||||||
byte bytes:3; /* Length (for Multibyte) */
|
byte bytes:3; /* Length (for Multibyte) */
|
||||||
__u8 eoframe:1; /* For BRI -- end of frame */
|
__u8 eoframe:1; /* For BRI -- end of frame */
|
||||||
__u8 portnum:3; /* For port specific registers */
|
__u8 portnum:3; /* For port specific registers */
|
||||||
__u8 is_multibyte:1;
|
__u8 is_multibyte:1;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
__u8 reserved:4;
|
__u8 reserved:4;
|
||||||
__u8 do_datah:1;
|
__u8 do_datah:1;
|
||||||
__u8 do_subreg:1;
|
__u8 do_subreg:1;
|
||||||
__u8 read_request:1;
|
__u8 read_request:1;
|
||||||
__u8 all_ports_broadcast:1;
|
__u8 all_ports_broadcast:1;
|
||||||
__u8 regnum;
|
__u8 regnum;
|
||||||
__u8 subreg;
|
__u8 subreg;
|
||||||
__u8 data_low;
|
__u8 data_low;
|
||||||
__u8 data_high;
|
__u8 data_high;
|
||||||
} PACKED r;
|
} PACKED r;
|
||||||
/* For Write-Multibyte commands in BRI */
|
/* For Write-Multibyte commands in BRI */
|
||||||
struct {
|
struct {
|
||||||
__u8 xdata[MULTIBYTE_MAX_LEN];
|
__u8 xdata[MULTIBYTE_MAX_LEN];
|
||||||
} PACKED d;
|
} PACKED d;
|
||||||
} PACKED alt;
|
} PACKED alt;
|
||||||
} PACKED reg_cmd_t;
|
} PACKED reg_cmd_t;
|
||||||
@ -197,18 +197,16 @@ typedef struct reg_cmd {
|
|||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
/*--------------------------- protocol tables ----------------------------------*/
|
/*--------------------------- protocol tables ----------------------------------*/
|
||||||
|
|
||||||
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);
|
||||||
@ -231,49 +229,50 @@ xproto_handler_t xproto_global_handler(__u8 opcode);
|
|||||||
(PHONE_METHOD(name, (xpd))((xpd), ## __VA_ARGS__ ))
|
(PHONE_METHOD(name, (xpd))((xpd), ## __VA_ARGS__ ))
|
||||||
|
|
||||||
struct phoneops {
|
struct phoneops {
|
||||||
void (*card_pcm_recompute)(xpd_t *xpd, xpp_line_t pcm_mask);
|
void (*card_pcm_recompute) (xpd_t *xpd, xpp_line_t pcm_mask);
|
||||||
void (*card_pcm_fromspan)(xpd_t *xpd, xpacket_t *pack);
|
void (*card_pcm_fromspan) (xpd_t *xpd, xpacket_t *pack);
|
||||||
void (*card_pcm_tospan)(xpd_t *xpd, xpacket_t *pack);
|
void (*card_pcm_tospan) (xpd_t *xpd, xpacket_t *pack);
|
||||||
int (*echocancel_timeslot)(xpd_t *xpd, int pos);
|
int (*echocancel_timeslot) (xpd_t *xpd, int pos);
|
||||||
int (*echocancel_setmask)(xpd_t *xpd, xpp_line_t ec_mask);
|
int (*echocancel_setmask) (xpd_t *xpd, xpp_line_t ec_mask);
|
||||||
int (*card_timing_priority)(xpd_t *xpd);
|
int (*card_timing_priority) (xpd_t *xpd);
|
||||||
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,
|
||||||
int (*card_open)(xpd_t *xpd, lineno_t pos);
|
unsigned long arg);
|
||||||
int (*card_close)(xpd_t *xpd, lineno_t pos);
|
int (*card_open) (xpd_t *xpd, lineno_t pos);
|
||||||
int (*card_state)(xpd_t *xpd, bool on);
|
int (*card_close) (xpd_t *xpd, lineno_t pos);
|
||||||
|
int (*card_state) (xpd_t *xpd, bool on);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct xops {
|
struct xops {
|
||||||
xpd_t *(*card_new)(xbus_t *xbus, int unit, int subunit,
|
xpd_t *(*card_new) (xbus_t *xbus, int unit, int subunit,
|
||||||
const xproto_table_t *proto_table, __u8 subtype,
|
const xproto_table_t *proto_table, __u8 subtype,
|
||||||
int subunits, int subunit_ports, bool to_phone);
|
int subunits, int subunit_ports, bool to_phone);
|
||||||
int (*card_init)(xbus_t *xbus, xpd_t *xpd);
|
int (*card_init) (xbus_t *xbus, xpd_t *xpd);
|
||||||
int (*card_remove)(xbus_t *xbus, xpd_t *xpd);
|
int (*card_remove) (xbus_t *xbus, xpd_t *xpd);
|
||||||
int (*card_tick)(xbus_t *xbus, xpd_t *xpd);
|
int (*card_tick) (xbus_t *xbus, xpd_t *xpd);
|
||||||
int (*card_register_reply)(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *reg);
|
int (*card_register_reply) (xbus_t *xbus, xpd_t *xpd, reg_cmd_t *reg);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct xproto_entry {
|
struct xproto_entry {
|
||||||
xproto_handler_t handler;
|
xproto_handler_t handler;
|
||||||
int datalen;
|
int datalen;
|
||||||
const char *name;
|
const char *name;
|
||||||
xproto_table_t *table;
|
xproto_table_t *table;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct xproto_table {
|
struct xproto_table {
|
||||||
struct module *owner;
|
struct module *owner;
|
||||||
xproto_entry_t entries[256]; /* Indexed by opcode */
|
xproto_entry_t entries[256]; /* Indexed by opcode */
|
||||||
const struct xops *xops; /* Card level operations */
|
const struct xops *xops; /* Card level operations */
|
||||||
const struct phoneops *phoneops; /* DAHDI operations */
|
const struct phoneops *phoneops; /* DAHDI operations */
|
||||||
const struct echoops *echoops; /* Echo Canceller operations */
|
const struct echoops *echoops; /* Echo Canceller operations */
|
||||||
xpd_type_t type;
|
xpd_type_t type;
|
||||||
__u8 ports_per_subunit;
|
__u8 ports_per_subunit;
|
||||||
const char *name;
|
const char *name;
|
||||||
bool (*packet_is_valid)(xpacket_t *pack);
|
bool (*packet_is_valid) (xpacket_t *pack);
|
||||||
void (*packet_dump)(const char *msg, xpacket_t *pack);
|
void (*packet_dump) (const char *msg, xpacket_t *pack);
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "card_global.h"
|
#include "card_global.h"
|
||||||
@ -282,11 +281,10 @@ 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 {
|
||||||
struct xpacket_header head;
|
struct xpacket_header head;
|
||||||
union {
|
union {
|
||||||
MEMBER(GLOBAL, NULL_REPLY);
|
MEMBER(GLOBAL, NULL_REPLY);
|
||||||
MEMBER(GLOBAL, PCM_WRITE);
|
MEMBER(GLOBAL, PCM_WRITE);
|
||||||
@ -297,20 +295,22 @@ struct xpacket {
|
|||||||
MEMBER(FXS, SIG_CHANGED);
|
MEMBER(FXS, SIG_CHANGED);
|
||||||
MEMBER(FXO, SIG_CHANGED);
|
MEMBER(FXO, SIG_CHANGED);
|
||||||
|
|
||||||
__u8 data[0];
|
__u8 data[0];
|
||||||
};
|
};
|
||||||
/* Last byte is chksum */
|
/* Last byte is chksum */
|
||||||
} 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);
|
||||||
const char *xproto_name(xpd_type_t xpd_type);
|
const char *xproto_name(xpd_type_t xpd_type);
|
||||||
|
|
||||||
#endif /* __KERNEL__ */
|
#endif /* __KERNEL__ */
|
||||||
|
|
||||||
#endif /* XPROTO_H */
|
#endif /* XPROTO_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user