[Pkg-voip-commits] r1160 - in zaptel/trunk/debian: . patches
Tzafrir Cohen
tzafrir-guest at costa.debian.org
Wed Jan 11 19:27:15 UTC 2006
Author: tzafrir-guest
Date: 2006-01-11 19:27:12 +0000 (Wed, 11 Jan 2006)
New Revision: 1160
Modified:
zaptel/trunk/debian/changelog
zaptel/trunk/debian/genzaptelconf
zaptel/trunk/debian/patches/xpp.dpatch
Log:
new versions of genzaptelconf and xpp.dpatch
Modified: zaptel/trunk/debian/changelog
===================================================================
--- zaptel/trunk/debian/changelog 2006-01-11 19:25:56 UTC (rev 1159)
+++ zaptel/trunk/debian/changelog 2006-01-11 19:27:12 UTC (rev 1160)
@@ -3,6 +3,7 @@
* Use KSRC as proposed on http://wiki.debian.org/KernelModulesPackaging to
build zaptel kernel module (Closes: #343521)
* ukcid.dpatch: for UK Caller ID support (Zaptel part)
+ * newer versions of genzaptelconf and xpp.dpatch
-- Kilian Krause <kilian at debian.org> Wed, 11 Jan 2006 18:01:39 +0100
Modified: zaptel/trunk/debian/genzaptelconf
===================================================================
--- zaptel/trunk/debian/genzaptelconf 2006-01-11 19:25:56 UTC (rev 1159)
+++ zaptel/trunk/debian/genzaptelconf 2006-01-11 19:27:12 UTC (rev 1160)
@@ -35,10 +35,16 @@
# 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.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.4.1
-VERSION_FULL="$VERSION $Id: genzaptelconf 84 2006-01-01 18:52:28Z tzafrir $"
+VERSION=0.4.2
+VERSION_FULL="$VERSION $Id: genzaptelconf 110 2006-01-11 08:09:58Z tzafrir $"
lc_country=us
base_exten=6000
# If set: no context changes are made in zapata-channels.conf
@@ -48,8 +54,8 @@
# TODO: what about PRI/BRI?
# If set: no group changes are made in zapata-channels.conf
#group_manual=yes
-group_phones=0 # group for phones
-group_lines=1 # group for lines
+group_phones=5 # group for phones
+group_lines=0 # group for lines
ZAPCONF_FILE=/etc/zaptel.conf
ZAPATA_FILE=/etc/asterisk/zapata-channels.conf
@@ -66,7 +72,8 @@
# A list of all modules. This is:
# - the list of modules which will be unloaded (in this order)
# - the list of modules which will be probed (in this order)
-ALL_MODULES="zaphfc qozap wctdm wctdm24xxp wcfxo wcfxs pciradio tor2 torisa wct1xxp wct4xxp wcte11xp wcusb ztd_eth ztdummy xpp_usb xpp"
+#ALL_MODULES="zaphfc qozap wctdm wctdm24xxp wcfxo wcfxs pciradio tor2 torisa wct1xxp wct4xxp wcte11xp wcusb ztdynamic ztd_eth ztdummy xpp_usb xpd_fxs xpp"
+ALL_MODULES="zaphfc qozap wctdm wctdm24xxp wcfxo wcfxs pciradio tor2 torisa wct1xxp wct4xxp wcte11xp wcusb ztd_eth xpp_usb"
# read default configuration from /etc/default/zaptel
if [ -r $ZAPTEL_BOOT ]; then . $ZAPTEL_BOOT; fi
@@ -361,7 +368,25 @@
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
+ for mod in `echo $4 | tr , ' '`; do
+ 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)"
@@ -370,15 +395,7 @@
die "Before unloading -- STOP asterisk (pids=$pids)."
fi
say "Unloading zaptel modules:"
- modlist=''
- for i in $ALL_MODULES zaptel
- do
- if lsmod | grep "^$i *" > /dev/null; then
- modlist="$modlist $i"
- say -n "$i "
- fi
- done
- /sbin/modprobe -r $modlist
+ unload_module zaptel
say ''
}
@@ -545,7 +562,7 @@
*XPP_FXO/*)
print_pattern $chan_num fxs $mode
;;
- *XPP_FXS/*)
+ *XPP_FXS/*|*XPP_OUT/*|*XPP_IN/*)
print_pattern $chan_num fxo $mode
;;
*ZTHFC*/*|*ztqoz*/*|*WCT1/*) # should also be used for other PRI channels
@@ -571,13 +588,13 @@
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 dk)
+ case "$lc_country" in nl)
# (Just an example for per-country info)
- echo 'ccs' >$tmp_dir/span_framing
- echo 'hdb3' >$tmp_dir/span_coding
- echo 'crc4' >$tmp_dir/span_yellow
- echo 'euroisdn' >$tmp_dir/span_switchtype
- echo 'pri_cpe' >$tmp_dir/span_signalling
+ echo 'ami' >$tmp_dir/span_framing
+ echo 'ccs' >$tmp_dir/span_coding
+ #echo 'crc4' >$tmp_dir/span_yellow
+ #echo 'euroisdn' >$tmp_dir/span_switchtype
+ #echo 'pri_cpe' >$tmp_dir/span_signalling
;;
esac
;;
Modified: zaptel/trunk/debian/patches/xpp.dpatch
===================================================================
--- zaptel/trunk/debian/patches/xpp.dpatch 2006-01-11 19:25:56 UTC (rev 1159)
+++ zaptel/trunk/debian/patches/xpp.dpatch 2006-01-11 19:27:12 UTC (rev 1160)
@@ -3,13 +3,13 @@
##
## All lines beginning with `## DP:' are a description of the patch.
## DP: The zaptel drivers for the Xorcom Astribank and friends.
-## DP: Revision 168.
+## DP: Revision 186 (trunk)
@DPATCH@
-diff -urNad zaptel-1.0.10/xpp/card_fxs.c /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/card_fxs.c
---- zaptel-1.0.10/xpp/card_fxs.c 1970-01-01 02:00:00.000000000 +0200
-+++ /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/card_fxs.c 2006-01-03 15:08:38.089954000 +0200
-@@ -0,0 +1,548 @@
+diff -urNad trunk/xpp/card_fxs.c /tmp/dpep.qIz4nf/trunk/xpp/card_fxs.c
+--- trunk/xpp/card_fxs.c 1970-01-01 02:00:00.000000000 +0200
++++ /tmp/dpep.qIz4nf/trunk/xpp/card_fxs.c 2006-01-11 10:12:52.381169000 +0200
+@@ -0,0 +1,703 @@
+/*
+ * Written by Oron Peled <oron at actcom.co.il>
+ * Copyright (C) 2004-2005, Xorcom
@@ -32,19 +32,44 @@
+ *
+ */
+
++#include <linux/init.h>
+#include <linux/module.h>
++#include <linux/fs.h>
+#include "xpd.h"
+#include "xproto.h"
+#include "xpp_zap.h"
+#include <linux/delay.h>
+
-+static const char rcsid[] = "$Id: card_fxs.c 168 2006-01-03 12:51:06Z oron $";
++static const char rcsid[] = "$Id: card_fxs.c 185 2006-01-10 14:39:07Z oron $";
++static const char revision[] = "$Revision: 185 $";
+
-+extern int print_dbg;
++DEF_PARM(int, print_dbg, 1, "Print DBG statements"); /* must be before zap_debug.h */
+
++#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 (MASK_BITS(LINES_DIGI_OUT) << LINES_REGULAR)
++#define MASK_DIGI_INP (MASK_BITS(LINES_DIGI_INP) << (LINES_REGULAR + LINES_DIGI_OUT))
++
+/*---------------- 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 bool fxs_packet_is_valid(xpacket_t *pack);
+static void fxs_packet_dump(xpacket_t *pack);
++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,...) \
+ { \
@@ -62,49 +87,103 @@
+};
+#undef S_
+
++#define PROC_SLIC_FNAME "slics"
++
++struct FXS_priv_data {
++ struct proc_dir_entry *xpd_slic;
++ slic_reply_t last_reply;
++};
++
+/*---------------- FXS: Methods -------------------------------------------*/
+
-+static int FXS_card_new(xbus_t *xbus, xpd_t *xpd, byte rev)
++static xpd_t *FXS_card_new(xbus_t *xbus, int xpd_num, const xproto_table_t *proto_table, byte revision)
+{
-+ int channels = min(8, CHANNELS_PERXPD);
++ xpd_t *xpd = NULL;
++ int channels = min(8, CHANNELS_PERXPD);
+
++ if(xpd_num == 0)
++ channels += 6; /* 2 DIGITAL OUTPUTS, 4 DIGITAL INPUTS */
++ xpd = xpd_alloc(sizeof(struct FXS_priv_data), xbus, xpd_num, proto_table, channels, revision);
++ if(!xpd)
++ return NULL;
++ if(xpd_num == 0) {
++ DBG("First XPD on %s detected. Initialize digital outputs/inputs\n", xbus->busname);
++ xpd->digital_outputs = MASK_DIGI_OUT;
++ xpd->digital_inputs = MASK_DIGI_INP;
++ }
+ xpd->direction = TO_PHONE;
-+ if(xpd->id == 0) {
-+ DBG("First XPD detected. Initialize digital outputs\n");
-+ channels += 2;
-+ xpd->digital_outputs = BIT(8) | BIT(9); // Two extra channels
-+ }
-+ xpd->channels = channels;
-+ return 0;
++ return xpd;
+}
+
+static int FXS_card_init(xbus_t *xbus, xpd_t *xpd)
+{
++ struct FXS_priv_data *priv;
++
++ BUG_ON(!xpd);
++ priv = xpd->priv;
+ CALL_PROTO(FXS, SLIC_INIT, xbus, xpd);
++#ifdef CONFIG_PROC_FS
++ 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;
++ }
++ 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
+ return 0;
+}
+
+static int FXS_card_remove(xbus_t *xbus, xpd_t *xpd)
+{
++ struct FXS_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 SLIC file %s/%s\n", xbus->busname, xpd->xpdname);
++ remove_proc_entry(PROC_SLIC_FNAME, xpd->proc_xpd_dir);
++ }
++#endif
+ return 0;
+}
+
-+xops_t FXS_xops = {
-+ .card_new = FXS_card_new,
-+ .card_init = FXS_card_init,
-+ .card_remove = FXS_card_remove,
++/*
++ * INPUT polling is done via SLIC register 0x06 (same as LEDS):
++ * 7 6 5 4 3 2 1 0
++ * +-----+-----+-----+-----+-----+-----+-----+-----+
++ * | I1 | I3 | | | I2 | I4 | | |
++ * +-----+-----+-----+-----+-----+-----+-----+-----+
++ *
++ */
++static int input_channels[] = { 6, 7, 2, 3 }; // Slic numbers of input relays
+
-+ .RING = XPROTO_CALLER(FXS, RING),
-+ .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),
++static void poll_inputs(xbus_t *xbus, xpd_t *xpd)
++{
++ int i;
+
-+ .SYNC_SOURCE = XPROTO_CALLER(GLOBAL, SYNC_SOURCE),
-+ .PCM_WRITE = XPROTO_CALLER(GLOBAL, PCM_WRITE),
-+};
++ for(i = 0; i < ARRAY_SIZE(input_channels); i++) {
++ int pos = input_channels[i];
+
++ CALL_PROTO(FXS, SLIC_QUERY, xbus, xpd, pos, 0x06);
++ }
++}
++
++static int FXS_card_tick(xbus_t *xbus, xpd_t *xpd)
++{
++ static int rate_limit = 0;
++
++ if((rate_limit++ % 1000) == 0) {
++ poll_inputs(xbus, xpd);
++ }
++ return 0;
++}
++
+/*---------------- FXS: HOST COMMANDS -------------------------------------*/
+
+/* 0x0F */ HOSTCMD(FXS, CHAN_ENABLE, xpp_line_t lines, bool on)
@@ -326,8 +405,22 @@
+
+/* 0x0F */ HOSTCMD(FXS, SLIC_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");
-+ return 0;
++ 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);
++
++ pack->datalen = len;
++
++ packet_send(xbus, pack);
++ return ret;
+}
+
+/*---------------- FXS: Astribank Reply Handlers --------------------------*/
@@ -344,11 +437,11 @@
+ 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 */
++ } else { /* TO_PSTN - line ring changes */
+ unsigned long flags;
+ int i;
+
-+ DBG("%s (TRUNK) sig_status=0x%04X\n", xpd->xpdname, sig_status);
++ 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++) {
+ if(IS_SET(sig_status, i)) {
@@ -366,8 +459,10 @@
+
+HANDLER_DEF(FXS, SLIC_REPLY)
+{
-+ slic_reply_t *info = &RPACKET_FIELD(pack, FXS, SLIC_REPLY, info);
-+ unsigned long flags;
++ slic_reply_t *info = &RPACKET_FIELD(pack, FXS, SLIC_REPLY, info);
++ xpp_line_t lines = RPACKET_FIELD(pack, FXS, SLIC_REPLY, lines);
++ unsigned long flags;
++ struct FXS_priv_data *priv;
+
+ if(!xpd) {
+ NOTICE("%s: received %s for non-existing xpd: %d\n",
@@ -375,9 +470,29 @@
+ return -EPROTO;
+ }
+ spin_lock_irqsave(&xpd->lock, flags);
++ priv = xpd->priv;
++ BUG_ON(!priv);
+ 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;
++ 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;
++
++ 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);
++ }
++ }
++ }
+ spin_unlock_irqrestore(&xpd->lock, flags);
+ return 0;
+}
@@ -390,6 +505,24 @@
+ XENTRY( FXS, SLIC_REPLY ),
+ },
+ .name = "FXS",
++ .type = XPD_TYPE(FXS),
++ .xops = {
++ .card_new = FXS_card_new,
++ .card_init = FXS_card_init,
++ .card_remove = FXS_card_remove,
++ .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),
++ .PCM_WRITE = XPROTO_CALLER(GLOBAL, PCM_WRITE),
++ },
+ .packet_is_valid = fxs_packet_is_valid,
+ .packet_dump = fxs_packet_dump,
+};
@@ -410,21 +543,24 @@
+
+/*------------------------- SLIC Handling --------------------------*/
+
-+int proc_xpd_slic_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)
+{
-+ int len = 0;
-+ unsigned long flags;
-+ xpd_t *xpd = data;
-+ //slic_reply_t *info;
++ int len = 0;
++ unsigned long flags;
++ xpd_t *xpd = data;
++ slic_reply_t *info;
++ struct FXS_priv_data *priv;
+
+ BUG_ON(!xpd);
+ spin_lock_irqsave(&xpd->lock, flags);
-+#if 0
-+ info = (slic_reply_t *)&xpd->slic_info;
++ 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, "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;
@@ -527,7 +663,7 @@
+ return 0;
+}
+
-+int proc_xpd_slic_write(struct file *file, const char __user *buffer, unsigned long count, void *data)
++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;
@@ -558,10 +694,29 @@
+}
+
+
-diff -urNad zaptel-1.0.10/xpp/card_fxs.h /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/card_fxs.h
---- zaptel-1.0.10/xpp/card_fxs.h 1970-01-01 02:00:00.000000000 +0200
-+++ /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/card_fxs.h 2006-01-03 13:22:53.823218000 +0200
-@@ -0,0 +1,67 @@
++int __init card_fxs_startup(void)
++{
++ INFO("%s revision %s\n", THIS_MODULE->name, revision);
++ xproto_register(&PROTO_TABLE(FXS));
++ return 0;
++}
++
++void __exit card_fxs_cleanup(void)
++{
++ xproto_unregister(&PROTO_TABLE(FXS));
++}
++
++MODULE_DESCRIPTION("XPP FXS Card Driver");
++MODULE_AUTHOR("Oron Peled <oron at actcom.co.il>");
++MODULE_LICENSE("GPL");
++MODULE_VERSION("$Id: card_fxs.c 185 2006-01-10 14:39:07Z oron $");
++
++module_init(card_fxs_startup);
++module_exit(card_fxs_cleanup);
+diff -urNad trunk/xpp/card_fxs.h /tmp/dpep.qIz4nf/trunk/xpp/card_fxs.h
+--- trunk/xpp/card_fxs.h 1970-01-01 02:00:00.000000000 +0200
++++ /tmp/dpep.qIz4nf/trunk/xpp/card_fxs.h 2006-01-09 18:14:37.000000000 +0200
+@@ -0,0 +1,45 @@
+#ifndef CARD_FXS_H
+#define CARD_FXS_H
+/*
@@ -588,7 +743,6 @@
+
+#include "xpd.h"
+#include "slic.h"
-+#include "xproto.h"
+
+DEF_RPACKET_DATA(FXS, SIG_CHANGED,
+ byte type; /* unused -- we have it from DEV_DESC */
@@ -607,32 +761,11 @@
+ slic_cmd_t slic_cmd;
+ );
+
-+#ifdef __KERNEL__
-+
-+#include <linux/fs.h>
-+
-+/* 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);
-+
-+extern xproto_table_t PROTO_TABLE(FXS);
-+extern xops_t FXS_xops;
-+int proc_xpd_slic_read(char *page, char **start, off_t off, int count, int *eof, void *data);
-+int proc_xpd_slic_write(struct file *file, const char __user *buffer, unsigned long count, void *data);
-+
-+#endif
-+
+#endif /* CARD_FXS_H */
-diff -urNad zaptel-1.0.10/xpp/card_global.c /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/card_global.c
---- zaptel-1.0.10/xpp/card_global.c 1970-01-01 02:00:00.000000000 +0200
-+++ /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/card_global.c 2006-01-03 15:08:38.089954000 +0200
-@@ -0,0 +1,270 @@
+diff -urNad trunk/xpp/card_global.c /tmp/dpep.qIz4nf/trunk/xpp/card_global.c
+--- trunk/xpp/card_global.c 1970-01-01 02:00:00.000000000 +0200
++++ /tmp/dpep.qIz4nf/trunk/xpp/card_global.c 2006-01-11 10:12:52.381169000 +0200
+@@ -0,0 +1,256 @@
+/*
+ * Written by Oron Peled <oron at actcom.co.il>
+ * Copyright (C) 2004-2005, Xorcom
@@ -661,7 +794,7 @@
+#include "xproto.h"
+#include <linux/module.h>
+
-+static const char rcsid[] = "$Id: card_global.c 165 2006-01-03 12:36:57Z oron $";
++static const char rcsid[] = "$Id: card_global.c 185 2006-01-10 14:39:07Z oron $";
+
+extern int print_dbg;
+static bool pcm_valid(xpd_t *xpd, xpacket_t *pack);
@@ -749,48 +882,34 @@
+ return 0;
+}
+
-+xops_t GLOBAL_xops = {
-+ .DESC_REQ = XPROTO_CALLER(GLOBAL, DESC_REQ),
-+ .PCM_WRITE = XPROTO_CALLER(GLOBAL, PCM_WRITE),
-+ .SYNC_SOURCE = XPROTO_CALLER(GLOBAL, SYNC_SOURCE),
-+};
-+
+/*---------------- GLOBAL: Astribank Reply Handlers -----------------------*/
+
+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);
-+ xops_t *xops;
++ 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);
++ struct card_desc_struct *card_desc;
+
+ DBG("xpd=%d type=%d rev=%d line_status=0x%04X\n",
+ xpd_num, type, rev, line_status);
-+ if(xpd) {
-+ if(type == XPD_TYPE(NOMODULE)) {
-+ NOTICE("DEV_DESC: xpd #%d: removed\n", xpd_num);
-+ xpd_remove(xpd);
-+ return 0;
-+ }
-+ NOTICE("DEV_DESC: xpd #%d: already exists\n", xpd_num);
-+ return 0;
++ if((card_desc = kmalloc(sizeof(struct card_desc_struct), GFP_ATOMIC)) == NULL) {
++ ERR("%s: Card description allocation failed.\n", __FUNCTION__);
++ return -ENOMEM;
+ }
-+ if(type == XPD_TYPE_NOMODULE) {
-+ DBG("No module at address=%d\n", xpd_num);
-+ return 0;
-+ }
-+ xops = get_xops(type);
-+ if(!xops) {
-+ NOTICE("DEV_DESC: xpd #%d: missing xops for type=%d\n", xpd_num, type);
++ memset(card_desc, 0, sizeof(struct card_desc_struct));
++ card_desc->magic = CARD_DESC_MAGIC;
++ 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;
+ }
-+ xpd = xpd_new(xbus, xpd_num, type, rev);
-+ if(!xpd) {
-+ NOTICE("xpd_new failed\n");
-+ return -EINVAL;
-+ }
-+ xpp_check_hookstate(xpd, line_status);
+ return 0;
+}
+
@@ -903,10 +1022,10 @@
+ return 1;
+}
+
-diff -urNad zaptel-1.0.10/xpp/card_global.h /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/card_global.h
---- zaptel-1.0.10/xpp/card_global.h 1970-01-01 02:00:00.000000000 +0200
-+++ /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/card_global.h 2006-01-03 13:22:53.823218000 +0200
-@@ -0,0 +1,56 @@
+diff -urNad trunk/xpp/card_global.h /tmp/dpep.qIz4nf/trunk/xpp/card_global.h
+--- trunk/xpp/card_global.h 1970-01-01 02:00:00.000000000 +0200
++++ /tmp/dpep.qIz4nf/trunk/xpp/card_global.h 2006-01-09 18:14:37.000000000 +0200
+@@ -0,0 +1,55 @@
+#ifndef CARD_GLOBAL_H
+#define CARD_GLOBAL_H
+/*
@@ -932,7 +1051,6 @@
+ */
+
+#include "xdefs.h"
-+#include "xproto.h"
+
+DEF_RPACKET_DATA(GLOBAL, DESC_REQ);
+DEF_RPACKET_DATA(GLOBAL, DEV_DESC,
@@ -957,15 +1075,15 @@
+
+
+/* 0x04 */ DECLARE_CMD(GLOBAL, DESC_REQ, int xpd_num);
-+/* 0x11 */ DECLARE_CMD(GLOBAL, PCM_WRITE, xpp_line_t hookstate, volatile byte *buf);
+/* 0x19 */ DECLARE_CMD(GLOBAL, SYNC_SOURCE, bool setit, bool is_master);
++/* 0x11 */ DECLARE_CMD(GLOBAL, PCM_WRITE, xpp_line_t lines, volatile byte *buf);
+
+extern xproto_table_t PROTO_TABLE(GLOBAL);
+
+#endif /* CARD_GLOBAL_H */
-diff -urNad zaptel-1.0.10/xpp/cards.c /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/cards.c
---- zaptel-1.0.10/xpp/cards.c 1970-01-01 02:00:00.000000000 +0200
-+++ /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/cards.c 2006-01-03 14:01:24.370308595 +0200
+diff -urNad trunk/xpp/cards.c /tmp/dpep.qIz4nf/trunk/xpp/cards.c
+--- trunk/xpp/cards.c 1970-01-01 02:00:00.000000000 +0200
++++ /tmp/dpep.qIz4nf/trunk/xpp/cards.c 2006-01-11 10:12:40.515108543 +0200
@@ -0,0 +1,394 @@
+#include <linux/module.h>
+#include "xpd.h"
@@ -1361,9 +1479,9 @@
+ return NULL;
+ return &xpd_card_ops[xpd_type];
+}
-diff -urNad zaptel-1.0.10/xpp/cards.h /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/cards.h
---- zaptel-1.0.10/xpp/cards.h 1970-01-01 02:00:00.000000000 +0200
-+++ /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/cards.h 2006-01-03 14:01:24.370308595 +0200
+diff -urNad trunk/xpp/cards.h /tmp/dpep.qIz4nf/trunk/xpp/cards.h
+--- trunk/xpp/cards.h 1970-01-01 02:00:00.000000000 +0200
++++ /tmp/dpep.qIz4nf/trunk/xpp/cards.h 2006-01-11 10:12:40.515108543 +0200
@@ -0,0 +1,23 @@
+#ifndef CARDS_H
+#define CARDS_H
@@ -1388,9 +1506,9 @@
+xops_t *get_xops(xpd_type_t xpd_type);
+
+#endif /* CARDS_H */
-diff -urNad zaptel-1.0.10/xpp/FPGA_XPD.hex /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/FPGA_XPD.hex
---- zaptel-1.0.10/xpp/FPGA_XPD.hex 1970-01-01 02:00:00.000000000 +0200
-+++ /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/FPGA_XPD.hex 2006-01-03 13:22:53.823218000 +0200
+diff -urNad trunk/xpp/FPGA_XPD.hex /tmp/dpep.qIz4nf/trunk/xpp/FPGA_XPD.hex
+--- trunk/xpp/FPGA_XPD.hex 1970-01-01 02:00:00.000000000 +0200
++++ /tmp/dpep.qIz4nf/trunk/xpp/FPGA_XPD.hex 2006-01-09 18:14:37.000000000 +0200
@@ -0,0 +1,243 @@
+:0A0B3C000001020203030404050592
+:100546005010C0C0F9A4B0999282F880988883C6EA
@@ -1635,9 +1753,9 @@
+:10093400F0A3C8C582C8CAC583CADFE9DEE780BEA2
+:0106360000C3
+:00000001FF
-diff -urNad zaptel-1.0.10/xpp/gen_slic_init /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/gen_slic_init
---- zaptel-1.0.10/xpp/gen_slic_init 1970-01-01 02:00:00.000000000 +0200
-+++ /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/gen_slic_init 2006-01-03 15:08:38.089954000 +0200
+diff -urNad trunk/xpp/gen_slic_init /tmp/dpep.qIz4nf/trunk/xpp/gen_slic_init
+--- trunk/xpp/gen_slic_init 1970-01-01 02:00:00.000000000 +0200
++++ /tmp/dpep.qIz4nf/trunk/xpp/gen_slic_init 2006-01-09 18:14:37.000000000 +0200
@@ -0,0 +1,37 @@
+#! /usr/bin/perl -w
+
@@ -1676,17 +1794,18 @@
+ }
+ print HF "\n";
+}
-diff -urNad zaptel-1.0.10/xpp/Makefile /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/Makefile
---- zaptel-1.0.10/xpp/Makefile 1970-01-01 02:00:00.000000000 +0200
-+++ /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/Makefile 2006-01-03 13:22:53.565151000 +0200
-@@ -0,0 +1,4 @@
+diff -urNad trunk/xpp/Makefile /tmp/dpep.qIz4nf/trunk/xpp/Makefile
+--- trunk/xpp/Makefile 1970-01-01 02:00:00.000000000 +0200
++++ /tmp/dpep.qIz4nf/trunk/xpp/Makefile 2006-01-09 18:14:36.000000000 +0200
+@@ -0,0 +1,5 @@
+EXTRA_CFLAGS = -I$(src)/..
+
-+obj-m = xpp.o xpp_usb.o
-+xpp-y += xproto.o card_global.o card_fxs.o slic.o xpp_zap.o zap_debug.o
-diff -urNad zaptel-1.0.10/xpp/slic.c /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/slic.c
---- zaptel-1.0.10/xpp/slic.c 1970-01-01 02:00:00.000000000 +0200
-+++ /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/slic.c 2006-01-03 13:22:53.823218000 +0200
++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
+diff -urNad trunk/xpp/slic.c /tmp/dpep.qIz4nf/trunk/xpp/slic.c
+--- trunk/xpp/slic.c 1970-01-01 02:00:00.000000000 +0200
++++ /tmp/dpep.qIz4nf/trunk/xpp/slic.c 2006-01-09 18:14:37.000000000 +0200
@@ -0,0 +1,129 @@
+/*
+ * Written by Oron Peled <oron at actcom.co.il>
@@ -1817,9 +1936,9 @@
+EXPORT_SYMBOL(dump_slic_cmd);
+
+#endif
-diff -urNad zaptel-1.0.10/xpp/slic.h /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/slic.h
---- zaptel-1.0.10/xpp/slic.h 1970-01-01 02:00:00.000000000 +0200
-+++ /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/slic.h 2006-01-03 13:22:53.823218000 +0200
+diff -urNad trunk/xpp/slic.h /tmp/dpep.qIz4nf/trunk/xpp/slic.h
+--- trunk/xpp/slic.h 1970-01-01 02:00:00.000000000 +0200
++++ /tmp/dpep.qIz4nf/trunk/xpp/slic.h 2006-01-09 18:14:37.000000000 +0200
@@ -0,0 +1,65 @@
+#ifndef SLIC_H
+#define SLIC_H
@@ -1886,9 +2005,9 @@
+
+
+#endif /* SLIC_H */
-diff -urNad zaptel-1.0.10/xpp/slic_init.inc /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/slic_init.inc
---- zaptel-1.0.10/xpp/slic_init.inc 1970-01-01 02:00:00.000000000 +0200
-+++ /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/slic_init.inc 2006-01-03 15:08:39.122220000 +0200
+diff -urNad trunk/xpp/slic_init.inc /tmp/dpep.qIz4nf/trunk/xpp/slic_init.inc
+--- trunk/xpp/slic_init.inc 1970-01-01 02:00:00.000000000 +0200
++++ /tmp/dpep.qIz4nf/trunk/xpp/slic_init.inc 2006-01-11 10:12:53.154369000 +0200
@@ -0,0 +1,65 @@
+// ----------------------------------==== 8-channel FXS unit initialization ===-----------------------------------------
+
@@ -1935,7 +2054,7 @@
+
+S_(0x000000FF, 0x02, 0x45, 0x0A),
+S_(0x000000FF, 0x02, 0x46, 0x0B),
-+S_(0x000000FF, 0x02, 0x47, 0x00),
++S_(0x000000FF, 0x02, 0x47, 0x07),
+
+
+// Setting of SLICs offsets
@@ -1955,24 +2074,25 @@
+S_(0x000000FF, 0x02, 0x42, 0x06),
+// -------------------------------------------------------------
+
-diff -urNad zaptel-1.0.10/xpp/sync.sh /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/sync.sh
---- zaptel-1.0.10/xpp/sync.sh 1970-01-01 02:00:00.000000000 +0200
-+++ /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/sync.sh 2006-01-03 15:35:29.050560735 +0200
-@@ -0,0 +1,30 @@
+diff -urNad trunk/xpp/sync.sh /tmp/dpep.qIz4nf/trunk/xpp/sync.sh
+--- trunk/xpp/sync.sh 1970-01-01 02:00:00.000000000 +0200
++++ /tmp/dpep.qIz4nf/trunk/xpp/sync.sh 2006-01-11 10:12:40.515108543 +0200
+@@ -0,0 +1,31 @@
+#!/bin/sh
+
+set -e
+
+SVN_ROOT=/home/tzafrir/Proj/Svn
-+XORTEL_DIR=$SVN_ROOT/xpp-zaptel/xortel
-+XPP_DIR=$SVN_ROOT/xpp-zaptel/zaptel/xpp
++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 $SVN_ROOT/xpp-zaptel
-+ svn update
++cd $XORTEL_DIR
++ cd ..; svn update;
+ cd xortel
-+ make FIRMWARE="$SVN_ROOT/fpgafirmware/init.dat" ../zaptel/xpp/slic_init.inc
++ make FIRMWARE="$FIRMWARE" ../zaptel/xpp/slic_init.inc
+cd $curdir
+
+cp -a $XORTEL_DIR/FPGA_XPD.hex ${TARGET_DIR}/
@@ -1989,9 +2109,9 @@
+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 -urNad zaptel-1.0.10/xpp/xdefs.h /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/xdefs.h
---- zaptel-1.0.10/xpp/xdefs.h 1970-01-01 02:00:00.000000000 +0200
-+++ /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/xdefs.h 2006-01-03 13:22:53.823218000 +0200
+diff -urNad trunk/xpp/xdefs.h /tmp/dpep.qIz4nf/trunk/xpp/xdefs.h
+--- trunk/xpp/xdefs.h 1970-01-01 02:00:00.000000000 +0200
++++ /tmp/dpep.qIz4nf/trunk/xpp/xdefs.h 2006-01-09 18:14:37.000000000 +0200
@@ -0,0 +1,82 @@
+#ifndef XDEFS_H
+#define XDEFS_H
@@ -2075,10 +2195,10 @@
+
+
+#endif /* XDEFS_H */
-diff -urNad zaptel-1.0.10/xpp/xpd.h /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/xpd.h
---- zaptel-1.0.10/xpp/xpd.h 1970-01-01 02:00:00.000000000 +0200
-+++ /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/xpd.h 2006-01-03 13:22:53.823218000 +0200
-@@ -0,0 +1,294 @@
+diff -urNad trunk/xpp/xpd.h /tmp/dpep.qIz4nf/trunk/xpp/xpd.h
+--- trunk/xpp/xpd.h 1970-01-01 02:00:00.000000000 +0200
++++ /tmp/dpep.qIz4nf/trunk/xpp/xpd.h 2006-01-11 10:12:52.381169000 +0200
+@@ -0,0 +1,290 @@
+#ifndef XPD_H
+#define XPD_H
+
@@ -2256,9 +2376,8 @@
+#endif
+
+#ifdef CONFIG_PROC_FS
-+ struct proc_dir_entry *procdir;
-+ struct proc_dir_entry *procsummary;
-+ struct proc_dir_entry *proc_ztregister;
++ struct proc_dir_entry *proc_xbus_dir;
++ struct proc_dir_entry *proc_xbus_summary;
+#endif
+
+ /* statistics */
@@ -2269,7 +2388,7 @@
+
+typedef enum xpd_direction {
+ TO_PHONE = 0,
-+ TO_TRUNK = 1,
++ TO_PSTN = 1,
+} xpd_direction_t;
+
+#define LINE_BITS (sizeof(xpp_line_t)*8)
@@ -2318,11 +2437,12 @@
+ struct zt_chan *chans;
+ int channels;
+ xpd_type_t type;
-+ xpd_direction_t direction; /* TO_PHONE, TO_LINE */
++ 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 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 */
@@ -2335,27 +2455,23 @@
+ spinlock_t lock;
+ atomic_t open_counter; /* Number of open channels */
+
-+ int flags;
-+ enum {
-+ XPD_STATE_OFF = 0x01,
-+ XPD_STATE_NOREPLY = 0x02,
-+ XPD_STATE_ACTIVE = 0x03,
-+ XPD_STATE_ZAPTEL_ERR = 0x04,
-+ } state;
++ int flags;
+
+ unsigned int board_flags;
+#define XPD_BOARD_LOOPBACK 1
+
+#ifdef CONFIG_PROC_FS
-+ struct proc_dir_entry *xpd_proc;
-+ struct proc_dir_entry *xpd_slic;
++ 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];
+
-+ xops_t *xops; /* Card level operations */
-+ void *card; /* Card level private data */
++ const xops_t *xops; /* Card level operations */
++ void *priv; /* Card level private data */
++ atomic_t card_present;
+
+ unsigned int recv_errors;
+ unsigned int seq_errors;
@@ -2373,9 +2489,9 @@
+#endif
+
+#endif /* XPD_H */
-diff -urNad zaptel-1.0.10/xpp/xpp_fxloader /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/xpp_fxloader
---- zaptel-1.0.10/xpp/xpp_fxloader 1970-01-01 02:00:00.000000000 +0200
-+++ /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/xpp_fxloader 2006-01-03 13:22:53.823218000 +0200
+diff -urNad trunk/xpp/xpp_fxloader /tmp/dpep.qIz4nf/trunk/xpp/xpp_fxloader
+--- trunk/xpp/xpp_fxloader 1970-01-01 02:00:00.000000000 +0200
++++ /tmp/dpep.qIz4nf/trunk/xpp/xpp_fxloader 2006-01-09 18:14:37.000000000 +0200
@@ -0,0 +1,11 @@
+#!/bin/bash
+
@@ -2388,23 +2504,29 @@
+ fxload -t fx2 -D "$DEVICE" -I "$FIRMWARE" || exit 1
+fi
+
-diff -urNad zaptel-1.0.10/xpp/xpp_fxloader.usermap /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/xpp_fxloader.usermap
---- zaptel-1.0.10/xpp/xpp_fxloader.usermap 1970-01-01 02:00:00.000000000 +0200
-+++ /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/xpp_fxloader.usermap 2006-01-03 13:22:53.823218000 +0200
+diff -urNad trunk/xpp/xpp_fxloader.usermap /tmp/dpep.qIz4nf/trunk/xpp/xpp_fxloader.usermap
+--- trunk/xpp/xpp_fxloader.usermap 1970-01-01 02:00:00.000000000 +0200
++++ /tmp/dpep.qIz4nf/trunk/xpp/xpp_fxloader.usermap 2006-01-09 18:14:37.000000000 +0200
@@ -0,0 +1,2 @@
+# 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 -urNad zaptel-1.0.10/xpp/xpp_modprobe /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/xpp_modprobe
---- zaptel-1.0.10/xpp/xpp_modprobe 1970-01-01 02:00:00.000000000 +0200
-+++ /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/xpp_modprobe 2006-01-03 13:22:53.823218000 +0200
-@@ -0,0 +1,4 @@
-+options zaptel debug=1
-+options wcfxo debug=1
-+options xpp print_dbg=1 ignore_xpds=0x00 softloop_xpds=0x00 enabled_channels=0x000000FF pcm_gen=0x00000000 max_queue_len=20000
-+options usb_test vendor=0x4B4 product=0x8613 altsetting=1 innum=2 outnum=4
-diff -urNad zaptel-1.0.10/xpp/xpp_proto.c /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/xpp_proto.c
---- zaptel-1.0.10/xpp/xpp_proto.c 1970-01-01 02:00:00.000000000 +0200
-+++ /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/xpp_proto.c 2006-01-03 14:01:24.370308595 +0200
+diff -urNad trunk/xpp/xpp_modprobe /tmp/dpep.qIz4nf/trunk/xpp/xpp_modprobe
+--- trunk/xpp/xpp_modprobe 1970-01-01 02:00:00.000000000 +0200
++++ /tmp/dpep.qIz4nf/trunk/xpp/xpp_modprobe 2006-01-11 10:12:52.381169000 +0200
+@@ -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
++
++# 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 -urNad trunk/xpp/xpp_proto.c /tmp/dpep.qIz4nf/trunk/xpp/xpp_proto.c
+--- trunk/xpp/xpp_proto.c 1970-01-01 02:00:00.000000000 +0200
++++ /tmp/dpep.qIz4nf/trunk/xpp/xpp_proto.c 2006-01-11 10:12:40.515108543 +0200
@@ -0,0 +1,1044 @@
+#include <linux/module.h>
+#include <linux/delay.h> /* for udelay */
@@ -3450,9 +3572,9 @@
+EXPORT_SYMBOL(packet_receive);
+EXPORT_SYMBOL(proc_xpd_slic_read);
+EXPORT_SYMBOL(proc_xpd_slic_write);
-diff -urNad zaptel-1.0.10/xpp/xpp_proto.h /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/xpp_proto.h
---- zaptel-1.0.10/xpp/xpp_proto.h 1970-01-01 02:00:00.000000000 +0200
-+++ /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/xpp_proto.h 2006-01-03 14:01:24.370308595 +0200
+diff -urNad trunk/xpp/xpp_proto.h /tmp/dpep.qIz4nf/trunk/xpp/xpp_proto.h
+--- trunk/xpp/xpp_proto.h 1970-01-01 02:00:00.000000000 +0200
++++ /tmp/dpep.qIz4nf/trunk/xpp/xpp_proto.h 2006-01-11 10:12:40.515108543 +0200
@@ -0,0 +1,188 @@
+#ifndef XPP_PROTO_H
+#define XPP_PROTO_H
@@ -3642,10 +3764,10 @@
+#endif
+
+#endif /* XPP_PROTO_H */
-diff -urNad zaptel-1.0.10/xpp/xpp_usb.c /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/xpp_usb.c
---- zaptel-1.0.10/xpp/xpp_usb.c 1970-01-01 02:00:00.000000000 +0200
-+++ /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/xpp_usb.c 2006-01-03 13:22:53.823218000 +0200
-@@ -0,0 +1,869 @@
+diff -urNad trunk/xpp/xpp_usb.c /tmp/dpep.qIz4nf/trunk/xpp/xpp_usb.c
+--- trunk/xpp/xpp_usb.c 1970-01-01 02:00:00.000000000 +0200
++++ /tmp/dpep.qIz4nf/trunk/xpp/xpp_usb.c 2006-01-09 18:14:37.000000000 +0200
+@@ -0,0 +1,873 @@
+/*
+ * Written by Oron Peled <oron at actcom.co.il>
+ * Copyright (C) 2004-2005, Xorcom
@@ -3689,7 +3811,7 @@
+#include "xproto.h"
+#include "xpp_zap.h"
+
-+static char revision[] = "$Revision: 159 $";
++static const char revision[] = "$Revision: 181 $";
+
+DEF_PARM(int, print_dbg, 1, "Print DBG statements"); /* must be before zap_debug.h */
+
@@ -3704,8 +3826,10 @@
+#define PROC_USBXPP_SUMMARY "xpp_usb"
+#endif
+
++#ifdef DEBUG_PCM_TIMING
+static cycles_t stamp_last_pcm_read;
+static cycles_t accumulate_diff;
++#endif
+
+struct xusb_model_info;
+
@@ -3884,7 +4008,7 @@
+ if(pack->content.opcode == XPROTO_NAME(GLOBAL,PCM_WRITE)) {
+ XUSB_COUNTER(xusb, PCM_WRITES)++;
+
-+#if 1
++#ifdef DEBUG_PCM_TIMING
+ /*
+ * DEBUG: high-res timing of PCM_READ to PCM_WRITE
+ */
@@ -4201,7 +4325,7 @@
+
+#ifdef CONFIG_PROC_FS
+ DBG("Creating proc entry " PROC_USBXPP_SUMMARY " in bus proc dir.\n");
-+ procsummary = create_proc_read_entry(PROC_USBXPP_SUMMARY, 0644, xbus->procdir,
++ 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) {
@@ -4266,8 +4390,8 @@
+ xusb_array[i] = NULL;
+
+#ifdef CONFIG_PROC_FS
-+ if(xbus->procdir) {
-+ remove_proc_entry(PROC_USBXPP_SUMMARY, xbus->procdir);
++ if(xbus->proc_xbus_dir) {
++ remove_proc_entry(PROC_USBXPP_SUMMARY, xbus->proc_xbus_dir);
+ }
+#endif
+ xusb->present = 0;
@@ -4362,7 +4486,7 @@
+ if(pack->content.opcode == XPROTO_NAME(GLOBAL,PCM_READ)) {
+ XUSB_COUNTER(xusb, PCM_READS)++;
+
-+#if 1
++#ifdef DEBUG_PCM_TIMING
+ /*
+ * DEBUG: high-res timing of PCM_READ to PCM_WRITE
+ */
@@ -4468,8 +4592,6 @@
+ 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"
@@ -4484,12 +4606,16 @@
+ xusb->ep_out.epnum,
+ xusb->ep_out.max_size
+ );
++#ifdef DEBUG_PCM_TIMING
+ len += sprintf(page + len, "\nstamp_last_pcm_read=%lld accumulate_diff=%lld\n", stamp_last_pcm_read, accumulate_diff);
++#endif
+ len += sprintf(page + len, "\nCOUNTERS:\n");
+ for(i = 0; i < XUSB_COUNTER_MAX; i++) {
+ len += sprintf(page + len, "\t%-15s = %d\n", xusb_counters[i].name, xusb->counters[i]);
+ }
++#if 0
+ len += sprintf(page + len, "<-- len=%d\n", len);
++#endif
+ spin_unlock_irqrestore(&xusb_lock, flags);
+out:
+ if (len <= off+count)
@@ -4511,14 +4637,14 @@
+MODULE_DESCRIPTION("XPP USB Driver");
+MODULE_AUTHOR("Oron Peled <oron at actcom.co.il>");
+MODULE_LICENSE("GPL");
-+MODULE_VERSION("$Id: xpp_usb.c 159 2006-01-03 08:49:05Z oron $");
++MODULE_VERSION("$Id: xpp_usb.c 181 2006-01-05 17:13:28Z oron $");
+
+module_init(xpp_usb_init);
+module_exit(xpp_usb_cleanup);
-diff -urNad zaptel-1.0.10/xpp/xpp_zap.c /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/xpp_zap.c
---- zaptel-1.0.10/xpp/xpp_zap.c 1970-01-01 02:00:00.000000000 +0200
-+++ /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/xpp_zap.c 2006-01-03 15:08:38.089954000 +0200
-@@ -0,0 +1,2273 @@
+diff -urNad trunk/xpp/xpp_zap.c /tmp/dpep.qIz4nf/trunk/xpp/xpp_zap.c
+--- trunk/xpp/xpp_zap.c 1970-01-01 02:00:00.000000000 +0200
++++ /tmp/dpep.qIz4nf/trunk/xpp/xpp_zap.c 2006-01-11 10:12:52.381169000 +0200
+@@ -0,0 +1,2312 @@
+/*
+ * Written by Oron Peled <oron at actcom.co.il>
+ * Copyright (C) 2004, Xorcom
@@ -4562,7 +4688,7 @@
+#include "xproto.h"
+#include "xpp_zap.h"
+
-+static char revision[] = "$Revision: 167 $";
++static char revision[] = "$Revision: 185 $";
+
+#ifdef CONFIG_PROC_FS
+struct proc_dir_entry *xpp_procdir = NULL;
@@ -4570,8 +4696,8 @@
+#define PROC_XBUSES "xbuses"
+#define PROC_SYNC "sync"
+#define PROC_XBUS_SUMMARY "summary"
-+#define PROC_XBUS_ZTREGISTER "zt_registration"
-+#define PROC_SLIC_FNAME "%s.slic"
++#define PROC_XPD_ZTREGISTER "zt_registration"
++#define PROC_XPD_SUMMARY "summary"
+#endif
+
+#undef WITH_RBS
@@ -4583,14 +4709,6 @@
+#define LED_BLINK_PERIOD (HZ/8)
+#define SAMPLE_TICKS 10000
+
-+#define N_(x) [ x] = #x
-+static const char *xpd_type_names[] = {
-+ N_(XPD_TYPE_FXO),
-+ N_(XPD_TYPE_FXS),
-+ N_(XPD_TYPE_NOMODULE),
-+};
-+#undef N_
-+
+static spinlock_t xbuses_lock = SPIN_LOCK_UNLOCKED;
+static xbus_t *xbuses_array[MAX_BUSES] = {};
+static int bus_count = 0;
@@ -4598,6 +4716,7 @@
+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);
+
@@ -4623,16 +4742,123 @@
+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);
-+/* global workqueue. needs to be global? */
-+struct workqueue_struct *xpd_init_workqueue=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
@@ -4702,7 +4928,7 @@
+ for(j = 0; j < MAX_XPDS; j++) {
+ xpd_t *xpd = xbus->xpds[j];
+ if(xpd)
-+ CALL_PROTO(GLOBAL, SYNC_SOURCE, xbus, xpd, 1, (the_xpd != NULL));
++ CALL_XMETHOD(SYNC_SOURCE, xbus, xpd, 1, (the_xpd != NULL));
+ }
+ }
+}
@@ -4767,13 +4993,14 @@
+
+ if(!xpd)
+ continue;
++ if(!atomic_read(&xpd->card_present))
++ continue;
+ xpd->timer_count++;
-+ if(xpd->state != XPD_STATE_ACTIVE)
-+ continue;
++ CALL_XMETHOD(card_tick, xbus, xpd);
+ if(!SPAN_REGISTERED(xpd))
+ continue;
+ xpd_blink_leds(xpd);
-+ if(xpd->direction == TO_TRUNK)
++ if(xpd->direction == TO_PSTN)
+ xpp_ring_generate(xpd);
+ xpp_transmitprep(xpd);
+ xpp_receiveprep(xpd);
@@ -4785,60 +5012,32 @@
+#error "xpp_timer must be sampled EXACTLY 1000/per second"
+#endif
+
-+/**
-+ * Process a registration request.
-+ *
-+ * A new xpd structure is created when we get a device description packet.
-+ * This happens from a timer interrupt context and we can't call zt_register
-+ * from there.
-+ *
-+ * Thus the xpd structure is generated and registerted with xpp. However the
-+ * registration to zaptel is done "off-line" by posting a registration to the
-+ * "reg" workqueue that calls this function.
-+ */
-+void xpd_initialize(void *data)
++static void xpd_cleanup(xpd_t *xpd)
+{
-+ xpd_t *xpd = (xpd_t *)data;
-+ xbus_t *xbus;
-+
-+ if (!xpd) {
-+ ERR("%s: called with a NULL xpd\n", __FUNCTION__);
++ xbus_t *xbus = NULL;
++
++ if(!xpd)
+ return;
-+ }
+ xbus = xpd->xbus;
-+#ifdef CONFIG_PROC_FS
-+ DBG("Creating xpd proc file %s.\n", xpd->xpdname);
-+ xpd->xpd_proc = create_proc_read_entry(xpd->xpdname, 0644, xbus->procdir,
-+ xpd_read_proc, xpd);
-+ if(!xpd->xpd_proc) {
-+ ERR("Failed to create proc file for xpd %s\n", xpd->xpdname);
-+ return;
-+ }
-+ {
-+ char fname[NAME_MAX];
-+
-+ snprintf(fname, NAME_MAX, PROC_SLIC_FNAME, xpd->xpdname);
-+ DBG("Creating xpd slic file %s.\n", fname);
-+ xpd->xpd_slic = create_proc_entry(fname, 0644, xbus->procdir);
-+ if(!xpd->xpd_slic) {
-+ ERR("Failed to create proc file for SLIC xpd %s\n", fname);
-+ return;
++ xpd_card_disable(xpd);
++ DBG("%s/%s\n", xbus->busname, xpd->xpdname);
++#ifdef CONFIG_PROC_FS
++ if(xpd->proc_xpd_dir) {
++ if(xpd->proc_xpd_summary) {
++ DBG("Removing proc '%s' for %s/%s\n", PROC_XPD_SUMMARY, xbus->busname, xpd->xpdname);
++ remove_proc_entry(PROC_XPD_SUMMARY, xpd->proc_xpd_dir);
++ xpd->proc_xpd_summary = NULL;
+ }
-+ xpd->xpd_slic->write_proc = proc_xpd_slic_write;
-+ xpd->xpd_slic->read_proc = proc_xpd_slic_read;
-+ xpd->xpd_slic->data = xpd;
++ if(xpd->proc_xpd_ztregister) {
++ DBG("Removing proc '%s' for %s/%s\n", PROC_XPD_ZTREGISTER, xbus->busname, xpd->xpdname);
++ remove_proc_entry(PROC_XPD_ZTREGISTER, xpd->proc_xpd_dir);
++ xpd->proc_xpd_ztregister = NULL;
++ }
++ DBG("Removing proc directory for %s/%s\n", xbus->busname, xpd->xpdname);
++ remove_proc_entry(xpd->xpdname, xbus->proc_xbus_dir);
++ xpd->proc_xpd_dir = NULL;
+ }
+#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);
-+ xpd_zaptel_register(xpd);
+}
+
+void init_xbus_packet_queue(packet_queue_t *q, const char name[])
@@ -4972,10 +5171,12 @@
+ sim = &xbus->sim[xpd->id];
+#endif
+ channels = xpd->channels;
-+ len += sprintf(page + len, "%s (%s ,state=%d, span_registered=%s)%s\n"
++ len += sprintf(page + len, "%s (%s ,card %s, span_registered=%s)%s\n"
+ "timer_count: %d span->mainttimer=%d\n"
+ ,
-+ xpd->xpdname, xpd_type_names[xpd->type], xpd->state, (SPAN_REGISTERED(xpd))?"yes":"no",
++ xpd->xpdname, xproto_name(xpd->type),
++ (atomic_read(&xpd->card_present))?"present":"missing",
++ (SPAN_REGISTERED(xpd))?"yes":"no",
+ (xpd == sync_master) ? " SYNCER" : "",
+ xpd->timer_count, xpd->span.mainttimer
+ );
@@ -4988,6 +5189,10 @@
+ for(i = 0; i < channels; 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++) {
++ 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++) {
+ len += sprintf(page + len, "%d ", IS_SET(xpd->hookstate, i));
@@ -5055,52 +5260,65 @@
+
+#endif
+
-+xpd_t *xpd_new(xbus_t *xbus, int xpd_num, xpd_type_t type, byte revision)
++/*
++ * xpd_alloc - Allocator for new XPD's
++ *
++ */
++xpd_t *xpd_alloc(size_t privsize, xbus_t *xbus, int xpd_num, const xproto_table_t *proto_table, int channels, byte revision)
+{
-+ unsigned long flags;
+ xpd_t *xpd = NULL;
-+ xops_t *xops;
++ size_t alloc_size = sizeof(xpd_t) + privsize;
+
-+ spin_lock_irqsave(&xbus->lock, flags);
+ INFO("New XPD #%d (Revision %d.%d) detected on xbus %s\n",
+ xpd_num, revision / 10, revision % 10, xbus->busname);
+ if(!VALID_XPD_NUM(xpd_num)) {
+ ERR("%s: illegal xpd id = %d\n", __FUNCTION__, xpd_num);
+ goto err;
+ }
-+ if((xops = get_xops(type)) == NULL) {
-+ ERR("%s: no xops for type=%d\n", __FUNCTION__, type);
++ if(channels > CHANNELS_PERXPD) {
++ ERR("%s: too many channels %d for xpd #%d\n", __FUNCTION__, channels, xpd_num);
+ goto err;
+ }
-+ if((xpd = kmalloc(sizeof(xpd_t), GFP_ATOMIC)) == NULL) {
-+ ERR("%s: Unable to allocate memory for xpd\n", __FUNCTION__);
++
++ if((xpd = kmalloc(alloc_size, GFP_KERNEL)) == NULL) {
++ ERR("%s: Unable to allocate memory for xpd #%d\n", __FUNCTION__, xpd_num);
+ goto err;
+ }
-+ memset(xpd, 0, sizeof(xpd_t));
++ memset(xpd, 0, alloc_size);
++ xpd->priv = (byte *)xpd + sizeof(xpd_t);
+
+ spin_lock_init(&xpd->lock);
-+ xpd->xops = xops;
+ xpd->xbus = xbus;
+ xpd->id = xpd_num;
++ xpd->channels = channels;
+ xpd->chans = NULL;
-+ xpd->state = XPD_STATE_OFF;
++ atomic_set(&xpd->card_present, 0);
+ snprintf(xpd->xpdname, XPD_NAMELEN, "XPD-%d", xpd_num);
+ xpd->hookstate = 0x0; /* ONHOOK */
-+ xpd->type = type;
++ xpd->type = proto_table->type;
++ xpd->xops = &proto_table->xops;
+ xpd->enabled_chans = enabled_channels[xpd_num];
+ xpd->digital_outputs = 0;
++ xpd->digital_inputs = 0;
+ atomic_set(&xpd->open_counter, 0);
+
-+ INIT_WORK(&xpd->xpd_post_init, xpd_initialize, xpd);
-+
-+ CALL_XMETHOD(card_new, xbus, xpd, revision);
-+ if(xpd_setup(xpd) != 0)
++ xpd->chans = kmalloc(sizeof(struct zt_chan)*xpd->channels, GFP_KERNEL);
++ if (xpd->chans == NULL) {
++ 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) {
++ 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;
+
-+ spin_unlock_irqrestore(&xbus->lock, flags);
+ return xpd;
+err:
-+ spin_unlock_irqrestore(&xbus->lock, flags);
+ if(xpd->chans)
+ kfree((void *)xpd->chans);
+ if(xpd->writechunk)
@@ -5110,44 +5328,12 @@
+ return NULL;
+}
+
-+int xpd_setup(xpd_t *xpd)
++static void xpd_card_disable(xpd_t *xpd)
+{
-+ xpd->chans = kmalloc(sizeof(struct zt_chan)*xpd->channels, GFP_ATOMIC);
-+ if (xpd->chans == NULL) {
-+ ERR("%s: Unable to allocate channels\n", __FUNCTION__);
-+ return -ENOMEM;
-+ }
-+ /* 8 channels, double buffer, Read/Write */
-+ int need = ZT_MAX_CHUNKSIZE * CHANNELS_PERXPD * 2 * 2;
-+ if((xpd->writechunk = kmalloc(need, GFP_ATOMIC)) == NULL) {
-+ ERR("%s: Unable to allocate memory for writechunks\n", __FUNCTION__);
-+ kfree(xpd->chans);
-+ xpd->chans = NULL;
-+ return -ENOMEM;
-+ }
-+ /* Initialize Write/Buffers to all blank data */
-+ memset((void *)xpd->writechunk, 0x00, need);
-+ xpd->readchunk = xpd->writechunk + ZT_CHUNKSIZE * CHANNELS_PERXPD * 2;
-+
-+#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
-+
-+ DBG("Queueing xpd_post_init for xpd %d\n", xpd->id);
-+ if(!queue_work(xpd_init_workqueue, &xpd->xpd_post_init)) {
-+ ERR("Failed to queue xpd_post_init work\n");
-+ return -EINVAL;
-+ }
-+ return 0;
++ BUG_ON(!xpd);
++ atomic_set(&xpd->card_present, 0);
++ if(SPAN_REGISTERED(xpd))
++ update_xpd_status(xpd, ZT_ALARM_NOTOPEN);
+}
+
+void xpd_remove(xpd_t *xpd)
@@ -5157,31 +5343,22 @@
+ BUG_ON(!xpd);
+ xbus = xpd->xbus;
+ INFO("Remove XPD #%d from xbus=%s\n", xpd->id, xbus->busname);
-+ xpd->state = XPD_STATE_OFF;
++#if 0
++ // TODO: elect a new sync master
++ if(sync_master == xpd)
++ set_sync_master(NULL);
++#endif
+ xpd_zaptel_unregister(xpd);
-+#ifdef CONFIG_PROC_FS
-+ if(xpd->xpd_proc) {
-+ DBG("Removing proc entry %s\n", xpd->xpdname);
-+ remove_proc_entry(xpd->xpdname, xbus->procdir);
-+ }
-+ if(xpd->xpd_slic) {
-+ char fname[NAME_MAX];
-+
-+ snprintf(fname, NAME_MAX, PROC_SLIC_FNAME, xpd->xpdname);
-+ DBG("Removing proc entry %s\n", fname);
-+ remove_proc_entry(fname, xbus->procdir);
-+ }
-+#endif
+ xbus->xpds[xpd->id] = NULL;
+ list_del(&xpd->xpd_list);
+ xbus->num_xpds--;
-+ cancel_delayed_work(&xpd->xpd_post_init);
+ CALL_XMETHOD(card_remove, xbus, xpd);
++ xpd_cleanup(xpd);
+ kfree((void *)xpd->writechunk);
+ kfree(xpd);
+}
+
-+void update_xpd_status(xpd_t *xpd, int alarm_flag)
++static void update_xpd_status(xpd_t *xpd, int alarm_flag)
+{
+ struct zt_span *span = &xpd->span;
+
@@ -5191,12 +5368,8 @@
+ }
+ switch (alarm_flag) {
+ case ZT_ALARM_NONE:
-+ xpd->state = XPD_STATE_ACTIVE;
+ xpd->last_response = jiffies;
+ break;
-+ case ZT_ALARM_RED:
-+ xpd->state = XPD_STATE_NOREPLY;
-+ break;
+ default:
+ // Nothing
+ break;
@@ -5208,6 +5381,31 @@
+ DBG("Update XPD alarms: %s -> %02X\n", xpd->span.name, alarm_flag);
+}
+
++void phone_hook(xpd_t *xpd, int channo, bool offhook)
++{
++ struct zt_chan *chan = &xpd->span.chans[channo];
++
++ if(offhook && !IS_SET(xpd->hookstate, channo)) { // OFFHOOK
++ DBG("OFFHOOK: channo=%d\n", chan->channo);
++ xpd->ringing[channo] = 0;
++ BIT_SET(xpd->hookstate, channo);
++ 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);
++ 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;
@@ -5215,7 +5413,7 @@
+
+ spin_lock_irqsave(&xpd->lock, flags);
+ if(xpd->direction != TO_PHONE) {
-+ ERR("%s: %s: Only FXS can report hookstate changes\n", __FUNCTION__, xpd->xpdname);
++ ERR("%s: %s: Only PHONE can report hookstate changes\n", __FUNCTION__, xpd->xpdname);
+ goto out;
+ }
+ if(!SPAN_REGISTERED(xpd)) {
@@ -5224,22 +5422,7 @@
+ }
+ 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++) {
-+ struct zt_chan *chan = &xpd->span.chans[i];
-+ if(IS_SET(fxs_off_hook, i) && !IS_SET(xpd->hookstate, i)) { // OFFHOOK
-+ DBG("OFFHOOK: channo=%d\n", chan->channo);
-+ xpd->ringing[i] = 0;
-+ BIT_SET(xpd->hookstate, i);
-+ zt_hooksig(chan, ZT_RXSIG_OFFHOOK);
-+ CALL_XMETHOD(CHAN_POWER, xpd->xbus, xpd, BIT(i), 0); // Power down (prevent overheating!!!)
-+ CALL_XMETHOD(LED, xpd->xbus, xpd, BIT(i), LED_GREEN, 1);
-+ } else if(!IS_SET(fxs_off_hook, i) && IS_SET(xpd->hookstate, i)) { // ONHOOK
-+ DBG("ONHOOK channo=%d\n", chan->channo);
-+ xpd->ringing[i] = 0;
-+ BIT_CLR(xpd->hookstate, i);
-+ zt_hooksig(chan, ZT_RXSIG_ONHOOK);
-+ CALL_XMETHOD(CHAN_POWER, xpd->xbus, xpd, BIT(i), 0); // Power down (prevent overheating!!!)
-+ CALL_XMETHOD(LED, xpd->xbus, xpd, BIT(i), LED_GREEN, 0);
-+ }
++ phone_hook(xpd, i, IS_SET(fxs_off_hook, i));
+ }
+out:
+ spin_unlock_irqrestore(&xpd->lock, flags);
@@ -5254,7 +5437,7 @@
+
+ spin_lock_irqsave(&xpd->lock, flags);
+ for(i = 0; i < xpd->channels; i++) {
-+ if(IS_SET(xpd->digital_outputs, i))
++ if(IS_SET(xpd->digital_outputs, i) || IS_SET(xpd->digital_inputs, i))
+ continue;
+ if(xpd->ringing[i]) {
+ // led state is toggled
@@ -5281,7 +5464,7 @@
+ BUG_ON(!xpd);
+
+ spin_lock_irqsave(&xpd->lock, flags);
-+ if(xpd->direction != TO_TRUNK && ((bug_counter++ % 1000) == 0)) {
++ if(xpd->direction != TO_PSTN && ((bug_counter++ % 1000) == 0)) {
+ ERR("%s: %s: Only FXO can report ring changes\n", __FUNCTION__, xpd->xpdname);
+ goto out;
+ }
@@ -5334,7 +5517,7 @@
+{
+ int i;
+
-+ NOTICE("Reseting counters of %s\n", xbus->busname);
++ DBG("Reseting counters of %s\n", xbus->busname);
+ for(i = 0; i < XBUS_COUNTER_MAX; i++) {
+ xbus->counters[i] = 0;
+ }
@@ -5364,11 +5547,11 @@
+ goto out;
+ spin_lock_irqsave(&xbus->lock, flags);
+
-+ len += sprintf(page + len, "%s: HW=%s bus_type=%d connected=%s\n",
++ len += sprintf(page + len, "%s: CONNECTOR=%s STATUS=%s bus_type=%d\n",
+ xbus->busname,
+ xbus->busdesc,
-+ xbus->bus_type,
-+ (xbus->hardware_exists) ? "yes" : "no"
++ (xbus->hardware_exists) ? "connected" : "missing",
++ xbus->bus_type
+ );
+ len += sprintf(page + len, "open_counter=%d packet_count=%d\n",
+ xbus->open_counter,
@@ -5407,16 +5590,20 @@
+{
+ int len = 0;
+
++ len += sprintf(page + len, "# To modify sync source write into this file:\n");
++ len += sprintf(page + len, "# HOST - For host based sync\n");
++ len += sprintf(page + len, "# 0 0 - XBUS-0/XPD-0 provide sync\n");
++ len += sprintf(page + len, "# m n - XBUS-m/XPD-n provide sync\n");
+ if(!sync_master)
+ len += sprintf(page + len, "HOST\n");
+ else
+ len += sprintf(page + len, "%s/%s\n", sync_master->xbus->busname, sync_master->xpdname);
-+ len += sprintf(page + len, "xpp_timer_count=%d\n", xpp_timer_count);
++ len += sprintf(page + len, "tick: #%d\n", xpp_timer_count);
+ unsigned int xpp_timer_rate = 0;
+ unsigned int 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, "xpp_timer_rate=%d\n", xpp_timer_rate);
++ len += sprintf(page + len, "tick rate: %4d/second (average over %d seconds)\n", xpp_timer_rate, SAMPLE_TICKS/HZ);
+ }
+ if (len <= off+count)
+ *eof = 1;
@@ -5468,26 +5655,17 @@
+ return count;
+}
+
-+int proc_xbus_ztregister_read(char *page, char **start, off_t off, int count, int *eof, void *data)
++int proc_xpd_ztregister_read(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;
++ int len = 0;
++ unsigned long flags;
++ xpd_t *xpd = data;
+
-+ if(!xbus)
-+ goto out;
-+ spin_lock_irqsave(&xbus->lock, flags);
++ BUG_ON(!xpd);
++ spin_lock_irqsave(&xpd->lock, flags);
+
-+ len += sprintf(page + len, "# To (un)register an XPD write into this file: <ID> <1/0>\n");
-+ len += sprintf(page + len, "# ID\tExists\tRegistered\n");
-+ for(i = 0; i < MAX_XPDS; i++) {
-+ xpd_t *xpd = xbus->xpds[i];
-+ bool registered = xpd && SPAN_REGISTERED(xpd);
-+ len += sprintf(page + len, "%d\t%s\t%s\n", i, (xpd)?"yes":"no", (registered)?"yes":"no");
-+ }
-+ spin_unlock_irqrestore(&xbus->lock, flags);
-+out:
++ len += sprintf(page + len, "%d\n", SPAN_REGISTERED(xpd));
++ spin_unlock_irqrestore(&xpd->lock, flags);
+ if (len <= off+count)
+ *eof = 1;
+ *start = page + off;
@@ -5499,31 +5677,25 @@
+ return len;
+}
+
-+static int proc_xbus_ztregister_write(struct file *file, const char __user *buffer, unsigned long count, void *data)
++static int proc_xpd_ztregister_write(struct file *file, const char __user *buffer, unsigned long count, void *data)
+{
-+ xbus_t *xbus = data;
-+ xpd_t *xpd;
-+ int xpd_num;
++ xpd_t *xpd = data;
+ const int NUM_SIZE = 100;
+ char buf[NUM_SIZE];
+ bool zt_reg;
+ int ret;
+
-+ BUG_ON(!xbus);
++ BUG_ON(!xpd);
+ if(count >= NUM_SIZE)
+ return -EINVAL;
+ if(copy_from_user(buf, buffer, count))
+ return -EFAULT;
+ buf[count] = '\0';
-+ ret = sscanf(buf, "%d %d", &xpd_num, &zt_reg);
-+ if(ret != 2)
++ ret = sscanf(buf, "%d", &zt_reg);
++ if(ret != 1)
+ return -EINVAL;
-+ xpd = xpd_of(xbus, xpd_num);
-+ if(!xpd) {
-+ ERR("%s: XPD number %d does not exist\n", __FUNCTION__, xpd_num);
-+ return -ENXIO;
-+ }
-+ DBG("%s: %s: xpd #%d %s\n", __FUNCTION__, xbus->busname, xpd_num, (zt_reg) ? "register" : "unregister");
++ 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
@@ -5531,14 +5703,6 @@
+ return (ret < 0) ? ret : count;
+}
+
-+int xpd_slic_write_proc(struct file *file, const char __user *buffer, unsigned long count, void *data)
-+{
-+ xpd_t *xpd = data;
-+
-+ BUG_ON(!xpd);
-+ return count;
-+}
-+
+#endif
+
+/**
@@ -5620,9 +5784,8 @@
+ DBG(" Skipping XPD #%d is MISSING\n", id);
+ continue;
+ }
-+ DBG(" XPD #%d STATE = %d\n", id, xpd->state);
-+ if(xpd->state != XPD_STATE_ACTIVE) {
-+ DBG(" Skipping XPD #%d not in ACTIVE state\n", id);
++ if(!atomic_read(&xpd->card_present)) {
++ DBG(" Skipping XPD #%d not present\n", id);
+ continue;
+ }
+ if(time_after(xpd->last_response+20, jiffies)) {
@@ -5724,9 +5887,7 @@
+ ERR("%s: BUG: xpd->id=%d != i=%d\n", __FUNCTION__, xpd->id, i);
+ continue;
+ }
-+ if (!SPAN_REGISTERED(xpd))
-+ continue;
-+ update_xpd_status(xpd, ZT_ALARM_NOTOPEN);
++ xpd_card_disable(xpd);
+ }
+ down_write(&xbus->in_use);
+ DBG("%s (deactivated)\n", xbus->busname);
@@ -5740,20 +5901,15 @@
+{
+ BUG_ON(!xbus);
+#ifdef CONFIG_PROC_FS
-+ if(xbus->procdir) {
-+ if(xbus->procsummary) {
-+ DBG("Removing proc entry " PROC_XBUS_SUMMARY ".\n");
-+ remove_proc_entry(PROC_XBUS_SUMMARY, xbus->procdir);
-+ xbus->procsummary = NULL;
++ 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_ztregister) {
-+ DBG("Removing proc entry " PROC_XBUS_ZTREGISTER ".\n");
-+ remove_proc_entry(PROC_XBUS_ZTREGISTER, xbus->procdir);
-+ xbus->proc_ztregister = NULL;
-+ }
-+ DBG("Removing proc entry %s.\n",xbus->busname);
++ DBG("Removing proc directory %s\n", xbus->busname);
+ remove_proc_entry(xbus->busname, xpp_procdir);
-+ xbus->procdir = NULL;
++ xbus->proc_xbus_dir = NULL;
+ }
+#endif
+ kfree(xbus);
@@ -5809,28 +5965,19 @@
+ xbus_reset_counters(xbus);
+#ifdef CONFIG_PROC_FS
+ DBG("Creating xbus proc directory %s.\n",xbus->busname);
-+ xbus->procdir = proc_mkdir(xbus->busname, xpp_procdir);
-+ if(!xbus->procdir) {
++ 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->procsummary = create_proc_read_entry(PROC_XBUS_SUMMARY, 0644, xbus->procdir,
++ xbus->proc_xbus_summary = create_proc_read_entry(PROC_XBUS_SUMMARY, 0444, xbus->proc_xbus_dir,
+ xbus_read_proc, xbus);
-+ if (!xbus->procsummary) {
++ 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_ztregister = create_proc_entry(PROC_XBUS_ZTREGISTER, 0644, xbus->procdir);
-+ if (!xbus->proc_ztregister) {
-+ ERR("Failed to create '%s' proc file for xbus %s\n", PROC_XBUS_ZTREGISTER, xbus->busname);
-+ err = -EIO;
-+ goto nobus;
-+ }
-+ xbus->proc_ztregister->data = xbus;
-+ xbus->proc_ztregister->read_proc = proc_xbus_ztregister_read;
-+ xbus->proc_ztregister->write_proc = proc_xbus_ztregister_write;
+#endif
+ return xbus;
+nobus:
@@ -5864,7 +6011,7 @@
+ xpd_t *xpd = xpd_of(xbus, i);
+
+ if(xpd) {
-+ xops_t *xops = xpd->xops;
++ const xops_t *xops = xpd->xops;
+
+ if(xpd->id != i) {
+ ERR("%s: BUG: xpd->id=%d != i=%d\n", __FUNCTION__, xpd->id, i);
@@ -5872,7 +6019,6 @@
+ }
+ BUG_ON(!xops);
+ DBG(" Removing xpd id=%d\n", xpd->id);
-+ BUG_ON(!xops->card_remove);
+ xpd_remove(xpd);
+ }
+ xbus->xpds[i] = NULL;
@@ -5929,7 +6075,7 @@
+ }
+ w += ZT_CHUNKSIZE;
+ }
-+ if(xpd->hookstate != 0 || sync_master == xpd) {
++ if(xpd->hookstate != 0 || sync_master == xpd || !sync_master) {
+ ret = CALL_XMETHOD(PCM_WRITE, xpd->xbus, xpd, xpd->hookstate, writechunk);
+ if(ret < 0) {
+ DBG("failed to write PCM %d\n", ret);
@@ -6101,10 +6247,14 @@
+
+ if (txsig == ZT_TXSIG_START) {
+ if(xpd->direction == TO_PHONE) {
-+ // An FXS line: ZT_START will be treated as ZT_RING
-+ DBG("Got ZT_START for FXS channel %d, treated as ZT_RING\n", pos);
++ // 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);
@@ -6118,7 +6268,7 @@
+ return ret;
+ }
+ return ret;
-+ } else { /* TO_TRUNK */
++ } 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;
@@ -6133,6 +6283,10 @@
+ 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);
@@ -6155,6 +6309,10 @@
+ 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);
@@ -6201,6 +6359,10 @@
+ * 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);
@@ -6235,7 +6397,7 @@
+ // Fall through
+ case ZT_OFFHOOK:
+ if(xpd->direction == TO_PHONE) {
-+ DBG("ZT_OFFHOOK: %s hookstate=0x%04X -- ignoring (FXS)\n", chan->name, xpd->hookstate);
++ 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);
@@ -6256,6 +6418,10 @@
+ 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);
@@ -6389,18 +6555,17 @@
+{
+ BUG_ON(!xpd);
+
-+ if (!SPAN_REGISTERED(xpd)) {
++ if(!SPAN_REGISTERED(xpd)) {
+ NOTICE("%s: %s is already unregistered\n", __FUNCTION__, xpd->xpdname);
+ return -EIDRM;
+ }
++ if(sync_master == xpd)
++ set_sync_master(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));
+ return -EBUSY;
+ }
-+ if(sync_master == xpd)
-+ set_sync_master(NULL); // FIXME: it's better to elect a new prince
-+ update_xpd_status(xpd, ZT_ALARM_NOTOPEN);
-+ xpd->state = XPD_STATE_OFF;
+ mdelay(2); // FIXME: This is to give chance for transmit/receiveprep to finish.
+ zt_unregister(&xpd->span);
+ return 0;
@@ -6414,7 +6579,7 @@
+ int sigfxs;
+ int i;
+ int cn;
-+ xops_t *xops;
++ const xops_t *xops;
+
+ BUG_ON(!xpd);
+ xops = xpd->xops;
@@ -6455,8 +6620,13 @@
+
+ cur_chan = &xpd->chans[i];
+ DBG("setting channel %d (sigfxs=%d)\n", i, sigfxs);
-+ snprintf(cur_chan->name, MAX_CHANNAME, "XPP_%s/%d-%d",
-+ (sigfxs) ? "FXO" : "FXS", xpd->id, i);
++ 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)
@@ -6513,11 +6683,8 @@
+ xbus->xpds[xpd->id] = NULL;
+ list_del(&xpd->xpd_list);
+ xbus->num_xpds--;
-+ xpd->state = XPD_STATE_ZAPTEL_ERR;
+ return -ENODEV;
+ }
-+ xpd->state = XPD_STATE_ACTIVE;
-+ CALL_PROTO(GLOBAL, SYNC_SOURCE, xbus, xpd, 0, 0); // Query SYNC_SOURCE
+// if(xpd->id == 0)
+// set_sync_master(xpd);
+
@@ -6534,26 +6701,23 @@
+ int len = 0;
+ unsigned long flags;
+ int i;
-+ unsigned long stamp = jiffies;
+
+ spin_lock_irqsave(&xbuses_lock, flags);
-+ len += sprintf(page + len, "Global:\n");
-+ len += sprintf(page + len, "\tjiffies=%ld\n", stamp);
-+ len += sprintf(page + len, "\txpacket_count=%d\n", atomic_read(&xpacket_count));
-+ len += sprintf(page + len, "\tbus_count=%d\n", bus_count);
+ for(i = 0; i < MAX_BUSES; i++) {
+ xbus_t *xbus = xbus_of(i);
+
+ if(xbus) {
-+ len += sprintf(page + len, "%s: HW=%s bus_type=%d connected=%s\n",
++ len += sprintf(page + len, "%s: CONNECTOR=%s STATUS=%s bus_type=%d\n",
+ xbus->busname,
+ xbus->busdesc,
-+ xbus->bus_type,
-+ (xbus->hardware_exists) ? "yes" : "no"
++ (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;
@@ -6684,10 +6848,10 @@
+ remove_proc_entry(PROC_DIR, NULL);
+ }
+#endif
-+ if (xpd_init_workqueue) {
-+ flush_workqueue(xpd_init_workqueue);
-+ destroy_workqueue(xpd_init_workqueue);
-+ xpd_init_workqueue=NULL;
++ if (xpp_worker) {
++ flush_workqueue(xpp_worker);
++ destroy_workqueue(xpp_worker);
++ xpp_worker = NULL;
+ }
+ kmem_cache_destroy(packet_cache);
+}
@@ -6719,15 +6883,15 @@
+ ent->read_proc = proc_sync_read;
+ ent->write_proc = proc_sync_write;
+ ent->data = NULL;
-+ ent = create_proc_read_entry(PROC_XBUSES, 0644, xpp_procdir, xpp_zap_read_proc, 0);
++ ent = create_proc_read_entry(PROC_XBUSES, 0444, xpp_procdir, xpp_zap_read_proc, 0);
+ if (!ent) {
+ do_cleanup();
+ return -EFAULT;
+ }
+#endif
-+ xpd_init_workqueue = create_singlethread_workqueue("XppReg");
-+ if(!xpd_init_workqueue) {
-+ ERR("Failed to create registration workqueue.\n");
++ xpp_worker = create_singlethread_workqueue("xppworker");
++ if(!xpp_worker) {
++ ERR("Failed to create card detector workqueue.\n");
+ do_cleanup();
+ return -ENOMEM;
+ }
@@ -6764,7 +6928,8 @@
+}
+
+EXPORT_SYMBOL(print_dbg);
-+EXPORT_SYMBOL(xpd_new);
++EXPORT_SYMBOL(card_detected);
++EXPORT_SYMBOL(xpd_alloc);
+EXPORT_SYMBOL(xbus_activate);
+EXPORT_SYMBOL(xbus_deactivate);
+EXPORT_SYMBOL(xpd_of);
@@ -6777,7 +6942,7 @@
+EXPORT_SYMBOL(xbus_dequeue_packet);
+EXPORT_SYMBOL(init_xbus_packet_queue);
+EXPORT_SYMBOL(drain_xbus_packet_queue);
-+EXPORT_SYMBOL(update_xpd_status);
++EXPORT_SYMBOL(phone_hook);
+EXPORT_SYMBOL(xpp_check_hookstate);
+EXPORT_SYMBOL(xpp_tick);
+EXPORT_SYMBOL(xpp_open);
@@ -6788,18 +6953,20 @@
+MODULE_DESCRIPTION("XPP Zaptel Driver");
+MODULE_AUTHOR("Oron Peled <oron at actcom.co.il>");
+MODULE_LICENSE("GPL");
-+MODULE_VERSION("$Id: xpp_zap.c 167 2006-01-03 12:39:36Z oron $");
++MODULE_VERSION("$Id: xpp_zap.c 185 2006-01-10 14:39:07Z oron $");
+
+module_init(xpp_zap_init);
+module_exit(xpp_zap_cleanup);
-diff -urNad zaptel-1.0.10/xpp/xpp_zap.h /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/xpp_zap.h
---- zaptel-1.0.10/xpp/xpp_zap.h 1970-01-01 02:00:00.000000000 +0200
-+++ /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/xpp_zap.h 2006-01-03 13:22:53.823218000 +0200
-@@ -0,0 +1,44 @@
+diff -urNad trunk/xpp/xpp_zap.h /tmp/dpep.qIz4nf/trunk/xpp/xpp_zap.h
+--- trunk/xpp/xpp_zap.h 1970-01-01 02:00:00.000000000 +0200
++++ /tmp/dpep.qIz4nf/trunk/xpp/xpp_zap.h 2006-01-11 10:12:52.381169000 +0200
+@@ -0,0 +1,58 @@
+#ifndef XPP_ZAP_H
+#define XPP_ZAP_H
+
++#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);
@@ -6816,11 +6983,11 @@
+
+void xbus_reset_counters(xbus_t *xbus);
+int packet_send(xbus_t *xbus, xpacket_t *pack_tx);
-+void update_xpd_status(xpd_t *xpd, int alarm_flag);
++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);
-+xpd_t *xpd_new(xbus_t *xbus, int xpd_num, xpd_type_t type, byte revision);
-+int xpd_setup(xpd_t *xpd);
++void card_detected(void *data);
++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 fill_beep(u_char *buf, int duration);
+void xpp_tick(unsigned long param);
@@ -6829,9 +6996,21 @@
+int xpp_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long arg);
+int xpp_maint(struct zt_span *span, int cmd);
+
++#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>
+
-+#ifdef CONFIG_PROC_FS
+extern struct proc_dir_entry *xpp_procdir;
+#endif
+extern xpd_t *sync_master;
@@ -6840,10 +7019,10 @@
+#define RINGS_NUM 3
+
+#endif /* XPP_ZAP_H */
-diff -urNad zaptel-1.0.10/xpp/xproto.c /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/xproto.c
---- zaptel-1.0.10/xpp/xproto.c 1970-01-01 02:00:00.000000000 +0200
-+++ /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/xproto.c 2006-01-03 13:22:53.823218000 +0200
-@@ -0,0 +1,244 @@
+diff -urNad trunk/xpp/xproto.c /tmp/dpep.qIz4nf/trunk/xpp/xproto.c
+--- trunk/xpp/xproto.c 1970-01-01 02:00:00.000000000 +0200
++++ /tmp/dpep.qIz4nf/trunk/xpp/xproto.c 2006-01-11 10:12:52.381169000 +0200
+@@ -0,0 +1,334 @@
+/*
+ * Written by Oron Peled <oron at actcom.co.il>
+ * Copyright (C) 2004-2005, Xorcom
@@ -6871,11 +7050,13 @@
+#include "xpp_zap.h"
+#include <linux/module.h>
+
-+static const char rcsid[] = "$Id: xproto.c 164 2006-01-03 11:14:34Z oron $";
++static const char rcsid[] = "$Id: xproto.c 184 2006-01-10 11:22:14Z 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];
++
+bool valid_xpd_addr(const xpd_addr_t *addr)
+{
+ return ((addr->bank_num & ~0x1) == 0) && ((addr->card_id & ~0x3) == 0);
@@ -6901,11 +7082,14 @@
+
+/*---------------- General Protocol Management ----------------------------*/
+
-+#define XTABLE_ENTRY(name) [ XPD_TYPE(name) ] &name ## _protocol_table
++const xproto_entry_t *xproto_card_entry(const xproto_table_t *table, byte opcode)
++{
++ const xproto_entry_t *xe;
+
-+xproto_table_t *xprotocol_tables[] = {
-+ XTABLE_ENTRY(FXS),
-+};
++ //DBG("\n");
++ xe = &table->entries[opcode];
++ return (xe->handler != NULL) ? xe : NULL;
++}
+
+const xproto_entry_t *xproto_global_entry(byte opcode)
+{
@@ -6921,18 +7105,30 @@
+ return xproto_card_handler(&PROTO_TABLE(GLOBAL), opcode);
+}
+
-+const xproto_table_t *get_xproto_table(xpd_type_t cardtype)
++const xproto_table_t *xproto_table(xpd_type_t cardtype)
+{
++ if(cardtype >= XPD_TYPE_NOMODULE)
++ return NULL;
+ return xprotocol_tables[cardtype];
+}
+
-+const xproto_entry_t *xproto_card_entry(const xproto_table_t *table, byte opcode)
++const xproto_table_t *get_xproto_table(xpd_type_t cardtype)
+{
-+ const xproto_entry_t *xe;
++ const xproto_table_t *xtable;
+
-+ //DBG("\n");
-+ xe = &table->entries[opcode];
-+ return (xe->handler != NULL) ? xe : NULL;
++ if(cardtype >= XPD_TYPE_NOMODULE)
++ return NULL;
++ xtable = xprotocol_tables[cardtype];
++ if(!xtable) { /* Try to load the relevant module */
++ int ret = request_module("xpd-type-%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... */
++ }
++ xtable = xprotocol_tables[cardtype];
++ }
++ return xtable;
+}
+
+const xproto_handler_t xproto_card_handler(const xproto_table_t *table, byte opcode)
@@ -6955,7 +7151,7 @@
+
+ if(!xpd)
+ return NULL;
-+ xtable = get_xproto_table(xpd->type);
++ xtable = xproto_table(xpd->type);
+ if(!xtable)
+ return NULL;
+ xe = xproto_card_entry(xtable, opcode);
@@ -6965,18 +7161,16 @@
+ return xe;
+}
+
-+#define DEF_(t) \
-+ [ XPD_TYPE_ ## t ] = & t ## _xops
++const xops_t *get_xops(xpd_type_t xpd_type)
++{
++ const xproto_table_t *proto_table;
+
-+xops_t *xpd_card_ops[XPD_TYPE_NOMODULE] = {
-+ DEF_(FXS),
-+};
-+
-+xops_t *get_xops(xpd_type_t xpd_type)
-+{
+ if(xpd_type >= XPD_TYPE_NOMODULE)
+ return NULL;
-+ return xpd_card_ops[xpd_type];
++ proto_table = xprotocol_tables[xpd_type];
++ if(!proto_table)
++ return NULL;
++ return &proto_table->xops;
+}
+
+int packet_receive(xbus_t *xbus, xpacket_t *pack)
@@ -7083,15 +7277,90 @@
+#endif
+}
+
++const char *xproto_name(xpd_type_t xpd_type)
++{
++ const xproto_table_t *proto_table;
++
++ BUG_ON(xpd_type >= XPD_TYPE(NOMODULE));
++ proto_table = xprotocol_tables[xpd_type];
++ if(!proto_table)
++ return NULL;
++ return proto_table->name;
++}
++
++#define CHECK_XOP(f) \
++ if(!(xops)->f) { \
++ ERR("%s: missing xmethod %s [%s (%d)]\n", __FUNCTION__, #f, name, type); \
++ return -EINVAL; \
++ }
++
++int xproto_register(const xproto_table_t *proto_table)
++{
++ int type;
++ const char *name;
++ const xops_t *xops;
++
++ BUG_ON(!proto_table);
++ type = proto_table->type;
++ name = proto_table->name;
++ if(type >= XPD_TYPE(NOMODULE)) {
++ NOTICE("%s: Bad xproto type %d\n", __FUNCTION__, type);
++ return -EINVAL;
++ }
++ DBG("%s (%d)\n", name, type);
++ if(xprotocol_tables[type])
++ NOTICE("%s: overriding registration of %s (%d)\n", __FUNCTION__, name, type);
++ xops = &proto_table->xops;
++ CHECK_XOP(card_new);
++ CHECK_XOP(card_init);
++ CHECK_XOP(card_remove);
++ CHECK_XOP(card_tick);
++ 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;
++ return 0;
++}
++
++void xproto_unregister(const xproto_table_t *proto_table)
++{
++ int type;
++ const char *name;
++
++ BUG_ON(!proto_table);
++ type = proto_table->type;
++ name = proto_table->name;
++ DBG("%s (%d)\n", name, type);
++ if(type >= XPD_TYPE(NOMODULE)) {
++ NOTICE("%s: Bad xproto type %s (%d)\n", __FUNCTION__, name, type);
++ return;
++ }
++ if(!xprotocol_tables[type])
++ NOTICE("%s: xproto type %s (%d) is already unregistered\n", __FUNCTION__, name, type);
++ xprotocol_tables[type] = NULL;
++}
++
+EXPORT_SYMBOL(dump_packet);
+EXPORT_SYMBOL(packet_receive);
+EXPORT_SYMBOL(valid_xpd_addr);
+EXPORT_SYMBOL(xpd_addr2num);
+EXPORT_SYMBOL(xpd_set_addr);
-diff -urNad zaptel-1.0.10/xpp/xproto.h /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/xproto.h
---- zaptel-1.0.10/xpp/xproto.h 1970-01-01 02:00:00.000000000 +0200
-+++ /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/xproto.h 2006-01-03 13:22:53.823218000 +0200
-@@ -0,0 +1,247 @@
++EXPORT_SYMBOL(xproto_global_entry);
++EXPORT_SYMBOL(xproto_card_entry);
++EXPORT_SYMBOL(xproto_name);
++EXPORT_SYMBOL(xproto_register);
++EXPORT_SYMBOL(xproto_unregister);
+diff -urNad trunk/xpp/xproto.h /tmp/dpep.qIz4nf/trunk/xpp/xproto.h
+--- trunk/xpp/xproto.h 1970-01-01 02:00:00.000000000 +0200
++++ /tmp/dpep.qIz4nf/trunk/xpp/xproto.h 2006-01-09 18:14:37.000000000 +0200
+@@ -0,0 +1,239 @@
+#ifndef XPROTO_H
+#define XPROTO_H
+/*
@@ -7218,20 +7487,6 @@
+ const xproto_entry_t *cmd,
+ xpacket_t *pack);
+
-+struct xproto_entry {
-+ xproto_handler_t handler;
-+ int datalen;
-+ const char *name;
-+ xproto_table_t *table;
-+};
-+
-+struct xproto_table {
-+ xproto_entry_t entries[255]; /* Indexed by opcode */
-+ const char *name;
-+ bool (*packet_is_valid)(xpacket_t *pack);
-+ void (*packet_dump)(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);
@@ -7241,44 +7496,47 @@
+const xproto_entry_t *xproto_global_entry(byte opcode);
+const xproto_handler_t xproto_global_handler(byte opcode);
+
-+#define XMETHOD(name, ...) \
-+ int (*name)(xbus_t *xbus, xpd_t *xpd, ## __VA_ARGS__ );
-+
-+#if 0
+#define CALL_XMETHOD(name, xbus, xpd, ...) \
-+ ( \
-+ (xpd) && (xpd)->xops && (xpd)->xops->name && \
-+ (xpd)->xops->name(xbus, xpd, ## __VA_ARGS__ ) \
-+ )
-+#else
-+#define CALL_XMETHOD(name, xbus, xpd, ...) \
+ (xpd)->xops->name(xbus, xpd, ## __VA_ARGS__ )
-+#endif
+
+struct xops {
-+ XMETHOD(card_new, byte rev);
-+ XMETHOD(card_init);
-+ XMETHOD(card_remove);
++ xpd_t *(*card_new)(xbus_t *xbus, int xpd_num, const xproto_table_t *proto_table, byte revision);
++ 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);
+
-+ XMETHOD(DESC_REQ, int xpd_num);
-+ XMETHOD(SYNC_SOURCE, bool setit, bool is_master);
-+ XMETHOD(PCM_WRITE, xpp_line_t hookstate, volatile byte *buf);
++ 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);
+
-+ XMETHOD(CHAN_ENABLE, xpp_line_t lines, bool on);
-+ XMETHOD(CHAN_POWER, xpp_line_t lines, bool on);
-+ XMETHOD(CHAN_CID, xpp_line_t lines);
-+ XMETHOD(RING, int pos, bool on);
-+ XMETHOD(SETHOOK, xpp_line_t hook_status);
-+ XMETHOD(LED, xpp_line_t lines, byte which, bool on);
-+ XMETHOD(RELAY_OUT, byte which, bool on);
-+ XMETHOD(SLIC_INIT);
-+ XMETHOD(SLIC_QUERY, int pos, byte reg_num);
++ 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 (*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 (*RELAY_OUT)(xbus_t *xbus, xpd_t *xpd, byte which, bool on);
+};
+
-+xops_t *get_xops(xpd_type_t xpd_type);
++const xops_t *get_xops(xpd_type_t xpd_type);
+
+#undef XMETHOD
+
++struct xproto_entry {
++ xproto_handler_t handler;
++ int datalen;
++ const char *name;
++ xproto_table_t *table;
++};
++
++struct xproto_table {
++ xproto_entry_t entries[255]; /* Indexed by opcode */
++ xops_t xops;
++ xpd_type_t type;
++ const char *name;
++ bool (*packet_is_valid)(xpacket_t *pack);
++ void (*packet_dump)(xpacket_t *pack);
++};
++
+#include "card_global.h"
+#include "card_fxs.h"
+
@@ -7334,14 +7592,17 @@
+ struct list_head list;
+};
+
-+
+void dump_packet(const char *msg, xpacket_t *packet, bool print_dbg);
+int packet_receive(xbus_t *xbus, xpacket_t *pack);
++int xproto_register(const xproto_table_t *proto_table);
++void xproto_unregister(const xproto_table_t *proto_table);
++const xproto_entry_t *xproto_global_entry(byte opcode);
++const char *xproto_name(xpd_type_t xpd_type);
+
+#endif /* XPROTO_H */
-diff -urNad zaptel-1.0.10/xpp/zap_debug.c /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/zap_debug.c
---- zaptel-1.0.10/xpp/zap_debug.c 1970-01-01 02:00:00.000000000 +0200
-+++ /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/zap_debug.c 2006-01-03 13:22:53.823218000 +0200
+diff -urNad trunk/xpp/zap_debug.c /tmp/dpep.qIz4nf/trunk/xpp/zap_debug.c
+--- trunk/xpp/zap_debug.c 1970-01-01 02:00:00.000000000 +0200
++++ /tmp/dpep.qIz4nf/trunk/xpp/zap_debug.c 2006-01-09 18:14:37.000000000 +0200
@@ -0,0 +1,136 @@
+/*
+ * Written by Oron Peled <oron at actcom.co.il>
@@ -7479,9 +7740,9 @@
+EXPORT_SYMBOL(dump_poll);
+EXPORT_SYMBOL(event2str);
+EXPORT_SYMBOL(dump_sigtype);
-diff -urNad zaptel-1.0.10/xpp/zap_debug.h /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/zap_debug.h
---- zaptel-1.0.10/xpp/zap_debug.h 1970-01-01 02:00:00.000000000 +0200
-+++ /tmp/dpep.lpTITx/zaptel-1.0.10/xpp/zap_debug.h 2006-01-03 13:22:53.823218000 +0200
+diff -urNad trunk/xpp/zap_debug.h /tmp/dpep.qIz4nf/trunk/xpp/zap_debug.h
+--- trunk/xpp/zap_debug.h 1970-01-01 02:00:00.000000000 +0200
++++ /tmp/dpep.qIz4nf/trunk/xpp/zap_debug.h 2006-01-09 18:14:37.000000000 +0200
@@ -0,0 +1,16 @@
+#ifndef ZAP_DEBUG_H
+#define ZAP_DEBUG_H
More information about the Pkg-voip-commits
mailing list