[Pkg-voip-commits] r8816 - in /dahdi-linux/trunk/debian: changelog patches/chanmute patches/dahdi_linux_extra patches/oslec_include_2634 patches/series patches/uk_rotary patches/voicebus_sem_h_2635 patches/xpp_usb_buffer_2635

tzafrir at alioth.debian.org tzafrir at alioth.debian.org
Mon Mar 7 10:15:00 UTC 2011


Author: tzafrir
Date: Mon Mar  7 10:14:41 2011
New Revision: 8816

URL: http://svn.debian.org/wsvn/pkg-voip/?sc=1&rev=8816
Log:
* New Upstream release: 2.4.1
  - Patch uk_rotary dropped: merged upstream.
  - Patch oslec_include_2634 dropped: merged upstream.
  - Patch xpp_usb_buffer_2635 dropped: merged upstream.
  - Patch voicebus_sem_h_2635 dropped: merged upstream.

Removed:
    dahdi-linux/trunk/debian/patches/oslec_include_2634
    dahdi-linux/trunk/debian/patches/uk_rotary
    dahdi-linux/trunk/debian/patches/voicebus_sem_h_2635
    dahdi-linux/trunk/debian/patches/xpp_usb_buffer_2635
Modified:
    dahdi-linux/trunk/debian/changelog
    dahdi-linux/trunk/debian/patches/chanmute
    dahdi-linux/trunk/debian/patches/dahdi_linux_extra
    dahdi-linux/trunk/debian/patches/series

Modified: dahdi-linux/trunk/debian/changelog
URL: http://svn.debian.org/wsvn/pkg-voip/dahdi-linux/trunk/debian/changelog?rev=8816&op=diff
==============================================================================
--- dahdi-linux/trunk/debian/changelog (original)
+++ dahdi-linux/trunk/debian/changelog Mon Mar  7 10:14:41 2011
@@ -1,3 +1,13 @@
+dahdi-linux (1:2.4.1+dfsg-1) UNRELEASED; urgency=low
+
+  * New Upstream release.
+    - Patch uk_rotary dropped: merged upstream.
+    - Patch oslec_include_2634 dropped: merged upstream. 
+    - Patch xpp_usb_buffer_2635 dropped: merged upstream.
+    - Patch voicebus_sem_h_2635 dropped: merged upstream.
+
+ -- Tzafrir Cohen <tzafrir at debian.org>  Mon, 07 Mar 2011 12:01:55 +0200
+
 dahdi-linux (1:2.3.0.1+dfsg-2) unstable; urgency=medium
 
   [ Faidon Liambotis ]

Modified: dahdi-linux/trunk/debian/patches/chanmute
URL: http://svn.debian.org/wsvn/pkg-voip/dahdi-linux/trunk/debian/patches/chanmute?rev=8816&op=diff
==============================================================================
--- dahdi-linux/trunk/debian/patches/chanmute (original)
+++ dahdi-linux/trunk/debian/patches/chanmute Mon Mar  7 10:14:41 2011
@@ -6,12 +6,9 @@
 whose audio is not useful. Currently only used by xpp drivers, and
 disabled by default by upstream.
 
-Also explicitly disable DAHDI_AUDIO_NOTIFY that is still not well-tested
-(does nothing if OPTIMIZE_CHANMUTE is not set).
-
 --- a/include/dahdi/dahdi_config.h
 +++ b/include/dahdi/dahdi_config.h
-@@ -176,12 +176,12 @@
+@@ -176,7 +176,7 @@
  /*
   * Skip processing PCM if low-level driver won't use it anyway
   */
@@ -20,9 +17,3 @@
  
  
  /*
-  * Pass DAHDI_AUDIOMODE to channel driver as well
-  */
--#define	DAHDI_AUDIO_NOTIFY
-+/* #define	DAHDI_AUDIO_NOTIFY */
- 
- #endif

Modified: dahdi-linux/trunk/debian/patches/dahdi_linux_extra
URL: http://svn.debian.org/wsvn/pkg-voip/dahdi-linux/trunk/debian/patches/dahdi_linux_extra?rev=8816&op=diff
==============================================================================
--- dahdi-linux/trunk/debian/patches/dahdi_linux_extra (original)
+++ dahdi-linux/trunk/debian/patches/dahdi_linux_extra Mon Mar  7 10:14:41 2011
@@ -1,36 +1,2996 @@
 Subject: dahdi-extra: out-of-tree DAHDI drivers 
-Origin: http://git.tzafrir.org.il/?p=dahdi-extra.git 
+Origin: http://gitorious.org/dahdi-extra 
 Forwarded: No 
-Last-Update: 2010-04-19 
+Last-Update: 2011-03-07 
  
 This patch includes a number of out-of-tree DAHDI drivers from the 
 dahdi-extra repository. They are all out-of-tree and are highly likely 
  not to be included in DAHDI-linux in the forseeable future. 
  
-Git-Commit: dc5f7b425aaca0db635a54c96d6e4b90212d94d9 
+Git-Commit: 0343810f314e7d934aaa7dde1e2e6d3ea6777251 
+Dahdi: tags/2.4.1 
 ---
 
