@@ -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
@@ -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
13:21:20.452131629 +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
@@ -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);
+