Remove support for xpp drivers.
authorKeith Morgan <kmorgan@digium.com>
Wed, 3 Oct 2018 15:31:08 +0000 (15:31 +0000)
committerKeith Morgan <kmorgan@digium.com>
Wed, 3 Oct 2018 15:31:08 +0000 (15:31 +0000)
68 files changed:
drivers/dahdi/Kbuild
drivers/dahdi/Kconfig
drivers/dahdi/xpp/Changelog_xpp [deleted file]
drivers/dahdi/xpp/Kbuild [deleted file]
drivers/dahdi/xpp/Kconfig [deleted file]
drivers/dahdi/xpp/Makefile [deleted file]
drivers/dahdi/xpp/XppConfig.pm [deleted file]
drivers/dahdi/xpp/card_bri.c [deleted file]
drivers/dahdi/xpp/card_bri.h [deleted file]
drivers/dahdi/xpp/card_echo.c [deleted file]
drivers/dahdi/xpp/card_echo.h [deleted file]
drivers/dahdi/xpp/card_fxo.c [deleted file]
drivers/dahdi/xpp/card_fxo.h [deleted file]
drivers/dahdi/xpp/card_fxs.c [deleted file]
drivers/dahdi/xpp/card_fxs.h [deleted file]
drivers/dahdi/xpp/card_global.c [deleted file]
drivers/dahdi/xpp/card_global.h [deleted file]
drivers/dahdi/xpp/card_pri.c [deleted file]
drivers/dahdi/xpp/card_pri.h [deleted file]
drivers/dahdi/xpp/dahdi_debug.c [deleted file]
drivers/dahdi/xpp/dahdi_debug.h [deleted file]
drivers/dahdi/xpp/firmwares/FPGA_1141.hex [deleted file]
drivers/dahdi/xpp/firmwares/FPGA_1151.hex [deleted file]
drivers/dahdi/xpp/firmwares/FPGA_1161.201.hex [deleted file]
drivers/dahdi/xpp/firmwares/FPGA_1161.202.hex [deleted symlink]
drivers/dahdi/xpp/firmwares/FPGA_1161.hex [deleted file]
drivers/dahdi/xpp/firmwares/FPGA_FXS.hex [deleted file]
drivers/dahdi/xpp/firmwares/LICENSE.firmware [deleted file]
drivers/dahdi/xpp/firmwares/Makefile [deleted file]
drivers/dahdi/xpp/firmwares/PIC_TYPE_1.hex [deleted file]
drivers/dahdi/xpp/firmwares/PIC_TYPE_2.hex [deleted file]
drivers/dahdi/xpp/firmwares/PIC_TYPE_3.hex [deleted file]
drivers/dahdi/xpp/firmwares/PIC_TYPE_4.hex [deleted file]
drivers/dahdi/xpp/firmwares/PIC_TYPE_6.hex [deleted file]
drivers/dahdi/xpp/firmwares/README [deleted file]
drivers/dahdi/xpp/firmwares/USB_FW.201.hex [deleted file]
drivers/dahdi/xpp/firmwares/USB_FW.202.hex [deleted symlink]
drivers/dahdi/xpp/firmwares/USB_FW.hex [deleted file]
drivers/dahdi/xpp/firmwares/USB_RECOV.hex [deleted file]
drivers/dahdi/xpp/init_card_1_30 [deleted file]
drivers/dahdi/xpp/init_card_2_30 [deleted file]
drivers/dahdi/xpp/init_card_3_30 [deleted file]
drivers/dahdi/xpp/init_card_4_30 [deleted file]
drivers/dahdi/xpp/init_card_5_30 [deleted file]
drivers/dahdi/xpp/init_card_6_30 [deleted file]
drivers/dahdi/xpp/mmapbus.c [deleted file]
drivers/dahdi/xpp/mmapbus.h [deleted file]
drivers/dahdi/xpp/mmapdrv.c [deleted file]
drivers/dahdi/xpp/param_doc [deleted file]
drivers/dahdi/xpp/parport_debug.c [deleted file]
drivers/dahdi/xpp/parport_debug.h [deleted file]
drivers/dahdi/xpp/print_fxo_modes.c [deleted file]
drivers/dahdi/xpp/xbus-core.c [deleted file]
drivers/dahdi/xpp/xbus-core.h [deleted file]
drivers/dahdi/xpp/xbus-pcm.c [deleted file]
drivers/dahdi/xpp/xbus-pcm.h [deleted file]
drivers/dahdi/xpp/xbus-sysfs.c [deleted file]
drivers/dahdi/xpp/xdefs.h [deleted file]
drivers/dahdi/xpp/xframe_queue.c [deleted file]
drivers/dahdi/xpp/xframe_queue.h [deleted file]
drivers/dahdi/xpp/xpd.h [deleted file]
drivers/dahdi/xpp/xpp.conf [deleted file]
drivers/dahdi/xpp/xpp_dahdi.c [deleted file]
drivers/dahdi/xpp/xpp_dahdi.h [deleted file]
drivers/dahdi/xpp/xpp_debug [deleted file]
drivers/dahdi/xpp/xpp_usb.c [deleted file]
drivers/dahdi/xpp/xproto.c [deleted file]
drivers/dahdi/xpp/xproto.h [deleted file]

index 855e5bf..6d9b91c 100644 (file)
@@ -41,7 +41,6 @@ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCB4XXP)         += wcb4xxp/
 
 endif
 
-obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPP)              += xpp/
 
 obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_JPAH)     += dahdi_echocan_jpah.o
 obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_STEVE)    += dahdi_echocan_sec.o
index 5b94bf1..2e9a6db 100644 (file)
@@ -223,4 +223,3 @@ config DAHDI_DYNAMIC_LOC
          If unsure, say Y.
 
 