---- a/drivers/dahdi/Kbuild
-+++ b/drivers/dahdi/Kbuild
-@@ -1,9 +1,15 @@
+diff -urN dahdi-svn-orig/drivers/dahdi/ap400/ap400_drv.c dahdi-svn-new/drivers/dahdi/ap400/ap400_drv.c
+--- dahdi-svn-orig/drivers/dahdi/ap400/ap400_drv.c	1970-01-01 02:00:00.000000000 +0200
++++ dahdi-svn-new/drivers/dahdi/ap400/ap400_drv.c	2011-03-07 11:52:51.411050187 +0200
+@@ -0,0 +1,2363 @@
++/*
++ * AP4XX PCI Card Driver
++ *
++ * Written by Ronaldo Valiati <aligera at aligera.com.br>
++ *
++ * Based on previous works, designs, and architectures conceived and
++ * written by Jim Dixon <jim at lambdatel.com> and Mark Spencer <markster at digium.com>.
++ *
++ * Copyright (C) 2001 Jim Dixon / Zapata Telephony.
++ * Copyright (C) 2001-2005, Digium, Inc.
++ *
++ * 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/kernel.h>
++#include <linux/errno.h>
++#include <linux/module.h>
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <linux/sched.h>
++#include <linux/interrupt.h>
++#include <linux/time.h>
++#include <linux/delay.h>
++#include <linux/proc_fs.h>
++#include <dahdi/kernel.h>
++#include <linux/moduleparam.h>
++
++#include "ap400.h"
++
++//#define AP400_DEBUG
++#ifdef AP400_DEBUG
++#define PDEBUG(fmt, args...) { \
++	printk(KERN_DEBUG "AP400 (%d): ",__LINE__); \
++	printk(fmt "\n", ## args); \
++}
++#else
++#define PDEBUG(fmt, args...)
++#endif
++
++/*
++ * Tasklets provide better system interactive response at the cost of the
++ * possibility of losing a frame of data at very infrequent intervals.  If
++ * you are more concerned with the performance of your machine, enable the
++ * tasklets.  If you are strict about absolutely no drops, then do not enable
++ * tasklets.
++ */
++
++/* #define ENABLE_TASKLETS */
++
++
++/* Work queues are a way to better distribute load on SMP systems */
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
++/*
++ * Work queues can significantly improve performance and scalability
++ * on multi-processor machines, but requires bypassing some kernel
++ * API's, so it's not guaranteed to be compatible with all kernels.
++ */
++/* #define ENABLE_WORKQUEUES */
++#endif
++
++/* Enable HDLC support by hardware */
++#ifdef AP400_HDLC
++#include "ap400_hdlc/ap400_hdlc.c"
++#endif
++
++//#define APEC_SUPPORT
++#ifdef APEC_SUPPORT
++#include "apec.h"
++#endif
++
++/* Workarounds */
++#ifndef IRQF_SHARED
++#define IRQF_SHARED		SA_SHIRQ
++#endif
++#ifndef IRQF_DISABLED
++#define IRQF_DISABLED		SA_INTERRUPT
++#endif
++#ifndef __iomem
++#define __iomem
++#endif
++
++/* Enable prefetching may help performance */
++#define ENABLE_PREFETCH
++
++/* Define to get more attention-grabbing but slightly more I/O using
++   alarm status */
++#define FANCY_ALARM
++
++#define DEBUG_MAIN 		(1 << 0)
++#define DEBUG_DTMF 		(1 << 1)
++#define DEBUG_REGS 		(1 << 2)
++#define DEBUG_TSI  		(1 << 3)
++#define DEBUG_ECHOCAN 		(1 << 4)
++#define DEBUG_RBS 		(1 << 5)
++#define DEBUG_FRAMER		(1 << 6)
++
++static int clock_source = -1;
++static int tdm_loop = 0;
++static int apec_enable = 1;
++module_param(tdm_loop, int, 0600);
++module_param(apec_enable, int, 0600);
++
++#ifdef ENABLE_WORKQUEUES
++#include <linux/cpumask.h>
++
++/* XXX UGLY!!!! XXX  We have to access the direct structures of the workqueue which
++  are only defined within workqueue.c because they don't give us a routine to allow us
++  to nail a work to a particular thread of the CPU.  Nailing to threads gives us substantially
++  higher scalability in multi-CPU environments though! */
++
++/*
++ * The per-CPU workqueue (if single thread, we always use cpu 0's).
++ *
++ * The sequence counters are for flush_scheduled_work().  It wants to wait
++ * until until all currently-scheduled works are completed, but it doesn't
++ * want to be livelocked by new, incoming ones.  So it waits until
++ * remove_sequence is >= the insert_sequence which pertained when
++ * flush_scheduled_work() was called.
++ */
++
++struct cpu_workqueue_struct {
++
++	spinlock_t lock;
++
++	long remove_sequence;	/* Least-recently added (next to run) */
++	long insert_sequence;	/* Next to add */
++
++	struct list_head worklist;
++	wait_queue_head_t more_work;
++	wait_queue_head_t work_done;
++
++	struct workqueue_struct *wq;
++	task_t *thread;
++
++	int run_depth;		/* Detect run_workqueue() recursion depth */
++} ____cacheline_aligned;
++
++/*
++ * The externally visible workqueue abstraction is an array of
++ * per-CPU workqueues:
++ */
++struct workqueue_struct {
++	struct cpu_workqueue_struct cpu_wq[NR_CPUS];
++	const char *name;
++	struct list_head list; 	/* Empty if single thread */
++};
++
++/* Preempt must be disabled. */
++static void __ap4_queue_work(struct cpu_workqueue_struct *cwq,
++			 struct work_struct *work)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&cwq->lock, flags);
++	work->wq_data = cwq;
++	list_add_tail(&work->entry, &cwq->worklist);
++	cwq->insert_sequence++;
++	wake_up(&cwq->more_work);
++	spin_unlock_irqrestore(&cwq->lock, flags);
++}
++
++/*
++ * Queue work on a workqueue. Return non-zero if it was successfully
++ * added.
++ *
++ * We queue the work to the CPU it was submitted, but there is no
++ * guarantee that it will be processed by that CPU.
++ */
++static inline int ap4_queue_work(struct workqueue_struct *wq, struct work_struct *work, int cpu)
++{
++	int ret = 0;
++
++	if (!test_and_set_bit(0, &work->pending)) {
++		BUG_ON(!list_empty(&work->entry));
++		__ap4_queue_work(wq->cpu_wq + cpu, work);
++		ret = 1;
++	}
++	return ret;
++}
++
++#endif
++
++static int debug=0;
++static int timingcable;
++static int highestorder;
++static int t1e1override = -1;
++static int j1mode = 0;
++static int loopback = 0;
++static int alarmdebounce = 0;
++
++/* Enabling bursting can more efficiently utilize PCI bus bandwidth, but
++   can also cause PCI bus starvation, especially in combination with other
++   aggressive cards.  Please note that burst mode has no effect on CPU
++   utilization / max number of calls / etc. */
++static int noburst = 1;
++static int debugslips = 0;
++static int polling = 0;
++
++#ifdef FANCY_ALARM
++static int altab[] = {
++0, 0, 0, 1, 2, 3, 4, 6, 8, 9, 11, 13, 16, 18, 20, 22, 24, 25, 27, 28, 29, 30, 31, 31, 32, 31, 31, 30, 29, 28, 27, 25, 23, 22, 20, 18, 16, 13, 11, 9, 8, 6, 4, 3, 2, 1, 0, 0,
++};
++#endif
++
++#define FLAG_STARTED (1 << 0)
++#define FLAG_NMF (1 << 1)
++#define FLAG_SENDINGYELLOW (1 << 2)
++
++#define	TYPE_T1	1		/* is a T1 card */
++#define	TYPE_E1	2		/* is an E1 card */
++#define TYPE_J1 3		/* is a running J1 */
++
++struct devtype {
++	char *desc;
++	unsigned int flags;
++};
++
++static struct devtype ap401  = { "Aligera AP401", 0 };
++static struct devtype ap402  = { "Aligera AP402", 0 };
++static struct devtype ap404  = { "Aligera AP404", 0 };
++static struct devtype ape401  = { "Aligera APE401", 0 };
++static struct devtype ape402  = { "Aligera APE402", 0 };
++static struct devtype ape404  = { "Aligera APE404", 0 };
++
++struct ap4;
++
++struct ap4_span {
++	struct ap4 *owner;
++	unsigned int *writechunk;					/* Double-word aligned write memory */
++	unsigned int *readchunk;					/* Double-word aligned read memory */
++	int spantype;		/* card type, T1 or E1 or J1 */
++	int sync;
++	int psync;
++	int alarmtimer;
++	int redalarms;
++	int notclear;
++	int alarmcount;
++	int spanflags;
++	int syncpos;
++	int e1check;			/* E1 check */
++	int reload_cas;
++	unsigned char casbuf[15];
++	unsigned int slipcount;
++	struct dahdi_span span;
++	unsigned char txsigs[16];	/* Transmit sigs */
++	int loopupcnt;
++	int loopdowncnt;
++	unsigned char ec_chunk1[31][DAHDI_CHUNKSIZE]; /* first EC chunk buffer */
++	unsigned char ec_chunk2[31][DAHDI_CHUNKSIZE]; /* second EC chunk buffer */
++	int irqmisses;
++#ifdef ENABLE_WORKQUEUES
++	struct work_struct swork;
++#endif
++	struct dahdi_chan *chans[32];		/* Individual channels */
++};
++
++struct ap4_regs {
++	volatile u32 card_id;		// 00h R0
++	volatile u16 fpga_ver;		// 04h R1
++	volatile u16 span_num;		// 06h R1
++	u32 __unused;			// 08h R2
++	volatile u32 liu_config;	// 0Ch R3
++	volatile u32 e1_config;		// 10h R4
++	volatile u32 e1_status;		// 14h R5
++	volatile u32 leds;		// 18h R6
++	volatile u32 clock_source;	// 1Ch R7
++	u32 __unused3[8];		// 20h - 3Ch R8 - R15
++	volatile u32 echo_ctrl;		// 40h R16
++	volatile u32 echo_data;		// 44h R17
++	volatile u32 t1_status;		// 48h R18
++	volatile u32 t1_config;		// 4Ch R19
++};
++
++struct ap4 {
++	/* This structure exists one per card */
++	struct pci_dev *dev;		/* Pointer to PCI device */
++	struct ap4_regs *hw_regs;
++	unsigned int intcount;
++	int flag_1st_irq;
++	int num;			/* Which card we are */
++	int fpgaver;		/* version of FPGA */
++	int hwid;			/* hardware ID */
++	int globalconfig;	/* Whether global setup has been done */
++	int syncsrc;			/* active sync source */
++	struct ap4_span *tspans[4];	/* Individual spans */
++	int numspans;			/* Number of spans on the card */
++	int blinktimer[4];
++#ifdef FANCY_ALARM
++	int alarmpos[4];
++#endif
++	int irq;			/* IRQ used by device */
++	int order;			/* Order */
++	int flags;			/* Device flags */
++	int ledreg;				/* LED Register */
++	int e1recover;			/* E1 recovery timer */
++	unsigned long memaddr;		/* Base address of card */
++	unsigned long memlen;
++	volatile unsigned int *membase;	/* Base address of card */
++	int spansstarted;		/* number of spans started */
++	/* spinlock_t lock; */		/* lock context */
++	spinlock_t reglock;		/* lock register access */
++	volatile unsigned int *writechunk;	/* Double-word aligned write memory */
++	volatile unsigned int *readchunk;	/* Double-word aligned read memory */
++#ifdef ENABLE_WORKQUEUES
++	atomic_t worklist;
++	struct workqueue_struct *workq;
++#else
++#ifdef ENABLE_TASKLETS
++	int taskletrun;
++	int taskletsched;
++	int taskletpending;
++	int taskletexec;
++	int txerrors;
++	struct tasklet_struct ap4_tlet;
++#endif
++#endif
++	unsigned int passno;	/* number of interrupt passes */
++	struct devtype *dt;
++	char *variety;
++	int last0;		/* for detecting double-missed IRQ */
++	int checktiming;	/* Set >0 to cause the timing source to be checked */
++#ifdef AP400_HDLC
++	struct card_s *hdlc_card;
++#endif
++#ifdef APEC_SUPPORT
++	int apec_enable;
++	struct apec_s *apec;
++#endif
++};
++
++
++static void __set_clear(struct ap4 *wc, int span);
++static int ap4_startup(struct dahdi_span *span);
++static int ap4_shutdown(struct dahdi_span *span);
++static int ap4_rbsbits(struct dahdi_chan *chan, int bits);
++static int ap4_maint(struct dahdi_span *span, int cmd);
++static int ap4_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long data);
++static void __ap4_set_timing_source(struct ap4 *wc, int unit);
++static void __ap4_check_alarms(struct ap4 *wc, int span);
++static void __ap4_check_sigbits(struct ap4 *wc, int span);
++
++
++#define AP_ACTIVATE	(1 << 12)
++
++#define AP_OFF	(0)
++#define AP_ON	(1)
++
++#define MAX_AP4_CARDS 64
++
++#ifdef ENABLE_TASKLETS
++static void ap4_tasklet(unsigned long data);
++#endif
++
++static struct ap4 *cards[MAX_AP4_CARDS];
++
++//#define ap_debugk(fmt,args...) printk("ap400 -> %s: "fmt, __PRETTY_FUNCTION__, ##args)
++#define ap_debugk(fmt,args...)
++
++//#define TIMER_DEBUG	1
++
++#ifdef TIMER_DEBUG
++struct timer_list ap4xx_opt_timer;
++unsigned int delay = 1000;
++module_param(delay, uint, S_IRUGO);
++#endif
++
++#define PCI_DEVICE_ID_AP4XX		0x1004
++
++static inline void __ap4_set_led(struct ap4 *wc, int span, int color)
++{
++	wc->ledreg &= ~(AP_ON << span);
++	wc->ledreg |= (color << span);
++	*(wc->membase+AP_LEDS_REG) &= ~0x0000000F;
++	*(wc->membase+AP_LEDS_REG) |= ((wc->ledreg)&0x0F);
++}
++
++static inline void ap4_activate(struct ap4 *wc)
++{
++	wc->ledreg |= AP_ACTIVATE;
++}
++
++static void __set_clear(struct ap4 *wc, int span)
++{
++	int i,j;
++	int oldnotclear;
++	unsigned short val=0;
++	struct ap4_span *ts = wc->tspans[span];
++
++	oldnotclear = ts->notclear;
++	if (ts->spantype == TYPE_T1) {
++		for (i=0;i<24;i++) {
++			j = (i/8);
++			if (ts->span.chans[i]->flags & DAHDI_FLAG_CLEAR) {
++				val |= 1 << (7 - (i % 8));
++				ts->notclear &= ~(1 << i);
++			} else
++				ts->notclear |= (1 << i);
++			if ((i % 8)==7) {
++				val = 0;
++			}
++		}
++	} else {
++		for (i=0;i<31;i++) {
++			if (ts->span.chans[i]->flags & DAHDI_FLAG_CLEAR)
++				ts->notclear &= ~(1 << i);
++			else
++				ts->notclear |= (1 << i);
++		}
++	}
++}
++
++#ifdef APEC_SUPPORT
++
++#define APEC_CTRL_RESET		0x80000000
++#define APEC_CTRL_DDR_NCKE	0x40000000
++#define APEC_CTRL_EC_DISABLE	0x20000000
++#define APEC_CTRL_DAS		0x00080000
++#define APEC_CTRL_RD		0x00040000
++#define APEC_CTRL_REQ		0x00020000
++#define APEC_CTRL_READY		0x00010000
++
++#define APEC_ACCESS_TIMEOUT	1000
++
++static inline u16 oct_raw_read (struct ap4_regs *regs, unsigned short addr)
++{
++	unsigned short data;
++	// Poll ready bit
++	while ((regs->echo_ctrl & APEC_CTRL_READY) == 0);
++	// Write control bits and address
++	regs->echo_ctrl = APEC_CTRL_RD | APEC_CTRL_REQ | (addr & 0xFFFF);
++	while ((regs->echo_ctrl & APEC_CTRL_READY) == 0);
++	data = regs->echo_data & 0xFFFF;
++	//PDEBUG("Raw Read 0x%04hX @ 0x%08X", data, addr);
++	return data;
++}
++
++static inline void oct_raw_write (struct ap4_regs *regs, unsigned short addr,
++							unsigned short data)
++{
++	// Poll ready bit
++	while ((regs->echo_ctrl & APEC_CTRL_READY) == 0);
++	// Write data, then control bits and address
++	regs->echo_data = data & 0xFFFF;
++	regs->echo_ctrl = APEC_CTRL_REQ | (addr & 0xFFFF);
++	// Poll ready bit
++	while ((regs->echo_ctrl & APEC_CTRL_READY) == 0);
++	//PDEBUG("Raw Write 0x%04hX @ 0x%08X", data, addr);
++	//oct_raw_read(regs, addr);
++}
++
++static inline int oct_ext_wait (struct ap4_regs *regs)
++{
++	int i = APEC_ACCESS_TIMEOUT;
++	while ((oct_raw_read(regs, 0x0) & 0x100) && (i-- > 0));
++	if (i == -1) {
++		printk(KERN_WARNING "Wait access_req timeout\n");
++		return -1;
++	}
++	return 0;
++}
++
++static inline u16 oct_ind_read (struct ap4_regs *regs, unsigned int addr)
++{
++	// Poll access_req bit
++	if (oct_ext_wait(regs))
++		return 0;
++	// Write extended indirect registers
++	oct_raw_write(regs, 0x8, (addr >> 20) & 0x1FFF);
++	oct_raw_write(regs, 0xA, (addr >> 4) & 0xFFFF);
++	oct_raw_write(regs, 0x0, ((addr & 0xE) << 8) | 0x101);
++	// Poll access_req bit
++	if (oct_ext_wait(regs))
++		return 0;
++	// Return data
++	return oct_raw_read(regs, 0x4);
++}
++
++static inline void oct_ind_write (struct ap4_regs *regs, unsigned int addr,
++							unsigned short data)
++{
++	// Poll access_req bit
++	if (oct_ext_wait(regs))
++		return;
++	oct_raw_write(regs, 0x8, (addr >> 20) & 0x1FFF);
++	oct_raw_write(regs, 0xA, (addr >> 4) & 0xFFFF);
++	oct_raw_write(regs, 0x4, data);
++	oct_raw_write(regs, 0x0, ((addr & 0xE) << 8) | 0x3101);
++	// Poll access_req bit
++	if (oct_ext_wait(regs))
++		return;
++}
++
++static inline u16 oct_dir_read (struct ap4_regs *regs, unsigned int addr)
++{
++	// Poll access_req bit
++	if (oct_ext_wait(regs))
++		return 0;
++	// Write extended direct registers
++	oct_raw_write(regs, 0x8, (addr >> 20) & 0x1FFF);
++	oct_raw_write(regs, 0xA, (addr >> 4) & 0xFFFF);
++	oct_raw_write(regs, 0x0, 0x1);
++	regs->echo_ctrl = APEC_CTRL_DAS | APEC_CTRL_RD | APEC_CTRL_REQ | (addr & 0xFFFF);
++	while ((regs->echo_ctrl & APEC_CTRL_READY) == 0);
++	// Return data
++	return regs->echo_data;
++}
++
++static inline void oct_dir_write (struct ap4_regs *regs, unsigned int addr,
++							unsigned short data)
++{
++	// Poll access_req bit
++	if (oct_ext_wait(regs))
++		return;
++	// Write extended direct registers
++	oct_raw_write(regs, 0x8, (addr >> 20) & 0x1FFF);
++	oct_raw_write(regs, 0xA, (addr >> 4) & 0xFFFF);
++	oct_raw_write(regs, 0x0, 0x3001);
++	regs->echo_data = data & 0xFFFF;
++	regs->echo_ctrl = APEC_CTRL_DAS | APEC_CTRL_REQ | (addr & 0xFFFF);
++	while ((regs->echo_ctrl & APEC_CTRL_READY) == 0);
++}
++
++
++unsigned int oct_read (void *card, unsigned int addr)
++{
++	struct ap4 *wc = card;
++	int flags;
++	unsigned short data;
++	spin_lock_irqsave(&wc->reglock, flags);
++	data = oct_ind_read(wc->hw_regs, addr);
++	spin_unlock_irqrestore(&wc->reglock, flags);
++	PDEBUG("Read 0x%04hX @ 0x%08X", data, addr);
++	return data;
++}
++
++void oct_write (void *card, unsigned int addr, unsigned int data)
++{
++	struct ap4 *wc = card;
++	int flags;
++	spin_lock_irqsave(&wc->reglock, flags);
++	oct_ind_write(wc->hw_regs, addr, data);
++	spin_unlock_irqrestore(&wc->reglock, flags);
++	PDEBUG("Write 0x%04hX @ 0x%08X", data, addr);
++}
++
++static int ap4_apec_init(struct ap4 *wc)
++{
++	int laws[4];
++	int i;
++	unsigned int apec_capacity;
++	struct firmware embedded_firmware;
++	const struct firmware *firmware = &embedded_firmware;
++#if !defined(HOTPLUG_FIRMWARE)
++	extern void _binary_OCT6104E_64D_ima_size;
++	extern u8 _binary_OCT6104E_64D_ima_start[];
++	extern void _binary_OCT6104E_128D_ima_size;
++	extern u8 _binary_OCT6104E_128D_ima_start[];
++#else
++	static const char oct64_firmware[] = "OCT6104E-64D.ima";
++	static const char oct128_firmware[] = "OCT6104E-128D.ima";
++#endif
++
++	// Enable DDR and Reset Octasic
++	wc->hw_regs->echo_ctrl |= APEC_CTRL_RESET;
++	wc->hw_regs->echo_ctrl |= APEC_CTRL_DDR_NCKE;
++	udelay(500);
++	wc->hw_regs->echo_ctrl &= APEC_CTRL_RESET;
++	wc->hw_regs->echo_ctrl &= APEC_CTRL_DDR_NCKE;
++	wc->hw_regs->echo_ctrl &= APEC_CTRL_EC_DISABLE;
++
++	/* Setup alaw vs ulaw rules */
++	for (i = 0; i < wc->numspans; i++) {
++		if (wc->tspans[i]->span.channels > 24)
++			laws[i] = 1;	// E1: alaw
++		else
++			laws[i] = 0;	// T1: ulaw
++	}
++
++	switch ((apec_capacity = apec_capacity_get(wc))) {
++	case 64:
++#if defined(HOTPLUG_FIRMWARE)
++		if ((request_firmware(&firmware, oct64_firmware, &wc->dev->dev) != 0) ||
++		    !firmware) {
++			printk("%s: firmware %s not available from userspace\n",
++					wc->variety, oct64_firmware);
++			return -1;
++		}
++#else
++		embedded_firmware.data = _binary_OCT6104E_64D_ima_start;
++		/* Yes... this is weird. objcopy gives us a symbol containing
++		   the size of the firmware, not a pointer to a variable containing
++		   the size. The only way we can get the value of the symbol
++		   is to take its address, so we define it as a pointer and
++		   then cast that value to the proper type.
++		*/
++		embedded_firmware.size = (size_t) &_binary_OCT6104E_64D_ima_size;
++#endif
++		break;
++	case 128:
++#if defined(HOTPLUG_FIRMWARE)
++		if ((request_firmware(&firmware, oct128_firmware, &wc->dev->dev) != 0) ||
++		    !firmware) {
++			printk("%s: firmware %s not available from userspace\n",
++					wc->variety, oct128_firmware);
++			return -1;
++		}
++#else
++		embedded_firmware.data = _binary_OCT6104E_128D_ima_start;
++		/* Yes... this is weird. objcopy gives us a symbol containing
++		   the size of the firmware, not a pointer to a variable containing
++		   the size. The only way we can get the value of the symbol
++		   is to take its address, so we define it as a pointer and
++		   then cast that value to the proper type.
++		*/
++		embedded_firmware.size = (size_t) &_binary_OCT6104E_128D_ima_size;
++#endif
++		break;
++	default:
++		printk(KERN_INFO "Unsupported channel capacity found on"
++				"echo cancellation module (%d).\n", apec_capacity);
++		return -1;
++	}
++
++	if (!(wc->apec = apec_init(wc, laws, wc->numspans, firmware))) {
++		printk(KERN_WARNING "APEC: Failed to initialize\n");
++		if (firmware != &embedded_firmware)
++			release_firmware(firmware);
++		return -1;
++	}
++
++	if (firmware != &embedded_firmware)
++		release_firmware(firmware);
++
++	printk(KERN_INFO "APEC: Present and operational servicing %d span(s)\n", wc->numspans);
++	return 0;
++}
++
++void ap4_apec_release(struct ap4 *wc)
++{
++	// Disabel DDR and reset Octasic
++	wc->hw_regs->echo_ctrl |= APEC_CTRL_RESET;
++	wc->hw_regs->echo_ctrl |= APEC_CTRL_DDR_NCKE;
++	wc->hw_regs->echo_ctrl |= APEC_CTRL_EC_DISABLE;
++	if (wc->apec)
++		apec_release(wc->apec);
++}
++
++
++static int ap4_echocan(struct dahdi_chan *chan, int eclen)
++{
++	struct ap4 *wc = chan->pvt;
++	int channel;
++
++	if (!wc->apec)
++		return -ENODEV;
++	if (debug)
++		printk(KERN_DEBUG "AP400: ap4_echocan @ Span %d Channel %d Length: %d\n",
++				chan->span->offset, chan->chanpos, eclen);
++	channel = (chan->chanpos << 2) | chan->span->offset;
++	apec_setec(wc->apec, channel, eclen);
++	return 0;
++}
++
++#endif // APEC_SUPPORT
++
++
++static int ap4_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long data)
++{
++	struct ap4 *wc = chan->pvt;
++	int span = 0;
++	int alarms = 0;
++	unsigned char c, e1_cfg;
++
++	switch(cmd) {
++		case AP4_GET_ALARMS:
++			if (copy_from_user(&span, (int *)data, sizeof(int)))
++				return -EFAULT;
++			// span starts in zero
++			span--;
++		if (wc->tspans[span]->spantype == TYPE_E1) {
++		        /* le status e configuracao do E1 */
++		        c = ((*(wc->membase+AP_E1_STATUS_REG))>>(8*span));
++		        e1_cfg = ((*(wc->membase+AP_E1_CONFIG_REG))>>(8*span));
++			if( c & AP_E1_LOS_STATUS) {
++				alarms = 0x01;
++			} else if( c & AP_E1_AIS_STATUS) {
++				alarms = 0x02;
++			} else if(!(c & AP_E1_BFAE_STATUS)) {
++				alarms = 0x04;
++				if (c & AP_E1_RAI_STATUS)
++					alarms |= 0x08;
++				// Erro de MFA: 00 - MFA desabilitado, 01 - erro de MFA, 10 - MFA OK
++				if ( (c & AP_E1_MFAE_STATUS) && (e1_cfg & AP_E1_CRCEN_CONFIG) )
++					alarms |= 0x10;
++				else if ( (!(c & AP_E1_MFAE_STATUS)) && (e1_cfg & AP_E1_CRCEN_CONFIG) )
++					alarms |= 0x20;
++				// Erro de CAS: 00 - desabilitado, 01 - erro de CAS, 10 - CAS OK
++				if ( (!(c & AP_E1_CAS_STATUS)) && (e1_cfg & AP_E1_PCM30_CONFIG))
++					alarms |= 0x40;
++				else if ( (c & AP_E1_CAS_STATUS) && (e1_cfg & AP_E1_PCM30_CONFIG))
++					alarms |= 0x80;
++			}
++		} else {
++			/* le status e configuracao do E1 */
++		        c = ((*(wc->membase+AP_E1_STATUS_REG))>>(8*span));
++		        if( c & AP_E1_LOS_STATUS)
++				alarms = 0x01;
++			else {
++			        c = wc->hw_regs->t1_status >> (8*span);
++			        if (!(c & AP4_T1_FRAME_SYNC))
++			        	alarms = 0x04;
++		        }
++		}
++			if(debug) printk("AP4_GET_ALARMS: span = %d, alarms = 0x%02x\n", span+1, alarms);
++			if (copy_to_user((int *)data, &alarms, sizeof(int)))
++				return -EFAULT;
++			break;
++
++		case AP4_GET_SLIPS:
++			if (copy_from_user(&span, (int *)data, sizeof(int)))
++				return -EFAULT;
++			// span starts in zero
++			span--;
++			if((span < wc->numspans) && (span >=0))
++				alarms = wc->tspans[span]->slipcount;
++			if(debug) printk("AP4_GET_SLIPS: span = %d, slips = 0x%02x\n", span+1, alarms);
++			if (copy_to_user((int *)data, &alarms, sizeof(int)))
++				return -EFAULT;
++			break;
++
++		default:
++			PDEBUG("%s: Unknown IOCTL CODE!", wc->variety);
++			return -ENOTTY;
++	}
++	return 0;
++}
++
++static inline struct ap4_span* ap4_span_from_span(struct dahdi_span *span) {
++	return container_of(span, struct ap4_span, span);
++}
++
++static int ap4_maint(struct dahdi_span *span, int cmd)
++{
++	struct ap4_span *ts = ap4_span_from_span(span);
++	struct ap4 *wc = ts->owner;
++
++
++	if (ts->spantype == TYPE_E1) {
++		switch(cmd) {
++		case DAHDI_MAINT_NONE:
++			printk("XXX Turn off local and remote loops E1 XXX\n");
++			*(wc->membase+AP_E1_CONFIG_REG) &= ~(AP_E1_LOOP_CONFIG<<((span->spanno-1)*8));
++			break;
++		case DAHDI_MAINT_LOCALLOOP:
++			printk("XXX Turn on local loopback E1 XXX\n");
++			break;
++		case DAHDI_MAINT_REMOTELOOP:
++			printk("XXX Turn on remote loopback E1 XXX\n");
++			break;
++		case DAHDI_MAINT_LOOPUP:
++			printk("XXX Turn on local loopback on E1 #%d instead of send loopup code XXX\n", span->spanno);
++			*(wc->membase+AP_E1_CONFIG_REG) |= (AP_E1_LOOP_CONFIG<<((span->spanno-1)*8));
++			break;
++		case DAHDI_MAINT_LOOPDOWN:
++			printk("XXX Turn on local loopback on E1 #%d instead of send loopdown code XXX\n", span->spanno);
++			*(wc->membase+AP_E1_CONFIG_REG) |= (AP_E1_LOOP_CONFIG<<((span->spanno-1)*8));
++			break;
++		case DAHDI_MAINT_LOOPSTOP:
++			printk("XXX Stop sending loop codes on E1 #%d XXX\n", span->spanno);
++			*(wc->membase+AP_E1_CONFIG_REG) &= ~(AP_E1_LOOP_CONFIG<<((span->spanno-1)*8));
++			break;
++		default:
++			printk("%s: Unknown E1 maint command: %d\n", wc->variety, cmd);
++			break;
++		}
++	} else {
++		switch(cmd) {
++	    case DAHDI_MAINT_NONE:
++			printk("XXX Turn off local and remote loops T1 XXX\n");
++			break;
++	    case DAHDI_MAINT_LOCALLOOP:
++			printk("XXX Turn on local loop and no remote loop XXX\n");
++			break;
++	    case DAHDI_MAINT_REMOTELOOP:
++			printk("XXX Turn on remote loopup XXX\n");
++			break;
++	    case DAHDI_MAINT_LOOPUP:
++			break;
++	    case DAHDI_MAINT_LOOPDOWN:
++			break;
++	    case DAHDI_MAINT_LOOPSTOP:
++			break;
++	    default:
++			printk("%s: Unknown T1 maint command: %d\n", wc->variety, cmd);
++			break;
++	   }
++    }
++	return 0;
++}
++
++static int ap4_rbsbits(struct dahdi_chan *chan, int bits)
++{
++	u_char m,c;
++	int k,n,b;
++	struct ap4 *wc = chan->pvt;
++	struct ap4_span *ts = wc->tspans[chan->span->offset];
++	unsigned long flags;
++	volatile unsigned int *writecas = (wc->membase+AP_CAS_BASE);
++	unsigned int allspansbits;
++
++	//ap_debugk("chan->channo = %d, int bits = 0x%08x\n", chan->channo, bits);
++	if(debug & DEBUG_RBS) printk("Setting bits to %d on channel %s\n", bits, chan->name);
++	spin_lock_irqsave(&wc->reglock, flags);
++	k = chan->span->offset;
++	if (ts->spantype == TYPE_E1) { /* do it E1 way */
++		if (chan->chanpos == 16) {
++			spin_unlock_irqrestore(&wc->reglock, flags);
++			return 0;
++		}
++		n = chan->chanpos - 1;
++		if (chan->chanpos > 15) n--;
++		b = (n % 15);
++		c = ts->txsigs[b];
++		m = (n / 15) << 2; /* nibble selector */
++		c &= (0xf << m); /* keep the other nibble */
++		c |= (bits & 0xf) << (4 - m); /* put our new nibble here */
++		ts->txsigs[b] = c;
++		/* monta a word de 32 bits com informacao de todos os spans */
++		allspansbits =  wc->tspans[0]->txsigs[b];
++		if (wc->numspans > 1) {
++			allspansbits |=	(wc->tspans[1]->txsigs[b] << 8);
++		}
++		if (wc->numspans == 4) {
++			allspansbits |=	(wc->tspans[2]->txsigs[b] << 16) |
++							(wc->tspans[3]->txsigs[b] << 24);
++		}
++		/* output them to the chip */
++		writecas[b] = allspansbits;
++		ap_debugk("escrito 0x%08x para ser transmitido pelo CAS (b = %d)\n", allspansbits, b);
++#if 0
++	} else if (ts->span.lineconfig & DAHDI_CONFIG_D4) {
++		n = chan->chanpos - 1;
++		b = (n/4);
++		c = ts->txsigs[b];
++		m = ((3 - (n % 4)) << 1); /* nibble selector */
++		c &= ~(0x3 << m); /* keep the other nibble */
++		c |= ((bits >> 2) & 0x3) << m; /* put our new nibble here */
++		ts->txsigs[b] = c;
++		  /* output them to the chip */
++		//__ap4_out( ... );
++	} else if (ts->span.lineconfig & DAHDI_CONFIG_ESF) {
++#endif
++	} else {
++		n = chan->chanpos - 1;
++		b = (n/2);
++		c = ts->txsigs[b];
++		m = ((n % 2) << 2); /* nibble selector */
++		c &= (0xf << m); /* keep the other nibble */
++		c |= (bits & 0xf) << (4 - m); /* put our new nibble here */
++		ts->txsigs[b] = c;
++		  /* output them to the chip */
++		/* monta a word de 32 bits com informacao de todos os spans */
++		allspansbits =  wc->tspans[0]->txsigs[b];
++		if (wc->numspans > 1) {
++			allspansbits |=	(wc->tspans[1]->txsigs[b] << 8);
++		}
++		if (wc->numspans == 4) {
++			allspansbits |=	(wc->tspans[2]->txsigs[b] << 16) |
++							(wc->tspans[3]->txsigs[b] << 24);
++		}
++		/* output them to the chip */
++		writecas[b] = allspansbits;
++		ap_debugk("escrito 0x%08x para ser transmitido pelo CAS (b = %d)\n", allspansbits, b);
++	}
++	spin_unlock_irqrestore(&wc->reglock, flags);
++	if (debug & DEBUG_RBS)
++		printk("Finished setting RBS bits\n");
++	return 0;
++}
++
++static int ap4_shutdown(struct dahdi_span *span)
++{
++	int tspan;
++	int wasrunning;
++	unsigned long flags;
++	struct ap4_span *ts = ap4_span_from_span(span);
++	struct ap4 *wc = ts->owner;
++
++	tspan = span->offset + 1;
++	if (tspan < 0) {
++		printk("%s: '%d' isn't us?\n", wc->variety, span->spanno);
++		return -1;
++	}
++
++	spin_lock_irqsave(&wc->reglock, flags);
++	wasrunning = span->flags & DAHDI_FLAG_RUNNING;
++
++	span->flags &= ~DAHDI_FLAG_RUNNING;
++	if (wasrunning)
++		wc->spansstarted--;
++	__ap4_set_led(wc, span->offset, AP_OFF);
++	if (((wc->numspans == 4) &&
++	    (!(wc->tspans[0]->span.flags & DAHDI_FLAG_RUNNING)) &&
++	    (!(wc->tspans[1]->span.flags & DAHDI_FLAG_RUNNING)) &&
++	    (!(wc->tspans[2]->span.flags & DAHDI_FLAG_RUNNING)) &&
++	    (!(wc->tspans[3]->span.flags & DAHDI_FLAG_RUNNING)))
++	    			||
++	    ((wc->numspans == 2) &&
++	    (!(wc->tspans[0]->span.flags & DAHDI_FLAG_RUNNING)) &&
++	    (!(wc->tspans[1]->span.flags & DAHDI_FLAG_RUNNING)))
++	    			||
++	    ((wc->numspans == 1) &&
++	    (!(wc->tspans[0]->span.flags & DAHDI_FLAG_RUNNING)))) {
++		/* No longer in use, disable interrupts */
++		printk("%s: Disabling interrupts since there are no active spans\n",
++				wc->variety);
++	} else wc->checktiming = 1;
++	spin_unlock_irqrestore(&wc->reglock, flags);
++	if (debug & DEBUG_MAIN)
++		printk("Span %d (%s) shutdown\n", span->spanno, span->name);
++	return 0;
++}
++
++static int ap4_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc)
++{
++	int i;
++	struct ap4_span *ts = ap4_span_from_span(span);
++	struct ap4 *wc = ts->owner;
++	unsigned int val;
++
++	printk("About to enter spanconfig!\n");
++	if (debug & DEBUG_MAIN)
++		printk("%s: Configuring span %d\n", wc->variety, span->spanno);
++	/* XXX We assume lineconfig is okay and shouldn't XXX */
++	span->lineconfig = lc->lineconfig;
++	span->txlevel = lc->lbo;
++	span->rxlevel = 0;
++	if (lc->sync < 0)
++		lc->sync = 0;
++	if (lc->sync > 4)
++		lc->sync = 0;
++
++	/* remove this span number from the current sync sources, if there */
++	for(i = 0; i < wc->numspans; i++) {
++		if (wc->tspans[i]->sync == span->spanno) {
++			wc->tspans[i]->sync = 0;
++			wc->tspans[i]->psync = 0;
++		}
++	}
++	wc->tspans[span->offset]->syncpos = lc->sync;
++	/* if a sync src, put it in proper place */
++	if (lc->sync) {
++		wc->tspans[lc->sync - 1]->sync = span->spanno;
++		wc->tspans[lc->sync - 1]->psync = span->offset + 1;
++	}
++	wc->checktiming = 1;
++	/* If we're already running, then go ahead and apply the changes */
++	if (span->flags & DAHDI_FLAG_RUNNING)
++		return ap4_startup(span);
++
++	// Limpa contadores de slips, crc e bpv
++	val = (*(wc->membase + AP_CNT_SLIP_REG));
++	val = (*(wc->membase + AP_CNT_CRC_REG));
++	val = (*(wc->membase + AP_CNT_CV_REG));
++
++	ap_debugk("habilitando interrupcao!\n");
++	// Nao considera as primeiras interrupcoes na soma das IRQs perdidas
++	wc->flag_1st_irq = 16;
++	// Enable interrupt
++	*(wc->membase + AP_INT_CONTROL_REG) |= AP_INT_CTL_ENABLE;
++	// Limpa interrupcao da FPGA para forcar borda de subida na proxima
++	val = *(wc->membase + AP_CLEAR_IRQ_REG);
++
++	printk("Done with spanconfig!\n");
++	return 0;
++}
++
++static int ap4_chanconfig(struct dahdi_chan *chan, int sigtype)
++{
++	int alreadyrunning;
++	unsigned long flags;
++	struct ap4 *wc = chan->pvt;
++
++	alreadyrunning = wc->tspans[chan->span->offset]->span.flags & DAHDI_FLAG_RUNNING;
++	if (debug & DEBUG_MAIN) {
++		if (alreadyrunning)
++			printk("%s: Reconfigured channel %d (%s) sigtype %d\n",
++					wc->variety, chan->channo, chan->name, sigtype);
++		else
++			printk("%s: Configured channel %d (%s) sigtype %d\n",
++					wc->variety, chan->channo, chan->name, sigtype);
++	}
++	spin_lock_irqsave(&wc->reglock, flags);
++	if (alreadyrunning)
++		__set_clear(wc, chan->span->offset);
++	spin_unlock_irqrestore(&wc->reglock, flags);
++	return 0;
++}
++
++static int ap4_open(struct dahdi_chan *chan)
++{
++	try_module_get(THIS_MODULE);
++	return 0;
++}
++
++static int ap4_close(struct dahdi_chan *chan)
++{
++	module_put(THIS_MODULE);
++	return 0;
++}
++
++static const struct dahdi_span_ops ap4_span_ops = {
++	.owner = THIS_MODULE,
++	.spanconfig = ap4_spanconfig,
++	.chanconfig = ap4_chanconfig,
++	.startup = ap4_startup,
++	.shutdown = ap4_shutdown,
++	.rbsbits = ap4_rbsbits,
++	.maint = ap4_maint,
++	.open = ap4_open,
++	.close  = ap4_close,
++#ifdef APEC_SUPPORT
++	.echocan = ap4_echocan,
++#endif
++	.ioctl = ap4_ioctl
++};
++
++static void init_spans(struct ap4 *wc)
++{
++	int x,y;
++	struct ap4_span *ts;
++
++	for (x=0;x<wc->numspans;x++) {
++		ts = wc->tspans[x];
++		sprintf(ts->span.name, "AP4%d%d/%d/%d", 0, wc->numspans, wc->num, x + 1);
++		snprintf(ts->span.desc, sizeof(ts->span.desc) - 1, "AP4%d%d Card %d Span %d", 0, wc->numspans, wc->num+1, x+1);
++		snprintf(ts->span.location, sizeof(ts->span.location) - 1,
++			 "PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1);
++		ts->span.manufacturer = "Aligera";
++		dahdi_copy_string(ts->span.devicetype, wc->variety, sizeof(ts->span.devicetype));
++		ts->span.ops = &ap4_span_ops;
++		if (ts->spantype == TYPE_E1) {
++			ts->span.channels = 31;
++			ts->span.spantype = "E1";
++			ts->span.linecompat = DAHDI_CONFIG_HDB3 | DAHDI_CONFIG_CCS | DAHDI_CONFIG_CRC4;
++			ts->span.deflaw = DAHDI_LAW_ALAW;
++		} else {
++			ts->span.channels = 24;
++			ts->span.spantype = "T1";
++			ts->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS | DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF;
++			ts->span.deflaw = DAHDI_LAW_MULAW;
++		}
++		ts->span.chans = ts->chans;
++		ts->span.flags = DAHDI_FLAG_RBS;
++		ts->owner = wc;
++		ts->span.offset = x;
++		ts->writechunk = (void *)(wc->writechunk + x * 32 * 2);
++		ts->readchunk = (void *)(wc->readchunk + x * 32 * 2);
++		init_waitqueue_head(&ts->span.maintq);
++		for (y=0;y<wc->tspans[x]->span.channels;y++) {
++			struct dahdi_chan *mychans = ts->chans[y];
++			sprintf(mychans->name, "AP4%d%d/%d/%d/%d", 0, wc->numspans, wc->num, x + 1, y + 1);
++			mychans->sigcap = DAHDI_SIG_EM | DAHDI_SIG_CLEAR | DAHDI_SIG_FXSLS | DAHDI_SIG_FXSGS | DAHDI_SIG_FXSKS |
++									 DAHDI_SIG_FXOLS | DAHDI_SIG_FXOGS | DAHDI_SIG_FXOKS | DAHDI_SIG_CAS | DAHDI_SIG_EM_E1 | DAHDI_SIG_DACS_RBS;
++			mychans->pvt = wc;
++			mychans->chanpos = y + 1;
++		}
++	}
++	printk("%s: Spans initialized\n", wc->variety);
++}
++
++
++
++static void __ap4_set_timing_source(struct ap4 *wc, int unit)
++{
++	unsigned int timing;
++	int x;
++
++	if (unit != wc->syncsrc) {
++		if ((unit > -1) && (unit < 4)) {
++			/* define fonte de clock para interface escolhida */
++			timing = *(wc->membase+AP_CLKSRC_REG);
++			timing &= ~AP_CLKSRC_MASK;
++			timing |= unit+1;
++			*(wc->membase+AP_CLKSRC_REG) = timing;
++		} else {
++			/* define clock para interno */
++			timing = *(wc->membase+AP_CLKSRC_REG);
++			timing &= ~AP_CLKSRC_MASK;
++			*(wc->membase+AP_CLKSRC_REG) = timing;
++		}
++		wc->syncsrc = unit;
++		if ((unit < 0) || (unit > 3))
++			unit = 0;
++		else
++			unit++;
++		for (x=0;x<wc->numspans;x++)
++			wc->tspans[x]->span.syncsrc = unit;
++	} else {
++		if (debug & DEBUG_MAIN)
++			printk("%s: Timing source already set to %d\n",
++					wc->variety, unit);
++	}
++	printk("%s: Timing source set to %d (clksrc_reg = 0x%08x)\n",
++			wc->variety, unit, *(wc->membase+AP_CLKSRC_REG));
++}
++
++static void __ap4_set_timing_source_auto(struct ap4 *wc)
++{
++	int x;
++
++	wc->checktiming = 0;
++	for (x=0;x<wc->numspans;x++) {
++		if (wc->tspans[x]->sync) {
++			if ((wc->tspans[wc->tspans[x]->psync - 1]->span.flags & DAHDI_FLAG_RUNNING) &&
++				!(wc->tspans[wc->tspans[x]->psync - 1]->span.alarms & (DAHDI_ALARM_RED | DAHDI_ALARM_BLUE) )) {
++					/* Valid timing source */
++					__ap4_set_timing_source(wc, wc->tspans[x]->psync - 1);
++					return;
++			}
++		}
++	}
++	__ap4_set_timing_source(wc, 4);
++}
++
++static void __ap4_configure_t1(struct ap4 *wc, int unit, int lineconfig, int txlevel)
++{
++	char *framing, *line;
++	unsigned int config = 0;
++	unsigned int param = 0;
++	unsigned int linecode = 0;
++
++	wc->tspans[unit]->spantype = TYPE_T1;
++	wc->tspans[unit]->span.channels = 24;
++	wc->tspans[unit]->span.deflaw = DAHDI_LAW_MULAW;
++
++	/* Configure line code */
++	if (unit < 2)
++		linecode = AP_LIU1_LINECODE;
++	else
++		linecode = AP_LIU2_LINECODE;
++	if (lineconfig & DAHDI_CONFIG_AMI) {
++		*(wc->membase+AP_LEDS_REG) |= linecode;
++		line = "AMI";
++	} else {
++		*(wc->membase+AP_LEDS_REG) &= ~linecode;
++		line = "B8ZS";
++	}
++
++	/* loopback test*/
++	//wc->hw_regs->e1_config |= (AP_E1_LOOP_CONFIG  << (8 * unit));
++	//printk("E1 config = 0x%08x\n", wc->hw_regs->e1_config);
++
++	/* Configure T1 */
++	config = wc->hw_regs->liu_config;
++	config &= ~(0x000000ff << (8 * unit));
++	config |= (AP_PULS_DSX1_0FT << (8 * unit));
++	wc->hw_regs->liu_config = config;
++
++	param = AP4_T1_NE1_SEL | AP4_T1_CAS_ENABLE;
++	if (lineconfig & DAHDI_CONFIG_D4) {
++		framing = "D4";
++	} else {
++		framing = "ESF";
++		param |= AP4_T1_ESF_NSF;
++	}
++	config = wc->hw_regs->t1_config;
++	config &= ~(0x000000ff << (8 * unit));
++	config |= (param << (8 * unit));
++	wc->hw_regs->t1_config = config;
++
++	printk("T1 Status: 0x%08x\tT1 Config: 0x%08x\tPARAM: 0x%08x\n",
++			wc->hw_regs->t1_status, wc->hw_regs->t1_config, param);
++
++	if (!polling) {
++		__ap4_check_alarms(wc, unit);
++		__ap4_check_sigbits(wc, unit);
++	}
++	printk("%s: Span %d configured for %s/%s\n", wc->variety, unit + 1, framing, line);
++}
++
++static void __ap4_configure_e1(struct ap4 *wc, int unit, int lineconfig)
++{
++	char *crc4 = "";
++	char *framing, *line;
++	unsigned int e1s_cfg, config = 0;
++	unsigned int linecode = 0;
++
++	wc->tspans[unit]->spantype = TYPE_E1;
++	wc->tspans[unit]->span.channels = 31;
++	wc->tspans[unit]->span.deflaw = DAHDI_LAW_ALAW;
++
++	if (loopback) {
++	}
++
++	if (lineconfig & DAHDI_CONFIG_CRC4) {
++		crc4 = "/CRC4";
++		config |= AP_E1_CRCEN_CONFIG;
++	}
++
++	if(unit < 2)
++		linecode = AP_LIU1_LINECODE;
++	else
++		linecode = AP_LIU2_LINECODE;
++	/* Configure line interface */
++	if (lineconfig & DAHDI_CONFIG_AMI) {
++		*(wc->membase+AP_LEDS_REG) |= linecode;
++		line = "AMI";
++	} else {
++		*(wc->membase+AP_LEDS_REG) &= ~linecode;
++		line = "HDB3";
++	}
++
++	if (lineconfig & DAHDI_CONFIG_CCS) {
++		framing = "CCS";
++	} else {
++		framing = "CAS";
++		config |= (AP_E1_CASEN_CONFIG | AP_E1_PCM30_CONFIG);
++	}
++
++	e1s_cfg = *(wc->membase+AP_E1_CONFIG_REG);
++	e1s_cfg &= ~(0x000000ff<<(8*unit));
++	e1s_cfg |= (config<<(8*unit));
++	*(wc->membase+AP_E1_CONFIG_REG) = e1s_cfg;
++
++	/* Disable T1 framer */
++	config = wc->hw_regs->t1_config;
++	config &= ~(0x000000ff << (8 * unit));
++	wc->hw_regs->t1_config = config;
++
++	/* Configure LIU Signalling */
++	e1s_cfg = *(wc->membase+AP_T1E1_CONFIG_REG);
++	e1s_cfg &= ~(0x000000ff<<(8*unit));
++	e1s_cfg |= (AP_PULS_E1_120<<(8*unit));
++	*(wc->membase+AP_T1E1_CONFIG_REG) = e1s_cfg;
++
++	if (!polling) {
++		__ap4_check_alarms(wc, unit);
++		__ap4_check_sigbits(wc, unit);
++	}
++	printk("%s: Span %d configured for %s/%s%s\n",
++ 			wc->variety, unit + 1, framing, line, crc4);
++}
++
++static int ap4_startup(struct dahdi_span *span)
++{
++	int i;
++	int tspan;
++	unsigned long flags;
++	int alreadyrunning;
++	struct ap4_span *ts = ap4_span_from_span(span);
++	struct ap4 *wc = ts->owner;
++
++	printk("About to enter startup!\n");
++	tspan = span->offset + 1;
++	if (tspan < 0) {
++		printk("%s: Span '%d' isn't us?\n", wc->variety, span->spanno);
++		return -1;
++	}
++
++	spin_lock_irqsave(&wc->reglock, flags);
++
++	alreadyrunning = span->flags & DAHDI_FLAG_RUNNING;
++
++	/* initialize the start value for the entire chunk of last ec buffer */
++	for(i = 0; i < span->channels; i++)
++	{
++		memset(ts->ec_chunk1[i],
++			DAHDI_LIN2X(0, span->chans[i]),DAHDI_CHUNKSIZE);
++		memset(ts->ec_chunk2[i],
++			DAHDI_LIN2X(0, span->chans[i]),DAHDI_CHUNKSIZE);
++	}
++
++	/* Force re-evaluation fo timing source */
++//	if (timingcable)
++		wc->syncsrc = -1;
++
++	if ((span->lineconfig & DAHDI_CONFIG_D4) || (span->lineconfig & DAHDI_CONFIG_ESF)) {
++		/* is a T1 card */
++		__ap4_configure_t1(wc, span->offset, span->lineconfig, span->txlevel);
++	} else { /* is a E1 card */
++		__ap4_configure_e1(wc, span->offset, span->lineconfig);
++	}
++
++	/* Note clear channel status */
++	wc->tspans[span->offset]->notclear = 0;
++	__set_clear(wc, span->offset);
++
++	if (!alreadyrunning) {
++		span->flags |= DAHDI_FLAG_RUNNING;
++		wc->spansstarted++;
++		/* enable interrupts */
++
++		if (!polling) {
++			__ap4_check_alarms(wc, span->offset);
++			__ap4_check_sigbits(wc, span->offset);
++		}
++	}
++	spin_unlock_irqrestore(&wc->reglock, flags);
++
++	if (wc->tspans[0]->sync == span->spanno) printk("SPAN %d: Primary Sync Source\n",span->spanno);
++	if (wc->numspans > 1) {
++		if (wc->tspans[1]->sync == span->spanno) printk("SPAN %d: Secondary Sync Source\n",span->spanno);
++	}
++	if (wc->numspans == 4) {
++		if (wc->tspans[2]->sync == span->spanno) printk("SPAN %d: Tertiary Sync Source\n",span->spanno);
++		if (wc->tspans[3]->sync == span->spanno) printk("SPAN %d: Quaternary Sync Source\n",span->spanno);
++	}
++
++#ifdef APEC_SUPPORT
++	if (!apec_enable || !wc->apec_enable)
++		wc->hw_regs->echo_ctrl = 0xe0000000;
++	else if (!alreadyrunning && !wc->apec)
++			if (ap4_apec_init(wc))
++				ap4_apec_release(wc);
++#else
++	wc->hw_regs->echo_ctrl = 0xe0000000;
++#endif
++
++	printk("Completed startup!\n");
++	return 0;
++}
++
++
++static void ap4_receiveprep(struct ap4 *wc)
++{
++	volatile unsigned int *readchunk;
++	unsigned int buffer[32];
++	unsigned char *byte = (unsigned char *) buffer;
++	int i, j, k;
++
++	readchunk = (wc->membase + (AP_DATA_BASE));
++	for (i = 0; i < DAHDI_CHUNKSIZE; i++) {
++		/* Prefetch Card data */
++		for (j = 0; j < 32; ++j) {
++			buffer[j] = readchunk[j];
++		}
++		for (j = 0; j < wc->numspans; j++) {
++			/* Set first timeslot for first channel */
++			if (wc->tspans[j]->spantype == TYPE_E1) {
++				for (k = 0; k < 31; ++k) {
++					/* Skip first timeslot from E1 */
++					wc->tspans[j]->span.chans[k]->readchunk[i] =
++							byte[4*(k+1)+j];
++				}
++			}
++			else {
++				for (k = 0; k < 24; ++k) {
++					wc->tspans[j]->span.chans[k]->readchunk[i] =
++							byte[4*k+j];
++				}
++			}
++		}
++		readchunk += 32;
++	}
++
++	for (i = 0; i < wc->numspans; i++) {
++		if (wc->tspans[i]->span.flags & DAHDI_FLAG_RUNNING) {
++			for (j = 0; j < wc->tspans[i]->span.channels; j++) {
++				/* Echo cancel double buffered data */
++				dahdi_ec_chunk(wc->tspans[i]->span.chans[j],
++				    wc->tspans[i]->span.chans[j]->readchunk,
++					wc->tspans[i]->ec_chunk2[j]);
++				memcpy(wc->tspans[i]->ec_chunk2[j],wc->tspans[i]->ec_chunk1[j],
++					DAHDI_CHUNKSIZE);
++				memcpy(wc->tspans[i]->ec_chunk1[j],
++					wc->tspans[i]->span.chans[j]->writechunk,
++						DAHDI_CHUNKSIZE);
++			}
++			dahdi_receive(&wc->tspans[i]->span);
++		}
++	}
++}
++
++#if (DAHDI_CHUNKSIZE != 8)
++#error Sorry, AP400 driver does not support chunksize != 8
++#endif
++
++#ifdef ENABLE_WORKQUEUES
++static void workq_handlespan(void *data)
++{
++	struct ap4_span *ts = data;
++	struct ap4 *wc = ts->owner;
++
++//	__receive_span(ts);
++//	__transmit_span(ts);
++	atomic_dec(&wc->worklist);
++	atomic_read(&wc->worklist);
++
++}
++#endif
++
++static void ap4_transmitprep(struct ap4 *wc)
++{
++	volatile unsigned int *writechunk;
++	int x,y,z;
++	unsigned int tmp;
++
++	for (y=0;y<wc->numspans;y++) {
++		if (wc->tspans[y]->span.flags & DAHDI_FLAG_RUNNING)
++			dahdi_transmit(&wc->tspans[y]->span);
++	}
++
++	writechunk = (wc->membase+(AP_DATA_BASE));
++	for (x=0;x<DAHDI_CHUNKSIZE;x++) {
++		// Once per chunk
++		for (z=0;z<32;z++) {
++			// All channels
++			tmp = 0;
++			for (y = 0; y < wc->numspans; ++y) {
++				if (wc->tspans[y]->spantype == TYPE_T1 && z < 24)
++					tmp |= (wc->tspans[y]->span.chans[z]->writechunk[x]
++					                           << (8*y));
++				else /* Span Type is E1 */
++					if (z > 0) /* Skip first timeslot */
++						tmp |= (wc->tspans[y]->span.chans[z-1]->writechunk[x]
++									<< (8*y));
++			}
++			writechunk[z] = tmp;
++		}
++		// Advance pointer by 4 TDM frame lengths
++		writechunk += 32;
++	}
++
++}
++
++static void ap4_tdm_loop(struct ap4 *wc)
++{
++	volatile unsigned int *buf_ptr;
++	int x,z;
++	unsigned int tmp;
++
++	buf_ptr = (wc->membase+AP_DATA_BASE);
++
++	for (x=0;x<DAHDI_CHUNKSIZE;x++) {
++		// Once per chunk
++		for (z=0;z<32;z++) {
++			tmp = buf_ptr[z];
++			buf_ptr[z] = tmp;
++		}
++		buf_ptr += 32;
++	}
++}
++
++static void __ap4_check_sigbits(struct ap4 *wc, int span)
++{
++	int a,i,rxs;
++	struct ap4_span *ts = wc->tspans[span];
++	volatile unsigned int *readcas = (wc->membase+AP_CAS_BASE);
++
++//	if (debug & DEBUG_RBS)
++//		printk("Checking sigbits on span %d\n", span + 1);
++
++	if (!(ts->span.flags & DAHDI_FLAG_RUNNING))
++		return;
++	// se span estiver com alarme RED ou BLUE...
++	if( (ts->span.alarms & DAHDI_ALARM_RED) || (ts->span.alarms & DAHDI_ALARM_BLUE) ) {
++		ts->reload_cas = 4;
++	} else if(ts->reload_cas > 0) {
++		// da mais um tempo para framer recuperar e enviar bits de CAS validos
++		ts->reload_cas--;
++	}
++
++	if (ts->spantype == TYPE_E1) {
++		for (i = 0; i < 15; i++) {
++
++			// Se estamos em alarme ou recuperando de um entao mascara os bits para "1101" (bloqueado)
++			if(ts->reload_cas) {
++				a = 0xdd;
++			} else {
++				a = (int) ts->casbuf[i];
++			}
++			ts->casbuf[i] = (unsigned char) (readcas[i] >> (8*span))&0xff;
++
++			/* Get high channel in low bits */
++			rxs = (a & 0xf);
++			if (!(ts->span.chans[i+16]->sig & DAHDI_SIG_CLEAR)) {
++				if (ts->span.chans[i+16]->rxsig != rxs) {
++					ap_debugk("CAS no canal %d mudou de 0x%02x para 0x%02x\n", i+16, ts->span.chans[i+16]->rxsig, rxs);
++					dahdi_rbsbits(ts->span.chans[i+16], rxs);
++				}
++			}
++			rxs = (a >> 4) & 0xf;
++			if (!(ts->span.chans[i]->sig & DAHDI_SIG_CLEAR)) {
++				if (ts->span.chans[i]->rxsig != rxs) {
++					ap_debugk("CAS no canal %d mudou de 0x%02x para 0x%02x\n", i, ts->span.chans[i]->rxsig, rxs);
++					dahdi_rbsbits(ts->span.chans[i], rxs);
++				}
++			}
++		}
++	} else if (ts->span.lineconfig & DAHDI_CONFIG_D4) {
++		for (i = 0; i < 12; i++) {
++			a = (unsigned char) (readcas[i] >> (8*span)) & 0xcc;
++			rxs = a & 0xc;
++			//rxs = (a & 0xc) >> 2;
++			if (!(ts->span.chans[2*i]->sig & DAHDI_SIG_CLEAR)) {
++				if (ts->span.chans[2*i]->rxsig != rxs)
++					dahdi_rbsbits(ts->span.chans[2*i], rxs);
++			}
++			rxs = (a >> 4) & 0xc;
++			//rxs = ((a >> 4) & 0xc) >> 2;
++			if (!(ts->span.chans[2*i+1]->sig & DAHDI_SIG_CLEAR)) {
++				if (ts->span.chans[2*i+1]->rxsig != rxs)
++					dahdi_rbsbits(ts->span.chans[2*i+1], rxs);
++			}
++		}
++	} else { // ESF
++		for (i = 0; i < 12; i++) {
++			a = (unsigned char) (readcas[i] >> (8*span)) & 0xff;
++			rxs = (a & 0xf);
++			if (!(ts->span.chans[2*i+1]->sig & DAHDI_SIG_CLEAR)) {
++				/* XXX Not really reset on every trans! XXX */
++				if (ts->span.chans[2*i+1]->rxsig != rxs) {
++					dahdi_rbsbits(ts->span.chans[2*i+1], rxs);
++				}
++			}
++			rxs = (a >> 4) & 0xf;
++			if (!(ts->span.chans[2*i]->sig & DAHDI_SIG_CLEAR)) {
++				/* XXX Not really reset on every trans! XXX */
++				if (ts->span.chans[2*i]->rxsig != rxs) {
++					dahdi_rbsbits(ts->span.chans[2*i], rxs);
++				}
++			}
++		}
++	}
++}
++
++static void __ap4_check_alarms(struct ap4 *wc, int span)
++{
++	unsigned char c;
++	int alarms;
++	int x,j;
++	struct ap4_span *ts = wc->tspans[span];
++	unsigned int e1_cfg;
++
++	if (!(ts->span.flags & DAHDI_FLAG_RUNNING))
++		return;
++
++	/* Assume no alarms */
++	alarms = DAHDI_ALARM_NONE;
++
++	/* And consider only carrier alarms */
++	ts->span.alarms &= (DAHDI_ALARM_RED | DAHDI_ALARM_BLUE | DAHDI_ALARM_NOTOPEN);
++
++	if (ts->span.lineconfig & DAHDI_CONFIG_NOTOPEN) {
++		for (x=0,j=0;x < ts->span.channels;x++)
++			if ((ts->span.chans[x]->flags & DAHDI_FLAG_OPEN) ||
++			    (ts->span.chans[x]->flags & DAHDI_FLAG_NETDEV))
++				j++;
++		if (!j)
++			alarms |= DAHDI_ALARM_NOTOPEN;
++	}
++
++/* le status e configuracao do E1 */
++	if (wc->tspans[span]->spantype == TYPE_E1) {
++		c = ((*(wc->membase+AP_E1_STATUS_REG))>>(8*span));
++		e1_cfg = ((*(wc->membase+AP_E1_CONFIG_REG))>>(8*span));
++
++		if ((c & AP_E1_LOS_STATUS)||(c & AP_E1_BFAE_STATUS)||(c & AP_E1_AIS_STATUS)) {
++			if (ts->alarmcount >= alarmdebounce)
++				alarms |= DAHDI_ALARM_RED;
++			else
++				ts->alarmcount++;
++		} else
++			ts->alarmcount = 0;
++
++		if ( c & AP_E1_MFAE_STATUS )
++			alarms |= DAHDI_ALARM_BLUE;
++
++		if ( (!(c & AP_E1_CAS_STATUS)) && (e1_cfg & AP_E1_PCM30_CONFIG))
++			alarms |= DAHDI_ALARM_BLUE;
++	} else {
++		c = ((*(wc->membase+AP_E1_STATUS_REG))>>(8*span));
++		if (c & AP_E1_LOS_STATUS) {
++			if (ts->alarmcount >= alarmdebounce)
++				alarms |= DAHDI_ALARM_RED;
++			else
++				ts->alarmcount++;
++		} else
++			ts->alarmcount = 0;
++		c = wc->hw_regs->t1_status >> (8 * span);
++		if (!(c & AP4_T1_FRAME_SYNC))
++			alarms |= DAHDI_ALARM_RED;
++	}
++
++	if (((!ts->span.alarms) && alarms) ||
++	    (ts->span.alarms && (!alarms)))
++		wc->checktiming = 1;
++
++	/* Keep track of recovering */
++	if ((!alarms) && ts->span.alarms)
++		ts->alarmtimer = DAHDI_ALARMSETTLE_TIME;
++	if (ts->alarmtimer)
++		alarms |= DAHDI_ALARM_RECOVER;
++
++
++	// If receiving alarms, go into Yellow alarm state
++	if (alarms && !(ts->spanflags & FLAG_SENDINGYELLOW)) {
++		printk("Setting yellow alarm on span %d\n", span + 1);
++		e1_cfg = *(wc->membase+AP_E1_CONFIG_REG);
++		e1_cfg |= (AP_E1_RAI_CONFIG<<(8*span));
++		*(wc->membase+AP_E1_CONFIG_REG) = e1_cfg;
++		ts->spanflags |= FLAG_SENDINGYELLOW;
++	} else if ((!alarms) && (ts->spanflags & FLAG_SENDINGYELLOW)) {
++		printk("Clearing yellow alarm on span %d\n", span + 1);
++		e1_cfg = *(wc->membase+AP_E1_CONFIG_REG);
++		e1_cfg &= ~(AP_E1_RAI_CONFIG<<(8*span));
++		*(wc->membase+AP_E1_CONFIG_REG) = e1_cfg;
++		ts->spanflags &= ~FLAG_SENDINGYELLOW;
++	}
++
++	// Re-check the timing source when we enter/leave alarm, not withstanding yellow alarm
++	if (c & AP_E1_RAI_STATUS)
++		alarms |= DAHDI_ALARM_YELLOW;
++
++	if (ts->span.mainttimer || ts->span.maintstat)
++		alarms |= DAHDI_ALARM_LOOPBACK;
++
++	ts->span.alarms = alarms;
++	dahdi_alarm_notify(&ts->span);
++}
++
++static void __ap4_do_counters(struct ap4 *wc)
++{
++	int span;
++
++	for (span=0;span<wc->numspans;span++) {
++		struct ap4_span *ts = wc->tspans[span];
++		int docheck=0;
++		if (ts->loopupcnt || ts->loopdowncnt)
++			docheck++;
++		if (ts->alarmtimer) {
++			if (!--ts->alarmtimer) {
++				docheck++;
++				ts->span.alarms &= ~(DAHDI_ALARM_RECOVER);
++			}
++		}
++		if (docheck) {
++			if (!polling)
++				__ap4_check_alarms(wc, span);
++			dahdi_alarm_notify(&ts->span);
++		}
++	}
++}
++
++static inline void __handle_leds(struct ap4 *wc)
++{
++	int x, span_status;
++	#define MAX_BLINKTIMER	0x14
++
++	for (x=0;x<wc->numspans;x++) {
++		struct ap4_span *ts = wc->tspans[x];
++		/* le status do E1 (para avaliar LOS) */
++		span_status = ((*(wc->membase+AP_E1_STATUS_REG))>>(8*x));
++		if (ts->span.flags & DAHDI_FLAG_RUNNING) {
++			if(span_status&AP_E1_LOS_STATUS) {
++				if (wc->blinktimer[x] >= (altab[wc->alarmpos[x]] /*>> 1*/)) {
++					__ap4_set_led(wc, x, AP_ON);
++				}
++				if (wc->blinktimer[x] >= (MAX_BLINKTIMER-1)) {
++					__ap4_set_led(wc, x, AP_OFF);
++				}
++				wc->blinktimer[x] += 1;
++			} else if (ts->span.alarms & (DAHDI_ALARM_RED | DAHDI_ALARM_BLUE)) {
++				if (wc->blinktimer[x] >= (altab[wc->alarmpos[x]] /*>> 1*/)) {
++					__ap4_set_led(wc, x, AP_ON);
++				}
++				if (wc->blinktimer[x] >= (MAX_BLINKTIMER-2)) {
++					__ap4_set_led(wc, x, AP_OFF);
++				}
++				wc->blinktimer[x] += 3;
++			} /*else if (ts->span.alarms & DAHDI_ALARM_YELLOW) {
++				// Yellow Alarm
++				__ap4_set_led(wc, x, AP_ON);
++			} else if (ts->span.mainttimer || ts->span.maintstat) {
++
++				if (wc->blinktimer == (altab[wc->alarmpos] >> 1)) {
++					__ap4_set_led(wc, x, AP_GREEN);
++				}
++				if (wc->blinktimer == 0xf) {
++					__ap4_set_led(wc, x, AP_OFF);
++				}
++
++			} */else {
++				/* No Alarm */
++				__ap4_set_led(wc, x, AP_ON);
++			}
++		}	else
++				__ap4_set_led(wc, x, AP_OFF);
++
++		if (wc->blinktimer[x] > MAX_BLINKTIMER) {
++			wc->blinktimer[x] = 0;
++			wc->alarmpos[x]++;
++			if (wc->alarmpos[x] >= (sizeof(altab) / sizeof(altab[0])))
++				wc->alarmpos[x] = 0;
++		}
++
++	}
++}
++
++
++DAHDI_IRQ_HANDLER(ap4_interrupt)
++{
++	struct ap4 *wc = dev_id;
++	unsigned long flags;
++	int x;
++	static unsigned int val, cfg;
++	unsigned int cnt_irq_misses;
++	static unsigned int cnt_tmp;
++	int ret = 0;
++
++	/* retorna se interrupcao nao foi habilitada ou nao esta ativa */
++	cfg = *(wc->membase + AP_INT_CONTROL_REG);
++	if((cfg & AP_INT_CTL_ENABLE) == 0 || (cfg & AP_INT_CTL_ACTIVE) == 0) {
++		ret = 0;
++		goto out;
++	}
++	/* se chegamos aqui eh porque a interrupcao esta habilitada
++	 * e esta ativa, ou seja, foi gerada pelo nosso cartao.
++	 * Agora damos o ack da interrupcao */
++	val = *(wc->membase + AP_CLEAR_IRQ_REG);
++
++	/* conta interrupcoes perdidas */
++	if (wc->flag_1st_irq > 0) {
++		// nao considera as primeiras passagens pela rotina
++		cnt_irq_misses = (*(wc->membase+AP_CNT_IRQ_REG));
++		// so considera int. para o cartao
++		if(cnt_irq_misses) {
++			wc->flag_1st_irq--;
++			*(wc->membase+AP_CNT_IRQ_REG)=0;
++			for(x=0;x<(wc->numspans);x++)
++				wc->tspans[x]->span.irqmisses = 0;
++		}
++		// zera erro de CRC
++		cnt_tmp = (*(wc->membase + AP_CNT_CRC_REG));
++	} else {
++		// neste registro da FPGA temos o numero de interrupcoes que aconteceram
++		// desde o ultimo reset do contador de interrupcoes. O normal eh ler 1.
++		cnt_irq_misses = (*(wc->membase+AP_CNT_IRQ_REG));
++		// Se for zero significa que a interrupcao nao foi gerada pelo nosso cartao
++		if(cnt_irq_misses == 0) {
++			if(debug) printk("Interrupcao gerada mas nao pela FPGA?!\n");
++			ret = 0;
++			goto out;
++		}
++		// reseta o contador
++		*(wc->membase+AP_CNT_IRQ_REG)=0;
++		for(x=0;x<(wc->numspans);x++)
++			wc->tspans[x]->span.irqmisses += (cnt_irq_misses-1);
++	}
++
++	if (!wc->spansstarted) {
++		/* Not prepped yet! */
++		ret = 0;
++		goto out;
++	}
++
++	wc->intcount++;
++
++#ifdef ENABLE_WORKQUEUES
++	int cpus = num_online_cpus();
++	atomic_set(&wc->worklist, wc->numspans);
++	if (wc->tspans[0]->span.flags & DAHDI_FLAG_RUNNING)
++		ap4_queue_work(wc->workq, &wc->tspans[0]->swork, 0);
++	else
++		atomic_dec(&wc->worklist);
++	if (wc->numspans > 1) {
++		if (wc->tspans[1]->span.flags & DAHDI_FLAG_RUNNING)
++			ap4_queue_work(wc->workq, &wc->tspans[1]->swork, 1 % cpus);
++		else
++			atomic_dec(&wc->worklist);
++	}
++	if (wc->numspans == 4) {
++		if (wc->tspans[2]->span.flags & DAHDI_FLAG_RUNNING)
++			ap4_queue_work(wc->workq, &wc->tspans[2]->swork, 2 % cpus);
++		else
++			atomic_dec(&wc->worklist);
++		if (wc->tspans[3]->span.flags & DAHDI_FLAG_RUNNING)
++			ap4_queue_work(wc->workq, &wc->tspans[3]->swork, 3 % cpus);
++		else
++			atomic_dec(&wc->worklist);
++	}
++#else
++	if (tdm_loop == 1)
++		ap4_tdm_loop(wc);
++	else {
++		ap4_receiveprep(wc);
++		ap4_transmitprep(wc);
++	}
++#endif
++
++	// Estatisticas a cada 128ms
++	if(!(wc->intcount&0x7f)){
++		clock_source = wc->hw_regs->clock_source;
++		cnt_tmp = (*(wc->membase + AP_CNT_CV_REG));
++		for(x=0;x<(wc->numspans);x++)
++			wc->tspans[x]->span.count.bpv += (cnt_tmp>>(8*x))&0xff;
++		cnt_tmp = (*(wc->membase + AP_CNT_CRC_REG));
++		for(x=0;x<(wc->numspans);x++)
++			wc->tspans[x]->span.count.crc4 += (cnt_tmp>>(8*x))&0xff;
++		cnt_tmp = (*(wc->membase + AP_CNT_SLIP_REG));
++		for(x=0;x<(wc->numspans);x++) {
++			if (((cnt_tmp>>(8*x))&0xff) && (!(wc->tspans[x]->span.alarms & DAHDI_ALARM_RED)) ){
++				wc->tspans[x]->slipcount++;
++				if(debug) printk("Slip detected on span %d: slipcount = %d\n", x+1, wc->tspans[x]->slipcount);
++			}
++		}
++	}
++
++	spin_lock_irqsave(&wc->reglock, flags);
++
++	__handle_leds(wc);
++
++	__ap4_do_counters(wc);
++
++	//x = wc->intcount & 15;
++	x = wc->intcount & 7;
++	switch(x) {
++	case 0:
++	case 1:
++	case 2:
++	case 3:
++		__ap4_check_alarms(wc, x);
++		break;
++	case 4:
++	case 5:
++	case 6:
++	case 7:
++		__ap4_check_sigbits(wc, x - 4);
++		break;
++	}
++
++	if (wc->checktiming > 0)
++		__ap4_set_timing_source_auto(wc);
++	spin_unlock_irqrestore(&wc->reglock, flags);
++	/* IRQ was treated */
++	ret = 1;
++out:
++#ifdef AP400_HDLC
++	/* Call AP400_HDLC_CARD IRQ handler before leave */
++	ret |= ap400_intr_handler(irq, wc->hdlc_card);
++#endif
++
++	return IRQ_RETVAL(ret);
++}
++
++
++static int __devinit ap4_launch(struct ap4 *wc)
++{
++	int x;
++	unsigned long flags;
++
++	if (wc->tspans[0]->span.flags & DAHDI_FLAG_REGISTERED)
++		return 0;
++	printk("%s: Launching card: %d\n", wc->variety, wc->order);
++
++	/* Setup serial parameters and system interface */
++	for (x=0;x<4;x++) {
++		//ap4_serial_setup(wc, x);
++		wc->globalconfig = 1;
++	}
++
++	if (dahdi_register(&wc->tspans[0]->span, 0)) {
++		printk(KERN_ERR "Unable to register span %s\n", wc->tspans[0]->span.name);
++		return -1;
++	}
++	if (wc->numspans > 1) {
++		if (dahdi_register(&wc->tspans[1]->span, 0)) {
++			printk(KERN_ERR "Unable to register span %s\n", wc->tspans[1]->span.name);
++			dahdi_unregister(&wc->tspans[0]->span);
++			return -1;
++		}
++	}
++	if (wc->numspans == 4) {
++		if (dahdi_register(&wc->tspans[2]->span, 0)) {
++			printk(KERN_ERR "Unable to register span %s\n", wc->tspans[2]->span.name);
++			dahdi_unregister(&wc->tspans[0]->span);
++			dahdi_unregister(&wc->tspans[1]->span);
++			return -1;
++		}
++		if (dahdi_register(&wc->tspans[3]->span, 0)) {
++			printk(KERN_ERR "Unable to register span %s\n", wc->tspans[3]->span.name);
++			dahdi_unregister(&wc->tspans[0]->span);
++			dahdi_unregister(&wc->tspans[1]->span);
++			dahdi_unregister(&wc->tspans[2]->span);
++			return -1;
++		}
++	}
++	wc->checktiming = 1;
++	spin_lock_irqsave(&wc->reglock, flags);
++//	__ap4_set_timing_source(wc,4);
++	spin_unlock_irqrestore(&wc->reglock, flags);
++#ifdef ENABLE_TASKLETS
++	tasklet_init(&wc->ap4_tlet, ap4_tasklet, (unsigned long)wc);
++#endif
++	return 0;
++}
++
++
++static int ap4xx_liu_reset(struct ap4 *wc)
++{
++ 	unsigned int jiffies_hold = jiffies;
++	*(wc->membase+AP_LEDS_REG) |= AP_LIU_RESET_BIT;
++	while(jiffies<=(jiffies_hold+2));
++	*(wc->membase+AP_LEDS_REG) &= ~AP_LIU_RESET_BIT;
++	return 0;
++}
++
++
++static int ap4xx_bus_test(struct ap4 *wc)
++{
++	int tst_result = 0;
++	unsigned int val;
++
++	*(wc->membase+AP_E1_CONFIG_REG) = 0xAAAAAAAA;
++	*wc->membase = 0; // flush
++	val = *(wc->membase+AP_E1_CONFIG_REG);
++	if(val != 0xAAAAAAAA) {
++		printk("Escrito 0xAAAAAAAA, lido 0x%08X!\n", val);
++		tst_result++;
++	}
++	*(wc->membase+AP_E1_CONFIG_REG) = 0x55555555;
++	*wc->membase = 0; // flush
++	val = *(wc->membase+AP_E1_CONFIG_REG);
++	if(val != 0x55555555) {
++		printk("Escrito 0x55555555, lido 0x%08X!\n", val);
++		tst_result++;
++	}
++	*(wc->membase+AP_E1_CONFIG_REG) = 0xFFFFFFFF;
++	*wc->membase = 0; // flush
++	val = *(wc->membase+AP_E1_CONFIG_REG);
++	if(val != 0xFFFFFFFF) {
++		printk("Escrito 0xFFFFFFFF, lido 0x%08X!\n", val);
++		tst_result++;
++	}
++	*(wc->membase+AP_E1_CONFIG_REG) = 0x00000000;
++	*wc->membase = 0xFFFFFFFF; // flush
++	val = *(wc->membase+AP_E1_CONFIG_REG);
++	if(val != 0x00000000) {
++		printk("Escrito 0x00000000, lido 0x%08X!\n", val);
++		tst_result++;
++	}
++	return tst_result;
++}
++
++#ifdef TIMER_DEBUG
++void ap4xx_opt_timeout(unsigned long arg)
++{
++	struct pci_dev *dev = (struct pci_dev *)arg;
++	struct ap4 *wc = pci_get_drvdata(dev);
++
++//	ap_debugk("wc->tspans[0]->span.chans[1].readchunk[1] = 0x%02x\n", wc->tspans[0]->span.chans[0].readchunk[1]);
++//	ap_debugk("e1s_cfg = 0x%08x\n", *(wc->membase+AP_E1_CONFIG_REG));
++//	ap_debugk("e1_status = 0x%08x\n", *(wc->membase + AP_E1_STATUS_REG));
++//	ap_debugk("clk_cfg = 0x%08x\n", *(wc->membase+0x07));
++//	ap_debugk("e1_data = 0x%08x\n", *(wc->membase + (AP_DATA_BASE + 1)));
++//	ap_debugk("cas_data = 0x%08x\n", *(wc->membase + AP_CAS_BASE));
++
++	// dispara timer novamente
++	init_timer(&ap4xx_opt_timer);
++	ap4xx_opt_timer.function = ap4xx_opt_timeout;
++	ap4xx_opt_timer.data = arg;
++	ap4xx_opt_timer.expires = jiffies + (delay/4);
++	add_timer(&ap4xx_opt_timer);
++
++}
++#endif
++
++static inline int ap4_card_detect (struct ap4 *wc) {
++	int i;
++	if ((wc->hw_regs->card_id != AP4XX_CARD_ID) &&
++			(wc->hw_regs->card_id != APE4XX_CARD_ID)) {
++		printk("AP400: Unknown card ID(0x%08X)! Aborting...\n", wc->hw_regs->card_id);
++		return -EPERM;
++	}
++	// Test bus integrity
++	for (i=0; i < 1000; i++) {
++		if (ap4xx_bus_test(wc)) {
++			printk("AP400: Bus integrity test failed! Aborting...\n");
++			return -EIO;
++		}
++	}
++	printk("AP400: Bus integrity OK!\n");
++
++	wc->fpgaver = wc->hw_regs->fpga_ver;
++	wc->numspans = wc->hw_regs->span_num;
++	wc->hwid = ((*(wc->membase+AP_HWCONFIG_REG))&AP_HWID_MASK)>>4;
++
++	if ((wc->hwid == AP_HWID_1E1_RJ && wc->numspans != 1) ||
++			(wc->hwid == AP_HWID_2E1_RJ && wc->numspans != 2) ||
++			(wc->hwid == AP_HWID_4E1_RJ && wc->numspans != 4)) {
++		printk("AP400: Incompatible Hardware ID(0x%02x)! Aborting...\n", wc->hwid);
++		return -EIO;
++	}
++
++	if (wc->hw_regs->card_id == AP4XX_CARD_ID)
++		switch (wc->numspans) {
++		case 1:
++			wc->dt = (struct devtype *) &ap401;
++			break;
++		case 2:
++			wc->dt = (struct devtype *) &ap402;
++			break;
++		case 4:
++			wc->dt = (struct devtype *) &ap404;
++			break;
++		default:
++			printk("AP400: Unsupported spans number(%d)! Aborting...\n",
++					wc->numspans);
++			return -EPERM;
++		}
++	else
++		switch (wc->numspans) {
++		case 1:
++			wc->dt = (struct devtype *) &ape401;
++			break;
++		case 2:
++			wc->dt = (struct devtype *) &ape402;
++			break;
++		case 4:
++			wc->dt = (struct devtype *) &ape404;
++			break;
++		default:
++			printk("APE400: Unsupported spans number(%d)! Aborting...\n",
++					wc->numspans);
++			return -EPERM;
++	}
++
++	wc->variety = wc->dt->desc;
++	printk("Found a %s (firmware version %d.%d) at base address %08lx, remapped to %p\n",
++			wc->variety, wc->fpgaver >> 8, wc->fpgaver & 0xFF,
++			wc->memaddr, wc->membase);
++
++	return 0;
++}
++
++static void __devexit ap4_remove_one(struct pci_dev *pdev);
++
++static int __devinit ap4_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
++{
++	int res;
++	struct ap4 *wc;
++	int x,f;
++	int basesize;
++	static int initd_ifaces=0;
++	// Initialize pointer struct
++	if(!initd_ifaces){
++		memset((void *)cards,0,(sizeof(struct ap4 *))*MAX_AP4_CARDS);
++		initd_ifaces=1;
++	}
++
++	if ((res = pci_enable_device(pdev)) != 0) {
++		goto out;
++	}
++	// Allocate card struct
++	wc = kmalloc(sizeof(struct ap4), GFP_KERNEL);
++	if (wc == NULL) {
++		res = -ENOMEM;
++		goto out;
++	}
++
++	memset(wc, 0x0, sizeof(struct ap4));
++	spin_lock_init(&wc->reglock);
++
++	basesize = DAHDI_MAX_CHUNKSIZE * 32 * 2 * 4;
++
++	// Request PCI regions
++	if ((res = pci_request_regions(pdev, "ap400")) != 0) {
++		printk("AP400: Unable to request regions!\n");
++		goto out;
++	}
++
++	// Remap PCI address
++	wc->memaddr = pci_resource_start(pdev, 2);
++	wc->memlen = pci_resource_len(pdev, 2);
++	wc->membase = ioremap_nocache(wc->memaddr, wc->memlen);
++	if(wc->membase == NULL) {
++		printk("AP400: ioremap failed!\n");
++		res = -EIO;
++		goto out;
++	}
++	wc->hw_regs = (struct ap4_regs *) wc->membase;
++
++	// Detect Card model
++	if ((res = ap4_card_detect(wc)) != 0)
++		goto out;
++
++	ap4xx_liu_reset(wc);
++
++	// This rids of the Double missed interrupt message after loading
++	wc->last0 = 1;
++
++	wc->dev = pdev;
++
++	// 32 channels, Double-buffer, Read/Write, 4 spans
++	wc->writechunk = kmalloc(basesize * 2, GFP_KERNEL);
++	if (!wc->writechunk) {
++		printk("%s: Unable to allocate memory!\n", wc->variety);
++		res = -ENOMEM;
++		goto out;
++	}
++
++	// Read is after the whole write piece (in words)
++	wc->readchunk = wc->writechunk + basesize / 4;
++
++
++	// Initialize Write/Buffers to all blank data
++	memset((void *) wc->writechunk, 0x00, basesize);
++	memset((void *) wc->readchunk, 0xff, basesize);
++
++	/* Keep track of which device we are */
++	pci_set_drvdata(pdev, wc);
++
++	/* inicializa contador de interrupcao */
++	wc->intcount = 0;
++
++	for(x = 0; x < MAX_AP4_CARDS; x++) {
++		if (!cards[x]) break;
++	}
++
++	if (x >= MAX_AP4_CARDS) {
++		printk("No cards[] slot available!!\n");
++		res = -ENOMEM;
++		goto out;
++	}
++
++	wc->num = x;
++	cards[x] = wc;
++
++	/* Allocate pieces we need here, consider 31 channels for E1*/
++	for (x=0;x<4;x++) {
++		wc->tspans[x] = kmalloc(sizeof(struct ap4_span), GFP_KERNEL);
++		if (wc->tspans[x]) {
++			memset(wc->tspans[x], 0, sizeof(struct ap4_span));
++			wc->tspans[x]->spantype = TYPE_E1;
++		} else {
++			res = -ENOMEM;
++			goto out;
++		}
++		for (f = 0; f < 31; f++) {
++			if (!(wc->tspans[x]->chans[f] = kmalloc(sizeof(*wc->tspans[x]->chans[f]), GFP_KERNEL))) {
++				res = -ENOMEM;
++				goto out;
++			}
++			memset(wc->tspans[x]->chans[f], 0, sizeof(*wc->tspans[x]->chans[f]));
++		}
++#ifdef ENABLE_WORKQUEUES
++		INIT_WORK(&wc->tspans[x]->swork, workq_handlespan, wc->tspans[x]);
++#endif
++		wc->tspans[x]->spanflags |= wc->dt->flags;
++	}
++
++	if (request_irq(pdev->irq, ap4_interrupt, IRQF_DISABLED | IRQF_SHARED, "ap400", wc))
++	{
++		printk("%s: Unable to request IRQ %d\n", wc->variety, pdev->irq);
++		res = -EIO;
++		goto out;
++	}
++
++	init_spans(wc);
++
++	/* Launch cards as appropriate */
++	x = 0;
++	for(;;) {
++		/* Find a card to activate */
++		f = 0;
++		for (x=0;cards[x];x++) {
++			if (cards[x]->order <= highestorder) {
++				ap4_launch(cards[x]);
++				if (cards[x]->order == highestorder)
++					f = 1;
++			}
++		}
++		/* If we found at least one, increment the highest order and search again, otherwise stop */
++		if (f)
++			highestorder++;
++		else
++			break;
++	}
++
++#ifdef APEC_SUPPORT
++	if (wc->fpgaver >= 0x0400)
++		wc->apec_enable = 1;
++#endif
++
++#ifdef TIMER_DEBUG
++	// dispara timer de debug
++	init_timer(&ap4xx_opt_timer);
++	ap4xx_opt_timer.function = ap4xx_opt_timeout;
++	ap4xx_opt_timer.data = (unsigned long) pdev;
++	ap4xx_opt_timer.expires = jiffies + 100;
++	add_timer(&ap4xx_opt_timer);
++#endif
++
++	/* Initialize HDLC_CARD */
++#ifdef AP400_HDLC
++	u8 __iomem *base_addr[3];
++	unsigned int bar_size[3];
++	int i;
++	base_addr[2] = (void *) wc->membase;
++	bar_size[2] = wc->memlen;
++	for (i = 0; i < 2; i++) {
++		bar_size[i] = (u32) pci_resource_len(pdev, i);
++		base_addr[i] = ioremap_nocache(pci_resource_start(pdev, i),
++								bar_size[i]);
++		if (base_addr[i] == NULL) {
++			printk(KERN_ERR "Memory map failed\n");
++			res = -ENODEV;
++			goto out;
++		}
++	}
++	ap400_card_init(&wc->hdlc_card, base_addr, bar_size);
++	ap400_intr_enable(wc->hdlc_card);
++#endif
++
++	res = 0;
++out:
++	if (res != 0) {
++		ap4_remove_one(pdev);
++	}
++	return res;
++}
++
++static void __devexit ap4_remove_one(struct pci_dev *pdev)
++{
++	struct ap4 *wc = pci_get_drvdata(pdev);
++	int x;
++
++	if (wc) {
++		ap_debugk("desabilita interrupcao!\n");
++		// desabilita interrupcao
++		*(wc->membase + AP_INT_CONTROL_REG) &= ~AP_INT_CTL_ENABLE;
++
++#ifdef APEC_SUPPORT
++		// Stop echo cancellation module
++		ap4_apec_release(wc);
++#endif
++		/* Unregister spans */
++		if (wc->tspans[0]->span.flags & DAHDI_FLAG_REGISTERED)
++			dahdi_unregister(&wc->tspans[0]->span);
++		if (wc->numspans > 1) {
++			if (wc->tspans[1]->span.flags & DAHDI_FLAG_REGISTERED)
++				dahdi_unregister(&wc->tspans[1]->span);
++		}
++		if (wc->numspans == 4) {
++			if (wc->tspans[2]->span.flags & DAHDI_FLAG_REGISTERED)
++				dahdi_unregister(&wc->tspans[2]->span);
++			if (wc->tspans[3]->span.flags & DAHDI_FLAG_REGISTERED)
++				dahdi_unregister(&wc->tspans[3]->span);
++		}
++#ifdef ENABLE_WORKQUEUES
++		if (wc->workq) {
++			flush_workqueue(wc->workq);
++			destroy_workqueue(wc->workq);
++		}
++#endif
++
++#ifdef TIMER_DEBUG
++		del_timer(&ap4xx_opt_timer);
++#endif
++
++		wc->hw_regs = NULL;
++		if(wc->membase)
++			iounmap((void *)wc->membase);
++
++		/* Immediately free resources */
++		kfree((void *) wc->writechunk);
++
++#ifdef AP400_HDLC
++		/* Remove HDLC Card */
++		ap400_card_remove(wc->hdlc_card);
++		if (wc->hdlc_card->cfg_base_addr)
++			iounmap(wc->hdlc_card->cfg_base_addr);
++		if (wc->hdlc_card->buf_base_addr)
++			iounmap(wc->hdlc_card->buf_base_addr);
++		kfree(wc->hdlc_card);
++#endif
++		free_irq(pdev->irq, wc);
++
++		cards[wc->num] = NULL;
++		for (x=0;x<wc->numspans;x++) {
++			if (wc->tspans[x])
++				kfree(wc->tspans[x]);
++		}
++		kfree(wc);
++	}
++	pci_release_regions(pdev);
++	pci_disable_device(pdev);
++	pci_set_drvdata(pdev, NULL);
++	printk(KERN_INFO "AP400 driver removed\n");
++}
++
++
++static struct pci_device_id ap4_pci_tbl[] __devinitdata =
++{
++	{ PCI_DEVICE(PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_AP4XX), },
++	{ 0, }
++};
++
++
++static struct pci_driver ap4_driver = {
++	.name = 	"Unified ap4xx driver",
++	.probe = 	ap4_init_one,
++#ifdef LINUX26
++	.remove =	__devexit_p(ap4_remove_one),
++#else
++	.remove =	ap4_remove_one,
++#endif
++	.id_table = ap4_pci_tbl,
++};
++
++static int __init ap4_init(void)
++{
++	int res;
++	printk("Unified AP4XX PCI Card Driver\n");
++	res = dahdi_pci_module(&ap4_driver);
++	if (res) {
++		return -ENODEV;
++	}
++	return 0;
++}
++
++static void __exit ap4_cleanup(void)
++{
++	printk("Unified AP4XX PCI Card Driver Cleanup\n");
++	pci_unregister_driver(&ap4_driver);
++}
++
++
++MODULE_AUTHOR("Aligera (aligera at aligera.com.br)");
++MODULE_DESCRIPTION("Unified AP4XX PCI Card Driver");
++#ifdef MODULE_LICENSE
++MODULE_LICENSE("GPL");
++#endif
++module_param(debug, int, 0600);
++module_param(loopback, int, 0600);
++module_param(noburst, int, 0600);
++module_param(debugslips, int, 0600);
++module_param(polling, int, 0600);
++module_param(timingcable, int, 0600);
++module_param(t1e1override, int, 0600);
++module_param(alarmdebounce, int, 0600);
++module_param(j1mode, int, 0600);
++
++MODULE_DEVICE_TABLE(pci, ap4_pci_tbl);
++
++module_init(ap4_init);
++module_exit(ap4_cleanup);
+diff -urN dahdi-svn-orig/drivers/dahdi/ap400/ap400.h dahdi-svn-new/drivers/dahdi/ap400/ap400.h
+--- dahdi-svn-orig/drivers/dahdi/ap400/ap400.h	1970-01-01 02:00:00.000000000 +0200
++++ dahdi-svn-new/drivers/dahdi/ap400/ap400.h	2011-03-07 11:52:51.411050187 +0200
+@@ -0,0 +1,107 @@
++/*
++ * AP4XX  T1/E1 PCI Driver
++ *
++ * Written by Ronaldo Valiati <aligera at aligera.com.br>
++ *
++ * Based on previous works, designs, and archetectures conceived and
++ * written by Jim Dixon <jim at lambdatel.com> and Mark Spencer <markster at digium.com>.
++ *
++ * Copyright (C) 2001 Jim Dixon / Zapata Telephony.
++ * Copyright (C) 2001-2005, Digium, Inc.
++ *
++ * 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/ioctl.h>
++
++
++#define AP4_GET_ALARMS  _IOW (DAHDI_CODE, 60, int)
++#define AP4_GET_SLIPS	_IOW (DAHDI_CODE, 61, int)
++
++#define AP4XX_CARD_ID		0x41434532		// "ACE2"
++#define APE4XX_CARD_ID		0x41504534		// "APE4"
++
++#define AP_CAS_BASE		0x0080
++#define AP_DATA_BASE		0x0100
++
++#define AP_CARD_TYPE_REG	0x0001
++#define AP_T1E1_CONFIG_REG	0x0003
++#define AP_E1_CONFIG_REG	0x0004
++#define AP_E1_STATUS_REG	0x0005
++#define AP_LEDS_REG		0x0006
++#define AP_CLKSRC_REG		0x0007
++#define AP_HWCONFIG_REG		0x0008
++#define AP_INT_CONTROL_REG	0x0009
++#define AP_CNT_IRQ_REG		0x000B
++#define AP_CNT_CV_REG		0x000C
++#define AP_CNT_CRC_REG		0x000D
++#define AP_CLEAR_IRQ_REG	0x000E
++#define AP_CNT_SLIP_REG		0x000F
++
++#define AP_HWID_MASK		0x00F0
++
++#define AP_CLKSRC_MASK		0x07
++
++#define AP_LIU1_LINECODE	0x0080
++#define AP_LIU2_LINECODE	0x0100
++#define AP_LIU_RESET_BIT	0x0200
++
++#define AP_E1_AIS_STATUS	0x01
++#define AP_E1_BFAE_STATUS	0x02
++#define AP_E1_MFAE_STATUS	0x04
++#define AP_E1_SYNC_STATUS	0x08
++#define AP_E1_CAS_STATUS	0x10
++#define AP_E1_LOS_STATUS	0x20
++#define AP_E1_RAI_STATUS	0x40
++
++#define AP_E1_RAI_CONFIG	0x01
++#define AP_E1_LOOP_CONFIG	0x10
++#define AP_E1_CASEN_CONFIG	0x20
++#define AP_E1_PCM30_CONFIG	0x40
++#define AP_E1_CRCEN_CONFIG	0x80
++
++#define AP_INT_CTL_ENABLE	0x01
++#define AP_INT_CTL_ACTIVE	0x02
++
++#define AP_HWID_1E1_RJ		0x01
++#define AP_HWID_2E1_RJ		0x00
++#define AP_HWID_4E1_RJ		0x02
++#define AP_HWID_T1		0x04
++
++#define AP4_T1_NE1_SEL		0x04
++#define AP4_T1_ESF_NSF		0x02
++#define AP4_T1_CAS_ENABLE	0x01
++
++#define AP4_T1_FRAME_SYNC	0x01
++
++
++typedef enum {
++	AP_PULS_E1_75 = 0,
++	AP_PULS_E1_120,
++	AP_PULS_DSX1_0FT,
++	AP_PULS_DSX1_133FT,
++	AP_PULS_DSX1_266FT,
++	AP_PULS_DSX1_399FT,
++	AP_PULS_DSX1_533FT,
++	AP_PULS_J1_110,
++	AP_PULS_DS1_0DB,
++	AP_PULS_DS1_M075DB,
++	AP_PULS_DS1_M150DB,
++	AP_PULS_DS1_M225DB
++} liu_mode;
++
+diff -urN dahdi-svn-orig/drivers/dahdi/ap400/apec.c dahdi-svn-new/drivers/dahdi/ap400/apec.c
+--- dahdi-svn-orig/drivers/dahdi/ap400/apec.c	1970-01-01 02:00:00.000000000 +0200
++++ dahdi-svn-new/drivers/dahdi/ap400/apec.c	2011-03-07 11:52:51.411050187 +0200
+@@ -0,0 +1,390 @@
++/*
++ * AP400 Echo Cancelation Hardware support
++ *
++ * Written by Wagner Gegler <aligera at aligera.com.br>
++ *
++ * Based on previous work written by Mark Spencer <markster at digium.com>
++ *
++ * Copyright (C) 2005-2006 Digium, Inc.
++ *
++ * Mark Spencer <markster at digium.com>
++ *
++ * 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/slab.h>
++#include <linux/vmalloc.h>
++#include <linux/string.h>
++#include <linux/time.h>
++#include <linux/version.h>
++#include <linux/delay.h>
++
++#include "apec.h"
++#include "oct6100api/oct6100_api.h"
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
++#include <linux/config.h>
++#else
++#include <linux/autoconf.h>
++#endif
++
++/* API for Octasic access */
++UINT32 Oct6100UserGetTime(tPOCT6100_GET_TIME f_pTime)
++{
++	/* Why couldn't they just take a timeval like everyone else? */
++	struct timeval tv;
++	unsigned long long total_usecs;
++	unsigned int mask = ~0;
++
++	do_gettimeofday(&tv);
++	total_usecs = (((unsigned long long)(tv.tv_sec)) * 1000000) +
++				  (((unsigned long long)(tv.tv_usec)));
++	f_pTime->aulWallTimeUs[0] = (total_usecs & mask);
++	f_pTime->aulWallTimeUs[1] = (total_usecs >> 32);
++	return cOCT6100_ERR_OK;
++}
++
++UINT32 Oct6100UserMemSet(PVOID f_pAddress, UINT32 f_ulPattern, UINT32 f_ulLength)
++{
++	memset(f_pAddress, f_ulPattern, f_ulLength);
++	return cOCT6100_ERR_OK;
++}
++
++UINT32 Oct6100UserMemCopy(PVOID f_pDestination, const void *f_pSource, UINT32 f_ulLength)
++{
++	memcpy(f_pDestination, f_pSource, f_ulLength);
++	return cOCT6100_ERR_OK;
++}
++
++UINT32 Oct6100UserCreateSerializeObject(tPOCT6100_CREATE_SERIALIZE_OBJECT f_pCreate)
++{
++	return cOCT6100_ERR_OK;
++}
++
++UINT32 Oct6100UserDestroySerializeObject(tPOCT6100_DESTROY_SERIALIZE_OBJECT f_pDestroy)
++{
++#ifdef OCTASIC_DEBUG
++	printk("I should never be called! (destroy serialize object)\n");
++#endif
++	return cOCT6100_ERR_OK;
++}
++
++UINT32 Oct6100UserSeizeSerializeObject(tPOCT6100_SEIZE_SERIALIZE_OBJECT f_pSeize)
++{
++	/* Not needed */
++	return cOCT6100_ERR_OK;
++}
++
++UINT32 Oct6100UserReleaseSerializeObject(tPOCT6100_RELEASE_SERIALIZE_OBJECT f_pRelease)
++{
++	/* Not needed */
++	return cOCT6100_ERR_OK;
++}
++
++UINT32 Oct6100UserDriverWriteApi(tPOCT6100_WRITE_PARAMS f_pWriteParams)
++{
++	oct_write(f_pWriteParams->pProcessContext, f_pWriteParams->ulWriteAddress, f_pWriteParams->usWriteData);
++	return cOCT6100_ERR_OK;
++}
++
++UINT32 Oct6100UserDriverWriteSmearApi(tPOCT6100_WRITE_SMEAR_PARAMS f_pSmearParams)
++{
++	unsigned int x;
++	for (x=0;x<f_pSmearParams->ulWriteLength;x++) {
++		oct_write(f_pSmearParams->pProcessContext, f_pSmearParams->ulWriteAddress + (x << 1), f_pSmearParams->usWriteData);
++	}
++	return cOCT6100_ERR_OK;
++}
++
++UINT32 Oct6100UserDriverWriteBurstApi(tPOCT6100_WRITE_BURST_PARAMS f_pBurstParams)
++{
++	unsigned int x;
++	for (x=0;x<f_pBurstParams->ulWriteLength;x++) {
++		oct_write(f_pBurstParams->pProcessContext, f_pBurstParams->ulWriteAddress + (x << 1), f_pBurstParams->pusWriteData[x]);
++	}
++	return cOCT6100_ERR_OK;
++}
++
++UINT32 Oct6100UserDriverReadApi(tPOCT6100_READ_PARAMS f_pReadParams)
++{
++	*(f_pReadParams->pusReadData) = oct_read(f_pReadParams->pProcessContext, f_pReadParams->ulReadAddress);
++	return cOCT6100_ERR_OK;
++}
++
++UINT32 Oct6100UserDriverReadBurstApi(tPOCT6100_READ_BURST_PARAMS f_pBurstParams)
++{
++	unsigned int x;
++	for (x=0;x<f_pBurstParams->ulReadLength;x++) {
++		f_pBurstParams->pusReadData[x] = oct_read(f_pBurstParams->pProcessContext, f_pBurstParams->ulReadAddress + (x << 1));
++	}
++	return cOCT6100_ERR_OK;
++}
++
++#if 0
++#define cOCT6100_ECHO_OP_MODE_DIGITAL cOCT6100_ECHO_OP_MODE_HT_FREEZE
++#else
++#define cOCT6100_ECHO_OP_MODE_DIGITAL cOCT6100_ECHO_OP_MODE_POWER_DOWN
++#endif
++
++struct apec_s {
++	tPOCT6100_INSTANCE_API pApiInstance;
++	UINT32 aulEchoChanHndl[128];
++	int chanflags[128];
++	int ecmode[128];
++	int numchans;
++};
++
++#define FLAG_DTMF	 (1 << 0)
++#define FLAG_MUTE	 (1 << 1)
++#define FLAG_ECHO	 (1 << 2)
++
++static void apec_setecmode(struct apec_s *apec, int channel, int mode)
++{
++	tOCT6100_CHANNEL_MODIFY *modify;
++	UINT32 ulResult;
++
++	if (apec->ecmode[channel] == mode)
++		return;
++	modify = kmalloc(sizeof(tOCT6100_CHANNEL_MODIFY), GFP_ATOMIC);
++	if (!modify) {
++		printk("APEC: Unable to allocate memory for setec!\n");
++		return;
++	}
++	Oct6100ChannelModifyDef(modify);
++	modify->ulEchoOperationMode = mode;
++	modify->ulChannelHndl = apec->aulEchoChanHndl[channel];
++	ulResult = Oct6100ChannelModify(apec->pApiInstance, modify);
++	if (ulResult != GENERIC_OK) {
++		printk("Failed to apply echo can changes on channel %d!\n", channel);
++	} else {
++#ifdef OCTASIC_DEBUG
++		printk("Echo can on channel %d set to %d\n", channel, mode);
++#endif
++		apec->ecmode[channel] = mode;
++	}
++	kfree(modify);
++}
++
++void apec_setec(struct apec_s *apec, int channel, int eclen)
++{
++	if (eclen) {
++		apec->chanflags[channel] |= FLAG_ECHO;
++		apec_setecmode(apec, channel, cOCT6100_ECHO_OP_MODE_HT_RESET);
++		apec_setecmode(apec, channel, cOCT6100_ECHO_OP_MODE_NORMAL);
++	} else {
++		apec->chanflags[channel] &= ~FLAG_ECHO;
++		if (apec->chanflags[channel] & (FLAG_DTMF | FLAG_MUTE)) {
++			apec_setecmode(apec, channel, cOCT6100_ECHO_OP_MODE_HT_RESET);
++			apec_setecmode(apec, channel, cOCT6100_ECHO_OP_MODE_HT_FREEZE);
++		} else
++			apec_setecmode(apec, channel, cOCT6100_ECHO_OP_MODE_DIGITAL);
++	}
++	printk("APEC: Setting EC on channel %d to %d\n", channel, eclen);
++}
++
++int apec_checkirq(struct apec_s *apec)
++{
++	tOCT6100_INTERRUPT_FLAGS InterruptFlags;
++
++	Oct6100InterruptServiceRoutineDef(&InterruptFlags);
++	Oct6100InterruptServiceRoutine(apec->pApiInstance, &InterruptFlags);
++
++	return InterruptFlags.fToneEventsPending ? 1 : 0;
++}
++
++unsigned int apec_capacity_get(void *wc)
++{
++	UINT32 ulResult;
++
++	tOCT6100_API_GET_CAPACITY_PINS CapacityPins;
++
++	Oct6100ApiGetCapacityPinsDef(&CapacityPins);
++	CapacityPins.pProcessContext = wc;
++	CapacityPins.ulMemoryType = cOCT6100_MEM_TYPE_DDR;
++	CapacityPins.fEnableMemClkOut = TRUE;
++	CapacityPins.ulMemClkFreq = cOCT6100_MCLK_FREQ_133_MHZ;
++
++	ulResult = Oct6100ApiGetCapacityPins(&CapacityPins);
++	if (ulResult != cOCT6100_ERR_OK) {
++		printk("Failed to get chip capacity, code %08x!\n", ulResult);
++		return 0;
++	}
++	return CapacityPins.ulCapacityValue;
++}
++
++struct apec_s *apec_init(void *wc, int *isalaw, int numspans, const struct firmware *firmware)
++{
++	tOCT6100_CHIP_OPEN *ChipOpen;
++	tOCT6100_GET_INSTANCE_SIZE InstanceSize;
++	tOCT6100_CHANNEL_OPEN *ChannelOpen;
++	UINT32 ulResult;
++	struct apec_s *apec;
++	int x, law;
++#ifdef CONFIG_4KSTACKS
++	unsigned long flags;
++#endif
++
++	if (!(apec = kmalloc(sizeof(struct apec_s), GFP_KERNEL)))
++		return NULL;
++
++	memset(apec, 0, sizeof(struct apec_s));
++
++	if (!(ChipOpen = kmalloc(sizeof(tOCT6100_CHIP_OPEN), GFP_KERNEL))) {
++		kfree(apec);
++		return NULL;
++	}
++
++	memset(ChipOpen, 0, sizeof(tOCT6100_CHIP_OPEN));
++
++	if (!(ChannelOpen = kmalloc(sizeof(tOCT6100_CHANNEL_OPEN), GFP_KERNEL))) {
++		kfree(apec);
++		kfree(ChipOpen);
++		return NULL;
++	}
++
++	memset(ChannelOpen, 0, sizeof(tOCT6100_CHANNEL_OPEN));
++
++	for (x=0;x<128;x++)
++		apec->ecmode[x] = -1;
++
++	apec->numchans = numspans * 32;
++	printk("APEC: echo cancellation for %d channels\n", apec->numchans);
++
++	Oct6100ChipOpenDef(ChipOpen);
++
++	/* Setup Chip Open Parameters */
++	ChipOpen->ulUpclkFreq = cOCT6100_UPCLK_FREQ_33_33_MHZ;
++	Oct6100GetInstanceSizeDef(&InstanceSize);
++
++	ChipOpen->pProcessContext = wc;
++
++	ChipOpen->pbyImageFile = firmware->data;
++	ChipOpen->ulImageSize = firmware->size;
++
++	ChipOpen->fEnableMemClkOut = TRUE;
++	ChipOpen->ulMemClkFreq = cOCT6100_MCLK_FREQ_133_MHZ;
++	ChipOpen->ulMaxChannels = apec->numchans;
++	ChipOpen->ulMemoryType = cOCT6100_MEM_TYPE_DDR;
++	ChipOpen->ulMemoryChipSize = cOCT6100_MEMORY_CHIP_SIZE_32MB;
++	ChipOpen->ulNumMemoryChips = 1;
++	ChipOpen->ulMaxTdmStreams = 4;
++	ChipOpen->aulTdmStreamFreqs[0] = cOCT6100_TDM_STREAM_FREQ_8MHZ;
++	ChipOpen->ulTdmSampling = cOCT6100_TDM_SAMPLE_AT_FALLING_EDGE;
++#if 0
++	ChipOpen->fEnableAcousticEcho = TRUE;
++#endif
++
++	ulResult = Oct6100GetInstanceSize(ChipOpen, &InstanceSize);
++	if (ulResult != cOCT6100_ERR_OK) {
++		printk("Failed to get instance size, code %08x!\n", ulResult);
++		kfree(apec);
++		return NULL;
++	}
++
++
++	apec->pApiInstance = vmalloc(InstanceSize.ulApiInstanceSize);
++	if (!apec->pApiInstance) {
++		printk("Out of memory (can't allocate %d bytes)!\n", InstanceSize.ulApiInstanceSize);
++		kfree(apec);
++		kfree(ChipOpen);
++		kfree(ChannelOpen);
++		return NULL;
++	}
++
++	/* I don't know what to curse more in this comment, the problems caused by
++	 * the 4K kernel stack limit change or the octasic API for being so darn
++	 * stack unfriendly.  Stupid, stupid, stupid.  So we disable IRQs so we
++	 * don't run the risk of overflowing the stack while we initialize the
++	 * octasic. */
++#ifdef CONFIG_4KSTACKS
++	local_irq_save(flags);
++#endif
++	ulResult = Oct6100ChipOpen(apec->pApiInstance, ChipOpen);
++	if (ulResult != cOCT6100_ERR_OK) {
++		printk("Failed to open chip, code %08x!\n", ulResult);
++#ifdef CONFIG_4KSTACKS
++		local_irq_restore(flags);
++#endif
++		kfree(apec);
++		kfree(ChipOpen);
++		kfree(ChannelOpen);
++		return NULL;
++	}
++	for (x=0; x < 128; x++) {
++		/* execute this loop always on 4 span cards but
++		*  on 2 span cards only execute for the channels related to our spans */
++		if ((x & 0x3) < numspans) {
++			/* span timeslots are interleaved 12341234...
++		 	*  therefore, the lower 2 bits tell us which span this
++			*  timeslot/channel
++		 	*/
++			if (isalaw[x & 0x03])
++				law = cOCT6100_PCM_A_LAW;
++			else
++				law = cOCT6100_PCM_U_LAW;
++			Oct6100ChannelOpenDef(ChannelOpen);
++			ChannelOpen->pulChannelHndl = &apec->aulEchoChanHndl[x];
++			ChannelOpen->ulUserChanId = x;
++			ChannelOpen->TdmConfig.ulRinPcmLaw = law;
++			ChannelOpen->TdmConfig.ulRinStream = 0;
++			ChannelOpen->TdmConfig.ulRinTimeslot = x;
++			ChannelOpen->TdmConfig.ulSinPcmLaw = law;
++			ChannelOpen->TdmConfig.ulSinStream = 1;
++			ChannelOpen->TdmConfig.ulSinTimeslot = x;
++			ChannelOpen->TdmConfig.ulSoutPcmLaw = law;
++			ChannelOpen->TdmConfig.ulSoutStream = 2;
++			ChannelOpen->TdmConfig.ulSoutTimeslot = x;
++			ChannelOpen->TdmConfig.ulRoutPcmLaw = law;
++			ChannelOpen->TdmConfig.ulRoutStream = 3;
++			ChannelOpen->TdmConfig.ulRoutTimeslot = x;
++			ChannelOpen->VqeConfig.fEnableNlp = TRUE;
++			ChannelOpen->VqeConfig.fRinDcOffsetRemoval = TRUE;
++			ChannelOpen->VqeConfig.fSinDcOffsetRemoval = TRUE;
++
++			ChannelOpen->fEnableToneDisabler = TRUE;
++			ChannelOpen->ulEchoOperationMode = cOCT6100_ECHO_OP_MODE_DIGITAL;
++
++			ulResult = Oct6100ChannelOpen(apec->pApiInstance, ChannelOpen);
++			if (ulResult != GENERIC_OK) {
++				printk("Failed to open channel %d!\n", x);
++			}
++		}
++	}
++
++#ifdef CONFIG_4KSTACKS
++	local_irq_restore(flags);
++#endif
++	kfree(ChipOpen);
++	kfree(ChannelOpen);
++	return apec;
++}
++
++void apec_release(struct apec_s *apec)
++{
++	UINT32 ulResult;
++	tOCT6100_CHIP_CLOSE ChipClose;
++
++	Oct6100ChipCloseDef(&ChipClose);
++	ulResult = Oct6100ChipClose(apec->pApiInstance, &ChipClose);
++	if (ulResult != cOCT6100_ERR_OK) {
++		printk("Failed to close chip, code %08x!\n", ulResult);
++	}
++	vfree(apec->pApiInstance);
++	kfree(apec);
++	printk(KERN_INFO "APEC: Releasing...\n");
++}
+diff -urN dahdi-svn-orig/drivers/dahdi/ap400/apec.h dahdi-svn-new/drivers/dahdi/ap400/apec.h
+--- dahdi-svn-orig/drivers/dahdi/ap400/apec.h	1970-01-01 02:00:00.000000000 +0200
++++ dahdi-svn-new/drivers/dahdi/ap400/apec.h	2011-03-07 11:52:51.411050187 +0200
+@@ -0,0 +1,48 @@
++/*
++ * AP400 Echo Cancelation Hardware support
++ *
++ * Written by Wagner Gegler <aligera at aligera.com.br>
++ * 
++ * Based on previous work written by Mark Spencer <markster at digium.com>
++ * 
++ * Copyright (C) 2005-2006 Digium, Inc.
++ *
++ * Mark Spencer <markster at digium.com>
++ *
++ * All Rights Reserved
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++#ifndef _APEC_H_
++#define _APEC_H_
++
++#include <linux/firmware.h>
++
++struct apec_s;
++
++/* From AP400 */
++unsigned int oct_read(void *card, unsigned int addr);
++void oct_write(void *card, unsigned int addr, unsigned int data);
++
++/* From APEC */
++struct apec_s *apec_init(void *wc, int *isalaw, int numspans, const struct firmware *firmware);
++unsigned int apec_capacity_get(void *wc);
++void apec_setec(struct apec_s *instance, int channel, int eclen);
++int apec_checkirq(struct apec_s *apec);
++void apec_release(struct apec_s *instance);
++
++#endif /*_APEC_H_*/
+diff -urN dahdi-svn-orig/drivers/dahdi/ap400/Kbuild dahdi-svn-new/drivers/dahdi/ap400/Kbuild
+--- dahdi-svn-orig/drivers/dahdi/ap400/Kbuild	1970-01-01 02:00:00.000000000 +0200
++++ dahdi-svn-new/drivers/dahdi/ap400/Kbuild	2011-03-07 11:52:51.411050187 +0200
+@@ -0,0 +1,26 @@
++obj-m += ap400.o
++
++EXTRA_CFLAGS := -I$(src)/.. 
++
++ap400-objs := ap400_drv.o
++
++# APEC_SUPPORT
++ECHO_FIRMWARE := $(wildcard $(src)/OCT61*.ima)
++ifneq ($(strip $(ECHO_FIRMWARE)),)
++	EXTRA_CFLAGS+=-DAPEC_SUPPORT $(shell $(src)/../oct612x/octasic-helper cflags $(src)/../oct612x) -Wno-undef
++	ap400-objs += apec.o $(shell $(src)/../oct612x/octasic-helper objects ../oct612x) firmware_oct6104e-64d.o firmware_oct6104e-128d.o
++endif
++
++$(obj)/apec.o: $(src)/apec.h $(src)/../oct612x/include/oct6100api/oct6100_api.h
++
++$(obj)/firmware_oct6104e-64d.o: $(src)/OCT6104E-64D.ima $(obj)/ap400_drv.o $(src)/../firmware/make_firmware_object
++	@echo Making firmware object file for $(notdir $<)
++	@cd $(src) && ../firmware/make_firmware_object $(notdir $<) $@ $(obj)/ap400_drv.o
++
++$(obj)/firmware_oct6104e-128d.o: $(src)/OCT6104E-128D.ima $(obj)/ap400_drv.o $(src)/../firmware/make_firmware_object
++	@echo Making firmware object file for $(notdir $<)
++	@cd $(src) && ../firmware/make_firmware_object $(notdir $<) $@ $(obj)/ap400_drv.o
++
++$(src)/../firmware/make_firmware_object:
++	make -C $(src)/../firmware make_firmware_object
++
+diff -urN dahdi-svn-orig/drivers/dahdi/Kbuild dahdi-svn-new/drivers/dahdi/Kbuild
+--- dahdi-svn-orig/drivers/dahdi/Kbuild	2010-05-17 17:45:12.512409000 +0300
++++ dahdi-svn-new/drivers/dahdi/Kbuild	2011-03-07 11:52:51.447051323 +0200
+@@ -1,11 +1,18 @@
  obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI)			+= dahdi.o
++obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_AP400)		+= ap400/
+ #obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_DUMMY)		+= dahdi_dummy.o
 +obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_OPVXA1200)		+= opvxa1200.o
- #obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_DUMMY)		+= dahdi_dummy.o
+ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_DYNAMIC)		+= dahdi_dynamic.o
 +obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCOPENPCI)		+= wcopenpci.o
- obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_DYNAMIC)		+= dahdi_dynamic.o
+ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_DYNAMIC_LOC)	+= dahdi_dynamic_loc.o
 +obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ZAPHFC)		+= zaphfc/
- obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_DYNAMIC_LOC)	+= dahdi_dynamic_loc.o
+ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_DYNAMIC_ETH)	+= dahdi_dynamic_eth.o
 +obj-$(DAHDI_BUILD_ALL)$(CONFIG_ECHO)			+= ../staging/echo/
- obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_DYNAMIC_ETH)	+= dahdi_dynamic_eth.o
+ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_DYNAMIC_ETHMF)	+= dahdi_dynamic_ethmf.o
 +obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_OSLEC)	+= dahdi_echocan_oslec.o
- obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_DYNAMIC_ETHMF)	+= dahdi_dynamic_ethmf.o
-+
  obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_TRANSCODE)		+= dahdi_transcode.o
  
