summaryrefslogtreecommitdiff
path: root/xpp/card_global.c
diff options
context:
space:
mode:
authortzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2007-04-29 20:19:13 +0000
committertzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2007-04-29 20:19:13 +0000
commit878abc56f013a9bd94a46bf1a009407e6c8ecceb (patch)
treed38e11f3cc2cdb3cc9357e9a1bee1f20c724f272 /xpp/card_global.c
parent47bcd1d6d884db6f92c68772aad712579f1c3b16 (diff)
xpp rev. 3814:
* Protocol no. 2.6: syncing improvements. * Support for 8-port Astribank BRI. * Firmware unloading now works: rmmod xpp_usb; /etc/hotplug/usb/xpp_fxloader reset * Defaults of kernel parameters are now part of parameter description. * World-readable kernel parameters. * No need for extra patch beyond bristuff for Astribank BRI. * Default poll intervals changed: 500 in BRI and FXO. * Allow changing FXS polls interval at run time. * BRI initalization fixed on SUSE (path to logger). * When using the SUSE zaptel rpm package, set modules_var=ZAPTEL_MODULES in /etc/sysconfig/zaptel . * zt_registration not verbose by default. * xpp_sync warns if FXO is sync slave. * Fixed genzaptelconf -z (zapscan output emulation). * PCM fixes. * Solves "multiple ticks" bug. No need for pcm_tasklets workaround. git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.2@2475 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'xpp/card_global.c')
-rw-r--r--xpp/card_global.c108
1 files changed, 57 insertions, 51 deletions
diff --git a/xpp/card_global.c b/xpp/card_global.c
index 0f2acb9..0ec6227 100644
--- a/xpp/card_global.c
+++ b/xpp/card_global.c
@@ -30,7 +30,7 @@
static const char rcsid[] = "$Id$";
-DEF_PARM(charp,initdir, "/usr/share/zaptel", 0600, "The directory of card initialization scripts");
+DEF_PARM(charp,initdir, "/usr/share/zaptel", 0644, "The directory of card initialization scripts");
extern int print_dbg;
static bool pcm_valid(xpd_t *xpd, xpacket_t *pack);
@@ -62,22 +62,16 @@ static void global_packet_dump(const char *msg, xpacket_t *pack);
/*
* The XPD parameter is totaly ignored by the driver and firmware as well.
*/
-/* 0x19 */ HOSTCMD(GLOBAL, SYNC_SOURCE, bool setit, bool is_master)
+/* 0x19 */ HOSTCMD(GLOBAL, SYNC_SOURCE, enum sync_mode mode, int drift)
{
xframe_t *xframe;
xpacket_t *pack;
- byte mask = 0;
BUG_ON(!xbus);
- if(is_master)
- mask |= BIT(0);
- if(!setit)
- mask |= BIT(1);
- DBG("%s: setit=%s is_master=%s\n",
- xbus->busname,
- (setit)?"yes":"no", (is_master)?"yes":"no");
+ DBG("%s: mode=0x%X drift=%d\n", xbus->busname, mode, drift);
XFRAME_NEW(xframe, pack, xbus, GLOBAL, SYNC_SOURCE, 0);
- RPACKET_FIELD(pack, GLOBAL, SYNC_SOURCE, mask) = mask;
+ RPACKET_FIELD(pack, GLOBAL, SYNC_SOURCE, sync_mode) = mode;
+ RPACKET_FIELD(pack, GLOBAL, SYNC_SOURCE, drift) = drift;
xframe_send(xbus, xframe);
return 0;
}
@@ -122,15 +116,37 @@ HANDLER_DEF(GLOBAL, PCM_READ)
/* FIXME: work around temporary hardware bug */
xpp_line_t lines = RPACKET_FIELD(pack, GLOBAL, PCM_READ, lines);
const byte *pcm = RPACKET_FIELD(pack, GLOBAL, PCM_READ, pcm);
+ xpd_addr_t addr = RPACKET_FIELD(pack, GLOBAL, PCM_READ, addr);
volatile u_char *readchunk;
volatile u_char *r;
unsigned long flags;
int i;
xpp_line_t old_lines = lines;
- bool is_bri;
+ int unit;
int subunit;
+ struct timeval now;
+ long sec_diff;
+ long usec_diff;
BUG_ON(!xbus);
+ do_gettimeofday(&now);
+ sec_diff = now.tv_sec - xbus->last_rx_sync.tv_sec;
+ usec_diff = sec_diff * 1000000 + (now.tv_usec - xbus->last_rx_sync.tv_usec);
+ if(unlikely(abs(sec_diff) > 2)) {
+ DBG("%s: PCM RX timing restart (sec_diff=%ld)\n",
+ xbus->busname, sec_diff);
+ } else {
+ if(abs(usec_diff - 1000) > TICK_TOLERANCE) {
+ if(print_dbg && printk_ratelimit())
+ DBG("%s: Bad PCM RX timing: usec_diff=%ld.\n",
+ xbus->busname, usec_diff);
+ }
+ if(usec_diff > xbus->max_rx_sync)
+ xbus->max_rx_sync = usec_diff;
+ if(usec_diff < xbus->min_rx_sync)
+ xbus->min_rx_sync = usec_diff;
+ }
+ xbus->last_rx_sync = now;
if(!xpd) {
#if 0
int xpd_num = XPD_NUM(pack->addr);
@@ -149,18 +165,24 @@ HANDLER_DEF(GLOBAL, PCM_READ)
xbus->busname, xpd->xpdname, old_lines, lines, xpd->addr.subunit);
return -EPROTO;
}
- 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) {
+ unit = xpd->addr.unit;
+ for(subunit = 0; subunit < MAX_SUBUNIT; subunit++, lines >>= SUBUNIT_PCM_SHIFT) {
+ xpd_t *tmp_xpd;
+
+ tmp_xpd = xpd_by_addr(xbus, unit, subunit);
+ if(!tmp_xpd || !tmp_xpd->card_present)
+ continue;
+ if(lines == 0)
+ break; /* Optimize */
+ spin_lock_irqsave(&tmp_xpd->lock, flags);
+ if (tmp_xpd->timer_count & 1) {
/* First part */
- r = readchunk = xpd->readchunk;
+ r = readchunk = tmp_xpd->readchunk;
} else {
- r = readchunk = xpd->readchunk + ZT_CHUNKSIZE * CHANNELS_PERXPD;
+ r = readchunk = tmp_xpd->readchunk + ZT_CHUNKSIZE * CHANNELS_PERXPD;
}
-
/* Copy PCM and put each channel in its index */
- for_each_line(xpd, i) {
+ for_each_line(tmp_xpd, i) {
if(IS_SET(lines, i)) {
memcpy((u_char *)r, pcm, ZT_CHUNKSIZE);
//memset((u_char *)r, 0x5A, ZT_CHUNKSIZE); // DEBUG
@@ -168,40 +190,26 @@ HANDLER_DEF(GLOBAL, PCM_READ)
}
r += ZT_CHUNKSIZE;
}
-
- XPD_COUNTER(xpd, PCM_READ)++;
+ XPD_COUNTER(tmp_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)
+ spin_unlock_irqrestore(&tmp_xpd->lock, flags);
+ if (!IS_BRI(tmp_xpd)) /* only BRI has subunits */
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);
-
+ }
+ /*
+ * Firmware marks the sync packets.
+ * This is out of the loop, so we don't send multiple times
+ * for BRI subunits.
+ */
+ if(addr.sync_master)
+ got_sync_from(xpd);
return 0;
}
HANDLER_DEF(GLOBAL, SYNC_REPLY)
{
- byte mask = RPACKET_FIELD(pack, GLOBAL, SYNC_REPLY, mask);
- bool setit = mask & 0x01;
+ byte mode = RPACKET_FIELD(pack, GLOBAL, SYNC_REPLY, sync_mode);
+ byte drift = RPACKET_FIELD(pack, GLOBAL, SYNC_REPLY, drift);
BUG_ON(!xbus);
if(!xpd) {
@@ -209,10 +217,8 @@ HANDLER_DEF(GLOBAL, SYNC_REPLY)
NOTICE("%s: received %s for non-existing xpd: addr=0x%02X\n", __FUNCTION__, cmd->name, xpd_num);
return -EPROTO;
}
- DBG("%s/%s: mask=0x%X %s\n",
- xpd->xbus->busname, xpd->xpdname,
- mask,
- (setit) ? "SET SYNC MASTER" : "");
+ DBG("%s/%s: mode=0x%X drift=%d\n", xpd->xbus->busname, xpd->xpdname,
+ mode, drift);
dump_packet("SYNC_REPLY", pack, 1);
return 0;
}