--- linux-2.6.27-rc2/MAINTAINERS	2008-08-08 13:21:10.470637659 +0300
+++ linux/MAINTAINERS	2008-08-08 13:25:00.661113955 +0300
@@ -1678,6 +1678,13 @@ P:	Mika Kuoppala
 M:	miku@iki.fi
 S:	Maintained

+ETP WAN DRIVERS
+P:	Matti Linnanvuori
+M:	matti.linnanvuori@ascom.com
+L:	netdev@vger.kernel.org
+L:	linux-kernel@vger.kernel.org
+S:	Supported
+
 EXT2 FILE SYSTEM
 L:	linux-ext4@vger.kernel.org
 S:	Maintained
--- linux-2.6.27-rc2/drivers/net/wan/Kconfig	2008-08-08 13:21:20.448131033 +0300
+++ linux/drivers/net/wan/Kconfig	2008-08-08 12:59:30.828005756 +0300
@@ -492,4 +492,23 @@ config SBNI_MULTILINE

 	  If unsure, say N.

+config ETP
+	tristate "ETP support"
+	depends on PCI
+	help
+	  Driver for ETP PCI and PCI104 cards, which
+	  support G.703 with Cisco-HDLC or Ethernet encapsulation.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called etp.
+
+config ETP_STREAM
+	tristate "ETP raw bitstream and sensitivity support"
+	depends on ETP
+	help
+	  Driver for ETP raw bitstream and sensitivity.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called etp_stream.
+
 endif # WAN
--- linux-2.6.27-rc2/drivers/net/wan/Makefile	2008-08-08
13:21:20.452131629 +0300
+++ linux/drivers/net/wan/Makefile	2008-08-08 12:59:30.828005756 +0300
@@ -41,6 +41,10 @@ obj-$(CONFIG_C101)		+= c101.o
 obj-$(CONFIG_WANXL)		+= wanxl.o
 obj-$(CONFIG_PCI200SYN)		+= pci200syn.o
 obj-$(CONFIG_PC300TOO)		+= pc300too.o
+etp-y				:= etp_main.o etp_idt.o etp_proc.o
+obj-$(CONFIG_ETP)		+= etp.o syncppp.o
+etp-objs			:= $(etp-y)
+obj-$(CONFIG_ETP_STREAM)	+= etp_stream/

 clean-files := wanxlfw.inc
 $(obj)/wanxl.o:	$(obj)/wanxlfw.inc
