[Pkg-voip-commits] r2068 - in zaptel/trunk/debian: . patches
Tzafrir Cohen
tzafrir-guest at costa.debian.org
Sat Jul 15 23:02:31 UTC 2006
Author: tzafrir-guest
Date: 2006-07-15 23:02:30 +0000 (Sat, 15 Jul 2006)
New Revision: 2068
Removed:
zaptel/trunk/debian/patches/xpp_xorcom_debian.dpatch
Modified:
zaptel/trunk/debian/changelog
zaptel/trunk/debian/control
zaptel/trunk/debian/copyright
zaptel/trunk/debian/patches/00list
zaptel/trunk/debian/patches/Makefile_bristuff.dpatch
zaptel/trunk/debian/patches/Makefile_uname.dpatch
Log:
* New upstream release
* xpp_xorcom_debian.dpatch obsolete by new version
* Makefile_uname.dpatch: Updated. Note: watch for PWD issues.
* Makefile_bristuff.dpatch: updated to reflect Makefile change.
Modified: zaptel/trunk/debian/changelog
===================================================================
--- zaptel/trunk/debian/changelog 2006-07-15 22:22:19 UTC (rev 2067)
+++ zaptel/trunk/debian/changelog 2006-07-15 23:02:30 UTC (rev 2068)
@@ -1,6 +1,7 @@
-zaptel (1:1.2.6-3) UNRELEASED; urgency=low
+zaptel (1:1.2.7-1) UNRELEASED; urgency=low
* NOT RELEASED YET
+ * New upstream release
[ Kilian Krause ]
* Add vzaphfc driver (enhanced zaphfc) by Jens Wilke.
@@ -11,16 +12,7 @@
* Removing some unneeded dirs from zaptel-source
* debian/patches/Makefile_kbuild: a small part of the original one.
Fixes building on Sarge
- * xpp revision r1608 (branches/RELEASE-1.1.0)
- - With EC
- - FXS caller ID working
- - Improved FXO
- - Back to RBS
- - genzaptelconf is now in zaptel
- - Generate ZT_EVENT_REMOVED in the right place: hinting asterisk to
- disconnect
- - Add support for fxotune ioctls
- - Remove old cmd2inc et al.
+ * genzaptelconf is now in zaptel
* xpp/utils/Makefile has a decent install target
* debian/rules: Use CURDIR
* debian/modulestest: Building modules for -3 kernels
@@ -30,10 +22,12 @@
* debian/control: require libusb-dev for building xpp firmware loader.
* debian/control: Recommend package xpp-firmware (should be added to
non-free)
- * bristuff_local_zaptelh.dpatch: Build bristuff modules with correct
+ * bristuff_local_zaptelh.dpatch: Build bristuff modules with correct
zaptel.conf (in Sarge)
+ * Makefile_uname.dpatch: Updated. Note: watch for PWD issues.
+ * Makefile_bristuff.dpatch: updated to reflect Makefile change.
- -- Kilian Krause <kilian at debian.org> Sat, 17 Jun 2006 16:05:32 +0200
+ -- Tzafrir Cohen <tzafrir.cohen at xorcom.com> Sat, 15 Jul 2006 01:59:23 +0300
zaptel (1:1.2.6-2) unstable; urgency=high
Modified: zaptel/trunk/debian/control
===================================================================
--- zaptel/trunk/debian/control 2006-07-15 22:22:19 UTC (rev 2067)
+++ zaptel/trunk/debian/control 2006-07-15 23:02:30 UTC (rev 2068)
@@ -12,7 +12,6 @@
# Xorcom packages depend on xpp-firmware. Debian zaptel will probably
# just recommend it.
Depends: ${shlibs:Depends}, procps, fxload
-Recommends: xpp-firmware
Description: zapata telephony utilities
Userspace utilities for configuring the Zapata telephony kernel driver,
which supports various telephony hardware, such as Wildcard series of
Modified: zaptel/trunk/debian/copyright
===================================================================
--- zaptel/trunk/debian/copyright 2006-07-15 22:22:19 UTC (rev 2067)
+++ zaptel/trunk/debian/copyright 2006-07-15 23:02:30 UTC (rev 2068)
@@ -54,6 +54,6 @@
*
* Modify from wctdm.c by MiaoLin<miaolin at openvox.com.cn>
-opvxa1200.c is not availble for download from the author's site yet
+opvxa1200.c is not available for download from the author's site yet
(it is distributed with the CD that is included with the product).
Author promisses to set up a public mirror soon.
Modified: zaptel/trunk/debian/patches/00list
===================================================================
--- zaptel/trunk/debian/patches/00list 2006-07-15 22:22:19 UTC (rev 2067)
+++ zaptel/trunk/debian/patches/00list 2006-07-15 23:02:30 UTC (rev 2068)
@@ -8,6 +8,5 @@
# touches the Makefile as well:
echocan_env
ukcid
-xpp_xorcom_debian
bristuff
bristuff_local_zaptelh
Modified: zaptel/trunk/debian/patches/Makefile_bristuff.dpatch
===================================================================
--- zaptel/trunk/debian/patches/Makefile_bristuff.dpatch 2006-07-15 22:22:19 UTC (rev 2067)
+++ zaptel/trunk/debian/patches/Makefile_bristuff.dpatch 2006-07-15 23:02:30 UTC (rev 2068)
@@ -56,6 +56,6 @@
+ cp $^ $@
+
+
- $(MODULESO): %.o: %.c zaptel.h
- $(HOSTCC) $(KFLAGS) -o $@ -c $<
+ $(filter-out wct4xxp.o,$(MODULESO)) wct4xxp_base.o: %.o: %.c zaptel.h
+ $(CC) $(KFLAGS) -o $@ -c $<
Modified: zaptel/trunk/debian/patches/Makefile_uname.dpatch
===================================================================
--- zaptel/trunk/debian/patches/Makefile_uname.dpatch 2006-07-15 22:22:19 UTC (rev 2067)
+++ zaptel/trunk/debian/patches/Makefile_uname.dpatch 2006-07-15 23:02:30 UTC (rev 2068)
@@ -12,9 +12,9 @@
--- zaptel-1.2.0-rc1~/Makefile 2005-11-09 21:22:00.000000000 +0000
+++ zaptel-1.2.0-rc1/Makefile 2005-11-09 21:24:20.000000000 +0000
@@ -7,6 +7,11 @@
- BASEADDR=0xd0000
-
- HOSTCC=gcc
+ ifeq ($(PWD),)
+ PWD:=$(shell pwd)
+ endif
+ifeq ($(DEB_HOST_GNU_TYPE),)
+UNAME_M:=$(shell uname -m)
+else
@@ -30,7 +30,7 @@
+KVERS_MAJ:=$(shell echo $(KVERS) | cut -d. -f1-2)
KINCLUDES:=$(KSRC)/include
- CFLAGS+=-I. -O4 -g -Wall -DBUILDING_TONEZONE #-DTONEZONE_DRIVER
+ CFLAGS+=-I. -Iinclude -O4 -g -Wall -DBUILDING_TONEZONE #-DTONEZONE_DRIVER
-CFLAGS_PPC:=$(shell if uname -m | grep -q ppc; then echo "-fsigned-char"; fi)
-CFLAGS_X86-64:=$(shell if uname -m | grep -q x86_64; then echo "-m64"; fi)
+ifneq (,$(findstring ppc,$(UNAME_M)))
Deleted: zaptel/trunk/debian/patches/xpp_xorcom_debian.dpatch
===================================================================
--- zaptel/trunk/debian/patches/xpp_xorcom_debian.dpatch 2006-07-15 22:22:19 UTC (rev 2067)
+++ zaptel/trunk/debian/patches/xpp_xorcom_debian.dpatch 2006-07-15 23:02:30 UTC (rev 2068)
@@ -1,13973 +0,0 @@
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## xpp_xorcom_debian.dpatch by Tzafrir Cohen <tzafrir.cohen at xorcom.com>
-##
-## DP: Up-to-date zaptel drivers for the Xorcom Astribank and friends.
-## DP: Revision r1608 (branches/RELEASE-1.1.0)
-
-## DP: This version omites the .version file and the firmware files.
-
- at DPATCH@
-diff -uNr -x .svn -x debian zaptel-1.2.6/.version zaptel-xpp-LJNBCn_dist/.version
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/card_fxo.c zaptel-xpp-LJNBCn_dist/xpp/card_fxo.c
---- zaptel-1.2.6/xpp/card_fxo.c 1970-01-01 02:00:00.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/card_fxo.c 2006-07-05 16:28:42.355959000 +0300
-@@ -0,0 +1,946 @@
-+/*
-+ * Written by Oron Peled <oron at actcom.co.il>
-+ * Copyright (C) 2004-2006, Xorcom
-+ *
-+ * All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/fs.h>
-+#include <linux/delay.h>
-+#include <version.h> /* For zaptel version */
-+#include "xpd.h"
-+#include "xproto.h"
-+#include "xpp_zap.h"
-+#include "card_fxo.h"
-+#include "zap_debug.h"
-+
-+static const char rcsid[] = "$Id: card_fxo.c 1584 2006-07-05 13:28:42Z tzafrir $";
-+
-+DEF_PARM(int, print_dbg, 0, "Print DBG statements"); /* must be before zap_debug.h */
-+DEF_PARM(uint, poll_battery_interval, 100, "Poll battery interval in milliseconds");
-+DEF_PARM(bool, report_battery, 0, "Report battery status to zaptel");
-+
-+/* Signaling is opposite (fxs signalling for fxo card) */
-+#if 1
-+#define FXO_DEFAULT_SIGCAP (ZT_SIG_FXSKS | ZT_SIG_FXSLS)
-+#else
-+#define FXO_DEFAULT_SIGCAP (ZT_SIG_SF)
-+#endif
-+
-+enum fxo_leds {
-+ LED_GREEN,
-+};
-+
-+#define NUM_LEDS 1
-+#define DELAY_UNTIL_DIALTONE 3000
-+
-+/*---------------- FXO Protocol Commands ----------------------------------*/
-+
-+static /* 0x0F */ DECLARE_CMD(FXO, CHAN_ENABLE, xpp_line_t lines, bool on);
-+static /* 0x0F */ DECLARE_CMD(FXO, CHAN_CID, int pos);
-+static /* 0x0F */ DECLARE_CMD(FXO, RING, int pos, bool on);
-+static /* 0x0F */ DECLARE_CMD(FXO, SETHOOK, int pos, bool offhook);
-+static /* 0x0F */ DECLARE_CMD(FXO, RELAY_OUT, byte which, bool on);
-+static /* 0x0F */ DECLARE_CMD(FXO, DAA_QUERY, int pos, byte reg_num);
-+
-+static bool fxo_packet_is_valid(xpacket_t *pack);
-+static void fxo_packet_dump(xpacket_t *pack);
-+static int proc_fxo_info_read(char *page, char **start, off_t off, int count, int *eof, void *data);
-+static int proc_xpd_slic_read(char *page, char **start, off_t off, int count, int *eof, void *data);
-+static int proc_xpd_slic_write(struct file *file, const char __user *buffer, unsigned long count, void *data);
-+static int process_slic_cmdline(xpd_t *xpd, char *cmdline);
-+
-+#define PROC_DAA_FNAME "slics"
-+#define PROC_FXO_INFO_FNAME "fxo_info"
-+
-+struct FXO_priv_data {
-+ struct proc_dir_entry *xpd_slic;
-+ struct proc_dir_entry *fxo_info;
-+ slic_reply_t requested_reply;
-+ slic_reply_t last_reply;
-+ xpp_line_t battery;
-+ xpp_line_t ledstate[NUM_LEDS]; /* 0 - OFF, 1 - ON */
-+ int blinking[NUM_LEDS][CHANNELS_PERXPD];
-+};
-+
-+/*---------------- FXO: Static functions ----------------------------------*/
-+
-+#define IS_BLINKING(priv,pos,color) ((priv)->blinking[color][pos] != 0)
-+#define DO_BLINK(priv,pos,color,val) ((priv)->blinking[color][pos] = (val))
-+
-+/*
-+ * LED control is done via DAA register 0x20
-+ */
-+static int do_led(xpd_t *xpd, lineno_t pos, byte which, bool on)
-+{
-+ int ret = 0;
-+ xpacket_t *pack;
-+ slic_cmd_t *sc;
-+ int len;
-+ struct FXO_priv_data *priv;
-+ xpp_line_t lines;
-+ xbus_t *xbus;
-+
-+ BUG_ON(!xpd);
-+ xbus = xpd->xbus;
-+ priv = xpd->priv;
-+ which = which % NUM_LEDS;
-+ if(IS_SET(xpd->digital_outputs, pos) || IS_SET(xpd->digital_inputs, pos))
-+ goto out;
-+ if(pos == ALL_LINES) {
-+ lines = ~0;
-+ priv->ledstate[which] = (on) ? ~0 : 0;
-+ } else {
-+ lines = BIT(pos);
-+ if(on) {
-+ BIT_SET(priv->ledstate[which], pos);
-+ } else {
-+ BIT_CLR(priv->ledstate[which], pos);
-+ }
-+ }
-+ if(!lines) // Nothing to do
-+ goto out;
-+ DBG("%s/%s: LED: lines=0x%04X which=%d -- %s\n", xbus->busname, xpd->xpdname, lines, which, (on) ? "on" : "off");
-+ XPACKET_NEW(pack, xbus, FXO, DAA_WRITE, xpd->id);
-+ sc = &RPACKET_FIELD(pack, FXO, DAA_WRITE, slic_cmd);
-+ len = slic_cmd_direct_write(sc, lines, 0x20, on);
-+ // DBG("LED pack: line=%d %s\n", i, (on)?"on":"off");
-+ pack->datalen = len;
-+ packet_send(xbus, pack);
-+out:
-+ return ret;
-+}
-+
-+static void handle_fxo_leds(xpd_t *xpd)
-+{
-+ int i;
-+ unsigned long flags;
-+ const enum fxo_leds color = LED_GREEN;
-+ unsigned int timer_count;
-+ struct FXO_priv_data *priv;
-+
-+ BUG_ON(!xpd);
-+ spin_lock_irqsave(&xpd->lock, flags);
-+ priv = xpd->priv;
-+ timer_count = xpd->timer_count;
-+ for_each_line(xpd, i) {
-+ if(IS_SET(xpd->digital_outputs, i) || IS_SET(xpd->digital_inputs, i))
-+ continue;
-+ if(IS_BLINKING(priv,i,color)) {
-+ // led state is toggled
-+ if((timer_count % LED_BLINK_PERIOD) == 0) {
-+ DBG("%s/%s/%d: led_state=%s\n", xpd->xbus->busname, xpd->xpdname, i,
-+ (IS_SET(priv->ledstate[color], i))?"ON":"OFF");
-+ if(!IS_SET(priv->ledstate[color], i)) {
-+ do_led(xpd, i, color, 1);
-+ } else {
-+ do_led(xpd, i, color, 0);
-+ }
-+ }
-+ }
-+ }
-+ spin_unlock_irqrestore(&xpd->lock, flags);
-+}
-+
-+static void do_sethook(xpd_t *xpd, int pos, bool offhook)
-+{
-+ unsigned long flags;
-+ struct FXO_priv_data *priv;
-+
-+ BUG_ON(!xpd);
-+ BUG_ON(xpd->direction == TO_PHONE); // We can SETHOOK state only on PSTN
-+ priv = xpd->priv;
-+ BUG_ON(!priv);
-+ if(!IS_SET(priv->battery, pos)) {
-+ DBG("%s/%s/%d: WARNING: called while battery is off\n", xpd->xbus->busname, xpd->xpdname, pos);
-+ }
-+ spin_lock_irqsave(&xpd->lock, flags);
-+ xpd->ringing[pos] = 0; // No more rings
-+ CALL_XMETHOD(SETHOOK, xpd->xbus, xpd, pos, offhook);
-+ if(offhook) {
-+ BIT_SET(xpd->hookstate, pos);
-+ } else {
-+ BIT_CLR(xpd->hookstate, pos);
-+ xpd->delay_until_dialtone[pos] = 0;
-+ }
-+ spin_unlock_irqrestore(&xpd->lock, flags);
-+ if(offhook)
-+ wake_up_interruptible(&xpd->txstateq[pos]);
-+}
-+
-+/*---------------- FXO: Methods -------------------------------------------*/
-+
-+static xpd_t *FXO_card_new(xbus_t *xbus, int xpd_num, const xproto_table_t *proto_table, byte revision)
-+{
-+ xpd_t *xpd = NULL;
-+ int channels = min(8, CHANNELS_PERXPD);
-+
-+ xpd = xpd_alloc(sizeof(struct FXO_priv_data), xbus, xpd_num, proto_table, channels, revision);
-+ if(!xpd)
-+ return NULL;
-+ xpd->direction = TO_PSTN;
-+ xpd->revision = revision;
-+ return xpd;
-+}
-+
-+static void clean_proc(xbus_t *xbus, xpd_t *xpd)
-+{
-+ struct FXO_priv_data *priv;
-+
-+ BUG_ON(!xpd);
-+ priv = xpd->priv;
-+ DBG("%s/%s\n", xbus->busname, xpd->xpdname);
-+#ifdef CONFIG_PROC_FS
-+ if(priv->xpd_slic) {
-+ DBG("Removing xpd DAA file %s/%s\n", xbus->busname, xpd->xpdname);
-+ remove_proc_entry(PROC_DAA_FNAME, xpd->proc_xpd_dir);
-+ }
-+ if(priv->fxo_info) {
-+ DBG("Removing xpd FXO_INFO file %s/%s\n", xbus->busname, xpd->xpdname);
-+ remove_proc_entry(PROC_FXO_INFO_FNAME, xpd->proc_xpd_dir);
-+ }
-+#endif
-+}
-+
-+static int FXO_card_init(xbus_t *xbus, xpd_t *xpd)
-+{
-+ struct FXO_priv_data *priv;
-+ int ret = 0;
-+ int i;
-+
-+ BUG_ON(!xpd);
-+ priv = xpd->priv;
-+#ifdef CONFIG_PROC_FS
-+ DBG("Creating FXO_INFO file for %s/%s\n", xbus->busname, xpd->xpdname);
-+ priv->fxo_info = create_proc_read_entry(PROC_FXO_INFO_FNAME, 0444, xpd->proc_xpd_dir, proc_fxo_info_read, xpd);
-+ if(!priv->fxo_info) {
-+ ERR("Failed to create proc '%s' for %s/%s\n", PROC_FXO_INFO_FNAME, xbus->busname, xpd->xpdname);
-+ ret = -ENOENT;
-+ goto err;
-+ }
-+ priv->fxo_info->owner = THIS_MODULE;
-+ DBG("Creating DAAs file for %s/%s\n", xbus->busname, xpd->xpdname);
-+ priv->xpd_slic = create_proc_entry(PROC_DAA_FNAME, 0644, xpd->proc_xpd_dir);
-+ if(!priv->xpd_slic) {
-+ ERR("Failed to create proc file for DAAs of %s/%s\n", xbus->busname, xpd->xpdname);
-+ ret = -ENOENT;
-+ goto err;
-+ }
-+ priv->xpd_slic->owner = THIS_MODULE;
-+ priv->xpd_slic->write_proc = proc_xpd_slic_write;
-+ priv->xpd_slic->read_proc = proc_xpd_slic_read;
-+ priv->xpd_slic->data = xpd;
-+#endif
-+ ret = run_initialize_registers(xpd);
-+ if(ret < 0)
-+ goto err;
-+ // Hanghup all lines
-+ for_each_line(xpd, i) {
-+ init_waitqueue_head(&xpd->txstateq[i]);
-+ do_sethook(xpd, i, 0);
-+ }
-+ DBG("done: %s/%s\n", xbus->busname, xpd->xpdname);
-+ return 0;
-+err:
-+ clean_proc(xbus, xpd);
-+ ERR("%s/%s: Failed initializing registers (%d)\n", xbus->busname, xpd->xpdname, ret);
-+ return ret;
-+}
-+
-+static int FXO_card_remove(xbus_t *xbus, xpd_t *xpd)
-+{
-+ struct FXO_priv_data *priv;
-+
-+ BUG_ON(!xpd);
-+ priv = xpd->priv;
-+ DBG("%s/%s\n", xbus->busname, xpd->xpdname);
-+ clean_proc(xbus, xpd);
-+ return 0;
-+}
-+
-+static int FXO_card_zaptel_preregistration(xpd_t *xpd, bool on)
-+{
-+ xbus_t *xbus;
-+ struct FXO_priv_data *priv;
-+ int i;
-+ unsigned long flags;
-+
-+ BUG_ON(!xpd);
-+ xbus = xpd->xbus;
-+ BUG_ON(!xbus);
-+ priv = xpd->priv;
-+ BUG_ON(!priv);
-+ DBG("%s/%s (%d)\n", xbus->busname, xpd->xpdname, on);
-+ snprintf(xpd->span.desc, MAX_SPANDESC, "Xorcom XPD #%d/%d: FXO", xbus->num, xpd->id);
-+ for_each_line(xpd, i) {
-+ struct zt_chan *cur_chan = &xpd->chans[i];
-+
-+ DBG("setting FXO channel %d\n", i);
-+ snprintf(cur_chan->name, MAX_CHANNAME, "XPP_FXO/%d/%d/%d", xbus->num, xpd->id, i);
-+ cur_chan->chanpos = i + 1;
-+ cur_chan->pvt = xpd;
-+ cur_chan->sigcap = FXO_DEFAULT_SIGCAP;
-+ }
-+ spin_lock_irqsave(&xpd->lock, flags);
-+ do_led(xpd, ALL_LINES, LED_GREEN, LED_OFF);
-+ spin_unlock_irqrestore(&xpd->lock, flags);
-+ for_each_line(xpd, i) {
-+ do_led(xpd, i, LED_GREEN, LED_ON);
-+ mdelay(50);
-+ }
-+ return 0;
-+}
-+
-+static int FXO_card_zaptel_postregistration(xpd_t *xpd, bool on)
-+{
-+ xbus_t *xbus;
-+ struct FXO_priv_data *priv;
-+ int i;
-+
-+ BUG_ON(!xpd);
-+ xbus = xpd->xbus;
-+ BUG_ON(!xbus);
-+ priv = xpd->priv;
-+ BUG_ON(!priv);
-+ DBG("%s/%s (%d)\n", xbus->busname, xpd->xpdname, on);
-+ for_each_line(xpd, i) {
-+ do_led(xpd, i, LED_GREEN, LED_OFF);
-+ mdelay(50);
-+ }
-+ return 0;
-+}
-+
-+#ifdef WITH_RBS
-+int FXO_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, zt_txsig_t txsig)
-+{
-+ struct FXO_priv_data *priv;
-+
-+ priv = xpd->priv;
-+ BUG_ON(!priv);
-+ DBG("%s/%s/%d: %s\n", xbus->busname, xpd->xpdname, pos, txsig2str(txsig));
-+ BUG_ON(xpd->direction != TO_PSTN);
-+ /* XXX Enable hooksig for FXO XXX */
-+ switch(txsig) {
-+ case ZT_TXSIG_START:
-+ break;
-+ case ZT_TXSIG_OFFHOOK:
-+ do_sethook(xpd, pos, 1);
-+ break;
-+ case ZT_TXSIG_ONHOOK:
-+ do_sethook(xpd, pos, 0);
-+ break;
-+ default:
-+ NOTICE("Can't set tx state to %s (%d)\n", txsig2str(txsig), txsig);
-+ return -EINVAL;
-+ }
-+ return 0;
-+}
-+
-+#else
-+int FXO_card_sethook(xbus_t *xbus, xpd_t *xpd, int pos, int hookstate)
-+{
-+ int ret = 0;
-+ struct FXO_priv_data *priv;
-+
-+ DBG("%s/%s/%d: %s\n", xbus->busname, xpd->xpdname, pos, hookstate2str(hookstate));
-+ switch(hookstate) {
-+ /* On-hook, off-hook: The PBX is playing a phone on an FXO line. */
-+ case ZT_ONHOOK:
-+ do_sethook(xpd, pos, 0);
-+ break;
-+ case ZT_START:
-+ DBG("%s/%s/%d: fall through ZT_OFFHOOK\n", xbus->busname, xpd->xpdname, pos);
-+ xpd->delay_until_dialtone[pos] = DELAY_UNTIL_DIALTONE;
-+ // Fall through
-+ case ZT_OFFHOOK:
-+ do_sethook(xpd, pos, 1);
-+ wait_event_interruptible(xpd->txstateq[pos], xpd->delay_until_dialtone[pos] <= 0);
-+ break;
-+ case ZT_WINK:
-+ WARN("No code yet\n");
-+ break;
-+ case ZT_FLASH:
-+ WARN("No code yet\n");
-+ break;
-+ case ZT_RING:
-+ DBG("%s/%s/%d: ZT_RING: %d\n", xbus->busname, xpd->xpdname, pos, xpd->ringing[pos]);
-+ break;
-+ case ZT_RINGOFF:
-+ WARN("No code yet\n");
-+ break;
-+ }
-+ return ret;
-+}
-+#endif
-+
-+static void poll_battery(xbus_t *xbus, xpd_t *xpd)
-+{
-+ int i;
-+
-+ for_each_line(xpd, i) {
-+ CALL_PROTO(FXO, DAA_QUERY, xbus, xpd, i, DAA_VBAT_REGISTER);
-+ }
-+}
-+
-+
-+static int FXO_card_tick(xbus_t *xbus, xpd_t *xpd)
-+{
-+ static unsigned rate_limit = 0;
-+ struct FXO_priv_data *priv;
-+
-+ BUG_ON(!xpd);
-+ priv = xpd->priv;
-+ BUG_ON(!priv);
-+ rate_limit++;
-+ if(poll_battery_interval != 0 && (rate_limit % poll_battery_interval) == 0) {
-+ poll_battery(xbus, xpd);
-+ }
-+ handle_fxo_leds(xpd);
-+ return 0;
-+}
-+
-+/* FIXME: based on data from from wctdm.h */
-+#include <wctdm.h>
-+static const int echotune_reg[] = {30,45,46,47,58,49,50,51,52};
-+union echotune {
-+ /* "coeff 0" is acim */
-+ unsigned char coeff[sizeof(echotune_reg)];
-+ struct wctdm_echo_coefs wctdm_struct;
-+};
-+
-+static int FXO_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd, unsigned long arg)
-+{
-+ union echotune echoregs;
-+ int i,ret;
-+
-+ BUG_ON(!xpd);
-+ DBG("cmd: 0x%x, expecting: 0x%x, pos=%d.\n", cmd, WCTDM_SET_ECHOTUNE, pos);
-+ switch (cmd) {
-+ case WCTDM_SET_ECHOTUNE:
-+ DBG("-- Setting echo registers: \n");
-+ /* first off: check if this span is fxs. If not: -EINVALID */
-+ if (copy_from_user(&echoregs.wctdm_struct,
-+ (struct wctdm_echo_coefs*)arg, sizeof(echoregs.wctdm_struct)))
-+ return -EFAULT;
-+
-+ /* Set the ACIM register */
-+ /* quick and dirty registers writing: */
-+ for (i=0; i<sizeof(echotune_reg); i++) {
-+ char buf[22];
-+ xpp_line_t lines = BIT(pos);
-+ sprintf(buf, "%02X %02X %02X %02X WD %2X %2X",
-+ (lines & 0xFF),
-+ ((lines >> 8) & 0xFF),
-+ ((lines >> 16) & 0xFF),
-+ ((lines >> 24) & 0xFF),
-+ echotune_reg[i],echoregs.coeff[i]
-+ );
-+ /* FIXME: code duplicated from proc_xpd_register_write */
-+ ret = process_slic_cmdline(xpd, buf);
-+ if(ret < 0)
-+ return ret;
-+ mdelay(1);
-+ }
-+
-+ DBG("-- Set echo registers successfully\n");
-+
-+ break;
-+ default:
-+ return -ENOTTY;
-+ }
-+ return 0;
-+}
-+
-+/*---------------- FXO: HOST COMMANDS -------------------------------------*/
-+
-+static /* 0x0F */ HOSTCMD(FXO, CHAN_ENABLE, xpp_line_t lines, bool on)
-+{
-+ unsigned long flags;
-+ int ret = 0;
-+ int i;
-+
-+ BUG_ON(!xbus);
-+ BUG_ON(!xpd);
-+ if(!lines) {
-+ return 0;
-+ }
-+ DBG("Channel Activation: 0x%4X %s\n", lines, (on) ? "on" : "off");
-+ if(on) {
-+ for_each_line(xpd, i) {
-+ spin_lock_irqsave(&xpd->lock, flags);
-+ do_led(xpd, i, LED_GREEN, LED_ON);
-+ spin_unlock_irqrestore(&xpd->lock, flags);
-+ mdelay(20);
-+ }
-+ for_each_line(xpd, i) {
-+ spin_lock_irqsave(&xpd->lock, flags);
-+ do_led(xpd, i, LED_GREEN, LED_OFF);
-+ spin_unlock_irqrestore(&xpd->lock, flags);
-+ mdelay(20);
-+ }
-+ }
-+ return ret;
-+}
-+
-+static /* 0x0F */ HOSTCMD(FXO, CHAN_CID, int pos)
-+{
-+ int ret = 0;
-+ xpp_line_t lines = BIT(pos);
-+
-+ BUG_ON(!xbus);
-+ BUG_ON(!xpd);
-+ if(!lines) {
-+ return 0;
-+ }
-+ DBG("%s/%s/%d:\n", xbus->busname, xpd->xpdname, pos);
-+ return ret;
-+}
-+
-+
-+static /* 0x0F */ HOSTCMD(FXO, RING, int pos, bool on)
-+{
-+ int ret = 0;
-+ xpacket_t *pack;
-+ slic_cmd_t *sc;
-+ xpp_line_t mask = BIT(pos);
-+ int len;
-+
-+ BUG_ON(!xbus);
-+ BUG_ON(!xpd);
-+ if(!mask) {
-+ return 0;
-+ }
-+ DBG("%s/%s/%d %s\n", xpd->xbus->busname, xpd->xpdname, pos, (on) ? "on" : "off");
-+ XPACKET_NEW(pack, xbus, FXO, DAA_WRITE, xpd->id);
-+ sc = &RPACKET_FIELD(pack, FXO, DAA_WRITE, slic_cmd);
-+ len = slic_cmd_direct_write(sc, mask, 0x40, (on)?0x04:0x01);
-+ pack->datalen = len;
-+
-+ packet_send(xbus, pack);
-+ return ret;
-+}
-+
-+static /* 0x0F */ HOSTCMD(FXO, SETHOOK, int pos, bool offhook)
-+{
-+ int ret = 0;
-+ xpacket_t *pack;
-+ slic_cmd_t *sc;
-+ int len;
-+ unsigned long flags;
-+ bool value;
-+
-+ BUG_ON(!xbus);
-+ BUG_ON(!xpd);
-+ value = (offhook) ? 0x09 : 0x08;
-+ // value |= BIT(3); /* Bit 3 is for CID */
-+ DBG("%s/%s/%d: SETHOOK: value=0x%02X %s\n", xbus->busname, xpd->xpdname, pos, value, (offhook)?"OFFHOOK":"ONHOOK");
-+ spin_lock_irqsave(&xpd->lock, flags);
-+ XPACKET_NEW(pack, xbus, FXO, DAA_WRITE, xpd->id);
-+ sc = &RPACKET_FIELD(pack, FXO, DAA_WRITE, slic_cmd);
-+ len = slic_cmd_direct_write(sc, BIT(pos), 0x05, value);
-+ pack->datalen = len;
-+ packet_send(xbus, pack);
-+ do_led(xpd, pos, LED_GREEN, (offhook)?LED_ON:LED_OFF);
-+ spin_unlock_irqrestore(&xpd->lock, flags);
-+ return ret;
-+}
-+
-+static /* 0x0F */ HOSTCMD(FXO, RELAY_OUT, byte which, bool on)
-+{
-+ return -ENOSYS;
-+}
-+
-+static /* 0x0F */ HOSTCMD(FXO, DAA_QUERY, int pos, byte reg_num)
-+{
-+ int ret = 0;
-+ xpacket_t *pack;
-+ slic_cmd_t *sc;
-+ int len;
-+
-+ BUG_ON(!xbus);
-+ BUG_ON(!xpd);
-+ // DBG("\n");
-+ XPACKET_NEW(pack, xbus, FXO, DAA_WRITE, xpd->id);
-+ sc = &RPACKET_FIELD(pack, FXO, DAA_WRITE, slic_cmd);
-+ len = slic_cmd_direct_read(sc, BIT(pos), reg_num);
-+
-+ pack->datalen = len;
-+
-+ packet_send(xbus, pack);
-+ return ret;
-+}
-+
-+/*---------------- FXO: Astribank Reply Handlers --------------------------*/
-+
-+HANDLER_DEF(FXO, SIG_CHANGED)
-+{
-+ xpp_line_t sig_status = RPACKET_FIELD(pack, FXO, SIG_CHANGED, sig_status);
-+ xpp_line_t sig_toggles = RPACKET_FIELD(pack, FXO, SIG_CHANGED, sig_toggles);
-+ unsigned long flags;
-+ int i;
-+
-+ if(!xpd) {
-+ NOTICE("%s: received %s for non-existing xpd: %d\n",
-+ __FUNCTION__, cmd->name, XPD_NUM(pack->content.addr));
-+ return -EPROTO;
-+ }
-+ DBG("%s/%s: (PSTN) sig_toggles=0x%04X sig_status=0x%04X\n", xpd->xbus->busname, xpd->xpdname, sig_toggles, sig_status);
-+ spin_lock_irqsave(&xpd->lock, flags);
-+ for_each_line(xpd, i) {
-+ if(IS_SET(sig_status, i)) {
-+ xpd->ringing[i] = 1;
-+ } else {
-+ xpd->ringing[i] = 0;
-+ }
-+ }
-+ spin_unlock_irqrestore(&xpd->lock, flags);
-+ return 0;
-+}
-+
-+HANDLER_DEF(FXO, DAA_REPLY)
-+{
-+ slic_reply_t *info = &RPACKET_FIELD(pack, FXO, DAA_REPLY, info);
-+ xpp_line_t lines = RPACKET_FIELD(pack, FXO, DAA_REPLY, lines);
-+ unsigned long flags;
-+ struct FXO_priv_data *priv;
-+
-+ if(!xpd) {
-+ NOTICE("%s: received %s for non-existing xpd: %d\n",
-+ __FUNCTION__, cmd->name, XPD_NUM(pack->content.addr));
-+ return -EPROTO;
-+ }
-+ spin_lock_irqsave(&xpd->lock, flags);
-+ priv = xpd->priv;
-+ BUG_ON(!priv);
-+ if(!info->indirect && info->reg_num == DAA_VBAT_REGISTER) {
-+ xpp_line_t last_batt_on = priv->battery;
-+ xpp_line_t changed_lines;
-+ int i;
-+
-+ if(abs(info->data_low) < BAT_THRESHOLD) {
-+ priv->battery &= ~lines;
-+ // DBG("%s/%s: BATTERY OFF (%04X) = %d\n", xpd->xbus->busname, xpd->xpdname, lines, info->data_low);
-+ } else {
-+ priv->battery |= lines;
-+ // DBG("%s/%s: BATTERY ON (%04X) = %d\n", xpd->xbus->busname, xpd->xpdname, lines, info->data_low);
-+ }
-+ changed_lines = last_batt_on ^ priv->battery;
-+ for_each_line(xpd, i) {
-+ if(IS_SET(changed_lines, i)) {
-+ update_line_status(xpd, i, IS_SET(priv->battery, i));
-+ }
-+ }
-+ }
-+#if 0
-+ DBG("DAA_REPLY: xpd #%d %s reg_num=0x%X, dataL=0x%X dataH=0x%X\n",
-+ xpd->id, (info->indirect)?"I":"D",
-+ info->reg_num, info->data_low, info->data_high);
-+#endif
-+
-+ /* Update /proc info only if reply relate to the last slic read request */
-+ if(priv->requested_reply.indirect == info->indirect &&
-+ priv->requested_reply.reg_num == info->reg_num) {
-+ priv->last_reply = *info;
-+ }
-+ spin_unlock_irqrestore(&xpd->lock, flags);
-+ return 0;
-+}
-+
-+
-+xproto_table_t PROTO_TABLE(FXO) = {
-+ .owner = THIS_MODULE,
-+ .entries = {
-+ /* Card Opcode */
-+ XENTRY( FXO, SIG_CHANGED ),
-+ XENTRY( FXO, DAA_REPLY ),
-+ },
-+ .name = "FXO",
-+ .type = XPD_TYPE_FXO,
-+ .xops = {
-+ .card_new = FXO_card_new,
-+ .card_init = FXO_card_init,
-+ .card_remove = FXO_card_remove,
-+ .card_zaptel_preregistration = FXO_card_zaptel_preregistration,
-+ .card_zaptel_postregistration = FXO_card_zaptel_postregistration,
-+#ifdef WITH_RBS
-+ .card_hooksig = FXO_card_hooksig,
-+#else
-+ .card_sethook = FXO_card_sethook,
-+#endif
-+ .card_tick = FXO_card_tick,
-+ .card_ioctl = FXO_card_ioctl,
-+
-+ .RING = XPROTO_CALLER(FXO, RING),
-+ .SETHOOK = XPROTO_CALLER(FXO, SETHOOK),
-+ .RELAY_OUT = XPROTO_CALLER(FXO, RELAY_OUT),
-+ .CHAN_ENABLE = XPROTO_CALLER(FXO, CHAN_ENABLE),
-+ .CHAN_CID = XPROTO_CALLER(FXO, CHAN_CID),
-+
-+ .SYNC_SOURCE = XPROTO_CALLER(GLOBAL, SYNC_SOURCE),
-+ .PCM_WRITE = XPROTO_CALLER(GLOBAL, PCM_WRITE),
-+ },
-+ .packet_is_valid = fxo_packet_is_valid,
-+ .packet_dump = fxo_packet_dump,
-+};
-+
-+static bool fxo_packet_is_valid(xpacket_t *pack)
-+{
-+ const xproto_entry_t *xe;
-+
-+ //DBG("\n");
-+ xe = xproto_card_entry(&PROTO_TABLE(FXO), pack->content.opcode);
-+ return xe != NULL;
-+}
-+
-+static void fxo_packet_dump(xpacket_t *pack)
-+{
-+ DBG("\n");
-+}
-+
-+/*------------------------- DAA Handling --------------------------*/
-+
-+static int proc_fxo_info_read(char *page, char **start, off_t off, int count, int *eof, void *data)
-+{
-+ int len = 0;
-+ unsigned long flags;
-+ xpd_t *xpd = data;
-+ struct FXO_priv_data *priv;
-+ int i;
-+
-+ if(!xpd)
-+ return -ENODEV;
-+ spin_lock_irqsave(&xpd->lock, flags);
-+ priv = xpd->priv;
-+ BUG_ON(!priv);
-+ len += sprintf(page + len, "\t%-17s: ", "Channel");
-+ for_each_line(xpd, i) {
-+ if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i))
-+ len += sprintf(page + len, "%d ", i % 10);
-+ }
-+ len += sprintf(page + len, "\n\t%-17s: ", "ledstate");
-+ for_each_line(xpd, i) {
-+ if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i))
-+ len += sprintf(page + len, "%d ", IS_SET(priv->ledstate[LED_GREEN], i));
-+ }
-+ len += sprintf(page + len, "\n\t%-17s: ", "blinking");
-+ for_each_line(xpd, i) {
-+ if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i))
-+ len += sprintf(page + len, "%d ", IS_BLINKING(priv,i,LED_GREEN));
-+ }
-+ len += sprintf(page + len, "\n\t%-17s: ", "battery");
-+ for_each_line(xpd, i) {
-+ len += sprintf(page + len, "%d ", IS_SET(priv->battery, i));
-+ }
-+ len += sprintf(page + len, "\n");
-+ spin_unlock_irqrestore(&xpd->lock, flags);
-+ if (len <= off+count)
-+ *eof = 1;
-+ *start = page + off;
-+ len -= off;
-+ if (len > count)
-+ len = count;
-+ if (len < 0)
-+ len = 0;
-+ return len;
-+}
-+
-+
-+static int proc_xpd_slic_read(char *page, char **start, off_t off, int count, int *eof, void *data)
-+{
-+ int len = 0;
-+ unsigned long flags;
-+ xpd_t *xpd = data;
-+ slic_reply_t *info;
-+ struct FXO_priv_data *priv;
-+
-+ BUG_ON(!xpd);
-+ spin_lock_irqsave(&xpd->lock, flags);
-+ priv = xpd->priv;
-+ BUG_ON(!priv);
-+ info = &priv->last_reply;
-+ len += sprintf(page + len, "# Writing bad data into this file may damage your hardware!\n");
-+ len += sprintf(page + len, "# Consult firmware docs first\n");
-+ len += sprintf(page + len, "DAA_REPLY: %s reg_num=0x%X, dataH=0x%X dataL=0x%X\n",
-+ (info->indirect)?"I":"D",
-+ info->reg_num, info->data_high, info->data_low);
-+ spin_unlock_irqrestore(&xpd->lock, flags);
-+ if (len <= off+count)
-+ *eof = 1;
-+ *start = page + off;
-+ len -= off;
-+ if (len > count)
-+ len = count;
-+ if (len < 0)
-+ len = 0;
-+ return len;
-+}
-+
-+/*
-+ * Direct/Indirect
-+ * v
-+ * FF FF FF FF WD 06 1
-+ * ^---------^ ^ Reg
-+ * | Write/Read
-+ * |
-+ * DAA #
-+ */
-+static int parse_slic_cmd(const char *buf, slic_cmd_t *sc, slic_reply_t *requested_reply)
-+{
-+ char op; /* [W]rite, [R]ead */
-+ char reg_type; /* [D]irect, [I]ndirect */
-+ int s1, s2, s3, s4;
-+ int reg_num;
-+ int data_low, data_high;
-+ xpp_line_t lines;
-+ int ret;
-+
-+ ret = sscanf(buf, "%x %x %x %x %c%c %x %x %x",
-+ &s1, &s2, &s3, &s4, &op, ®_type, ®_num, &data_high, &data_low);
-+ lines = (s4 << 24) | (s3 << 16) | (s2 << 8) | (s1);
-+ switch(op) {
-+ case 'R':
-+ if(reg_type == 'D' && ret == 7) {
-+ // DBG("0x%X 0x%X 0x%X 0x%X %c %x\n", s1, s2, s3, s4, reg_type, reg_num);
-+ ret = slic_cmd_direct_read(sc, lines, reg_num);
-+ if(requested_reply) {
-+ requested_reply->indirect = 0;
-+ requested_reply->reg_num = reg_num;
-+ }
-+ } else if(reg_type == 'I' && ret == 7) {
-+ // DBG("0x%X 0x%X 0x%X 0x%X %c %x\n", s1, s2, s3, s4, reg_type, reg_num);
-+ ret = slic_cmd_indirect_read(sc, lines, reg_num);
-+ if(requested_reply) {
-+ requested_reply->indirect = 1;
-+ requested_reply->reg_num = reg_num;
-+ }
-+ } else {
-+ NOTICE("%s: Bad read input: ret=%d buf='%s' reg_type=%c\n", __FUNCTION__, ret, buf, reg_type);
-+ goto err;
-+ }
-+ break;
-+ case 'W':
-+ if(reg_type == 'D' && ret == 8) {
-+ // DBG("0x%X 0x%X 0x%X 0x%X %c %x %X\n", s1, s2, s3, s4, reg_type, reg_num, data_high);
-+ ret = slic_cmd_direct_write(sc, lines, reg_num, data_high);
-+ } else if(reg_type == 'I' && ret == 9) {
-+ // DBG("0x%X 0x%X 0x%X 0x%X %c %x %X %X\n", s1, s2, s3, s4, reg_type, reg_num, data_high, data_low);
-+ ret = slic_cmd_indirect_write(sc, lines, reg_num, data_low, data_high);
-+ } else {
-+ NOTICE("%s: Bad write input: ret=%d buf='%s' reg_type=%c\n", __FUNCTION__, ret, buf, reg_type);
-+ goto err;
-+ }
-+ break;
-+ default:
-+ NOTICE("%s: Bad input: ret=%d buf='%s' op=%c\n", __FUNCTION__, ret, buf, op);
-+ goto err;
-+ }
-+ return ret;
-+err:
-+ return -EINVAL;
-+}
-+
-+static int process_slic_cmdline(xpd_t *xpd, char *cmdline)
-+{
-+ xbus_t *xbus;
-+ struct FXO_priv_data *priv;
-+ slic_cmd_t sc;
-+ xpacket_t *pack;
-+ char *p;
-+ int len = strlen(cmdline);
-+
-+ BUG_ON(!xpd);
-+ xbus = xpd->xbus;
-+ priv = xpd->priv;
-+ if((p = strchr(cmdline, '#')) != NULL) /* Truncate comments */
-+ *p = '\0';
-+ if((p = strchr(cmdline, ';')) != NULL) /* Truncate comments */
-+ *p = '\0';
-+ for(p = cmdline; *p && (*p == ' ' || *p == '\t'); p++) /* Trim leading whitespace */
-+ ;
-+ if(*p == '\0')
-+ return 0;
-+ len = parse_slic_cmd(p, &sc, &priv->requested_reply);
-+ if(len < 0)
-+ return len;
-+ if(!sc.lines) {
-+ NOTICE("%s: no channels are marked. Skip.\n", __FUNCTION__);
-+ return 0;
-+ }
-+ dump_slic_cmd("WRITE_DAA", &sc);
-+ XPACKET_NEW(pack, xbus, FXO, DAA_WRITE, xpd->id);
-+ RPACKET_FIELD(pack, FXO, DAA_WRITE, slic_cmd) = sc;
-+ pack->datalen = len;
-+ packet_send(xbus, pack);
-+ return 0;
-+}
-+
-+static int proc_xpd_slic_write(struct file *file, const char __user *buffer, unsigned long count, void *data)
-+{
-+ xpd_t *xpd = data;
-+ const int LINE_LEN = 500;
-+ char buf[LINE_LEN];
-+ char *p;
-+ int i;
-+ int ret;
-+
-+ if(!xpd)
-+ return -ENODEV;
-+ for(i = 0; i < count; /* noop */) {
-+ for(p = buf; p < buf + LINE_LEN; p++) { /* read a line */
-+ if(i >= count)
-+ break;
-+ if(get_user(*p, buffer + i))
-+ return -EFAULT;
-+ i++;
-+ if(*p == '\n' || *p == '\r') /* whatever */
-+ break;
-+ }
-+ if(p >= buf + LINE_LEN)
-+ return -E2BIG;
-+ *p = '\0';
-+ ret = process_slic_cmdline(xpd, buf);
-+ if(ret < 0)
-+ return ret;
-+ mdelay(1);
-+ }
-+ return count;
-+}
-+
-+
-+int __init card_fxo_startup(void)
-+{
-+ INFO("%s revision %s\n", THIS_MODULE->name, ZAPTEL_VERSION);
-+ xproto_register(&PROTO_TABLE(FXO));
-+ return 0;
-+}
-+
-+void __exit card_fxo_cleanup(void)
-+{
-+ xproto_unregister(&PROTO_TABLE(FXO));
-+}
-+
-+MODULE_DESCRIPTION("XPP FXO Card Driver");
-+MODULE_AUTHOR("Oron Peled <oron at actcom.co.il>");
-+MODULE_LICENSE("GPL");
-+MODULE_VERSION(ZAPTEL_VERSION);
-+MODULE_ALIAS_XPD(XPD_TYPE_FXO);
-+
-+module_init(card_fxo_startup);
-+module_exit(card_fxo_cleanup);
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/card_fxo.h zaptel-xpp-LJNBCn_dist/xpp/card_fxo.h
---- zaptel-1.2.6/xpp/card_fxo.h 1970-01-01 02:00:00.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/card_fxo.h 2006-07-02 17:17:18.812352000 +0300
-@@ -0,0 +1,61 @@
-+#ifndef CARD_FXO_H
-+#define CARD_FXO_H
-+/*
-+ * Written by Oron Peled <oron at actcom.co.il>
-+ * Copyright (C) 2004-2006, Xorcom
-+ *
-+ * All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ */
-+
-+#include "xpd.h"
-+#include "slic.h"
-+
-+enum fxo_opcodes {
-+ XPROTO_NAME(FXO, SIG_CHANGED) = 0x06,
-+/**/
-+ XPROTO_NAME(FXO, DAA_WRITE) = 0x0F, /* Write to DAA */
-+ XPROTO_NAME(FXO, CHAN_ENABLE) = 0x0F, /* Write to DAA */
-+ XPROTO_NAME(FXO, CHAN_CID) = 0x0F, /* Write to DAA */
-+ XPROTO_NAME(FXO, RING) = 0x0F, /* Write to DAA */
-+ XPROTO_NAME(FXO, SETHOOK) = 0x0F, /* Write to DAA */
-+ XPROTO_NAME(FXO, LED) = 0x0F, /* Write to DAA */
-+ XPROTO_NAME(FXO, RELAY_OUT) = 0x0F, /* Write to DAA */
-+ XPROTO_NAME(FXO, DAA_INIT) = 0x0F, /* Write to DAA */
-+ XPROTO_NAME(FXO, DAA_QUERY) = 0x0F, /* Write to DAA */
-+/**/
-+ XPROTO_NAME(FXO, DAA_REPLY) = 0x10,
-+};
-+
-+
-+DEF_RPACKET_DATA(FXO, SIG_CHANGED,
-+ byte type; /* unused -- we have it from DEV_DESC */
-+ xpp_line_t sig_status; /* channels: lsb=1, msb=8 */
-+ xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */
-+ );
-+DEF_RPACKET_DATA(FXO, DAA_REPLY, /* Get status of a single DAA (for debugging) */
-+ xpp_line_t lines;
-+ slic_reply_t info;
-+ );
-+DEF_RPACKET_DATA(FXO, DAA_WRITE,
-+ slic_cmd_t slic_cmd;
-+ );
-+
-+#define DAA_VBAT_REGISTER 29
-+#define BAT_THRESHOLD 3
-+
-+#endif /* CARD_FXO_H */
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/card_fxs.c zaptel-xpp-LJNBCn_dist/xpp/card_fxs.c
---- zaptel-1.2.6/xpp/card_fxs.c 2006-04-03 10:08:13.000000000 +0300
-+++ zaptel-xpp-LJNBCn_dist/xpp/card_fxs.c 2006-07-10 12:13:42.526183000 +0300
-@@ -1,6 +1,6 @@
- /*
- * Written by Oron Peled <oron at actcom.co.il>
-- * Copyright (C) 2004-2005, Xorcom
-+ * Copyright (C) 2004-2006, Xorcom
- *
- * All rights reserved.
- *
-@@ -23,65 +23,232 @@
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/fs.h>
-+#include <linux/delay.h>
-+#include <version.h> /* For zaptel version */
- #include "xpd.h"
- #include "xproto.h"
- #include "xpp_zap.h"
--#include <linux/delay.h>
-+#include "card_fxo.h"
-+#include "zap_debug.h"
-
--static const char rcsid[] = "$Id: card_fxs.c 995 2006-04-03 07:08:13Z tzafrir $";
--static const char revision[] = "$Revision: 995 $";
-+static const char rcsid[] = "$Id: card_fxs.c 1604 2006-07-10 09:13:42Z tzafrir $";
-
- DEF_PARM(int, print_dbg, 0, "Print DBG statements"); /* must be before zap_debug.h */
-+DEF_PARM(bool, poll_digital_inputs, 1, "Poll Digital Inputs"); /* must be before zap_debug.h */
-+
-+/* Signaling is opposite (fxo signalling for fxs card) */
-+#if 1
-+#define FXS_DEFAULT_SIGCAP (ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS)
-+#else
-+#define FXS_DEFAULT_SIGCAP (ZT_SIG_SF | ZT_SIG_EM)
-+#endif
-
- #define LINES_REGULAR 8
- #define LINES_DIGI_OUT 2
- #define LINES_DIGI_INP 4
-
--#define MASK_BITS(b) ((1U << (b)) - 1)
-+#define MASK_DIGI_OUT (BITMASK(LINES_DIGI_OUT) << LINES_REGULAR)
-+#define MASK_DIGI_INP (BITMASK(LINES_DIGI_INP) << (LINES_REGULAR + LINES_DIGI_OUT))
-+
-+enum fxs_leds {
-+ LED_GREEN,
-+ LED_RED,
-+ OUTPUT_RELAY,
-+};
-
--#define MASK_DIGI_OUT (MASK_BITS(LINES_DIGI_OUT) << LINES_REGULAR)
--#define MASK_DIGI_INP (MASK_BITS(LINES_DIGI_INP) << (LINES_REGULAR + LINES_DIGI_OUT))
-+#define NUM_LEDS 2
-+
-+static int SLIC_DIRECT_REQUEST(xbus_t *xbus, xpd_t *xpd, xpp_line_t lines, byte reg, byte dL)
-+{
-+ xpacket_t *pack;
-+ slic_cmd_t *sc;
-+ int len;
-+
-+ XPACKET_NEW(pack, xbus, FXS, SLIC_WRITE, xpd->id);
-+ sc = &RPACKET_FIELD(pack, FXS, SLIC_WRITE, slic_cmd);
-+ len = slic_cmd_direct_write(sc, lines, reg, dL);
-+ pack->datalen = len;
-+ packet_send(xbus, pack);
-+ return 0;
-+}
-
- /*---------------- FXS Protocol Commands ----------------------------------*/
-
--/* 0x0F */ DECLARE_CMD(FXS, CHAN_ENABLE, xpp_line_t lines, bool on);
--/* 0x0F */ DECLARE_CMD(FXS, CHAN_POWER, xpp_line_t lines, bool on);
--/* 0x0F */ DECLARE_CMD(FXS, CHAN_CID, xpp_line_t lines);
--/* 0x0F */ DECLARE_CMD(FXS, RING, int pos, bool on);
--/* 0x0F */ DECLARE_CMD(FXS, SETHOOK, xpp_line_t hook_status);
--/* 0x0F */ DECLARE_CMD(FXS, LED, xpp_line_t lines, byte which, bool on);
--/* 0x0F */ DECLARE_CMD(FXS, RELAY_OUT, byte which, bool on);
--/* 0x0F */ DECLARE_CMD(FXS, SLIC_INIT);
--/* 0x0F */ DECLARE_CMD(FXS, SLIC_QUERY, int pos, byte reg_num);
-+static /* 0x0F */ DECLARE_CMD(FXS, CHAN_ENABLE, xpp_line_t lines, bool on);
-+static /* 0x0F */ DECLARE_CMD(FXS, CHAN_CID, int pos);
-+static /* 0x0F */ DECLARE_CMD(FXS, RING, int pos, bool on);
-+static /* 0x0F */ DECLARE_CMD(FXS, SETHOOK, int pos, bool offhook);
-+static /* 0x0F */ DECLARE_CMD(FXS, RELAY_OUT, byte which, bool on);
-+static /* 0x0F */ DECLARE_CMD(FXS, SLIC_QUERY, int pos, byte reg_num);
-
- static bool fxs_packet_is_valid(xpacket_t *pack);
- static void fxs_packet_dump(xpacket_t *pack);
-+static int proc_fxs_info_read(char *page, char **start, off_t off, int count, int *eof, void *data);
- static int proc_xpd_slic_read(char *page, char **start, off_t off, int count, int *eof, void *data);
- static int proc_xpd_slic_write(struct file *file, const char __user *buffer, unsigned long count, void *data);
-
--#define S_(s,l,...) \
-- { \
-- .lines = s, \
-- { \
-- .len = l, \
-- .data = { __VA_ARGS__ }, \
-- } \
-- }
--struct slic_init_data {
-- xpp_line_t lines;
-- slic_data_t slic_data;
--} slic_init_data[] = {
--#include "slic_init.inc"
--};
--#undef S_
--
- #define PROC_SLIC_FNAME "slics"
-+#define PROC_FXS_INFO_FNAME "fxs_info"
-
- struct FXS_priv_data {
-- struct proc_dir_entry *xpd_slic;
-- slic_reply_t last_reply;
-+ struct proc_dir_entry *xpd_slic;
-+ struct proc_dir_entry *fxs_info;
-+ slic_reply_t requested_reply;
-+ slic_reply_t last_reply;
-+ xpp_line_t ledstate[NUM_LEDS]; /* 0 - OFF, 1 - ON */
-+ xpp_line_t ledcontrol[NUM_LEDS]; /* 0 - OFF, 1 - ON */
-+ int blinking[NUM_LEDS][CHANNELS_PERXPD];
- };
-
-+/*---------------- FXS: Static functions ----------------------------------*/
-+static int do_chan_power(xbus_t *xbus, xpd_t *xpd, xpp_line_t lines, bool on)
-+{
-+ int ret = 0;
-+ xpacket_t *pack;
-+ slic_cmd_t *sc;
-+ int len;
-+
-+ BUG_ON(!xbus);
-+ BUG_ON(!xpd);
-+ if(!lines) {
-+ return 0;
-+ }
-+ DBG("%s/%s: 0x%04X %s\n", xbus->busname, xpd->xpdname, lines, (on) ? "up" : "down");
-+ XPACKET_NEW(pack, xbus, FXS, SLIC_WRITE, xpd->id);
-+ sc = &RPACKET_FIELD(pack, FXS, SLIC_WRITE, slic_cmd);
-+ if(on) {
-+ // Power up
-+ len = slic_cmd_direct_write(sc, lines, 0x42, 0x06);
-+ } else {
-+ // Power down
-+ len = slic_cmd_direct_write(sc, lines, 0x42, 0x00);
-+ }
-+ pack->datalen = len;
-+
-+ packet_send(xbus, pack);
-+ return ret;
-+}
-+
-+#define IS_BLINKING(priv,pos,color) ((priv)->blinking[color][pos] != 0)
-+#define MARK_BLINK(priv,pos,color,val) ((priv)->blinking[color][pos] = (val))
-+#define MARK_LED(priv,pos,color,val) ((val)?BIT_SET((priv)->ledcontrol[color],(pos)):BIT_CLR((priv)->ledcontrol[color],(pos)))
-+
-+/*
-+ * LED and RELAY control is done via SLIC register 0x06:
-+ * 7 6 5 4 3 2 1 0
-+ * +-----+-----+-----+-----+-----+-----+-----+-----+
-+ * | M2 | M1 | M3 | C2 | O1 | O3 | C1 | C3 |
-+ * +-----+-----+-----+-----+-----+-----+-----+-----+
-+ *
-+ * Cn - Control bit (control one digital line)
-+ * On - Output bit (program a digital line for output)
-+ * Mn - Mask bit (only the matching output control bit is affected)
-+ *
-+ * C3 - OUTPUT RELAY (0 - OFF, 1 - ON)
-+ * C1 - GREEN LED (0 - OFF, 1 - ON)
-+ * O3 - Output RELAY (this line is output)
-+ * O1 - Output GREEN (this line is output)
-+ * C2 - RED LED (0 - OFF, 1 - ON)
-+ * M3 - Mask RELAY. (1 - C3 effect the OUTPUT RELAY)
-+ * M2 - Mask RED. (1 - C2 effect the RED LED)
-+ * M1 - Mask GREEN. (1 - C1 effect the GREEN LED)
-+ *
-+ * The OUTPUT RELAY (actually a relay out) is connected to line 0 and 4 only.
-+ */
-+
-+// GREEN RED OUTPUT RELAY
-+static const int led_register_mask[] = { BIT(7), BIT(6), BIT(5) };
-+static const int led_register_vals[] = { BIT(4), BIT(1), BIT(0) };
-+
-+/*
-+ * pos can be:
-+ * - A line number
-+ * - ALL_LINES
-+ */
-+static int do_led(xpd_t *xpd, lineno_t pos, byte which, bool on)
-+{
-+ int ret = 0;
-+ xpacket_t *pack;
-+ slic_cmd_t *sc;
-+ int len;
-+ int value;
-+ struct FXS_priv_data *priv;
-+ xpp_line_t lines;
-+ xbus_t *xbus;
-+
-+ BUG_ON(!xpd);
-+ xbus = xpd->xbus;
-+ priv = xpd->priv;
-+ which = which % NUM_LEDS;
-+ if(IS_SET(xpd->digital_outputs, pos) || IS_SET(xpd->digital_inputs, pos))
-+ goto out;
-+ if(pos == ALL_LINES) {
-+ lines = ~0;
-+ priv->ledstate[which] = (on) ? ~0 : 0;
-+ } else {
-+ lines = BIT(pos);
-+ if(on) {
-+ BIT_SET(priv->ledstate[which], pos);
-+ } else {
-+ BIT_CLR(priv->ledstate[which], pos);
-+ }
-+ }
-+ if(!lines) // Nothing to do
-+ goto out;
-+ DBG("%s/%s: LED: lines=0x%04X which=%d -- %s\n", xbus->busname, xpd->xpdname, lines, which, (on) ? "on" : "off");
-+ value = BIT(2) | BIT(3);
-+ value |= ((BIT(5) | BIT(6) | BIT(7)) & ~led_register_mask[which]);
-+ if(on)
-+ value |= led_register_vals[which];
-+ XPACKET_NEW(pack, xbus, FXS, SLIC_WRITE, xpd->id);
-+ sc = &RPACKET_FIELD(pack, FXS, SLIC_WRITE, slic_cmd);
-+ len = slic_cmd_direct_write(sc, lines, 0x06, value);
-+ pack->datalen = len;
-+ packet_send(xbus, pack);
-+
-+out:
-+ return ret;
-+}
-+
-+static void handle_fxs_leds(xpd_t *xpd)
-+{
-+ int i;
-+ unsigned long flags;
-+ const enum fxs_leds colors[] = { LED_GREEN, LED_RED };
-+ int color;
-+ unsigned int timer_count;
-+ struct FXS_priv_data *priv;
-+
-+ BUG_ON(!xpd);
-+ spin_lock_irqsave(&xpd->lock, flags);
-+ priv = xpd->priv;
-+ timer_count = xpd->timer_count;
-+ for(color = 0; color < ARRAY_SIZE(colors); color++) {
-+ for_each_line(xpd, i) {
-+ if(IS_SET(xpd->digital_outputs, i) || IS_SET(xpd->digital_inputs, i))
-+ continue;
-+ if(IS_BLINKING(priv, i, color)) { // Blinking
-+ // led state is toggled
-+ if((timer_count % LED_BLINK_PERIOD) == 0) {
-+ DBG("%s/%s/%d ledstate=%s\n", xpd->xbus->busname, xpd->xpdname, i,
-+ (IS_SET(priv->ledstate[color], i))?"ON":"OFF");
-+ if(!IS_SET(priv->ledstate[color], i)) {
-+ do_led(xpd, i, color, 1);
-+ } else {
-+ do_led(xpd, i, color, 0);
-+ }
-+ }
-+ } else if(IS_SET(priv->ledcontrol[color], i) && !IS_SET(priv->ledstate[color], i)) {
-+ do_led(xpd, i, color, 1);
-+ } else if(!IS_SET(priv->ledcontrol[color], i) && IS_SET(priv->ledstate[color], i)) {
-+ do_led(xpd, i, color, 0);
-+ }
-+
-+ }
-+ }
-+ spin_unlock_irqrestore(&xpd->lock, flags);
-+}
-+
- /*---------------- FXS: Methods -------------------------------------------*/
-
- static xpd_t *FXS_card_new(xbus_t *xbus, int xpd_num, const xproto_table_t *proto_table, byte revision)
-@@ -100,29 +267,82 @@
- xpd->digital_inputs = MASK_DIGI_INP;
- }
- xpd->direction = TO_PHONE;
-+ xpd->revision = revision;
- return xpd;
- }
-
-+static void clean_proc(xbus_t *xbus, xpd_t *xpd)
-+{
-+ struct FXS_priv_data *priv;
-+
-+ BUG_ON(!xpd);
-+ priv = xpd->priv;
-+#ifdef CONFIG_PROC_FS
-+ if(priv->xpd_slic) {
-+ DBG("Removing xpd SLIC file %s/%s\n", xbus->busname, xpd->xpdname);
-+ priv->xpd_slic->data = NULL;
-+ remove_proc_entry(PROC_SLIC_FNAME, xpd->proc_xpd_dir);
-+ }
-+ if(priv->fxs_info) {
-+ DBG("Removing xpd FXS_INFO file %s/%s\n", xbus->busname, xpd->xpdname);
-+ remove_proc_entry(PROC_FXS_INFO_FNAME, xpd->proc_xpd_dir);
-+ }
-+#endif
-+}
-+
- static int FXS_card_init(xbus_t *xbus, xpd_t *xpd)
- {
- struct FXS_priv_data *priv;
-+ int ret = 0;
-
- BUG_ON(!xpd);
- priv = xpd->priv;
-- CALL_PROTO(FXS, SLIC_INIT, xbus, xpd);
- #ifdef CONFIG_PROC_FS
-+ DBG("Creating FXS_INFO file for %s/%s\n", xbus->busname, xpd->xpdname);
-+ priv->fxs_info = create_proc_read_entry(PROC_FXS_INFO_FNAME, 0444, xpd->proc_xpd_dir, proc_fxs_info_read, xpd);
-+ if(!priv->fxs_info) {
-+ ERR("Failed to create proc '%s' for %s/%s\n", PROC_FXS_INFO_FNAME, xbus->busname, xpd->xpdname);
-+ ret = -ENOENT;
-+ goto err;
-+ }
-+ priv->fxs_info->owner = THIS_MODULE;
- DBG("Creating SLICs file for %s/%s\n", xbus->busname, xpd->xpdname);
- priv->xpd_slic = create_proc_entry(PROC_SLIC_FNAME, 0644, xpd->proc_xpd_dir);
- if(!priv->xpd_slic) {
- ERR("Failed to create proc file for SLICs of %s/%s\n", xbus->busname, xpd->xpdname);
-- goto out;
-+ ret = -ENOENT;
-+ goto err;
- }
-+ priv->xpd_slic->owner = THIS_MODULE;
- priv->xpd_slic->write_proc = proc_xpd_slic_write;
- priv->xpd_slic->read_proc = proc_xpd_slic_read;
- priv->xpd_slic->data = xpd;
--out:
- #endif
-+ ret = run_initialize_registers(xpd);
-+ if(ret < 0)
-+ goto err;
-+ /*
-+ * Setup ring timers
-+ */
-+#ifdef WITH_RBS
-+ /* Software controled ringing (for CID) */
-+ ret = SLIC_DIRECT_REQUEST(xbus, xpd, ALL_LINES, 0x22, 0x00); /* Ringing Oscilator Control */
-+#else
-+ /* Hardware controled ringing (no CID) */
-+ ret += SLIC_DIRECT_REQUEST(xbus, xpd, ALL_LINES, 0x30, 0x80); /* Active timer low byte */
-+ ret += SLIC_DIRECT_REQUEST(xbus, xpd, ALL_LINES, 0x31, 0x3E); /* Active timer high byte */
-+ ret += SLIC_DIRECT_REQUEST(xbus, xpd, ALL_LINES, 0x32, 0x80); /* Inactive timer low byte */
-+ ret += SLIC_DIRECT_REQUEST(xbus, xpd, ALL_LINES, 0x33, 0x3E); /* Inactive timer high byte */
-+ ret += SLIC_DIRECT_REQUEST(xbus, xpd, ALL_LINES, 0x22, 0x18); /* Ringing Oscilator Control */
-+#endif
-+ if(ret < 0)
-+ goto err;
-+ DBG("%s/%s: done\n", xbus->busname, xpd->xpdname);
- return 0;
-+err:
-+ clean_proc(xbus, xpd);
-+ ERR("%s/%s: Failed initializing registers (%d)\n", xbus->busname, xpd->xpdname, ret);
-+ return ret;
- }
-
- static int FXS_card_remove(xbus_t *xbus, xpd_t *xpd)
-@@ -132,15 +352,210 @@
- BUG_ON(!xpd);
- priv = xpd->priv;
- DBG("%s/%s\n", xbus->busname, xpd->xpdname);
--#ifdef CONFIG_PROC_FS
-- if(priv->xpd_slic) {
-- DBG("Removing xpd SLIC file %s/%s\n", xbus->busname, xpd->xpdname);
-- remove_proc_entry(PROC_SLIC_FNAME, xpd->proc_xpd_dir);
-+ clean_proc(xbus, xpd);
-+ return 0;
-+}
-+
-+static int FXS_card_zaptel_preregistration(xpd_t *xpd, bool on)
-+{
-+ xbus_t *xbus;
-+ struct FXS_priv_data *priv;
-+ int i;
-+ unsigned long flags;
-+ const enum fxs_leds color = (on) ? LED_GREEN : LED_RED;
-+
-+ BUG_ON(!xpd);
-+ xbus = xpd->xbus;
-+ BUG_ON(!xbus);
-+ priv = xpd->priv;
-+ BUG_ON(!priv);
-+ DBG("%s/%s (%d)\n", xbus->busname, xpd->xpdname, on);
-+ snprintf(xpd->span.desc, MAX_SPANDESC, "Xorcom XPD #%d/%d: FXS", xbus->num, xpd->id);
-+ for_each_line(xpd, i) {
-+ struct zt_chan *cur_chan = &xpd->chans[i];
-+
-+ DBG("setting FXS channel %d\n", i);
-+ if(IS_SET(xpd->digital_outputs, i)) {
-+ snprintf(cur_chan->name, MAX_CHANNAME, "XPP_OUT/%d/%d/%d", xbus->num, xpd->id, i);
-+ } else if(IS_SET(xpd->digital_inputs, i)) {
-+ snprintf(cur_chan->name, MAX_CHANNAME, "XPP_IN/%d/%d/%d", xbus->num, xpd->id, i);
-+ } else {
-+ snprintf(cur_chan->name, MAX_CHANNAME, "XPP_FXS/%d/%d/%d", xbus->num, xpd->id, i);
-+ }
-+ cur_chan->chanpos = i + 1;
-+ cur_chan->pvt = xpd;
-+ cur_chan->sigcap = FXS_DEFAULT_SIGCAP;
-+ }
-+ spin_lock_irqsave(&xpd->lock, flags);
-+ do_led(xpd, ALL_LINES, color, LED_OFF);
-+ spin_unlock_irqrestore(&xpd->lock, flags);
-+ for_each_line(xpd, i) {
-+ MARK_LED(priv, i, color, LED_ON);
-+ mdelay(50);
- }
--#endif
- return 0;
- }
-
-+static int FXS_card_zaptel_postregistration(xpd_t *xpd, bool on)
-+{
-+ xbus_t *xbus;
-+ struct FXS_priv_data *priv;
-+ int i;
-+ const enum fxs_leds color = (on) ? LED_GREEN : LED_RED;
-+
-+ BUG_ON(!xpd);
-+ xbus = xpd->xbus;
-+ BUG_ON(!xbus);
-+ priv = xpd->priv;
-+ BUG_ON(!priv);
-+ DBG("%s/%s (%d)\n", xbus->busname, xpd->xpdname, on);
-+ for_each_line(xpd, i) {
-+ MARK_LED(priv, i, color, LED_OFF);
-+ mdelay(50);
-+ }
-+ return 0;
-+}
-+
-+#ifdef WITH_RBS
-+int FXS_card_hooksig(xbus_t *xbus, xpd_t *xpd, int pos, zt_txsig_t txsig)
-+{
-+ int ret = 0;
-+
-+ DBG("%s/%s/%d: %s\n", xbus->busname, xpd->xpdname, pos, txsig2str(txsig));
-+ BUG_ON(xpd->direction != TO_PHONE);
-+ if (IS_SET(xpd->digital_inputs, pos)) {
-+ DBG("Ignoring signal sent to digital input line\n");
-+ return 0;
-+ }
-+ switch(txsig) {
-+ case ZT_TXSIG_ONHOOK:
-+ xpd->ringing[pos] = 0;
-+ BIT_CLR(xpd->cid_on, pos);
-+ if(IS_SET(xpd->digital_outputs, pos)) {
-+ DBG("%s/%s/%d: digital output OFF\n", xbus->busname, xpd->xpdname, pos);
-+ ret = CALL_XMETHOD(RELAY_OUT, xpd->xbus, xpd, pos-8, 0);
-+ return ret;
-+ }
-+ ret = CALL_XMETHOD(RING, xbus, xpd, pos, 0); // RING off
-+#if 0
-+ switch(chan->sig) {
-+ case ZT_SIG_EM:
-+ case ZT_SIG_FXOKS:
-+ case ZT_SIG_FXOLS:
-+ xpd->lasttxhook[pos] = xpd->idletxhookstate[pos];
-+ break;
-+ case ZT_SIG_FXOGS:
-+ xpd->lasttxhook[pos] = FXS_LINE_TIPOPEN;
-+ break;
-+ }
-+#endif
-+ break;
-+ case ZT_TXSIG_OFFHOOK:
-+ if(xpd->ringing[pos]) {
-+ BIT_SET(xpd->cid_on, pos);
-+ ret = CALL_XMETHOD(CHAN_CID, xpd->xbus, xpd, pos); // CALLER ID
-+ }
-+ xpd->ringing[pos] = 0;
-+#if 0
-+ switch(chan->sig) {
-+ case ZT_SIG_EM:
-+ xpd->lasttxhook[pos] = FXS_LINE_REV_ACTIVE;
-+ break;
-+ default:
-+ xpd->lasttxhook[pos] = xpd->idletxhookstate[pos];
-+ break;
-+ }
-+#endif
-+ break;
-+ case ZT_TXSIG_START:
-+ xpd->lasttxhook[pos] = FXS_LINE_RING;
-+ xpd->ringing[pos] = 1;
-+ BIT_CLR(xpd->cid_on, pos);
-+ if(IS_SET(xpd->digital_outputs, pos)) {
-+ DBG("%s/%s/%d: %s digital output ON\n", xbus->busname, xpd->xpdname, pos, txsig2str(txsig));
-+ ret = CALL_XMETHOD(RELAY_OUT, xpd->xbus, xpd, pos-8, 1);
-+ return ret;
-+ }
-+ ret = CALL_XMETHOD(RING, xbus, xpd, pos, 1); // RING on
-+ break;
-+ case ZT_TXSIG_KEWL:
-+ xpd->lasttxhook[pos] = FXS_LINE_DISABLED;
-+ break;
-+ default:
-+ NOTICE("%s: Can't set tx state to %s (%d)\n", __FUNCTION__, txsig2str(txsig), txsig);
-+ ret = -EINVAL;
-+ }
-+ return ret;
-+}
-+
-+#else
-+int FXS_card_sethook(xbus_t *xbus, xpd_t *xpd, int pos, int hookstate)
-+{
-+ int ret = 0;
-+
-+ DBG("%s/%s/%d: %s\n", xbus->busname, xpd->xpdname, pos, hookstate2str(hookstate));
-+ switch(hookstate) {
-+ /* On-hook, off-hook: The PBX is playing a phone on an FXO line.
-+ * Can be ignored for an FXS line
-+ */
-+ case ZT_ONHOOK:
-+ if(IS_SET(xpd->digital_inputs, pos)) {
-+ NOTICE("%s: Trying to ONHOOK a digital input channel %d. Ignoring\n", __FUNCTION__, pos);
-+ ret = -EINVAL;
-+ break;
-+ }
-+ if(IS_SET(xpd->digital_outputs, pos)) {
-+ DBG("%s/%s/%d: digital output OFF\n", xbus->busname, xpd->xpdname, pos);
-+ ret = CALL_XMETHOD(RELAY_OUT, xpd->xbus, xpd, pos-8, 0);
-+ break;
-+ }
-+ xpd->ringing[pos] = 0;
-+ DBG("%s/%s/%d: stop ringing\n", xbus->busname, xpd->xpdname, pos);
-+#if 1 // FIXME: Not needed -- verify
-+ ret = CALL_XMETHOD(RING, xbus, xpd, pos, 0); // RING off
-+#endif
-+ if(ret) {
-+ DBG("ZT_ONHOOK(stop ring) Failed: ret=0x%02X\n", ret);
-+ break;
-+ }
-+ break;
-+ case ZT_START:
-+ DBG("%s/%s/%d: fall through ZT_OFFHOOK\n", xbus->busname, xpd->xpdname, pos);
-+ // Fall through
-+ case ZT_OFFHOOK:
-+ DBG("%s/%s/%d: ZT_OFFHOOK (ignoring for PHONES)\n", xbus->busname, xpd->xpdname, pos);
-+ break;
-+ case ZT_WINK:
-+ WARN("No code yet\n");
-+ break;
-+ case ZT_FLASH:
-+ WARN("No code yet\n");
-+ break;
-+ case ZT_RING:
-+ DBG("%s/%s/%d: ZT_RING: %d\n", xbus->busname, xpd->xpdname, pos, xpd->ringing[pos]);
-+ if(IS_SET(xpd->digital_inputs, pos)) {
-+ NOTICE("%s: Trying to RING a digital input channel %d. Ignoring\n", __FUNCTION__, pos);
-+ return -EINVAL;
-+ }
-+ if(IS_SET(xpd->digital_outputs, pos)) {
-+ DBG("%s/%s/%d: digital output ON\n", xbus->busname, xpd->xpdname, pos);
-+ ret = CALL_XMETHOD(RELAY_OUT, xpd->xbus, xpd, pos-8, 1);
-+ return ret;
-+ }
-+ xpd->ringing[pos] = 1;
-+ ret = CALL_XMETHOD(RING, xbus, xpd, pos, 1); // RING on
-+ if(ret) {
-+ DBG("ZT_RING Failed: ret=0x%02X\n", ret);
-+ }
-+ break;
-+ case ZT_RINGOFF:
-+ WARN("No code yet\n");
-+ break;
-+ }
-+ return ret;
-+}
-+#endif
-+
- /*
- * INPUT polling is done via SLIC register 0x06 (same as LEDS):
- * 7 6 5 4 3 2 1 0
-@@ -155,6 +570,7 @@
- {
- int i;
-
-+ BUG_ON(xpd->id != 0); // Only unit #0 has digital inputs
- for(i = 0; i < ARRAY_SIZE(input_channels); i++) {
- int pos = input_channels[i];
-
-@@ -164,177 +580,129 @@
-
- static int FXS_card_tick(xbus_t *xbus, xpd_t *xpd)
- {
-- static int rate_limit = 0;
-+ static int rate_limit = 0;
-+ struct FXS_priv_data *priv;
-
-- if((rate_limit++ % 1000) == 0) {
-- poll_inputs(xbus, xpd);
-+ BUG_ON(!xpd);
-+ priv = xpd->priv;
-+ BUG_ON(!priv);
-+#if POLL_DIGITAL_INPUTS
-+ if(poll_digital_inputs && xpd->id == 0) {
-+ if((rate_limit++ % 1000) == 0) {
-+ poll_inputs(xbus, xpd);
-+ }
- }
-+#endif
-+ handle_fxs_leds(xpd);
- return 0;
- }
-
- /*---------------- FXS: HOST COMMANDS -------------------------------------*/
-
--/* 0x0F */ HOSTCMD(FXS, CHAN_ENABLE, xpp_line_t lines, bool on)
-+static /* 0x0F */ HOSTCMD(FXS, CHAN_ENABLE, xpp_line_t lines, bool on)
- {
- int ret = 0;
- xpacket_t *pack;
- slic_cmd_t *sc;
- int len;
-+ enum fxs_state value = (on) ? 0x01 : 0x00;
-+ unsigned long flags;
-+ int i;
-
- BUG_ON(!xbus);
- BUG_ON(!xpd);
-- lines &= xpd->enabled_chans; // Ignore disabled channels
- if(!lines) {
- return 0;
- }
- DBG("Channel Activation: 0x%4X %s\n", lines, (on) ? "on" : "off");
-+ // Make sure we use normal (low battery) power
-+ for_each_line(xpd, i)
-+ if (BIT_SET(lines,i))
-+ do_chan_power(xbus, xpd, BIT(i), 0);
- XPACKET_NEW(pack, xbus, FXS, SLIC_WRITE, xpd->id);
- sc = &RPACKET_FIELD(pack, FXS, SLIC_WRITE, slic_cmd);
-- len = slic_cmd_direct_write(sc, lines, 0x40, (on)?0x01:0x00);
-+ len = slic_cmd_direct_write(sc, lines, 0x40, value);
- pack->datalen = len;
-+ for_each_line(xpd, i)
-+ xpd->lasttxhook[i] = value;
-
- packet_send(xbus, pack);
-- return ret;
--}
--
--/* 0x0F */ HOSTCMD(FXS, CHAN_POWER, xpp_line_t lines, bool on)
--{
-- int ret = 0;
-- xpacket_t *pack;
-- slic_cmd_t *sc;
-- int len;
--
-- BUG_ON(!xbus);
-- BUG_ON(!xpd);
-- lines &= xpd->enabled_chans; // Ignore disabled channels
-- if(!lines) {
-- return 0;
-- }
-- DBG("Channel Power: 0x%04X %s\n", lines, (on) ? "up" : "down");
-- XPACKET_NEW(pack, xbus, FXS, SLIC_WRITE, xpd->id);
-- sc = &RPACKET_FIELD(pack, FXS, SLIC_WRITE, slic_cmd);
-+ spin_lock_irqsave(&xpd->lock, flags);
- if(on) {
-- // Power up
-- len = slic_cmd_direct_write(sc, lines, 0x42, 0x06);
-+ do_led(xpd, ALL_LINES, LED_GREEN, LED_ON);
- } else {
-- // Power down
-- len = slic_cmd_direct_write(sc, lines, 0x42, 0x00);
-+ do_led(xpd, ALL_LINES, LED_GREEN, LED_OFF);
- }
-- pack->datalen = len;
--
-- packet_send(xbus, pack);
-+ spin_unlock_irqrestore(&xpd->lock, flags);
- return ret;
- }
-
--/* 0x0F */ HOSTCMD(FXS, CHAN_CID, xpp_line_t lines)
-+static /* 0x0F */ HOSTCMD(FXS, CHAN_CID, int pos)
- {
- int ret = 0;
- xpacket_t *pack;
- slic_cmd_t *sc;
-+ int i;
-+ xpp_line_t lines = BIT(pos);
-
- BUG_ON(!xbus);
- BUG_ON(!xpd);
-- lines &= xpd->enabled_chans; // Ignore disabled channels
- if(!lines) {
- return 0;
- }
-- DBG("Channel CID: 0x%04X\n", lines);
-+ DBG("%s/%s/%d:\n", xbus->busname, xpd->xpdname, pos);
-+ //do_chan_power(xbus, xpd, BIT(pos), 0); // Low battery for normal (non-ring) operation
- XPACKET_NEW(pack, xbus, FXS, SLIC_WRITE, xpd->id);
- sc = &RPACKET_FIELD(pack, FXS, SLIC_WRITE, slic_cmd);
-- pack->datalen = slic_cmd_direct_write(sc, lines, 0x40, 0x02);
-+ pack->datalen = slic_cmd_direct_write(sc, lines, 0x40, FXS_LINE_CID);
- packet_send(xbus, pack);
-+ for_each_line(xpd, i)
-+ xpd->lasttxhook[i] = FXS_LINE_CID;
- return ret;
- }
-
-
--/* 0x0F */ HOSTCMD(FXS, RING, int pos, bool on)
-+static /* 0x0F */ HOSTCMD(FXS, RING, int pos, bool on)
- {
- int ret = 0;
-+ struct FXS_priv_data *priv;
- xpacket_t *pack;
- slic_cmd_t *sc;
-- xpp_line_t mask = (1 << pos);
-+ xpp_line_t mask = BIT(pos);
- int len;
-+ enum fxs_state value = (on) ? 0x04 : 0x01;
-
- BUG_ON(!xbus);
- BUG_ON(!xpd);
-- mask &= xpd->enabled_chans; // Ignore disabled channels
-+ priv = xpd->priv;
- if(!mask) {
- return 0;
- }
-- DBG("%s pos=%d %s\n", xpd->xpdname, pos, (on) ? "on" : "off");
-+ DBG("%s/%s/%d %s\n", xbus->busname, xpd->xpdname, pos, (on) ? "on" : "off");
-+ do_chan_power(xbus, xpd, BIT(pos), on); // Power up (for ring)
- XPACKET_NEW(pack, xbus, FXS, SLIC_WRITE, xpd->id);
- sc = &RPACKET_FIELD(pack, FXS, SLIC_WRITE, slic_cmd);
-- len = slic_cmd_direct_write(sc, mask, 0x40, (on)?0x04:0x01);
-+ len = slic_cmd_direct_write(sc, mask, 0x40, value);
-+ xpd->lasttxhook[pos] = value;
- pack->datalen = len;
-
- packet_send(xbus, pack);
-+ if(on) {
-+ MARK_BLINK(priv,pos,LED_GREEN,LED_BLINK);
-+ } else {
-+ if(IS_BLINKING(priv, pos, LED_GREEN))
-+ MARK_BLINK(priv,pos,LED_GREEN,0);
-+ }
- return ret;
- }
-
--/* 0x0F */ HOSTCMD(FXS, SETHOOK, xpp_line_t hook_status)
-+static /* 0x0F */ HOSTCMD(FXS, SETHOOK, int pos, bool offhook)
- {
-- DBG("\n");
-+ BUG(); // Should never be called
- return 0;
- }
-
--/*
-- * LED control is done via SLIC register 0x06:
-- * 7 6 5 4 3 2 1 0
-- * +-----+-----+-----+-----+-----+-----+-----+-----+
-- * | MR | MG | MB | R | OG | OB | G | B |
-- * +-----+-----+-----+-----+-----+-----+-----+-----+
-- *
-- * B - BLUE LED (0 - OFF, 1 - ON)
-- * G - GREEN LED (0 - OFF, 1 - ON)
-- * OB - Output BLUE (this line is output)
-- * OG - Output GREEN (this line is output)
-- * R - RED LED (0 - OFF, 1 - ON)
-- * MB - Mask BLUE. (1 - B effect the BLUE LED)
-- * MR - Mask RED. (1 - R effect the RED LED)
-- * MG - Mask GREEN. (1 - G effect the GREEN LED)
-- *
-- * The BLUE LED (actually a relay out) is connected to line 0 and 4 only.
-- */
--
--// GREEN RED BLUE
--static const int led_mask[NUM_LEDS] = { BIT(7), BIT(6), BIT(5) };
--static const int led_vals[NUM_LEDS] = { BIT(4), BIT(1), BIT(0) };
--
--/* 0x0F */ HOSTCMD(FXS, LED, xpp_line_t lines, byte which, bool on)
--{
-- int ret = 0;
-- xpacket_t *pack;
-- slic_cmd_t *sc;
-- int len;
-- int value;
-- int i;
--
-- BUG_ON(!xbus);
-- BUG_ON(!xpd);
-- lines &= xpd->enabled_chans; // Ignore disabled channels
-- if(!lines) {
-- return 0;
-- }
-- DBG("LED: lines=0x%04X which=%d -- %s\n", lines, which, (on) ? "on" : "off");
-- which = which % NUM_LEDS;
-- value = BIT(2) | BIT(3);
-- value |= ((BIT(5) | BIT(6) | BIT(7)) & ~led_mask[which]);
-- if(on)
-- value |= led_vals[which];
-- for(i = 0; i < CHANNELS_PERXPD; i++) {
-- if(!IS_SET(lines, i))
-- continue;
-- XPACKET_NEW(pack, xbus, FXS, SLIC_WRITE, xpd->id);
-- sc = &RPACKET_FIELD(pack, FXS, SLIC_WRITE, slic_cmd);
-- len = slic_cmd_direct_write(sc, lines, 0x06, value);
-- DBG("LED pack: line=%d value=0x%04X\n", i, value);
-- pack->datalen = len;
-- packet_send(xbus, pack);
-- }
-- return ret;
--}
--
--/* 0x0F */ HOSTCMD(FXS, RELAY_OUT, byte which, bool on)
-+static /* 0x0F */ HOSTCMD(FXS, RELAY_OUT, byte which, bool on)
- {
- int ret = 0;
- xpacket_t *pack;
-@@ -351,9 +719,9 @@
- which = which % ARRAY_SIZE(relay_channels);
- lines = BIT(relay_channels[which]);
- value = BIT(2) | BIT(3);
-- value |= ((BIT(5) | BIT(6) | BIT(7)) & ~led_mask[LED_BLUE]);
-+ value |= ((BIT(5) | BIT(6) | BIT(7)) & ~led_register_mask[OUTPUT_RELAY]);
- if(on)
-- value |= led_vals[LED_BLUE];
-+ value |= led_register_vals[OUTPUT_RELAY];
- XPACKET_NEW(pack, xbus, FXS, SLIC_WRITE, xpd->id);
- sc = &RPACKET_FIELD(pack, FXS, SLIC_WRITE, slic_cmd);
- len = slic_cmd_direct_write(sc, lines, 0x06, value);
-@@ -364,34 +732,7 @@
- return ret;
- }
-
--/* 0x0F */ HOSTCMD(FXS, SLIC_INIT)
--{
-- int ret = 0;
-- xpacket_t *pack;
-- slic_data_t *slic;
-- struct slic_init_data *source;
-- int i;
--
-- BUG_ON(!xbus);
-- BUG_ON(!xpd);
-- DBG("INITIALIZING SLIC\n");
-- for(i = 0; i < ARRAY_SIZE(slic_init_data); i++) {
-- source = &slic_init_data[i];
-- XPACKET_NEW(pack, xbus, FXS, SLIC_INIT, xpd->id);
-- RPACKET_FIELD(pack, FXS, SLIC_INIT, lines) = source->lines;
--
-- slic = &RPACKET_FIELD(pack, FXS, SLIC_INIT, slic_data);
-- slic->len = source->slic_data.len;
-- memcpy(slic->data, source->slic_data.data, source->slic_data.len);
-- pack->datalen = sizeof(xpp_line_t) + slic->len + 1;
--// dump_packet("SLIC", pack, print_dbg);
-- packet_send(xbus, pack);
-- mdelay(10); // FIXME: check with Dima
-- }
-- return ret;
--}
--
--/* 0x0F */ HOSTCMD(FXS, SLIC_QUERY, int pos, byte reg_num)
-+static /* 0x0F */ HOSTCMD(FXS, SLIC_QUERY, int pos, byte reg_num)
- {
- int ret = 0;
- xpacket_t *pack;
-@@ -400,7 +741,7 @@
-
- BUG_ON(!xbus);
- BUG_ON(!xpd);
-- DBG("\n");
-+ // DBG("\n");
- XPACKET_NEW(pack, xbus, FXS, SLIC_WRITE, xpd->id);
- sc = &RPACKET_FIELD(pack, FXS, SLIC_WRITE, slic_cmd);
- len = slic_cmd_direct_read(sc, BIT(pos), reg_num);
-@@ -416,31 +757,39 @@
- HANDLER_DEF(FXS, SIG_CHANGED)
- {
- xpp_line_t sig_status = RPACKET_FIELD(pack, FXS, SIG_CHANGED, sig_status);
-+ xpp_line_t sig_toggles = RPACKET_FIELD(pack, FXS, SIG_CHANGED, sig_toggles);
-+ struct FXS_priv_data *priv;
-+ int i;
-
-- if(!xpd) {
-- NOTICE("%s: received %s for non-existing xpd: %d\n",
-- __FUNCTION__, cmd->name, XPD_NUM(pack->content.addr));
-- return -EPROTO;
-- }
-- if(xpd->direction == TO_PHONE) { /* Hook state changes */
-- DBG("%s (PHONE) sig_status=0x%04X\n", xpd->xpdname, sig_status);
-- xpp_check_hookstate(xpd, sig_status);
-- } else { /* TO_PSTN - line ring changes */
-- unsigned long flags;
-- int i;
--
-- DBG("%s (PSTN) sig_status=0x%04X\n", xpd->xpdname, sig_status);
-- spin_lock_irqsave(&xpd->lock, flags);
-- for(i = 0; i < xpd->channels; i++) {
-+ BUG_ON(!xpd);
-+ BUG_ON(xpd->direction != TO_PHONE);
-+ priv = xpd->priv;
-+ DBG("%s/%s: (PHONE) sig_toggles=0x%04X sig_status=0x%04X\n", xbus->busname, xpd->xpdname, sig_toggles, sig_status);
-+ if(!SPAN_REGISTERED(xpd)) {
-+ NOTICE("%s: %s/%s is not registered. Skipping.\n", __FUNCTION__, xbus->busname, xpd->xpdname);
-+ return -ENODEV;
-+ }
-+ for_each_line(xpd, i) {
-+ if(IS_SET(xpd->digital_outputs, i) || IS_SET(xpd->digital_inputs, i))
-+ continue;
-+ if(IS_SET(sig_toggles, i)) {
-+ struct zt_chan *chan = &xpd->span.chans[i];
-+
-+ xpd->ringing[i] = 0; // No more ringing...
-+ do_chan_power(xpd->xbus, xpd, BIT(i), 0); // When not ringing, VBAT is always Low
-+ MARK_BLINK(priv,i,LED_GREEN,0);
- if(IS_SET(sig_status, i)) {
-- xpd->ringing[i] = RINGS_NUM*2;
-- zt_hooksig(&xpd->chans[i], ZT_RXSIG_OFFHOOK);
-+ DBG("OFFHOOK: channo=%d\n", chan->channo);
-+ MARK_LED(priv,i,LED_GREEN,LED_ON);
-+ BIT_SET(xpd->hookstate, i);
-+ zt_hooksig(chan, ZT_RXSIG_OFFHOOK);
- } else {
-- zt_hooksig(&xpd->chans[i], ZT_RXSIG_ONHOOK);
-- xpd->ringing[i] = 0;
-+ DBG("ONHOOK channo=%d\n", chan->channo);
-+ MARK_LED(priv,i,LED_GREEN,LED_OFF);
-+ BIT_CLR(xpd->hookstate, i);
-+ zt_hooksig(chan, ZT_RXSIG_ONHOOK);
- }
- }
-- spin_unlock_irqrestore(&xpd->lock, flags);
- }
- return 0;
- }
-@@ -460,52 +809,75 @@
- spin_lock_irqsave(&xpd->lock, flags);
- priv = xpd->priv;
- BUG_ON(!priv);
-+#if 0
- DBG("SLIC_REPLY: xpd #%d %s reg_num=0x%X, dataL=0x%X dataH=0x%X\n",
- xpd->id, (info->indirect)?"I":"D",
- info->reg_num, info->data_low, info->data_high);
-- priv->last_reply = *info;
-+#endif
- if(xpd->id == 0 && info->indirect == 0 && info->reg_num == 0x06) { /* Digital Inputs Poll Result */
- int i;
- bool offhook = (info->data_low & 0x1) == 0;
-
- /* Map SLIC number into line number */
- for(i = 0; i < ARRAY_SIZE(input_channels); i++) {
-- int channo = input_channels[i];
-- int newchanno;
-+ int channo = input_channels[i];
-+ int newchanno;
-+ struct zt_chan *chan;
-
- if(IS_SET(lines, channo)) {
- newchanno = LINES_REGULAR + LINES_DIGI_OUT + i;
- BIT_CLR(lines, channo);
- BIT_SET(lines, newchanno);
-- phone_hook(xpd, newchanno, offhook);
-+ chan = &xpd->span.chans[newchanno];
-+ xpd->ringing[newchanno] = 0; // Stop ringing. No leds for digital inputs.
-+ if(offhook && !IS_SET(xpd->hookstate, newchanno)) { // OFFHOOK
-+ DBG("OFFHOOK: channo=%d\n", chan->channo);
-+ BIT_SET(xpd->hookstate, newchanno);
-+ zt_hooksig(chan, ZT_RXSIG_OFFHOOK);
-+ } else if(!offhook && IS_SET(xpd->hookstate, newchanno)) { // ONHOOK
-+ DBG("ONHOOK channo=%d\n", chan->channo);
-+ BIT_CLR(xpd->hookstate, newchanno);
-+ zt_hooksig(chan, ZT_RXSIG_ONHOOK);
-+ }
- }
- }
- }
-+
-+ /* Update /proc info only if reply relate to the last slic read request */
-+ if(priv->requested_reply.indirect == info->indirect &&
-+ priv->requested_reply.reg_num == info->reg_num) {
-+ priv->last_reply = *info;
-+ }
- spin_unlock_irqrestore(&xpd->lock, flags);
- return 0;
- }
-
--
- xproto_table_t PROTO_TABLE(FXS) = {
-+ .owner = THIS_MODULE,
- .entries = {
- /* Card Opcode */
- XENTRY( FXS, SIG_CHANGED ),
- XENTRY( FXS, SLIC_REPLY ),
- },
- .name = "FXS",
-- .type = XPD_TYPE(FXS),
-+ .type = XPD_TYPE_FXS,
- .xops = {
- .card_new = FXS_card_new,
- .card_init = FXS_card_init,
- .card_remove = FXS_card_remove,
-+ .card_zaptel_preregistration = FXS_card_zaptel_preregistration,
-+ .card_zaptel_postregistration = FXS_card_zaptel_postregistration,
-+#ifdef WITH_RBS
-+ .card_hooksig = FXS_card_hooksig,
-+#else
-+ .card_sethook = FXS_card_sethook,
-+#endif
- .card_tick = FXS_card_tick,
-
- .RING = XPROTO_CALLER(FXS, RING),
- .SETHOOK = XPROTO_CALLER(FXS, SETHOOK),
-- .LED = XPROTO_CALLER(FXS, LED),
- .RELAY_OUT = XPROTO_CALLER(FXS, RELAY_OUT),
- .CHAN_ENABLE = XPROTO_CALLER(FXS, CHAN_ENABLE),
-- .CHAN_POWER = XPROTO_CALLER(FXS, CHAN_POWER),
- .CHAN_CID = XPROTO_CALLER(FXS, CHAN_CID),
-
- .SYNC_SOURCE = XPROTO_CALLER(GLOBAL, SYNC_SOURCE),
-@@ -519,7 +891,7 @@
- {
- const xproto_entry_t *xe;
-
-- DBG("\n");
-+ // DBG("\n");
- xe = xproto_card_entry(&PROTO_TABLE(FXS), pack->content.opcode);
- return xe != NULL;
- }
-@@ -531,6 +903,57 @@
-
- /*------------------------- SLIC Handling --------------------------*/
-
-+static int proc_fxs_info_read(char *page, char **start, off_t off, int count, int *eof, void *data)
-+{
-+ int len = 0;
-+ unsigned long flags;
-+ xpd_t *xpd = data;
-+ struct FXS_priv_data *priv;
-+ int i;
-+ int led;
-+
-+ if(!xpd)
-+ return -ENODEV;
-+ spin_lock_irqsave(&xpd->lock, flags);
-+ priv = xpd->priv;
-+ BUG_ON(!priv);
-+ len += sprintf(page + len, "\t%-17s: ", "Channel");
-+ for_each_line(xpd, i) {
-+ if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i))
-+ len += sprintf(page + len, "%d ", i % 10);
-+ }
-+ len += sprintf(page + len, "\n");
-+ for(led = 0; led < NUM_LEDS; led++) {
-+ len += sprintf(page + len, "LED #%d", led);
-+ len += sprintf(page + len, "\n\t%-17s: ", "ledstate");
-+ for_each_line(xpd, i) {
-+ if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i))
-+ len += sprintf(page + len, "%d ", IS_SET(priv->ledstate[led], i));
-+ }
-+ len += sprintf(page + len, "\n\t%-17s: ", "ledcontrol");
-+ for_each_line(xpd, i) {
-+ if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i))
-+ len += sprintf(page + len, "%d ", IS_SET(priv->ledcontrol[led], i));
-+ }
-+ len += sprintf(page + len, "\n\t%-17s: ", "blinking");
-+ for_each_line(xpd, i) {
-+ if(!IS_SET(xpd->digital_outputs, i) && !IS_SET(xpd->digital_inputs, i))
-+ len += sprintf(page + len, "%d ", IS_BLINKING(priv,i,led));
-+ }
-+ len += sprintf(page + len, "\n");
-+ }
-+ spin_unlock_irqrestore(&xpd->lock, flags);
-+ if (len <= off+count)
-+ *eof = 1;
-+ *start = page + off;
-+ len -= off;
-+ if (len > count)
-+ len = count;
-+ if (len < 0)
-+ len = 0;
-+ return len;
-+}
-+
- static int proc_xpd_slic_read(char *page, char **start, off_t off, int count, int *eof, void *data)
- {
- int len = 0;
-@@ -570,7 +993,7 @@
- * |
- * SLIC #
- */
--static int parse_slic_cmd(const char *buf, slic_cmd_t *sc)
-+static int parse_slic_cmd(const char *buf, slic_cmd_t *sc, slic_reply_t *requested_reply)
- {
- char op; /* [W]rite, [R]ead */
- char reg_type; /* [D]irect, [I]ndirect */
-@@ -588,9 +1011,17 @@
- if(reg_type == 'D' && ret == 7) {
- // DBG("0x%X 0x%X 0x%X 0x%X %c %x\n", s1, s2, s3, s4, reg_type, reg_num);
- ret = slic_cmd_direct_read(sc, lines, reg_num);
-+ if(requested_reply) {
-+ requested_reply->indirect = 0;
-+ requested_reply->reg_num = reg_num;
-+ }
- } else if(reg_type == 'I' && ret == 7) {
- // DBG("0x%X 0x%X 0x%X 0x%X %c %x\n", s1, s2, s3, s4, reg_type, reg_num);
- ret = slic_cmd_indirect_read(sc, lines, reg_num);
-+ if(requested_reply) {
-+ requested_reply->indirect = 1;
-+ requested_reply->reg_num = reg_num;
-+ }
- } else {
- NOTICE("%s: Bad read input: ret=%d buf='%s' reg_type=%c\n", __FUNCTION__, ret, buf, reg_type);
- goto err;
-@@ -619,14 +1050,16 @@
-
- static int process_slic_cmdline(xpd_t *xpd, char *cmdline)
- {
-- xbus_t *xbus;
-- slic_cmd_t sc;
-- xpacket_t *pack;
-- char *p;
-- int len = strlen(cmdline);
-+ xbus_t *xbus;
-+ struct FXS_priv_data *priv;
-+ slic_cmd_t sc;
-+ xpacket_t *pack;
-+ char *p;
-+ int len = strlen(cmdline);
-
- BUG_ON(!xpd);
- xbus = xpd->xbus;
-+ priv = xpd->priv;
- if((p = strchr(cmdline, '#')) != NULL) /* Truncate comments */
- *p = '\0';
- if((p = strchr(cmdline, ';')) != NULL) /* Truncate comments */
-@@ -635,12 +1068,11 @@
- ;
- if(*p == '\0')
- return 0;
-- len = parse_slic_cmd(p, &sc);
-+ len = parse_slic_cmd(p, &sc, &priv->requested_reply);
- if(len < 0)
- return len;
-- sc.lines &= xpd->enabled_chans; // Ignore disabled channels
- if(!sc.lines) {
-- NOTICE("%s: no enabled channels are marked. Skip.\n", __FUNCTION__);
-+ NOTICE("%s: no channels are marked. Skip.\n", __FUNCTION__);
- return 0;
- }
- dump_slic_cmd("WRITE_SLIC", &sc);
-@@ -660,7 +1092,8 @@
- int i;
- int ret;
-
-- BUG_ON(!xpd);
-+ if(!xpd)
-+ return -ENODEV;
- for(i = 0; i < count; /* noop */) {
- for(p = buf; p < buf + LINE_LEN; p++) { /* read a line */
- if(i >= count)
-@@ -677,6 +1110,7 @@
- ret = process_slic_cmdline(xpd, buf);
- if(ret < 0)
- return ret;
-+ mdelay(1);
- }
- return count;
- }
-@@ -684,7 +1118,13 @@
-
- int __init card_fxs_startup(void)
- {
-- INFO("%s revision %s\n", THIS_MODULE->name, revision);
-+ INFO("%s revision %s\n", THIS_MODULE->name, ZAPTEL_VERSION);
-+#ifdef POLL_DIGITAL_INPUTS
-+ INFO("FEATURE: %s with DIGITAL INPUTS support (%s activated)\n",
-+ THIS_MODULE->name, (poll_digital_inputs) ? "is" : "is not");
-+#else
-+ INFO("FEATURE: %s without DIGITAL INPUTS support\n", THIS_MODULE->name);
-+#endif
- xproto_register(&PROTO_TABLE(FXS));
- return 0;
- }
-@@ -697,7 +1137,8 @@
- MODULE_DESCRIPTION("XPP FXS Card Driver");
- MODULE_AUTHOR("Oron Peled <oron at actcom.co.il>");
- MODULE_LICENSE("GPL");
--MODULE_VERSION("$Id: card_fxs.c 995 2006-04-03 07:08:13Z tzafrir $");
-+MODULE_VERSION(ZAPTEL_VERSION);
-+MODULE_ALIAS_XPD(XPD_TYPE_FXS);
-
- module_init(card_fxs_startup);
- module_exit(card_fxs_cleanup);
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/card_fxs.h zaptel-xpp-LJNBCn_dist/xpp/card_fxs.h
---- zaptel-1.2.6/xpp/card_fxs.h 2006-02-15 04:24:18.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/card_fxs.h 2006-07-02 17:17:18.812352000 +0300
-@@ -2,7 +2,7 @@
- #define CARD_FXS_H
- /*
- * Written by Oron Peled <oron at actcom.co.il>
-- * Copyright (C) 2004-2005, Xorcom
-+ * Copyright (C) 2004-2006, Xorcom
- *
- * All rights reserved.
- *
-@@ -25,6 +25,24 @@
- #include "xpd.h"
- #include "slic.h"
-
-+enum fxs_opcodes {
-+ XPROTO_NAME(FXS, SIG_CHANGED) = 0x06,
-+/**/
-+ XPROTO_NAME(FXS, SLIC_WRITE) = 0x0F, /* Write to SLIC */
-+ XPROTO_NAME(FXS, CHAN_ENABLE) = 0x0F, /* Write to SLIC */
-+ XPROTO_NAME(FXS, CHAN_POWER) = 0x0F, /* Write to SLIC */
-+ XPROTO_NAME(FXS, CHAN_CID) = 0x0F, /* Write to SLIC */
-+ XPROTO_NAME(FXS, RING) = 0x0F, /* Write to SLIC */
-+ XPROTO_NAME(FXS, SETHOOK) = 0x0F, /* Write to SLIC */
-+ XPROTO_NAME(FXS, LED) = 0x0F, /* Write to SLIC */
-+ XPROTO_NAME(FXS, RELAY_OUT) = 0x0F, /* Write to SLIC */
-+ XPROTO_NAME(FXS, SLIC_INIT) = 0x0F, /* Write to SLIC */
-+ XPROTO_NAME(FXS, SLIC_QUERY) = 0x0F, /* Write to SLIC */
-+/**/
-+ XPROTO_NAME(FXS, SLIC_REPLY) = 0x10,
-+};
-+
-+
- DEF_RPACKET_DATA(FXS, SIG_CHANGED,
- byte type; /* unused -- we have it from DEV_DESC */
- xpp_line_t sig_status; /* channels: lsb=1, msb=8 */
-@@ -34,10 +52,6 @@
- xpp_line_t lines;
- slic_reply_t info;
- );
--DEF_RPACKET_DATA(FXS, SLIC_INIT,
-- xpp_line_t lines;
-- slic_data_t slic_data;
-- );
- DEF_RPACKET_DATA(FXS, SLIC_WRITE,
- slic_cmd_t slic_cmd;
- );
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/card_global.c zaptel-xpp-LJNBCn_dist/xpp/card_global.c
---- zaptel-1.2.6/xpp/card_global.c 2006-02-15 04:24:18.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/card_global.c 2006-07-03 14:04:21.414889000 +0300
-@@ -1,6 +1,6 @@
- /*
- * Written by Oron Peled <oron at actcom.co.il>
-- * Copyright (C) 2004-2005, Xorcom
-+ * Copyright (C) 2004-2006, Xorcom
- *
- * All rights reserved.
- *
-@@ -24,9 +24,10 @@
- #include "xpd.h"
- #include "xpp_zap.h"
- #include "xproto.h"
-+#include "zap_debug.h"
- #include <linux/module.h>
-
--static const char rcsid[] = "$Id: card_global.c 949 2006-02-15 02:24:18Z kpfleming $";
-+static const char rcsid[] = "$Id: card_global.c 1549 2006-07-03 11:04:21Z oron $";
-
- extern int print_dbg;
- static bool pcm_valid(xpd_t *xpd, xpacket_t *pack);
-@@ -61,13 +62,10 @@
- byte *pcm;
- byte *start_pcm;
- int i;
-- extern ulong pcm_gen;
-
- BUG_ON(!xbus);
- BUG_ON(!xpd);
-- lines &= xpd->enabled_chans;
-- if(pcm_gen != 0)
-- return 0;
-+ lines &= ~xpd->no_pcm;
- // if(lines == 0)
- // return 0;
-
-@@ -81,7 +79,7 @@
- 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(i = 0; i < CHANNELS_PERXPD; i++) {
-+ for_each_line(xpd, i) {
- if(IS_SET(lines, i)) {
- memcpy(pcm, (byte *)buf, ZT_CHUNKSIZE);
- pcm += ZT_CHUNKSIZE;
-@@ -116,32 +114,44 @@
-
- /*---------------- GLOBAL: Astribank Reply Handlers -----------------------*/
-
-+HANDLER_DEF(GLOBAL, NULL_REPLY)
-+{
-+ DBG("got len=%d\n", pack->datalen);
-+ return 0;
-+}
-+
- HANDLER_DEF(GLOBAL, DEV_DESC)
- {
- byte rev = RPACKET_FIELD(pack, GLOBAL, DEV_DESC, rev);
- byte type = RPACKET_FIELD(pack, GLOBAL, DEV_DESC, type);
- xpp_line_t line_status = RPACKET_FIELD(pack, GLOBAL, DEV_DESC, line_status);
-- int xpd_num = XPD_NUM(pack->content.addr);
-+ xpd_addr_t xpd_addr = RPACKET_FIELD(pack, GLOBAL, DEV_DESC, addr);
- struct card_desc_struct *card_desc;
-+ unsigned long flags;
-
-- DBG("xpd=%d type=%d rev=%d line_status=0x%04X\n",
-- xpd_num, type, rev, line_status);
-+ BUG_ON(!xbus);
- if((card_desc = kmalloc(sizeof(struct card_desc_struct), GFP_ATOMIC)) == NULL) {
- ERR("%s: Card description allocation failed.\n", __FUNCTION__);
- return -ENOMEM;
- }
- memset(card_desc, 0, sizeof(struct card_desc_struct));
- card_desc->magic = CARD_DESC_MAGIC;
-+ INIT_LIST_HEAD(&card_desc->card_list);
- card_desc->xbus = xbus;
- card_desc->type = type;
- card_desc->rev = rev;
-- card_desc->xpd_num = xpd_num;
-- INIT_WORK(&card_desc->work, card_detected, card_desc);
-- DBG("Queueing xpp_worker for xpd %d\n", xpd_num);
-- if(!queue_work(xpp_worker, &card_desc->work)) {
-- ERR("Failed to queue card description work\n");
-- return -EINVAL;
-- }
-+ card_desc->xpd_addr = xpd_addr;
-+ spin_lock_irqsave(&xbus->lock, flags);
-+ DBG("xpd=%d-%d type=%d rev=%d line_status=0x%04X\n",
-+ xpd_addr.unit, xpd_addr.subunit, type, rev, line_status);
-+ if(type == XPD_TYPE_NOMODULE)
-+ XBUS_COUNTER(xbus, DEV_DESC_EMPTY)++;
-+ else
-+ XBUS_COUNTER(xbus, DEV_DESC_FULL)++;
-+ atomic_inc(&xbus->count_poll_answers);
-+ wake_up(&xbus->wait_for_polls);
-+ list_add_tail(&card_desc->card_list, &xbus->poll_results);
-+ spin_unlock_irqrestore(&xbus->lock, flags);
- return 0;
- }
-
-@@ -155,6 +165,7 @@
- unsigned long flags;
- int i;
-
-+ BUG_ON(!xbus);
- if(!xpd) {
- #if 0
- int xpd_num = XPD_NUM(pack->content.addr);
-@@ -177,7 +188,7 @@
- }
-
- /* Copy PCM and put each channel in its index */
-- for (i = 0; i < CHANNELS_PERXPD; i++) {
-+ 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
-@@ -195,12 +206,19 @@
-
- HANDLER_DEF(GLOBAL, SYNC_REPLY)
- {
-+ byte mask = RPACKET_FIELD(pack, GLOBAL, SYNC_REPLY, mask);
-+ bool setit = mask & 0x01;
-+
-+ 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);
- return -EPROTO;
- }
-- DBG("SYNC_REPLY: 0x%X\n", RPACKET_FIELD(pack, GLOBAL, SYNC_REPLY, mask));
-+ 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;
- }
-
-@@ -208,6 +226,7 @@
- xproto_table_t PROTO_TABLE(GLOBAL) = {
- .entries = {
- /* Card Opcode */
-+ XENTRY( GLOBAL, NULL_REPLY ),
- XENTRY( GLOBAL, DEV_DESC ),
- XENTRY( GLOBAL, PCM_READ ),
- XENTRY( GLOBAL, SYNC_REPLY ),
-@@ -239,7 +258,7 @@
-
- BUG_ON(!pack);
- BUG_ON(pack->content.opcode != XPROTO_NAME(GLOBAL, PCM_READ));
-- for (i = 0; i < CHANNELS_PERXPD; i++)
-+ for_each_line(xpd, i)
- if(IS_SET(lines, i))
- count++;
- if(pack->datalen != (sizeof(xpp_line_t) + count * 8)) {
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/card_global.h zaptel-xpp-LJNBCn_dist/xpp/card_global.h
---- zaptel-1.2.6/xpp/card_global.h 2006-02-15 04:24:18.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/card_global.h 2006-07-03 13:44:48.152691000 +0300
-@@ -2,7 +2,7 @@
- #define CARD_GLOBAL_H
- /*
- * Written by Oron Peled <oron at actcom.co.il>
-- * Copyright (C) 2004-2005, Xorcom
-+ * Copyright (C) 2004-2006, Xorcom
- *
- * All rights reserved.
- *
-@@ -24,6 +24,7 @@
-
- #include "xdefs.h"
-
-+DEF_RPACKET_DATA(GLOBAL, NULL_REPLY);
- DEF_RPACKET_DATA(GLOBAL, DESC_REQ);
- DEF_RPACKET_DATA(GLOBAL, DEV_DESC,
- byte rev; /* Revision number */
-@@ -31,11 +32,11 @@
- xpp_line_t line_status; /* hook/ring status, depending on unit */
- );
- DEF_RPACKET_DATA(GLOBAL, PCM_WRITE,
-- xpp_line_t lines; // Must be 0xFF
-+ xpp_line_t lines;
- byte pcm[PCM_CHUNKSIZE];
- );
- DEF_RPACKET_DATA(GLOBAL, PCM_READ,
-- xpp_line_t lines; // Must be 0xFF
-+ xpp_line_t lines;
- byte pcm[PCM_CHUNKSIZE];
- );
- DEF_RPACKET_DATA(GLOBAL, SYNC_SOURCE,
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/cards.c zaptel-xpp-LJNBCn_dist/xpp/cards.c
---- zaptel-1.2.6/xpp/cards.c 2006-02-15 04:24:18.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/cards.c 1970-01-01 02:00:00.000000000 +0200
-@@ -1,394 +0,0 @@
--#include <linux/module.h>
--#include "xpd.h"
--#include "xpp_zap.h"
--#include "xpp_proto.h"
--#include "cards.h"
--
--static char rcsid[] = "$Id: cards.c 949 2006-02-15 02:24:18Z kpfleming $";
--
--extern int print_dbg;
--#include "zap_debug.h"
--
--#define MAX_SLIC_REGISTERS 100
--
--struct FXS_private_data {
-- slic_reply_t last_slic_reply;
--};
--
--/*------------------------- FXS Functions --------------------------*/
--int FXS_card_new(xpd_t *xpd)
--{
-- xpd->direction = TO_PHONE;
-- xpd->channels = min(8, CHANNELS_PERXPD);
-- if(xpd->id == 0) {
-- DBG("First XPD detected. Initialize digital outputs\n");
-- xpd->channels += 2;
-- xpd->digital_outputs = BIT(8) | BIT(9); // Two extra channels
-- }
-- return 0;
--}
--
--int FXS_card_remove(xpd_t *xpd)
--{
-- return 0;
--}
--
--static int FXS_card_startup(struct zt_span *span)
--{
-- DBG("\n");
-- return 0;
--}
--
--/*
-- * Called only for 'span' keyword in /etc/zaptel.conf
-- */
--static int FXS_card_spanconfig(struct zt_span *span, struct zt_lineconfig *lc)
--{
-- xpd_t *xpd = span->pvt;
--
-- DBG("%s\n", xpd->xpdname);
-- return 0;
--}
--
--/* Set signalling type (if appropriate) */
--static int FXS_card_chanconfig(struct zt_chan *chan, int sigtype)
--{
-- DBG("channel %d (%s), sigtype %d.\n", chan->channo, chan->name, sigtype);
-- dump_sigtype(print_dbg, " ", sigtype);
-- // FIXME: sanity checks:
-- // - should be supported (within the sigcap)
-- // - should not replace fxs <->fxo ??? (covered by previous?)
-- return 0;
--}
--
--/*
-- * Called only for 'span' keyword in /etc/zaptel.conf
-- */
--static int FXS_card_shutdown(struct zt_span *span)
--{
-- xpd_t *xpd = span->pvt;
--
-- DBG("%s\n", xpd->xpdname);
-- return 0;
--}
--
--static int FXS_card_sethook(struct zt_chan *chan, int hookstate)
--{
-- int pos = chan->chanpos - 1;
-- xpd_t *xpd = chan->pvt;
-- xbus_t *xbus;
-- int ret = 0;
--
-- if(!xpd) {
-- ERR("%s: channel=%d without an XPD!\n", __FUNCTION__, pos);
-- return -EINVAL;
-- }
-- xbus = xpd->xbus;
-- // DBG("%s (%d) (old=0x%04X, hook-command=%d)\n", chan->name, pos, xpd->hookstate, hookstate);
-- switch(hookstate) {
-- /* On-hook, off-hook: The PBX is playing a phone on an FXO line.
-- * Can be ignored for an FXS line
-- */
-- case ZT_ONHOOK:
-- if(IS_SET(xpd->digital_outputs, pos)) {
-- DBG("ZT_ONHOOK %s digital output OFF\n", chan->name);
-- ret = CALL_PROTO(RELAY_OUT, xpd->xbus, xpd, pos-8, 0);
-- return ret;
-- }
-- DBG("ZT_ONHOOK: %s hookstate=0x%04X (stop ringing pos=%d)\n", chan->name, xpd->hookstate, pos);
-- xpd->ringing[pos] = 0;
--#if 1 // FIXME: Not needed -- verify
-- ret = CALL_PROTO(RING, xbus, xpd, pos, 0); // RING off
--#endif
-- ret = CALL_PROTO(LED, xpd->xbus, xpd, BIT(pos), LED_GREEN, 0);
-- ret = CALL_PROTO(CHAN_POWER, xbus, xpd, BIT(pos), 0); // Power down (prevent overheating!!!)
-- if(ret) {
-- DBG("ZT_ONHOOK(stop ring) Failed: ret=0x%02X\n", ret);
-- break;
-- }
-- break;
-- case ZT_START:
-- DBG("ZT_START: %s hookstate=0x%04X (fall through ZT_OFFHOOK)\n", chan->name, xpd->hookstate);
-- // Fall through
-- case ZT_OFFHOOK:
-- DBG("ZT_OFFHOOK: %s hookstate=0x%04X -- ignoring (FXS)\n", chan->name, xpd->hookstate);
-- break;
-- case ZT_WINK:
-- DBG("ZT_WINK %s\n", chan->name);
-- break;
-- case ZT_FLASH:
-- DBG("ZT_FLASH %s\n", chan->name);
-- break;
-- case ZT_RING:
-- DBG("ZT_RING %s pos=%d (ringing[pos]=%d)\n", chan->name, pos, xpd->ringing[pos]);
-- if(IS_SET(xpd->digital_outputs, pos)) {
-- DBG("ZT_ONHOOK %s digital output ON\n", chan->name);
-- ret = CALL_PROTO(RELAY_OUT, xpd->xbus, xpd, pos-8, 1);
-- return ret;
-- }
-- xpd->ringing[pos] = RINGS_NUM*2;
-- ret = CALL_PROTO(CHAN_POWER, xbus, xpd, (1 << pos), 1); // Power up (for ring)
-- ret = CALL_PROTO(RING, xbus, xpd, pos, 1); // RING on
-- if(ret) {
-- DBG("ZT_RING Failed: ret=0x%02X\n", ret);
-- }
-- break;
-- case ZT_RINGOFF:
-- DBG("ZT_RINGOFF %s\n", chan->name);
-- break;
-- default:
-- DBG("UNKNOWN hookstate=0x%X\n", hookstate);
-- }
-- return ret;
--}
--
--static int FXS_card_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long arg)
--{
-- switch (cmd) {
-- default:
-- return xpp_ioctl(chan, cmd, arg);
-- }
-- return 0;
--}
--
--#if 0
--int FXS_zaptel_setup(xpd_t *xpd)
--{
-- struct zt_chan *cur_chan;
-- struct zt_span *span;
-- xbus_t *xbus;
-- int i;
-- int cn;
--
-- BUG_ON(!xpd);
--
-- sigfxs = ! (xpd->direction == TO_PHONE); /* signaling is opposite */
-- cn = xpd->channels;
-- DBG("Initializing span: xpd %d have %d channels.\n", xpd->id, cn);
--
-- xpd->chans = kmalloc(sizeof(struct zt_chan)*cn, GFP_ATOMIC);
-- if (xpd->chans == NULL) {
-- ERR("xpd: Unable to allocate channels\n");
-- return -ENOMEM;
-- }
-- memset(xpd->chans, 0, sizeof(struct zt_chan)*cn);
-- memset(&xpd->span, 0, sizeof(struct zt_span));
--
-- span = &xpd->span;
-- xbus = xpd->xbus;
-- snprintf(span->name, MAX_SPANNAME, "%s/%s",
-- xbus->busname, xpd->xpdname);
-- {
-- char tmp[MAX_SPANNAME];
-- struct xpd_sim *sim = &xbus->sim[xpd->id];
--
-- if(sim->simulated)
-- snprintf(tmp, MAX_SPANNAME, " (sim to=%d)", sim->loopto);
-- else
-- tmp[0] = '\0';
--
-- snprintf(span->desc, MAX_SPANDESC, "Xorcom XPD #%d/%d: %s%s",
-- xbus->num, xpd->id,
-- (xpd->direction == TO_PHONE) ? "FXS" : "FXO",
-- tmp
-- );
-- }
-- for(i = 0; i < cn; i++) {
--
-- cur_chan = &xpd->chans[i];
-- DBG("setting channel %d\n", i);
-- snprintf(cur_chan->name, MAX_CHANNAME, "XPP_FXS/%d-%d", xpd->id, i);
-- cur_chan->chanpos = i + 1;
-- cur_chan->pvt = xpd;
-- cur_chan->sigcap =
--#if 1
-- ZT_SIG_FXOKS |
-- ZT_SIG_FXOLS |
-- ZT_SIG_FXOGS |
--#else
-- ZT_SIG_SF |
-- ZT_SIG_EM |
--#endif
-- 0;
-- }
-- span->deflaw = ZT_LAW_MULAW;
-- init_waitqueue_head(&span->maintq);
-- span->pvt = xpd;
-- span->channels = cn;
-- span->chans = xpd->chans;
--
-- span->startup = FXS_xpp_startup;
-- span->shutdown = FXS_xpp_shutdown;
-- span->spanconfig = FXS_xpp_spanconfig;
-- span->chanconfig = FXS_xpp_chanconfig;
-- span->open = xpp_open;
-- span->close = xpp_close;
--#ifdef WITH_RBS
-- span->flags = ZT_FLAG_RBS;
-- span->hooksig = xpp_hooksig; /* Only with RBS bits */
--#else
-- span->sethook = FXS_xpp_sethook;
--#endif
-- span->ioctl = FXS_xpp_ioctl;
-- span->maint = xpp_maint;
--#ifdef CONFIG_ZAPTEL_WATCHDOG
-- span->watchdog = xpp_watchdog;
--#endif
--
-- return 0;
--}
--#endif
--
--int FXS_zaptel_cleanup(xpd_t *xpd)
--{
-- return 0;
--}
--
--/*------------------------- FXO Functions --------------------------*/
--static int FXO_card_new(xpd_t *xpd)
--{
-- xpd->direction = TO_TRUNK;
-- xpd->channels = min(8, CHANNELS_PERXPD);
-- return 0;
--}
--
--static int FXO_card_remove(xpd_t *xpd)
--{
-- return 0;
--}
--
--static int FXO_card_startup(struct zt_span *span)
--{
-- DBG("\n");
-- return 0;
--}
--
--/*
-- * Called only for 'span' keyword in /etc/zaptel.conf
-- */
--static int FXO_card_spanconfig(struct zt_span *span, struct zt_lineconfig *lc)
--{
-- xpd_t *xpd = span->pvt;
--
-- DBG("%s\n", xpd->xpdname);
-- return 0;
--}
--
--/* Set signalling type (if appropriate) */
--static int FXO_card_chanconfig(struct zt_chan *chan, int sigtype)
--{
-- DBG("channel %d (%s), sigtype %d.\n", chan->channo, chan->name, sigtype);
-- dump_sigtype(print_dbg, " ", sigtype);
-- // FIXME: sanity checks:
-- // - should be supported (within the sigcap)
-- // - should not replace fxs <->fxo ??? (covered by previous?)
-- return 0;
--}
--
--/*
-- * Called only for 'span' keyword in /etc/zaptel.conf
-- */
--static int FXO_card_shutdown(struct zt_span *span)
--{
-- xpd_t *xpd = span->pvt;
--
-- DBG("%s\n", xpd->xpdname);
-- return 0;
--}
--
--
--static int FXO_card_sethook(struct zt_chan *chan, int hookstate)
--{
-- int pos = chan->chanpos - 1;
-- xpd_t *xpd = chan->pvt;
-- xbus_t *xbus;
-- int ret = 0;
--
-- BUG_ON(!xpd);
-- xbus = xpd->xbus;
-- // DBG("%s (%d) (old=0x%04X, hook-command=%d)\n", chan->name, pos, xpd->hookstate, hookstate);
-- switch(hookstate) {
-- /* On-hook, off-hook: The PBX is playing a phone on an FXO line.
-- * Can be ignored for an FXS line
-- */
-- case ZT_ONHOOK:
-- if(IS_SET(xpd->digital_outputs, pos)) {
-- DBG("ZT_ONHOOK %s digital output OFF\n", chan->name);
-- ret = CALL_PROTO(RELAY_OUT, xpd->xbus, xpd, pos-8, 0);
-- return ret;
-- }
-- DBG("ZT_ONHOOK: %s hookstate=0x%04X (pos=%d)\n", chan->name, xpd->hookstate, pos);
-- xpd->ringing[pos] = 0;
-- BIT_CLR(xpd->hookstate, pos);
-- ret = CALL_PROTO(SETHOOK, xbus, xpd, xpd->hookstate);
-- if(ret) {
-- DBG("ZT_ONHOOK Failed: ret=0x%02X\n", ret);
-- break;
-- }
-- break;
-- case ZT_START:
-- DBG("ZT_START: %s hookstate=0x%04X (fall through ZT_OFFHOOK)\n", chan->name, xpd->hookstate);
-- // Fall through
-- case ZT_OFFHOOK:
-- DBG("ZT_OFFHOOK: %s hookstate=0x%04X (pos=%d)\n", chan->name, xpd->hookstate, pos);
-- BIT_SET(xpd->hookstate, pos);
-- xpd->ringing[pos] = 0;
-- ret = CALL_PROTO(SETHOOK, xbus, xpd, xpd->hookstate);
-- if(ret) {
-- DBG("ZT_OFFHOOK Failed: ret=0x%02X\n", ret);
-- break;
-- }
-- break;
-- case ZT_WINK:
-- DBG("ZT_WINK %s\n", chan->name);
-- break;
-- case ZT_FLASH:
-- DBG("ZT_FLASH %s\n", chan->name);
-- break;
-- case ZT_RING:
-- DBG("ZT_RING %s pos=%d (ringing[pos]=%d)\n", chan->name, pos, xpd->ringing[pos]);
-- break;
-- case ZT_RINGOFF:
-- DBG("ZT_RINGOFF %s\n", chan->name);
-- break;
-- default:
-- DBG("UNKNOWN hookstate=0x%X\n", hookstate);
-- }
-- return ret;
--}
--
--static int FXO_card_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long arg)
--{
-- switch (cmd) {
-- default:
-- return xpp_ioctl(chan, cmd, arg);
-- }
-- return 0;
--}
--
--
--/*------------------------- Function table -------------------------*/
--
--#define DEF_(t) \
-- [XPD_TYPE_ ## t] { \
-- .card_new = t ## _card_new, \
-- .card_remove = t ## _card_remove, \
-- .card_startup = t ## _card_startup, \
-- .card_shutdown = t ## _card_shutdown, \
-- .card_spanconfig = t ## _card_spanconfig, \
-- .card_chanconfig = t ## _card_chanconfig, \
-- .card_sethook = t ## _card_sethook, \
-- .card_ioctl = t ## _card_ioctl, \
-- }
--
--xops_t xpd_card_ops[XPD_TYPE_NOMODULE] = {
-- DEF_(FXS),
-- DEF_(FXO)
--};
--
--xops_t *get_xops(xpd_type_t xpd_type)
--{
-- if(xpd_type >= XPD_TYPE_NOMODULE)
-- return NULL;
-- return &xpd_card_ops[xpd_type];
--}
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/cards.h zaptel-xpp-LJNBCn_dist/xpp/cards.h
---- zaptel-1.2.6/xpp/cards.h 2006-02-15 04:24:18.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/cards.h 1970-01-01 02:00:00.000000000 +0200
-@@ -1,23 +0,0 @@
--#ifndef CARDS_H
--#define CARDS_H
--
--#include "xpd.h"
--
--struct xpd_card_ops {
-- int (*card_new)(xpd_t *xpd);
-- int (*card_remove)(xpd_t *xpd);
--#if 0
-- int (*zaptel_setup)(xpd_t *xpd);
-- int (*zaptel_cleanup)(xpd_t *xpd);
--#endif
-- int (*card_startup)(struct zt_span *span);
-- int (*card_shutdown)(struct zt_span *span);
-- int (*card_spanconfig)(struct zt_span *span, struct zt_lineconfig *lc);
-- int (*card_chanconfig)(struct zt_chan *chan, int sigtype);
-- int (*card_sethook)(struct zt_chan *chan, int hookstate);
-- int (*card_ioctl)(struct zt_chan *chan, unsigned int cmd, unsigned long arg);
--};
--
--xops_t *get_xops(xpd_type_t xpd_type);
--
--#endif /* CARDS_H */
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/FPGA_XPD.hex zaptel-xpp-LJNBCn_dist/xpp/FPGA_XPD.hex
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/gen_slic_init zaptel-xpp-LJNBCn_dist/xpp/gen_slic_init
---- zaptel-1.2.6/xpp/gen_slic_init 2006-02-15 04:24:18.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/gen_slic_init 1970-01-01 02:00:00.000000000 +0200
-@@ -1,37 +0,0 @@
--#! /usr/bin/perl -w
--
--use strict;
--
--my $input;
--my $header;
--my $comment;
--
-- at ARGV == 2 or die "Usage: $0 <infile> <outfile>\n";
--$input = $ARGV[0];
--$header = $ARGV[1];
--open(IF, "$input") or die "Failed to write '$input': $!\n";
--open(HF, ">$header") or die "Failed to write '$header': $!\n";
--
--while(<IF>) {
-- chomp;
-- undef $comment;
-- s/\r//; # CRLF -> LF
-- if(s/\s*[;#]\s*(.*?)$//) { # Comments
-- $comment = $1;
-- }
-- if(/^\s*$/) { # Empty lines
-- next;
-- }
-- my ($slic0, $slic1, $slic2, $slic3, $len, @data) = split;
-- die "Bad input (len=$len)" if hex($len) != @data;
-- my $slic = "$slic3$slic2$slic1$slic0";
-- die "Bad slic address '$slic'" if length($slic) != 8;
-- grep(s/\w+/0x$&/g, ($slic, $len, @data));
-- my $str = join(", ", @data);
-- print HF "S_($slic,\t$len,\t$str),\t";
--} continue {
-- if(defined($comment)) {
-- print HF "// $comment";
-- }
-- print HF "\n";
--}
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/init_data_3_19.cmd zaptel-xpp-LJNBCn_dist/xpp/init_data_3_19.cmd
---- zaptel-1.2.6/xpp/init_data_3_19.cmd 1970-01-01 02:00:00.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/init_data_3_19.cmd 2006-06-26 11:48:58.007317000 +0300
-@@ -0,0 +1,169 @@
-+#
-+# Written by Oron Peled <oron at actcom.co.il>
-+# Copyright (C) 2006, Xorcom
-+#
-+# All rights reserved.
-+#
-+# This program is free software; you can redistribute it and/or modify
-+# it under the terms of the GNU General Public License as published by
-+# the Free Software Foundation; either version 2 of the License, or
-+# (at your option) any later version.
-+#
-+# See the file LICENSE in the top level of this tarball.
-+#
-+
-+;
-+; $Id: init_data_fxs.cmd 540 2006-03-01 12:30:36Z oron $
-+;
-+; SLICS CMD Reg High Low
-+
-+; ----------------------------------==== 8-channel FXS unit initialization ===-----------------------------------------
-+; INTERNAL PS
-+; Change SLICs states to "Open state"s (Off,all transfers tristated to avoid data collision), Voltage sense
-+
-+FF 00 00 00 WD 40 00
-+FF 00 00 00 WD 6C 01
-+
-+; ------------------------------------- Initialization of indirect registers ------------------------------------------
-+
-+FF 00 00 00 WI 00 55 C2
-+FF 00 00 00 WI 01 51 E6
-+FF 00 00 00 WI 02 4B 85
-+FF 00 00 00 WI 03 49 37
-+
-+FF 00 00 00 WI 04 33 33
-+FF 00 00 00 WI 05 02 02
-+FF 00 00 00 WI 06 02 02
-+FF 00 00 00 WI 07 01 98
-+
-+FF 00 00 00 WI 08 01 98
-+FF 00 00 00 WI 09 06 11
-+FF 00 00 00 WI 0A 02 02
-+FF 00 00 00 WI 0B 00 E5
-+
-+FF 00 00 00 WI 0C 0A 1C
-+FF 00 00 00 WI 0D 7B 30
-+FF 00 00 00 WI 0E 00 63
-+FF 00 00 00 WI 0F 00 00
-+
-+FF 00 00 00 WI 10 78 70
-+FF 00 00 00 WI 11 00 7D
-+FF 00 00 00 WI 12 00 00
-+FF 00 00 00 WI 13 00 00
-+
-+FF 00 00 00 WI 14 7E F0
-+FF 00 00 00 WI 15 01 60
-+FF 00 00 00 WI 16 00 00
-+FF 00 00 00 WI 17 20 00
-+
-+FF 00 00 00 WI 18 20 00
-+FF 00 00 00 WI 19 00 00
-+FF 00 00 00 WI 1A 40 00
-+FF 00 00 00 WI 1B 40 00
-+
-+FF 00 00 00 WI 1C 18 00
-+FF 00 00 00 WI 1D 40 00
-+FF 00 00 00 WI 1E 10 00
-+FF 00 00 00 WI 1F 00 80
-+
-+FF 00 00 00 WI 20 0F F4
-+FF 00 00 00 WI 21 6E 7E
-+FF 00 00 00 WI 22 0F F4
-+FF 00 00 00 WI 23 88 00
-+
-+FF 00 00 00 WI 24 03 20
-+FF 00 00 00 WI 25 00 12
-+FF 00 00 00 WI 26 00 12
-+FF 00 00 00 WI 27 00 12
-+
-+FF 00 00 00 WI 28 0C 00
-+FF 00 00 00 WI 29 0C 00
-+FF 00 00 00 WI 2B 08 00
-+
-+FF 00 00 00 WI 63 00 DA
-+FF 00 00 00 WI 64 6B 60
-+FF 00 00 00 WI 65 00 74
-+FF 00 00 00 WI 66 79 C0
-+
-+FF 00 00 00 WI 67 11 20
-+FF 00 00 00 WI 68 3B E0
-+
-+; ------------------------------------- Initialization of direct registers --------------------------------------------
-+
-+; Mode(8-bit,u-Law,1 PCLK ) setting, Loopbacks and Interrupts clear
-+
-+FF 00 00 00 WD 01 29
-+FF 00 00 00 WD 08 00
-+FF 00 00 00 WD 09 00
-+FF 00 00 00 WD 0E 00
-+
-+FF 00 00 00 WD 15 00
-+FF 00 00 00 WD 16 03
-+FF 00 00 00 WD 17 00
-+FF 00 00 00 WD 12 FF
-+FF 00 00 00 WD 13 FF
-+FF 00 00 00 WD 14 FF
-+
-+; Automatic/Manual Control: defaults - Cancel Power Alarm
-+FF 00 00 00 WD 43 1E
-+
-+FF 00 00 00 WD 4A 31
-+FF 00 00 00 WD 4B 10
-+
-+; Battery Feed Control: Battery low (DCSW low)
-+FF 00 00 00 WD 42 00
-+
-+; Slic Calibration
-+FF 00 00 00 WD 61 1F
-+FF 00 00 00 WD 60 5F
-+
-+; Loop Closure Debounce Interval
-+FF 00 00 00 WD 45 0A
-+
-+; Ring Detect Debounce Interval
-+FF 00 00 00 WD 46 0B
-+
-+; Loop Current Limit
-+FF 00 00 00 WD 47 07
-+
-+; Setting of SLICs offsets
-+
-+01 00 00 00 WD 02 01
-+01 00 00 00 WD 03 00
-+01 00 00 00 WD 04 01
-+01 00 00 00 WD 05 00
-+
-+02 00 00 00 WD 02 09
-+02 00 00 00 WD 03 00
-+02 00 00 00 WD 04 09
-+02 00 00 00 WD 05 00
-+
-+04 00 00 00 WD 02 11
-+04 00 00 00 WD 03 00
-+04 00 00 00 WD 04 11
-+04 00 00 00 WD 05 00
-+
-+08 00 00 00 WD 02 19
-+08 00 00 00 WD 03 00
-+08 00 00 00 WD 04 19
-+08 00 00 00 WD 05 00
-+
-+10 00 00 00 WD 02 21
-+10 00 00 00 WD 03 00
-+10 00 00 00 WD 04 21
-+10 00 00 00 WD 05 00
-+
-+20 00 00 00 WD 02 29
-+20 00 00 00 WD 03 00
-+20 00 00 00 WD 04 29
-+20 00 00 00 WD 05 00
-+
-+40 00 00 00 WD 02 31
-+40 00 00 00 WD 03 00
-+40 00 00 00 WD 04 31
-+40 00 00 00 WD 05 00
-+
-+80 00 00 00 WD 02 39
-+80 00 00 00 WD 03 00
-+80 00 00 00 WD 04 39
-+80 00 00 00 WD 05 00
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/init_data_3_20.cmd zaptel-xpp-LJNBCn_dist/xpp/init_data_3_20.cmd
---- zaptel-1.2.6/xpp/init_data_3_20.cmd 1970-01-01 02:00:00.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/init_data_3_20.cmd 2006-07-10 12:13:42.526183000 +0300
-@@ -0,0 +1,172 @@
-+#
-+# Written by Oron Peled <oron at actcom.co.il>
-+# Copyright (C) 2006, Xorcom
-+#
-+# All rights reserved.
-+#
-+# This program is free software; you can redistribute it and/or modify
-+# it under the terms of the GNU General Public License as published by
-+# the Free Software Foundation; either version 2 of the License, or
-+# (at your option) any later version.
-+#
-+# See the file LICENSE in the top level of this tarball.
-+#
-+
-+;
-+; $Id: init_data_fxs.cmd 540 2006-03-01 12:30:36Z oron $
-+;
-+; SLICS CMD Reg High Low
-+
-+; ----------------------------------==== 8-channel FXS unit initialization ===-----------------------------------------
-+; INTERNAL PS
-+; Change SLICs states to "Open state"s (Off,all transfers tristated to avoid data collision), Voltage sense
-+
-+FF 00 00 00 WD 40 00
-+FF 00 00 00 WD 6C 01
-+
-+; ------------------------------------- Initialization of indirect registers ------------------------------------------
-+
-+FF 00 00 00 WI 00 55 C2
-+FF 00 00 00 WI 01 51 E6
-+FF 00 00 00 WI 02 4B 85
-+FF 00 00 00 WI 03 49 37
-+
-+FF 00 00 00 WI 04 33 33
-+FF 00 00 00 WI 05 02 02
-+FF 00 00 00 WI 06 02 02
-+FF 00 00 00 WI 07 01 98
-+
-+FF 00 00 00 WI 08 01 98
-+FF 00 00 00 WI 09 06 11
-+FF 00 00 00 WI 0A 02 02
-+FF 00 00 00 WI 0B 00 E5
-+
-+FF 00 00 00 WI 0C 0A 1C
-+FF 00 00 00 WI 0D 7B 30
-+FF 00 00 00 WI 0E 00 63
-+FF 00 00 00 WI 0F 00 00
-+
-+FF 00 00 00 WI 10 78 70
-+FF 00 00 00 WI 11 00 7D
-+FF 00 00 00 WI 12 00 00
-+FF 00 00 00 WI 13 00 00
-+
-+FF 00 00 00 WI 14 7E F0
-+FF 00 00 00 WI 15 01 60
-+FF 00 00 00 WI 16 00 00
-+FF 00 00 00 WI 17 20 00
-+
-+FF 00 00 00 WI 18 20 00
-+FF 00 00 00 WI 19 00 00
-+FF 00 00 00 WI 1A 40 00
-+FF 00 00 00 WI 1B 40 00
-+
-+FF 00 00 00 WI 1C 18 00
-+FF 00 00 00 WI 1D 40 00
-+FF 00 00 00 WI 1E 10 00
-+FF 00 00 00 WI 1F 00 80
-+
-+FF 00 00 00 WI 20 0F F4
-+FF 00 00 00 WI 21 6E 7E
-+FF 00 00 00 WI 22 0F F4
-+FF 00 00 00 WI 23 88 00
-+
-+FF 00 00 00 WI 24 03 20
-+FF 00 00 00 WI 25 00 12
-+FF 00 00 00 WI 26 00 12
-+FF 00 00 00 WI 27 00 12
-+
-+FF 00 00 00 WI 28 0C 00
-+FF 00 00 00 WI 29 0C 00
-+FF 00 00 00 WI 2B 08 00
-+
-+FF 00 00 00 WI 63 00 DA
-+FF 00 00 00 WI 64 6B 60
-+FF 00 00 00 WI 65 00 74
-+FF 00 00 00 WI 66 79 C0
-+
-+FF 00 00 00 WI 67 11 20
-+FF 00 00 00 WI 68 3B E0
-+
-+; ------------------------------------- Initialization of direct registers --------------------------------------------
-+
-+; Mode(8-bit,u-Law,1 PCLK ) setting, Loopbacks and Interrupts clear
-+
-+FF 00 00 00 WD 01 29
-+FF 00 00 00 WD 08 00
-+FF 00 00 00 WD 09 00
-+FF 00 00 00 WD 0E 00
-+
-+FF 00 00 00 WD 15 00
-+FF 00 00 00 WD 16 03
-+FF 00 00 00 WD 17 00
-+FF 00 00 00 WD 12 FF
-+FF 00 00 00 WD 13 FF
-+FF 00 00 00 WD 14 FF
-+
-+; Automatic/Manual Control:
-+; Manual BATL/BATH select. NOTE: bit 08 switches VBAT to Low AND to High!
-+FF 00 00 00 WD 43 16
-+
-+FF 00 00 00 WD 4A 31
-+FF 00 00 00 WD 4B 10
-+
-+; Battery Feed Control: Battery low (DCSW low)
-+FF 00 00 00 WD 42 00
-+
-+; Slic Calibration
-+FF 00 00 00 WD 61 1F
-+FF 00 00 00 WD 60 5F
-+
-+; Loop Closure Debounce Interval
-+FF 00 00 00 WD 45 0A
-+
-+; Ring Detect Debounce Interval
-+FF 00 00 00 WD 46 0B
-+
-+; Loop Current Limit
-+; 23 milliampere for line current
-+FF 00 00 00 WD 47 01
-+
-+; Setting of SLICs offsets
-+
-+# New card initialization
-+01 00 00 00 WD 02 00
-+01 00 00 00 WD 03 00
-+01 00 00 00 WD 04 00
-+01 00 00 00 WD 05 00
-+
-+02 00 00 00 WD 02 08
-+02 00 00 00 WD 03 00
-+02 00 00 00 WD 04 08
-+02 00 00 00 WD 05 00
-+
-+04 00 00 00 WD 02 10
-+04 00 00 00 WD 03 00
-+04 00 00 00 WD 04 10
-+04 00 00 00 WD 05 00
-+
-+08 00 00 00 WD 02 18
-+08 00 00 00 WD 03 00
-+08 00 00 00 WD 04 18
-+08 00 00 00 WD 05 00
-+
-+10 00 00 00 WD 02 20
-+10 00 00 00 WD 03 00
-+10 00 00 00 WD 04 20
-+10 00 00 00 WD 05 00
-+
-+20 00 00 00 WD 02 28
-+20 00 00 00 WD 03 00
-+20 00 00 00 WD 04 28
-+20 00 00 00 WD 05 00
-+
-+40 00 00 00 WD 02 30
-+40 00 00 00 WD 03 00
-+40 00 00 00 WD 04 30
-+40 00 00 00 WD 05 00
-+
-+80 00 00 00 WD 02 38
-+80 00 00 00 WD 03 00
-+80 00 00 00 WD 04 38
-+80 00 00 00 WD 05 00
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/init_data_4_19.cmd zaptel-xpp-LJNBCn_dist/xpp/init_data_4_19.cmd
---- zaptel-1.2.6/xpp/init_data_4_19.cmd 1970-01-01 02:00:00.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/init_data_4_19.cmd 2006-04-27 16:03:25.463235000 +0300
-@@ -0,0 +1,69 @@
-+#
-+# Written by Oron Peled <oron at actcom.co.il>
-+# Copyright (C) 2006, Xorcom
-+#
-+# All rights reserved.
-+#
-+# This program is free software; you can redistribute it and/or modify
-+# it under the terms of the GNU General Public License as published by
-+# the Free Software Foundation; either version 2 of the License, or
-+# (at your option) any later version.
-+#
-+# See the file LICENSE in the top level of this tarball.
-+#
-+
-+;
-+; $Id: init_data_fxo.cmd 540 2006-03-01 12:30:36Z oron $
-+;
-+; DAA's CMD Reg High Low
-+
-+; ----------------------------------==== 8-channel FXO unit initialization ===-----------------------------------------
-+
-+FF FF 00 00 WD 21 28
-+FF FF 00 00 WD 18 99
-+FF FF 00 00 WD 06 00
-+
-+; ----------- DAA PCM start offset ----------
-+
-+01 00 00 00 WD 22 01
-+01 00 00 00 WD 23 00
-+01 00 00 00 WD 24 01
-+01 00 00 00 WD 25 00
-+
-+02 00 00 00 WD 22 09
-+02 00 00 00 WD 23 00
-+02 00 00 00 WD 24 09
-+02 00 00 00 WD 25 00
-+
-+04 00 00 00 WD 22 11
-+04 00 00 00 WD 23 00
-+04 00 00 00 WD 24 11
-+04 00 00 00 WD 25 00
-+
-+08 00 00 00 WD 22 19
-+08 00 00 00 WD 23 00
-+08 00 00 00 WD 24 19
-+08 00 00 00 WD 25 00
-+
-+10 00 00 00 WD 22 21
-+10 00 00 00 WD 23 00
-+10 00 00 00 WD 24 21
-+10 00 00 00 WD 25 00
-+
-+20 00 00 00 WD 22 29
-+20 00 00 00 WD 23 00
-+20 00 00 00 WD 24 29
-+20 00 00 00 WD 25 00
-+
-+40 00 00 00 WD 22 31
-+40 00 00 00 WD 23 00
-+40 00 00 00 WD 24 31
-+40 00 00 00 WD 25 00
-+
-+80 00 00 00 WD 22 39
-+80 00 00 00 WD 23 00
-+80 00 00 00 WD 24 39
-+80 00 00 00 WD 25 00
-+
-+; ----------- DAA ONHOOK --------------------
-+FF FF 00 00 WD 05 00
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/init_data_4_20.cmd zaptel-xpp-LJNBCn_dist/xpp/init_data_4_20.cmd
---- zaptel-1.2.6/xpp/init_data_4_20.cmd 1970-01-01 02:00:00.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/init_data_4_20.cmd 2006-07-05 16:28:42.355959000 +0300
-@@ -0,0 +1,60 @@
-+#
-+# Written by Oron Peled <oron at actcom.co.il>
-+# Copyright (C) 2006, Xorcom
-+#
-+# All rights reserved.
-+#
-+# This program is free software; you can redistribute it and/or modify
-+# it under the terms of the GNU General Public License as published by
-+# the Free Software Foundation; either version 2 of the License, or
-+# (at your option) any later version.
-+#
-+# See the file LICENSE in the top level of this tarball.
-+#
-+
-+;
-+; $Id: init_data_fxo.cmd 540 2006-03-01 12:30:36Z oron $
-+;
-+; DAA's CMD Reg High Low
-+
-+; Start with a software reset:
-+FF FF 00 00 WD 01 80
-+
-+; ----------------------------------==== 8-channel FXO unit initialization ===-----------------------------------------
-+
-+FF FF 00 00 WD 21 28
-+; 99 also sets ring validation
-+;FF FF 00 00 WD 18 99
-+FF FF 00 00 WD 06 00
-+
-+; ----------- DAA PCM start offset ----------
-+
-+FF FF 00 00 WD 23 00
-+FF FF 00 00 WD 25 00
-+
-+01 00 00 00 WD 22 00
-+01 00 00 00 WD 24 00
-+
-+02 00 00 00 WD 22 08
-+02 00 00 00 WD 24 08
-+
-+04 00 00 00 WD 22 10
-+04 00 00 00 WD 24 10
-+
-+08 00 00 00 WD 22 18
-+08 00 00 00 WD 24 18
-+
-+10 00 00 00 WD 22 20
-+10 00 00 00 WD 24 20
-+
-+20 00 00 00 WD 22 28
-+20 00 00 00 WD 24 28
-+
-+40 00 00 00 WD 22 30
-+40 00 00 00 WD 24 30
-+
-+80 00 00 00 WD 22 38
-+80 00 00 00 WD 24 38
-+
-+; ----------- DAA ONHOOK --------------------
-+FF FF 00 00 WD 05 08
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/initialize_registers zaptel-xpp-LJNBCn_dist/xpp/initialize_registers
---- zaptel-1.2.6/xpp/initialize_registers 1970-01-01 02:00:00.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/initialize_registers 2006-05-01 12:49:12.732258000 +0300
-@@ -0,0 +1,39 @@
-+#! /bin/sh
-+# XPD_BUS - bus name
-+# XPD_NAME - xpd name
-+# XPD_TYPE - xpd type number (from protocol reply):
-+# 3 - FXS
-+# 4 - FXO
-+# XPD_REVISION - xpd revision number
-+
-+set -e
-+
-+LOGGER="logger -i -t `basename $0`"
-+
-+INIT_DIR=`dirname $0`
-+BASE=/proc/xpp
-+
-+SLICS="$BASE/$XPD_BUS/$XPD_NAME/slics"
-+FILE="$INIT_DIR/init_data_${XPD_TYPE}_${XPD_REVISION}.cmd"
-+
-+if [ ! -f "$SLICS" ]; then
-+ $LOGGER "missing slics file '$SLICS'"
-+ exit 1
-+fi
-+
-+if [ ! -f "$FILE" ]; then
-+ $LOGGER "missing register initialization file '$FILE'"
-+ exit 1
-+fi
-+
-+case "$XPD_TYPE" in
-+3|4)
-+ cat "$FILE" > "$SLICS"
-+ ;;
-+*)
-+ $LOGGER "Unknown type '$XPD_TYPE'"
-+ exit 2
-+esac
-+$LOGGER "Wrote '$FILE' into '$SLICS'"
-+
-+exit 0
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/LICENSE.firmware zaptel-xpp-LJNBCn_dist/xpp/LICENSE.firmware
---- zaptel-1.2.6/xpp/LICENSE.firmware 1970-01-01 02:00:00.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/LICENSE.firmware 2006-05-01 22:45:43.558912000 +0300
-@@ -0,0 +1,37 @@
-+The firmware files (*.hex) in this directory are software for the
-+Astribank itself and not intended to run on the Linux system itself.
-+They are generally freely distriributable (see exact terms below).
-+
-+/****************************************************************************/
-+/* Copyright (c) 2004-2006 Xorcom Inc. All Rights Reserved. */
-+/* Redistribution and use of the microcode software ( Firmware ) is */
-+/* permitted provided that the following conditions are met: */
-+/* */
-+/* 1. Firmware is redistributed verbatim without any modification; */
-+/* 2. Any reproduction of Firmware must contain the above */
-+/* copyright notice, this list of conditions and the below */
-+/* disclaimer in the documentation and/or other materials */
-+/* provided with the distribution; and */
-+/* 3. The name of Xorcom may not be used to endorse or promote */
-+/* products derived from this Firmware without specific prior */
-+/* written consent. */
-+/* */
-+/* Disclaimer: Xorcom provides this firmware "as is" with no warranties */
-+/* or indemnities whatsoever. Xorcom expressly disclaims any express, */
-+/* statutory or implied warranties, including, but not limited to, the */
-+/* implied warranties of merchantability, fitness for a particular */
-+/* purpose and non-infringement. In no event shall Xorcom be liable for */
-+/* any direct, indirect, incidental, special, exemplary, or consequential */
-+/* damages (including, but not limited to, procurement of substitute */
-+/* goods or services; loss of use, data, or profits; or business */
-+/* interruption) however caused and on any theory of liability, whether */
-+/* in contract, strict liability, or tort (including negligence or */
-+/* otherwise) arising in any way out of the use of this firmware, even */
-+/* if advised of the possibility of such damage. User acknowledges and */
-+/* agrees that the purchase or use of the firmware will not create or */
-+/* give grounds for a license by implication, estoppel, or otherwise in */
-+/* any intellectual property rights (patent, copyright, trade secret, */
-+/* mask work, or other proprietary right) embodied in any other Xorcom */
-+/* hardware or firmware either solely or in combination with the firmware. */
-+/****************************************************************************/
-+
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/Makefile zaptel-xpp-LJNBCn_dist/xpp/Makefile
---- zaptel-1.2.6/xpp/Makefile 2006-02-15 04:24:18.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/Makefile 2006-07-02 17:17:18.812352000 +0300
-@@ -1,5 +1,9 @@
--EXTRA_CFLAGS = -I$(src)/.. -DSOFT_SIMULATOR=0
-+EXTRA_CFLAGS = -I$(SUBDIRS) -DDEBUG -DPOLL_DIGITAL_INPUTS -DWITH_ECHO_SUPPRESSION -DXPP_EC_CHUNK -DWITH_RBS
-
--obj-m = xpd_fxs.o xpp.o xpp_usb.o
--xpp-y += xproto.o card_global.o xpp_zap.o zap_debug.o
--xpd_fxs-y += card_fxs.o slic.o
-+obj-m = xpp.o xpp_usb.o xpd_fxs.o xpd_fxo.o
-+xpp-y += xbus-core.o xpp_zap.o xproto.o card_global.o
-+xpd_fxs-y += card_fxs.o slic.o
-+xpd_fxo-y += card_fxo.o slic.o
-+
-+ctags:
-+ ctags *.[ch]
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/README.Astribank zaptel-xpp-LJNBCn_dist/xpp/README.Astribank
---- zaptel-1.2.6/xpp/README.Astribank 2006-03-03 21:11:53.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/README.Astribank 2006-06-19 11:29:10.334411000 +0300
-@@ -5,15 +5,63 @@
- Building and Installation:
- """""""""""""""""""""""""
- Building and installation is basically like the normal procedure of
--installing Zaptel. Follow the rest of the documentation here.
-+installing Zaptel with some additions.
-
--In addition, the file xpp/xpp_modprobe contains modprobe settings. It
--should be copied verbatim into /etc/modprobe.conf or (better) copied to
--/etc/modprobe.d/ . If you fail to do so, xpp_usb.ko will fail to load
--xpd_fxs.ko and as a result will not detect your Astribank.
--
--Loading Firmware
-+Building drivers:
- """"""""""""""""
-+From the toplevel zaptel directory run a command similar to (I used line
-+continuation to prevent line wrapping):
-+
-+ $ make \
-+ KSRC=/usr/src/kernel-headers-2.6.12-1-386 \
-+ KVERS=2.6.12-1-386 \
-+ XPPMOD=xpp/ \
-+ EC_TYPE=CAN_KB1
-+
-+ - The KSRC= points to a configured kernel source tree.
-+ - The KVERS= should match the relevant tree version.
-+ - The XPPMOD= instructs the Zaptel Makefile to descend into the xpp/
-+ subdirectory. The slash (/) in the end is mandatory.
-+ - The EC_TYPE= select the echo canceler.
-+
-+Building firmware utilities:
-+"""""""""""""""""""""""""""
-+Then you should compile the firmware loading utilities. Simply go
-+to the zaptel/xpp/utils and run make.
-+
-+Those who don't use prepackaged drivers should make sure they also
-+install the (externally available) fxload utility.
-+
-+Installation:
-+""""""""""""
-+
-+apart from the standard 'make install' in the zaptel directory,
-+run:
-+
-+ make -C xpp/utils install
-+
-+Alternatively, do the following manually:
-+
-+All firmware files should be copied to a new directory:
-+ /usr/share/zaptel/
-+
-+The xpp_fxloader and xpp_fxloader.usbmap should be copied to:
-+ /etc/hotplug/usb/
-+
-+In addition, the file xpp/xpp_modprobe contains optional modprobe settings.
-+It may be copied verbatim into /etc/modprobe.conf or (better) copied to
-+/etc/modprobe.d/ .
-+
-+
-+Note that loading through udev is not yet provided. Run
-+
-+ /etc/hotplug/usb/xpp_fxloader xppdetect
-+
-+to load firmware.
-+
-+
-+Loading Firmware Details:
-+""""""""""""""""""""""""
- The Astribank needs a firmware loaded into it. Without the firmware,
- the device will appear in lsusb with vendor ID 04b4 and product ID 8613
- The firmware is provided in the Intel hex format. It can be loaded using
-@@ -21,12 +69,11 @@
- 'hotplug-utils' .
-
- To load the firmware automatically using the standard hotplug script,
--place xpp/xpp_fxloader and xpp/xpp_fxloader.usermap in /etc/hotplug/usb
--and place xpp/FPGA_XPD.hex in /etc/xortel (or edit xpp_fxloader
--accordingly).
-+place xpp/utils/xpp_fxloader and xpp/utils/xpp_fxloader.usermap in
-+/etc/hotplug/usb and place xpp/utils/*.hex in /usr/share/zaptel .
-
- Alternatively, xpp_fxloader when given the parameter 'xppdetect' will load
--the firmware from /etc/xortel/FPGA_XPD.hex . You can use it to load the
-+the firmwares from /usr/share/zaptel/ . You can use it to load the
- firmware manually.
-
- You should then get in lsusb the vendor ID e4e4 and device ID 2121
-@@ -128,6 +175,25 @@
- (There are a bunch of other status files under /proc/xpp/ )
-
-
-+Useful Module Parameters:
-+""""""""""""""""""""""""
-+zap_autoreg: (xpp)
-+Register spans automatically (1) or not (0). Default: 1.
-+Unsetting this could be useful if you have several Astribanks and you
-+want to set their registration order manually using zt_registration in
-+the /proc interface.
-+
-+initialize_registers (xpd_fxs)
-+The script that is run to initilize registers of the device. The default is
-+/usr/share/zaptel/initialize_registers .
-+Setting this value could be useful if that location is inconvient for you.
-+
-+print_dbg: (all modules)
-+It will make the driver print tons of debugging messages. Can be sometime
-+even handy, but overly-verbose in the case of xpp_usb. Can be safely
-+set/unset at run-time using /sys/modules .
-+
-+
-
- BTW: XPP here does not stand for X Printing Panel, XML Pull Parser,
- X-Windows Phase Plane or XML Professional Publisher. It is simply the
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/slic.c zaptel-xpp-LJNBCn_dist/xpp/slic.c
---- zaptel-1.2.6/xpp/slic.c 2006-02-15 04:24:18.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/slic.c 2006-05-01 12:37:15.907543000 +0300
-@@ -1,6 +1,6 @@
- /*
- * Written by Oron Peled <oron at actcom.co.il>
-- * Copyright (C) 2004-2005, Xorcom
-+ * Copyright (C) 2004-2006, Xorcom
- *
- * All rights reserved.
- *
-@@ -23,13 +23,16 @@
- #include "xproto.h"
- #include "slic.h"
-
--static const char rcsid[] = "$Id: slic.c 949 2006-02-15 02:24:18Z kpfleming $";
-+static const char rcsid[] = "$Id: slic.c 1097 2006-05-01 09:37:15Z oron $";
-
- #ifdef __KERNEL__
- #include <linux/module.h>
-
- extern int print_dbg;
- #include "zap_debug.h"
-+
-+DEF_PARM(charp,initialize_registers, "/usr/share/zaptel/initialize_registers", "The script to initialize detected cards slics");
-+
- #else
- #include <stdio.h>
- #endif
-@@ -120,6 +123,50 @@
-
- #ifdef __KERNEL__
-
-+#define MAX_ENV_STR 20
-+
-+int run_initialize_registers(xpd_t *xpd)
-+{
-+ int ret;
-+ xbus_t *xbus;
-+ char busstr[MAX_ENV_STR];
-+ char xpdstr[MAX_ENV_STR];
-+ char typestr[MAX_ENV_STR];
-+ char revstr[MAX_ENV_STR];
-+ char *argv[] = {
-+ initialize_registers,
-+ NULL
-+ };
-+ char *envp[] = {
-+ busstr,
-+ xpdstr,
-+ typestr,
-+ revstr,
-+ NULL
-+ };
-+
-+ BUG_ON(!xpd);
-+ xbus = xpd->xbus;
-+ if(!initialize_registers || !initialize_registers[0]) {
-+ NOTICE("%s/%s: No runtime register initialization\n", xbus->busname, xpd->xpdname);
-+ return 0;
-+ }
-+ DBG("%s/%s: running: '%s'\n", xbus->busname, xpd->xpdname, initialize_registers);
-+ snprintf(busstr, MAX_ENV_STR, "XPD_BUS=%s", xbus->busname);
-+ snprintf(xpdstr, MAX_ENV_STR, "XPD_NAME=%s", xpd->xpdname);
-+ snprintf(typestr, MAX_ENV_STR, "XPD_TYPE=%d", xpd->type);
-+ snprintf(revstr, MAX_ENV_STR, "XPD_REVISION=%d", xpd->revision);
-+ DBG("%s/%s: type=%d revision=%d\n", xbus->busname, xpd->xpdname, xpd->type, xpd->revision);
-+ ret = call_usermodehelper(initialize_registers, argv, envp, 1);
-+ if(ret != 0) {
-+ ERR("%s/%s: Failed running '%s' (errno %d, sig=%d)\n",
-+ xbus->busname, xpd->xpdname, initialize_registers,
-+ ((unsigned)ret >> 8) & 0xFF, ret & 0xFF);
-+ ret = -EFAULT;
-+ }
-+ return ret;
-+}
-+
- EXPORT_SYMBOL(slic_cmd_direct_write);
- EXPORT_SYMBOL(slic_cmd_direct_read);
- EXPORT_SYMBOL(slic_cmd_indirect_write);
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/slic.h zaptel-xpp-LJNBCn_dist/xpp/slic.h
---- zaptel-1.2.6/xpp/slic.h 2006-02-15 04:24:18.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/slic.h 2006-07-02 17:17:18.812352000 +0300
-@@ -1,5 +1,26 @@
- #ifndef SLIC_H
- #define SLIC_H
-+/*
-+ * Written by Oron Peled <oron at actcom.co.il>
-+ * Copyright (C) 2004-2006, Xorcom
-+ *
-+ * All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ */
-
- #include "xdefs.h"
-
-@@ -46,12 +67,6 @@
- (slic_reg)->reg_data = data; \
- } while(0);
-
--/* OLD SLIC_INIT data */
--typedef struct slic_data {
-- byte len;
-- byte data[40];
--} __attribute__((packed)) slic_data_t;
--
-
- /*------------------------------ SLIC Initializers -------------------------*/
-
-@@ -60,6 +75,7 @@
- int slic_cmd_indirect_write(slic_cmd_t *sc, xpp_line_t lines, byte reg, byte data_low, byte data_high);
- int slic_cmd_indirect_read(slic_cmd_t *sc, xpp_line_t lines, byte reg);
- void dump_slic_cmd(const char msg[], slic_cmd_t *sc);
-+int run_initialize_registers(xpd_t *xpd);
-
-
- #endif /* SLIC_H */
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/slic_init.inc zaptel-xpp-LJNBCn_dist/xpp/slic_init.inc
---- zaptel-1.2.6/xpp/slic_init.inc 2006-02-15 04:24:18.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/slic_init.inc 1970-01-01 02:00:00.000000000 +0200
-@@ -1,65 +0,0 @@
--// ----------------------------------==== 8-channel FXS unit initialization ===-----------------------------------------
--
--// INTERNAL PS
--// Change SLICs states to "Open state"s (Off,all transfers tristated to avoid data collision), Voltage sense
--S_(0x000000FF, 0x04, 0x40, 0x00, 0x6C, 0x01),
--
--
--// ------------------------------------- Initialization of indirect registers ------------------------------------------
--S_(0x000000FF, 0x02, 0x40, 0x00),
--S_(0x000000FF, 0x18, 0x1C, 0xC2, 0x1D, 0x55, 0x1E, 0x00, 0x1C, 0xE6, 0x1D, 0x51, 0x1E, 0x01, 0x1C, 0x85, 0x1D, 0x4B, 0x1E, 0x02, 0x1C, 0x37, 0x1D, 0x49, 0x1E, 0x03),
--S_(0x000000FF, 0x18, 0x1C, 0x33, 0x1D, 0x33, 0x1E, 0x04, 0x1C, 0x02, 0x1D, 0x02, 0x1E, 0x05, 0x1C, 0x02, 0x1D, 0x02, 0x1E, 0x06, 0x1C, 0x98, 0x1D, 0x01, 0x1E, 0x07),
--S_(0x000000FF, 0x18, 0x1C, 0x98, 0x1D, 0x01, 0x1E, 0x08, 0x1C, 0x11, 0x1D, 0x06, 0x1E, 0x09, 0x1C, 0x02, 0x1D, 0x02, 0x1E, 0x0A, 0x1C, 0xE5, 0x1D, 0x00, 0x1E, 0x0B),
--S_(0x000000FF, 0x18, 0x1C, 0x1C, 0x1D, 0x0A, 0x1E, 0x0C, 0x1C, 0x30, 0x1D, 0x7B, 0x1E, 0x0D, 0x1C, 0x63, 0x1D, 0x00, 0x1E, 0x0E, 0x1C, 0x00, 0x1D, 0x00, 0x1E, 0x0F),
--
--S_(0x000000FF, 0x18, 0x1C, 0x70, 0x1D, 0x78, 0x1E, 0x10, 0x1C, 0x7D, 0x1D, 0x00, 0x1E, 0x11, 0x1C, 0x00, 0x1D, 0x00, 0x1E, 0x12, 0x1C, 0x00, 0x1D, 0x00, 0x1E, 0x13),
--S_(0x000000FF, 0x18, 0x1C, 0xF0, 0x1D, 0x7E, 0x1E, 0x14, 0x1C, 0x60, 0x1D, 0x01, 0x1E, 0x15, 0x1C, 0x00, 0x1D, 0x00, 0x1E, 0x16, 0x1C, 0x00, 0x1D, 0x20, 0x1E, 0x17),
--S_(0x000000FF, 0x18, 0x1C, 0x00, 0x1D, 0x20, 0x1E, 0x18, 0x1C, 0x00, 0x1D, 0x00, 0x1E, 0x19, 0x1C, 0x00, 0x1D, 0x40, 0x1E, 0x1A, 0x1C, 0x00, 0x1D, 0x40, 0x1E, 0x1B),
--S_(0x000000FF, 0x18, 0x1C, 0x00, 0x1D, 0x18, 0x1E, 0x1C, 0x1C, 0x00, 0x1D, 0x40, 0x1E, 0x1D, 0x1C, 0x00, 0x1D, 0x10, 0x1E, 0x1E, 0x1C, 0x80, 0x1D, 0x00, 0x1E, 0x1F),
--
--S_(0x000000FF, 0x18, 0x1C, 0xF4, 0x1D, 0x0F, 0x1E, 0x20, 0x1C, 0x7E, 0x1D, 0x6E, 0x1E, 0x21, 0x1C, 0xF4, 0x1D, 0x0F, 0x1E, 0x22, 0x1C, 0x00, 0x1D, 0x88, 0x1E, 0x23),
--S_(0x000000FF, 0x18, 0x1C, 0x20, 0x1D, 0x03, 0x1E, 0x24, 0x1C, 0x12, 0x1D, 0x00, 0x1E, 0x25, 0x1C, 0x12, 0x1D, 0x00, 0x1E, 0x26, 0x1C, 0x12, 0x1D, 0x00, 0x1E, 0x27),
--S_(0x000000FF, 0x12, 0x1C, 0x00, 0x1D, 0x0C, 0x1E, 0x28, 0x1C, 0x00, 0x1D, 0x0C, 0x1E, 0x29, 0x1C, 0x00, 0x1D, 0x08, 0x1E, 0x2B),
--
--S_(0x000000FF, 0x18, 0x1C, 0xDA, 0x1D, 0x00, 0x1E, 0x63, 0x1C, 0x60, 0x1D, 0x6B, 0x1E, 0x64, 0x1C, 0x74, 0x1D, 0x00, 0x1E, 0x65, 0x1C, 0xC0, 0x1D, 0x79, 0x1E, 0x66),
--S_(0x000000FF, 0x0C, 0x1C, 0x20, 0x1D, 0x11, 0x1E, 0x67, 0x1C, 0xE0, 0x1D, 0x3B, 0x1E, 0x68),
--
--// ------------------------------------- Initialization of direct registers --------------------------------------------
--
--// Mode(8-bit,u-Law,1 PCLK ) setting, Loopbacks and Interrupts clear
--// --Temporary digital loopback
--S_(0x000000FF, 0x08, 0x01, 0x29, 0x08, 0x00, 0x09, 0x00, 0x0E, 0x00),
--S_(0x000000FF, 0x0C, 0x15, 0x00, 0x16, 0x03, 0x17, 0x00, 0x12, 0xFF, 0x13, 0xFF, 0x14, 0xFF),
--
--// Ring timers settings
--S_(0x000000FF, 0x06, 0x30, 0x80, 0x31, 0x3E, 0x32, 0x80),
--S_(0x000000FF, 0x02, 0x33, 0x3E),
--S_(0x000000FF, 0x02, 0x22, 0x18),
--
--// Battery feed control(DCSW), Automatic control of Ring Trip and Loop Closure, VBATH, VBATL
--S_(0x000000FF, 0x02, 0x42, 0x00),
--S_(0x000000FF, 0x02, 0x43, 0x1E),
--S_(0x000000FF, 0x04, 0x4A, 0x31, 0x4B, 0x10),
--
--S_(0x000000FF, 0x02, 0x45, 0x0A),
--S_(0x000000FF, 0x02, 0x46, 0x0B),
--S_(0x000000FF, 0x02, 0x47, 0x07),
--
--
--// Setting of SLICs offsets
--S_(0x00000001, 0x08, 0x02, 0x01, 0x03, 0x00, 0x04, 0x01, 0x05, 0x00),
--S_(0x00000002, 0x08, 0x02, 0x09, 0x03, 0x00, 0x04, 0x09, 0x05, 0x00),
--S_(0x00000004, 0x08, 0x02, 0x11, 0x03, 0x00, 0x04, 0x11, 0x05, 0x00),
--S_(0x00000008, 0x08, 0x02, 0x19, 0x03, 0x00, 0x04, 0x19, 0x05, 0x00),
--S_(0x00000010, 0x08, 0x02, 0x21, 0x03, 0x00, 0x04, 0x21, 0x05, 0x00),
--S_(0x00000020, 0x08, 0x02, 0x29, 0x03, 0x00, 0x04, 0x29, 0x05, 0x00),
--S_(0x00000040, 0x08, 0x02, 0x31, 0x03, 0x00, 0x04, 0x31, 0x05, 0x00),
--S_(0x00000080, 0x08, 0x02, 0x39, 0x03, 0x00, 0x04, 0x39, 0x05, 0x00),
--
--// Change SLICs states to "Normal state"s (On, after offsets are set already)
--
--
--S_(0x000000FF, 0x02, 0x40, 0x1),
--S_(0x000000FF, 0x02, 0x42, 0x06),
--// -------------------------------------------------------------
--
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/supress/ec_xpp.h zaptel-xpp-LJNBCn_dist/xpp/supress/ec_xpp.h
---- zaptel-1.2.6/xpp/supress/ec_xpp.h 1970-01-01 02:00:00.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/supress/ec_xpp.h 2006-06-25 14:42:21.798100000 +0300
-@@ -0,0 +1,100 @@
-+#ifndef __EC_XPP_H__
-+#define __EC_XPP_H__
-+
-+#ifdef __KERNEL__
-+# include <linux/kernel.h>
-+# include <linux/slab.h>
-+# define EC_MALLOC(a) kmalloc((a), GFP_ATOMIC)
-+# define EC_FREE(a) kfree(a)
-+# define printf printk
-+#else
-+# include <stdlib.h>
-+# include <unistd.h>
-+# include <stdint.h>
-+# include <string.h>
-+#include <math.h>
-+# define EC_MALLOC(a) malloc(a)
-+# define EC_FREE(a) free(a)
-+#endif
-+
-+#include "suppressor.c"
-+
-+typedef struct {
-+#define XPP_EC_MAGIC 0xfee1dead
-+ int magic;
-+ int objSize;
-+ void* pEchoSuppressionObj;
-+} xpp_echo_can_state_t;
-+
-+static inline echo_can_state_t* xpp_echo_can_create(int len, int adaption_mode)
-+{
-+ xpp_echo_can_state_t *state;
-+ ES_WINDOW_SIZE_ID currentWindowId;
-+
-+ DBG("EC: len=%d adaption_mode=%d\n", len, adaption_mode);
-+ switch (len) {
-+ case 32: currentWindowId = ES_WINDOW_SIZE_ID_32_MSEC; break;
-+ case 64: currentWindowId = ES_WINDOW_SIZE_ID_64_MSEC; break;
-+ case 128: currentWindowId = ES_WINDOW_SIZE_ID_128_MSEC; break;
-+ case 256: currentWindowId = ES_WINDOW_SIZE_ID_256_MSEC; break;
-+ default:
-+ NOTICE("%s: Unknown len=%d\n", __FUNCTION__, len);
-+ currentWindowId = ES_WINDOW_SIZE_ID_64_MSEC; break;
-+ }
-+
-+ if ( 0 == (state = EC_MALLOC(sizeof(*state)) ))
-+ return NULL;
-+
-+ if (0 > (state->objSize = ES_GetObjectSize(currentWindowId))){
-+ EC_FREE(state);
-+ return NULL;
-+ }
-+
-+ if (NULL == (state->pEchoSuppressionObj = EC_MALLOC(state->objSize))) {
-+ EC_FREE(state);
-+ return NULL;
-+ }
-+
-+ if ( !ES_Initialize(state->pEchoSuppressionObj, currentWindowId, ES_HYBRID_LOSS_LEVEL_6_DB)){
-+ EC_FREE(state->pEchoSuppressionObj);
-+ EC_FREE(state);
-+ return NULL;
-+ }
-+ state->magic = XPP_EC_MAGIC;
-+ return (echo_can_state_t *)state;
-+}
-+
-+static inline void xpp_echo_can_free(echo_can_state_t *ec)
-+{
-+ xpp_echo_can_state_t *mystate;
-+
-+ DBG("EC: %p\n", ec);
-+ if (!ec)
-+ return;
-+ mystate = (xpp_echo_can_state_t *)ec;
-+ if(mystate->magic != XPP_EC_MAGIC) {
-+ ERR("%s: corrupted EC\n", __FUNCTION__);
-+ return;
-+ }
-+ ES_Reset(mystate->pEchoSuppressionObj);
-+ EC_FREE(mystate);
-+}
-+
-+static inline int16_t xpp_echo_can_update(echo_can_state_t *ec, int16_t tx, int16_t rx)
-+{
-+ xpp_echo_can_state_t *mystate;
-+
-+ if(!ec) {
-+ ERR("%s: missing EC\n", __FUNCTION__);
-+ return -EINVAL;
-+ }
-+ mystate = (xpp_echo_can_state_t *)ec;
-+ if(mystate->magic != XPP_EC_MAGIC) {
-+ ERR("%s: corrupted EC\n", __FUNCTION__);
-+ return -EINVAL;
-+ }
-+ return ES_ProcessSamples(mystate->pEchoSuppressionObj, tx, rx);
-+}
-+
-+#endif
-+
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/supress/suppressor.c zaptel-xpp-LJNBCn_dist/xpp/supress/suppressor.c
---- zaptel-1.2.6/xpp/supress/suppressor.c 1970-01-01 02:00:00.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/supress/suppressor.c 2006-06-25 14:42:21.798100000 +0300
-@@ -0,0 +1,321 @@
-+ /***********************************************************************
-+ * Written by Sergey Serik.
-+ * Copyright (C) 2006, Xorcom Ltd.
-+ * All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ ***********************************************************************/
-+
-+
-+
-+#include "suppressor.h"
-+
-+#define PRINTF(fmt, ...)
-+
-+static inline ES_BOOL IsFirstMoreThanSecond(
-+ ES_LONG_VALUE* pFirstValue,
-+ ES_LONG_VALUE* pSecondValue)
-+{
-+ if( (pFirstValue->integer > pSecondValue->integer)
-+ || ( (pFirstValue->integer == pSecondValue->integer)
-+ && (pFirstValue->fractional > pSecondValue->fractional)))
-+ {
-+ return ES_TRUE;
-+ }
-+
-+ return ES_FALSE;
-+}
-+
-+
-+static inline ES_BOOL IsFirstLessThanSecond(
-+ ES_LONG_VALUE* pFirstValue,
-+ ES_LONG_VALUE* pSecondValue)
-+{
-+ if( (pFirstValue->integer < pSecondValue->integer)
-+ || ( (pFirstValue->integer == pSecondValue->integer)
-+ && (pFirstValue->fractional < pSecondValue->fractional)))
-+ {
-+ return ES_TRUE;
-+ }
-+
-+ return ES_FALSE;
-+}
-+
-+static inline ES_LONG_VALUE* MultiplyByFactor(
-+ ES_LONG_VALUE* pValue,
-+ ES_LONG_VALUE* pNewValue,
-+ int factor)
-+{
-+ pNewValue->integer = pValue->integer * factor + (pValue->fractional * factor) / ES_ALFA_INT;
-+ pNewValue->fractional = (pValue->fractional * factor) % ES_ALFA_INT;
-+
-+ return pNewValue;
-+}
-+
-+static inline int GetWindowSize(
-+ ES_WINDOW_SIZE_ID sizeId)
-+{
-+ switch(sizeId)
-+ {
-+ case ES_WINDOW_SIZE_ID_4_MSEC:
-+ return ES_SAMPLES_IN_4_MSEC;
-+
-+ case ES_WINDOW_SIZE_ID_8_MSEC:
-+ return ES_SAMPLES_IN_8_MSEC;
-+
-+ case ES_WINDOW_SIZE_ID_16_MSEC:
-+ return ES_SAMPLES_IN_16_MSEC;
-+
-+ case ES_WINDOW_SIZE_ID_32_MSEC:
-+ return ES_SAMPLES_IN_32_MSEC;
-+
-+ case ES_WINDOW_SIZE_ID_64_MSEC:
-+ return ES_SAMPLES_IN_64_MSEC;
-+
-+ case ES_WINDOW_SIZE_ID_128_MSEC:
-+ return ES_SAMPLES_IN_128_MSEC;
-+
-+ case ES_WINDOW_SIZE_ID_256_MSEC:
-+ return ES_SAMPLES_IN_256_MSEC;
-+
-+ default:
-+ PRINTF("GetWindowSize - error: unsupported Search Window Size ID <%d>\n", sizeId);
-+ return -1;
-+ }
-+}
-+
-+static inline void ObtainFarMaximum(
-+ SUPPRESSOR* pES_Obj)
-+{
-+ if(pES_Obj->tailIndex == pES_Obj->maximalFar.index)
-+ {
-+ if(IsFirstMoreThanSecond(&pES_Obj->maximalFar.value, &pES_Obj->previousFar))
-+ {
-+ int n;
-+
-+ memset(&pES_Obj->maximalFar, 0, sizeof(pES_Obj->maximalFar));
-+
-+ for(n = 0; n < pES_Obj->windowSize; n++)
-+ {
-+ if(IsFirstMoreThanSecond(&pES_Obj->pHistoryOfFar[n], &pES_Obj->maximalFar.value))
-+ {
-+ pES_Obj->maximalFar.value.integer = pES_Obj->pHistoryOfFar[n].integer;
-+ pES_Obj->maximalFar.value.fractional = pES_Obj->pHistoryOfFar[n].fractional;
-+ pES_Obj->maximalFar.index = n;
-+ }
-+ }
-+ }
-+ else
-+ {
-+ pES_Obj->maximalFar.value.integer = pES_Obj->previousFar.integer;
-+ pES_Obj->maximalFar.value.fractional = pES_Obj->previousFar.fractional;
-+ }
-+ }
-+ else if(IsFirstLessThanSecond(&pES_Obj->maximalFar.value, &pES_Obj->previousFar))
-+ {
-+ pES_Obj->maximalFar.value.integer = pES_Obj->previousFar.integer;
-+ pES_Obj->maximalFar.value.fractional = pES_Obj->previousFar.fractional;
-+ pES_Obj->maximalFar.index = pES_Obj->tailIndex;
-+ }
-+}
-+
-+int ES_GetObjectSize(
-+ ES_WINDOW_SIZE_ID sizeId)
-+{
-+ int longValueSize = sizeof(ES_LONG_VALUE);
-+ switch(sizeId)
-+ {
-+ case ES_WINDOW_SIZE_ID_4_MSEC:
-+ return (sizeof(SUPPRESSOR) + ES_SAMPLES_IN_4_MSEC * longValueSize - longValueSize);
-+
-+ case ES_WINDOW_SIZE_ID_8_MSEC:
-+ return (sizeof(SUPPRESSOR) + ES_SAMPLES_IN_8_MSEC * longValueSize - longValueSize);
-+
-+ case ES_WINDOW_SIZE_ID_16_MSEC:
-+ return (sizeof(SUPPRESSOR) + ES_SAMPLES_IN_16_MSEC * longValueSize - longValueSize);
-+
-+ case ES_WINDOW_SIZE_ID_32_MSEC:
-+ return (sizeof(SUPPRESSOR) + ES_SAMPLES_IN_32_MSEC * longValueSize - longValueSize);
-+
-+ case ES_WINDOW_SIZE_ID_64_MSEC:
-+ return (sizeof(SUPPRESSOR) + ES_SAMPLES_IN_64_MSEC * longValueSize - longValueSize);
-+
-+ case ES_WINDOW_SIZE_ID_128_MSEC:
-+ return (sizeof(SUPPRESSOR) + ES_SAMPLES_IN_128_MSEC * longValueSize - longValueSize);
-+
-+ case ES_WINDOW_SIZE_ID_256_MSEC:
-+ return (sizeof(SUPPRESSOR) + ES_SAMPLES_IN_256_MSEC * longValueSize - longValueSize);
-+
-+ default:
-+ PRINTF("ES_GetObjectSize - error: unsupported Search Window Size ID <%d>\n", sizeId);
-+ return -1;
-+ }
-+}
-+
-+ES_BOOL ES_Initialize(
-+ void* pObject,
-+ ES_WINDOW_SIZE_ID sizeId,
-+ ES_HYBRID_LOSS_LEVEL level)
-+{
-+ SUPPRESSOR* pES_Obj = (SUPPRESSOR*) pObject;
-+ int objectSize;
-+
-+ if(NULL == pES_Obj)
-+ {
-+ PRINTF("ES_Initialize - error: wrong pObject value <NULL>\n");
-+ return ES_FALSE;
-+ }
-+
-+ if(0 > (objectSize = ES_GetObjectSize(sizeId)))
-+ {
-+ PRINTF("ES_Initialize - error: on ES_GetObjectSize(%d) call\n", sizeId);
-+ pES_Obj->initialized = ES_FALSE;
-+ return ES_FALSE;
-+ }
-+
-+ memset(pES_Obj, 0, objectSize);
-+
-+ switch(level)
-+ {
-+ case ES_HYBRID_LOSS_LEVEL_0_DB:
-+ pES_Obj->comparer.factorNear = ES_COMPARE_MULTI_0_DB_NEAR;
-+ pES_Obj->comparer.factorFar = ES_COMPARE_MULTI_0_DB_FAR;
-+ pES_Obj->doubleTalkDetectionCountMax = ES_MAX_DTD_COUNT_0_DB;
-+ pES_Obj->echoDetectionCountMax = ES_MAX_DTD_COUNT_0_DB;
-+ break;
-+
-+ case ES_HYBRID_LOSS_LEVEL_3_DB:
-+ pES_Obj->comparer.factorNear = ES_COMPARE_MULTI_3_DB_NEAR;
-+ pES_Obj->comparer.factorFar = ES_COMPARE_MULTI_3_DB_FAR;
-+ pES_Obj->doubleTalkDetectionCountMax = ES_MAX_DTD_COUNT_3_DB;
-+ pES_Obj->echoDetectionCountMax = ES_MAX_DTD_COUNT_3_DB;
-+ break;
-+
-+ case ES_HYBRID_LOSS_LEVEL_6_DB:
-+ pES_Obj->comparer.factorNear = ES_COMPARE_MULTI_6_DB_NEAR;
-+ pES_Obj->comparer.factorFar = ES_COMPARE_MULTI_6_DB_FAR;
-+ pES_Obj->doubleTalkDetectionCountMax = ES_MAX_DTD_COUNT_6_DB;
-+ pES_Obj->echoDetectionCountMax = ES_MAX_DTD_COUNT_6_DB;
-+ break;
-+
-+ default:
-+ PRINTF("ES_Initialize - error: unsupported Hybrid Loss Level <%d>\n", level);
-+ return ES_FALSE;
-+ }
-+
-+ pES_Obj->windowSize = GetWindowSize(sizeId);
-+
-+ return (pES_Obj->initialized = ES_TRUE);
-+}
-+
-+
-+ES_BOOL ES_Reset(
-+ void* pObject)
-+{
-+ SUPPRESSOR* pES_Obj = (SUPPRESSOR*) pObject;
-+
-+ if(NULL == pES_Obj)
-+ {
-+ PRINTF("ES_Reset - error: wrong pObject value <NULL>\n");
-+ return ES_FALSE;
-+ }
-+
-+ if(!pES_Obj->initialized)
-+ {
-+ PRINTF("ES_Reset - error: the pObject is not initialized\n");
-+ return ES_FALSE;
-+ }
-+
-+ memset(pES_Obj->pHistoryOfFar, 0, pES_Obj->windowSize * sizeof(ES_LONG_VALUE));
-+ return ES_TRUE;
-+}
-+
-+
-+short ES_NEAR_CLEAN ES_ProcessSamples(
-+ void* pObject,
-+ ES_FAR_CLEAN short farSample,
-+ ES_NEAR_MIX short nearSample)
-+{
-+ SUPPRESSOR* pES_Obj = (SUPPRESSOR*) pObject;
-+ unsigned long temp;
-+ ES_LONG_VALUE newNear, newFar;
-+
-+ if(NULL == pES_Obj)
-+ {
-+ PRINTF("ES_ProcessSamples - error: wrong pObject value <NULL>\n");
-+ return nearSample;
-+ }
-+
-+ if(!pES_Obj->initialized)
-+ {
-+ PRINTF("ES_ProcessSamples - error: the pObject is not initialized\n");
-+ return nearSample;
-+ }
-+
-+ temp = pES_Obj->previousNear.integer % ES_ALFA_INT + pES_Obj->previousNear.fractional;
-+ pES_Obj->previousNear.fractional = temp % ES_ALFA_INT;
-+ pES_Obj->previousNear.integer = (ES_ALFA_INT - 1) * pES_Obj->previousNear.integer / ES_ALFA_INT
-+ + temp / ES_ALFA_INT + pES_Obj->moduleOfPreviousNear;
-+
-+ temp = pES_Obj->previousFar.integer % ES_ALFA_INT + pES_Obj->previousFar.fractional;
-+ pES_Obj->previousFar.fractional = temp % ES_ALFA_INT;
-+ pES_Obj->previousFar.integer = (ES_ALFA_INT - 1) * pES_Obj->previousFar.integer / ES_ALFA_INT
-+ + temp / ES_ALFA_INT + pES_Obj->moduleOfPreviousFar;
-+
-+ pES_Obj->pHistoryOfFar[pES_Obj->tailIndex].integer = pES_Obj->previousFar.integer;
-+ pES_Obj->pHistoryOfFar[pES_Obj->tailIndex].fractional = pES_Obj->previousFar.fractional;
-+
-+ pES_Obj->moduleOfPreviousNear = nearSample * ((nearSample < 0) ? -1 : 1);
-+ pES_Obj->moduleOfPreviousFar = farSample * ((farSample < 0) ? -1 : 1);
-+
-+ ObtainFarMaximum(pES_Obj);
-+
-+ if(IsFirstLessThanSecond(MultiplyByFactor(&pES_Obj->previousNear, &newNear, pES_Obj->comparer.factorNear),
-+ MultiplyByFactor(&pES_Obj->maximalFar.value, &newFar, pES_Obj->comparer.factorFar)))
-+ {
-+ if(0 == pES_Obj->echoDetectionCount)
-+ {
-+ nearSample /= ES_DIVISOR_VALUE;
-+ pES_Obj->doubleTalkDetectionCount = pES_Obj->doubleTalkDetectionCountMax;
-+ }
-+ else
-+ {
-+ pES_Obj->echoDetectionCount--;
-+ pES_Obj->doubleTalkDetectionCount = 0;
-+ }
-+ }
-+ else
-+ {
-+ pES_Obj->echoDetectionCount = pES_Obj->echoDetectionCountMax;
-+
-+ if(0 < pES_Obj->doubleTalkDetectionCount)
-+ {
-+ if(IsFirstLessThanSecond(MultiplyByFactor(&pES_Obj->maximalFar.value, &newFar, pES_Obj->comparer.factorFar + 1),
-+ MultiplyByFactor(&pES_Obj->previousNear, &newNear, pES_Obj->comparer.factorNear)))
-+ {
-+ pES_Obj->doubleTalkDetectionCount = 0;
-+ }
-+ else
-+ {
-+ pES_Obj->doubleTalkDetectionCount--;
-+ nearSample /= ES_DIVISOR_VALUE;
-+ }
-+ }
-+ }
-+
-+ pES_Obj->tailIndex = (pES_Obj->tailIndex + 1) % pES_Obj->windowSize;
-+
-+ return nearSample;
-+}
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/supress/suppressor.h zaptel-xpp-LJNBCn_dist/xpp/supress/suppressor.h
---- zaptel-1.2.6/xpp/supress/suppressor.h 1970-01-01 02:00:00.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/supress/suppressor.h 2006-06-25 14:42:21.798100000 +0300
-@@ -0,0 +1,160 @@
-+#if 0 /* File Header */
-+************************************************************************
-+ * Copyright (C) 2006, Xorcom Ltd.
-+ * All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+************************************************************************
-+#endif /* File Header */
-+
-+
-+#ifndef __SUPPRESSOR_H__
-+#define __SUPPRESSOR_H__
-+
-+#ifdef __cplusplus
-+extern "C" {
-+#endif
-+
-+
-+#ifndef WIN32
-+#define FILE void
-+#endif
-+
-+#define ES_NEAR_MIX
-+#define ES_NEAR_CLEAN
-+#define ES_FAR_CLEAN
-+
-+#define ES_ALFA_INT 32
-+
-+#define ES_DIVISOR_VALUE 64
-+
-+#define ES_MAX_DTD_COUNT_6_DB 16
-+#define ES_MAX_DTD_COUNT_3_DB 32
-+#define ES_MAX_DTD_COUNT_0_DB 64
-+
-+#define ES_COMPARE_MULTI_6_DB_NEAR 2
-+#define ES_COMPARE_MULTI_6_DB_FAR 1
-+
-+#define ES_COMPARE_MULTI_3_DB_NEAR 3
-+#define ES_COMPARE_MULTI_3_DB_FAR 2
-+
-+#define ES_COMPARE_MULTI_0_DB_NEAR 1
-+#define ES_COMPARE_MULTI_0_DB_FAR 1
-+
-+#define ES_SAMPLES_IN_4_MSEC (4 * 8)
-+#define ES_SAMPLES_IN_8_MSEC (8 * 8)
-+#define ES_SAMPLES_IN_16_MSEC (16 * 8)
-+#define ES_SAMPLES_IN_32_MSEC (32 * 8)
-+#define ES_SAMPLES_IN_64_MSEC (64 * 8)
-+#define ES_SAMPLES_IN_128_MSEC (128 * 8)
-+#define ES_SAMPLES_IN_256_MSEC (256 * 8)
-+
-+
-+typedef enum
-+{
-+ ES_FALSE = 0,
-+ ES_TRUE = 1
-+}
-+ES_BOOL;
-+
-+
-+typedef enum
-+{
-+ ES_HYBRID_LOSS_LEVEL_6_DB = 0,
-+ ES_HYBRID_LOSS_LEVEL_3_DB = 1,
-+ ES_HYBRID_LOSS_LEVEL_0_DB = 2
-+}
-+ES_HYBRID_LOSS_LEVEL;
-+
-+
-+typedef enum
-+{
-+ ES_WINDOW_SIZE_ID_4_MSEC = 0,
-+ ES_WINDOW_SIZE_ID_8_MSEC = 1,
-+ ES_WINDOW_SIZE_ID_16_MSEC = 2,
-+ ES_WINDOW_SIZE_ID_32_MSEC = 3,
-+ ES_WINDOW_SIZE_ID_64_MSEC = 4,
-+ ES_WINDOW_SIZE_ID_128_MSEC = 5,
-+ ES_WINDOW_SIZE_ID_256_MSEC = 6
-+}
-+ES_WINDOW_SIZE_ID;
-+
-+
-+typedef struct
-+{
-+ unsigned char factorNear;
-+ unsigned char factorFar;
-+}
-+ES_COMPARER;
-+
-+
-+typedef struct
-+{
-+ unsigned long integer;
-+ unsigned long fractional;
-+}
-+ES_LONG_VALUE;
-+
-+
-+typedef struct
-+{
-+ int index;
-+ ES_LONG_VALUE value;
-+}
-+ES_MAXIMAL_FAR;
-+
-+
-+typedef struct
-+{
-+ ES_BOOL initialized;
-+ int windowSize;
-+ ES_MAXIMAL_FAR maximalFar;
-+ int moduleOfPreviousFar;
-+ ES_LONG_VALUE previousFar;
-+ int moduleOfPreviousNear;
-+ ES_LONG_VALUE previousNear;
-+ int tailIndex;
-+ int doubleTalkDetectionCount;
-+ int doubleTalkDetectionCountMax;
-+ int echoDetectionCount;
-+ int echoDetectionCountMax;
-+ ES_COMPARER comparer;
-+ ES_LONG_VALUE pHistoryOfFar[1];
-+}
-+SUPPRESSOR;
-+
-+
-+static inline int ES_GetObjectSize(
-+ ES_WINDOW_SIZE_ID sizeId);
-+
-+static inline ES_BOOL ES_Initialize(
-+ void* pObject,
-+ ES_WINDOW_SIZE_ID sizeId,
-+ ES_HYBRID_LOSS_LEVEL level);
-+
-+static inline ES_BOOL ES_Reset(
-+ void* pObject);
-+
-+static inline short ES_NEAR_CLEAN ES_ProcessSamples(
-+ void* pObject,
-+ ES_FAR_CLEAN short farSample,
-+ ES_NEAR_MIX short nearSample);
-+
-+
-+#if __cplusplus
-+}
-+#endif
-+
-+#endif /* __SUPPRESSOR_H__ */
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/sync.sh zaptel-xpp-LJNBCn_dist/xpp/sync.sh
---- zaptel-1.2.6/xpp/sync.sh 2006-02-15 04:24:18.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/sync.sh 1970-01-01 02:00:00.000000000 +0200
-@@ -1,31 +0,0 @@
--#!/bin/sh
--
--set -e
--
--SVN_ROOT=/home/tzafrir/Proj/Svn
--XORTEL_DIR=$SVN_ROOT/xpp-zaptel/trunk/xortel
--XPP_DIR=$SVN_ROOT/xpp-zaptel/trunk/zaptel/xpp
--TARGET_DIR=xpp
--FIRMWARE=$SVN_ROOT/fpgafirmware/init.dat
--
--curdir=$PWD
--cd $XORTEL_DIR
-- cd ..; svn update;
-- cd xortel
-- make FIRMWARE="$FIRMWARE" ../zaptel/xpp/slic_init.inc
--cd $curdir
--
--cp -a $XORTEL_DIR/FPGA_XPD.hex ${TARGET_DIR}/
--cp -a $XORTEL_DIR/xpd.h ${TARGET_DIR}/
--cp -a $XORTEL_DIR/xpp_zap.[ch] ${TARGET_DIR}/
--cp -a $XORTEL_DIR/xproto.[ch] ${TARGET_DIR}/
--cp -a $XORTEL_DIR/xdefs.h ${TARGET_DIR}/
--cp -a $XORTEL_DIR/xpp_usb.c ${TARGET_DIR}/
--cp -a $XORTEL_DIR/zap_debug.[ch] ${TARGET_DIR}/
--cp -a $XORTEL_DIR/slic.[ch] ${TARGET_DIR}/
--cp -a $XORTEL_DIR/card_*.[ch] ${TARGET_DIR}/
--cp -a $XORTEL_DIR/xpp_fxloader{,.usermap} ${TARGET_DIR}/
--cp -a $XORTEL_DIR/xpp_modprobe ${TARGET_DIR}/
--cp -a $XORTEL_DIR/gen_slic_init ${TARGET_DIR}/
--cp -a $XPP_DIR/Makefile ${TARGET_DIR}/
--cp -a $XPP_DIR/slic_init.inc ${TARGET_DIR}/
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/utils/FPGA_FXS.hex zaptel-xpp-LJNBCn_dist/xpp/utils/FPGA_FXS.hex
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/utils/fpga_load.8 zaptel-xpp-LJNBCn_dist/xpp/utils/fpga_load.8
---- zaptel-1.2.6/xpp/utils/fpga_load.8 1970-01-01 02:00:00.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/utils/fpga_load.8 2006-04-16 16:20:04.117881000 +0300
-@@ -0,0 +1,72 @@
-+.TH "FPGA_LOAD" "8" "16 April 2006" "" ""
-+
-+.SH NAME
-+ztcfg \- reads and loads zaptel.conf
-+.SH SYNOPSIS
-+
-+.B fpga_load
-+[\fB-g\fR|\fB-d\fR] [\fB-v\fR] \fB-D\fR/proc/bus/usb/\fIBUS/DEV\fR
-+
-+.B fpga_load
-+[\fB-g\fR] [\fB-v\fR] \fB-D\fR/proc/bus/usb/\fIBUS/DEV\fR \fB-I \fIfirmware.hex\fR [\fB-b \fIdump.bin\fR]
-+
-+.B fpga_load -h
-+
-+.SH DESCRIPTION
-+.B fpga_load
-+loads the FPGA firmware to the Xorcom Astribank device.
-+The syntax resembles that of fxload(8).
-+
-+.SH OPTIONS
-+.B -d
-+.I dump.bin
-+.RS
-+Before writing firmware, bump the processed binary file to
-+.I dump.bin\fR.
-+.RE
-+
-+.B -d
-+.RS
-+Print Version number bytes from eeprom (to standard output). Implies -g.
-+.RE
-+
-+.B -D
-+.I DEVICE
-+.RS
-+Required. The device to read from/write to. This is normally
-+/proc/bus/usb/\fIbus_num\fR/\fIdevice_num\fR , where \fIbus_num\fR and
-+\fIdevice_num\fR are the first two numbers in the output of lsusb(8).
-+.RE
-+
-+.B -g
-+.RS
-+Dump all eeprom data to standard error.
-+.RE
-+
-+.B -I
-+.I fireware_file
-+.RS
-+The firmware file to write to the device.
-+.RE
-+
-+.B -v
-+.RS
-+Be verobse.
-+.RE
-+
-+.B -h
-+.RS
-+Displays usage message.
-+.RE
-+
-+.SH SEE ALSO
-+fxload(8), lsusb(8)
-+
-+.SH AUTHOR
-+This manual page was written by Tzafrir Cohen <tzafrir.cohen at xorcom.com> .
-+Permission is granted to copy, distribute and/or modify this document under
-+the terms of the GNU General Public License, Version 2 any
-+later version published by the Free Software Foundation.
-+
-+On Debian systems, the complete text of the GNU General Public
-+License can be found in /usr/share/common-licenses/GPL.
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/utils/fpga_load.c zaptel-xpp-LJNBCn_dist/xpp/utils/fpga_load.c
---- zaptel-1.2.6/xpp/utils/fpga_load.c 1970-01-01 02:00:00.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/utils/fpga_load.c 2006-06-01 11:50:28.294045000 +0300
-@@ -0,0 +1,822 @@
-+#include <stdio.h>
-+#include <assert.h>
-+#include <string.h>
-+#include <stdint.h>
-+#include <errno.h>
-+#include <sys/types.h>
-+#include <sys/param.h>
-+#include <usb.h>
-+#include "hexfile.h"
-+
-+static const char rcsid[] = "$Id: fpga_load.c 1304 2006-06-01 08:50:28Z tzafrir $";
-+
-+#define ERR(fmt, arg...) fprintf(stderr, "%s: ERROR: " fmt, progname, ## arg)
-+#define INFO(fmt, arg...) fprintf(stderr, "%s: " fmt, progname, ## arg)
-+
-+static int verbose = LOG_WARNING;
-+static char *progname;
-+
-+#define MAX_HEX_LINES 2000
-+#define PACKET_SIZE 512
-+#define EEPROM_SIZE 16
-+#define SERIAL_SIZE 8
-+
-+enum fpga_load_packet_types {
-+ STATUS_REPLY = 0x01,
-+ DATA_PACKET = 0x01,
-+#ifdef XORCOM_INTERNAL
-+ EEPROM_SET = 0x04,
-+#endif
-+ EEPROM_GET = 0x08,
-+ RENUMERATE = 0x10,
-+ BAD_COMMAND = 0xAA
-+};
-+
-+struct myeeprom {
-+ uint8_t source;
-+ uint16_t vendor;
-+ uint16_t product;
-+ uint8_t release_major;
-+ uint8_t release_minor;
-+ uint8_t reserved;
-+ uint8_t serial[SERIAL_SIZE];
-+} PACKED;
-+
-+struct fpga_packet_header {
-+ struct {
-+ uint8_t op;
-+ } PACKED header;
-+ union {
-+ struct {
-+ uint16_t seq;
-+ uint8_t status;
-+ } PACKED status_reply;
-+ struct {
-+ uint16_t seq;
-+ uint8_t reserved;
-+ uint8_t data[ZERO_SIZE];
-+ } PACKED data_packet;
-+ struct {
-+ struct myeeprom data;
-+ } PACKED eeprom_set;
-+ struct {
-+ struct myeeprom data;
-+ } PACKED eeprom_get;
-+ } d;
-+} PACKED;
-+
-+enum fpga_load_status {
-+ FW_FAIL_RESET = 1,
-+ FW_FAIL_TRANS = 2,
-+ FW_TRANS_OK = 4,
-+ FW_CONFIG_DONE = 8
-+};
-+
-+int my_usb_device(struct usb_device *dev, usb_dev_handle *handle);
-+
-+const char *load_status2str(enum fpga_load_status s)
-+{
-+ switch(s) {
-+ case FW_FAIL_RESET: return "FW_FAIL_RESET";
-+ case FW_FAIL_TRANS: return "FW_FAIL_TRANS";
-+ case FW_TRANS_OK: return "FW_TRANS_OK";
-+ case FW_CONFIG_DONE: return "FW_CONFIG_DONE";
-+ default: return "UNKNOWN";
-+ }
-+}
-+
-+int path_of_dev(char buf[], unsigned int buflen, struct usb_device *dev)
-+{
-+ return snprintf(buf, buflen, "/proc/bus/usb/%s/%s", dev->bus->dirname, dev->filename);
-+}
-+
-+struct usb_device *dev_of_path(const char *path)
-+{
-+ struct usb_bus *bus;
-+ struct usb_device *dev;
-+ char dirname[PATH_MAX];
-+ char filename[PATH_MAX];
-+ const char prefix[] = "/proc/bus/usb/";
-+ const int prefix_len = strlen(prefix);
-+ const char *p;
-+ int bnum;
-+ int dnum;
-+ int ret;
-+
-+ assert(path != NULL);
-+ if(strncmp(prefix, path, prefix_len) != 0) {
-+ ERR("wrong path: '%s'\n", path);
-+ return NULL;
-+ }
-+ p = path + prefix_len;
-+ ret = sscanf(p, "%d/%d", &bnum, &dnum);
-+ if(ret != 2) {
-+ ERR("wrong path tail: '%s'\n", p);
-+ return NULL;
-+ }
-+ sprintf(dirname, "%03d", bnum);
-+ sprintf(filename, "%03d", dnum);
-+ for (bus = usb_busses; bus; bus = bus->next) {
-+ if(strcmp(bus->dirname, dirname) != 0)
-+ continue;
-+ for (dev = bus->devices; dev; dev = dev->next) {
-+ if(strcmp(dev->filename, filename) == 0)
-+ return dev;
-+ }
-+ }
-+ ERR("no usb device match '%s'\n", path);
-+ return NULL;
-+}
-+
-+int get_usb_string(char *buf, unsigned int len, uint16_t item, usb_dev_handle *handle)
-+{
-+ char tmp[BUFSIZ];
-+ int ret;
-+
-+ if (!item)
-+ return 0;
-+ ret = usb_get_string_simple(handle, item, tmp, BUFSIZ);
-+ if (ret <= 0)
-+ return ret;
-+ return snprintf(buf, len, "%s", tmp);
-+}
-+
-+/* My device parameters */
-+#define MY_INTERFACE 0
-+#define MY_CONFIG 1
-+#define MY_ENDPOINTS 4
-+
-+#define MY_EP_OUT 0x04
-+#define MY_EP_IN 0x88
-+
-+#define TIMEOUT 5000
-+
-+static const int my_endpoints[MY_ENDPOINTS] = {
-+ 0x02,
-+ 0x04,
-+ 0x86,
-+ 0x88
-+};
-+
-+void usb_cleanup(usb_dev_handle *handle)
-+{
-+ if(usb_release_interface(handle, MY_INTERFACE) != 0) {
-+ ERR("Releasing interface: usb: %s\n", usb_strerror());
-+ }
-+ if(usb_close(handle) != 0) {
-+ ERR("Closing device: usb: %s\n", usb_strerror());
-+ }
-+}
-+
-+void print_bcd_ver(const struct myeeprom *eeprom)
-+{
-+ /* In this case, print only the version. Also note that this
-+ * is an output, and sent to stdout
-+ */
-+ printf("%d.%03d\n", eeprom->release_major, eeprom->release_minor);
-+ return;
-+}
-+
-+void dump_eeprom(const struct myeeprom *eeprom)
-+{
-+ const uint8_t *data = eeprom->serial;
-+
-+ INFO("Source: 0x%02X\n", eeprom->source);
-+ INFO("Vendor: 0x%04X\n", eeprom->vendor);
-+ INFO("Product: 0x%04X\n", eeprom->product);
-+ INFO("Release: %d.%03d\n", eeprom->release_major, eeprom->release_minor);
-+ INFO("Data: 0x[%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X]\n",
-+ data[0], data[1], data[2], data[3],
-+ data[4], data[5], data[6], data[7]);
-+}
-+
-+void dump_packet(const char *buf, int len)
-+{
-+ int i;
-+
-+ for(i = 0; i < len; i++)
-+ INFO("dump: %2d> 0x%02X\n", i, (uint8_t)buf[i]);
-+}
-+
-+#ifdef XORCOM_INTERNAL
-+int eeprom_set(struct usb_dev_handle *handle, const struct myeeprom *eeprom)
-+{
-+ int ret;
-+ int len;
-+ char buf[PACKET_SIZE];
-+ struct fpga_packet_header *phead = (struct fpga_packet_header *)buf;
-+
-+ if(verbose >= LOG_INFO)
-+ INFO("%s Start...\n", __FUNCTION__);
-+ assert(handle != NULL);
-+ phead->header.op = EEPROM_SET;
-+ memcpy(&phead->d.eeprom_set.data, eeprom, EEPROM_SIZE);
-+ len = sizeof(phead->d.eeprom_set) + sizeof(phead->header.op);
-+ if(verbose >= LOG_INFO) {
-+ INFO("%s write %d bytes\n", __FUNCTION__, len);
-+ dump_packet((char *)phead, len);
-+ }
-+ ret = usb_bulk_write(handle, MY_EP_OUT, (char *)phead, len, TIMEOUT);
-+ if(ret < 0) {
-+ ERR("usb: bulk_write failed (%d)\n", ret);
-+ return ret;
-+ } else if(ret != len) {
-+ ERR("usb: bulk_write short write (%d)\n", ret);
-+ return -EFAULT;
-+ }
-+ ret = usb_bulk_read(handle, MY_EP_IN, buf, sizeof(buf), TIMEOUT);
-+ if(ret < 0) {
-+ ERR("usb: bulk_read failed (%d)\n", ret);
-+ return ret;
-+ } else if(ret == 0)
-+ return 0;
-+ phead = (struct fpga_packet_header *)buf;
-+ if(phead->header.op == BAD_COMMAND) {
-+ ERR("BAD_COMMAND\n");
-+ return -EINVAL;
-+ } else if(phead->header.op != EEPROM_SET) {
-+ ERR("Got unexpected reply op=%d\n", phead->header.op);
-+ return -EINVAL;
-+ }
-+ if(verbose >= LOG_INFO) {
-+ INFO("%s read %d bytes\n", __FUNCTION__, ret);
-+ dump_packet(buf, ret);
-+ }
-+ return 0;
-+}
-+#endif
-+
-+int eeprom_get(struct usb_dev_handle *handle, struct myeeprom *eeprom)
-+{
-+ int ret;
-+ int len;
-+ char buf[PACKET_SIZE];
-+ struct fpga_packet_header *phead = (struct fpga_packet_header *)buf;
-+
-+ assert(handle != NULL);
-+ if(verbose >= LOG_INFO)
-+ INFO("%s Start...\n", __FUNCTION__);
-+ phead->header.op = EEPROM_GET;
-+ len = sizeof(phead->header.op); /* warning: sending small packet */
-+ if(verbose >= LOG_INFO) {
-+ INFO("%s write %d bytes\n", __FUNCTION__, len);
-+ dump_packet(buf, len);
-+ }
-+ ret = usb_bulk_write(handle, MY_EP_OUT, (char *)phead, len, TIMEOUT);
-+ if(ret < 0) {
-+ ERR("usb: bulk_write failed (%d)\n", ret);
-+ return ret;
-+ } else if(ret != len) {
-+ ERR("usb: bulk_write short write (%d)\n", ret);
-+ return -EFAULT;
-+ }
-+ ret = usb_bulk_read(handle, MY_EP_IN, buf, sizeof(buf), TIMEOUT);
-+ if(ret < 0) {
-+ ERR("usb: bulk_read failed (%d)\n", ret);
-+ return ret;
-+ } else if(ret == 0)
-+ return 0;
-+ phead = (struct fpga_packet_header *)buf;
-+ if(phead->header.op == BAD_COMMAND) {
-+ ERR("BAD_COMMAND\n");
-+ return -EINVAL;
-+ } else if(phead->header.op != EEPROM_GET) {
-+ ERR("Got unexpected reply op=%d\n", phead->header.op);
-+ return -EINVAL;
-+ }
-+ if(verbose >= LOG_INFO) {
-+ INFO("%s read %d bytes\n", __FUNCTION__, ret);
-+ dump_packet(buf, ret);
-+ }
-+ memcpy(eeprom, &phead->d.eeprom_get.data, EEPROM_SIZE);
-+ return 0;
-+}
-+
-+int send_hexline(struct usb_dev_handle *handle, struct hexline *hexline, int seq)
-+{
-+ int ret;
-+ int len;
-+ uint8_t *data;
-+ char buf[PACKET_SIZE];
-+ struct fpga_packet_header *phead = (struct fpga_packet_header *)buf;
-+ enum fpga_load_status status;
-+
-+ assert(handle != NULL);
-+ assert(hexline != NULL);
-+ len = hexline->d.content.header.ll; /* don't send checksum */
-+ data = hexline->d.content.tt_data.data;
-+ if(hexline->d.content.header.tt != TT_DATA) {
-+ ERR("Bad record %d type = %d\n", seq, hexline->d.content.header.tt);
-+ return -EINVAL;
-+ }
-+ phead->header.op = DATA_PACKET;
-+ phead->d.data_packet.seq = seq;
-+ phead->d.data_packet.reserved = 0x00;
-+ memcpy(phead->d.data_packet.data, data, len);
-+ len += sizeof(phead);
-+ if(verbose >= LOG_INFO)
-+ INFO("%04d+\r", seq);
-+ ret = usb_bulk_write(handle, MY_EP_OUT, (char *)phead, len, TIMEOUT);
-+ if(ret < 0) {
-+ ERR("usb: bulk_write failed (%d)\n", ret);
-+ return ret;
-+ } else if(ret != len) {
-+ ERR("usb: bulk_write short write (%d)\n", ret);
-+ return -EFAULT;
-+ }
-+ ret = usb_bulk_read(handle, MY_EP_IN, buf, sizeof(buf), TIMEOUT);
-+ if(ret < 0) {
-+ ERR("usb: bulk_read failed (%d)\n", ret);
-+ return ret;
-+ } else if(ret == 0)
-+ return 0;
-+ if(verbose >= LOG_INFO)
-+ INFO("%04d-\r", seq);
-+ phead = (struct fpga_packet_header *)buf;
-+ if(phead->header.op != STATUS_REPLY) {
-+ ERR("Got unexpected reply op=%d\n", phead->header.op);
-+ return -EINVAL;
-+ }
-+ status = (enum fpga_load_status)phead->d.status_reply.status;
-+ switch(status) {
-+ case FW_TRANS_OK:
-+ case FW_CONFIG_DONE:
-+ break;
-+ case FW_FAIL_RESET:
-+ case FW_FAIL_TRANS:
-+ ERR("status reply %s (%d)\n", load_status2str(status), status);
-+ if(verbose >= LOG_INFO)
-+ dump_packet(buf, ret);
-+ return -EPROTO;
-+ default:
-+ ERR("Unknown status reply %d\n", status);
-+ if(verbose >= LOG_INFO)
-+ dump_packet(buf, ret);
-+ return -EPROTO;
-+ }
-+ return 0;
-+}
-+
-+//. returns > 0 - ok, the number of lines sent
-+//. returns < 0 - error number
-+int send_splited_hexline(struct usb_dev_handle *handle, struct hexline *hexline, int seq, uint8_t maxwidth)
-+{
-+ struct hexline *extraline;
-+ int linessent = 0;
-+ int allocsize;
-+ int extra_offset = 0;
-+ unsigned int this_line = 0;
-+ uint8_t bytesleft = 0;
-+
-+ if(!hexline) {
-+ ERR("Bad record %d type = %d\n", seq, hexline->d.content.header.tt);
-+ return -EINVAL;
-+ }
-+ bytesleft = hexline->d.content.header.ll;
-+ // split the line into several lines
-+ while (bytesleft > 0) {
-+ int status;
-+ this_line = (bytesleft >= maxwidth) ? maxwidth : bytesleft;
-+ allocsize = sizeof(struct hexline) + this_line + 1;
-+ // generate the new line
-+ if((extraline = (struct hexline *)malloc(allocsize)) == NULL) {
-+ ERR("Not enough memory for spliting the lines\n" );
-+ return -EINVAL;
-+ }
-+ memset( extraline, 0, allocsize );
-+ extraline->d.content.header.ll = this_line;
-+ extraline->d.content.header.offset = hexline->d.content.header.offset + extra_offset;
-+ extraline->d.content.header.tt = hexline->d.content.header.tt;
-+ memcpy( extraline->d.content.tt_data.data, hexline->d.content.tt_data.data+extra_offset, this_line);
-+ status = send_hexline( handle, extraline, seq+linessent );
-+ // cleanups
-+ free(extraline);
-+ extra_offset += this_line;
-+ bytesleft -= this_line;
-+ if (status)
-+ return status;
-+ linessent++;
-+ }
-+ return linessent;
-+}
-+
-+int my_usb_device(struct usb_device *dev, usb_dev_handle *handle)
-+{
-+ struct usb_device_descriptor *dev_desc;
-+ struct usb_config_descriptor *config_desc;
-+ struct usb_interface *interface;
-+ struct usb_interface_descriptor *iface_desc;
-+ struct usb_endpoint_descriptor *endpoint;
-+ char iManufacturer[BUFSIZ];
-+ char iProduct[BUFSIZ];
-+ int ret;
-+ int i;
-+
-+ assert(dev != NULL);
-+ dev_desc = &dev->descriptor;
-+ config_desc = dev->config;
-+ interface = config_desc->interface;
-+ iface_desc = interface->altsetting;
-+ if(verbose >= LOG_INFO)
-+ INFO("Vendor:Product=%04X:%04X Class=%d (endpoints=%d)\n",
-+ dev_desc->idVendor, dev_desc->idProduct, dev_desc->bDeviceClass, iface_desc->bNumEndpoints);
-+ if(iface_desc->bInterfaceClass != 0xFF) {
-+ ERR("Wrong Interface class %d\n", iface_desc->bInterfaceClass);
-+ return -EINVAL;
-+ }
-+ if(iface_desc->bInterfaceNumber != MY_INTERFACE) {
-+ ERR("Wrong Interface number %d\n", iface_desc->bInterfaceNumber);
-+ return -EINVAL;
-+ }
-+ if(iface_desc->bNumEndpoints != MY_ENDPOINTS) {
-+ ERR("Wrong number of endpoints: %d\n", iface_desc->bNumEndpoints);
-+ return -EINVAL;
-+ }
-+ endpoint = iface_desc->endpoint;
-+ for(i = 0; i < iface_desc->bNumEndpoints; i++, endpoint++) {
-+ if(endpoint->bEndpointAddress != my_endpoints[i]) {
-+ ERR("Wrong endpoint %d: address = 0x%X\n", i, endpoint->bEndpointAddress);
-+ return -EINVAL;
-+ }
-+ if(endpoint->bEndpointAddress == MY_EP_OUT || endpoint->bEndpointAddress == MY_EP_IN) {
-+ if(endpoint->wMaxPacketSize > PACKET_SIZE) {
-+ ERR("Endpoint #%d wMaxPacketSize too large (%d)\n", i, endpoint->wMaxPacketSize);
-+ return -EINVAL;
-+ }
-+ }
-+ }
-+ if(usb_reset(handle) != 0) {
-+ ERR("Reseting device: usb: %s\n", usb_strerror());
-+ }
-+ if(usb_set_configuration(handle, MY_CONFIG) != 0) {
-+ ERR("usb: %s\n", usb_strerror());
-+ return -EINVAL;
-+ }
-+ if(usb_claim_interface(handle, MY_INTERFACE) != 0) {
-+ ERR("usb: %s\n", usb_strerror());
-+ return -EINVAL;
-+ }
-+ if(usb_resetep(handle, MY_EP_OUT) != 0) {
-+ ERR("usb: %s\n", usb_strerror());
-+ return -EINVAL;
-+ }
-+ if(usb_resetep(handle, MY_EP_IN) != 0) {
-+ ERR("usb: %s\n", usb_strerror());
-+ return -EINVAL;
-+ }
-+ ret = get_usb_string(iManufacturer, BUFSIZ, dev_desc->iManufacturer, handle);
-+ ret = get_usb_string(iProduct, BUFSIZ, dev_desc->iProduct, handle);
-+ if(verbose >= LOG_INFO)
-+ INFO("iManufacturer=%s iProduct=%s\n", iManufacturer, iProduct);
-+ return 0;
-+}
-+
-+int renumerate_device(struct usb_dev_handle *handle)
-+{
-+ char buf[PACKET_SIZE];
-+ struct fpga_packet_header *phead = (struct fpga_packet_header *)buf;
-+ int ret;
-+
-+ assert(handle != NULL);
-+ if(verbose >= LOG_INFO)
-+ INFO("Renumerating\n");
-+ phead->header.op = RENUMERATE;
-+ ret = usb_bulk_write(handle, MY_EP_OUT, (char *)phead, 1, TIMEOUT);
-+ if(ret < 0) {
-+ ERR("usb: bulk_write failed (%d)\n", ret);
-+ return ret;
-+ } else if(ret != 1) {
-+ ERR("usb: bulk_write short write (%d)\n", ret);
-+ return -EFAULT;
-+ }
-+ return 0;
-+}
-+
-+int fpga_load(struct usb_dev_handle *handle, const struct hexdata *hexdata)
-+{
-+ unsigned int i;
-+ int ret;
-+ int finished = 0;
-+
-+ assert(handle != NULL);
-+ if(verbose >= LOG_INFO)
-+ INFO("Start...\n");
-+
-+ for(i = 0; i < hexdata->maxlines; i++) {
-+ struct hexline *hexline = hexdata->lines[i];
-+
-+ if(!hexline)
-+ break;
-+ if(finished) {
-+ ERR("Extra data after End Of Data Record (line %d)\n", i);
-+ return 0;
-+ }
-+ if(hexline->d.content.header.tt == TT_EOF) {
-+ INFO("End of data\n");
-+ finished = 1;
-+ continue;
-+ }
-+ if((ret = send_hexline(handle, hexline, i)) != 0) {
-+ perror("Failed sending hexline");
-+ return 0;
-+ }
-+ }
-+ if(verbose >= LOG_INFO)
-+ INFO("Finished...\n");
-+ return 1;
-+}
-+
-+int fpga_load_usb1(struct usb_dev_handle *handle, const struct hexdata *hexdata)
-+{
-+ unsigned int i,j=0;
-+ int ret;
-+ int finished = 0;
-+
-+ assert(handle != NULL);
-+ if(verbose >= LOG_INFO)
-+ INFO("Start...\n");
-+
-+ // i - is the line number
-+ // j - is the sequence number, on USB 2, i=j, but on
-+ // USB 1 send_splited_hexline may increase the sequence
-+ // number, as it needs
-+ for(i = 0; i < hexdata->maxlines; i++) {
-+ struct hexline *hexline = hexdata->lines[i];
-+
-+
-+ if(!hexline)
-+ break;
-+ if(finished) {
-+ ERR("Extra data after End Of Data Record (line %d)\n", i);
-+ return 0;
-+ }
-+ if(hexline->d.content.header.tt == TT_EOF) {
-+ INFO("End of data\n");
-+ finished = 1;
-+ continue;
-+ }
-+
-+ if((ret = send_splited_hexline(handle, hexline, j, 60)) < 0) {
-+ perror("Failed sending hexline (splitting did not help)");
-+ return 0;
-+ }
-+ j += ret;
-+ }
-+ if(verbose >= LOG_INFO)
-+ INFO("Finished...\n");
-+ return 1;
-+}
-+
-+#include <getopt.h>
-+
-+void usage()
-+{
-+ fprintf(stderr, "Usage: %s -D /proc/bus/usb/<bus>/<dev> [options...]\n", progname);
-+ fprintf(stderr, "\tOptions:\n");
-+ fprintf(stderr, "\t\t[-b <binfile>] # output to <binfile>\n");
-+ fprintf(stderr, "\t\t[-d] # Get device version from eeprom\n");
-+ fprintf(stderr, "\t\t[-I <hexfile>] # Input from <hexfile>\n");
-+ fprintf(stderr, "\t\t[-g] # Get eeprom from device\n");
-+ fprintf(stderr, "\t\t[-C srC byte] # Set Address sourCe (default: C0)\n");
-+ fprintf(stderr, "\t\t[-V vendorid] # Set Vendor id on device\n");
-+ fprintf(stderr, "\t\t[-P productid] # Set Product id on device\n");
-+ fprintf(stderr, "\t\t[-R release] # Set Release. 2 dot separated decimals\n");
-+ fprintf(stderr, "\t\t[-S serial] # Set Serial. 8 comma separated numbers\n");
-+ exit(1);
-+}
-+
-+static void parse_report_func(int level, const char *msg, ...)
-+{
-+ va_list ap;
-+
-+ va_start(ap, msg);
-+ if(level <= verbose)
-+ vfprintf(stderr, msg, ap);
-+ va_end(ap);
-+}
-+
-+int hasUSB2( struct usb_device *dev )
-+{
-+ if (dev->config->interface->altsetting->endpoint->wMaxPacketSize != 512)
-+ return 0;
-+ else
-+ return 1;
-+}
-+
-+// usb_interface_descriptor->usb_endpoint_descriptor.wMaxPacketSize
-+
-+int main(int argc, char *argv[])
-+{
-+ struct usb_device *dev;
-+ usb_dev_handle *handle;
-+ const char *devpath = NULL;
-+ const char *binfile = NULL;
-+ const char *hexfile = NULL;
-+ struct hexdata *hexdata = NULL;
-+ struct myeeprom eeprom_buf;
-+ int opt_read_eeprom = 0;
-+ int opt_print_bcdver_only = 0;
-+#ifdef XORCOM_INTERNAL
-+ int opt_write_eeprom = 0;
-+ char *vendor = NULL;
-+ char *source = NULL;
-+ int is_source_given = 0;
-+ char *product = NULL;
-+ char *release = NULL;
-+ char *serial = NULL;
-+ uint8_t serial_buf[SERIAL_SIZE];
-+ const char options[] = "b:C:dD:ghI:vV:P:R:S:";
-+#else
-+ const char options[] = "b:dD:ghI:v";
-+#endif
-+ int ret = 0;
-+
-+ progname = argv[0];
-+ assert(sizeof(struct fpga_packet_header) <= PACKET_SIZE);
-+ assert(sizeof(struct myeeprom) == EEPROM_SIZE);
-+ while (1) {
-+ int c;
-+
-+ c = getopt (argc, argv, options);
-+ if (c == -1)
-+ break;
-+
-+ switch (c) {
-+ case 'D':
-+ devpath = optarg;
-+ break;
-+ case 'b':
-+ binfile = optarg;
-+ break;
-+ case 'd':
-+ opt_print_bcdver_only = 1;
-+ opt_read_eeprom = 1;
-+ break;
-+ case 'g':
-+ opt_read_eeprom = 1;
-+ break;
-+ case 'I':
-+ hexfile = optarg;
-+ break;
-+#ifdef XORCOM_INTERNAL
-+ case 'V':
-+ vendor = optarg;
-+ break;
-+ case 'C':
-+ source = optarg;
-+ is_source_given = 1;
-+ break;
-+ case 'P':
-+ product = optarg;
-+ break;
-+ case 'R':
-+ release = optarg;
-+ break;
-+ case 'S':
-+ serial = optarg;
-+ {
-+ int i;
-+ char *p;
-+ unsigned long val;
-+
-+ p = strtok(serial, ",");
-+ for(i = 0; i < SERIAL_SIZE && p; i++) {
-+ val = strtoul(p, NULL, 0);
-+ if(val > 0xFF) {
-+ ERR("Value #%d for -S option is too large (%lu)\n", i+1, val);
-+ usage();
-+ }
-+ serial_buf[i] = val;
-+ p = strtok(NULL, ",");
-+ }
-+ if(i < SERIAL_SIZE) {
-+ ERR("got only %d values for -S option. Need %d\n", i, SERIAL_SIZE);
-+ usage();
-+ }
-+ }
-+
-+ break;
-+#endif
-+ case 'v':
-+ verbose++;
-+ break;
-+ case 'h':
-+ default:
-+ ERR("Unknown option '%c'\n", c);
-+ usage();
-+ }
-+ }
-+
-+ if (optind != argc) {
-+ usage();
-+ }
-+ if(hexfile) {
-+ parse_hexfile_set_reporting(parse_report_func);
-+ hexdata = parse_hexfile(hexfile, MAX_HEX_LINES);
-+ if(!hexdata) {
-+ ERR("Bailing out\n");
-+ exit(1);
-+ }
-+ if(binfile) {
-+ dump_binary(hexdata, binfile);
-+ return 0;
-+ }
-+ }
-+ if(!devpath) {
-+ ERR("Missing device path\n");
-+ usage();
-+ }
-+ if(verbose)
-+ INFO("Startup %s\n", devpath);
-+
-+ usb_init();
-+ usb_find_busses();
-+ usb_find_devices();
-+ dev = dev_of_path(devpath);
-+ if(!dev) {
-+ ERR("Bailing out\n");
-+ exit(1);
-+ }
-+ handle = usb_open(dev);
-+ if(!handle) {
-+ ERR("Failed to open usb device '%s/%s': %s\n", dev->bus->dirname, dev->filename, usb_strerror());
-+ return -ENODEV;
-+ }
-+ if(my_usb_device(dev, handle)) {
-+ ERR("Foreign usb device '%s/%s'\n", dev->bus->dirname, dev->filename);
-+ ret = -ENODEV;
-+ goto dev_err;
-+ }
-+
-+ if(hexdata) {
-+ int status;
-+
-+ if (hasUSB2(dev))
-+ status = fpga_load(handle, hexdata);
-+ else {
-+ INFO("Warning: working on a low end USB1 backend\n");
-+ status = fpga_load_usb1(handle, hexdata);
-+ }
-+
-+ if(!status) {
-+ ERR("FPGA loading failed\n");
-+ ret = -ENODEV;
-+ goto dev_err;
-+ }
-+ ret = renumerate_device(handle);
-+ if(ret < 0) {
-+ ERR("Renumeration failed: errno=%d\n", ret);
-+ goto dev_err;
-+ }
-+ }
-+#ifdef XORCOM_INTERNAL
-+ if(vendor || product || release || serial || source )
-+ opt_read_eeprom = opt_write_eeprom = 1;
-+#endif
-+ if(opt_read_eeprom) {
-+ ret = eeprom_get(handle, &eeprom_buf);
-+ if(ret < 0) {
-+ ERR("Failed reading eeprom: %d\n", ret);
-+ goto dev_err;
-+ }
-+ if (opt_print_bcdver_only)
-+ print_bcd_ver(&eeprom_buf);
-+ else
-+ dump_eeprom(&eeprom_buf);
-+ }
-+#ifdef XORCOM_INTERNAL
-+ if(opt_write_eeprom) {
-+ // FF: address source is from device. C0: from eeprom
-+ if (is_source_given)
-+ eeprom_buf.source = strtoul(source, NULL, 0);
-+ else
-+ eeprom_buf.source = 0xC0;
-+ if(vendor)
-+ eeprom_buf.vendor = strtoul(vendor, NULL, 0);
-+ if(product)
-+ eeprom_buf.product = strtoul(product, NULL, 0);
-+ if(release) {
-+ int release_major = 0;
-+ int release_minor = 0;
-+
-+ sscanf(release, "%d.%d", &release_major, &release_minor);
-+ eeprom_buf.release_major = release_major;
-+ eeprom_buf.release_minor = release_minor;
-+ }
-+ if(serial) {
-+ memcpy(eeprom_buf.serial, serial_buf, SERIAL_SIZE);
-+ }
-+ dump_eeprom(&eeprom_buf);
-+ ret = eeprom_set(handle, &eeprom_buf);
-+ if(ret < 0) {
-+ ERR("Failed writing eeprom: %d\n", ret);
-+ goto dev_err;
-+ }
-+ }
-+#endif
-+ if(verbose)
-+ INFO("Exiting\n");
-+dev_err:
-+ usb_cleanup(handle);
-+ return ret;
-+}
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/utils/genzaptelconf zaptel-xpp-LJNBCn_dist/xpp/utils/genzaptelconf
---- zaptel-1.2.6/xpp/utils/genzaptelconf 1970-01-01 02:00:00.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/utils/genzaptelconf 2006-07-10 14:41:08.140923000 +0300
-@@ -0,0 +1,944 @@
-+#! /bin/bash
-+
-+# genzaptelconf: generate as smartly as you can:
-+# /etc/zaptel.conf
-+# /etc/asterisk/zapata-channels.conf (to be #include-d into zapata.conf)
-+# update:
-+# With '-M' /etc/modules (list of modules to load)
-+#
-+# Copyright (C) 2005 by Xorcom <support at xorcom.com>
-+#
-+# This program is free software; you can redistribute it and/or modify
-+# it under the terms of the GNU General Public License as published by
-+# the Free Software Foundation; either version 2 of the License, or
-+# (at your option) any later version.
-+#
-+# This program is distributed in the hope that it will be useful,
-+# but WITHOUT ANY WARRANTY; without even the implied warranty of
-+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+# GNU General Public License for more details.
-+#
-+# You should have received a copy of the GNU General Public License
-+# along with this program; if not, write to the Free Software
-+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+#
-+#
-+# If you have any technical questions, contact
-+# Tzafrir Cohen <tzafrir.cohen at xorcom.com>
-+#
-+
-+# The script uses a number of bash-specific features
-+# TODO: either ditch them or convert to perl
-+# Don't override variables here. Override them in /etc/default/zaptel
-+#
-+# 0.5.3:
-+# * Experimental support for Sangoma analog cards (A20x)
-+# * Support OpenVox A1200P (A TDM400P clone refactored)
-+# * Fixed timeout for Astribank load
-+# * Delete unsuccessfully-probe modules
-+# * Pass callerid from trunks
-+# * A simpler wait_for_xpp using new proc wait_for_xpds
-+# * fixed confusion between framing and coding for E1/{il/nl}
-+# 0.5.2:
-+# * Now it should detect most PRI cards and even wcusb
-+# 0.5.1:
-+# * Initial support for ztgsm (Junghanns's PCI GSM card)
-+# * Wait for the xpp module to register if just loaded
-+# 0.5.0:
-+# * Not trying to read from zaptel channels: we can run genzaptelconf even
-+# with asterisk up.
-+# * Don't add ztdummy to the list of detected modules
-+# 0.4.4:
-+# * remove ztdummy when rewriting modules file
-+# * Better ISDN PRI behaviour in Israel (il)
-+# 0.4.3:
-+# * Added -F: to disable writing about FXS ports in zapata.conf
-+# * if we have an astribank: start zaptel rather than simple ztcfg (xpd sync)
-+# 0.4.2:
-+# * support for digital input/output ports of Astribank
-+# * Different ISDN parameters for the Netherlands (nl)
-+# * unload zaptel and its dependencies, not a hard-coded list
-+# * hence we can reduce the list of modules
-+
-+# /etc/default/zaptel may override the following variables
-+VERSION=0.5.3
-+VERSION_FULL="$VERSION $Id: genzaptelconf 1202 2006-05-16 03:16:41Z tzafrir $"
-+lc_country=us
-+base_exten=6000
-+# If set: no context changes are made in zapata-channels.conf
-+#context_manual=yes
-+context_lines=from-pstn # context into which PSTN calls go
-+context_phones=from-internal # context for internal phones calls.
-+# The two below apply to input and output ports of the Xorcom Astribank:
-+context_input=astbank-input
-+context_output=astbank-output # useless, but helps marking the channels :-)
-+# TODO: what about PRI/BRI?
-+# If set: no group changes are made in zapata-channels.conf
-+#group_manual=yes
-+group_phones=5 # group for phones
-+group_lines=0 # group for lines
-+# set 'immediate=yes' for Asteribank input channels and 'immediate=no'
-+# for others. Note that if an Astribank is not detected, the script
-+# will set this to "no", so you can safely leave it as "yes".
-+set_immediate=yes
-+
-+ZAPCONF_FILE=/etc/zaptel.conf
-+ZAPATA_FILE=/etc/asterisk/zapata-channels.conf
-+ZAPTEL_BOOT=/etc/default/zaptel
-+MODLIST_FILE=/etc/modules
-+exten_base_dir=/etc/asterisk/extensions-phones.d
-+exten_defs_file=/etc/asterisk/extensions-defs.conf
-+ZTCFG=/sbin/ztcfg
-+
-+# a temporary directory. Created when the switch -r is parsed on getopts
-+# and deleted in the end on update_extensions_defs
-+tmp_dir=
-+
-+# A list of all modules:
-+# - the list of modules which will be probed (in this order) if -d is used
-+# - The module that will be deleted from /etc/modules , if -d -M is used
-+ALL_MODULES="zaphfc qozap ztgsm wctdm wctdm24xxp wcfxo wcfxs pciradio tor2 torisa wct1xxp wct4xxp wcte11xp wanpipe wcusb xpp_usb"
-+
-+# read default configuration from /etc/default/zaptel
-+if [ -r $ZAPTEL_BOOT ]; then . $ZAPTEL_BOOT; fi
-+
-+# it is safe to use -c twice: the last one will be used.
-+ztcfg_cmd="$ZTCFG -c $ZAPCONF_FILE"
-+
-+# work around a bug (that was already fixed) in the installer:
-+if [ "$lc_country" = '' ]; then lc_country=us; fi
-+
-+force_stop_ast=no
-+do_detect=no
-+do_unload=no
-+do_module_list=no
-+verbose=no
-+fxsdisable=no
-+rapid_extens=''
-+# global: current extension number in extensions list. Should only be
-+# changed in print_pattern:
-+rapid_cur_exten=1
-+# set the TRUNK in extensidialplan dialplan defs file rapid_conf_mode=no
-+
-+die() {
-+ echo "$@" >&2
-+ exit 1
-+}
-+
-+say() {
-+ if [ "$verbose" = no ]; then
-+ return
-+ fi
-+ echo "$@" >&2
-+}
-+
-+run_ztcfg() {
-+ if [ "$verbose" = no ]; then
-+ $ztcfg_cmd "$@"
-+ else
-+ say "Reconfiguring identified channels"
-+ $ztcfg_cmd -vv "$@"
-+ fi
-+}
-+
-+update_module_list() {
-+ del_args=`for i in $ALL_MODULES ztdummy
-+ do
-+ echo "$i" | sed s:.\*:-e\ '/^&/d':
-+ done`
-+ add_args=`for i in $*
-+ do
-+ echo "$i" | sed s:.\*:-e\ '\$a&':
-+ done`
-+
-+ sed -i.bak $del_args "$MODLIST_FILE"
-+ for i in $*
-+ do
-+ echo "$i"
-+ done >> "$MODLIST_FILE"
-+}
-+
-+do_update() {
-+ if [ ! -d `dirname ${ZAPTEL_BOOT}` ]
-+ then
-+ return
-+ fi
-+ sed -i.bak "s/^$1=.*\$/$1=\"$2\"/" ${ZAPTEL_BOOT}
-+ if ! grep -q "^$1=" ${ZAPTEL_BOOT}; then
-+ echo "$1=\"$2\"" >> ${ZAPTEL_BOOT}
-+ fi
-+}
-+
-+update_extensions_defs() {
-+ if [ "$rapid_conf_mode" = 'yes' ]
-+ then
-+ say "DEBUG: Updating dialplan defs file $exten_defs_file"
-+ if [ "`echo $tmp_dir/fxo_* | grep -v '*'`" != '' ]
-+ then
-+ trunk_nums=`cat $tmp_dir/fxo_* | sort -n | xargs`
-+ say "Configuring TRUNK to be [first of] zaptel channels: $trunk_nums"
-+ trunk_dev=`echo $trunk_nums| sed -e 's/ /\\\\\\&/g' -e 's/[0-9a-zA-Z]\+/Zap\\\\\\/&/g'`
-+ echo >&2 sed -i "s/^TRUNK.*=>.*/TRUNK => $trunk_dev/" $exten_defs_file
-+ sed -i "s/^TRUNK.*=>.*/TRUNK => $trunk_dev/" $exten_defs_file
-+ if ! grep -q "^TRUNK =>" $exten_defs_file; then
-+ trunk_dev=`echo $trunk_nums| sed -e 's/ /&/g' -e 's/[0-9a-zA-Z]*/Zap\\/&/g'`
-+ echo "TRUNK => $trunk_dev" >> $exten_defs_file
-+ fi
-+ else
-+ say "Warning: No FXO channel for trunk. Moving on."
-+ fi
-+ if [ "`echo $tmp_dir/fxs_* | grep -v '*'`" != '' ]
-+ then
-+ fxs_nums=`cat $tmp_dir/fxs_* | sort -n | xargs`
-+ zap_nums=`grep '^[^;].*Zap/\${CHAN_ZAP_' $exten_base_dir/*.conf | \
-+ sed -e 's/.*Zap\/\${CHAN_ZAP_\([0-9]*\)}.*/\1/' | sort -u | xargs`
-+ say "Configuring channels: $fxs_nums as channel placeholders: $zap_nums"
-+ j=1
-+ for i in $zap_nums
-+ do
-+ chan=`echo $fxs_nums | awk "{print \\$$i}"`
-+ if [ "$chan" = '' ]
-+ then
-+ # if the result is empty, we probably got past the last one.
-+ # bail out.
-+ say "Warning: No FXS channel for CHAN_ZAP_$i. Moving on"
-+ break
-+ fi
-+ say "DEBUG: setting channel $chan to placeholder $i"
-+ if grep -q "^CHAN_ZAP_$i " $exten_defs_file
-+ then
-+ sed -i -e "s/^CHAN_ZAP_$i .*/CHAN_ZAP_$i => Zap\/$chan/" $exten_defs_file
-+ else
-+ echo "CHAN_ZAP_$i => Zap/$chan" >> $exten_defs_file
-+ fi
-+ done
-+ fi
-+ # cleaning up the temp dir
-+ fi
-+ if [ -d "$tmp_dir" ]; then rm -rf "$tmp_dir"; fi
-+}
-+
-+check_for_astribank(){
-+ if ! grep -q XPP_IN/ /proc/zaptel/* 2>/dev/null
-+ then
-+ # we only get here is if we find no Astribank input channels
-+ # in /proc/zaptel . Hence we can safely disable their special settings:
-+ set_immediate=no
-+ fi
-+}
-+
-+usage() {
-+ program=`basename $0`
-+
-+ echo >&2 "$program: generate zaptel.conf and zapata.conf"
-+ echo >&2 "(version $VERSION_FULL)"
-+ echo >&2 "usage:"
-+ echo >&2 " $program [-sdv] [-m k|l|g] [-c <country_code>] [-r |-e <base_exten>] "
-+ echo >&2 " $program [-sdv] -l"
-+ echo >&2 " $program -su"
-+ echo >&2 " $program -h (this screen)"
-+ echo >&2 ""
-+ echo >&2 "Options:"
-+ echo >&2 " -c CODE: set the country code (default: $lc_country)"
-+ echo >&2 " -e NUM: set the base extension number (default: $base_exten)"
-+ echo >&2 " -F: Don't print FXSs in zapata.conf"
-+ echo >&2 " -l: output a list of detected channels instead of zaptel.conf"
-+ echo >&2 " -d: Perform hardware detection"
-+ echo >&2 " -u: Unload zaptel modules"
-+ echo >&2 " -v: verbose"
-+ echo >&2 " -s: Don't fail if asterisk is running. Stop it"
-+ echo >&2 " -r: rapid configuration mode: configure Zaptel FXS channels from "
-+ echo >&2 " existing Rapid extension files. FXOs will all be TRUNK "
-+}
-+
-+# $1: channel number
-+print_pattern() {
-+ local astbank_type=''
-+ OPTIND=1
-+ while getopts 'a:' arg
-+ do
-+ case "$arg" in
-+ a) case "$OPTARG" in input|output) astbank_type=$OPTARG;;esac ;;
-+ esac
-+ done
-+ shift $(( $OPTIND-1 ))
-+
-+
-+ local chan=$1
-+ local sig=$2 #fxs/fxo
-+ local mode=$3
-+ local method='ks'
-+ if [ "$lc_country" = il ] && [ "$sig" = 'fxs' ]
-+ then method=ls
-+ fi
-+ case "$mode" in
-+ zaptel)
-+ # sadly, both input ports and output ports go into the same span as
-+ # the FXS ports. Thus we need to separate between them. See also
-+ # the zapata.conf section:
-+ if [ "$astbank_type" != '' ]; then echo "# astbanktype: $astbank_type"; fi
-+ echo "${sig}$method=$chan"
-+ ;;
-+ list) echo $chan $sig $astbanktype;;
-+ zapata)
-+ # zap2amp will rewrite those from zaptel.conf and hints there
-+ if [ "$fxsdisable" = 'yes' ] && [ $sig = 'fxo' ]; then return; fi
-+
-+ echo "signalling=${sig}_$method"
-+ if [ "$sig" = 'fxo' ]
-+ then
-+ # to preconfigure channel 1's extension to 550, set
-+ # chan_1_exten=550
-+ # in, e.g, /etc/default/zaptel
-+ var_name=`echo chan_${chan}_exten`
-+ cfg_exten=`echo ${!var_name} | tr -d -c 0-9`
-+ var_name=`echo chan_${chan}_vmbox`
-+ cfg_vmbox=`echo ${!var_name} | tr -d -c 0-9`
-+ var_name=`echo chan_${chan}_cntxt`
-+ cfg_cntxt=`echo ${!var_name} | tr -d -c 0-9`
-+
-+ # if option -E was given, get configuration from current extension
-+ if [ "$rapid_conf_mode" = 'yes' ]
-+ then
-+ rap_exten=`echo $rapid_extens |awk "{print \\$$rapid_cur_exten}"`
-+ if [ "$rap_exten" != '' ]
-+ then
-+ rap_cfgfile="$exten_base_dir/$rap_exten.conf"
-+ if [ -r "$rap_exten" ]
-+ then
-+ cfg_exten=$rap_exten
-+ # the vmbox is the third parameter to stdexten
-+ rap_vmbox=`grep '^[^;].*Macro(stdexten' $rap_exten | cut -d, -f3 \
-+ | cut -d')' -f1 | tr -d -c '0-9 at a-zA-Z'`
-+ if [ "$rap_vmbox" ]!= '' ; then cfg_vmbox=$rap_vmbox; fi
-+ fi
-+ fi
-+ rapid_cur_exten=$(($rapid_cur_exten + 1))
-+ fi
-+
-+ if [ "$cfg_exten" = '' ]
-+ then # No extension number set for this channel
-+ exten=$(($chan+$base_exten))
-+ else # use the pre-configured extension number
-+ exten=$cfg_exten
-+ fi
-+ # is there any real need to set 'mailbox=' ?
-+ if [ "x$cfg_vmbox" = x ]
-+ then # No extension number set for this channel
-+ vmbox=$exten
-+ else # use the pre-configured extension number
-+ vmbox=$cfg_vmbox
-+ fi
-+ echo "callerid=\"Channel $chan\" <$exten>"
-+ echo "mailbox=$exten"
-+ if [ "$group_manual" != "yes" ]
-+ then
-+ echo "group=$group_phones"
-+ fi
-+ if [ "$context_manual" != "yes" ]
-+ then
-+ if [ "$astbank_type" != '' ];
-+ then
-+ context_var_name=context_$astbank_type
-+ echo context=${!context_var_name}
-+ else
-+ echo "context=$context_phones"
-+ fi
-+ fi
-+ else # this is an FXO (trunk/phone: FXO signalling)
-+ # we have may have set it. So reset it:
-+ echo "callerid=asrecieved"
-+ echo "mailbox="
-+ if [ "$group_manual" != "yes" ]
-+ then
-+ echo "group=$group_lines"
-+ fi
-+ if [ "$context_manual" != "yes" ]
-+ then
-+ echo "context=$context_lines"
-+ fi
-+ if [ "$lc_country" = 'uk' ]
-+ then
-+ echo "cidsignalling=v23"
-+ case $line in
-+ *WCFXO*) echo "cidstart=history";;
-+ *) echo "cidstart=polarity";; #a TDM400
-+ esac
-+ fi
-+ echo ";;; line=\"$line\""
-+ # if kewlstart is not used, busydetect has to be employed:
-+ if [ "$method" = 'ls' ]
-+ then echo 'busydetect=yes'
-+ else echo 'busydetect=no'
-+ fi
-+ fi
-+
-+ if [ "$set_immediate" = 'yes' ]
-+ then
-+ if [ "$astbank_type" = 'input' ]
-+ then echo 'immediate=yes'
-+ else echo 'immediate=no'
-+ fi
-+ fi
-+ echo "channel => $chan"
-+ echo ""
-+
-+ # Keep a note of what channels we have identified
-+ say "DEBUG: adding to channels list: channel: $chan, sig: $sig"
-+ case "$sig" in
-+ fxs)
-+ echo $chan >$tmp_dir/fxo_$chan
-+ say "DEBUG: FXO list now contains: `cat $tmp_dir/fxo_* |xargs`"
-+ ;;
-+ fxo)
-+ echo $chan >$tmp_dir/fxs_$chan
-+ say "DEBUG: FXS list now contains: `cat $tmp_dir/fxs_* |xargs`"
-+ ;;
-+ esac
-+ ;;
-+ esac
-+
-+}
-+
-+# the number of channels from /proc/zaptel
-+# must always print a number as its output.
-+count_proc_zap_lines() {
-+ # if zaptel is not loaded there are 0 channels:
-+ if [ ! -d /proc/zaptel ]; then echo '0'; return; fi
-+
-+ (
-+ for file in `echo /proc/zaptel/* |grep -v '\*'`
-+ do sed -e 1,2d $file # remove the two header lines
-+ done
-+ ) | wc -l # the total number of lines
-+}
-+
-+load_modules() {
-+ say "Test Loading modules:"
-+ for i in $ALL_MODULES
-+ do
-+ lines_before=`count_proc_zap_lines`
-+ args="${i}_args"
-+ eval "args=\$$args"
-+ # a module is worth listing if it:
-+ # a. loaded successfully, and
-+ # b. added channels lines under /proc/zaptel/*
-+ if /sbin/modprobe $i $args 2> /dev/null
-+ then
-+ check=0
-+ case "$i" in
-+ xpp_usb) check=`grep 'STATUS=connected' 2>/dev/null /proc/xpp/xbuses | wc -l` ;;
-+ *) if [ $lines_before -lt `count_proc_zap_lines` ]; then check=1; fi ;;
-+ esac
-+ if [ "$check" != 0 ]
-+ then
-+ probed_modules="$probed_modules $i"
-+ say " ok $i $args"
-+ else
-+ say " - $i $args"
-+ rmmod $i
-+ fi
-+ else
-+ say " - $i $args"
-+ fi
-+ done
-+}
-+
-+# recursively unload a module and its dependencies, if possible.
-+# where's modprobe -r when you need it?
-+# inputs: module to unload.
-+# returns: the result from
-+unload_module() {
-+ module="$1"
-+ line=`lsmod 2>/dev/null | grep "^$1 "`
-+ if [ "$line" = '' ]; then return; fi # module was not loaded
-+
-+ set -- $line
-+ # $1: the original module, $2: size, $3: refcount, $4: deps list
-+ mods=`echo $4 | tr , ' '`
-+ # old versions of xpd_fxs actually depend on xpp, but forget to tell it.
-+ # bug has already been fixed but the code will remain here for a while
-+ # just in case
-+ case "$module" in xpd_*) mods="xpp_usb $mods";; esac
-+ for mod in $mods; do
-+ # run in a subshell, so it won't step over our vars:
-+ (unload_module $mod)
-+ # TODO: the following is probably the error handling we want:
-+ # if [ $? != 0 ]; then return 1; fi
-+ done
-+ rmmod $module
-+}
-+
-+unload_modules() {
-+ if
-+ pids="$(pgrep asterisk)"
-+ [ "$pids" != '' ]
-+ then
-+ die "Before unloading -- STOP asterisk (pids=$pids)."
-+ fi
-+ say "Unloading zaptel modules:"
-+ unload_module zaptel
-+ say ''
-+}
-+
-+# sleep a while until the xpp modules fully register
-+wait_for_xpp() {
-+ if [ -d /proc/xpp ] && \
-+ [ "`cat /sys/module/xpp/parameters/zap_autoreg`" = 'Y' ]
-+ then
-+ # wait for the XPDs to register:
-+ # TODO: improve error reporting and produce a messagee here
-+ cat /proc/xpp/XBUS-*/wait_for_xpds 2>/dev/null >/dev/null || true
-+ fi
-+}
-+
-+detect() {
-+ unload_modules
-+ load_modules
-+ modlist="$probed_modules"
-+ #for i in $ALL_MODULES
-+ #do
-+ # if lsmod | grep "^$i *" > /dev/null; then
-+ # modlist="$modlist $i"
-+ # fi
-+ #done
-+ modlist="$(echo $modlist)" # clean spaces
-+ if [ "$do_module_list" = yes ]
-+ then
-+ say "Updating '${MODLIST_FILE}'"
-+ update_module_list "$modlist"
-+ fi
-+ if echo $modlist | grep -q xpp_usb; then wait_for_xpp; fi
-+}
-+
-+# TODO: kill this function. It is now unreferenced from anywhere.
-+check_tdm_sigtype() {
-+ chan_num=$1
-+ sig_type=$2
-+ mode=$3
-+
-+ case "$sig_type" in
-+ fxs)chan_sig_type=fxo;;
-+ fxo)chan_sig_type=fxs;;
-+ esac
-+
-+# print_pattern $chan_num $chan_sig_type $mode
-+
-+ # if you get syntax error from this line, make sure you use 'bash'
-+ # rather than 'sh'
-+ $ztcfg_cmd -c <(print_pattern $chan_num $chan_sig_type zaptel) 2>/dev/null \
-+ || return 1
-+ if head -c1 /dev/zap/$chan_num >/dev/null 2>/dev/null
-+ then
-+ print_pattern $chan_num $chan_sig_type $mode
-+ return 0
-+ else
-+ return 1
-+ fi
-+}
-+
-+# output a list of extensions that need a channel
-+get_rapid_extens() {
-+ if [ "$rapid_conf_mode" = 'yes' ]
-+ then
-+ rapid_extens=`grep -l '^[^;].*Zap/\${CHAN_ZAP_' $exten_base_dir/*.conf 2>/dev/null | \
-+ rev | cut -d/ -f1 | cut -d. -f2- | rev | xargs`
-+ say "Need to configure extensions: $rapid_extens"
-+ fi
-+}
-+
-+genconf() {
-+ local mode=$1
-+
-+ # reset FXO list (global)
-+ #say "DEBUG: resetting channels lists"
-+ rm -f $tmp_dir/fx{s,o}_*
-+
-+ if [ "$mode" = 'zapata' ]
-+ then
-+ rem_char=';'
-+ else
-+ rem_char='#'
-+ fi
-+
-+ spanlist=`echo /proc/zaptel/* | grep -v '\*'`
-+
-+ #if [ "$spanlist" == "" ]; then
-+ # die "No zapata interfaces in /proc/zaptel"
-+ #fi
-+
-+
-+ case "$mode" in
-+ zaptel)
-+ cat <<EOF
-+# Autogenerated by $0 -- do not hand edit
-+# Zaptel Configuration File
-+#
-+# This file is parsed by the Zaptel Configurator, ztcfg
-+#
-+
-+# It must be in the module loading order
-+
-+EOF
-+ ;;
-+ zapata)
-+ cat <<EOF
-+; Autogenerated by $0 -- do not hand edit
-+; Zaptel Channels Configurations (zapata.conf)
-+;
-+; This is not intended to be a complete zapata.conf. Rather, it is intended
-+; to be #include-d by /etc/zapata.conf that will include the global settings
-+;
-+EOF
-+ ;;
-+ esac
-+
-+ # For each line in the spanlist: see if it represents a channel.
-+ # if it does, test that the channel is usable.
-+ # we do that by configuring it (using ztcfg with a 1-line config file)
-+ # and then trying to read 1 byte from the device file.
-+ #
-+ # The '<(command)' syntax creates a temporary file whose content is is the
-+ # output of 'command'.
-+ #
-+ # This approach failed with the T1 card we have: the read operation simply
-+ # hung.
-+ #
-+ # Another problem with such an approach is how to include an existing
-+ # configuration file. For instance: how to include some default settings.
-+ #
-+ # Maybe an 'include' directive should be added to zaptel.conf ?
-+ #cat $spanlist |
-+ for procfile in $spanlist
-+ do
-+ span_num=`basename $procfile`
-+ # the first line is the title line. It states the model name
-+ # the second line is empty
-+ title=`head -n 1 $procfile`
-+ echo ""
-+ # stuff that needs to be remembered accross lines (for PRI support)
-+ echo "$rem_char $title"
-+ echo '-1' >$tmp_dir/span_begin
-+ echo '-1' >$tmp_dir/span_end
-+ echo '1' >$tmp_dir/span_timing
-+ echo '1' >$tmp_dir/span_lbo
-+ echo '' >$tmp_dir/span_framing
-+ echo 'ami' >$tmp_dir/span_coding
-+ echo '' >$tmp_dir/span_switchtype
-+ echo '' >$tmp_dir/span_signalling
-+
-+ if echo $title | egrep -q '((quad|octo)BRI PCI ISDN Card.* \[NT\]\ |octoBRI \[NT\] |HFC-S PCI A ISDN.* \[NT\] )'
-+ then
-+ echo 'nt' >$tmp_dir/span_termtype
-+ else
-+ if echo $title | egrep -q '((quad|octo)BRI PCI ISDN Card.* \[TE\]\ |octoBRI \[TE\] |HFC-S PCI A ISDN.* \[TE\] )'
-+ then
-+ echo 'te' >$tmp_dir/span_termtype
-+ fi
-+ fi
-+ # The rest of the lines are per-channel lines
-+ sed -e 1,2d $procfile | \
-+ while read line
-+ do
-+ # in case this is a real channel.
-+ chan_num=`echo $line |awk '{print $1}'`
-+ case "$line" in
-+ *WCTDM/*|*/WRTDM/*|*OPVXA1200/*)
-+ # this can be either FXS or FXO
-+ maybe_fxs=0
-+ maybe_fxo=0
-+ $ztcfg_cmd -c <(print_pattern $chan_num fxo zaptel) &>/dev/null && maybe_fxs=1
-+ $ztcfg_cmd -c <(print_pattern $chan_num fxs zaptel) &>/dev/null && maybe_fxo=1
-+ if [ $maybe_fxs = 1 ] && [ $maybe_fxo = 1 ]
-+ then
-+ # An installed module won't accept both FXS and FXO signalling types:
-+ # this is an empty slot.
-+ # TODO: I believe that the Sangoma A20x will reject both and thus
-+ # print nothing here.
-+ echo "$rem_char channel $chan_num, WCTDM, no module."
-+ continue
-+ fi
-+
-+ if [ $maybe_fxs = 1 ]; then print_pattern $chan_num fxo $mode; fi
-+ if [ $maybe_fxo = 1 ]; then print_pattern $chan_num fxs $mode; fi
-+ ;;
-+ *WCFXO/*)
-+ print_pattern $chan_num fxs $mode || \
-+ echo "$rem_char channel $chan_num, WCFXO, inactive."
-+ ;;
-+ *WCUSB/*)
-+ print_pattern $chan_num fxo $mode
-+ ;;
-+ *XPP_FXO/*)
-+ print_pattern $chan_num fxs $mode
-+ ;;
-+ *XPP_FXS/*)
-+ print_pattern $chan_num fxo $mode
-+ ;;
-+ *XPP_OUT/*)
-+ print_pattern -a output $chan_num fxo $mode
-+ ;;
-+ *XPP_IN/*)
-+ print_pattern -a input $chan_num fxo $mode
-+ ;;
-+ *ZTHFC*/*|*ztqoz*/*|*ztgsm/*|*TE4/*|*TE2/*|*WCT1/*|*Tor2/*|*TorISA/*) # should also be used for other PRI channels
-+ if [ "`cat $tmp_dir/span_begin`" = "-1" ]
-+ then
-+ echo $chan_num >$tmp_dir/span_begin
-+ echo $span_num >$tmp_dir/span_num
-+ case "$line" in
-+ *ZTHFC*/*|*ztqoz*/*)
-+ echo 'ccs' >$tmp_dir/span_framing
-+ echo 'euroisdn' >$tmp_dir/span_switchtype
-+ if [ "`cat $tmp_dir/span_termtype`" = 'nt' 2>/dev/null ]
-+ then
-+ echo 'bri_net' >$tmp_dir/span_signalling
-+ else
-+ echo 'bri_cpe' >$tmp_dir/span_signalling
-+ fi
-+ ;;
-+ *ztgsm*/*)
-+ echo 'ccs' >$tmp_dir/span_framing
-+ # what switch type? Any meaning to it?
-+ echo 'gsm' >$tmp_dir/span_signalling
-+ ;;
-+ *TE4/*|*TE2/*|*WCT1/*|*Tor2/*|*TorISA/*)
-+ echo 'esf' >$tmp_dir/span_framing
-+ echo 'b8zs' >$tmp_dir/span_coding
-+ echo 'national' >$tmp_dir/span_switchtype
-+ echo 'pri_cpe' >$tmp_dir/span_signalling
-+ # an example of country-specific setup. This is probably not accurate
-+ # Contributions are welcome
-+ case "$lc_country" in
-+ nl)
-+ # (Just an example for per-country info)
-+ echo 'ccs' >$tmp_dir/span_framing
-+ echo 'ami' >$tmp_dir/span_coding
-+ #echo 'crc4' >$tmp_dir/span_yellow
-+ #echo 'euroisdn' >$tmp_dir/span_switchtype
-+ #echo 'pri_cpe' >$tmp_dir/span_signalling
-+ ;;
-+ il)
-+ echo 'ccs' >$tmp_dir/span_framing
-+ echo 'hdb3' >$tmp_dir/span_coding
-+ echo 'crc4' >$tmp_dir/span_yellow
-+ echo 'euroisdn' >$tmp_dir/span_switchtype
-+ esac
-+ ;;
-+ esac
-+ fi
-+ # span_lastd is always the one before last
-+ # channel. span_bchan is the last:
-+ echo $chan_num >$tmp_dir/span_end
-+ ;;
-+ '') ;; # Empty line (after span header)
-+ *) echo "$rem_char ??: $line";;
-+ esac
-+ done
-+ if [ "`cat $tmp_dir/span_begin`" != -1 ]
-+ then # write PRI span ocnfig:
-+ # read files to variables:
-+ for suffix in num begin end timing lbo framing \
-+ coding switchtype signalling yellow termtype
-+ do
-+ eval span_$suffix=`cat $tmp_dir/span_$suffix 2>/dev/null`
-+ done
-+ if [ "$span_yellow" != '' ]; then span_yellow=",$span_yellow"; fi
-+ # exactly the same logic is used in asterisk's chan_zap.c.
-+ # also not that $(( )) is bash-specific
-+ case "$((1+ $span_end - $span_begin))" in
-+ 2|3|24) #ztgsm, BRI or T1
-+ dchan=$span_end
-+ bchans="$span_begin-$(($span_end-1))"
-+ ;;
-+ 31) #E1
-+ dchan="$(($span_begin+15))"
-+ bchans="$span_begin-$(($span_begin+14)),$(($span_begin+16))-$span_end"
-+ ;;
-+ esac
-+ case "$mode" in
-+ zaptel)
-+ echo span=$span_num,$span_timing,$span_lbo,$span_framing,$span_coding$span_yellow
-+ if [ "$span_termtype" != '' ]
-+ then echo "# termtype: $span_termtype"
-+ fi
-+ echo bchan=$bchans
-+ echo dchan=$dchan
-+ ;;
-+ zapata)
-+ if [ "$span_termtype" != '' ]
-+ then
-+ # an ISDN card's span that we know if it is in NT mode or TE mode.
-+ # NT is the same as FXS for us and TE is the same as FXO
-+ if [ "$span_termtype" = 'nt' ]
-+ then
-+ echo "callerid=\"Channels $span_begin - $span_end\" <$span_begin>"
-+ #echo "mailbox=$exten"
-+ if [ "$group_manual" != "yes" ]
-+ then
-+ echo "group=$group_phones"
-+ fi
-+ if [ "$context_manual" != "yes" ]
-+ then
-+ echo "context=$context_phones"
-+ fi
-+ else # we have may have set it. So reset it:
-+ echo "callerid=asrecieved"
-+ #echo "mailbox="
-+ if [ "$group_manual" != "yes" ]
-+ then
-+ echo "group=$group_lines"
-+ fi
-+ if [ "$context_manual" != "yes" ]
-+ then
-+ echo "context=$context_lines"
-+ fi
-+ fi
-+ fi
-+ echo "switchtype = $span_switchtype"
-+ echo "signalling = $span_signalling"
-+ echo "channel => $bchans"
-+ ;;
-+ list)
-+ echo BRI/PRI: chans: $bchans, control: $dchan
-+ ;;
-+ esac
-+ fi
-+ done
-+
-+ if [ "$mode" = 'zaptel' ]
-+ then
-+ cat <<EOF
-+
-+# Global data
-+
-+EOF
-+ echo "loadzone = $loadzone"
-+ echo "defaultzone = $defaultzone"
-+ fi
-+
-+ if [ "$mode" = 'zapata' ] || [ "$mode" = 'list' ]
-+ then
-+ update_extensions_defs
-+ fi
-+}
-+
-+while getopts 'c:de:Fhlm:Mrsuv' arg
-+do
-+ case "$arg" in
-+ e) # guarantee that it is a number:
-+ new_base_exten=`echo $OPTARG | tr -d -c 0-9`
-+ if [ "x$new_base_exten" != x ]; then base_exten=$new_base_exten; fi
-+ ;;
-+ c) lc_country=`echo $OPTARG | tr -d -c a-z` ;;
-+ d) do_detect=yes ;;
-+ F) fxsdisable=yes;;
-+ u) do_unload=yes ;;
-+ v) verbose=yes ;;
-+ l) mode='list' ;;
-+ M) do_module_list=yes; do_detect=yes ;;
-+ s) force_stop_ast=yes ;;
-+ r)
-+ rapid_conf_mode=yes
-+ ;;
-+ h) usage; exit 0;;
-+ *) echo >&2 "unknown parameter -$arg, Aborting"; usage; exit 1;;
-+ esac
-+done
-+shift $(( $OPTIND-1 ))
-+if [ $# != 0 ]; then
-+ echo >&2 "$0: too many parameters"
-+ usage
-+ exit 1
-+fi
-+
-+tmp_dir=`mktemp -d -t` || \
-+ die "$0: failed to create temporary directory. Aborting"
-+
-+
-+case "$lc_country" in
-+ # the list was generated from the source of zaptel:
-+ #grep '{.*[0-9]\+,.*"[a-z][a-z]"' zonedata.c | cut -d'"' -f 2 | xargs |tr ' ' '|'
-+ us|au|fr|nl|uk|fi|es|jp|no|at|nz|it|gr|tw|cl|se|be|sg|il|br|hu|lt|pl|za|pt|ee|mx|in|de|ch|dk|cz|cn):;;
-+ *)
-+ lc_country=us
-+ echo >&2 "unknown country-code $lc_country, defaulting to \"us\""
-+ ;;
-+esac
-+# any reason for loadzone and defaultzone to be different? If so, this is
-+# the place to make that difference
-+loadzone=$lc_country
-+defaultzone=$loadzone
-+
-+# make sure asterisk is not in our way
-+if [ "$force_stop_ast" = 'yes' ]
-+then
-+ /etc/init.d/asterisk stop 1>&2
-+else
-+ # if asterisk is running and we wanted to detect modules
-+ # or simply to unload modules, asterisk needs to go away.
-+ if ( [ "$do_unload" = yes ] || [ "$do_detect" = yes ] ) && \
-+ pidof asterisk >/dev/null
-+ then
-+ echo >&2 "Asterisk is already running. Configuration left untouched"
-+ echo >&2 "You can use the option -s to shut down Asterisk for the"
-+ echo >&2 "duration of the detection."
-+ exit 1
-+ fi
-+fi
-+
-+if [ "$do_unload" = yes ]
-+then
-+ unload_modules
-+ exit
-+fi
-+
-+if [ "$do_detect" = yes ]
-+then
-+ detect
-+fi
-+
-+if [ "$mode" = list ]; then
-+ genconf list
-+else
-+ check_for_astribank
-+ get_rapid_extens
-+ say "Generating '${ZAPCONF_FILE}'"
-+ mv "${ZAPCONF_FILE}" "${ZAPCONF_FILE}.bak"
-+ genconf zaptel > "${ZAPCONF_FILE}"
-+ say "Generating '${ZAPATA_FILE}'"
-+ mv "${ZAPATA_FILE}" "${ZAPATA_FILE}.bak"
-+ genconf zapata > "${ZAPATA_FILE}"
-+ if [ "$set_immediate" = 'yes' ] && [ -x /etc/init.d/zaptel ]
-+ then /etc/init.d/zaptel start
-+ else run_ztcfg
-+ fi
-+fi
-+
-+if [ "$tmp_dir" != '' ]
-+then
-+ rm -rf "$tmp_dir"
-+fi
-+
-+if [ "$force_stop_ast" = 'yes' ]
-+then
-+ if [ -x /etc/init.d/asterisk ]
-+ then
-+ /etc/init.d/asterisk start 1>&2
-+ fi
-+fi
-+
-+# if in verbose mode: verify that asterisk is running
-+if [ "$verbose" != 'no' ] && [ "$force_stop_ast" = 'yes' ]
-+ then
-+ say "Checking channels configured in Asterisk:"
-+ sleep 1 # give it some time. This is enough on our simple test server
-+ if [ -x ast-cmd ]
-+ then
-+ ast-cmd cmd "zap show channels"
-+ else
-+ asterisk -rx "zap show channels"
-+ fi
-+fi
-+
-+# vim:ts=2:
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/utils/genzaptelconf.8 zaptel-xpp-LJNBCn_dist/xpp/utils/genzaptelconf.8
---- zaptel-1.2.6/xpp/utils/genzaptelconf.8 1970-01-01 02:00:00.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/utils/genzaptelconf.8 2006-06-17 09:56:07.169240000 +0300
-@@ -0,0 +1,258 @@
-+.TH GENZAPTELCONF 8 "July 18th, 2005" "Xorcom Rapid Asterisk" "Linux Programmer's Manual"
-+.SH "NAME"
-+.B genzaptelconf
-+-- generates zaptel configuration (TDM adaptors)
-+.SH SYNOPSIS
-+.PP
-+.B genzaptelconf
-+[-sdv] [-c <country_code>] [-r |-e <base_exten>] [ -F ]
-+
-+.B genzaptelconf
-+[-sdv] -l -- only list to standard output
-+
-+.B genzaptelconf
-+-su -- only unload zaptel modules
-+
-+.B genzaptelconf
-+-h -- Help screen
-+
-+.SH DESCRIPTION
-+.B genzaptelconf
-+is a script to detect zaptel devices (currently mostly TDM cards are
-+supported). It generates both
-+.I /etc/zaptel.conf
-+and
-+.I /etc/asterisk/zapata-channels.conf
-+
-+.I PRI
-+and
-+.I BRI
-+(HFC, with ZapBRI) cards are basically identified as well. However the span
-+configiration is a default that I only hope is sane. Looking for feedback
-+
-+.SH OPTIONS
-+.B -c
-+.I country_code
-+.RS
-+A two-letter country code. Sets the country-code for the zonezone
-+entries in
-+.I zaptel.conf
-+, The default is the value of
-+.I lc_country
-+from
-+.I /etc/default/zaptel
-+and failing that, "us".
-+.RE
-+
-+.B -d
-+.RS
-+Also try to detect modules. Unloads all zaptel modules and loads them
-+one by one. Considers a module useful if it loaded successfully and if
-+loading it has generated at least one zapata channel.
-+
-+The list of detected modules is written as the value of
-+.I ZAPTEL_MODS
-+in
-+.I /etc/default/zaptel
-+.RE
-+
-+.B -e
-+.I base_exten_num
-+.RS
-+Configure channel
-+.I i
-+as extension
-+.I exten_num
-++
-+.I i
-+. This is mostly for the caller-id values. Crude, but may be good enough.
-+See also
-+.I -r
-+.RE
-+
-+.B -F
-+.RS
-+Disable writing FXS extensions in zapata.conf
-+.RE
-+
-+.B -l
-+.RS
-+Only list deceted channels and their signalling. Don't write
-+configuration files. Note, however that
-+.I -ld
-+will still rewrite the modules line in
-+.I /etc/default/zaptel
-+(see
-+.I -d
-+above).
-+.RE
-+
-+.B -M
-+.RS
-+Update
-+.I /etc/modules
-+with a list of our modules, thereby
-+triggers their loading via modprobe on the next boot.
-+
-+This triggers the
-+.I -d
-+option as well.
-+.RE
-+
-+.B -r
-+.RS
-+Try to guess a useful
-+.I zapata-channels
-+configuration for Xorcom Rapid .
-+.RE
-+
-+.B -s
-+.RS
-+Stop asterisk for the duration of the test. The detection will only
-+work if nobody uses the zaptel channels:
-+
-+* To allow unloading of modules
-+
-+* to allow reading configuration files.
-+
-+By default the script will check if asterisk is running and alert if so.
-+This option tells the script to stop asterisk (if it was running) and to
-+try to start it after the end of the test.
-+.RE
-+
-+.B -v
-+.RS
-+Be verbose. lists the detected modules if
-+.I -d
-+is used. Lists detected channls. In the end tries to connect to asterisk
-+to get a list of configured zaptel channels.
-+.RE
-+.SH FILES
-+.I /etc/zaptel.conf
-+.RS
-+The configuration file used by
-+.I ztcfg
-+to configure zaptel devices. re-written by
-+.I genzaptelconf
-+.RE
-+
-+.I /etc/zaptel.conf.bak
-+.RS
-+When
-+.I zaptel.conf
-+The original zaptel.conf
-+.RE
-+
-+.I /etc/asterisk/zapata.conf
-+.RS
-+The configuration file of Asterisk's
-+.I chan_zap.
-+Not modified directly by
-+.I genzaptelconf.
-+If you want genzaptelconf's setting to take effect, add the following
-+line at the end of
-+.I zapata.conf:
-+.RS
-+#include "zapata-channels.conf"
-+.RE
-+.RE
-+
-+.I /etc/asterisk/zapata-channels.conf
-+.RS
-+This is the snippet of
-+.I chan_zap
-+configuration file that
-+.I genzaptelconf generates.
-+.RE
-+
-+.I /etc/asterisk/zapata-channels.conf.bak
-+.RS
-+The backup copy of
-+.I zapata-channels.conf
-+.RE
-+
-+.I /etc/default/zaptel
-+.RS
-+This file holds configuration for both
-+.I genzaptelconf
-+and
-+.I /etc/init.d/zaptel .
-+It is sourced by both scripts and can thus be used to override settings
-+of variables from those scripts.
-+Some of the variables that can be set in /etc/default/zaptel and affect
-+genzaptelconf:
-+
-+.I lc_country
-+.RS
-+The default country. Can be also overriden by the option -c
-+.RE
-+
-+.I base_exten
-+.RS
-+The base number used for automatic numbering
-+.RE
-+
-+.I context_manual
-+.RS
-+If set to 'yes', no context changes are made in zapata-channels.conf
-+.RE
-+
-+.I context_lines
-+.RS
-+The context into which calls will go from zaptel trunks.
-+.RE
-+
-+.I context_phones
-+.RS
-+The context into which calls will go from zaptel phones.
-+.RE
-+
-+.I context_manual
-+.RS
-+If set to 'yes', no group settings are made in zapata-channels.conf
-+.RE
-+
-+.I group_lines
-+.RS
-+The group number for zaptel trunks.
-+.RE
-+
-+.I group_phones
-+.RS
-+The group number for zaptel phones.
-+.RE
-+
-+.I ALL_MODULES
-+.RS
-+modules list. Used for unloading and modules detection. The order of modules
-+is the same for both.
-+.RE
-+.RE
-+
-+.I /etc/modules
-+.RS
-+A debian-specific list of kernel modules to be loaded by modprobe at
-+boot time. When the option
-+.I -d
-+(detect) is used, genzaptelconf will write in this file zaptel modules
-+to be loaded. If you want to use a different file, set
-+.I MOD_FILELIST
-+.RE
-+
-+.I /etc/modules.bak
-+.RS
-+The backup copy of
-+.I /etc/modules
-+.RE
-+
-+.SH "SEE ALSO"
-+ztcfg(8) asterisk(8).
-+
-+.SH "AUTHOR"
-+This manual page was written by Tzafrir Cohen <tzafrir.cohen at xorcom.com>
-+Permission is granted to copy, distribute and/or modify this document under
-+the terms of the GNU General Public License, Version 2 any
-+later version published by the Free Software Foundation.
-+
-+On Debian systems, the complete text of the GNU General Public
-+License can be found in /usr/share/common-licenses/GPL.
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/utils/hexfile.c zaptel-xpp-LJNBCn_dist/xpp/utils/hexfile.c
---- zaptel-1.2.6/xpp/utils/hexfile.c 1970-01-01 02:00:00.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/utils/hexfile.c 2006-06-18 17:05:04.917972000 +0300
-@@ -0,0 +1,360 @@
-+/*
-+ * Written by Oron Peled <oron at actcom.co.il>
-+ * Copyright (C) 2006, Xorcom
-+ *
-+ * All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ */
-+
-+#include <stdio.h>
-+#include <assert.h>
-+#include <string.h>
-+#include <stdlib.h>
-+#include <errno.h>
-+#include "hexfile.h"
-+
-+static const char rcsid[] = "$Id:$";
-+
-+static parse_hexfile_report_func_t report_func = NULL;
-+
-+parse_hexfile_report_func_t parse_hexfile_set_reporting(parse_hexfile_report_func_t rf)
-+{
-+ parse_hexfile_report_func_t old_rf = report_func;
-+ report_func = rf;
-+ return old_rf;
-+}
-+
-+static void chomp(char buf[])
-+{
-+ size_t last = strlen(buf) - 1;
-+ while(last >= 0 && (buf[last] == '\n' || buf[last] == '\r'))
-+ buf[last--] = '\0';
-+}
-+
-+int checksum(struct hexline *hexline)
-+{
-+ unsigned int i;
-+ unsigned int chksm = 0;
-+ int ll = hexline->d.content.header.ll;
-+
-+ for(i = 0; i <= sizeof(hexline->d.content.header) + ll; i++) {
-+ chksm += hexline->d.raw[i];
-+ }
-+ return chksm & 0xFF;
-+}
-+
-+static int update_hexline(struct hexdata *hexdata, char *buf)
-+{
-+ int ret;
-+ unsigned int ll, offset, tt;
-+ char *p;
-+ struct hexline *hexline;
-+ unsigned int i;
-+ int allocsize;
-+ unsigned int last_line = hexdata->last_line;
-+
-+ if(hexdata->got_eof) {
-+ if(report_func)
-+ report_func(LOG_ERR, "Extranous data after EOF record\n");
-+ return -EINVAL;
-+ }
-+ if(last_line >= hexdata->maxlines) {
-+ if(report_func)
-+ report_func(LOG_ERR, "Hexfile too large (maxline %d)\n", hexdata->maxlines);
-+ return -ENOMEM;
-+ }
-+ ret = sscanf(buf, "%02X%04X%02X", &ll, &offset, &tt);
-+ if(ret != 3) {
-+ if(report_func)
-+ report_func(LOG_ERR, "Bad line header (only %d items out of 3 parsed)\n", ret);
-+ return -EINVAL;
-+ }
-+ switch(tt) {
-+ case TT_DATA:
-+ break;
-+ case TT_EOF:
-+ if(ll != 0) {
-+ if(report_func)
-+ report_func(LOG_ERR, "Bad EOF record len = %d\n", ll);
-+ return -EINVAL;
-+ }
-+ if(offset != 0) {
-+ if(report_func)
-+ report_func(LOG_ERR, "Bad EOF record offset = %d\n", offset);
-+ return -EINVAL;
-+ }
-+ hexdata->got_eof = 1;
-+ break;
-+ case TT_EXT_SEG: /* Unimplemented */
-+ case TT_START_SEG: /* Unimplemented */
-+ case TT_EXT_LIN: /* Unimplemented */
-+ case TT_START_LIN: /* Unimplemented */
-+ return 1;
-+ default:
-+ if(report_func)
-+ report_func(LOG_ERR, "Unknown record type %d\n", tt);
-+ return -EINVAL;
-+ }
-+ buf += 8; /* Skip header */
-+ ll++; /* include the checksum for now */
-+ allocsize = sizeof(struct hexline) + ll;
-+ if((hexline = (struct hexline *)malloc(allocsize)) == NULL) {
-+ if(report_func)
-+ report_func(LOG_ERR, "No more memory for hexfile lines\n");
-+ return -EINVAL;
-+ }
-+ memset(hexline, 0, allocsize);
-+ hexline->d.content.header.ll = ll;
-+ hexline->d.content.header.offset = offset;
-+ hexline->d.content.header.tt = tt;
-+ hexdata->lines[last_line++] = hexline;
-+ p = buf;
-+ for(i = 0; i < ll; i++) {
-+ unsigned int val;
-+
-+ if((*p == '\0') || (*(p+1) == '\0')) {
-+ if(report_func)
-+ report_func(LOG_ERR, "Short data string '%s'\n", buf);
-+ return -EINVAL;
-+ }
-+ ret = sscanf(p, "%02X", &val);
-+ if(ret != 1) {
-+ if(report_func)
-+ report_func(LOG_ERR, "Bad data byte #%d\n", i);
-+ return -EINVAL;
-+ }
-+ hexline->d.content.tt_data.data[i] = val;
-+ p += 2;
-+ }
-+ hexline->d.content.header.ll--; /* Fix the checksum */
-+ if(checksum(hexline) != 0) {
-+ if(report_func)
-+ report_func(LOG_ERR, "Bad checksum\n");
-+ return -EINVAL;
-+ }
-+ if(hexdata->got_eof)
-+ return 0;
-+ hexdata->last_line++;
-+ return 1;
-+}
-+
-+void free_hexdata(struct hexdata *hexdata)
-+{
-+ if(hexdata) {
-+ unsigned int i;
-+
-+ for(i = 0; i < hexdata->maxlines; i++)
-+ if(hexdata->lines[i] != NULL)
-+ free(hexdata->lines[i]);
-+ free(hexdata);
-+ }
-+}
-+
-+int dump_hexfile(struct hexdata *hexdata, FILE *outfile)
-+{
-+ uint8_t ll;
-+ uint16_t offset;
-+ uint8_t tt;
-+ uint8_t old_chksum;
-+ uint8_t new_chksum;
-+ uint8_t *data;
-+ unsigned int i;
-+ unsigned int j;
-+
-+ for(i = 0; i <= hexdata->last_line; i++) {
-+ struct hexline *line = hexdata->lines[i];
-+ if(!line) {
-+ if(report_func)
-+ report_func(LOG_ERR, "Missing line at #%d\n", i);
-+ return -EINVAL;
-+ }
-+ ll = line->d.content.header.ll;
-+ offset = line->d.content.header.offset;
-+ tt = line->d.content.header.tt;
-+ fprintf(outfile, ":%02X%04X%02X", ll, offset, tt);
-+ data = line->d.content.tt_data.data;
-+ for(j = 0; j < ll; j++) {
-+ fprintf(outfile, "%02X", data[j]);
-+ }
-+ old_chksum = data[ll];
-+ data[ll] = 0;
-+ new_chksum = 0xFF - checksum(line) + 1;
-+ data[ll] = old_chksum;
-+ assert(new_chksum == old_chksum);
-+ fprintf(outfile, "%02X\n", new_chksum);
-+ }
-+ return 0;
-+}
-+
-+int dump_hexfile2(struct hexdata *hexdata, FILE *outfile, uint8_t maxwidth)
-+{
-+ uint8_t ll;
-+ uint8_t tt;
-+ uint8_t new_chksum;
-+ uint8_t *data;
-+ unsigned int i;
-+ unsigned int j;
-+
-+ if (maxwidth <= sizeof(hexdata->lines[0]->d.content.header) ){
-+ if(report_func)
-+ report_func(LOG_ERR, "Line width too small %d\n", maxwidth);
-+ return -EINVAL;
-+ }
-+
-+ for(i = 0; i <= hexdata->last_line; i++) {
-+ struct hexline *line = hexdata->lines[i];
-+ struct hexline *extraline;
-+ int allocsize;
-+ int bytesleft = 0;
-+ int extra_offset = 0;
-+ unsigned int this_line = 0;
-+
-+ if(!line) {
-+ if(report_func)
-+ report_func(LOG_ERR, "Missing line at #%d\n", i);
-+ return -EINVAL;
-+ }
-+ ll = line->d.content.header.ll;
-+ bytesleft = ll;
-+ /* split the line into several lines */
-+ tt = line->d.content.header.tt;
-+ while (bytesleft > 0) {
-+ this_line = (bytesleft >= maxwidth) ? maxwidth : bytesleft;
-+ allocsize = sizeof(struct hexline) + this_line + 1;
-+ /* generate the new line */
-+ if((extraline = (struct hexline *)malloc(allocsize)) == NULL) {
-+ if(report_func)
-+ report_func(LOG_ERR, "No more memory for hexfile lines\n");
-+ return -EINVAL;
-+ }
-+ memset( extraline, 0, allocsize );
-+ extraline->d.content.header.ll = this_line;
-+ extraline->d.content.header.offset = line->d.content.header.offset + extra_offset;
-+ extraline->d.content.header.tt = tt;
-+ memcpy( extraline->d.content.tt_data.data, line->d.content.tt_data.data+extra_offset, this_line);
-+ new_chksum = 0xFF - checksum(extraline) + 1;
-+ /* print it */
-+ data = extraline->d.content.tt_data.data;
-+ fprintf(outfile, ":%02X%04X%02X", extraline->d.content.header.ll, extraline->d.content.header.offset, tt);
-+ for(j = 0; j < this_line; j++) {
-+ fprintf(outfile, "%02X", data[j]);
-+ }
-+ fprintf(outfile, "%02X\n", new_chksum);
-+ /* cleanups */
-+ free( extraline);
-+ extra_offset += this_line;
-+ bytesleft -= this_line;
-+ }
-+ }
-+ return 0;
-+}
-+
-+struct hexdata *parse_hexfile(const char *fname, unsigned int maxlines)
-+{
-+ FILE *fp;
-+ struct hexdata *hexdata = NULL;
-+ int datasize;
-+ char buf[BUFSIZ];
-+ int line;
-+ int ret;
-+
-+ assert(fname != NULL);
-+ if(report_func)
-+ report_func(LOG_INFO, "Parsing %s\n", fname);
-+ datasize = sizeof(struct hexdata) + maxlines * sizeof(char *);
-+ hexdata = (struct hexdata *)malloc(datasize);
-+ if(!hexdata) {
-+ if(report_func)
-+ report_func(LOG_ERR, "Failed to allocate %d bytes for hexfile contents\n", datasize);
-+ goto err;
-+ }
-+ memset(hexdata, 0, datasize);
-+ hexdata->maxlines = maxlines;
-+ if((fp = fopen(fname, "r")) == NULL) {
-+ if(report_func)
-+ report_func(LOG_ERR, "Failed to open hexfile '%s'\n", fname);
-+ goto err;
-+ }
-+ line = 0;
-+ while(fgets(buf, BUFSIZ, fp)) {
-+ line++;
-+ if(buf[0] == '\0') {
-+ if(report_func)
-+ report_func(LOG_ERR, "Short line at %s:%d\n", fname, line);
-+ goto err;
-+ }
-+ chomp(buf);
-+ if(buf[0] == '#') {
-+ if(report_func)
-+ report_func(LOG_INFO, "Comment '%s'\n", buf + 1);
-+ continue;
-+ }
-+ if(buf[0] != ':') {
-+ if(report_func)
-+ report_func(LOG_ERR, "Line begins with 0x%X at %s:%d\n", buf[0], fname, line);
-+ goto err;
-+ }
-+ if((ret = update_hexline(hexdata, buf + 1)) < 0) {
-+ if(report_func)
-+ report_func(LOG_ERR, "Failed parsing %s at line: %d\n", fname, line);
-+ goto err;
-+ }
-+ }
-+ fclose(fp);
-+ if(report_func)
-+ report_func(LOG_INFO, "%s parsed OK\n", fname);
-+ return hexdata;
-+err:
-+ free_hexdata(hexdata);
-+ return NULL;
-+}
-+
-+void dump_binary(struct hexdata *hexdata, const char *outfile)
-+{
-+ FILE *fp;
-+ unsigned int i;
-+ size_t len;
-+
-+ if(report_func)
-+ report_func(LOG_INFO, "Dumping binary data into '%s'\n", outfile);
-+ if((fp = fopen(outfile, "w")) == NULL) {
-+ perror(outfile);
-+ exit(1);
-+ }
-+ for(i = 0; i < hexdata->maxlines; i++) {
-+ struct hexline *hexline = hexdata->lines[i];
-+
-+ if(!hexline)
-+ break;
-+ if(hexline->d.content.header.tt == TT_EOF) {
-+ if(report_func)
-+ report_func(LOG_INFO, "\ndump: good EOF record");
-+ continue;
-+ }
-+ if(report_func)
-+ report_func(LOG_INFO, "dump: %6d\r", i);
-+ len = hexline->d.content.header.ll;
-+ if(fwrite(hexline->d.content.tt_data.data, 1, len, fp) != len) {
-+ perror("write");
-+ exit(1);
-+ }
-+ }
-+ if(report_func)
-+ report_func(LOG_INFO, "\nDump finished\n");
-+ fclose(fp);
-+}
-+
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/utils/hexfile.h zaptel-xpp-LJNBCn_dist/xpp/utils/hexfile.h
---- zaptel-1.2.6/xpp/utils/hexfile.h 1970-01-01 02:00:00.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/utils/hexfile.h 2006-05-15 17:27:26.264723000 +0300
-@@ -0,0 +1,120 @@
-+/*
-+ * Written by Oron Peled <oron at actcom.co.il>
-+ * Copyright (C) 2006, Xorcom
-+ *
-+ * All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ */
-+
-+#ifndef PARSE_HEXFILE_H
-+#define PARSE_HEXFILE_H
-+
-+#include <stdarg.h>
-+
-+/*
-+ * Some portability workarounds
-+ */
-+#ifdef _WINDOWS
-+
-+#include <windows.h> /* for UCHAR USHORT */
-+typedef UCHAR uint8_t;
-+typedef USHORT uint16_t;
-+#define PACKED
-+#define sscanf sscanf_s
-+#define ZERO_SIZE 1
-+
-+/* From /usr/include/syslog.h */
-+#define LOG_EMERG 0 /* system is unusable */
-+#define LOG_ALERT 1 /* action must be taken immediately */
-+#define LOG_CRIT 2 /* critical conditions */
-+#define LOG_ERR 3 /* error conditions */
-+#define LOG_WARNING 4 /* warning conditions */
-+#define LOG_NOTICE 5 /* normal but significant condition */
-+#define LOG_INFO 6 /* informational */
-+#define LOG_DEBUG 7 /* debug-level messages */
-+
-+#ifdef __cplusplus
-+# define __BEGIN_DECLS extern "C" {
-+# define __END_DECLS }
-+#else
-+# define __BEGIN_DECLS
-+# define __END_DECLS
-+#endif
-+
-+#elif __GNUC__
-+
-+#include <stdint.h>
-+#include <syslog.h>
-+#define PACKED __attribute__((packed))
-+#define ZERO_SIZE 1
-+
-+#else
-+
-+#error "Cannot compile on this platform"
-+
-+#endif
-+
-+/* Record types in hexfile */
-+enum {
-+ TT_DATA = 0,
-+ TT_EOF = 1,
-+ TT_EXT_SEG = 2,
-+ TT_START_SEG = 3,
-+ TT_EXT_LIN = 4,
-+ TT_START_LIN = 5,
-+ TT_NO_SUCH_TT
-+};
-+
-+#pragma pack(1)
-+struct hexline {
-+ union {
-+ uint8_t raw[ZERO_SIZE];
-+ struct content {
-+ struct header {
-+ uint8_t ll; /* len */
-+ uint16_t offset; /* offset */
-+ uint8_t tt; /* type */
-+ } PACKED header;
-+ struct tt_data {
-+ uint8_t data[ZERO_SIZE];
-+ } tt_data;
-+ } PACKED content;
-+ } d;
-+} PACKED;
-+#pragma pack()
-+
-+struct hexdata {
-+ unsigned int maxlines;
-+ unsigned int last_line;
-+ int got_eof;
-+ struct hexline *lines[ZERO_SIZE];
-+};
-+
-+
-+__BEGIN_DECLS
-+
-+typedef void (*parse_hexfile_report_func_t)(int level, const char *msg, ...);
-+
-+parse_hexfile_report_func_t parse_hexfile_set_reporting(parse_hexfile_report_func_t rf);
-+void free_hexdata(struct hexdata *hexdata);
-+struct hexdata *parse_hexfile(const char *fname, unsigned int maxlines);
-+int dump_hexfile(struct hexdata *hexdata, FILE *outfile);
-+int dump_hexfile2(struct hexdata *hexdata, FILE *outfile, uint8_t maxwidth);
-+void dump_binary(struct hexdata *hexdata, const char *outfile);
-+__END_DECLS
-+
-+#endif
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/utils/Makefile zaptel-xpp-LJNBCn_dist/xpp/utils/Makefile
---- zaptel-1.2.6/xpp/utils/Makefile 1970-01-01 02:00:00.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/utils/Makefile 2006-07-02 17:49:51.471281000 +0300
-@@ -0,0 +1,50 @@
-+PEDANTIC = -ansi -pedantic -std=c99
-+
-+CC = gcc
-+RANLIB = ranlib
-+INSTALL = install
-+INSTALL_DATA = install -m 644
-+
-+BINDIR = /usr/sbin
-+DATADIR = /usr/share/zaptel
-+MANDIR = /usr/share/man/man8
-+HOTPLUG_USB_DIR = /etc/hotplug/usb
-+
-+DATA_FILES = $(wildcard ../init_data_*.cmd *.hex)
-+
-+CFLAGS = -g -Wall $(EXTRA_CFLAGS)
-+
-+TARGETS = libhexfile.a fpga_load test_parse
-+
-+all: $(TARGETS)
-+
-+install: all
-+ $(INSTALL) -d $(DESTDIR)$(BINDIR)
-+ $(INSTALL) genzaptelconf fpga_load $(DESTDIR)$(BINDIR)/
-+ $(INSTALL) -d $(DESTDIR)$(DATADIR)
-+ $(INSTALL_DATA) $(DATA_FILES) $(DESTDIR)$(DATADIR)/
-+ $(INSTALL) ../initialize_registers $(DESTDIR)$(DATADIR)/
-+ $(INSTALL) -d $(DESTDIR)$(MANDIR)
-+ $(INSTALL_DATA) fpga_load.8 genzaptelconf.8 $(DESTDIR)$(MANDIR)/
-+ $(INSTALL) -d $(DESTDIR)$(HOTPLUG_USB_DIR)
-+ $(INSTALL_DATA) xpp_fxloader.usermap $(DESTDIR)$(HOTPLUG_USB_DIR)/
-+ $(INSTALL) xpp_fxloader $(DESTDIR)$(HOTPLUG_USB_DIR)/
-+
-+libhexfile.a: hexfile.o
-+ $(AR) cru $@ $^
-+ $(RANLIB) $@
-+
-+fpga_load: fpga_load.o libhexfile.a
-+ $(CC) -L. -o $@ $@.o $(EXTRA_LIBS) -lhexfile -lusb
-+
-+hexfile.o: hexfile.c hexfile.h
-+ $(CC) $(CFLAGS) $(PEDANTIC) -c $*.c
-+
-+test_parse.o: test_parse.c hexfile.h
-+ $(CC) $(CFLAGS) $(PEDANTIC) -c $*.c
-+
-+test_parse: test_parse.o libhexfile.a
-+ $(CC) -L. -o $@ $@.o $(EXTRA_LIBS) -lhexfile -lusb
-+
-+clean:
-+ $(RM) *.o $(TARGETS)
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/utils/test_parse.c zaptel-xpp-LJNBCn_dist/xpp/utils/test_parse.c
---- zaptel-1.2.6/xpp/utils/test_parse.c 1970-01-01 02:00:00.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/utils/test_parse.c 2006-05-15 17:27:26.264723000 +0300
-@@ -0,0 +1,34 @@
-+#include <stdio.h>
-+#include <stdarg.h>
-+#include "hexfile.h"
-+
-+static void default_report_func(int level, const char *msg, ...)
-+{
-+ va_list ap;
-+
-+ va_start(ap, msg);
-+ vfprintf(stderr, msg, ap);
-+ va_end(ap);
-+}
-+
-+int main(int argc, char *argv[])
-+{
-+ struct hexdata *hd;
-+ int i;
-+
-+ if(argc < 2) {
-+ fprintf(stderr, "Usage: program hexfile...\n");
-+ return 1;
-+ }
-+ parse_hexfile_set_reporting(default_report_func);
-+ for(i = 1; i < argc; i++) {
-+ hd = parse_hexfile(argv[i], 2000);
-+ if(!hd) {
-+ fprintf(stderr, "Parsing failed\n");
-+ return 1;
-+ }
-+ dump_hexfile2(hd, stdout, 60 );
-+ free_hexdata(hd);
-+ }
-+ return 0;
-+}
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/utils/USB_1130.hex zaptel-xpp-LJNBCn_dist/xpp/utils/USB_1130.hex
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/utils/USB_8613.hex zaptel-xpp-LJNBCn_dist/xpp/utils/USB_8613.hex
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/utils/xpp_fxloader zaptel-xpp-LJNBCn_dist/xpp/utils/xpp_fxloader
---- zaptel-1.2.6/xpp/utils/xpp_fxloader 1970-01-01 02:00:00.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/utils/xpp_fxloader 2006-07-02 17:49:51.471281000 +0300
-@@ -0,0 +1,163 @@
-+#!/bin/sh
-+
-+# xpp_fxload: load XPP firmware
-+#
-+# This script can be run manually or from hotplug.
-+#
-+# Firmware files should be located in $FIRMWARE_DIR which defaults:
-+# 1. /usr/share/zaptel
-+# 2. Can be overidden by setting $FIRMWARE_DIR in the environment
-+# 3. Can be overidden by setting $FIRMWARE_DIR in /etc/default/zaptel
-+#
-+# Manual Run
-+# ##########
-+#
-+# path/to/xpp_fxloader xppdetect
-+#
-+# Make sure the firmware files are in $FIRMWARE_DIR
-+#
-+#
-+# Hotplg Run
-+# ##########
-+#
-+# 1. Copy this file and the file xpp_fxloader.usermap to /etc/hotplug/usb/
-+# 2. tail -f /var/log/messages...
-+#
-+#
-+# Written by Tzafrir Cohen <tzafrir.cohen at xorcom.com>
-+# Copyright (C) 2006, Xorcom
-+#
-+# All rights reserved.
-+#
-+# This program is free software; you can redistribute it and/or modify
-+# it under the terms of the GNU General Public License as published by
-+# the Free Software Foundation; either version 2 of the License, or
-+# (at your option) any later version.
-+#
-+# This program is distributed in the hope that it will be useful,
-+# but WITHOUT ANY WARRANTY; without even the implied warranty of
-+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+# GNU General Public License for more details.
-+#
-+# You should have received a copy of the GNU General Public License
-+# along with this program; if not, write to the Free Software
-+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+
-+set -e
-+
-+me=`basename $0`
-+DEFAULTS="/etc/default/zaptel"
-+
-+if [ -t 2 ]; then
-+ LOGGER="logger -i -t '$me' -s"
-+else
-+ LOGGER="logger -i -t '$me'"
-+fi
-+
-+if [ -r "$DEFAULTS" ]; then
-+ . "$DEFAULTS"
-+fi
-+
-+FIRMWARE_DIR="${FIRMWARE_DIR:-/usr/share/zaptel}"
-+
-+FIRM_FXS=$FIRMWARE_DIR/FPGA_FXS.hex
-+REENUM_SLEEP_TIME=3 # only used on manual runs
-+
-+FPGA_LOAD="/usr/sbin/fpga_load"
-+
-+find_dev() {
-+ v_id=$1
-+ p_id=$2
-+
-+ lsusb | tr -d : | awk "/ ID $v_id$p_id/{printf \"/proc/bus/usb/%s/%s \",\$2,\$4}"
-+}
-+
-+do_fxload() {
-+ ( fxload -t fx2 $* 2>&1 1>/dev/null || exit 1 ) | $LOGGER
-+}
-+
-+load_fw() {
-+ v_id=$1
-+ p_id=$2
-+ fw=$3
-+
-+ devices=`find_dev $v_id $p_id`
-+ for dev in $devices
-+ do
-+ $LOGGER "USB Firmware $FIRMWARE_DIR/$fw into $dev"
-+ do_fxload -D $dev -I $FIRMWARE_DIR/$fw || exit 1
-+ done
-+
-+ # Allow time for reenumeration: This only matters in the manual case.
-+ if [ "$devices" != '' ]; then sleep $REENUM_SLEEP_TIME; fi
-+}
-+
-+hexfile_version() {
-+ hexfile=$1
-+
-+ grep '$Id:' "$hexfile" | sed -e 's/^.*$Id: *[^ ]\+ *//' -e 's/ .*$//'
-+}
-+
-+load_fpga() {
-+ v_id=$1
-+ p_id=$2
-+ fw=$3
-+
-+ devices=`find_dev $v_id $p_id`
-+ for dev in $devices
-+ do
-+ card_ver=`$FPGA_LOAD -d -D $dev`
-+ firm_ver=`hexfile_version $FIRMWARE_DIR/$fw`
-+
-+ $LOGGER "FPGA Firmware $FIRMWARE_DIR/$fw into $dev"
-+ $FPGA_LOAD -D "$dev" -I "$FIRMWARE_DIR/$fw" 2>&1 >/dev/null | $LOGGER
-+ status=$PIPESTATUS
-+ if [ $status != 0 ]; then
-+ echo "fpga_load failed with status $status" | $LOGGER
-+ exit 77
-+ fi
-+ done
-+}
-+
-+#########################
-+##
-+## Manual run
-+##
-+
-+# to run manually, pass the parameter 'xppdetect'
-+if [ "$1" = 'xppdetect' ]; then
-+ echo "--------- FIRMWARE LOADING"
-+ load_fw 04b4 8613 USB_8613.hex
-+ load_fw e4e4 1130 USB_1130.hex
-+ load_fpga e4e4 1131 FPGA_FXS.hex
-+
-+ sleep 3 # Let it stabilize
-+ echo "--------- FIRMWARE IS LOADED"
-+ exit $?
-+fi
-+
-+#########################
-+##
-+## Hotplug run
-+##
-+
-+if [ "$ACTION" = "add" ] && [ -f "$DEVICE" ]
-+then
-+ $LOGGER "Trying to find what to do for product $PRODUCT, device $DEVICE"
-+ prod_id=`echo "$PRODUCT" | cut -d/ -f2`
-+ case "$PRODUCT" in
-+ 4b4/8613/*|e4e4/1130/*|e4e4/1140/*)
-+ FIRM_USB="$FIRMWARE_DIR/USB_$prod_id.hex"
-+ $LOGGER "Loading firmware '$FIRM_USB' into '$DEVICE'"
-+ do_fxload -D "$DEVICE" -I "$FIRM_USB"
-+ ;;
-+ e4e4/1131/*|e4e4/1141/*)
-+ if [ "$prod_id" = 1131 ]; then
-+ FIRM_FPGA="$FIRMWARE_DIR/FPGA_FXS.hex" # Legacy
-+ else
-+ FIRM_FPGA="$FIRMWARE_DIR/FPGA_$prod_id.hex"
-+ fi
-+ $FPGA_LOAD -D "$DEVICE" -I "$FIRM_FPGA" 2>&1 >/dev/null | $LOGGER
-+ ;;
-+ esac
-+fi
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/utils/xpp_fxloader.usermap zaptel-xpp-LJNBCn_dist/xpp/utils/xpp_fxloader.usermap
---- zaptel-1.2.6/xpp/utils/xpp_fxloader.usermap 1970-01-01 02:00:00.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/utils/xpp_fxloader.usermap 2006-05-01 18:45:04.050100000 +0300
-@@ -0,0 +1,4 @@
-+# module match_flags idVendor idProduct bcdDevice_lo bcdDevice_hi bDeviceClass bDeviceSubClass bDeviceProtocol bInterfaceClass bInterfaceSubClass bInterfaceProtocol driver_info
-+xpp_fxloader 0x0003 0x04b4 0x8613 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x0
-+xpp_fxloader 0x0003 0xe4e4 0x1130 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x0
-+xpp_fxloader 0x0003 0xe4e4 0x1131 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x0
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/utils/xpp_modprobe zaptel-xpp-LJNBCn_dist/xpp/utils/xpp_modprobe
---- zaptel-1.2.6/xpp/utils/xpp_modprobe 1970-01-01 02:00:00.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/utils/xpp_modprobe 2006-05-01 17:08:34.781705000 +0300
-@@ -0,0 +1,10 @@
-+# Some debugging options for the brave of heart:
-+#options zaptel debug=1
-+#options wcfxo debug=1
-+#options xpp print_dbg=1
-+#options xpp_usb print_dbg=1
-+#options xpd_fxs print_dbg=1
-+#options xpd_fxo print_dbg=1
-+
-+# For pre-loading of card modules (e.g: xpp_fxs)
-+#install xpp_usb /sbin/modprobe xpd_fxs && /sbin/modprobe --ignore-install xpp_usb
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/xbus-core.c zaptel-xpp-LJNBCn_dist/xpp/xbus-core.c
---- zaptel-1.2.6/xpp/xbus-core.c 1970-01-01 02:00:00.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/xbus-core.c 2006-07-03 12:11:26.109424000 +0300
-@@ -0,0 +1,874 @@
-+/*
-+ * Written by Oron Peled <oron at actcom.co.il>
-+ * Copyright (C) 2004-2006, Xorcom
-+ *
-+ * All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ */
-+#include <linux/version.h>
-+
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
-+# warning "This module is tested only with 2.6 kernels"
-+#endif
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/errno.h>
-+#include <linux/proc_fs.h>
-+#include <linux/device.h>
-+#include <linux/delay.h> /* for mdelay() to debug */
-+#include "xpd.h"
-+#include "xpp_zap.h"
-+#include "xbus-core.h"
-+#include "zap_debug.h"
-+
-+static const char rcsid[] = "$Id: xbus-core.c 1543 2006-07-03 09:11:26Z oron $";
-+
-+/* Defines */
-+#define POLL_TIMEOUT (MAX_XPDS) /* in jiffies */
-+#define PROC_XBUSES "xbuses"
-+#define PROC_XBUS_SUMMARY "summary"
-+#define PROC_XBUS_WAITFOR_XPDS "waitfor_xpds"
-+
-+/* Command line parameters */
-+extern int print_dbg;
-+extern int max_queue_len;
-+
-+/* Forward declarations */
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
-+#define DEVICE_ATTR_FUNC(name,dev,buf) \
-+ ssize_t name(struct device *dev, struct device_attribute *attr, char *buf)
-+#else
-+#define DEVICE_ATTR_FUNC(name,dev,buf) \
-+ ssize_t name(struct device *dev, char *buf)
-+#endif
-+
-+static DEVICE_ATTR_FUNC(connector_show, dev, buf);
-+static DEVICE_ATTR_FUNC(status_show, dev, buf);
-+
-+static int xbus_poll(void *data);
-+static void xbus_release(struct device *dev);
-+static int xbus_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data);
-+static int xbus_read_waitfor_xpds(char *page, char **start, off_t off, int count, int *eof, void *data);
-+
-+/* Data structures */
-+struct workqueue_struct *xpp_worker = NULL;
-+static spinlock_t xbuses_lock = SPIN_LOCK_UNLOCKED;
-+static xbus_t *xbuses_array[MAX_BUSES] = {};
-+static int bus_count = 0;
-+static struct proc_dir_entry *proc_xbuses = NULL;
-+
-+static DEVICE_ATTR(connector, S_IRUGO, connector_show, NULL);
-+static DEVICE_ATTR(status, S_IRUGO, status_show, NULL);
-+
-+/*------------------------- Packet Handling ------------------------*/
-+static kmem_cache_t *packet_cache = NULL;
-+static atomic_t xpacket_count = ATOMIC_INIT(0);
-+
-+/**
-+ * Allocates a new XPP packet.
-+ * @xbus The XPP bus in which the packet will flow (for counters
-+ * maintenance)
-+ * @flags Flags for kernel memory allocation.
-+ * @returns A pointer to the new packet, or NULL in case of failure.
-+ *
-+ *
-+ * Packet allocation/deallocation:
-+ * Sent packets:
-+ * - Allocated by protocol commands
-+ * - Deallocated by xmus_xmitter
-+ * Receive packets:
-+ * - Allocated/deallocated by xbus_xmiter
-+ */
-+xpacket_t *xbus_packet_new(xbus_t *xbus, int flags)
-+{
-+ xpacket_t *pack;
-+
-+ /* To avoid races we increament counter in advance and decrement it later
-+ * in case of failure */
-+ atomic_inc(&xbus->packet_counter);
-+ //DBG("Incremented packet_counter of bus %s (new packet) to %d\n",
-+ // xbus->busname, atomic_read(&xbus->packet_counter));
-+ pack = kmem_cache_alloc(packet_cache, flags);
-+ if (pack) {
-+ memset(pack, 0, sizeof(xpacket_t));
-+ atomic_inc(&xpacket_count);
-+ } else {
-+ atomic_dec(&xbus->packet_counter);
-+ //DBG("Decremented packet_counter of bus %s (failed new packet) to %d\n",
-+ // xbus->busname, atomic_read(&xbus->packet_counter));
-+ }
-+ return pack;
-+}
-+
-+void xbus_packet_free(xbus_t *xbus, xpacket_t *p)
-+{
-+ kmem_cache_free(packet_cache, p);
-+ atomic_dec(&xpacket_count);
-+ atomic_dec(&xbus->packet_counter);
-+ //DBG("Decremented packet_counter of bus %s (freed packet) to %d\n",
-+ // xbus->busname, atomic_read(&xbus->packet_counter));
-+}
-+
-+/*------------------------- Packet Queues --------------------------*/
-+void init_xbus_packet_queue(packet_queue_t *q, const char name[])
-+{
-+ INIT_LIST_HEAD(&q->head);
-+ spin_lock_init(&q->lock);
-+ q->count = 0;
-+ q->worst_count = 0;
-+ q->overflows = 0;
-+ snprintf(q->qname, XPD_NAMELEN, "%s", name);
-+}
-+
-+#if 0
-+/*
-+ * Assume the queue is locked
-+ */
-+void __dump_packet_queue(const char *msg, packet_queue_t *q)
-+{
-+ xpacket_t *tmp;
-+
-+ list_for_each_entry(tmp, &q->head, list) {
-+ dump_packet(msg, tmp);
-+ }
-+}
-+#endif
-+
-+void drain_xbus_packet_queue(xbus_t *xbus, packet_queue_t *q)
-+{
-+ unsigned long flags;
-+ xpacket_t *pack;
-+ xpacket_t *next;
-+
-+ spin_lock_irqsave(&q->lock, flags);
-+ DBG("queue=%s count=%d\n", q->qname, q->count);
-+ DBG(" total packets count=%d\n", atomic_read(&xpacket_count));
-+ list_for_each_entry_safe(pack, next, &q->head, list) {
-+ list_del(&pack->list);
-+ q->count--;
-+ xbus->ops->packet_free(xbus, pack);
-+ }
-+ if(q->count != 0)
-+ ERR("drain_xbus_packet_queue: queue %s still has %d packets\n",
-+ q->qname, q->count);
-+ spin_unlock_irqrestore(&q->lock, flags);
-+}
-+
-+void xbus_enqueue_packet(xbus_t *xbus, packet_queue_t *q, xpacket_t *pack)
-+{
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&q->lock, flags);
-+
-+ if(q->count >= max_queue_len) {
-+ static unsigned long last_notice = 0; // rate limit
-+
-+ if((jiffies - last_notice) < HZ) {
-+ NOTICE("xbus_enqueue_packet: dropping packet (queue len = %d, max=%d)\n",
-+ q->count, max_queue_len);
-+ last_notice = jiffies;
-+ }
-+ q->overflows++;
-+ xbus->ops->packet_free(xbus, pack);
-+ goto out;
-+ }
-+ list_add_tail(&pack->list, &q->head);
-+ q->count++;
-+
-+ if(q->count > q->worst_count)
-+ q->worst_count = q->count;
-+
-+ if(q->count < max_queue_len/100 && q->worst_count > q->count) // Decay worst_count
-+ q->worst_count--;
-+
-+ // dump_packet("ENQUEUED", pack, print_dbg);
-+out:
-+ spin_unlock_irqrestore(&q->lock, flags);
-+}
-+
-+xpacket_t *xbus_dequeue_packet(packet_queue_t *q)
-+{
-+ unsigned long flags;
-+ struct list_head *p;
-+ xpacket_t *pack = NULL;
-+
-+ spin_lock_irqsave(&q->lock, flags);
-+
-+ if(list_empty(&q->head)) {
-+ // DBG("LIST EMPTY (count=%d)\n", q->count);
-+ goto out;
-+ }
-+ p = q->head.next;
-+ list_del(p);
-+ q->count--;
-+ pack = list_entry(p, xpacket_t, list);
-+ // dump_packet("DEQUEUED", pack, print_dbg);
-+out:
-+ spin_unlock_irqrestore(&q->lock, flags);
-+ return pack;
-+}
-+
-+
-+/*------------------------- Bus Management -------------------------*/
-+xbus_t *xbus_of(int xbus_num)
-+{
-+ if(xbus_num < 0 || xbus_num >= MAX_BUSES)
-+ return NULL;
-+ return xbuses_array[xbus_num];
-+}
-+
-+xpd_t *xpd_of(xbus_t *xbus, int xpd_num)
-+{
-+ if(!VALID_XPD_NUM(xpd_num))
-+ return NULL;
-+ return xbus->xpds[xpd_num];
-+}
-+
-+int xbus_register_xpd(xbus_t *xbus, xpd_t *xpd)
-+{
-+ unsigned int xpd_num = xpd->id;
-+ unsigned long flags;
-+ int ret = 0;
-+
-+ spin_lock_irqsave(&xbus->lock, flags);
-+ if(!VALID_XPD_NUM(xpd_num)) {
-+ ERR("%s: Bad xpd_num = %d\n", xbus->busname, xpd_num);
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+ if(xbus->xpds[xpd_num] != NULL) {
-+ xpd_t *other = xbus->xpds[xpd_num];
-+
-+ ERR("%s: xpd_num=%d is occupied by %p (%s)\n",
-+ xbus->busname, xpd_num, other, other->xpdname);
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+ xbus->xpds[xpd_num] = xpd;
-+ xbus->num_xpds++;
-+out:
-+ spin_unlock_irqrestore(&xbus->lock, flags);
-+ return ret;
-+}
-+
-+int xbus_unregister_xpd(xbus_t *xbus, xpd_t *xpd)
-+{
-+ unsigned int xpd_num = xpd->id;
-+ unsigned long flags;
-+ int ret = 0;
-+
-+ spin_lock_irqsave(&xbus->lock, flags);
-+ if(!VALID_XPD_NUM(xpd_num)) {
-+ ERR("%s: Bad xpd_num = %d\n", xbus->busname, xpd_num);
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+ if(xbus->xpds[xpd_num] != xpd) {
-+ xpd_t *other = xbus->xpds[xpd_num];
-+
-+ ERR("%s: xpd_num=%d is occupied by %p (%s)\n",
-+ xbus->busname, xpd_num, other, other->xpdname);
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+ xbus->xpds[xpd_num] = NULL;
-+ xbus->num_xpds--;
-+ xpd->xbus = NULL;
-+out:
-+ spin_unlock_irqrestore(&xbus->lock, flags);
-+ return ret;
-+}
-+
-+/*
-+ * This must be called from synchronous (non-interrupt) context
-+ * it returns only when all XPD's on the bus are detected and
-+ * initialized.
-+ */
-+static int xbus_poll(void *data)
-+{
-+ int id;
-+ int ret;
-+ unsigned long flags;
-+ struct list_head *card;
-+ struct list_head *next_card;
-+ struct list_head removal_list;
-+ struct list_head additions_list;
-+ int count_removed;
-+ int count_added;
-+ int xpd_num;
-+ xbus_t *xbus = data;
-+
-+ spin_lock_irqsave(&xbus->lock, flags);
-+ DBG("%s\n", xbus->busname);
-+
-+ /*
-+ * Send out the polls
-+ */
-+ atomic_set(&xbus->count_poll_answers, 0);
-+ for(id = 0; id < MAX_XPDS; id++) {
-+ if(!xbus->hardware_exists)
-+ break;
-+ // DBG(" Polling slot %d %s\n", id, xbus->busname);
-+ spin_unlock_irqrestore(&xbus->lock, flags);
-+ ret = CALL_PROTO(GLOBAL, DESC_REQ, xbus, NULL, id);
-+ spin_lock_irqsave(&xbus->lock, flags);
-+ if(ret < 0) {
-+ NOTICE("xpp: %s: Failed sending DESC_REQ to XPD #%d\n", __FUNCTION__, id);
-+ break;
-+ }
-+ mdelay(1); /* FIXME: debugging for Dima */
-+ }
-+ spin_unlock_irqrestore(&xbus->lock, flags);
-+ DBG("%s: Polled %d XPD's. Waiting for replies\n", xbus->busname, MAX_XPDS);
-+ ret = wait_event_timeout(xbus->wait_for_polls, atomic_read(&xbus->count_poll_answers) >= MAX_XPDS, POLL_TIMEOUT);
-+ if(ret < 0) {
-+ ERR("%s: Poll timeout %d\n", xbus->busname, ret);
-+ return ret;
-+ }
-+ DBG("%s: Poll finished. Start processing.\n", xbus->busname);
-+ spin_lock_irqsave(&xbus->lock, flags);
-+ INIT_LIST_HEAD(&removal_list);
-+ INIT_LIST_HEAD(&additions_list);
-+ count_removed = 0;
-+ count_added = 0;
-+ list_for_each_safe(card, next_card, &xbus->poll_results) {
-+ struct card_desc_struct *card_desc = list_entry(card, struct card_desc_struct, card_list);
-+ byte type = card_desc->type;
-+ xpd_t *xpd;
-+
-+ BUG_ON(card_desc->magic != CARD_DESC_MAGIC);
-+ xpd_num = xpd_addr2num(&card_desc->xpd_addr);
-+ xpd = xpd_of(xbus, xpd_num);
-+
-+ if(xpd && type == XPD_TYPE_NOMODULE) { /* card removal */
-+ list_move_tail(card, &removal_list);
-+ count_removed++;
-+ } else if(!xpd && type != XPD_TYPE_NOMODULE) { /* card detection */
-+ list_move_tail(card, &additions_list);
-+ count_added++;
-+ } else { /* same same */
-+ list_del(card);
-+ kfree(card_desc);
-+ }
-+ }
-+ spin_unlock_irqrestore(&xbus->lock, flags);
-+ INFO("%s: Poll results: removals=%d additions=%d\n", xbus->busname, count_removed, count_added);
-+ list_for_each_safe(card, next_card, &removal_list) {
-+ struct card_desc_struct *card_desc = list_entry(card, struct card_desc_struct, card_list);
-+ xpd_t *xpd;
-+
-+ list_del(card);
-+ xpd_num = xpd_addr2num(&card_desc->xpd_addr);
-+ xpd = xpd_of(xbus, xpd_num);
-+ if(xpd)
-+ xpd_disconnect(xpd);
-+ kfree(card);
-+ }
-+ list_for_each_safe(card, next_card, &additions_list) {
-+ struct card_desc_struct *card_desc = list_entry(card, struct card_desc_struct, card_list);
-+
-+ list_del(card);
-+ card_detected(card_desc);
-+ }
-+ complete_all(&xbus->xpds_initialized);
-+ return 0;
-+}
-+
-+
-+void xbus_activate(xbus_t *xbus)
-+{
-+ xbus_ops_t *ops;
-+
-+ BUG_ON(!xbus);
-+ ops = xbus->ops;
-+ BUG_ON(!ops);
-+ BUG_ON(!xbus->priv);
-+ /* Sanity checks */
-+ BUG_ON(!ops->packet_send);
-+ BUG_ON(!ops->packet_new || !ops->packet_free);
-+ xbus->hardware_exists = 1;
-+ DBG("Activating: %s\n", xbus->busname);
-+ /* Poll it */
-+ INIT_WORK(&xbus->xpds_init_work, (void (*)(void *))xbus_poll, (void *)xbus);
-+ if(!queue_work(xpp_worker, &xbus->xpds_init_work)) {
-+ ERR("Failed to queue xpd initialization work\n");
-+ /* FIXME: need to return error */
-+ }
-+}
-+
-+void xbus_disconnect(xbus_t *xbus)
-+{
-+ int i;
-+
-+ BUG_ON(!xbus);
-+ DBG("%s\n", xbus->busname);
-+ xbus->hardware_exists = 0;
-+ for(i = 0; i < MAX_XPDS; i++) {
-+ xpd_t *xpd = xpd_of(xbus, i);
-+ if(!xpd)
-+ continue;
-+ if(xpd->id != i) {
-+ ERR("%s: BUG: xpd->id=%d != i=%d\n", __FUNCTION__, xpd->id, i);
-+ continue;
-+ }
-+ xpd_disconnect(xpd);
-+ }
-+ DBG("%s (deactivated)\n", xbus->busname);
-+ if(xbus->open_counter == 0) {
-+ xbus_remove(xbus);
-+ }
-+}
-+
-+static xbus_t *xbus_alloc(void)
-+{
-+ unsigned long flags;
-+ xbus_t *xbus;
-+ int i;
-+
-+ xbus = kmalloc(sizeof(xbus_t), GFP_KERNEL);
-+ if(!xbus) {
-+ ERR("%s: out of memory\n", __FUNCTION__);
-+ return NULL;
-+ }
-+ memset(xbus, 0, sizeof(xbus_t));
-+ spin_lock_irqsave(&xbuses_lock, flags);
-+ for(i = 0; i < MAX_BUSES; i++)
-+ if(xbuses_array[i] == NULL)
-+ break;
-+ if(i >= MAX_BUSES) {
-+ ERR("%s: No free slot for new bus. i=%d\n", __FUNCTION__, i);
-+ kfree(xbus);
-+ return NULL;
-+ }
-+ /* Found empty slot */
-+ xbuses_array[i] = xbus;
-+ xbus->num = i;
-+ bus_count++;
-+ spin_unlock_irqrestore(&xbuses_lock, flags);
-+ return xbus;
-+}
-+
-+
-+static void xbus_free(xbus_t *xbus)
-+{
-+ unsigned long flags;
-+
-+ if(!xbus)
-+ return;
-+ spin_lock_irqsave(&xbuses_lock, flags);
-+ BUG_ON(xbus != xbus_of(xbus->num));
-+ xbuses_array[xbus->num] = NULL;
-+ bus_count--;
-+ spin_unlock_irqrestore(&xbuses_lock, flags);
-+#ifdef CONFIG_PROC_FS
-+ if(xbus->proc_xbus_dir) {
-+ if(xbus->proc_xbus_summary) {
-+ DBG("Removing proc '%s' for %s\n", PROC_XBUS_SUMMARY, xbus->busname);
-+ remove_proc_entry(PROC_XBUS_SUMMARY, xbus->proc_xbus_dir);
-+ xbus->proc_xbus_summary = NULL;
-+ }
-+ if(xbus->proc_xbus_waitfor_xpds) {
-+ DBG("Removing proc '%s' for %s\n", PROC_XBUS_WAITFOR_XPDS, xbus->busname);
-+ remove_proc_entry(PROC_XBUS_WAITFOR_XPDS, xbus->proc_xbus_dir);
-+ xbus->proc_xbus_waitfor_xpds = NULL;
-+ }
-+ DBG("Removing proc directory %s\n", xbus->busname);
-+ remove_proc_entry(xbus->busname, xpp_proc_toplevel);
-+ xbus->proc_xbus_dir = NULL;
-+ }
-+#endif
-+ device_remove_file(&xbus->the_bus, &dev_attr_status);
-+ device_remove_file(&xbus->the_bus, &dev_attr_connector);
-+ device_unregister(&xbus->the_bus);
-+ kfree(xbus);
-+}
-+
-+static void xbus_release(struct device *dev)
-+{
-+ xbus_t *xbus;
-+
-+ BUG_ON(!dev);
-+ xbus = dev->driver_data;
-+ DBG("%s\n", xbus->busname);
-+}
-+
-+
-+xbus_t *xbus_new(xbus_ops_t *ops)
-+{
-+ int err;
-+ xbus_t *xbus = NULL;
-+
-+ BUG_ON(!ops);
-+ xbus = xbus_alloc();
-+ if(!xbus)
-+ return NULL;
-+
-+ /* Init data structures */
-+ spin_lock_init(&xbus->lock);
-+ snprintf(xbus->busname, XBUS_NAMELEN, "XBUS-%d", xbus->num);
-+ INFO("New xbus: %s\n", xbus->busname);
-+ init_waitqueue_head(&xbus->packet_cache_empty);
-+ atomic_set(&xbus->packet_counter, 0);
-+ atomic_set(&xbus->count_poll_answers, 0);
-+ init_waitqueue_head(&xbus->wait_for_polls);
-+ init_rwsem(&xbus->in_use);
-+ INIT_LIST_HEAD(&xbus->poll_results);
-+ init_completion(&xbus->xpds_initialized);
-+ xbus->num_xpds = 0;
-+ xbus_reset_counters(xbus);
-+
-+ /* Device-Model */
-+ snprintf(xbus->the_bus.bus_id, BUS_ID_SIZE, "xbus-%d", xbus->num);
-+ xbus->the_bus.driver_data = xbus;
-+ xbus->the_bus.release = xbus_release;
-+
-+ err = device_register(&xbus->the_bus);
-+ if(err) {
-+ ERR("%s: device_register failed: %d\n", __FUNCTION__, err);
-+ goto nobus;
-+ }
-+ err = device_create_file(&xbus->the_bus, &dev_attr_connector);
-+ if(err) {
-+ ERR("%s: device_create_file failed: %d\n", __FUNCTION__, err);
-+ goto nobus;
-+ }
-+ err = device_create_file(&xbus->the_bus, &dev_attr_status);
-+ if(err) {
-+ ERR("%s: device_create_file failed: %d\n", __FUNCTION__, err);
-+ goto nobus;
-+ }
-+
-+#ifdef CONFIG_PROC_FS
-+ DBG("Creating xbus proc directory %s.\n",xbus->busname);
-+ xbus->proc_xbus_dir = proc_mkdir(xbus->busname, xpp_proc_toplevel);
-+ if(!xbus->proc_xbus_dir) {
-+ ERR("Failed to create proc directory for xbus %s\n", xbus->busname);
-+ err = -EIO;
-+ goto nobus;
-+ }
-+ xbus->proc_xbus_summary = create_proc_read_entry(PROC_XBUS_SUMMARY, 0444, xbus->proc_xbus_dir,
-+ xbus_read_proc, xbus);
-+ if (!xbus->proc_xbus_summary) {
-+ ERR("Failed to create '%s' proc file for xbus %s\n", PROC_XBUS_SUMMARY, xbus->busname);
-+ err = -EIO;
-+ goto nobus;
-+ }
-+ xbus->proc_xbus_summary->owner = THIS_MODULE;
-+ xbus->proc_xbus_waitfor_xpds = create_proc_read_entry(PROC_XBUS_WAITFOR_XPDS, 0444, xbus->proc_xbus_dir,
-+ xbus_read_waitfor_xpds, xbus);
-+ if (!xbus->proc_xbus_waitfor_xpds) {
-+ ERR("Failed to create '%s' proc file for xbus %s\n", PROC_XBUS_WAITFOR_XPDS, xbus->busname);
-+ err = -EIO;
-+ goto nobus;
-+ }
-+ xbus->proc_xbus_waitfor_xpds->owner = THIS_MODULE;
-+#endif
-+ /* Sanity checks */
-+ if(!ops->packet_send) {
-+ ERR("%s: missing mandatory handler: packet_send\n", __FUNCTION__);
-+ goto nobus;
-+ }
-+ if(!ops->packet_new || !ops->packet_free) {
-+ NOTICE("%s: Using default packet allocators\n", __FUNCTION__);
-+ ops->packet_new = xbus_packet_new;
-+ ops->packet_free = xbus_packet_free;
-+ }
-+
-+ xbus->ops = ops;
-+ return xbus;
-+nobus:
-+ xbus_free(xbus);
-+ return NULL;
-+}
-+
-+void xbus_remove(xbus_t *xbus)
-+{
-+ int i;
-+ int ret;
-+
-+ BUG_ON(!xbus);
-+ DBG("%s\n", xbus->busname);
-+
-+ /* Block until no one use */
-+ down_write(&xbus->in_use);
-+
-+ INFO("Removing xbus(%d) %s\n", xbus->num, xbus->busname);
-+ for(i = 0; i < MAX_XPDS; i++) {
-+ xpd_t *xpd = xpd_of(xbus, i);
-+
-+ if(xpd) {
-+ if(xpd->id != i) {
-+ ERR("%s: BUG: xpd->id=%d != i=%d\n", __FUNCTION__, xpd->id, i);
-+ continue;
-+ }
-+ DBG(" Removing xpd id=%d\n", xpd->id);
-+ xpd_remove(xpd);
-+ }
-+ xbus->xpds[i] = NULL;
-+ }
-+ ret = wait_event_interruptible(xbus->packet_cache_empty,
-+ atomic_read(&xbus->packet_counter) == 0);
-+ if(ret) {
-+ ERR("waiting for packet_cache_empty interrupted!!!\n");
-+ }
-+ xbus_free(xbus);
-+}
-+
-+/*------------------------- Proc handling --------------------------*/
-+
-+void xbus_reset_counters(xbus_t *xbus)
-+{
-+ int i;
-+
-+ DBG("Reseting counters of %s\n", xbus->busname);
-+ for(i = 0; i < XBUS_COUNTER_MAX; i++) {
-+ xbus->counters[i] = 0;
-+ }
-+}
-+
-+#if CONFIG_PROC_FS
-+static int xbus_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
-+{
-+ int len = 0;
-+ unsigned long flags;
-+ xbus_t *xbus = data;
-+ int i;
-+
-+ if(!xbus)
-+ goto out;
-+ spin_lock_irqsave(&xbus->lock, flags);
-+
-+ len += sprintf(page + len, "%s: CONNECTOR=%s STATUS=%s bus_type=%d\n",
-+ xbus->busname,
-+ xbus->busdesc,
-+ (xbus->hardware_exists) ? "connected" : "missing",
-+ xbus->bus_type
-+ );
-+ len += sprintf(page + len, "POLLS: %d/%d\n", atomic_read(&xbus->count_poll_answers), MAX_XPDS);
-+ len += sprintf(page + len, "XPDS_READY: %s\n", (xbus->xpds_initialized.done) ? "YES" : "NO");
-+ len += sprintf(page + len, "\nmax_packet_size=%d open_counter=%d packet_count=%d\n",
-+ xbus->max_packet_size,
-+ xbus->open_counter,
-+ atomic_read(&xbus->packet_counter)
-+ );
-+ len += sprintf(page + len, "COUNTERS:\n");
-+ for(i = 0; i < XBUS_COUNTER_MAX; i++) {
-+ len += sprintf(page + len, "\t%-15s = %d\n",
-+ xbus_counters[i].name, xbus->counters[i]);
-+ }
-+ len += sprintf(page + len, "<-- len=%d\n", len);
-+ spin_unlock_irqrestore(&xbus->lock, flags);
-+out:
-+ if (len <= off+count)
-+ *eof = 1;
-+ *start = page + off;
-+ len -= off;
-+ if (len > count)
-+ len = count;
-+ if (len < 0)
-+ len = 0;
-+ return len;
-+
-+}
-+
-+static int xbus_read_waitfor_xpds(char *page, char **start, off_t off, int count, int *eof, void *data)
-+{
-+ int len = 0;
-+ unsigned long flags;
-+ xbus_t *xbus = data;
-+ int i;
-+
-+ if(!xbus)
-+ goto out;
-+ i = wait_for_completion_interruptible_timeout(&xbus->xpds_initialized, 40*HZ);
-+ if(i < 0) {
-+ NOTICE("PID=%d waiting for XPDS initialization failed: %d\n", current->pid, i);
-+ return i;
-+ }
-+ spin_lock_irqsave(&xbus->lock, flags);
-+ len += sprintf(page + len, "XPDS_READY: %s\n", (xbus->xpds_initialized.done) ? "YES" : "NO");
-+ spin_unlock_irqrestore(&xbus->lock, flags);
-+out:
-+ if (len <= off+count)
-+ *eof = 1;
-+ *start = page + off;
-+ len -= off;
-+ if (len > count)
-+ len = count;
-+ if (len < 0)
-+ len = 0;
-+ return len;
-+
-+}
-+
-+static int read_proc_xbuses(char *page, char **start, off_t off, int count, int *eof, void *data)
-+{
-+ int len = 0;
-+ unsigned long flags;
-+ int i;
-+
-+ spin_lock_irqsave(&xbuses_lock, flags);
-+ for(i = 0; i < MAX_BUSES; i++) {
-+ xbus_t *xbus = xbus_of(i);
-+
-+ if(xbus) {
-+ len += sprintf(page + len, "%s: CONNECTOR=%s STATUS=%s bus_type=%d\n",
-+ xbus->busname,
-+ xbus->busdesc,
-+ (xbus->hardware_exists) ? "connected" : "missing",
-+ xbus->bus_type
-+ );
-+ }
-+ }
-+#if 0
-+ len += sprintf(page + len, "<-- len=%d\n", len);
-+#endif
-+ spin_unlock_irqrestore(&xbuses_lock, flags);
-+ if (len <= off+count)
-+ *eof = 1;
-+ *start = page + off;
-+ len -= off;
-+ if (len > count)
-+ len = count;
-+ if (len < 0)
-+ len = 0;
-+ return len;
-+
-+}
-+#endif
-+
-+/*------------------------- Initialization -------------------------*/
-+
-+static DEVICE_ATTR_FUNC(connector_show, dev, buf)
-+{
-+ xbus_t *xbus;
-+ int ret;
-+
-+ xbus = dev->driver_data;
-+ ret = snprintf(buf, PAGE_SIZE, "%s\n", xbus->busdesc);
-+ return ret;
-+}
-+
-+static DEVICE_ATTR_FUNC(status_show, dev, buf)
-+{
-+ xbus_t *xbus;
-+ int ret;
-+
-+ xbus = dev->driver_data;
-+ ret = snprintf(buf, PAGE_SIZE, "%s\n", (xbus->hardware_exists)?"connected":"missing");
-+ return ret;
-+}
-+
-+static int xbus_match(struct device *dev, struct device_driver *driver)
-+{
-+ DBG("dev->bus_id = %s, driver->name = %s\n", dev->bus_id, driver->name);
-+ return strncmp(dev->bus_id, driver->name, strlen(driver->name)) == 0;
-+}
-+
-+#if 0
-+/* Hotplug replaced with uevent in 2.6.16 */
-+static int xbus_hotplug(struct device *device, char **envp, int envnum, char *buff, int bufsize)
-+{
-+ envp[0] = buff;
-+ if(snprintf(buff, bufsize, "XBUS_VERSION=%s", revision) >= bufsize)
-+ return -ENOMEM;
-+ envp[1] = NULL;
-+ return 0;
-+}
-+#endif
-+
-+struct bus_type xbus_bus_type = {
-+ .name = "xbus",
-+ .match = xbus_match,
-+/* FIXME: Hotplug replaced with uevent in 2.6.16 */
-+#if 0
-+ .hotplug = xbus_hotplug,
-+#endif
-+};
-+
-+static void xbus_core_cleanup(void)
-+{
-+ if (xpp_worker) {
-+ flush_workqueue(xpp_worker);
-+ destroy_workqueue(xpp_worker);
-+ xpp_worker = NULL;
-+ }
-+#ifdef CONFIG_PROC_FS
-+ if(proc_xbuses)
-+ remove_proc_entry(PROC_XBUSES, xpp_proc_toplevel);
-+#endif
-+ if(packet_cache)
-+ kmem_cache_destroy(packet_cache);
-+}
-+
-+int __init xbus_core_init(void)
-+{
-+ int ret;
-+
-+ packet_cache = kmem_cache_create("xpp_packets",
-+ sizeof(xpacket_t),
-+ 0, 0,
-+ NULL, NULL);
-+ if(!packet_cache) {
-+ return -ENOMEM;
-+ }
-+ xpp_worker = create_singlethread_workqueue("xppworker");
-+ if(!xpp_worker) {
-+ ERR("Failed to create card detector workqueue.\n");
-+ xbus_core_cleanup();
-+ return -ENOMEM;
-+ }
-+#ifdef CONFIG_PROC_FS
-+ proc_xbuses = create_proc_read_entry(PROC_XBUSES, 0444, xpp_proc_toplevel, read_proc_xbuses, 0);
-+ if (!proc_xbuses) {
-+ ERR("Failed to create proc file %s\n", PROC_XBUSES);
-+ xbus_core_cleanup();
-+ return -EFAULT;
-+ }
-+ proc_xbuses->owner = THIS_MODULE;
-+#endif
-+ ret = bus_register(&xbus_bus_type);
-+ if(ret) {
-+ ERR("%s: bus_register failed. Error number %d", __FUNCTION__, ret);
-+ xbus_core_cleanup();
-+ return ret;
-+ }
-+ return 0;
-+}
-+
-+
-+void __exit xbus_core_shutdown(void)
-+{
-+ int i;
-+
-+ for(i = 0; i < MAX_BUSES; i++) {
-+ xbus_t *xbus = xbus_of(i);
-+ if(xbus)
-+ xbus_remove(xbus);
-+ }
-+ BUG_ON(bus_count);
-+ bus_unregister(&xbus_bus_type);
-+ xbus_core_cleanup();
-+}
-+
-+EXPORT_SYMBOL(xpd_of);
-+EXPORT_SYMBOL(xbus_new);
-+EXPORT_SYMBOL(xbus_remove);
-+EXPORT_SYMBOL(xbus_activate);
-+EXPORT_SYMBOL(xbus_disconnect);
-+EXPORT_SYMBOL(xbus_reset_counters);
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/xbus-core.h zaptel-xpp-LJNBCn_dist/xpp/xbus-core.h
---- zaptel-1.2.6/xpp/xbus-core.h 1970-01-01 02:00:00.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/xbus-core.h 2006-07-02 19:47:41.666262000 +0300
-@@ -0,0 +1,56 @@
-+/*
-+ * Written by Oron Peled <oron at actcom.co.il>
-+ * Copyright (C) 2004-2006, Xorcom
-+ *
-+ * All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ */
-+#ifndef XBUS_CORE_H
-+#define XBUS_CORE_H
-+
-+#include "xpd.h"
-+
-+#define MAX_BUSES 16
-+
-+int xbus_core_init(void); /* Initializer */
-+void xbus_core_shutdown(void); /* Terminator */
-+
-+/* Packet handling */
-+xpacket_t *xbus_packet_new(xbus_t *xbus, int flags);
-+void xbus_packet_free(xbus_t *xbus, xpacket_t *p);
-+
-+/* packet queues */
-+void init_xbus_packet_queue(packet_queue_t *q, const char name[]);
-+void drain_xbus_packet_queue(xbus_t *xbus, packet_queue_t *q);
-+void xbus_enqueue_packet(xbus_t *xbus, packet_queue_t *q, xpacket_t *pack);
-+xpacket_t *xbus_dequeue_packet(packet_queue_t *q);
-+
-+/* XBUS handling */
-+xbus_t *xbus_of(int xbus_num);
-+xpd_t *xpd_of(xbus_t *xbus, int xpd_num);
-+xbus_t *xbus_new(xbus_ops_t *ops);
-+void xbus_remove(xbus_t *xbus);
-+void xbus_activate(xbus_t *xbus);
-+void xbus_disconnect(xbus_t *xbus);
-+
-+void xbus_reset_counters(xbus_t *xbus);
-+
-+int xbus_register_xpd(xbus_t *xbus, xpd_t *xpd);
-+int xbus_unregister_xpd(xbus_t *xbus, xpd_t *xpd);
-+
-+#endif /* XBUS_CORE_H */
-+
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/xdefs.h zaptel-xpp-LJNBCn_dist/xpp/xdefs.h
---- zaptel-1.2.6/xpp/xdefs.h 2006-02-15 04:24:18.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/xdefs.h 2006-07-03 12:11:26.109424000 +0300
-@@ -2,7 +2,7 @@
- #define XDEFS_H
- /*
- * Written by Oron Peled <oron at actcom.co.il>
-- * Copyright (C) 2004-2005, Xorcom
-+ * Copyright (C) 2004-2006, Xorcom
- *
- * All rights reserved.
- *
-@@ -26,15 +26,10 @@
-
- #include <linux/kernel.h>
-
--#define DBG(fmt, ...) \
-- ((print_dbg) && printk(KERN_DEBUG "DBG-%s: %s: " fmt, \
-- THIS_MODULE->name, __FUNCTION__, ## __VA_ARGS__))
--#define INFO(fmt, ...) printk(KERN_INFO "INFO-%s: " fmt, THIS_MODULE->name, ## __VA_ARGS__)
--#define NOTICE(fmt, ...) printk(KERN_NOTICE "NOTICE-%s: " fmt, THIS_MODULE->name, ## __VA_ARGS__)
--#define ERR(fmt, ...) printk(KERN_ERR "ERR-%s: " fmt, THIS_MODULE->name, ## __VA_ARGS__)
--
- #else
-
-+/* This is to enable user-space programs to include this. */
-+
- #include <stdint.h>
- typedef uint32_t __u32;
-
-@@ -50,33 +45,58 @@
-
- #endif
-
--typedef char *charp;
--typedef unsigned char byte;
--typedef int bool;
--typedef struct xbus xbus_t;
--typedef struct xpd xpd_t;
--typedef struct xpacket_raw xpacket_raw_t;
--typedef struct xpacket xpacket_t;
--typedef struct xops xops_t;
--typedef __u32 xpp_line_t; /* at most 31 lines for E1 */
-+#define PACKED __attribute__((packed))
-
-+#define ALL_LINES ((lineno_t)-1)
-
--#define BIT_SET(x,i) ((x) |= (1 << (i)))
--#define BIT_CLR(x,i) ((x) &= ~(1 << (i)))
--#define IS_SET(x,i) (((x) & (1 << (i))) != 0)
- #define BIT(i) (1 << (i))
-+#define BIT_SET(x,i) ((x) |= BIT(i))
-+#define BIT_CLR(x,i) ((x) &= ~BIT(i))
-+#define IS_SET(x,i) (((x) & BIT(i)) != 0)
-+#define BITMASK(i) (BIT(i) - 1)
-+
-+#define CHANNELS_PERXPD 30 /* Depends on xpp_line_t and protocol fields */
-
--#undef SUPPORT_USB1
-+#define MAX_SPANNAME 20 /* From zaptel.h */
-+#define MAX_SPANDESC 40 /* From zaptel.h */
-+#define MAX_CHANNAME 40 /* From zaptel.h */
-+
-+#define XPD_NAMELEN 10 /* must be <= from maximal workqueue name */
-+#define XPD_DESCLEN 20
-+#define XBUS_NAMELEN 20 /* must be <= from maximal workqueue name */
-+#define XBUS_DESCLEN 40
-+
-+#define UNIT_BITS 4 /* Bit for Astribank unit number */
-+#define SUBUNIT_BITS 4 /* Bit for Astribank subunit number */
-+
-+#define MAX_UNIT 4 /* 1 FXS + 3 FXS/FXO */
-+#define MAX_SUBUNIT 1 /* Firmware does not support subunits yet */
-
--#ifdef SUPPORT_USB1
- /*
-- * packet size <= 64 bytes:
-- * ZT_CHUNKSIZE * 7 channels + header size <= 64
-+ * Compile time sanity checks
- */
--#define CHANNELS_PERXPD 7 /* 7 * ZT_CHUNKSIZE + header <= 64 bytes */
--#else
--#define CHANNELS_PERXPD 30 /* Depends on xpp_line_t and protocol fields */
-+#if MAX_UNIT > BIT(UNIT_BITS)
-+#error "MAX_UNIT too large"
-+#endif
-+
-+#if MAX_SUBUNIT > BIT(SUBUNIT_BITS)
-+#error "MAX_SUBUNIT too large"
- #endif
-
-+#define MAX_XPDS (MAX_UNIT*MAX_SUBUNIT)
-+
-+#define VALID_XPD_NUM(x) ((x) < MAX_XPDS && (x) >= 0)
-+
-+typedef char *charp;
-+typedef unsigned char byte;
-+typedef int bool;
-+typedef struct xbus xbus_t;
-+typedef struct xpd xpd_t;
-+typedef struct xpacket_raw xpacket_raw_t;
-+typedef struct xpacket xpacket_t;
-+typedef struct xops xops_t;
-+typedef __u32 xpp_line_t; /* at most 31 lines for E1 */
-+typedef int lineno_t;
-+
-
- #endif /* XDEFS_H */
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/xpd.h zaptel-xpp-LJNBCn_dist/xpp/xpd.h
---- zaptel-1.2.6/xpp/xpd.h 2006-03-03 22:14:09.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/xpd.h 2006-07-03 12:11:26.109424000 +0300
-@@ -3,7 +3,7 @@
-
- /*
- * Written by Oron Peled <oron at actcom.co.il>
-- * Copyright (C) 2004-2005, Xorcom
-+ * Copyright (C) 2004-2006, Xorcom
- *
- * All rights reserved.
- *
-@@ -28,6 +28,7 @@
-
- #ifdef __KERNEL__
- #include <linux/kernel.h>
-+#include <linux/device.h>
- #include <asm/atomic.h>
- #include <asm/semaphore.h>
- #include <linux/moduleparam.h>
-@@ -61,20 +62,6 @@
- #endif // __KERNEL__
-
-
--#define MAX_SPANNAME 20
--#define MAX_SPANDESC 40
--#define MAX_CHANNAME 20
--
--#define XPD_NAMELEN 10 /* must be <= from maximal workqueue name */
--#define XPD_DESCLEN 20
--#define XBUS_NAMELEN 20 /* must be <= from maximal workqueue name */
--#define XBUS_DESCLEN 40
--
--/* Hardware does not check bank_num yet. So only 4 cards can be used */
--#define MAX_XPDS 4 // 1 FXS + 2 E1/T1 + 1 (Quad * E1/T1)
--
--#define VALID_XPD_NUM(x) ((x) < MAX_XPDS && (x) >= 0)
--
- typedef struct xbus_ops xbus_ops_t;
-
- typedef enum xbus_type {
-@@ -100,15 +87,17 @@
- void (*packet_free)(xbus_t *xbus, xpacket_t *p);
- };
-
-+/*
-+ * XBUS statistics counters
-+ */
- enum {
- XBUS_N_DESC_REQ,
-- XBUS_N_DEV_DESC,
-+ XBUS_N_DEV_DESC_FULL,
-+ XBUS_N_DEV_DESC_EMPTY,
- XBUS_N_PCM_WRITE,
- XBUS_N_PCM_READ,
- XBUS_N_TX_BYTES,
- XBUS_N_RX_BYTES,
-- XBUS_N_SOFTSIM_PACKETS,
-- XBUS_N_SIM_PACKETS,
- };
-
- #define XBUS_COUNTER(xbus, counter) ((xbus)->counters[XBUS_N_ ## counter])
-@@ -120,68 +109,76 @@
- char *name;
- } xbus_counters[] = {
- C_(DESC_REQ),
-- C_(DEV_DESC),
-+ C_(DEV_DESC_FULL),
-+ C_(DEV_DESC_EMPTY),
- C_(PCM_WRITE),
- C_(PCM_READ),
- C_(TX_BYTES),
- C_(RX_BYTES),
-- C_(SOFTSIM_PACKETS),
-- C_(SIM_PACKETS),
- };
-
- #undef C_
-
- #define XBUS_COUNTER_MAX ARRAY_SIZE(xbus_counters)
-
--struct xpd_sim {
-- bool simulated;
-- bool softloop_xpd;
-- int loopto;
-- xpd_type_t xpd_type;
-- xpp_line_t hookstate;
-+#define CARD_DESC_MAGIC 0xca9dde5c
-+
-+struct card_desc_struct {
-+ struct list_head card_list;
-+ u32 magic;
-+ xbus_t *xbus;
-+ byte rev; /* Revision number */
-+ byte type; /* LSB: 1 - to_phone, 0 - to_line */
-+ xpd_addr_t xpd_addr;
- };
-
-
-+/*
-+ * An xbus is a transport layer for Xorcom Protocol commands
-+ */
- struct xbus {
-- char busname[XBUS_NAMELEN]; /* only xbus_new set this */
-- char busdesc[XBUS_DESCLEN]; /* lowlevel drivers set this */
-- int num;
-- xbus_ops_t *ops;
-- struct xpd *xpds[MAX_XPDS];
-+ char busname[XBUS_NAMELEN]; /* only xbus_new set this */
-+ char busdesc[XBUS_DESCLEN]; /* lowlevel drivers set this */
-+ int num;
-+ xbus_ops_t *ops;
-+ struct xpd *xpds[MAX_XPDS];
-+ int max_packet_size;
-
-- /* Simulator data */
-- xbus_type_t bus_type;
--#if SOFT_SIMULATOR
-- struct xpd_sim sim[MAX_XPDS];
-- struct workqueue_struct *sim_workqueue;
-- struct work_struct sim_work; // workqueue job for running simulator
-- packet_queue_t sim_packet_queue;
--#endif
-+ /* Device-Model */
-+ struct device the_bus;
-
-- spinlock_t lock;
-+ /* Simulator data */
-+ xbus_type_t bus_type;
-
-- bool hardware_exists; /* Hardware is functional */
-- int open_counter; /* Number of open channels */
-- atomic_t packet_counter; /* Allocated packets */
-- wait_queue_head_t packet_cache_empty;
--
-- struct timer_list poll_timer;
-- struct rw_semaphore in_use;
-- int num_xpds;
-- void *priv; /* Pointer to transport level data structures */
-+ spinlock_t lock;
-
--#ifdef XPP_PACKET_LOG
-- struct cyclic_buff *packet_log;
--#endif
-+ bool hardware_exists; /* Hardware is functional */
-+ int open_counter; /* Number of open channels */
-+ atomic_t packet_counter; /* Allocated packets */
-+ wait_queue_head_t packet_cache_empty;
-+
-+ struct timer_list poll_timer;
-+ /*
-+ * Bus scanning
-+ */
-+ atomic_t count_poll_answers;
-+ struct list_head poll_results;
-+ wait_queue_head_t wait_for_polls;
-+ struct work_struct xpds_init_work;
-+ struct completion xpds_initialized;
-+
-+ struct rw_semaphore in_use;
-+ int num_xpds;
-+ void *priv; /* Pointer to transport level data structures */
-
- #ifdef CONFIG_PROC_FS
- struct proc_dir_entry *proc_xbus_dir;
- struct proc_dir_entry *proc_xbus_summary;
-+ struct proc_dir_entry *proc_xbus_waitfor_xpds;
- #endif
-
- /* statistics */
- int counters[XBUS_COUNTER_MAX];
--
- };
- #endif
-
-@@ -190,15 +187,11 @@
- TO_PSTN = 1,
- } xpd_direction_t;
-
--#define LINE_BITS (sizeof(xpp_line_t)*8)
--
--
- #ifdef __KERNEL__
--#define BIT_SET(x,i) ((x) |= (1 << (i)))
--#define BIT_CLR(x,i) ((x) &= ~(1 << (i)))
--#define IS_SET(x,i) (((x) & (1 << (i))) != 0)
--#define BIT(i) (1 << (i))
-
-+/*
-+ * XPD statistics counters
-+ */
- enum {
- XPD_N_PCM_READ,
- XPD_N_PCM_WRITE,
-@@ -222,60 +215,74 @@
-
- #define XPD_COUNTER_MAX (sizeof(xpd_counters)/sizeof(xpd_counters[0]))
-
--enum leds {
-- LED_GREEN,
-- LED_RED,
-- LED_BLUE,
--};
-+#define LED_BLINK_PERIOD (HZ/8)
-
--#define NUM_LEDS 3
-+#define LED_ON 1
-+#define LED_OFF 0
-+#define LED_BLINK (-LED_BLINK_PERIOD)
-+
-+/* Values of SLIC register 0x40 */
-+enum fxs_state {
-+ FXS_LINE_DISABLED = 0x00,
-+ FXS_LINE_ENABLED = 0x01,
-+ FXS_LINE_CID = 0x02,
-+ FXS_LINE_TIPOPEN = 0x03, /* For GroundStart signalling */
-+ FXS_LINE_RING = 0x04,
-+ FXS_LINE_REV_ACTIVE = 0x05
-+};
-
-+/*
-+ * An XPD is a single Xorcom Protocol Device
-+ */
- struct xpd {
- char xpdname[XPD_NAMELEN];
- struct zt_span span;
- struct zt_chan *chans;
- int channels;
- xpd_type_t type;
-+ byte revision; /* Card revision */
- xpd_direction_t direction; /* TO_PHONE, TO_PSTN */
-- xpp_line_t enabled_chans; /* hardware activation: 0 - off, 1 - on */
-- xpp_line_t hookstate; /* 0 - ONHOOK, 1 - OFHOOK */
-- xpp_line_t ledstate[NUM_LEDS]; /* 0 - OFF, 1 - ON */
-+ xpp_line_t no_pcm; /* Temporary: disable PCM (for USB-1) */
-+ xpp_line_t hookstate; /* Actual chip state: 0 - ONHOOK, 1 - OFHOOK */
-+ xpp_line_t cid_on;
- xpp_line_t digital_outputs; /* 0 - no, 1 - yes */
- xpp_line_t digital_inputs; /* 0 - no, 1 - yes */
-
-- int ringing[CHANNELS_PERXPD];
-- bool ringer_on[CHANNELS_PERXPD]; /* For ring toggling */
-- bool led_on[CHANNELS_PERXPD]; /* For led toggling */
-- int lasttxhook[CHANNELS_PERXPD];
-+ int ringing[CHANNELS_PERXPD];
-+ bool ringer_on[CHANNELS_PERXPD]; /* For ring toggling */
-+
-+ wait_queue_head_t txstateq[CHANNELS_PERXPD]; /* waiting on the tx state to change */
-+ int delay_until_dialtone[CHANNELS_PERXPD];
-
-- struct work_struct xpd_post_init;
-- xbus_t *xbus;
-+ enum fxs_state lasttxhook[CHANNELS_PERXPD];
-+ int idletxhookstate[CHANNELS_PERXPD]; /* IDLE changing hook state */
-+ int ohttimer[CHANNELS_PERXPD];
-+
-+ xbus_t *xbus; /* The XBUS we are connected to */
-
- spinlock_t lock;
-- atomic_t open_counter; /* Number of open channels */
-+ atomic_t open_counter; /* Number of open channels */
-
- int flags;
-
-- unsigned int board_flags;
--#define XPD_BOARD_LOOPBACK 1
--
- #ifdef CONFIG_PROC_FS
- struct proc_dir_entry *proc_xpd_dir;
- struct proc_dir_entry *proc_xpd_summary;
- struct proc_dir_entry *proc_xpd_ztregister;
- #endif
-- // Bit numbers of board_flags
-
- int counters[XPD_COUNTER_MAX];
-
-- const xops_t *xops; /* Card level operations */
-- void *priv; /* Card level private data */
-- atomic_t card_present;
-+ const xproto_table_t *xproto; /* Card level protocol table */
-+ const xops_t *xops; /* Card level operations */
-+ void *priv; /* Card level private data */
-+ bool card_present;
-
- unsigned int recv_errors;
- unsigned int seq_errors;
- unsigned long last_response; /* in jiffies */
- unsigned id;
-+ xpd_addr_t addr;
- struct list_head xpd_list;
- unsigned int timer_count;
- volatile u_char *writechunk; /* Double-word aligned write memory */
-@@ -285,6 +292,9 @@
- u_char ec_chunk2[CHANNELS_PERXPD][ZT_CHUNKSIZE];
- };
-
-+#define for_each_line(xpd,i) \
-+ for((i) = 0; (i) < (xpd)->channels; (i)++)
-+
- #endif
-
- #endif /* XPD_H */
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/xpp_fxloader zaptel-xpp-LJNBCn_dist/xpp/xpp_fxloader
---- zaptel-1.2.6/xpp/xpp_fxloader 2006-02-15 04:24:18.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/xpp_fxloader 1970-01-01 02:00:00.000000000 +0200
-@@ -1,24 +0,0 @@
--#!/bin/sh
--
--FIRMWARE="/etc/xortel/FPGA_XPD.hex"
--me=`basename $0`
--
--# to run manually, pass the parameter 'xppdetect'
--V_ID=04b4
--P_ID=8613
--if [ "$1" = 'xppdetect' ]; then
-- DEVICES=`lsusb | tr -d : | awk "/ ID $V_ID$P_ID /{printf \"/proc/bus/usb/%s/%s \",\\$2,\\$4}"`
-- echo "Loading firmware for $DEVICES"
-- for dev in $DEVICES
-- do
-- fxload -t fx2 -D $dev -I $FIRMWARE
-- done
-- exit 0
--fi
--
--if [ "$ACTION" = "add" ] && [ -f "$DEVICE" ]
--then
-- logger -i -t "$me" "Loading firmware '$FIRMWARE' into '$DEVICE'"
-- fxload -t fx2 -D "$DEVICE" -I "$FIRMWARE" || exit 1
--fi
--
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/xpp_fxloader.usermap zaptel-xpp-LJNBCn_dist/xpp/xpp_fxloader.usermap
---- zaptel-1.2.6/xpp/xpp_fxloader.usermap 2006-02-15 04:24:18.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/xpp_fxloader.usermap 1970-01-01 02:00:00.000000000 +0200
-@@ -1,2 +0,0 @@
--# module match_flags idVendor idProduct bcdDevice_lo bcdDevice_hi bDeviceClass bDeviceSubClass bDeviceProtocol bInterfaceClass bInterfaceSubClass bInterfaceProtocol driver_info
--xpp_fxloader 0x0003 0x04b4 0x8613 0x0000 0x0000 0x00 0x00 0x00 0x00 0x00 0x00 0x0
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/xpp_modprobe zaptel-xpp-LJNBCn_dist/xpp/xpp_modprobe
---- zaptel-1.2.6/xpp/xpp_modprobe 2006-02-15 04:24:18.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/xpp_modprobe 1970-01-01 02:00:00.000000000 +0200
-@@ -1,10 +0,0 @@
--# Some debugging options for the brave of heart:
--#options zaptel debug=1
--#options wcfxo debug=1
--#options xpp print_dbg=1
--
--# For pre-loading of card modules (e.g: xpp_fxs)
--#install xpp_usb /sbin/modprobe xpd_fxs && /sbin/modprobe --ignore-install xpp_usb
--
--# For auto loading of card modules
--alias xpd-type-3 xpd_fxs
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/xpp_proto.c zaptel-xpp-LJNBCn_dist/xpp/xpp_proto.c
---- zaptel-1.2.6/xpp/xpp_proto.c 2006-02-15 04:24:18.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/xpp_proto.c 1970-01-01 02:00:00.000000000 +0200
-@@ -1,1044 +0,0 @@
--#include <linux/module.h>
--#include <linux/delay.h> /* for udelay */
--#include "xpd.h"
--#include "xpp_proto.h"
--#include "xpp_zap.h"
--
--static char rcsid[] = "$Id: xpp_proto.c 949 2006-02-15 02:24:18Z kpfleming $";
--
--extern int print_dbg;
--#include "zap_debug.h"
--
--typedef struct xpp_command xpp_command_t;
--typedef int (*xpp_handler_t)(xbus_t *xbus, int id, xpp_command_t *cmd, xpacket_t *packet);
--
--struct xpp_command {
-- xpp_opcode_t opcode;
-- unsigned int header_size;
-- bool varsize;
-- const char *name;
-- const char *desc;
-- xpp_handler_t handler;
--};
--
--#define S_(s,l,...) \
-- { \
-- .lines = s, \
-- { \
-- .len = l, \
-- .data = { __VA_ARGS__ }, \
-- } \
-- }
--
--struct slic_init_data {
-- xpp_line_t lines;
-- slic_data_t slic_data;
--} slic_init_data[] = {
--#include "slic_init.inc"
--};
--
--static int packet_process(xbus_t *xbus, int xpd_num, xpacket_t *pack);
--static int simulate_xpd(xbus_t *xbus, int xpd_num, xpacket_t *sent_packet);
--static bool pcm_valid(xpd_t *xpd, xpacket_t *reply);
--
--#define NEW_PACKET(p, xbus, name, to) \
-- do { \
-- p = xbus->ops->packet_new(xbus, GFP_ATOMIC); \
-- if(!p) \
-- return -ENOMEM; \
-- PACKET_INIT(p, name); \
-- XPD_ADDR_SET(p->content.addr, to); \
-- } while(0);
--
--/*------------------------- SLIC Handling --------------------------*/
--
--int proc_xpd_slic_read(char *page, char **start, off_t off, int count, int *eof, void *data)
--{
-- int len = 0;
-- unsigned long flags;
-- xpd_t *xpd = data;
-- //slic_reply_t *info;
--
-- BUG_ON(!xpd);
-- spin_lock_irqsave(&xpd->lock, flags);
--#if 0
-- info = (slic_reply_t *)&xpd->slic_info;
-- len += sprintf(page + len, "SLIC_REPLY: %s reg_num=0x%X, dataH=0x%X dataL=0x%X\n",
-- (info->indirect)?"I":"D",
-- info->reg_num, info->data_high, info->data_low);
--#endif
-- spin_unlock_irqrestore(&xpd->lock, flags);
-- if (len <= off+count)
-- *eof = 1;
-- *start = page + off;
-- len -= off;
-- if (len > count)
-- len = count;
-- if (len < 0)
-- len = 0;
-- return len;
--}
--
--static int parse_slic_cmd(const char *buf, slic_cmd_t *sc)
--{
-- char op; /* [W]rite, [R]ead */
-- char reg_type; /* [D]irect, [I]ndirect */
-- int s1, s2, s3, s4;
-- int reg_num;
-- int data_low, data_high;
-- xpp_line_t lines;
-- int ret;
--
-- ret = sscanf(buf, "%x %x %x %x %c%c %x %x %x",
-- &s1, &s2, &s3, &s4, &op, ®_type, ®_num, &data_high, &data_low);
-- lines = (s4 << 24) | (s3 << 16) | (s2 << 8) | (s1);
-- switch(op) {
-- case 'R':
-- if(reg_type == 'D' && ret == 7) {
-- // DBG("0x%X 0x%X 0x%X 0x%X %c %x\n", s1, s2, s3, s4, reg_type, reg_num);
-- ret = slic_cmd_direct_read(sc, lines, reg_num);
-- } else if(reg_type == 'I' && ret == 7) {
-- // DBG("0x%X 0x%X 0x%X 0x%X %c %x\n", s1, s2, s3, s4, reg_type, reg_num);
-- ret = slic_cmd_indirect_read(sc, lines, reg_num);
-- } else {
-- NOTICE("%s: Bad read input: ret=%d buf='%s' reg_type=%c\n", __FUNCTION__, ret, buf, reg_type);
-- goto err;
-- }
-- break;
-- case 'W':
-- if(reg_type == 'D' && ret == 8) {
-- // DBG("0x%X 0x%X 0x%X 0x%X %c %x %X\n", s1, s2, s3, s4, reg_type, reg_num, data_high);
-- ret = slic_cmd_direct_write(sc, lines, reg_num, data_high);
-- } else if(reg_type == 'I' && ret == 9) {
-- // DBG("0x%X 0x%X 0x%X 0x%X %c %x %X %X\n", s1, s2, s3, s4, reg_type, reg_num, data_high, data_low);
-- ret = slic_cmd_indirect_write(sc, lines, reg_num, data_low, data_high);
-- } else {
-- NOTICE("%s: Bad write input: ret=%d buf='%s' reg_type=%c\n", __FUNCTION__, ret, buf, reg_type);
-- goto err;
-- }
-- break;
-- default:
-- NOTICE("%s: Bad input: ret=%d buf='%s' op=%c\n", __FUNCTION__, ret, buf, op);
-- goto err;
-- }
-- return ret;
--err:
-- return -EINVAL;
--}
--
--static int process_slic_cmdline(xpd_t *xpd, char *cmdline)
--{
-- xbus_t *xbus;
-- slic_cmd_t sc;
-- xpacket_t *pack_tx;
-- char *p;
-- int len = strlen(cmdline);
--
-- BUG_ON(!xpd);
-- xbus = xpd->xbus;
-- if((p = strchr(cmdline, '#')) != NULL) /* Truncate comments */
-- *p = '\0';
-- if((p = strchr(cmdline, ';')) != NULL) /* Truncate comments */
-- *p = '\0';
-- for(p = cmdline; *p && (*p == ' ' || *p == '\t'); p++) /* Trim leading whitespace */
-- ;
-- if(*p == '\0')
-- return 0;
-- len = parse_slic_cmd(p, &sc);
-- if(len < 0)
-- return len;
-- sc.lines &= xpd->enabled_chans; // Ignore disabled channels
-- if(!sc.lines) {
-- NOTICE("%s: no enabled channels are marked. Skip.\n", __FUNCTION__);
-- return 0;
-- }
-- dump_slic_cmd("WRITE_SLIC", &sc);
-- NEW_PACKET(pack_tx, xbus, SLIC_WRITE, xpd->id);
-- PACKET_FIELD(pack_tx, SLIC_WRITE, slic_cmd) = sc;
-- pack_tx->datalen = len;
-- packet_send(xbus, pack_tx);
-- return 0;
--}
--
--int proc_xpd_slic_write(struct file *file, const char __user *buffer, unsigned long count, void *data)
--{
-- xpd_t *xpd = data;
-- const int LINE_LEN = 500;
-- char buf[LINE_LEN];
-- char *p;
-- int i;
-- int ret;
--
-- BUG_ON(!xpd);
-- for(i = 0; i < count; /* noop */) {
-- for(p = buf; p < buf + LINE_LEN; p++) { /* read a line */
-- if(i >= count)
-- break;
-- if(get_user(*p, buffer + i))
-- return -EFAULT;
-- i++;
-- if(*p == '\n' || *p == '\r') /* whatever */
-- break;
-- }
-- if(p >= buf + LINE_LEN)
-- return -E2BIG;
-- *p = '\0';
-- ret = process_slic_cmdline(xpd, buf);
-- if(ret < 0)
-- return ret;
-- }
-- return count;
--}
--
--
--
--/*------------------------- Protocol Functions ---------------------*/
--
--#define HOSTCMD(name, ...) \
-- DECLARE_CMD(name, ## __VA_ARGS__ ); \
-- EXPORT_SYMBOL(xpp_proto_ ## name); \
-- DECLARE_CMD(name, ## __VA_ARGS__ )
--
--
--/* 0x04 */ HOSTCMD(DESC_REQ, int xpd_num)
--{
-- int ret = 0;
-- xpacket_t *pack_tx;
--
-- DBG("\n");
-- if(!xbus) {
-- DBG("NO XBUS\n");
-- return -EINVAL;
-- }
-- NEW_PACKET(pack_tx, xbus, DESC_REQ, xpd_num);
-- DBG("calling packet_send for a DESC_REQ packet.\n");
-- ret = packet_send(xbus, pack_tx);
-- DBG("after packet_send, updating counter (ret=%d)\n", ret);
-- XBUS_COUNTER(xbus, DESC_REQ)++;
-- return ret;
--}
--
--/* 0x0F */ HOSTCMD(CHAN_POWER, xpp_line_t lines, bool on)
--{
-- int ret = 0;
-- xpacket_t *pack_tx;
-- slic_cmd_t *sc;
-- int len;
--
-- BUG_ON(!xbus);
-- BUG_ON(!xpd);
-- lines &= xpd->enabled_chans; // Ignore disabled channels
-- if(!lines) {
-- return 0;
-- }
-- DBG("Channel Power: 0x%04X %s\n", lines, (on) ? "up" : "down");
-- NEW_PACKET(pack_tx, xbus, SLIC_WRITE, xpd->id);
-- sc = &PACKET_FIELD(pack_tx, SLIC_WRITE, slic_cmd);
-- if(on) {
-- // Power up
-- len = slic_cmd_direct_write(sc, lines, 0x42, 0x06);
-- } else {
-- // Power down
-- len = slic_cmd_direct_write(sc, lines, 0x42, 0x00);
-- }
-- pack_tx->datalen = len;
--
-- packet_send(xbus, pack_tx);
-- return ret;
--}
--
--/* 0x0F */ HOSTCMD(CHAN_ENABLE, xpp_line_t lines, bool on)
--{
-- int ret = 0;
-- xpacket_t *pack_tx;
-- slic_cmd_t *sc;
-- int len;
--
-- BUG_ON(!xbus);
-- BUG_ON(!xpd);
-- lines &= xpd->enabled_chans; // Ignore disabled channels
-- if(!lines) {
-- return 0;
-- }
-- DBG("Channel Activation: 0x%4X %s\n", lines, (on) ? "on" : "off");
-- NEW_PACKET(pack_tx, xbus, SLIC_WRITE, xpd->id);
-- sc = &PACKET_FIELD(pack_tx, SLIC_WRITE, slic_cmd);
-- len = slic_cmd_direct_write(sc, lines, 0x40, (on)?0x01:0x00);
-- pack_tx->datalen = len;
--
-- packet_send(xbus, pack_tx);
-- return ret;
--}
--
--/* 0x0F */ HOSTCMD(RING, int pos, bool on)
--{
-- int ret = 0;
-- xpacket_t *pack_tx;
-- slic_cmd_t *sc;
-- xpp_line_t mask = (1 << pos);
-- int len;
--
-- BUG_ON(!xbus);
-- BUG_ON(!xpd);
-- mask &= xpd->enabled_chans; // Ignore disabled channels
-- if(!mask) {
-- return 0;
-- }
-- DBG("%s pos=%d %s\n", xpd->xpdname, pos, (on) ? "on" : "off");
-- NEW_PACKET(pack_tx, xbus, SLIC_WRITE, xpd->id);
-- sc = &PACKET_FIELD(pack_tx, SLIC_WRITE, slic_cmd);
-- len = slic_cmd_direct_write(sc, mask, 0x40, (on)?0x04:0x01);
-- pack_tx->datalen = len;
--
-- packet_send(xbus, pack_tx);
-- return ret;
--}
--
--/* 0x0F */ HOSTCMD(SETHOOK, xpp_line_t hook_status)
--{
-- int ret = 0;
-- xpacket_t *pack_tx;
-- slic_cmd_t *sc;
-- int len;
--
-- BUG_ON(!xbus);
-- BUG_ON(!xpd);
-- hook_status &= xpd->enabled_chans; // Ignore disabled channels
-- if(!hook_status) {
-- return 0;
-- }
-- DBG("New hook_status: %d\n", hook_status);
-- NEW_PACKET(pack_tx, xbus, SLIC_WRITE, xpd->id);
-- sc = &PACKET_FIELD(pack_tx, SLIC_WRITE, slic_cmd);
-- /* FIXME: This is fake, until Dima implements FXO */
-- len = slic_cmd_direct_write(sc, hook_status, 0x02, 0x00);
-- pack_tx->datalen = len;
--
-- packet_send(xbus, pack_tx);
-- return ret;
--}
--
--/*
-- * LED control is done via SLIC register 0x06:
-- * 7 6 5 4 3 2 1 0
-- * +-----+-----+-----+-----+-----+-----+-----+-----+
-- * | MR | MG | MB | R | OG | OB | G | B |
-- * +-----+-----+-----+-----+-----+-----+-----+-----+
-- *
-- * B - BLUE LED (0 - OFF, 1 - ON)
-- * G - GREEN LED (0 - OFF, 1 - ON)
-- * OB - Output BLUE (this line is output)
-- * OG - Output GREEN (this line is output)
-- * R - RED LED (0 - OFF, 1 - ON)
-- * MB - Mask BLUE. (1 - B effect the BLUE LED)
-- * MR - Mask RED. (1 - R effect the RED LED)
-- * MG - Mask GREEN. (1 - G effect the GREEN LED)
-- *
-- * The BLUE LED (actually a relay out) is connected to line 0 and 4 only.
-- */
--
--// GREEN RED BLUE
--static int led_mask[NUM_LEDS] = { BIT(6), BIT(7), BIT(5) };
--static int led_vals[NUM_LEDS] = { BIT(1), BIT(4), BIT(0) };
--
--/* 0x0F */ HOSTCMD(LED, xpp_line_t lines, byte which, bool on)
--{
-- int ret = 0;
-- xpacket_t *pack_tx;
-- slic_cmd_t *sc;
-- int len;
-- int value;
-- int i;
--
-- BUG_ON(!xbus);
-- BUG_ON(!xpd);
-- lines &= xpd->enabled_chans; // Ignore disabled channels
-- if(!lines) {
-- return 0;
-- }
-- DBG("LED: lines=0x%04X which=%d -- %s\n", lines, which, (on) ? "on" : "off");
-- which = which % NUM_LEDS;
-- value = BIT(2) | BIT(3);
-- value |= ((BIT(5) | BIT(6) | BIT(7)) & ~led_mask[which]);
-- if(on)
-- value |= led_vals[which];
-- for(i = 0; i < CHANNELS_PERXPD; i++) {
-- if(!IS_SET(lines, i))
-- continue;
-- NEW_PACKET(pack_tx, xbus, SLIC_WRITE, xpd->id);
-- sc = &PACKET_FIELD(pack_tx, SLIC_WRITE, slic_cmd);
-- len = slic_cmd_direct_write(sc, lines, 0x06, value);
-- DBG("LED pack: line=%d value=0x%04X\n", i, value);
-- pack_tx->datalen = len;
-- packet_send(xbus, pack_tx);
-- }
-- return ret;
--}
--
--/* 0x0F */ HOSTCMD(RELAY_OUT, byte which, bool on)
--{
-- int ret = 0;
-- xpacket_t *pack_tx;
-- slic_cmd_t *sc;
-- int len;
-- int value;
-- xpp_line_t lines;
-- int relay_channels[] = { 0, 4 };
--
-- BUG_ON(!xbus);
-- BUG_ON(!xpd);
--
-- DBG("RELAY_OUT: which=%d -- %s\n", which, (on) ? "on" : "off");
-- which = which % ARRAY_SIZE(relay_channels);
-- lines = BIT(relay_channels[which]);
-- value = BIT(2) | BIT(3);
-- value |= ((BIT(5) | BIT(6) | BIT(7)) & ~led_mask[LED_BLUE]);
-- if(on)
-- value |= led_vals[LED_BLUE];
-- NEW_PACKET(pack_tx, xbus, SLIC_WRITE, xpd->id);
-- sc = &PACKET_FIELD(pack_tx, SLIC_WRITE, slic_cmd);
-- len = slic_cmd_direct_write(sc, lines, 0x06, value);
--
-- DBG("RELAY_OUT pack: line=%d value=0x%04X\n", lines, value);
-- pack_tx->datalen = len;
-- packet_send(xbus, pack_tx);
-- return ret;
--}
--
--/* 0x0F */ HOSTCMD(SLIC_INIT)
--{
-- int ret = 0;
-- xpacket_t *pack_tx;
-- slic_data_t *slic;
-- struct slic_init_data *source;
-- int i;
--
-- BUG_ON(!xbus);
-- BUG_ON(!xpd);
-- DBG("INITIALIZING SLIC\n");
-- for(i = 0; i < ARRAY_SIZE(slic_init_data); i++) {
-- source = &slic_init_data[i];
-- NEW_PACKET(pack_tx, xbus, SLIC_INIT, xpd->id);
-- PACKET_FIELD(pack_tx, SLIC_INIT, lines) = source->lines;
--
-- slic = &PACKET_FIELD(pack_tx, SLIC_INIT, slic_data);
-- slic->len = source->slic_data.len;
-- memcpy(slic->data, source->slic_data.data, source->slic_data.len);
-- pack_tx->datalen = sizeof(xpp_line_t) + slic->len + 1;
--// dump_packet("SLIC", pack_tx, print_dbg);
-- packet_send(xbus, pack_tx);
-- mdelay(10); // FIXME: Temporary -- Dima need to fix it
-- }
-- return ret;
--}
--
--/* 0x0F */ HOSTCMD(SLIC_QUERY, int pos, byte reg_num)
--{
-- int ret = 0;
-- xpacket_t *pack_tx;
-- slic_cmd_t *sc;
-- int len;
--
-- BUG_ON(!xbus);
-- BUG_ON(!xpd);
-- NEW_PACKET(pack_tx, xbus, SLIC_WRITE, xpd->id);
-- sc = &PACKET_FIELD(pack_tx, SLIC_WRITE, slic_cmd);
-- len = slic_cmd_direct_read(sc, (1<<pos), reg_num);
--
-- pack_tx->datalen = len;
--
-- packet_send(xbus, pack_tx);
-- return ret;
--}
--
--/* 0x11 */ HOSTCMD(PCM_WRITE, xpp_line_t lines, volatile byte *buf)
--{
-- int ret = 0;
-- xpacket_t *pack_tx;
-- byte *pcm;
-- byte *start_pcm;
-- int i;
-- extern ulong pcm_gen;
--
-- BUG_ON(!xbus);
-- BUG_ON(!xpd);
-- lines &= xpd->enabled_chans;
-- // DBG("PCM_WRITE\n");
-- if(pcm_gen != 0)
-- return 0;
--// if(lines == 0)
--// return 0;
--
-- /*
-- * FIXME: Workaround a bug in sync code of the Astribank.
-- * Send dummy PCM for sync.
-- */
-- if(lines == 0)
-- lines = BIT(0);
--
-- NEW_PACKET(pack_tx, xbus, PCM_WRITE, xpd->id);
-- PACKET_FIELD(pack_tx, PCM_WRITE, lines) = lines;
-- start_pcm = pcm = PACKET_FIELD(pack_tx, PCM_WRITE, pcm);
-- for(i = 0; i < CHANNELS_PERXPD; i++) {
-- if(IS_SET(lines, i)) {
-- memcpy(pcm, (byte *)buf, ZT_CHUNKSIZE);
-- pcm += ZT_CHUNKSIZE;
-- }
-- buf += ZT_CHUNKSIZE;
-- }
-- pack_tx->datalen = sizeof(xpp_line_t) + (pcm - start_pcm);
-- packet_send(xbus, pack_tx);
-- XPD_COUNTER(xpd, PCM_WRITE)++;
-- XBUS_COUNTER(xbus, PCM_WRITE)++;
-- return ret;
--}
--
--/* 0x13 */ HOSTCMD(PCM_GEN, xpp_line_t lines, volatile byte *buf)
--{
-- xpacket_t *pack_tx;
-- bool gen_seq = ((lines != 0) && (buf != NULL));
--
-- BUG_ON(!xbus);
-- BUG_ON(!xpd);
-- lines &= xpd->enabled_chans; // Ignore disabled channels
-- if(!lines) {
-- return 0;
-- }
-- DBG("PCM_GEN lines=0x%04X %s\n", lines, (gen_seq) ? "seq" : "off");
-- NEW_PACKET(pack_tx, xbus, PCM_GEN, xpd->id);
-- PACKET_FIELD(pack_tx, PCM_GEN, lines) = lines;
-- if(gen_seq) {
-- PACKET_FIELD(pack_tx, PCM_GEN, gen) = 0;
-- memcpy(&PACKET_FIELD(pack_tx, PCM_GEN, pcm_seq), (byte *)buf, ZT_CHUNKSIZE);
-- } else {
-- PACKET_FIELD(pack_tx, PCM_GEN, gen) = 2;
-- }
-- packet_send(xbus, pack_tx);
-- return 0;
--}
--
--/*
-- * Sync source is controled by a mask byte to 0x19 command:
-- * 7 6 5 4 3 2 1 0
-- * +-----+-----+-----+-----+-----+-----+-----+-----+
-- * | | | | | | | RW | AB |
-- * +-----+-----+-----+-----+-----+-----+-----+-----+
-- *
-- * RW - Read or set (0 - Write, 1 - Read)
-- * AB - This Astribank provide sync (0 - no, 1 - yes)
-- *
-- */
--
--/* 0x19 */ HOSTCMD(SYNC_SOURCE, bool setit, bool is_master)
--{
-- xpacket_t *pack_tx;
-- byte mask = 0;
--
-- BUG_ON(!xbus);
-- BUG_ON(!xpd);
-- if(is_master)
-- mask |= BIT(0);
-- if(!setit)
-- 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);
-- NEW_PACKET(pack_tx, xbus, SYNC_SOURCE, xpd->id);
-- PACKET_FIELD(pack_tx, SYNC_SOURCE, mask) = mask;
-- packet_send(xbus, pack_tx);
-- return 0;
--}
--
--/* 0x31 */ HOSTCMD(LOOPBACK_AX, byte *data, unsigned int size)
--{
-- xpacket_t *pack_tx;
--
-- BUG_ON(!xbus);
-- BUG_ON(!xpd);
-- DBG("LOOPBACK_AX %d bytes\n", size);
-- NEW_PACKET(pack_tx, xbus, LOOPBACK_AX, xpd->id);
-- memcpy(&PACKET_FIELD(pack_tx, LOOPBACK_AX, data), data, size);
-- packet_send(xbus, pack_tx);
-- return 0;
--}
--
--/*------------------------- Protocol Simulator ---------------------*/
--
--
--static int simulate_xpd(xbus_t *xbus, int xpd_num, xpacket_t *sent_packet)
--{
-- xpacket_t *pack = sent_packet;
-- struct xpd_sim *xpd_sim;
-- struct xpd_sim *loopto_sim;
-- xpp_opcode_t opcode;
-- int dest_xpd_num;
-- int ret = 0;
--
-- // Sanity checks
-- BUG_ON(!xbus);
-- BUG_ON(xpd_num > MAX_XPDS || xpd_num < 0);
-- BUG_ON(!sent_packet);
-- BUG_ON(!xbus->sim[xpd_num].simulated);
--
-- XBUS_COUNTER(xbus, SIM_PACKETS)++;
-- xpd_sim = &xbus->sim[xpd_num];
-- opcode = pack->content.opcode;
-- dest_xpd_num = xpd_sim->loopto;
-- loopto_sim = &xbus->sim[dest_xpd_num];
--// DBG("before: addr=%d, opcode=0x%X\n", xpd_num, opcode);
-- switch(opcode) {
-- case XPP_DESC_REQ:
-- DBG("SIM DESC_REQ (xpd_num=%d)\n", xpd_num);
-- PACKET_INIT(pack, DEV_DESC);
-- PACKET_FIELD(pack, DEV_DESC, type) = xpd_sim->xpd_type;
-- dest_xpd_num = xpd_num; // Reply as the original XPD
-- break;
-- case XPP_PCM_WRITE:
-- PACKET_INIT(pack, PCM_READ);
-- XPD_ADDR_SET(pack->content.addr, dest_xpd_num);
-- break;
-- case XPP_SLIC_WRITE:
--#if FINISHED_DECODING_SLICS
-- slic_cmd_t *sc;
-- int len;
--
-- sc = &PACKET_FIELD(pack_tx, SLIC_WRITE, slic_cmd);
-- lines = sc->lines;
-- bool slic_write = ! (slic->data[0] & 0x80);
-- int slic_reg = slic->data[0] & ~0x80;
--
-- if(slic->len == 2 && slic_write && slic_reg == 0x40) { // RING
-- bool on = (slic->data[1] == 0x04);
-- if(on) {
-- loopto_sim->hookstate |= lines;
-- } else {
-- loopto_sim->hookstate &= ~lines;
-- }
--
-- DBG("SIM RING to: xpd=%d (type=%d): (%s) ringing=0x%04X lines=0x%04X\n", dest_xpd_num, loopto_sim->xpd_type,
-- (on)?"on":"off", loopto_sim->hookstate, lines);
-- PACKET_INIT(pack, SIG_CHANGED);
-- PACKET_FIELD(pack, SIG_CHANGED, type) = loopto_sim->xpd_type;
-- PACKET_FIELD(pack, SIG_CHANGED, sig_status) = loopto_sim->hookstate;
-- PACKET_FIELD(pack, SIG_CHANGED, sig_toggles) = lines;
-- dump_packet("SIM RING TO", pack, print_dbg);
-- break;
-- } else if(slic->len == 1 && slic_write && slic_reg == 0x02) { // SETHOOK
-- DBG("SIM SETHOOK: xpd=%d: hookstate=0x%04X lines=0x%04X\n", dest_xpd_num, loopto_sim->hookstate, lines);
-- PACKET_INIT(pack, SIG_CHANGED);
-- PACKET_FIELD(pack, SIG_CHANGED, type) = loopto_sim->xpd_type;
-- PACKET_FIELD(pack, SIG_CHANGED, sig_status) = lines;
-- PACKET_FIELD(pack, SIG_CHANGED, sig_toggles) = loopto_sim->hookstate ^ lines;
-- loopto_sim->hookstate = lines;
-- break;
-- } else if(slic->len == 2 && slic_write && slic_reg == 0x06) { // LED
-- DBG("SIM LED: xpd=%d: 0x%04X=%s\n", xpd_num, lines, (0x10)? "on" : "off");
-- ret = 0;
-- goto junk;
-- } else if(slic->len == 2 && ! slic_write) { // SLIC_QUERY
-- DBG("SIM SLIC_QUERY: xpd=%d: register=0x%02X\n", xpd_num, slic_reg);
-- ret = 0;
-- goto junk;
-- } else if(slic->len >= 4) { // INITIALIZATION?
-- DBG("SIM INITIALIZATION? xpd=%d len=%d\n", xpd_num, slic->len);
-- ret = 0;
-- goto junk;
-- }
-- NOTICE("%s: xpd=%d: SLIC_WRITE: len=%d\n", __FUNCTION__, xpd_num, slic->len);
--#endif
-- dump_packet("BAD SLIC_WRITE", pack, print_dbg);
-- // FALL THROUGH
-- default:
-- NOTICE("%s: xpd=%d: CANNOT SIMULATE OPCODE=0x%02X\n",
-- __FUNCTION__, xpd_num, opcode);
--// dump_packet("BAD OPCODE", pack, print_dbg);
-- ret = -EINVAL;
-- goto junk;
-- }
--// DBG("after reversing: addr=%d, opcode=0x%X\n", xpd_num, pack->header.opcode);
-- return packet_process(xbus, dest_xpd_num, pack);
--junk:
-- xbus->ops->packet_free(xbus, pack);
-- return ret;
--}
--
--#define VERBOSE_DEBUG 1
--#define ERR_REPORT_LIMIT 20
--
--void dump_packet(const char *msg, xpacket_t *packet, bool print_dbg)
--{
-- xpp_opcode_t op = (byte)packet->content.opcode;
--
-- if(!print_dbg)
-- return;
-- DBG("%s: @0x%02X OP=0x%02X flags=0x%02X LEN=%d\n",
-- msg,
-- XPD_NUM(packet->content.addr),
-- op,
-- (byte)packet->flags,
-- (byte)packet->datalen);
--#if VERBOSE_DEBUG
-- {
-- int i;
-- byte *p = packet->content.raw;
--
-- for(i = 0; i < packet->datalen; i++) {
-- static int limiter = 0;
--
-- if(i >= sizeof(xpp_packet_r_t)) {
-- if(limiter < ERR_REPORT_LIMIT) {
-- ERR("dump_packet: length overflow i=%d > sizeof(xpp_packet_r_t)=%d\n",
-- i+1, sizeof(xpp_packet_r_t));
-- } else if(limiter == ERR_REPORT_LIMIT) {
-- ERR("dump_packet: error packet #%d... squelsh reports.\n", limiter);
-- }
-- limiter++;
-- break;
-- }
-- DBG(" %2d> %02X\n", i+1, p[i]);
-- }
-- }
--#endif
--}
--
--/*------------------------- Reply Handlers -------------------------*/
--
--#define HANDLER_DEF(name) \
-- int CALL_PROTO(name, xbus_t *xbus, int xpd_num, xpp_command_t *cmd, xpacket_t *reply)
--
--/*
--static HANDLER_DEF(notimp)
--{
-- NOTICE("xpp protocol error: command %s is not implemented yet\n", cmd->name);
-- return -EPROTO;
--}
--*/
--static HANDLER_DEF(DEV_DESC)
--{
-- byte type = PACKET_FIELD(reply, DEV_DESC, type) & 0x7; // 3 LSB's
-- byte rev = PACKET_FIELD(reply, DEV_DESC, rev);
-- xpp_line_t line_status = PACKET_FIELD(reply, DEV_DESC, line_status);
-- xpd_t *xpd = xpd_of(xbus, xpd_num);
--
-- if(xpd) {
-- NOTICE("Received DEV_DESC packet for an existing xpd %s of type %d\n",
-- xpd->xpdname, type);
-- return 0;
-- }
-- XBUS_COUNTER(xbus, DEV_DESC)++;
-- DBG("xpd=%d type=%d rev=%d line_status=0x%04X\n", xpd_num, type, rev, line_status);
-- switch(type) {
-- case XPD_TYPE_FXS:
-- break;
-- case XPD_TYPE_FXO:
-- break;
-- case XPD_TYPE_NOMODULE:
-- DBG("No module at address=%d\n", xpd_num);
-- return 0;
-- default:
-- NOTICE("DEV_DESC: unkown type=%d\n", type);
-- return -EPROTO;
-- }
-- if((xpd = xpd_new(xbus, xpd_num, type, rev)) == NULL) {
-- NOTICE("xpd_new failed\n");
-- }
-- xpp_check_hookstate(xpd, line_status);
-- return 0;
--}
--
--/**
-- * Handle signalling
-- */
--static HANDLER_DEF(SIG_CHANGED)
--{
-- xpd_t *xpd = xpd_of(xbus, xpd_num);
-- xpp_line_t sig_status = PACKET_FIELD(reply, SIG_CHANGED, sig_status);
--
-- if(!xpd) {
-- NOTICE("%s: received %s for non-existing xpd: %d\n", __FUNCTION__, cmd->name, xpd_num);
-- return -EPROTO;
-- }
-- if(xpd->direction == TO_PHONE) { /* Hook state changes */
-- DBG("%s (PHONE) sig_status=0x%04X\n", xpd->xpdname, sig_status);
-- xpp_check_hookstate(xpd, sig_status);
-- } else { /* TO_TRUNK - line ring changes */
-- unsigned long flags;
-- int i;
--
-- DBG("%s (TRUNK) sig_status=0x%04X\n", xpd->xpdname, sig_status);
-- spin_lock_irqsave(&xpd->lock, flags);
-- for(i = 0; i < xpd->channels; i++) {
-- if(IS_SET(sig_status, i)) {
-- xpd->ringing[i] = RINGS_NUM*2;
-- zt_hooksig(&xpd->chans[i], ZT_RXSIG_OFFHOOK);
-- } else {
-- zt_hooksig(&xpd->chans[i], ZT_RXSIG_ONHOOK);
-- xpd->ringing[i] = 0;
-- }
-- }
-- spin_unlock_irqrestore(&xpd->lock, flags);
-- }
-- return 0;
--}
--
--static HANDLER_DEF(SLIC_REPLY)
--{
-- slic_reply_t *info = &PACKET_FIELD(reply, SLIC_REPLY, info);
-- xpd_t *xpd = xpd_of(xbus, xpd_num);
-- unsigned long flags;
--
-- if(!xpd) {
-- NOTICE("%s: received %s for non-existing xpd: %d\n", __FUNCTION__, cmd->name, xpd_num);
-- return -EPROTO;
-- }
-- spin_lock_irqsave(&xpd->lock, flags);
-- DBG("SLIC_REPLY: xpd #%d %s reg_num=0x%X, dataL=0x%X dataH=0x%X\n",
-- xpd_num, (info->indirect)?"I":"D",
-- info->reg_num, info->data_low, info->data_high);
-- spin_unlock_irqrestore(&xpd->lock, flags);
-- return 0;
--}
--
--static HANDLER_DEF(PCM_READ)
--{
-- /* FIXME: work around temporary hardware bug */
-- xpd_num = 0;
--
-- xpp_line_t lines = PACKET_FIELD(reply, PCM_READ, lines);
-- const byte *pcm = PACKET_FIELD(reply, PCM_READ, pcm);
-- xpd_t *xpd = xpd_of(xbus, xpd_num);
-- volatile u_char *readchunk;
-- volatile u_char *r;
-- unsigned long flags;
-- int i;
--
-- if(!xpd) {
-- NOTICE("%s: received %s for non-existing xpd: %d\n", __FUNCTION__, cmd->name, xpd_num);
-- return -EPROTO;
-- }
-- // DBG("lines=0x%04X\n", lines);
--
-- if(!pcm_valid(xpd, reply)) {
-- 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;
-- }
--
-- /* Copy PCM and put each channel in its index */
-- for (i = 0; i < CHANNELS_PERXPD; 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;
-- }
--
-- XPD_COUNTER(xpd, PCM_READ)++;
-- XBUS_COUNTER(xpd->xbus, PCM_READ)++;
-- spin_unlock_irqrestore(&xpd->lock, flags);
-- if(xpd->id == 0)
-- xpp_tick(0);
-- return 0;
--}
--
--static HANDLER_DEF(SYNC_REPLY)
--{
-- xpd_t *xpd = xpd_of(xbus, xpd_num);
--
-- if(!xpd) {
-- NOTICE("%s: received %s for non-existing xpd: %d\n", __FUNCTION__, cmd->name, xpd_num);
-- return -EPROTO;
-- }
-- DBG("SYNC_REPLY: 0x%X\n", PACKET_FIELD(reply, SYNC_REPLY, mask));
-- return 0;
--}
--
--static HANDLER_DEF(LOOPBACK_XA)
--{
-- xpd_t *xpd = xpd_of(xbus, xpd_num);
--
-- if(!xpd) {
-- NOTICE("%s: received %s for non-existing xpd: %d\n", __FUNCTION__, cmd->name, xpd_num);
-- return -EPROTO;
-- }
-- dump_packet("LOOPBACK_XA", reply, print_dbg);
-- CALL_PROTO(LED, xpd->xbus, xpd, xpd->enabled_chans, LED_RED, 0); // FIXME: Find usage for extra LED
-- return 0;
--}
--
--static HANDLER_DEF(DIAG_FE)
--{
-- dump_packet("DIAG_FE", reply, print_dbg);
-- return 0;
--}
--
--static const xpp_packet_r_t FOR_SIZE_CALC; // Ugly hack, so we have something to sizeof()
--
--#define C_(op,var,txt) \
-- [ XPP_##op ] { \
-- .opcode = XPP_##op, \
-- .varsize = var, \
-- .header_size = sizeof(FOR_SIZE_CALC.cmd_##op), \
-- .name = #op, \
-- .desc = txt, \
-- .handler = PROTO_FUNC(op) \
-- }
--
--static xpp_command_t xpp_commands[] = {
-- /* OP V DESCRIPTION */
-- C_( DEV_DESC, 0, "Device description reply"),
-- C_( SIG_CHANGED, 0, "Signaling change (hookstate/ringing)"),
-- C_( SLIC_REPLY, 0, "Reply to slic state"),
-- C_( PCM_READ, 1, "Read PCM data"),
-- C_( SYNC_REPLY, 0, "SYNC_REPLY"),
-- C_( LOOPBACK_XA, 1, "LOOPBACK Reply"),
-- C_( DIAG_FE, 1, "DIAG FE Opcode"),
--};
--
--#undef C_
--
--static unsigned int xpp_max_opcode(void)
--{
-- return ARRAY_SIZE(xpp_commands);
--}
--
--static bool xpp_valid_opcode(xpp_opcode_t op)
--{
-- if(op <= 0 || op >= xpp_max_opcode())
-- return 0;
-- return xpp_commands[op].opcode != XPP_NOTIMP;
--}
--
--static xpp_command_t *xpp_command(xpp_opcode_t op)
--{
-- if(!xpp_valid_opcode(op))
-- return 0;
-- return &xpp_commands[op];
--}
--
--static bool xpp_valid_size(xpp_opcode_t op, xpacket_t *pack)
--{
-- xpp_command_t *cmd = xpp_command(op);
-- unsigned int hsize = cmd->header_size;
-- unsigned int size = pack->datalen;
-- int varsize = cmd->varsize;
--
-- // ERR("op=%d hsize=%d size=%d\n", op, hsize, size);
-- return (hsize == size) ||
-- (varsize && size <= sizeof(struct xpp_packet_r));
--}
--
--static bool pcm_valid(xpd_t *xpd, xpacket_t *reply)
--{
-- xpp_opcode_t op;
-- xpp_command_t *cmd;
-- xpp_line_t lines = PACKET_FIELD(reply, PCM_READ, lines);
-- int i;
-- int count = 0;
--
-- BUG_ON(!reply);
-- op = reply->content.opcode;
-- cmd = xpp_command(op);
-- if(!cmd) {
-- ERR("xpp: %s -- bad command op=0x%02X\n", __FUNCTION__, op);
-- return 0;
-- }
-- for (i = 0; i < CHANNELS_PERXPD; i++)
-- if(IS_SET(lines, i))
-- count++;
-- if(reply->datalen != (sizeof(xpp_line_t) + count * 8)) {
-- static int rate_limit = 0;
--
-- XPD_COUNTER(xpd, RECV_ERRORS)++;
-- if((rate_limit++ % 1000) <= 10) {
-- ERR("BAD PCM REPLY: reply->datalen=%d, count=%d\n", reply->datalen, count);
-- }
-- return 0;
-- }
-- return 1;
--}
--
--int packet_receive(xbus_t *xbus, xpacket_t *pack)
--{
-- int xpd_num = XPD_NUM(pack->content.addr);
--
-- if(!VALID_XPD_NUM(xpd_num)) {
-- dump_packet("martian packet", pack, print_dbg);
-- xbus->ops->packet_free(xbus, pack);
-- return -EPROTO;
-- }
-- if(xbus->sim[xpd_num].simulated) {
-- //dump_packet("packet_receive -> simulate", pack, print_dbg);
-- return simulate_xpd(xbus, xpd_num, pack);
-- } else {
-- //dump_packet("packet_receive -> process", pack, print_dbg);
-- return packet_process(xbus, xpd_num, pack);
-- }
--}
--
--static int packet_process(xbus_t *xbus, int xpd_num, xpacket_t *pack)
--{
-- xpp_opcode_t op;
-- xpp_command_t *cmd;
-- xpp_handler_t handler;
-- int ret = 0;
--
-- BUG_ON(!pack);
-- op = pack->content.opcode;
-- cmd = xpp_command(op);
-- /*-------- Validations -----------*/
-- if(!cmd) {
-- ERR("xpp: %s -- bad command op=0x%02X\n", __FUNCTION__, op);
-- dump_packet("packet_process -- bad command", pack, print_dbg);
-- ret = -EPROTO;
-- goto out;
-- }
-- if(!xpp_valid_size(op, pack)) {
-- ERR("xpp: %s: wrong size %d for op=0x%02X\n",
-- __FUNCTION__, pack->datalen, op);
-- dump_packet("packet_process -- wrong size", pack, print_dbg);
-- ret = -EPROTO;
-- goto out;
-- }
-- handler = cmd->handler;
-- BUG_ON(!handler);
-- XBUS_COUNTER(xbus, RX_BYTES) += pack->datalen;
-- handler(xbus, xpd_num, cmd, pack);
--out:
-- xbus->ops->packet_free(xbus, pack);
-- return ret;
--}
--
--
--void process_sim_queue(void *data)
--{
-- xbus_t *xbus = data;
-- xpacket_t *pack;
--
--// DBG("\n");
-- BUG_ON(!xbus);
-- while((pack = xbus_dequeue_packet(&xbus->sim_packet_queue)) != NULL) {
--// DBG("pack->addr=0x%X pack->opcode=0x%X\n", XPD_NUM(pack->addr), pack->header.opcode);
-- packet_receive(xbus, pack);
-- }
--}
--
--/**
-- * processes a packet recieved from the lower-level.
-- * @xbus the data bus
-- * @pack the handled packet
-- * @returns return status (0 for success).
-- *
-- * Should not be blocking.
-- * Has separate handling for PCM packets (direct write) and command packets (queued)
-- */
--
--EXPORT_SYMBOL(dump_packet);
--EXPORT_SYMBOL(packet_receive);
--EXPORT_SYMBOL(proc_xpd_slic_read);
--EXPORT_SYMBOL(proc_xpd_slic_write);
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/xpp_proto.h zaptel-xpp-LJNBCn_dist/xpp/xpp_proto.h
---- zaptel-1.2.6/xpp/xpp_proto.h 2006-02-15 04:24:18.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/xpp_proto.h 1970-01-01 02:00:00.000000000 +0200
-@@ -1,188 +0,0 @@
--#ifndef XPP_PROTO_H
--#define XPP_PROTO_H
--
--#include "xpd.h"
--#include "slic.h"
--#ifdef __KERNEL__
--#include <linux/list.h>
--#endif
--
--#define PCM_CHUNKSIZE (CHANNELS_PERXPD * ZT_MAX_CHUNKSIZE)
--
--typedef enum xpp_opcode {
-- XPP_NOTIMP = 0x00,
--//
-- XPP_DESC_REQ = 0x04,
-- XPP_DEV_DESC = 0x05,
--//
-- XPP_SIG_CHANGED = 0x06,
--//
-- XPP_SLIC_WRITE = 0x0F, // Write to SLIC
-- XPP_CHAN_ENABLE = 0x0F, // Write to SLIC
-- XPP_CHAN_POWER = 0x0F, // Write to SLIC
-- XPP_RING = 0x0F, // Write to SLIC
-- XPP_SETHOOK = 0x0F, // Write to SLIC
-- XPP_LED = 0x0F, // Write to SLIC
-- XPP_RELAY_OUT = 0x0F, // Write to SLIC
-- XPP_SLIC_INIT = 0x0F, // Write to SLIC
-- XPP_SLIC_QUERY = 0x0F, // Write to SLIC
--//
-- XPP_SLIC_REPLY = 0x10,
--//
-- XPP_PCM_WRITE = 0x11,
-- XPP_PCM_READ = 0x12,
--//
-- XPP_PCM_GEN = 0x13,
--//
-- XPP_SYNC_SOURCE = 0x19,
-- XPP_SYNC_REPLY = 0x1A,
--//
-- XPP_LOOPBACK_AX = 0x31,
-- XPP_LOOPBACK_XA = 0x32,
-- XPP_DIAG_FE = 0xFE,
--} xpp_opcode_t;
--
--/*------------------------- PROTOCOL COMMANDS ----------------------*/
--
--#define XPP_MAX_DATA 50
--
--typedef struct slic_data {
-- byte len;
-- byte data[40];
--} __attribute__((packed)) slic_data_t;
--
--#define PROTO_FUNC(name) xpp_proto_ ## name
--#define CALL_PROTO(name, ...) PROTO_FUNC(name)( __VA_ARGS__ )
--#define DECLARE_CMD(name, ...) \
-- int CALL_PROTO(name, xbus_t *xbus, xpd_t *xpd, ## __VA_ARGS__ )
--
--/* 0x04 */ DECLARE_CMD(DESC_REQ, int xpd_num);
--/* 0x0F */ DECLARE_CMD(CHAN_ENABLE, xpp_line_t lines, bool on);
--/* 0x0F */ DECLARE_CMD(CHAN_POWER, xpp_line_t lines, bool on);
--/* 0x0F */ DECLARE_CMD(RING, int pos, bool on);
--/* 0x0F */ DECLARE_CMD(SETHOOK, xpp_line_t hook_status);
--/* 0x0F */ DECLARE_CMD(LED, xpp_line_t lines, byte which, bool on);
--/* 0x0F */ DECLARE_CMD(RELAY_OUT, byte which, bool on);
--/* 0x0F */ DECLARE_CMD(SLIC_INIT);
--/* 0x0F */ DECLARE_CMD(SLIC_QUERY, int pos, byte reg_num);
--/* 0x11 */ DECLARE_CMD(PCM_WRITE, xpp_line_t hookstate, volatile byte *buf);
--/* 0x13 */ DECLARE_CMD(PCM_GEN, xpp_line_t lines, volatile byte *buf);
--/* 0x19 */ DECLARE_CMD(SYNC_SOURCE, bool setit, bool is_master);
--/* 0x31 */ DECLARE_CMD(LOOPBACK_AX, byte *data, unsigned int size);
--
--#define H_(op, ...) struct { \
-- __VA_ARGS__ \
-- } __attribute__((packed)) cmd_##op
--
--/*
-- * This struct must be packed exactly as the wire
-- * representation of the packet header after the
-- * XPD address byte
-- */
--typedef struct xpp_packet_r {
-- byte opcode;
-- xpp_addr_t addr;
-- union {
--
-- H_(NOTIMP);
-- H_(DESC_REQ);
-- H_(DEV_DESC,
-- byte rev; /* Revision number */
-- byte type;
-- xpp_line_t line_status; /* hook/ring status, depending on unit */
-- );
--
-- H_(SIG_CHANGED,
-- byte type; /* unused -- we have it from DEV_DESC */
-- xpp_line_t sig_status; /* channels: lsb=1, msb=8 */
-- xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */
-- );
--
-- H_(SLIC_INIT,
-- xpp_line_t lines;
-- slic_data_t slic_data;
-- );
-- H_(SLIC_WRITE,
-- slic_cmd_t slic_cmd;
-- );
-- H_(SLIC_REPLY, /* Get status of a single SLIC (for debugging) */
-- xpp_line_t lines;
-- slic_reply_t info;
-- );
--
-- H_(PCM_WRITE,
-- xpp_line_t lines; // Must be 0xFF
-- byte pcm[PCM_CHUNKSIZE];
-- );
-- H_(PCM_READ,
-- xpp_line_t lines; // Must be 0xFF
-- byte pcm[PCM_CHUNKSIZE];
-- );
--
-- H_(PCM_GEN,
-- xpp_line_t lines;
-- byte gen;
-- byte pcm_seq[ZT_CHUNKSIZE];
-- );
--
-- H_(SYNC_SOURCE,
-- byte mask;
-- );
-- H_(SYNC_REPLY,
-- byte mask;
-- );
--
-- H_(LOOPBACK_AX,
-- byte data[XPP_MAX_DATA]; // FIXME: what data size?
-- );
-- H_(LOOPBACK_XA,
-- byte data[XPP_MAX_DATA]; // FIXME: what data size?
-- );
-- H_(DIAG_FE);
-- unsigned char raw[0];
-- };
--} __attribute__((packed)) xpp_packet_r_t;
--#undef H_
--
--#ifdef __KERNEL__
--
--enum {
-- XPP_PACKET_FIREANDFORGET = 0x1,
--};
--
--/**
-- * The packet that will actually be sent on the wire.
-- *
-- * TODO: not a good medium-level abstrction
-- */
--struct xpp_packet {
-- struct xpp_packet_r content;
-- unsigned int flags;
-- size_t datalen;
-- struct list_head list;
--};
--
--#define DATA_LEN(p, name) \
-- sizeof(p->content.cmd_ ## name)
--
--#define PACKET_LEN(p) \
-- ((p)->datalen + sizeof(xpp_addr_t) + 1)
--
--#define PACKET_INIT(p, name) \
-- p->content.opcode = XPP_ ## name; \
-- p->datalen = DATA_LEN(p, name)
--
--#define PACKET_FIELD(p, name, field) \
-- p->content.cmd_ ## name.field
--
--void dump_packet(const char *msg, xpacket_t *packet, bool print_dbg);
--void enqueue_xmit(xbus_t *xbus, xpacket_t *pack);
--void process_sim_queue(void *xbus);
--int validate_reply(xpacket_t *reply);
--int packet_receive(xbus_t *xbus, xpacket_t *pack);
--int proc_xpd_slic_write(struct file *file, const char __user *buffer, unsigned long count, void *data);
--int proc_xpd_slic_read(char *page, char **start, off_t off, int count, int *eof, void *data);
--
--#endif
--
--#endif /* XPP_PROTO_H */
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/xpp_usb.c zaptel-xpp-LJNBCn_dist/xpp/xpp_usb.c
---- zaptel-1.2.6/xpp/xpp_usb.c 2006-04-03 10:08:13.000000000 +0300
-+++ zaptel-xpp-LJNBCn_dist/xpp/xpp_usb.c 2006-07-04 17:49:04.495340000 +0300
-@@ -1,6 +1,6 @@
- /*
- * Written by Oron Peled <oron at actcom.co.il>
-- * Copyright (C) 2004-2005, Xorcom
-+ * Copyright (C) 2004-2006, Xorcom
- *
- * All rights reserved.
- *
-@@ -30,6 +30,7 @@
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/errno.h>
-+#include <linux/interrupt.h>
- #include <linux/delay.h> /* for udelay */
- #include <linux/seq_file.h>
- #include <asm/uaccess.h>
-@@ -37,11 +38,16 @@
- #include <asm/timex.h>
- #include <linux/proc_fs.h>
- #include <linux/usb.h>
-+#include <version.h> /* For zaptel version */
- #include "xpd.h"
- #include "xproto.h"
--#include "xpp_zap.h"
-+#include "xbus-core.h"
-+#ifdef DEBUG
-+#include "card_fxs.h"
-+#include "card_fxo.h"
-+#endif
-
--static const char revision[] = "$Revision: 995 $";
-+static const char rcsid[] = "$Id: xpp_usb.c 1576 2006-07-04 14:49:04Z oron $";
-
- DEF_PARM(int, print_dbg, 0, "Print DBG statements"); /* must be before zap_debug.h */
-
-@@ -52,13 +58,11 @@
- #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
- # define URB_ASYNC_UNLINK 0
- #endif
--
- #define USBDEV_MAX 10
- /* Get a minor range for your devices from the usb maintainer */
- #define USB_SKEL_MINOR_BASE 192
-
- #ifdef CONFIG_PROC_FS
--#define PROC_XBUSES "xpp_usb"
- #define PROC_USBXPP_SUMMARY "xpp_usb"
- #endif
-
-@@ -70,8 +74,9 @@
- struct xusb_model_info;
-
- struct xusb_endpoint {
-- int epnum;
-- int max_size;
-+ int ep_addr;
-+ int max_size;
-+ usb_complete_t callback;
- };
-
- static int xusb_packet_send(xbus_t *xbus, xpacket_t *pack);
-@@ -110,18 +115,24 @@
-
- #define XUSB_COUNTER_MAX ARRAY_SIZE(xusb_counters)
-
-+#define MAX_PENDING_WRITES 100
-+
-+enum xusb_dir {
-+ XUSB_RECV = 0,
-+ XUSB_SEND = 1,
-+};
-+
- /*
- * USB XPP Bus (a USB Device)
- */
--struct xpp_usb_bus {
-+typedef struct xpp_usb_bus {
- xbus_t *xbus;
- struct usb_device *udev; /* save off the usb device pointer */
- struct usb_interface *interface; /* the interface for this device */
- unsigned char minor; /* the starting minor number for this device */
-
- struct xusb_model_info *model_info;
-- struct xusb_endpoint ep_in;
-- struct xusb_endpoint ep_out;
-+ struct xusb_endpoint endpoints[2]; /* RECV/SEND endpoints */
-
- struct urb *read_urb;
-
-@@ -129,12 +140,13 @@
-
- int present; /* if the device is not disconnected */
- int reading; /* is the read_urb reading (listening) */
-+ atomic_t pending_writes; /* submited but not out yet */
- struct semaphore sem; /* locks this structure */
- int counters[XUSB_COUNTER_MAX];
--};
-+} xusb_t;
-
- static spinlock_t xusb_lock = SPIN_LOCK_UNLOCKED;
--static struct xpp_usb_bus *xusb_array[USBDEV_MAX] = {};
-+static xusb_t *xusb_array[USBDEV_MAX] = {};
- static unsigned bus_count = 0;
-
-
-@@ -153,7 +165,7 @@
- static void xusb_write_bulk_callback (struct urb *urb, struct pt_regs *regs);
- #endif
- static void xpp_urb_delete(struct urb *urb);
--static struct urb *xpp_urb_new(struct xpp_usb_bus *dev, unsigned int ep_addr, size_t size, usb_complete_t urb_cb);
-+static struct urb *xpp_urb_new(xusb_t *dev, enum xusb_dir dir, size_t size);
- static void xpp_send_callback(struct urb *urb, struct pt_regs *regs);
- static void xpp_receive_callback(struct urb *urb, struct pt_regs *regs);
-
-@@ -208,42 +220,34 @@
- //DBG("Decremented packet_counter of bus %s (freed packet) to %d\n",
- // xbus->busname, atomic_read(&xbus->packet_counter));
- }
-+
- #endif
-
--static int xusb_packet_send(xbus_t *xbus, xpacket_t *pack)
--{
-- struct xpp_usb_bus *xusb = xbus->priv;
-- struct urb *urb;
-- int ret = 0;
-- size_t size;
-+#ifndef DEBUG
-
-- BUG_ON(!pack);
-- if(!xusb->present) {
-- NOTICE("tried to send packets to non-exitant USB device. Ignored\n");
-- goto error;
-- }
--#if SOFT_SIMULATOR
-- {
-- int toxpd = XPD_NUM(pack->content.addr);
-+#define packet_debug(m, x, p)
-
-- if (xbus->sim[toxpd].softloop_xpd) {
-- // "send" through loopback queue
-- //DBG("%s: ENQUEUE toxpd=%d, opcode=%X\n", xbus->busname, toxpd, pack->content.opcode);
-- XBUS_COUNTER(xbus, SOFTSIM_PACKETS)++;
-- xbus_enqueue_packet(xbus, &xbus->sim_packet_queue, pack);
-- ret = queue_work(xbus->sim_workqueue, &xbus->sim_work);
-- if(ret < 0) {
-- ERR("%s: queue_work failed with %d (ignoring)\n", __FUNCTION__, ret);
-- goto error;
-- }
-- }
-- return 0;
-- }
--#endif
-- size = min(PACKET_LEN(pack), (size_t)xusb->ep_out.max_size);
-- if(pack->content.opcode == XPROTO_NAME(GLOBAL,PCM_WRITE)) {
-- XUSB_COUNTER(xusb, PCM_WRITES)++;
-+#else
-+
-+static void packet_debug(const char msg[], xusb_t *xusb, xpacket_t *pack)
-+{
-+ char title[XBUS_DESCLEN];
-
-+ if(pack->content.opcode == XPROTO_NAME(GLOBAL,PCM_READ)) {
-+#ifdef DEBUG_PCM_TIMING
-+ /*
-+ * DEBUG: high-res timing of PCM_READ to PCM_WRITE
-+ */
-+ stamp_last_pcm_read = get_cycles();
-+#endif
-+#if 0
-+ // fill_beep((u_char *)&PACKET_FIELD(pack, PCM_READS, pcm), 2); // Debugging BEEP
-+ static int rate_limit;
-+ if((rate_limit++ % 1000) < 10)
-+ dump_packet("USB RECEIVE PCM", pack, print_dbg);
-+#endif
-+ return;
-+ } else if(pack->content.opcode == XPROTO_NAME(GLOBAL,PCM_WRITE)) {
- #ifdef DEBUG_PCM_TIMING
- /*
- * DEBUG: high-res timing of PCM_READ to PCM_WRITE
-@@ -253,50 +257,96 @@
- #endif
- #if 0
- static int rate_limit;
-- if((rate_limit++ % 1009) < 3) {
-+ if((rate_limit++ % 1000) < 10)
- dump_packet("USB SEND PCM", pack, print_dbg);
-- }
- #endif
-- } else {
-- dump_packet("USB_PACKET_SEND", pack, print_dbg);
-+ return;
-+ } else if(pack->content.opcode == XPROTO_NAME(FXS, SLIC_WRITE)) {
-+ slic_cmd_t *sc;
-+
-+ sc = &RPACKET_FIELD(pack, FXS, SLIC_WRITE, slic_cmd);
-+ if(sc->bytes == 2 && sc->content.direct.reg_num == 0x06 && sc->content.direct.read) /* ignore SLIC_QUERY */
-+ return;
-+ if(sc->bytes == 2 && sc->content.direct.reg_num == DAA_VBAT_REGISTER && sc->content.direct.read) /* ignore DAA_QUERY */
-+ return;
-+ } else if(pack->content.opcode == XPROTO_NAME(FXS, SLIC_REPLY)) {
-+ return;
-+ }
-+ snprintf(title, XBUS_DESCLEN, "%s: %s", msg, xusb->xbus->busname);
-+ dump_packet(title, pack, print_dbg);
-+}
-+#endif
-+
-+static int xusb_packet_send(xbus_t *xbus, xpacket_t *pack)
-+{
-+ xusb_t *xusb;
-+ struct urb *urb;
-+ int ret = 0;
-+ size_t size;
-+ struct xusb_endpoint *xusb_ep;
-+
-+ BUG_ON(!pack);
-+ BUG_ON(!xbus);
-+ xusb = xbus->priv;
-+ BUG_ON(!xusb);
-+ if(!xusb->present) {
-+ NOTICE("tried to send packets to non-exitant USB device. Ignored\n");
-+ ret = -ENODEV;
-+ goto out;
- }
-- urb = xpp_urb_new(xusb, xusb->ep_out.epnum, size, xpp_send_callback);
-+ size = PACKET_LEN(pack);
-+ xusb_ep = &xusb->endpoints[XUSB_SEND];
-+ urb = xpp_urb_new(xusb, XUSB_SEND, size);
- if (!urb) {
- ERR("No free urbs available\n");
- ret = -ENOMEM;
-- goto error;
-+ goto out;
- }
-+ packet_debug("USB_PACKET_SEND", xusb, pack);
-
- /* FIXME: FIXME: FIXME: we use copy+free until low-level drivers allocate memory themselves */
- memcpy(urb->transfer_buffer, &pack->content, size);
-- xbus->ops->packet_free(xbus, pack);
-
-- ret = usb_submit_urb(urb, GFP_KERNEL);
-+ ret = usb_submit_urb(urb, GFP_ATOMIC);
- if(ret < 0) {
-- ERR("%s: failed submit_urb\n", __FUNCTION__);
-- XUSB_COUNTER(xusb, TX_ERRORS)++;
-+ ERR("%s: failed submit_urb: %d\n", __FUNCTION__, ret);
- xpp_urb_delete(urb);
-- return -EBADF;
-+ ret = -EBADF;
-+ goto out;
- }
-- return 0;
--error:
-+ atomic_inc(&xusb->pending_writes);
-+ if(atomic_read(&xusb->pending_writes) > MAX_PENDING_WRITES) {
-+ static int rate_limit;
-+
-+ if((rate_limit++ % 1000) < 10)
-+ ERR("%s: %s: more than %d pending writes. Dropping.\n", __FUNCTION__, xbus->busname, MAX_PENDING_WRITES);
-+ ret = -ENODEV;
-+ }
-+ if(pack->content.opcode == XPROTO_NAME(GLOBAL,PCM_WRITE))
-+ XUSB_COUNTER(xusb, PCM_WRITES)++;
-+out:
-+ if(ret < 0)
-+ XUSB_COUNTER(xusb, TX_ERRORS)++;
- xbus->ops->packet_free(xbus, pack); // FIXME: eventually will be done in the urb callback
- return ret;
- }
-
- static void xpp_urb_delete(struct urb *urb)
- {
-+ BUG_ON(!urb);
- // DBG("%s: (%d) %p %X", __FUNCTION__, urb->transfer_buffer_length, urb->transfer_buffer, urb->transfer_dma);
- usb_buffer_free (urb->dev, urb->transfer_buffer_length,
- urb->transfer_buffer,
- urb->transfer_dma);
-- usb_free_urb (urb);
-+ usb_free_urb(urb);
- }
-
--static struct urb *xpp_urb_new(struct xpp_usb_bus *dev, unsigned int ep_addr, size_t size, usb_complete_t urb_cb)
--
-+static struct urb *xpp_urb_new(xusb_t *xusb, enum xusb_dir dir, size_t size)
- {
-- struct usb_device *udev = dev->udev;
-+ struct usb_device *udev = xusb->udev;
-+ struct xusb_endpoint *xusb_ep = &xusb->endpoints[dir];
-+ unsigned int ep_addr = xusb_ep->ep_addr;
-+ usb_complete_t urb_cb = xusb_ep->callback;
- struct urb *urb;
- unsigned char *buffer; /* the buffer to send data */
- unsigned int epnum = ep_addr & USB_ENDPOINT_NUMBER_MASK;
-@@ -304,6 +354,8 @@
- ? usb_rcvbulkpipe(udev, epnum)
- : usb_sndbulkpipe(udev, epnum);
-
-+ if(size > xusb_ep->max_size)
-+ return NULL;
- urb = usb_alloc_urb(0, GFP_ATOMIC);
- if (!urb) {
- err("No free urbs available");
-@@ -326,32 +378,36 @@
- usb_free_urb(urb);
- return NULL;
- }
-- usb_fill_bulk_urb(urb, udev, pipe, buffer, size, urb_cb, dev);
-+ usb_fill_bulk_urb(urb, udev, pipe, buffer, size, urb_cb, xusb);
- return urb;
- }
-
- /*------------------------- XPP USB Bus Handling -------------------*/
-
--static struct xusb_model_info {
-+#define XUSB_MODEL(ep_in,ep_out,type,str) \
-+ { \
-+ .in = { .ep_addr = (ep_in) }, \
-+ .out = { .ep_addr = (ep_out) }, \
-+ .bus_type = (type), \
-+ .desc = (str) \
-+ }
-+
-+static const struct xusb_model_info {
- const char *desc;
- struct xusb_endpoint in;
- struct xusb_endpoint out;
- xbus_type_t bus_type;
- } model_table[] = {
-- { .in = { .epnum = 0x86 }, .out = { .epnum = 0x2 }, .bus_type = FIRMWARE_LOOPBACK, .desc = "bulkloop.hex" },
-- { .in = { .epnum = 0x86 }, .out = { .epnum = 0x2 }, .bus_type = FIRMWARE_LOOPBACK, .desc = "FPGA_bulkloop.hex" },
-- { .in = { .epnum = 0x86 }, .out = { .epnum = 0x2 }, .bus_type = FIRMWARE_XPP, .desc = "FPGA_XPD.hex" },
-+ XUSB_MODEL(0x86, 0x02, FIRMWARE_LOOPBACK, "bulkloop.hex"),
-+ XUSB_MODEL(0x86, 0x02, FIRMWARE_LOOPBACK, "FPGA_bulkloop.hex"),
-+ XUSB_MODEL(0x86, 0x02, FIRMWARE_XPP, "FPGA_XPD.hex"),
- };
-
- /* table of devices that work with this driver */
--static struct usb_device_id xusb_table [] = {
-+static const struct usb_device_id xusb_table [] = {
- // { USB_DEVICE(0x04B4, 0x8613) }, // default of cypress
-- { USB_DEVICE(0x0547, 0x1002), .driver_info=(int)&model_table[0] }, // bulkloop.hex
--// { USB_DEVICE(0x04B4, 0x1004), .driver_info=(int)&model_table[1] }, // FPGA_bulkloop.hex
--// { USB_DEVICE(0x04B4, 0x1004), .driver_info=(int)&model_table[2] }, // FIXME: temporary test for Dima
-- { USB_DEVICE(0xE4E4, 0x2211), .driver_info=(int)&model_table[2] }, // FPGA_XPD.hex
-- //{ USB_DEVICE(0x0548, 0x1) },
-- //{ USB_DEVICE(0x062a, 0x0) },
-+ { USB_DEVICE(0xE4E4, 0x2211), .driver_info=(kernel_ulong_t)&model_table[2] }, // FPGA_XPD.hex
-+ { USB_DEVICE(0xE4E4, 0x1132), .driver_info=(kernel_ulong_t)&model_table[2] }, // FPGA_XPD.hex
- /* "Gadget Zero" firmware runs under Linux */
- //{ USB_DEVICE(0x0525, 0xa4a0) },
- { } /* Terminating entry */
-@@ -363,7 +419,7 @@
- /* usb specific object needed to register this driver with the usb subsystem */
- static struct usb_driver xusb_driver = {
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
-- .owner = THIS_MODULE,
-+ .owner = THIS_MODULE,
- #endif
- .name = "xpp_usb",
- .probe = xusb_probe,
-@@ -412,10 +468,12 @@
- * check out the endpoints
- * FIXME: Should be simplified (above 2.6.10) to use usb_dev->ep_in[0..16] and usb_dev->ep_out[0..16]
- */
--static int set_endpoints(struct xpp_usb_bus *xusb, struct usb_interface *interface, struct xusb_model_info *model_info)
-+static int set_endpoints(xusb_t *xusb, struct usb_interface *interface, struct xusb_model_info *model_info)
- {
- struct usb_host_interface *iface_desc;
- struct usb_endpoint_descriptor *endpoint;
-+ struct xusb_endpoint *xusb_ep;
-+ int ep_addr;
- int i;
-
- iface_desc = &interface->altsetting[0];
-@@ -425,37 +483,40 @@
-
- for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
- endpoint = &iface_desc->endpoint[i].desc;
-- int epnum = endpoint->bEndpointAddress;
-+ ep_addr = endpoint->bEndpointAddress;
-
- if(!BULK_ENDPOINT(endpoint)) {
- DBG("endpoint 0x%x is not bulk: mbAttributes=0x%X\n",
-- epnum, endpoint->bmAttributes);
-+ ep_addr, endpoint->bmAttributes);
- continue;
- }
-- if(epnum & USB_DIR_IN) { // Input
-- if(epnum == model_info->in.epnum) {
-+ if(usb_pipein(ep_addr)) { // Input
-+ if(ep_addr == model_info->in.ep_addr) {
- if(endpoint->wMaxPacketSize < sizeof(xpacket_raw_t)) {
-- ERR("USB input endpoint 0x%X support only wMaxPacketSize=%d (need USB-2)\n", epnum, endpoint->wMaxPacketSize);
-- break;
-+ NOTICE("USB input endpoint 0x%X support only wMaxPacketSize=%d (need USB-2)\n", ep_addr, endpoint->wMaxPacketSize);
- }
-- xusb->ep_in.epnum = epnum;
-- xusb->ep_in.max_size = endpoint->wMaxPacketSize;
-+ xusb_ep = &xusb->endpoints[XUSB_RECV];
-+ xusb_ep->ep_addr = ep_addr;
-+ xusb_ep->max_size = endpoint->wMaxPacketSize;
-+ xusb_ep->callback = xpp_receive_callback;
- }
-- } else { // Output
-- if(epnum == model_info->out.epnum) {
-+ } else { // Output
-+ if(ep_addr == model_info->out.ep_addr) {
- if(endpoint->wMaxPacketSize < sizeof(xpacket_raw_t)) {
-- ERR("USB output endpoint 0x%X support only wMaxPacketSize=%d (need USB-2)\n", epnum, endpoint->wMaxPacketSize);
-- break;
-+ NOTICE("USB output endpoint 0x%X support only wMaxPacketSize=%d (need USB-2)\n", ep_addr, endpoint->wMaxPacketSize);
- }
-- xusb->ep_out.epnum = epnum;
-- xusb->ep_out.max_size = endpoint->wMaxPacketSize;
-+ xusb_ep = &xusb->endpoints[XUSB_SEND];
-+ xusb_ep->ep_addr = ep_addr;
-+ xusb_ep->max_size = endpoint->wMaxPacketSize;
-+ xusb_ep->callback = xpp_send_callback;
- }
- }
- }
-- if (!xusb->ep_in.epnum || !xusb->ep_out.epnum) {
-+ if (!xusb->endpoints[XUSB_RECV].ep_addr || !xusb->endpoints[XUSB_SEND].ep_addr) {
- ERR("Couldn't find bulk-in or bulk-out endpoints\n");
- return 0;
- }
-+ DBG("in=0x%02X out=0x%02X\n", xusb->endpoints[XUSB_RECV].ep_addr, xusb->endpoints[XUSB_SEND].ep_addr);
- return 1;
- }
-
-@@ -468,10 +529,11 @@
- static int xusb_probe(struct usb_interface *interface, const struct usb_device_id *id)
- {
- struct usb_device *udev = interface_to_usbdev(interface);
-- struct xpp_usb_bus *xusb = NULL;
-+ xusb_t *xusb = NULL;
- struct xusb_model_info *model_info = (struct xusb_model_info*)id->driver_info;
-- struct proc_dir_entry *procsummary;
-- xbus_t *xbus;
-+ struct proc_dir_entry *procsummary = NULL;
-+ xbus_t *xbus = NULL;
-+ struct xusb_endpoint *xusb_ep;
- unsigned long flags;
- int retval = -ENOMEM;
- int i;
-@@ -490,15 +552,16 @@
- }
-
- /* allocate memory for our device state and initialize it */
-- xusb = kmalloc(sizeof(struct xpp_usb_bus), GFP_KERNEL);
-+ xusb = kmalloc(sizeof(xusb_t), GFP_KERNEL);
- if (xusb == NULL) {
- ERR("xpp_usb: Unable to allocate new xpp usb bus\n");
- retval = -ENOMEM;
- goto probe_failed;
- }
-- memset(xusb, 0, sizeof(struct xpp_usb_bus));
-+ memset(xusb, 0, sizeof(xusb_t));
-
- init_MUTEX (&xusb->sem);
-+ atomic_set(&xusb->pending_writes, 0);
- xusb->udev = udev;
- xusb->interface = interface;
- xusb->model_info = model_info;
-@@ -507,12 +570,14 @@
- retval = -ENODEV;
- goto probe_failed;
- }
-- xusb->read_urb = xpp_urb_new(xusb, xusb->ep_in.epnum, xusb->ep_in.max_size, xpp_receive_callback);
-+ xusb_ep = &xusb->endpoints[XUSB_RECV];
-+ xusb->read_urb = xpp_urb_new(xusb, XUSB_RECV, xusb_ep->max_size);
- if (!xusb->read_urb) {
- ERR("No free urbs available\n");
- retval = -ENOMEM;
- goto probe_failed;
- }
-+
- /* allow device read, write and ioctl */
- xusb->present = 1;
-
-@@ -521,7 +586,7 @@
- retval = usb_register_dev (interface, &xusb_class);
- if (retval) {
- /* something prevented us from registering this driver */
-- ERR ("Not able to get a minor for this device.");
-+ ERR ("Not able to get a minor for this device.\n");
- goto probe_failed;
- }
-
-@@ -531,33 +596,31 @@
- INFO ("USB XPP device now attached to minor %d\n", xusb->minor);
-
- /* Allocate high level structures */
-- xbus = xbus_new((model_info->bus_type == FIRMWARE_LOOPBACK) ? ~0 : 0);
-+ xbus = xbus_new(&xusb_ops);
- if(!xbus) {
- retval = -ENOMEM;
- goto probe_failed;
- }
-- xusb->xbus = xbus;
-- xbus->priv = xusb;
- xbus->bus_type = model_info->bus_type;
-+ xbus->max_packet_size = min(xusb->endpoints[XUSB_SEND].max_size , xusb->endpoints[XUSB_RECV].max_size);
-
- spin_lock_irqsave(&xusb_lock, flags);
- for(i = 0; i < USBDEV_MAX; i++) {
- if(xusb_array[i] == NULL)
- break;
- }
-+ spin_unlock_irqrestore(&xusb_lock, flags);
- if(i >= USBDEV_MAX) {
- ERR("xpp_usb: Too many XPP USB buses\n");
- retval = -ENOMEM;
- goto probe_failed;
- }
-- spin_unlock_irqrestore(&xusb_lock, flags);
- {
- char path[XBUS_DESCLEN];
-
- usb_make_path(udev, path, XBUS_DESCLEN); // May trunacte... ignore
- snprintf(xbus->busdesc, XBUS_DESCLEN, "%s", path);
- }
-- xbus->ops = &xusb_ops;
-
- DBG("GOT XPP USB BUS #%d: %s (type=%d)\n", i, xbus->busdesc, xbus->bus_type);
-
-@@ -568,20 +631,22 @@
- DBG("Creating proc entry " PROC_USBXPP_SUMMARY " in bus proc dir.\n");
- procsummary = create_proc_read_entry(PROC_USBXPP_SUMMARY, 0444, xbus->proc_xbus_dir,
- xusb_read_proc, xusb);
-- //xbus->procsummary = 1; // temporary: not 0, for the condition below
- if (!procsummary) {
- ERR("Failed to create proc read entry for xbus %s\n", xbus->busname);
- // FIXME: better error handling
- retval = -EIO;
- goto probe_failed;
- }
-+ procsummary->owner = THIS_MODULE;
- #endif
-+ bus_count++;
- retval = usb_submit_urb(xusb->read_urb, GFP_ATOMIC);
- if(retval < 0) {
- ERR("%s: Failed to submit the receive URB errno=%d\n", __FUNCTION__, retval);
- }
-- bus_count++;
-- xbus_activate(xusb->xbus);
-+ xusb->xbus = xbus;
-+ xbus->priv = xusb;
-+ xbus_activate(xbus);
- return retval;
- probe_failed:
- ERR("Failed to initialize xpp usb bus: %d\n", retval);
-@@ -593,6 +658,13 @@
- usb_deregister_dev(interface, &xusb_class);
- kfree(xusb);
- }
-+ if(xbus) {
-+ if(procsummary) {
-+ DBG("Remove proc_entry: " PROC_USBXPP_SUMMARY "\n");
-+ remove_proc_entry(PROC_USBXPP_SUMMARY, xbus->proc_xbus_dir);
-+ }
-+ xbus_disconnect(xbus); // Blocking until fully deactivated!
-+ }
- return retval;
- }
-
-@@ -609,7 +681,7 @@
- */
- static void xusb_disconnect(struct usb_interface *interface)
- {
-- struct xpp_usb_bus *xusb;
-+ xusb_t *xusb;
- xbus_t *xbus;
- int minor;
- int i;
-@@ -636,7 +708,7 @@
- }
- #endif
- xusb->present = 0;
-- xbus_deactivate(xbus); // Blocking until fully deactivated!
-+ xbus_disconnect(xbus); // Blocking until fully deactivated!
-
- down (&xusb->sem);
-
-@@ -645,6 +717,7 @@
- /* give back our minor */
- usb_deregister_dev (interface, &xusb_class);
-
-+ /* terminate an ongoing read */
- /* terminate an ongoing write */
- // FIXME: Does it really kill pending URB's?
-
-@@ -657,59 +730,71 @@
- kfree(xusb);
-
- up (&disconnect_sem);
-- INFO("XUSB #%d now disconnected", minor);
-+ INFO("XUSB #%d now disconnected\n", minor);
- }
-
- static void xpp_send_callback(struct urb *urb, struct pt_regs *regs)
- {
-- struct xpp_usb_bus *xusb = (struct xpp_usb_bus *)urb->context;
-+ xusb_t *xusb = (xusb_t *)urb->context;
- xbus_t *xbus = xusb->xbus;
-
- BUG_ON(!xbus);
-+ atomic_dec(&xusb->pending_writes);
- /* sync/async unlink faults aren't errors */
- if (urb->status && !(urb->status == -ENOENT || urb->status == -ECONNRESET)) {
- static int rate_limit;
- if((rate_limit++ % 1000) < 10)
-- DBG("nonzero read bulk status received: %d", urb->status);
-+ DBG("nonzero read bulk status received: %d\n", urb->status);
- XUSB_COUNTER(xusb, TX_ERRORS)++;
- }
-+ xpp_urb_delete(urb);
- if(!xusb->present) {
- ERR("A packet from non-connected device?\n");
- return;
- }
-- xpp_urb_delete(urb);
- /* allow device read, write and ioctl */
- XUSB_COUNTER(xusb, TX_PACKETS)++;
- }
-
- static void xpp_receive_callback(struct urb *urb, struct pt_regs *regs)
- {
-- struct xpp_usb_bus *xusb = (struct xpp_usb_bus *)urb->context;
-- xbus_t *xbus = xusb->xbus;
--
-- xpacket_t *pack;
-- size_t size;
-- int retval;
-+ xusb_t *xusb = (xusb_t *)urb->context;
-+ xbus_t *xbus;
-+ xpacket_t *pack;
-+ size_t size;
-+ int retval;
-+ bool do_resubmit = 1;
-+ bool is_inuse = 0;
-
-- BUG_ON(!xbus);
-+ BUG_ON(!xusb);
-+ xbus = xusb->xbus;
-+ if(!xbus) {
-+ NOTICE("spurious URB\n");
-+ return;
-+ }
- if (urb->status) {
-- /* sync/async unlink faults aren't errors */
-- if (!(urb->status == -EOVERFLOW || urb->status == -EMSGSIZE)) {
-- ERR("Dropped connection due to bad URB status: %d\n", urb->status);
-- return;
-- } else {
-- DBG("nonzero read bulk status received: %d\n", urb->status);
-- goto end;
-+ DBG("nonzero read bulk status received: %d\n", urb->status);
-+ XUSB_COUNTER(xusb, RX_ERRORS)++;
-+ /* Free old URB, allocate a fresh one */
-+ if(xusb->read_urb)
-+ xpp_urb_delete(xusb->read_urb);
-+ xusb->read_urb = xpp_urb_new(xusb, XUSB_RECV, xusb->endpoints[XUSB_RECV].max_size);
-+ if (!xusb->read_urb) {
-+ ERR("URB allocation failed\n");
-+ do_resubmit = 0;;
- }
-+ goto end;
- }
- if(!down_read_trylock(&xbus->in_use)) {
- ERR("%s: xbus is going down\n", __FUNCTION__);
-- return;
-+ do_resubmit = 0;
-+ goto end;
- }
-+ is_inuse = 1;
- if(!xusb->present) {
- ERR("A packet from non-connected device?\n");
-- up_read(&xbus->in_use);
-- return;
-+ do_resubmit = 0;
-+ goto end;
- }
- pack = xbus->ops->packet_new(xbus, GFP_ATOMIC);
- if(!pack) {
-@@ -723,42 +808,21 @@
- pack->datalen = size - sizeof(xpd_addr_t) - 1; // opcode size
- // DBG("datalen of new packet: %d\n", pack->datalen);
-
-- // Send UP
-- if(pack->content.opcode == XPROTO_NAME(GLOBAL,PCM_READ)) {
-+ packet_debug("USB_PACKET_RECEIVE", xusb, pack);
-+ XUSB_COUNTER(xusb, RX_PACKETS)++;
-+ if(pack->content.opcode == XPROTO_NAME(GLOBAL,PCM_READ))
- XUSB_COUNTER(xusb, PCM_READS)++;
--
--#ifdef DEBUG_PCM_TIMING
-- /*
-- * DEBUG: high-res timing of PCM_READ to PCM_WRITE
-- */
-- stamp_last_pcm_read = get_cycles();
--#endif
-- // fill_beep((u_char *)&PACKET_FIELD(pack, PCM_READS, pcm), 2); // Debugging BEEP
--#if 0
-- static int rate_limit;
-- if((rate_limit++ % 1000) == 0)
-- dump_packet("USB RECEIVE PCM", pack, print_dbg);
--#endif
-- } else if(pack->content.opcode == XPROTO_NAME(GLOBAL,PCM_WRITE)) { // FIRMWARE_LOOPBACK
--#if 0
-- static int rate_limit;
-- if((rate_limit++ % 1000) == 0)
-- dump_packet("USB RECEIVE (LOOPBACK) PCM", pack, print_dbg);
--#endif
-- } else {
-- char title[XBUS_DESCLEN];
--
-- snprintf(title, XBUS_DESCLEN, "USB_PACKET_RECEIVE callback (%s)", xbus->busname);
-- dump_packet(title, pack, print_dbg);
-- }
-+ // Send UP
- packet_receive(xbus, pack);
-- XUSB_COUNTER(xusb, RX_PACKETS)++;
- end:
-- up_read(&xbus->in_use);
-- retval = usb_submit_urb(urb, GFP_KERNEL);
-- if (retval < 0) {
-- ERR("failed re-submitting read urb, error %d\n", retval);
-- return;
-+ if(is_inuse)
-+ up_read(&xbus->in_use);
-+ if(do_resubmit) {
-+ retval = usb_submit_urb(urb, GFP_ATOMIC);
-+ if (retval < 0) {
-+ ERR("failed re-submitting read urb, error %d\n", retval);
-+ return;
-+ }
- }
- }
-
-@@ -768,14 +832,14 @@
- int __init xpp_usb_init(void)
- {
- int result;
-- //struct xpp_usb_bus *xusb;
-+ //xusb_t *xusb;
-
-- INFO("%s revision %s\n", THIS_MODULE->name, revision);
-+ INFO("%s revision %s\n", THIS_MODULE->name, ZAPTEL_VERSION);
-
- /* register this driver with the USB subsystem */
- result = usb_register(&xusb_driver);
- if (result) {
-- ERR("usb_register failed. Error number %d", result);
-+ ERR("usb_register failed. Error number %d\n", result);
- return result;
- }
- return 0;
-@@ -784,34 +848,7 @@
-
- void __exit xpp_usb_cleanup(void)
- {
-- int i, j;
--
- DBG("\n");
-- for(i = 0; i < USBDEV_MAX; i++) {
-- xbus_t *xbus;
--
-- if(xusb_array[i] == NULL)
-- continue;
-- xbus = xusb_array[i]->xbus;
-- if(!xbus) {
-- ERR("%s: missing xbus. Skipping\n", __FUNCTION__);
-- continue;
-- }
-- for(j = 0; j < MAX_XPDS; j++) {
-- xpd_t *xpd = xpd_of(xbus, j);
--
-- if(xpd) {
-- if(xpd->id != j) {
-- ERR("%s: BUG: xpd->id=%d != j=%d\n", __FUNCTION__, xpd->id, j);
-- continue;
-- }
--#if 0 // FIXME: retest after new driver start working
-- CALL_XMETHOD(CHAN_ENABLE, xbus, xpd, 0xFF, 0); // Disable all hardware channels
-- CALL_XMETHOD(LED, xbus, xpd, 0xFF, 1, 0); // FIXME: Show activated channels
--#endif
-- }
-- }
-- }
- /* deregister this driver with the USB subsystem */
- usb_deregister(&xusb_driver);
- }
-@@ -822,31 +859,31 @@
-
- static int xusb_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
- {
-- int len = 0;
-- unsigned long flags;
-+ int len = 0;
-+ unsigned long flags;
-+ int i;
- //unsigned long stamp = jiffies;
-- struct xpp_usb_bus *xusb = data;
-+ xusb_t *xusb = data;
-
- if(!xusb)
- goto out;
- // TODO: probably needs a per-xusb lock:
- spin_lock_irqsave(&xusb_lock, flags);
-- int i;
--
- len += sprintf(page + len, "device: %d, #altsettings: %d, minor: %d\n"
-- "\tBus Type:%d (Model Info: %s)\n"
-- "\tIn: 0x%02X - Size: %d\n"
-- "\tOut: 0x%02X - Size: %d\n",
-+ "\tModel Info: Bus Type=%d (%s)\n"
-+ "\tIn: 0x%02X - Size: %d)\n"
-+ "\tOut: 0x%02X - Size: %d)\n",
- xusb->udev->devnum,
- xusb->interface->num_altsetting,
- xusb->minor,
- xusb->model_info->bus_type,
- xusb->model_info->desc,
-- xusb->ep_in.epnum,
-- xusb->ep_in.max_size,
-- xusb->ep_out.epnum,
-- xusb->ep_out.max_size
-+ xusb->endpoints[XUSB_RECV].ep_addr,
-+ xusb->endpoints[XUSB_RECV].max_size,
-+ xusb->endpoints[XUSB_SEND].ep_addr,
-+ xusb->endpoints[XUSB_SEND].max_size
- );
-+ len += sprintf(page + len, "\npending_writes=%d\n", atomic_read(&xusb->pending_writes));
- #ifdef DEBUG_PCM_TIMING
- len += sprintf(page + len, "\nstamp_last_pcm_read=%lld accumulate_diff=%lld\n", stamp_last_pcm_read, accumulate_diff);
- #endif
-@@ -878,7 +915,7 @@
- MODULE_DESCRIPTION("XPP USB Driver");
- MODULE_AUTHOR("Oron Peled <oron at actcom.co.il>");
- MODULE_LICENSE("GPL");
--MODULE_VERSION("$Id: xpp_usb.c 995 2006-04-03 07:08:13Z tzafrir $");
-+MODULE_VERSION(ZAPTEL_VERSION);
-
- module_init(xpp_usb_init);
- module_exit(xpp_usb_cleanup);
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/xpp_zap.c zaptel-xpp-LJNBCn_dist/xpp/xpp_zap.c
---- zaptel-1.2.6/xpp/xpp_zap.c 2006-04-03 10:08:13.000000000 +0300
-+++ zaptel-xpp-LJNBCn_dist/xpp/xpp_zap.c 2006-07-10 23:59:46.263727324 +0300
-@@ -33,245 +33,64 @@
- #include <linux/kernel.h>
- #include <linux/errno.h>
- #include <linux/module.h>
-+#include <linux/device.h>
- #include <linux/init.h>
- #include <linux/delay.h> /* for udelay */
- #include <linux/workqueue.h>
- #include <linux/proc_fs.h>
- #include <zaptel.h>
-+#include <version.h> /* For zaptel version */
-+#include "xbus-core.h"
- #include "xproto.h"
- #include "xpp_zap.h"
-
--static char revision[] = "$Revision: 995 $";
-+static const char rcsid[] = "$Id: xpp_zap.c 1588 2006-07-06 11:10:00Z tzafrir $";
-
- #ifdef CONFIG_PROC_FS
--struct proc_dir_entry *xpp_procdir = NULL;
-+struct proc_dir_entry *xpp_proc_toplevel = NULL;
- #define PROC_DIR "xpp"
--#define PROC_XBUSES "xbuses"
- #define PROC_SYNC "sync"
--#define PROC_XBUS_SUMMARY "summary"
- #define PROC_XPD_ZTREGISTER "zt_registration"
- #define PROC_XPD_SUMMARY "summary"
- #endif
-
--#undef WITH_RBS
--//#define WITH_RBS
--
- #define XPP_CTL_MAJOR 42
--#define MAX_BUSES 16
- #define MAX_QUEUE_LEN 10000
--#define LED_BLINK_PERIOD (HZ/8)
- #define SAMPLE_TICKS 10000
-+#define DELAY_UNTIL_DIALTONE 3000
-
--static spinlock_t xbuses_lock = SPIN_LOCK_UNLOCKED;
--static xbus_t *xbuses_array[MAX_BUSES] = {};
--static int bus_count = 0;
- static struct timer_list xpp_timer;
--xpd_t *sync_master = NULL; // Start with host based sync
-+static xpd_t *sync_master = NULL; // Start with host based sync
- static unsigned int xpp_timer_count = 0;
- static unsigned int xpp_last_jiffies = 0;
--struct workqueue_struct *xpp_worker = NULL;
--
--static LIST_HEAD(xpd_list);
-
- DEF_PARM(int, print_dbg, 0, "Print DBG statements");
- DEF_PARM(int, max_queue_len, MAX_QUEUE_LEN, "Maximum Queue Length.");
--DEF_PARM(int, xbus_err_disable_bus, 1000, "Number of errors needed to disable bus");
--DEF_PARM(int, ignore_xpds, 0, "a bitmask of xpd numbers to ignore");
--#ifdef SOFT_SIMULATOR
--DEF_PARM(ulong, softloop_xpds, 0, "a bitmask of software xpd numbers");
--#endif
--DEF_PARM(ulong, pcm_gen, 0, "a bitmask of line numbers for hardware tone generator");
--
--DEF_ARRAY(ulong, enabled_channels, MAX_XPDS, ~0, "Enabled channels for each xpd");
-+DEF_PARM(bool, have_sync_bus, 0, "True if all Astribank(TM) devices are connected via a sync-cable");
-+DEF_PARM(bool, zap_autoreg, 1, "Register spans automatically (1) or not (0)");
-
- #include "zap_debug.h"
-+#ifdef XPP_EC_CHUNK
-+#include "supress/ec_xpp.h"
-+#endif
-
-
--static int xpd_zaptel_register(xpd_t *xpd);
--static int xpd_zaptel_unregister(xpd_t *xpd);
--static void xbus_remove(xbus_t *xbus);
--static void xpd_blink_leds(xpd_t *xpd);
-+static int zaptel_register_xpd(xpd_t *xpd);
-+static int zaptel_unregister_xpd(xpd_t *xpd);
- static void xpp_ring_generate(xpd_t *xpd);
- static void xpp_transmitprep(xpd_t *xpd);
- static void xpp_receiveprep(xpd_t *xpd);
- static int xpd_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data);
- static int proc_xpd_ztregister_read(char *page, char **start, off_t off, int count, int *eof, void *data);
- static int proc_xpd_ztregister_write(struct file *file, const char __user *buffer, unsigned long count, void *data);
--xbus_t *xbus_of(int xbus_num);
--static void xpd_cleanup(xpd_t *xpd);
--static void xpd_card_disable(xpd_t *xpd);
--static void update_xpd_status(xpd_t *xpd, int alarm_flag);
--
--#define SPAN_REGISTERED(xpd) ((xpd)->span.flags & ZT_FLAG_REGISTERED)
--
--/*------------------------- Packet Handling ------------------------*/
--static kmem_cache_t *packet_cache = NULL;
--static atomic_t xpacket_count = ATOMIC_INIT(0);
--
--void card_detected(void *data)
--{
-- struct card_desc_struct *card_desc = (struct card_desc_struct *)data;
-- xbus_t *xbus;
-- xpd_t *xpd;
-- int xpd_num;
-- byte type;
-- byte rev;
-- const xops_t *xops;
-- const xproto_table_t *proto_table;
--
-- BUG_ON(!card_desc);
-- BUG_ON(card_desc->magic != CARD_DESC_MAGIC);
-- xbus = card_desc->xbus;
-- xpd_num = card_desc->xpd_num;
-- type = card_desc->type;
-- rev = card_desc->rev;
-- BUG_ON(!xbus);
-- DBG("%s: xpd_num=%d type=%d rev=%d\n", xbus->busname, xpd_num, type, rev);
-- xpd = xpd_of(xbus, xpd_num);
-- if(xpd) {
-- if(type == XPD_TYPE(NOMODULE)) {
-- NOTICE("%s: xpd #%d: removed\n", __FUNCTION__, xpd_num);
-- xpd_card_disable(xpd);
-- goto out;
-- }
-- NOTICE("%s: xpd #%d: already exists\n", __FUNCTION__, xpd_num);
-- goto out;
-- }
-- if(type == XPD_TYPE(NOMODULE)) {
-- DBG("No module at address=%d\n", xpd_num);
-- goto out;
-- }
-- proto_table = get_xproto_table(type);
-- if(!proto_table) {
-- NOTICE("%s: xpd #%d: missing protocol table for type=%d. Ignored.\n", __FUNCTION__, xpd_num, type);
-- goto out;
-- }
-- xops = &proto_table->xops;
-- BUG_ON(!xops);
-- xpd = xops->card_new(xbus, xpd_num, proto_table, rev);
-- if(!xpd) {
-- NOTICE("card_new(%s,%d,%d,%d) failed. Ignored.\n", xbus->busname, xpd_num, proto_table->type, rev);
-- goto out;
-- }
--#if 0
-- /*
-- * Is it nessessary?
-- */
-- if(xpd->type == XPD_TYPE_FXO) {
-- int i;
--
-- for(i = 0; i < xpd->channels; i++) {
-- zt_hooksig(&xpd->chans[i], ZT_RXSIG_ONHOOK);
-- }
-- }
--#endif
--#ifdef CONFIG_PROC_FS
-- DBG("Creating xpd proc directory for %s/%s\n", xbus->busname, xpd->xpdname);
-- xpd->proc_xpd_dir = proc_mkdir(xpd->xpdname, xbus->proc_xbus_dir);
-- if(!xpd->proc_xpd_dir) {
-- ERR("Failed to create proc directory for %s/%s\n", xbus->busname, xpd->xpdname);
-- goto err;
-- }
-- xpd->proc_xpd_summary = create_proc_read_entry(PROC_XPD_SUMMARY, 0444, xpd->proc_xpd_dir,
-- xpd_read_proc, xpd);
-- if(!xpd->proc_xpd_summary) {
-- ERR("Failed to create proc '%s' for %s/%s\n", PROC_XPD_SUMMARY, xbus->busname, xpd->xpdname);
-- goto err;
-- }
-- xpd->proc_xpd_ztregister = create_proc_entry(PROC_XPD_ZTREGISTER, 0644, xpd->proc_xpd_dir);
-- if (!xpd->proc_xpd_ztregister) {
-- ERR("Failed to create proc '%s' for %s/%s\n", PROC_XPD_ZTREGISTER, xbus->busname, xpd->xpdname);
-- goto err;
-- }
-- xpd->proc_xpd_ztregister->data = xpd;
-- xpd->proc_xpd_ztregister->read_proc = proc_xpd_ztregister_read;
-- xpd->proc_xpd_ztregister->write_proc = proc_xpd_ztregister_write;
--#endif
-- list_add(&xpd->xpd_list, &xpd_list);
-- xbus->xpds[xpd->id] = xpd;
-- xbus->num_xpds++;
-- CALL_XMETHOD(card_init, xbus, xpd);
-- // Turn off all channels
-- CALL_XMETHOD(CHAN_ENABLE, xbus, xpd, 0xFF, 0);
--// CALL_XMETHOD(LED, xbus, xpd, 0xFF, LED_RED, 0); // FIXME: Show activated channels
-- // Turn on enabled channels
-- CALL_XMETHOD(CHAN_ENABLE, xbus, xpd, xpd->enabled_chans, 1);
-- atomic_set(&xpd->card_present, 1);
-- xpd_zaptel_register(xpd);
--#if 0
-- // FIXME: not yet initialized...
-- xpp_check_hookstate(xpd, line_status);
--#endif
--
--out:
-- memset(card_desc, 0, sizeof(struct card_desc_struct));
-- kfree(card_desc);
-- return;
--err:
-- xpd_cleanup(xpd);
-- goto out;
--}
--
--/**
-- * Allocates a new XPP packet.
-- * @xbus The XPP bus in which the packet will flow (for counters
-- * maintenance)
-- * @flags Flags for kernel memory allocation.
-- * @returns A pointer to the new packet, or NULL in case of failure.
-- *
-- *
-- * Packet allocation/deallocation:
-- * Sent packets:
-- * - Allocated by protocol commands
-- * - Deallocated by xmus_xmitter
-- * Receive packets:
-- * - Allocated/deallocated by xbus_xmiter
-- */
--xpacket_t *softloop_packet_new(xbus_t *xbus, int flags)
--{
-- xpacket_t *pack;
--
-- /* To avoid races we increament counter in advance and decrement it later
-- * in case of failure */
-- atomic_inc(&xbus->packet_counter);
-- //DBG("Incremented packet_counter of bus %s (new packet) to %d\n",
-- // xbus->busname, atomic_read(&xbus->packet_counter));
-- pack = kmem_cache_alloc(packet_cache, flags);
-- if (pack) {
-- memset(pack, 0, sizeof(xpacket_t));
-- atomic_inc(&xpacket_count);
-- } else {
-- atomic_dec(&xbus->packet_counter);
-- //DBG("Decremented packet_counter of bus %s (failed new packet) to %d\n",
-- // xbus->busname, atomic_read(&xbus->packet_counter));
-- }
-- return pack;
--}
--
--void softloop_packet_free(xbus_t *xbus, xpacket_t *p)
--{
-- kmem_cache_free(packet_cache, p);
-- atomic_dec(&xpacket_count);
-- atomic_dec(&xbus->packet_counter);
-- //DBG("Decremented packet_counter of bus %s (freed packet) to %d\n",
-- // xbus->busname, atomic_read(&xbus->packet_counter));
--}
--
--int call_proto(xbus_t *xbus, xpacket_t *pack)
--{
-- const xproto_entry_t *xe;
-- int toxpd = XPD_NUM(pack->content.addr);
-- xpd_t *xpd = xpd_of(xbus, toxpd);
--
-- xe = find_xproto_entry(xpd, pack->content.opcode);
-- return 0;
--}
-+static void xpd_free(xpd_t *xpd);
-
- static void external_sync(xpd_t *the_xpd)
- {
- int i, j;
-
-- DBG("SYNC %s\n", (the_xpd) ? "EXTERNAL" : "HOST");
-+ DBG("SYNC %s (%s sync cable)\n", (the_xpd)?"Astribanks":"HOST", (have_sync_bus)?"with":"without");
-+ // Shut all down
- for(i = 0; i < MAX_BUSES; i++) {
- xbus_t *xbus = xbus_of(i);
- if(!xbus)
-@@ -279,21 +98,26 @@
- if (!xbus->hardware_exists)
- continue;
- for(j = 0; j < MAX_XPDS; j++) {
-- xpd_t *xpd = xbus->xpds[j];
-- if(xpd)
-- CALL_XMETHOD(SYNC_SOURCE, xbus, xpd, 1, (the_xpd != NULL));
-+ xpd_t *xpd = xpd_of(xbus, j);
-+ if(xpd) {
-+ CALL_XMETHOD(SYNC_SOURCE, xbus, xpd, 1, 0);
-+ }
- }
- }
-+ if(the_xpd)
-+ CALL_XMETHOD(SYNC_SOURCE, the_xpd->xbus, the_xpd, 1, 1);
- }
-
--void set_sync_master(xpd_t *xpd)
-+void sync_master_is(xpd_t *xpd)
- {
-- DBG("SYNC: %s => %s\n",
-+ DBG("SYNC MASTER CHANGED: %s => %s\n",
- (sync_master) ? sync_master->xpdname : "HOST",
-- (xpd) ? xpd->xpdname : "HOST"
-- );
-+ (xpd) ? xpd->xpdname : "HOST");
- sync_master = xpd;
-- if(!sync_master) {
-+ if(xpd) { // XPD
-+ del_timer_sync(&xpp_timer);
-+ xpp_tick((unsigned long)xpd);
-+ } else { // HOST
- external_sync(NULL);
- if(!timer_pending(&xpp_timer)) {
- xpp_timer.function = xpp_tick;
-@@ -301,10 +125,6 @@
- xpp_timer.expires = jiffies + 1; /* Must be 1KHz rate */
- add_timer(&xpp_timer);
- }
-- } else {
-- del_timer_sync(&xpp_timer);
-- external_sync(xpd);
-- xpp_tick((unsigned long)xpd);
- }
- }
-
-@@ -337,43 +157,49 @@
- continue;
- if (!xbus->hardware_exists)
- continue;
-+ if(!down_read_trylock(&xbus->in_use)) {
-+ DBG("Dropped packet. %s is in_use\n", xbus->busname);
-+ continue;
-+ }
- #if 0
- if(xbus->open_counter == 0)
- continue; // optimize, but zttool loopback won't function
- #endif
- for(j = 0; j < MAX_XPDS; j++) {
-- xpd_t *xpd = xbus->xpds[j];
-+ xpd_t *xpd = xpd_of(xbus, j);
-
- if(!xpd)
- continue;
-- if(!atomic_read(&xpd->card_present))
-+ if(!xpd->card_present)
- continue;
- xpd->timer_count++;
- CALL_XMETHOD(card_tick, xbus, xpd);
- if(!SPAN_REGISTERED(xpd))
- continue;
-- xpd_blink_leds(xpd);
- if(xpd->direction == TO_PSTN)
- xpp_ring_generate(xpd);
- xpp_transmitprep(xpd);
- xpp_receiveprep(xpd);
- }
-+ up_read(&xbus->in_use);
- }
- }
-
- #if HZ != 1000
--#warning This module will not be usable since the kernel HZ setting is not 1000 ticks per second.
-+#warning "xpp_timer must be sampled EXACTLY 1000/per second"
- #endif
-
--static void xpd_cleanup(xpd_t *xpd)
-+static void xpd_free(xpd_t *xpd)
- {
- xbus_t *xbus = NULL;
-
- if(!xpd)
- return;
- xbus = xpd->xbus;
-- xpd_card_disable(xpd);
-+ if(!xbus)
-+ return;
- DBG("%s/%s\n", xbus->busname, xpd->xpdname);
-+ xbus_unregister_xpd(xbus, xpd);
- #ifdef CONFIG_PROC_FS
- if(xpd->proc_xpd_dir) {
- if(xpd->proc_xpd_summary) {
-@@ -391,109 +217,149 @@
- xpd->proc_xpd_dir = NULL;
- }
- #endif
-+ if(xpd->writechunk)
-+ kfree((void *)xpd->writechunk);
-+ xpd->writechunk = NULL;
-+ if(xpd->xproto)
-+ xproto_put(xpd->xproto);
-+ xpd->xproto = NULL;
-+ kfree(xpd);
- }
-
--void init_xbus_packet_queue(packet_queue_t *q, const char name[])
--{
-- INIT_LIST_HEAD(&q->head);
-- spin_lock_init(&q->lock);
-- q->count = 0;
-- q->worst_count = 0;
-- q->overflows = 0;
-- snprintf(q->qname, XPD_NAMELEN, "%s", name);
--}
-
--#if 0
--/*
-- * Assume the queue is locked
-- */
--void __dump_packet_queue(const char *msg, packet_queue_t *q)
--{
-- xpacket_t *tmp;
-+/*------------------------- XPD Management -------------------------*/
-
-- list_for_each_entry(tmp, &q->head, list) {
-- dump_packet(msg, tmp);
-- }
--}
--#endif
-+#define REV(x,y) (10 * (x) + (y))
-+static byte good_revs[] = {
-+ REV(1,9),
-+ REV(2,0),
-+};
-+#undef REV
-
--void drain_xbus_packet_queue(xbus_t *xbus, packet_queue_t *q)
-+static bool good_rev(byte rev)
- {
-- unsigned long flags;
-- xpacket_t *pack;
-- xpacket_t *next;
-+ int i;
-
-- spin_lock_irqsave(&q->lock, flags);
-- DBG("queue=%s count=%d\n", q->qname, q->count);
-- DBG(" total packets count=%d\n", atomic_read(&xpacket_count));
-- list_for_each_entry_safe(pack, next, &q->head, list) {
-- list_del(&pack->list);
-- q->count--;
-- xbus->ops->packet_free(xbus, pack);
-- }
-- if(q->count != 0)
-- ERR("drain_xbus_packet_queue: queue %s still has %d packets\n",
-- q->qname, q->count);
-- spin_unlock_irqrestore(&q->lock, flags);
-+ for(i = 0; i < ARRAY_SIZE(good_revs); i++) {
-+ if(good_revs[i] == rev)
-+ return 1;
-+ }
-+ return 0;
- }
-
--void xbus_enqueue_packet(xbus_t *xbus, packet_queue_t *q, xpacket_t *pack)
-+/*
-+ * Synchronous part of XPD detection.
-+ * Called from xbus_poll()
-+ */
-+void card_detected(struct card_desc_struct *card_desc)
- {
-- unsigned long flags;
--
-- spin_lock_irqsave(&q->lock, flags);
-+ xbus_t *xbus;
-+ xpd_t *xpd = NULL;
-+ int xpd_num;
-+ byte type;
-+ byte rev;
-+ const xops_t *xops;
-+ const xproto_table_t *proto_table;
-
-- if(q->count >= max_queue_len) {
-- static unsigned long last_notice = 0; // rate limit
-
-- if((jiffies - last_notice) < HZ) {
-- NOTICE("xbus_enqueue_packet: dropping packet (queue len = %d, max=%d)\n",
-- q->count, max_queue_len);
-- last_notice = jiffies;
-+ BUG_ON(!card_desc);
-+ BUG_ON(card_desc->magic != CARD_DESC_MAGIC);
-+ xbus = card_desc->xbus;
-+ xpd_num = xpd_addr2num(&card_desc->xpd_addr);
-+ type = card_desc->type;
-+ rev = card_desc->rev;
-+ BUG_ON(!xbus);
-+ if(!good_rev(rev)) {
-+ NOTICE("%s: New XPD #%d (%d-%d) type=%d has bad firmware revision %d.%d\n", xbus->busname,
-+ xpd_num, card_desc->xpd_addr.unit, card_desc->xpd_addr.subunit,
-+ type, rev / 10, rev % 10);
-+ goto err;
-+ }
-+ INFO("%s: New XPD #%d (%d-%d) type=%d Revision %d.%d\n", xbus->busname,
-+ xpd_num, card_desc->xpd_addr.unit, card_desc->xpd_addr.subunit,
-+ type, rev / 10, rev % 10);
-+ xpd = xpd_of(xbus, xpd_num);
-+ if(xpd) {
-+ if(type == XPD_TYPE_NOMODULE) {
-+ NOTICE("%s: xpd #%d: removed\n", __FUNCTION__, xpd_num);
-+ BUG();
-+ goto out;
- }
-- q->overflows++;
-- xbus->ops->packet_free(xbus, pack);
-+ NOTICE("%s: xpd #%d: already exists\n", __FUNCTION__, xpd_num);
- goto out;
- }
-- list_add_tail(&pack->list, &q->head);
-- q->count++;
--
-- if(q->count > q->worst_count)
-- q->worst_count = q->count;
--
-- if(q->count < max_queue_len/100 && q->worst_count > q->count) // Decay worst_count
-- q->worst_count--;
--
-- // dump_packet("ENQUEUED", pack, print_dbg);
--out:
-- spin_unlock_irqrestore(&q->lock, flags);
--}
--
--xpacket_t *xbus_dequeue_packet(packet_queue_t *q)
--{
-- unsigned long flags;
-- struct list_head *p;
-- xpacket_t *pack = NULL;
--
-- spin_lock_irqsave(&q->lock, flags);
--
-- if(list_empty(&q->head)) {
-- // DBG("LIST EMPTY (count=%d)\n", q->count);
-+ if(type == XPD_TYPE_NOMODULE) {
-+ DBG("No module at address=%d\n", xpd_num);
-+ goto out;
-+ }
-+ proto_table = xproto_get(type);
-+ if(!proto_table) {
-+ NOTICE("%s: xpd #%d: missing protocol table for type=%d. Ignored.\n", __FUNCTION__, xpd_num, type);
- goto out;
- }
-- p = q->head.next;
-- list_del(p);
-- q->count--;
-- pack = list_entry(p, xpacket_t, list);
-- // dump_packet("DEQUEUED", pack, print_dbg);
-+ xops = &proto_table->xops;
-+ BUG_ON(!xops);
-+ xpd = xops->card_new(xbus, xpd_num, proto_table, rev);
-+ if(!xpd) {
-+ NOTICE("card_new(%s,%d,%d,%d) failed. Ignored.\n", xbus->busname, xpd_num, proto_table->type, rev);
-+ goto err;
-+ }
-+ xpd->addr = card_desc->xpd_addr;
-+
-+ /* For USB-1 disable some channels */
-+ if(xbus->max_packet_size < RPACKET_SIZE(GLOBAL, PCM_WRITE)) {
-+ xpp_line_t no_pcm;
-+
-+ no_pcm = 0x7F | xpd->digital_outputs | xpd->digital_inputs;
-+ xpd->no_pcm = no_pcm;
-+ NOTICE("%s: max packet size = %d, disabling some PCM channels. no_pcm=0x%04X\n",
-+ xbus->busname, xbus->max_packet_size, xpd->no_pcm);
-+ }
-+#ifdef CONFIG_PROC_FS
-+ DBG("Creating xpd proc directory for %s/%s\n", xbus->busname, xpd->xpdname);
-+ xpd->proc_xpd_dir = proc_mkdir(xpd->xpdname, xbus->proc_xbus_dir);
-+ if(!xpd->proc_xpd_dir) {
-+ ERR("Failed to create proc directory for %s/%s\n", xbus->busname, xpd->xpdname);
-+ goto err;
-+ }
-+ xpd->proc_xpd_summary = create_proc_read_entry(PROC_XPD_SUMMARY, 0444, xpd->proc_xpd_dir,
-+ xpd_read_proc, xpd);
-+ if(!xpd->proc_xpd_summary) {
-+ ERR("Failed to create proc '%s' for %s/%s\n", PROC_XPD_SUMMARY, xbus->busname, xpd->xpdname);
-+ goto err;
-+ }
-+ xpd->proc_xpd_summary->owner = THIS_MODULE;
-+ xpd->proc_xpd_ztregister = create_proc_entry(PROC_XPD_ZTREGISTER, 0644, xpd->proc_xpd_dir);
-+ if (!xpd->proc_xpd_ztregister) {
-+ ERR("Failed to create proc '%s' for %s/%s\n", PROC_XPD_ZTREGISTER, xbus->busname, xpd->xpdname);
-+ goto err;
-+ }
-+ xpd->proc_xpd_ztregister->owner = THIS_MODULE;
-+ xpd->proc_xpd_ztregister->data = xpd;
-+ xpd->proc_xpd_ztregister->read_proc = proc_xpd_ztregister_read;
-+ xpd->proc_xpd_ztregister->write_proc = proc_xpd_ztregister_write;
-+#endif
-+ xbus_register_xpd(xbus, xpd);
-+ if(CALL_XMETHOD(card_init, xbus, xpd) < 0)
-+ goto err;
-+ // Turn off all channels
-+ CALL_XMETHOD(CHAN_ENABLE, xbus, xpd, ~0, 0);
-+ xpd->card_present = 1;
-+ // Turn on all channels
-+ CALL_XMETHOD(CHAN_ENABLE, xbus, xpd, ALL_LINES, 1);
-+
-+ if(zap_autoreg)
-+ zaptel_register_xpd(xpd);
- out:
-- spin_unlock_irqrestore(&q->lock, flags);
-- return pack;
-+ memset(card_desc, 0, sizeof(struct card_desc_struct));
-+ kfree(card_desc);
-+ return;
-+err:
-+ xpd_free(xpd);
-+ goto out;
- }
-
-
--/*------------------------- XPD Management -------------------------*/
--
- #ifdef CONFIG_PROC_FS
-
- /**
-@@ -510,83 +376,78 @@
- int len = 0;
- xpd_t *xpd = data;
- xbus_t *xbus;
--#if SOFT_SIMULATOR
-- struct xpd_sim *sim;
--#endif
-- int channels;
- int i;
-
- if(!xpd)
- goto out;
-
- xbus = xpd->xbus;
--#if SOFT_SIMULATOR
-- sim = &xbus->sim[xpd->id];
--#endif
-- channels = xpd->channels;
-- len += sprintf(page + len, "%s (%s ,card %s, span_registered=%s)%s\n"
-+ len += sprintf(page + len, "%s (%s ,card %s, span %s) %s\n"
- "timer_count: %d span->mainttimer=%d\n"
- ,
- xpd->xpdname, xproto_name(xpd->type),
-- (atomic_read(&xpd->card_present))?"present":"missing",
-- (SPAN_REGISTERED(xpd))?"yes":"no",
-- (xpd == sync_master) ? " SYNCER" : "",
-+ (xpd->card_present) ? "present" : "missing",
-+ (SPAN_REGISTERED(xpd)) ? "registered" : "NOT registered",
-+ (xpd == sync_master) ? "SYNC MASTER" : "SYNC SLAVE",
- xpd->timer_count, xpd->span.mainttimer
- );
- len += sprintf(page + len, "STATES:");
-- len += sprintf(page + len, "\n\t%-17s: ", "enabled");
-- for(i = 0; i < channels; i++) {
-- len += sprintf(page + len, "%d ", IS_SET(xpd->enabled_chans, i));
-- }
- len += sprintf(page + len, "\n\t%-17s: ", "output_relays");
-- for(i = 0; i < channels; i++) {
-+ for_each_line(xpd, i) {
- len += sprintf(page + len, "%d ", IS_SET(xpd->digital_outputs, i));
- }
- len += sprintf(page + len, "\n\t%-17s: ", "input_relays");
-- for(i = 0; i < channels; i++) {
-+ for_each_line(xpd, i) {
- len += sprintf(page + len, "%d ", IS_SET(xpd->digital_inputs, i));
- }
- len += sprintf(page + len, "\n\t%-17s: ", "hookstate");
-- for(i = 0; i < channels; i++) {
-+ for_each_line(xpd, i) {
- len += sprintf(page + len, "%d ", IS_SET(xpd->hookstate, i));
- }
-- len += sprintf(page + len, "\n\t%-17s: ", "ring-state");
-- for(i = 0; i < channels; i++) {
-- len += sprintf(page + len, "%d ", xpd->lasttxhook[i]);
-- }
- len += sprintf(page + len, "\n\t%-17s: ", "ringing");
-- for(i = 0; i < channels; i++) {
-+ for_each_line(xpd, i) {
- len += sprintf(page + len, "%d ", xpd->ringing[i]);
- }
- #if 1
- if(SPAN_REGISTERED(xpd)) {
-- len += sprintf(page + len, "\nreadchunk: ");
-- for(i = 0; i < channels; i++) {
-+ len += sprintf(page + len, "\nPCM:\n | [readchunk] | [writechunk] | delay");
-+ for_each_line(xpd, i) {
- struct zt_chan *chans = xpd->span.chans;
-- byte chunk[ZT_CHUNKSIZE];
-+ byte rchunk[ZT_CHUNKSIZE];
-+ byte wchunk[ZT_CHUNKSIZE];
-+ byte *rp;
-+ byte *wp;
- int j;
-
-- memcpy(chunk, chans[i].readchunk, ZT_CHUNKSIZE);
-- len += sprintf(page + len, "\n\tport %2d> ", i);
-+ if(IS_SET(xpd->digital_outputs, i))
-+ continue;
-+ if(IS_SET(xpd->digital_inputs, i))
-+ continue;
-+#if 1
-+ rp = chans[i].readchunk;
-+ wp = chans[i].writechunk;
-+#else
-+ rp = (byte *)xpd->readchunk + (ZT_CHUNKSIZE * i);
-+ wp = chans[i].writechunk;
-+#endif
-+ memcpy(rchunk, rp, ZT_CHUNKSIZE);
-+ memcpy(wchunk, wp, ZT_CHUNKSIZE);
-+ len += sprintf(page + len, "\n port %2d> | ", i);
- for(j = 0; j < ZT_CHUNKSIZE; j++) {
-- len += sprintf(page + len, "%02X ", chunk[j]);
-+ len += sprintf(page + len, "%02X ", rchunk[j]);
- }
-- }
-- }
--#endif
--#if SOFT_SIMULATOR
-- if(sim->simulated) {
-- len += sprintf(page + len, "\nSIMULATED (xpd_type=%d, loopto=%d):", sim->xpd_type, sim->loopto);
-- len += sprintf(page + len, "\n\t%-17s: ", "hookstate");
-- for(i = 0; i < channels; i++) {
-- len += sprintf(page + len, "%d ", IS_SET(sim->hookstate, i));
-+ len += sprintf(page + len, " | ");
-+ for(j = 0; j < ZT_CHUNKSIZE; j++) {
-+ len += sprintf(page + len, "%02X ", wchunk[j]);
-+ }
-+ len += sprintf(page + len, " | %d ", xpd->delay_until_dialtone[i]);
- }
- }
- #endif
- #if 0
- if(SPAN_REGISTERED(xpd)) {
- len += sprintf(page + len, "\nSignalling:\n");
-- for(i = 0; i < channels; i++) {
-+ for_each_line(xpd, i) {
- struct zt_chan *chan = &xpd->span.chans[i];
- len += sprintf(page + len, "\t%2d> sigcap=0x%04X sig=0x%04X\n", i, chan->sigcap, chan->sig);
- }
-@@ -620,10 +481,11 @@
- xpd_t *xpd_alloc(size_t privsize, xbus_t *xbus, int xpd_num, const xproto_table_t *proto_table, int channels, byte revision)
- {
- xpd_t *xpd = NULL;
-+ size_t pcm_size;
- size_t alloc_size = sizeof(xpd_t) + privsize;
-+ int i;
-
-- INFO("New XPD #%d (Revision %d.%d) detected on xbus %s\n",
-- xpd_num, revision / 10, revision % 10, xbus->busname);
-+ DBG("%s: xpd #%d\n", xbus->busname, xpd_num);
- if(!VALID_XPD_NUM(xpd_num)) {
- ERR("%s: illegal xpd id = %d\n", __FUNCTION__, xpd_num);
- goto err;
-@@ -645,14 +507,19 @@
- xpd->id = xpd_num;
- xpd->channels = channels;
- xpd->chans = NULL;
-- atomic_set(&xpd->card_present, 0);
-+ xpd->card_present = 0;
- snprintf(xpd->xpdname, XPD_NAMELEN, "XPD-%d", xpd_num);
- xpd->hookstate = 0x0; /* ONHOOK */
- xpd->type = proto_table->type;
-+ xpd->xproto = proto_table;
- xpd->xops = &proto_table->xops;
-- xpd->enabled_chans = enabled_channels[xpd_num];
- xpd->digital_outputs = 0;
- xpd->digital_inputs = 0;
-+
-+ for_each_line(xpd, i) {
-+ xpd->idletxhookstate[i] = FXS_LINE_ENABLED; /* By default, don't send on hook */
-+ }
-+
- atomic_set(&xpd->open_counter, 0);
-
- xpd->chans = kmalloc(sizeof(struct zt_chan)*xpd->channels, GFP_KERNEL);
-@@ -660,33 +527,61 @@
- ERR("%s: Unable to allocate channels\n", __FUNCTION__);
- goto err;
- }
-- /* 8 channels, double buffer, Read/Write */
-- int need = ZT_MAX_CHUNKSIZE * CHANNELS_PERXPD * 2 * 2;
-- if((xpd->writechunk = kmalloc(need, GFP_KERNEL)) == NULL) {
-+ pcm_size = ZT_MAX_CHUNKSIZE * CHANNELS_PERXPD * 2; /* Double Buffer */
-+ alloc_size = pcm_size * 2; /* Read/Write */
-+ if((xpd->writechunk = kmalloc(alloc_size, GFP_KERNEL)) == NULL) {
- ERR("%s: Unable to allocate memory for writechunks\n", __FUNCTION__);
- goto err;
- }
- /* Initialize Write/Buffers to all blank data */
-- memset((void *)xpd->writechunk, 0x00, need);
-- xpd->readchunk = xpd->writechunk + ZT_CHUNKSIZE * CHANNELS_PERXPD * 2;
-+ memset((void *)xpd->writechunk, 0x00, alloc_size);
-+ xpd->readchunk = xpd->writechunk + pcm_size;
-
- return xpd;
- err:
-- if(xpd->chans)
-- kfree((void *)xpd->chans);
-- if(xpd->writechunk)
-- kfree((void *)xpd->writechunk);
-- if(xpd)
-+ if(xpd) {
-+ if(xpd->chans)
-+ kfree((void *)xpd->chans);
-+ if(xpd->writechunk)
-+ kfree((void *)xpd->writechunk);
- kfree(xpd);
-+ }
- return NULL;
- }
-
--static void xpd_card_disable(xpd_t *xpd)
-+/* FIXME: this should be removed once digium patch their zaptel.h
-+ * I simply wish to avoid changing zaptel.h in the xpp patches.
-+ */
-+#ifndef ZT_EVENT_REMOVED
-+#define ZT_EVENT_REMOVED (20)
-+#endif
-+
-+void xpd_disconnect(xpd_t *xpd)
- {
-+ unsigned long flags;
-+
- BUG_ON(!xpd);
-- atomic_set(&xpd->card_present, 0);
-- if(SPAN_REGISTERED(xpd))
-+
-+ // TODO: elect a new sync master
-+ if(sync_master == xpd)
-+ sync_master_is(NULL);
-+
-+ spin_lock_irqsave(&xpd->lock, flags);
-+ DBG("%s/%s (%p)\n", xpd->xbus->busname, xpd->xpdname, xpd->xproto);
-+ if(!xpd->card_present) /* Multiple reports */
-+ goto out;
-+ xpd->card_present = 0;
-+ if(SPAN_REGISTERED(xpd)) {
-+ int i;
-+
- update_xpd_status(xpd, ZT_ALARM_NOTOPEN);
-+ /* TODO: Should this be done before releasing the spinlock? */
-+ DBG("Queuing ZT_EVENT_REMOVED on all channels to ask user to release them\n");
-+ for (i=0; i<xpd->span.channels; i++)
-+ zt_qevent_lock(&xpd->chans[i],ZT_EVENT_REMOVED);
-+ }
-+out:
-+ spin_unlock_irqrestore(&xpd->lock, flags);
- }
-
- void xpd_remove(xpd_t *xpd)
-@@ -695,23 +590,14 @@
-
- BUG_ON(!xpd);
- xbus = xpd->xbus;
-- INFO("Remove XPD #%d from xbus=%s\n", xpd->id, xbus->busname);
--#if 0
-- // TODO: elect a new sync master
-- if(sync_master == xpd)
-- set_sync_master(NULL);
--#endif
-- xpd_zaptel_unregister(xpd);
-- xbus->xpds[xpd->id] = NULL;
-- list_del(&xpd->xpd_list);
-- xbus->num_xpds--;
-+ INFO("%s: Remove XPD #%d from\n", xbus->busname, xpd->id);
-+
-+ zaptel_unregister_xpd(xpd);
- CALL_XMETHOD(card_remove, xbus, xpd);
-- xpd_cleanup(xpd);
-- kfree((void *)xpd->writechunk);
-- kfree(xpd);
-+ xpd_free(xpd);
- }
-
--static void update_xpd_status(xpd_t *xpd, int alarm_flag)
-+void update_xpd_status(xpd_t *xpd, int alarm_flag)
- {
- struct zt_span *span = &xpd->span;
-
-@@ -734,78 +620,16 @@
- DBG("Update XPD alarms: %s -> %02X\n", xpd->span.name, alarm_flag);
- }
-
--void phone_hook(xpd_t *xpd, int channo, bool offhook)
-+void update_line_status(xpd_t *xpd, int pos, bool good)
- {
-- struct zt_chan *chan = &xpd->span.chans[channo];
-+ struct zt_chan *chan;
-
-- if(offhook && !IS_SET(xpd->hookstate, channo)) { // OFFHOOK
-- DBG("OFFHOOK: channo=%d\n", chan->channo);
-- xpd->ringing[channo] = 0;
-- BIT_SET(xpd->hookstate, channo);
-+ BUG_ON(!xpd);
-+ chan = &xpd->chans[pos];
-+ if(good)
- zt_hooksig(chan, ZT_RXSIG_OFFHOOK);
-- if(!IS_SET(xpd->digital_outputs, channo) && !IS_SET(xpd->digital_inputs, channo)) {
-- CALL_XMETHOD(CHAN_POWER, xpd->xbus, xpd, BIT(channo), 0); // Power down (prevent overheating!!!)
-- CALL_XMETHOD(LED, xpd->xbus, xpd, BIT(channo), LED_GREEN, 1);
-- }
-- } else if(!offhook && IS_SET(xpd->hookstate, channo)) { // ONHOOK
-- DBG("ONHOOK channo=%d\n", chan->channo);
-- xpd->ringing[channo] = 0;
-- BIT_CLR(xpd->hookstate, channo);
-+ else
- zt_hooksig(chan, ZT_RXSIG_ONHOOK);
-- if(!IS_SET(xpd->digital_outputs, channo) && !IS_SET(xpd->digital_inputs, channo)) {
-- CALL_XMETHOD(CHAN_POWER, xpd->xbus, xpd, BIT(channo), 0); // Power down (prevent overheating!!!)
-- CALL_XMETHOD(LED, xpd->xbus, xpd, BIT(channo), LED_GREEN, 0);
-- }
-- }
--}
--
--void xpp_check_hookstate(xpd_t *xpd, xpp_line_t fxs_off_hook)
--{
-- int i;
-- unsigned long flags;
--
-- spin_lock_irqsave(&xpd->lock, flags);
-- if(xpd->direction != TO_PHONE) {
-- ERR("%s: %s: Only PHONE can report hookstate changes\n", __FUNCTION__, xpd->xpdname);
-- goto out;
-- }
-- if(!SPAN_REGISTERED(xpd)) {
-- NOTICE("%s: %s is not registered. Skipping.\n", __FUNCTION__, xpd->xpdname);
-- goto out;
-- }
-- DBG("%s: hookstate=0x%04X fxs_off_hook=0x%04X\n", xpd->xpdname, xpd->hookstate, fxs_off_hook);
-- for(i = 0; i < xpd->channels; i++) {
-- phone_hook(xpd, i, IS_SET(fxs_off_hook, i));
-- }
--out:
-- spin_unlock_irqrestore(&xpd->lock, flags);
--}
--
--static void xpd_blink_leds(xpd_t *xpd)
--{
-- int i;
-- unsigned long flags;
--
-- BUG_ON(!xpd);
--
-- spin_lock_irqsave(&xpd->lock, flags);
-- for(i = 0; i < xpd->channels; i++) {
-- if(IS_SET(xpd->digital_outputs, i) || IS_SET(xpd->digital_inputs, i))
-- continue;
-- if(xpd->ringing[i]) {
-- // led state is toggled
-- if((xpd->timer_count % LED_BLINK_PERIOD) == 0) {
-- DBG("%s pos=%d ringing=%d led_on=%d\n", xpd->xpdname, i, xpd->ringing[i], xpd->led_on[i]);
-- if(xpd->ringing[i] && xpd->led_on[i]) {
-- CALL_XMETHOD(LED, xpd->xbus, xpd, BIT(i), LED_GREEN, 1);
-- } else {
-- CALL_XMETHOD(LED, xpd->xbus, xpd, BIT(i), LED_GREEN, 0);
-- }
-- xpd->led_on[i] = !xpd->led_on[i];
-- }
-- }
-- }
-- spin_unlock_irqrestore(&xpd->lock, flags);
- }
-
- static void xpp_ring_generate(xpd_t *xpd)
-@@ -829,7 +653,7 @@
- * Ring detect logic:
- * fxo_power is toggled
- */
-- for(i = 0; i < xpd->channels; i++) {
-+ for_each_line(xpd, i) {
- if(xpd->ringing[i] || xpd->ringer_on[i]) {
- // ring state is only changed once per second:
- if((xpd->timer_count % 1000) == 0) {
-@@ -839,10 +663,7 @@
- } else {
- zt_hooksig(&xpd->chans[i], ZT_RXSIG_RING);
- }
-- xpd->ringing[i]--;
- xpd->ringer_on[i] = !xpd->ringer_on[i];
-- if (xpd->ringing[i] < 0)
-- xpd->ringing[i]=0;
- }
- }
- }
-@@ -850,98 +671,13 @@
- spin_unlock_irqrestore(&xpd->lock, flags);
- }
-
--/*------------------------- Bus Management -------------------------*/
--
--xbus_t *xbus_of(int xbus_num)
--{
-- if(xbus_num < 0 || xbus_num >= MAX_BUSES)
-- return NULL;
-- return xbuses_array[xbus_num];
--}
--
--xpd_t *xpd_of(xbus_t *xbus, int xpd_num)
--{
-- if(!VALID_XPD_NUM(xpd_num))
-- return NULL;
-- return xbus->xpds[xpd_num];
--}
--
--void xbus_reset_counters(xbus_t *xbus)
--{
-- int i;
--
-- DBG("Reseting counters of %s\n", xbus->busname);
-- for(i = 0; i < XBUS_COUNTER_MAX; i++) {
-- xbus->counters[i] = 0;
-- }
--// xbus->xmit_queue.worst_count = 0;
--// xbus->xmit_queue.overflows = 0;
--}
--
- #ifdef CONFIG_PROC_FS
-
--/**
-- * Prints a general procfs entry for the bus, under xpp/BUSNAME/summary
-- * @page TODO: figure out procfs
-- * @start TODO: figure out procfs
-- * @off TODO: figure out procfs
-- * @count TODO: figure out procfs
-- * @eof TODO: figure out procfs
-- * @data an xbus_t pointer with the bus data.
-- */
--static int xbus_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
--{
-- int len = 0;
-- unsigned long flags;
-- xbus_t *xbus = data;
-- int i;
--
-- if(!xbus)
-- goto out;
-- spin_lock_irqsave(&xbus->lock, flags);
--
-- len += sprintf(page + len, "%s: CONNECTOR=%s STATUS=%s bus_type=%d\n",
-- xbus->busname,
-- xbus->busdesc,
-- (xbus->hardware_exists) ? "connected" : "missing",
-- xbus->bus_type
-- );
-- len += sprintf(page + len, "open_counter=%d packet_count=%d\n",
-- xbus->open_counter,
-- atomic_read(&xbus->packet_counter)
-- );
--#if SOFT_SIMULATOR
-- len += sprintf(page + len, "XPDS SIM\n");
-- for(i = 0; i < MAX_XPDS; i++) {
-- struct xpd_sim *sim = &xbus->sim[i];
-- xpd_t *xpd = xpd_of(xbus, i);
-- len += sprintf(page + len, "\t%d> ignored=%d simulated=%d softloop_xpd=%d loopto=%d instanciated=%s\n",
-- i, IS_SET(ignore_xpds, i), sim->simulated, sim->softloop_xpd, sim->loopto, (xpd) ? "yes" : "no");
-- }
--#endif
-- len += sprintf(page + len, "COUNTERS:\n");
-- for(i = 0; i < XBUS_COUNTER_MAX; i++) {
-- len += sprintf(page + len, "\t%-15s = %d\n",
-- xbus_counters[i].name, xbus->counters[i]);
-- }
-- len += sprintf(page + len, "<-- len=%d\n", len);
-- spin_unlock_irqrestore(&xbus->lock, flags);
--out:
-- if (len <= off+count)
-- *eof = 1;
-- *start = page + off;
-- len -= off;
-- if (len > count)
-- len = count;
-- if (len < 0)
-- len = 0;
-- return len;
--
--}
--
- int proc_sync_read(char *page, char **start, off_t off, int count, int *eof, void *data)
- {
-- int len = 0;
-+ int len = 0;
-+ unsigned int xpp_timer_rate;
-+ unsigned int now;
-
- len += sprintf(page + len, "# To modify sync source write into this file:\n");
- len += sprintf(page + len, "# HOST - For host based sync\n");
-@@ -952,8 +688,8 @@
- else
- len += sprintf(page + len, "%s/%s\n", sync_master->xbus->busname, sync_master->xpdname);
- len += sprintf(page + len, "tick: #%d\n", xpp_timer_count);
-- unsigned int xpp_timer_rate = 0;
-- unsigned int now = jiffies;
-+ xpp_timer_rate = 0;
-+ now = jiffies;
- if(now - xpp_last_jiffies > 0) {
- xpp_timer_rate = ((xpp_timer_count % SAMPLE_TICKS) * 1000) / (now - xpp_last_jiffies);
- len += sprintf(page + len, "tick rate: %4d/second (average over %d seconds)\n", xpp_timer_rate, SAMPLE_TICKS/HZ);
-@@ -971,7 +707,6 @@
-
- static int proc_sync_write(struct file *file, const char __user *buffer, unsigned long count, void *data)
- {
-- DBG("%s: count=%ld\n", __FUNCTION__, count);
- const int NUM_SIZE = 100;
- char buf[NUM_SIZE];
- int xbus_num;
-@@ -979,31 +714,47 @@
- xbus_t *xbus;
- xpd_t *xpd;
- int ret;
-+ bool setit;
-
-+ // DBG("%s: count=%ld\n", __FUNCTION__, count);
- if(count >= NUM_SIZE)
- return -EINVAL;
- if(copy_from_user(buf, buffer, count))
- return -EFAULT;
- buf[count] = '\0';
- if(strncmp("HOST", buf, 4) == 0) {
-- set_sync_master(NULL);
-+ sync_master_is(NULL);
- goto out;
- }
-- ret = sscanf(buf, "%d %d", &xbus_num, &xpd_num);
-- if(ret != 2)
-+ ret = sscanf(buf, "%d %d %d", &xbus_num, &xpd_num, &setit);
-+ if(ret == 2) {
-+ // For backward compatibility: before query was introduced,
-+ // only two parameters were possible
-+ setit = 1;
-+ ret = 3;
-+ }
-+ if(ret != 3 || (setit != 0 && setit != 1)) {
-+ ERR("Bad format for SYNC.\n");
-+ ERR("Usage: <bus_num> <xpd_num> <0/1> # 0 - QUERY, 1 - SET\n");
- return -EINVAL;
-- DBG("%s: %d/%d\n", __FUNCTION__, xbus_num, xpd_num);
-- if(xbus_num >= MAX_BUSES)
-+ }
-+ if(xbus_num >= MAX_BUSES) {
-+ ERR("Invalid xbus number %d\n", xbus_num);
- return -EINVAL;
-+ }
- xbus = xbus_of(xbus_num);
-- if(!xbus)
-+ if(!xbus) {
-+ ERR("No bus %d exists\n", xbus_num);
- return -EINVAL;
-+ }
- xpd = xpd_of(xbus, xpd_num);
- if(!xpd) {
- ERR("%s: XPD number %d does not exist\n", __FUNCTION__, xpd_num);
- return -ENXIO;
- }
-- set_sync_master(xpd);
-+ DBG("%s: %d/%d %s\n", __FUNCTION__, xbus_num, xpd_num, (setit)?"SET":"QUERY");
-+ if(setit)
-+ external_sync(xpd);
- out:
- return count;
- }
-@@ -1050,346 +801,73 @@
- DBG("%s: %s/%s %s\n", __FUNCTION__,
- xpd->xbus->busname, xpd->xpdname, (zt_reg) ? "register" : "unregister");
- if(zt_reg)
-- ret = xpd_zaptel_register(xpd);
-- else
-- ret = xpd_zaptel_unregister(xpd);
-- return (ret < 0) ? ret : count;
--}
--
--#endif
--
--/**
-- *
-- * Packet is freed:
-- * - In case of error, by this function.
-- * - Otherwise, by the underlying sending mechanism
-- */
--int packet_send(xbus_t *xbus, xpacket_t *pack_tx)
--{
-- int ret = -ENODEV;
-- int toxpd;
--
-- if(!pack_tx) {
-- DBG("null pack\n");
-- return -EINVAL;
-- }
-- toxpd = XPD_NUM(pack_tx->content.addr);
-- if(!xbus) {
-- DBG("null xbus\n");
-- ret = -EINVAL;
-- goto error;
-- }
-- if (!xbus->hardware_exists) {
-- DBG("xbus %s Dropped a packet -- NO HARDWARE.", xbus->busname);
-- ret = -ENODEV;
-- goto error;
-- }
-- if(!VALID_XPD_NUM(toxpd)) {
-- ERR("%s: toxpd=%d > MAX_XPDS\n", __FUNCTION__, toxpd);
-- ret = -EINVAL;
-- goto error;
-- }
--#if 0
-- // DEBUG: For Dima
-- if(pack_tx->content.opcode == XPP_PCM_WRITE) {
-- static int rate_limit;
-- static int count;
--
-- if(sync_master == NULL)
-- count = 0;
-- if(count++ > 5) {
-- ret = 0;
-- goto error;
-- }
-- if(rate_limit++ % 1000 == 0)
-- INFO("DEBUG: TRANSMIT (PCM_WRITE)\n");
-- }
--#endif
-- if(down_read_trylock(&xbus->in_use)) {
-- ret = xbus->ops->packet_send(xbus, pack_tx);
-- XBUS_COUNTER(xbus, TX_BYTES) += pack_tx->datalen;
-- up_read(&xbus->in_use);
-- } else {
-- DBG("Dropped packet. %s is in_use\n", xbus->busname);
-- }
-- return ret;
--
--error:
-- xbus->ops->packet_free(xbus, pack_tx);
-- return ret;
--}
--
--static void xbus_poll(xbus_t *xbus, int probe_all)
--{
-- int id;
-- int ret;
-- xpd_t **xpds;
-- xpd_t *xpd;
--
-- DBG("%s (probe_all=%d)\n", xbus->busname, probe_all);
-- xpds = xbus->xpds;
-- for(id = 0; id < MAX_XPDS; id++) {
-- if(!xbus->hardware_exists)
-- break;
-- xpd = xpd_of(xbus, id);
-- if(!probe_all) {
-- if(!xpd) {
-- DBG(" Skipping XPD #%d is MISSING\n", id);
-- continue;
-- }
-- if(!atomic_read(&xpd->card_present)) {
-- DBG(" Skipping XPD #%d not present\n", id);
-- continue;
-- }
-- if(time_after(xpd->last_response+20, jiffies)) {
-- DBG(" SKIP DESC_REQ\n");
-- continue;
-- }
-- }
-- if(IS_SET(ignore_xpds, id)) { /* skip xpds */
-- DBG(" Ignoring XPD #%d\n", id);
-- continue;
-- }
-- DBG(" Polling slot %d %s\n", id, xbus->busname);
-- ret = CALL_PROTO(GLOBAL, DESC_REQ, xbus, NULL, id);
-- if(ret < 0) {
-- NOTICE("xpp: %s: Failed sending DESC_REQ to XPD #%d\n", __FUNCTION__, id);
-- }
-- }
--}
--
--void process_xbus_poll(void *data) {
-- xbus_t *xbus = (xbus_t*) data;
--
-- ERR("%s: issuing xbus_poll\n", __FUNCTION__);
-- xbus_poll(xbus, 1);
--}
--
--
--#if SOFT_SIMULATOR
--/*
-- * Assume xbus->lock is held
-- */
--static void simulator_setup(xbus_t *xbus, ulong sim_xpds)
--{
-- int i;
-- int last_fxo = 0;
-- bool first = 1;
--
-- DBG("%s: sim_xpds=0x%lX\n", xbus->busname, sim_xpds);
-- for(i = 0; i < MAX_XPDS; i++) {
-- if (!IS_SET(sim_xpds, i) || xbus->sim[i].simulated)
-- continue;
-- if (first) {
-- last_fxo=i;
-- } else {
-- // setting simulated twice here: in case of odd number of simulated XPDs
-- xbus->sim[i].xpd_type = XPD_TYPE_FXO;
-- xbus->sim[i].loopto = last_fxo;
-- xbus->sim[i].simulated = 1;
-- xbus->sim[last_fxo].xpd_type = XPD_TYPE_FXS;
-- xbus->sim[last_fxo].loopto = i;
-- xbus->sim[last_fxo].simulated = 1;
--
-- }
-- if(IS_SET(softloop_xpds, i))
-- xbus->sim[i].softloop_xpd = 1;
-- xbus->sim[i].hookstate = 0;
--
-- first = !first;
-- }
--}
--#endif
--
--void xbus_activate(xbus_t *xbus)
--{
-- xbus_ops_t *ops;
--
-- BUG_ON(!xbus);
-- ops = xbus->ops;
-- BUG_ON(!ops);
-- BUG_ON(!xbus->priv);
-- /* Sanity checks */
-- if(!ops->packet_send) {
-- ERR("%s: missing mandatory handler: packet_send=\n", __FUNCTION__);
-- return;
-- }
-- if(!ops->packet_new || !ops->packet_free) {
-- ops->packet_new = softloop_packet_new;
-- ops->packet_free = softloop_packet_free;
-- }
--
-- xbus->hardware_exists = 1;
-- DBG("Activating: %s\n", xbus->busname);
-- /* Poll it */
-- xbus_poll(xbus, 1);
--}
--
--void xbus_deactivate(xbus_t *xbus)
--{
-- int i;
--
-- BUG_ON(!xbus);
-- DBG("%s\n", xbus->busname);
-- xbus->hardware_exists = 0;
-- for(i = 0; i < MAX_XPDS; i++) {
-- xpd_t *xpd = xpd_of(xbus, i);
-- if(!xpd)
-- continue;
-- if(xpd->id != i) {
-- ERR("%s: BUG: xpd->id=%d != i=%d\n", __FUNCTION__, xpd->id, i);
-- continue;
-- }
-- xpd_card_disable(xpd);
-- }
-- down_write(&xbus->in_use);
-- DBG("%s (deactivated)\n", xbus->busname);
-- if(xbus->open_counter == 0) {
-- xbus_remove(xbus);
-- }
--}
--
--
--static void xbus_cleanup(xbus_t *xbus)
--{
-- BUG_ON(!xbus);
--#ifdef CONFIG_PROC_FS
-- if(xbus->proc_xbus_dir) {
-- if(xbus->proc_xbus_summary) {
-- DBG("Removing proc '%s' for %s\n", PROC_XBUS_SUMMARY, xbus->busname);
-- remove_proc_entry(PROC_XBUS_SUMMARY, xbus->proc_xbus_dir);
-- xbus->proc_xbus_summary = NULL;
-- }
-- DBG("Removing proc directory %s\n", xbus->busname);
-- remove_proc_entry(xbus->busname, xpp_procdir);
-- xbus->proc_xbus_dir = NULL;
-- }
--#endif
-- kfree(xbus);
-+ ret = zaptel_register_xpd(xpd);
-+ else
-+ ret = zaptel_unregister_xpd(xpd);
-+ return (ret < 0) ? ret : count;
- }
-
--xbus_t *xbus_new(ulong loopback_xpds)
--{
-- unsigned long flags;
-- int xbus_num;
-- int err;
-- xbus_t *xbus;
--
-- xbus = kmalloc(sizeof(xbus_t), GFP_KERNEL);
-- if(!xbus)
-- return NULL;
-- memset(xbus, 0, sizeof(xbus_t));
--
-- spin_lock_irqsave(&xbuses_lock, flags);
-- for(xbus_num = 0; xbus_num < MAX_BUSES; xbus_num++)
-- if(xbuses_array[xbus_num] == NULL)
-- break;
-- if(xbus_num >= MAX_BUSES) {
-- spin_unlock_irqrestore(&xbuses_lock, flags);
-- err = -ENOMEM;
-- goto nobus;
-- }
-- /* Found empty slot */
-- xbuses_array[xbus_num] = xbus;
-- bus_count++;
-- spin_unlock_irqrestore(&xbuses_lock, flags);
--
-- /* Init data structures */
-- spin_lock_init(&xbus->lock);
-- snprintf(xbus->busname, XBUS_NAMELEN, "XBUS-%d", xbus_num);
-- INFO("New xbus: %s\n", xbus->busname);
-- init_waitqueue_head(&xbus->packet_cache_empty);
-- atomic_set(&xbus->packet_counter, 0);
-- init_rwsem(&xbus->in_use);
-- xbus->num = xbus_num;
-- xbus->num_xpds = 0;
--#if SOFT_SIMULATOR
-- xbus->sim_workqueue = create_singlethread_workqueue(xbus->busname);
-- if(!xbus->sim_workqueue) {
-- ERR("Failed to create workqueue for xbus %s\n", xbus->busname);
-- err = -ENOMEM;
-- goto nobus;
-- }
-- init_xbus_packet_queue(&xbus->sim_packet_queue, "SIM_PACKET_QUEUE");
-- INIT_WORK(&xbus->sim_work, process_sim_queue, xbus);
-- simulator_setup(xbus, loopback_xpds); // Hardware loopback must use simulator
-- simulator_setup(xbus, softloop_xpds); // Add the soft loopback to the simulated set
--#endif
-- xbus_reset_counters(xbus);
--#ifdef CONFIG_PROC_FS
-- DBG("Creating xbus proc directory %s.\n",xbus->busname);
-- xbus->proc_xbus_dir = proc_mkdir(xbus->busname, xpp_procdir);
-- if(!xbus->proc_xbus_dir) {
-- ERR("Failed to create proc directory for xbus %s\n", xbus->busname);
-- err = -EIO;
-- goto nobus;
-- }
-- xbus->proc_xbus_summary = create_proc_read_entry(PROC_XBUS_SUMMARY, 0444, xbus->proc_xbus_dir,
-- xbus_read_proc, xbus);
-- if (!xbus->proc_xbus_summary) {
-- ERR("Failed to create '%s' proc file for xbus %s\n", PROC_XBUS_SUMMARY, xbus->busname);
-- err = -EIO;
-- goto nobus;
-- }
- #endif
-- return xbus;
--nobus:
-- spin_lock_irqsave(&xbuses_lock, flags);
-- xbuses_array[xbus_num] = NULL;
-- bus_count--;
-- spin_unlock_irqrestore(&xbuses_lock, flags);
-- xbus_cleanup(xbus);
-- return NULL;
--}
-
--static void xbus_remove(xbus_t *xbus)
-+/**
-+ *
-+ * Packet is freed:
-+ * - In case of error, by this function.
-+ * - Otherwise, by the underlying sending mechanism
-+ */
-+int packet_send(xbus_t *xbus, xpacket_t *pack_tx)
- {
-- int i;
-- unsigned long flags;
-+ int ret = -ENODEV;
-+ int toxpd;
-
-- BUG_ON(!xbus);
-- DBG("%s\n", xbus->busname);
-- spin_lock_irqsave(&xbuses_lock, flags);
-- BUG_ON(xbus != xbus_of(xbus->num));
-- xbuses_array[xbus->num] = NULL;
-- bus_count--;
-- spin_unlock_irqrestore(&xbuses_lock, flags);
--#if SOFT_SIMULATOR
-- if(xbus->sim_workqueue) {
-- cancel_delayed_work(&xbus->sim_work);
-+ if(!pack_tx) {
-+ DBG("null pack\n");
-+ return -EINVAL;
- }
--#endif
-- INFO("Removing xbus(%d) %s\n", xbus->num, xbus->busname);
-- for(i = 0; i < MAX_XPDS; i++) {
-- xpd_t *xpd = xpd_of(xbus, i);
--
-- if(xpd) {
-- const xops_t *xops = xpd->xops;
-+ toxpd = XPD_NUM(pack_tx->content.addr);
-+ if(!xbus) {
-+ DBG("null xbus\n");
-+ ret = -EINVAL;
-+ goto error;
-+ }
-+ if (!xbus->hardware_exists) {
-+ DBG("xbus %s Dropped a packet -- NO HARDWARE.", xbus->busname);
-+ ret = -ENODEV;
-+ goto error;
-+ }
-+ if(!VALID_XPD_NUM(toxpd)) {
-+ ERR("%s: toxpd=%d > MAX_XPDS\n", __FUNCTION__, toxpd);
-+ ret = -EINVAL;
-+ goto error;
-+ }
-+#if 0
-+ // DEBUG: For Dima
-+ if(pack_tx->content.opcode == XPP_PCM_WRITE) {
-+ static int rate_limit;
-+ static int count;
-
-- if(xpd->id != i) {
-- ERR("%s: BUG: xpd->id=%d != i=%d\n", __FUNCTION__, xpd->id, i);
-- continue;
-- }
-- BUG_ON(!xops);
-- DBG(" Removing xpd id=%d\n", xpd->id);
-- xpd_remove(xpd);
-+ if(sync_master == NULL)
-+ count = 0;
-+ if(count++ > 5) {
-+ ret = 0;
-+ goto error;
- }
-- xbus->xpds[i] = NULL;
-- }
--#if SOFT_SIMULATOR
-- if(xbus->sim_workqueue) {
-- flush_workqueue(xbus->sim_workqueue);
-- destroy_workqueue(xbus->sim_workqueue);
-- xbus->sim_workqueue = NULL;
-+ if(rate_limit++ % 1000 == 0)
-+ INFO("DEBUG: TRANSMIT (PCM_WRITE)\n");
- }
-- drain_xbus_packet_queue(xbus, &xbus->sim_packet_queue);
- #endif
-- int ret = wait_event_interruptible(xbus->packet_cache_empty,
-- atomic_read(&xbus->packet_counter) == 0);
-- if(ret) {
-- ERR("waiting for packet_cache_empty interrupted!!!\n");
-+ if(down_read_trylock(&xbus->in_use)) {
-+ ret = xbus->ops->packet_send(xbus, pack_tx);
-+ XBUS_COUNTER(xbus, TX_BYTES) += pack_tx->datalen;
-+ up_read(&xbus->in_use);
-+ } else {
-+ DBG("Dropped packet. %s is in_use\n", xbus->busname);
- }
-- xbus_cleanup(xbus);
-+ return ret;
-+
-+error:
-+ xbus->ops->packet_free(xbus, pack_tx);
-+ return ret;
- }
-
-
-@@ -1407,12 +885,12 @@
- int i;
- int channels = xpd->channels;
- struct zt_chan *chans = xpd->span.chans;
-+ unsigned long flags;
-
-+ spin_lock_irqsave(&xpd->lock, flags);
- // if((xpd->timer_count % PREP_REPORT_RATE) < 10)
- // DBG("%d\n", xpd->timer_count);
-
--// if(xpd->hookstate == 0)
--// return;
- if (xpd->timer_count & 1) {
- /* First part */
- w = writechunk = xpd->writechunk /* + 1 */;
-@@ -1422,18 +900,26 @@
- zt_transmit(&xpd->span);
-
- for (i = 0; i < channels; i++) {
-- if(IS_SET(xpd->hookstate, i)) {
-+ if (xpd->delay_until_dialtone[i] > 0) {
-+ xpd->delay_until_dialtone[i]--;
-+ if (xpd->delay_until_dialtone[i] <= 0) {
-+ xpd->delay_until_dialtone[i] = 0;
-+ wake_up_interruptible(&xpd->txstateq[i]);
-+ }
-+ }
-+ if(IS_SET(xpd->hookstate, i) || IS_SET(xpd->cid_on, i)) {
- memcpy((u_char *)w, chans[i].writechunk, ZT_CHUNKSIZE);
- // fill_beep((u_char *)w, 5);
- }
- w += ZT_CHUNKSIZE;
- }
-- if(xpd->hookstate != 0 || sync_master == xpd || !sync_master) {
-- ret = CALL_XMETHOD(PCM_WRITE, xpd->xbus, xpd, xpd->hookstate, writechunk);
-+// if(xpd->hookstate != 0 || sync_master != xpd) {
-+ ret = CALL_XMETHOD(PCM_WRITE, xpd->xbus, xpd, xpd->hookstate | xpd->cid_on, writechunk);
- if(ret < 0) {
- DBG("failed to write PCM %d\n", ret);
- }
-- }
-+// }
-+ spin_unlock_irqrestore(&xpd->lock, flags);
- }
-
- void fill_beep(u_char *buf, int duration)
-@@ -1446,20 +932,46 @@
- static u_char beep[] = {
- // 0x7F, 0xBE, 0xD8, 0xBE, 0x80, 0x41, 0x24, 0x41, /* Dima */
- // 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, /* silence */
-- 0x67, 0x90, 0x89, 0x90, 0xFF, 0x10, 0x09, 0x10, /* Izzy */
-+// 0x67, 0x90, 0x89, 0x90, 0xFF, 0x10, 0x09, 0x10, /* Izzy */
- // 0x67, 0xCD, 0xC5, 0xCD, 0xFF, 0x49, 0x41, 0x49, /* Dima 2 */
--// 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, /* silence */
-+ 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, /* silence */
- };
- memcpy(buf, &beep[(which*8) % ARRAY_SIZE(beep)], ZT_CHUNKSIZE);
- }
-
-+#ifdef XPP_EC_CHUNK
-+/*
-+ * Taken from zaptel.c
-+ */
-+static inline void xpp_ec_chunk(struct zt_chan *chan, unsigned char *rxchunk, const unsigned char *txchunk)
-+{
-+ short rxlin;
-+ int x;
-+ unsigned long flags;
-+
-+ /* Perform echo cancellation on a chunk if necessary */
-+ if (!chan->ec)
-+ return;
-+ spin_lock_irqsave(&chan->lock, flags);
-+ for (x=0;x<ZT_CHUNKSIZE;x++) {
-+ rxlin = ZT_XLAW(rxchunk[x], chan);
-+ rxlin = xpp_echo_can_update(chan->ec, ZT_XLAW(txchunk[x], chan), rxlin);
-+ rxchunk[x] = ZT_LIN2X((int)rxlin, chan);
-+ }
-+ spin_unlock_irqrestore(&chan->lock, flags);
-+}
-+#endif
-+
-+
- static void xpp_receiveprep(xpd_t *xpd)
- {
- volatile u_char *readchunk;
- int i;
- int channels = xpd->channels;
- struct zt_chan *chans = xpd->span.chans;
-+ unsigned long flags;
-
-+ spin_lock_irqsave(&xpd->lock, flags);
- // if((xpd->timer_count % PREP_REPORT_RATE) == 0)
- // DBG("%d\n", xpd->timer_count);
-
-@@ -1472,20 +984,29 @@
-
- for (i = 0; i < channels; i++) {
- if(IS_SET(xpd->hookstate, i)) {
-+ // memset((u_char *)readchunk, 0x5A, ZT_CHUNKSIZE); // DEBUG
-+ // fill_beep((u_char *)readchunk, 1); // DEBUG: BEEP
- memcpy(chans[i].readchunk, (u_char *)readchunk, ZT_CHUNKSIZE);
-+ } else {
-+ memset(chans[i].readchunk, 0x7F, ZT_CHUNKSIZE); // SILENCE
- }
- readchunk += ZT_CHUNKSIZE;
- }
-
--#if 0
-+#if WITH_ECHO_SUPPRESSION
- /* FIXME: need to Echo cancel double buffered data */
- for (i = 0;i < xpd->span.channels; i++) {
-+#ifdef XPP_EC_CHUNK
-+ xpp_ec_chunk(&chans[i], chans[i].readchunk, xpd->ec_chunk2[i]);
-+#else
- zt_ec_chunk(&chans[i], chans[i].readchunk, xpd->ec_chunk2[i]);
-+#endif
- memcpy(xpd->ec_chunk2[i], xpd->ec_chunk1[i], ZT_CHUNKSIZE);
- memcpy(xpd->ec_chunk1[i], chans[i].writechunk, ZT_CHUNKSIZE);
- }
- #endif
- zt_receive(&xpd->span);
-+ spin_unlock_irqrestore(&xpd->lock, flags);
- }
-
- static int xpp_startup(struct zt_span *span)
-@@ -1540,13 +1061,18 @@
- spin_lock_irqsave(&xbus->lock, flags);
- xbus->open_counter--;
- atomic_dec(&xpd->open_counter);
-+ if(xpd->direction == TO_PHONE) { /* Hangup phone */
-+ xpd->idletxhookstate[chan->chanpos - 1] = FXS_LINE_ENABLED;
-+ }
- if (!xbus->hardware_exists && xbus->open_counter == 0)
- should_remove = 1;
- spin_unlock_irqrestore(&xbus->lock, flags);
-
- DBG("chan=%d (open_counter=%d, should_remove=%d)\n", chan->chanpos, xbus->open_counter, should_remove);
-- if(should_remove)
-+ if(should_remove) {
-+ DBG("Going to remove: %s\n", xbus->busname);
- xbus_remove(xbus);
-+ }
- return 0;
- }
-
-@@ -1560,10 +1086,11 @@
- case ZT_ONHOOKTRANSFER:
- if (get_user(x, (int *)arg))
- return -EFAULT;
-- if (xpd->lasttxhook[pos] == 0x1) {
-+ xpd->ohttimer[pos] = x << 3;
-+ xpd->idletxhookstate[pos] = FXS_LINE_CID; /* OHT mode when idle */
-+ if (xpd->lasttxhook[pos] == FXS_LINE_ENABLED) {
- /* Apply the change if appropriate */
-- xpd->lasttxhook[pos] = 0x2;
-- // CALL_XMETHOD(CHAN_CID, xpd->xbus, xpd, BIT(pos)); // CALLER ID
-+ CALL_XMETHOD(CHAN_CID, xpd->xbus, xpd, pos); // CALLER ID
- }
- DBG("xpd=%d: ZT_ONHOOKTRANSFER (%d millis) chan=%d\n", xpd->id, x, pos);
- return -ENOTTY;
-@@ -1574,6 +1101,13 @@
- xpd->id, pos, (x & ZT_TONEDETECT_ON), (x & ZT_TONEDETECT_MUTE));
- return -ENOTTY;
- default:
-+ /* Some span-specific commands before we give up: */
-+ if (xpd->xops->card_ioctl != NULL) {
-+ x = xpd->xops->card_ioctl(xpd, pos, cmd, arg);
-+ if (x != -ENOTTY)
-+ return x;
-+ }
-+
- DBG("ENOTTY: chan=%d cmd=0x%x\n", pos, cmd);
- DBG(" IOC_TYPE=0x%02X\n", _IOC_TYPE(cmd));
- DBG(" IOC_DIR=0x%02X\n", _IOC_DIR(cmd));
-@@ -1590,109 +1124,15 @@
- xpd_t *xpd = chan->pvt;
- xbus_t *xbus;
- int pos = chan->chanpos - 1;
-- int ret = 0;
--
-- if(!xpd) {
-- ERR("%s: channel=%d without an XPD!\n", __FUNCTION__, pos);
-- return -EINVAL;
-- }
-- xbus = xpd->xbus;
-
-- if (txsig == ZT_TXSIG_START) {
-- if(xpd->direction == TO_PHONE) {
-- // A PHONE line: ZT_START will be treated as ZT_RING
-- DBG("Got ZT_START for PHONE channel %d, treated as ZT_RING\n", pos);
-- //hookstate = ZT_TXSIG_RING;
--
-- if(IS_SET(xpd->digital_inputs, pos)) {
-- NOTICE("%s: Trying to RING a digital input channel %d. Ignoring\n", __FUNCTION__, pos);
-- return -EINVAL;
-- }
-- if(IS_SET(xpd->digital_outputs, pos)) {
-- DBG("ZT_RING %s digital output ON\n", chan->name);
-- ret = CALL_XMETHOD(RELAY_OUT, xpd->xbus, xpd, pos-8, 1);
-- return ret;
-- }
-- xpd->ringing[pos] = RINGS_NUM*2;
-- DBG("ZT_RING %s ringing=%d\n", chan->name, xpd->ringing[pos]);
-- ret = CALL_XMETHOD(RING, xbus, xpd, pos, 1); // RING on
-- if(ret) {
-- DBG("ZT_RING Failed: ret=0x%02X\n", ret);
-- return ret;
-- }
-- return ret;
-- } else { /* TO_PSTN */
-- // An FXO line: ZT_START will be treated as ZT_OFFHOOK
-- DBG("Got ZT_START for FXO channel %d, treated as ZT_OFFHOOK\n", pos);
-- txsig = ZT_TXSIG_OFFHOOK;
-- }
-- }
-- switch(txsig) {
-- case ZT_TXSIG_START:
-- DBG("ZT_TXSIG_START: (doing OFFHOOK) %s (chan->dialing=%d)\n", chan->name, chan->dialing);
-- break;
-- /* Fall through */
-- case ZT_TXSIG_OFFHOOK:
-- DBG("ZT_TXSIG_OFFHOOK: %s hookstate=0x%04X\n", chan->name, xpd->hookstate);
-- BIT_SET(xpd->hookstate, pos);
-- xpd->ringing[pos] = 0;
-- if(IS_SET(xpd->digital_inputs, pos)) {
-- NOTICE("%s: Trying to OFFHOOK a digital input channel %d. Ignoring\n", __FUNCTION__, pos);
-- return -EINVAL;
-- }
-- if(IS_SET(xpd->digital_outputs, pos)) {
-- DBG("ZT_TXSIG_OFFHOOK %s digital output OFF\n", chan->name);
-- ret = CALL_XMETHOD(RELAY_OUT, xpd->xbus, xpd, pos-8, 0);
-- return ret;
-- }
-- ret = CALL_XMETHOD(SETHOOK, xbus, xpd->id, xpd->hookstate);
-- if(ret) {
-- DBG("ZT_TXSIG_OFFHOOK Failed: ret=0x%02X\n", ret);
-- break;
-- }
-- CALL_XMETHOD(LED, xpd->xbus, xpd, BIT(i), LED_GREEN, 0);
-- break;
-- //DBG("ZT_TXSIG_OFFHOOK %d\n", pos);
-- //BIT_SET(xpd->hookstate, pos);
-- //break;
-- case ZT_TXSIG_KEWL:
-- DBG("ZT_TXSIG_KEWL (doing ONHOOK): %d.\n", pos);
-- break;
-- /* Fall through */
-- case ZT_TXSIG_ONHOOK:
-- DBG("ZT_TXSIG_ONHOOK: %s hookstate=0x%04X\n", chan->name, xpd->hookstate);
-- xpd->ringing[pos] = 0;
-- if(IS_SET(xpd->digital_inputs, pos)) {
-- NOTICE("%s: Trying to ONHOOK a digital input channel %d. Ignoring\n", __FUNCTION__, pos);
-- return -EINVAL;
-- }
-- if(IS_SET(xpd->digital_outputs, pos)) {
-- DBG("ZT_TXSIG_ONHOOK %s digital output OFF\n", chan->name);
-- ret = CALL_XMETHOD(RELAY_OUT, xpd->xbus, xpd, pos-8, 0);
-- return ret;
-- }
-- BIT_CLR(xpd->hookstate, pos);
-- ret = CALL_XMETHOD(SETHOOK, xbus, xpd->id, xpd->hookstate);
-- if(ret) {
-- DBG("ZT_ONHOOK Failed: ret=0x%02X\n", ret);
-- break;
-- }
-- CALL_XMETHOD(LED, xpd->xbus, xpd, BIT(i), LED_GREEN, 0);
-- break;
-- //DBG("ZT_TXSIG_ONHOOK: %d\n", pos);
-- //BIT_CLR(xpd->hookstate, pos);
-- //break;
-- default:
-- DBG("hooksig: unkown txsig=%d on channel %d\n", txsig, pos);
-- return -EINVAL;
-- }
-- //ret = CALL_XMETHOD(SETHOOK, xbus, xpd->id, xpd->hookstate);
-- //if(ret) {
-- // DBG("ZT_TXSIG_START Failed: ret=0x%02X\n", ret);
-- //}
-- return ret;
-+ BUG_ON(!xpd);
-+ xbus = xpd->xbus;
-+ BUG_ON(!xbus);
-+ DBG("Setting %s to %s (%d)\n", chan->name, txsig2str(txsig), txsig);
-+ return CALL_XMETHOD(card_hooksig, xbus, xpd, pos, txsig);
- }
--#endif
-+
-+#else
-
- static int xpp_sethook(struct zt_chan *chan, int hookstate)
- {
-@@ -1701,102 +1141,15 @@
- xbus_t *xbus;
- int ret = 0;
-
-- if(!xpd) {
-- ERR("%s: channel=%d without an XPD!\n", __FUNCTION__, pos);
-- return -EINVAL;
-- }
-+ BUG_ON(!xpd);
- xbus = xpd->xbus;
- DBG("%s (%d) (old=0x%04X, hook-command=%d)\n", chan->name, pos, xpd->hookstate, hookstate);
-- switch(hookstate) {
-- /* On-hook, off-hook: The PBX is playing a phone on an FXO line.
-- * Can be ignored for an FXS line
-- */
-- case ZT_ONHOOK:
-- if(IS_SET(xpd->digital_inputs, pos)) {
-- NOTICE("%s: Trying to ONHOOK a digital input channel %d. Ignoring\n", __FUNCTION__, pos);
-- return -EINVAL;
-- }
-- if(IS_SET(xpd->digital_outputs, pos)) {
-- DBG("ZT_ONHOOK %s digital output OFF\n", chan->name);
-- ret = CALL_XMETHOD(RELAY_OUT, xpd->xbus, xpd, pos-8, 0);
-- return ret;
-- }
-- if(xpd->direction == TO_PHONE) { /* Stop ring */
-- DBG("ZT_ONHOOK: %s hookstate=0x%04X (stop ringing pos=%d)\n", chan->name, xpd->hookstate, pos);
-- xpd->ringing[pos] = 0;
--#if 1 // FIXME: Not needed -- verify
-- ret = CALL_XMETHOD(RING, xbus, xpd, pos, 0); // RING off
--#endif
-- xpd->lasttxhook[pos] = 1;
-- ret = CALL_XMETHOD(LED, xpd->xbus, xpd, BIT(pos), LED_GREEN, 0);
-- ret = CALL_XMETHOD(CHAN_POWER, xbus, xpd, BIT(pos), 0); // Power down (prevent overheating!!!)
-- if(ret) {
-- DBG("ZT_ONHOOK(stop ring) Failed: ret=0x%02X\n", ret);
-- break;
-- }
-- } else {
-- DBG("ZT_ONHOOK: %s hookstate=0x%04X (pos=%d)\n", chan->name, xpd->hookstate, pos);
-- xpd->ringing[pos] = 0;
-- BIT_CLR(xpd->hookstate, pos);
-- ret = CALL_XMETHOD(SETHOOK, xbus, xpd, xpd->hookstate);
-- if(ret) {
-- DBG("ZT_ONHOOK Failed: ret=0x%02X\n", ret);
-- break;
-- }
-- }
-- break;
-- case ZT_START:
-- DBG("ZT_START: %s hookstate=0x%04X (fall through ZT_OFFHOOK)\n", chan->name, xpd->hookstate);
-- // Fall through
-- case ZT_OFFHOOK:
-- if(xpd->direction == TO_PHONE) {
-- DBG("ZT_OFFHOOK: %s hookstate=0x%04X -- ignoring (PHONE)\n", chan->name, xpd->hookstate);
-- break;
-- }
-- DBG("ZT_OFFHOOK: %s hookstate=0x%04X (pos=%d)\n", chan->name, xpd->hookstate, pos);
-- BIT_SET(xpd->hookstate, pos);
-- xpd->ringing[pos] = 0;
-- ret = CALL_XMETHOD(SETHOOK, xbus, xpd, xpd->hookstate);
-- if(ret) {
-- DBG("ZT_OFFHOOK Failed: ret=0x%02X\n", ret);
-- break;
-- }
-- break;
-- case ZT_WINK:
-- DBG("ZT_WINK %s\n", chan->name);
-- break;
-- case ZT_FLASH:
-- DBG("ZT_FLASH %s\n", chan->name);
-- break;
-- case ZT_RING:
-- DBG("ZT_RING %s pos=%d (ringing[pos]=%d)\n", chan->name, pos, xpd->ringing[pos]);
-- if(xpd->direction == TO_PHONE) {
-- if(IS_SET(xpd->digital_inputs, pos)) {
-- NOTICE("%s: Trying to RING a digital input channel %d. Ignoring\n", __FUNCTION__, pos);
-- return -EINVAL;
-- }
-- if(IS_SET(xpd->digital_outputs, pos)) {
-- DBG("ZT_ONHOOK %s digital output ON\n", chan->name);
-- ret = CALL_XMETHOD(RELAY_OUT, xpd->xbus, xpd, pos-8, 1);
-- return ret;
-- }
-- xpd->ringing[pos] = RINGS_NUM*2;
-- ret = CALL_XMETHOD(CHAN_POWER, xbus, xpd, BIT(pos), 1); // Power up (for ring)
-- ret = CALL_XMETHOD(RING, xbus, xpd, pos, 1); // RING on
-- if(ret) {
-- DBG("ZT_RING Failed: ret=0x%02X\n", ret);
-- }
-- }
-- break;
-- case ZT_RINGOFF:
-- DBG("ZT_RINGOFF %s\n", chan->name);
-- break;
-- default:
-- DBG("UNKNOWN hookstate=0x%X\n", hookstate);
-- }
-+ ret = CALL_XMETHOD(card_sethook, xpd->xbus, xpd, pos, hookstate);
- return ret;
- }
-
-+#endif
-+
- /* Req: Set the requested chunk size. This is the unit in which you must
- report results for conferencing, etc */
- int xpp_setchunksize(struct zt_span *span, int chunksize);
-@@ -1815,7 +1168,6 @@
- switch(cmd) {
- case ZT_MAINT_NONE:
- printk("XXX Turn off local and remote loops XXX\n");
-- CALL_XMETHOD(LED, xpd->xbus, xpd, xpd->enabled_chans, LED_RED, 0); // FIXME: Find usage for extra LED
- break;
- case ZT_MAINT_LOCALLOOP:
- printk("XXX Turn on local loopback XXX\n");
-@@ -1825,12 +1177,10 @@
- break;
- case ZT_MAINT_LOOPUP:
- printk("XXX Send loopup code XXX\n");
-- CALL_XMETHOD(LED, xpd->xbus, xpd, xpd->enabled_chans, LED_RED, 1); // FIXME: Find usage for extra LED
- // CALL_XMETHOD(LOOPBACK_AX, xpd->xbus, xpd, loopback_data, ARRAY_SIZE(loopback_data));
- break;
- case ZT_MAINT_LOOPDOWN:
- printk("XXX Send loopdown code XXX\n");
-- CALL_XMETHOD(LED, xpd->xbus, xpd, xpd->enabled_chans, LED_RED, 0); // FIXME: Find usage for extra LED
- break;
- case ZT_MAINT_LOOPSTOP:
- printk("XXX Stop sending loop codes XXX\n");
-@@ -1848,8 +1198,7 @@
- /* Set signalling type (if appropriate) */
- static int xpp_chanconfig(struct zt_chan *chan, int sigtype)
- {
-- DBG("channel %d (%s), sigtype %d.\n", chan->channo, chan->name, sigtype);
-- dump_sigtype(print_dbg, " ", sigtype);
-+ DBG("channel %d (%s) -> %s\n", chan->channo, chan->name, sig2str(sigtype));
- // FIXME: sanity checks:
- // - should be supported (within the sigcap)
- // - should not replace fxs <->fxo ??? (covered by previous?)
-@@ -1878,6 +1227,29 @@
- int (*sethook)(struct zt_chan *chan, int hookstate);
- #endif
-
-+#ifdef XPP_EC_CHUNK
-+static int xpp_echocan(struct zt_chan *chan, int len)
-+{
-+ if(len == 0) { /* shut down */
-+ /* zaptel calls this also during channel initialization */
-+ if(chan->ec) {
-+ xpp_echo_can_free(chan->ec);
-+ }
-+ return 0;
-+ }
-+ if(chan->ec) {
-+ ERR("%s: Trying to override an existing EC (%p)\n", __FUNCTION__, chan->ec);
-+ return -EINVAL;
-+ }
-+ chan->ec = xpp_echo_can_create(len, 0);
-+ if(!chan->ec) {
-+ ERR("%s: Failed creating xpp EC (len=%d)\n", __FUNCTION__, len);
-+ return -EINVAL;
-+ }
-+ return 0;
-+}
-+#endif
-+
- #ifdef CONFIG_ZAPTEL_WATCHDOG
- /*
- * If the watchdog detects no received data, it will call the
-@@ -1904,33 +1276,40 @@
- * - User action through /proc
- * - During xpd_remove()
- */
--static int xpd_zaptel_unregister(xpd_t *xpd)
-+static int zaptel_unregister_xpd(xpd_t *xpd)
- {
-+ unsigned long flags;
-+
- BUG_ON(!xpd);
-+ spin_lock_irqsave(&xpd->lock, flags);
-
- if(!SPAN_REGISTERED(xpd)) {
- NOTICE("%s: %s is already unregistered\n", __FUNCTION__, xpd->xpdname);
-+ spin_unlock_irqrestore(&xpd->lock, flags);
- return -EIDRM;
- }
- if(sync_master == xpd)
-- set_sync_master(NULL); // FIXME: it's better to elect a new prince
-+ sync_master_is(NULL); // FIXME: it's better to elect a new prince
- update_xpd_status(xpd, ZT_ALARM_NOTOPEN);
- if(atomic_read(&xpd->open_counter)) {
- NOTICE("%s: %s is busy (open_counter=%d). Skipping.\n", __FUNCTION__, xpd->xpdname, atomic_read(&xpd->open_counter));
-+ spin_unlock_irqrestore(&xpd->lock, flags);
- return -EBUSY;
- }
- mdelay(2); // FIXME: This is to give chance for transmit/receiveprep to finish.
-+ spin_unlock_irqrestore(&xpd->lock, flags);
-+ if(xpd->card_present)
-+ xpd->xops->card_zaptel_preregistration(xpd, 0);
- zt_unregister(&xpd->span);
-+ if(xpd->card_present)
-+ xpd->xops->card_zaptel_postregistration(xpd, 0);
- return 0;
- }
-
--static int xpd_zaptel_register(xpd_t *xpd)
-+static int zaptel_register_xpd(xpd_t *xpd)
- {
-- struct zt_chan *cur_chan;
- struct zt_span *span;
- xbus_t *xbus;
-- int sigfxs;
-- int i;
- int cn;
- const xops_t *xops;
-
-@@ -1941,7 +1320,6 @@
- ERR("xpd %s already registered\n", xpd->xpdname);
- return -EEXIST;
- }
-- sigfxs = ! (xpd->direction == TO_PHONE); /* signaling is opposite */
- cn = xpd->channels;
- DBG("Initializing span: xpd %d have %d channels.\n", xpd->id, cn);
-
-@@ -1950,59 +1328,7 @@
-
- span = &xpd->span;
- xbus = xpd->xbus;
-- snprintf(span->name, MAX_SPANNAME, "%s/%s",
-- xbus->busname, xpd->xpdname);
-- {
-- char tmp[MAX_SPANNAME];
--#if SOFT_SIMULATOR
-- struct xpd_sim *sim = &xbus->sim[xpd->id];
--
-- if(sim->simulated)
-- snprintf(tmp, MAX_SPANNAME, " (sim to=%d)", sim->loopto);
-- else
--#endif
-- tmp[0] = '\0';
--
-- snprintf(span->desc, MAX_SPANDESC, "Xorcom XPD #%d/%d: %s%s",
-- xbus->num, xpd->id,
-- (xpd->direction == TO_PHONE) ? "FXS" : "FXO",
-- tmp
-- );
-- }
-- for(i = 0; i < cn; i++) {
--
-- cur_chan = &xpd->chans[i];
-- DBG("setting channel %d (sigfxs=%d)\n", i, sigfxs);
-- if(IS_SET(xpd->digital_outputs, i)) {
-- snprintf(cur_chan->name, MAX_CHANNAME, "XPP_OUT/%d-%d", xpd->id, i);
-- } else if(IS_SET(xpd->digital_inputs, i)) {
-- snprintf(cur_chan->name, MAX_CHANNAME, "XPP_IN/%d-%d", xpd->id, i);
-- } else {
-- snprintf(cur_chan->name, MAX_CHANNAME, "XPP_%s/%d-%d", (sigfxs) ? "FXO" : "FXS", xpd->id, i);
-- }
-- cur_chan->chanpos = i + 1;
-- cur_chan->pvt = xpd;
-- if (sigfxs)
-- cur_chan->sigcap =
--#if 1
-- ZT_SIG_FXSKS |
-- ZT_SIG_FXSLS |
--#else
-- ZT_SIG_SF |
--#endif
-- 0;
-- else
-- cur_chan->sigcap =
--#if 1
-- ZT_SIG_FXOKS |
-- ZT_SIG_FXOLS |
-- ZT_SIG_FXOGS |
--#else
-- ZT_SIG_SF |
-- ZT_SIG_EM |
--#endif
-- 0;
-- }
-+ snprintf(span->name, MAX_SPANNAME, "%s/%s", xbus->busname, xpd->xpdname);
- span->deflaw = ZT_LAW_MULAW;
- init_waitqueue_head(&span->maintq);
- span->pvt = xpd;
-@@ -2023,67 +1349,28 @@
- #endif
- span->ioctl = xpp_ioctl;
- span->maint = xpp_maint;
-+#ifdef XPP_EC_CHUNK
-+ span->echocan = xpp_echocan;
-+#endif
- #ifdef CONFIG_ZAPTEL_WATCHDOG
- span->watchdog = xpp_watchdog;
- #endif
-
-- DBG("Finished span_load: ZT_FLAG_RUNNING=%d\n", span->flags & ZT_FLAG_RUNNING);
--
- DBG("Registering span of %s.\n", xpd->xpdname);
-+ xpd->xops->card_zaptel_preregistration(xpd, 1);
- if(zt_register(&xpd->span, 1)) {
- xbus_t *xbus = xpd->xbus;
-- ERR("Failed to zt_register of span of xpd %s.\n", xpd->xpdname);
-- xbus->xpds[xpd->id] = NULL;
-- list_del(&xpd->xpd_list);
-- xbus->num_xpds--;
-+ ERR("%s/%s: Failed to zt_register span\n", xbus->busname, xpd->xpdname);
- return -ENODEV;
- }
--// if(xpd->id == 0)
--// set_sync_master(xpd);
--
-+ xpd->xops->card_zaptel_postregistration(xpd, 1);
- return 0;
- }
-
--
- /*------------------------- Proc debugging interface ---------------*/
-
- #ifdef CONFIG_PROC_FS
-
--static int xpp_zap_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
--{
-- int len = 0;
-- unsigned long flags;
-- int i;
--
-- spin_lock_irqsave(&xbuses_lock, flags);
-- for(i = 0; i < MAX_BUSES; i++) {
-- xbus_t *xbus = xbus_of(i);
--
-- if(xbus) {
-- len += sprintf(page + len, "%s: CONNECTOR=%s STATUS=%s bus_type=%d\n",
-- xbus->busname,
-- xbus->busdesc,
-- (xbus->hardware_exists) ? "connected" : "missing",
-- xbus->bus_type
-- );
-- }
-- }
--#if 0
-- len += sprintf(page + len, "<-- len=%d\n", len);
--#endif
-- spin_unlock_irqrestore(&xbuses_lock, flags);
-- if (len <= off+count)
-- *eof = 1;
-- *start = page + off;
-- len -= off;
-- if (len > count)
-- len = count;
-- if (len < 0)
-- len = 0;
-- return len;
--
--}
--
- #if 0
- static int xpp_zap_write_proc(struct file *file, const char __user *buffer, unsigned long count, void *data)
- {
-@@ -2097,6 +1384,7 @@
- #define MINOR_XBUS_NUM(m) ((m) >> 4)
- #define MINOR_XPD_NUM(m) ((m) & 0xF);
-
-+#if 0
- static int xpp_sys_open (struct inode * inode, struct file * file)
- {
- xbus_t *xbus;
-@@ -2164,7 +1452,7 @@
- if (copy_from_user (pack_tx->content.raw, buf, count)) {
- return -EFAULT;
- }
-- XPD_ADDR_SET(pack_tx->content.addr, xpdnum);
-+ xpd_set_addr(&pack_tx->content.addr, xpdnum);
- pack_tx->datalen = count;
- // pack_tx->flags |= XPP_PACKET_FIREANDFORGET;
- DBG("sending op=%d to %d\n", pack_tx->content.opcode, xpdnum);
-@@ -2186,6 +1474,7 @@
- .release = xpp_sys_release,
- };
-
-+#endif
-
- /*------------------------- Initialization -------------------------*/
-
-@@ -2193,42 +1482,47 @@
- {
- if(timer_pending(&xpp_timer))
- del_timer_sync(&xpp_timer);
-+#if 0
- unregister_chrdev(XPP_CTL_MAJOR, THIS_MODULE->name);
-+#endif
- #ifdef CONFIG_PROC_FS
-- remove_proc_entry(PROC_SYNC, xpp_procdir);
-- remove_proc_entry(PROC_XBUSES, xpp_procdir);
-- if(xpp_procdir) {
-+ remove_proc_entry(PROC_SYNC, xpp_proc_toplevel);
-+ if(xpp_proc_toplevel) {
- remove_proc_entry(PROC_DIR, NULL);
- }
- #endif
-- if (xpp_worker) {
-- flush_workqueue(xpp_worker);
-- destroy_workqueue(xpp_worker);
-- xpp_worker = NULL;
-- }
-- kmem_cache_destroy(packet_cache);
- }
-
- int __init xpp_zap_init(void)
- {
-- INFO("%s revision %s\n", THIS_MODULE->name, revision);
-+ int ret;
-+ struct proc_dir_entry *ent;
-+
-+ INFO("%s revision %s\n", THIS_MODULE->name, ZAPTEL_VERSION);
-+#ifdef WITH_RBS
-+ INFO("FEATURE: %s (RBS signalling)\n", THIS_MODULE->name);
-+#else
-+ INFO("FEATURE: %s (NO RBS signalling)\n", THIS_MODULE->name);
-+#endif
-+#if WITH_ECHO_SUPPRESSION
-+ INFO("FEATURE: %s (with ECHO_SUPPRESSION)\n", THIS_MODULE->name);
-+#else
-+ INFO("FEATURE: %s (without ECHO_SUPPRESSION)\n", THIS_MODULE->name);
-+#endif
-+#ifdef XPP_EC_CHUNK
-+ INFO("FEATURE: %s (with XPP_EC_CHUNK)\n", THIS_MODULE->name);
-+#else
-+ INFO("FEATURE: %s (without XPP_EC_CHUNK)\n", THIS_MODULE->name);
-+#endif
-
-- packet_cache = kmem_cache_create("xpp_packets",
-- sizeof(xpacket_t),
-- 0, 0,
-- NULL, NULL);
-- if(!packet_cache) {
-- return -ENOMEM;
-- }
- #ifdef CONFIG_PROC_FS
-- xpp_procdir = proc_mkdir(PROC_DIR, NULL);
-- if(!xpp_procdir) {
-+ xpp_proc_toplevel = proc_mkdir(PROC_DIR, NULL);
-+ if(!xpp_proc_toplevel) {
- do_cleanup();
- return -EIO;
- }
-- struct proc_dir_entry *ent;
-
-- ent = create_proc_entry(PROC_SYNC, 0644, xpp_procdir);
-+ ent = create_proc_entry(PROC_SYNC, 0644, xpp_proc_toplevel);
- if(!ent) {
- do_cleanup();
- return -EFAULT;
-@@ -2236,67 +1530,42 @@
- ent->read_proc = proc_sync_read;
- ent->write_proc = proc_sync_write;
- ent->data = NULL;
-- ent = create_proc_read_entry(PROC_XBUSES, 0444, xpp_procdir, xpp_zap_read_proc, 0);
-- if (!ent) {
-- do_cleanup();
-- return -EFAULT;
-- }
- #endif
-- xpp_worker = create_singlethread_workqueue("xppworker");
-- if(!xpp_worker) {
-- ERR("Failed to create card detector workqueue.\n");
-+ ret = xbus_core_init();
-+ if(ret) {
-+ ERR("xbus_core_init failed (%d)\n", ret);
- do_cleanup();
-- return -ENOMEM;
-+ return ret;
- }
-
-+#if 0
- if (register_chrdev(XPP_CTL_MAJOR, THIS_MODULE->name, &xpp_fops)) {
- printk (KERN_WARNING "%s: unable to get major %d\n", THIS_MODULE->name, XPP_CTL_MAJOR);
- do_cleanup();
- return -EIO;
- }
-+#endif
-
- /* Only timer init. We add it only *after* zt_register */
- init_timer(&xpp_timer);
-- set_sync_master(NULL); /* Internal ticking */
-+ sync_master_is(NULL); /* Internal ticking */
- return 0;
- }
-
- void __exit xpp_zap_cleanup(void)
- {
--// unsigned long flags;
-- int i;
--
-- for(i = 0; i < MAX_BUSES; i++) {
-- xbus_t *xbus = xbus_of(i);
-- if(!xbus)
-- continue;
-- xbus_remove(xbus);
-- }
--// spin_lock_irqsave(&xbuses_lock, flags);
-- if(bus_count) {
-- ERR("%s: bus_count=%d!\n", __FUNCTION__, bus_count);
-- }
--// spin_unlock_irqrestore(&xbuses_lock, flags);
-+ xbus_core_shutdown();
- do_cleanup();
- }
-
- EXPORT_SYMBOL(print_dbg);
- EXPORT_SYMBOL(card_detected);
- EXPORT_SYMBOL(xpd_alloc);
--EXPORT_SYMBOL(xbus_activate);
--EXPORT_SYMBOL(xbus_deactivate);
--EXPORT_SYMBOL(xpd_of);
--EXPORT_SYMBOL(xbus_new);
--EXPORT_SYMBOL(xbus_remove);
--EXPORT_SYMBOL(xbus_reset_counters);
-+EXPORT_SYMBOL(xpd_disconnect);
- EXPORT_SYMBOL(packet_send);
-+EXPORT_SYMBOL(update_xpd_status);
-+EXPORT_SYMBOL(update_line_status);
- EXPORT_SYMBOL(fill_beep);
--EXPORT_SYMBOL(xbus_enqueue_packet);
--EXPORT_SYMBOL(xbus_dequeue_packet);
--EXPORT_SYMBOL(init_xbus_packet_queue);
--EXPORT_SYMBOL(drain_xbus_packet_queue);
--EXPORT_SYMBOL(phone_hook);
--EXPORT_SYMBOL(xpp_check_hookstate);
- EXPORT_SYMBOL(xpp_tick);
- EXPORT_SYMBOL(xpp_open);
- EXPORT_SYMBOL(xpp_close);
-@@ -2306,7 +1575,7 @@
- MODULE_DESCRIPTION("XPP Zaptel Driver");
- MODULE_AUTHOR("Oron Peled <oron at actcom.co.il>");
- MODULE_LICENSE("GPL");
--MODULE_VERSION("$Id: xpp_zap.c 995 2006-04-03 07:08:13Z tzafrir $");
-+MODULE_VERSION(ZAPTEL_VERSION);
-
- module_init(xpp_zap_init);
- module_exit(xpp_zap_cleanup);
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/xpp_zap.h zaptel-xpp-LJNBCn_dist/xpp/xpp_zap.h
---- zaptel-1.2.6/xpp/xpp_zap.h 2006-02-15 04:24:18.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/xpp_zap.h 2006-07-02 19:47:41.666262000 +0300
-@@ -1,58 +1,54 @@
- #ifndef XPP_ZAP_H
- #define XPP_ZAP_H
-+/*
-+ * Written by Oron Peled <oron at actcom.co.il>
-+ * Copyright (C) 2004-2006, Xorcom
-+ *
-+ * All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ */
-
- #include <linux/workqueue.h>
- #include "xpd.h"
- #include "xproto.h"
-
--xpacket_t *xpacket_new(xbus_t *xbus, int flags);
--void xpacket_free(xbus_t *xbus, xpacket_t *p);
--
--/* packet queues */
--void init_xbus_packet_queue(packet_queue_t *q, const char name[]);
--void drain_xbus_packet_queue(xbus_t *xbus, packet_queue_t *q);
--void xbus_enqueue_packet(xbus_t *xbus, packet_queue_t *q, xpacket_t *pack);
--xpacket_t *xbus_dequeue_packet(packet_queue_t *q);
--
--xbus_t *xbus_new(ulong loopback_xpds);
--void xbus_activate(xbus_t *xbus);
--void xbus_deactivate(xbus_t *xbus);
--
--void xbus_reset_counters(xbus_t *xbus);
-+void xpd_disconnect(xpd_t *xpd);
- int packet_send(xbus_t *xbus, xpacket_t *pack_tx);
--void phone_hook(xpd_t *xpd, int channo, bool offhook);
--void xpp_check_hookstate(xpd_t *xpd, xpp_line_t fxs_off_hook);
--xpd_t *xpd_of(xbus_t *xbus, int xpd_num);
--void card_detected(void *data);
-+void card_detected(struct card_desc_struct *card_desc);
- xpd_t *xpd_alloc(size_t privsize, xbus_t *xbus, int xpd_num, const xproto_table_t *proto_table, int channels, byte revision);
- void xpd_remove(xpd_t *xpd);
-+void update_xpd_status(xpd_t *xpd, int alarm_flag);
-+void update_line_status(xpd_t *xpd, int pos, bool good);
- void fill_beep(u_char *buf, int duration);
- void xpp_tick(unsigned long param);
- int xpp_open(struct zt_chan *chan);
- int xpp_close(struct zt_chan *chan);
- int xpp_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long arg);
- int xpp_maint(struct zt_span *span, int cmd);
-+void sync_master_is(xpd_t *xpd);
-
--#define CARD_DESC_MAGIC 0xca9dde5c
--
--struct card_desc_struct {
-- struct work_struct work;
-- u32 magic;
-- xbus_t *xbus;
-- byte rev; /* Revision number */
-- byte type; /* LSB: 1 - to_phone, 0 - to_line */
-- byte xpd_num;
--};
- extern struct workqueue_struct *xpp_worker;
-
- #ifdef CONFIG_PROC_FS
- #include <linux/proc_fs.h>
-
--extern struct proc_dir_entry *xpp_procdir;
-+extern struct proc_dir_entry *xpp_proc_toplevel;
- #endif
--extern xpd_t *sync_master;
-
--// Number of rings our simulated phone will ring:
--#define RINGS_NUM 3
-+#define SPAN_REGISTERED(xpd) ((xpd)->span.flags & ZT_FLAG_REGISTERED)
-
- #endif /* XPP_ZAP_H */
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/xproto.c zaptel-xpp-LJNBCn_dist/xpp/xproto.c
---- zaptel-1.2.6/xpp/xproto.c 2006-02-15 04:24:18.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/xproto.c 2006-07-03 12:11:26.109424000 +0300
-@@ -1,6 +1,6 @@
- /*
- * Written by Oron Peled <oron at actcom.co.il>
-- * Copyright (C) 2004-2005, Xorcom
-+ * Copyright (C) 2004-2006, Xorcom
- *
- * All rights reserved.
- *
-@@ -23,35 +23,36 @@
- #include "xpd.h"
- #include "xproto.h"
- #include "xpp_zap.h"
-+#include "xbus-core.h"
-+#include "zap_debug.h"
- #include <linux/module.h>
-
--static const char rcsid[] = "$Id: xproto.c 949 2006-02-15 02:24:18Z kpfleming $";
-+static const char rcsid[] = "$Id: xproto.c 1543 2006-07-03 09:11:26Z oron $";
-
- extern int print_dbg;
- static int packet_process(xbus_t *xbus, int xpd_num, xpacket_t *pack);
-
- static const xproto_table_t *xprotocol_tables[XPD_TYPE_NOMODULE];
-
-+#if MAX_UNIT*MAX_SUBUNIT > MAX_XPDS
-+#error MAX_XPDS is too small
-+#endif
-+
- bool valid_xpd_addr(const xpd_addr_t *addr)
- {
-- return ((addr->bank_num & ~0x1) == 0) && ((addr->card_id & ~0x3) == 0);
-+ return ((addr->subunit & ~0x1) == 0) && ((addr->unit & ~0x3) == 0);
- }
-
- int xpd_addr2num(const xpd_addr_t *addr)
- {
- BUG_ON(!valid_xpd_addr(addr));
-- return addr->bank_num * 4 + addr->card_id;
-+ return addr->unit + addr->subunit * MAX_UNIT;
- }
-
- void xpd_set_addr(xpd_addr_t *addr, int xpd_num)
- {
-- if(xpd_num < 4) {
-- addr->card_id = xpd_num;
-- addr->bank_num = 0;
-- } else {
-- addr->card_id = xpd_num % 4;
-- addr->bank_num = xpd_num / 4;
-- }
-+ addr->unit = xpd_num % MAX_UNIT;
-+ addr->subunit = xpd_num / MAX_UNIT;
- }
-
-
-@@ -75,7 +76,7 @@
- return xe;
- }
-
--const xproto_handler_t xproto_global_handler(byte opcode)
-+xproto_handler_t xproto_global_handler(byte opcode)
- {
- return xproto_card_handler(&PROTO_TABLE(GLOBAL), opcode);
- }
-@@ -87,7 +88,7 @@
- return xprotocol_tables[cardtype];
- }
-
--const xproto_table_t *get_xproto_table(xpd_type_t cardtype)
-+const xproto_table_t *xproto_get(xpd_type_t cardtype)
- {
- const xproto_table_t *xtable;
-
-@@ -95,18 +96,34 @@
- return NULL;
- xtable = xprotocol_tables[cardtype];
- if(!xtable) { /* Try to load the relevant module */
-- int ret = request_module("xpd-type-%d", cardtype);
-+ int ret = request_module(XPD_TYPE_PREFIX "%d", cardtype);
- if(ret != 0) {
- NOTICE("%s: Failed to load module for type=%d. exit status=%d.\n",
- __FUNCTION__, cardtype, ret);
-- /* Drop through: we may be luck... */
-+ /* Drop through: we may be lucky... */
- }
- xtable = xprotocol_tables[cardtype];
- }
-+ if(xtable) {
-+ BUG_ON(!xtable->owner);
-+ DBG("%s refcount was %d\n", xtable->name, module_refcount(xtable->owner));
-+ if(!try_module_get(xtable->owner)) {
-+ ERR("%s: try_module_get for %s failed.\n", __FUNCTION__, xtable->name);
-+ return NULL;
-+ }
-+ }
- return xtable;
- }
-
--const xproto_handler_t xproto_card_handler(const xproto_table_t *table, byte opcode)
-+void xproto_put(const xproto_table_t *xtable)
-+{
-+ BUG_ON(!xtable);
-+ DBG("%s refcount was %d\n", xtable->name, module_refcount(xtable->owner));
-+ BUG_ON(module_refcount(xtable->owner) <= 0);
-+ module_put(xtable->owner);
-+}
-+
-+xproto_handler_t xproto_card_handler(const xproto_table_t *table, byte opcode)
- {
- const xproto_entry_t *xe;
-
-@@ -115,7 +132,7 @@
- return xe->handler;
- }
-
--const xproto_entry_t *find_xproto_entry(xpd_t *xpd, byte opcode)
-+static const xproto_entry_t *find_xproto_entry(xpd_t *xpd, byte opcode)
- {
- const xproto_entry_t *xe;
-
-@@ -136,18 +153,6 @@
- return xe;
- }
-
--const xops_t *get_xops(xpd_type_t xpd_type)
--{
-- const xproto_table_t *proto_table;
--
-- if(xpd_type >= XPD_TYPE_NOMODULE)
-- return NULL;
-- proto_table = xprotocol_tables[xpd_type];
-- if(!proto_table)
-- return NULL;
-- return &proto_table->xops;
--}
--
- int packet_receive(xbus_t *xbus, xpacket_t *pack)
- {
- int xpd_num;
-@@ -161,7 +166,7 @@
- return -EPROTO;
- }
- xpd_num = XPD_NUM(pack->content.addr);
--#if SOFT_SIMULATOR
-+#ifdef SOFT_SIMULATOR
- if(xbus->sim[xpd_num].simulated) {
- //dump_packet("packet_receive -> simulate", pack, print_dbg);
- return simulate_xpd(xbus, xpd_num, pack);
-@@ -189,7 +194,8 @@
- xe = find_xproto_entry(xpd, op);
- /*-------- Validations -----------*/
- if(!xe) {
-- ERR("xpp: %s -- bad command op=0x%02X\n", __FUNCTION__, op);
-+ ERR("xpp: %s: %s unit #%d: bad command op=0x%02X\n",
-+ __FUNCTION__, xbus->busname, xpd_num, op);
- dump_packet("packet_process -- bad command", pack, print_dbg);
- ret = -EPROTO;
- goto out;
-@@ -221,10 +227,10 @@
-
- if(!print_dbg)
- return;
-- DBG("%s: @0x%1X%1X OP=0x%02X LEN=%d\n",
-+ DBG("%s: U=0x%1X S=0x%1X OP=0x%02X LEN=%d\n",
- msg,
-- packet->content.addr.bank_num,
-- packet->content.addr.card_id,
-+ packet->content.addr.unit,
-+ packet->content.addr.subunit,
- op,
- (byte)packet->datalen);
- #if VERBOSE_DEBUG
-@@ -256,7 +262,7 @@
- {
- const xproto_table_t *proto_table;
-
-- BUG_ON(xpd_type >= XPD_TYPE(NOMODULE));
-+ BUG_ON(xpd_type >= XPD_TYPE_NOMODULE);
- proto_table = xprotocol_tables[xpd_type];
- if(!proto_table)
- return NULL;
-@@ -278,7 +284,7 @@
- BUG_ON(!proto_table);
- type = proto_table->type;
- name = proto_table->name;
-- if(type >= XPD_TYPE(NOMODULE)) {
-+ if(type >= XPD_TYPE_NOMODULE) {
- NOTICE("%s: Bad xproto type %d\n", __FUNCTION__, type);
- return -EINVAL;
- }
-@@ -290,14 +296,20 @@
- CHECK_XOP(card_init);
- CHECK_XOP(card_remove);
- CHECK_XOP(card_tick);
-+ CHECK_XOP(card_zaptel_preregistration);
-+ CHECK_XOP(card_zaptel_postregistration);
-+#ifdef WITH_RBS
-+ CHECK_XOP(card_hooksig);
-+#else
-+ CHECK_XOP(card_sethook);
-+#endif
-+ // CHECK_XOP(card_ioctl); // optional method -- call after testing
- CHECK_XOP(SYNC_SOURCE);
- CHECK_XOP(PCM_WRITE);
- CHECK_XOP(CHAN_ENABLE);
-- CHECK_XOP(CHAN_POWER);
- CHECK_XOP(CHAN_CID);
- CHECK_XOP(RING);
- CHECK_XOP(SETHOOK);
-- CHECK_XOP(LED);
- CHECK_XOP(RELAY_OUT);
-
- xprotocol_tables[type] = proto_table;
-@@ -313,7 +325,7 @@
- type = proto_table->type;
- name = proto_table->name;
- DBG("%s (%d)\n", name, type);
-- if(type >= XPD_TYPE(NOMODULE)) {
-+ if(type >= XPD_TYPE_NOMODULE) {
- NOTICE("%s: Bad xproto type %s (%d)\n", __FUNCTION__, name, type);
- return;
- }
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/xproto.h zaptel-xpp-LJNBCn_dist/xpp/xproto.h
---- zaptel-1.2.6/xpp/xproto.h 2006-02-15 04:24:18.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/xproto.h 2006-07-03 13:44:48.152691000 +0300
-@@ -2,7 +2,7 @@
- #define XPROTO_H
- /*
- * Written by Oron Peled <oron at actcom.co.il>
-- * Copyright (C) 2004-2005, Xorcom
-+ * Copyright (C) 2004-2006, Xorcom
- *
- * All rights reserved.
- *
-@@ -26,31 +26,39 @@
-
- #ifdef __KERNEL__
- #include <linux/list.h>
-+#include <zaptel.h>
- #endif
-
--#define XPD_TYPE(n) XPD_TYPE_ ## n
- #define PROTO_TABLE(n) n ## _protocol_table
-
--typedef enum xpd_type {
-- XPD_TYPE(FXO) = 0x02,
-- XPD_TYPE(FXS) = 0x03,
-- XPD_TYPE(NOMODULE) = 0x0F,
--} xpd_type_t;
-+/*
-+ * The LSB of the type number signifies:
-+ * 0 - TO_PSTN
-+ * 1 - TO_PHONE
-+ */
-+#define XPD_TYPE_FXS 3 // TO_PHONE
-+#define XPD_TYPE_FXO 4 // TO_PSTN
-+#define XPD_TYPE_NOMODULE 15
-+
-+typedef byte xpd_type_t;
-+
-+#define XPD_TYPE_PREFIX "xpd-type-"
-+
-+#define MODULE_ALIAS_XPD(type) \
-+ MODULE_ALIAS(XPD_TYPE_PREFIX __stringify(type))
-
--#define LINE_BITS (sizeof(xpp_line_t)*8)
- #define PCM_CHUNKSIZE (CHANNELS_PERXPD * 8) /* samples of 8 bytes */
-
- typedef struct xpd_addr {
-- byte card_id:4;
-- byte bank_num:4;
--} __attribute__((packed)) xpd_addr_t;
-+ byte unit:UNIT_BITS;
-+ byte subunit:SUBUNIT_BITS;
-+} PACKED xpd_addr_t;
-
- bool valid_xpd_addr(const xpd_addr_t *addr);
- int xpd_addr2num(const xpd_addr_t *addr);
- void xpd_set_addr(xpd_addr_t *addr, int xpd_num);
-
- #define XPD_NUM(x) xpd_addr2num(&x)
--#define XPD_ADDR_SET(x,val) xpd_set_addr(&x, val)
- #define MAX_XPACKET_DATALEN 100
-
- #define XPROTO_NAME(card,op) card ## _ ## op
-@@ -82,11 +90,12 @@
- byte opcode; \
- xpd_addr_t addr; \
- __VA_ARGS__ \
-- } __attribute__((packed))
-+ } PACKED
-
- #define RPACKET_CAST(p,card,op) ((RPACKET_TYPE(card,op) *)p)
- #define RPACKET_FIELD(p,card,op,field) (RPACKET_CAST(p,card,op)->field)
- #define RPACKET_SIZE(card,op) sizeof(RPACKET_TYPE(card,op))
-+#define RPACKET_DATALEN(card,op) (RPACKET_SIZE(card,op) - sizeof(xpd_addr_t) - 1)
-
- #define PACKET_LEN(p) \
- ((p)->datalen + sizeof(xpd_addr_t) + 1)
-@@ -94,7 +103,7 @@
- #define XENTRY(card,op) \
- [ XPROTO_NAME(card,op) ] { \
- .handler = XPROTO_HANDLER(card,op), \
-- .datalen = RPACKET_SIZE(card,op), \
-+ .datalen = RPACKET_DATALEN(card,op), \
- .name = #op, \
- .table = &PROTO_TABLE(card) \
- }
-@@ -103,7 +112,7 @@
- #define XPACKET_INIT(p, card, op) \
- do { \
- p->content.opcode = XPROTO_NAME(card,op); \
-- p->datalen = RPACKET_SIZE(card,op); \
-+ p->datalen = RPACKET_DATALEN(card,op); \
- } while(0)
-
- #define XPACKET_NEW(p, xbus, card, op, to) \
-@@ -112,7 +121,7 @@
- if(!p) \
- return -ENOMEM; \
- XPACKET_INIT(p, card, op); \
-- XPD_ADDR_SET(p->content.addr, to); \
-+ xpd_set_addr(&p->content.addr, to); \
- } while(0);
-
- typedef struct xproto_entry xproto_entry_t;
-@@ -124,14 +133,13 @@
- const xproto_entry_t *cmd,
- xpacket_t *pack);
-
--const xproto_entry_t *find_xproto_entry(xpd_t *xpd, byte opcode);
--
--const xproto_table_t *get_xproto_table(xpd_type_t cardtype);
-+const xproto_table_t *xproto_get(xpd_type_t cardtype);
-+void xproto_put(const xproto_table_t *xtable);
- const xproto_entry_t *xproto_card_entry(const xproto_table_t *table, byte opcode);
--const xproto_handler_t xproto_card_handler(const xproto_table_t *table, byte opcode);
-+xproto_handler_t xproto_card_handler(const xproto_table_t *table, byte opcode);
-
- const xproto_entry_t *xproto_global_entry(byte opcode);
--const xproto_handler_t xproto_global_handler(byte opcode);
-+xproto_handler_t xproto_global_handler(byte opcode);
-
- #define CALL_XMETHOD(name, xbus, xpd, ...) \
- (xpd)->xops->name(xbus, xpd, ## __VA_ARGS__ )
-@@ -141,23 +149,25 @@
- int (*card_init)(xbus_t *xbus, xpd_t *xpd);
- int (*card_remove)(xbus_t *xbus, xpd_t *xpd);
- int (*card_tick)(xbus_t *xbus, xpd_t *xpd);
-+ int (*card_zaptel_preregistration)(xpd_t *xpd, bool on);
-+ int (*card_zaptel_postregistration)(xpd_t *xpd, bool on);
-+#ifdef WITH_RBS
-+ int (*card_hooksig)(xbus_t *xbus, xpd_t *xpd, int pos, zt_txsig_t txsig);
-+#else
-+ int (*card_sethook)(xbus_t *xbus, xpd_t *xpd, int pos, int hookstate);
-+#endif
-+ int (*card_ioctl)(xpd_t *xpd, int pos, unsigned int cmd, unsigned long arg);
-
- int (*SYNC_SOURCE)(xbus_t *xbus, xpd_t *xpd, bool setit, bool is_master);
- int (*PCM_WRITE)(xbus_t *xbus, xpd_t *xpd, xpp_line_t hookstate, volatile byte *buf);
-
- int (*CHAN_ENABLE)(xbus_t *xbus, xpd_t *xpd, xpp_line_t lines, bool on);
-- int (*CHAN_POWER)(xbus_t *xbus, xpd_t *xpd, xpp_line_t lines, bool on);
-- int (*CHAN_CID)(xbus_t *xbus, xpd_t *xpd, xpp_line_t lines);
-+ int (*CHAN_CID)(xbus_t *xbus, xpd_t *xpd, int pos);
- int (*RING)(xbus_t *xbus, xpd_t *xpd, int pos, bool on);
-- int (*SETHOOK)(xbus_t *xbus, xpd_t *xpd, xpp_line_t hook_status);
-- int (*LED)(xbus_t *xbus, xpd_t *xpd, xpp_line_t lines, byte which, bool on);
-+ int (*SETHOOK)(xbus_t *xbus, xpd_t *xpd, int pos, bool offhook);
- int (*RELAY_OUT)(xbus_t *xbus, xpd_t *xpd, byte which, bool on);
- };
-
--const xops_t *get_xops(xpd_type_t xpd_type);
--
--#undef XMETHOD
--
- struct xproto_entry {
- xproto_handler_t handler;
- int datalen;
-@@ -166,6 +176,7 @@
- };
-
- struct xproto_table {
-+ struct module *owner;
- xproto_entry_t entries[255]; /* Indexed by opcode */
- xops_t xops;
- xpd_type_t type;
-@@ -176,8 +187,10 @@
-
- #include "card_global.h"
- #include "card_fxs.h"
-+#include "card_fxo.h"
-
- enum opcodes {
-+ XPROTO_NAME(GLOBAL, NULL_REPLY) = 0xFE,
- XPROTO_NAME(GLOBAL, DESC_REQ) = 0x04,
- XPROTO_NAME(GLOBAL, DEV_DESC) = 0x05,
- /**/
-@@ -186,21 +199,6 @@
- /**/
- XPROTO_NAME(GLOBAL, SYNC_SOURCE) = 0x19,
- XPROTO_NAME(GLOBAL, SYNC_REPLY) = 0x1A,
--
-- XPROTO_NAME(FXS, SIG_CHANGED) = 0x06,
--/**/
-- XPROTO_NAME(FXS, SLIC_WRITE) = 0x0F, /* Write to SLIC */
-- XPROTO_NAME(FXS, CHAN_ENABLE) = 0x0F, /* Write to SLIC */
-- XPROTO_NAME(FXS, CHAN_POWER) = 0x0F, /* Write to SLIC */
-- XPROTO_NAME(FXS, CHAN_CID) = 0x0F, /* Write to SLIC */
-- XPROTO_NAME(FXS, RING) = 0x0F, /* Write to SLIC */
-- XPROTO_NAME(FXS, SETHOOK) = 0x0F, /* Write to SLIC */
-- XPROTO_NAME(FXS, LED) = 0x0F, /* Write to SLIC */
-- XPROTO_NAME(FXS, RELAY_OUT) = 0x0F, /* Write to SLIC */
-- XPROTO_NAME(FXS, SLIC_INIT) = 0x0F, /* Write to SLIC */
-- XPROTO_NAME(FXS, SLIC_QUERY) = 0x0F, /* Write to SLIC */
--/**/
-- XPROTO_NAME(FXS, SLIC_REPLY) = 0x10,
- };
-
-
-@@ -210,6 +208,7 @@
- byte opcode;
- xpd_addr_t addr;
- union {
-+ MEMBER(GLOBAL, NULL_REPLY);
- MEMBER(GLOBAL, DESC_REQ);
- MEMBER(GLOBAL, DEV_DESC);
- MEMBER(GLOBAL, PCM_WRITE);
-@@ -218,15 +217,21 @@
-
- MEMBER(FXS, SIG_CHANGED);
- MEMBER(FXS, SLIC_REPLY);
-+ MEMBER(FXS, SLIC_WRITE);
-+
-+ MEMBER(FXO, SIG_CHANGED);
-+ MEMBER(FXO, DAA_REPLY);
-+ MEMBER(FXO, DAA_WRITE);
-
- byte data[0];
- };
--} __attribute__((packed));
-+} PACKED;
-
- struct xpacket {
- xpacket_raw_t content;
-- size_t datalen;
-+ int datalen;
- struct list_head list;
-+ void *packet_priv;
- };
-
- void dump_packet(const char *msg, xpacket_t *packet, bool print_dbg);
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/zap_debug.c zaptel-xpp-LJNBCn_dist/xpp/zap_debug.c
---- zaptel-1.2.6/xpp/zap_debug.c 2006-02-15 04:24:18.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/zap_debug.c 2006-03-30 12:42:46.619481000 +0200
-@@ -1,6 +1,6 @@
- /*
- * Written by Oron Peled <oron at actcom.co.il>
-- * Copyright (C) 2004-2005, Xorcom
-+ * Copyright (C) 2004-2006, Xorcom
- *
- * All rights reserved.
- *
-@@ -31,7 +31,7 @@
- #include <zaptel.h>
- #include "zap_debug.h"
-
--static const char rcsid[] = "$Id: zap_debug.c 949 2006-02-15 02:24:18Z kpfleming $";
-+static const char rcsid[] = "$Id: zap_debug.c 733 2006-03-30 10:42:46Z oron $";
-
- #define P_(x) [ x ] = { .value = x, .name = #x, }
- static struct {
-@@ -63,74 +63,5 @@
- }
- }
-
--#define E_(x) [ x ] = { .value = x, .name = #x, }
--static struct {
-- int value;
-- char *name;
--} zt_event_names[] = {
-- E_(ZT_EVENT_NONE),
-- E_(ZT_EVENT_ONHOOK),
-- E_(ZT_EVENT_RINGOFFHOOK),
-- E_(ZT_EVENT_WINKFLASH),
-- E_(ZT_EVENT_ALARM),
-- E_(ZT_EVENT_NOALARM),
-- E_(ZT_EVENT_ABORT),
-- E_(ZT_EVENT_OVERRUN),
-- E_(ZT_EVENT_BADFCS),
-- E_(ZT_EVENT_DIALCOMPLETE),
-- E_(ZT_EVENT_RINGERON),
-- E_(ZT_EVENT_RINGEROFF),
-- E_(ZT_EVENT_HOOKCOMPLETE),
-- E_(ZT_EVENT_BITSCHANGED),
-- E_(ZT_EVENT_PULSE_START),
-- E_(ZT_EVENT_TIMER_EXPIRED),
-- E_(ZT_EVENT_TIMER_PING),
-- E_(ZT_EVENT_POLARITY)
--};
--#undef E_
--
--char *event2str(int event)
--{
-- BUG_ON(event > ARRAY_SIZE(zt_event_names));
-- return zt_event_names[event].name;
--}
--
--#define S_(x) [ x ] = { .value = x, .name = #x, }
--static struct {
-- int value;
-- char *name;
--} zt_sig_types[] = {
-- S_(ZT_SIG_NONE),
-- S_(ZT_SIG_FXSLS),
-- S_(ZT_SIG_FXSGS),
-- S_(ZT_SIG_FXSKS),
-- S_(ZT_SIG_FXOLS),
-- S_(ZT_SIG_FXOGS),
-- S_(ZT_SIG_FXOKS),
-- S_(ZT_SIG_EM),
-- S_(ZT_SIG_CLEAR),
-- S_(ZT_SIG_HDLCRAW),
-- S_(ZT_SIG_HDLCFCS),
-- S_(ZT_SIG_HDLCNET),
-- S_(ZT_SIG_SLAVE),
-- S_(ZT_SIG_SF),
-- S_(ZT_SIG_CAS),
-- S_(ZT_SIG_DACS),
-- S_(ZT_SIG_EM_E1),
-- S_(ZT_SIG_DACS_RBS)
--};
--#undef S_
--
--void dump_sigtype(int print_dbg, const char *msg, int sigtype)
--{
-- int i;
--
-- for(i = 0; i < ARRAY_SIZE(zt_sig_types); i++) {
-- if(sigtype == zt_sig_types[i].value)
-- DBG("%s: %s\n", msg, zt_sig_types[i].name);
-- }
--}
-
- EXPORT_SYMBOL(dump_poll);
--EXPORT_SYMBOL(event2str);
--EXPORT_SYMBOL(dump_sigtype);
-diff -uNr -x .svn -x debian zaptel-1.2.6/xpp/zap_debug.h zaptel-xpp-LJNBCn_dist/xpp/zap_debug.h
---- zaptel-1.2.6/xpp/zap_debug.h 2006-02-15 04:24:18.000000000 +0200
-+++ zaptel-xpp-LJNBCn_dist/xpp/zap_debug.h 2006-06-19 10:36:29.741020000 +0300
-@@ -1,16 +1,125 @@
- #ifndef ZAP_DEBUG_H
- #define ZAP_DEBUG_H
-+/*
-+ * Written by Oron Peled <oron at actcom.co.il>
-+ * Copyright (C) 2004-2006, Xorcom
-+ *
-+ * All rights reserved.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ */
-
-+/* Debugging Macros */
- #define DBG(fmt, ...) \
-- ((print_dbg) && printk(KERN_DEBUG "DBG-%s: %s: " fmt, \
-- THIS_MODULE->name, __FUNCTION__, ## __VA_ARGS__))
-+ ((void)((print_dbg) && printk(KERN_DEBUG "DBG-%s: %s: " fmt, \
-+ THIS_MODULE->name, __FUNCTION__, ## __VA_ARGS__)))
- #define INFO(fmt, ...) printk(KERN_INFO "INFO-%s: " fmt, THIS_MODULE->name, ## __VA_ARGS__)
- #define NOTICE(fmt, ...) printk(KERN_NOTICE "NOTICE-%s: " fmt, THIS_MODULE->name, ## __VA_ARGS__)
-+#define WARN(fmt, ...) printk(KERN_WARNING "WARN-%s: %s: " fmt, THIS_MODULE->name, __FUNCTION__, ## __VA_ARGS__)
- #define ERR(fmt, ...) printk(KERN_ERR "ERR-%s: " fmt, THIS_MODULE->name, ## __VA_ARGS__)
-
--
- void dump_poll(int print_dbg, const char *msg, int poll);
--char *event2str(int event);
--void dump_sigtype(int print_dbg, const char *msg, int sigtype);
-+
-+static inline char *rxsig2str(zt_rxsig_t sig)
-+{
-+ switch(sig) {
-+ case ZT_RXSIG_ONHOOK: return "ONHOOK";
-+ case ZT_RXSIG_OFFHOOK: return "OFFHOOK";
-+ case ZT_RXSIG_START: return "START";
-+ case ZT_RXSIG_RING: return "RING";
-+ case ZT_RXSIG_INITIAL: return "INITIAL";
-+ }
-+ return "Unknown rxsig";
-+}
-+
-+static inline char *txsig2str(zt_txsig_t sig)
-+{
-+ switch(sig) {
-+ case ZT_TXSIG_ONHOOK: return "TXSIG_ONHOOK";
-+ case ZT_TXSIG_OFFHOOK: return "TXSIG_OFFHOOK";
-+ case ZT_TXSIG_START: return "TXSIG_START";
-+ case ZT_TXSIG_KEWL: return "TXSIG_KEWL"; /* Drop battery if possible */
-+ }
-+ return "Unknown txsig";
-+}
-+
-+static inline char *event2str(int event)
-+{
-+ switch(event) {
-+ case ZT_EVENT_NONE: return "NONE";
-+ case ZT_EVENT_ONHOOK: return "ONHOOK";
-+ case ZT_EVENT_RINGOFFHOOK: return "RINGOFFHOOK";
-+ case ZT_EVENT_WINKFLASH: return "WINKFLASH";
-+ case ZT_EVENT_ALARM: return "ALARM";
-+ case ZT_EVENT_NOALARM: return "NOALARM";
-+ case ZT_EVENT_ABORT: return "ABORT";
-+ case ZT_EVENT_OVERRUN: return "OVERRUN";
-+ case ZT_EVENT_BADFCS: return "BADFCS";
-+ case ZT_EVENT_DIALCOMPLETE: return "DIALCOMPLETE";
-+ case ZT_EVENT_RINGERON: return "RINGERON";
-+ case ZT_EVENT_RINGEROFF: return "RINGEROFF";
-+ case ZT_EVENT_HOOKCOMPLETE: return "HOOKCOMPLETE";
-+ case ZT_EVENT_BITSCHANGED: return "BITSCHANGED";
-+ case ZT_EVENT_PULSE_START: return "PULSE_START";
-+ case ZT_EVENT_TIMER_EXPIRED: return "TIMER_EXPIRED";
-+ case ZT_EVENT_TIMER_PING: return "TIMER_PING";
-+ case ZT_EVENT_POLARITY: return "POLARITY";
-+ }
-+ return "Unknown event";
-+}
-+
-+static inline char *hookstate2str(int hookstate)
-+{
-+ switch(hookstate) {
-+ case ZT_ONHOOK: return "ZT_ONHOOK";
-+ case ZT_START: return "ZT_START";
-+ case ZT_OFFHOOK: return "ZT_OFFHOOK";
-+ case ZT_WINK: return "ZT_WINK";
-+ case ZT_FLASH: return "ZT_FLASH";
-+ case ZT_RING: return "ZT_RING";
-+ case ZT_RINGOFF: return "ZT_RINGOFF";
-+ }
-+ return "Unknown hookstate";
-+}
-+
-+/* From zaptel.c */
-+static inline char *sig2str(int sig)
-+{
-+ switch (sig) {
-+ case ZT_SIG_FXSLS: return "FXSLS";
-+ case ZT_SIG_FXSKS: return "FXSKS";
-+ case ZT_SIG_FXSGS: return "FXSGS";
-+ case ZT_SIG_FXOLS: return "FXOLS";
-+ case ZT_SIG_FXOKS: return "FXOKS";
-+ case ZT_SIG_FXOGS: return "FXOGS";
-+ case ZT_SIG_EM: return "E&M";
-+ case ZT_SIG_EM_E1: return "E&M-E1";
-+ case ZT_SIG_CLEAR: return "Clear";
-+ case ZT_SIG_HDLCRAW: return "HDLCRAW";
-+ case ZT_SIG_HDLCFCS: return "HDLCFCS";
-+ case ZT_SIG_HDLCNET: return "HDLCNET";
-+ case ZT_SIG_SLAVE: return "Slave";
-+ case ZT_SIG_CAS: return "CAS";
-+ case ZT_SIG_DACS: return "DACS";
-+ case ZT_SIG_DACS_RBS: return "DACS+RBS";
-+ case ZT_SIG_SF: return "SF (ToneOnly)";
-+ case ZT_SIG_NONE:
-+ break;
-+ }
-+ return "Unconfigured";
-+}
-
- #endif /* ZAP_DEBUG_H */
More information about the Pkg-voip-commits
mailing list