summaryrefslogtreecommitdiff
path: root/xpp/card_global.c
diff options
context:
space:
mode:
authortzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2007-01-25 10:48:33 +0000
committertzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2007-01-25 10:48:33 +0000
commitd717b83056e5076a64c9471dd85573de409582d7 (patch)
treef46ebf64df73d8f513989d29f54e5b22b8bce2a5 /xpp/card_global.c
parenta11cf4664ea4fd14478f88c9118acd0f87ad7008 (diff)
* Xbus protocol version: 2.4 (Zaptel 1.2.12/1.4.0 had 2.3).
XPS Init scripts renamed accordingly. * Performance improvements for multi-XPD (span) devices. * Astribank BRI driver (in next commit). * Changes under /proc: - XBUS and XPD numbers have two digits. - Every script wildcard should be replaced from XBUS-? to XBUS-[0-9]* - Added /proc/xpp/XBUS-*/XPD-*/blink: echo 1 to start and 0 to stop. * Several countries (South Africa, UAE, anybody else) require a shorter ring delay. Adjust FXO reg 0x17 (23)'s bits 0:2 to 011. * Use tasklets to move most of the interrupt PCM copying out of the interrupt. * Debugfs-based code to dump data to userspace (used to debug BRI D channel). * Pretend every 2.6.9 actually has later RHEL's typedefs. * fpga_load supports /dev/bus/usb . * Fixed physical order sorting in genzaptelconf. git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.2@1966 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'xpp/card_global.c')
-rw-r--r--xpp/card_global.c161
1 files changed, 73 insertions, 88 deletions
diff --git a/xpp/card_global.c b/xpp/card_global.c
index 22456bc..17e94ef 100644
--- a/xpp/card_global.c
+++ b/xpp/card_global.c
@@ -25,6 +25,7 @@
#include "xpp_zap.h"
#include "xproto.h"
#include "zap_debug.h"
+#include "xbus-core.h"
#include <linux/module.h>
static const char rcsid[] = "$Id$";
@@ -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,14 +215,12 @@ 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;
}
@@ -257,11 +232,13 @@ HANDLER_DEF(GLOBAL, ERROR_CODE)
BUG_ON(!xbus);
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(xpdname, XPD_NAMELEN, "#%d", xpd_num);
} else {
snprintf(xpdname, XPD_NAMELEN, "%s", xpd->xpdname);
}
+ if(!printk_ratelimit())
+ return 0;
NOTICE("%s/%s: %s CODE = 0x%X\n", xbus->busname, xpdname, cmd->name, errorcode);
switch(errorcode) {
case 1:
@@ -298,7 +275,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 +289,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;