summaryrefslogtreecommitdiff
path: root/xpp/card_global.c
diff options
context:
space:
mode:
Diffstat (limited to 'xpp/card_global.c')
-rw-r--r--xpp/card_global.c182
1 files changed, 86 insertions, 96 deletions
diff --git a/xpp/card_global.c b/xpp/card_global.c
index 22456bc..c2c7022 100644
--- a/xpp/card_global.c
+++ b/xpp/card_global.c
@@ -25,11 +25,12 @@
#include "xpp_zap.h"
#include "xproto.h"
#include "zap_debug.h"
+#include "xbus-core.h"
#include <linux/module.h>
static const char rcsid[] = "$Id$";
-DEF_PARM(charp,initdir, "/usr/share/zaptel", "The directory of card initialization scripts");
+DEF_PARM(charp,initdir, "/usr/share/zaptel", 0600, "The directory of card initialization scripts");
extern int print_dbg;
static bool pcm_valid(xpd_t *xpd, xpacket_t *pack);
@@ -44,64 +45,23 @@ static void global_packet_dump(const char *msg, xpacket_t *pack);
/* 0x04 */ HOSTCMD(GLOBAL, DESC_REQ, int xpd_num)
{
int ret = 0;
+ xframe_t *xframe;
xpacket_t *pack;
if(!xbus) {
DBG("NO XBUS\n");
return -EINVAL;
}
- XPACKET_NEW(pack, xbus, GLOBAL, DESC_REQ, xpd_num);
+ XFRAME_NEW(xframe, pack, xbus, GLOBAL, DESC_REQ, xpd_num);
DBG("on %s #%d\n", xbus->busname, xpd_num);
- ret = packet_send(xbus, pack);
+ ret = xframe_send(xbus, xframe);
XBUS_COUNTER(xbus, DESC_REQ)++;
return ret;
}
-/* 0x11 */ HOSTCMD(GLOBAL, PCM_WRITE, xpp_line_t lines, volatile byte *buf)
-{
- int ret = 0;
- xpacket_t *pack;
- byte *pcm;
- byte *start_pcm;
- int i;
-
- BUG_ON(!xbus);
- BUG_ON(!xpd);
- lines &= ~xpd->no_pcm;
- /*
- * FIXME: Workaround a bug in sync code of the Astribank.
- * Send dummy PCM for sync.
- */
- if(lines == 0)
- lines = BIT(0);
-
- XPACKET_NEW(pack, xbus, GLOBAL, PCM_WRITE, xpd->id);
- RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines) = lines;
- start_pcm = pcm = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, pcm);
- for_each_line(xpd, i) {
- if(IS_SET(lines, i)) {
- memcpy(pcm, (byte *)buf, ZT_CHUNKSIZE);
- pcm += ZT_CHUNKSIZE;
- }
- buf += ZT_CHUNKSIZE;
- }
- /*
- * BRI: Software workaround for firmware limitation.
- * The BRI firmware count PCM channel number globally across subunits.
- */
- if(xpd->type == XPD_TYPE_BRI_NT || xpd->type == XPD_TYPE_BRI_TE) {
- lines = lines << (xpd->addr.subunit * 4);
- RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines) = lines;
- }
- pack->datalen = sizeof(xpp_line_t) + (pcm - start_pcm);
- packet_send(xbus, pack);
- XPD_COUNTER(xpd, PCM_WRITE)++;
- XBUS_COUNTER(xbus, PCM_WRITE)++;
- return ret;
-}
-
/* 0x19 */ HOSTCMD(GLOBAL, SYNC_SOURCE, bool setit, bool is_master)
{
+ xframe_t *xframe;
xpacket_t *pack;
byte mask = 0;
@@ -113,9 +73,9 @@ static void global_packet_dump(const char *msg, xpacket_t *pack);
mask |= BIT(1);
DBG("SYNC_SOURCE %s setit=%s is_master=%s (mask=0x%X)\n",
xpd->xpdname, (setit)?"yes":"no", (is_master)?"yes":"no", mask);
- XPACKET_NEW(pack, xbus, GLOBAL, SYNC_SOURCE, xpd->id);
+ XFRAME_NEW(xframe, pack, xbus, GLOBAL, SYNC_SOURCE, xpd->id);
RPACKET_FIELD(pack, GLOBAL, SYNC_SOURCE, mask) = mask;
- packet_send(xbus, pack);
+ xframe_send(xbus, xframe);
return 0;
}
@@ -177,11 +137,13 @@ HANDLER_DEF(GLOBAL, PCM_READ)
unsigned long flags;
int i;
xpp_line_t old_lines = lines;
+ bool is_bri;
+ int subunit;
BUG_ON(!xbus);
if(!xpd) {
#if 0
- int xpd_num = XPD_NUM(pack->content.addr);
+ int xpd_num = XPD_NUM(pack->addr);
NOTICE("%s: received %s for non-existing xpd: %d\n",
__FUNCTION__, cmd->name, xpd_num);
#endif
@@ -189,44 +151,59 @@ HANDLER_DEF(GLOBAL, PCM_READ)
}
// DBG("lines=0x%04X\n", lines);
- /*
- * BRI: Software workaround for firmware limitation.
- * The BRI firmware count PCM channel number globally across subunits.
- */
- if(xpd->type == XPD_TYPE_BRI_NT || xpd->type == XPD_TYPE_BRI_TE) {
- lines = (lines >> (xpd->addr.subunit * 4)) & 0x7;
- RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines) = lines;
- }
if(!pcm_valid(xpd, pack)) {
static int rate_limit;
if((rate_limit++ % 5001) == 0)
ERR("%s/%s: old_lines=0x%04X lines=0x%04X subunit=%d\n",
- xpd->xbus->busname, xpd->xpdname, old_lines, lines, xpd->addr.subunit);
+ xbus->busname, xpd->xpdname, old_lines, lines, xpd->addr.subunit);
return -EPROTO;
}
- spin_lock_irqsave(&xpd->lock, flags);
- if (xpd->timer_count & 1) {
- /* First part */
- r = readchunk = xpd->readchunk;
- } else {
- r = readchunk = xpd->readchunk + ZT_CHUNKSIZE * CHANNELS_PERXPD;
- }
+ is_bri = (xpd->type == XPD_TYPE_BRI_NT || xpd->type == XPD_TYPE_BRI_TE);
+ do {
+ spin_lock_irqsave(&xpd->lock, flags);
+ if (xpd->timer_count & 1) {
+ /* First part */
+ r = readchunk = xpd->readchunk;
+ } else {
+ r = readchunk = xpd->readchunk + ZT_CHUNKSIZE * CHANNELS_PERXPD;
+ }
- /* Copy PCM and put each channel in its index */
- for_each_line(xpd, i) {
- if(IS_SET(lines, i)) {
- memcpy((u_char *)r, pcm, ZT_CHUNKSIZE);
- //memset((u_char *)r, 0x5A, ZT_CHUNKSIZE); // DEBUG
- pcm += ZT_CHUNKSIZE;
+ /* Copy PCM and put each channel in its index */
+ for_each_line(xpd, i) {
+ if(IS_SET(lines, i)) {
+ memcpy((u_char *)r, pcm, ZT_CHUNKSIZE);
+ //memset((u_char *)r, 0x5A, ZT_CHUNKSIZE); // DEBUG
+ pcm += ZT_CHUNKSIZE;
+ }
+ r += ZT_CHUNKSIZE;
}
- r += ZT_CHUNKSIZE;
- }
- XPD_COUNTER(xpd, PCM_READ)++;
- XBUS_COUNTER(xpd->xbus, PCM_READ)++;
- spin_unlock_irqrestore(&xpd->lock, flags);
- xpp_tick((unsigned long)xpd);
+ XPD_COUNTER(xpd, PCM_READ)++;
+ XBUS_COUNTER(xbus, PCM_READ)++;
+ spin_unlock_irqrestore(&xpd->lock, flags);
+ got_pcm_from(xpd);
+
+ if (!is_bri)
+ break;
+ /*
+ * Handle BRI subunits
+ */
+ lines >>= SUBUNIT_PCM_SHIFT; /* B1, B2, D, E */
+ if (lines == 0)
+ break;
+ for(subunit = xpd->addr.subunit + 1; subunit < MAX_SUBUNIT; subunit++) {
+ xpd_t *tmp_xpd;
+
+ tmp_xpd = xpd_by_addr(xbus, xpd->addr.unit, subunit);
+ if(!tmp_xpd || !tmp_xpd->card_present)
+ continue;
+ xpd = tmp_xpd;
+ break;
+ }
+ if(subunit == MAX_SUBUNIT && printk_ratelimit())
+ NOTICE("%s/%s: subunit=%d lines=0x%04X\n", xbus->busname, xpd->xpdname, subunit, lines);
+ } while (1);
return 0;
}
@@ -238,38 +215,43 @@ HANDLER_DEF(GLOBAL, SYNC_REPLY)
BUG_ON(!xbus);
if(!xpd) {
- int xpd_num = XPD_NUM(pack->content.addr);
- NOTICE("%s: received %s for non-existing xpd: %d\n", __FUNCTION__, cmd->name, xpd_num);
+ int xpd_num = XPD_NUM(pack->addr);
+ NOTICE("%s: received %s for non-existing xpd: addr=0x%02X\n", __FUNCTION__, cmd->name, xpd_num);
return -EPROTO;
}
DBG("%s/%s: SYNC_REPLY: 0x%X %s\n", xpd->xbus->busname, xpd->xpdname,
mask, (setit) ? "SET SYNC MASTER" : "");
- if(setit)
- sync_master_is(xpd);
return 0;
}
HANDLER_DEF(GLOBAL, ERROR_CODE)
{
- byte errorcode = RPACKET_FIELD(pack, GLOBAL, ERROR_CODE, errorcode);
- reg_cmd_t *bad_cmd;
- char xpdname[XPD_NAMELEN];
+ byte errorcode = RPACKET_FIELD(pack, GLOBAL, ERROR_CODE, errorcode);
+ reg_cmd_t *bad_cmd;
+ char tmp_xpdname[XPD_NAMELEN];
+ static long rate_limit;
BUG_ON(!xbus);
+ if((rate_limit++ % 5003) > 200)
+ return 0;
if(!xpd) {
- int xpd_num = XPD_NUM(pack->content.addr);
- snprintf(xpdname, XPD_NAMELEN, "....#%d", xpd_num);
+ int xpd_num = XPD_NUM(pack->addr);
+ snprintf(tmp_xpdname, XPD_NAMELEN, "#%d", xpd_num);
} else {
- snprintf(xpdname, XPD_NAMELEN, "%s", xpd->xpdname);
+ snprintf(tmp_xpdname, XPD_NAMELEN, "%s", xpd->xpdname);
}
- NOTICE("%s/%s: %s CODE = 0x%X\n", xbus->busname, xpdname, cmd->name, errorcode);
+ NOTICE("%s/%s: FIRMWARE: %s CODE = 0x%X (rate_limit=%ld)\n",
+ xbus->busname, tmp_xpdname, cmd->name, errorcode, rate_limit);
switch(errorcode) {
case 1:
bad_cmd = &RPACKET_FIELD(pack, GLOBAL, ERROR_CODE, info.bad_spi_cmd);
- dump_packet("BAD_SPI_CMD", pack, 1);
+ dump_packet("FIRMWARE: BAD_SPI_CMD", pack, 1);
+ break;
+ case 0xAB:
+ dump_packet("FIRMWARE: BAD_PACKET_LEN", pack, 1);
break;
default:
- NOTICE("%s/%s: %s UNKNOWN CODE = 0x%X\n", xbus->busname, xpdname, cmd->name, errorcode);
+ NOTICE("%s/%s: FIRMWARE: %s UNKNOWN CODE = 0x%X\n", xbus->busname, tmp_xpdname, cmd->name, errorcode);
dump_packet("PACKET", pack, 1);
}
/*
@@ -298,7 +280,7 @@ static bool global_packet_is_valid(xpacket_t *pack)
const xproto_entry_t *xe;
//DBG("\n");
- xe = xproto_global_entry(pack->content.opcode);
+ xe = xproto_global_entry(pack->opcode);
return xe != NULL;
}
@@ -312,19 +294,27 @@ static bool pcm_valid(xpd_t *xpd, xpacket_t *pack)
xpp_line_t lines = RPACKET_FIELD(pack, GLOBAL, PCM_READ, lines);
int i;
int count = 0;
+ uint16_t good_len;
BUG_ON(!pack);
- BUG_ON(pack->content.opcode != XPROTO_NAME(GLOBAL, PCM_READ));
- for_each_line(xpd, i)
+ BUG_ON(pack->opcode != XPROTO_NAME(GLOBAL, PCM_READ));
+/*
+ * Don't use for_each_line(xpd, i) here because for BRI it will ignore the channels of the other
+ * xpd's in the same unit.
+ */
+ for (i = 0; i < CHANNELS_PERXPD; i++)
if(IS_SET(lines, i))
count++;
- if(pack->datalen != (sizeof(xpp_line_t) + count * 8)) {
+ /* FRAMES: include opcode in calculation */
+ good_len = RPACKET_HEADERSIZE + sizeof(xpp_line_t) + count * 8;
+ if(pack->datalen != good_len) {
static int rate_limit = 0;
XPD_COUNTER(xpd, RECV_ERRORS)++;
if((rate_limit++ % 1000) <= 10) {
- ERR("%s/%s: BAD PCM REPLY: pack->datalen=%d, count=%d\n",
- xpd->xbus->busname, xpd->xpdname, pack->datalen, count);
+ ERR("%s/%s: BAD PCM REPLY: pack->datalen=%d (should be %d), count=%d\n",
+ xpd->xbus->busname, xpd->xpdname,
+ pack->datalen, good_len, count);
dump_packet("BAD PCM REPLY", pack, 1);
}
return 0;