--- linux-2.6.27-rc2/drivers/net/wan/etp.h	1970-01-01 02:00:00.000000000 +0200
+++ linux/drivers/net/wan/etp.h	2008-08-08 13:07:06.884725537 +0300
@@ -0,0 +1,459 @@
+/* etp.h */
+
+/*
+	Copyright (C) 2005 Jouni Kujala, Flexibilis Oy.
+
+	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.
+
+	All the drivers derived from or based on this code must retain
+	the copyright notice.
+*/
+
+#ifndef _ETP_H_
+#define _ETP_H_
+
+#include <linux/netdevice.h>
+#include <linux/if.h>
+#include <linux/pci.h>
+#include <linux/rcupdate.h>
+#include <net/syncppp.h>
+#include "etp_ioctl.h"
+
+#define PCI_DEVICE_ID_ETP_ORIGINAL	0x2
+#define PCI_DEVICE_ID_ETP_104		0xA
+#define PCI_DEVICE_ID_DONTCARE		0x0
+
+/* Offsets to the registers. */
+#define REG_GENERAL	0x0
+#define REG_LED_CTRL	0x4
+#define REG_RST_CTRL	0x10
+#define REG_NCO_CTRL	0x20
+#define REG_CLK_STAT	0x30
+#define REG_E1_CTRL	0x40
+
+#define	REG_INT_MASK0	0x80
+#define	REG_INT_MASK1	0x84
+#define	REG_INT_MASK2	0x88
+#define	REG_INT_STAT0	0xc0
+#define	REG_INT_STAT1	0xc4
+#define	REG_INT_STAT2	0xc8
+
+#define REG_RXCTRL_IF(x)	(0x2000 + (x) * 0x80)
+#define REG_RXCTRL1_IF(x)	(0x2004 + (x) * 0x80)
+#define REG_TXCTRL_IF(x)	(0x3000 + (x) * 0x80)
+#define REG_TXCTRL1_IF(x)	(0x3004 + (x) * 0x80)
+#define REG_RXCTRL_CH(x)	(0x4000 + (x) * 0x80)
+#define REG_TXCTRL_CH(x)	(0x6000 + (x) * 0x80)
+
+#define REG_RXDESCxA_CHy(x, y) (0x10000 + (x) * 0x8 + (y) * 0x80)
+#define REG_RXDESCxB_CHy(x, y) (0x10004 + (x) * 0x8 + (y) * 0x80)
+
+#define REG_TXDESCxA_CHy(x, y) (0x18000 + (x) * 0x8 + (y) * 0x80)
+#define REG_TXDESCxB_CHy(x, y) (0x18004 + (x) * 0x8 + (y) * 0x80)
+
+struct rxdesc {
+	uint32_t desc_a;
+	uint32_t desc_b;
+};
+
+struct txdesc {
+	uint32_t desc_a;
+	uint32_t desc_b;
+};
+
+/* Bits in General register: */
+
+#define LVDS_ENABLE_MASK	(1 << 20)
+#define LVDS_ENABLE		(1 << 20)
+
+#define E1_RESET_MASK	(1 << 21)
+#define E1_RESET_ENABLE	(1 << 21)
+
+#define E1_HIGH_Z_MASK		(1 << 22)
+#define E1_HIFH_Z_ENABLE	(1 << 22)
+
+#define OUTPUT_CLK_SELECT_MASK	((1 << 27) | (1 << 28) | (1 << 29))
+#define OUTPUT_CLK_SELECT_SHIFT	27
+#define CLOCK_SELECT_LOCAL	0x0
+#define CLOCK_SELECT_DALLAS	0x1
+#define CLOCK_SELECT_RJ		0x2
+#define CLOCK_SELECT_LVDS	0x3
+#define CLOCK_SELECT_E1_GEN	0x5
+#define CLOCK_SELECT_E1_A	0x6
+#define CLOCK_SELECT_NO_CLOCK	0x7
+
+/* Bits in Reset Control register. */
+#define RESET_CH(x)	(1 << (x))
+
+/* Bits in LED ctrl register: */
+#define ALL_LED_BITS		(0x3)
+#define LED_CTRL_OFF		(0x0)
+#define LED_CTRL_ON		(0x1)
+#define LED_CTRL_BLINK		(0x2)
+#define LED_CTRL_TRAFFIC	(0x3)
+
+#define LEDx_SHIFT(x)	((x) * 2)
+
+
+/* Bits in CLOCK STATUS register: */
+#define EXT_CLOCK_RJ_STATUS_MASK	0xFF
+#define EXT_CLOCK_RJ_STATUS_SHIFT	0
+#define EXT_CLOCK_LVDS_STATUS_MASK	0xFF0000
+#define EXT_CLOCK_LVDS_STATUS_SHIFT	16
+#define EXT_CLOCK_NCO_STATUS_MASK	0xFF000000
+#define EXT_CLOCK_NCO_STATUS_SHIFT	24
+
+/* Bits in E1 control register: */
+#define E1_DATA_MASK		0xFF
+#define E1_REGISTER_MASK	0xFFF0000
+#define E1_REGISTER_MASK_NO_IF	0xFF0000
+#define E1_REGISTER_MASK_IF	0xF000000
+#define E1_REGISTER_SHIFT	16
+#define E1_REGISTER_SHIFT_IF	24
+#define E1_DIR_MASK		(1 << 30)
+#define E1_DIR_READ		(1 << 30)
+#define E1_DIR_WRITE		0x0
+#define E1_ACCESS_ON		(1 << 31)
+
+/* Bits in interrupt mask0 and status0 register: */
+#define INT_0_RECEIVED_CH(x)	(1 << (4 * (x)))
+#define INT_0_TRANSMITTED_CH(x)	(1 << (4 * (x) + 1))
+#define INT_0_RX_DROPPED_CH(x)	(1 << (4 * (x) + 2))
+#define INT_0_TX_UNDERF_CH(x)	(1 << (4 * (x) + 3))
+
+/* Bits in interrupt mask2 and status2 register: */
+#define INT_2_E1_INT		(1 << 0)
+#define INT_2_E1_ACCESS_DONE	(1 << 8)
+#define INT_2_ALLINTS		(INT_2_E1_INT | INT_2_E1_ACCESS_DONE)
+#define INT_2_RX_RESYNC_CH(x)	(1 << (16 + (x)))
+#define INT_2_TX_RESYNC_CH(x)	(1 << (24 + (x)))
+
+/* Interrupt bit generalization */
+#define INT_0_BIT_SHIFT_CH(x)	((x) * 4)
+#define INT_2_BIT_SHIFT_CH(x)	((x) + 16)
+#define CH_ALLINTS_MASK		0xF
+#define INT_RECEIVED		(1 << 0)
+#define INT_TRANSMITTED		(1 << 1)
+#define INT_RX_DROPPED		(1 << 2)
+#define INT_TX_UNDERF		(1 << 3)
+
+#define INT2_RX_RESYNC		(1 << 0)
+#define INT2_TX_RESYNC		(1 << 8)
+#define CH_ALLINTS2_MASK	(INT2_RX_RESYNC | INT2_TX_RESYNC)
+
+/* Bits in interface RX control register. */
+#define E1_MODE_HDLC		1
+#define E1_MODE_TIMESLOT	0
+#define E1_MODE_MASK		1
+#define HDLC_CRC_16		(1 << 4)
+#define HDLC_CRC_32		(0)
+#define HDLC_CRC_DELAY		(1 << 5)
+#define HDLC_CRC_MASK		((1 << 4) | (1 << 5))
+#define HDLC_RETINA_FLAG	(1 << 6)
+
+#define CLOCK_SELECT_RX_X	0x8	/* check if clock is rx clock */
+#define CLOCK_SELECT_RX(x)	(((x) | 0x8) & 0xF) /* interface clock */
+#define CLOCK_SELECT_RX_TO_CH(x) ((x) & 0x7)	/* clock select to interface */
+#define TX_CLOCK_SELECT_SHIFT	24
+#define TX_CLOCK_SELECT_MASK	(0xF << TX_CLOCK_SELECT_SHIFT)
+
+/* Bits in channel RX control register */
+#define DMA_LENGTH_LIMIT_MASK		(0xFFF)
+#define FIFO_THRESHOLD_SHIFT		24
+#define FIFO_THRESHOLD_MASK		(0x7 << FIFO_THRESHOLD_SHIFT)
+#define RX_FIFO_THRESHOLD_DEFAULT	(0x2 << FIFO_THRESHOLD_SHIFT)
+#define DMA_ENABLE_MASK			(1 << 31)
+#define DMA_ENABLE			(1 << 31)
+
+/* Bits in channel TX control register */
+#define TX_FIFO_THRESHOLD_DEFAULT (0x6 << FIFO_THRESHOLD_SHIFT)
+#define TX_START_LEVEL_SHIFT	27
+#define TX_START_LEVEL_MASK	(0x7 << TX_START_LEVEL_SHIFT)
+#define TX_START_LEVEL_DEFAULT	(0x4 << TX_START_LEVEL_SHIFT)
+
+/* Bits in descriptors */
+#define RX_DESCB_LENGT_MASK	(0xFFF)
+#define RX_DESCB_FIFO_ERR	(1 << 16)
+#define RX_DESCB_SIZE_ERR	(1 << 17)
+#define RX_DESCB_CRC_ERR	(1 << 18)
+#define RX_DESCB_OCTET_ERR	(1 << 19)
+#define RX_DESCB_TRANSFER	(1 << 31)
+
+#define TX_DESCB_LENGT_MASK	(0xFFF)
+#define TX_DESCB_FIFO_ERR	(1 << 16)
+#define TX_DESCB_TRANSFER	(1 << 31)
+
+/* interface to channel defines: */
+#define IF_TO_CH(x) (x)
+#define CH_TO_IF(x) (x)
+
+#define DESCRIPTORS_PER_CHANNEL	8
+#define TX_TIMEOUT	(1*HZ)	/* 1 sec in jiffies */
+
+struct etp_netdev_priv {
+	void *if_ptr;		/* General purpose pointer (used by SPPP) */
+	struct etp_channel_private *cp;
+};
+
+#define MAX_SLOTS  65535
+#define MIN_SLOTS  0x8
+#define SLOT_SIZE  0x100
+
+#define E1_TIMESLOTS_PER_CHANNEL  32
+struct e1_frame {
+	uint8_t e1_timeslot[E1_TIMESLOTS_PER_CHANNEL];
+};
+
+#define FRAMES_IN_SLOT 8
+struct slot_struct {
+	struct e1_frame e1_frame[FRAMES_IN_SLOT];
+};
+
+#define ETP_TIMER (HZ > 1000 / DESCRIPTORS_PER_CHANNEL)
+
+struct rx_descriptor {
+	struct rxdesc __iomem *descriptor;
+	struct sk_buff *skb;
+	DECLARE_PCI_UNMAP_ADDR(address)
+};
+
+struct tx_descriptor {
+	struct txdesc __iomem *descriptor;
+	struct sk_buff *skb;
+	DECLARE_PCI_UNMAP_ADDR(address)
+};
+
+struct etp_channel_private {
+	struct etp_device_private *this_dev_priv;
+	struct net_device *this_netdev;
+	struct napi_struct napi;
+	bool interrupt; /* A reception or transmission event to handle? */
+	unsigned char channel_number;	/* channel number inside a device */
+	unsigned char device_number;
+	uint32_t __iomem *reg_ch_rxctrl;
+	struct rx_descriptor rx_descriptor[DESCRIPTORS_PER_CHANNEL];
+	uint32_t __iomem *reg_ch_txctrl;
+	struct tx_descriptor tx_descriptor[DESCRIPTORS_PER_CHANNEL];
+/* ------------ hdlc mode specific: ------------- */
+	uint32_t hdlc_mode_g704_used_timeslots;
+	unsigned char hdlc_mode;	/* HDLC_MODE_XXXX */
+	/* last or next sent descriptor written by etp_netdev_start_xmit */
+	unsigned char last_tx_desc_transmitted;
+/* ------------ timeslot mode specific: ------------- */
+	unsigned short tx_slots; /* 8 - */
+/* ------------- syncppp specific: ----------------- */
+	struct ppp_device pppdevice;
+#if ETP_TIMER
+	struct timer_list timer;
+#endif
+	struct slot_struct *rx;
+	dma_addr_t rx_address;
+	void (*rx_callback) (unsigned device,
+			     unsigned interface,
+			     unsigned read,
+			     const struct slot_struct *rx);
+	unsigned short rx_slots; /* 8 - */
+	unsigned short last_rx_slot_received;
+	/* last or next received descriptor */
+	unsigned char last_rx_desc_received;
+	unsigned char last_tx_desc_released; /* last tx descriptor released */
+	unsigned short last_tx_slot_transmitted;
+	struct slot_struct *tx;
+	dma_addr_t tx_address;
+	void (*tx_callback) (unsigned device,
+			     unsigned interface,
+			     unsigned written,
+			     struct slot_struct *tx);
+	atomic_t owner; /* Owner (0, 1 or unowned) of callbacks. */
+};
+
+/**
+ * Locking order: 1 struct etp_device_private idt[0]
+ *		  2 struct etp_device_private idt[1]
+ *		  3 struct etp_interface_private semaphore e1_00
+ *		  ...
+ *		  66 struct etp_interface_private semaphore e1_63
+ *		  67 rtnl_lock();
+ *		  68 struct etp_device_private mutex
+ **/
+
+struct etp_interface_private {
+	struct etp_channel_private ch_priv;
+	struct rw_semaphore semaphore;
+	uint32_t tx_clock_source;
+	/* The updates of the next word are synchronized with rtnl_lock(): */
+	unsigned char if_mode;
+	bool los; /* Loss of signal? */
+
+	/* interface specific register locations: */
+	uint32_t __iomem *reg_if_rxctrl;
+	uint32_t __iomem *reg_if_txctrl;
+	uint32_t __iomem *reg_if_rxctrl1;
+	uint32_t __iomem *reg_if_txctrl1;
+};
+
+enum { ETP_CALLBACKS = 2 };
+typedef void (*etp_idt_callback_t) (unsigned device);
+
+struct etp_device_private {
+	struct work_struct status_work;
+	struct mutex idt; /* The next word is written with mutex locked. */
+	unsigned char number; /* The number of the card. */
+	unsigned char run[ETP_CALLBACKS]; /* Run callback with index? Bitmap. */
+	etp_idt_callback_t idt_int_callback[ETP_CALLBACKS];
+	struct delayed_work led;
+	struct workqueue_struct *queue;
+	struct etp_interface_private interface_privates[INTERFACES_PER_DEVICE];
+
+	struct mutex mutex; /* IDT chip access mutex */
+	atomic_t reset;	/* 1: device unusable; 0: device usable. */
+	atomic_t interrupt; /* 1: IDT interrupt; 0: no IDT interrupt. */
+	uint32_t led_register_value;
+	spinlock_t lock2;
+	uint32_t reg_int_mask2;
+
+	struct pci_dev *pci_dev;	/* this PCI device */
+	uint8_t __iomem *ioaddr;
+	spinlock_t lock0;
+	uint32_t reg_int_mask0;
+};
+
+extern unsigned get_led(const struct etp_interface_private *ip);
+
+extern struct etp_device_private **etp_devices;
+
+static inline struct etp_device_private *get_dev_priv(unsigned device)
+{
+	struct etp_device_private *card;
+	rcu_read_lock();
+	card = rcu_dereference(etp_devices[device]);
+	rcu_read_unlock();
+	return card;
+}
+
+static inline
+struct etp_interface_private *this_if_priv(const struct
etp_channel_private *cp)
+{
+	return container_of(cp, struct etp_interface_private, ch_priv);
+}
+
+static inline unsigned device_number(const struct etp_device_private *dp)
+{
+	return dp->number;
+}
+
+/* kernel interface: struct to be used when registering callback functions: */
+
+struct etp_callback_struct {
+	void (*rx_callback) (unsigned device,
+			     unsigned interface,
+			     unsigned read,
+			     const struct slot_struct *buffer);
+	void (*tx_callback) (unsigned device,
+			     unsigned interface,
+			     unsigned written,
+			     struct slot_struct *buffer);
+	void (*idt_int_callback) (unsigned device);
+	unsigned device, interface;
+	bool index;
+};
+
+/**
+ * Functions callable from inside kernel, i.e.  kernel interface functions.
+ * Unless otherwise stated, the functions return 0 on success.
+ **/
+
+static inline struct etp_device_private *
+this_device_priv(const struct etp_channel_private *cp)
+{
+	return cp->this_dev_priv;
+}
+
+static inline
+struct etp_device_private *this_dev_priv(const struct
etp_interface_private *ip)
+{
+	return this_device_priv(&ip->ch_priv);
+}
+
+static inline unsigned interface_number(const struct etp_interface_private *ip)
+{
+	return CH_TO_IF(ip->ch_priv.channel_number);
+}
+
+/* Registers callback fuctions. */
+extern int etp_register_callbacks(const struct etp_callback_struct *callback);
+
+/* Open interface (timeslot and stream mode only). */
+extern int etp_if_open(unsigned device,
+		       unsigned interface,
+		       unsigned if_mode,
+		       unsigned rx_slots,
+		       unsigned tx_slots);
+
+/**
+ * Set timeslot (true) or stream (false) mode for an interface that
is in stream
+ * or timeslot mode. Caller must hold rtnl_lock().
+ **/
+extern int etp_frame(unsigned device, unsigned interface, bool frame);
+
+/* Close interface (timeslot and stream mode only) */
+extern int etp_if_close(unsigned device, unsigned interface);
+
+/* Start transmitter (timeslotand stream mode only) */
+int etp_tx_on(unsigned device, unsigned interface);
+
+/* Stop transmitter (timeslot and stream mode only). */
+int etp_tx_off(unsigned device, unsigned interface);
+
+/* Start receiver (timeslot and stream mode only) */
+int etp_rx_on(unsigned device, unsigned interface);
+
+/* Stop receiver (timeslot and stream mode only) */
+int etp_rx_off(unsigned device, unsigned interface);
+
+/* Change settings of an interface. */
+int etp_if_settings(unsigned device,
+		    unsigned interface,
+		    uint32_t clock_source,
+		    unsigned hdlc_mode,	/* HDLC_MODE_XXX  */
+		    uint32_t hdlc_mode_g704_used_timeslots);
+
+/* Det output clock source. */
+int etp_ext_output_clock(unsigned device, uint32_t clock_source);
+
+/* Fine tune local clock frequency */
+int etp_nco_adjust(unsigned device, uint32_t nco_addend_value);
+
+extern unsigned etp_number;
+/* Ask the number of devices installed in the system. */
+static inline unsigned etp_number_devices(void)
+{
+	return etp_number;
+}
+
+/* Gets the current settings and status of a device */
+int etp_device_status_get(unsigned device,
+			  struct etp_device_status_struct *device_status);
+
+int etp_interface_status_get(unsigned device, unsigned interface,
+			     struct etp_interface_status_struct *status);
+
+extern uint32_t etp_rx_on_get(const struct etp_channel_private *cp);
+
+extern uint32_t etp_tx_on_get(const struct etp_channel_private *cp);
+
+void etp_down(struct etp_device_private *device);
+
+void etp_up(struct etp_device_private *device);
+
