diff options
author | tzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2007-01-25 10:48:33 +0000 |
---|---|---|
committer | tzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2007-01-25 10:48:33 +0000 |
commit | d717b83056e5076a64c9471dd85573de409582d7 (patch) | |
tree | f46ebf64df73d8f513989d29f54e5b22b8bce2a5 /xpp/card_global.c | |
parent | a11cf4664ea4fd14478f88c9118acd0f87ad7008 (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.c | 161 |
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; |