diff options
author | tzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2007-04-29 20:19:13 +0000 |
---|---|---|
committer | tzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2007-04-29 20:19:13 +0000 |
commit | 878abc56f013a9bd94a46bf1a009407e6c8ecceb (patch) | |
tree | d38e11f3cc2cdb3cc9357e9a1bee1f20c724f272 /xpp/card_global.c | |
parent | 47bcd1d6d884db6f92c68772aad712579f1c3b16 (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.c | 108 |
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; } |