xpp: a separate unit_descriptor

The new FXS chip supports two ports for each chip and hence we once
again need to look at hardware differently.

Struct unit_description includes information about all chips/port in a
specific module.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
This commit is contained in:
Oron Peled 2015-11-16 15:42:21 -05:00 committed by Tzafrir Cohen
parent 17ac18d675
commit d3a28c50cf
11 changed files with 148 additions and 94 deletions

View File

@ -686,20 +686,21 @@ static int bri_proc_create(xbus_t *xbus, xpd_t *xpd)
}
static xpd_t *BRI_card_new(xbus_t *xbus, int unit, int subunit,
const xproto_table_t *proto_table, __u8 subtype,
int subunits, int subunit_ports, bool to_phone)
const xproto_table_t *proto_table,
const struct unit_descriptor *unit_descriptor,
bool to_phone)
{
xpd_t *xpd = NULL;
int channels = min(3, CHANNELS_PERXPD);
if (subunit_ports != 1) {
XBUS_ERR(xbus, "Bad subunit_ports=%d\n", subunit_ports);
if (unit_descriptor->ports_per_chip != 1) {
XBUS_ERR(xbus, "Bad subunit_ports=%d\n", unit_descriptor->ports_per_chip);
return NULL;
}
XBUS_DBG(GENERAL, xbus, "\n");
xpd =
xpd_alloc(xbus, unit, subunit, subtype, subunits,
sizeof(struct BRI_priv_data), proto_table, channels);
xpd_alloc(xbus, unit, subunit,
sizeof(struct BRI_priv_data), proto_table, unit_descriptor, channels);
if (!xpd)
return NULL;
PHONEDEV(xpd).direction = (to_phone) ? TO_PHONE : TO_PSTN;

View File

@ -54,20 +54,21 @@ static xproto_table_t PROTO_TABLE(ECHO);
/*---------------- ECHO: Methods -------------------------------------------*/
static xpd_t *ECHO_card_new(xbus_t *xbus, int unit, int subunit,
const xproto_table_t *proto_table, __u8 subtype,
int subunits, int subunit_ports, bool to_phone)
const xproto_table_t *proto_table,
const struct unit_descriptor *unit_descriptor,
bool to_phone)
{
xpd_t *xpd = NULL;
int channels = 0;
if (subunit_ports != 1) {
XBUS_ERR(xbus, "Bad subunit_ports=%d\n", subunit_ports);
if (unit_descriptor->ports_per_chip != 1) {
XBUS_ERR(xbus, "Bad subunit_ports=%d\n", unit_descriptor->ports_per_chip);
return NULL;
}
XBUS_DBG(GENERAL, xbus, "\n");
xpd =
xpd_alloc(xbus, unit, subunit, subtype, subunits,
sizeof(struct ECHO_priv_data), proto_table, channels);
xpd_alloc(xbus, unit, subunit,
sizeof(struct ECHO_priv_data), proto_table, unit_descriptor, channels);
if (!xpd)
return NULL;
xpd->type_name = "ECHO";

View File

@ -487,11 +487,13 @@ static int fxo_proc_create(xbus_t *xbus, xpd_t *xpd)
}
static xpd_t *FXO_card_new(xbus_t *xbus, int unit, int subunit,
const xproto_table_t *proto_table, __u8 subtype,
int subunits, int subunit_ports, bool to_phone)
const xproto_table_t *proto_table,
const struct unit_descriptor *unit_descriptor,
bool to_phone)
{
xpd_t *xpd = NULL;
int channels;
int subunit_ports;
if (to_phone) {
XBUS_NOTICE(xbus,
@ -500,13 +502,14 @@ static xpd_t *FXO_card_new(xbus_t *xbus, int unit, int subunit,
unit, subunit);
return NULL;
}
if (subtype == 2)
subunit_ports = unit_descriptor->numchips * unit_descriptor->ports_per_chip;
if (unit_descriptor->subtype == 2)
channels = min(2, subunit_ports);
else
channels = min(8, subunit_ports);
xpd =
xpd_alloc(xbus, unit, subunit, subtype, subunits,
sizeof(struct FXO_priv_data), proto_table, channels);
xpd_alloc(xbus, unit, subunit,
sizeof(struct FXO_priv_data), proto_table, unit_descriptor, channels);
if (!xpd)
return NULL;
PHONEDEV(xpd).direction = TO_PSTN;

View File

@ -445,11 +445,13 @@ static int fxs_proc_create(xbus_t *xbus, xpd_t *xpd)
}
static xpd_t *FXS_card_new(xbus_t *xbus, int unit, int subunit,
const xproto_table_t *proto_table, __u8 subtype,
int subunits, int subunit_ports, bool to_phone)
const xproto_table_t *proto_table,
const struct unit_descriptor *unit_descriptor,
bool to_phone)
{
xpd_t *xpd = NULL;
int channels;
int subunit_ports;
int regular_channels;
struct FXS_priv_data *priv;
int i;
@ -462,20 +464,21 @@ static xpd_t *FXS_card_new(xbus_t *xbus, int unit, int subunit,
unit, subunit);
return NULL;
}
if (subtype == 2)
subunit_ports = unit_descriptor->numchips * unit_descriptor->ports_per_chip;
if (unit_descriptor->subtype == 2)
regular_channels = min(6, subunit_ports);
else
regular_channels = min(8, subunit_ports);
channels = regular_channels;
/* Calculate digital inputs/outputs */
if (unit == 0 && subtype != 4) {
if (unit == 0 && unit_descriptor->subtype != 4) {
channels += 6; /* 2 DIGITAL OUTPUTS, 4 DIGITAL INPUTS */
d_inputs = LINES_DIGI_INP;
d_outputs = LINES_DIGI_OUT;
}
xpd =
xpd_alloc(xbus, unit, subunit, subtype, subunits,
sizeof(struct FXS_priv_data), proto_table, channels);
xpd_alloc(xbus, unit, subunit,
sizeof(struct FXS_priv_data), proto_table, unit_descriptor, channels);
if (!xpd)
return NULL;
/* Initialize digital inputs/outputs */
@ -795,7 +798,7 @@ static int relay_out(xpd_t *xpd, int pos, bool on)
BUG_ON(!xpd);
/* map logical position to output port number (0/1) */
which -= (xpd->subtype == 2) ? 6 : 8;
which -= (XPD_HW(xpd).subtype == 2) ? 6 : 8;
LINE_DBG(SIGNAL, xpd, pos, "which=%d -- %s\n", which,
(on) ? "on" : "off");
which = which % ARRAY_SIZE(relay_channels);

View File

@ -544,21 +544,14 @@ HANDLER_DEF(GLOBAL, AB_DESCRIPTION)
}
card_desc->magic = CARD_DESC_MAGIC;
INIT_LIST_HEAD(&card_desc->card_list);
card_desc->type = this_unit->type;
card_desc->subtype = this_unit->subtype;
card_desc->xpd_addr = this_unit->addr;
card_desc->numchips = this_unit->numchips;
card_desc->ports_per_chip = this_unit->ports_per_chip;
card_desc->port_dir = this_unit->port_dir;
card_desc->ports =
card_desc->numchips * card_desc->ports_per_chip;
card_desc->unit_descriptor = *this_unit;
XBUS_INFO(xbus,
" CARD %d type=%d.%d ports=%d (%dx%d), "
" CARD %d type=%d.%d ports=(%dx%d), "
"port-dir=0x%02X\n",
card_desc->xpd_addr.unit, card_desc->type,
card_desc->subtype, card_desc->ports,
card_desc->numchips, card_desc->ports_per_chip,
card_desc->port_dir);
this_unit->addr.unit, this_unit->type,
this_unit->subtype,
this_unit->numchips, this_unit->ports_per_chip,
this_unit->port_dir);
spin_lock_irqsave(&worker->worker_lock, flags);
worker->num_units++;
XBUS_COUNTER(xbus, UNITS)++;
@ -710,6 +703,7 @@ int run_initialize_registers(xpd_t *xpd)
char xbuslabel[MAX_ENV_STR];
char init_card[MAX_PATH_STR];
__u8 direction_mask;
__u8 hw_type = XPD_HW(xpd).type;
int i;
char *argv[] = {
init_card,
@ -756,6 +750,7 @@ int run_initialize_registers(xpd_t *xpd)
snprintf(busnumstr, MAX_ENV_STR, "XBUS_NUMBER=%d", xbus->num);
snprintf(modelstr, MAX_ENV_STR, "XBUS_MODEL_STRING=%s",
xbus->transport.model_string);
snprintf(typestr, MAX_ENV_STR, "HW_TYPE=%d", hw_type);
snprintf(unitstr, MAX_ENV_STR, "UNIT_NUMBER=%d", xpd->addr.unit);
snprintf(typestr, MAX_ENV_STR, "UNIT_TYPE=%d", xpd->xpd_type);
snprintf(subunitsstr, MAX_ENV_STR, "UNIT_SUBUNITS=%d", xpd->subunits);
@ -766,7 +761,7 @@ int run_initialize_registers(xpd_t *xpd)
xbus->connector);
snprintf(xbuslabel, MAX_ENV_STR, "XBUS_LABEL=%s", xbus->label);
if (snprintf
(init_card, MAX_PATH_STR, "%s/init_card_%d_%d", initdir, xpd->xpd_type,
(init_card, MAX_PATH_STR, "%s/init_card_%d_%d", initdir, hw_type,
xbus->revision) > MAX_PATH_STR) {
XPD_NOTICE(xpd,
"Cannot initialize. pathname is longer "

View File

@ -1253,21 +1253,22 @@ static int pri_chanconfig(struct file *file, struct dahdi_chan *chan,
}
static xpd_t *PRI_card_new(xbus_t *xbus, int unit, int subunit,
const xproto_table_t *proto_table, __u8 subtype,
int subunits, int subunit_ports, bool to_phone)
const xproto_table_t *proto_table,
const struct unit_descriptor *unit_descriptor,
bool to_phone)
{
xpd_t *xpd = NULL;
struct PRI_priv_data *priv;
int channels = min(31, CHANNELS_PERXPD); /* worst case */
if (subunit_ports != 1) {
XBUS_ERR(xbus, "Bad subunit_ports=%d\n", subunit_ports);
if (unit_descriptor->ports_per_chip != 1) {
XBUS_ERR(xbus, "Bad subunit_ports=%d\n", unit_descriptor->ports_per_chip);
return NULL;
}
XBUS_DBG(GENERAL, xbus, "\n");
xpd =
xpd_alloc(xbus, unit, subunit, subtype, subunits,
sizeof(struct PRI_priv_data), proto_table, channels);
xpd_alloc(xbus, unit, subunit,
sizeof(struct PRI_priv_data), proto_table, unit_descriptor, channels);
if (!xpd)
return NULL;
priv = xpd->priv;

View File

@ -687,10 +687,47 @@ int xbus_xpd_unbind(xbus_t *xbus, xpd_t *xpd)
return 0;
}
static int new_card(xbus_t *xbus, int unit, __u8 type, __u8 subtype,
__u8 numchips, __u8 ports_per_chip, __u8 ports,
__u8 port_dir)
static xpd_type_t xpd_hw2xpd_type(const struct unit_descriptor *unit_descriptor)
{
xpd_type_t xpd_type;
switch (unit_descriptor->type) {
case 1:
case 6:
xpd_type = XPD_TYPE_FXS;
break;
case 2:
xpd_type = XPD_TYPE_FXO;
break;
case 3:
xpd_type = XPD_TYPE_BRI;
break;
case 4:
xpd_type = XPD_TYPE_PRI;
break;
case 5:
xpd_type = XPD_TYPE_ECHO;
break;
case 7:
xpd_type = XPD_TYPE_NOMODULE;
break;
default:
NOTICE("WARNING: xpd hw type is: %d\n", unit_descriptor->type);
xpd_type = XPD_TYPE_NOMODULE;
break;
}
return xpd_type;
}
static int new_card(xbus_t *xbus, const struct unit_descriptor *unit_descriptor)
{
int unit = unit_descriptor->addr.unit;
xpd_type_t xpd_type;
__u8 hw_type;
__u8 numchips;
__u8 ports_per_chip;
__u8 ports;
__u8 port_dir;
const xproto_table_t *proto_table;
int i;
int subunits;
@ -698,12 +735,19 @@ static int new_card(xbus_t *xbus, int unit, __u8 type, __u8 subtype,
int remaining_ports;
const struct echoops *echoops;
proto_table = xproto_get(type);
/* Translate parameters from "unit_descriptor" */
hw_type = unit_descriptor->type;
numchips = unit_descriptor->numchips;
ports_per_chip = unit_descriptor->ports_per_chip;
port_dir = unit_descriptor->port_dir;
ports = unit_descriptor->ports_per_chip * unit_descriptor->numchips;
xpd_type = xpd_hw2xpd_type(unit_descriptor);
proto_table = xproto_get(xpd_type);
if (!proto_table) {
XBUS_NOTICE(xbus,
"CARD %d: missing protocol table for type %d. "
"CARD %d: missing protocol table for xpd_type %d. "
"Ignored.\n",
unit, type);
unit, xpd_type);
return -EINVAL;
}
echoops = proto_table->echoops;
@ -711,9 +755,9 @@ static int new_card(xbus_t *xbus, int unit, __u8 type, __u8 subtype,
XBUS_INFO(xbus, "Detected ECHO Canceler (%d)\n", unit);
if (ECHOOPS(xbus)) {
XBUS_NOTICE(xbus,
"CARD %d: tryies to define echoops (type %d) "
"CARD %d: tryies to define echoops (xpd_type %d) "
"but we already have one. Ignored.\n",
unit, type);
unit, xpd_type);
return -EINVAL;
}
xbus->echo_state.echoops = echoops;
@ -724,13 +768,13 @@ static int new_card(xbus_t *xbus, int unit, __u8 type, __u8 subtype,
(ports + proto_table->ports_per_subunit -
1) / proto_table->ports_per_subunit;
XBUS_DBG(DEVICES, xbus,
"CARD %d type=%d.%d ports=%d (%dx%d), "
"CARD %d xpd_type=%d/hw_type=%d ports=%d (%dx%d), "
"%d subunits, port-dir=0x%02X\n",
unit, type, subtype, ports, numchips, ports_per_chip, subunits,
unit, xpd_type, hw_type, ports, numchips, ports_per_chip, subunits,
port_dir);
if (type == XPD_TYPE_PRI || type == XPD_TYPE_BRI)
if (xpd_type == XPD_TYPE_PRI || xpd_type == XPD_TYPE_BRI)
xbus->quirks.has_digital_span = 1;
if (type == XPD_TYPE_FXO)
if (xpd_type == XPD_TYPE_FXO)
xbus->quirks.has_fxo = 1;
xbus->worker.num_units += subunits - 1;
for (i = 0; i < subunits; i++) {
@ -754,11 +798,10 @@ static int new_card(xbus_t *xbus, int unit, __u8 type, __u8 subtype,
goto out;
}
XBUS_DBG(DEVICES, xbus,
"Creating XPD=%d%d type=%d.%d (%d ports)\n", unit, i,
type, subtype, subunit_ports);
"Creating XPD=%d%d xpd_type=%d.%d hw_type=%d (%d ports)\n", unit, i,
xpd_type, unit_descriptor->subtype, hw_type, subunit_ports);
ret =
create_xpd(xbus, proto_table, unit, i, type, subtype,
subunits, subunit_ports, port_dir);
create_xpd(xbus, proto_table, unit_descriptor, unit, i, xpd_type);
if (ret < 0) {
XBUS_ERR(xbus, "Creation of XPD=%d%d failed %d\n", unit,
i, ret);
@ -1130,11 +1173,7 @@ void xbus_populate(void *data)
BUG_ON(card_desc->magic != CARD_DESC_MAGIC);
/* Release/Reacquire locks around blocking calls */
spin_unlock_irqrestore(&xbus->worker.worker_lock, flags);
ret =
new_card(xbus, card_desc->xpd_addr.unit, card_desc->type,
card_desc->subtype, card_desc->numchips,
card_desc->ports_per_chip, card_desc->ports,
card_desc->port_dir);
ret = new_card(xbus, &card_desc->unit_descriptor);
spin_lock_irqsave(&xbus->worker.worker_lock, flags);
KZFREE(card_desc);
if (ret)

View File

@ -78,14 +78,7 @@
struct card_desc_struct {
struct list_head card_list;
u32 magic;
__u8 type; /* LSB: 1 - to_phone, 0 - to_line */
__u8 subtype;
struct xpd_addr xpd_addr;
__u8 numchips;
__u8 ports_per_chip;
__u8 ports;
__u8 port_dir;
struct xpd_addr ec_addr; /* echo canceler address */
struct unit_descriptor unit_descriptor;
};
typedef enum xpd_direction {
@ -174,11 +167,12 @@ struct phonedev {
struct xpd {
char xpdname[XPD_NAMELEN];
struct phonedev phonedev;
struct unit_descriptor unit_descriptor;
#define XPD_HW(xpd) ((xpd)->unit_descriptor)
const struct xops *xops;
xpd_type_t xpd_type;
const char *type_name;
__u8 subtype;
int subunits; /* all siblings */
enum xpd_state xpd_state;
struct device xpd_dev;

View File

@ -216,33 +216,43 @@ EXPORT_SYMBOL(xpd_free);
* Synchronous part of XPD detection.
* Called from new_card()
*/
int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table, int unit,
int subunit, __u8 type, __u8 subtype, int subunits,
int subunit_ports, __u8 port_dir)
int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table,
const struct unit_descriptor *unit_descriptor,
int unit,
int subunit, __u8 type)
{
xpd_t *xpd = NULL;
bool to_phone;
BUG_ON(type == XPD_TYPE_NOMODULE);
to_phone = BIT(subunit) & port_dir;
to_phone = BIT(subunit) & unit_descriptor->port_dir;
BUG_ON(!xbus);
xpd = xpd_byaddr(xbus, unit, subunit);
if (xpd) {
XPD_NOTICE(xpd, "XPD at %d%d already exists\n", unit, subunit);
return 0;
}
if (subunit_ports <= 0 || subunit_ports > CHANNELS_PERXPD) {
INFO("%s: [%d.%d] type=%d subtype=%d numchips=%d ports_per_chip=%d ports_dir=%d\n",
__func__,
unit_descriptor->addr.unit,
unit_descriptor->addr.subunit,
unit_descriptor->type,
unit_descriptor->subtype,
unit_descriptor->numchips,
unit_descriptor->ports_per_chip,
unit_descriptor->port_dir);
if (unit_descriptor->ports_per_chip <= 0 || unit_descriptor->ports_per_chip > CHANNELS_PERXPD) {
XBUS_NOTICE(xbus, "Illegal number of ports %d for XPD %d%d\n",
subunit_ports, unit, subunit);
unit_descriptor->ports_per_chip, unit, subunit);
return 0;
}
xpd =
proto_table->xops->card_new(xbus, unit, subunit, proto_table,
subtype, subunits, subunit_ports,
unit_descriptor,
to_phone);
if (!xpd) {
XBUS_NOTICE(xbus, "card_new(%d,%d,%d,%d,%d) failed. Ignored.\n",
unit, subunit, proto_table->type, subtype,
XBUS_NOTICE(xbus, "card_new(%d,%d,%d,%d) failed. Ignored.\n",
unit, subunit, proto_table->type,
to_phone);
return -EINVAL;
}
@ -279,7 +289,8 @@ static int xpd_read_proc_show(struct seq_file *sfile, void *data)
seq_printf(sfile, "Address: U=%d S=%d\n", xpd->addr.unit,
xpd->addr.subunit);
seq_printf(sfile, "Subunits: %d\n", xpd->subunits);
seq_printf(sfile, "Type: %d.%d\n\n", xpd->xpd_type, xpd->subtype);
seq_printf(sfile, "Type: %d.%d\n", xpd->xpd_type, XPD_HW(xpd).subtype);
seq_printf(sfile, "Hardware type: %d.%d\nn", XPD_HW(xpd).type, XPD_HW(xpd).subtype);
seq_printf(sfile, "pcm_len=%d\n\n", PHONEDEV(xpd).pcm_len);
seq_printf(sfile, "wanted_pcm_mask=0x%04X\n\n",
PHONEDEV(xpd).wanted_pcm_mask);
@ -529,8 +540,10 @@ err:
*
*/
__must_check 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)
size_t privsize,
const xproto_table_t *proto_table,
const struct unit_descriptor *unit_descriptor,
int channels)
{
xpd_t *xpd = NULL;
size_t alloc_size = sizeof(xpd_t) + privsize;
@ -556,10 +569,9 @@ __must_check xpd_t *xpd_alloc(xbus_t *xbus, int unit, int subunit,
xpd->card_present = 0;
xpd->xpd_type = proto_table->type;
xpd->xproto = proto_table;
xpd->unit_descriptor = *unit_descriptor;
xpd->xops = proto_table->xops;
xpd->xpd_state = XPD_STATE_START;
xpd->subtype = subtype;
xpd->subunits = subunits;
kref_init(&xpd->kref);
/* For USB-1 disable some channels */

View File

@ -30,11 +30,13 @@ int xpd_dahdi_preregister(xpd_t *xpd, unsigned offset);
int xpd_dahdi_postregister(xpd_t *xpd);
void xpd_dahdi_preunregister(xpd_t *xpd);
void xpd_dahdi_postunregister(xpd_t *xpd);
int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table, int unit,
int subunit, __u8 type, __u8 subtype, int subunits,
int subunit_ports, __u8 port_dir);
xpd_t *xpd_alloc(xbus_t *xbus, int unit, int subunit, int subtype, int subunits,
int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table,
const struct unit_descriptor *unit_descriptor,
int unit,
int subunit, __u8 type);
xpd_t *xpd_alloc(xbus_t *xbus, int unit, int subunit,
size_t privsize, const xproto_table_t *proto_table,
const struct unit_descriptor *unit_descriptor,
int channels);
void xpd_free(xpd_t *xpd);
void xpd_remove(xpd_t *xpd);

View File

@ -34,6 +34,8 @@
*/
#define XPP_PROTOCOL_VERSION 30
struct unit_descriptor;
struct xpd_addr {
uint8_t subunit:SUBUNIT_BITS;
uint8_t reserved:1;
@ -277,8 +279,9 @@ struct phoneops {
struct xops {
xpd_t *(*card_new) (xbus_t *xbus, int unit, int subunit,
const xproto_table_t *proto_table, __u8 subtype,
int subunits, int subunit_ports, bool to_phone);
const xproto_table_t *proto_table,
const struct unit_descriptor *unit_descriptor,
bool to_phone);
int (*card_init) (xbus_t *xbus, xpd_t *xpd);
int (*card_remove) (xbus_t *xbus, xpd_t *xpd);
int (*card_tick) (xbus_t *xbus, xpd_t *xpd);