++
  obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCT4XXP)		+= wct4xxp/
---- a/drivers/dahdi/Kconfig
-+++ b/drivers/dahdi/Kconfig
-@@ -292,3 +292,54 @@ config DAHDI_WCTE11XP
+ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTC4XXP)		+= wctc4xxp/
+ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTDM24XXP)	+= wctdm24xxp/
+diff -urN dahdi-svn-orig/drivers/dahdi/Kconfig dahdi-svn-new/drivers/dahdi/Kconfig
+--- dahdi-svn-orig/drivers/dahdi/Kconfig	2010-02-25 21:10:02.273471000 +0200
++++ dahdi-svn-new/drivers/dahdi/Kconfig	2011-03-07 11:52:51.443051289 +0200
+@@ -292,3 +292,54 @@
  	  If unsure, say Y.
  
  source "drivers/dahdi/xpp/Kconfig"
@@ -85,9 +3045,10 @@
 +
 +	  If unsure, say Y.
 +
---- /dev/null
-+++ b/drivers/dahdi/opvxa1200.c
-@@ -0,0 +1,3018 @@
+diff -urN dahdi-svn-orig/drivers/dahdi/opvxa1200.c dahdi-svn-new/drivers/dahdi/opvxa1200.c
+--- dahdi-svn-orig/drivers/dahdi/opvxa1200.c	1970-01-01 02:00:00.000000000 +0200
++++ dahdi-svn-new/drivers/dahdi/opvxa1200.c	2011-03-07 11:52:51.407062026 +0200
+@@ -0,0 +1,3026 @@
 +/*
 + * OpenVox A1200P FXS/FXO Interface Driver for DAHDI Telephony interface
 + *
@@ -2357,10 +5318,14 @@
 +	return 0;
 +}
 +
++static inline struct wctdm* wctdm_from_span(struct dahdi_span *span) {
++	return container_of(span, struct wctdm, span);
++}
++
 +static int wctdm_watchdog(struct dahdi_span *span, int event)
 +{
 +	printk(KERN_INFO "opvxa1200: Restarting DMA\n");
-+	wctdm_restart_dma(span->pvt);
++	wctdm_restart_dma(wctdm_from_span(span));
 +	return 0;
 +}
 +
@@ -2453,6 +5418,15 @@
 +	return 0;
 +}
 +
++static const struct dahdi_span_ops wctdm_span_ops = {
++	.owner = THIS_MODULE,
++	.hooksig = wctdm_hooksig,
++	.open = wctdm_open,
++	.close = wctdm_close,
++	.ioctl = wctdm_ioctl,
++	.watchdog = wctdm_watchdog
++};
++
 +static int wctdm_initialize(struct wctdm *wc)
 +{
 +	int x;
@@ -2492,16 +5466,11 @@
 +	}
 +	wc->span.chans = wc->chans;
 +	wc->span.channels = wc->max_cards;	/*MAX_NUM_CARDS;*/