-source "drivers/dahdi/xpp/Kconfig"
diff --git a/drivers/dahdi/xpp/Changelog_xpp b/drivers/dahdi/xpp/Changelog_xpp
deleted file mode 100644 (file)
index 5408651..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-Sun Mar  1 2009 Oron Peled <oron@actcom.co.il> - xpp.r6795
-  * Fix cases where the command_queue overflowed during initialization.
-    - Also add a 'command_queue_length' parameter to xpp.ko
-  * More migrations to sysfs:
-    - Add a 'transport' attribute to our astribank devices which
-      points to the usb device we use. E.g:
-       /sys/bus/astribanks/devices/xbus-00/transport is symlinked to
-       ../../../../../../devices/pci0000:00/0000:00:10.4/usb5/5-4
-    - Move /proc/xpp/XBUS-??/XPD-??/span to
-      /sys/bus/xpds/devices/??:?:?/span
-    - Migrate from /proc/xpp/sync to:
-      /sys/bus/astribanks/drivers/xppdrv/sync
-    - New 'offhook' attribute in:
-      /sys/bus/xpds/devices/??:?:?/offhook
-  * PRI: change the "timing" priority to match the convention used by
-         other PRI cards -- I.e: lower numbers (not 0) have higher
-        priority.
-  * FXO: 
-    - Power denial: create two module parameters instead of hard-coded
-      constants (power_denial_safezone, power_denial_minlen).
-      For sites that get non-standard power-denial signals from central
-      office on offhook.
-    - Don't hangup on power-denial, just notify Dahdi and wait for
-    - Fix caller-id detection for the case central office sends it before
-      first ring without any indication before.
-      Asterisk's desicion.
-  * USB_FW.hex:
-    - Fixes cases where firmware loading would fail.
-
-Thu, Aug 14 2008 Oron Peled <oron@actcom.co.il> - xpp.r6056
-  * First DAHDI-linux release.
diff --git a/drivers/dahdi/xpp/Kbuild b/drivers/dahdi/xpp/Kbuild
deleted file mode 100644 (file)
index 2965af0..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-EXTRA_CFLAGS   =       $(XPP_LOCAL_CFLAGS)     \
-                       -DDEBUG                 \
-                       -DPOLL_DIGITAL_INPUTS   \
-                       -DDEBUG_PCMTX           \
-                       -DPROTOCOL_DEBUG        \
-                       -g
-                       #
-
-WITH_BRISTUFF  := $(shell grep -c '^[[:space:]]*\#[[:space:]]*define[[:space:]]\+CONFIG_DAHDI_BRI_DCHANS\>' $(src)/../../../include/dahdi/dahdi_config.h)
-
-obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPP)              += xpp.o
-obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPD_FXS)          += xpd_fxs.o
-obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPD_FXO)          += xpd_fxo.o
-obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPD_PRI)          += xpd_pri.o
-obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPD_BRI)          += xpd_bri.o
-obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPD_ECHO)         += xpd_echo.o
-
-# Build only supported modules
-ifneq  (,$(filter y m,$(CONFIG_USB)))
-obj-$(DAHDI_BUILD_ALL)$(CONFIG_XPP_USB)                        += xpp_usb.o
-endif
-ifneq  (,$(filter y m,$(CONFIG_BF537)))
-obj-$(DAHDI_BUILD_ALL)$(CONFIG_XPP_MMAP)               += xpp_mmap.o
-endif
-
-xpp-objs               += xbus-core.o xbus-sysfs.o xbus-pcm.o xframe_queue.o xpp_dahdi.o xproto.o card_global.o dahdi_debug.o
-xpd_fxs-objs           += card_fxs.o
-xpd_fxo-objs           += card_fxo.o
-xpd_bri-objs           += card_bri.o
-xpd_pri-objs           += card_pri.o
-xpd_echo-objs          += card_echo.o
-xpp_mmap-objs          += mmapbus.o mmapdrv.o
-
-ifeq   (y,$(PARPORT_DEBUG))
-EXTRA_CFLAGS   += -DDEBUG_SYNC_PARPORT
-obj-m          += parport_debug.o
-endif
-
-# Just in case it was left from an older version:
-clean-files    += xpp_version.h
-
-# Validations:
-#  - Syntactic verification of perl scripts
-#  - Handle country table validation for init_card_2_*
-
-XPP_PROTOCOL_VERSION   := $(shell grep XPP_PROTOCOL_VERSION $(src)/xproto.h | sed -e 's/^.*XPP_PROTOCOL_VERSION[ \t]*//')
-
-xpp_verifications              = \
-                               init_card_1_$(XPP_PROTOCOL_VERSION)     \
-                               init_card_2_$(XPP_PROTOCOL_VERSION)     \
-                               init_card_3_$(XPP_PROTOCOL_VERSION)     \
-                               init_card_4_$(XPP_PROTOCOL_VERSION)     \
-                               init_fxo_modes
-
-xpp_verified                   = $(foreach file, $(xpp_verifications), $(file).verified)
-
-FXO_MODES  = $(src)/../fxo_modes.h
-FXO_VERIFY = $(obj)/init_card_2_$(XPP_PROTOCOL_VERSION) -v $(obj)/init_fxo_modes
-
-hostprogs-y                    := print_fxo_modes
-always                         := $(xpp_verified)
-print_fxo_modes-objs           := print_fxo_modes.o
-HOSTCFLAGS_print_fxo_modes.o   += -include $(FXO_MODES)
-
-clean-files                    += print_fxo_modes init_fxo_modes $(xpp_verified)
-
-$(obj)/init_fxo_modes: $(obj)/print_fxo_modes
-       @echo '  GEN     $@'
-       $(Q)$(obj)/print_fxo_modes >$@ || (rm -f $@; exit 1)
-
-$(obj)/init_fxo_modes.verified: $(obj)/init_card_2_$(XPP_PROTOCOL_VERSION) $(obj)/init_fxo_modes
-       @echo '  CHECK   $(obj)/init_card_2_$(XPP_PROTOCOL_VERSION)'
-       $(Q)$(FXO_VERIFY) || (rm -f $@; exit 1)
-       $(Q)touch $@
-
-$(obj)/init_card_%_$(XPP_PROTOCOL_VERSION).verified: $(src)/init_card_%_$(XPP_PROTOCOL_VERSION)
-       @echo '  VERIFY  $<'
-       $(Q)perl -c $< 2> $@ || (cat $@; rm -f $@; exit 1)
-
-.PHONY: FORCE
-FORCE:
diff --git a/drivers/dahdi/xpp/Kconfig b/drivers/dahdi/xpp/Kconfig
deleted file mode 100644 (file)
index aebd29c..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-#
-# XPP configuration
-#
-
-menuconfig DAHDI_XPP
-       tristate "Xorcom Astribank Support"
-       depends on DAHDI
-       default DAHDI
-       ---help---
-         Infrastructure support for Xorcom Astribank products.
-
-         To compile this driver as a module, choose M here: the
-         module will be called xpp.
-
-         If unsure, say Y.
-
-config DAHDI_XPP_USB
-       tristate "Astribank USB transport"
-       depends on DAHDI_XPP && USB
-       default DAHDI_XPP
-       ---help---
-         To compile this driver as a module, choose M here: the
-         module will be called xpp_usb.
-
-         If unsure, say Y.
-
-config DAHDI_XPP_MMAP
-       tristate "Astribank Blackfin transport"
-       depends on DAHDI_XPP && BF537
-       default DAHDI_XPP
-       ---help---
-         To compile this driver as a module, choose M here: the
-         module will be called xpp_mmap.
-         
-         This module can be compiled only on Blackfin architecture
-         (with uClinux).
-
-         If unsure, say N.
-
-config DAHDI_XPD_FXS
-       tristate "FXS port Support"
-       depends on DAHDI_XPP && (DAHDI_XPP_USB || DAHDI_XPP_MMAP)
-       default DAHDI_XPP
-       ---help---
-         To compile this driver as a module, choose M here: the
-         module will be called xpd_fxs.
-
-         If unsure, say Y.
-
-config DAHDI_XPD_FXO
-       tristate "FXO port Support"
-       depends on DAHDI_XPP && (DAHDI_XPP_USB || DAHDI_XPP_MMAP)
-       default DAHDI_XPP
-       ---help---
-         To compile this driver as a module, choose M here: the
-         module will be called xpd_fxo.
-
-         If unsure, say Y.
-
-config DAHDI_XPD_BRI
-       tristate "BRI port Support"
-       depends on DAHDI_XPP && (DAHDI_XPP_USB || DAHDI_XPP_MMAP)
-       default DAHDI_XPP
-       ---help---
-         To compile this driver as a module, choose M here: the
-         module will be called xpd_pri.
-
-         Note: this driver will be automatically excluded
-               from compilation if dahdi driver does not
-               contain the "bristuff" patch.
-
-         If unsure, say Y.
-
-config DAHDI_XPD_PRI
-       tristate "PRI port Support"
-       depends on DAHDI_XPP && (DAHDI_XPP_USB || DAHDI_XPP_MMAP)
-       default DAHDI_XPP
-       ---help---
-         To compile this driver as a module, choose M here: the
-         module will be called xpd_pri.
-
-         If unsure, say Y.
diff --git a/drivers/dahdi/xpp/Makefile b/drivers/dahdi/xpp/Makefile
deleted file mode 100644 (file)
index 00fc5ee..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-# We only get here on kernels 2.6.0-2.6.9 .
-# For newer kernels, Kbuild will be included directly by the kernel
-# build system.
--include $(src)/Kbuild
-
-ctags:
-       ctags *.[ch]
diff --git a/drivers/dahdi/xpp/XppConfig.pm b/drivers/dahdi/xpp/XppConfig.pm
deleted file mode 100644 (file)
index f00811f..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-package XppConfig;
-#
-# Written by Oron Peled <oron@actcom.co.il>
-# Copyright (C) 2008, Xorcom
-# This program is free software; you can redistribute and/or
-# modify it under the same terms as Perl itself.
-#
-# $Id$
-#
-use strict;
-
-my $conf_file = "/etc/dahdi/xpp.conf";
-
-sub import {
-       my $pack = shift || die "Import without package?";
-       my $init_dir = shift || die "$pack::import -- missing init_dir parameter";
-       my $local_conf = "$init_dir/xpp.conf";
-       $conf_file = $local_conf if -r $local_conf;
-}
-
-sub read_config($) {
-       my $opts = shift || die;
-
-       open(F, $conf_file) || return ();
-       while(<F>) {
-               chomp;
-               s/#.*//;        # strip comments
-               next unless /\S/;
-               s/\s*$//;       # Trim trailing whitespace
-               my ($key, $value) = split(/\s+/, $_, 2);
-               $opts->{$key} = $value;
-       }
-       close F;
-       $opts->{'xppconf'} = $conf_file;
-       return %{$opts};
-}
-
-1;
diff --git a/drivers/dahdi/xpp/card_bri.c b/drivers/dahdi/xpp/card_bri.c
deleted file mode 100644 (file)
index 12efecf..0000000
+++ /dev/null
@@ -1,1808 +0,0 @@
-/*
- * Written by Oron Peled <oron@actcom.co.il>
- * Copyright (C) 2004-2006, Xorcom
- *
- * Parts derived from Cologne demo driver for the chip.
- *
- * 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 <linux/seq_file.h>
-#include "xpd.h"
-#include "xproto.h"
-#include "xpp_dahdi.h"
-#include "card_bri.h"
-#include "dahdi_debug.h"
-#include "xbus-core.h"
-
-static const char rcsid[] = "$Id$";
-
-#ifndef        DAHDI_SIG_HARDHDLC
-#error Cannot build BRI without HARDHDLC supprt
-#endif
-
-/* must be before dahdi_debug.h */
-static DEF_PARM(int, debug, 0, 0644, "Print DBG statements");
-static DEF_PARM(uint, poll_interval, 500, 0644,
-               "Poll channel state interval in milliseconds (0 - disable)");
-static DEF_PARM_BOOL(nt_keepalive, 1, 0644,
-                    "Force BRI_NT to keep trying connection");
-
-enum xhfc_states {
-       ST_RESET = 0,           /* G/F0 */
-       /* TE */
-       ST_TE_SENSING = 2,      /* F2   */
-       ST_TE_DEACTIVATED = 3,  /* F3   */
-       ST_TE_SIGWAIT = 4,      /* F4   */
-       ST_TE_IDENT = 5,        /* F5   */
-       ST_TE_SYNCED = 6,       /* F6   */
-       ST_TE_ACTIVATED = 7,    /* F7   */
-       ST_TE_LOST_FRAMING = 8, /* F8   */
-       /* NT */
-       ST_NT_DEACTIVATED = 1,  /* G1   */
-       ST_NT_ACTIVATING = 2,   /* G2   */
-       ST_NT_ACTIVATED = 3,    /* G3   */
-       ST_NT_DEACTIVTING = 4,  /* G4   */
-};
-
-#ifdef CONFIG_PROC_FS
-static const char *xhfc_state_name(bool is_nt, enum xhfc_states state)
-{
-       const char *p;
-
-#define        _E(x)   [ST_ ## x] = #x
-       static const char *te_names[] = {
-               _E(RESET),
-               _E(TE_SENSING),
-               _E(TE_DEACTIVATED),
-               _E(TE_SIGWAIT),
-               _E(TE_IDENT),
-               _E(TE_SYNCED),
-               _E(TE_ACTIVATED),
-               _E(TE_LOST_FRAMING),
-       };
-       static const char *nt_names[] = {
-               _E(RESET),
-               _E(NT_DEACTIVATED),
-               _E(NT_ACTIVATING),
-               _E(NT_ACTIVATED),
-               _E(NT_DEACTIVTING),
-       };
-#undef _E
-       if (is_nt) {
-               if (state > ST_NT_DEACTIVTING)
-                       p = "NT ???";
-               else
-                       p = nt_names[state];
-       } else {
-               if (state > ST_TE_LOST_FRAMING)
-                       p = "TE ???";
-               else
-                       p = te_names[state];
-       }
-       return p;
-}
-#endif
-
-/* xhfc Layer1 physical commands */
-#define HFC_L1_ACTIVATE_TE             0x01
-#define HFC_L1_FORCE_DEACTIVATE_TE     0x02
-#define HFC_L1_ACTIVATE_NT             0x03
-#define HFC_L1_DEACTIVATE_NT           0x04
-
-#define HFC_L1_ACTIVATING      1
-#define HFC_L1_ACTIVATED       2
-#define        HFC_TIMER_T1            2500
-#define        HFC_TIMER_T3            8000    /* 8s activation timer T3 */
-#define        HFC_TIMER_OFF           -1      /* timer disabled */
-
-#define        A_SU_WR_STA             0x30    /* ST/Up state machine register */
-#define                V_SU_LD_STA     0x10
-#define        V_SU_ACT        0x60    /* start activation/deactivation        */
-#define        STA_DEACTIVATE  0x40    /* start deactivation in A_SU_WR_STA */
-#define        STA_ACTIVATE    0x60    /* start activation   in A_SU_WR_STA */
-#define        V_SU_SET_G2_G3  0x80
-
-#define        A_SU_RD_STA             0x30
-typedef union {
-       struct {
-               __u8 v_su_sta:4;
-               __u8 v_su_fr_sync:1;
-               __u8 v_su_t2_exp:1;
-               __u8 v_su_info0:1;
-               __u8 v_g2_g3:1;
-       } bits;
-       __u8 reg;
-} su_rd_sta_t;
-
-#define        REG30_LOST      3       /* in polls */
-#define        DCHAN_LOST      15000   /* in ticks */
-
-#define        BRI_DCHAN_SIGCAP        DAHDI_SIG_HARDHDLC
-#define        BRI_BCHAN_SIGCAP        (DAHDI_SIG_CLEAR | DAHDI_SIG_DACS)
-
-#define        IS_NT(xpd)              (PHONEDEV(xpd).direction == TO_PHONE)
-#define        BRI_PORT(xpd)           ((xpd)->addr.subunit)
-
-/* shift in PCM highway */
-#define        SUBUNIT_PCM_SHIFT       4
-#define        PCM_SHIFT(mask, sunit)  ((mask) << (SUBUNIT_PCM_SHIFT * (sunit)))
-
-/*---------------- BRI Protocol Commands ----------------------------------*/
-
-static int write_state_register(xpd_t *xpd, __u8 value);
-static bool bri_packet_is_valid(xpacket_t *pack);
-static void bri_packet_dump(const char *msg, xpacket_t *pack);
-#ifdef CONFIG_PROC_FS
-static const struct file_operations proc_bri_info_ops;
-#endif
-static int bri_spanconfig(struct file *file, struct dahdi_span *span,
-                         struct dahdi_lineconfig *lc);
-static int bri_chanconfig(struct file *file, struct dahdi_chan *chan,
-                         int sigtype);
-static int bri_startup(struct file *file, struct dahdi_span *span);
-static int bri_shutdown(struct dahdi_span *span);
-
-#define        PROC_BRI_INFO_FNAME     "bri_info"
-
-enum led_state {
-       BRI_LED_OFF = 0x0,
-       BRI_LED_ON = 0x1,
-       /*
-        * We blink by software from driver, so that
-        * if the driver malfunction that blink would stop.
-        */
-       // BRI_LED_BLINK_SLOW   = 0x2,  /* 1/2 a second blink cycle */
-       // BRI_LED_BLINK_FAST   = 0x3   /* 1/4 a second blink cycle */
-};
-
-enum bri_led_names {
-       GREEN_LED = 0,
-       RED_LED = 1
-};
-
-#define        NUM_LEDS        2
-#define        LED_TICKS       100
-
-struct bri_leds {
-       __u8 state:2;
-       __u8 led_sel:1;         /* 0 - GREEN, 1 - RED */
-       __u8 reserved:5;
-};
-
-#ifndef MAX_DFRAME_LEN_L1
-#define MAX_DFRAME_LEN_L1 300
-#endif
-
-#define        DCHAN_BUFSIZE   MAX_DFRAME_LEN_L1
-
-struct BRI_priv_data {
-       struct proc_dir_entry *bri_info;
-       su_rd_sta_t state_register;
-       bool initialized;
-       bool dchan_is_open;
-       int t1;                 /* timer 1 for NT deactivation */
-       int t3;                 /* timer 3 for TE activation */
-       ulong l1_flags;
-       bool reg30_good;
-       uint reg30_ticks;
-       bool layer1_up;
-
-       /*
-        * D-Chan: buffers + extra state info.
-        */
-       atomic_t hdlc_pending;
-       bool txframe_begin;
-
-       uint tick_counter;
-       uint poll_counter;
-       uint dchan_tx_counter;
-       uint dchan_rx_counter;
-       uint dchan_rx_drops;
-       bool dchan_alive;
-       uint dchan_alive_ticks;
-       uint dchan_notx_ticks;
-       uint dchan_norx_ticks;
-       enum led_state ledstate[NUM_LEDS];
-};
-
-static xproto_table_t PROTO_TABLE(BRI);
-
-DEF_RPACKET_DATA(BRI, SET_LED, /* Set one of the LED's */
-                struct bri_leds bri_leds;);
-
-static /* 0x33 */ DECLARE_CMD(BRI, SET_LED, enum bri_led_names which_led,
-                             enum led_state to_led_state);
-
-#define        DO_LED(xpd, which, tostate) \
-               CALL_PROTO(BRI, SET_LED, (xpd)->xbus, (xpd), (which), (tostate))
-
-#define DEBUG_BUF_SIZE (100)
-static void dump_hex_buf(xpd_t *xpd, char *msg, __u8 *buf, size_t len)
-{
-       char debug_buf[DEBUG_BUF_SIZE + 1];
-       int i;
-       int n = 0;
-
-       debug_buf[0] = '\0';
-       for (i = 0; i < len && n < DEBUG_BUF_SIZE; i++)
-               n += snprintf(&debug_buf[n], DEBUG_BUF_SIZE - n, "%02X ",
-                             buf[i]);
-       XPD_NOTICE(xpd, "%s[0..%zd]: %s%s\n", msg, len - 1, debug_buf,
-                  (n >= DEBUG_BUF_SIZE) ? "..." : "");
-}
-
-static void dump_dchan_packet(xpd_t *xpd, bool transmit, __u8 *buf, int len)
-{
-       struct BRI_priv_data *priv;
-       char msgbuf[MAX_PROC_WRITE];
-       char ftype = '?';
-       char *direction;
-       int frame_begin;
-
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       if (transmit) {
-               direction = "TX";
-               frame_begin = priv->txframe_begin;
-       } else {
-               direction = "RX";
-               frame_begin = 1;
-       }
-       if (frame_begin) {      /* Packet start */
-               if (!IS_SET(buf[0], 7))
-                       ftype = 'I';    /* Information */
-               else if (IS_SET(buf[0], 7) && !IS_SET(buf[0], 6))
-                       ftype = 'S';    /* Supervisory */
-               else if (IS_SET(buf[0], 7) && IS_SET(buf[0], 6))
-                       ftype = 'U';    /* Unnumbered */
-               else
-                       XPD_NOTICE(xpd, "Unknown frame type 0x%X\n", buf[0]);
-
-               snprintf(msgbuf, MAX_PROC_WRITE, "D-Chan %s = (%c) ", direction,
-                        ftype);
-       } else {
-               snprintf(msgbuf, MAX_PROC_WRITE, "D-Chan %s =     ", direction);
-       }
-       dump_hex_buf(xpd, msgbuf, buf, len);
-}
-
-static void set_bri_timer(xpd_t *xpd, const char *name, int *bri_timer,
-                         int value)
-{
-       if (value == HFC_TIMER_OFF)
-               XPD_DBG(SIGNAL, xpd, "Timer %s DISABLE\n", name);
-       else
-               XPD_DBG(SIGNAL, xpd, "Timer %s: set to %d\n", name, value);
-       *bri_timer = value;
-}
-
-static void dchan_state(xpd_t *xpd, bool up)
-{
-       struct BRI_priv_data *priv;
-
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       if (priv->dchan_alive == up)
-               return;
-       if (up) {
-               XPD_DBG(SIGNAL, xpd, "STATE CHANGE: D-Channel RUNNING\n");
-               priv->dchan_alive = 1;
-       } else {
-               XPD_DBG(SIGNAL, xpd, "STATE CHANGE: D-Channel STOPPED\n");
-               priv->dchan_rx_counter = priv->dchan_tx_counter =
-                   priv->dchan_rx_drops = 0;
-               priv->dchan_alive = 0;
-               priv->dchan_alive_ticks = 0;
-       }
-}
-
-static void layer1_state(xpd_t *xpd, bool up)
-{
-       struct BRI_priv_data *priv;
-
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       if (priv->layer1_up == up)
-               return;
-       priv->layer1_up = up;
-       XPD_DBG(SIGNAL, xpd, "STATE CHANGE: Layer1 %s\n", (up) ? "UP" : "DOWN");
-       if (!up)
-               dchan_state(xpd, 0);
-}
-
-static void te_activation(xpd_t *xpd, bool on)
-{
-       struct BRI_priv_data *priv;
-       __u8 curr_state;
-
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       curr_state = priv->state_register.bits.v_su_sta;
-       XPD_DBG(SIGNAL, xpd, "%s\n", (on) ? "ON" : "OFF");
-       if (on) {
-               if (curr_state == ST_TE_DEACTIVATED) {
-                       XPD_DBG(SIGNAL, xpd, "HFC_L1_ACTIVATE_TE\n");
-                       set_bit(HFC_L1_ACTIVATING, &priv->l1_flags);
-                       write_state_register(xpd, STA_ACTIVATE);
-                       set_bri_timer(xpd, "T3", &priv->t3, HFC_TIMER_T3);
-               } else {
-                       XPD_DBG(SIGNAL, xpd,
-                               "HFC_L1_ACTIVATE_TE (state %d, ignored)\n",
-                               curr_state);
-               }
-       } else {                /* happen only because of T3 expiry */
-               switch (curr_state) {
-               case ST_TE_DEACTIVATED: /* F3   */
-               case ST_TE_SYNCED:      /* F6   */
-               case ST_TE_ACTIVATED:   /* F7   */
-                       XPD_DBG(SIGNAL, xpd,
-                               "HFC_L1_FORCE_DEACTIVATE_TE "
-                               "(state %d, ignored)\n",
-                               curr_state);
-                       break;
-               case ST_TE_SIGWAIT:     /* F4   */
-               case ST_TE_IDENT:       /* F5   */
-               case ST_TE_LOST_FRAMING:        /* F8   */
-                       XPD_DBG(SIGNAL, xpd, "HFC_L1_FORCE_DEACTIVATE_TE\n");
-                       write_state_register(xpd, STA_DEACTIVATE);
-                       break;
-               default:
-                       XPD_NOTICE(xpd, "Bad TE state: %d\n", curr_state);
-                       break;
-               }
-       }
-}
-
-static void nt_activation(xpd_t *xpd, bool on)
-{
-       struct BRI_priv_data *priv;
-       __u8 curr_state;
-
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       curr_state = priv->state_register.bits.v_su_sta;
-       XPD_DBG(SIGNAL, xpd, "%s\n", (on) ? "ON" : "OFF");
-       if (on) {
-               switch (curr_state) {
-               case ST_RESET:  /* F/G 0 */
-               case ST_NT_DEACTIVATED: /* G1 */
-               case ST_NT_DEACTIVTING: /* G4 */
-                       XPD_DBG(SIGNAL, xpd, "HFC_L1_ACTIVATE_NT\n");
-                       set_bri_timer(xpd, "T1", &priv->t1, HFC_TIMER_T1);
-                       set_bit(HFC_L1_ACTIVATING, &priv->l1_flags);
-                       write_state_register(xpd, STA_ACTIVATE);
-                       break;
-               case ST_NT_ACTIVATING:  /* G2 */
-               case ST_NT_ACTIVATED:   /* G3 */
-                       XPD_DBG(SIGNAL, xpd,
-                               "HFC_L1_ACTIVATE_NT (in state %d, ignored)\n",
-                               curr_state);
-                       break;
-               }
-       } else {
-               switch (curr_state) {
-               case ST_RESET:  /* F/G 0 */
-               case ST_NT_DEACTIVATED: /* G1 */
-               case ST_NT_DEACTIVTING: /* G4 */
-                       XPD_DBG(SIGNAL, xpd,
-                               "HFC_L1_DEACTIVATE_NT (in state %d, ignored)\n",
-                               curr_state);
-                       break;
-               case ST_NT_ACTIVATING:  /* G2 */
-               case ST_NT_ACTIVATED:   /* G3 */
-                       XPD_DBG(SIGNAL, xpd, "HFC_L1_DEACTIVATE_NT\n");
-                       write_state_register(xpd, STA_DEACTIVATE);
-                       break;
-               default:
-                       XPD_NOTICE(xpd, "Bad NT state: %d\n", curr_state);
-                       break;
-               }
-       }
-}
-
-/*
- * D-Chan receive
- */
-static int bri_check_stat(xpd_t *xpd, struct dahdi_chan *dchan, __u8 *buf,
-                         int len)
-{
-       struct BRI_priv_data *priv;
-       __u8 status;
-
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       if (len <= 0) {
-               XPD_NOTICE(xpd, "D-Chan RX DROP: short frame (len=%d)\n", len);
-               dahdi_hdlc_abort(dchan, DAHDI_EVENT_ABORT);
-               return -EPROTO;
-       }
-       status = buf[len - 1];
-       if (status) {
-               int event = DAHDI_EVENT_ABORT;
-
-               if (status == 0xFF) {
-                       XPD_NOTICE(xpd, "D-Chan RX DROP: ABORT: %d\n", status);
-               } else {
-                       XPD_NOTICE(xpd, "D-Chan RX DROP: BADFCS: %d\n", status);
-                       event = DAHDI_EVENT_BADFCS;
-               }
-               dump_hex_buf(xpd, "D-Chan RX:    current packet", buf, len);
-               dahdi_hdlc_abort(dchan, event);
-               return -EPROTO;
-       }
-       return 0;
-}
-
-static int rx_dchan(xpd_t *xpd, reg_cmd_t *regcmd)
-{
-       struct BRI_priv_data *priv;
-       __u8 *src;
-       struct dahdi_chan *dchan;
-       uint len;
-       bool eoframe;
-       int ret = 0;
-
-       src = REG_XDATA(regcmd);
-       len = regcmd->h.bytes;
-       eoframe = regcmd->h.eoframe;
-       if (len <= 0)
-               return 0;
-       if (!SPAN_REGISTERED(xpd))      /* Nowhere to copy data */
-               return 0;
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       dchan = XPD_CHAN(xpd, 2);
-       if (!IS_OFFHOOK(xpd, 2)) {      /* D-chan is used? */
-               static int rate_limit;
-
-               if ((rate_limit++ % 1000) == 0)
-                       XPD_DBG(SIGNAL, xpd, "D-Chan unused\n");
-               goto out;
-       }
-       XPD_DBG(GENERAL, xpd, "D-Chan RX: eoframe=%d len=%d\n", eoframe, len);
-       dahdi_hdlc_putbuf(dchan, src, (eoframe) ? len - 1 : len);
-       if (!eoframe)
-               goto out;
-       if ((ret = bri_check_stat(xpd, dchan, src, len)) < 0)
-               goto out;
-       /*
-        * Tell Dahdi that we received len-1 bytes.
-        * They include the data and a 2-byte checksum.
-        * The last byte (that we don't pass on) is 0 if the
-        * checksum is correct. If it were wrong, we would drop the
-        * packet in the "if (src[len-1])" above.
-        */
-       dahdi_hdlc_finish(dchan);
-       priv->dchan_rx_counter++;
-       priv->dchan_norx_ticks = 0;
-out:
-       return ret;
-}
-
-/*
- * D-Chan transmit
- */
-/*
- * DAHDI calls this when it has data it wants to send to
- * the HDLC controller
- */
-static void bri_hdlc_hard_xmit(struct dahdi_chan *chan)
-{
-       xpd_t *xpd = chan->pvt;
-       struct dahdi_chan *dchan;
-       struct BRI_priv_data *priv;
-
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       dchan = XPD_CHAN(xpd, 2);
-       if (dchan == chan)
-               atomic_inc(&priv->hdlc_pending);
-}
-
-static int send_dchan_frame(xpd_t *xpd, xframe_t *xframe, bool is_eof)
-{
-       struct BRI_priv_data *priv;
-       int ret;
-
-       XPD_DBG(COMMANDS, xpd, "eoframe=%d\n", is_eof);
-       priv = xpd->priv;
-       if (!test_bit(HFC_L1_ACTIVATED, &priv->l1_flags)
-           && !test_bit(HFC_L1_ACTIVATING, &priv->l1_flags)) {
-               XPD_DBG(SIGNAL, xpd,
-                       "Want to transmit: Kick D-Channel transmiter\n");
-               if (!IS_NT(xpd))
-                       te_activation(xpd, 1);
-               else
-                       nt_activation(xpd, 1);
-       }
-       dump_xframe("send_dchan_frame", xpd->xbus, xframe, debug);
-       ret = send_cmd_frame(xpd->xbus, xframe);
-       if (ret < 0)
-               XPD_ERR(xpd, "%s: failed sending xframe\n", __func__);
-       if (is_eof) {
-               atomic_dec(&priv->hdlc_pending);
-               priv->dchan_tx_counter++;
-               priv->txframe_begin = 1;
-       } else
-               priv->txframe_begin = 0;
-       priv->dchan_notx_ticks = 0;
-       return ret;
-}
-
-/*
- * Fill a single multibyte REGISTER_REQUEST
- */
-static void fill_multibyte(xpd_t *xpd, xpacket_t *pack,
-       bool eoframe, char *buf, int len)
-{
-       reg_cmd_t *reg_cmd;
-       char *p;
-
-       XPACKET_INIT(pack, GLOBAL, REGISTER_REQUEST, xpd->xbus_idx, 0, 0);
-       XPACKET_LEN(pack) = XFRAME_CMD_LEN(REG);
-       reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
-       reg_cmd->h.bytes = len;
-       reg_cmd->h.is_multibyte = 1;
-       reg_cmd->h.portnum = xpd->addr.subunit;
-       reg_cmd->h.eoframe = eoframe;
-       p = REG_XDATA(reg_cmd);
-       memcpy(p, buf, len);
-       if (debug)
-               dump_dchan_packet(xpd, 1, p, len);
-}
-
-/*
- * Transmit available D-Channel frames
- *
- * - FPGA firmware expect to get this as a sequence of REGISTER_REQUEST
- *   multibyte commands.
- * - The payload of each command is limited to MULTIBYTE_MAX_LEN bytes.
- * - We batch several REGISTER_REQUEST packets into a single xframe.
- * - The xframe is terminated when we get a bri "end of frame"
- *   or when the xframe is full (should not happen).
- */
-static int tx_dchan(xpd_t *xpd)
-{
-       struct BRI_priv_data *priv;
-       xframe_t *xframe;
-       xpacket_t *pack;
-       int packet_count;
-       int eoframe;
-       int ret;
-
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       if (atomic_read(&priv->hdlc_pending) == 0)
-               return 0;
-       if (!SPAN_REGISTERED(xpd)
-           || !(PHONEDEV(xpd).span.flags & DAHDI_FLAG_RUNNING))
-               return 0;
-       /* Allocate frame */
-       xframe = ALLOC_SEND_XFRAME(xpd->xbus);
-       if (!xframe) {
-               XPD_NOTICE(xpd, "%s: failed to allocate new xframe\n",
-                          __func__);
-               return -ENOMEM;
-       }
-       for (packet_count = 0, eoframe = 0; !eoframe; packet_count++) {
-               int packet_len = XFRAME_CMD_LEN(REG);
-               char buf[MULTIBYTE_MAX_LEN];
-               int len = MULTIBYTE_MAX_LEN;
-
-               /* Reserve packet */
-               pack = xframe_next_packet(xframe, packet_len);
-               if (!pack) {
-                       BUG_ON(!packet_count);
-                       /*
-                        * A split. Send what we currently have.
-                        */
-                       XPD_NOTICE(xpd, "%s: xframe is full (%d packets)\n",
-                                  __func__, packet_count);
-                       break;
-               }
-               /* Get data from DAHDI */
-               eoframe = dahdi_hdlc_getbuf(XPD_CHAN(xpd, 2), buf, &len);
-               if (len <= 0) {
-                       /*
-                        * Already checked priv->hdlc_pending,
-                        * should never get here.
-                        */
-                       if (printk_ratelimit())
-                               XPD_ERR(xpd,
-                                       "%s: hdlc_pending, but nothing "
-                                       "to transmit?\n", __func__);
-                       FREE_SEND_XFRAME(xpd->xbus, xframe);
-                       return -EINVAL;
-               }
-               BUG_ON(len > MULTIBYTE_MAX_LEN);
-               fill_multibyte(xpd, pack, eoframe != 0, buf, len);
-       }
-       return send_dchan_frame(xpd, xframe, eoframe != 0);
-       return ret;
-}
-
-/*---------------- BRI: Methods -------------------------------------------*/
-
-static void bri_proc_remove(xbus_t *xbus, xpd_t *xpd)
-{
-       struct BRI_priv_data *priv;
-
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-       XPD_DBG(PROC, xpd, "\n");
-#ifdef CONFIG_PROC_FS
-       if (priv->bri_info) {
-               XPD_DBG(PROC, xpd, "Removing '%s'\n", PROC_BRI_INFO_FNAME);
-               remove_proc_entry(PROC_BRI_INFO_FNAME, xpd->proc_xpd_dir);
-       }
-#endif
-}
-
-static int bri_proc_create(xbus_t *xbus, xpd_t *xpd)
-{
-       struct BRI_priv_data *priv;
-
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-       XPD_DBG(PROC, xpd, "\n");
-#ifdef CONFIG_PROC_FS
-       XPD_DBG(PROC, xpd, "Creating '%s'\n", PROC_BRI_INFO_FNAME);
-       priv->bri_info = proc_create_data(PROC_BRI_INFO_FNAME, 0444,
-                                xpd->proc_xpd_dir, &proc_bri_info_ops, xpd);
-       if (!priv->bri_info) {
-               XPD_ERR(xpd, "Failed to create proc file '%s'\n",
-                       PROC_BRI_INFO_FNAME);
-               bri_proc_remove(xbus, xpd);
-               return -EINVAL;
-       }
-       SET_PROC_DIRENTRY_OWNER(priv->bri_info);
-#endif
-       return 0;
-}
-
-static xpd_t *BRI_card_new(xbus_t *xbus, int unit, int subunit,
-                          const xproto_table_t *proto_table,
-                          const struct unit_descriptor *unit_descriptor,
-                          bool to_phone)
-{
-       xpd_t *xpd = NULL;
-       int channels = min(3, CHANNELS_PERXPD);
-
-       if ((unit_descriptor->ports_per_chip < 1) ||
-                       (unit_descriptor->ports_per_chip > 4)) {
-               XBUS_ERR(xbus, "Bad ports_per_chip=%d\n",
-                               unit_descriptor->ports_per_chip);
-               return NULL;
-       }
-       if ((unit_descriptor->numchips) < 1 ||
-                       (unit_descriptor->numchips > 2)) {
-               XBUS_ERR(xbus, "Bad numchips=%d\n",
-                               unit_descriptor->numchips);
-               return NULL;
-       }
-       XBUS_DBG(GENERAL, xbus, "\n");
-       xpd =
-           xpd_alloc(xbus, unit, subunit,
-                     sizeof(struct BRI_priv_data), proto_table, unit_descriptor, channels);
-       if (!xpd)
-               return NULL;
-       PHONEDEV(xpd).direction = (to_phone) ? TO_PHONE : TO_PSTN;
-       xpd->type_name = (to_phone) ? "BRI_NT" : "BRI_TE";
-       xbus->sync_mode_default = SYNC_MODE_AB;
-       if (bri_proc_create(xbus, xpd) < 0)
-               goto err;
-       return xpd;
-err:
-       xpd_free(xpd);
-       return NULL;
-}
-
-static int BRI_card_init(xbus_t *xbus, xpd_t *xpd)
-{
-       struct BRI_priv_data *priv;
-
-       BUG_ON(!xpd);
-       XPD_DBG(GENERAL, xpd, "\n");
-       priv = xpd->priv;
-       DO_LED(xpd, GREEN_LED, BRI_LED_OFF);
-       DO_LED(xpd, RED_LED, BRI_LED_OFF);
-       set_bri_timer(xpd, "T1", &priv->t1, HFC_TIMER_OFF);
-       write_state_register(xpd, 0);   /* Enable L1 state machine */
-       priv->initialized = 1;
-       return 0;
-}
-
-static int BRI_card_remove(xbus_t *xbus, xpd_t *xpd)
-{
-       BUG_ON(!xpd);
-       XPD_DBG(GENERAL, xpd, "\n");
-       bri_proc_remove(xbus, xpd);
-       return 0;
-}
-
-#ifdef DAHDI_AUDIO_NOTIFY
-static int bri_audio_notify(struct dahdi_chan *chan, int on)
-{
-       xpd_t *xpd = chan->pvt;
-       int pos = chan->chanpos - 1;
-
-       BUG_ON(!xpd);
-       LINE_DBG(SIGNAL, xpd, pos, "BRI-AUDIO: %s\n", (on) ? "on" : "off");
-       mark_offhook(xpd, pos, on);
-       return 0;
-}
-#endif
-
-static const struct dahdi_span_ops BRI_span_ops = {
-       .owner = THIS_MODULE,
-       .spanconfig = bri_spanconfig,
-       .chanconfig = bri_chanconfig,
-       .startup = bri_startup,
-       .shutdown = bri_shutdown,
-       .hdlc_hard_xmit = bri_hdlc_hard_xmit,
-       .open = xpp_open,
-       .close = xpp_close,
-       .hooksig = xpp_hooksig, /* Only with RBS bits */
-       .ioctl = xpp_ioctl,
-       .maint = xpp_maint,
-       .echocan_create = xpp_echocan_create,
-       .echocan_name = xpp_echocan_name,
-       .assigned = xpp_span_assigned,
-#ifdef DAHDI_SYNC_TICK
-       .sync_tick = dahdi_sync_tick,
-#endif
-#ifdef CONFIG_DAHDI_WATCHDOG
-       .watchdog = xpp_watchdog,
-#endif
-
-#ifdef DAHDI_AUDIO_NOTIFY
-       .audio_notify = bri_audio_notify,
-#endif
-};
-
-static int BRI_card_dahdi_preregistration(xpd_t *xpd, bool on)
-{
-       xbus_t *xbus;
-       struct BRI_priv_data *priv;
-       int i;
-
-       BUG_ON(!xpd);
-       xbus = xpd->xbus;
-       priv = xpd->priv;
-       BUG_ON(!xbus);
-       XPD_DBG(GENERAL, xpd, "%s\n", (on) ? "on" : "off");
-       if (!on) {
-               /* Nothing to do yet */
-               return 0;
-       }
-       PHONEDEV(xpd).span.spantype =
-               (PHONEDEV(xpd).direction == TO_PHONE)
-                       ? SPANTYPE_DIGITAL_BRI_NT
-                       : SPANTYPE_DIGITAL_BRI_TE;
-       PHONEDEV(xpd).span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_CCS;
-       PHONEDEV(xpd).span.deflaw = DAHDI_LAW_ALAW;
-       BIT_SET(PHONEDEV(xpd).digital_signalling, 2);   /* D-Channel */
-       for_each_line(xpd, i) {
-               struct dahdi_chan *cur_chan = XPD_CHAN(xpd, i);
-
-               XPD_DBG(GENERAL, xpd, "setting BRI channel %d\n", i);
-               snprintf(cur_chan->name, MAX_CHANNAME, "XPP_%s/%02d/%1d%1d/%d",
-                        xpd->type_name, xbus->num, xpd->addr.unit,
-                        xpd->addr.subunit, i);
-               cur_chan->chanpos = i + 1;
-               cur_chan->pvt = xpd;
-               if (i == 2) {   /* D-CHAN */
-                       cur_chan->sigcap = BRI_DCHAN_SIGCAP;
-                       clear_bit(DAHDI_FLAGBIT_HDLC, &cur_chan->flags);
-                       priv->txframe_begin = 1;
-                       atomic_set(&priv->hdlc_pending, 0);
-               } else {
-                       cur_chan->sigcap = BRI_BCHAN_SIGCAP;
-               }
-       }
-       CALL_PHONE_METHOD(card_pcm_recompute, xpd, 0);
-       PHONEDEV(xpd).span.ops = &BRI_span_ops;
-       return 0;
-}
-
-static int BRI_card_dahdi_postregistration(xpd_t *xpd, bool on)
-{
-       xbus_t *xbus;
-
-       BUG_ON(!xpd);
-       xbus = xpd->xbus;
-       BUG_ON(!xbus);
-       XPD_DBG(GENERAL, xpd, "%s\n", (on) ? "on" : "off");
-       return (0);
-}
-
-static int BRI_card_hooksig(xpd_t *xpd, int pos, enum dahdi_txsig txsig)
-{
-       LINE_DBG(SIGNAL, xpd, pos, "%s\n", txsig2str(txsig));
-       return 0;
-}
-
-/*
- * LED managment is done by the driver now:
- *   - Turn constant ON RED/GREEN led to indicate NT/TE port
- *   - Very fast "Double Blink" to indicate Layer1 alive (without D-Channel)
- *   - Constant blink (1/2 sec cycle) to indicate D-Channel alive.
- */
-static void handle_leds(xbus_t *xbus, xpd_t *xpd)
-{
-       struct BRI_priv_data *priv;
-       unsigned int timer_count;
-       int which_led;
-       int other_led;
-       int mod;
-
-       BUG_ON(!xpd);
-       if (IS_NT(xpd)) {
-               which_led = RED_LED;
-               other_led = GREEN_LED;
-       } else {
-               which_led = GREEN_LED;
-               other_led = RED_LED;
-       }
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       timer_count = xpd->timer_count;
-       if (xpd->blink_mode) {
-               if ((timer_count % DEFAULT_LED_PERIOD) == 0) {
-                       // led state is toggled
-                       if (priv->ledstate[which_led] == BRI_LED_OFF) {
-                               DO_LED(xpd, which_led, BRI_LED_ON);
-                               DO_LED(xpd, other_led, BRI_LED_ON);
-                       } else {
-                               DO_LED(xpd, which_led, BRI_LED_OFF);
-                               DO_LED(xpd, other_led, BRI_LED_OFF);
-                       }
-               }
-               return;
-       }
-       if (priv->ledstate[other_led] != BRI_LED_OFF)
-               DO_LED(xpd, other_led, BRI_LED_OFF);
-       if (priv->dchan_alive) {
-               mod = timer_count % 1000;
-               switch (mod) {
-               case 0:
-                       DO_LED(xpd, which_led, BRI_LED_ON);
-                       break;
-               case 500:
-                       DO_LED(xpd, which_led, BRI_LED_OFF);
-                       break;
-               }
-       } else if (priv->layer1_up) {
-               mod = timer_count % 1000;
-               switch (mod) {
-               case 0:
-               case 100:
-                       DO_LED(xpd, which_led, BRI_LED_ON);
-                       break;
-               case 50:
-               case 150:
-                       DO_LED(xpd, which_led, BRI_LED_OFF);
-                       break;
-               }
-       } else {
-               if (priv->ledstate[which_led] != BRI_LED_ON)
-                       DO_LED(xpd, which_led, BRI_LED_ON);
-       }
-}
-
-static void handle_bri_timers(xpd_t *xpd)
-{
-       struct BRI_priv_data *priv;
-
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       if (IS_NT(xpd)) {
-               if (priv->t1 > HFC_TIMER_OFF) {
-                       if (--priv->t1 == 0) {
-                               set_bri_timer(xpd, "T1", &priv->t1,
-                                             HFC_TIMER_OFF);
-                               if (!nt_keepalive) {
-                                       /* G2 */
-                                       if (priv->state_register.bits.v_su_sta == ST_NT_ACTIVATING) {
-                                               XPD_DBG(SIGNAL, xpd,
-                                                       "T1 Expired. "
-                                                       "Deactivate NT\n");
-                                               clear_bit(HFC_L1_ACTIVATING,
-                                                         &priv->l1_flags);
-                                               /* Deactivate NT */
-                                               nt_activation(xpd, 0);
-                                       } else
-                                               XPD_DBG(SIGNAL, xpd,
-                                                       "T1 Expired. "
-                                                       "(state %d, ignored)\n",
-                                                       priv->state_register.
-                                                       bits.v_su_sta);
-                               }
-                       }
-               }
-       } else {
-               if (priv->t3 > HFC_TIMER_OFF) {
-                       /* timer expired ? */
-                       if (--priv->t3 == 0) {
-                               XPD_DBG(SIGNAL, xpd,
-                                       "T3 expired. Deactivate TE\n");
-                               set_bri_timer(xpd, "T3", &priv->t3,
-                                             HFC_TIMER_OFF);
-                               clear_bit(HFC_L1_ACTIVATING, &priv->l1_flags);
-                               te_activation(xpd, 0);  /* Deactivate TE */
-                       }
-               }
-       }
-}
-
-/* Poll the register ST/Up-State-machine Register, to see if the cable
- * if a cable is connected to the port.
- */
-static int BRI_card_tick(xbus_t *xbus, xpd_t *xpd)
-{
-       struct BRI_priv_data *priv;
-
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       if (!priv->initialized || !xbus->self_ticking)
-               return 0;
-       if (poll_interval != 0 && (priv->tick_counter % poll_interval) == 0) {
-               // XPD_DBG(GENERAL, xpd, "%d\n", priv->tick_counter);
-               priv->poll_counter++;
-               xpp_register_request(xbus, xpd,
-                       BRI_PORT(xpd),  /* portno       */
-                       0,              /* writing      */
-                       A_SU_RD_STA,    /* regnum       */
-                       0,              /* do_subreg    */
-                       0,              /* subreg       */
-                       0,              /* data_low     */
-                       0,              /* do_datah     */
-                       0,              /* data_high    */
-                       0,              /* should_reply */
-                       0               /* do_expander  */
-                   );
-
-               if (IS_NT(xpd) && nt_keepalive
-                   && !test_bit(HFC_L1_ACTIVATED, &priv->l1_flags)
-                   && !test_bit(HFC_L1_ACTIVATING, &priv->l1_flags)) {
-                       XPD_DBG(SIGNAL, xpd, "Kick NT D-Channel\n");
-                       nt_activation(xpd, 1);
-               }
-       }
-       /* Detect D-Channel disconnect heuristic */
-       priv->dchan_notx_ticks++;
-       priv->dchan_norx_ticks++;
-       priv->dchan_alive_ticks++;
-       if (priv->dchan_alive
-           && (priv->dchan_notx_ticks > DCHAN_LOST
-               || priv->dchan_norx_ticks > DCHAN_LOST)) {
-               /*
-                * No tx_dchan() or rx_dchan() for many ticks
-                * This D-Channel is probabelly dead.
-                */
-               dchan_state(xpd, 0);
-       } else if (priv->dchan_rx_counter > 1 && priv->dchan_tx_counter > 1) {
-               if (!priv->dchan_alive)
-                       dchan_state(xpd, 1);
-       }
-       /* Detect Layer1 disconnect */
-       if (priv->reg30_good && priv->reg30_ticks > poll_interval * REG30_LOST) {
-               /* No reply for 1/2 a second */
-               XPD_ERR(xpd, "Lost state tracking for %d ticks\n",
-                       priv->reg30_ticks);
-               priv->reg30_good = 0;
-               layer1_state(xpd, 0);
-       }
-       handle_leds(xbus, xpd);
-       handle_bri_timers(xpd);
-       tx_dchan(xpd);
-       priv->tick_counter++;
-       priv->reg30_ticks++;
-       return 0;
-}
-
-static int BRI_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd,
-                         unsigned long arg)
-{
-       BUG_ON(!xpd);
-       if (!XBUS_IS(xpd->xbus, READY))
-               return -ENODEV;
-       switch (cmd) {
-       case DAHDI_TONEDETECT:
-               /*
-                * Asterisk call all span types with this (FXS specific)
-                * call. Silently ignore it.
-                */
-               LINE_DBG(SIGNAL, xpd, pos, "BRI: Starting a call\n");
-               return -ENOTTY;
-       default:
-               report_bad_ioctl(THIS_MODULE->name, xpd, pos, cmd);
-               return -ENOTTY;
-       }
-       return 0;
-}
-
-static int BRI_card_open(xpd_t *xpd, lineno_t pos)
-{
-       struct BRI_priv_data *priv;
-
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-       if (pos == 2) {
-               priv->dchan_is_open = 1;
-               LINE_DBG(SIGNAL, xpd, pos, "OFFHOOK the whole span\n");
-               BIT_SET(PHONEDEV(xpd).offhook_state, 0);
-               BIT_SET(PHONEDEV(xpd).offhook_state, 1);
-               BIT_SET(PHONEDEV(xpd).offhook_state, 2);
-               CALL_PHONE_METHOD(card_pcm_recompute, xpd, 0);
-       }
-       return 0;
-}
-
-static int BRI_card_close(xpd_t *xpd, lineno_t pos)
-{
-       struct BRI_priv_data *priv;
-
-       priv = xpd->priv;
-       /* Clear D-Channel pending data */
-       if (pos == 2) {
-               LINE_DBG(SIGNAL, xpd, pos, "ONHOOK the whole span\n");
-               BIT_CLR(PHONEDEV(xpd).offhook_state, 0);
-               BIT_CLR(PHONEDEV(xpd).offhook_state, 1);
-               BIT_CLR(PHONEDEV(xpd).offhook_state, 2);
-               CALL_PHONE_METHOD(card_pcm_recompute, xpd, 0);
-               priv->dchan_is_open = 0;
-       } else if (!priv->dchan_is_open)
-               mark_offhook(xpd, pos, 0);      /* e.g: patgen/pattest */
-       return 0;
-}
-
-/*
- * Called only for 'span' keyword in /etc/dahdi/system.conf
- */
-static int bri_spanconfig(struct file *file, struct dahdi_span *span,
-                         struct dahdi_lineconfig *lc)
-{
-       struct phonedev *phonedev = container_of(span, struct phonedev, span);
-       xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
-       const char *framingstr = "";
-       const char *codingstr = "";
-       const char *crcstr = "";
-
-       /* framing first */
-       if (lc->lineconfig & DAHDI_CONFIG_B8ZS)
-               framingstr = "B8ZS";
-       else if (lc->lineconfig & DAHDI_CONFIG_AMI)
-               framingstr = "AMI";
-       else if (lc->lineconfig & DAHDI_CONFIG_HDB3)
-               framingstr = "HDB3";
-       /* then coding */
-       if (lc->lineconfig & DAHDI_CONFIG_ESF)
-               codingstr = "ESF";
-       else if (lc->lineconfig & DAHDI_CONFIG_D4)
-               codingstr = "D4";
-       else if (lc->lineconfig & DAHDI_CONFIG_CCS)
-               codingstr = "CCS";
-       /* E1's can enable CRC checking */
-       if (lc->lineconfig & DAHDI_CONFIG_CRC4)
-               crcstr = "CRC4";
-       XPD_DBG(GENERAL, xpd,
-               "[%s]: span=%d (%s) lbo=%d lineconfig=%s/%s/%s (0x%X) sync=%d\n",
-               IS_NT(xpd) ? "NT" : "TE", lc->span, lc->name, lc->lbo,
-               framingstr, codingstr, crcstr, lc->lineconfig, lc->sync);
-       PHONEDEV(xpd).timing_priority = lc->sync;
-       elect_syncer("BRI-spanconfig");
-       /*
-        * FIXME: validate
-        */
-       span->lineconfig = lc->lineconfig;
-       return 0;
-}
-
-/*
- * Set signalling type (if appropriate)
- * Called from dahdi with spinlock held on chan. Must not call back
- * dahdi functions.
- */
-static int bri_chanconfig(struct file *file, struct dahdi_chan *chan,
-                         int sigtype)
-{
-       DBG(GENERAL, "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?)
-       return 0;
-}
-
-/*
- * Called only for 'span' keyword in /etc/dahdi/system.conf
- */
-static int bri_startup(struct file *file, struct dahdi_span *span)
-{
-       struct phonedev *phonedev = container_of(span, struct phonedev, span);
-       xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
-       struct BRI_priv_data *priv;
-       struct dahdi_chan *dchan;
-
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       if (!XBUS_IS(xpd->xbus, READY)) {
-               XPD_DBG(GENERAL, xpd,
-                       "Startup called by dahdi. No Hardware. Ignored\n");
-               return -ENODEV;
-       }
-       XPD_DBG(GENERAL, xpd, "STARTUP\n");
-       // Turn on all channels
-       CALL_PHONE_METHOD(card_state, xpd, 1);
-       if (SPAN_REGISTERED(xpd)) {
-               dchan = XPD_CHAN(xpd, 2);
-               span->flags |= DAHDI_FLAG_RUNNING;
-               /*
-                * Dahdi (wrongly) assume that D-Channel need HDLC decoding
-                * and during dahdi registration override our flags.
-                *
-                * Don't Get Mad, Get Even:  Now we override dahdi :-)
-                */
-               clear_bit(DAHDI_FLAGBIT_HDLC, &dchan->flags);
-       }
-       return 0;
-}
-
-/*
- * Called only for 'span' keyword in /etc/dahdi/system.conf
- */
-static int bri_shutdown(struct dahdi_span *span)
-{
-       struct phonedev *phonedev = container_of(span, struct phonedev, span);
-       xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
-       struct BRI_priv_data *priv;
-
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       if (!XBUS_IS(xpd->xbus, READY)) {
-               XPD_DBG(GENERAL, xpd,
-                       "Shutdown called by dahdi. No Hardware. Ignored\n");
-               return -ENODEV;
-       }
-       XPD_DBG(GENERAL, xpd, "SHUTDOWN\n");
-       // Turn off all channels
-       CALL_PHONE_METHOD(card_state, xpd, 0);
-       return 0;
-}
-
-static void BRI_card_pcm_recompute(xpd_t *xpd, xpp_line_t dont_care)
-{
-       int i;
-       int line_count;
-       xpp_line_t pcm_mask;
-       uint pcm_len;
-       xpd_t *main_xpd;
-       unsigned long flags;
-
-       BUG_ON(!xpd);
-       main_xpd = xpd_byaddr(xpd->xbus, xpd->addr.unit, 0);
-       if (!main_xpd) {
-               XPD_DBG(DEVICES, xpd,
-                       "Unit 0 is already gone. Ignore request\n");
-               return;
-       }
-       /*
-        * We calculate all subunits, so use the main lock
-        * as a mutex for the whole operation.
-        */
-       spin_lock_irqsave(&PHONEDEV(main_xpd).lock_recompute_pcm, flags);
-       line_count = 0;
-       pcm_mask = 0;
-       for (i = 0; i < MAX_SUBUNIT; i++) {
-               xpd_t *sub_xpd = xpd_byaddr(xpd->xbus, main_xpd->addr.unit, i);
-
-               if (sub_xpd) {
-                       xpp_line_t lines =
-                           PHONEDEV(sub_xpd).
-                           offhook_state & ~(PHONEDEV(sub_xpd).
-                                             digital_signalling);
-
-                       if (lines) {
-                               pcm_mask |= PCM_SHIFT(lines, i);
-                               line_count += 2;
-                       }
-                       /* subunits have fake pcm_len and wanted_pcm_mask */
-                       if (i > 0)
-                               update_wanted_pcm_mask(sub_xpd, lines, 0);
-               }
-       }
-       /*
-        * FIXME: Workaround a bug in sync code of the Astribank.
-        *        Send dummy PCM for sync.
-        */
-       if (main_xpd->addr.unit == 0 && line_count == 0) {
-               pcm_mask = BIT(0);
-               line_count = 1;
-       }
-       /*
-        * The main unit account for all subunits (pcm_len and wanted_pcm_mask).
-        */
-       pcm_len = (line_count)
-           ? RPACKET_HEADERSIZE + sizeof(xpp_line_t) +
-           line_count * DAHDI_CHUNKSIZE : 0L;
-       update_wanted_pcm_mask(main_xpd, pcm_mask, pcm_len);
-       spin_unlock_irqrestore(&PHONEDEV(main_xpd).lock_recompute_pcm, flags);
-}
-
-static void BRI_card_pcm_fromspan(xpd_t *xpd, xpacket_t *pack)
-{
-       __u8 *pcm;
-       unsigned long flags;
-       int i;
-       int subunit;
-       xpp_line_t pcm_mask = 0;
-       xpp_line_t wanted_lines;
-
-       BUG_ON(!xpd);
-       BUG_ON(!pack);
-       pcm = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, pcm);
-       for (subunit = 0; subunit < MAX_SUBUNIT; subunit++) {
-               xpd_t *tmp_xpd;
-
-               tmp_xpd = xpd_byaddr(xpd->xbus, xpd->addr.unit, subunit);
-               if (!tmp_xpd || !tmp_xpd->card_present)
-                       continue;
-               spin_lock_irqsave(&tmp_xpd->lock, flags);
-               wanted_lines = PHONEDEV(tmp_xpd).wanted_pcm_mask;
-               for_each_line(tmp_xpd, i) {
-                       struct dahdi_chan *chan = XPD_CHAN(tmp_xpd, i);
-
-                       if (IS_SET(wanted_lines, i)) {
-                               if (SPAN_REGISTERED(tmp_xpd)) {
-#ifdef DEBUG_PCMTX
-                                       int channo = chan->channo;
-
-                                       if (pcmtx >= 0 && pcmtx_chan == channo)
-                                               memset((u_char *)pcm, pcmtx,
-                                                      DAHDI_CHUNKSIZE);
-                                       else
-#endif
-                                               memcpy((u_char *)pcm,
-                                                      chan->writechunk,
-                                                      DAHDI_CHUNKSIZE);
-                               } else
-                                       memset((u_char *)pcm, 0x7F,
-                                              DAHDI_CHUNKSIZE);
-                               pcm += DAHDI_CHUNKSIZE;
-                       }
-               }
-               pcm_mask |= PCM_SHIFT(wanted_lines, subunit);
-               XPD_COUNTER(tmp_xpd, PCM_WRITE)++;
-               spin_unlock_irqrestore(&tmp_xpd->lock, flags);
-       }
-       RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines) = pcm_mask;
-}
-
-static void BRI_card_pcm_tospan(xpd_t *xpd, xpacket_t *pack)
-{
-       __u8 *pcm;
-       xpp_line_t pcm_mask;
-       unsigned long flags;
-       int subunit;
-       int i;
-
-       /*
-        * Subunit 0 handle all other subunits
-        */
-       if (xpd->addr.subunit != 0)
-               return;
-       if (!SPAN_REGISTERED(xpd))
-               return;
-       pcm = RPACKET_FIELD(pack, GLOBAL, PCM_READ, pcm);
-       pcm_mask = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines);
-       for (subunit = 0; subunit < MAX_SUBUNIT;
-            subunit++, pcm_mask >>= SUBUNIT_PCM_SHIFT) {
-               xpd_t *tmp_xpd;
-
-               if (!pcm_mask)
-                       break;  /* optimize */
-               tmp_xpd = xpd_byaddr(xpd->xbus, xpd->addr.unit, subunit);
-               if (!tmp_xpd || !tmp_xpd->card_present
-                   || !SPAN_REGISTERED(tmp_xpd))
-                       continue;
-               spin_lock_irqsave(&tmp_xpd->lock, flags);
-               for (i = 0; i < 2; i++) {
-                       xpp_line_t tmp_mask = pcm_mask & (BIT(0) | BIT(1));
-                       volatile u_char *r;
-
-                       if (IS_SET(tmp_mask, i)) {
-                               r = XPD_CHAN(tmp_xpd, i)->readchunk;
-#if 0
-                               /* DEBUG */
-                               memset((u_char *)r, 0x5A, DAHDI_CHUNKSIZE);
-#endif
-                               memcpy((u_char *)r, pcm, DAHDI_CHUNKSIZE);
-                               pcm += DAHDI_CHUNKSIZE;
-                       }
-               }
-               XPD_COUNTER(tmp_xpd, PCM_READ)++;
-               spin_unlock_irqrestore(&tmp_xpd->lock, flags);
-       }
-}
-
-static int BRI_timing_priority(xpd_t *xpd)
-{
-       struct BRI_priv_data *priv;
-
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       if (priv->layer1_up)
-               return PHONEDEV(xpd).timing_priority;
-       XPD_DBG(SYNC, xpd, "No timing priority (no layer1)\n");
-       return -ENOENT;
-}
-
-static int BRI_echocancel_timeslot(xpd_t *xpd, int pos)
-{
-       return xpd->addr.subunit * 4 + pos;
-}
-
-static int BRI_echocancel_setmask(xpd_t *xpd, xpp_line_t ec_mask)
-{
-       struct BRI_priv_data *priv;
-       int i;
-
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       XPD_DBG(GENERAL, xpd, "0x%8X\n", ec_mask);
-       if (!ECHOOPS(xpd->xbus)) {
-               XPD_DBG(GENERAL, xpd,
-                       "No echo canceller in XBUS: Doing nothing.\n");
-               return -EINVAL;
-       }
-       for (i = 0; i < PHONEDEV(xpd).channels - 1; i++) {
-               int on = BIT(i) & ec_mask;
-
-               CALL_EC_METHOD(ec_set, xpd->xbus, xpd, i, on);
-       }
-       CALL_EC_METHOD(ec_update, xpd->xbus, xpd->xbus);
-       return 0;
-}
-
-/*---------------- BRI: HOST COMMANDS -------------------------------------*/
-
-static /* 0x33 */ HOSTCMD(BRI, SET_LED, enum bri_led_names which_led,
-                         enum led_state to_led_state)
-{
-       int ret = 0;
-       xframe_t *xframe;
-       xpacket_t *pack;
-       struct bri_leds *bri_leds;
-       struct BRI_priv_data *priv;
-
-       BUG_ON(!xbus);
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       XPD_DBG(LEDS, xpd, "%s -> %d\n", (which_led) ? "RED" : "GREEN",
-               to_led_state);
-       XFRAME_NEW_CMD(xframe, pack, xbus, BRI, SET_LED, xpd->xbus_idx);
-       bri_leds = &RPACKET_FIELD(pack, BRI, SET_LED, bri_leds);
-       bri_leds->state = to_led_state;
-       bri_leds->led_sel = which_led;
-       XPACKET_LEN(pack) = RPACKET_SIZE(BRI, SET_LED);
-       ret = send_cmd_frame(xbus, xframe);
-       priv->ledstate[which_led] = to_led_state;
-       return ret;
-}
-
-static int write_state_register(xpd_t *xpd, __u8 value)
-{
-       int ret;
-
-       XPD_DBG(REGS, xpd, "value = 0x%02X\n", value);
-       ret = xpp_register_request(xpd->xbus, xpd,
-               BRI_PORT(xpd),  /* portno       */
-               1,              /* writing      */
-               A_SU_WR_STA,    /* regnum       */
-               0,              /* do_subreg    */
-               0,              /* subreg       */
-               value,          /* data_low     */
-               0,              /* do_datah     */
-               0,              /* data_high    */
-               0,              /* should_reply */
-               0               /* do_expander */
-           );
-       return ret;
-}
-
-/*---------------- BRI: Astribank Reply Handlers --------------------------*/
-static void su_new_state(xpd_t *xpd, __u8 reg_x30)
-{
-       struct BRI_priv_data *priv;
-       su_rd_sta_t new_state;
-
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       if (!priv->initialized) {
-               XPD_ERR(xpd, "%s called on uninitialized AB\n", __func__);
-               return;
-       }
-       new_state.reg = reg_x30;
-       if (new_state.bits.v_su_t2_exp)
-               XPD_NOTICE(xpd, "T2 Expired\n");
-       priv->reg30_ticks = 0;
-       priv->reg30_good = 1;
-       if (priv->state_register.bits.v_su_sta == new_state.bits.v_su_sta)
-               return;         /* same same */
-       XPD_DBG(SIGNAL, xpd, "%02X ---> %02X (info0=%d) (%s%i)\n",
-               priv->state_register.reg, reg_x30, new_state.bits.v_su_info0,
-               IS_NT(xpd) ? "G" : "F", new_state.bits.v_su_sta);
-       if (!IS_NT(xpd)) {
-               switch (new_state.bits.v_su_sta) {
-               case ST_TE_DEACTIVATED: /* F3 */
-                       XPD_DBG(SIGNAL, xpd, "State ST_TE_DEACTIVATED (F3)\n");
-                       clear_bit(HFC_L1_ACTIVATED, &priv->l1_flags);
-                       layer1_state(xpd, 0);
-                       break;
-               case ST_TE_SIGWAIT:     /* F4   */
-                       XPD_DBG(SIGNAL, xpd, "State ST_TE_SIGWAIT (F4)\n");
-                       layer1_state(xpd, 0);
-                       break;
-               case ST_TE_IDENT:       /* F5   */
-                       XPD_DBG(SIGNAL, xpd, "State ST_TE_IDENT (F5)\n");
-                       layer1_state(xpd, 0);
-                       break;
-               case ST_TE_SYNCED:      /* F6   */
-                       XPD_DBG(SIGNAL, xpd, "State ST_TE_SYNCED (F6)\n");
-                       layer1_state(xpd, 0);
-                       break;
-               case ST_TE_ACTIVATED:   /* F7 */
-                       XPD_DBG(SIGNAL, xpd, "State ST_TE_ACTIVATED (F7)\n");
-                       set_bri_timer(xpd, "T3", &priv->t3, HFC_TIMER_OFF);
-                       clear_bit(HFC_L1_ACTIVATING, &priv->l1_flags);
-                       set_bit(HFC_L1_ACTIVATED, &priv->l1_flags);
-                       layer1_state(xpd, 1);
-                       update_xpd_status(xpd, DAHDI_ALARM_NONE);
-                       break;
-               case ST_TE_LOST_FRAMING:        /* F8 */
-                       XPD_DBG(SIGNAL, xpd, "State ST_TE_LOST_FRAMING (F8)\n");
-                       layer1_state(xpd, 0);
-                       break;
-               default:
-                       XPD_NOTICE(xpd, "Bad TE state: %d\n",
-                                  new_state.bits.v_su_sta);
-                       break;
-               }
-
-       } else {
-               switch (new_state.bits.v_su_sta) {
-               case ST_NT_DEACTIVATED: /* G1 */
-                       XPD_DBG(SIGNAL, xpd, "State ST_NT_DEACTIVATED (G1)\n");
-                       clear_bit(HFC_L1_ACTIVATED, &priv->l1_flags);
-                       set_bri_timer(xpd, "T1", &priv->t1, HFC_TIMER_OFF);
-                       layer1_state(xpd, 0);
-                       break;
-               case ST_NT_ACTIVATING:  /* G2 */
-                       XPD_DBG(SIGNAL, xpd, "State ST_NT_ACTIVATING (G2)\n");
-                       layer1_state(xpd, 0);
-                       if (!test_bit(HFC_L1_ACTIVATED, &priv->l1_flags))
-                               nt_activation(xpd, 1);
-                       break;
-               case ST_NT_ACTIVATED:   /* G3 */
-                       XPD_DBG(SIGNAL, xpd, "State ST_NT_ACTIVATED (G3)\n");
-                       clear_bit(HFC_L1_ACTIVATING, &priv->l1_flags);
-                       set_bit(HFC_L1_ACTIVATED, &priv->l1_flags);
-                       set_bri_timer(xpd, "T1", &priv->t1, HFC_TIMER_OFF);
-                       layer1_state(xpd, 1);
-                       update_xpd_status(xpd, DAHDI_ALARM_NONE);
-                       break;
-               case ST_NT_DEACTIVTING: /* G4 */
-                       XPD_DBG(SIGNAL, xpd, "State ST_NT_DEACTIVTING (G4)\n");
-                       set_bri_timer(xpd, "T1", &priv->t1, HFC_TIMER_OFF);
-                       layer1_state(xpd, 0);
-                       break;
-               default:
-                       XPD_NOTICE(xpd, "Bad NT state: %d\n",
-                                  new_state.bits.v_su_sta);
-                       break;
-               }
-       }
-       priv->state_register.reg = new_state.reg;
-}
-
-static int BRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
-{
-       unsigned long flags;
-       struct BRI_priv_data *priv;
-       struct xpd_addr addr;
-       xpd_t *orig_xpd;
-       int ret;
-
-       /* Map UNIT + PORTNUM to XPD */
-       orig_xpd = xpd;
-       addr.unit = orig_xpd->addr.unit;
-       addr.subunit = info->h.portnum;
-       xpd = xpd_byaddr(xbus, addr.unit, addr.subunit);
-       if (!xpd) {
-               static int rate_limit;
-
-               if ((rate_limit++ % 1003) < 5)
-                       notify_bad_xpd(__func__, xbus, addr, orig_xpd->xpdname);
-               return -EPROTO;
-       }
-       spin_lock_irqsave(&xpd->lock, flags);
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       if (REG_FIELD(info, do_subreg)) {
-               XPD_DBG(REGS, xpd, "RI %02X %02X %02X\n",
-                       REG_FIELD(info, regnum), REG_FIELD(info, subreg),
-                       REG_FIELD(info, data_low));
-       } else {
-               if (REG_FIELD(info, regnum) != A_SU_RD_STA)
-                       XPD_DBG(REGS, xpd, "RD %02X %02X\n",
-                               REG_FIELD(info, regnum), REG_FIELD(info,
-                                                                  data_low));
-               else
-                       XPD_DBG(REGS, xpd, "Got SU_RD_STA=%02X\n",
-                               REG_FIELD(info, data_low));
-       }
-       if (info->h.is_multibyte) {
-               XPD_DBG(REGS, xpd, "Got Multibyte: %d bytes, eoframe: %d\n",
-                       info->h.bytes, info->h.eoframe);
-               ret = rx_dchan(xpd, info);
-               if (ret < 0) {
-                       priv->dchan_rx_drops++;
-                       if (atomic_read(&PHONEDEV(xpd).open_counter) > 0)
-                               XPD_NOTICE(xpd, "Multibyte Drop: errno=%d\n",
-                                          ret);
-               }
-               goto end;
-       }
-       if (REG_FIELD(info, regnum) == A_SU_RD_STA)
-               su_new_state(xpd, REG_FIELD(info, data_low));
-
-       /* Update /proc info only if reply relate to the last slic read request */
-       if (REG_FIELD(&xpd->requested_reply, regnum) ==
-                       REG_FIELD(info, regnum)
-               && REG_FIELD(&xpd->requested_reply, do_subreg) ==
-                       REG_FIELD(info, do_subreg)
-               && REG_FIELD(&xpd->requested_reply, subreg) ==
-                       REG_FIELD(info, subreg)) {
-               xpd->last_reply = *info;
-       }
-
-end:
-       spin_unlock_irqrestore(&xpd->lock, flags);
-       return 0;
-}
-
-static int BRI_card_state(xpd_t *xpd, bool on)
-{
-       struct BRI_priv_data *priv;
-
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-       XPD_DBG(GENERAL, xpd, "%s\n", (on) ? "ON" : "OFF");
-       if (on) {
-               if (!test_bit(HFC_L1_ACTIVATED, &priv->l1_flags)) {
-                       if (!IS_NT(xpd))
-                               te_activation(xpd, 1);
-                       else
-                               nt_activation(xpd, 1);
-               }
-       } else if (IS_NT(xpd))
-               nt_activation(xpd, 0);
-       return 0;
-}
-
-static const struct xops bri_xops = {
-       .card_new = BRI_card_new,
-       .card_init = BRI_card_init,
-       .card_remove = BRI_card_remove,
-       .card_tick = BRI_card_tick,
-       .card_register_reply = BRI_card_register_reply,
-};
-
-static const struct phoneops bri_phoneops = {
-       .card_dahdi_preregistration = BRI_card_dahdi_preregistration,
-       .card_dahdi_postregistration = BRI_card_dahdi_postregistration,
-       .card_hooksig = BRI_card_hooksig,
-       .card_pcm_recompute = BRI_card_pcm_recompute,
-       .card_pcm_fromspan = BRI_card_pcm_fromspan,
-       .card_pcm_tospan = BRI_card_pcm_tospan,
-       .card_timing_priority = BRI_timing_priority,
-       .echocancel_timeslot = BRI_echocancel_timeslot,
-       .echocancel_setmask = BRI_echocancel_setmask,
-       .card_ioctl = BRI_card_ioctl,
-       .card_open = BRI_card_open,
-       .card_close = BRI_card_close,
-       .card_state = BRI_card_state,
-};
-
-static xproto_table_t PROTO_TABLE(BRI) = {
-       .owner = THIS_MODULE,
-       .entries = {
-               /*      Table   Card    Opcode          */
-       },
-       .name = "BRI",  /* protocol name */
-       .ports_per_subunit = 1,
-       .type = XPD_TYPE_BRI,
-       .xops = &bri_xops,
-       .phoneops = &bri_phoneops,
-       .packet_is_valid = bri_packet_is_valid,
-       .packet_dump = bri_packet_dump,
-};
-
-static bool bri_packet_is_valid(xpacket_t *pack)
-{
-       const xproto_entry_t *xe = NULL;
-       // DBG(GENERAL, "\n");
-       xe = xproto_card_entry(&PROTO_TABLE(BRI), XPACKET_OP(pack));
-       return xe != NULL;
-}
-
-static void bri_packet_dump(const char *msg, xpacket_t *pack)
-{
-       DBG(GENERAL, "%s\n", msg);
-}
-
-/*------------------------- REGISTER Handling --------------------------*/
-
-#ifdef CONFIG_PROC_FS
-static int proc_bri_info_show(struct seq_file *sfile, void *not_used)
-{
-       unsigned long flags;
-       xpd_t *xpd = sfile->private;
-       struct BRI_priv_data *priv;
-
-       DBG(PROC, "\n");
-       if (!xpd)
-               return -ENODEV;
-       spin_lock_irqsave(&xpd->lock, flags);
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       seq_printf(sfile, "%05d Layer 1: ", priv->poll_counter);
-       if (priv->reg30_good) {
-               seq_printf(sfile, "%-5s ", (priv->layer1_up) ? "UP" : "DOWN");
-               seq_printf(sfile,
-                          "%c%d %-15s -- fr_sync=%d t2_exp=%d info0=%d g2_g3=%d\n",
-                          IS_NT(xpd) ? 'G' : 'F',
-                          priv->state_register.bits.v_su_sta,
-                          xhfc_state_name(IS_NT(xpd),
-                                   priv->state_register.bits.v_su_sta),
-                          priv->state_register.bits.v_su_fr_sync,
-                          priv->state_register.bits.v_su_t2_exp,
-                          priv->state_register.bits.v_su_info0,
-                          priv->state_register.bits.v_g2_g3);
-       } else {
-               seq_printf(sfile, "Unknown\n");
-       }
-       if (IS_NT(xpd))
-               seq_printf(sfile, "T1 Timer: %d\n", priv->t1);
-       else
-               seq_printf(sfile, "T3 Timer: %d\n", priv->t3);
-       seq_printf(sfile, "Tick Counter: %d\n", priv->tick_counter);
-       seq_printf(sfile, "Last Poll Reply: %d ticks ago\n",
-                   priv->reg30_ticks);
-       seq_printf(sfile, "reg30_good=%d\n", priv->reg30_good);
-       seq_printf(sfile, "D-Channel: TX=[%5d]    RX=[%5d]    BAD=[%5d] ",
-                   priv->dchan_tx_counter, priv->dchan_rx_counter,
-                   priv->dchan_rx_drops);
-       if (priv->dchan_alive) {
-               seq_printf(sfile, "(alive %d K-ticks)\n",
-                           priv->dchan_alive_ticks / 1000);
-       } else {
-               seq_printf(sfile, "(dead)\n");
-       }
-       seq_printf(sfile, "dchan_notx_ticks: %d\n",
-                   priv->dchan_notx_ticks);
-       seq_printf(sfile, "dchan_norx_ticks: %d\n",
-                   priv->dchan_norx_ticks);
-       seq_printf(sfile, "LED: %-10s = %d\n", "GREEN",
-                   priv->ledstate[GREEN_LED]);
-       seq_printf(sfile, "LED: %-10s = %d\n", "RED",
-                   priv->ledstate[RED_LED]);
-       seq_printf(sfile, "\nDCHAN:\n");
-       seq_printf(sfile, "\n");
-       spin_unlock_irqrestore(&xpd->lock, flags);
-       return 0;
-}
-
-static int proc_bri_info_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, proc_bri_info_show, PDE_DATA(inode));
-}
-
-static const struct file_operations proc_bri_info_ops = {
-       .owner          = THIS_MODULE,
-       .open           = proc_bri_info_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-#endif
-
-static int bri_xpd_probe(struct device *dev)
-{
-       xpd_t *xpd;
-
-       xpd = dev_to_xpd(dev);
-       /* Is it our device? */
-       if (xpd->xpd_type != XPD_TYPE_BRI) {
-               XPD_ERR(xpd, "drop suggestion for %s (%d)\n", dev_name(dev),
-                       xpd->xpd_type);
-               return -EINVAL;
-       }
-       XPD_DBG(DEVICES, xpd, "SYSFS\n");
-       return 0;
-}
-
-static int bri_xpd_remove(struct device *dev)
-{
-       xpd_t *xpd;
-
-       xpd = dev_to_xpd(dev);
-       XPD_DBG(DEVICES, xpd, "SYSFS\n");
-       return 0;
-}
-
-static struct xpd_driver bri_driver = {
-       .xpd_type = XPD_TYPE_BRI,
-       .driver = {
-                  .name = "bri",
-                  .owner = THIS_MODULE,
-                  .probe = bri_xpd_probe,
-                  .remove = bri_xpd_remove}
-};
-
-static int __init card_bri_startup(void)
-{
-       int ret;
-
-       if ((ret = xpd_driver_register(&bri_driver.driver)) < 0)
-               return ret;
-       xproto_register(&PROTO_TABLE(BRI));
-       return 0;
-}
-
-static void __exit card_bri_cleanup(void)
-{
-       DBG(GENERAL, "\n");
-       xproto_unregister(&PROTO_TABLE(BRI));
-       xpd_driver_unregister(&bri_driver.driver);
-}
-
-MODULE_DESCRIPTION("XPP BRI Card Driver");
-MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_XPD(XPD_TYPE_BRI);
-
-module_init(card_bri_startup);
-module_exit(card_bri_cleanup);
diff --git a/drivers/dahdi/xpp/card_bri.h b/drivers/dahdi/xpp/card_bri.h
deleted file mode 100644 (file)
index 8c49021..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef        CARD_BRI_H
-#define        CARD_BRI_H
-/*
- * Written by Oron Peled <oron@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"
-
-enum bri_opcodes {
-       XPROTO_NAME(BRI, SET_LED) = 0x33,
-};
-
-#endif /* CARD_BRI_H */
diff --git a/drivers/dahdi/xpp/card_echo.c b/drivers/dahdi/xpp/card_echo.c
deleted file mode 100644 (file)
index 4ddc06b..0000000
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * Written by Oron Peled <oron@actcom.co.il>
- * Copyright (C) 2011, 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 "xpd.h"
-#include "xproto.h"
-#include "card_echo.h"
-#include "xpp_dahdi.h"
-#include "dahdi_debug.h"
-#include "xpd.h"
-#include "xbus-core.h"
-
-static const char rcsid[] = "$Id$";
-
-/* must be before dahdi_debug.h: */
-static DEF_PARM(int, debug, 0, 0644, "Print DBG statements");
-
-/*---------------- ECHO Protocol Commands ----------------------------------*/
-
-static bool echo_packet_is_valid(xpacket_t *pack);
-static void echo_packet_dump(const char *msg, xpacket_t *pack);
-
-DEF_RPACKET_DATA(ECHO, SET, __u8 timeslots[ECHO_TIMESLOTS];);
-
-DEF_RPACKET_DATA(ECHO, SET_REPLY, __u8 status; __u8 reserved;);
-
-struct ECHO_priv_data {
-};
-
-static xproto_table_t PROTO_TABLE(ECHO);
-
-/*---------------- ECHO: Methods -------------------------------------------*/
-
-static xpd_t *ECHO_card_new(xbus_t *xbus, int unit, int subunit,
-                           const xproto_table_t *proto_table,
-                           const struct unit_descriptor *unit_descriptor,
-                           bool to_phone)
-{
-       xpd_t *xpd = NULL;
-       int channels = 0;
-
-       if (unit_descriptor->ports_per_chip != 1) {
-               XBUS_ERR(xbus, "Bad subunit_ports=%d\n", unit_descriptor->ports_per_chip);
-               return NULL;
-       }
-       XBUS_DBG(GENERAL, xbus, "\n");
-       xpd =
-           xpd_alloc(xbus, unit, subunit,
-                     sizeof(struct ECHO_priv_data), proto_table, unit_descriptor, channels);
-       if (!xpd)
-               return NULL;
-       xpd->type_name = "ECHO";
-       return xpd;
-}
-
-static int ECHO_card_init(xbus_t *xbus, xpd_t *xpd)
-{
-       int ret = 0;
-
-       BUG_ON(!xpd);
-       XPD_DBG(GENERAL, xpd, "\n");
-       xpd->xpd_type = XPD_TYPE_ECHO;
-       XPD_DBG(DEVICES, xpd, "%s\n", xpd->type_name);
-       ret = CALL_EC_METHOD(ec_update, xbus, xbus);
-       return ret;
-}
-
-static int ECHO_card_remove(xbus_t *xbus, xpd_t *xpd)
-{
-       BUG_ON(!xpd);
-       XPD_DBG(GENERAL, xpd, "\n");
-       return 0;
-}
-
-static int ECHO_card_tick(xbus_t *xbus, xpd_t *xpd)
-{
-       struct ECHO_priv_data *priv;
-
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       return 0;
-}
-
-static int ECHO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
-{
-       unsigned long flags;
-       struct xpd_addr addr;
-       xpd_t *orig_xpd;
-
-       /* Map UNIT + PORTNUM to XPD */
-       orig_xpd = xpd;
-       addr.unit = orig_xpd->addr.unit;
-       addr.subunit = info->h.portnum;
-       xpd = xpd_byaddr(xbus, addr.unit, addr.subunit);
-       if (!xpd) {
-               static int rate_limit;
-
-               if ((rate_limit++ % 1003) < 5)
-                       notify_bad_xpd(__func__, xbus, addr, orig_xpd->xpdname);
-               return -EPROTO;
-       }
-       spin_lock_irqsave(&xpd->lock, flags);
-       /* Update /proc info only if reply related to last reg read request */
-       if (REG_FIELD(&xpd->requested_reply, regnum) ==
-                       REG_FIELD(info, regnum)
-               && REG_FIELD(&xpd->requested_reply, do_subreg) ==
-                       REG_FIELD(info, do_subreg)
-               && REG_FIELD(&xpd->requested_reply, subreg) ==
-                       REG_FIELD(info, subreg)) {
-               xpd->last_reply = *info;
-       }
-       spin_unlock_irqrestore(&xpd->lock, flags);
-       return 0;
-}
-
-/*---------------- ECHO: HOST COMMANDS -------------------------------------*/
-
-static /* 0x39 */ HOSTCMD(ECHO, SET)
-{
-       struct xbus_echo_state *es;
-       __u8 *ts;
-       xframe_t *xframe;
-       xpacket_t *pack;
-       int ret;
-       uint16_t frm_len;
-       int xpd_idx;
-
-       BUG_ON(!xbus);
-       /*
-        * Find echo canceller XPD address
-        */
-       es = &xbus->echo_state;
-       xpd_idx = es->xpd_idx;
-       XFRAME_NEW_CMD(xframe, pack, xbus, ECHO, SET, xpd_idx);
-       ts = RPACKET_FIELD(pack, ECHO, SET, timeslots);
-       memcpy(ts, es->timeslots, ECHO_TIMESLOTS);
-       frm_len = XFRAME_LEN(xframe);
-       XBUS_DBG(GENERAL, xbus, "ECHO SET: (len = %d)\n", frm_len);
-       ret = send_cmd_frame(xbus, xframe);
-       return ret;
-}
-
-static int ECHO_ec_set(xpd_t *xpd, int pos, bool on)
-{
-       int ts_number;
-       int ts_mask;
-       __u8 *ts;
-
-       ts = xpd->xbus->echo_state.timeslots;
-       /*
-        * ts_number = PCM time slot ("channel number" in the PCM XPP packet)
-        *
-        * Bit 0 is for UNIT=0
-        * PRI: ts_number * 4 + SUBUNIT
-        * BRI: ts_number
-        * FXS/FXO(all units): UNIT * 32 + ts_number
-        *
-        * Bit 1 is for UNIT=1-3: FXS/FXO
-        *
-        */
-       ts_mask = (xpd->addr.unit == 0) ? 0x1 : 0x2;    /* Which bit? */
-       ts_number = CALL_PHONE_METHOD(echocancel_timeslot, xpd, pos);
-       if (ts_number >= ECHO_TIMESLOTS || ts_number < 0) {
-               XPD_ERR(xpd, "Bad ts_number=%d\n", ts_number);
-               return -EINVAL;
-       } else {
-               if (on)
-                       ts[ts_number] |= ts_mask;
-               else
-                       ts[ts_number] &= ~ts_mask;
-       }
-       LINE_DBG(GENERAL, xpd, pos, "%s = %d -- ts_number=%d ts_mask=0x%X\n",
-                __func__, on, ts_number, ts_mask);
-       return 0;
-}
-
-static int ECHO_ec_get(xpd_t *xpd, int pos)
-{
-       int ts_number;
-       int ts_mask;
-       int is_on;
-       __u8 *ts;
-
-       ts = xpd->xbus->echo_state.timeslots;
-       ts_mask = (xpd->addr.unit == 0) ? 0x1 : 0x2;    /* Which bit? */
-       ts_number = CALL_PHONE_METHOD(echocancel_timeslot, xpd, pos);
-       if (ts_number >= ECHO_TIMESLOTS || ts_number < 0) {
-               XPD_ERR(xpd, "Bad ts_number=%d\n", ts_number);
-               return -EINVAL;
-       } else {
-               is_on = ts[ts_number] & ts_mask;
-       }
-#if 0
-       LINE_DBG(GENERAL, xpd, pos, "ec_get=%d -- ts_number=%d ts_mask=0x%X\n",
-                is_on, ts_number, ts_mask);
-#endif
-       return is_on;
-}
-
-static void ECHO_ec_dump(xbus_t *xbus)
-{
-       __u8 *ts;
-       int i;
-
-       ts = xbus->echo_state.timeslots;
-       for (i = 0; i + 15 < ECHO_TIMESLOTS; i += 16) {
-               XBUS_DBG(GENERAL, xbus,
-                       "EC-DUMP[%03d]: "
-                       "0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X "
-                       "0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n",
-                       i, ts[i + 0], ts[i + 1], ts[i + 2], ts[i + 3],
-                       ts[i + 4], ts[i + 5], ts[i + 6], ts[i + 7], ts[i + 8],
-                       ts[i + 9], ts[i + 10], ts[i + 11], ts[i + 12],
-                       ts[i + 13], ts[i + 14], ts[i + 15]
-                   );
-       }
-}
-
-static int ECHO_ec_update(xbus_t *xbus)
-{
-       XBUS_DBG(GENERAL, xbus, "%s\n", __func__);
-       //ECHO_ec_dump(xbus);
-       return CALL_PROTO(ECHO, SET, xbus, NULL);
-}
-
-/*---------------- ECHO: Astribank Reply Handlers --------------------------*/
-HANDLER_DEF(ECHO, SET_REPLY)
-{
-       __u8 status;
-
-       BUG_ON(!xpd);
-       status = RPACKET_FIELD(pack, ECHO, SET_REPLY, status);
-       XPD_DBG(GENERAL, xpd, "status=0x%X\n", status);
-       return 0;
-}
-
-static const struct xops echo_xops = {
-       .card_new = ECHO_card_new,
-       .card_init = ECHO_card_init,
-       .card_remove = ECHO_card_remove,
-       .card_tick = ECHO_card_tick,
-       .card_register_reply = ECHO_card_register_reply,
-};
-
-static const struct echoops echoops = {
-       .ec_set = ECHO_ec_set,
-       .ec_get = ECHO_ec_get,
-       .ec_update = ECHO_ec_update,
-       .ec_dump = ECHO_ec_dump,
-};
-
-static xproto_table_t PROTO_TABLE(ECHO) = {
-       .owner = THIS_MODULE,
-       .entries = {
-               /*      Table   Card    Opcode          */
-               XENTRY( ECHO,   ECHO,   SET_REPLY       ),
-       },
-       .name = "ECHO",
-       .ports_per_subunit = 1,
-       .type = XPD_TYPE_ECHO,
-       .xops = &echo_xops,
-       .echoops = &echoops,
-       .packet_is_valid = echo_packet_is_valid,
-       .packet_dump = echo_packet_dump,
-};
-
-static bool echo_packet_is_valid(xpacket_t *pack)
-{
-       const xproto_entry_t *xe = NULL;
-       // DBG(GENERAL, "\n");
-       xe = xproto_card_entry(&PROTO_TABLE(ECHO), XPACKET_OP(pack));
-       return xe != NULL;
-}
-
-static void echo_packet_dump(const char *msg, xpacket_t *pack)
-{
-       DBG(GENERAL, "%s\n", msg);
-}
-
-/*------------------------- sysfs stuff --------------------------------*/
-static int echo_xpd_probe(struct device *dev)
-{
-       xpd_t *ec_xpd;
-       int ret = 0;
-
-       ec_xpd = dev_to_xpd(dev);
-       /* Is it our device? */
-       if (ec_xpd->xpd_type != XPD_TYPE_ECHO) {
-               XPD_ERR(ec_xpd, "drop suggestion for %s (%d)\n", dev_name(dev),
-                       ec_xpd->xpd_type);
-               return -EINVAL;
-       }
-       XPD_DBG(DEVICES, ec_xpd, "SYSFS\n");
-       return ret;
-}
-
-static int echo_xpd_remove(struct device *dev)
-{
-       xpd_t *ec_xpd;
-
-       ec_xpd = dev_to_xpd(dev);
-       XPD_DBG(DEVICES, ec_xpd, "SYSFS\n");
-       return 0;
-}
-
-static struct xpd_driver echo_driver = {
-       .xpd_type = XPD_TYPE_ECHO,
-       .driver = {
-                  .name = "echo",
-                  .owner = THIS_MODULE,
-                  .probe = echo_xpd_probe,
-                  .remove = echo_xpd_remove}
-};
-
-static int __init card_echo_startup(void)
-{
-       int ret;
-
-       ret = xpd_driver_register(&echo_driver.driver);
-       if (ret < 0)
-               return ret;
-       INFO("FEATURE: WITH Octasic echo canceller\n");
-       xproto_register(&PROTO_TABLE(ECHO));
-       return 0;
-}
-
-static void __exit card_echo_cleanup(void)
-{
-       DBG(GENERAL, "\n");
-       xproto_unregister(&PROTO_TABLE(ECHO));
-       xpd_driver_unregister(&echo_driver.driver);
-}
-
-MODULE_DESCRIPTION("XPP ECHO Card Driver");
-MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_XPD(XPD_TYPE_ECHO);
-
-module_init(card_echo_startup);
-module_exit(card_echo_cleanup);
diff --git a/drivers/dahdi/xpp/card_echo.h b/drivers/dahdi/xpp/card_echo.h
deleted file mode 100644 (file)
index 55c1d73..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef        CARD_ECHO_H
-#define        CARD_ECHO_H
-/*
- * Written by Oron Peled <oron@actcom.co.il>
- * Copyright (C) 2011, 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"
-
-enum echo_opcodes {
-       XPROTO_NAME(ECHO, SET) = 0x39,
-       XPROTO_NAME(ECHO, SET_REPLY) = 0x3A,
-};
-
-#endif /* CARD_ECHO_H */
diff --git a/drivers/dahdi/xpp/card_fxo.c b/drivers/dahdi/xpp/card_fxo.c
deleted file mode 100644 (file)
index 1dbd299..0000000
+++ /dev/null
@@ -1,1643 +0,0 @@
-/*
- * Written by Oron Peled <oron@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 <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include "xpd.h"
-#include "xproto.h"
-#include "xpp_dahdi.h"
-#include "card_fxo.h"
-#include "dahdi_debug.h"
-#include "xbus-core.h"
-
-static const char rcsid[] = "$Id$";
-
-static DEF_PARM(int, debug, 0, 0644, "Print DBG statements");
-static DEF_PARM(uint, poll_battery_interval, 500, 0644,
-               "Poll battery interval in milliseconds (0 - disable)");
-static DEF_PARM_BOOL(use_polrev_firmware, 1, 0444,
-               "Use firmware reports of polarity reversal");
-static DEF_PARM_BOOL(squelch_polrev, 0, 0644,
-               "Never report polarity reversal");
-#ifdef WITH_METERING
-static DEF_PARM(uint, poll_metering_interval, 500, 0644,
-               "Poll metering interval in milliseconds (0 - disable)");
-#endif
-static DEF_PARM(int, ring_debounce, 50, 0644,
-               "Number of ticks to debounce a false RING indication");
-static DEF_PARM(int, caller_id_style, 0, 0444,
-               "Caller-Id detection style: "
-               "0 - [BELL], "
-               "1 - [ETSI_FSK], "
-               "2 - [ETSI_DTMF], "
-               "3 - [PASSTHROUGH]");
-static DEF_PARM(int, power_denial_safezone, 650, 0644,
-               "msec after offhook to ignore power-denial ( (0 - disable power-denial)");
-static DEF_PARM(int, power_denial_minlen, 80, 0644,
-               "Minimal detected power-denial length (msec) (0 - disable power-denial)");
-static DEF_PARM(uint, battery_threshold, 3, 0644,
-               "Minimum voltage that shows there is battery");
-static DEF_PARM(uint, battery_debounce, 1000, 0644,
-               "Minimum interval (msec) for detection of battery off");
-
-enum cid_style {
-       CID_STYLE_BELL = 0,     /* E.g: US (Bellcore) */
-       CID_STYLE_ETSI_FSK = 1, /* E.g: UK (British Telecom) */
-       CID_STYLE_ETSI_DTMF = 2,        /* E.g: DK, Russia */
-       CID_STYLE_PASSTHROUGH = 3,      /* No change: Let asterisk  */
-                                       /* (>= 1.8) DSP handle this */
-};
-
-/* Signaling is opposite (fxs signalling for fxo card) */
-#if 1
-#define        FXO_DEFAULT_SIGCAP      (DAHDI_SIG_FXSKS | DAHDI_SIG_FXSLS)
-#else
-#define        FXO_DEFAULT_SIGCAP      (DAHDI_SIG_SF)
-#endif
-
-enum fxo_leds {
-       LED_GREEN,
-       LED_RED,
-};
-
-#define        NUM_LEDS                2
-#define        DELAY_UNTIL_DIALTONE    3000
-
-/*
- * Minimum duration for polarity reversal detection (in ticks)
- * Should be longer than the time to detect a ring, so voltage
- * fluctuation during ring won't trigger false detection.
- */
-#define        POLREV_THRESHOLD        200
-#define        POWER_DENIAL_CURRENT    3
-#define        POWER_DENIAL_DELAY      2500    /* ticks */
-
-/* Shortcuts */
-#define        DAA_WRITE       1
-#define        DAA_READ        0
-#define        DAA_DIRECT_REQUEST(xbus, xpd, port, writing, reg, dL)   \
-               xpp_register_request((xbus), (xpd), (port), \
-               (writing), (reg), 0, 0, (dL), 0, 0, 0, 0)
-
-/*---------------- FXO Protocol Commands ----------------------------------*/
-
-static bool fxo_packet_is_valid(xpacket_t *pack);
-static void fxo_packet_dump(const char *msg, xpacket_t *pack);
-#ifdef CONFIG_PROC_FS
-static const struct file_operations proc_fxo_info_ops;
-#ifdef WITH_METERING
-static const struct file_operations proc_xpd_metering_ops;
-#endif
-#endif
-static void dahdi_report_battery(xpd_t *xpd, lineno_t chan);
-static void report_polarity_reversal(xpd_t *xpd, xportno_t portno, char *msg);
-
-#define        PROC_FXO_INFO_FNAME     "fxo_info"
-#ifdef WITH_METERING
-#define        PROC_METERING_FNAME     "metering_read"
-#endif
-
-#define        REG_INTERRUPT_SRC       0x04    /*  4 -  Interrupt Source  */
-#define        REG_INTERRUPT_SRC_POLI  BIT(0)  /*  Polarity Reversal Detect Interrupt*/
-#define        REG_INTERRUPT_SRC_RING  BIT(7)  /*  Ring Detect Interrupt */
-
-#define        REG_DAA_CONTROL1        0x05    /*  5 -  DAA Control 1  */
-#define        REG_DAA_CONTROL1_OH     BIT(0)  /* Off-Hook.            */
-#define        REG_DAA_CONTROL1_ONHM   BIT(3)  /* On-Hook Line Monitor */
-
-#define        DAA_REG_METERING        0x11    /* 17 */
-#define        DAA_REG_CURRENT         0x1C    /* 28 */
-#define        DAA_REG_VBAT            0x1D    /* 29 */
-
-enum battery_state {
-       BATTERY_UNKNOWN = 0,
-       BATTERY_ON = 1,
-       BATTERY_OFF = -1
-};
-
-enum polarity_state {
-       POL_UNKNOWN = 0,
-       POL_POSITIVE = 1,
-       POL_NEGATIVE = -1
-};
-
-enum power_state {
-       POWER_UNKNOWN = 0,
-       POWER_ON = 1,
-       POWER_OFF = -1
-};
-
-struct FXO_priv_data {
-#ifdef WITH_METERING
-       struct proc_dir_entry *meteringfile;
-#endif
-       struct proc_dir_entry *fxo_info;
-       uint poll_counter;
-       signed char battery_voltage[CHANNELS_PERXPD];
-       signed char battery_current[CHANNELS_PERXPD];
-       enum battery_state battery[CHANNELS_PERXPD];
-       ushort nobattery_debounce[CHANNELS_PERXPD];
-       enum polarity_state polarity[CHANNELS_PERXPD];
-       ushort polarity_debounce[CHANNELS_PERXPD];
-       int  polarity_last_interval[CHANNELS_PERXPD];
-#define        POLARITY_LAST_INTERVAL_NONE     (-1)
-#define        POLARITY_LAST_INTERVAL_MAX      40
-       enum power_state power[CHANNELS_PERXPD];
-       ushort power_denial_delay[CHANNELS_PERXPD];
-       ushort power_denial_length[CHANNELS_PERXPD];
-       ushort power_denial_safezone[CHANNELS_PERXPD];
-       xpp_line_t cidfound;    /* 0 - OFF, 1 - ON */
-       unsigned int cidtimer[CHANNELS_PERXPD];
-       xpp_line_t ledstate[NUM_LEDS];  /* 0 - OFF, 1 - ON */
-       xpp_line_t ledcontrol[NUM_LEDS];        /* 0 - OFF, 1 - ON */
-       int led_counter[NUM_LEDS][CHANNELS_PERXPD];
-       atomic_t ring_debounce[CHANNELS_PERXPD];
-#ifdef WITH_METERING
-       uint metering_count[CHANNELS_PERXPD];
-       xpp_line_t metering_tone_state;
-#endif
-};
-
-/*
- * LED counter values:
- *     n>1     : BLINK every n'th tick
- */
-#define        LED_COUNTER(priv, pos, color)   ((priv)->led_counter[color][pos])
-#define        IS_BLINKING(priv, pos, color)   (LED_COUNTER(priv, pos, color) > 0)
-#define        MARK_BLINK(priv, pos, color, t) \
-               ((priv)->led_counter[color][pos] = (t))
-#define        MARK_OFF(priv, pos, color) \
-               do { \
-                       BIT_CLR((priv)->ledcontrol[color], (pos)); \
-                       MARK_BLINK((priv), (pos), (color), 0); \
-               } while (0)
-#define        MARK_ON(priv, pos, color) \
-               do { \
-                       BIT_SET((priv)->ledcontrol[color], (pos)); \
-                       MARK_BLINK((priv), (pos), (color), 0); \
-               } while (0)
-
-#define        LED_BLINK_RING                  (1000/8)        /* in ticks */
-
-/*---------------- FXO: Static functions ----------------------------------*/
-
-static const char *power2str(enum power_state pw)
-{
-       switch (pw) {
-       case POWER_UNKNOWN:
-               return "UNKNOWN";
-       case POWER_OFF:
-               return "OFF";
-       case POWER_ON:
-               return "ON";
-       }
-       return NULL;
-}
-
-static void power_change(xpd_t *xpd, int portno, enum power_state pw)
-{
-       struct FXO_priv_data *priv;
-
-       priv = xpd->priv;
-       LINE_DBG(SIGNAL, xpd, portno, "power: %s -> %s\n",
-                power2str(priv->power[portno]), power2str(pw));
-       priv->power[portno] = pw;
-}
-
-static void reset_battery_readings(xpd_t *xpd, lineno_t pos)
-{
-       struct FXO_priv_data *priv = xpd->priv;
-
-       priv->nobattery_debounce[pos] = 0;
-       priv->power_denial_delay[pos] = 0;
-       power_change(xpd, pos, POWER_UNKNOWN);
-}
-
-static const int led_register_mask[] = { BIT(7), BIT(6), BIT(5) };
-
-/*
- * LED control is done via DAA register 0x20
- */
-static int do_led(xpd_t *xpd, lineno_t chan, __u8 which, bool on)
-{
-       int ret = 0;
-       struct FXO_priv_data *priv;
-       xbus_t *xbus;
-       __u8 value;
-
-       BUG_ON(!xpd);
-       xbus = xpd->xbus;
-       priv = xpd->priv;
-       which = which % NUM_LEDS;
-       if (IS_SET(PHONEDEV(xpd).digital_outputs, chan)
-           || IS_SET(PHONEDEV(xpd).digital_inputs, chan))
-               goto out;
-       if (chan == PORT_BROADCAST) {
-               priv->ledstate[which] = (on) ? ~0 : 0;
-       } else {
-               if (on)
-                       BIT_SET(priv->ledstate[which], chan);
-               else
-                       BIT_CLR(priv->ledstate[which], chan);
-       }
-       value = 0;
-       value |= ((BIT(5) | BIT(6) | BIT(7)) & ~led_register_mask[which]);
-       value |= (on) ? BIT(0) : 0;
-       value |= (on) ? BIT(1) : 0;
-       LINE_DBG(LEDS, xpd, chan, "LED: which=%d -- %s\n", which,
-                (on) ? "on" : "off");
-       ret = DAA_DIRECT_REQUEST(xbus, xpd, chan, DAA_WRITE, 0x20, value);
-out:
-       return ret;
-}
-
-static void handle_fxo_leds(xpd_t *xpd)
-{
-       int i;
-       unsigned long flags;
-       const enum fxo_leds colors[] = { LED_GREEN, LED_RED };
-       enum fxo_leds color;
-       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 (color = 0; color < ARRAY_SIZE(colors); color++) {
-               for_each_line(xpd, i) {
-                       if (IS_SET(PHONEDEV(xpd).digital_outputs, i)
-                           || IS_SET(PHONEDEV(xpd).digital_inputs, i))
-                               continue;
-                       /* Blinking? */
-                       if ((xpd->blink_mode & BIT(i)) || IS_BLINKING(priv, i, color)) {
-                               int mod_value = LED_COUNTER(priv, i, color);
-
-                               if (!mod_value)
-                                       /* safety value */
-                                       mod_value = DEFAULT_LED_PERIOD;
-                               // led state is toggled
-                               if ((timer_count % mod_value) == 0) {
-                                       LINE_DBG(LEDS, xpd, i, "ledstate=%s\n",
-                                                (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);
-}
-
-static void update_dahdi_ring(xpd_t *xpd, int pos, bool on)
-{
-       BUG_ON(!xpd);
-       if (caller_id_style == CID_STYLE_BELL)
-               oht_pcm(xpd, pos, !on);
-       /*
-        * We should not spinlock before calling dahdi_hooksig() as
-        * it may call back into our xpp_hooksig() and cause
-        * a nested spinlock scenario
-        */
-       notify_rxsig(xpd, pos, (on) ? DAHDI_RXSIG_RING : DAHDI_RXSIG_OFFHOOK);
-}
-
-static void mark_ring(xpd_t *xpd, lineno_t pos, bool on, bool update_dahdi)
-{
-       struct FXO_priv_data *priv;
-
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       atomic_set(&priv->ring_debounce[pos], 0);       /* Stop debouncing */
-       /*
-        * We don't want to check battery during ringing
-        * due to voltage fluctuations.
-        */
-       reset_battery_readings(xpd, pos);
-       if (on && !PHONEDEV(xpd).ringing[pos]) {
-               LINE_DBG(SIGNAL, xpd, pos, "START\n");
-               PHONEDEV(xpd).ringing[pos] = 1;
-               priv->cidtimer[pos] = xpd->timer_count;
-               MARK_BLINK(priv, pos, LED_GREEN, LED_BLINK_RING);
-               if (update_dahdi)
-                       update_dahdi_ring(xpd, pos, on);
-       } else if (!on && PHONEDEV(xpd).ringing[pos]) {
-               LINE_DBG(SIGNAL, xpd, pos, "STOP\n");
-               PHONEDEV(xpd).ringing[pos] = 0;
-               priv->cidtimer[pos] = xpd->timer_count;
-               if (IS_BLINKING(priv, pos, LED_GREEN))
-                       MARK_BLINK(priv, pos, LED_GREEN, 0);
-               if (update_dahdi)
-                       update_dahdi_ring(xpd, pos, on);
-               priv->polarity_last_interval[pos] = POLARITY_LAST_INTERVAL_NONE;
-       }
-}
-
-static int do_sethook(xpd_t *xpd, int pos, bool to_offhook)
-{
-       unsigned long flags;
-       xbus_t *xbus;
-       struct FXO_priv_data *priv;
-       int ret = 0;
-       __u8 value;
-
-       BUG_ON(!xpd);
-       /* We can SETHOOK state only on PSTN */
-       BUG_ON(PHONEDEV(xpd).direction == TO_PHONE);
-       xbus = xpd->xbus;
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       if (priv->battery[pos] != BATTERY_ON && to_offhook) {
-               LINE_NOTICE(xpd, pos,
-                           "Cannot take offhook while battery is off!\n");
-               return -EINVAL;
-       }
-       spin_lock_irqsave(&xpd->lock, flags);
-       mark_ring(xpd, pos, 0, 0);      // No more rings
-       value = REG_DAA_CONTROL1_ONHM;  /* Bit 3 is for CID */
-       if (to_offhook)
-               value |= REG_DAA_CONTROL1_OH;
-       LINE_DBG(SIGNAL, xpd, pos, "SETHOOK: value=0x%02X %s\n", value,
-                (to_offhook) ? "OFFHOOK" : "ONHOOK");
-       if (to_offhook)
-               MARK_ON(priv, pos, LED_GREEN);
-       else
-               MARK_OFF(priv, pos, LED_GREEN);
-       ret =
-           DAA_DIRECT_REQUEST(xbus, xpd, pos, DAA_WRITE, REG_DAA_CONTROL1,
-                              value);
-       mark_offhook(xpd, pos, to_offhook);
-       switch (caller_id_style) {
-       case CID_STYLE_ETSI_DTMF:
-       case CID_STYLE_PASSTHROUGH:
-               break;
-       default:
-               oht_pcm(xpd, pos, 0);
-               break;
-       }
-#ifdef WITH_METERING
-       priv->metering_count[pos] = 0;
-       priv->metering_tone_state = 0L;
-       DAA_DIRECT_REQUEST(xbus, xpd, pos, DAA_WRITE, DAA_REG_METERING, 0x2D);
-#endif
-       /* unstable during hook changes */
-       reset_battery_readings(xpd, pos);
-       if (to_offhook) {
-               priv->power_denial_safezone[pos] = power_denial_safezone;
-       } else {
-               priv->power_denial_length[pos] = 0;
-               priv->power_denial_safezone[pos] = 0;
-       }
-       priv->cidtimer[pos] = xpd->timer_count;
-       spin_unlock_irqrestore(&xpd->lock, flags);
-       return ret;
-}
-
-/*---------------- FXO: Methods -------------------------------------------*/
-
-static void fxo_proc_remove(xbus_t *xbus, xpd_t *xpd)
-{
-       struct FXO_priv_data *priv;
-
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-       XPD_DBG(PROC, xpd, "\n");
-#ifdef CONFIG_PROC_FS
-#ifdef WITH_METERING
-       if (priv->meteringfile) {
-               XPD_DBG(PROC, xpd, "Removing xpd metering tone file\n");
-               remove_proc_entry(PROC_METERING_FNAME, xpd->proc_xpd_dir);
-               priv->meteringfile = NULL;
-       }
-#endif
-       if (priv->fxo_info) {
-               XPD_DBG(PROC, xpd, "Removing xpd FXO_INFO file\n");
-               remove_proc_entry(PROC_FXO_INFO_FNAME, xpd->proc_xpd_dir);
-               priv->fxo_info = NULL;
-       }
-#endif
-}
-
-static int fxo_proc_create(xbus_t *xbus, xpd_t *xpd)
-{
-       struct FXO_priv_data *priv;
-
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-#ifdef CONFIG_PROC_FS
-       XPD_DBG(PROC, xpd, "Creating FXO_INFO file\n");
-       priv->fxo_info = proc_create_data(PROC_FXO_INFO_FNAME, 0444,
-                                         xpd->proc_xpd_dir,
-                                         &proc_fxo_info_ops, xpd);
-       if (!priv->fxo_info) {
-               XPD_ERR(xpd, "Failed to create proc file '%s'\n",
-                       PROC_FXO_INFO_FNAME);
-               fxo_proc_remove(xbus, xpd);
-               return -EINVAL;
-       }
-       SET_PROC_DIRENTRY_OWNER(priv->fxo_info);
-#ifdef WITH_METERING
-       XPD_DBG(PROC, xpd, "Creating Metering tone file\n");
-       priv->meteringfile = proc_create_data(PROC_METERING_FNAME, 0444,
-                                             xpd->proc_xpd_dir,
-                                             &proc_xpd_metering_ops, xpd);
-       if (!priv->meteringfile) {
-               XPD_ERR(xpd, "Failed to create proc file '%s'\n",
-                       PROC_METERING_FNAME);
-               fxo_proc_remove(xbus, xpd);
-               return -EINVAL;
-       }
-       SET_PROC_DIRENTRY_OWNER(priv->meteringfile);
-#endif
-#endif
-       return 0;
-}
-
-static xpd_t *FXO_card_new(xbus_t *xbus, int unit, int subunit,
-                          const xproto_table_t *proto_table,
-                          const struct unit_descriptor *unit_descriptor,
-                          bool to_phone)
-{
-       xpd_t *xpd = NULL;
-       int channels;
-       int subunit_ports;
-
-       if (to_phone) {
-               XBUS_NOTICE(xbus,
-                       "XPD=%d%d: try to instanciate FXO with "
-                       "reverse direction\n",
-                       unit, subunit);
-               return NULL;
-       }
-       subunit_ports = unit_descriptor->numchips * unit_descriptor->ports_per_chip;
-       if (unit_descriptor->subtype == 2)
-               channels = min(2, subunit_ports);
-       else
-               channels = min(8, subunit_ports);
-       xpd =
-           xpd_alloc(xbus, unit, subunit,
-                     sizeof(struct FXO_priv_data), proto_table, unit_descriptor, channels);
-       if (!xpd)
-               return NULL;
-       PHONEDEV(xpd).direction = TO_PSTN;
-       xpd->type_name = "FXO";
-       if (fxo_proc_create(xbus, xpd) < 0)
-               goto err;
-       return xpd;
-err:
-       xpd_free(xpd);
-       return NULL;
-}
-
-static int FXO_card_init(xbus_t *xbus, xpd_t *xpd)
-{
-       struct FXO_priv_data *priv;
-       int i;
-
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-       // Hanghup all lines
-       for_each_line(xpd, i) {
-               do_sethook(xpd, i, 0);
-               /* will be updated on next battery sample */
-               priv->polarity[i] = POL_UNKNOWN;
-               priv->polarity_debounce[i] = 0;
-               /* will be updated on next battery sample */
-               priv->battery[i] = BATTERY_UNKNOWN;
-               /* will be updated on next battery sample */
-               priv->power[i] = POWER_UNKNOWN;
-               switch (caller_id_style) {
-               case CID_STYLE_ETSI_DTMF:
-               case CID_STYLE_PASSTHROUGH:
-                       oht_pcm(xpd, i, 1);
-                       break;
-               }
-               priv->polarity_last_interval[i] = POLARITY_LAST_INTERVAL_NONE;
-       }
-       XPD_DBG(GENERAL, xpd, "done\n");
-       for_each_line(xpd, i) {
-               do_led(xpd, i, LED_GREEN, 0);
-       }
-       for_each_line(xpd, i) {
-               do_led(xpd, i, LED_GREEN, 1);
-               msleep(50);
-       }
-       for_each_line(xpd, i) {
-               do_led(xpd, i, LED_GREEN, 0);
-               msleep(50);
-       }
-       CALL_PHONE_METHOD(card_pcm_recompute, xpd, 0);
-       return 0;
-}
-
-static int FXO_card_remove(xbus_t *xbus, xpd_t *xpd)
-{
-       BUG_ON(!xpd);
-       XPD_DBG(GENERAL, xpd, "\n");
-       fxo_proc_remove(xbus, xpd);
-       return 0;
-}
-
-static int FXO_card_dahdi_preregistration(xpd_t *xpd, bool on)
-{
-       xbus_t *xbus;
-       struct FXO_priv_data *priv;
-       int i;
-       unsigned int timer_count;
-
-       BUG_ON(!xpd);
-       xbus = xpd->xbus;
-       BUG_ON(!xbus);
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       timer_count = xpd->timer_count;
-       XPD_DBG(GENERAL, xpd, "%s\n", (on) ? "ON" : "OFF");
-       PHONEDEV(xpd).span.spantype = SPANTYPE_ANALOG_FXO;
-       for_each_line(xpd, i) {
-               struct dahdi_chan *cur_chan = XPD_CHAN(xpd, i);
-
-               XPD_DBG(GENERAL, xpd, "setting FXO channel %d\n", i);
-               snprintf(cur_chan->name, MAX_CHANNAME, "XPP_FXO/%02d/%1d%1d/%d",
-                        xbus->num, xpd->addr.unit, xpd->addr.subunit, i);
-               cur_chan->chanpos = i + 1;
-               cur_chan->pvt = xpd;
-               cur_chan->sigcap = FXO_DEFAULT_SIGCAP;
-       }
-       for_each_line(xpd, i) {
-               MARK_ON(priv, i, LED_GREEN);
-               msleep(4);
-               MARK_ON(priv, i, LED_RED);
-       }
-       for_each_line(xpd, i) {
-               priv->cidtimer[i] = timer_count;
-       }
-       return 0;
-}
-
-static int FXO_card_dahdi_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);
-       XPD_DBG(GENERAL, xpd, "%s\n", (on) ? "ON" : "OFF");
-       for_each_line(xpd, i) {
-               MARK_OFF(priv, i, LED_GREEN);
-               msleep(2);
-               MARK_OFF(priv, i, LED_RED);
-               msleep(2);
-       }
-       return 0;
-}
-
-static int FXO_span_assigned(xpd_t *xpd)
-{
-       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);
-       XPD_DBG(GENERAL, xpd, "\n");
-       for_each_line(xpd, i)
-               dahdi_report_battery(xpd, i);
-       return 0;
-}
-
-static int FXO_card_hooksig(xpd_t *xpd, int pos, enum dahdi_txsig txsig)
-{
-       struct FXO_priv_data *priv;
-       int ret = 0;
-
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       LINE_DBG(SIGNAL, xpd, pos, "%s\n", txsig2str(txsig));
-       BUG_ON(PHONEDEV(xpd).direction != TO_PSTN);
-       /* XXX Enable hooksig for FXO XXX */
-       switch (txsig) {
-       case DAHDI_TXSIG_START:
-       case DAHDI_TXSIG_OFFHOOK:
-               ret = do_sethook(xpd, pos, 1);
-               break;
-       case DAHDI_TXSIG_ONHOOK:
-               ret = do_sethook(xpd, pos, 0);
-               break;
-       default:
-               XPD_NOTICE(xpd, "Can't set tx state to %s (%d)\n",
-                          txsig2str(txsig), txsig);
-               return -EINVAL;
-       }
-       return ret;
-}
-
-static void dahdi_report_battery(xpd_t *xpd, lineno_t chan)
-{
-       struct FXO_priv_data *priv;
-
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-       if (SPAN_REGISTERED(xpd)) {
-               switch (priv->battery[chan]) {
-               case BATTERY_UNKNOWN:
-                       /* no-op */
-                       break;
-               case BATTERY_OFF:
-                       LINE_DBG(SIGNAL, xpd, chan, "Send DAHDI_ALARM_RED\n");
-                       dahdi_alarm_channel(XPD_CHAN(xpd, chan),
-                                           DAHDI_ALARM_RED);
-                       break;
-               case BATTERY_ON:
-                       LINE_DBG(SIGNAL, xpd, chan, "Send DAHDI_ALARM_NONE\n");
-                       dahdi_alarm_channel(XPD_CHAN(xpd, chan),
-                                           DAHDI_ALARM_NONE);
-                       break;
-               }
-       }
-}
-
-static int FXO_card_open(xpd_t *xpd, lineno_t chan)
-{
-       BUG_ON(!xpd);
-       return 0;
-}
-
-static void poll_battery(xbus_t *xbus, xpd_t *xpd)
-{
-       int i;
-
-       for_each_line(xpd, i) {
-               DAA_DIRECT_REQUEST(xbus, xpd, i, DAA_READ, DAA_REG_VBAT, 0);
-       }
-}
-
-#ifdef WITH_METERING
-static void poll_metering(xbus_t *xbus, xpd_t *xpd)
-{
-       int i;
-
-       for_each_line(xpd, i) {
-               if (IS_OFFHOOK(xpd, i))
-                       DAA_DIRECT_REQUEST(xbus, xpd, i, DAA_READ,
-                                          DAA_REG_METERING, 0);
-       }
-}
-#endif
-
-static void handle_fxo_ring(xpd_t *xpd)
-{
-       struct FXO_priv_data *priv;
-       int i;
-
-       priv = xpd->priv;
-       for_each_line(xpd, i) {
-               if (likely(use_polrev_firmware)) {
-                       int *t = &priv->polarity_last_interval[i];
-                       if (*t != POLARITY_LAST_INTERVAL_NONE) {
-                               (*t)++;
-                               if (*t > POLARITY_LAST_INTERVAL_MAX) {
-                                       LINE_DBG(SIGNAL, xpd, i,
-                                               "polrev(GOOD): %d msec\n", *t);
-                                       *t = POLARITY_LAST_INTERVAL_NONE;
-                                       report_polarity_reversal(xpd,
-                                                               i, "firmware");
-                               }
-                       }
-               }
-               if (atomic_read(&priv->ring_debounce[i]) > 0) {
-                       /* Maybe start ring */
-                       if (atomic_dec_and_test(&priv->ring_debounce[i]))
-                               mark_ring(xpd, i, 1, 1);
-               } else if (atomic_read(&priv->ring_debounce[i]) < 0) {
-                       /* Maybe stop ring */
-                       if (atomic_inc_and_test(&priv->ring_debounce[i]))
-                               mark_ring(xpd, i, 0, 1);
-               }
-       }
-}
-
-static void handle_fxo_power_denial(xpd_t *xpd)
-{
-       struct FXO_priv_data *priv;
-       int i;
-
-       if (!power_denial_safezone)
-               return;         /* Ignore power denials */
-       priv = xpd->priv;
-       for_each_line(xpd, i) {
-               if (PHONEDEV(xpd).ringing[i] || !IS_OFFHOOK(xpd, i)) {
-                       priv->power_denial_delay[i] = 0;
-                       continue;
-               }
-               if (priv->power_denial_safezone[i] > 0) {
-                       if (--priv->power_denial_safezone[i] == 0) {
-                               /*
-                                * Poll current, prev answers are meaningless
-                                */
-                               DAA_DIRECT_REQUEST(xpd->xbus, xpd, i, DAA_READ,
-                                                  DAA_REG_CURRENT, 0);
-                       }
-                       continue;
-               }
-               if (priv->power_denial_length[i] > 0) {
-                       priv->power_denial_length[i]--;
-                       if (priv->power_denial_length[i] <= 0) {
-                               /*
-                                * But maybe the FXS started to ring (and
-                                * the firmware haven't detected it yet).
-                                * This would cause false power denials so
-                                * we just flag it and schedule more ticks
-                                * to wait.
-                                */
-                               LINE_DBG(SIGNAL, xpd, i,
-                                        "Possible Power Denial Hangup\n");
-                               priv->power_denial_delay[i] =
-                                   POWER_DENIAL_DELAY;
-                       }
-                       continue;
-               }
-               if (priv->power_denial_delay[i] > 0) {
-                       /*
-                        * Ring detection by the firmware takes some time.
-                        * Therefore we delay our decision until we are
-                        * sure that no ring has started during this time.
-                        */
-                       priv->power_denial_delay[i]--;
-                       if (priv->power_denial_delay[i] <= 0) {
-                               LINE_DBG(SIGNAL, xpd, i,
-                                        "Power Denial Hangup\n");
-                               priv->power_denial_delay[i] = 0;
-                               /*
-                                * Let Asterisk decide what to do
-                                */
-                               notify_rxsig(xpd, i, DAHDI_RXSIG_ONHOOK);
-                       }
-               }
-       }
-}
-
-/*
- * For caller-id CID_STYLE_ETSI_DTMF:
- *   - No indication is passed before the CID
- *   - We try to detect it and send "fake" polarity reversal.
- *   - The chan_dahdi.conf should have cidstart=polarity
- *   - Based on an idea in http://bugs.digium.com/view.php?id=9096
- */
-static void check_etsi_dtmf(xpd_t *xpd)
-{
-       struct FXO_priv_data *priv;
-       int portno;
-       unsigned int timer_count;
-
-       if (!SPAN_REGISTERED(xpd))
-               return;
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       timer_count = xpd->timer_count;
-       for_each_line(xpd, portno) {
-               /* Skip offhook and ringing ports */
-               if (IS_OFFHOOK(xpd, portno) || PHONEDEV(xpd).ringing[portno])
-                       continue;
-               if (IS_SET(priv->cidfound, portno)) {
-                       if (timer_count > priv->cidtimer[portno] + 4000) {
-                               /* reset flags if it's been a while */
-                               priv->cidtimer[portno] = timer_count;
-                               BIT_CLR(priv->cidfound, portno);
-                               LINE_DBG(SIGNAL, xpd, portno,
-                                        "Reset CID flag\n");
-                       }
-                       continue;
-               }
-               if (timer_count > priv->cidtimer[portno] + 400) {
-                       struct dahdi_chan *chan = XPD_CHAN(xpd, portno);
-                       int sample;
-                       int i;
-
-                       for (i = 0; i < DAHDI_CHUNKSIZE; i++) {
-                               sample = DAHDI_XLAW(chan->readchunk[i], chan);
-                               if (sample > 16000 || sample < -16000) {
-                                       priv->cidtimer[portno] = timer_count;
-                                       BIT_SET(priv->cidfound, portno);
-                                       LINE_DBG(SIGNAL, xpd, portno,
-                                               "Found DTMF CLIP (%d)\n", i);
-                                       report_polarity_reversal(xpd, portno,
-                                                       "fake");
-                                       break;
-                               }
-                       }
-               }
-       }
-}
-
-static int FXO_card_tick(xbus_t *xbus, xpd_t *xpd)
-{
-       struct FXO_priv_data *priv;
-
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       if (poll_battery_interval != 0
-           && (priv->poll_counter % poll_battery_interval) == 0)
-               poll_battery(xbus, xpd);
-#ifdef WITH_METERING
-       if (poll_metering_interval != 0
-           && (priv->poll_counter % poll_metering_interval) == 0)
-               poll_metering(xbus, xpd);
-#endif
-       handle_fxo_leds(xpd);
-       handle_fxo_ring(xpd);
-       handle_fxo_power_denial(xpd);
-       if (caller_id_style == CID_STYLE_ETSI_DTMF && likely(xpd->card_present))
-               check_etsi_dtmf(xpd);
-       priv->poll_counter++;
-       return 0;
-}
-
-#include <dahdi/wctdm_user.h>
-/*
- * The first register is the ACIM, the other are coefficient registers.
- * We define the array size explicitly to track possible inconsistencies
- * if the struct is modified.
- */
-static const char echotune_regs[sizeof(struct wctdm_echo_coefs)] =
-    { 30, 45, 46, 47, 48, 49, 50, 51, 52 };
-
-static int FXO_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd,
-                         unsigned long arg)
-{
-       int i, ret;
-       unsigned char echotune_data[ARRAY_SIZE(echotune_regs)];
-
-       BUG_ON(!xpd);
-       if (!XBUS_IS(xpd->xbus, READY))
-               return -ENODEV;
-       switch (cmd) {
-       case WCTDM_SET_ECHOTUNE:
-               XPD_DBG(GENERAL, xpd, "-- Setting echo registers: \n");
-               /* first off: check if this span is fxs. If not: -EINVALID */
-               if (copy_from_user
-                   (&echotune_data, (void __user *)arg, sizeof(echotune_data)))
-                       return -EFAULT;
-
-               for (i = 0; i < ARRAY_SIZE(echotune_regs); i++) {
-                       XPD_DBG(REGS, xpd, "Reg=0x%02X, data=0x%02X\n",
-                               echotune_regs[i], echotune_data[i]);
-                       ret =
-                           DAA_DIRECT_REQUEST(xpd->xbus, xpd, pos, DAA_WRITE,
-                                              echotune_regs[i],
-                                              echotune_data[i]);
-                       if (ret < 0) {
-                               LINE_NOTICE(xpd, pos,
-                                       "Couldn't write %0x02X to "
-                                       "register %0x02X\n",
-                                       echotune_data[i], echotune_regs[i]);
-                               return ret;
-                       }
-                       msleep(1);
-               }
-
-               XPD_DBG(GENERAL, xpd, "-- Set echo registers successfully\n");
-               break;
-       case DAHDI_TONEDETECT:
-               /*
-                * Asterisk call all span types with this (FXS specific)
-                * call. Silently ignore it.
-                */
-               LINE_DBG(GENERAL, xpd, pos,
-                        "DAHDI_TONEDETECT (FXO: NOTIMPLEMENTED)\n");
-               return -ENOTTY;
-       default:
-               report_bad_ioctl(THIS_MODULE->name, xpd, pos, cmd);
-               return -ENOTTY;
-       }
-       return 0;
-}
-
-/*---------------- FXO: HOST COMMANDS -------------------------------------*/
-
-/*---------------- 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;
-       struct FXO_priv_data *priv;
-
-       if (!xpd) {
-               notify_bad_xpd(__func__, xbus, XPACKET_ADDR(pack), cmd->name);
-               return -EPROTO;
-       }
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       XPD_DBG(SIGNAL, xpd, "(PSTN) sig_toggles=0x%04X sig_status=0x%04X\n",
-               sig_toggles, sig_status);
-       spin_lock_irqsave(&xpd->lock, flags);
-       for_each_line(xpd, i) {
-               int debounce;
-
-               if (IS_SET(sig_toggles, i)) {
-                       if (priv->battery[i] == BATTERY_OFF) {
-                               /*
-                                * With poll_battery_interval==0 we cannot
-                                * have BATTERY_OFF so we won't get here
-                                */
-                               LINE_NOTICE(xpd, i,
-                                       "SIG_CHANGED while battery is off. "
-                                       "Ignored.\n");
-                               continue;
-                       }
-                       /* First report false ring alarms */
-                       debounce = atomic_read(&priv->ring_debounce[i]);
-                       if (debounce)
-                               LINE_NOTICE(xpd, i,
-                                       "Ignored a false short ring "
-                                       "(lasted only %dms)\n",
-                                       ring_debounce - debounce);
-                       /*
-                        * Now set a new ring alarm.
-                        * It will be checked in handle_fxo_ring()
-                        */
-                       debounce =
-                           (IS_SET(sig_status, i)) ? ring_debounce :
-                           -ring_debounce;
-                       atomic_set(&priv->ring_debounce[i], debounce);
-               }
-       }
-       spin_unlock_irqrestore(&xpd->lock, flags);
-       return 0;
-}
-
-static void report_polarity_reversal(xpd_t *xpd, xportno_t portno, char *msg)
-{
-       /*
-        * Inform dahdi/Asterisk:
-        * 1. Maybe used for hangup detection during offhook
-        * 2. In some countries used to report caller-id
-        *    during onhook but before first ring.
-        */
-       if (caller_id_style == CID_STYLE_ETSI_FSK)
-               /* will be cleared on ring/offhook */
-               oht_pcm(xpd, portno, 1);
-       if (SPAN_REGISTERED(xpd)) {
-               LINE_DBG(SIGNAL, xpd, portno,
-                       "%s DAHDI_EVENT_POLARITY (%s)\n",
-                       (squelch_polrev) ? "Squelch" : "Send",
-                       msg);
-               if (!squelch_polrev)
-                       dahdi_qevent_lock(XPD_CHAN(xpd, portno),
-                               DAHDI_EVENT_POLARITY);
-       }
-}
-
-static void update_battery_voltage(xpd_t *xpd, __u8 data_low,
-       xportno_t portno)
-{
-       struct FXO_priv_data *priv;
-       enum polarity_state pol;
-       int msec;
-       signed char volts = (signed char)data_low;
-
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       priv->battery_voltage[portno] = volts;
-       if (PHONEDEV(xpd).ringing[portno])
-               goto ignore_reading;    /* ring voltage create false alarms */
-       if (abs(volts) < battery_threshold) {
-               /*
-                * Check for battery voltage fluctuations
-                */
-               if (priv->battery[portno] != BATTERY_OFF) {
-                       int milliseconds;
-
-                       milliseconds =
-                           priv->nobattery_debounce[portno]++ *
-                           poll_battery_interval;
-                       if (milliseconds > battery_debounce) {
-                               LINE_DBG(SIGNAL, xpd, portno,
-                                        "BATTERY OFF voltage=%d\n", volts);
-                               priv->battery[portno] = BATTERY_OFF;
-                               dahdi_report_battery(xpd, portno);
-                               /* What's the polarity ? */
-                               priv->polarity[portno] = POL_UNKNOWN;
-                               priv->polarity_debounce[portno] = 0;
-                               /* What's the current ? */
-                               power_change(xpd, portno, POWER_UNKNOWN);
-                               /*
-                                * Stop further processing for now
-                                */
-                               goto ignore_reading;
-                       }
-
-               }
-       } else {
-               priv->nobattery_debounce[portno] = 0;
-               if (priv->battery[portno] != BATTERY_ON) {
-                       LINE_DBG(SIGNAL, xpd, portno, "BATTERY ON voltage=%d\n",
-                                volts);
-                       priv->battery[portno] = BATTERY_ON;
-                       dahdi_report_battery(xpd, portno);
-               }
-       }
-#if 0
-       /*
-        * Mark FXO ports without battery!
-        */
-       if (priv->battery[portno] != BATTERY_ON)
-               MARK_ON(priv, portno, LED_RED);
-       else
-               MARK_OFF(priv, portno, LED_RED);
-#endif
-       if (priv->battery[portno] != BATTERY_ON) {
-               /* What's the polarity ? */
-               priv->polarity[portno] = POL_UNKNOWN;
-               return;
-       }
-       /*
-        * Handle reverse polarity
-        */
-       if (volts == 0)
-               pol = POL_UNKNOWN;
-       else if (volts < 0)
-               pol = POL_NEGATIVE;
-       else
-               pol = POL_POSITIVE;
-       if (priv->polarity[portno] == pol) {
-               /*
-                * Same polarity, reset debounce counter
-                */
-               priv->polarity_debounce[portno] = 0;
-               return;
-       }
-       /*
-        * Track polarity reversals and debounce spikes.
-        * Only reversals with long duration count.
-        */
-       msec = priv->polarity_debounce[portno]++ * poll_battery_interval;
-       if (msec >= POLREV_THRESHOLD) {
-               priv->polarity_debounce[portno] = 0;
-               if (pol != POL_UNKNOWN && priv->polarity[portno] != POL_UNKNOWN) {
-                       char *polname = NULL;
-
-                       if (pol == POL_POSITIVE)
-                               polname = "Positive";
-                       else if (pol == POL_NEGATIVE)
-                               polname = "Negative";
-                       else
-                               BUG();
-                       LINE_DBG(SIGNAL, xpd, portno,
-                                "Polarity changed to %s\n", polname);
-                       if (!use_polrev_firmware)
-                               report_polarity_reversal(xpd, portno, polname);
-               }
-               priv->polarity[portno] = pol;
-       }
-       return;
-ignore_reading:
-       /*
-        * Reset debounce counters to prevent false alarms
-        */
-       /* unstable during hook changes */
-       reset_battery_readings(xpd, portno);
-}
-
-static void update_battery_current(xpd_t *xpd, __u8 data_low,
-       xportno_t portno)
-{
-       struct FXO_priv_data *priv;
-
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       priv->battery_current[portno] = data_low;
-       /*
-        * During ringing, current is not stable.
-        * During onhook there should not be current anyway.
-        */
-       if (PHONEDEV(xpd).ringing[portno] || !IS_OFFHOOK(xpd, portno))
-               goto ignore_it;
-       /*
-        * Power denial with no battery voltage is meaningless
-        */
-       if (priv->battery[portno] != BATTERY_ON)
-               goto ignore_it;
-       /* Safe zone after offhook */
-       if (priv->power_denial_safezone[portno] > 0)
-               goto ignore_it;
-       if (data_low < POWER_DENIAL_CURRENT) {
-               if (priv->power[portno] == POWER_ON) {
-                       power_change(xpd, portno, POWER_OFF);
-                       priv->power_denial_length[portno] = power_denial_minlen;
-               }
-       } else {
-               if (priv->power[portno] != POWER_ON) {
-                       power_change(xpd, portno, POWER_ON);
-                       priv->power_denial_length[portno] = 0;
-                       /* We are now OFFHOOK */
-                       hookstate_changed(xpd, portno, 1);
-               }
-       }
-       return;
-ignore_it:
-       priv->power_denial_delay[portno] = 0;
-}
-
-#ifdef WITH_METERING
-#define        BTD_BIT BIT(0)
-
-static void update_metering_state(xpd_t *xpd, __u8 data_low, lineno_t portno)
-{
-       struct FXO_priv_data *priv;
-       bool metering_tone = data_low & BTD_BIT;
-       bool old_metering_tone;
-
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       old_metering_tone = IS_SET(priv->metering_tone_state, portno);
-       LINE_DBG(SIGNAL, xpd, portno, "METERING: %s [dL=0x%X] (%d)\n",
-                (metering_tone) ? "ON" : "OFF", data_low,
-                priv->metering_count[portno]);
-       if (metering_tone && !old_metering_tone) {
-               /* Rising edge */
-               priv->metering_count[portno]++;
-               BIT_SET(priv->metering_tone_state, portno);
-       } else if (!metering_tone && old_metering_tone)
-               BIT_CLR(priv->metering_tone_state, portno);
-       if (metering_tone) {
-               /* Clear the BTD bit */
-               data_low &= ~BTD_BIT;
-               DAA_DIRECT_REQUEST(xpd->xbus, xpd, portno, DAA_WRITE,
-                                  DAA_REG_METERING, data_low);
-       }
-}
-#endif
-
-static void got_chip_interrupt(xpd_t *xpd, __u8 data_low,
-       xportno_t portno)
-{
-       struct FXO_priv_data *priv;
-       int t;
-
-       if (!use_polrev_firmware)
-               return;
-       priv = xpd->priv;
-       LINE_DBG(SIGNAL, xpd, portno, "mask=0x%X\n", data_low);
-       if (!(data_low & REG_INTERRUPT_SRC_POLI))
-               return;
-       t = priv->polarity_last_interval[portno];
-       if (PHONEDEV(xpd).ringing[portno]) {
-               priv->polarity_last_interval[portno] =
-                       POLARITY_LAST_INTERVAL_NONE;
-               LINE_DBG(SIGNAL, xpd, portno,
-                       "polrev(false): %d msec (while ringing)\n", t);
-       } else if (data_low & REG_INTERRUPT_SRC_RING) {
-               priv->polarity_last_interval[portno] =
-                       POLARITY_LAST_INTERVAL_NONE;
-               LINE_DBG(SIGNAL, xpd, portno,
-                       "polrev(false): %d msec (with chip-interrupt ring)\n",
-                       t);
-       } else if (t == POLARITY_LAST_INTERVAL_NONE) {
-               priv->polarity_last_interval[portno] = 0;
-               LINE_DBG(SIGNAL, xpd, portno,
-                       "polrev(start)\n");
-       } else if (t < POLARITY_LAST_INTERVAL_MAX) {
-               /*
-                * Start counting upward from -POLARITY_LAST_INTERVAL_MAX
-                * Until we reach POLARITY_LAST_INTERVAL_NONE.
-                * This way we filter bursts of false reports we get
-                * during ringing.
-                */
-               priv->polarity_last_interval[portno] =
-                       POLARITY_LAST_INTERVAL_NONE -
-                       POLARITY_LAST_INTERVAL_MAX;
-               LINE_DBG(SIGNAL, xpd, portno,
-                       "polrev(false): %d msec (interval shorter than %d)\n",
-                       t, POLARITY_LAST_INTERVAL_MAX);
-       }
-}
-
-static int FXO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
-{
-       struct FXO_priv_data *priv;
-       lineno_t portno;
-
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       portno = info->h.portnum;
-       switch (REG_FIELD(info, regnum)) {
-       case REG_INTERRUPT_SRC:
-               got_chip_interrupt(xpd, REG_FIELD(info, data_low), portno);
-               break;
-       case DAA_REG_VBAT:
-               update_battery_voltage(xpd, REG_FIELD(info, data_low), portno);
-               break;
-       case DAA_REG_CURRENT:
-               update_battery_current(xpd, REG_FIELD(info, data_low), portno);
-               break;
-#ifdef WITH_METERING
-       case DAA_REG_METERING:
-               update_metering_state(xpd, REG_FIELD(info, data_low), portno);
-               break;
-#endif
-       }
-       LINE_DBG(REGS, xpd, portno, "%c reg_num=0x%X, dataL=0x%X dataH=0x%X\n",
-                ((info->h.bytes == 3) ? 'I' : 'D'), REG_FIELD(info, regnum),
-                REG_FIELD(info, data_low), REG_FIELD(info, data_high));
-       /* Update /proc info only if reply relate to the last slic read request */
-       if (REG_FIELD(&xpd->requested_reply, regnum) ==
-                       REG_FIELD(info, regnum)
-               && REG_FIELD(&xpd->requested_reply, do_subreg) ==
-                       REG_FIELD(info, do_subreg)
-               && REG_FIELD(&xpd->requested_reply, subreg) ==
-                       REG_FIELD(info, subreg)) {
-               xpd->last_reply = *info;
-       }
-       return 0;
-}
-
-static int FXO_card_state(xpd_t *xpd, bool on)
-{
-       int ret = 0;
-       struct FXO_priv_data *priv;
-
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       XPD_DBG(GENERAL, xpd, "%s\n", (on) ? "on" : "off");
-       return ret;
-}
-
-static const struct xops fxo_xops = {
-       .card_new = FXO_card_new,
-       .card_init = FXO_card_init,
-       .card_remove = FXO_card_remove,
-       .card_tick = FXO_card_tick,
-       .card_register_reply = FXO_card_register_reply,
-};
-
-static const struct phoneops fxo_phoneops = {
-       .card_dahdi_preregistration = FXO_card_dahdi_preregistration,
-       .card_dahdi_postregistration = FXO_card_dahdi_postregistration,
-       .card_hooksig = FXO_card_hooksig,
-       .card_pcm_recompute = generic_card_pcm_recompute,
-       .card_pcm_fromspan = generic_card_pcm_fromspan,
-       .card_pcm_tospan = generic_card_pcm_tospan,
-       .card_timing_priority = generic_timing_priority,
-       .echocancel_timeslot = generic_echocancel_timeslot,
-       .echocancel_setmask = generic_echocancel_setmask,
-       .card_ioctl = FXO_card_ioctl,
-       .card_open = FXO_card_open,
-       .card_state = FXO_card_state,
-       .span_assigned = FXO_span_assigned,
-};
-
-static xproto_table_t PROTO_TABLE(FXO) = {
-       .owner = THIS_MODULE,
-       .entries = {
-               /*      Prototable      Card    Opcode          */
-               XENTRY( FXO,            FXO,    SIG_CHANGED     ),
-       },
-       .name = "FXO",  /* protocol name */
-       .ports_per_subunit = 8,
-       .type = XPD_TYPE_FXO,
-       .xops = &fxo_xops,
-       .phoneops = &fxo_phoneops,
-       .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(GENERAL, "\n");
-       xe = xproto_card_entry(&PROTO_TABLE(FXO), XPACKET_OP(pack));
-       return xe != NULL;
-}
-
-static void fxo_packet_dump(const char *msg, xpacket_t *pack)
-{
-       DBG(GENERAL, "%s\n", msg);
-}
-
-/*------------------------- DAA Handling --------------------------*/
-
-#ifdef CONFIG_PROC_FS
-static int proc_fxo_info_show(struct seq_file *sfile, void *not_used)
-{
-       unsigned long flags;
-       xpd_t *xpd = sfile->private;
-       struct FXO_priv_data *priv;
-       int i;
-
-       if (!xpd)
-               return -ENODEV;
-       spin_lock_irqsave(&xpd->lock, flags);
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       seq_printf(sfile, "\t%-17s: ", "Channel");
-       for_each_line(xpd, i) {
-               if (!IS_SET(PHONEDEV(xpd).digital_outputs, i)
-                   && !IS_SET(PHONEDEV(xpd).digital_inputs, i)) {
-                       seq_printf(sfile, "%4d ", i % 10);
-               }
-       }
-       seq_printf(sfile, "\nLeds:");
-       seq_printf(sfile, "\n\t%-17s: ", "state");
-       for_each_line(xpd, i) {
-               if (!IS_SET(PHONEDEV(xpd).digital_outputs, i)
-                   && !IS_SET(PHONEDEV(xpd).digital_inputs, i)) {
-                       seq_printf(sfile, "  %d%d ",
-                                  IS_SET(priv->ledstate[LED_GREEN], i),
-                                  IS_SET(priv->ledstate[LED_RED], i));
-               }
-       }
-       seq_printf(sfile, "\n\t%-17s: ", "blinking");
-       for_each_line(xpd, i) {
-               if (!IS_SET(PHONEDEV(xpd).digital_outputs, i)
-                   && !IS_SET(PHONEDEV(xpd).digital_inputs, i)) {
-                       seq_printf(sfile, "  %d%d ",
-                                  IS_BLINKING(priv, i, LED_GREEN),
-                                  IS_BLINKING(priv, i, LED_RED));
-               }
-       }
-       seq_printf(sfile, "\nBattery-Data:");
-       seq_printf(sfile, "\n\t%-17s: ", "voltage");
-       for_each_line(xpd, i) {
-               seq_printf(sfile, "%4d ", priv->battery_voltage[i]);
-       }
-       seq_printf(sfile, "\n\t%-17s: ", "current");
-       for_each_line(xpd, i) {
-               seq_printf(sfile, "%4d ", priv->battery_current[i]);
-       }
-       seq_printf(sfile, "\nBattery:");
-       seq_printf(sfile, "\n\t%-17s: ", "on");
-       for_each_line(xpd, i) {
-               char *bat;
-
-               if (priv->battery[i] == BATTERY_ON)
-                       bat = "+";
-               else if (priv->battery[i] == BATTERY_OFF)
-                       bat = "-";
-               else
-                       bat = ".";
-               seq_printf(sfile, "%4s ", bat);
-       }
-       seq_printf(sfile, "\n\t%-17s: ", "debounce");
-       for_each_line(xpd, i) {
-               seq_printf(sfile, "%4d ", priv->nobattery_debounce[i]);
-       }
-       seq_printf(sfile, "\nPolarity-Reverse:");
-       seq_printf(sfile, "\n\t%-17s: ", "polarity");
-       for_each_line(xpd, i) {
-               char *polname;
-
-               if (priv->polarity[i] == POL_POSITIVE)
-                       polname = "+";
-               else if (priv->polarity[i] == POL_NEGATIVE)
-                       polname = "-";
-               else
-                       polname = ".";
-               seq_printf(sfile, "%4s ", polname);
-       }
-       seq_printf(sfile, "\n\t%-17s: ", "debounce");
-       for_each_line(xpd, i) {
-               seq_printf(sfile, "%4d ", priv->polarity_debounce[i]);
-       }
-       seq_printf(sfile, "\nPower-Denial:");
-       seq_printf(sfile, "\n\t%-17s: ", "power");
-       for_each_line(xpd, i) {
-               char *curr;
-
-               if (priv->power[i] == POWER_ON)
-                       curr = "+";
-               else if (priv->power[i] == POWER_OFF)
-                       curr = "-";
-               else
-                       curr = ".";
-               seq_printf(sfile, "%4s ", curr);
-       }
-       seq_printf(sfile, "\n\t%-17s: ", "safezone");
-       for_each_line(xpd, i) {
-               seq_printf(sfile, "%4d ", priv->power_denial_safezone[i]);
-       }
-       seq_printf(sfile, "\n\t%-17s: ", "delay");
-       for_each_line(xpd, i) {
-               seq_printf(sfile, "%4d ", priv->power_denial_delay[i]);
-       }
-#ifdef WITH_METERING
-       seq_printf(sfile, "\nMetering:");
-       seq_printf(sfile, "\n\t%-17s: ", "count");
-       for_each_line(xpd, i) {
-               seq_printf(sfile, "%4d ", priv->metering_count[i]);
-       }
-#endif
-       seq_printf(sfile, "\n");
-       spin_unlock_irqrestore(&xpd->lock, flags);
-       return 0;
-}
-
-static int proc_fxo_info_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, proc_fxo_info_show, PDE_DATA(inode));
-}
-
-static const struct file_operations proc_fxo_info_ops = {
-       .owner          = THIS_MODULE,
-       .open           = proc_fxo_info_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-
-#ifdef WITH_METERING
-static int proc_xpd_metering_show(struct seq_file *sfile, void *not_used)
-{
-       unsigned long flags;
-       xpd_t *xpd = sfile->private;
-       struct FXO_priv_data *priv;
-       int i;
-
-       if (!xpd)
-               return -ENODEV;
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       spin_lock_irqsave(&xpd->lock, flags);
-       seq_printf(sfile, "# Chan\tMeter (since last read)\n");
-       for_each_line(xpd, i) {
-               seq_printf(sfile, "%d\t%d\n", i, priv->metering_count[i]);
-       }
-       spin_unlock_irqrestore(&xpd->lock, flags);
-       /* Zero meters */
-       for_each_line(xpd, i)
-           priv->metering_count[i] = 0;
-       return 0;
-}
-
-static int proc_xpd_metering_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, proc_xpd_metering_show, PDE_DATA(inode));
-}
-
-static const struct file_operations proc_xpd_metering_ops = {
-       .owner          = THIS_MODULE,
-       .open           = proc_xpd_metering_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-
-#endif
-#endif
-
-static DEVICE_ATTR_READER(fxo_battery_show, dev, buf)
-{
-       xpd_t *xpd;
-       struct FXO_priv_data *priv;
-       unsigned long flags;
-       int len = 0;
-       int i;
-
-       BUG_ON(!dev);
-       xpd = dev_to_xpd(dev);
-       if (!xpd)
-               return -ENODEV;
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       spin_lock_irqsave(&xpd->lock, flags);
-       for_each_line(xpd, i) {
-               char bat;
-
-               if (priv->battery[i] == BATTERY_ON)
-                       bat = '+';
-               else if (priv->battery[i] == BATTERY_OFF)
-                       bat = '-';
-               else
-                       bat = '.';
-               len += sprintf(buf + len, "%c ", bat);
-       }
-       len += sprintf(buf + len, "\n");
-       spin_unlock_irqrestore(&xpd->lock, flags);
-       return len;
-}
-
-static DEVICE_ATTR(fxo_battery, S_IRUGO, fxo_battery_show, NULL);
-
-static int fxo_xpd_probe(struct device *dev)
-{
-       xpd_t *xpd;
-       int ret;
-
-       xpd = dev_to_xpd(dev);
-       /* Is it our device? */
-       if (xpd->xpd_type != XPD_TYPE_FXO) {
-               XPD_ERR(xpd, "drop suggestion for %s (%d)\n", dev_name(dev),
-                       xpd->xpd_type);
-               return -EINVAL;
-       }
-       XPD_DBG(DEVICES, xpd, "SYSFS\n");
-       ret = device_create_file(dev, &dev_attr_fxo_battery);
-       if (ret) {
-               XPD_ERR(xpd, "%s: device_create_file(fxo_battery) failed: %d\n",
-                       __func__, ret);
-               goto fail_fxo_battery;
-       }
-       return 0;
-fail_fxo_battery:
-       return ret;
-}
-
-static int fxo_xpd_remove(struct device *dev)
-{
-       xpd_t *xpd;
-
-       xpd = dev_to_xpd(dev);
-       XPD_DBG(DEVICES, xpd, "SYSFS\n");
-       device_remove_file(dev, &dev_attr_fxo_battery);
-       return 0;
-}
-
-static struct xpd_driver fxo_driver = {
-       .xpd_type = XPD_TYPE_FXO,
-       .driver = {
-                  .name = "fxo",
-                  .owner = THIS_MODULE,
-                  .probe = fxo_xpd_probe,
-                  .remove = fxo_xpd_remove}
-};
-
-static int __init card_fxo_startup(void)
-{
-       int ret;
-
-       if (ring_debounce <= 0) {
-               ERR("ring_debounce=%d. Must be positive number of ticks\n",
-                   ring_debounce);
-               return -EINVAL;
-       }
-       if ((ret = xpd_driver_register(&fxo_driver.driver)) < 0)
-               return ret;
-#ifdef WITH_METERING
-       INFO("FEATURE: WITH METERING Detection\n");
-#else
-       INFO("FEATURE: NO METERING Detection\n");
-#endif
-       xproto_register(&PROTO_TABLE(FXO));
-       return 0;
-}
-
-static void __exit card_fxo_cleanup(void)
-{
-       xproto_unregister(&PROTO_TABLE(FXO));
-       xpd_driver_unregister(&fxo_driver.driver);
-}
-
-MODULE_DESCRIPTION("XPP FXO Card Driver");
-MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_XPD(XPD_TYPE_FXO);
-
-module_init(card_fxo_startup);
-module_exit(card_fxo_cleanup);
diff --git a/drivers/dahdi/xpp/card_fxo.h b/drivers/dahdi/xpp/card_fxo.h
deleted file mode 100644 (file)
index 00cf20f..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef        CARD_FXO_H
-#define        CARD_FXO_H
-/*
- * Written by Oron Peled <oron@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"
-
-enum fxo_opcodes {
-       XPROTO_NAME(FXO, SIG_CHANGED) = 0x06,           /**/
-       XPROTO_NAME(FXO, DAA_WRITE) = 0x0F,             /* Write to DAA */
-       XPROTO_NAME(FXO, CHAN_CID) = 0x0F,              /* Write to DAA */
-       XPROTO_NAME(FXO, LED) = 0x0F,                   /* Write to DAA */
-};
-
-
-DEF_RPACKET_DATA(FXO, SIG_CHANGED,
-               xpp_line_t sig_status;  /* channels: lsb=1, msb=8 */
-               xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */
-               );
-
-#endif /* CARD_FXO_H */
diff --git a/drivers/dahdi/xpp/card_fxs.c b/drivers/dahdi/xpp/card_fxs.c
deleted file mode 100644 (file)
index ab5f5a8..0000000
+++ /dev/null
@@ -1,2379 +0,0 @@
-/*
- * Written by Oron Peled <oron@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 <linux/seq_file.h>
-#include "xpd.h"
-#include "xproto.h"
-#include "xpp_dahdi.h"
-#include "card_fxs.h"
-#include "dahdi_debug.h"
-#include "xbus-core.h"
-
-static const char rcsid[] = "$Id$";
-
-/* must be before dahdi_debug.h */
-static DEF_PARM(int, debug, 0, 0644, "Print DBG statements");
-static DEF_PARM_BOOL(reversepolarity, 0, 0644, "Reverse Line Polarity");
-static DEF_PARM_BOOL(dtmf_detection, 1, 0644, "Do DTMF detection in hardware");
-#ifdef POLL_DIGITAL_INPUTS
-static DEF_PARM(uint, poll_digital_inputs, 1000, 0644, "Poll Digital Inputs");
-#endif
-static DEF_PARM(uint, poll_chan_linefeed, 30000, 0644, "Poll Channel Linefeed");
-
-static DEF_PARM_BOOL(vmwi_ioctl, 1, 0644,
-                    "Asterisk support VMWI notification via ioctl");
-static DEF_PARM_BOOL(ring_trapez, 0, 0664, "Use trapezoid ring type");
-static DEF_PARM_BOOL(lower_ringing_noise, 0, 0664,
-               "Lower ringing noise (may loose CallerID)");
-
-/* Signaling is opposite (fxo signalling for fxs card) */
-#if 1
-#define        FXS_DEFAULT_SIGCAP \
-               (DAHDI_SIG_FXOKS | DAHDI_SIG_FXOLS | DAHDI_SIG_FXOGS)
-#else
-#define        FXS_DEFAULT_SIGCAP \
-               (DAHDI_SIG_SF | DAHDI_SIG_EM)
-#endif
-
-#define        VMWI_TYPE(priv, pos, type)      \
-       ((priv)->vmwisetting[pos].vmwi_type & DAHDI_VMWI_ ## type)
-#define        VMWI_NEON(priv, pos)            VMWI_TYPE(priv, pos, HVAC)
-
-#define        LINES_DIGI_OUT  2
-#define        LINES_DIGI_INP  4
-
-enum fxs_leds {
-       LED_GREEN,
-       LED_RED,
-       OUTPUT_RELAY,
-};
-
-#define        NUM_LEDS        2
-
-/* Shortcuts */
-#define        SLIC_WRITE      1
-#define        SLIC_READ       0
-#define        SLIC_DIRECT_REQUEST(xbus, xpd, port, writing, reg, dL)  \
-       xpp_register_request((xbus), (xpd), (port), \
-       (writing), (reg), 0, 0, (dL), 0, 0, 0, 0)
-#define        SLIC_INDIRECT_REQUEST(xbus, xpd, port, writing, reg, dL, dH)    \
-       xpp_register_request((xbus), (xpd), (port), \
-       (writing), 0x1E, 1, (reg), (dL), 1, (dH), 0, 0)
-#define        EXP_REQUEST(xbus, xpd, writing, reg, dL, dH)    \
-       xpp_register_request((xbus), (xpd), 0, \
-       (writing), (reg), 1, 0, (dL), 1, (dH), 0, 1)
-#define        RAM_REQUEST(xbus, xpd, port, writing, addr, data)       \
-       xpp_ram_request((xbus), (xpd), (port), \
-       (writing), (__u8)(addr), (__u8)((addr) >> 8), (__u8)(data), (__u8)((data) >> 8), (__u8)((data) >> 16), (__u8)((data) >> 24), 0)
-
-#define        VALID_PORT(port) \
-               (((port) >= 0 && (port) <= 7) || (port) == PORT_BROADCAST)
-
-#define        REG_TYPE1_DIGITAL_IOCTRL        0x06    /* LED and RELAY control */
-
-/* Values of SLIC linefeed control register (0x40) */
-enum fxs_state {
-       FXS_LINE_OPEN = 0x00,   /* Open */
-       FXS_LINE_ACTIVE = 0x01, /* Forward active */
-       FXS_LINE_OHTRANS = 0x02,        /* Forward on-hook transmission */
-       FXS_LINE_TIPOPEN = 0x03,        /* TIP open */
-       FXS_LINE_RING = 0x04,   /* Ringing */
-       FXS_LINE_REV_ACTIVE = 0x05,     /* Reverse active */
-       FXS_LINE_REV_OHTRANS = 0x06,    /* Reverse on-hook transmission */
-       FXS_LINE_RING_OPEN = 0x07       /* RING open */
-};
-
-enum neon_state {
-       END_NEON = 0,
-       INIT_NEON = 1,
-};
-
-#define        FXS_LINE_POL_ACTIVE \
-               ((reversepolarity) ? FXS_LINE_REV_ACTIVE : FXS_LINE_ACTIVE)
-#define        FXS_LINE_POL_OHTRANS \
-               ((reversepolarity) ? FXS_LINE_REV_OHTRANS : FXS_LINE_OHTRANS)
-
-/* FXS type 1 registers */
-#define REG_TYPE1_RINGCON              0x22    /* 34 - Ringing Oscillator Control */
-
-/*
- * DTMF detection
- */
-#define REG_TYPE1_DTMF_DECODE          0x18    /* 24 - DTMF Decode Status */
-#define REG_TYPE1_BATTERY              0x42    /* 66 - Battery Feed Control */
-#define        REG_TYPE1_BATTERY_BATSL         BIT(1)  /* Battery Feed Select */
-
-/* 68 -  Loop Closure/Ring Trip Detect Status */
-#define        REG_TYPE1_LOOPCLOSURE           0x44
-#define        REG_TYPE1_LOOPCLOSURE_ZERO      0xF8    /* Loop Closure zero bits. */
-#define        REG_TYPE1_LOOPCLOSURE_LCR       BIT(0)  /* Loop Closure Detect Indicator. */
-
-/* FXS type 6 registers */
-#define REG_TYPE6_RINGCON              0x26    /* 38 - Ringing Oscillator Control */
-
-/* 34 -  Loop Closure/Ring Trip Detect Status */
-#define        REG_TYPE6_LCRRTP                0x22
-#define        REG_TYPE6_LCRRTP_ZERO           0xF0    /* Loop Closure zero bits. */
-#define        REG_TYPE6_LCRRTP_LCR            BIT(1)  /* Loop Closure Detect Indicator. */
-
-#define        REG_TYPE6_TONEN                 0x3E    /* 62 - Hardware DTMF detection */
-#define        REG_TYPE6_TONEN_DTMF_DIS        BIT(2)  /*      DTMF Disable */
-#define REG_TYPE6_LINEFEED             0x1E    /* 30 - Linefeed */
-#define REG_TYPE6_TONDTMF              0x3C    /* 60 - DTMF Decode Status */
-#define        REG_TYPE6_EXP_GPIOA             0x12    /* I/O Expander GPIOA */
-#define        REG_TYPE6_EXP_GPIOB             0x13    /* I/O Expander GPIOB */
-#define        REG_TYPE6_ENHANCE               0x2F    /* 47 - Enhance */
-#define        REG_TYPE6_USERSTAT              0x42    /* 66 - Userstat */
-#define        REG_TYPE6_DIAG1                 0x47    /* 71 - Diag1 */
-#define RAM_TYPE6_SLOPE_VLIM           634
-#define SLOPE_VLIM_DFLT                        0x1E655196L
-#define SLOPE_VLIM_MWI                 0x8000000L
-#define RAM_TYPE6_VBATH_EXPECT         767
-#define VBATH_EXPECT_DFLT              0x2B10A20L
-#define VBATH_EXPECT_MWI               0x6147AB2L
-
-/*---------------- FXS Protocol Commands ----------------------------------*/
-
-static bool fxs_packet_is_valid(xpacket_t *pack);
-static void fxs_packet_dump(const char *msg, xpacket_t *pack);
-#ifdef CONFIG_PROC_FS
-static const struct file_operations proc_fxs_info_ops;
-#ifdef WITH_METERING
-static const struct file_operations proc_xpd_metering_ops;
-#endif
-#endif
-static void start_stop_vm_led(xbus_t *xbus, xpd_t *xpd, lineno_t pos);
-
-#define        PROC_FXS_INFO_FNAME     "fxs_info"
-#ifdef WITH_METERING
-#define        PROC_METERING_FNAME     "metering_gen"
-#endif
-
-struct FXS_priv_data {
-#ifdef WITH_METERING
-       struct proc_dir_entry *meteringfile;
-#endif
-       struct proc_dir_entry *fxs_info;
-       xpp_line_t ledstate[NUM_LEDS];  /* 0 - OFF, 1 - ON */
-       xpp_line_t ledcontrol[NUM_LEDS];        /* 0 - OFF, 1 - ON */
-       xpp_line_t search_fsk_pattern;
-       xpp_line_t found_fsk_pattern;
-       xpp_line_t update_offhook_state;
-       xpp_line_t want_dtmf_events;    /* what dahdi want */
-       xpp_line_t want_dtmf_mute;      /* what dahdi want */
-       xpp_line_t prev_key_down;       /* DTMF down sets the bit */
-       xpp_line_t neon_blinking;
-       xpp_line_t neonstate;
-       xpp_line_t vbat_h;              /* High voltage */
-       struct timeval prev_key_time[CHANNELS_PERXPD];
-       int led_counter[NUM_LEDS][CHANNELS_PERXPD];
-       int overheat_reset_counter[CHANNELS_PERXPD];
-       int ohttimer[CHANNELS_PERXPD];
-#define OHT_TIMER              6000    /* How long after RING to retain OHT */
-       /* IDLE changing hook state */
-       enum fxs_state idletxhookstate[CHANNELS_PERXPD];
-       enum fxs_state lasttxhook[CHANNELS_PERXPD];
-       enum fxs_state polledhook[CHANNELS_PERXPD];
-       struct dahdi_vmwi_info vmwisetting[CHANNELS_PERXPD];
-};
-
-/*
- * LED counter values:
- *     n>1     : BLINK every n'th tick
- */
-#define        LED_COUNTER(priv, pos, color)   ((priv)->led_counter[color][pos])
-#define        IS_BLINKING(priv, pos, color)   (LED_COUNTER(priv, pos, color) > 0)
-#define        MARK_BLINK(priv, pos, color, t) \
-               ((priv)->led_counter[color][pos] = (t))
-#define        MARK_OFF(priv, pos, color) \
-       do { \
-               BIT_CLR((priv)->ledcontrol[color], (pos)); \
-               MARK_BLINK((priv), (pos), (color), 0); \
-       } while (0)
-#define        MARK_ON(priv, pos, color) \
-       do { \
-               BIT_SET((priv)->ledcontrol[color], (pos)); \
-               MARK_BLINK((priv), (pos), (color), 0); \
-       } while (0)
-
-#define        LED_BLINK_RING                  (1000/8)        /* in ticks */
-
-/*---------------- FXS: Static functions ----------------------------------*/
-static int set_vm_led_mode(xbus_t *xbus, xpd_t *xpd, int pos,
-                          unsigned int msg_waiting);
-
-static int do_chan_power(xbus_t *xbus, xpd_t *xpd, lineno_t chan, bool on)
-{
-       struct FXS_priv_data *priv;
-       unsigned long *p;
-       int was;
-
-       BUG_ON(!xbus);
-       BUG_ON(!xpd);
-       if (XPD_HW(xpd).type == 6) {
-               LINE_DBG(SIGNAL, xpd, chan, "is ignored in Si32260\n");
-               return 0;
-       }
-       priv = xpd->priv;
-       p = (unsigned long *)&priv->vbat_h;
-       if (on)
-               was = test_and_set_bit(chan, p) != 0;
-       else
-               was = test_and_clear_bit(chan, p) != 0;
-       if (was == on) {
-               LINE_DBG(SIGNAL, xpd, chan,
-                       "%s (same, ignored)\n", (on) ? "up" : "down");
-               return 0;
-       }
-       LINE_DBG(SIGNAL, xpd, chan, "%s\n", (on) ? "up" : "down");
-       return SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, REG_TYPE1_BATTERY,
-                       (on) ? (int)REG_TYPE1_BATTERY_BATSL : 0x00);
-}
-
-static int linefeed_control(xbus_t *xbus, xpd_t *xpd, lineno_t chan,
-                           enum fxs_state value)
-{
-       struct FXS_priv_data *priv;
-       bool want_vbat_h;
-
-       priv = xpd->priv;
-       /*
-        * Should we drop vbat_h only during actuall ring?
-        *   - It would lower the noise caused to other channels by
-        *     group ringing
-        *   - But it may also stop CallerID from passing through the SLIC
-        */
-       want_vbat_h = value == FXS_LINE_RING;
-       if (lower_ringing_noise || want_vbat_h)
-               do_chan_power(xbus, xpd, chan, want_vbat_h);
-       LINE_DBG(SIGNAL, xpd, chan, "value=0x%02X\n", value);
-       priv->lasttxhook[chan] = value;
-       if (XPD_HW(xpd).type == 6) {
-               int ret;
-
-               /* Make sure NEON state is off for */
-               if (value == FXS_LINE_POL_OHTRANS && IS_SET(priv->neon_blinking, chan))
-                       set_vm_led_mode(xpd->xbus, xpd, chan, 0);
-               ret = SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, REG_TYPE6_LINEFEED, value);
-               if (value == FXS_LINE_POL_ACTIVE && PHONEDEV(xpd).msg_waiting[chan])
-                       set_vm_led_mode(xpd->xbus, xpd, chan, PHONEDEV(xpd).msg_waiting[chan]);
-               return ret;
-       } else {
-               return SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, 0x40, value);
-       }
-       return 0;
-}
-
-static void vmwi_search(xpd_t *xpd, lineno_t pos, bool on)
-{
-       struct FXS_priv_data *priv;
-
-       priv = xpd->priv;
-       BUG_ON(!xpd);
-       if (VMWI_NEON(priv, pos) && on) {
-               LINE_DBG(SIGNAL, xpd, pos, "START\n");
-               BIT_SET(priv->search_fsk_pattern, pos);
-       } else {
-               LINE_DBG(SIGNAL, xpd, pos, "STOP\n");
-               BIT_CLR(priv->search_fsk_pattern, 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. This is not valid anymore since 8-Jan-2007.
- */
-static int do_led(xpd_t *xpd, lineno_t chan, __u8 which, bool on)
-{
-       int ret = 0;
-       struct FXS_priv_data *priv;
-       int value;
-       xbus_t *xbus;
-
-       BUG_ON(!xpd);
-       BUG_ON(chan == ALL_LINES);
-       xbus = xpd->xbus;
-       priv = xpd->priv;
-       which = which % NUM_LEDS;
-       if (IS_SET(PHONEDEV(xpd).digital_outputs, chan)
-           || IS_SET(PHONEDEV(xpd).digital_inputs, chan))
-               goto out;
-       if (chan == PORT_BROADCAST) {
-               priv->ledstate[which] = (on) ? ~0 : 0;
-       } else {
-               if (on)
-                       BIT_SET(priv->ledstate[which], chan);
-               else
-                       BIT_CLR(priv->ledstate[which], chan);
-       }
-       LINE_DBG(LEDS, xpd, chan, "LED: (type=%d) which=%d -- %s\n", XPD_HW(xpd).type, which,
-                (on) ? "on" : "off");
-       if (XPD_HW(xpd).type == 6) {
-               int mask = 1 << chan;
-               value = (on) << chan;
-               XPD_DBG(LEDS, xpd, "LED(%d): 0x%0X (mask: 0x%0X)\n", chan,
-                               value, mask);
-               if (which == LED_GREEN) { /* other leds ignored */
-                       ret = EXP_REQUEST(xbus, xpd, SLIC_WRITE,
-                               REG_TYPE6_EXP_GPIOA, value, mask);
-               }
-       } else {
-               value = BIT(2) | BIT(3);
-               value |= ((BIT(5) | BIT(6) | BIT(7)) & ~led_register_mask[which]);
-               if (on)
-                       value |= led_register_vals[which];
-               ret = SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE,
-                               REG_TYPE1_DIGITAL_IOCTRL, value);
-       }
-       return 0;
-out:
-       return ret;
-}
-
-static inline void set_mwi_led(xpd_t *xpd, int pos, int on)
-{
-       struct FXS_priv_data *priv;
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-
-       if (XPD_HW(xpd).type != 6)
-               return;
-       if (on) {
-               if (! IS_SET(priv->neonstate, pos)) {
-                       SLIC_DIRECT_REQUEST(xpd->xbus, xpd, pos, SLIC_WRITE, REG_TYPE6_ENHANCE, 0x00);
-                       SLIC_DIRECT_REQUEST(xpd->xbus, xpd, pos, SLIC_WRITE, REG_TYPE6_USERSTAT, 0x04);
-                       SLIC_DIRECT_REQUEST(xpd->xbus, xpd, pos, SLIC_WRITE, REG_TYPE6_DIAG1, 0x0F);
-                       BIT_SET(priv->neonstate, pos);
-               }
-       } else {
-               if (IS_SET(priv->neonstate, pos)) {
-                       SLIC_DIRECT_REQUEST(xpd->xbus, xpd, pos, SLIC_WRITE, REG_TYPE6_DIAG1, 0x00);
-                       BIT_CLR(priv->neonstate, pos);
-               }
-       }
-}
-
-static void blink_mwi(xpd_t *xpd)
-{
-       struct FXS_priv_data *priv;
-       unsigned int timer_count;
-       int i;
-
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-       timer_count = xpd->timer_count;
-       for_each_line(xpd, i) {
-               unsigned int msgs = PHONEDEV(xpd).msg_waiting[i];
-               /* LED duty cycle: 300ms on, 700ms off */
-               unsigned int in_range = (timer_count % 1000) >= 0 && (timer_count % 1000) <= 300;
-
-               if (!IS_OFFHOOK(xpd, i) && msgs && in_range && 
-                       IS_SET(priv->neon_blinking,i) && priv->ohttimer[i] == 0)
-                       set_mwi_led(xpd, i, 1);
-               else
-                       set_mwi_led(xpd, i, 0);
-       }
-}
-
-static void handle_fxs_leds(xpd_t *xpd)
-{
-       int i;
-       const enum fxs_leds colors[] = { LED_GREEN, LED_RED };
-       enum fxs_leds color;
-       unsigned int timer_count;
-       struct FXS_priv_data *priv;
-
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-       timer_count = xpd->timer_count;
-       for (color = 0; color < ARRAY_SIZE(colors); color++) {
-               for_each_line(xpd, i) {
-                       if (IS_SET
-                           (PHONEDEV(xpd).digital_outputs | PHONEDEV(xpd).
-                            digital_inputs, i))
-                               continue;
-                       /* Blinking? */
-                       if ((xpd->blink_mode & BIT(i)) || IS_BLINKING(priv, i, color)) {
-                               int mod_value = LED_COUNTER(priv, i, color);
-
-                               if (!mod_value)
-                                       /* safety value */
-                                       mod_value = DEFAULT_LED_PERIOD;
-                               /* led state is toggled */
-                               if ((timer_count % mod_value) == 0) {
-                                       LINE_DBG(LEDS, xpd, i, "ledstate=%s\n",
-                                                (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] & ~priv->
-                                ledstate[color], i)) {
-                               do_led(xpd, i, color, 1);
-                       } else
-                           if (IS_SET
-                               (~priv->ledcontrol[color] & priv->
-                                ledstate[color], i)) {
-                               do_led(xpd, i, color, 0);
-                       }
-
-               }
-       }
-}
-
-static void restore_leds(xpd_t *xpd)
-{
-       struct FXS_priv_data *priv;
-       int i;
-
-       priv = xpd->priv;
-       for_each_line(xpd, i) {
-               if (IS_OFFHOOK(xpd, i))
-                       MARK_ON(priv, i, LED_GREEN);
-               else
-                       MARK_OFF(priv, i, LED_GREEN);
-       }
-}
-
-#ifdef WITH_METERING
-static int metering_gen(xpd_t *xpd, lineno_t chan, bool on)
-{
-       __u8 value = (on) ? 0x94 : 0x00;
-
-       if (XPD_HW(xpd).type == 6) {
-               XBUS_NOTICE("Metering not supported with FXS type 6");
-               return 0;
-       }
-       LINE_DBG(SIGNAL, xpd, chan, "METERING Generate: %s\n",
-                (on) ? "ON" : "OFF");
-       return SLIC_DIRECT_REQUEST(xpd->xbus, xpd, chan, SLIC_WRITE, 0x23,
-                                  value);
-}
-#endif
-
-/*---------------- FXS: Methods -------------------------------------------*/
-
-static void fxs_proc_remove(xbus_t *xbus, xpd_t *xpd)
-{
-       struct FXS_priv_data *priv;
-
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-#ifdef CONFIG_PROC_FS
-#ifdef WITH_METERING
-       if (priv->meteringfile) {
-               XPD_DBG(PROC, xpd, "Removing xpd metering tone file\n");
-               remove_proc_entry(PROC_METERING_FNAME, xpd->proc_xpd_dir);
-               priv->meteringfile = NULL;
-       }
-#endif
-       if (priv->fxs_info) {
-               XPD_DBG(PROC, xpd, "Removing xpd FXS_INFO file\n");
-               remove_proc_entry(PROC_FXS_INFO_FNAME, xpd->proc_xpd_dir);
-               priv->fxs_info = NULL;
-       }
-#endif
-}
-
-static int fxs_proc_create(xbus_t *xbus, xpd_t *xpd)
-{
-       struct FXS_priv_data *priv;
-
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-
-#ifdef CONFIG_PROC_FS
-       XPD_DBG(PROC, xpd, "Creating FXS_INFO file\n");
-       priv->fxs_info = proc_create_data(PROC_FXS_INFO_FNAME, 0444,
-                                         xpd->proc_xpd_dir,
-                                         &proc_fxs_info_ops, xpd);
-       if (!priv->fxs_info) {
-               XPD_ERR(xpd, "Failed to create proc file '%s'\n",
-                       PROC_FXS_INFO_FNAME);
-               fxs_proc_remove(xbus, xpd);
-               return -EINVAL;
-       }
-       SET_PROC_DIRENTRY_OWNER(priv->fxs_info);
-#ifdef WITH_METERING
-       XPD_DBG(PROC, xpd, "Creating Metering tone file\n");
-       priv->meteringfile = proc_create_data(PROC_METERING_FNAME, 0200,
-                                             xpd->proc_xpd_dir,
-                                             &proc_xpd_metering_ops, xpd);
-       if (!priv->meteringfile) {
-               XPD_ERR(xpd, "Failed to create proc file '%s'\n",
-                       PROC_METERING_FNAME);
-               fxs_proc_remove(xbus, xpd);
-               return -EINVAL;
-       }
-#endif
-#endif
-       return 0;
-}
-
-static xpd_t *FXS_card_new(xbus_t *xbus, int unit, int subunit,
-                          const xproto_table_t *proto_table,
-                          const struct unit_descriptor *unit_descriptor,
-                          bool to_phone)
-{
-       xpd_t *xpd = NULL;
-       int channels;
-       int subunit_ports;
-       int regular_channels;
-       struct FXS_priv_data *priv;
-       int i;
-       int d_inputs = 0;
-       int d_outputs = 0;
-
-       if (!to_phone) {
-               XBUS_NOTICE(xbus,
-                           "XPD=%d%d: try to instanciate FXS with reverse direction\n",
-                           unit, subunit);
-               return NULL;
-       }
-       subunit_ports = unit_descriptor->numchips * unit_descriptor->ports_per_chip;
-       if (unit_descriptor->subtype == 2)
-               regular_channels = min(6, subunit_ports);
-       else
-               regular_channels = min(8, subunit_ports);
-       channels = regular_channels;
-       /* Calculate digital inputs/outputs */
-       if (unit == 0 && unit_descriptor->subtype != 4 && unit_descriptor->numchips != 4) {
-               channels += 6;  /* 2 DIGITAL OUTPUTS, 4 DIGITAL INPUTS */
-               d_inputs = LINES_DIGI_INP;
-               d_outputs = LINES_DIGI_OUT;
-       }
-       xpd =
-           xpd_alloc(xbus, unit, subunit,
-                     sizeof(struct FXS_priv_data), proto_table, unit_descriptor, channels);
-       if (!xpd)
-               return NULL;
-       /* Initialize digital inputs/outputs */
-       if (d_inputs) {
-               XBUS_DBG(GENERAL, xbus, "Initialize %d digital inputs\n",
-                        d_inputs);
-               PHONEDEV(xpd).digital_inputs =
-                   BITMASK(d_inputs) << (regular_channels + d_outputs);
-       } else
-               XBUS_DBG(GENERAL, xbus, "No digital inputs\n");
-       if (d_outputs) {
-               XBUS_DBG(GENERAL, xbus, "Initialize %d digital outputs\n",
-                        d_outputs);
-               PHONEDEV(xpd).digital_outputs =
-                   BITMASK(d_outputs) << regular_channels;
-       } else
-               XBUS_DBG(GENERAL, xbus, "No digital outputs\n");
-       PHONEDEV(xpd).direction = TO_PHONE;
-       xpd->type_name = "FXS";
-       if (fxs_proc_create(xbus, xpd) < 0)
-               goto err;
-       priv = xpd->priv;
-       for_each_line(xpd, i) {
-               priv->idletxhookstate[i] = FXS_LINE_POL_ACTIVE;
-       }
-       return xpd;
-err:
-       xpd_free(xpd);
-       return NULL;
-}
-
-static int FXS_card_init(xbus_t *xbus, xpd_t *xpd)
-{
-       struct FXS_priv_data *priv;
-       int ret = 0;
-       int i;
-
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-       /*
-        * Setup ring timers
-        */
-       /* Software controled ringing (for CID) */
-       /* Ringing Oscilator Control */
-       if (XPD_HW(xpd).type == 6) {
-               ret = SLIC_DIRECT_REQUEST(xbus, xpd, PORT_BROADCAST, SLIC_WRITE,
-                       REG_TYPE6_RINGCON, 0x00);
-       } else {
-               ret = SLIC_DIRECT_REQUEST(xbus, xpd, PORT_BROADCAST, SLIC_WRITE,
-                       REG_TYPE1_RINGCON, 0x00);
-       }
-       if (ret < 0)
-               goto err;
-       for_each_line(xpd, i) {
-               if (XPD_HW(xpd).type == 6)
-                       /* An arbitrary value that is not FXS_LINE_OPEN */
-                       priv->polledhook[i] = FXS_LINE_ACTIVE;
-               linefeed_control(xbus, xpd, i, FXS_LINE_POL_ACTIVE);
-       }
-       XPD_DBG(GENERAL, xpd, "done\n");
-       for_each_line(xpd, i) {
-               do_led(xpd, i, LED_GREEN, 0);
-               do_led(xpd, i, LED_RED, 0);
-       }
-       for_each_line(xpd, i) {
-               do_led(xpd, i, LED_GREEN, 1);
-               msleep(50);
-       }
-       for_each_line(xpd, i) {
-               do_led(xpd, i, LED_GREEN, 0);
-               msleep(50);
-       }
-       restore_leds(xpd);
-       CALL_PHONE_METHOD(card_pcm_recompute, xpd, 0);
-       /*
-        * We should query our offhook state long enough time after we
-        * set the linefeed_control()
-        * So we do this after the LEDs
-        */
-       for_each_line(xpd, i) {
-               if (IS_SET
-                   (PHONEDEV(xpd).digital_outputs | PHONEDEV(xpd).
-                    digital_inputs, i))
-                       continue;
-               if (XPD_HW(xpd).type == 6) {
-                       SLIC_DIRECT_REQUEST(xbus, xpd, i, SLIC_READ, REG_TYPE6_LCRRTP,
-                                           0);
-               } else {
-                       SLIC_DIRECT_REQUEST(xbus, xpd, i, SLIC_READ, REG_TYPE1_LOOPCLOSURE,
-                                           0);
-               }
-       }
-       return 0;
-err:
-       fxs_proc_remove(xbus, xpd);
-       XPD_ERR(xpd, "Failed initializing registers (%d)\n", ret);
-       return ret;
-}
-
-static int FXS_card_remove(xbus_t *xbus, xpd_t *xpd)
-{
-       BUG_ON(!xpd);
-       XPD_DBG(GENERAL, xpd, "\n");
-       fxs_proc_remove(xbus, xpd);
-       return 0;
-}
-
-static int FXS_card_dahdi_preregistration(xpd_t *xpd, bool on)
-{
-       xbus_t *xbus;
-       struct FXS_priv_data *priv;
-       int i;
-
-       BUG_ON(!xpd);
-       xbus = xpd->xbus;
-       BUG_ON(!xbus);
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       XPD_DBG(GENERAL, xpd, "%s\n", (on) ? "on" : "off");
-       PHONEDEV(xpd).span.spantype = SPANTYPE_ANALOG_FXS;
-       for_each_line(xpd, i) {
-               struct dahdi_chan *cur_chan = XPD_CHAN(xpd, i);
-
-               XPD_DBG(GENERAL, xpd, "setting FXS channel %d\n", i);
-               if (IS_SET(PHONEDEV(xpd).digital_outputs, i)) {
-                       snprintf(cur_chan->name, MAX_CHANNAME,
-                                "XPP_OUT/%02d/%1d%1d/%d", xbus->num,
-                                xpd->addr.unit, xpd->addr.subunit, i);
-               } else if (IS_SET(PHONEDEV(xpd).digital_inputs, i)) {
-                       snprintf(cur_chan->name, MAX_CHANNAME,
-                                "XPP_IN/%02d/%1d%1d/%d", xbus->num,
-                                xpd->addr.unit, xpd->addr.subunit, i);
-               } else {
-                       snprintf(cur_chan->name, MAX_CHANNAME,
-                                "XPP_FXS/%02d/%1d%1d/%d", xbus->num,
-                                xpd->addr.unit, xpd->addr.subunit, i);
-               }
-               cur_chan->chanpos = i + 1;
-               cur_chan->pvt = xpd;
-               cur_chan->sigcap = FXS_DEFAULT_SIGCAP;
-               if (!vmwi_ioctl) {
-                       /* Old asterisk, assume default VMWI type */
-                       priv->vmwisetting[i].vmwi_type = DAHDI_VMWI_HVAC;
-               }
-       }
-       for_each_line(xpd, i) {
-               MARK_ON(priv, i, LED_GREEN);
-               msleep(4);
-               MARK_ON(priv, i, LED_RED);
-       }
-       return 0;
-}
-
-static int FXS_card_dahdi_postregistration(xpd_t *xpd, bool on)
-{
-       xbus_t *xbus;
-       struct FXS_priv_data *priv;
-       int i;
-
-       BUG_ON(!xpd);
-       xbus = xpd->xbus;
-       BUG_ON(!xbus);
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       XPD_DBG(GENERAL, xpd, "%s\n", (on) ? "on" : "off");
-       for_each_line(xpd, i) {
-               MARK_OFF(priv, i, LED_GREEN);
-               msleep(2);
-               MARK_OFF(priv, i, LED_RED);
-               msleep(2);
-       }
-       restore_leds(xpd);
-       return 0;
-}
-
-/*
- * Called with XPD spinlocked
- */
-static void __do_mute_dtmf(xpd_t *xpd, int pos, bool muteit)
-{
-       struct FXS_priv_data *priv;
-
-       priv = xpd->priv;
-       LINE_DBG(SIGNAL, xpd, pos, "%s\n", (muteit) ? "MUTE" : "UNMUTE");
-       if (muteit)
-               BIT_SET(PHONEDEV(xpd).mute_dtmf, pos);
-       else
-               BIT_CLR(PHONEDEV(xpd).mute_dtmf, pos);
-       /* already spinlocked */
-       CALL_PHONE_METHOD(card_pcm_recompute, xpd, priv->search_fsk_pattern);
-}
-
-struct ring_reg_param {
-       int is_indirect;
-       int regno;
-       uint8_t h_val;
-       uint8_t l_val;
-};
-
-enum ring_types {
-       RING_TYPE_NEON = 0,
-       RING_TYPE_TRAPEZ,
-       RING_TYPE_NORMAL,
-};
-
-struct byte_pair {
-       uint8_t h_val;
-       uint8_t l_val;
-};
-
-struct ring_reg_params {
-       const int is_indirect;
-       const int regno;
-       struct byte_pair values[1 + RING_TYPE_NORMAL - RING_TYPE_NEON];
-};
-
-#define        REG_ENTRY(di, reg, vh1, vl1, vh2, vl2, vh3, vl3) \
-       { (di), (reg), .values = { \
-               [RING_TYPE_NEON]        = { .h_val = (vh1), .l_val = (vl1) }, \
-               [RING_TYPE_TRAPEZ]      = { .h_val = (vh2), .l_val = (vl2) }, \
-               [RING_TYPE_NORMAL]      = { .h_val = (vh3), .l_val = (vl3) }, \
-               }, \
-       }
-
-static struct ring_reg_params ring_parameters[] = {
-       /*        INDIR REG     NEON            TRAPEZ          NORMAL */
-       REG_ENTRY(1,    0x16,   0xE8, 0x03,     0xC8, 0x00,     0x00, 0x00),
-       REG_ENTRY(1,    0x15,   0xEF, 0x7B,     0xAB, 0x5E,     0x77, 0x01),
-       REG_ENTRY(1,    0x14,   0x9F, 0x00,     0x8C, 0x01,     0xFD, 0x7E),
-
-       REG_ENTRY(0,    0x22,   0x00, 0x19,     0x00, 0x01,     0x00, 0x00),
-
-       REG_ENTRY(0,    0x30,   0x00, 0xE0,     0x00, 0x00,     0x00, 0x00),
-       REG_ENTRY(0,    0x31,   0x00, 0x01,     0x00, 0x00,     0x00, 0x00),
-       REG_ENTRY(0,    0x32,   0x00, 0xF0,     0x00, 0x00,     0x00, 0x00),
-       REG_ENTRY(0,    0x33,   0x00, 0x05,     0x00, 0x00,     0x00, 0x00),
-
-       REG_ENTRY(1,    0x1D,   0x00, 0x46,     0x00, 0x36,     0x00, 0x36),
-};
-
-static void set_neon_state(xbus_t *xbus, xpd_t *xpd, int pos,
-               enum neon_state ns)
-{
-       struct FXS_priv_data *priv;
-
-       LINE_DBG(SIGNAL, xpd, pos, "set NEON -> %d\n", ns);
-       priv = xpd->priv;
-       if (ns == INIT_NEON)
-               BIT_SET(priv->neon_blinking, pos);
-       else
-               BIT_CLR(priv->neon_blinking, pos);
-       if (XPD_HW(xpd).type == 6) {
-               switch (ns) {
-               case INIT_NEON:
-                       RAM_REQUEST(xbus, xpd, pos, SLIC_WRITE, RAM_TYPE6_VBATH_EXPECT, VBATH_EXPECT_MWI << 3);
-                       //RAM_REQUEST(xbus, xpd, pos, SLIC_WRITE, RAM_TYPE6_SLOPE_VLIM, SLOPE_VLIM_MWI << 3);
-                       break;
-               default:
-                       LINE_DBG(REGS, xpd, pos, "0x%04X: R 0x\n", RAM_TYPE6_SLOPE_VLIM);
-                       set_mwi_led(xpd, pos, 0);       /* Cannot have NEON LED during OHT (type == 6) */
-                       SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, REG_TYPE6_USERSTAT, 0x00);
-                       SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, REG_TYPE6_ENHANCE, 0x10);
-                       RAM_REQUEST(xbus, xpd, pos, SLIC_WRITE, RAM_TYPE6_VBATH_EXPECT, VBATH_EXPECT_DFLT << 3);
-                       RAM_REQUEST(xbus, xpd, pos, SLIC_WRITE, RAM_TYPE6_SLOPE_VLIM, SLOPE_VLIM_DFLT << 3);
-                       break;
-               }
-       }
-}
-static int send_ring_parameters(xbus_t *xbus, xpd_t *xpd, int pos,
-               enum ring_types rtype)
-{
-       const struct ring_reg_params *p;
-       const struct byte_pair *v;
-       int ret = 0;
-       int i;
-
-       if (XPD_HW(xpd).type == 6)
-               return 0;
-       if (rtype < RING_TYPE_NEON || rtype > RING_TYPE_NORMAL)
-               return -EINVAL;
-       for (i = 0; i < ARRAY_SIZE(ring_parameters); i++) {
-               p = &ring_parameters[i];
-               v = &(p->values[rtype]);
-               if (p->is_indirect) {
-                       LINE_DBG(REGS, xpd, pos,
-                                       "[%d] 0x%02X: I 0x%02X 0x%02X\n",
-                                       i, p->regno, v->h_val, v->l_val);
-                       ret = SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
-                               p->regno, v->h_val, v->l_val);
-                       if (ret < 0) {
-                               LINE_ERR(xpd, pos,
-                                       "Failed: 0x%02X: I 0x%02X, 0x%02X\n",
-                                       p->regno, v->h_val, v->l_val);
-                               break;
-                       }
-               } else {
-                       LINE_DBG(REGS, xpd, pos, "[%d] 0x%02X: D 0x%02X\n",
-                               i, p->regno, v->l_val);
-                       ret = SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
-                               p->regno, v->l_val);
-                       if (ret < 0) {
-                               LINE_ERR(xpd, pos,
-                                       "Failed: 0x%02X: D 0x%02X\n",
-                                       p->regno, v->l_val);
-                               break;
-                       }
-               }
-       }
-       return ret;
-}
-
-static int set_vm_led_mode(xbus_t *xbus, xpd_t *xpd, int pos,
-                          unsigned int msg_waiting)
-{
-       int ret = 0;
-       struct FXS_priv_data *priv;
-       BUG_ON(!xbus);
-       BUG_ON(!xpd);
-
-       priv = xpd->priv;
-       if (VMWI_NEON(priv, pos) && msg_waiting) {
-               /* A write to register 0x40 will now turn on/off the VM led */
-               LINE_DBG(SIGNAL, xpd, pos, "NEON\n");
-               set_neon_state(xbus, xpd, pos, INIT_NEON);
-               ret = send_ring_parameters(xbus, xpd, pos, RING_TYPE_NEON);
-       } else if (ring_trapez) {
-               LINE_DBG(SIGNAL, xpd, pos, "RINGER: Trapez ring\n");
-               set_neon_state(xbus, xpd, pos, END_NEON);
-               ret = send_ring_parameters(xbus, xpd, pos, RING_TYPE_TRAPEZ);
-       } else {
-               /* A write to register 0x40 will now turn on/off the ringer */
-               LINE_DBG(SIGNAL, xpd, pos, "RINGER\n");
-               set_neon_state(xbus, xpd, pos, END_NEON);
-               ret = send_ring_parameters(xbus, xpd, pos, RING_TYPE_NORMAL);
-       }
-       return (ret ? -EPROTO : 0);
-}
-
-static void start_stop_vm_led(xbus_t *xbus, xpd_t *xpd, lineno_t pos)
-{
-       struct FXS_priv_data *priv;
-       unsigned int msgs;
-
-       BUG_ON(!xpd);
-       if (IS_SET
-           (PHONEDEV(xpd).digital_outputs | PHONEDEV(xpd).digital_inputs, pos))
-               return;
-       priv = xpd->priv;
-       msgs = PHONEDEV(xpd).msg_waiting[pos];
-       LINE_DBG(SIGNAL, xpd, pos, "%s\n", (msgs) ? "ON" : "OFF");
-       set_vm_led_mode(xbus, xpd, pos, msgs);
-       if (XPD_HW(xpd).type == 1) {
-               do_chan_power(xbus, xpd, pos, msgs > 0);
-               linefeed_control(xbus, xpd, pos,
-                       (msgs > 0) ? FXS_LINE_RING : priv->idletxhookstate[pos]);
-       }
-}
-
-static int relay_out(xpd_t *xpd, int pos, bool on)
-{
-       int ret = 0;
-       int value = 0;
-       int which = pos;
-
-       BUG_ON(!xpd);
-       /* map logical position to output port number (0/1) */
-       which -= (XPD_HW(xpd).subtype == 2) ? 6 : 8;
-       LINE_DBG(SIGNAL, xpd, pos, "which=%d -- %s\n", which,
-                (on) ? "on" : "off");
-       if (XPD_HW(xpd).type == 6) {
-               int relay_values_type6[] = { 0x01, 0x40 };
-               which = which % ARRAY_SIZE(relay_values_type6);
-               if (on)
-                       value |= relay_values_type6[which];
-               ret = EXP_REQUEST(xpd->xbus, xpd, SLIC_WRITE,
-                       REG_TYPE6_EXP_GPIOB, value, relay_values_type6[which]);
-       } else {
-               int relay_channels_type1[] = { 0, 4 };
-               which = which % ARRAY_SIZE(relay_channels_type1);
-               value = BIT(2) | BIT(3);
-               value |=
-                   ((BIT(5) | BIT(6) | BIT(7)) & ~led_register_mask[OUTPUT_RELAY]);
-               if (on)
-                       value |= led_register_vals[OUTPUT_RELAY];
-               ret = SLIC_DIRECT_REQUEST(xpd->xbus, xpd, relay_channels_type1[which],
-                                  SLIC_WRITE, REG_TYPE1_DIGITAL_IOCTRL, value);
-       }
-       return ret;
-}
-
-static int send_ring(xpd_t *xpd, lineno_t chan, bool on)
-{
-       int ret = 0;
-       xbus_t *xbus;
-       struct FXS_priv_data *priv;
-       enum fxs_state value = (on) ? FXS_LINE_RING : FXS_LINE_POL_ACTIVE;
-
-       BUG_ON(!xpd);
-       xbus = xpd->xbus;
-       BUG_ON(!xbus);
-       LINE_DBG(SIGNAL, xpd, chan, "%s\n", (on) ? "on" : "off");
-       priv = xpd->priv;
-       set_vm_led_mode(xbus, xpd, chan, 0);
-       do_chan_power(xbus, xpd, chan, on);     /* Power up (for ring) */
-       ret = linefeed_control(xbus, xpd, chan, value);
-       if (on) {
-               MARK_BLINK(priv, chan, LED_GREEN, LED_BLINK_RING);
-       } else {
-               if (IS_BLINKING(priv, chan, LED_GREEN))
-                       MARK_BLINK(priv, chan, LED_GREEN, 0);
-       }
-       return ret;
-}
-
-static int FXS_card_hooksig(xpd_t *xpd, int pos, enum dahdi_txsig txsig)
-{
-       struct FXS_priv_data *priv;
-       int ret = 0;
-       struct dahdi_chan *chan = NULL;
-       enum fxs_state txhook;
-       unsigned long flags;
-
-       LINE_DBG(SIGNAL, xpd, pos, "%s\n", txsig2str(txsig));
-       priv = xpd->priv;
-       BUG_ON(PHONEDEV(xpd).direction != TO_PHONE);
-       if (IS_SET(PHONEDEV(xpd).digital_inputs, pos)) {
-               LINE_DBG(SIGNAL, xpd, pos,
-                        "Ignoring signal sent to digital input line\n");
-               return 0;
-       }
-       if (SPAN_REGISTERED(xpd))
-               chan = XPD_CHAN(xpd, pos);
-       switch (txsig) {
-       case DAHDI_TXSIG_ONHOOK:
-               spin_lock_irqsave(&xpd->lock, flags);
-               PHONEDEV(xpd).ringing[pos] = 0;
-               oht_pcm(xpd, pos, 0);
-               vmwi_search(xpd, pos, 0);
-               BIT_CLR(priv->want_dtmf_events, pos);
-               BIT_CLR(priv->want_dtmf_mute, pos);
-               __do_mute_dtmf(xpd, pos, 0);
-               spin_unlock_irqrestore(&xpd->lock, flags);
-               if (IS_SET(PHONEDEV(xpd).digital_outputs, pos)) {
-                       LINE_DBG(SIGNAL, xpd, pos, "%s -> digital output OFF\n",
-                                txsig2str(txsig));
-                       ret = relay_out(xpd, pos, 0);
-                       return ret;
-               }
-               if (priv->lasttxhook[pos] == FXS_LINE_OPEN) {
-                       /*
-                        * Restore state after KEWL hangup.
-                        */
-                       LINE_DBG(SIGNAL, xpd, pos, "KEWL STOP\n");
-                       linefeed_control(xpd->xbus, xpd, pos,
-                                        FXS_LINE_POL_ACTIVE);
-                       if (IS_OFFHOOK(xpd, pos))
-                               MARK_ON(priv, pos, LED_GREEN);
-               }
-               ret = send_ring(xpd, pos, 0);   // RING off
-               if (!IS_OFFHOOK(xpd, pos))
-                       start_stop_vm_led(xpd->xbus, xpd, pos);
-               txhook = priv->lasttxhook[pos];
-               if (chan) {
-                       switch (chan->sig) {
-                       case DAHDI_SIG_EM:
-                       case DAHDI_SIG_FXOKS:
-                       case DAHDI_SIG_FXOLS:
-                               txhook = priv->idletxhookstate[pos];
-                               break;
-                       case DAHDI_SIG_FXOGS:
-                               txhook = FXS_LINE_TIPOPEN;
-                               break;
-                       }
-               }
-               ret = linefeed_control(xpd->xbus, xpd, pos, txhook);
-               break;
-       case DAHDI_TXSIG_OFFHOOK:
-               if (IS_SET(PHONEDEV(xpd).digital_outputs, pos)) {
-                       LINE_NOTICE(xpd, pos,
-                                   "%s -> Is digital output. Ignored\n",
-                                   txsig2str(txsig));
-                       return -EINVAL;
-               }
-               txhook = priv->lasttxhook[pos];
-               if (PHONEDEV(xpd).ringing[pos]) {
-                       oht_pcm(xpd, pos, 1);
-                       txhook = FXS_LINE_OHTRANS;
-               }
-               PHONEDEV(xpd).ringing[pos] = 0;
-               if (chan) {
-                       switch (chan->sig) {
-                       case DAHDI_SIG_EM:
-                               txhook = FXS_LINE_POL_ACTIVE;
-                               break;
-                       default:
-                               txhook = priv->idletxhookstate[pos];
-                               break;
-                       }
-               }
-               ret = linefeed_control(xpd->xbus, xpd, pos, txhook);
-               break;
-       case DAHDI_TXSIG_START:
-               PHONEDEV(xpd).ringing[pos] = 1;
-               oht_pcm(xpd, pos, 0);
-               vmwi_search(xpd, pos, 0);
-               if (IS_SET(PHONEDEV(xpd).digital_outputs, pos)) {
-                       LINE_DBG(SIGNAL, xpd, pos, "%s -> digital output ON\n",
-                                txsig2str(txsig));
-                       ret = relay_out(xpd, pos, 1);
-                       return ret;
-               }
-               ret = send_ring(xpd, pos, 1);   // RING on
-               break;
-       case DAHDI_TXSIG_KEWL:
-               if (IS_SET(PHONEDEV(xpd).digital_outputs, pos)) {
-                       LINE_DBG(SIGNAL, xpd, pos,
-                                "%s -> Is digital output. Ignored\n",
-                                txsig2str(txsig));
-                       return -EINVAL;
-               }
-               linefeed_control(xpd->xbus, xpd, pos, FXS_LINE_OPEN);
-               MARK_OFF(priv, pos, LED_GREEN);
-               break;
-       default:
-               XPD_NOTICE(xpd, "%s: Can't set tx state to %s (%d)\n", __func__,
-                          txsig2str(txsig), txsig);
-               ret = -EINVAL;
-       }
-       return ret;
-}
-
-static int set_vmwi(xpd_t *xpd, int pos, unsigned long arg)
-{
-       struct FXS_priv_data *priv;
-       struct dahdi_vmwi_info vmwisetting;
-       const int vmwi_flags =
-           DAHDI_VMWI_LREV | DAHDI_VMWI_HVDC | DAHDI_VMWI_HVAC;
-
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       if (copy_from_user
-           (&vmwisetting, (__user void *)arg, sizeof(vmwisetting)))
-               return -EFAULT;
-       if ((vmwisetting.vmwi_type & ~vmwi_flags) != 0) {
-               LINE_NOTICE(xpd, pos, "Bad DAHDI_VMWI_CONFIG: 0x%X\n",
-                           vmwisetting.vmwi_type);
-               return -EINVAL;
-       }
-       LINE_DBG(SIGNAL, xpd, pos, "DAHDI_VMWI_CONFIG: 0x%X\n",
-                vmwisetting.vmwi_type);
-       if (VMWI_TYPE(priv, pos, LREV)) {
-               LINE_NOTICE(xpd, pos,
-                           "%s: VMWI(lrev) is not implemented yet. Ignored.\n",
-                           __func__);
-       }
-       if (VMWI_TYPE(priv, pos, HVDC)) {
-               LINE_NOTICE(xpd, pos,
-                           "%s: VMWI(hvdc) is not implemented yet. Ignored.\n",
-                           __func__);
-       }
-       if (VMWI_TYPE(priv, pos, HVAC))
-               ;               /* VMWI_NEON */
-       if (priv->vmwisetting[pos].vmwi_type == 0)
-               ;               /* Disable VMWI */
-       priv->vmwisetting[pos] = vmwisetting;
-       set_vm_led_mode(xpd->xbus, xpd, pos, PHONEDEV(xpd).msg_waiting[pos]);
-       return 0;
-}
-
-static int hardware_dtmf_control(xpd_t *xpd, int pos, bool on)
-{
-       int ret = 0;
-
-       LINE_DBG(SIGNAL, xpd, pos, "%s: %s\n", __func__, (on) ? "on" : "off");
-       if (XPD_HW(xpd).type == 6) {
-               int value = (on) ? 0xE0 : REG_TYPE6_TONEN_DTMF_DIS;
-               ret = SLIC_DIRECT_REQUEST(xpd->xbus, xpd, pos, SLIC_WRITE,
-                       REG_TYPE6_TONEN, value);
-       } else {
-               ret = SLIC_DIRECT_REQUEST(xpd->xbus, xpd, pos, SLIC_WRITE, 0x17, on);
-       }
-       return ret;
-}
-
-/*
- * Private ioctl()
- * We don't need it now, since we detect vmwi via FSK patterns
- */
-static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd,
-                         unsigned long arg)
-{
-       struct FXS_priv_data *priv;
-       xbus_t *xbus;
-       int val;
-       unsigned long flags;
-
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       xbus = xpd->xbus;
-       BUG_ON(!xbus);
-       if (!XBUS_IS(xbus, READY))
-               return -ENODEV;
-       if (pos < 0 || pos >= PHONEDEV(xpd).channels) {
-               XPD_NOTICE(xpd, "Bad channel number %d in %s(), cmd=%u\n", pos,
-                          __func__, cmd);
-               return -EINVAL;
-       }
-
-       switch (cmd) {
-       case DAHDI_ONHOOKTRANSFER:
-               if (get_user(val, (int __user *)arg))
-                       return -EFAULT;
-               LINE_DBG(SIGNAL, xpd, pos, "DAHDI_ONHOOKTRANSFER (%d millis)\n",
-                        val);
-               if (IS_SET
-                   (PHONEDEV(xpd).digital_inputs | PHONEDEV(xpd).
-                    digital_outputs, pos))
-                       return 0;       /* Nothing to do */
-               oht_pcm(xpd, pos, 1);   /* Get ready of VMWI FSK tones */
-               if (priv->lasttxhook[pos] == FXS_LINE_POL_ACTIVE
-                   || IS_SET(priv->neon_blinking, pos)) {
-                       priv->ohttimer[pos] = val;
-                       priv->idletxhookstate[pos] = FXS_LINE_POL_OHTRANS;
-                       vmwi_search(xpd, pos, 1);
-                       CALL_PHONE_METHOD(card_pcm_recompute, xpd,
-                                         priv->search_fsk_pattern);
-                       LINE_DBG(SIGNAL, xpd, pos,
-                                "Start OHT_TIMER. wanted_pcm_mask=0x%X\n",
-                                PHONEDEV(xpd).wanted_pcm_mask);
-               }
-               if (VMWI_NEON(priv, pos) && !IS_OFFHOOK(xpd, pos))
-                       start_stop_vm_led(xbus, xpd, pos);
-               return 0;
-       case DAHDI_TONEDETECT:
-               if (get_user(val, (int __user *)arg))
-                       return -EFAULT;
-               LINE_DBG(SIGNAL, xpd, pos,
-                        "DAHDI_TONEDETECT: %s %s (dtmf_detection=%s)\n",
-                        (val & DAHDI_TONEDETECT_ON) ? "ON" : "OFF",
-                        (val & DAHDI_TONEDETECT_MUTE) ? "MUTE" : "NO-MUTE",
-                        (dtmf_detection ? "YES" : "NO"));
-               if (!dtmf_detection) {
-                       spin_lock_irqsave(&xpd->lock, flags);
-                       if (IS_SET(priv->want_dtmf_events, pos)) {
-                               /*
-                                * Detection mode changed:
-                                * Disable DTMF interrupts
-                                */
-                       }
-                       hardware_dtmf_control(xpd, pos, 0);
-                       BIT_CLR(priv->want_dtmf_events, pos);
-                       BIT_CLR(priv->want_dtmf_mute, pos);
-                       __do_mute_dtmf(xpd, pos, 0);
-                       spin_unlock_irqrestore(&xpd->lock, flags);
-                       return -ENOTTY;
-               }
-               /*
-                * During natively bridged calls, Asterisk
-                * will request one of the sides to stop sending
-                * dtmf events. Check the requested state.
-                */
-               spin_lock_irqsave(&xpd->lock, flags);
-               if (val & DAHDI_TONEDETECT_ON) {
-                       if (!IS_SET(priv->want_dtmf_events, pos)) {
-                               /*
-                                * Detection mode changed:
-                                * Enable DTMF interrupts
-                                */
-                               LINE_DBG(SIGNAL, xpd, pos,
-                                       "DAHDI_TONEDETECT: "
-                                       "Enable Hardware DTMF\n");
-                               hardware_dtmf_control(xpd, pos, 1);
-                       }
-                       BIT_SET(priv->want_dtmf_events, pos);
-               } else {
-                       if (IS_SET(priv->want_dtmf_events, pos)) {
-                               /*
-                                * Detection mode changed:
-                                * Disable DTMF interrupts
-                                */
-                               LINE_DBG(SIGNAL, xpd, pos,
-                                       "DAHDI_TONEDETECT: "
-                                       "Disable Hardware DTMF\n");
-                               hardware_dtmf_control(xpd, pos, 0);
-                       }
-                       BIT_CLR(priv->want_dtmf_events, pos);
-               }
-               if (val & DAHDI_TONEDETECT_MUTE) {
-                       BIT_SET(priv->want_dtmf_mute, pos);
-               } else {
-                       BIT_CLR(priv->want_dtmf_mute, pos);
-                       __do_mute_dtmf(xpd, pos, 0);
-               }
-               spin_unlock_irqrestore(&xpd->lock, flags);
-               return 0;
-       case DAHDI_SETPOLARITY:
-               if (get_user(val, (int __user *)arg))
-                       return -EFAULT;
-               /*
-                * Asterisk may send us this if chan_dahdi config
-                * has "hanguponpolarityswitch=yes" to notify
-                * that the other side has hanged up.
-                *
-                * This has no effect on normal phone (but we may
-                * be connected to another FXO equipment).
-                * note that this chan_dahdi settings has different
-                * meaning for FXO, where it signals polarity
-                * reversal *detection* logic.
-                *
-                * It seems that sometimes we get this from
-                * asterisk in wrong state (e.g: while ringing).
-                * In these cases, silently ignore it.
-                */
-               if (priv->lasttxhook[pos] == FXS_LINE_RING
-                   || priv->lasttxhook[pos] == FXS_LINE_OPEN) {
-                       LINE_DBG(SIGNAL, xpd, pos,
-                               "DAHDI_SETPOLARITY: %s Cannot change "
-                               "when lasttxhook=0x%X\n",
-                               (val) ? "ON" : "OFF", priv->lasttxhook[pos]);
-                       return -EINVAL;
-               }
-               LINE_DBG(SIGNAL, xpd, pos, "DAHDI_SETPOLARITY: %s\n",
-                        (val) ? "ON" : "OFF");
-               if ((val && !reversepolarity) || (!val && reversepolarity))
-                       priv->lasttxhook[pos] |= FXS_LINE_RING;
-               else
-                       priv->lasttxhook[pos] &= ~FXS_LINE_RING;
-               linefeed_control(xbus, xpd, pos, priv->lasttxhook[pos]);
-               return 0;
-       case DAHDI_VMWI_CONFIG:
-               if (set_vmwi(xpd, pos, arg) < 0)
-                       return -EINVAL;
-               return 0;
-       case DAHDI_VMWI:        /* message-waiting led control */
-               if (get_user(val, (int __user *)arg))
-                       return -EFAULT;
-               if (!vmwi_ioctl) {
-                       static bool notified;
-
-                       if (!notified) {
-                               notified = true;
-                               LINE_NOTICE(xpd, pos,
-                                       "Got DAHDI_VMWI notification "
-                                       "but vmwi_ioctl parameter is off. "
-                                       "Ignoring.\n");
-                       }
-                       return 0;
-               }
-               /* Digital inputs/outputs don't have VM leds */
-               if (IS_SET
-                   (PHONEDEV(xpd).digital_inputs | PHONEDEV(xpd).
-                    digital_outputs, pos))
-                       return 0;
-               PHONEDEV(xpd).msg_waiting[pos] = val;
-               LINE_DBG(SIGNAL, xpd, pos, "DAHDI_VMWI: %s\n",
-                        (val) ? "yes" : "no");
-               return 0;
-       default:
-               report_bad_ioctl(THIS_MODULE->name, xpd, pos, cmd);
-       }
-       return -ENOTTY;
-}
-
-static int FXS_card_open(xpd_t *xpd, lineno_t chan)
-{
-       struct FXS_priv_data *priv;
-
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-       if (IS_OFFHOOK(xpd, chan))
-               LINE_NOTICE(xpd, chan, "Already offhook during open. OK.\n");
-       else
-               LINE_DBG(SIGNAL, xpd, chan, "is onhook\n");
-       /*
-        * Delegate updating dahdi to FXS_card_tick():
-        *   The problem is that dahdi_hooksig() is spinlocking the channel and
-        *   we are called by dahdi with the spinlock already held on the
-        *   same channel.
-        */
-       BIT_SET(priv->update_offhook_state, chan);
-       return 0;
-}
-
-static int FXS_card_close(xpd_t *xpd, lineno_t chan)
-{
-       struct FXS_priv_data *priv;
-
-       BUG_ON(!xpd);
-       LINE_DBG(GENERAL, xpd, chan, "\n");
-       priv = xpd->priv;
-       priv->idletxhookstate[chan] = FXS_LINE_POL_ACTIVE;
-       return 0;
-}
-
-#ifdef POLL_DIGITAL_INPUTS
-/*
- * 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_ports_type1[] = {
-       /* slic = input_port */
-       [0]     = -1,
-       [1]     = -1,
-       [2]     = 2,
-       [3]     = 3,
-       [4]     = -1,
-       [5]     = -1,
-       [6]     = 0,
-       [7]     = 1,
-       };
-
-static void poll_inputs(xpd_t *xpd)
-{
-       int i;
-
-       BUG_ON(xpd->xbus_idx != 0);     // Only unit #0 has digital inputs
-       if (XPD_HW(xpd).type == 6) {
-               EXP_REQUEST(xpd->xbus, xpd, SLIC_READ,
-                       REG_TYPE6_EXP_GPIOB, 0, 0);
-       } else {
-               for (i = 0; i < ARRAY_SIZE(input_ports_type1); i++) {
-                       int pos = input_ports_type1[i];
-                       if (pos >= 0) {
-                               SLIC_DIRECT_REQUEST(xpd->xbus, xpd, i, SLIC_READ, 0x06, 0);
-                       }
-               }
-       }
-}
-#endif
-
-static void poll_linefeed(xpd_t *xpd)
-{
-       struct FXS_priv_data *priv;
-       int i;
-
-       if (XPD_HW(xpd).type != 6)
-               return;
-       if (xpd->xpd_state != XPD_STATE_READY)
-               return;
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       BUG_ON(!xpd->xbus);
-
-       XPD_DBG(GENERAL, xpd, "periodic poll");
-       for_each_line(xpd, i) {
-               if (IS_SET(PHONEDEV(xpd).digital_outputs, i)
-                   || IS_SET(PHONEDEV(xpd).digital_inputs, i))
-                       continue;
-               if (priv->polledhook[i] == FXS_LINE_OPEN &&
-                               priv->lasttxhook[i] != FXS_LINE_OPEN) {
-                       LINE_NOTICE(xpd, i, "Overheat detected, resetting.");
-                       priv->overheat_reset_counter[i]++;
-                       linefeed_control(xpd->xbus, xpd, i,
-                                       priv->lasttxhook[i]);
-               }
-               SLIC_DIRECT_REQUEST(xpd->xbus, xpd, i, SLIC_READ,
-                               REG_TYPE6_LINEFEED, 0);
-       }
-}
-
-static void handle_linefeed(xpd_t *xpd)
-{
-       struct FXS_priv_data *priv;
-       int i;
-
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       for_each_line(xpd, i) {
-               if (priv->lasttxhook[i] == FXS_LINE_RING
-                   && !IS_SET(priv->neon_blinking, i)) {
-                       /* RINGing, prepare for OHT */
-                       priv->ohttimer[i] = OHT_TIMER;
-                       priv->idletxhookstate[i] = FXS_LINE_POL_OHTRANS;
-               } else {
-                       if (priv->ohttimer[i]) {
-                               priv->ohttimer[i]--;
-                               if (!priv->ohttimer[i]) {
-                                       LINE_DBG(SIGNAL, xpd, i,
-                                                "ohttimer expired\n");
-                                       priv->idletxhookstate[i] =
-                                           FXS_LINE_POL_ACTIVE;
-                                       oht_pcm(xpd, i, 0);
-                                       vmwi_search(xpd, i, 0);
-                                       if (priv->lasttxhook[i] ==
-                                           FXS_LINE_POL_OHTRANS) {
-                                               /* Apply the change if appropriate */
-                                               linefeed_control(xpd->xbus, xpd,
-                                                                i,
-                                                                FXS_LINE_POL_ACTIVE);
-                                       }
-                               }
-                       }
-               }
-       }
-}
-
-/*
- * Optimized memcmp() like function. Only test for equality (true/false).
- * This optimization reduced the detect_vmwi() runtime by a factor of 3.
- */
-static inline bool mem_equal(const char a[], const char b[], size_t len)
-{
-       int i;
-
-       for (i = 0; i < len; i++)
-               if (a[i] != b[i])
-                       return 0;
-       return 1;
-}
-
-/*
- * Detect Voice Mail Waiting Indication
- */
-static void detect_vmwi(xpd_t *xpd)
-{
-       struct FXS_priv_data *priv;
-       xbus_t *xbus;
-       static const __u8 FSK_COMMON_PATTERN[] =
-           { 0xA8, 0x49, 0x22, 0x3B, 0x9F, 0xFF, 0x1F, 0xBB };
-       static const __u8 FSK_ON_PATTERN[] =
-           { 0xA2, 0x2C, 0x1F, 0x2C, 0xBB, 0xA1, 0xA5, 0xFF };
-       static const __u8 FSK_OFF_PATTERN[] =
-           { 0xA2, 0x2C, 0x28, 0xA5, 0xB1, 0x21, 0x49, 0x9F };
-       int i;
-       xpp_line_t ignore_mask;
-
-       BUG_ON(!xpd);
-       xbus = xpd->xbus;
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       ignore_mask =
-               PHONEDEV(xpd).offhook_state |
-               ~(PHONEDEV(xpd).oht_pcm_pass) |
-               ~(priv->search_fsk_pattern) |
-               PHONEDEV(xpd).digital_inputs |
-               PHONEDEV(xpd).digital_outputs;
-       for_each_line(xpd, i) {
-               struct dahdi_chan *chan = XPD_CHAN(xpd, i);
-               __u8 *writechunk = chan->writechunk;
-
-               if (IS_SET(ignore_mask, i))
-                       continue;
-#if 0
-               if (writechunk[0] != 0x7F && writechunk[0] != 0) {
-                       int j;
-
-                       LINE_DBG(GENERAL, xpd, i, "MSG:");
-                       for (j = 0; j < DAHDI_CHUNKSIZE; j++) {
-                               if (debug)
-                                       printk(" %02X", writechunk[j]);
-                       }
-                       if (debug)
-                               printk("\n");
-               }
-#endif
-               if (unlikely
-                   (mem_equal
-                    (writechunk, FSK_COMMON_PATTERN, DAHDI_CHUNKSIZE))) {
-                       LINE_DBG(SIGNAL, xpd, i,
-                               "Found common FSK pattern. "
-                               "Start looking for ON/OFF patterns.\n");
-                       BIT_SET(priv->found_fsk_pattern, i);
-               } else if (unlikely(IS_SET(priv->found_fsk_pattern, i))) {
-                       BIT_CLR(priv->found_fsk_pattern, i);
-                       oht_pcm(xpd, i, 0);
-                       if (unlikely
-                           (mem_equal
-                            (writechunk, FSK_ON_PATTERN, DAHDI_CHUNKSIZE))) {
-                               LINE_DBG(SIGNAL, xpd, i, "MSG WAITING ON\n");
-                               PHONEDEV(xpd).msg_waiting[i] = 1;
-                               start_stop_vm_led(xbus, xpd, i);
-                       } else
-                           if (unlikely
-                               (mem_equal
-                                (writechunk, FSK_OFF_PATTERN,
-                                 DAHDI_CHUNKSIZE))) {
-                               LINE_DBG(SIGNAL, xpd, i, "MSG WAITING OFF\n");
-                               PHONEDEV(xpd).msg_waiting[i] = 0;
-                               start_stop_vm_led(xbus, xpd, i);
-                       } else {
-                               int j;
-
-                               LINE_NOTICE(xpd, i, "MSG WAITING Unexpected:");
-                               for (j = 0; j < DAHDI_CHUNKSIZE; j++)
-                                       printk(" %02X", writechunk[j]);
-                               printk("\n");
-                       }
-               }
-       }
-}
-
-static int FXS_card_tick(xbus_t *xbus, xpd_t *xpd)
-{
-       struct FXS_priv_data *priv;
-
-       BUG_ON(!xpd);
-       priv = xpd->priv;
-       BUG_ON(!priv);
-#ifdef POLL_DIGITAL_INPUTS
-       if (poll_digital_inputs && PHONEDEV(xpd).digital_inputs) {
-               if ((xpd->timer_count % poll_digital_inputs) == 0)
-                       poll_inputs(xpd);
-       }
-#endif
-       if ((xpd->timer_count % poll_chan_linefeed) == 0)
-               poll_linefeed(xpd);
-       handle_fxs_leds(xpd);
-       handle_linefeed(xpd);
-       if (XPD_HW(xpd).type == 6)
-               blink_mwi(xpd);
-       /*
-        * Hack alert (FIXME):
-        *   Asterisk did FXS_card_open() and we wanted to report
-        *   offhook state. However, the channel is spinlocked by dahdi
-        *   so we marked it in the priv->update_offhook_state mask and
-        *   now we take care of notification to dahdi and Asterisk
-        */
-       if (priv->update_offhook_state) {
-               enum dahdi_rxsig rxsig;
-               int i;
-
-               for_each_line(xpd, i) {
-                       if (!IS_SET(priv->update_offhook_state, i))
-                               continue;
-                       rxsig =
-                           IS_OFFHOOK(xpd,
-                                      i) ? DAHDI_RXSIG_OFFHOOK :
-                           DAHDI_RXSIG_ONHOOK;
-                       /* Notify after open() */
-                       notify_rxsig(xpd, i, rxsig);
-                       BIT_CLR(priv->update_offhook_state, i);
-               }
-       }
-       if (SPAN_REGISTERED(xpd)) {
-               if (!vmwi_ioctl && priv->search_fsk_pattern)
-                       detect_vmwi(xpd);       /* Detect via FSK modulation */
-       }
-       return 0;
-}
-
-/*---------------- FXS: HOST COMMANDS -------------------------------------*/
-
-/*---------------- FXS: Astribank Reply Handlers --------------------------*/
-
-/*
- * Should be called with spinlocked XPD
- */
-static void process_hookstate(xpd_t *xpd, xpp_line_t offhook,
-                             xpp_line_t change_mask)
-{
-       xbus_t *xbus;
-       struct FXS_priv_data *priv;
-       int i;
-
-       BUG_ON(!xpd);
-       BUG_ON(PHONEDEV(xpd).direction != TO_PHONE);
-       xbus = xpd->xbus;
-       priv = xpd->priv;
-       XPD_DBG(SIGNAL, xpd, "offhook=0x%X change_mask=0x%X\n", offhook,
-               change_mask);
-       for_each_line(xpd, i) {
-               if (IS_SET(PHONEDEV(xpd).digital_outputs, i)
-                   || IS_SET(PHONEDEV(xpd).digital_inputs, i))
-                       continue;
-               if (IS_SET(change_mask, i)) {
-                       PHONEDEV(xpd).ringing[i] = 0;   /* No more ringing... */
-#ifdef WITH_METERING
-                       metering_gen(xpd, i, 0);        /* Stop metering... */
-#endif
-                       MARK_BLINK(priv, i, LED_GREEN, 0);
-                       /*
-                        * Reset our previous DTMF memories...
-                        */
-                       BIT_CLR(priv->prev_key_down, i);
-                       priv->prev_key_time[i].tv_sec =
-                           priv->prev_key_time[i].tv_usec = 0L;
-                       if (IS_SET(offhook, i)) {
-                               LINE_DBG(SIGNAL, xpd, i, "OFFHOOK\n");
-                               MARK_ON(priv, i, LED_GREEN);
-                               hookstate_changed(xpd, i, 1);
-                       } else {
-                               LINE_DBG(SIGNAL, xpd, i, "ONHOOK\n");
-                               MARK_OFF(priv, i, LED_GREEN);
-                               hookstate_changed(xpd, i, 0);
-                       }
-                       /*
-                        * Must switch to low power. In high power, an ONHOOK
-                        * won't be detected.
-                        */
-                       do_chan_power(xbus, xpd, i, 0);
-               }
-       }
-}
-
-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);
-       unsigned long flags;
-
-       BUG_ON(!xpd);
-       BUG_ON(PHONEDEV(xpd).direction != TO_PHONE);
-       XPD_DBG(SIGNAL, xpd, "(PHONE) sig_toggles=0x%04X sig_status=0x%04X\n",
-               sig_toggles, sig_status);
-#if 0
-       Is this needed ? for_each_line(xpd, i) {
-               // Power down (prevent overheating!!!)
-               if (IS_SET(sig_toggles, i))
-                       do_chan_power(xpd->xbus, xpd, BIT(i), 0);
-       }
-#endif
-       spin_lock_irqsave(&xpd->lock, flags);
-       process_hookstate(xpd, sig_status, sig_toggles);
-       spin_unlock_irqrestore(&xpd->lock, flags);
-       return 0;
-}
-
-#ifdef POLL_DIGITAL_INPUTS
-static inline void notify_digital_input(xpd_t *xpd, int input_port, int offhook)
-{
-       int channo = PHONEDEV(xpd).channels - LINES_DIGI_INP + input_port;
-
-       /* Stop ringing. No leds for digital inputs. */
-       PHONEDEV(xpd).ringing[channo] = 0;
-       if (offhook && !IS_OFFHOOK(xpd, channo)) {
-               LINE_DBG(SIGNAL, xpd, channo, "OFFHOOK\n");
-               hookstate_changed(xpd, channo, 1);
-       } else if (!offhook && IS_OFFHOOK(xpd, channo)) {
-               LINE_DBG(SIGNAL, xpd, channo, "ONHOOK\n");
-               hookstate_changed(xpd, channo, 0);
-       }
-}
-
-static void process_digital_inputs(xpd_t *xpd, const reg_cmd_t *info)
-{
-       bool offhook;
-       /* Sanity check */
-       if (!PHONEDEV(xpd).digital_inputs) {
-               XPD_NOTICE(xpd, "%s called without digital inputs. Ignored\n",
-                          __func__);
-               return;
-       }
-       if (XPD_HW(xpd).type == 6) {
-               static int input_values_type6[] = { 0x80, 0x20, 0x08, 0x02 };   /* I/O Expander values of input relays */
-               int i;
-
-               /* Map I/O Expander GPIO into line number */
-               for (i = 0; i < ARRAY_SIZE(input_values_type6); i++) {
-                       int chanmask = input_values_type6[i];
-
-                       offhook = (REG_FIELD(info, data_low) & chanmask) == 0;
-                       notify_digital_input(xpd, i, offhook);
-               }
-       } else {
-               int channo = info->h.portnum;
-               int input_port;
-               offhook = (REG_FIELD(info, data_low) & 0x1) == 0;
-               if (channo < 0 || channo >= ARRAY_SIZE(input_ports_type1)) {
-                       XPD_ERR(xpd, "%s: got bad portnum=%d\n", __func__, channo);
-                       return;
-               }
-               input_port = input_ports_type1[channo];
-               if (input_port < 0) {
-                       XPD_ERR(xpd, "%s: portnum=%d is not input port\n", __func__, channo);
-                       return;
-               }
-               notify_digital_input(xpd, input_port, offhook);
-       }
-}
-#endif
-
-static const char dtmf_digits[] = {
-       'D', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '*', '#',
-       'A', 'B', 'C'
-};
-
-/*
- * This function is called with spinlocked XPD
- */
-static void process_dtmf(xpd_t *xpd, uint portnum, __u8 val)
-{
-       __u8 digit;
-       bool key_down = val & 0x10;
-       bool want_mute;
-       bool want_event;
-       struct FXS_priv_data *priv;
-       struct timeval now;
-       int msec = 0;
-
-       if (!dtmf_detection)
-               return;
-       if (!SPAN_REGISTERED(xpd))
-               return;
-       priv = xpd->priv;
-       val &= 0xF;
-       digit = dtmf_digits[val];
-       want_mute = IS_SET(priv->want_dtmf_mute, portnum);
-       want_event = IS_SET(priv->want_dtmf_events, portnum);
-       if (!IS_SET(priv->prev_key_down, portnum) && !key_down)
-               LINE_NOTICE(xpd, portnum, "DTMF: duplicate UP (%c)\n", digit);
-       if (key_down)
-               BIT_SET(priv->prev_key_down, portnum);
-       else
-               BIT_CLR(priv->prev_key_down, portnum);
-       do_gettimeofday(&now);
-       if (priv->prev_key_time[portnum].tv_sec != 0)
-               msec = usec_diff(&now, &priv->prev_key_time[portnum]) / 1000;
-       priv->prev_key_time[portnum] = now;
-       LINE_DBG(SIGNAL, xpd, portnum,
-               "[%lu.%06lu] DTMF digit %-4s '%c' "
-               "(val=%d, want_mute=%s want_event=%s, delta=%d msec)\n",
-               now.tv_sec, now.tv_usec, (key_down) ? "DOWN" : "UP", digit,
-               val, (want_mute) ? "yes" : "no", (want_event) ? "yes" : "no",
-               msec);
-       /*
-        * FIXME: we currently don't use the want_dtmf_mute until
-        * we are sure about the logic in Asterisk native bridging.
-        * Meanwhile, simply mute it on button press.
-        */
-       if (key_down && want_mute)
-               __do_mute_dtmf(xpd, portnum, 1);
-       else
-               __do_mute_dtmf(xpd, portnum, 0);
-       if (want_event) {
-               int event =
-                   (key_down) ? DAHDI_EVENT_DTMFDOWN : DAHDI_EVENT_DTMFUP;
-
-               dahdi_qevent_lock(XPD_CHAN(xpd, portnum), event | digit);
-       }
-}
-
-static int FXS_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
-{
-       unsigned long flags;
-       struct FXS_priv_data *priv;
-       __u8 regnum = 0;
-       bool indirect = 0;
-
-       spin_lock_irqsave(&xpd->lock, flags);
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       if (info->h.bytes == REG_CMD_SIZE(REG)) {
-               if ((XPD_HW(xpd).type == 1) && (REG_FIELD(info, regnum) == 0x1E))
-                       indirect = 1;
-               regnum = (indirect) ? REG_FIELD(info, subreg) : REG_FIELD(info, regnum);
-               XPD_DBG(REGS, xpd, "%s reg_num=0x%X, dataL=0x%X dataH=0x%X\n",
-                       (indirect) ? "I" : "D", regnum, REG_FIELD(info, data_low),
-                       REG_FIELD(info, data_high));
-       }
-       if (info->h.bytes == REG_CMD_SIZE(RAM)) {
-               uint addr;
-               unsigned long val;
-               XPD_DBG(REGS, xpd, "port=%d, addr_low=0x%X, addr_high=0x%X, data_0=0x%X data_1=0x%X data_2=0x%X data_3=0x%X\n",
-                       info->h.portnum,
-                       REG_FIELD_RAM(info, addr_low),
-                       REG_FIELD_RAM(info, addr_high),
-                       REG_FIELD_RAM(info, data_0),
-                       REG_FIELD_RAM(info, data_1),
-                       REG_FIELD_RAM(info, data_2),
-                       REG_FIELD_RAM(info, data_3));
-               addr = (REG_FIELD_RAM(info, addr_high) << 8) | REG_FIELD_RAM(info, addr_low);
-               val = (REG_FIELD_RAM(info, data_3) << 24) |
-                     (REG_FIELD_RAM(info, data_2) << 16) |
-                     (REG_FIELD_RAM(info, data_1) << 8) |
-                      REG_FIELD_RAM(info, data_0);
-       } else if ((XPD_HW(xpd).type == 1 && !indirect && regnum == REG_TYPE1_DTMF_DECODE) ||
-           (XPD_HW(xpd).type == 6 && !indirect && regnum == REG_TYPE6_TONDTMF)) {
-               __u8 val = REG_FIELD(info, data_low);
-
-               process_dtmf(xpd, info->h.portnum, val);
-       } else if ((XPD_HW(xpd).type == 6 && !indirect && regnum == REG_TYPE6_LINEFEED)) {
-               __u8 val = REG_FIELD(info, data_low);
-
-               LINE_DBG(SIGNAL, xpd, info->h.portnum,
-                       "REG_TYPE6_LINEFEED: dataL=0x%X \n", val);
-               priv->polledhook[info->h.portnum] = val;
-       }
-#ifdef POLL_DIGITAL_INPUTS
-       /*
-        * Process digital inputs polling results
-        */
-       else if ( (XPD_HW(xpd).type == 1 && !indirect && regnum == REG_TYPE1_DIGITAL_IOCTRL) ||
-                 (XPD_HW(xpd).type == 6 && !indirect && regnum == REG_TYPE6_EXP_GPIOB && 
-                  REG_FIELD(info, do_expander)))
-               process_digital_inputs(xpd, info);
-#endif
-       else if (XPD_HW(xpd).type == 1 && !indirect && regnum == REG_TYPE1_LOOPCLOSURE) { /* OFFHOOK ? */
-               __u8 val = REG_FIELD(info, data_low);
-               xpp_line_t mask = BIT(info->h.portnum);
-               xpp_line_t offhook;
-
-               /*
-                * Validate reply. Non-existing/disabled ports
-                * will reply with 0xFF. Ignore these.
-                */
-               if ((val & REG_TYPE1_LOOPCLOSURE_ZERO) == 0) {
-                       offhook = (val & REG_TYPE1_LOOPCLOSURE_LCR) ? mask : 0;
-                       LINE_DBG(SIGNAL, xpd, info->h.portnum,
-                               "REG_TYPE1_LOOPCLOSURE: dataL=0x%X "
-                               "(offhook=0x%X mask=0x%X)\n",
-                               val, offhook, mask);
-                       process_hookstate(xpd, offhook, mask);
-               }
-       } else if (XPD_HW(xpd).type == 6 && !indirect && regnum == REG_TYPE6_LCRRTP) { /* OFFHOOK ? */
-               __u8 val = REG_FIELD(info, data_low);
-               xpp_line_t mask = BIT(info->h.portnum);
-               xpp_line_t offhook;
-
-               /*
-                * Validate reply. Non-existing/disabled ports
-                * will reply with 0xFF. Ignore these.
-                */
-               if ((val & REG_TYPE6_LCRRTP_ZERO) == 0) {
-                       offhook = (val & REG_TYPE6_LCRRTP_LCR) ? mask : 0;
-                       LINE_DBG(SIGNAL, xpd, info->h.portnum,
-                               "REG_TYPE6_LCRRTP: dataL=0x%X "
-                               "(offhook=0x%X mask=0x%X)\n",
-                               val, offhook, mask);
-                       process_hookstate(xpd, offhook, mask);
-               }
-       } else {
-#if 0
-               XPD_NOTICE(xpd,
-                       "Spurious register reply(ignored): "
-                       "%s reg_num=0x%X, dataL=0x%X dataH=0x%X\n",
-                       (indirect) ? "I" : "D",
-                       regnum, REG_FIELD(info, data_low),
-                       REG_FIELD(info, data_high));
-#endif
-       }
-       /*
-        * Update /proc info only if reply relate to the last slic
-        * read request
-        */
-       if (REG_FIELD(&xpd->requested_reply, regnum) ==
-                       REG_FIELD(info, regnum)
-               && REG_FIELD(&xpd->requested_reply, do_subreg) ==
-                       REG_FIELD(info, do_subreg)
-               && REG_FIELD(&xpd->requested_reply, subreg) ==
-                       REG_FIELD(info, subreg)) {
-               xpd->last_reply = *info;
-       }
-       spin_unlock_irqrestore(&xpd->lock, flags);
-       return 0;
-}
-
-static int FXS_card_state(xpd_t *xpd, bool on)
-{
-       BUG_ON(!xpd);
-       XPD_DBG(GENERAL, xpd, "%s\n", (on) ? "on" : "off");
-       return 0;
-}
-
-static const struct xops fxs_xops = {
-       .card_new = FXS_card_new,
-       .card_init = FXS_card_init,
-       .card_remove = FXS_card_remove,
-       .card_tick = FXS_card_tick,
-       .card_register_reply = FXS_card_register_reply,
-};
-
-static const struct phoneops fxs_phoneops = {
-       .card_dahdi_preregistration = FXS_card_dahdi_preregistration,
-       .card_dahdi_postregistration = FXS_card_dahdi_postregistration,
-       .card_hooksig = FXS_card_hooksig,
-       .card_pcm_recompute = generic_card_pcm_recompute,
-       .card_pcm_fromspan = generic_card_pcm_fromspan,
-       .card_pcm_tospan = generic_card_pcm_tospan,
-       .card_timing_priority = generic_timing_priority,
-       .echocancel_timeslot = generic_echocancel_timeslot,
-       .echocancel_setmask = generic_echocancel_setmask,
-       .card_open = FXS_card_open,
-       .card_close = FXS_card_close,
-       .card_ioctl = FXS_card_ioctl,
-       .card_state = FXS_card_state,
-};
-
-static xproto_table_t PROTO_TABLE(FXS) = {
-       .owner = THIS_MODULE,
-       .entries = {
-               /*      Prototable      Card    Opcode          */
-               XENTRY( FXS,            FXS,    SIG_CHANGED     ),
-       },
-       .name = "FXS",  /* protocol name */
-       .ports_per_subunit = 8,
-       .type = XPD_TYPE_FXS,
-       .xops = &fxs_xops,
-       .phoneops = &fxs_phoneops,
-       .packet_is_valid = fxs_packet_is_valid,
-       .packet_dump = fxs_packet_dump,
-};
-
-static bool fxs_packet_is_valid(xpacket_t *pack)
-{
-       const xproto_entry_t *xe;
-
-       // DBG(GENERAL, "\n");
-       xe = xproto_card_entry(&PROTO_TABLE(FXS), XPACKET_OP(pack));
-       return xe != NULL;
-}
-
-static void fxs_packet_dump(const char *msg, xpacket_t *pack)
-{
-       DBG(GENERAL, "%s\n", msg);
-}
-
-/*------------------------- SLIC Handling --------------------------*/
-
-#ifdef CONFIG_PROC_FS
-static int proc_fxs_info_show(struct seq_file *sfile, void *not_used)
-{
-       unsigned long flags;
-       xpd_t *xpd = sfile->private;
-       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);
-       seq_printf(sfile, "%-12s", "Channel:");
-       for_each_line(xpd, i) {
-               seq_printf(sfile, "%4d", i);
-       }
-       seq_printf(sfile, "\n%-12s", "");
-       for_each_line(xpd, i) {
-               char *chan_type;
-
-               if (IS_SET(PHONEDEV(xpd).digital_outputs, i))
-                       chan_type = "out";
-               else if (IS_SET(PHONEDEV(xpd).digital_inputs, i))
-                       chan_type = "in";
-               else
-                       chan_type = "";
-               seq_printf(sfile, "%4s", chan_type);
-       }
-       seq_printf(sfile, "\n%-12s", "idletxhook:");
-       for_each_line(xpd, i) {
-               seq_printf(sfile, "%4d", priv->idletxhookstate[i]);
-       }
-       seq_printf(sfile, "\n%-12s", "lasttxhook:");
-       for_each_line(xpd, i) {
-               seq_printf(sfile, "%4d", priv->lasttxhook[i]);
-       }
-       seq_printf(sfile, "\n%-12s", "ohttimer:");
-       for_each_line(xpd, i) {
-               seq_printf(sfile, "%4d", priv->ohttimer[i]);
-       }
-       seq_printf(sfile, "\n%-12s", "neon_blink:");
-       for_each_line(xpd, i) {
-               seq_printf(sfile, "%4d",
-                           IS_SET(priv->neon_blinking, i));
-       }
-       seq_printf(sfile, "\n%-12s", "search_fsk:");
-       for_each_line(xpd, i) {
-               seq_printf(sfile, "%4d",
-                           IS_SET(priv->search_fsk_pattern, i));
-       }
-       seq_printf(sfile, "\n%-12s", "vbat_h:");
-       for_each_line(xpd, i) {
-               seq_printf(sfile, "%4d",
-                       test_bit(i, (unsigned long *)&priv->vbat_h));
-       }
-       seq_printf(sfile, "\n");
-       for (led = 0; led < NUM_LEDS; led++) {
-               seq_printf(sfile, "\nLED #%d\t%-12s: ",
-                       led, "ledstate");
-               for_each_line(xpd, i) {
-                       if (!IS_SET(PHONEDEV(xpd).digital_outputs, i)
-                           && !IS_SET(PHONEDEV(xpd).digital_inputs, i))
-                               seq_printf(sfile, "%d ",
-                                           IS_SET(priv->ledstate[led], i));
-               }
-               seq_printf(sfile, "\nLED #%d\t%-12s: ",
-                       led, "ledcontrol");
-               for_each_line(xpd, i) {
-                       if (!IS_SET(PHONEDEV(xpd).digital_outputs, i)
-                           && !IS_SET(PHONEDEV(xpd).digital_inputs, i))
-                               seq_printf(sfile, "%d ",
-                                           IS_SET(priv->ledcontrol[led], i));
-               }
-               seq_printf(sfile, "\nLED #%d\t%-12s: ",
-                       led, "led_counter");
-               for_each_line(xpd, i) {
-                       if (!IS_SET(PHONEDEV(xpd).digital_outputs, i)
-                           && !IS_SET(PHONEDEV(xpd).digital_inputs, i))
-                               seq_printf(sfile, "%d ",
-                                           LED_COUNTER(priv, i, led));
-               }
-       }
-       seq_printf(sfile, "\n%-12s", "overheats:");
-       for_each_line(xpd, i) {
-               seq_printf(sfile, "%4d", priv->overheat_reset_counter[i]);
-       }
-       seq_printf(sfile, "\n");
-       spin_unlock_irqrestore(&xpd->lock, flags);
-       return 0;
-}
-
-static int proc_fxs_info_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, proc_fxs_info_show, PDE_DATA(inode));
-}
-
-static const struct file_operations proc_fxs_info_ops = {
-       .owner          = THIS_MODULE,
-       .open           = proc_fxs_info_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-};
-
-#ifdef WITH_METERING
-static ssize_t proc_xpd_metering_write(struct file *file,
-               const char __user *buffer, size_t count, loff_t *offset)
-{
-       xpd_t *xpd = file->private_data;
-       char buf[MAX_PROC_WRITE];
-       lineno_t chan;
-       int num;
-       int ret;
-
-       if (!xpd)
-               return -ENODEV;
-       if (count >= MAX_PROC_WRITE - 1) {
-               XPD_ERR(xpd, "Metering string too long (%zu)\n", count);
-               return -EINVAL;
-       }
-       if (copy_from_user(&buf, buffer, count))
-               return -EFAULT;
-       buf[count] = '\0';
-       ret = sscanf(buf, "%d", &num);
-       if (ret != 1) {
-               XPD_ERR(xpd, "Metering value should be number. Got '%s'\n",
-                       buf);
-               return -EINVAL;
-       }
-       chan = num;
-       if (chan != PORT_BROADCAST && chan > xpd->channels) {
-               XPD_ERR(xpd, "Metering tone: bad channel number %d\n", chan);
-               return -EINVAL;
-       }
-       if ((ret = metering_gen(xpd, chan, 1)) < 0) {
-               XPD_ERR(xpd, "Failed sending metering tone\n");
-               return ret;
-       }
-       return count;
-}
-
-static int proc_xpd_metering_open(struct inode *inode, struct file *file)
-{
-       file->private_data = PDE_DATA(inode);
-}
-
-static const struct file_operations proc_xpd_metering_ops = {
-       .owner          = THIS_MODULE,
-       .open           = proc_xpd_metering_open,
-       .write          = proc_xpd_metering_write,
-       .release        = single_release,
-};
-#endif
-#endif
-
-static DEVICE_ATTR_READER(fxs_ring_registers_show, dev, buf)
-{
-       xpd_t *xpd;
-       struct FXS_priv_data *priv;
-       unsigned long flags;
-       const struct ring_reg_params *p;
-       const struct byte_pair *v;
-       enum ring_types rtype;
-       int len = 0;
-       int i;
-
-       BUG_ON(!dev);
-       xpd = dev_to_xpd(dev);
-       if (!xpd)
-               return -ENODEV;
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       spin_lock_irqsave(&xpd->lock, flags);
-       len += sprintf(buf + len, "#   Reg#: D/I\tNEON     \tTRAPEZ   \tNORMAL   \n");
-       for (i = 0; i < ARRAY_SIZE(ring_parameters); i++) {
-               p = &ring_parameters[i];
-               len += sprintf(buf + len, "[%d] 0x%02X: %c",
-                       i, p->regno, (p->is_indirect) ? 'I' : 'D');
-               for (rtype = RING_TYPE_NEON; rtype <= RING_TYPE_NORMAL; rtype++) {
-                       v = &(p->values[rtype]);
-                       if (p->is_indirect)
-                               len += sprintf(buf + len, "\t0x%02X 0x%02X",
-                                       v->h_val, v->l_val);
-                       else
-                               len += sprintf(buf + len, "\t0x%02X ----",
-                                       v->l_val);
-               }
-               len += sprintf(buf + len, "\n");
-       }
-       spin_unlock_irqrestore(&xpd->lock, flags);
-       return len;
-}
-
-static DEVICE_ATTR_WRITER(fxs_ring_registers_store, dev, buf, count)
-{
-       xpd_t *xpd;
-       struct FXS_priv_data *priv;
-       unsigned long flags;
-       char rtype_name[MAX_PROC_WRITE];
-       enum ring_types rtype;
-       struct ring_reg_params *params;
-       struct byte_pair *v;
-       int regno;
-       int h_val;
-       int l_val;
-       int ret;
-       int i;
-
-       BUG_ON(!dev);
-       xpd = dev_to_xpd(dev);
-       if (!xpd)
-               return -ENODEV;
-       priv = xpd->priv;
-       BUG_ON(!priv);
-       ret = sscanf(buf, "%10s %X %X %X\n",
-               rtype_name, &regno, &h_val, &l_val);
-       if (ret < 3 || ret > 4) {
-               XPD_ERR(xpd, "Bad input: '%s'\n", buf);
-               XPD_ERR(xpd, "# Correct input\n");
-               XPD_ERR(xpd, "{NEON|TRAPEZ|NORMAL} <regno> <byte> [<byte>]\n");
-               goto invalid_input;
-       }
-       if (strcasecmp("NEON", rtype_name) == 0)
-               rtype = RING_TYPE_NEON;
-       else if (strcasecmp("TRAPEZ", rtype_name) == 0)
-               rtype = RING_TYPE_TRAPEZ;
-       else if (strcasecmp("NORMAL", rtype_name) == 0)
-               rtype = RING_TYPE_NORMAL;
-       else {
-               XPD_ERR(xpd, "Unknown ring type '%s' (NEON/TRAPEZ/NORMAL)\n",
-                       rtype_name);
-               goto invalid_input;
-       }
-       params = NULL;
-       for (i = 0; i < ARRAY_SIZE(ring_parameters); i++) {
-               if (ring_parameters[i].regno == regno) {
-                       params = &ring_parameters[i];
-                       break;
-               }
-       }
-       if (!params) {
-               XPD_ERR(xpd, "Bad register 0x%X\n", regno);
-               goto invalid_input;
-       }
-       if (params->is_indirect) {
-               if (ret != 4) {
-                       XPD_ERR(xpd,
-                               "Missing low-byte (0x%X is indirect register)\n",
-                               regno);
-                       goto invalid_input;
-               }
-               XPD_DBG(SIGNAL, xpd, "%s Indirect 0x%X <=== 0x%X 0x%X\n",
-                       rtype_name, regno, h_val, l_val);
-       } else {
-               if (ret != 3) {
-                       XPD_ERR(xpd,
-                               "Should give exactly one value (0x%X is direct register)\n",
-                               regno);
-                       goto invalid_input;
-               }
-               l_val = h_val;
-               h_val = 0;
-               XPD_DBG(SIGNAL, xpd, "%s Direct 0x%X <=== 0x%X\n",
-                       rtype_name, regno, h_val);
-       }
-       spin_lock_irqsave(&xpd->lock, flags);
-       v = &(params->values[rtype]);
-       v->h_val = h_val;
-       v->l_val = l_val;
-       spin_unlock_irqrestore(&xpd->lock, flags);
-       return count;
-invalid_input:
-       return -EINVAL;
-}
-
-static DEVICE_ATTR(fxs_ring_registers, S_IRUGO | S_IWUSR,
-       fxs_ring_registers_show,
-       fxs_ring_registers_store);
-
-static int fxs_xpd_probe(struct device *dev)
-{
-       xpd_t *xpd;
-       int ret;
-
-       xpd = dev_to_xpd(dev);
-       /* Is it our device? */
-       if (xpd->xpd_type != XPD_TYPE_FXS) {
-               XPD_ERR(xpd, "drop suggestion for %s (%d)\n", dev_name(dev),
-                       xpd->xpd_type);
-               return -EINVAL;
-       }
-       XPD_DBG(DEVICES, xpd, "SYSFS\n");
-       ret = device_create_file(dev, &dev_attr_fxs_ring_registers);
-       if (ret) {
-               XPD_ERR(xpd, "%s: device_create_file(fxs_ring_registers) failed: %d\n",
-                       __func__, ret);
-               goto fail_fxs_ring_registers;
-       }
-       return 0;
-fail_fxs_ring_registers:
-       return ret;
-}
-
-static int fxs_xpd_remove(struct device *dev)
-{
-       xpd_t *xpd;
-
-       xpd = dev_to_xpd(dev);
-       XPD_DBG(DEVICES, xpd, "SYSFS\n");
-       device_remove_file(dev, &dev_attr_fxs_ring_registers);
-       return 0;
-}
-
-static struct xpd_driver fxs_driver = {
-       .xpd_type = XPD_TYPE_FXS,
-       .driver = {
-                  .name = "fxs",
-                  .owner = THIS_MODULE,
-                  .probe = fxs_xpd_probe,
-                  .remove = fxs_xpd_remove}
-};
-
-static int __init card_fxs_startup(void)
-{
-       int ret;
-
-       if ((ret = xpd_driver_register(&fxs_driver.driver)) < 0)
-               return ret;
-
-#ifdef POLL_DIGITAL_INPUTS
-       INFO("FEATURE: with DIGITAL INPUTS support (polled every %d msec)\n",
-            poll_digital_inputs);
-#else
-       INFO("FEATURE: without DIGITAL INPUTS support\n");
-#endif
-       INFO("FEATURE: DAHDI_VMWI (HVAC only)\n");
-#ifdef WITH_METERING
-       INFO("FEATURE: WITH METERING Generation\n");
-#else
-       INFO("FEATURE: NO METERING Generation\n");
-#endif
-       xproto_register(&PROTO_TABLE(FXS));
-       return 0;
-}
-
-static void __exit card_fxs_cleanup(void)
-{
-       xproto_unregister(&PROTO_TABLE(FXS));
-       xpd_driver_unregister(&fxs_driver.driver);
-}
-
-MODULE_DESCRIPTION("XPP FXS Card Driver");
-MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_XPD(XPD_TYPE_FXS);
-
-module_init(card_fxs_startup);
-module_exit(card_fxs_cleanup);
diff --git a/drivers/dahdi/xpp/card_fxs.h b/drivers/dahdi/xpp/card_fxs.h
deleted file mode 100644 (file)
index 5be4833..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef        CARD_FXS_H
-#define        CARD_FXS_H
-/*
- * Written by Oron Peled <oron@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"
-
-enum fxs_opcodes {
-       XPROTO_NAME(FXS, SIG_CHANGED) = 0x06,
-        /**/ XPROTO_NAME(FXS, CHAN_POWER) = 0x0F,      /* Write to SLIC */
-       XPROTO_NAME(FXS, CHAN_CID) = 0x0F,      /* Write to SLIC */
-       XPROTO_NAME(FXS, LED) = 0x0F,   /* Write to SLIC */
-};
-
-DEF_RPACKET_DATA(FXS, SIG_CHANGED,
-               xpp_line_t sig_status;  /* channels: lsb=1, msb=8 */
-               xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */
-               );
-
-#endif /* CARD_FXS_H */
diff --git a/drivers/dahdi/xpp/card_global.c b/drivers/dahdi/xpp/card_global.c
deleted file mode 100644 (file)
index da1393e..0000000
+++ /dev/null
@@ -1,907 +0,0 @@
-/*
- * Written by Oron Peled <oron@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/module.h>
-#include <linux/delay.h>
-#include <linux/kmod.h>
-#include "xdefs.h"
-#include "xpd.h"
-#include "xpp_dahdi.h"
-#include "xproto.h"
-#include "dahdi_debug.h"
-#include "xbus-core.h"
-#include "parport_debug.h"
-
-static const char rcsid[] = "$Id$";
-
-DEF_PARM(charp, initdir, "/usr/share/dahdi", 0644,
-        "The directory of card initialization scripts");
-
-#define        CHIP_REGISTERS  "chipregs"
-
-extern int debug;
-
-/*---------------- GLOBAL PROC handling -----------------------------------*/
-
-static int send_magic_request(xbus_t *xbus, unsigned unit, xportno_t portno,
-                             bool eoftx)
-{
-       xframe_t *xframe;
-       xpacket_t *pack;
-       reg_cmd_t *reg_cmd;
-       int ret;
-
-       /*
-        * Zero length multibyte is legal and has special meaning for the
-        * firmware:
-        *   eoftx==1: Start sending us D-channel packets.
-        *   eoftx==0: Stop sending us D-channel packets.
-        */
-       XFRAME_NEW_REG_CMD(xframe, pack, xbus, GLOBAL, REG, unit);
-       reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
-       reg_cmd->h.bytes = 0;
-       reg_cmd->h.is_multibyte = 1;
-       reg_cmd->h.portnum = portno;
-       reg_cmd->h.eoframe = eoftx;
-       PORT_DBG(REGS, xbus, unit, portno, "Magic Packet (eoftx=%d)\n", eoftx);
-       if (debug & DBG_REGS)
-               dump_xframe(__func__, xbus, xframe, debug);
-       ret = send_cmd_frame(xbus, xframe);
-       if (ret < 0)
-               PORT_ERR(xbus, unit, portno, "%s: failed sending xframe\n",
-                        __func__);
-       return ret;
-}
-
-static int parse_hexbyte(const char *buf)
-{
-       char *endp;
-       unsigned val;
-
-       val = simple_strtoul(buf, &endp, 16);
-       if (*endp != '\0' || val > 0xFF)
-               return -EBADR;
-       return (__u8)val;
-}
-
-static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
-{
-       int argno;
-       char num_args;
-       int portno;
-       bool writing;
-       int op;                 /* [W]rite, [R]ead */
-       int addr_mode;          /* [D]irect, [I]ndirect, [Mm]ulti, [R]AM */
-       bool do_subreg = 0;
-       int regnum;
-       int subreg;
-       int data_low;
-       bool do_datah;
-       int data_high;
-       bool do_expander = 0;
-       int ret = -EBADR;
-
-       num_args = 2;           /* port + operation */
-       if (argc < num_args) {
-               XPD_ERR(xpd, "Not enough arguments (%d)\n", argc);
-               XPD_ERR(xpd,
-                       "Any Command is composed of at least %d words "
-                       "(got only %d)\n",
-                       num_args, argc);
-               goto out;
-       }
-       /* Process the arguments */
-       argno = 0;
-       if (strcmp(argv[argno], "*") == 0) {
-               portno = PORT_BROADCAST;
-               //XPD_DBG(REGS, xpd, "Port broadcast\n");
-       } else {
-               portno = parse_hexbyte(argv[argno]);
-               if (portno < 0 || portno >= 8) {
-                       XPD_ERR(xpd, "Illegal port number '%s'\n", argv[argno]);
-                       goto out;
-               }
-               //XPD_DBG(REGS, xpd, "Port is %d\n", portno);
-       }
-       argno++;
-       if (strlen(argv[argno]) != 2) {
-               XPD_ERR(xpd, "Wrong operation codes '%s'\n", argv[argno]);
-               goto out;
-       }
-       op = argv[argno][0];
-       switch (op) {
-       case 'W':
-               writing = 1;
-               num_args++;     /* data low */
-               //XPD_DBG(REGS, xpd, "WRITING\n");
-               break;
-       case 'R':
-               writing = 0;
-               //XPD_DBG(REGS, xpd, "READING\n");
-               break;
-       default:
-               XPD_ERR(xpd, "Unknown operation type '%c'\n", op);
-               goto out;
-       }
-       addr_mode = argv[argno][1];
-       switch (addr_mode) {
-       case 'I':
-               XPD_NOTICE(xpd,
-                       "'I' is deprecated in register commands. "
-                       "Use 'S' instead.\n");
-               /* fall through */
-       case 'S':
-               do_subreg = 1;
-               num_args += 2;  /* register + subreg */
-               //XPD_DBG(REGS, xpd, "SUBREG\n");
-               break;
-       case 'D':
-               do_subreg = 0;
-               num_args++;     /* register */
-               //XPD_DBG(REGS, xpd, "DIRECT\n");
-               break;
-       case 'X':
-               do_subreg = 0;
-               do_expander = 1;
-               num_args++;     /* register */
-               //XPD_DBG(REGS, xpd, "EXPANDER\n");
-               break;
-       case 'M':
-       case 'm':
-               if (op != 'W') {
-                       XPD_ERR(xpd,
-                               "Can use Multibyte (%c) only with op 'W'\n",
-                               addr_mode);
-                       goto out;
-               }
-               num_args--;     /* No data low */
-               //XPD_DBG(REGS, xpd, "Multibyte (%c)\n", addr_mode);
-               break;
-       case 'R':
-               switch (op) {
-               case 'W':
-                       num_args += 5;  /* add: addr_high, data_[0-3] */
-                       break;
-               case 'R':
-                       num_args += 2;  /* add: addr_low, addr_high */
-                       break;
-               }
-               break;
-       default:
-               XPD_ERR(xpd, "Unknown addressing type '%c'\n", addr_mode);
-               goto out;
-       }
-       if (argv[argno][2] != '\0') {
-               XPD_ERR(xpd, "Bad operation field '%s'\n", argv[argno]);
-               goto out;
-       }
-       if (argc < num_args) {
-               XPD_ERR(xpd,
-                       "Command \"%s\" is composed of at least %d words "
-                       "(got only %d)\n",
-                       argv[argno], num_args, argc);
-               goto out;
-       }
-       argno++;
-       if (addr_mode == 'M' || addr_mode == 'm') {
-               if (argno < argc) {
-                       XPD_ERR(xpd,
-                               "Magic-Multibyte(%c) with %d extra arguments\n",
-                               addr_mode, argc - argno);
-                       goto out;
-               }
-               ret =
-                   send_magic_request(xpd->xbus, xpd->addr.unit, portno,
-                                      addr_mode == 'm');
-               goto out;
-       }
-       if (addr_mode == 'R') {
-               __u8 input[6];
-               int i;
-
-               if (num_args - 2 > 6) {
-                       XPD_ERR(xpd, "Too many args (%d) -- should be less than 6\n", num_args - 2);
-                       goto out;
-               }
-               for (i = 0; i < num_args - 2; i++, argno++) {
-                       int hexbyte= parse_hexbyte(argv[argno]);
-                       if (hexbyte < 0) {
-                               XPD_ERR(xpd, "Illegal input[%d] number '%s'\n", i, argv[argno]);
-                               goto out;
-                       }
-                       input[i] = hexbyte;
-               }
-               ret = xpp_ram_request(xpd->xbus, xpd, portno, writing,
-                       input[0],
-                       input[1],
-                       input[2],
-                       input[3],
-                       input[4],
-                       input[5],
-                       1);
-               goto out;
-       }
-       /* Normal (non-Magic) register commands */
-       do_datah = 0;
-       if (argno >= argc) {
-               XPD_ERR(xpd, "Missing register number\n");
-               goto out;
-       }
-       regnum = parse_hexbyte(argv[argno]);
-       if (regnum < 0) {
-               XPD_ERR(xpd, "Illegal register number '%s'\n", argv[argno]);
-               goto out;
-       }
-       //XPD_DBG(REGS, xpd, "Register is %X\n", regnum);
-       argno++;
-       if (do_subreg) {
-               if (argno >= argc) {
-                       XPD_ERR(xpd, "Missing subregister number\n");
-                       goto out;
-               }
-               subreg = parse_hexbyte(argv[argno]);
-               if (subreg < 0) {
-                       XPD_ERR(xpd, "Illegal subregister number '%s'\n",
-                               argv[argno]);
-                       goto out;
-               }
-               //XPD_DBG(REGS, xpd, "Subreg is %X\n", subreg);
-               argno++;
-       } else
-               subreg = 0;
-       if (writing) {
-               if (argno >= argc) {
-                       XPD_ERR(xpd, "Missing data low number\n");
-                       goto out;
-               }
-               data_low = parse_hexbyte(argv[argno]);
-               if (data_low < 0) {
-                       XPD_ERR(xpd, "Illegal data_low number '%s'\n",
-                               argv[argno]);
-                       goto out;
-               }
-               //XPD_DBG(REGS, xpd, "Data Low is %X\n", data_low);
-               argno++;
-       } else
-               data_low = 0;
-       if (argno < argc) {
-               do_datah = 1;
-               if (!argv[argno]) {
-                       XPD_ERR(xpd, "Missing data high number\n");
-                       goto out;
-               }
-               data_high = parse_hexbyte(argv[argno]);
-               if (data_high < 0) {
-                       XPD_ERR(xpd, "Illegal data_high number '%s'\n",
-                               argv[argno]);
-                       goto out;
-               }
-               //XPD_DBG(REGS, xpd, "Data High is %X\n", data_high);
-               argno++;
-       } else
-               data_high = 0;
-       if (argno < argc) {
-               XPD_ERR(xpd, "Command contains an extra %d argument\n",
-                       argc - argno);
-               goto out;
-       }
-#if 0
-       XPD_DBG(REGS, xpd,
-               "portno=%d writing=%d regnum=%d do_subreg=%d subreg=%d "
-               "dataL=%d do_datah=%d dataH=%d do_expander=%d\n",
-               portno,                 /* portno       */
-               writing,                /* writing      */
-               regnum, do_subreg,      /* use subreg   */
-               subreg,                 /* subreg       */
-               data_low, do_datah,     /* use data_high */
-               data_high, do_expander);
-#endif
-       ret = xpp_register_request(xpd->xbus, xpd, portno,
-               writing, regnum, do_subreg, subreg,
-               data_low, do_datah, data_high, 1, do_expander);
-out:
-       return ret;
-}
-
-#define        MAX_ARGS        10
-
-int parse_chip_command(xpd_t *xpd, char *cmdline)
-{
-       xbus_t *xbus;
-       int ret = -EBADR;
-       __u8 buf[MAX_PROC_WRITE];
-       char *str;
-       char *p;
-       char *argv[MAX_ARGS + 1];
-       int argc;
-       int i;
-
-       BUG_ON(!xpd);
-       xbus = xpd->xbus;
-       if (!XBUS_FLAGS(xbus, CONNECTED)) {
-               XBUS_DBG(GENERAL, xbus, "Dropped packet. Disconnected.\n");
-               return -EBUSY;
-       }
-       strlcpy(buf, cmdline, MAX_PROC_WRITE);  /* Save a copy */
-       if (buf[0] == '#' || buf[0] == ';')
-               XPD_DBG(REGS, xpd, "Note: '%s'\n", buf);
-       if ((p = strchr(buf, '#')) != NULL)     /* Truncate comments */
-               *p = '\0';
-       if ((p = strchr(buf, ';')) != NULL)     /* Truncate comments */
-               *p = '\0';
-       /* Trim leading whitespace */
-       for (p = buf; *p && (*p == ' ' || *p == '\t'); p++)
-               ;
-       str = p;
-       for (i = 0; (p = strsep(&str, " \t")) != NULL && i < MAX_ARGS;) {
-               if (*p != '\0') {
-                       argv[i] = p;
-                       // XPD_DBG(REGS, xpd, "ARG %d = '%s'\n", i, p);
-                       i++;
-               }
-       }
-       argv[i] = NULL;
-       argc = i;
-       if (p) {
-               XPD_ERR(xpd, "Too many words (%d) to process. Last was '%s'\n",
-                       i, p);
-               goto out;
-       }
-       if (argc)
-               ret = execute_chip_command(xpd, argc, argv);
-       else
-               ret = 0;        /* empty command - no op */
-out:
-       return ret;
-}
-
-/*---------------- GLOBAL Protocol Commands -------------------------------*/
-
-static bool global_packet_is_valid(xpacket_t *pack);
-static void global_packet_dump(const char *msg, xpacket_t *pack);
-
-/*---------------- GLOBAL: HOST COMMANDS ----------------------------------*/
-
-/* 0x07 */ HOSTCMD(GLOBAL, AB_REQUEST)
-{
-       int ret = -ENODEV;
-       xframe_t *xframe;
-       xpacket_t *pack;
-
-       if (!xbus) {
-               DBG(DEVICES, "NO XBUS\n");
-               return -EINVAL;
-       }
-       if (xbus_check_unique(xbus))
-               return -EBUSY;
-       XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, AB_REQUEST, 0);
-       RPACKET_FIELD(pack, GLOBAL, AB_REQUEST, rev) = XPP_PROTOCOL_VERSION;
-       RPACKET_FIELD(pack, GLOBAL, AB_REQUEST, reserved) = 0;
-       XBUS_DBG(DEVICES, xbus, "Protocol Version %d\n", XPP_PROTOCOL_VERSION);
-       if (xbus_setstate(xbus, XBUS_STATE_SENT_REQUEST))
-               ret = send_cmd_frame(xbus, xframe);
-       return ret;
-}
-
-int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
-                        bool writing, __u8 regnum, bool do_subreg, __u8 subreg,
-                        __u8 data_low, bool do_datah, __u8 data_high,
-                        bool should_reply, bool do_expander)
-{
-       int ret = 0;
-       xframe_t *xframe;
-       xpacket_t *pack;
-       reg_cmd_t *reg_cmd;
-
-       if (!xbus) {
-               DBG(REGS, "NO XBUS\n");
-               return -EINVAL;
-       }
-       XFRAME_NEW_REG_CMD(xframe, pack, xbus, GLOBAL, REG, xpd->xbus_idx);
-       LINE_DBG(REGS, xpd, portno, "%c%c %02X %02X %02X %02X\n",
-                (writing) ? 'W' : 'R', (do_subreg) ? 'S' : 'D', regnum, subreg,
-                data_low, data_high);
-       reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
-       /* do not count the 'bytes' field */
-       reg_cmd->h.bytes = REG_CMD_SIZE(REG);
-       reg_cmd->h.is_multibyte = 0;
-       if (portno == PORT_BROADCAST) {
-               reg_cmd->h.portnum = 0;
-               REG_FIELD(reg_cmd, all_ports_broadcast) = 1;
-       } else {
-               reg_cmd->h.portnum = portno;
-               REG_FIELD(reg_cmd, all_ports_broadcast) = 0;
-       }
-       reg_cmd->h.eoframe = 0;
-       REG_FIELD(reg_cmd, reserved) = 0;       /* force reserved bits to 0 */
-       REG_FIELD(reg_cmd, read_request) = (writing) ? 0 : 1;
-       REG_FIELD(reg_cmd, do_subreg) = do_subreg;
-       REG_FIELD(reg_cmd, regnum) = regnum;
-       REG_FIELD(reg_cmd, subreg) = subreg;
-       REG_FIELD(reg_cmd, do_datah) = do_datah;
-       REG_FIELD(reg_cmd, data_low) = data_low;
-       REG_FIELD(reg_cmd, data_high) = data_high;
-       REG_FIELD(reg_cmd, do_expander) = do_expander;
-       if (should_reply)
-               xpd->requested_reply = *reg_cmd;
-       if (debug & DBG_REGS) {
-               dump_reg_cmd("REG_REQ", 1, xbus, xpd->addr.unit,
-                            reg_cmd->h.portnum, reg_cmd);
-               dump_packet("REG_REQ", pack, 1);
-       }
-       if (!xframe->usec_towait) {     /* default processing time of SPI */
-               if (subreg)
-                       xframe->usec_towait = 2000;
-               else
-                       xframe->usec_towait = 1000;
-       }
-       ret = send_cmd_frame(xbus, xframe);
-       return ret;
-}
-EXPORT_SYMBOL(xpp_register_request);
-
-int xpp_ram_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
-                        bool writing,
-                       __u8 addr_low,
-                       __u8 addr_high,
-                       __u8 data_0,
-                       __u8 data_1,
-                       __u8 data_2,
-                       __u8 data_3,
-                        bool should_reply)
-{
-       int ret = 0;
-       xframe_t *xframe;
-       xpacket_t *pack;
-       reg_cmd_t *reg_cmd;
-
-       if (!xbus) {
-               DBG(REGS, "NO XBUS\n");
-               return -EINVAL;
-       }
-       XFRAME_NEW_REG_CMD(xframe, pack, xbus, GLOBAL, RAM, xpd->xbus_idx);
-       LINE_DBG(REGS, xpd, portno, "%cR %02X %02X %02X %02X %02X %02X\n",
-               (writing) ? 'W' : 'R',
-               addr_low, addr_high,
-               data_0, data_1, data_2, data_3);
-       reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
-       /* do not count the 'bytes' field */
-       reg_cmd->h.bytes = REG_CMD_SIZE(RAM);
-       reg_cmd->h.is_multibyte = 0;
-       if (portno == PORT_BROADCAST) {
-               reg_cmd->h.portnum = 0;
-               REG_FIELD_RAM(reg_cmd, all_ports_broadcast) = 1;
-       } else {
-               reg_cmd->h.portnum = portno;
-               REG_FIELD_RAM(reg_cmd, all_ports_broadcast) = 0;
-       }
-       reg_cmd->h.eoframe = 0;
-       REG_FIELD_RAM(reg_cmd, reserved) = 0;   /* force reserved bits to 0 */
-       REG_FIELD_RAM(reg_cmd, read_request) = (writing) ? 0 : 1;
-       REG_FIELD_RAM(reg_cmd, do_datah) = 1;
-       REG_FIELD_RAM(reg_cmd, do_subreg) = 1;
-       REG_FIELD_RAM(reg_cmd, addr_low) = addr_low;
-       REG_FIELD_RAM(reg_cmd, addr_high) = addr_high;
-       REG_FIELD_RAM(reg_cmd, data_0) = data_0;
-       REG_FIELD_RAM(reg_cmd, data_1) = data_1;
-       REG_FIELD_RAM(reg_cmd, data_2) = data_2;
-       REG_FIELD_RAM(reg_cmd, data_3) = data_3;
-       if (should_reply)
-               xpd->requested_reply = *reg_cmd;
-       if (debug & DBG_REGS) {
-               dump_reg_cmd("REG_RAM", 1, xbus, xpd->addr.unit,
-                            reg_cmd->h.portnum, reg_cmd);
-               dump_packet("REG_RAM", pack, 1);
-       }
-       if (!xframe->usec_towait) {     /* default processing time of SPI */
-               xframe->usec_towait = 1000;
-       }
-       ret = send_cmd_frame(xbus, xframe);
-       return ret;
-}
-EXPORT_SYMBOL(xpp_ram_request);
-
-/*
- * The XPD parameter is totaly ignored by the driver and firmware as well.
- */
-/* 0x19 */ HOSTCMD(GLOBAL, SYNC_SOURCE, enum sync_mode mode, int drift)
-{
-       xframe_t *xframe;
-       xpacket_t *pack;
-       const char *mode_name;
-
-       BUG_ON(!xbus);
-       if ((mode_name = sync_mode_name(mode)) == NULL) {
-               XBUS_ERR(xbus, "SYNC_SOURCE: bad sync_mode=0x%X\n", mode);
-               return -EINVAL;
-       }
-       XBUS_DBG(SYNC, xbus, "%s (0x%X), drift=%d\n", mode_name, mode, drift);
-       XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, SYNC_SOURCE, 0);
-       RPACKET_FIELD(pack, GLOBAL, SYNC_SOURCE, sync_mode) = mode;
-       RPACKET_FIELD(pack, GLOBAL, SYNC_SOURCE, drift) = drift;
-       send_cmd_frame(xbus, xframe);
-       return 0;
-}
-
-/*
- * Wrapper for different types of xbus reset
- */
-static int send_xbus_reset(xbus_t *xbus, uint8_t reset_mask)
-{
-       xframe_t *xframe;
-       xpacket_t *pack;
-
-       BUG_ON(!xbus);
-       XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, XBUS_RESET, 0);
-       RPACKET_FIELD(pack, GLOBAL, XBUS_RESET, mask) = reset_mask;
-       send_cmd_frame(xbus, xframe);
-       return 0;
-}
-
-/* 0x23 */ HOSTCMD(GLOBAL, RESET_SPI)
-{
-       XBUS_DBG(DEVICES, xbus, "Sending SPI reset\n");
-       /* toggle reset line */
-       send_xbus_reset(xbus, 0x04);
-       send_xbus_reset(xbus, 0x00);
-       return 0;
-}
-
-
-/* 0x23 */ HOSTCMD(GLOBAL, RESET_SYNC_COUNTERS)
-{
-       //XBUS_DBG(SYNC, xbus, "\n");
-       return send_xbus_reset(xbus, 0x10);
-}
-
-/*---------------- GLOBAL: Astribank Reply Handlers -----------------------*/
-
-HANDLER_DEF(GLOBAL, NULL_REPLY)
-{
-       XBUS_DBG(GENERAL, xbus, "got len=%d\n", XPACKET_LEN(pack));
-       return 0;
-}
-
-HANDLER_DEF(GLOBAL, AB_DESCRIPTION)
-{                              /* 0x08 */
-       struct xbus_workqueue *worker;
-       __u8 rev;
-       struct unit_descriptor *units;
-       int count_units;
-       int i;
-       int ret = 0;
-
-       if (!xbus) {
-               NOTICE("%s: xbus is gone!!!\n", __func__);
-               goto out;
-       }
-       rev = RPACKET_FIELD(pack, GLOBAL, AB_DESCRIPTION, rev);
-       units = RPACKET_FIELD(pack, GLOBAL, AB_DESCRIPTION, unit_descriptor);
-       count_units = XPACKET_LEN(pack) - ((__u8 *)units - (__u8 *)pack);
-       count_units /= sizeof(*units);
-       if (rev != XPP_PROTOCOL_VERSION) {
-               XBUS_NOTICE(xbus, "Bad protocol version %d (should be %d)\n",
-                           rev, XPP_PROTOCOL_VERSION);
-               ret = -EPROTO;
-               goto proto_err;
-       }
-       if (count_units > NUM_UNITS) {
-               XBUS_NOTICE(xbus, "Too many units %d (should be %d)\n",
-                           count_units, NUM_UNITS);
-               ret = -EPROTO;
-               goto proto_err;
-       }
-       if (count_units <= 0) {
-               XBUS_NOTICE(xbus, "Empty astribank? (%d units)\n", count_units);
-               ret = -EPROTO;
-               goto proto_err;
-       }
-       if (units[0].addr.unit != 0 || units[0].addr.subunit != 0) {
-               XBUS_NOTICE(xbus, "No first module. Astribank unusable.\n");
-               ret = -EPROTO;
-               goto proto_err;
-       }
-       if (!xbus_setstate(xbus, XBUS_STATE_RECVD_DESC)) {
-               ret = -EPROTO;
-               goto proto_err;
-       }
-       XBUS_INFO(xbus, "DESCRIPTOR: %d cards, protocol revision %d\n",
-                 count_units, rev);
-       if (xbus_check_unique(xbus))
-               return -EBUSY;
-       xbus->revision = rev;
-       worker = &xbus->worker;
-       if (!worker->wq) {
-               XBUS_ERR(xbus, "missing worker thread\n");
-               ret = -ENODEV;
-               goto out;
-       }
-       for (i = 0; i < count_units; i++) {
-               struct unit_descriptor *this_unit = &units[i];
-               struct card_desc_struct *card_desc;
-               unsigned long flags;
-
-               if ((card_desc =
-                    KZALLOC(sizeof(struct card_desc_struct),
-                            GFP_ATOMIC)) == NULL) {
-                       XBUS_ERR(xbus, "Card description allocation failed.\n");
-                       ret = -ENOMEM;
-                       goto out;
-               }
-               card_desc->magic = CARD_DESC_MAGIC;
-               INIT_LIST_HEAD(&card_desc->card_list);
-               card_desc->unit_descriptor = *this_unit;
-               XBUS_INFO(xbus,
-                       "    CARD %d type=%d.%d ports=(%dx%d), "
-                       "port-dir=0x%02X\n",
-                       this_unit->addr.unit, this_unit->type,
-                       this_unit->subtype,
-                       this_unit->numchips, this_unit->ports_per_chip,
-                       this_unit->port_dir);
-               spin_lock_irqsave(&worker->worker_lock, flags);
-               worker->num_units++;
-               XBUS_COUNTER(xbus, UNITS)++;
-               list_add_tail(&card_desc->card_list, &worker->card_list);
-               spin_unlock_irqrestore(&worker->worker_lock, flags);
-       }
-       CALL_PROTO(GLOBAL, RESET_SPI, xbus, NULL);
-       if (!xbus_process_worker(xbus)) {
-               ret = -ENODEV;
-               goto out;
-       }
-       goto out;
-proto_err:
-       xbus_setstate(xbus, XBUS_STATE_FAIL);
-       dump_packet("AB_DESCRIPTION", pack, DBG_ANY);
-out:
-       return ret;
-}
-
-HANDLER_DEF(GLOBAL, REGISTER_REPLY)
-{
-       reg_cmd_t *reg = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REPLY, regcmd);
-
-       if (!xpd) {
-               static int rate_limit;
-
-               if ((rate_limit++ % 1003) < 5)
-                       notify_bad_xpd(__func__, xbus, XPACKET_ADDR(pack), "");
-               return -EPROTO;
-       }
-       if (debug & DBG_REGS) {
-               dump_reg_cmd("REG_REPLY", 0, xbus, xpd->addr.unit, reg->h.portnum,
-                            reg);
-               dump_packet("REG_REPLY", pack, 1);
-       }
-       if (!XMETHOD(card_register_reply, xpd)) {
-               XPD_ERR(xpd,
-                       "REGISTER_REPLY: missing card_register_reply()\n");
-               return -EINVAL;
-       }
-       return CALL_XMETHOD(card_register_reply, xpd, reg);
-}
-
-HANDLER_DEF(GLOBAL, SYNC_REPLY)
-{
-       __u8 mode = RPACKET_FIELD(pack, GLOBAL, SYNC_REPLY, sync_mode);
-       __u8 drift = RPACKET_FIELD(pack, GLOBAL, SYNC_REPLY, drift);
-       const char *mode_name;
-
-       BUG_ON(!xbus);
-       if ((mode_name = sync_mode_name(mode)) == NULL) {
-               XBUS_ERR(xbus, "SYNC_REPLY: bad sync_mode=0x%X\n", mode);
-               return -EINVAL;
-       }
-       XBUS_DBG(SYNC, xbus, "%s (0x%X), drift=%d\n", mode_name, mode, drift);
-       //dump_packet("SYNC_REPLY", pack, debug & DBG_SYNC);
-       got_new_syncer(xbus, mode, drift);
-       return 0;
-}
-
-#define        TMP_NAME_LEN    (XBUS_NAMELEN + XPD_NAMELEN + 5)
-
-HANDLER_DEF(GLOBAL, ERROR_CODE)
-{
-       char tmp_name[TMP_NAME_LEN];
-       static long rate_limit;
-       __u8 category_code;
-       __u8 errorbits;
-
-       BUG_ON(!xbus);
-       if ((rate_limit++ % 5003) > 200)
-               return 0;
-       category_code = RPACKET_FIELD(pack, GLOBAL, ERROR_CODE, category_code);
-       errorbits = RPACKET_FIELD(pack, GLOBAL, ERROR_CODE, errorbits);
-       if (!xpd) {
-               snprintf(tmp_name, TMP_NAME_LEN, "%s(%1d%1d)", xbus->busname,
-                        XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack));
-       } else {
-               snprintf(tmp_name, TMP_NAME_LEN, "%s/%s", xbus->busname,
-                        xpd->xpdname);
-       }
-       NOTICE
-           ("%s: FIRMWARE %s: category=%d errorbits=0x%02X (rate_limit=%ld)\n",
-            tmp_name, cmd->name, category_code, errorbits, rate_limit);
-       dump_packet("FIRMWARE: ", pack, 1);
-       /*
-        * FIXME: Should implement an error recovery plan
-        */
-       return 0;
-}
-
-xproto_table_t PROTO_TABLE(GLOBAL) = {
-       .entries = {
-               /*      Prototable      Card    Opcode          */
-               XENTRY( GLOBAL,         GLOBAL, NULL_REPLY      ),
-               XENTRY( GLOBAL,         GLOBAL, AB_DESCRIPTION  ),
-               XENTRY( GLOBAL,         GLOBAL, SYNC_REPLY      ),
-               XENTRY( GLOBAL,         GLOBAL, ERROR_CODE      ),
-               XENTRY( GLOBAL,         GLOBAL, REGISTER_REPLY  ),
-       },
-       .name = "GLOBAL",
-       .packet_is_valid = global_packet_is_valid,
-       .packet_dump = global_packet_dump,
-};
-
-static bool global_packet_is_valid(xpacket_t *pack)
-{
-       const xproto_entry_t *xe;
-
-       //DBG(GENERAL, "\n");
-       xe = xproto_global_entry(XPACKET_OP(pack));
-       return xe != NULL;
-}
-
-static void global_packet_dump(const char *msg, xpacket_t *pack)
-{
-       DBG(GENERAL, "%s\n", msg);
-}
-
-#define        MAX_PATH_STR    128
-
-#ifndef        UMH_WAIT_PROC
-/*
- * - UMH_WAIT_PROC was introduced as enum in 2.6.23
- *   with a value of 1
- * - It was changed to a macro (and it's value was modified) in 3.3.0
- */
-#define        UMH_WAIT_PROC   1
-#endif
-
-int run_initialize_registers(xpd_t *xpd)
-{
-       int ret;
-       xbus_t *xbus;
-       char busstr[MAX_ENV_STR];
-       char busnumstr[MAX_ENV_STR];
-       char modelstr[MAX_ENV_STR];
-       char unitstr[MAX_ENV_STR];
-       char subunitsstr[MAX_ENV_STR];
-       char typestr[MAX_ENV_STR];
-       char directionstr[MAX_ENV_STR];
-       char revstr[MAX_ENV_STR];
-       char connectorstr[MAX_ENV_STR];
-       char xbuslabel[MAX_ENV_STR];
-       char init_card[MAX_PATH_STR];
-       __u8 direction_mask;
-       __u8 hw_type = XPD_HW(xpd).type;
-       int i;
-       char *argv[] = {
-               init_card,
-               NULL
-       };
-       char *envp[] = {
-               busstr,
-               busnumstr,
-               modelstr,
-               unitstr,
-               subunitsstr,
-               typestr,
-               directionstr,
-               revstr,
-               connectorstr,
-               xbuslabel,
-               NULL
-       };
-
-       BUG_ON(!xpd);
-       xbus = xpd->xbus;
-       if (!initdir || !initdir[0]) {
-               XPD_NOTICE(xpd, "Missing initdir parameter\n");
-               ret = -EINVAL;
-               goto err;
-       }
-       if (!xpd_setstate(xpd, XPD_STATE_INIT_REGS)) {
-               ret = -EINVAL;
-               goto err;
-       }
-       direction_mask = 0;
-       for (i = 0; i < xpd->subunits; i++) {
-               xpd_t *su = xpd_byaddr(xbus, xpd->addr.unit, i);
-
-               if (!su) {
-                       XPD_ERR(xpd, "Have %d subunits, but not subunit #%d\n",
-                               xpd->subunits, i);
-                       continue;
-               }
-               direction_mask |=
-                   (PHONEDEV(su).direction == TO_PHONE) ? BIT(i) : 0;
-       }
-       snprintf(busstr, MAX_ENV_STR, "XBUS_NAME=%s", xbus->busname);
-       snprintf(busnumstr, MAX_ENV_STR, "XBUS_NUMBER=%d", xbus->num);
-       snprintf(modelstr, MAX_ENV_STR, "XBUS_MODEL_STRING=%s",
-                xbus->transport.model_string);
-       snprintf(typestr, MAX_ENV_STR, "HW_TYPE=%d", hw_type);
-       snprintf(unitstr, MAX_ENV_STR, "UNIT_NUMBER=%d", xpd->addr.unit);
-       snprintf(typestr, MAX_ENV_STR, "UNIT_TYPE=%d", xpd->xpd_type);
-       snprintf(subunitsstr, MAX_ENV_STR, "UNIT_SUBUNITS=%d", xpd->subunits);
-       snprintf(directionstr, MAX_ENV_STR, "UNIT_SUBUNITS_DIR=%d",
-                direction_mask);
-       snprintf(revstr, MAX_ENV_STR, "XBUS_REVISION=%d", xbus->revision);
-       snprintf(connectorstr, MAX_ENV_STR, "XBUS_CONNECTOR=%s",
-                xbus->connector);
-       snprintf(xbuslabel, MAX_ENV_STR, "XBUS_LABEL=%s", xbus->label);
-       if (snprintf
-           (init_card, MAX_PATH_STR, "%s/init_card_%d_%d", initdir, hw_type,
-            xbus->revision) > MAX_PATH_STR) {
-               XPD_NOTICE(xpd,
-                       "Cannot initialize. pathname is longer "
-                       "than %d characters.\n",
-                       MAX_PATH_STR);
-               ret = -E2BIG;
-               goto err;
-       }
-       if (!XBUS_IS(xbus, RECVD_DESC)) {
-               XBUS_ERR(xbus,
-                        "Skipped register initialization. In state %s.\n",
-                        xbus_statename(XBUS_STATE(xbus)));
-               ret = -ENODEV;
-               goto err;
-       }
-       XPD_DBG(DEVICES, xpd, "running '%s' for type=%d revision=%d\n",
-               init_card, xpd->xpd_type, xbus->revision);
-       ret = call_usermodehelper(init_card, argv, envp, UMH_WAIT_PROC);
-       /*
-        * Carefully report results
-        */
-       if (ret == 0)
-               XPD_DBG(DEVICES, xpd, "'%s' finished OK\n", init_card);
-       else if (ret < 0) {
-               XPD_ERR(xpd, "Failed running '%s' (errno %d)\n", init_card,
-                       ret);
-       } else {
-               __u8 exitval = ((unsigned)ret >> 8) & 0xFF;
-               __u8 sigval = ret & 0xFF;
-
-               if (!exitval) {
-                       XPD_ERR(xpd, "'%s' killed by signal %d\n", init_card,
-                               sigval);
-               } else {
-                       XPD_ERR(xpd, "'%s' aborted with exitval %d\n",
-                               init_card, exitval);
-               }
-               ret = -EINVAL;
-       }
-err:
-       return ret;
-}
-EXPORT_SYMBOL(run_initialize_registers);
diff --git a/drivers/dahdi/xpp/card_global.h b/drivers/dahdi/xpp/card_global.h
deleted file mode 100644 (file)
index bdd1b62..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-#ifndef        CARD_GLOBAL_H
-#define        CARD_GLOBAL_H
-/*
- * Written by Oron Peled <oron@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"
-#include "xbus-pcm.h"
-
-enum global_opcodes {
-       XPROTO_NAME(GLOBAL, AB_REQUEST) = 0x07,
-       XPROTO_NAME(GLOBAL, AB_DESCRIPTION) = 0x08,
-       XPROTO_NAME(GLOBAL, REGISTER_REQUEST) = 0x0F,
-       XPROTO_NAME(GLOBAL, REGISTER_REPLY) = 0x10,
-        /**/ XPROTO_NAME(GLOBAL, PCM_WRITE) = 0x11,
-       XPROTO_NAME(GLOBAL, PCM_READ) = 0x12,
-        /**/ XPROTO_NAME(GLOBAL, SYNC_SOURCE) = 0x19,
-       XPROTO_NAME(GLOBAL, SYNC_REPLY) = 0x1A,
-        /**/ XPROTO_NAME(GLOBAL, ERROR_CODE) = 0x22,
-       XPROTO_NAME(GLOBAL, XBUS_RESET) = 0x23,
-       XPROTO_NAME(GLOBAL, NULL_REPLY) = 0xFE,
-};
-
-struct unit_descriptor {
-       struct xpd_addr addr;
-       __u8 subtype:4;
-       __u8 type:4;
-       __u8 numchips;
-       __u8 ports_per_chip;
-       __u8 port_dir;          /* bitmask: 0 - PSTN, 1 - PHONE */
-       __u8 reserved[2];
-       struct xpd_addr ec_addr;
-};
-
-#define        NUM_UNITS       6
-
-DEF_RPACKET_DATA(GLOBAL, NULL_REPLY);
-DEF_RPACKET_DATA(GLOBAL, AB_REQUEST, __u8 rev; __u8 reserved;);
-DEF_RPACKET_DATA(GLOBAL, AB_DESCRIPTION, __u8 rev; __u8 reserved[3];
-                struct unit_descriptor unit_descriptor[NUM_UNITS];);
-DEF_RPACKET_DATA(GLOBAL, REGISTER_REQUEST, reg_cmd_t reg_cmd;);
-DEF_RPACKET_DATA(GLOBAL, PCM_WRITE, xpp_line_t lines; __u8 pcm[PCM_CHUNKSIZE];);
-DEF_RPACKET_DATA(GLOBAL, PCM_READ, xpp_line_t lines; __u8 pcm[PCM_CHUNKSIZE];);
-DEF_RPACKET_DATA(GLOBAL, SYNC_SOURCE, __u8 sync_mode; __u8 drift;);
-DEF_RPACKET_DATA(GLOBAL, SYNC_REPLY, __u8 sync_mode; __u8 drift;);
-DEF_RPACKET_DATA(GLOBAL, REGISTER_REPLY, reg_cmd_t regcmd;);
-DEF_RPACKET_DATA(GLOBAL, XBUS_RESET, __u8 mask;);
-DEF_RPACKET_DATA(GLOBAL, ERROR_CODE, __u8 category_code; __u8 errorbits