[Pkg-voip-commits] r3133 - in zaptel/trunk: . debian debian/patches
Tzafrir Cohen
tzafrir-guest at alioth.debian.org
Mon Feb 12 00:55:45 CET 2007
Author: tzafrir-guest
Date: 2007-02-12 00:55:44 +0100 (Mon, 12 Feb 2007)
New Revision: 3133
Added:
zaptel/trunk/ds1x1f.c
Modified:
zaptel/trunk/debian/changelog
zaptel/trunk/debian/patches/Makefile_bristuff.dpatch
Log:
Add the driver ds1x1f for the TG-DG T1/E1 card (Closes: 403013).
Modified: zaptel/trunk/debian/changelog
===================================================================
--- zaptel/trunk/debian/changelog 2007-02-11 14:15:21 UTC (rev 3132)
+++ zaptel/trunk/debian/changelog 2007-02-11 23:55:44 UTC (rev 3133)
@@ -14,8 +14,9 @@
* Also install the xpp firmware loading udev rules. (Closes: #405502).
* List the tonezones supported by ztcfg and libtonezone in tonezones.txt
(Closes: #379108).
+ * Add the driver ds1x1f for the TG-DG T1/E1 card (Closes: 403013).
- -- Tzafrir Cohen <tzafrir.cohen at xorcom.com> Sun, 11 Feb 2007 06:56:07 +0200
+ -- Tzafrir Cohen <tzafrir.cohen at xorcom.com> Mon, 12 Feb 2007 01:32:11 +0200
zaptel (1:1.2.12~dfsg-4) UNRELEASED; urgency=low
Modified: zaptel/trunk/debian/patches/Makefile_bristuff.dpatch
===================================================================
--- zaptel/trunk/debian/patches/Makefile_bristuff.dpatch 2007-02-11 14:15:21 UTC (rev 3132)
+++ zaptel/trunk/debian/patches/Makefile_bristuff.dpatch 2007-02-11 23:55:44 UTC (rev 3133)
@@ -15,7 +15,7 @@
+BRIMODS=cwain qozap zaphfc ztgsm
+MODULES+=$(BRIMODS)
-+MODULES+=opvxa1200
++MODULES+=opvxa1200 ds1x1f
+BINS+=ztpty
+
MODULESO:=$(MODULES:%=%.o)
Added: zaptel/trunk/ds1x1f.c
===================================================================
--- zaptel/trunk/ds1x1f.c 2007-02-11 14:15:21 UTC (rev 3132)
+++ zaptel/trunk/ds1x1f.c 2007-02-11 23:55:44 UTC (rev 3133)
@@ -0,0 +1,2089 @@
+//=======================================================================
+// T1/E1 PCI card with failover DS1x1F card Driver
+//
+// Ver: 2.14 Date: 17.Jan.2007
+//
+// based of work by:
+// Mark Spencer <markster at digium.com>
+// Matthew Fredrickson <creslin at digium.com>
+// William Meadows <wmeadows at digium.com>
+//
+// Copyright (c)2006,2007 TCDG Corp.
+// All rights reserved.
+//
+// http://www.tc-dg.net
+//
+// 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/interrupt.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+
+#ifdef STANDALONE_ZAPATA
+#include "zaptel.h"
+#else
+#include <linux/zaptel.h>
+#endif
+
+
+#define WC_MAX_CARDS 32
+#define NUM_REGS 0xa9
+#define NUM_PCI 12
+
+#define OFS_FALC 0x0000 // pci address space offset for FALC registers 256 * 32 bit words (only 8 LSB used)
+#define OFS_TDM_WR 0x0800 // pci address space offset for TDM media shift register buffers 8 * 32 bit words
+#define OFS_TDM_RD 0x0900 // pci address space offset for TDM media shift register buffers 8 * 32 bit words
+#define OFS_CTRL 0x1000 // pci address space offset for card control register 1 * 32 bit
+#define OFS_CLK 0x1004 // pci address space offset for card clock / h.100 register 1 * 32 bit
+
+
+#define FLAG_STARTED 0x01
+#define FLAG_NMF 0x02
+#define FLAG_SENDINGYELLOW 0x04
+
+#define MODE_SW -1 // mode controlled by DIP switch
+#define MODE_T1 0x01 // T1 mode bit.0 = T1
+#define MODE_E1 0x02 // E1 mode bit.1 = E1
+#define MODE_UE1 0x82 // unchannelized E1 bit.7 = unchannelized
+#define MODE_J1 0x41 // J1 mode bit.6 = j1mode
+
+
+#define DS1_SET_REL 7 // new MAINT commands for controlling the bypass relay and monitoring, hot-standby
+#define DS1_CLR_REL 8
+#define DS1_SET_RXMON 9
+#define DS1_CLR_RXMON 10
+#define DS1_SET_TXEN 11
+#define DS1_CLR_TXEN 12
+
+
+
+//======================================= Control register bit definitions ================================
+
+#define CTRL_LOFF 0x0000 // All LED off
+#define CTRL_LGRN 0x0001 // Green LED control bit
+#define CTRL_LRED 0x0002 // Red LED control bit
+#define CTRL_REL 0x0004 // bypass relay L = bypass H = normal operation
+#define CTRL_TEST 0x0008 // relay presence test bit L = normal operation H= presence test
+#define CTRL_FRST 0x0010 // Falc reset bit L = normal operation H = Falc Reset
+#define CTRL_INTA 0x0100 // Interrupt acknowledge bit writing a '1' resets IRQ and IRM
+#define CTRL_IRQ 0x0100 // Interrupt request bit
+#define CTRL_IRM 0x0400 // Interrupt missed bit = previous interrupt has not yet been serviced when new one was triggered
+#define CTRL_RELI 0x0800 // relay presence bit H = no relay L = relay present (valid only when CTRL_TEST = H)
+#define CTRL_SW1 0x1000 // DIP switch #1
+#define CTRL_SW2 0x2000 // DIP switch #2
+#define CTRL_SW3 0x4000 // DIP switch #3
+#define CTRL_SW4 0x8000 // DIP switch #4
+
+//==================================== FALC-56 PEF-2256 register definitions ===============================
+
+#define FR_XFIFO 0x00
+#define FR_RFIFO 0x00
+#define FR_CMDR 0x02
+#define FR_MODE 0x03
+#define FR_RAH1 0x04
+#define FR_RAH2 0x05
+#define FR_RAL1 0x06
+#define FR_RAL2 0x07
+#define FR_IPC 0x08
+#define FR_CCR1 0x09
+#define FR_CCR2 0x0a
+#define FR_RTR1 0x0c
+#define FR_RTR2 0x0d
+#define FR_RTR3 0x0e
+#define FR_RTR4 0x0f
+#define FR_TTR1 0x10
+#define FR_TTR2 0x11
+#define FR_TTR3 0x12
+#define FR_TTR4 0x13
+#define FR_IMR0 0x14
+#define FR_IMR1 0x15
+#define FR_IMR2 0x16
+#define FR_IMR3 0x17
+#define FR_IMR4 0x18
+#define FR_IMR5 0x19
+#define FR_IERR 0x1b
+#define FR_FMR0 0x1c
+#define FR_FMR1 0x1d
+#define FR_FMR2 0x1e
+#define FR_LOOP 0x1f
+#define FR_FMR4 0x20
+#define FR_FMR5 0x21
+#define FR_XSW 0x20
+#define FR_XSP 0x21
+#define FR_XC0 0x22
+#define FR_XC1 0x23
+#define FR_RC0 0x24
+#define FR_RC1 0x25
+#define FR_XPM0 0x26
+#define FR_XPM1 0x27
+#define FR_XPM2 0x28
+#define FR_TSWM 0x29
+#define FR_IDLE 0x2b
+#define FR_XSA4 0x2c
+#define FR_XSA5 0x2d
+#define FR_XSA6 0x2e
+#define FR_XSA7 0x2f
+#define FR_XSA8 0x30
+#define FR_FMR3 0x31
+#define FR_CCB1 0x2f
+#define FR_CCB2 0x30
+#define FR_CCB3 0x31
+#define FR_ICB1 0x32
+#define FR_ICB2 0x33
+#define FR_ICB3 0x34
+#define FR_ICB4 0x35
+#define FR_LIM0 0x36
+#define FR_LIM1 0x37
+#define FR_PCD 0x38
+#define FR_PCR 0x39
+#define FR_LIM2 0x3a
+#define FR_LCR1 0x3b
+#define FR_LCR2 0x3c
+#define FR_LCR3 0x3d
+#define FR_SIC1 0x3e
+#define FR_SIC2 0x3f
+#define FR_SIC3 0x40
+#define FR_CMR1 0x44
+#define FR_CMR2 0x45
+#define FR_GCR 0x46
+#define FR_ESM 0x47
+#define FR_RBD 0x49
+#define FR_VSTR 0x4a
+#define FR_RES 0x4b
+#define FR_FRS0 0x4c
+#define FR_FRS1 0x4d
+#define FR_RSW 0x4e
+#define FR_RSP 0x4f
+#define FR_FECL 0x50
+#define FR_FECH 0x51
+#define FR_CVCL 0x52
+#define FR_CVCH 0x53
+#define FR_CEC1L 0x54
+#define FR_CEC1H 0x55
+#define FR_EBCL 0x56
+#define FR_EBCH 0x57
+#define FR_CEC2L 0x58
+#define FR_CEC2H 0x59
+#define FR_CEC3L 0x5a
+#define FR_CEC3H 0x5b
+#define FR_RSA4 0x5c
+#define FR_RSA5 0x5d
+#define FR_RSA6 0x5e
+#define FR_RSA7 0x5f
+#define FR_RSA8 0x60
+#define FR_DEC 0x60
+#define FR_RSA6S 0x61
+#define FR_RSP1 0x62
+#define FR_RSP2 0x63
+#define FR_SIS 0x64
+#define FR_RSIS 0x65
+#define FR_RBCL 0x66
+#define FR_RBCH 0x67
+#define FR_ISR0 0x68
+#define FR_ISR1 0x69
+#define FR_ISR2 0x6a
+#define FR_ISR3 0x6b
+#define FR_ISR4 0x6c
+#define FR_ISR5 0x6d
+#define FR_GIS 0x6e
+#define FR_XS1 0x70
+#define FR_XS2 0x71
+#define FR_XS3 0x72
+#define FR_XS4 0x73
+#define FR_XS5 0x74
+#define FR_XS6 0x75
+#define FR_XS7 0x76
+#define FR_XS8 0x77
+#define FR_XS9 0x78
+#define FR_XS10 0x79
+#define FR_XS11 0x7a
+#define FR_XS12 0x7b
+#define FR_XS13 0x7c
+#define FR_XS14 0x7d
+#define FR_XS15 0x7e
+#define FR_XS16 0x7f
+#define FR_RS1 0x70
+#define FR_RS2 0x71
+#define FR_RS3 0x72
+#define FR_RS4 0x73
+#define FR_RS5 0x74
+#define FR_RS6 0x75
+#define FR_RS7 0x76
+#define FR_RS8 0x77
+#define FR_RS9 0x78
+#define FR_RS10 0x79
+#define FR_RS11 0x7a
+#define FR_RS12 0x7b
+#define FR_RS13 0x7c
+#define FR_RS14 0x7d
+#define FR_RS15 0x7e
+#define FR_RS16 0x7f
+#define FR_PC1 0x80
+#define FR_PC2 0x81
+#define FR_PC3 0x82
+#define FR_PC4 0x83
+#define FR_PC5 0x84
+#define FR_GPC1 0x85
+#define FR_PC6 0x86
+#define FR_CMDR2 0x87
+#define FR_CMDR3 0x88
+#define FR_CMDR4 0x89
+#define FR_CCR3 0x8b
+#define FR_CCR4 0x8c
+#define FR_CCR5 0x8d
+#define FR_MODE2 0x8e
+#define FR_MODE3 0x8f
+#define FR_RBC2 0x90
+#define FR_RBC3 0x91
+#define FR_GCM1 0x92
+#define FR_GCM2 0x93
+#define FR_GCM3 0x94
+#define FR_GCM4 0x95
+#define FR_GCM5 0x96
+#define FR_GCM6 0x97
+#define FR_GCM7 0x98
+#define FR_GCM8 0x99
+#define FR_SIS2 0x98
+#define FR_RSIS2 0x99
+#define FR_SIS3 0x9a
+#define FR_RSIS3 0x9b
+#define FR_XFIFO2 0x9c
+#define FR_RFIFO2 0x9c
+#define FR_XFIFO3 0x9e
+#define FR_RFIFO3 0x9e
+#define FR_TSEO 0xa0
+#define FR_TSBS1 0xa1
+#define FR_TSBS2 0xa2
+#define FR_TSBS3 0xa3
+#define FR_TSS2 0xa4
+#define FR_TSS3 0xa5
+#define FR_TPC0 0xa8
+#define FR_WID 0xec
+
+//========================================================================================================
+
+struct t4_regs {
+ unsigned int pci[NUM_PCI];
+ unsigned char regs[NUM_REGS];
+};
+
+
+#define WCT4_GET_REGS _IOW (ZT_CODE, 60, struct t4_regs)
+
+
+
+static int clrtab[] = {0x80,0x40,0x20,0x10,0x8,0x4,0x2,0x1};
+
+static char name[] = {"ds1x1f"};
+
+struct t1 {
+ struct pci_dev *dev;
+ spinlock_t lock;
+ int spantype;
+ int spanflags; // Span flags
+ unsigned char txsigs[16]; // Copy of tx sig registers
+ int num;
+ int alarmcount; // How much red alarm we've seen
+ int alarmdebounce;
+ char *variety;
+
+ unsigned int intcount;
+ int prescaler; // interrupt divider
+
+ int usecount;
+ int blinktimer;
+ int alarmtimer;
+ int loopupcnt;
+ int loopdowncnt;
+ unsigned char ledtestreg;
+
+ void * cnaddr; // PCI and driver related parameters
+ void * ioaddr;
+ unsigned long iostart;
+ unsigned long iolen;
+ unsigned long cnstart;
+ unsigned long cnlen;
+ struct resource * cres;
+ struct resource * ires;
+
+ unsigned char txchunkptr; // pointer for rd/wr audiosamples
+ unsigned char rxchunkptr;
+
+ unsigned char ec_chunk1[32][ZT_CHUNKSIZE]; // echocanceller memory buffers
+ unsigned char ec_chunk2[32][ZT_CHUNKSIZE];
+
+ struct zt_span span; // Span
+ struct zt_chan chans[32]; // Channels
+};
+
+
+ // module paramter variables
+static int debug = 0; // defines debug modes 0,1,2
+static int cardmode = -1; // forces card into T1, E1, J1, UE1 mode , -1 = use DIP switches
+static int alarmdebounce = 0;
+static int loopback = 0;
+static int frames = -1; // sets the size of the cards framebuffer 1-8 frames (preferred are 1,2,4,8)
+static int extclk = -1; // controls the clock synchronization via H.100 bus connector
+static int monitor = 0; // monitor = 3 puts the card in a Hi-Z mode and enabling it to monitor T1/E1 traffic
+
+static struct t1 *cards[WC_MAX_CARDS];
+
+
+static inline void start_alarm(struct t1 *wc)
+{
+ wc->blinktimer = 0;
+}
+
+
+static int ds1_open(struct zt_chan *chan)
+{
+ struct t1 *wc = chan->pvt;
+
+ wc->usecount++;
+
+ try_module_get(THIS_MODULE);
+
+ return 0;
+}
+
+//-------------------------------------------------------------------------------------------------------------------------------------------
+static inline unsigned int led_write_reg(struct t1 *wc, unsigned int val) // write to the cards 32 bit control register
+{
+ unsigned int x;
+
+ x = (ioread32(wc->ioaddr + OFS_CTRL) & 0xfc) | (val & 0x03); // combine LED content with all other register data
+
+ iowrite32(x, wc->ioaddr + OFS_CTRL); // write back register content
+
+ return x;
+}
+
+//-------------------------------------------------------------------------------------------------------------------------------------------
+static inline unsigned int ctrl_set_reg(struct t1 *wc, unsigned int val) // set bits in control register
+{
+ unsigned x;
+
+ x = (ioread32(wc->ioaddr + OFS_CTRL) & 0xff) | val; // OR newcontent with all other register data
+
+ iowrite32(x, wc->ioaddr + OFS_CTRL); // write back register content
+
+ return x;
+}
+
+//-------------------------------------------------------------------------------------------------------------------------------------------
+static inline unsigned int ctrl_clr_reg(struct t1 *wc, unsigned int val) // clear bits in control register
+{
+ unsigned x;
+
+ x = (ioread32(wc->ioaddr + OFS_CTRL) & 0xff) & (val ^ 0xff); // OR newcontent with all other register data
+
+ iowrite32(x, wc->ioaddr + OFS_CTRL); // write back register content
+
+ return x;
+}
+
+//-------------------------------------------------------------------------------------------------------------------------------------------
+static inline unsigned int ctrl_write_reg(struct t1 *wc, unsigned int val) // write to the cards 32 bit control register
+{
+ iowrite32(val, wc->ioaddr + OFS_CTRL); // write back register content
+
+ return val;
+}
+
+
+//-------------------------------------------------------------------------------------------------------------------------------------------
+static inline unsigned int ctrl_read_reg(struct t1 *wc) // read control register
+{
+ return (ioread32(wc->ioaddr + OFS_CTRL)); // return content of control register
+}
+
+
+//-------------------------------------------------------------------------------------------------------------------------------------------
+static inline unsigned int clk_write_reg(struct t1 *wc, unsigned int val) // write to the cards 32 bit clock/ h.100 bus register
+{
+ iowrite32(val, wc->ioaddr + OFS_CLK); // write back register content
+
+ return val;
+}
+
+
+//-------------------------------------------------------------------------------------------------------------------------------------------
+static inline unsigned int clk_read_reg(struct t1 *wc) // read clock / h.100 bus register
+{
+ return (ioread32(wc->ioaddr + OFS_CLK)); // return content of control register
+}
+
+
+//-------------------------------------------------------------------------------------------------------------------------------------------
+static inline unsigned int __t1_framer_in(struct t1 *wc, const unsigned int reg) // read a Falc framer register
+{
+ int loc = ((reg & 0x00ff) << 2) + OFS_FALC; // FALC registers are on doubleword boundaries
+
+ return ((ioread32(wc->ioaddr + loc)) & 0xff); // return only the 8 lsb
+}
+
+
+
+static inline unsigned int t1_framer_in(struct t1 *wc, const unsigned int addr) // spinlock wrapper
+{
+ unsigned long flags;
+ unsigned int ret;
+
+ spin_lock_irqsave(&wc->lock, flags);
+
+ ret = __t1_framer_in(wc, addr);
+
+ spin_unlock_irqrestore(&wc->lock, flags);
+
+ return ret;
+}
+
+
+static inline void __t1_framer_out(struct t1 *wc, const unsigned int reg, const unsigned int val) // write to Falc framer register
+{
+ int loc = ((reg & 0x00ff) << 2) + OFS_FALC; // FALC registers are on doubleword boundaries
+ int ret;
+
+ iowrite32(val, wc->ioaddr + loc); // write to register
+
+ ret = (ioread32(wc->ioaddr + loc)) & 0xff; // for debugging read back register content
+
+ if (debug > 1)
+ {
+ if (ret == val) // check if write was successful
+ printk("Wrote: %02x to Adr: %02x \n", val, reg); // and print on the console
+ else
+ printk("Wrote: %02x to Adr: %02x but read back: %02x !!!\n", val, reg, ret); // print results on the console
+ }
+}
+
+
+static inline void t1_framer_out(struct t1 *wc, const unsigned int addr, const unsigned int value) // spinlock wrapper
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&wc->lock, flags);
+
+ __t1_framer_out(wc, addr, value);
+
+ spin_unlock_irqrestore(&wc->lock, flags);
+}
+
+//-------------------------------------------------------------------------------------------------------------------------------------------
+static void ds1_release(struct t1 *wc)
+{
+ zt_unregister(&wc->span);
+
+ kfree(wc);
+
+ printk("Freed a DS1x1F card\n");
+}
+
+
+static int ds1_close(struct zt_chan *chan)
+{
+ struct t1 *wc = chan->pvt;
+ wc->usecount--;
+
+ module_put(THIS_MODULE);
+
+ if (!wc->usecount) // If we're dead, release us now
+ ds1_release(wc);
+
+ return 0;
+}
+
+//----------------------------------------------------------------------------------------------------------------------------------------
+// HARDWARE INTERRUPT CONTROL Enable / Disable
+
+static void ds1_enable_interrupts(struct t1 *wc) // enable 8 kHz TDM interrupts from the pci card
+{
+ iowrite32(0x00000001, wc->cnaddr + 0x1ec); // enable internal interrupt
+
+ ctrl_set_reg(wc, CTRL_INTA); // clear interrupt status bit
+
+ if (debug)
+ printk("Enabled interrupts!\n");
+}
+
+static void ds1_disable_interrupts(struct t1 *wc) // disable all interrupts from the card
+{
+ ctrl_set_reg(wc, CTRL_INTA); // clear interrupt status bit
+
+ iowrite32(0x00000000, wc->cnaddr + 0x1ec); // disable internal interrupt
+
+ if (debug)
+ printk("Disabled interrupts!\n");
+}
+
+//----------------------------------------------------------------------------------------------------------------------------------------
+static void __ds1_set_clear(struct t1 *wc) // SELECT CLEAR CHANNEL MODE - FOR T1 ONLY
+{
+ int i;
+ unsigned short val;
+
+ val = 0;
+ for (i=0; i<8; i++) // go through channel 0-7
+ {
+ if (wc->span.chans[i ].flags & ZT_FLAG_CLEAR) // check if this channel is marked Clear channel
+ val |= clrtab[i];
+ }
+ __t1_framer_out(wc, FR_CCB1, val); // write register CCB1
+
+ val = 0;
+ for (i=0; i<8; i++) // go through channel 8-15
+ {
+ if (wc->span.chans[i+ 8].flags & ZT_FLAG_CLEAR) // check if this channel is marked Clear channel
+ val |= clrtab[i];
+ }
+ __t1_framer_out(wc, FR_CCB2, val); // write register CCB2
+
+ val = 0;
+ for (i=0; i<8; i++) // go through channel 16-23
+ {
+ if (wc->span.chans[i+16].flags & ZT_FLAG_CLEAR) // check if this channel is marked Clear channel
+ val |= clrtab[i];
+ }
+ __t1_framer_out(wc, FR_CCB3, val); // write register CCB3
+
+
+
+}
+
+//----------------------------------------------------------------------------------------------------------------------------------------
+static int ds1_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data)
+{
+ struct t4_regs regs;
+ int x;
+ struct t1 *wc;
+
+ wc = chan->pvt;
+
+ switch(cmd)
+ {
+ case WCT4_GET_REGS:
+ for (x=0; x<NUM_PCI; x++)
+ regs.pci[x] = (ioread32(wc->ioaddr + (x << 2)));
+
+ for (x=0; x<NUM_REGS; x++)
+ regs.regs[x] = t1_framer_in(wc, x);
+
+ if (copy_to_user((struct t4_regs *)data, ®s, sizeof(regs)))
+ return -EFAULT;
+ break;
+
+ case DS1_SET_REL: // Turn on failover relay - normal operation
+ ctrl_set_reg (wc, CTRL_REL);
+ break;
+
+ case DS1_CLR_REL: // turn off failover relay - bypass
+ ctrl_clr_reg (wc, CTRL_REL);
+ break;
+
+ case DS1_SET_RXMON: // Enable receiver Hi-Z monitor mode
+ __t1_framer_out(wc, FR_LIM2,__t1_framer_in(wc, FR_LIM2) & 0xFD); // LIM2: turn off AS1
+ break;
+
+ case DS1_CLR_RXMON: // Set receiver to normal 100 Ohm impedance
+ __t1_framer_out(wc, FR_LIM2,__t1_framer_in(wc, FR_LIM2) | 0x02); // LIM2: turn on AS1
+ break;
+
+ case DS1_SET_TXEN: // Enable transmitter - normal operation
+ __t1_framer_out(wc, FR_LIM2,__t1_framer_in(wc, FR_XPM2) & 0xBF); // XPM2: turn on line drivers
+ break;
+
+ case DS1_CLR_TXEN: // Disable transmitter - set to Hi-Z
+ __t1_framer_out(wc, FR_LIM2,__t1_framer_in(wc, FR_XPM2) | 0x40); // XPM2: turn off line drivers
+ break;
+
+
+
+ default:
+ return -ENOTTY;
+ }
+ return 0;
+}
+
+
+static int ds1_maint(struct zt_span *span, int cmd)
+{
+ struct t1 *wc = span->pvt;
+
+ if (wc->spantype == MODE_E1)
+ {
+ switch(cmd)
+ {
+ case ZT_MAINT_NONE:
+ printk("XXX Turn off local and remote loops E1 XXX\n");
+ break;
+
+ case ZT_MAINT_LOCALLOOP:
+ printk("XXX Turn on local loopback E1 XXX\n");
+ break;
+
+ case ZT_MAINT_REMOTELOOP:
+ printk("XXX Turn on remote loopback E1 XXX\n");
+ break;
+
+ case ZT_MAINT_LOOPUP:
+ printk("XXX Send loopup code E1 XXX\n");
+ break;
+
+ case ZT_MAINT_LOOPDOWN:
+ printk("XXX Send loopdown code E1 XXX\n");
+ break;
+
+ case ZT_MAINT_LOOPSTOP:
+ printk("XXX Stop sending loop codes E1 XXX\n");
+ break;
+
+ case DS1_SET_REL:
+ ctrl_set_reg (wc, CTRL_REL);
+ printk("XXX Turn off E1 bypass XXX\n");
+ break;
+
+ case DS1_CLR_REL:
+ ctrl_clr_reg (wc, CTRL_REL);
+ printk("XXX Turn on E1 bypass XXX\n");
+ break;
+
+ default:
+ printk("DS1x1F: Unknown E1 maintainance command: %d\n", cmd);
+ break;
+ }
+ }
+ else
+ {
+ switch(cmd)
+ {
+ case ZT_MAINT_NONE:
+ printk("XXX Turn off local and remote loops T1 XXX\n");
+ break;
+
+ case ZT_MAINT_LOCALLOOP:
+ printk("XXX Turn on local loop and no remote loop XXX\n");
+ break;
+
+ case ZT_MAINT_REMOTELOOP:
+ printk("XXX Turn on remote loopup XXX\n");
+ break;
+
+ case ZT_MAINT_LOOPUP:
+ t1_framer_out(wc, FR_FMR5, 0x50); /* FMR5: Nothing but RBS mode */
+ break;
+
+ case ZT_MAINT_LOOPDOWN:
+ t1_framer_out(wc, FR_FMR5, 0x60); /* FMR5: Nothing but RBS mode */
+ break;
+
+ case ZT_MAINT_LOOPSTOP:
+ t1_framer_out(wc, FR_FMR5, 0x40); /* FMR5: Nothing but RBS mode */
+ break;
+
+ case DS1_SET_REL:
+ ctrl_set_reg (wc, CTRL_REL);
+ printk("XXX Turn off T1 bypass XXX\n");
+ break;
+
+ case DS1_CLR_REL:
+ ctrl_clr_reg (wc, CTRL_REL);
+ printk("XXX Turn on T1 bypass XXX\n");
+ break;
+
+ default:
+ printk("DS1x1F: Unknown T1 maintainance command: %d\n", cmd);
+ break;
+ }
+ }
+ return 0;
+}
+
+
+static int ds1_rbsbits(struct zt_chan *chan, int bits)
+{
+ u_char m,c;
+ int n,b;
+ struct t1 *wc = chan->pvt;
+ unsigned long flags;
+
+ if(debug > 2)
+ printk("Setting CAS signalling bits to: %d for ch: %s\n", bits, chan->name);
+
+ spin_lock_irqsave(&wc->lock, flags);
+
+ if (wc->spantype == MODE_E1) // E1 CAS (R2) signalling
+ {
+ if (chan->chanpos == 16) // channel 16 is the signalling channel even for CAS
+ {
+ spin_unlock_irqrestore(&wc->lock, flags);
+ return 0; // so leave it alone
+ }
+
+ n = chan->chanpos - 1;
+
+ if (chan->chanpos > 15) // move everything above channel 16 one down
+ n--;
+
+ b = (n % 15);
+ c = wc->txsigs[b];
+ m = (n / 15) << 2; // we have to write one nibble with new bits
+ c &= (0xf << m); // while keeping the other nibble as is
+ c |= (bits & 0xf) << (4 - m);
+
+ wc->txsigs[b] = c;
+
+ __t1_framer_out(wc,FR_XS2 + b,c); // In E1 mode XS1 is not used for CAS signalling
+
+ }
+ else // T1 or J1 CAS mode
+ {
+ if (wc->span.lineconfig & ZT_CONFIG_D4) // Old D4 framin selected
+ {
+ n = chan->chanpos - 1;
+ b = (n/4);
+ c = wc->txsigs[b];
+ m = ((3 - (n % 4)) << 1); // D4 only uses 2 CAS bits per channel
+ c &= ~(0x3 << m); // do the nibble thing
+ c |= ((bits >> 2) & 0x3) << m;
+ wc->txsigs[b] = c;
+ // output them to the chip */
+ __t1_framer_out(wc,FR_XS1 + b ,c); // since there are only 2 bits per channel
+ __t1_framer_out(wc,FR_XS6 + b ,c); // write them into the CAS registers twice
+ }
+ else
+ {
+ if (wc->span.lineconfig & ZT_CONFIG_ESF) // ESF = CAS 4 bits per channel
+ {
+ n = chan->chanpos - 1;
+ b = (n/2);
+ c = wc->txsigs[b];
+ m = ((n % 2) << 2); // do the nibble thing
+ c &= (0xf << m);
+ c |= (bits & 0xf) << (4 - m);
+ wc->txsigs[b] = c;
+ // output them to the chip
+ __t1_framer_out(wc,FR_XS1 + b,c); // write only once
+ }
+ }
+ }
+
+ spin_unlock_irqrestore(&wc->lock, flags);
+
+ if (debug > 2)
+ printk("Finished setting CAS signalling bits\n");
+
+ return 0;
+}
+
+
+static void __t1_check_sigbits(struct t1 *wc) // read the current CAS bits from framerchip
+{
+ int a,i,rxs;
+
+ if (!(wc->span.flags & ZT_FLAG_RUNNING))
+ return;
+
+ if (wc->spantype == MODE_E1) // E1 CAS mode selected
+ {
+ for (i = 0; i < 15; i++) // do this in 16 steps
+ {
+ a = __t1_framer_in(wc, FR_RS2 + i); // RS1 is not used for CAS bits
+ rxs = (a & 0xf);
+
+ if (!(wc->span.chans[i+16].sig & ZT_SIG_CLEAR)) // get lower nibble = channel+16
+ {
+ if (wc->span.chans[i+16].rxsig != rxs)
+ zt_rbsbits(&wc->span.chans[i+16], rxs);
+ }
+
+ rxs = (a >> 4) & 0xf; // get upper nibble = channel +0
+
+ if (!(wc->span.chans[i].sig & ZT_SIG_CLEAR))
+ {
+ if (wc->span.chans[i].rxsig != rxs)
+ zt_rbsbits(&wc->span.chans[i], rxs);
+ }
+ }
+ }
+ else // T1 or J1 mode selected
+ {
+ if (wc->span.lineconfig & ZT_CONFIG_D4) // D4 framing selected
+ { // D4 uses only 2 CAS bits per channel
+ for (i = 0; i < 24; i+=4) // do it in 6 steps
+ {
+ a = __t1_framer_in(wc, FR_RS1 + (i>>2));
+
+ rxs = (a & 0x3) << 2; // get bits.0 and .1 = channel +3
+ if (!(wc->span.chans[i+3].sig & ZT_SIG_CLEAR))
+ {
+ if (wc->span.chans[i+3].rxsig != rxs)
+ zt_rbsbits(&wc->span.chans[i+3], rxs);
+ }
+
+ rxs = (a & 0xc); // get bits.2 and .3 = channel +2
+ if (!(wc->span.chans[i+2].sig & ZT_SIG_CLEAR))
+ {
+ if (wc->span.chans[i+2].rxsig != rxs)
+ zt_rbsbits(&wc->span.chans[i+2], rxs);
+ }
+
+ rxs = (a >> 2) & 0xc; // get bits.4 and .5 = channel +1
+ if (!(wc->span.chans[i+1].sig & ZT_SIG_CLEAR))
+ {
+ if (wc->span.chans[i+1].rxsig != rxs)
+ zt_rbsbits(&wc->span.chans[i+1], rxs);
+ }
+
+ rxs = (a >> 4) & 0xc; // get bits.6 and .7 = channel +0
+ if (!(wc->span.chans[i].sig & ZT_SIG_CLEAR))
+ {
+ if (wc->span.chans[i].rxsig != rxs)
+ zt_rbsbits(&wc->span.chans[i], rxs);
+ }
+ }
+ }
+ else // ESF framing uses 4 CAS bits per channel
+ {
+ for (i = 0; i < 24; i+=2) // do this in 12 steps
+ {
+ a = __t1_framer_in(wc, FR_RS1 + (i>>1));
+
+ rxs = (a & 0xf); // get lower nibble = channel +1
+ if (!(wc->span.chans[i+1].sig & ZT_SIG_CLEAR))
+ {
+ if (wc->span.chans[i+1].rxsig != rxs)
+ zt_rbsbits(&wc->span.chans[i+1], rxs);
+ }
+
+ rxs = (a >> 4) & 0xf; // get upper nibble = channel +0
+ if (!(wc->span.chans[i].sig & ZT_SIG_CLEAR))
+ {
+ if (wc->span.chans[i].rxsig != rxs)
+ zt_rbsbits(&wc->span.chans[i], rxs);
+ }
+ }
+ }
+ }
+}
+
+
+static void t4_serial_setup(struct t1 *wc)
+{
+ unsigned int RC,XC;
+
+ switch (wc->spantype)
+ {
+ case MODE_E1: // E1 mode
+ printk("DS1x1F: Setting global parameters for E1 \n");
+ break;
+
+ case MODE_UE1: // NEW - Unframed E1 mode
+ printk("DS1x1F: Setting global parameters for Unchannelized E1 \n");
+ break;
+
+ case MODE_J1: // J1 mode
+ printk("DS1x1F: Setting global parameters for J1 \n");
+ break;
+
+ default: // All others default to T1
+ printk("DS1x1F: Setting global parameters for T1 \n");
+ break;
+ }
+
+
+ RC = 0x000; // Rt = 4 x 125 ns cycle
+ XC = 0x004; // Xt = 0 x 125 nS cycles
+
+ t1_framer_out(wc, FR_GPC1, 0xe0); // GPC1: Multiplex mode enabled, FSC is output, active low, RCLK from channel 0
+ t1_framer_out(wc, FR_IPC, 0x05); // IPC: Interrupt push/pull active low
+
+ t1_framer_out(wc, FR_GCM1, 0x66);
+ t1_framer_out(wc, FR_GCM2, 0x0e);
+ t1_framer_out(wc, FR_GCM3, 0x3f);
+ t1_framer_out(wc, FR_GCM4, 0x0f);
+ t1_framer_out(wc, FR_GCM5, 0x04);
+ t1_framer_out(wc, FR_GCM6, 0x3c);
+ t1_framer_out(wc, FR_GCM7, 0x9c);
+ t1_framer_out(wc, FR_GCM8, 0x90);
+
+ t1_framer_out(wc, FR_GCR, 0x40); // GCR: Interrupt on Activation/Deactivation of AIX, LOS
+ t1_framer_out(wc, FR_SIC1, 0x82); // SIC1: 2.048 Mhz clock/bus, double buffer receive / transmit, byte interleaved
+ t1_framer_out(wc, FR_SIC2, 0x00); // SIC2: No FFS, no center receive eliastic buffer, phase 0
+ t1_framer_out(wc, FR_SIC3, 0x08); // SIC3: Edges for capture tx latches with rising edge / rx changes with falling edge
+ t1_framer_out(wc, FR_CMR1, 0x30); // CMR1: RCLK is at 8.192 Mhz dejittered
+ t1_framer_out(wc, FR_CMR2, 0x25); // CMR2: sync and clock for tx and rx provided by FALC
+
+ t1_framer_out(wc, FR_XC0, 0x00 | ((XC >> 8) & 0x07)); // XC0: Normal operation of Sa-bits
+ t1_framer_out(wc, FR_XC1, XC & 0xff); // XC1: tx offset
+
+ t1_framer_out(wc, FR_RC0, 0x00 | ((RC >> 8) & 0x07)); // RC0: rx offset
+ t1_framer_out(wc, FR_RC1, RC & 0xff); // RC1:
+
+ // ------------- Configure ports ---------------
+ t1_framer_out(wc, FR_PC1, 0x10); // PC1: FMR/SPYX output/input on RPA/XPA
+ t1_framer_out(wc, FR_PC2, 0x65); // PC2: unused
+ t1_framer_out(wc, FR_PC3, 0x65); // PC3: unused
+ t1_framer_out(wc, FR_PC4, 0x35); // PC4: unused
+ t1_framer_out(wc, FR_PC5, 0x33); // PC5: XMFS active low, SCLKR is input, RCLK is output
+ t1_framer_out(wc, FR_PC6, 0x01); // PC6: CLK1 is Tx Clock output, CLK2 is 2.048 Mhz from DCO-R
+
+ t1_framer_out(wc, FR_LCR1, 0x00); // Clear LCR1
+
+ printk("DS1x1F: Successfully initialized card\n");
+}
+
+
+static void __t1_configure_t1(struct t1 *wc, int lineconfig, int txlevel)
+{
+ char *mode, *frame, *lcode;
+ char as1;
+ char xlt;
+
+ __t1_framer_out(wc, FR_FMR1, 0xbc); // FMR1: Mode 1, T1 mode, CRC on for ESF, 2.048 Mhz system data rate, no XAIS
+
+ switch (monitor) // module parameter monitor
+ {
+ case 1:
+ as1 = 0x00; // Tx = normal / Rx = Hi-Z
+ xlt = 0x00;
+ break;
+
+ case 2:
+ as1 = 0x02; // Tx = Hi-Z / Rx = 100 Ohm
+ xlt = 0x40;
+ break;
+
+ case 3:
+ as1 = 0x00; // Tx = Hi-Z / Rx = Hi-Z
+ xlt = 0x40;
+ break;
+
+ default: // Tx = normal / Rx = 100 Ohm
+ as1 = 0x02;
+ xlt = 0x00;
+ break;
+ }
+
+ /* Configure line interface */
+ if (lineconfig & ZT_CONFIG_AMI)
+ {
+ lcode = "AMI";
+ __t1_framer_out(wc, FR_FMR0, 0xa0);
+ }
+ else
+ {
+ lcode = "B8ZS";
+ __t1_framer_out(wc, FR_FMR0, 0xf0);
+ }
+
+ if (!(lineconfig & ZT_CONFIG_D4) && !(lineconfig & ZT_CONFIG_ESF)) // support for F4 4 frame format
+ {
+ frame = "F4";
+ if (loopback)
+ __t1_framer_out(wc, FR_FMR2, 0x26);
+ else
+ __t1_framer_out(wc, FR_FMR2, 0x22);
+
+ if (wc->spantype == MODE_J1)
+ __t1_framer_out(wc, FR_FMR4, 0x1d);
+ else
+ __t1_framer_out(wc, FR_FMR4, 0x0d);
+ }
+
+ if (!(lineconfig & ZT_CONFIG_D4) && (lineconfig & ZT_CONFIG_ESF)) // standard ESF 24 frame format
+ {
+ frame = "ESF";
+
+ if (loopback)
+ __t1_framer_out(wc, FR_FMR2, 0xe6);
+ else
+ __t1_framer_out(wc, FR_FMR2, 0xe2);
+
+ if (wc->spantype == MODE_J1)
+ __t1_framer_out(wc, FR_FMR4, 0x1e);
+ else
+ __t1_framer_out(wc, FR_FMR4, 0x0e);
+ }
+
+ if ((lineconfig & ZT_CONFIG_D4) && !(lineconfig & ZT_CONFIG_ESF)) // standard D4 12 frame format
+ {
+ frame = "D4";
+ if (loopback)
+ __t1_framer_out(wc, FR_FMR2, 0x26);
+ else
+ __t1_framer_out(wc, FR_FMR2, 0x22);
+
+ if (wc->spantype == MODE_J1)
+ __t1_framer_out(wc, FR_FMR4, 0x1c);
+ else
+ __t1_framer_out(wc, FR_FMR4, 0x0c);
+ }
+
+ if ((lineconfig & ZT_CONFIG_D4) && (lineconfig & ZT_CONFIG_ESF)) // support for SLC96 framing mode used in TR-08 circuits
+ {
+ frame = "SLC96";
+ if (loopback)
+ __t1_framer_out(wc, FR_FMR2, 0x26);
+ else
+ __t1_framer_out(wc, FR_FMR2, 0x22);
+
+ if (wc->spantype == MODE_J1)
+ __t1_framer_out(wc, FR_FMR4, 0x1f);
+ else
+ __t1_framer_out(wc, FR_FMR4, 0x0f);
+ }
+
+
+ __t1_framer_out(wc, FR_FMR5, 0x40); // FMR5: Enable RBS mode */
+
+ __t1_framer_out(wc, FR_LIM1, 0xf8); // LIM1: Clear data in case of LOS, Set receiver threshold (0.5V), No remote loop, no DRS
+ __t1_framer_out(wc, FR_LIM0, 0x08); // LIM0: Enable auto long haul mode, no local loop (must be set after LIM1)
+
+ __t1_framer_out(wc, FR_CMDR, 0x50); // CMDR: Reset the receiver and transmitter line interface
+ __t1_framer_out(wc, FR_CMDR, 0x00); // CMDR: Reset the receiver and transmitter line interface
+
+ __t1_framer_out(wc, FR_PCD, 0x0a); // PCD: LOS after 176 consecutive "zeros"
+ __t1_framer_out(wc, FR_PCR, 0x15); // PCR: 22 "ones" clear LOS
+
+ if (wc->spantype == MODE_J1)
+ {
+ mode = "J1";
+ __t1_framer_out(wc, FR_RC0, 0x80); // J1 overide
+ }
+ else
+ {
+ mode = "T1";
+ }
+
+ switch (txlevel) // Set Tx pulse mask + Rx line build out
+ {
+ case 7:
+ __t1_framer_out(wc, FR_LIM2, 0xe1 | as1); // LIM2: LBO=3, RST=50%, LOS1=1
+ __t1_framer_out(wc, FR_XPM0, 0x07); // XPM0
+ __t1_framer_out(wc, FR_XPM1, 0x01); // XPM1
+ __t1_framer_out(wc, FR_XPM2, 0x00 | xlt); // XPM2
+ break;
+
+ case 6:
+ __t1_framer_out(wc, FR_LIM2, 0xa1 | as1); // LIM2: LBO=2, RST=50%, LOS1=1
+ __t1_framer_out(wc, FR_XPM0, 0x8c); // XPM0
+ __t1_framer_out(wc, FR_XPM1, 0x11); // XPM1
+ __t1_framer_out(wc, FR_XPM2, 0x01 | xlt); // XPM2
+ break;
+
+ case 5:
+ __t1_framer_out(wc, FR_LIM2, 0x61 | as1); // LIM2: LBO=1, RST=50%, LOS1=1
+ __t1_framer_out(wc, FR_XPM0, 0x8c); // XPM0
+ __t1_framer_out(wc, FR_XPM1, 0x01); // XPM1
+ __t1_framer_out(wc, FR_XPM2, 0x00 | xlt); // XPM2
+ break;
+
+ default:
+ __t1_framer_out(wc, FR_LIM2, 0x21 | as1); // LIM2: LBO=0, RST=50%, LOS1=1
+ __t1_framer_out(wc, FR_XPM0, 0xd7); // XPM0
+ __t1_framer_out(wc, FR_XPM1, 0x22); // XPM1
+ __t1_framer_out(wc, FR_XPM2, 0x01 | xlt); // XPM2
+ break;
+ }
+
+
+ printk("DS1x1F: Configured Mode: %s Framing: %s Linecode: %s\n", mode, frame, lcode);
+}
+
+
+static void __t1_configure_e1(struct t1 *wc, int lineconfig)
+{
+ unsigned int fmr2, fmr1;
+ unsigned int cas = 0;
+ char *crc4 = "";
+ char *frame, *lcode;
+ char as1;
+ char xlt;
+
+ fmr1 = 0x44; /* FMR1: E1 mode, Automatic force resync, PCM30 mode, 2.048 Mhz backplane, no XAIS */
+ fmr2 = 0x03; /* FMR2: Auto transmit remote alarm, auto loss of multiframe recovery, no payload loopback */
+
+ switch (monitor) // module parameter monitor
+ {
+ case 1:
+ as1 = 0x00; // Tx = normal / Rx = Hi-Z
+ xlt = 0x00;
+ break;
+
+ case 2:
+ as1 = 0x02; // Tx = Hi-Z / Rx = 100 Ohm
+ xlt = 0x40;
+ break;
+
+ case 3:
+ as1 = 0x00; // Tx = Hi-Z / Rx = Hi-Z
+ xlt = 0x40;
+ break;
+
+ default: // Tx = normal / Rx = 100 Ohm
+ as1 = 0x02;
+ xlt = 0x00;
+ break;
+ }
+
+
+ if (wc->spantype == MODE_UE1)
+ fmr2 |= 0x30;
+
+ if (loopback)
+ fmr2 |= 0x4;
+
+ if (lineconfig & ZT_CONFIG_CRC4)
+ {
+ fmr1 |= 0x08; /* CRC4 transmit */
+ fmr2 |= 0xc0; /* CRC4 receive */
+ crc4 = "/CRC4";
+ }
+
+ __t1_framer_out(wc, FR_FMR1, fmr1);
+ __t1_framer_out(wc, FR_FMR2, fmr2);
+
+
+ if (lineconfig & ZT_CONFIG_AMI) /* Configure line interface */
+ {
+ lcode = "AMI";
+ __t1_framer_out(wc, FR_FMR0, 0xa0);
+ }
+ else
+ {
+ lcode = "HDB3";
+ __t1_framer_out(wc, FR_FMR0, 0xf0);
+ }
+
+ if (lineconfig & ZT_CONFIG_CCS)
+ {
+ frame = "CCS";
+ }
+ else
+ {
+ frame = "CAS";
+ cas = 0x40;
+ }
+
+ if (wc->spantype == MODE_UE1)
+ __t1_framer_out(wc, FR_LOOP, 0x40);
+
+ __t1_framer_out(wc, FR_LIM1, 0xf0); // LIM1: Clear data in case of LOS, Set receiver threshold (0.5V), No remote loop, no DRS
+ __t1_framer_out(wc, FR_LIM0, 0x08); // LIM0: Enable auto long haul mode, no local loop (must be after LIM1)
+
+ __t1_framer_out(wc, FR_CMDR, 0x50); // CMDR: Reset the receiver and transmitter line interface
+ __t1_framer_out(wc, FR_CMDR, 0x00); // CMDR: Reset the receiver and transmitter line interface
+
+ // Condition receive line interface for E1 after reset
+ __t1_framer_out(wc, 0xbb, 0x17);
+ __t1_framer_out(wc, 0xbc, 0x55);
+ __t1_framer_out(wc, 0xbb, 0x97);
+ __t1_framer_out(wc, 0xbb, 0x11);
+ __t1_framer_out(wc, 0xbc, 0xaa);
+ __t1_framer_out(wc, 0xbb, 0x91);
+ __t1_framer_out(wc, 0xbb, 0x12);
+ __t1_framer_out(wc, 0xbc, 0x55);
+ __t1_framer_out(wc, 0xbb, 0x92);
+ __t1_framer_out(wc, 0xbb, 0x0c);
+ __t1_framer_out(wc, 0xbb, 0x00);
+ __t1_framer_out(wc, 0xbb, 0x8c);
+
+ __t1_framer_out(wc, FR_LIM2, 0x20 | as1); // LIM2: 50% peak amplitude is a "1"
+ __t1_framer_out(wc, FR_PCD, 0x0a); // PCD: LOS after 176 consecutive "zeros"
+ __t1_framer_out(wc, FR_PCR, 0x15); // PCR: 22 "ones" clear LOS
+
+ __t1_framer_out(wc, FR_XSW, 0x9f); // XSW: Spare bits all to 1
+
+ if (wc->spantype == MODE_UE1)
+ __t1_framer_out(wc, FR_XSP, 0x3c );
+ else
+ __t1_framer_out(wc, FR_XSP, 0x1c | cas); // XSP: E-bit set when async. AXS auto, XSIF to 1
+
+ // Generate pulse mask for E1
+ __t1_framer_out(wc, FR_XPM0, 0x54); // XPM0
+ __t1_framer_out(wc, FR_XPM1, 0x02); // XPM1
+ __t1_framer_out(wc, FR_XPM2, 0x00 | xlt); // XPM2
+
+ if (wc->spantype == MODE_UE1)
+ printk("DS1x1F: Configured Mode: E1-Unchannelized Framing: %s Linecode: %s\n", frame, lcode);
+ else
+ printk("DS1x1F: Configured Mode: E1%s Framing: %s Linecode: %s\n", crc4, frame, lcode);
+
+}
+//-----------------------------------------------------------------------------------------------------------------------------------------
+
+
+static void ds1_framer_start(struct t1 *wc, struct zt_span *span)
+{
+ int alreadyrunning = wc->span.flags & ZT_FLAG_RUNNING;
+ unsigned long flags;
+
+ spin_lock_irqsave(&wc->lock, flags);
+
+ if (wc->spantype & MODE_E1)
+ { // configure in E1/ UE1 mode
+ __t1_configure_e1(wc, span->lineconfig);
+ }
+ else
+ { // configure in T1 / J1 mode
+ __t1_configure_t1(wc, span->lineconfig, span->txlevel);
+ __ds1_set_clear(wc);
+ }
+
+ if (!alreadyrunning)
+ wc->span.flags |= ZT_FLAG_RUNNING;
+
+ spin_unlock_irqrestore(&wc->lock, flags);
+}
+
+
+static int ds1_startup(struct zt_span *span)
+{
+ struct t1 *wc = span->pvt;
+
+ int alreadyrunning = span->flags & ZT_FLAG_RUNNING;
+ // initialize the start value for the entire chunk of last ec buffer
+ // Reset framer with proper parameters and start
+ ds1_framer_start(wc, span);
+ printk("Calling startup (flags is %d)\n", span->flags);
+
+ ctrl_write_reg(wc, CTRL_REL | CTRL_LRED); // now enable the relay
+
+
+ if (!alreadyrunning)
+ { // Only if we're not already going
+ ds1_enable_interrupts(wc);
+ span->flags |= ZT_FLAG_RUNNING;
+ }
+ return 0;
+}
+
+
+static int ds1_shutdown(struct zt_span *span)
+{
+ struct t1 *wc = span->pvt;
+ unsigned long flags;
+
+ spin_lock_irqsave(&wc->lock, flags);
+
+ __t1_framer_out(wc, FR_GCR, 0x41); // GCR: Interrupt on Activation/Deactivation of AIX, LOS
+
+ ds1_disable_interrupts(wc);
+
+ ctrl_write_reg(wc, CTRL_LRED); // turn off relay and turn on RED LED only
+
+ span->flags &= ~ZT_FLAG_RUNNING;
+ spin_unlock_irqrestore(&wc->lock, flags);
+ return 0;
+}
+
+
+static int ds1_chanconfig(struct zt_chan *chan, int sigtype)
+{
+ struct t1 *wc = chan->pvt;
+ unsigned long flags;
+ int alreadyrunning = chan->span->flags & ZT_FLAG_RUNNING;
+
+ spin_lock_irqsave(&wc->lock, flags);
+
+ if (alreadyrunning && (wc->spantype != MODE_E1))
+ __ds1_set_clear(wc);
+
+ spin_unlock_irqrestore(&wc->lock, flags);
+ return 0;
+}
+
+
+static int ds1_spanconfig(struct zt_span *span, struct zt_lineconfig *lc)
+{
+ span->lineconfig = lc->lineconfig;
+ span->txlevel = lc->lbo;
+ span->rxlevel = 0;
+ /* Do we want to SYNC on receive or not */
+ /* If already running, apply changes immediately */
+ if (span->flags & ZT_FLAG_RUNNING)
+ return ds1_startup(span);
+
+ return 0;
+}
+
+
+static int ds1_software_init(struct t1 *wc)
+{
+ int x; /* Find position */
+
+ for (x = 0; x < WC_MAX_CARDS; x++)
+ {
+ if (!cards[x])
+ {
+ cards[x] = wc;
+ break;
+ }
+ }
+
+ if (x >= WC_MAX_CARDS)
+ return -1;
+
+ t4_serial_setup(wc);
+ wc->num = x;
+
+ sprintf(wc->span.name, "WCT1/%d" , wc->num);
+ sprintf(wc->span.desc, "%s Card %d", wc->variety, wc->num);
+
+ wc->span.spanconfig = ds1_spanconfig;
+ wc->span.chanconfig = ds1_chanconfig;
+ wc->span.startup = ds1_startup;
+ wc->span.shutdown = ds1_shutdown;
+ wc->span.rbsbits = ds1_rbsbits;
+ wc->span.maint = ds1_maint;
+ wc->span.open = ds1_open;
+ wc->span.close = ds1_close;
+
+ switch (wc->spantype)
+ {
+ case MODE_UE1:
+ wc->span.channels = 32;
+ break;
+
+ case MODE_E1:
+ wc->span.channels = 31;
+ break;
+
+ default:
+ wc->span.channels = 24;
+ break;
+ }
+
+ wc->span.chans = wc->chans;
+ wc->span.flags = ZT_FLAG_RBS;
+ wc->span.linecompat = ZT_CONFIG_AMI | ZT_CONFIG_B8ZS | ZT_CONFIG_D4 | ZT_CONFIG_ESF;
+ wc->span.ioctl = ds1_ioctl;
+ wc->span.pvt = wc;
+
+ if (wc->spantype & MODE_E1)
+ wc->span.deflaw = ZT_LAW_ALAW;
+ else
+ wc->span.deflaw = ZT_LAW_MULAW;
+
+ init_waitqueue_head(&wc->span.maintq);
+
+ for (x=0;x<wc->span.channels;x++)
+ {
+ sprintf(wc->chans[x].name, "WCT1/%d/%d", wc->num, x + 1);
+ wc->chans[x].sigcap = ZT_SIG_EM | ZT_SIG_CLEAR | ZT_SIG_EM_E1 |
+ ZT_SIG_FXSLS | ZT_SIG_FXSGS |
+ ZT_SIG_FXSKS | ZT_SIG_FXOLS | ZT_SIG_DACS_RBS |
+ ZT_SIG_FXOGS | ZT_SIG_FXOKS | ZT_SIG_CAS | ZT_SIG_SF;
+ wc->chans[x].pvt = wc;
+ wc->chans[x].chanpos = x + 1;
+ }
+
+ if (zt_register(&wc->span, 0))
+ {
+ printk("Unable to register span with zaptel\n");
+ return -1;
+ }
+ return 0;
+}
+
+
+static inline void __handle_leds(struct t1 *wc)
+{
+ int oldreg;
+
+ wc->blinktimer++;
+
+ if (wc->blinktimer >= 4000)
+ wc->blinktimer = 0;
+
+ oldreg = wc->ledtestreg;
+
+ if (wc->span.alarms & ZT_ALARM_RED) // RED alarm active
+ { // LOS = loss of signal
+ if (wc->blinktimer < 50)
+ wc->ledtestreg = CTRL_LRED;
+ else
+ wc->ledtestreg = CTRL_LOFF;
+
+ if (wc->blinktimer >= 200) // very fast flickering
+ wc->blinktimer = 0;
+
+ }
+ else
+ {
+ if (wc->span.alarms & ZT_ALARM_YELLOW) // YELLOW ALARM = RED LED flashing
+ { // other side can't see our signal
+ if (wc->blinktimer < 250)
+ wc->ledtestreg = CTRL_LRED;
+ else
+ wc->ledtestreg = CTRL_LOFF;
+
+ if (wc->blinktimer >= 500) // flashing
+ wc->blinktimer = 0;
+ }
+ else
+ {
+ if (wc->span.alarms & ZT_ALARM_BLUE) // BLUE ALARM
+ { // T1 failure in front of a repeater down the line
+ if (wc->blinktimer < 250)
+ wc->ledtestreg = CTRL_LGRN; // GREEN LED flashing
+ else
+ wc->ledtestreg = CTRL_LOFF;
+
+ if (wc->blinktimer >= 500) // flashing
+ wc->blinktimer = 0;
+ }
+ else
+ { // NO ALARM
+ if (wc->blinktimer < 150) // slow winking green led heartbeat
+ wc->ledtestreg = CTRL_LOFF;
+ else
+ wc->ledtestreg = CTRL_LGRN; // GREEN LED on most of the time
+ }
+ }
+ }
+
+ if (oldreg != wc->ledtestreg) // only when some bits have changed
+ led_write_reg(wc, wc->ledtestreg); // write LED bits 0,1
+}
+
+
+//====================================== SEND MEDIA DATA =====================================
+static void ds1_media(struct t1 *wc)
+{
+ int x,y,ty,ry,shift;
+ unsigned int tx,rx;
+ char frm;
+
+ frm = (clk_read_reg(wc) & 0x07) + 1; // see how many frames are to be read by card
+
+ ty = wc->txchunkptr;
+ ry = wc->rxchunkptr;
+
+
+ for (y = 0; y < frm; y++)
+ {
+ int reg = y * 32;
+
+ if (ty >= ZT_CHUNKSIZE)
+ {
+ ty = 0;
+ zt_transmit(&wc->span);
+ }
+
+ rx = ioread32(wc->ioaddr + OFS_TDM_RD + 0 + reg); // read in first 4 channels
+ tx = 0xff; // FALC-56 uses TS0 for sync purposes only
+
+ for (x=1; x<=wc->span.channels; x++)
+ {
+ if ((x % 4) == 0)
+ {
+ iowrite32(tx, wc->ioaddr + OFS_TDM_WR + x - 4 + reg); // write 4 bytes (channels) of pcm data
+ tx = 0;
+ rx = ioread32(wc->ioaddr + OFS_TDM_RD + x + reg);
+ }
+
+ shift = ((x % 4) << 3);
+ tx |= (wc->chans[x-1].writechunk[ty] & 0xff) << shift;
+ wc->chans[x-1].readchunk [ry] = (rx >> shift) & 0xff;
+ }
+
+ iowrite32(tx, wc->ioaddr + OFS_TDM_WR + (x & 0xfc) + reg); // write 4 bytes (channels) of pcm data
+
+ ty++;
+ ry++;
+
+ if (ry >= ZT_CHUNKSIZE)
+ {
+ ry = 0;
+
+ for (x=0; x<wc->span.channels; x++) // handle echocanceller memory fill
+ {
+ zt_ec_chunk(&wc->chans[x], wc->chans[x].readchunk, wc->ec_chunk2[x]);
+
+ memcpy(wc->ec_chunk2[x], wc->ec_chunk1[x] , ZT_CHUNKSIZE);
+ memcpy(wc->ec_chunk1[x], wc->chans[x].writechunk, ZT_CHUNKSIZE);
+ }
+
+ zt_receive(&wc->span);
+ }
+ }
+
+ wc->txchunkptr = ty;
+ wc->rxchunkptr = ry;
+}
+
+
+
+//===============================================================================================================================================================================
+
+
+static void __t1_check_alarms(struct t1 *wc)
+{
+ unsigned char c,d;
+ int alarms;
+ int x,j;
+
+ if (!(wc->span.flags & ZT_FLAG_RUNNING))
+ return;
+
+ c = __t1_framer_in(wc, FR_FRS0);
+ d = __t1_framer_in(wc, FR_FRS1);
+
+ /* Assume no alarms */
+ alarms = 0;
+
+ /* And consider only carrier alarms */
+ wc->span.alarms &= (ZT_ALARM_RED | ZT_ALARM_BLUE | ZT_ALARM_NOTOPEN);
+
+ if (wc->spantype & MODE_E1)
+ {
+ if (c & 0x04)
+ { /* No multiframe found, force RAI high after 400ms only if we haven't found a multiframe since last loss of frame */
+ if (!(wc->spanflags & FLAG_NMF))
+ {
+ __t1_framer_out(wc, FR_FMR4, 0x9f | 0x20); /* FMR4: Force RAI High */
+ wc->spanflags |= FLAG_NMF;
+ printk("NMF workaround on!\n");
+ }
+
+ __t1_framer_out(wc, FR_FMR2, 0xc3); /* Reset to CRC4 mode */
+ __t1_framer_out(wc, FR_FMR0, 0xf2); /* Force Resync */
+ __t1_framer_out(wc, FR_FMR0, 0xf0); /* Force Resync */
+ }
+ else
+ {
+ if (!(c & 0x02))
+ {
+ if ((wc->spanflags & FLAG_NMF))
+ {
+ __t1_framer_out(wc, FR_FMR4, 0x9f); /* FMR4: Clear forced RAI */
+ wc->spanflags &= ~FLAG_NMF;
+ printk("NMF workaround off!\n");
+ }
+ }
+ }
+ }
+ else
+ { /* Detect loopup code if we're not sending one */
+ if ((!wc->span.mainttimer) && (d & 0x08))
+ {
+ if ((wc->loopupcnt++ > 80) && (wc->span.maintstat != ZT_MAINT_REMOTELOOP)) // Loop-up code detected
+ {
+ __t1_framer_out(wc, FR_LIM0, 0x08); // LIM0: Disable any local loop
+ __t1_framer_out(wc, FR_LIM1, 0xf6); // LIM1: Enable remote loop
+
+ wc->span.maintstat = ZT_MAINT_REMOTELOOP; // maintainance status = REMOTELOOP
+ }
+ }
+ else
+ wc->loopupcnt = 0;
+
+ /* Same for loopdown code */
+ if ((!wc->span.mainttimer) && (d & 0x10))
+ { /* Loop-down code detected */
+ if ((wc->loopdowncnt++ > 80) && (wc->span.maintstat == ZT_MAINT_REMOTELOOP))
+ {
+ __t1_framer_out(wc, FR_LIM0, 0x08); /* LIM0: Disable any local loop */
+ __t1_framer_out(wc, FR_LIM1, 0xf0); /* LIM1: Disable remote loop */
+ wc->span.maintstat = ZT_MAINT_NONE;
+ }
+ }
+ else
+ wc->loopdowncnt = 0;
+ }
+
+ if (wc->span.lineconfig & ZT_CONFIG_NOTOPEN)
+ {
+ for (x=0,j=0;x < wc->span.channels;x++)
+ {
+ if ((wc->span.chans[x].flags & ZT_FLAG_OPEN) || (wc->span.chans[x].flags & ZT_FLAG_NETDEV))
+ j++;
+ }
+
+ if (!j)
+ alarms |= ZT_ALARM_NOTOPEN;
+ }
+
+ if (c & 0xa0)
+ {
+ if (wc->alarmcount >= alarmdebounce)
+ {
+ if (!(wc->spantype & 0x80))
+ alarms |= ZT_ALARM_RED;
+ }
+ else
+ wc->alarmcount++;
+ }
+ else
+ wc->alarmcount = 0;
+
+ if (c & 0x4)
+ alarms |= ZT_ALARM_BLUE;
+
+ /* Keep track of recovering */
+ if ((!alarms) && wc->span.alarms)
+ wc->alarmtimer = ZT_ALARMSETTLE_TIME;
+
+ if (wc->alarmtimer)
+ alarms |= ZT_ALARM_RECOVER;
+
+ /* If receiving alarms, go into Yellow alarm state */
+ if (alarms && !(wc->spanflags & FLAG_SENDINGYELLOW))
+ {
+ unsigned char fmr4;
+ printk("DS1x1F: Setting yellow alarm\n");
+ /* We manually do yellow alarm to handle RECOVER and NOTOPEN, otherwise it's auto anyway */
+ fmr4 = __t1_framer_in(wc, FR_FMR4);
+ __t1_framer_out(wc, FR_FMR4, fmr4 | 0x20);
+
+ wc->spanflags |= FLAG_SENDINGYELLOW;
+ }
+ else
+ {
+ if ((!alarms) && (wc->spanflags & FLAG_SENDINGYELLOW))
+ {
+ unsigned char fmr4;
+ printk("DS1x1F: Clearing yellow alarm\n");
+ // We manually do yellow alarm to handle RECOVER
+ fmr4 = __t1_framer_in(wc, FR_FMR4);
+ __t1_framer_out(wc, FR_FMR4, fmr4 & ~0x20);
+
+ wc->spanflags &= ~FLAG_SENDINGYELLOW;
+ }
+ }
+ // Re-check the timing source when we enter/leave alarm, not withstanding yellow alarm
+ if ((c & 0x10) && !(wc->spantype & 0x80))
+ alarms |= ZT_ALARM_YELLOW;
+
+ if (wc->span.mainttimer || wc->span.maintstat)
+ alarms |= ZT_ALARM_LOOPBACK;
+
+ wc->span.alarms = alarms;
+ zt_alarm_notify(&wc->span);
+}
+
+
+static void __ds1_do_counters(struct t1 *wc)
+{
+ if (wc->alarmtimer)
+ {
+ if (!--wc->alarmtimer)
+ {
+ wc->span.alarms &= ~(ZT_ALARM_RECOVER);
+ zt_alarm_notify(&wc->span);
+ }
+ }
+}
+
+///--------------------------------------------------------------------------------------------------------------------------------
+static irqreturn_t ds1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct t1 *wc = dev_id;
+ unsigned long flags;
+ unsigned int x;
+ int y;
+
+ x = ctrl_read_reg(wc); // read statusregister
+
+ if (!(x & CTRL_IRQ))
+ return IRQ_NONE;
+
+ ctrl_set_reg(wc, CTRL_INTA); // clear the interrupt flag
+
+ if (!wc->intcount && debug)
+ printk("DS1x1F: Got interrupt\n");
+
+ if (x & CTRL_IRM) // we missed at least one interrupt
+ printk("DS1x1F: Missed an Interrupt !!!\n");
+
+ ds1_media(wc); // handle media / audio- buffers
+
+ x = clk_read_reg(wc) & 0x07; // get the current frame buffer setting
+
+ spin_lock_irqsave(&wc->lock, flags);
+
+ y = wc->prescaler - 1;
+
+ if (y < 1)
+ {
+ y = 8 / (x + 1);
+
+ __handle_leds(wc);
+ // Count down timers
+ __ds1_do_counters(wc);
+
+ wc->intcount++;
+
+ x = wc->intcount & 0x0f; // Do some things that we don't have to do very often
+
+ switch(x)
+ {
+ case 0:
+ case 1:
+ break;
+ case 2:
+ __t1_check_sigbits(wc);
+ break;
+ case 4: // Check alarms 1/4 as frequently
+ if (!(wc->intcount & 0x30))
+ __t1_check_alarms(wc);
+ break;
+ }
+ }
+ wc->prescaler = y;
+
+ spin_unlock_irqrestore(&wc->lock, flags);
+
+ return IRQ_RETVAL(1);
+}
+
+static int memory_test(struct t1 *wc, int pattern)
+{
+ int ret = 0;
+ int x, y;
+
+ for (x=0; x<31; x++) // clear out tx tdm memory to FF
+ {
+ iowrite32 (pattern, wc->ioaddr + OFS_TDM_WR + (8 * x) );
+
+ y = ioread32( wc->ioaddr + OFS_TDM_WR + (8 * x) );
+
+ if (y != pattern)
+ {
+ ret = 1;
+ if (debug)
+ printk("DS1x1F: TDM tx memory failure %08x / %08x @ %02x LSB\n", pattern, y, x);
+ }
+ else
+ if (debug)
+ printk("DS1x1F: TDM tx memory OK %08x / %08x @ %02x LSB\n", pattern, y, x);
+
+ iowrite32 (pattern, wc->ioaddr + OFS_TDM_RD + (8 * x));
+
+ y = ioread32( wc->ioaddr + OFS_TDM_RD + (8 * x));
+
+ if (y != pattern)
+ {
+ ret = 1;
+ if (debug)
+ printk("DS1x1F: TDM rx memory failure %08x / %08x @ %02x MSB\n", pattern, y, x);
+ }
+ else
+ if (debug)
+ printk("DS1x1F: TDM rx memory OK %08x / %08x @ %02x MSB\n", pattern, y, x);
+
+
+ }
+ return (ret);
+}
+
+
+//--------------------------------------------------------------------------------------------------------------------------------------
+static int ds1_hardware_init(struct t1 *wc)
+{
+ unsigned int vstr, wid;
+ unsigned int x;
+
+ if (frames < 1) // setting frames = 0 autoadjust to current ZT_CHUNKSIZE
+ frames = ZT_CHUNKSIZE;
+
+ if (frames > 8) // maximum framebuffer size is 8 frames
+ frames = 8;
+
+ if (extclk == -1) // extclk not specified by parameter
+ {
+ x = ctrl_read_reg(wc); // read DIP switch
+ extclk = (x >> 14) & 0x03; // SW 3-4 => clock selection
+ }
+
+ switch (extclk) // external / H.100 bus clocking options
+ {
+ case 1: // clock derived from H.100 bus if available
+ x = 0x30 | (frames - 1);
+ break;
+
+ case 2: // this card is bus clock master
+ x = 0x20 | (frames - 1);
+ break;
+
+ default: // all other cases - internally clocked / no clk output
+ x = frames - 1;
+ break;
+ }
+
+ clk_write_reg (wc, x); // no loopback
+
+ mdelay(10); // wait for 10 msec. for FDET settle time
+
+ x = clk_read_reg(wc);
+
+ switch (x & 0x30)
+ {
+ case 0x20:
+ printk("DS1x1F: Clocking: Busmaster Framebuffer: %d frames\n",(x & 0x07) + 1);
+ break;
+
+ case 0x30:
+ if (x & 0x00010000)
+ printk("DS1x1F: Clocking: External ( clock present on bus) Framebuffer: %d frames\n",(x & 0x07) + 1);
+ else
+ printk("DS1x1F: Clocking: (External) no clock present on bus Framebuffer: %d frames\n",(x & 0x07) + 1);
+ break;
+
+ default:
+ printk("DS1x1F: Clocking: Internal Framebuffer: %d frames\n",(x & 0x07) + 1);
+ break;
+ }
+
+ ctrl_write_reg(wc, CTRL_INTA | CTRL_TEST | CTRL_FRST);
+
+ mdelay(10); // wait for 10 msec.
+
+ x = ctrl_read_reg(wc); // read in the controlregister
+
+ ctrl_write_reg(wc, CTRL_LRED);
+
+ mdelay(1); // wait for 1 msec.
+
+ if (cardmode != -1)
+ wc->spantype = cardmode; // read in spanmode paramter
+ else
+ switch (x & 0x3000) // check if SW-1 and SW-2
+ {
+ case 0x0000:
+ wc->spantype = MODE_T1; // OFF - OFF = T1
+ break;
+
+ case 0x1000:
+ wc->spantype = MODE_J1; // OFF - ON = J1
+ break;
+
+ case 0x2000:
+ wc->spantype = MODE_UE1; // ON - OFF = unchannelized E1
+ break;
+
+ case 0x3000:
+ wc->spantype = MODE_E1; // ON - ON = E1
+ break;
+ }
+
+ if (x & CTRL_RELI)
+ printk("DS1x1 Board Ver: %01x.%01x SW=%01x-%01x-%01x-%01x [%x]\n",(x>>28),((x>>20)&0xf),((x>>15)&1),((x>>14)&1),((x>>13)&1),((x>>12)&1),x);
+ else
+ printk("DS1x1F Board Ver: %01x.%01x SW=%01x-%01x-%01x-%01x [%x]\n",(x>>28),((x>>20)&0xf),((x>>15)&1),((x>>14)&1),((x>>13)&1),((x>>12)&1),x);
+
+ vstr = t1_framer_in(wc ,FR_VSTR); // identify FALC framer chip version
+ wid = t1_framer_in(wc ,FR_WID );
+
+ if (vstr == 0x05)
+ {
+ if (wid & 0xc0)
+ printk("FALC PEF-2256 Ver: 2.2 detected\n");
+ else
+ printk("FALC PEF-2256 Ver: 2.1 detected\n");
+ }
+ else
+ {
+ if ((wid & 0x03) == 0x03)
+ printk("!!! WARNING !!! Old FALC PEB-2256 Ver: 1.2 detected\n");
+ else
+ printk("!!! WARNING !!! FALC Version unknown: VSTR: %02x WID: %02x\n", vstr, wid);
+ }
+
+ ds1_disable_interrupts(wc);
+
+ x = 0;
+
+ if (memory_test (wc, 0x5555aaaa)) x = 1;
+ if (memory_test (wc, 0x01234567)) x = 1;
+ if (memory_test (wc, 0xaaaa5555)) x = 1;
+ if (memory_test (wc, 0x76543210)) x = 1;
+
+ if (x)
+ printk("DS1x1F: Card TDM memory test failed !!!\n");
+ else
+ printk("DS1x1F: Card TDM memory test completed.\n");
+
+ ds1_enable_interrupts(wc);
+
+ start_alarm(wc);
+ return 0;
+
+}
+
+
+static int __devinit ds1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ struct t1 *wc;
+ unsigned long end;
+
+
+ if (pci_enable_device(pdev))
+ {
+ printk (KERN_ALERT "DS1x1F: PCI enable failed\n");
+ pci_disable_device (pdev);
+ return (-EIO);
+ }
+ else
+ {
+ wc = kmalloc(sizeof(struct t1), GFP_KERNEL);
+
+ printk("Trying to init an DS1x1F\n");
+
+ if (wc)
+ {
+ memset(wc, 0x0, sizeof(struct t1)); // initialize structure with 0x00
+ spin_lock_init(&wc->lock);
+
+ wc->cnstart = pci_resource_start(pdev, 0); // read the assigned memory resources for region 0
+ end = pci_resource_end (pdev, 0);
+ wc->cnlen = end - wc->cnstart + 1;
+ wc->cres = request_mem_region(wc->cnstart,wc->cnlen,name);
+ wc->cnaddr = ioremap_nocache (wc->cnstart,wc->cnlen );
+
+ if(debug)
+ printk (KERN_INFO "Config resources = [0x%lx-0x%lx] (%ld) \n", wc->cnstart, end, wc->cnlen);
+
+ wc->iostart = pci_resource_start(pdev, 2); // read the assigned memory resources for region 2
+ end = pci_resource_end (pdev, 2);
+ wc->iolen = end - wc->iostart + 1;
+ wc->ires = request_mem_region(wc->iostart,wc->iolen,name);
+ wc->ioaddr = ioremap_nocache (wc->iostart,wc->iolen );
+
+ if(debug)
+ printk (KERN_INFO "I/O resources = [0x%lx-0x%lx] (%ld) \n", wc->iostart, end, wc->iolen);
+
+ wc->dev = pdev;
+
+ pci_set_drvdata(pdev, wc); // keep track of our device - i.e. for later removal
+
+ if (request_irq(pdev->irq, ds1_interrupt, SA_INTERRUPT | SA_SHIRQ, "ds1x1f", wc))
+ {
+ printk("DS1x1F: Unable to request IRQ %d\n", pdev->irq);
+ kfree(wc);
+ return -EIO;
+ }
+
+ ds1_hardware_init(wc); // Initialize hardware
+
+ wc->variety = "DS1x1F T1/E1-card"; // We now know which version of card we have
+ ds1_software_init(wc); // Misc. software stuff
+
+ printk("Found an: %s\n", wc->variety);
+ return (0);
+ }
+ else
+ {
+ printk (KERN_ALERT "DS1x1F: failed to allocate memory\n");
+ return (-ENOMEM);
+ }
+ }
+ return (0);
+}
+
+
+static void __devexit ds1_remove(struct pci_dev *pdev)
+{
+ struct t1 *wc = pci_get_drvdata(pdev);
+
+ if (wc)
+ {
+
+ ds1_disable_interrupts(wc); // In case hardware is still there
+ free_irq(pdev->irq, wc); // release the interrupt resource
+ mdelay(10);
+
+ zt_unregister(&wc->span);
+
+ if (debug)
+ printk (KERN_ALERT "DS1x1F: resetting relay / falc / red led on\n");
+
+ ctrl_write_reg(wc, CTRL_FRST | CTRL_LRED); // reset FALC, relay= off, Red LED = on
+
+ if (wc->ioaddr != NULL) // unmap io space
+ iounmap (wc->ioaddr);
+
+ if (wc->cnaddr != NULL) // unmap control space
+ iounmap (wc->cnaddr);
+
+ release_mem_region(wc->iostart, wc->iolen); // release io memory region
+ release_mem_region(wc->cnstart, wc->cnlen); // release control memory region
+
+ kfree(wc);
+
+ printk (KERN_ALERT "DS1x1F: disable pci device\n");
+ pci_disable_device (pdev);
+ }
+ else
+ printk (KERN_ALERT "DS1x1F: WARNING Removal Failed !!!\n");
+
+}
+
+
+static struct pci_device_id ds1_ids[] = { { PCI_DEVICE( 0x2321, 0x011f) }, { 0, }, };
+
+
+MODULE_DEVICE_TABLE(pci,ds1_ids);
+
+
+static struct pci_driver ds1_driver = {
+ name: "ds1x1f",
+ probe: ds1_probe,
+ remove: __devexit_p(ds1_remove),
+ suspend: NULL,
+ resume: NULL,
+ id_table: ds1_ids,
+};
+
+
+static int __init ds1_init(void)
+{
+ int res;
+ res = zap_pci_module(&ds1_driver);
+
+ if (res)
+ return -ENODEV;
+
+ return 0;
+}
+
+
+static void __exit ds1_cleanup(void)
+{
+ pci_unregister_driver(&ds1_driver);
+}
+
+
+
+module_param(alarmdebounce, int, 0600);
+module_param(loopback, int, 0600);
+module_param(cardmode, int, 0600);
+module_param(frames, int, 0600);
+module_param(debug, int, 0600);
+module_param(extclk, int, 0600);
+module_param(monitor, int, 0600);
+
+MODULE_DESCRIPTION("TC-DG ds1x1f Zaptel Driver");
+MODULE_AUTHOR("TCDG Corp. <tech at tc-dg.net");
+MODULE_LICENSE("GPL");
+
+module_init(ds1_init);
+module_exit(ds1_cleanup);
+
More information about the Pkg-voip-commits
mailing list