-+	wc->span.hooksig = wctdm_hooksig;
 +	wc->span.irq = wc->dev->irq;
-+	wc->span.open = wctdm_open;
-+	wc->span.close = wctdm_close;
 +	wc->span.flags = DAHDI_FLAG_RBS;
-+	wc->span.ioctl = wctdm_ioctl;
-+	wc->span.watchdog = wctdm_watchdog;
++	wc->span.ops = &wctdm_span_ops;
 +	init_waitqueue_head(&wc->span.maintq);
 +
-+	wc->span.pvt = wc;
 +	if (dahdi_register(&wc->span, 0)) {
 +		printk(KERN_NOTICE "Unable to register span with Dahdi\n");
 +		return -1;
@@ -3106,9 +6075,10 @@
 +
 +module_init(wctdm_init);
 +module_exit(wctdm_cleanup);
---- /dev/null
-+++ b/drivers/dahdi/wcopenpci.c
-@@ -0,0 +1,1842 @@
+diff -urN dahdi-svn-orig/drivers/dahdi/wcopenpci.c dahdi-svn-new/drivers/dahdi/wcopenpci.c
+--- dahdi-svn-orig/drivers/dahdi/wcopenpci.c	1970-01-01 02:00:00.000000000 +0200
++++ dahdi-svn-new/drivers/dahdi/wcopenpci.c	2011-03-07 11:52:51.407062026 +0200
+@@ -0,0 +1,1850 @@
 +/*
 + * Voicetronix OpenPCI Interface Driver for Zapata Telephony interface
 + *
@@ -4269,10 +7239,14 @@
 +	return 0;
 +}
 +
++static inline struct openpci* openpci_from_span(struct dahdi_span *span) {
++	return container_of(span, struct openpci, span);
++}
++
 +static int openpci_watchdog(struct dahdi_span *span, int event)
 +{
 +	info("TDM: Restarting DMA");
-+	restart_dma(span->pvt);
++	restart_dma(openpci_from_span(span));
 +	return 0;
 +}
 +
@@ -4402,6 +7376,15 @@
 +	return 0;
 +} //}}}
 +
++static const struct dahdi_span_ops openpci_span_ops = {
++	.owner = THIS_MODULE,
++	.hooksig = openpci_hooksig,
++	.open = openpci_open,
++	.close = openpci_close,
++	.ioctl = openpci_ioctl,
++	.watchdog = openpci_watchdog
++};
++
 +static int span_initialize(struct openpci *wc)
 +{ //{{{
 +	int x;
@@ -4423,15 +7406,10 @@
 +	wc->span.deflaw = DAHDI_LAW_MULAW;
 +	wc->span.chans = wc->chans;
 +	wc->span.channels = MAX_PORTS;
-+	wc->span.hooksig = openpci_hooksig;
-+	wc->span.open = openpci_open;
-+	wc->span.close = openpci_close;
 +	wc->span.flags = DAHDI_FLAG_RBS;
-+	wc->span.ioctl = openpci_ioctl;
-+	wc->span.watchdog = openpci_watchdog;
++	wc->span.ops = &openpci_span_ops;
 +	init_waitqueue_head(&wc->span.maintq);
 +
-+	wc->span.pvt = wc;
 +	if (dahdi_register(&wc->span, 0)) {
 +		cardcrit(wc->boardnum, "Unable to register span with dahdi");
 +		return RET_FAIL;
@@ -4951,9 +7929,10 @@
 +MODULE_VERSION(DAHDI_VERSION);
 +MODULE_LICENSE("GPL");
 +
---- /dev/null
-+++ b/drivers/dahdi/zaphfc/base.c
-@@ -0,0 +1,1706 @@
+diff -urN dahdi-svn-orig/drivers/dahdi/zaphfc/base.c dahdi-svn-new/drivers/dahdi/zaphfc/base.c
+--- dahdi-svn-orig/drivers/dahdi/zaphfc/base.c	1970-01-01 02:00:00.000000000 +0200
++++ dahdi-svn-new/drivers/dahdi/zaphfc/base.c	2011-03-07 11:52:51.411050187 +0200
+@@ -0,0 +1,1710 @@
 +/*
 + * zaphfc.c - Dahdi driver for HFC-S PCI A based ISDN BRI cards
 + *
@@ -5548,7 +8527,7 @@
 +
 +static int hfc_zap_startup(struct dahdi_span *span)
 +{
-+    struct dahdi_hfc *zthfc = span->pvt;
++    struct dahdi_hfc *zthfc = dahdi_hfc_from_span(span);
 +    struct hfc_card *hfctmp = zthfc->card;
 +    int alreadyrunning;
 +
@@ -5598,6 +8577,20 @@
 +
 +	return 0;
 +}
++
++static const struct dahdi_span_ops hfc_zap_span_ops = {
++	.owner = THIS_MODULE,
++	.chanconfig = hfc_zap_chanconfig,
++	.spanconfig = hfc_zap_spanconfig,
++	.startup = hfc_zap_startup,
++	.shutdown = hfc_zap_shutdown,
++	.maint = hfc_zap_maint,
++	.rbsbits = hfc_zap_rbsbits,
++	.open = hfc_zap_open,
++	.close = hfc_zap_close,
++	.ioctl = hfc_zap_ioctl,
++	.hdlc_hard_xmit = hfc_hdlc_hard_xmit
++};
 +
 +static int hfc_zap_initialize(struct dahdi_hfc *hfccard)
 +{
@@ -5612,17 +8605,8 @@
 +			hfctmp->nt_mode ? "NT" : "TE");
 +	hfccard->span.spantype = hfctmp->nt_mode ? "NT" : "TE";
 +	hfccard->span.manufacturer = "Cologne Chips";
-+	hfccard->span.spanconfig = hfc_zap_spanconfig;
-+	hfccard->span.chanconfig = hfc_zap_chanconfig;
-+	hfccard->span.startup = hfc_zap_startup;
-+	hfccard->span.shutdown = hfc_zap_shutdown;
-+	hfccard->span.maint = hfc_zap_maint;
-+	hfccard->span.rbsbits = hfc_zap_rbsbits;
-+	hfccard->span.open = hfc_zap_open;
-+	hfccard->span.close = hfc_zap_close;
-+	hfccard->span.ioctl = hfc_zap_ioctl;
-+	hfccard->span.hdlc_hard_xmit = hfc_hdlc_hard_xmit;
 +	hfccard->span.flags = 0;
++	hfccard->span.ops = &hfc_zap_span_ops;
 +	hfccard->span.irq = hfctmp->pcidev->irq;
 +	dahdi_copy_string(hfccard->span.devicetype, "HFC-S PCI-A ISDN",
 +			sizeof(hfccard->span.devicetype));
@@ -5637,7 +8621,6 @@
 +	hfccard->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_CCS;
 +	hfccard->span.offset = 0;
 +	init_waitqueue_head(&hfccard->span.maintq);
-+	hfccard->span.pvt = hfccard;
 +
 +	for (i = 0; i < hfccard->span.channels; i++) {
 +		memset(&hfccard->chans[i], 0x0, sizeof(struct dahdi_chan));
@@ -5654,7 +8637,7 @@
 +
 +		if (i == hfccard->span.channels - 1) {
 +			hfccard->chans[i].sigcap = DAHDI_SIG_HARDHDLC;
-+			hfccard->sigchan = &hfccard->chans[DAHDI_D];
++			hfccard->sigchan = &hfccard->chans[D];
 +			hfccard->sigactive = 0;
 +			atomic_set(&hfccard->hdlc_pending, 0);
 +		} else {
@@ -6660,8 +9643,9 @@
 +#ifdef DEBUG
 +MODULE_PARM_DESC(debug_level, "Debug verbosity level");
 +#endif
---- /dev/null
-+++ b/drivers/dahdi/zaphfc/fifo.c
+diff -urN dahdi-svn-orig/drivers/dahdi/zaphfc/fifo.c dahdi-svn-new/drivers/dahdi/zaphfc/fifo.c
+--- dahdi-svn-orig/drivers/dahdi/zaphfc/fifo.c	1970-01-01 02:00:00.000000000 +0200
++++ dahdi-svn-new/drivers/dahdi/zaphfc/fifo.c	2011-03-07 11:52:51.411050187 +0200
 @@ -0,0 +1,375 @@
 +/*
 + * fifo.c - HFC FIFO management routines
@@ -7038,8 +10022,9 @@
 +	}
 +}
 +
---- /dev/null
-+++ b/drivers/dahdi/zaphfc/fifo.h
+diff -urN dahdi-svn-orig/drivers/dahdi/zaphfc/fifo.h dahdi-svn-new/drivers/dahdi/zaphfc/fifo.h
+--- dahdi-svn-orig/drivers/dahdi/zaphfc/fifo.h	1970-01-01 02:00:00.000000000 +0200
++++ dahdi-svn-new/drivers/dahdi/zaphfc/fifo.h	2011-03-07 11:52:51.411050187 +0200
 @@ -0,0 +1,139 @@
 +/*
 + * fifo.h - Dahdi driver for HFC-S PCI A based ISDN BRI cards
@@ -7180,8 +10165,9 @@
 +void hfc_clear_fifo_tx(struct hfc_chan_simplex *chan);
 +
 +#endif
---- /dev/null
-+++ b/drivers/dahdi/zaphfc/Kbuild
+diff -urN dahdi-svn-orig/drivers/dahdi/zaphfc/Kbuild dahdi-svn-new/drivers/dahdi/zaphfc/Kbuild
+--- dahdi-svn-orig/drivers/dahdi/zaphfc/Kbuild	1970-01-01 02:00:00.000000000 +0200
++++ dahdi-svn-new/drivers/dahdi/zaphfc/Kbuild	2011-03-07 11:52:51.411050187 +0200
 @@ -0,0 +1,10 @@
 +obj-m += zaphfc.o
 +
@@ -7193,9 +10179,10 @@
 +$(obj)/fifo.o: $(src)/fifo.h
 +
 +
---- /dev/null
-+++ b/drivers/dahdi/zaphfc/zaphfc.h
-@@ -0,0 +1,414 @@
+diff -urN dahdi-svn-orig/drivers/dahdi/zaphfc/zaphfc.h dahdi-svn-new/drivers/dahdi/zaphfc/zaphfc.h
+--- dahdi-svn-orig/drivers/dahdi/zaphfc/zaphfc.h	1970-01-01 02:00:00.000000000 +0200
++++ dahdi-svn-new/drivers/dahdi/zaphfc/zaphfc.h	2011-03-07 11:52:51.411050187 +0200
+@@ -0,0 +1,418 @@
 +/*
 + * zaphfc.h - Dahdi driver for HFC-S PCI A based ISDN BRI cards
 + *
@@ -7599,6 +10586,10 @@
 +
 +} dahdi_hfc;
 +
++static inline struct dahdi_hfc* dahdi_hfc_from_span(struct dahdi_span *span) {
++	return container_of(span, struct dahdi_hfc, span);
++}
++
 +static inline u8 hfc_inb(struct hfc_card *card, int offset)
 +{
 + return readb(card->io_mem + offset);
@@ -7610,8 +10601,9 @@
 +}
 +
 +#endif
---- /dev/null
-+++ b/drivers/staging/echo/echo.c
+diff -urN dahdi-svn-orig/drivers/staging/echo/echo.c dahdi-svn-new/drivers/staging/echo/echo.c
+--- dahdi-svn-orig/drivers/staging/echo/echo.c	1970-01-01 02:00:00.000000000 +0200
++++ dahdi-svn-new/drivers/staging/echo/echo.c	2011-03-07 11:52:51.415060067 +0200
 @@ -0,0 +1,662 @@
 +/*
 + * SpanDSP - a series of DSP components for telephony
@@ -8275,8 +11267,9 @@
 +MODULE_AUTHOR("David Rowe");
 +MODULE_DESCRIPTION("Open Source Line Echo Canceller");
 +MODULE_VERSION("0.3.0");
---- /dev/null
-+++ b/drivers/staging/echo/echo.h
+diff -urN dahdi-svn-orig/drivers/staging/echo/echo.h dahdi-svn-new/drivers/staging/echo/echo.h
+--- dahdi-svn-orig/drivers/staging/echo/echo.h	1970-01-01 02:00:00.000000000 +0200
++++ dahdi-svn-new/drivers/staging/echo/echo.h	2011-03-07 11:52:51.415060067 +0200
 @@ -0,0 +1,175 @@
 +/*
 + * SpanDSP - a series of DSP components for telephony
@@ -8453,8 +11446,9 @@
 +};
 +
 +#endif /* __ECHO_H */
---- /dev/null
-+++ b/drivers/staging/echo/fir.h
+diff -urN dahdi-svn-orig/drivers/staging/echo/fir.h dahdi-svn-new/drivers/staging/echo/fir.h
+--- dahdi-svn-orig/drivers/staging/echo/fir.h	1970-01-01 02:00:00.000000000 +0200
++++ dahdi-svn-new/drivers/staging/echo/fir.h	2011-03-07 11:52:51.415060067 +0200
 @@ -0,0 +1,286 @@
 +/*
 + * SpanDSP - a series of DSP components for telephony
@@ -8742,8 +11736,9 @@
 +}
 +
 +#endif
---- /dev/null
-+++ b/drivers/staging/echo/Kbuild
+diff -urN dahdi-svn-orig/drivers/staging/echo/Kbuild dahdi-svn-new/drivers/staging/echo/Kbuild
+--- dahdi-svn-orig/drivers/staging/echo/Kbuild	1970-01-01 02:00:00.000000000 +0200
++++ dahdi-svn-new/drivers/staging/echo/Kbuild	2011-03-07 11:52:51.415060067 +0200
 @@ -0,0 +1,6 @@
 +ifdef DAHDI_USE_MMX
 +EXTRA_CFLAGS += -DUSE_MMX
@@ -8751,8 +11746,9 @@
 +
 +# An explicit 'obj-m' , unlike the Makefile
 +obj-m += echo.o
---- /dev/null
-+++ b/drivers/staging/echo/mmx.h
+diff -urN dahdi-svn-orig/drivers/staging/echo/mmx.h dahdi-svn-new/drivers/staging/echo/mmx.h
+--- dahdi-svn-orig/drivers/staging/echo/mmx.h	1970-01-01 02:00:00.000000000 +0200
++++ dahdi-svn-new/drivers/staging/echo/mmx.h	2011-03-07 11:52:51.415060067 +0200
 @@ -0,0 +1,288 @@
 +/*
 + * mmx.h
@@ -9042,8 +12038,9 @@
 +
 +
 +#endif /* AVCODEC_I386MMX_H */
---- /dev/null
-+++ b/drivers/staging/echo/oslec.h
+diff -urN dahdi-svn-orig/drivers/staging/echo/oslec.h dahdi-svn-new/drivers/staging/echo/oslec.h
+--- dahdi-svn-orig/drivers/staging/echo/oslec.h	1970-01-01 02:00:00.000000000 +0200
++++ dahdi-svn-new/drivers/staging/echo/oslec.h	2011-03-07 11:52:51.415060067 +0200
 @@ -0,0 +1,94 @@
 +/*
 + *  OSLEC - A line echo canceller.  This code is being developed

Modified: dahdi-linux/trunk/debian/patches/series
URL: http://svn.debian.org/wsvn/pkg-voip/dahdi-linux/trunk/debian/patches/series?rev=8816&op=diff
==============================================================================
--- dahdi-linux/trunk/debian/patches/series (original)
+++ dahdi-linux/trunk/debian/patches/series Mon Mar  7 10:14:41 2011
@@ -1,9 +1,5 @@
 # Mega-patch of extra drivers:
 dahdi_linux_extra
 no_firmware_download
-uk_rotary
 chanmute
-oslec_include_2634
-xpp_usb_buffer_2635
-voicebus_sem_h_2635
 wcb4xxp_bn4s0e




More information about the Pkg-voip-commits mailing list