~ubuntu-branches/ubuntu/quantal/zaptel/quantal

« back to all changes in this revision

Viewing changes to wctdm24xxp.c

  • Committer: Bazaar Package Importer
  • Author(s): Tzafrir Cohen
  • Date: 2008-08-28 22:58:23 UTC
  • mfrom: (11.1.11 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080828225823-r8bdunirm8hmc76m
Tags: 1:1.4.11~dfsg-2
* Patch xpp_fxs_power: Fixed an issue with hook detection of the Astribank
  FXS module.
* Don't fail init.d script if fxotune fails. This may happen if running it
  when Asterisk is already running.
* Bump standards version to 3.8.0.0 .
* Ignore false lintian warning ("m-a a-i" has "a a").
* Patch xpp_fxo_cid_always: do always pass PCM if that's what the user
  asked.
* Patch vzaphfc_proc_root_dir: fix vzaphfc on 2.6.26.
* Patch wcte12xp_flags: Proper time for irq save flags.
* Patch headers_2627: Fix location of semaphore.h for 2.6.27 .
* Patch xpp_fxs_dtmf_leak: Don't play DTMFs to the wrong channel.
* Patch wctdm_fix_alarm: Fix sending channel alarms.
* Patch device_class_2626: Fix building 2.6.26 (Closes: #493397).
* Using dh_lintian for lintian overrides, hence requiring debhelper 6.0.7.
* Lintian: we know we have direct changes. Too bad we're half-upstream :-(
* Fix doc-base section names. 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Wilcard TDM2400P TDM FXS/FXO Interface Driver for Zapata Telephony interface
3
 
 *
4
 
 * Written by Mark Spencer <markster@digium.com>
5
 
 *
6
 
 * Copyright (C) 2005, 2006, Digium, Inc.
7
 
 *
8
 
 * All rights reserved.
9
 
 *
10
 
 * This program is free software; you can redistribute it and/or modify
11
 
 * it under the terms of the GNU General Public License as published by
12
 
 * the Free Software Foundation; either version 2 of the License, or
13
 
 * (at your option) any later version.
14
 
 * 
15
 
 * This program is distributed in the hope that it will be useful,
16
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 
 * GNU General Public License for more details.
19
 
 * 
20
 
 * You should have received a copy of the GNU General Public License
21
 
 * along with this program; if not, write to the Free Software
22
 
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
23
 
 *
24
 
 */
25
 
 
26
 
#include <linux/kernel.h>
27
 
#include <linux/errno.h>
28
 
#include <linux/module.h>
29
 
#include <linux/init.h>
30
 
#include <linux/errno.h>
31
 
#include <linux/pci.h>
32
 
#include <linux/interrupt.h>
33
 
#include "proslic.h"
34
 
#include "wctdm.h"
35
 
 
36
 
/* Comment to disable VPM support */
37
 
#define VPM_SUPPORT
38
 
 
39
 
#ifdef VPM_SUPPORT
40
 
 
41
 
/* Define to get more attention-grabbing but slightly more CPU using echocan status */
42
 
#define FANCY_ECHOCAN
43
 
 
44
 
#endif
45
 
 
46
 
/*
47
 
  Experimental max loop current limit for the proslic
48
 
  Loop current limit is from 20 mA to 41 mA in steps of 3
49
 
  (according to datasheet)
50
 
  So set the value below to:
51
 
  0x00 : 20mA (default)
52
 
  0x01 : 23mA
53
 
  0x02 : 26mA
54
 
  0x03 : 29mA
55
 
  0x04 : 32mA
56
 
  0x05 : 35mA
57
 
  0x06 : 37mA
58
 
  0x07 : 41mA
59
 
*/
60
 
static int loopcurrent = 20;
61
 
 
62
 
static alpha  indirect_regs[] =
63
 
{
64
 
{0,255,"DTMF_ROW_0_PEAK",0x55C2},
65
 
{1,255,"DTMF_ROW_1_PEAK",0x51E6},
66
 
{2,255,"DTMF_ROW2_PEAK",0x4B85},
67
 
{3,255,"DTMF_ROW3_PEAK",0x4937},
68
 
{4,255,"DTMF_COL1_PEAK",0x3333},
69
 
{5,255,"DTMF_FWD_TWIST",0x0202},
70
 
{6,255,"DTMF_RVS_TWIST",0x0202},
71
 
{7,255,"DTMF_ROW_RATIO_TRES",0x0198},
72
 
{8,255,"DTMF_COL_RATIO_TRES",0x0198},
73
 
{9,255,"DTMF_ROW_2ND_ARM",0x0611},
74
 
{10,255,"DTMF_COL_2ND_ARM",0x0202},
75
 
{11,255,"DTMF_PWR_MIN_TRES",0x00E5},
76
 
{12,255,"DTMF_OT_LIM_TRES",0x0A1C},
77
 
{13,0,"OSC1_COEF",0x7B30},
78
 
{14,1,"OSC1X",0x0063},
79
 
{15,2,"OSC1Y",0x0000},
80
 
{16,3,"OSC2_COEF",0x7870},
81
 
{17,4,"OSC2X",0x007D},
82
 
{18,5,"OSC2Y",0x0000},
83
 
{19,6,"RING_V_OFF",0x0000},
84
 
{20,7,"RING_OSC",0x7EF0},
85
 
{21,8,"RING_X",0x0160},
86
 
{22,9,"RING_Y",0x0000},
87
 
{23,255,"PULSE_ENVEL",0x2000},
88
 
{24,255,"PULSE_X",0x2000},
89
 
{25,255,"PULSE_Y",0x0000},
90
 
//{26,13,"RECV_DIGITAL_GAIN",0x4000},   // playback volume set lower
91
 
{26,13,"RECV_DIGITAL_GAIN",0x2000},     // playback volume set lower
92
 
{27,14,"XMIT_DIGITAL_GAIN",0x4000},
93
 
//{27,14,"XMIT_DIGITAL_GAIN",0x2000},
94
 
{28,15,"LOOP_CLOSE_TRES",0x1000},
95
 
{29,16,"RING_TRIP_TRES",0x3600},
96
 
{30,17,"COMMON_MIN_TRES",0x1000},
97
 
{31,18,"COMMON_MAX_TRES",0x0200},
98
 
{32,19,"PWR_ALARM_Q1Q2",0x07C0},
99
 
{33,20,"PWR_ALARM_Q3Q4", 0x4C00 /* 0x2600 */},
100
 
{34,21,"PWR_ALARM_Q5Q6",0x1B80},
101
 
{35,22,"LOOP_CLOSURE_FILTER",0x8000},
102
 
{36,23,"RING_TRIP_FILTER",0x0320},
103
 
{37,24,"TERM_LP_POLE_Q1Q2",0x008C},
104
 
{38,25,"TERM_LP_POLE_Q3Q4",0x0100},
105
 
{39,26,"TERM_LP_POLE_Q5Q6",0x0010},
106
 
{40,27,"CM_BIAS_RINGING",0x0C00},
107
 
{41,64,"DCDC_MIN_V",0x0C00},
108
 
{42,255,"DCDC_XTRA",0x1000},
109
 
{43,66,"LOOP_CLOSE_TRES_LOW",0x1000},
110
 
};
111
 
 
112
 
#ifdef FANCY_ECHOCAN
113
 
static char ectab[] = {
114
 
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, 
115
 
32, 32, 32, 32, 32, 32, 32, 32, 32, 32 ,32 ,32, 32,
116
 
32, 32, 32, 32, 32, 32, 32, 32, 32, 32 ,32 ,32, 32,
117
 
32, 32, 32, 32, 32, 32, 32, 32, 32, 32 ,32 ,32, 32,
118
 
31, 31, 30, 29, 28, 27, 25, 23, 22, 20, 18, 16, 13, 11, 9, 8, 6, 4, 3, 2, 1, 0, 0, 
119
 
};
120
 
static int ectrans[4] = { 0, 1, 3, 2 };
121
 
#define EC_SIZE (sizeof(ectab))
122
 
#define EC_SIZE_Q (sizeof(ectab) / 4)
123
 
#endif
124
 
 
125
 
/* Undefine to enable Power alarm / Transistor debug -- note: do not
126
 
   enable for normal operation! */
127
 
/* #define PAQ_DEBUG */
128
 
 
129
 
static struct fxo_mode {
130
 
        char *name;
131
 
        /* FXO */
132
 
        int ohs;
133
 
        int ohs2;
134
 
        int rz;
135
 
        int rt;
136
 
        int ilim;
137
 
        int dcv;
138
 
        int mini;
139
 
        int acim;
140
 
        int ring_osc;
141
 
        int ring_x;
142
 
} fxo_modes[] =
143
 
{
144
 
        { "FCC", 0, 0, 0, 1, 0, 0x3, 0, 0, },   /* US, Canada */
145
 
        { "TBR21", 0, 0, 0, 0, 1, 0x3, 0, 0x2, 0x7e6c, 0x023a, },
146
 
                                                                                /* Austria, Belgium, Denmark, Finland, France, Germany, 
147
 
                                                                                   Greece, Iceland, Ireland, Italy, Luxembourg, Netherlands,
148
 
                                                                                   Norway, Portugal, Spain, Sweden, Switzerland, and UK */
149
 
        { "ARGENTINA", 0, 0, 0, 0, 0, 0x3, 0, 0, },
150
 
        { "AUSTRALIA", 1, 0, 0, 0, 0, 0, 0x3, 0x3, },
151
 
        { "AUSTRIA", 0, 1, 0, 0, 1, 0x3, 0, 0x3, },
152
 
        { "BAHRAIN", 0, 0, 0, 0, 1, 0x3, 0, 0x2, },
153
 
        { "BELGIUM", 0, 1, 0, 0, 1, 0x3, 0, 0x2, },
154
 
        { "BRAZIL", 0, 0, 0, 0, 0, 0, 0x3, 0, },
155
 
        { "BULGARIA", 0, 0, 0, 0, 1, 0x3, 0x0, 0x3, },
156
 
        { "CANADA", 0, 0, 0, 0, 0, 0x3, 0, 0, },
157
 
        { "CHILE", 0, 0, 0, 0, 0, 0x3, 0, 0, },
158
 
        { "CHINA", 0, 0, 0, 0, 0, 0, 0x3, 0xf, },
159
 
        { "COLUMBIA", 0, 0, 0, 0, 0, 0x3, 0, 0, },
160
 
        { "CROATIA", 0, 0, 0, 0, 1, 0x3, 0, 0x2, },
161
 
        { "CYRPUS", 0, 0, 0, 0, 1, 0x3, 0, 0x2, },
162
 
        { "CZECH", 0, 0, 0, 0, 1, 0x3, 0, 0x2, },
163
 
        { "DENMARK", 0, 1, 0, 0, 1, 0x3, 0, 0x2, },
164
 
        { "ECUADOR", 0, 0, 0, 0, 0, 0x3, 0, 0, },
165
 
        { "EGYPT", 0, 0, 0, 0, 0, 0, 0x3, 0, },
166
 
        { "ELSALVADOR", 0, 0, 0, 0, 0, 0x3, 0, 0, },
167
 
        { "FINLAND", 0, 1, 0, 0, 1, 0x3, 0, 0x2, },
168
 
        { "FRANCE", 0, 1, 0, 0, 1, 0x3, 0, 0x2, },
169
 
        { "GERMANY", 0, 1, 0, 0, 1, 0x3, 0, 0x3, },
170
 
        { "GREECE", 0, 1, 0, 0, 1, 0x3, 0, 0x2, },
171
 
        { "GUAM", 0, 0, 0, 0, 0, 0x3, 0, 0, },
172
 
        { "HONGKONG", 0, 0, 0, 0, 0, 0x3, 0, 0, },
173
 
        { "HUNGARY", 0, 0, 0, 0, 0, 0x3, 0, 0, },
174
 
        { "ICELAND", 0, 1, 0, 0, 1, 0x3, 0, 0x2, },
175
 
        { "INDIA", 0, 0, 0, 0, 0, 0x3, 0, 0x4, },
176
 
        { "INDONESIA", 0, 0, 0, 0, 0, 0x3, 0, 0, },
177
 
        { "IRELAND", 0, 1, 0, 0, 1, 0x3, 0, 0x2, },
178
 
        { "ISRAEL", 0, 0, 0, 0, 1, 0x3, 0, 0x2, },
179
 
        { "ITALY", 0, 1, 0, 0, 1, 0x3, 0, 0x2, },
180
 
        { "JAPAN", 0, 0, 0, 0, 0, 0, 0x3, 0, },
181
 
        { "JORDAN", 0, 0, 0, 0, 0, 0, 0x3, 0, },
182
 
        { "KAZAKHSTAN", 0, 0, 0, 0, 0, 0x3, 0, },
183
 
        { "KUWAIT", 0, 0, 0, 0, 0, 0x3, 0, 0, },
184
 
        { "LATVIA", 0, 0, 0, 0, 1, 0x3, 0, 0x2, },
185
 
        { "LEBANON", 0, 0, 0, 0, 1, 0x3, 0, 0x2, },
186
 
        { "LUXEMBOURG", 0, 1, 0, 0, 1, 0x3, 0, 0x2, },
187
 
        { "MACAO", 0, 0, 0, 0, 0, 0x3, 0, 0, },
188
 
        { "MALAYSIA", 0, 0, 0, 0, 0, 0, 0x3, 0, },      /* Current loop >= 20ma */
189
 
        { "MALTA", 0, 0, 0, 0, 1, 0x3, 0, 0x2, },
190
 
        { "MEXICO", 0, 0, 0, 0, 0, 0x3, 0, 0, },
191
 
        { "MOROCCO", 0, 0, 0, 0, 1, 0x3, 0, 0x2, },
192
 
        { "NETHERLANDS", 0, 1, 0, 0, 1, 0x3, 0, 0x2, },
193
 
        { "NEWZEALAND", 0, 0, 0, 0, 0, 0x3, 0, 0x4, },
194
 
        { "NIGERIA", 0, 0, 0, 0, 0x1, 0x3, 0, 0x2, },
195
 
        { "NORWAY", 0, 1, 0, 0, 1, 0x3, 0, 0x2, },
196
 
        { "OMAN", 0, 0, 0, 0, 0, 0, 0x3, 0, },
197
 
        { "PAKISTAN", 0, 0, 0, 0, 0, 0, 0x3, 0, },
198
 
        { "PERU", 0, 0, 0, 0, 0, 0x3, 0, 0, },
199
 
        { "PHILIPPINES", 0, 0, 0, 0, 0, 0, 0x3, 0, },
200
 
        { "POLAND", 0, 0, 1, 1, 0, 0x3, 0, 0, },
201
 
        { "PORTUGAL", 0, 1, 0, 0, 1, 0x3, 0, 0x2, },
202
 
        { "ROMANIA", 0, 0, 0, 0, 0, 3, 0, 0, },
203
 
        { "RUSSIA", 0, 0, 0, 0, 0, 0, 0x3, 0, },
204
 
        { "SAUDIARABIA", 0, 0, 0, 0, 0, 0x3, 0, 0, },
205
 
        { "SINGAPORE", 0, 0, 0, 0, 0, 0x3, 0, 0, },
206
 
        { "SLOVAKIA", 0, 0, 0, 0, 0, 0x3, 0, 0x3, },
207
 
        { "SLOVENIA", 0, 0, 0, 0, 0, 0x3, 0, 0x2, },
208
 
        { "SOUTHAFRICA", 1, 0, 1, 0, 0, 0x3, 0, 0x3, },
209
 
        { "SOUTHKOREA", 0, 0, 0, 0, 0, 0x3, 0, 0, },
210
 
        { "SPAIN", 0, 1, 0, 0, 1, 0x3, 0, 0x2, },
211
 
        { "SWEDEN", 0, 1, 0, 0, 1, 0x3, 0, 0x2, },
212
 
        { "SWITZERLAND", 0, 1, 0, 0, 1, 0x3, 0, 0x2, },
213
 
        { "SYRIA", 0, 0, 0, 0, 0, 0, 0x3, 0, },
214
 
        { "TAIWAN", 0, 0, 0, 0, 0, 0, 0x3, 0, },
215
 
        { "THAILAND", 0, 0, 0, 0, 0, 0, 0x3, 0, },
216
 
        { "UAE", 0, 0, 0, 0, 0, 0x3, 0, 0, },
217
 
        { "UK", 0, 1, 0, 0, 1, 0x3, 0, 0x5, },
218
 
        { "USA", 0, 0, 0, 0, 0, 0x3, 0, 0, },
219
 
        { "YEMEN", 0, 0, 0, 0, 0, 0x3, 0, 0, },
220
 
};
221
 
 
222
 
#ifdef STANDALONE_ZAPATA
223
 
#include "zaptel.h"
224
 
#else
225
 
#include <linux/zaptel.h>
226
 
#endif
227
 
 
228
 
#ifdef LINUX26
229
 
#include <linux/moduleparam.h>
230
 
#endif
231
 
 
232
 
#define NUM_FXO_REGS 60
233
 
 
234
 
#define WC_MAX_IFACES 128
235
 
 
236
 
#define FLAG_EMPTY      0
237
 
#define FLAG_WRITE      1
238
 
#define FLAG_READ       2
239
 
 
240
 
#define RING_DEBOUNCE   128             /* Ringer Debounce (in ms) */
241
 
#define DEFAULT_BATT_DEBOUNCE   64              /* Battery debounce (in ms) */
242
 
#define POLARITY_DEBOUNCE 64           /* Polarity debounce (in ms) */
243
 
#define DEFAULT_BATT_THRESH     3               /* Anything under this is "no battery" */
244
 
 
245
 
#define OHT_TIMER               6000    /* How long after RING to retain OHT */
246
 
 
247
 
#define FLAG_3215       (1 << 0)
248
 
 
249
 
#define NUM_CARDS 24
250
 
#define NUM_EC    4
251
 
#define NUM_SLOTS 6
252
 
#define MAX_TDM_CHAN 31
253
 
 
254
 
#define EFRAME_SIZE     108
255
 
#define ERING_SIZE 16           /* Maximum ring size */
256
 
#define EFRAME_GAP 20
257
 
#define SFRAME_SIZE ((EFRAME_SIZE * ZT_CHUNKSIZE) + (EFRAME_GAP * (ZT_CHUNKSIZE - 1)))
258
 
 
259
 
#define MAX_ALARMS 10
260
 
 
261
 
#define MOD_TYPE_NONE           0
262
 
#define MOD_TYPE_FXS            1
263
 
#define MOD_TYPE_FXO            2
264
 
#define MOD_TYPE_FXSINIT        3       
265
 
#define MOD_TYPE_VPM            4
266
 
 
267
 
#define MINPEGTIME      10 * 8          /* 30 ms peak to peak gets us no more than 100 Hz */
268
 
#define PEGTIME         50 * 8          /* 50ms peak to peak gets us rings of 10 Hz or more */
269
 
#define PEGCOUNT        5               /* 5 cycles of pegging means RING */
270
 
 
271
 
#define SDI_CLK         (0x00010000)
272
 
#define SDI_DOUT        (0x00020000)
273
 
#define SDI_DREAD       (0x00040000)
274
 
#define SDI_DIN         (0x00080000)
275
 
 
276
 
#define NUM_CAL_REGS 12
277
 
 
278
 
#define PCI_WINDOW_SIZE ((2 * 2 * 2 * SFRAME_SIZE) + (2 * ERING_SIZE * 4))
279
 
 
280
 
#define USER_COMMANDS 8
281
 
#define ISR_COMMANDS  2
282
 
 
283
 
#define MAX_COMMANDS (USER_COMMANDS + ISR_COMMANDS)
284
 
 
285
 
#define __CMD_RD   (1 << 20)            /* Read Operation */
286
 
#define __CMD_WR   (1 << 21)            /* Write Operation */
287
 
#define __CMD_FIN  (1 << 22)            /* Has finished receive */
288
 
#define __CMD_TX   (1 << 23)            /* Has been transmitted */
289
 
 
290
 
#define CMD_WR(a,b) (((a) << 8) | (b) | __CMD_WR)
291
 
#define CMD_RD(a) (((a) << 8) | __CMD_RD)
292
 
#define CMD_BYTE(card,bit) (((((card) & 0x3) * 3 + (bit)) * 7) \
293
 
                        + ((card) >> 2))
294
 
 
295
 
 
296
 
struct calregs {
297
 
        unsigned char vals[NUM_CAL_REGS];
298
 
};
299
 
 
300
 
struct cmdq {
301
 
        unsigned int cmds[MAX_COMMANDS];
302
 
        unsigned char isrshadow[ISR_COMMANDS];
303
 
};
304
 
 
305
 
struct wctdm {
306
 
        struct pci_dev *dev;
307
 
        char *variety;
308
 
        struct zt_span span;
309
 
        unsigned char ios;
310
 
        unsigned int sdi;
311
 
        int usecount;
312
 
        unsigned int intcount;
313
 
        unsigned int rxints;
314
 
        unsigned int txints;
315
 
        unsigned int intmask;
316
 
        unsigned char txident;
317
 
        unsigned char rxident;
318
 
        int dead;
319
 
        int pos;
320
 
        int flags[NUM_CARDS];
321
 
        int freeregion;
322
 
        int alt;
323
 
        int rdbl;
324
 
        int tdbl;
325
 
        int curcard;
326
 
        unsigned char ctlreg;
327
 
        int cards;
328
 
        int cardflag;           /* Bit-map of present cards */
329
 
        spinlock_t reglock;
330
 
        wait_queue_head_t regq;
331
 
        /* FXO Stuff */
332
 
        union {
333
 
                struct {
334
 
                        int wasringing;
335
 
                        int ringdebounce;
336
 
                        int offhook;
337
 
                        int battdebounce;
338
 
                        int nobatttimer;
339
 
                        int battery;
340
 
                        int lastpol;
341
 
                        int polarity;
342
 
                        int polaritydebounce;
343
 
                } fxo;
344
 
                struct {
345
 
                        int oldrxhook;
346
 
                        int debouncehook;
347
 
                        int lastrxhook;
348
 
                        int debounce;
349
 
                        int ohttimer;
350
 
                        int idletxhookstate;            /* IDLE changing hook state */
351
 
                        int lasttxhook;
352
 
                        int palarms;
353
 
                        struct calregs calregs;
354
 
                } fxs;
355
 
        } mods[NUM_CARDS];
356
 
        struct cmdq cmdq[NUM_CARDS + NUM_EC];
357
 
        /* Receive hook state and debouncing */
358
 
        int modtype[NUM_CARDS + NUM_EC];
359
 
        /* Set hook */
360
 
        int sethook[NUM_CARDS + NUM_EC];
361
 
 
362
 
#ifdef VPM_SUPPORT
363
 
        int vpm;
364
 
        unsigned int dtmfactive;
365
 
        unsigned int dtmfmask;
366
 
        unsigned int dtmfmutemask;
367
 
        short dtmfenergy[NUM_CARDS];
368
 
        short dtmfdigit[NUM_CARDS];
369
 
#ifdef FANCY_ECHOCAN
370
 
        int echocanpos;
371
 
        int blinktimer;
372
 
#endif  
373
 
#endif
374
 
        unsigned long iobase;
375
 
        dma_addr_t      readdma;
376
 
        dma_addr_t      writedma;
377
 
        dma_addr_t  descripdma;
378
 
        volatile unsigned int *writechunk;                                      /* Double-word aligned write memory */
379
 
        volatile unsigned int *readchunk;                                       /* Double-word aligned read memory */
380
 
        volatile unsigned int *descripchunk;                                    /* Descriptors */
381
 
        struct zt_chan chans[NUM_CARDS];
382
 
};
383
 
 
384
 
 
385
 
struct wctdm_desc {
386
 
        char *name;
387
 
        int flags;
388
 
};
389
 
 
390
 
static struct wctdm_desc wctdm = { "Wildcard TDM2400P", 0 };
391
 
static int acim2tiss[16] = { 0x0, 0x1, 0x4, 0x5, 0x7, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x2, 0x0, 0x3 };
392
 
 
393
 
static struct wctdm *ifaces[WC_MAX_IFACES];
394
 
 
395
 
static void wctdm_release(struct wctdm *wc);
396
 
 
397
 
static int battdebounce = DEFAULT_BATT_DEBOUNCE;
398
 
static int battthresh = DEFAULT_BATT_THRESH;
399
 
static int debug = 0;
400
 
static int robust = 0;
401
 
static int timingonly = 0;
402
 
static int lowpower = 0;
403
 
static int boostringer = 0;
404
 
static int fastringer = 0;
405
 
static int _opermode = 0;
406
 
static char *opermode = "FCC";
407
 
static int fxshonormode = 0;
408
 
static int alawoverride = 0;
409
 
static int fxo_addrs[4] = { 0x00, 0x08, 0x04, 0x0c };
410
 
#ifdef VPM_SUPPORT
411
 
static int vpmsupport = 1;
412
 
static int vpmdtmfsupport = 0;
413
 
static int vpmspans = 4;
414
 
#define VPM_DEFAULT_DTMFTHRESHOLD 1250
415
 
static int dtmfthreshold = VPM_DEFAULT_DTMFTHRESHOLD;
416
 
#endif
417
 
 
418
 
static int wctdm_init_proslic(struct wctdm *wc, int card, int fast , int manual, int sane);
419
 
 
420
 
/* sleep in user space until woken up. Equivilant of tsleep() in BSD */
421
 
static int schluffen(wait_queue_head_t *q)
422
 
{
423
 
        DECLARE_WAITQUEUE(wait, current);
424
 
        add_wait_queue(q, &wait);
425
 
        current->state = TASK_INTERRUPTIBLE;
426
 
        if (!signal_pending(current)) schedule();
427
 
        current->state = TASK_RUNNING;
428
 
        remove_wait_queue(q, &wait);
429
 
        if (signal_pending(current)) return -ERESTARTSYS;
430
 
        return(0);
431
 
}
432
 
 
433
 
static inline int empty_slot(struct wctdm *wc, int card)
434
 
{
435
 
        int x;
436
 
        for (x=0;x<USER_COMMANDS;x++) {
437
 
                if (!wc->cmdq[card].cmds[x])
438
 
                        return x;
439
 
        }
440
 
        return -1;
441
 
}
442
 
 
443
 
static inline void cmd_dequeue(struct wctdm *wc, volatile unsigned char *writechunk, int card, int pos)
444
 
{
445
 
        unsigned long flags;
446
 
        unsigned int curcmd=0;
447
 
        int x;
448
 
#ifdef FANCY_ECHOCAN
449
 
        int ecval;
450
 
        ecval = wc->echocanpos;
451
 
        ecval += EC_SIZE_Q * ectrans[(card & 0x3)];
452
 
        ecval = ecval % EC_SIZE;
453
 
#endif
454
 
 
455
 
        /* Skip audio */
456
 
        writechunk += 24;
457
 
        spin_lock_irqsave(&wc->reglock, flags);
458
 
        /* Search for something waiting to transmit */
459
 
        if (pos) {
460
 
                for (x=0;x<MAX_COMMANDS;x++) {
461
 
                        if ((wc->cmdq[card].cmds[x] & (__CMD_RD | __CMD_WR)) && 
462
 
                           !(wc->cmdq[card].cmds[x] & (__CMD_TX | __CMD_FIN))) {
463
 
                                curcmd = wc->cmdq[card].cmds[x];
464
 
#if 0
465
 
                                printk("Transmitting command '%08x' in slot %d\n", wc->cmdq[card].cmds[x], wc->txident);
466
 
#endif                  
467
 
                                wc->cmdq[card].cmds[x] |= (wc->txident << 24) | __CMD_TX;
468
 
                                break;
469
 
                        }
470
 
                }
471
 
        }
472
 
        if (!curcmd) {
473
 
                /* If nothing else, use filler */
474
 
                if (wc->modtype[card] == MOD_TYPE_FXS)
475
 
                        curcmd = CMD_RD(64);
476
 
                else if (wc->modtype[card] == MOD_TYPE_FXO)
477
 
                        curcmd = CMD_RD(12);
478
 
                else if (wc->modtype[card] == MOD_TYPE_VPM) {
479
 
#ifdef FANCY_ECHOCAN
480
 
                        if (wc->blinktimer >= 0xf) {
481
 
                                curcmd = CMD_WR(0x1ab, 0x0f);
482
 
                        } else if (wc->blinktimer == (ectab[ecval] >> 1)) {
483
 
                                curcmd = CMD_WR(0x1ab, 0x00);
484
 
                        } else
485
 
#endif
486
 
                        curcmd = CMD_RD(0x1a0);
487
 
                }
488
 
        }
489
 
        if (wc->modtype[card] == MOD_TYPE_FXS) {
490
 
                writechunk[CMD_BYTE(card, 0)] = (1 << (card & 0x3));
491
 
                if (curcmd & __CMD_WR)
492
 
                        writechunk[CMD_BYTE(card, 1)] = (curcmd >> 8) & 0x7f;
493
 
                else
494
 
                        writechunk[CMD_BYTE(card, 1)] = 0x80 | ((curcmd >> 8) & 0x7f);
495
 
                writechunk[CMD_BYTE(card, 2)] = curcmd & 0xff;
496
 
        } else if (wc->modtype[card] == MOD_TYPE_FXO) {
497
 
                if (curcmd & __CMD_WR)
498
 
                        writechunk[CMD_BYTE(card, 0)] = 0x20 | fxo_addrs[card & 0x3];
499
 
                else
500
 
                        writechunk[CMD_BYTE(card, 0)] = 0x60 | fxo_addrs[card & 0x3];
501
 
                writechunk[CMD_BYTE(card, 1)] = (curcmd >> 8) & 0xff;
502
 
                writechunk[CMD_BYTE(card, 2)] = curcmd & 0xff;
503
 
        } else if (wc->modtype[card] == MOD_TYPE_FXSINIT) {
504
 
                /* Special case, we initialize the FXS's into the three-byte command mode then
505
 
                   switch to the regular mode.  To send it into thee byte mode, treat the path as
506
 
                   6 two-byte commands and in the last one we initialize register 0 to 0x80. All modules
507
 
                   read this as the command to switch to daisy chain mode and we're done.  */
508
 
                writechunk[CMD_BYTE(card, 0)] = 0x00;
509
 
                writechunk[CMD_BYTE(card, 1)] = 0x00;
510
 
                if ((card & 0x1) == 0x1) 
511
 
                        writechunk[CMD_BYTE(card, 2)] = 0x80;
512
 
                else
513
 
                        writechunk[CMD_BYTE(card, 2)] = 0x00;
514
 
#ifdef VPM_SUPPORT
515
 
        } else if (wc->modtype[card] == MOD_TYPE_VPM) {
516
 
                if (curcmd & __CMD_WR)
517
 
                        writechunk[CMD_BYTE(card, 0)] = ((card & 0x3) << 4) | 0xc | ((curcmd >> 16) & 0x1);
518
 
                else
519
 
                        writechunk[CMD_BYTE(card, 0)] = ((card & 0x3) << 4) | 0xa | ((curcmd >> 16) & 0x1);
520
 
                writechunk[CMD_BYTE(card, 1)] = (curcmd >> 8) & 0xff;
521
 
                writechunk[CMD_BYTE(card, 2)] = curcmd & 0xff;
522
 
#endif
523
 
        } else if (wc->modtype[card] == MOD_TYPE_NONE) {
524
 
                writechunk[CMD_BYTE(card, 0)] = 0x00;
525
 
                writechunk[CMD_BYTE(card, 1)] = 0x00;
526
 
                writechunk[CMD_BYTE(card, 2)] = 0x00;
527
 
        }
528
 
#if 0
529
 
        /* XXX */
530
 
        if (cmddesc < 40)
531
 
                printk("Pass %d, card = %d (modtype=%d), pos = %d, CMD_BYTES = %d,%d,%d, (%02x,%02x,%02x) curcmd = %08x\n", cmddesc, card, wc->modtype[card], pos, CMD_BYTE(card, 0), CMD_BYTE(card, 1), CMD_BYTE(card, 2), writechunk[CMD_BYTE(card, 0)], writechunk[CMD_BYTE(card, 1)], writechunk[CMD_BYTE(card, 2)], curcmd);
532
 
#endif
533
 
        spin_unlock_irqrestore(&wc->reglock, flags);
534
 
#if 0
535
 
        /* XXX */
536
 
        cmddesc++;
537
 
#endif  
538
 
}
539
 
 
540
 
static inline void cmd_decifer(struct wctdm *wc, volatile unsigned char *readchunk, int card)
541
 
{
542
 
        unsigned long flags;
543
 
        unsigned char ident;
544
 
        int x;
545
 
 
546
 
        /* Skip audio */
547
 
        readchunk += 24;
548
 
        spin_lock_irqsave(&wc->reglock, flags);
549
 
        /* Search for any pending results */
550
 
        for (x=0;x<MAX_COMMANDS;x++) {
551
 
                if ((wc->cmdq[card].cmds[x] & (__CMD_RD | __CMD_WR)) && 
552
 
                    (wc->cmdq[card].cmds[x] & (__CMD_TX)) && 
553
 
                   !(wc->cmdq[card].cmds[x] & (__CMD_FIN))) {
554
 
                        ident = (wc->cmdq[card].cmds[x] >> 24) & 0xff;
555
 
                        if (ident == wc->rxident) {
556
 
                                /* Store result */
557
 
                                wc->cmdq[card].cmds[x] |= readchunk[CMD_BYTE(card, 2)];
558
 
                                wc->cmdq[card].cmds[x] |= __CMD_FIN;
559
 
                                if (wc->cmdq[card].cmds[x] & __CMD_WR) {
560
 
                                        /* Go ahead and clear out writes since they need no acknowledgement */
561
 
                                        wc->cmdq[card].cmds[x] = 0x00000000;
562
 
                                } else if (x >= USER_COMMANDS) {
563
 
                                        /* Clear out ISR reads */
564
 
                                        wc->cmdq[card].isrshadow[x - USER_COMMANDS] = wc->cmdq[card].cmds[x] & 0xff;
565
 
                                        wc->cmdq[card].cmds[x] = 0x00000000;
566
 
                                }
567
 
                                break;
568
 
                        }
569
 
                }
570
 
        }
571
 
#if 0
572
 
        /* XXX */
573
 
        if (!pos && (cmddesc < 256))
574
 
                printk("Card %d: Command '%08x' => %02x\n",card,  wc->cmdq[card].lasttx[pos], wc->cmdq[card].lastrd[pos]);
575
 
#endif
576
 
        spin_unlock_irqrestore(&wc->reglock, flags);
577
 
}
578
 
 
579
 
static inline void cmd_checkisr(struct wctdm *wc, int card)
580
 
{
581
 
        if (!wc->cmdq[card].cmds[USER_COMMANDS + 0]) {
582
 
                if (wc->sethook[card]) {
583
 
                        wc->cmdq[card].cmds[USER_COMMANDS + 0] = wc->sethook[card];
584
 
                        wc->sethook[card] = 0;
585
 
                } else if (wc->modtype[card] == MOD_TYPE_FXS) {
586
 
                        wc->cmdq[card].cmds[USER_COMMANDS + 0] = CMD_RD(68);    /* Hook state */
587
 
                } else if (wc->modtype[card] == MOD_TYPE_FXO) {
588
 
                        wc->cmdq[card].cmds[USER_COMMANDS + 0] = CMD_RD(5);     /* Hook/Ring state */
589
 
#ifdef VPM_SUPPORT
590
 
                } else if (wc->modtype[card] == MOD_TYPE_VPM) {
591
 
                        wc->cmdq[card].cmds[USER_COMMANDS + 0] = CMD_RD(0xb9); /* DTMF interrupt */
592
 
#endif
593
 
                }
594
 
        }
595
 
        if (!wc->cmdq[card].cmds[USER_COMMANDS + 1]) {
596
 
                if (wc->modtype[card] == MOD_TYPE_FXS) {
597
 
#ifdef PAQ_DEBUG
598
 
                        wc->cmdq[card].cmds[USER_COMMANDS + 1] = CMD_RD(19);    /* Transistor interrupts */
599
 
#else
600
 
                        wc->cmdq[card].cmds[USER_COMMANDS + 1] = CMD_RD(64);    /* Battery mode */
601
 
#endif
602
 
                } else if (wc->modtype[card] == MOD_TYPE_FXO) {
603
 
                        wc->cmdq[card].cmds[USER_COMMANDS + 1] = CMD_RD(29);    /* Battery */
604
 
#ifdef VPM_SUPPORT
605
 
                } else if (wc->modtype[card] == MOD_TYPE_VPM) {
606
 
                        wc->cmdq[card].cmds[USER_COMMANDS + 1] = CMD_RD(0xbd); /* DTMF interrupt */
607
 
#endif
608
 
                }
609
 
        }
610
 
}
611
 
 
612
 
static inline void wctdm_transmitprep(struct wctdm *wc, int dbl)
613
 
{
614
 
        volatile unsigned char *writechunk;
615
 
        int x,y;
616
 
 
617
 
        dbl = dbl % 2;
618
 
 
619
 
        writechunk = (volatile unsigned char *)(wc->writechunk);
620
 
        if (dbl) 
621
 
                /* Write is at interrupt address.  Start writing from normal offset */
622
 
                writechunk += SFRAME_SIZE;
623
 
 
624
 
        /* Calculate Transmission */
625
 
        zt_transmit(&wc->span);
626
 
 
627
 
        for (x=0;x<ZT_CHUNKSIZE;x++) {
628
 
                /* Send a sample, as a 32-bit word */
629
 
                for (y=0;y < wc->cards;y++) {
630
 
                        if (!x)
631
 
                                cmd_checkisr(wc, y);
632
 
                        writechunk[y] = wc->chans[y].writechunk[x];
633
 
                        cmd_dequeue(wc, writechunk, y, x);
634
 
                }
635
 
#ifdef VPM_SUPPORT
636
 
                if (wc->vpm) {
637
 
                        if (!x)
638
 
                                wc->blinktimer++;
639
 
                        for (y=24;y<28;y++) {
640
 
                                if (!x)
641
 
                                        cmd_checkisr(wc, y);
642
 
                                cmd_dequeue(wc, writechunk, y, x);
643
 
                        }
644
 
#ifdef FANCY_ECHOCAN
645
 
                        if (wc->blinktimer >= 0xf) {
646
 
                                wc->blinktimer = -1;
647
 
                                wc->echocanpos++;
648
 
                        }
649
 
#endif                  
650
 
                }
651
 
#endif          
652
 
#if 0
653
 
                if (cmddesc < 1024)
654
 
                        printk("TC Result: %02x\n", wc->txident);
655
 
#endif                  
656
 
                if (x < ZT_CHUNKSIZE - 1) {
657
 
                        writechunk[EFRAME_SIZE] = wc->ctlreg;
658
 
                        writechunk[EFRAME_SIZE + 1] = wc->txident++;
659
 
                }
660
 
                writechunk += (EFRAME_SIZE + EFRAME_GAP);
661
 
        }
662
 
}
663
 
 
664
 
static inline void __wctdm_setctl(struct wctdm *wc, unsigned int addr, unsigned int val)
665
 
{
666
 
        outl(val, wc->iobase + addr);
667
 
}
668
 
 
669
 
static inline unsigned int __wctdm_getctl(struct wctdm *wc, unsigned int addr)
670
 
{
671
 
        return inl(wc->iobase + addr);
672
 
}
673
 
 
674
 
static inline void wctdm_setctl(struct wctdm *wc, unsigned int addr, unsigned int val)
675
 
{
676
 
        unsigned long flags;
677
 
        spin_lock_irqsave(&wc->reglock, flags);
678
 
        __wctdm_setctl(wc, addr, val);
679
 
        spin_unlock_irqrestore(&wc->reglock, flags);
680
 
}
681
 
 
682
 
static inline int wctdm_setreg_full(struct wctdm *wc, int card, int addr, int val, int inisr)
683
 
{
684
 
        unsigned long flags;
685
 
        int hit=0;
686
 
        int ret;
687
 
        do {
688
 
                spin_lock_irqsave(&wc->reglock, flags);
689
 
                hit = empty_slot(wc, card);
690
 
                if (hit > -1) {
691
 
                        wc->cmdq[card].cmds[hit] = CMD_WR(addr, val);
692
 
                }
693
 
                spin_unlock_irqrestore(&wc->reglock, flags);
694
 
                if (inisr)
695
 
                        break;
696
 
                if (hit < 0) {
697
 
                        if ((ret = schluffen(&wc->regq)))
698
 
                                return ret;
699
 
                }
700
 
        } while (hit < 0);
701
 
        return (hit > -1) ? 0 : -1;
702
 
}
703
 
 
704
 
static inline int wctdm_setreg_intr(struct wctdm *wc, int card, int addr, int val)
705
 
{
706
 
        return wctdm_setreg_full(wc, card, addr, val, 1);
707
 
}
708
 
static inline int wctdm_setreg(struct wctdm *wc, int card, int addr, int val)
709
 
{
710
 
        return wctdm_setreg_full(wc, card, addr, val, 0);
711
 
}
712
 
 
713
 
static inline int wctdm_getreg(struct wctdm *wc, int card, int addr)
714
 
{
715
 
        unsigned long flags;
716
 
        int hit;
717
 
        int ret=0;
718
 
        do {
719
 
                spin_lock_irqsave(&wc->reglock, flags);
720
 
                hit = empty_slot(wc, card);
721
 
                if (hit > -1) {
722
 
                        wc->cmdq[card].cmds[hit] = CMD_RD(addr);
723
 
                }
724
 
                spin_unlock_irqrestore(&wc->reglock, flags);
725
 
                if (hit < 0) {
726
 
                        if ((ret = schluffen(&wc->regq)))
727
 
                                return ret;
728
 
                }
729
 
        } while (hit < 0);
730
 
        do {
731
 
                spin_lock_irqsave(&wc->reglock, flags);
732
 
                if (wc->cmdq[card].cmds[hit] & __CMD_FIN) {
733
 
                        ret = wc->cmdq[card].cmds[hit] & 0xff;
734
 
                        wc->cmdq[card].cmds[hit] = 0x00000000;
735
 
                        hit = -1;
736
 
                }
737
 
                spin_unlock_irqrestore(&wc->reglock, flags);
738
 
                if (hit > -1) {
739
 
                        if ((ret = schluffen(&wc->regq)))
740
 
                                return ret;
741
 
                }
742
 
        } while (hit > -1);
743
 
        return ret;
744
 
}
745
 
 
746
 
static inline unsigned int wctdm_getctl(struct wctdm *wc, unsigned int addr)
747
 
{
748
 
        unsigned long flags;
749
 
        unsigned int val;
750
 
        spin_lock_irqsave(&wc->reglock, flags);
751
 
        val = __wctdm_getctl(wc, addr);
752
 
        spin_unlock_irqrestore(&wc->reglock, flags);
753
 
        return val;
754
 
}
755
 
 
756
 
static inline int __wctdm_sdi_clk(struct wctdm *wc)
757
 
{
758
 
        unsigned int ret;
759
 
        wc->sdi &= ~SDI_CLK;
760
 
        __wctdm_setctl(wc, 0x0048, wc->sdi);
761
 
        ret = __wctdm_getctl(wc, 0x0048);
762
 
        wc->sdi |= SDI_CLK;
763
 
        __wctdm_setctl(wc, 0x0048, wc->sdi);
764
 
        return ret & SDI_DIN;
765
 
}
766
 
 
767
 
static inline void __wctdm_sdi_sendbits(struct wctdm *wc, unsigned int bits, int count)
768
 
{
769
 
        wc->sdi &= ~SDI_DREAD;
770
 
        __wctdm_setctl(wc, 0x0048, wc->sdi);
771
 
        while(count--) {
772
 
                if (bits & (1 << count))
773
 
                        wc->sdi |= SDI_DOUT;
774
 
                else
775
 
                        wc->sdi &= ~SDI_DOUT;
776
 
                __wctdm_sdi_clk(wc);
777
 
        }
778
 
}
779
 
 
780
 
static inline unsigned int __wctdm_sdi_recvbits(struct wctdm *wc, int count)
781
 
{
782
 
        unsigned int bits=0;
783
 
        wc->sdi |= SDI_DREAD;
784
 
        __wctdm_setctl(wc, 0x0048, wc->sdi);
785
 
        while(count--) {
786
 
                bits <<= 1;
787
 
                if (__wctdm_sdi_clk(wc))
788
 
                        bits |= 1;
789
 
                else
790
 
                        bits &= ~1;
791
 
        }
792
 
        return bits;
793
 
}
794
 
 
795
 
static inline void __wctdm_setsdi(struct wctdm *wc, unsigned char addr, unsigned short value)
796
 
{
797
 
        unsigned int bits;
798
 
        /* Send preamble */
799
 
        bits = 0xffffffff;
800
 
        __wctdm_sdi_sendbits(wc, bits, 32);
801
 
        bits = (0x5 << 12) | (1 << 7) | (addr << 2) | 0x2;
802
 
        __wctdm_sdi_sendbits(wc, bits, 16);
803
 
        __wctdm_sdi_sendbits(wc, value, 16);
804
 
        
805
 
}
806
 
 
807
 
static inline unsigned short __wctdm_getsdi(struct wctdm *wc, unsigned char addr)
808
 
{
809
 
        unsigned int bits;
810
 
        /* Send preamble */
811
 
        bits = 0xffffffff;
812
 
        __wctdm_sdi_sendbits(wc, bits, 32);
813
 
        bits = (0x6 << 10) | (1 << 5) | (addr);
814
 
        __wctdm_sdi_sendbits(wc, bits, 14);
815
 
        return __wctdm_sdi_recvbits(wc, 18);
816
 
}
817
 
 
818
 
static inline void wctdm_setsdi(struct wctdm *wc, unsigned char addr, unsigned short value)
819
 
{
820
 
        unsigned long flags;
821
 
        spin_lock_irqsave(&wc->reglock, flags);
822
 
        __wctdm_setsdi(wc, addr, value);
823
 
        spin_unlock_irqrestore(&wc->reglock, flags);
824
 
}
825
 
 
826
 
static inline unsigned short wctdm_getsdi(struct wctdm *wc, unsigned char addr)
827
 
{
828
 
        unsigned long flags;
829
 
        unsigned short val;
830
 
        spin_lock_irqsave(&wc->reglock, flags);
831
 
        val = __wctdm_getsdi(wc, addr);
832
 
        spin_unlock_irqrestore(&wc->reglock, flags);
833
 
        return val;
834
 
}
835
 
#ifdef VPM_SUPPORT
836
 
static inline unsigned char wctdm_vpm_in(struct wctdm *wc, int unit, const unsigned int addr)
837
 
{
838
 
        return wctdm_getreg(wc, unit + NUM_CARDS, addr);
839
 
}
840
 
 
841
 
static inline void wctdm_vpm_out(struct wctdm *wc, int unit, const unsigned int addr, const unsigned char val)
842
 
{
843
 
        wctdm_setreg(wc, unit + NUM_CARDS, addr, val);
844
 
}
845
 
#endif
846
 
 
847
 
static inline void cmd_retransmit(struct wctdm *wc)
848
 
{
849
 
        int x,y;
850
 
        unsigned long flags;
851
 
        /* Force retransmissions */
852
 
        spin_lock_irqsave(&wc->reglock, flags);
853
 
        for (x=0;x<MAX_COMMANDS;x++) {
854
 
                for (y=0;y<wc->cards;y++) {
855
 
                        if (!(wc->cmdq[y].cmds[x] & __CMD_FIN))
856
 
                                wc->cmdq[y].cmds[x] &= ~(__CMD_TX | (0xff << 24));
857
 
                }
858
 
        }
859
 
        spin_unlock_irqrestore(&wc->reglock, flags);
860
 
}
861
 
 
862
 
static inline void wctdm_receiveprep(struct wctdm *wc, int dbl)
863
 
{
864
 
        volatile unsigned char *readchunk;
865
 
        int x,y;
866
 
        unsigned char expected;
867
 
 
868
 
        dbl = dbl % 2;
869
 
 
870
 
        readchunk = (volatile unsigned char *)wc->readchunk;
871
 
        if (dbl)
872
 
                readchunk += SFRAME_SIZE;
873
 
        for (x=0;x<ZT_CHUNKSIZE;x++) {
874
 
                if (x < ZT_CHUNKSIZE - 1) {
875
 
                        expected = wc->rxident+1;
876
 
                        wc->rxident = readchunk[EFRAME_SIZE + 1];
877
 
                        if (wc->rxident != expected) {
878
 
                                wc->span.irqmisses++;
879
 
                                cmd_retransmit(wc);
880
 
                        }
881
 
                }
882
 
                for (y=0;y < wc->cards;y++) {
883
 
                        wc->chans[y].readchunk[x] = readchunk[y];
884
 
                        cmd_decifer(wc, readchunk, y);
885
 
                }
886
 
#ifdef VPM_SUPPORT
887
 
                if (wc->vpm) {
888
 
                        for (y=NUM_CARDS;y < NUM_CARDS + NUM_EC; y++)
889
 
                                cmd_decifer(wc, readchunk, y);
890
 
                }
891
 
#endif
892
 
#if 0
893
 
                if (cmddesc < 1024) {
894
 
                        printk("RC Result: %02x\n", readchunk[EFRAME_SIZE+1]);
895
 
                }
896
 
#endif          
897
 
                readchunk += (EFRAME_SIZE + EFRAME_GAP);
898
 
        }
899
 
        /* XXX We're wasting 8 taps.  We should get closer :( */
900
 
        for (x=0;x<wc->cards;x++) {
901
 
                if (wc->cardflag & (1 << x))
902
 
                        zt_ec_chunk(&wc->chans[x], wc->chans[x].readchunk, wc->chans[x].writechunk);
903
 
        }
904
 
        zt_receive(&wc->span);
905
 
        /* Wake up anyone sleeping to read/write a new register */
906
 
        wake_up_interruptible(&wc->regq);
907
 
}
908
 
 
909
 
static void wctdm_stop_dma(struct wctdm *wc);
910
 
static void wctdm_restart_dma(struct wctdm *wc);
911
 
 
912
 
static int wait_access(struct wctdm *wc, int card)
913
 
{
914
 
    unsigned char data=0;
915
 
    long origjiffies;
916
 
    int count = 0;
917
 
 
918
 
    #define MAX 10 /* attempts */
919
 
 
920
 
 
921
 
    origjiffies = jiffies;
922
 
    /* Wait for indirect access */
923
 
    while (count++ < MAX)
924
 
         {
925
 
                data = wctdm_getreg(wc, card, I_STATUS);
926
 
 
927
 
                if (!data)
928
 
                        return 0;
929
 
 
930
 
         }
931
 
 
932
 
    if(count > (MAX-1)) printk(" ##### Loop error (%02x) #####\n", data);
933
 
 
934
 
        return 0;
935
 
}
936
 
 
937
 
static unsigned char translate_3215(unsigned char address)
938
 
{
939
 
        int x;
940
 
        for (x=0;x<sizeof(indirect_regs)/sizeof(indirect_regs[0]);x++) {
941
 
                if (indirect_regs[x].address == address) {
942
 
                        address = indirect_regs[x].altaddr;
943
 
                        break;
944
 
                }
945
 
        }
946
 
        return address;
947
 
}
948
 
 
949
 
static int wctdm_proslic_setreg_indirect(struct wctdm *wc, int card, unsigned char address, unsigned short data)
950
 
{
951
 
        int res = -1;
952
 
        /* Translate 3215 addresses */
953
 
        if (wc->flags[card] & FLAG_3215) {
954
 
                address = translate_3215(address);
955
 
                if (address == 255)
956
 
                        return 0;
957
 
        }
958
 
        if(!wait_access(wc, card)) {
959
 
                wctdm_setreg(wc, card, IDA_LO,(unsigned char)(data & 0xFF));
960
 
                wctdm_setreg(wc, card, IDA_HI,(unsigned char)((data & 0xFF00)>>8));
961
 
                wctdm_setreg(wc, card, IAA,address);
962
 
                res = 0;
963
 
        };
964
 
        return res;
965
 
}
966
 
 
967
 
static int wctdm_proslic_getreg_indirect(struct wctdm *wc, int card, unsigned char address)
968
 
969
 
        int res = -1;
970
 
        char *p=NULL;
971
 
        /* Translate 3215 addresses */
972
 
        if (wc->flags[card] & FLAG_3215) {
973
 
                address = translate_3215(address);
974
 
                if (address == 255)
975
 
                        return 0;
976
 
        }
977
 
        if (!wait_access(wc, card)) {
978
 
                wctdm_setreg(wc, card, IAA, address);
979
 
                if (!wait_access(wc, card)) {
980
 
                        unsigned char data1, data2;
981
 
                        data1 = wctdm_getreg(wc, card, IDA_LO);
982
 
                        data2 = wctdm_getreg(wc, card, IDA_HI);
983
 
                        res = data1 | (data2 << 8);
984
 
                } else
985
 
                        p = "Failed to wait inside\n";
986
 
        } else
987
 
                p = "failed to wait\n";
988
 
        if (p)
989
 
                printk(p);
990
 
        return res;
991
 
}
992
 
 
993
 
static int wctdm_proslic_init_indirect_regs(struct wctdm *wc, int card)
994
 
{
995
 
        unsigned char i;
996
 
 
997
 
        for (i=0; i<sizeof(indirect_regs) / sizeof(indirect_regs[0]); i++)
998
 
        {
999
 
                if(wctdm_proslic_setreg_indirect(wc, card, indirect_regs[i].address,indirect_regs[i].initial))
1000
 
                        return -1;
1001
 
        }
1002
 
 
1003
 
        return 0;
1004
 
}
1005
 
 
1006
 
static int wctdm_proslic_verify_indirect_regs(struct wctdm *wc, int card)
1007
 
1008
 
        int passed = 1;
1009
 
        unsigned short i, initial;
1010
 
        int j;
1011
 
 
1012
 
        for (i=0; i<sizeof(indirect_regs) / sizeof(indirect_regs[0]); i++) 
1013
 
        {
1014
 
                if((j = wctdm_proslic_getreg_indirect(wc, card, (unsigned char) indirect_regs[i].address)) < 0) {
1015
 
                        printk("Failed to read indirect register %d\n", i);
1016
 
                        return -1;
1017
 
                }
1018
 
                initial= indirect_regs[i].initial;
1019
 
 
1020
 
                if ( j != initial && (!(wc->flags[card] & FLAG_3215) || (indirect_regs[i].altaddr != 255)))
1021
 
                {
1022
 
                         printk("!!!!!!! %s  iREG %X = %X  should be %X\n",
1023
 
                                indirect_regs[i].name,indirect_regs[i].address,j,initial );
1024
 
                         passed = 0;
1025
 
                }       
1026
 
        }
1027
 
 
1028
 
    if (passed) {
1029
 
                if (debug)
1030
 
                        printk("Init Indirect Registers completed successfully.\n");
1031
 
    } else {
1032
 
                printk(" !!!!! Init Indirect Registers UNSUCCESSFULLY.\n");
1033
 
                return -1;
1034
 
    }
1035
 
    return 0;
1036
 
}
1037
 
 
1038
 
static inline void wctdm_proslic_recheck_sanity(struct wctdm *wc, int card)
1039
 
{
1040
 
        int res;
1041
 
#ifdef PAQ_DEBUG
1042
 
        res = wc->cmdq[card].isrshadow[1];
1043
 
        res &= ~0x3;
1044
 
        if (res) {
1045
 
                wc->cmdq[card].isrshadow[1]=0;
1046
 
                wc->mods[card].fxs.palarms++;
1047
 
                if (wc->mods[card].fxs.palarms < MAX_ALARMS) {
1048
 
                        printk("Power alarm (%02x) on module %d, resetting!\n", res, card + 1);
1049
 
                        if (wc->mods[card].fxs.lasttxhook == 4)
1050
 
                                wc->mods[card].fxs.lasttxhook = 1;
1051
 
                        wc->sethook[card] = CMD_WR(19, res);
1052
 
#if 0
1053
 
                        wc->sethook[card] = CMD_WR(64, wc->mods[card].fxs.lasttxhook);
1054
 
#endif
1055
 
 
1056
 
                        /* wctdm_setreg_intr(wc, card, 64, wc->mods[card].fxs.lasttxhook); */
1057
 
                        /* Update shadow register to avoid extra power alarms until next read */
1058
 
                        wc->cmdq[card].isrshadow[1] = 0;
1059
 
                } else {
1060
 
                        if (wc->mods[card].fxs.palarms == MAX_ALARMS)
1061
 
                                printk("Too many power alarms on card %d, NOT resetting!\n", card + 1);
1062
 
                }
1063
 
        }
1064
 
#else
1065
 
        res = wc->cmdq[card].isrshadow[1];
1066
 
        if (!res && (res != wc->mods[card].fxs.lasttxhook)) {
1067
 
                wc->mods[card].fxs.palarms++;
1068
 
                if (wc->mods[card].fxs.palarms < MAX_ALARMS) {
1069
 
                        printk("Power alarm on module %d, resetting!\n", card + 1);
1070
 
                        if (wc->mods[card].fxs.lasttxhook == 4)
1071
 
                                wc->mods[card].fxs.lasttxhook = 1;
1072
 
                        wc->sethook[card] = CMD_WR(64, wc->mods[card].fxs.lasttxhook);
1073
 
 
1074
 
                        /* wctdm_setreg_intr(wc, card, 64, wc->mods[card].fxs.lasttxhook); */
1075
 
                        /* Update shadow register to avoid extra power alarms until next read */
1076
 
                        wc->cmdq[card].isrshadow[1] = wc->mods[card].fxs.lasttxhook;
1077
 
                } else {
1078
 
                        if (wc->mods[card].fxs.palarms == MAX_ALARMS)
1079
 
                                printk("Too many power alarms on card %d, NOT resetting!\n", card + 1);
1080
 
                }
1081
 
        }
1082
 
#endif
1083
 
}
1084
 
 
1085
 
static inline void wctdm_voicedaa_check_hook(struct wctdm *wc, int card)
1086
 
{
1087
 
        unsigned char res;
1088
 
        signed char b;
1089
 
        /* Try to track issues that plague slot one FXO's */
1090
 
        b = wc->cmdq[card].isrshadow[0];        /* Hook/Ring state */
1091
 
        b &= 0x9b;
1092
 
        if (wc->mods[card].fxo.offhook) {
1093
 
                if (b != 0x9)
1094
 
                        wctdm_setreg_intr(wc, card, 5, 0x9);
1095
 
        } else {
1096
 
                if (b != 0x8)
1097
 
                        wctdm_setreg_intr(wc, card, 5, 0x8);
1098
 
        }
1099
 
        if (!wc->mods[card].fxo.offhook) {
1100
 
                res = wc->cmdq[card].isrshadow[0];      /* Hook/Ring state */
1101
 
                if ((res & 0x60) && wc->mods[card].fxo.battery) {
1102
 
                        wc->mods[card].fxo.ringdebounce += (ZT_CHUNKSIZE * 4);
1103
 
                        if (wc->mods[card].fxo.ringdebounce >= ZT_CHUNKSIZE * RING_DEBOUNCE) {
1104
 
                                if (!wc->mods[card].fxo.wasringing) {
1105
 
                                        wc->mods[card].fxo.wasringing = 1;
1106
 
                                        zt_hooksig(&wc->chans[card], ZT_RXSIG_RING);
1107
 
                                        if (debug)
1108
 
                                                printk("RING on %d/%d!\n", wc->span.spanno, card + 1);
1109
 
                                }
1110
 
                                wc->mods[card].fxo.ringdebounce = ZT_CHUNKSIZE * RING_DEBOUNCE;
1111
 
                        }
1112
 
                } else {
1113
 
                        wc->mods[card].fxo.ringdebounce -= ZT_CHUNKSIZE;
1114
 
                        if (wc->mods[card].fxo.ringdebounce <= 0) {
1115
 
                                if (wc->mods[card].fxo.wasringing) {
1116
 
                                        wc->mods[card].fxo.wasringing = 0;
1117
 
                                        zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK);
1118
 
                                        if (debug)
1119
 
                                                printk("NO RING on %d/%d!\n", wc->span.spanno, card + 1);
1120
 
                                }
1121
 
                                wc->mods[card].fxo.ringdebounce = 0;
1122
 
                        }
1123
 
                                
1124
 
                }
1125
 
        }
1126
 
        b = wc->cmdq[card].isrshadow[1]; /* Voltage */
1127
 
        if (abs(b) < battthresh) {
1128
 
                wc->mods[card].fxo.nobatttimer++;
1129
 
#if 0
1130
 
                if (wc->mods[card].fxo.battery)
1131
 
                        printk("Battery loss: %d (%d debounce)\n", b, wc->mods[card].fxo.battdebounce);
1132
 
#endif
1133
 
                if (wc->mods[card].fxo.battery && !wc->mods[card].fxo.battdebounce) {
1134
 
                        if (debug)
1135
 
                                printk("NO BATTERY on %d/%d!\n", wc->span.spanno, card + 1);
1136
 
                        wc->mods[card].fxo.battery =  0;
1137
 
#ifdef  JAPAN
1138
 
                        if ((!wc->ohdebounce) && wc->offhook) {
1139
 
                                zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK);
1140
 
                                if (debug)
1141
 
                                        printk("Signalled On Hook\n");
1142
 
#ifdef  ZERO_BATT_RING
1143
 
                                wc->onhook++;
1144
 
#endif
1145
 
                        }
1146
 
#else
1147
 
                        zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK);
1148
 
#endif
1149
 
                        wc->mods[card].fxo.battdebounce = battdebounce;
1150
 
                } else if (!wc->mods[card].fxo.battery)
1151
 
                        wc->mods[card].fxo.battdebounce = battdebounce;
1152
 
        } else if (abs(b) > battthresh) {
1153
 
                if (!wc->mods[card].fxo.battery && !wc->mods[card].fxo.battdebounce) {
1154
 
                        if (debug)
1155
 
                                printk("BATTERY on %d/%d (%s)!\n", wc->span.spanno, card + 1, 
1156
 
                                        (b < 0) ? "-" : "+");                       
1157
 
#ifdef  ZERO_BATT_RING
1158
 
                        if (wc->onhook) {
1159
 
                                wc->onhook = 0;
1160
 
                                zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK);
1161
 
                                if (debug)
1162
 
                                        printk("Signalled Off Hook\n");
1163
 
                        }
1164
 
#else
1165
 
                        zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK);
1166
 
#endif
1167
 
                        wc->mods[card].fxo.battery = 1;
1168
 
                        wc->mods[card].fxo.nobatttimer = 0;
1169
 
                        wc->mods[card].fxo.battdebounce = battdebounce;
1170
 
                } else if (wc->mods[card].fxo.battery)
1171
 
                        wc->mods[card].fxo.battdebounce = battdebounce;
1172
 
 
1173
 
                if (wc->mods[card].fxo.lastpol >= 0) {
1174
 
                    if (b < 0) {
1175
 
                        wc->mods[card].fxo.lastpol = -1;
1176
 
                        wc->mods[card].fxo.polaritydebounce = POLARITY_DEBOUNCE;
1177
 
                    }
1178
 
                } 
1179
 
                if (wc->mods[card].fxo.lastpol <= 0) {
1180
 
                    if (b > 0) {
1181
 
                        wc->mods[card].fxo.lastpol = 1;
1182
 
                        wc->mods[card].fxo.polaritydebounce = POLARITY_DEBOUNCE;
1183
 
                    }
1184
 
                }
1185
 
        } else {
1186
 
                /* It's something else... */
1187
 
                wc->mods[card].fxo.battdebounce = battdebounce;
1188
 
        }
1189
 
        if (wc->mods[card].fxo.battdebounce)
1190
 
                wc->mods[card].fxo.battdebounce--;
1191
 
        if (wc->mods[card].fxo.polaritydebounce) {
1192
 
                wc->mods[card].fxo.polaritydebounce--;
1193
 
                if (wc->mods[card].fxo.polaritydebounce < 1) {
1194
 
                    if (wc->mods[card].fxo.lastpol != wc->mods[card].fxo.polarity) {
1195
 
                        if (debug)
1196
 
                                printk("%lu Polarity reversed (%d -> %d)\n", jiffies, 
1197
 
                               wc->mods[card].fxo.polarity, 
1198
 
                               wc->mods[card].fxo.lastpol);
1199
 
                        if (wc->mods[card].fxo.polarity)
1200
 
                            zt_qevent_lock(&wc->chans[card], ZT_EVENT_POLARITY);
1201
 
                        wc->mods[card].fxo.polarity = wc->mods[card].fxo.lastpol;
1202
 
                    }
1203
 
                }
1204
 
        }
1205
 
}
1206
 
 
1207
 
static inline void wctdm_proslic_check_hook(struct wctdm *wc, int card)
1208
 
{
1209
 
        char res;
1210
 
        int hook;
1211
 
 
1212
 
        /* For some reason we have to debounce the
1213
 
           hook detector.  */
1214
 
 
1215
 
        res = wc->cmdq[card].isrshadow[0];      /* Hook state */
1216
 
        hook = (res & 1);
1217
 
                
1218
 
        if (hook != wc->mods[card].fxs.lastrxhook) {
1219
 
                /* Reset the debounce (must be multiple of 4ms) */
1220
 
                wc->mods[card].fxs.debounce = 8 * (4 * 8);
1221
 
#if 0
1222
 
                printk("Resetting debounce card %d hook %d, %d\n", card, hook, wc->mods[card].fxs.debounce);
1223
 
#endif
1224
 
        } else {
1225
 
                if (wc->mods[card].fxs.debounce > 0) {
1226
 
                        wc->mods[card].fxs.debounce-= 4 * ZT_CHUNKSIZE;
1227
 
#if 0
1228
 
                        printk("Sustaining hook %d, %d\n", hook, wc->mods[card].fxs.debounce);
1229
 
#endif
1230
 
                        if (!wc->mods[card].fxs.debounce) {
1231
 
#if 0
1232
 
                                printk("Counted down debounce, newhook: %d...\n", hook);
1233
 
#endif
1234
 
                                wc->mods[card].fxs.debouncehook = hook;
1235
 
                        }
1236
 
                        if (!wc->mods[card].fxs.oldrxhook && wc->mods[card].fxs.debouncehook) {
1237
 
                                /* Off hook */
1238
 
                                if (debug)
1239
 
                                        printk("wctdm: Card %d Going off hook\n", card);
1240
 
                                zt_hooksig(&wc->chans[card], ZT_RXSIG_OFFHOOK);
1241
 
                                if (robust)
1242
 
                                        wctdm_init_proslic(wc, card, 1, 0, 1);
1243
 
                                wc->mods[card].fxs.oldrxhook = 1;
1244
 
                        
1245
 
                        } else if (wc->mods[card].fxs.oldrxhook && !wc->mods[card].fxs.debouncehook) {
1246
 
                                /* On hook */
1247
 
                                if (debug)
1248
 
                                        printk("wctdm: Card %d Going on hook\n", card);
1249
 
                                zt_hooksig(&wc->chans[card], ZT_RXSIG_ONHOOK);
1250
 
                                wc->mods[card].fxs.oldrxhook = 0;
1251
 
                        }
1252
 
                }
1253
 
        }
1254
 
        wc->mods[card].fxs.lastrxhook = hook;
1255
 
}
1256
 
 
1257
 
 
1258
 
static inline void wctdm_reinit_descriptor(struct wctdm *wc, int tx, int dbl, char *s)
1259
 
{
1260
 
        int o2 = 0;
1261
 
        o2 += dbl * 4;
1262
 
        if (!tx)
1263
 
                o2 += ERING_SIZE * 4;
1264
 
        wc->descripchunk[o2] = 0x80000000;
1265
 
}
1266
 
 
1267
 
#ifdef VPM_SUPPORT
1268
 
static inline void wctdm_vpm_check(struct wctdm *wc, int x)
1269
 
{
1270
 
        if (wc->cmdq[x].isrshadow[0]) {
1271
 
                if (debug)
1272
 
                        printk("VPM: Detected dtmf ON channel %02x on chip %d!\n", wc->cmdq[x].isrshadow[0], x - NUM_CARDS);
1273
 
                wc->sethook[x] = CMD_WR(0xb9, wc->cmdq[x].isrshadow[0]);
1274
 
                wc->cmdq[x].isrshadow[0] = 0;
1275
 
                /* Cancel most recent lookup, if there is one */
1276
 
                wc->cmdq[x].cmds[USER_COMMANDS+0] = 0x00000000; 
1277
 
        } else if (wc->cmdq[x].isrshadow[1]) {
1278
 
                if (debug)
1279
 
                        printk("VPM: Detected dtmf OFF channel %02x on chip %d!\n", wc->cmdq[x].isrshadow[1], x - NUM_CARDS);
1280
 
                wc->sethook[x] = CMD_WR(0xbd, wc->cmdq[x].isrshadow[1]);
1281
 
                wc->cmdq[x].isrshadow[1] = 0;
1282
 
                /* Cancel most recent lookup, if there is one */
1283
 
                wc->cmdq[x].cmds[USER_COMMANDS+1] = 0x00000000; 
1284
 
        }
1285
 
}
1286
 
 
1287
 
static int wctdm_echocan(struct zt_chan *chan, int eclen)
1288
 
{
1289
 
        struct wctdm *wc = chan->pvt;
1290
 
        int channel;
1291
 
        int unit;
1292
 
        if (!wc->vpm)
1293
 
                return -ENODEV;
1294
 
        channel = (chan->chanpos - 1);
1295
 
        unit = (chan->chanpos - 1) & 0x3;
1296
 
        if (wc->vpm < 2)
1297
 
                channel >>= 2;
1298
 
 
1299
 
        if(debug) 
1300
 
                printk("echocan: Unit is %d, Channel is  %d length %d\n", 
1301
 
                        unit, channel, eclen);
1302
 
        if (eclen)
1303
 
                wctdm_vpm_out(wc,unit,channel,0x3e);
1304
 
        else
1305
 
                wctdm_vpm_out(wc,unit,channel,0x01);
1306
 
        return 0;
1307
 
}
1308
 
#endif
1309
 
static inline void wctdm_isr_misc(struct wctdm *wc)
1310
 
{
1311
 
        int x;
1312
 
        for (x=0;x<wc->cards;x++) {
1313
 
                if (wc->cardflag & (1 << x)) {
1314
 
                        if (wc->modtype[x] == MOD_TYPE_FXS) {
1315
 
                                if (!(wc->intcount % 10000)) {
1316
 
                                        /* Accept an alarm once per 10 seconds */
1317
 
                                        if (wc->mods[x].fxs.palarms)
1318
 
                                                wc->mods[x].fxs.palarms--;
1319
 
                                }
1320
 
                                wctdm_proslic_check_hook(wc, x);
1321
 
                                if (!(wc->intcount & 0xfc))
1322
 
                                        wctdm_proslic_recheck_sanity(wc, x);
1323
 
                                if (wc->mods[x].fxs.lasttxhook == 0x4) {
1324
 
                                        /* RINGing, prepare for OHT */
1325
 
                                        wc->mods[x].fxs.ohttimer = OHT_TIMER << 3;
1326
 
                                        wc->mods[x].fxs.idletxhookstate = 0x2;  /* OHT mode when idle */
1327
 
                                } else {
1328
 
                                        if (wc->mods[x].fxs.ohttimer) {
1329
 
                                                wc->mods[x].fxs.ohttimer-= ZT_CHUNKSIZE;
1330
 
                                                if (!wc->mods[x].fxs.ohttimer) {
1331
 
                                                        wc->mods[x].fxs.idletxhookstate = 0x1;  /* Switch to active */
1332
 
                                                        if (wc->mods[x].fxs.lasttxhook == 0x2) {
1333
 
                                                                /* Apply the change if appropriate */
1334
 
                                                                wc->mods[x].fxs.lasttxhook = 0x1;
1335
 
                                                                wc->sethook[x] = CMD_WR(64, wc->mods[x].fxs.lasttxhook);
1336
 
                                                                /* wctdm_setreg_intr(wc, x, 64, wc->mods[x].fxs.lasttxhook); */
1337
 
                                                        }
1338
 
                                                }
1339
 
                                        }
1340
 
                                }
1341
 
                        } else if (wc->modtype[x] == MOD_TYPE_FXO) {
1342
 
                                wctdm_voicedaa_check_hook(wc, x);
1343
 
                        }
1344
 
                }
1345
 
        }
1346
 
#ifdef VPM_SUPPORT
1347
 
        if (wc->vpm > 0) {
1348
 
                for (x=NUM_CARDS;x<NUM_CARDS+NUM_EC;x++) {
1349
 
                        wctdm_vpm_check(wc, x);
1350
 
                }
1351
 
        }
1352
 
#endif
1353
 
}
1354
 
 
1355
 
static inline int wctdm_check_descriptor(struct wctdm *wc, int tx)
1356
 
{
1357
 
        int o2 = 0;
1358
 
        if (!tx) {
1359
 
                o2 += ERING_SIZE * 4;
1360
 
                o2 += wc->rdbl * 4;
1361
 
        } else {
1362
 
                o2 += wc->tdbl * 4;
1363
 
        }
1364
 
        if (!(wc->descripchunk[o2] & 0x80000000)) {
1365
 
                if (tx) {
1366
 
                        wc->txints++;
1367
 
                        wctdm_transmitprep(wc, wc->tdbl);
1368
 
                        wctdm_reinit_descriptor(wc, tx, wc->tdbl, "txchk");
1369
 
                        wc->tdbl = (wc->tdbl + 1) % ERING_SIZE;
1370
 
                        wctdm_isr_misc(wc);
1371
 
                        wc->intcount++;
1372
 
                } else {
1373
 
                        wc->rxints++;
1374
 
                        wctdm_receiveprep(wc, wc->rdbl);
1375
 
                        wctdm_reinit_descriptor(wc, tx, wc->rdbl, "rxchk");
1376
 
                        wc->rdbl = (wc->rdbl + 1) % ERING_SIZE;
1377
 
                }
1378
 
                return 1;
1379
 
        }
1380
 
        return 0;
1381
 
}
1382
 
 
1383
 
static void wctdm_init_descriptors(struct wctdm *wc)
1384
 
{
1385
 
        volatile unsigned int *descrip;
1386
 
        dma_addr_t descripdma;
1387
 
        dma_addr_t writedma;
1388
 
        dma_addr_t readdma;
1389
 
        int x;
1390
 
        
1391
 
        descrip = wc->descripchunk;
1392
 
        descripdma = wc->descripdma;
1393
 
        writedma = wc->writedma;
1394
 
        readdma = wc->readdma;
1395
 
 
1396
 
        for (x=0;x<ERING_SIZE;x++) {
1397
 
                if (x < ERING_SIZE - 1)
1398
 
                        descripdma += 16;
1399
 
                else
1400
 
                        descripdma = wc->descripdma;
1401
 
 
1402
 
                /* Transmit descriptor */
1403
 
                descrip[0 ] = 0x80000000;
1404
 
                descrip[1 ] = 0xe5800000 | (SFRAME_SIZE);
1405
 
                if (x % 2)
1406
 
                        descrip[2 ] = writedma + SFRAME_SIZE;
1407
 
                else
1408
 
                        descrip[2 ] = writedma;
1409
 
                descrip[3 ] = descripdma;
1410
 
        
1411
 
                /* Receive descriptor */
1412
 
                descrip[0 + ERING_SIZE * 4] = 0x80000000;
1413
 
                descrip[1 + ERING_SIZE * 4] = 0x01000000 | (SFRAME_SIZE);
1414
 
                if (x % 2)
1415
 
                        descrip[2 + ERING_SIZE * 4] = readdma + SFRAME_SIZE;
1416
 
                else
1417
 
                        descrip[2 + ERING_SIZE * 4] = readdma;
1418
 
                descrip[3 + ERING_SIZE * 4] = descripdma + ERING_SIZE * 16;
1419
 
        
1420
 
                /* Advance descriptor */
1421
 
                descrip += 4;
1422
 
        }       
1423
 
}
1424
 
 
1425
 
#ifdef LINUX26
1426
 
static irqreturn_t wctdm_interrupt(int irq, void *dev_id, struct pt_regs *regs)
1427
 
#else
1428
 
static void wctdm_interrupt(int irq, void *dev_id, struct pt_regs *regs)
1429
 
#endif
1430
 
{
1431
 
        struct wctdm *wc = dev_id;
1432
 
        unsigned int ints;
1433
 
        int res;
1434
 
 
1435
 
        /* Read and clear interrupts */
1436
 
        ints = wctdm_getctl(wc, 0x0028);
1437
 
        wctdm_setctl(wc, 0x0028, ints);
1438
 
 
1439
 
        if (!ints)
1440
 
#ifdef LINUX26
1441
 
                return IRQ_NONE;
1442
 
#else
1443
 
                return;
1444
 
#endif          
1445
 
        ints &= wc->intmask;
1446
 
        if (ints & 0x00000041) {
1447
 
                do {
1448
 
                        res = wctdm_check_descriptor(wc, 0);
1449
 
                        res |= wctdm_check_descriptor(wc, 1);
1450
 
                } while(res);
1451
 
#if 0 
1452
 
                while(wctdm_check_descriptor(wc, 0));
1453
 
                wctdm_setctl(wc, 0x0010, 0x00000000);
1454
 
        }
1455
 
        if (ints & 0x00000005) {
1456
 
                while(wctdm_check_descriptor(wc, 1));
1457
 
                wctdm_setctl(wc, 0x0008, 0x00000000);
1458
 
#endif
1459
 
        }
1460
 
#ifdef LINUX26
1461
 
        return IRQ_RETVAL(1);
1462
 
#endif          
1463
 
        
1464
 
}
1465
 
 
1466
 
static int wctdm_voicedaa_insane(struct wctdm *wc, int card)
1467
 
{
1468
 
        int blah;
1469
 
        blah = wctdm_getreg(wc, card, 2);
1470
 
        if (blah != 0x3)
1471
 
                return -2;
1472
 
        blah = wctdm_getreg(wc, card, 11);
1473
 
        if (debug)
1474
 
                printk("VoiceDAA System: %02x\n", blah & 0xf);
1475
 
        return 0;
1476
 
}
1477
 
 
1478
 
static int wctdm_proslic_insane(struct wctdm *wc, int card)
1479
 
{
1480
 
        int blah,insane_report;
1481
 
        insane_report=0;
1482
 
 
1483
 
        blah = wctdm_getreg(wc, card, 0);
1484
 
        if (debug) 
1485
 
                printk("ProSLIC on module %d, product %d, version %d\n", card, (blah & 0x30) >> 4, (blah & 0xf));
1486
 
 
1487
 
#if 0
1488
 
        if ((blah & 0x30) >> 4) {
1489
 
                printk("ProSLIC on module %d is not a 3210.\n", card);
1490
 
                return -1;
1491
 
        }
1492
 
#endif
1493
 
        if (((blah & 0xf) == 0) || ((blah & 0xf) == 0xf)) {
1494
 
                /* SLIC not loaded */
1495
 
                return -1;
1496
 
        }
1497
 
        if ((blah & 0xf) < 2) {
1498
 
                printk("ProSLIC 3210 version %d is too old\n", blah & 0xf);
1499
 
                return -1;
1500
 
        }
1501
 
        if (wctdm_getreg(wc, card, 1) & 0x80)
1502
 
                /* ProSLIC 3215, not a 3210 */
1503
 
                wc->flags[card] |= FLAG_3215;
1504
 
 
1505
 
        blah = wctdm_getreg(wc, card, 8);
1506
 
        if (blah != 0x2) {
1507
 
                printk("ProSLIC on module %d insane (1) %d should be 2\n", card, blah);
1508
 
                return -1;
1509
 
        } else if ( insane_report)
1510
 
                printk("ProSLIC on module %d Reg 8 Reads %d Expected is 0x2\n",card,blah);
1511
 
 
1512
 
        blah = wctdm_getreg(wc, card, 64);
1513
 
        if (blah != 0x0) {
1514
 
                printk("ProSLIC on module %d insane (2)\n", card);
1515
 
                return -1;
1516
 
        } else if ( insane_report)
1517
 
                printk("ProSLIC on module %d Reg 64 Reads %d Expected is 0x0\n",card,blah);
1518
 
 
1519
 
        blah = wctdm_getreg(wc, card, 11);
1520
 
        if (blah != 0x33) {
1521
 
                printk("ProSLIC on module %d insane (3)\n", card);
1522
 
                return -1;
1523
 
        } else if ( insane_report)
1524
 
                printk("ProSLIC on module %d Reg 11 Reads %d Expected is 0x33\n",card,blah);
1525
 
 
1526
 
        /* Just be sure it's setup right. */
1527
 
        wctdm_setreg(wc, card, 30, 0);
1528
 
 
1529
 
        if (debug) 
1530
 
                printk("ProSLIC on module %d seems sane.\n", card);
1531
 
        return 0;
1532
 
}
1533
 
 
1534
 
static int wctdm_proslic_powerleak_test(struct wctdm *wc, int card)
1535
 
{
1536
 
        unsigned long origjiffies;
1537
 
        unsigned char vbat;
1538
 
 
1539
 
        /* Turn off linefeed */
1540
 
        wctdm_setreg(wc, card, 64, 0);
1541
 
 
1542
 
        /* Power down */
1543
 
        wctdm_setreg(wc, card, 14, 0x10);
1544
 
 
1545
 
        /* Wait for one second */
1546
 
        origjiffies = jiffies;
1547
 
 
1548
 
        while((vbat = wctdm_getreg(wc, card, 82)) > 0x6) {
1549
 
                if ((jiffies - origjiffies) >= (HZ/2))
1550
 
                        break;;
1551
 
        }
1552
 
 
1553
 
        if (vbat < 0x06) {
1554
 
                printk("Excessive leakage detected on module %d: %d volts (%02x) after %d ms\n", card,
1555
 
                       376 * vbat / 1000, vbat, (int)((jiffies - origjiffies) * 1000 / HZ));
1556
 
                return -1;
1557
 
        } else if (debug) {
1558
 
                printk("Post-leakage voltage: %d volts\n", 376 * vbat / 1000);
1559
 
        }
1560
 
        return 0;
1561
 
}
1562
 
 
1563
 
static int wctdm_powerup_proslic(struct wctdm *wc, int card, int fast)
1564
 
{
1565
 
        unsigned char vbat;
1566
 
        unsigned long origjiffies;
1567
 
        int lim;
1568
 
 
1569
 
        /* Set period of DC-DC converter to 1/64 khz */
1570
 
        wctdm_setreg(wc, card, 92, 0xc0 /* was 0xff */);
1571
 
 
1572
 
        /* Wait for VBat to powerup */
1573
 
        origjiffies = jiffies;
1574
 
 
1575
 
        /* Disable powerdown */
1576
 
        wctdm_setreg(wc, card, 14, 0);
1577
 
 
1578
 
        /* If fast, don't bother checking anymore */
1579
 
        if (fast)
1580
 
                return 0;
1581
 
 
1582
 
        while((vbat = wctdm_getreg(wc, card, 82)) < 0xc0) {
1583
 
                /* Wait no more than 500ms */
1584
 
                if ((jiffies - origjiffies) > HZ/2) {
1585
 
                        break;
1586
 
                }
1587
 
        }
1588
 
 
1589
 
        if (vbat < 0xc0) {
1590
 
                printk("ProSLIC on module %d failed to powerup within %d ms (%d mV only)\n\n -- DID YOU REMEMBER TO PLUG IN THE HD POWER CABLE TO THE TDM2400P??\n",
1591
 
                       card, (int)(((jiffies - origjiffies) * 1000 / HZ)),
1592
 
                        vbat * 375);
1593
 
                return -1;
1594
 
        } else if (debug) {
1595
 
                printk("ProSLIC on module %d powered up to -%d volts (%02x) in %d ms\n",
1596
 
                       card, vbat * 376 / 1000, vbat, (int)(((jiffies - origjiffies) * 1000 / HZ)));
1597
 
        }
1598
 
 
1599
 
        /* Proslic max allowed loop current, reg 71 LOOP_I_LIMIT */
1600
 
        /* If out of range, just set it to the default value     */
1601
 
        lim = (loopcurrent - 20) / 3;
1602
 
        if ( loopcurrent > 41 ) {
1603
 
                lim = 0;
1604
 
                if (debug)
1605
 
                        printk("Loop current out of range! Setting to default 20mA!\n");
1606
 
        }
1607
 
        else if (debug)
1608
 
                        printk("Loop current set to %dmA!\n",(lim*3)+20);
1609
 
        wctdm_setreg(wc,card,LOOP_I_LIMIT,lim);
1610
 
 
1611
 
        /* Engage DC-DC converter */
1612
 
        wctdm_setreg(wc, card, 93, 0x19 /* was 0x19 */);
1613
 
#if 0
1614
 
        origjiffies = jiffies;
1615
 
        while(0x80 & wctdm_getreg(wc, card, 93)) {
1616
 
                if ((jiffies - origjiffies) > 2 * HZ) {
1617
 
                        printk("Timeout waiting for DC-DC calibration on module %d\n", card);
1618
 
                        return -1;
1619
 
                }
1620
 
        }
1621
 
 
1622
 
#if 0
1623
 
        /* Wait a full two seconds */
1624
 
        while((jiffies - origjiffies) < 2 * HZ);
1625
 
 
1626
 
        /* Just check to be sure */
1627
 
        vbat = wctdm_getreg(wc, card, 82);
1628
 
        printk("ProSLIC on module %d powered up to -%d volts (%02x) in %d ms\n",
1629
 
                       card, vbat * 376 / 1000, vbat, (int)(((jiffies - origjiffies) * 1000 / HZ)));
1630
 
#endif
1631
 
#endif
1632
 
        return 0;
1633
 
 
1634
 
}
1635
 
 
1636
 
static int wctdm_proslic_manual_calibrate(struct wctdm *wc, int card)
1637
 
{
1638
 
        unsigned long origjiffies;
1639
 
        unsigned char i;
1640
 
 
1641
 
        wctdm_setreg(wc, card, 21, 0);//(0)  Disable all interupts in DR21
1642
 
        wctdm_setreg(wc, card, 22, 0);//(0)Disable all interupts in DR21
1643
 
        wctdm_setreg(wc, card, 23, 0);//(0)Disable all interupts in DR21
1644
 
        wctdm_setreg(wc, card, 64, 0);//(0)
1645
 
 
1646
 
        wctdm_setreg(wc, card, 97, 0x18); //(0x18)Calibrations without the ADC and DAC offset and without common mode calibration.
1647
 
        wctdm_setreg(wc, card, 96, 0x47); //(0x47)      Calibrate common mode and differential DAC mode DAC + ILIM
1648
 
 
1649
 
        origjiffies=jiffies;
1650
 
        while( wctdm_getreg(wc,card,96)!=0 ){
1651
 
                if((jiffies-origjiffies)>80)
1652
 
                        return -1;
1653
 
        }
1654
 
//Initialized DR 98 and 99 to get consistant results.
1655
 
// 98 and 99 are the results registers and the search should have same intial conditions.
1656
 
 
1657
 
/*******************************The following is the manual gain mismatch calibration****************************/
1658
 
/*******************************This is also available as a function *******************************************/
1659
 
        // Delay 10ms
1660
 
        origjiffies=jiffies; 
1661
 
        while((jiffies-origjiffies)<1);
1662
 
        wctdm_proslic_setreg_indirect(wc, card, 88,0);
1663
 
        wctdm_proslic_setreg_indirect(wc,card,89,0);
1664
 
        wctdm_proslic_setreg_indirect(wc,card,90,0);
1665
 
        wctdm_proslic_setreg_indirect(wc,card,91,0);
1666
 
        wctdm_proslic_setreg_indirect(wc,card,92,0);
1667
 
        wctdm_proslic_setreg_indirect(wc,card,93,0);
1668
 
 
1669
 
        wctdm_setreg(wc, card, 98,0x10); // This is necessary if the calibration occurs other than at reset time
1670
 
        wctdm_setreg(wc, card, 99,0x10);
1671
 
 
1672
 
        for ( i=0x1f; i>0; i--)
1673
 
        {
1674
 
                wctdm_setreg(wc, card, 98,i);
1675
 
                origjiffies=jiffies; 
1676
 
                while((jiffies-origjiffies)<4);
1677
 
                if((wctdm_getreg(wc,card,88)) == 0)
1678
 
                        break;
1679
 
        } // for
1680
 
 
1681
 
        for ( i=0x1f; i>0; i--)
1682
 
        {
1683
 
                wctdm_setreg(wc, card, 99,i);
1684
 
                origjiffies=jiffies; 
1685
 
                while((jiffies-origjiffies)<4);
1686
 
                if((wctdm_getreg(wc,card,89)) == 0)
1687
 
                        break;
1688
 
        }//for
1689
 
 
1690
 
/*******************************The preceding is the manual gain mismatch calibration****************************/
1691
 
/**********************************The following is the longitudinal Balance Cal***********************************/
1692
 
        wctdm_setreg(wc,card,64,1);
1693
 
        while((jiffies-origjiffies)<10); // Sleep 100?
1694
 
 
1695
 
        wctdm_setreg(wc, card, 64, 0);
1696
 
        wctdm_setreg(wc, card, 23, 0x4);  // enable interrupt for the balance Cal
1697
 
        wctdm_setreg(wc, card, 97, 0x1); // this is a singular calibration bit for longitudinal calibration
1698
 
        wctdm_setreg(wc, card, 96,0x40);
1699
 
 
1700
 
        wctdm_getreg(wc,card,96); /* Read Reg 96 just cause */
1701
 
 
1702
 
        wctdm_setreg(wc, card, 21, 0xFF);
1703
 
        wctdm_setreg(wc, card, 22, 0xFF);
1704
 
        wctdm_setreg(wc, card, 23, 0xFF);
1705
 
 
1706
 
        /**The preceding is the longitudinal Balance Cal***/
1707
 
        return(0);
1708
 
 
1709
 
}
1710
 
 
1711
 
static int wctdm_proslic_calibrate(struct wctdm *wc, int card)
1712
 
{
1713
 
        unsigned long origjiffies;
1714
 
        int x;
1715
 
        /* Perform all calibrations */
1716
 
        wctdm_setreg(wc, card, 97, 0x1f);
1717
 
        
1718
 
        /* Begin, no speedup */
1719
 
        wctdm_setreg(wc, card, 96, 0x5f);
1720
 
 
1721
 
        /* Wait for it to finish */
1722
 
        origjiffies = jiffies;
1723
 
        while(wctdm_getreg(wc, card, 96)) {
1724
 
                if ((jiffies - origjiffies) > 2 * HZ) {
1725
 
                        printk("Timeout waiting for calibration of module %d\n", card);
1726
 
                        return -1;
1727
 
                }
1728
 
        }
1729
 
        
1730
 
        if (debug) {
1731
 
                /* Print calibration parameters */
1732
 
                printk("Calibration Vector Regs 98 - 107: \n");
1733
 
                for (x=98;x<108;x++) {
1734
 
                        printk("%d: %02x\n", x, wctdm_getreg(wc, card, x));
1735
 
                }
1736
 
        }
1737
 
        return 0;
1738
 
}
1739
 
 
1740
 
static void wait_just_a_bit(int foo)
1741
 
{
1742
 
        long newjiffies;
1743
 
        newjiffies = jiffies + foo;
1744
 
        while(jiffies < newjiffies);
1745
 
}
1746
 
 
1747
 
static int wctdm_init_voicedaa(struct wctdm *wc, int card, int fast, int manual, int sane)
1748
 
{
1749
 
        unsigned char reg16=0, reg26=0, reg30=0, reg31=0;
1750
 
        long newjiffies;
1751
 
 
1752
 
        wc->modtype[card] = MOD_TYPE_NONE;
1753
 
        /* Wait just a bit */
1754
 
        wait_just_a_bit(HZ/10);
1755
 
 
1756
 
        wc->modtype[card] = MOD_TYPE_FXO;
1757
 
        wait_just_a_bit(HZ/10);
1758
 
 
1759
 
        if (!sane && wctdm_voicedaa_insane(wc, card))
1760
 
                return -2;
1761
 
 
1762
 
        /* Software reset */
1763
 
        wctdm_setreg(wc, card, 1, 0x80);
1764
 
 
1765
 
        /* Wait just a bit */
1766
 
        wait_just_a_bit(HZ/10);
1767
 
 
1768
 
        /* Enable PCM, ulaw */
1769
 
        if (alawoverride)
1770
 
                wctdm_setreg(wc, card, 33, 0x20);
1771
 
        else
1772
 
                wctdm_setreg(wc, card, 33, 0x28);
1773
 
 
1774
 
        /* Set On-hook speed, Ringer impedence, and ringer threshold */
1775
 
        reg16 |= (fxo_modes[_opermode].ohs << 6);
1776
 
        reg16 |= (fxo_modes[_opermode].rz << 1);
1777
 
        reg16 |= (fxo_modes[_opermode].rt);
1778
 
        wctdm_setreg(wc, card, 16, reg16);
1779
 
        
1780
 
        /* Set DC Termination:
1781
 
           Tip/Ring voltage adjust, minimum operational current, current limitation */
1782
 
        reg26 |= (fxo_modes[_opermode].dcv << 6);
1783
 
        reg26 |= (fxo_modes[_opermode].mini << 4);
1784
 
        reg26 |= (fxo_modes[_opermode].ilim << 1);
1785
 
        wctdm_setreg(wc, card, 26, reg26);
1786
 
 
1787
 
        /* Set AC Impedence */
1788
 
        reg30 = (fxo_modes[_opermode].acim);
1789
 
        wctdm_setreg(wc, card, 30, reg30);
1790
 
 
1791
 
        /* Misc. DAA parameters */
1792
 
        reg31 = 0xa3;
1793
 
        reg31 |= (fxo_modes[_opermode].ohs2 << 3);
1794
 
        wctdm_setreg(wc, card, 31, reg31);
1795
 
 
1796
 
        /* Set Transmit/Receive timeslot */
1797
 
        wctdm_setreg(wc, card, 34, (card * 8) & 0xff);
1798
 
        wctdm_setreg(wc, card, 35, (card * 8) >> 8);
1799
 
        wctdm_setreg(wc, card, 36, (card * 8) & 0xff);
1800
 
        wctdm_setreg(wc, card, 37, (card * 8) >> 8);
1801
 
 
1802
 
        /* Enable ISO-Cap */
1803
 
        wctdm_setreg(wc, card, 6, 0x00);
1804
 
 
1805
 
        /* Wait 1000ms for ISO-cap to come up */
1806
 
        newjiffies = jiffies;
1807
 
        newjiffies += 2 * HZ;
1808
 
        while((jiffies < newjiffies) && !(wctdm_getreg(wc, card, 11) & 0xf0))
1809
 
                wait_just_a_bit(HZ/10);
1810
 
 
1811
 
        if (!(wctdm_getreg(wc, card, 11) & 0xf0)) {
1812
 
                printk("VoiceDAA did not bring up ISO link properly!\n");
1813
 
                return -1;
1814
 
        }
1815
 
        if (debug)
1816
 
                printk("ISO-Cap is now up, line side: %02x rev %02x\n", 
1817
 
                       wctdm_getreg(wc, card, 11) >> 4,
1818
 
                       (wctdm_getreg(wc, card, 13) >> 2) & 0xf);
1819
 
        /* Enable on-hook line monitor */
1820
 
        wctdm_setreg(wc, card, 5, 0x08);
1821
 
        
1822
 
        /* Apply negative Tx gain of 4.5db to DAA */
1823
 
        wctdm_setreg(wc, card, 38, 0x14);       /* 4db */
1824
 
        wctdm_setreg(wc, card, 40, 0x15);       /* 0.5db */
1825
 
 
1826
 
        /* Apply negative Rx gain of 4.5db to DAA */
1827
 
        wctdm_setreg(wc, card, 39, 0x14);       /* 4db */
1828
 
        wctdm_setreg(wc, card, 41, 0x15);       /* 0.5db */
1829
 
        
1830
 
        return 0;
1831
 
                
1832
 
}
1833
 
 
1834
 
static int wctdm_init_proslic(struct wctdm *wc, int card, int fast, int manual, int sane)
1835
 
{
1836
 
 
1837
 
        unsigned short tmp[5];
1838
 
        unsigned char r19;
1839
 
        int x;
1840
 
        int fxsmode=0;
1841
 
 
1842
 
        /* By default, don't send on hook */
1843
 
        wc->mods[card].fxs.idletxhookstate = 1;
1844
 
 
1845
 
        /* Sanity check the ProSLIC */
1846
 
        if (!sane && wctdm_proslic_insane(wc, card))
1847
 
                return -2;
1848
 
                
1849
 
        if (sane) {
1850
 
                /* Make sure we turn off the DC->DC converter to prevent anything from blowing up */
1851
 
                wctdm_setreg(wc, card, 14, 0x10);
1852
 
        }
1853
 
 
1854
 
        if (wctdm_proslic_init_indirect_regs(wc, card)) {
1855
 
                printk(KERN_INFO "Indirect Registers failed to initialize on module %d.\n", card);
1856
 
                return -1;
1857
 
        }
1858
 
 
1859
 
        /* Clear scratch pad area */
1860
 
        wctdm_proslic_setreg_indirect(wc, card, 97,0);
1861
 
 
1862
 
        /* Clear digital loopback */
1863
 
        wctdm_setreg(wc, card, 8, 0);
1864
 
 
1865
 
        /* Revision C optimization */
1866
 
        wctdm_setreg(wc, card, 108, 0xeb);
1867
 
 
1868
 
        /* Disable automatic VBat switching for safety to prevent
1869
 
           Q7 from accidently turning on and burning out. */
1870
 
        wctdm_setreg(wc, card, 67, 0x17);
1871
 
 
1872
 
        /* Turn off Q7 */
1873
 
        wctdm_setreg(wc, card, 66, 1);
1874
 
 
1875
 
        /* Flush ProSLIC digital filters by setting to clear, while
1876
 
           saving old values */
1877
 
        for (x=0;x<5;x++) {
1878
 
                tmp[x] = wctdm_proslic_getreg_indirect(wc, card, x + 35);
1879
 
                wctdm_proslic_setreg_indirect(wc, card, x + 35, 0x8000);
1880
 
        }
1881
 
 
1882
 
        /* Power up the DC-DC converter */
1883
 
        if (wctdm_powerup_proslic(wc, card, fast)) {
1884
 
                printk("Unable to do INITIAL ProSLIC powerup on module %d\n", card);
1885
 
                return -1;
1886
 
        }
1887
 
 
1888
 
        if (!fast) {
1889
 
 
1890
 
                /* Check for power leaks */
1891
 
                if (wctdm_proslic_powerleak_test(wc, card)) {
1892
 
                        printk("ProSLIC module %d failed leakage test.  Check for short circuit\n", card);
1893
 
                }
1894
 
                /* Power up again */
1895
 
                if (wctdm_powerup_proslic(wc, card, fast)) {
1896
 
                        printk("Unable to do FINAL ProSLIC powerup on module %d\n", card);
1897
 
                        return -1;
1898
 
                }
1899
 
#ifndef NO_CALIBRATION
1900
 
                /* Perform calibration */
1901
 
                if(manual) {
1902
 
                        if (wctdm_proslic_manual_calibrate(wc, card)) {
1903
 
                                //printk("Proslic failed on Manual Calibration\n");
1904
 
                                if (wctdm_proslic_manual_calibrate(wc, card)) {
1905
 
                                        printk("Proslic Failed on Second Attempt to Calibrate Manually. (Try -DNO_CALIBRATION in Makefile)\n");
1906
 
                                        return -1;
1907
 
                                }
1908
 
                                printk("Proslic Passed Manual Calibration on Second Attempt\n");
1909
 
                        }
1910
 
                }
1911
 
                else {
1912
 
                        if(wctdm_proslic_calibrate(wc, card))  {
1913
 
                                //printk("ProSlic died on Auto Calibration.\n");
1914
 
                                if (wctdm_proslic_calibrate(wc, card)) {
1915
 
                                        printk("Proslic Failed on Second Attempt to Auto Calibrate\n");
1916
 
                                        return -1;
1917
 
                                }
1918
 
                                printk("Proslic Passed Auto Calibration on Second Attempt\n");
1919
 
                        }
1920
 
                }
1921
 
                /* Perform DC-DC calibration */
1922
 
                wctdm_setreg(wc, card, 93, 0x99);
1923
 
                r19 = wctdm_getreg(wc, card, 107);
1924
 
                if ((r19 < 0x2) || (r19 > 0xd)) {
1925
 
                        printk("DC-DC cal has a surprising direct 107 of 0x%02x!\n", r19);
1926
 
                        wctdm_setreg(wc, card, 107, 0x8);
1927
 
                }
1928
 
 
1929
 
                /* Save calibration vectors */
1930
 
                for (x=0;x<NUM_CAL_REGS;x++)
1931
 
                        wc->mods[card].fxs.calregs.vals[x] = wctdm_getreg(wc, card, 96 + x);
1932
 
#endif
1933
 
 
1934
 
        } else {
1935
 
                /* Restore calibration registers */
1936
 
                for (x=0;x<NUM_CAL_REGS;x++)
1937
 
                        wctdm_setreg(wc, card, 96 + x, wc->mods[card].fxs.calregs.vals[x]);
1938
 
        }
1939
 
        /* Calibration complete, restore original values */
1940
 
        for (x=0;x<5;x++) {
1941
 
                wctdm_proslic_setreg_indirect(wc, card, x + 35, tmp[x]);
1942
 
        }
1943
 
 
1944
 
        if (wctdm_proslic_verify_indirect_regs(wc, card)) {
1945
 
                printk(KERN_INFO "Indirect Registers failed verification.\n");
1946
 
                return -1;
1947
 
        }
1948
 
 
1949
 
 
1950
 
#if 0
1951
 
    /* Disable Auto Power Alarm Detect and other "features" */
1952
 
    wctdm_setreg(wc, card, 67, 0x0e);
1953
 
    blah = wctdm_getreg(wc, card, 67);
1954
 
#endif
1955
 
 
1956
 
#if 0
1957
 
    if (wctdm_proslic_setreg_indirect(wc, card, 97, 0x0)) { // Stanley: for the bad recording fix
1958
 
                 printk(KERN_INFO "ProSlic IndirectReg Died.\n");
1959
 
                 return -1;
1960
 
        }
1961
 
#endif
1962
 
 
1963
 
    if (alawoverride)
1964
 
        wctdm_setreg(wc, card, 1, 0x20);
1965
 
    else
1966
 
        wctdm_setreg(wc, card, 1, 0x28);
1967
 
        // U-Law 8-bit interface
1968
 
    wctdm_setreg(wc, card, 2, (card * 8) & 0xff);    // Tx Start count low byte  0
1969
 
    wctdm_setreg(wc, card, 3, (card * 8) >> 8);    // Tx Start count high byte 0
1970
 
    wctdm_setreg(wc, card, 4, (card * 8) & 0xff);    // Rx Start count low byte  0
1971
 
    wctdm_setreg(wc, card, 5, (card * 8) >> 8);    // Rx Start count high byte 0
1972
 
    wctdm_setreg(wc, card, 18, 0xff);     // clear all interrupt
1973
 
    wctdm_setreg(wc, card, 19, 0xff);
1974
 
    wctdm_setreg(wc, card, 20, 0xff);
1975
 
    wctdm_setreg(wc, card, 22, 0xff);
1976
 
    wctdm_setreg(wc, card, 73, 0x04);
1977
 
        if (fxshonormode) {
1978
 
                fxsmode = acim2tiss[fxo_modes[_opermode].acim];
1979
 
                wctdm_setreg(wc, card, 10, 0x08 | fxsmode);
1980
 
                if (fxo_modes[_opermode].ring_osc)
1981
 
                        wctdm_proslic_setreg_indirect(wc, card, 20, fxo_modes[_opermode].ring_osc);
1982
 
                if (fxo_modes[_opermode].ring_x)
1983
 
                        wctdm_proslic_setreg_indirect(wc, card, 21, fxo_modes[_opermode].ring_x);
1984
 
        }
1985
 
    if (lowpower)
1986
 
        wctdm_setreg(wc, card, 72, 0x10);
1987
 
 
1988
 
#if 0
1989
 
    wctdm_setreg(wc, card, 21, 0x00);   // enable interrupt
1990
 
    wctdm_setreg(wc, card, 22, 0x02);   // Loop detection interrupt
1991
 
    wctdm_setreg(wc, card, 23, 0x01);   // DTMF detection interrupt
1992
 
#endif
1993
 
 
1994
 
#if 0
1995
 
    /* Enable loopback */
1996
 
    wctdm_setreg(wc, card, 8, 0x2);
1997
 
    wctdm_setreg(wc, card, 14, 0x0);
1998
 
    wctdm_setreg(wc, card, 64, 0x0);
1999
 
    wctdm_setreg(wc, card, 1, 0x08);
2000
 
#endif
2001
 
 
2002
 
        if (fastringer) {
2003
 
                /* Speed up Ringer */
2004
 
                wctdm_proslic_setreg_indirect(wc, card, 20, 0x7e6d);
2005
 
                wctdm_proslic_setreg_indirect(wc, card, 21, 0x01b9);
2006
 
                /* Beef up Ringing voltage to 89V */
2007
 
                if (boostringer) {
2008
 
                        wctdm_setreg(wc, card, 74, 0x3f);
2009
 
                        if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x247)) 
2010
 
                                return -1;
2011
 
                        printk("Boosting fast ringer on slot %d (89V peak)\n", card + 1);
2012
 
                } else if (lowpower) {
2013
 
                        if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x14b)) 
2014
 
                                return -1;
2015
 
                        printk("Reducing fast ring power on slot %d (50V peak)\n", card + 1);
2016
 
                } else
2017
 
                        printk("Speeding up ringer on slot %d (25Hz)\n", card + 1);
2018
 
        } else {
2019
 
                /* Beef up Ringing voltage to 89V */
2020
 
                if (boostringer) {
2021
 
                        wctdm_setreg(wc, card, 74, 0x3f);
2022
 
                        if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x1d1)) 
2023
 
                                return -1;
2024
 
                        printk("Boosting ringer on slot %d (89V peak)\n", card + 1);
2025
 
                } else if (lowpower) {
2026
 
                        if (wctdm_proslic_setreg_indirect(wc, card, 21, 0x108)) 
2027
 
                                return -1;
2028
 
                        printk("Reducing ring power on slot %d (50V peak)\n", card + 1);
2029
 
                }
2030
 
        }
2031
 
        wctdm_setreg(wc, card, 64, 0x01);
2032
 
        wc->mods[card].fxs.lasttxhook = 1;
2033
 
        return 0;
2034
 
}
2035
 
 
2036
 
 
2037
 
static int wctdm_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long data)
2038
 
{
2039
 
        struct wctdm_stats stats;
2040
 
        struct wctdm_regs regs;
2041
 
        struct wctdm_regop regop;
2042
 
        struct wctdm_echo_coefs echoregs;
2043
 
        struct wctdm *wc = chan->pvt;
2044
 
        int x;
2045
 
 
2046
 
#if 0
2047
 
        /* XXX */
2048
 
        printk("RxInts: %d, TxInts: %d\n", wc->rxints, wc->txints);
2049
 
        printk("RxIdent: %d, TxIdent: %d\n", wc->rxident, wc->txident);
2050
 
        for (x=0;x<wc->cards;x++)
2051
 
                printk("Card %d isrshadow: %02x/%02x\n", x, wc->cmdq[x].isrshadow[0], wc->cmdq[x].isrshadow[1]);
2052
 
        cmddesc = 0;
2053
 
#endif  
2054
 
#if 0 
2055
 
        if (wc->vpm) {
2056
 
                char tmp[80];
2057
 
                for (x=0;x<0x200;x++) {
2058
 
                        switch (x & 0xf) {
2059
 
                        case 0:
2060
 
                                sprintf(tmp, "%03x: %02x ", x, wctdm_vpm_in(wc, 0, x));
2061
 
                                break;
2062
 
                        case 0xf:
2063
 
                                printk("%s%02x\n", tmp, wctdm_vpm_in(wc, 0, x));
2064
 
                                break;
2065
 
                        default:
2066
 
                                sprintf(tmp + strlen(tmp), "%02x ", wctdm_vpm_in(wc, 0, x));
2067
 
                                break;
2068
 
                        }
2069
 
                }
2070
 
        }
2071
 
 
2072
 
#endif
2073
 
        switch (cmd) {
2074
 
        case ZT_ONHOOKTRANSFER:
2075
 
                if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS)
2076
 
                        return -EINVAL;
2077
 
                if (get_user(x, (int *)data))
2078
 
                        return -EFAULT;
2079
 
                wc->mods[chan->chanpos - 1].fxs.ohttimer = x << 3;
2080
 
                wc->mods[chan->chanpos - 1].fxs.idletxhookstate = 0x2;  /* OHT mode when idle */
2081
 
                if (wc->mods[chan->chanpos - 1].fxs.lasttxhook == 0x1) {
2082
 
                        /* Apply the change if appropriate */
2083
 
                        wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0x2;
2084
 
                        wc->sethook[chan->chanpos - 1] = CMD_WR(64, wc->mods[chan->chanpos - 1].fxs.lasttxhook);
2085
 
                        /* wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mods[chan->chanpos - 1].fxs.lasttxhook); */
2086
 
                }
2087
 
                break;
2088
 
        case WCTDM_GET_STATS:
2089
 
                if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) {
2090
 
                        stats.tipvolt = wctdm_getreg(wc, chan->chanpos - 1, 80) * -376;
2091
 
                        stats.ringvolt = wctdm_getreg(wc, chan->chanpos - 1, 81) * -376;
2092
 
                        stats.batvolt = wctdm_getreg(wc, chan->chanpos - 1, 82) * -376;
2093
 
                } else if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) {
2094
 
                        stats.tipvolt = (signed char)wctdm_getreg(wc, chan->chanpos - 1, 29) * 1000;
2095
 
                        stats.ringvolt = (signed char)wctdm_getreg(wc, chan->chanpos - 1, 29) * 1000;
2096
 
                        stats.batvolt = (signed char)wctdm_getreg(wc, chan->chanpos - 1, 29) * 1000;
2097
 
                } else 
2098
 
                        return -EINVAL;
2099
 
                if (copy_to_user((struct wctdm_stats *)data, &stats, sizeof(stats)))
2100
 
                        return -EFAULT;
2101
 
                break;
2102
 
        case WCTDM_GET_REGS:
2103
 
                if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXS) {
2104
 
                        for (x=0;x<NUM_INDIRECT_REGS;x++)
2105
 
                                regs.indirect[x] = wctdm_proslic_getreg_indirect(wc, chan->chanpos -1, x);
2106
 
                        for (x=0;x<NUM_REGS;x++)
2107
 
                                regs.direct[x] = wctdm_getreg(wc, chan->chanpos - 1, x);
2108
 
                } else {
2109
 
                        memset(&regs, 0, sizeof(regs));
2110
 
                        for (x=0;x<NUM_FXO_REGS;x++)
2111
 
                                regs.direct[x] = wctdm_getreg(wc, chan->chanpos - 1, x);
2112
 
                }
2113
 
                if (copy_to_user((struct wctdm_regs *)data, &regs, sizeof(regs)))
2114
 
                        return -EFAULT;
2115
 
                break;
2116
 
        case WCTDM_SET_REG:
2117
 
                if (copy_from_user(&regop, (struct wctdm_regop *)data, sizeof(regop)))
2118
 
                        return -EFAULT;
2119
 
                if (regop.indirect) {
2120
 
                        if (wc->modtype[chan->chanpos - 1] != MOD_TYPE_FXS)
2121
 
                                return -EINVAL;
2122
 
                        printk("Setting indirect %d to 0x%04x on %d\n", regop.reg, regop.val, chan->chanpos);
2123
 
                        wctdm_proslic_setreg_indirect(wc, chan->chanpos - 1, regop.reg, regop.val);
2124
 
                } else {
2125
 
                        regop.val &= 0xff;
2126
 
                        printk("Setting direct %d to %04x on %d\n", regop.reg, regop.val, chan->chanpos);
2127
 
                        wctdm_setreg(wc, chan->chanpos - 1, regop.reg, regop.val);
2128
 
                }
2129
 
                break;
2130
 
        case WCTDM_SET_ECHOTUNE:
2131
 
                printk("-- Setting echo registers: \n");
2132
 
                if (copy_from_user(&echoregs, (struct wctdm_echo_coefs*)data, sizeof(echoregs)))
2133
 
                        return -EFAULT;
2134
 
 
2135
 
                if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) {
2136
 
                        /* Set the ACIM register */
2137
 
                        wctdm_setreg(wc, chan->chanpos - 1, 30, echoregs.acim);
2138
 
 
2139
 
                        /* Set the digital echo canceller registers */
2140
 
                        wctdm_setreg(wc, chan->chanpos - 1, 45, echoregs.coef1);
2141
 
                        wctdm_setreg(wc, chan->chanpos - 1, 46, echoregs.coef2);
2142
 
                        wctdm_setreg(wc, chan->chanpos - 1, 47, echoregs.coef3);
2143
 
                        wctdm_setreg(wc, chan->chanpos - 1, 48, echoregs.coef4);
2144
 
                        wctdm_setreg(wc, chan->chanpos - 1, 49, echoregs.coef5);
2145
 
                        wctdm_setreg(wc, chan->chanpos - 1, 50, echoregs.coef6);
2146
 
                        wctdm_setreg(wc, chan->chanpos - 1, 51, echoregs.coef7);
2147
 
                        wctdm_setreg(wc, chan->chanpos - 1, 52, echoregs.coef8);
2148
 
 
2149
 
                        printk("-- Set echo registers successfully\n");
2150
 
 
2151
 
                        break;
2152
 
                } else {
2153
 
                        return -EINVAL;
2154
 
 
2155
 
                }
2156
 
                break;
2157
 
#ifdef VPM_SUPPORT
2158
 
        case ZT_TONEDETECT:
2159
 
                if (get_user(x, (int *) data))
2160
 
                        return -EFAULT;
2161
 
                if (!wc->vpm)
2162
 
                        return -ENOSYS;
2163
 
                if (x && !vpmdtmfsupport)
2164
 
                        return -ENOSYS;
2165
 
                if (x & ZT_TONEDETECT_ON)
2166
 
                        wc->dtmfmask |= (1 << (chan->chanpos - 1));
2167
 
                else
2168
 
                        wc->dtmfmask &= ~(1 << (chan->chanpos - 1));
2169
 
                if (x & ZT_TONEDETECT_MUTE)
2170
 
                        wc->dtmfmutemask |= (1 << (chan->chanpos - 1));
2171
 
                else
2172
 
                        wc->dtmfmutemask &= ~(1 << (chan->chanpos - 1));
2173
 
                return 0;
2174
 
#endif
2175
 
        default:
2176
 
                return -ENOTTY;
2177
 
        }
2178
 
        return 0;
2179
 
 
2180
 
}
2181
 
static int wctdm_open(struct zt_chan *chan)
2182
 
{
2183
 
        struct wctdm *wc = chan->pvt;
2184
 
        if (!(wc->cardflag & (1 << (chan->chanpos - 1))))
2185
 
                return -ENODEV;
2186
 
        if (wc->dead)
2187
 
                return -ENODEV;
2188
 
        wc->usecount++;
2189
 
#ifndef LINUX26
2190
 
        MOD_INC_USE_COUNT;
2191
 
#else
2192
 
        try_module_get(THIS_MODULE);
2193
 
#endif  
2194
 
        return 0;
2195
 
}
2196
 
 
2197
 
static int wctdm_watchdog(struct zt_span *span, int event)
2198
 
{
2199
 
        printk("TDM: Restarting DMA\n");
2200
 
        wctdm_restart_dma(span->pvt);
2201
 
        return 0;
2202
 
}
2203
 
 
2204
 
static int wctdm_close(struct zt_chan *chan)
2205
 
{
2206
 
        struct wctdm *wc = chan->pvt;
2207
 
        int x;
2208
 
        wc->usecount--;
2209
 
#ifndef LINUX26
2210
 
        MOD_DEC_USE_COUNT;
2211
 
#else
2212
 
        module_put(THIS_MODULE);
2213
 
#endif
2214
 
        for (x=0;x<wc->cards;x++) {
2215
 
                if (wc->modtype[x] == MOD_TYPE_FXS)
2216
 
                        wc->mods[x].fxs.idletxhookstate = 1;
2217
 
        }
2218
 
        /* If we're dead, release us now */
2219
 
        if (!wc->usecount && wc->dead) 
2220
 
                wctdm_release(wc);
2221
 
        return 0;
2222
 
}
2223
 
 
2224
 
static int wctdm_hooksig(struct zt_chan *chan, zt_txsig_t txsig)
2225
 
{
2226
 
        struct wctdm *wc = chan->pvt;
2227
 
        int reg=0;
2228
 
        if (wc->modtype[chan->chanpos - 1] == MOD_TYPE_FXO) {
2229
 
                switch(txsig) {
2230
 
                case ZT_TXSIG_START:
2231
 
                case ZT_TXSIG_OFFHOOK:
2232
 
                        wc->mods[chan->chanpos - 1].fxo.offhook = 1;
2233
 
                        wc->sethook[chan->chanpos - 1] = CMD_WR(5, 0x9);
2234
 
                        /* wctdm_setreg(wc, chan->chanpos - 1, 5, 0x9); */
2235
 
                        break;
2236
 
                case ZT_TXSIG_ONHOOK:
2237
 
                        wc->mods[chan->chanpos - 1].fxo.offhook = 0;
2238
 
                        wc->sethook[chan->chanpos - 1] = CMD_WR(5, 0x8);
2239
 
                        /* wctdm_setreg(wc, chan->chanpos - 1, 5, 0x8); */
2240
 
                        break;
2241
 
                default:
2242
 
                        printk("wctdm24xxp: Can't set tx state to %d\n", txsig);
2243
 
                }
2244
 
        } else {
2245
 
                switch(txsig) {
2246
 
                case ZT_TXSIG_ONHOOK:
2247
 
                        switch(chan->sig) {
2248
 
                        case ZT_SIG_EM:
2249
 
                        case ZT_SIG_FXOKS:
2250
 
                        case ZT_SIG_FXOLS:
2251
 
                                wc->mods[chan->chanpos - 1].fxs.lasttxhook = wc->mods[chan->chanpos - 1].fxs.idletxhookstate;
2252
 
                                break;
2253
 
                        case ZT_SIG_FXOGS:
2254
 
                                wc->mods[chan->chanpos - 1].fxs.lasttxhook = 3;
2255
 
                                break;
2256
 
                        }
2257
 
                        break;
2258
 
                case ZT_TXSIG_OFFHOOK:
2259
 
                        switch(chan->sig) {
2260
 
                        case ZT_SIG_EM:
2261
 
                                wc->mods[chan->chanpos - 1].fxs.lasttxhook = 5;
2262
 
                                break;
2263
 
                        default:
2264
 
                                wc->mods[chan->chanpos - 1].fxs.lasttxhook = wc->mods[chan->chanpos - 1].fxs.idletxhookstate;
2265
 
                                break;
2266
 
                        }
2267
 
                        break;
2268
 
                case ZT_TXSIG_START:
2269
 
                        wc->mods[chan->chanpos - 1].fxs.lasttxhook = 4;
2270
 
                        break;
2271
 
                case ZT_TXSIG_KEWL:
2272
 
                        wc->mods[chan->chanpos - 1].fxs.lasttxhook = 0;
2273
 
                        break;
2274
 
                default:
2275
 
                        printk("wctdm24xxp: Can't set tx state to %d\n", txsig);
2276
 
                }
2277
 
                if (debug)
2278
 
                        printk("Setting FXS hook state to %d (%02x)\n", txsig, reg);
2279
 
 
2280
 
                
2281
 
                wc->sethook[chan->chanpos - 1] = CMD_WR(64, wc->mods[chan->chanpos - 1].fxs.lasttxhook);
2282
 
                /* wctdm_setreg(wc, chan->chanpos - 1, 64, wc->mods[chan->chanpos - 1].fxs.lasttxhook); */
2283
 
        }
2284
 
        return 0;
2285
 
}
2286
 
 
2287
 
static int wctdm_initialize(struct wctdm *wc)
2288
 
{
2289
 
        int x;
2290
 
 
2291
 
        /* Zapata stuff */
2292
 
        sprintf(wc->span.name, "WCTDM/%d", wc->pos);
2293
 
        sprintf(wc->span.desc, "%s Board %d", wc->variety, wc->pos + 1);
2294
 
        if (alawoverride) {
2295
 
                printk("ALAW override parameter detected.  Device will be operating in ALAW\n");
2296
 
                wc->span.deflaw = ZT_LAW_ALAW;
2297
 
        } else
2298
 
                wc->span.deflaw = ZT_LAW_MULAW;
2299
 
        for (x=0;x<wc->cards;x++) {
2300
 
                sprintf(wc->chans[x].name, "WCTDM/%d/%d", wc->pos, x);
2301
 
                wc->chans[x].sigcap = ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_SF | ZT_SIG_EM | ZT_SIG_CLEAR;
2302
 
                wc->chans[x].sigcap |= ZT_SIG_FXSKS | ZT_SIG_FXSLS | ZT_SIG_SF | ZT_SIG_CLEAR;
2303
 
                wc->chans[x].chanpos = x+1;
2304
 
                wc->chans[x].pvt = wc;
2305
 
        }
2306
 
        wc->span.chans = wc->chans;
2307
 
        wc->span.channels = wc->cards;
2308
 
        wc->span.hooksig = wctdm_hooksig;
2309
 
        wc->span.open = wctdm_open;
2310
 
        wc->span.close = wctdm_close;
2311
 
        wc->span.flags = ZT_FLAG_RBS;
2312
 
        wc->span.ioctl = wctdm_ioctl;
2313
 
        wc->span.watchdog = wctdm_watchdog;
2314
 
#ifdef VPM_SUPPORT
2315
 
        wc->span.echocan = wctdm_echocan;
2316
 
#endif  
2317
 
        init_waitqueue_head(&wc->span.maintq);
2318
 
 
2319
 
        wc->span.pvt = wc;
2320
 
        if (zt_register(&wc->span, 0)) {
2321
 
                printk("Unable to register span with zaptel\n");
2322
 
                return -1;
2323
 
        }
2324
 
        return 0;
2325
 
}
2326
 
 
2327
 
static void wctdm_post_initialize(struct wctdm *wc)
2328
 
{
2329
 
        int x;
2330
 
        /* Finalize signalling  */
2331
 
        for (x=0;x<wc->cards;x++) {
2332
 
                if (wc->cardflag & (1 << x)) {
2333
 
                        if (wc->modtype[x] == MOD_TYPE_FXO)
2334
 
                                wc->chans[x].sigcap = ZT_SIG_FXSKS | ZT_SIG_FXSLS | ZT_SIG_SF | ZT_SIG_CLEAR;
2335
 
                        else if (wc->modtype[x] == MOD_TYPE_FXS)
2336
 
                                wc->chans[x].sigcap = ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS | ZT_SIG_SF | ZT_SIG_EM | ZT_SIG_CLEAR;
2337
 
                }
2338
 
        }
2339
 
}
2340
 
 
2341
 
static int wctdm_hardware_init(struct wctdm *wc)
2342
 
{
2343
 
        /* Hardware stuff */
2344
 
        unsigned int reg;
2345
 
        unsigned long newjiffies;
2346
 
 
2347
 
        /* Initialize descriptors */
2348
 
        wctdm_init_descriptors(wc);
2349
 
        
2350
 
        /* Enable I/O Access */
2351
 
        pci_read_config_dword(wc->dev, 0x0004, &reg);
2352
 
        reg |= 0x00000007;
2353
 
        pci_write_config_dword(wc->dev, 0x0004, reg);
2354
 
        printk("PCI Config reg is %08x\n", reg);
2355
 
 
2356
 
        wctdm_setctl(wc, 0x0000, 0xfff88001);
2357
 
 
2358
 
        newjiffies = jiffies + HZ/10;
2359
 
        while(((reg = wctdm_getctl(wc,0x0000)) & 0x00000001) && (newjiffies > jiffies));
2360
 
        printk("WCTDM2400P: New Reg: %08x!\n", reg);
2361
 
 
2362
 
        
2363
 
        /* Configure watchdogs, access, etc */
2364
 
        wctdm_setctl(wc, 0x0030, 0x00080048);
2365
 
        wctdm_setctl(wc, 0x0078, 0x00000013 /* | (1 << 28) */);
2366
 
 
2367
 
#if 0
2368
 
        /* XXX Enable loopback XXX */
2369
 
        reg = wctdm_getctl(wc, 0x0030);
2370
 
        wctdm_setctl(wc, 0x0030, reg | 0x00000400);
2371
 
 
2372
 
#else
2373
 
        reg = wctdm_getctl(wc, 0x00fc);
2374
 
        wctdm_setctl(wc, 0x00fc, (reg & ~0x7) | 0x7);
2375
 
        wctdm_setsdi(wc, 0x00, 0x0100);
2376
 
        wctdm_setsdi(wc, 0x16, 0x2100);
2377
 
        printk("Detected REG0: %08x\n", wctdm_getsdi(wc, 0x00));
2378
 
        printk("Detected REG1: %08x\n", wctdm_getsdi(wc, 0x01));
2379
 
        printk("Detected REG2: %08x\n", wctdm_getsdi(wc, 0x02));
2380
 
        
2381
 
        reg = wctdm_getctl(wc, 0x00fc);
2382
 
        printk("(pre) Reg fc is %08x\n", reg);
2383
 
 
2384
 
        wctdm_setctl(wc, 0x00fc, (reg & ~0x7) | 0x4);
2385
 
        wctdm_setsdi(wc, 0x00, 0x0100); 
2386
 
        wctdm_setsdi(wc, 0x16, 0x2100);
2387
 
        reg = wctdm_getctl(wc, 0x00fc);
2388
 
        printk("(post) Reg fc is %08x\n", reg);
2389
 
        printk("Detected REG2: %08x\n", wctdm_getsdi(wc, 0x02));
2390
 
#endif
2391
 
        printk("wctdm2400p: reg is %08x\n", wctdm_getctl(wc, 0x0088));
2392
 
 
2393
 
        return 0;
2394
 
}
2395
 
 
2396
 
static void wctdm_setintmask(struct wctdm *wc, unsigned int intmask)
2397
 
{
2398
 
        wc->intmask = intmask;
2399
 
        wctdm_setctl(wc, 0x0038, intmask);
2400
 
}
2401
 
 
2402
 
static void wctdm_enable_interrupts(struct wctdm *wc)
2403
 
{
2404
 
        /* Enable interrupts */ 
2405
 
        wctdm_setintmask(wc, 0x00010041);
2406
 
}
2407
 
 
2408
 
static void wctdm_restart_dma(struct wctdm *wc)
2409
 
{
2410
 
}
2411
 
 
2412
 
static void wctdm_start_dma(struct wctdm *wc)
2413
 
{
2414
 
        unsigned int reg;
2415
 
        wmb();
2416
 
        wctdm_setctl(wc, 0x0020, wc->descripdma);
2417
 
        wctdm_setctl(wc, 0x0018, wc->descripdma + (16 * ERING_SIZE));
2418
 
        /* Start receiver/transmitter */
2419
 
        reg = wctdm_getctl(wc, 0x0030);
2420
 
        wctdm_setctl(wc, 0x0030, reg | 0x00002002);
2421
 
        wctdm_setctl(wc, 0x0008, 0x00000000);
2422
 
        wctdm_setctl(wc, 0x0010, 0x00000000);
2423
 
        reg = wctdm_getctl(wc, 0x0028);
2424
 
        wctdm_setctl(wc, 0x0028, reg);
2425
 
 
2426
 
}
2427
 
 
2428
 
static void wctdm_stop_dma(struct wctdm *wc)
2429
 
{
2430
 
        /* Disable interrupts and reset */
2431
 
        unsigned int reg;
2432
 
        /* Disable interrupts */
2433
 
        wctdm_setintmask(wc, 0x00000000);
2434
 
        wctdm_setctl(wc, 0x0084, 0x00000000);
2435
 
        wctdm_setctl(wc, 0x0048, 0x00000000);
2436
 
        /* Reset the part to be on the safe side */
2437
 
        reg = wctdm_getctl(wc, 0x0000);
2438
 
        reg |= 0x00000001;
2439
 
        wctdm_setctl(wc, 0x0000, reg);
2440
 
}
2441
 
 
2442
 
static void wctdm_disable_interrupts(struct wctdm *wc)  
2443
 
{
2444
 
        /* Disable interrupts */
2445
 
        wctdm_setintmask(wc, 0x00000000);
2446
 
        wctdm_setctl(wc, 0x0084, 0x00000000);
2447
 
}
2448
 
 
2449
 
 
2450
 
#ifdef VPM_SUPPORT
2451
 
static void wctdm_vpm_set_dtmf_threshold(struct wctdm *wc, unsigned int threshold)
2452
 
{
2453
 
        unsigned int x;
2454
 
 
2455
 
        for (x = 0; x < 4; x++) {
2456
 
                wctdm_vpm_out(wc, x, 0xC4, (threshold >> 8) & 0xFF);
2457
 
                wctdm_vpm_out(wc, x, 0xC5, (threshold & 0xFF));
2458
 
        }
2459
 
        printk("VPM: DTMF threshold set to %d\n", threshold);
2460
 
}
2461
 
 
2462
 
static void wctdm_vpm_init(struct wctdm *wc)
2463
 
{
2464
 
        unsigned char reg;
2465
 
        unsigned int mask;
2466
 
        unsigned int ver;
2467
 
        unsigned char vpmver=0;
2468
 
        unsigned int i, x, y;
2469
 
 
2470
 
        if (!vpmsupport) {
2471
 
                printk("VPM: Support Disabled\n");
2472
 
                wc->vpm = 0;
2473
 
                return;
2474
 
        }
2475
 
 
2476
 
        for (x=0;x<NUM_EC;x++) {
2477
 
                ver = wctdm_vpm_in(wc, x, 0x1a0); /* revision */
2478
 
                if (debug)
2479
 
                        printk("VPM: Chip %d: ver %02x\n", x, ver);
2480
 
                if (ver != 0x33) {
2481
 
                        printk("VPM: %s\n", x ? "Inoperable" : "Not Present");
2482
 
                        wc->vpm = 0;
2483
 
                        return;
2484
 
                }       
2485
 
 
2486
 
                if (!x) {
2487
 
                        vpmver = wctdm_vpm_in(wc, x, 0x1a6) & 0xf;
2488
 
                        printk("VPM Revision: %02x\n", vpmver);
2489
 
                }
2490
 
 
2491
 
 
2492
 
                /* Setup GPIO's */
2493
 
                for (y=0;y<4;y++) {
2494
 
                        wctdm_vpm_out(wc, x, 0x1a8 + y, 0x00); /* GPIO out */
2495
 
                        if (y == 3)
2496
 
                                wctdm_vpm_out(wc, x, 0x1ac + y, 0x00); /* GPIO dir */
2497
 
                        else
2498
 
                                wctdm_vpm_out(wc, x, 0x1ac + y, 0xff); /* GPIO dir */
2499
 
                        wctdm_vpm_out(wc, x, 0x1b0 + y, 0x00); /* GPIO sel */
2500
 
                }
2501
 
 
2502
 
                /* Setup TDM path - sets fsync and tdm_clk as inputs */
2503
 
                reg = wctdm_vpm_in(wc, x, 0x1a3); /* misc_con */
2504
 
                wctdm_vpm_out(wc, x, 0x1a3, reg & ~2);
2505
 
 
2506
 
                /* Setup Echo length (256 taps) */
2507
 
                wctdm_vpm_out(wc, x, 0x022, 0);
2508
 
 
2509
 
                /* Setup timeslots */
2510
 
                if (vpmver == 0x01) {
2511
 
                        wctdm_vpm_out(wc, x, 0x02f, 0x00); 
2512
 
                        wctdm_vpm_out(wc, x, 0x023, 0xff);
2513
 
                        mask = 0x11111111 << x;
2514
 
                } else {
2515
 
                        wctdm_vpm_out(wc, x, 0x02f, 0x20  | (x << 3)); 
2516
 
                        wctdm_vpm_out(wc, x, 0x023, 0x3f);
2517
 
                        mask = 0x0000003f;
2518
 
                }
2519
 
 
2520
 
                /* Setup the tdm channel masks for all chips*/
2521
 
                for (i = 0; i < 4; i++)
2522
 
                        wctdm_vpm_out(wc, x, 0x33 - i, (mask >> (i << 3)) & 0xff);
2523
 
 
2524
 
                /* Setup convergence rate */
2525
 
                reg = wctdm_vpm_in(wc,x,0x20);
2526
 
                reg &= 0xE0;
2527
 
                if (alawoverride) {
2528
 
                        if (!x)
2529
 
                                printk("VPM: A-law mode\n");
2530
 
                        reg |= 0x01;
2531
 
                } else {
2532
 
                        if (!x)
2533
 
                                printk("VPM: U-law mode\n");
2534
 
                        reg &= ~0x01;
2535
 
                }
2536
 
                wctdm_vpm_out(wc,x,0x20,(reg | 0x20));
2537
 
 
2538
 
                /* Initialize echo cans */
2539
 
                for (i = 0 ; i < MAX_TDM_CHAN; i++) {
2540
 
                        if (mask & (0x00000001 << i))
2541
 
                                wctdm_vpm_out(wc,x,i,0x00);
2542
 
                }
2543
 
 
2544
 
                for (i=0;i<30;i++) 
2545
 
                        schluffen(&wc->regq);
2546
 
 
2547
 
                /* Put in bypass mode */
2548
 
                for (i = 0 ; i < MAX_TDM_CHAN ; i++) {
2549
 
                        if (mask & (0x00000001 << i)) {
2550
 
                                wctdm_vpm_out(wc,x,i,0x01);
2551
 
                        }
2552
 
                }
2553
 
 
2554
 
                /* Enable bypass */
2555
 
                for (i = 0 ; i < MAX_TDM_CHAN ; i++) {
2556
 
                        if (mask & (0x00000001 << i))
2557
 
                                wctdm_vpm_out(wc,x,0x78 + i,0x01);
2558
 
                }
2559
 
      
2560
 
                /* Enable DTMF detectors (always DTMF detect all spans) */
2561
 
                for (i = 0; i < 6; i++) {
2562
 
                        if (vpmver == 0x01) 
2563
 
                                wctdm_vpm_out(wc, x, 0x98 + i, 0x40 | (i << 2) | x);
2564
 
                        else
2565
 
                                wctdm_vpm_out(wc, x, 0x98 + i, 0x40 | i);
2566
 
                }
2567
 
 
2568
 
                for (i = 0xB8; i < 0xC0; i++)
2569
 
                        wctdm_vpm_out(wc, x, i, 0xFF);
2570
 
                for (i = 0xC0; i < 0xC4; i++)
2571
 
                        wctdm_vpm_out(wc, x, i, 0xff);
2572
 
 
2573
 
        } 
2574
 
        /* set DTMF detection threshold */
2575
 
        wctdm_vpm_set_dtmf_threshold(wc, dtmfthreshold);
2576
 
        
2577
 
        if (vpmver == 0x01)
2578
 
                wc->vpm = 2;
2579
 
        else
2580
 
                wc->vpm = 1;
2581
 
}
2582
 
 
2583
 
#endif
2584
 
 
2585
 
static void wctdm_locate_modules(struct wctdm *wc)
2586
 
{
2587
 
        int x;
2588
 
        unsigned long flags;
2589
 
        printk("Resetting the modules...\n");
2590
 
        /* Initialize control register */
2591
 
        wc->ctlreg = 0x00;
2592
 
        /* Set Reset */
2593
 
        wctdm_setctl(wc, 0x0048, 0x00000000);
2594
 
        for (x=0;x<10;x++) 
2595
 
                schluffen(&wc->regq);
2596
 
        printk("During Resetting the modules...\n");
2597
 
        /* Clear reset */
2598
 
        wctdm_setctl(wc, 0x0048, 0x00010000);
2599
 
        for (x=0;x<10;x++) 
2600
 
                schluffen(&wc->regq);
2601
 
        printk("After resetting the modules...\n");
2602
 
        /* Switch to caring only about receive interrupts */
2603
 
        wctdm_setintmask(wc, 0x00010040);
2604
 
        
2605
 
        /* Make sure all units go into daisy chain mode */
2606
 
        spin_lock_irqsave(&wc->reglock, flags);
2607
 
        wc->span.irqmisses = 0;
2608
 
        for (x=0;x<wc->cards;x++) 
2609
 
                wc->modtype[x] = MOD_TYPE_FXSINIT;
2610
 
#ifdef VPM_SUPPORT
2611
 
        wc->vpm = -1;
2612
 
        for (x=wc->cards;x<wc->cards+NUM_EC;x++)
2613
 
                wc->modtype[x] = MOD_TYPE_VPM;
2614
 
#endif
2615
 
        spin_unlock_irqrestore(&wc->reglock, flags);
2616
 
        /* Wait just a bit */
2617
 
        for (x=0;x<10;x++) 
2618
 
                schluffen(&wc->regq);
2619
 
        spin_lock_irqsave(&wc->reglock, flags);
2620
 
        for (x=0;x<wc->cards;x++) 
2621
 
                wc->modtype[x] = MOD_TYPE_FXS;
2622
 
        spin_unlock_irqrestore(&wc->reglock, flags);
2623
 
#if 0
2624
 
        /* XXX */
2625
 
        cmddesc = 0;
2626
 
#endif  
2627
 
        /* Reset modules */
2628
 
        for (x=0;x<wc->cards;x++) {
2629
 
                int sane=0,ret=0,readi=0;
2630
 
                /* Init with Auto Calibration */
2631
 
                if (!(ret = wctdm_init_proslic(wc, x, 0, 0, sane))) {
2632
 
                        wc->cardflag |= (1 << x);
2633
 
                        if (debug) {
2634
 
                                readi = wctdm_getreg(wc,x,LOOP_I_LIMIT);
2635
 
                                printk("Proslic module %d loop current is %dmA\n",x,
2636
 
                                ((readi*3)+20));
2637
 
                        }
2638
 
                        printk("Port %d: Installed -- AUTO FXS/DPO\n", x + 1);
2639
 
                } else {
2640
 
                        if(ret!=-2) {
2641
 
                                sane=1;
2642
 
                                /* Init with Manual Calibration */
2643
 
                                if (!wctdm_init_proslic(wc, x, 0, 1, sane)) {
2644
 
                                        wc->cardflag |= (1 << x);
2645
 
                                if (debug) {
2646
 
                                        readi = wctdm_getreg(wc,x,LOOP_I_LIMIT);
2647
 
                                        printk("Proslic module %d loop current is %dmA\n",x,
2648
 
                                        ((readi*3)+20));
2649
 
                                }
2650
 
                                        printk("Port %d: Installed -- MANUAL FXS\n",x + 1);
2651
 
                                } else {
2652
 
                                        printk("Port %d: FAILED FXS (%s)\n", x + 1, fxshonormode ? fxo_modes[_opermode].name : "FCC");
2653
 
                                } 
2654
 
                        } else if (!(ret = wctdm_init_voicedaa(wc, x, 0, 0, sane))) {
2655
 
                                wc->cardflag |= (1 << x);
2656
 
                                printk("Port %d: Installed -- AUTO FXO (%s mode)\n",x + 1, fxo_modes[_opermode].name);
2657
 
                        } else
2658
 
                                printk("Port %d: Not installed\n", x + 1);
2659
 
                }
2660
 
        }
2661
 
#ifdef VPM_SUPPORT
2662
 
        wctdm_vpm_init(wc);
2663
 
        if (wc->vpm) {
2664
 
                printk("VPM: Present and operational (Rev %c)\n", 'A' + wc->vpm - 1);
2665
 
                wc->ctlreg |= 0x10;
2666
 
        }
2667
 
#endif
2668
 
}
2669
 
 
2670
 
static int __devinit wctdm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
2671
 
{
2672
 
        int res;
2673
 
        struct wctdm *wc;
2674
 
        struct wctdm_desc *d = (struct wctdm_desc *)ent->driver_data;
2675
 
        int x;
2676
 
        int y;
2677
 
        static int initd_ifaces=0;
2678
 
        
2679
 
        if(initd_ifaces){
2680
 
                memset((void *)ifaces,0,(sizeof(struct wctdm *))*WC_MAX_IFACES);
2681
 
                initd_ifaces=1;
2682
 
        }
2683
 
        for (x=0;x<WC_MAX_IFACES;x++)
2684
 
                if (!ifaces[x]) break;
2685
 
        if (x >= WC_MAX_IFACES) {
2686
 
                printk("Too many interfaces\n");
2687
 
                return -EIO;
2688
 
        }
2689
 
        
2690
 
        if (pci_enable_device(pdev)) {
2691
 
                res = -EIO;
2692
 
        } else {
2693
 
                wc = kmalloc(sizeof(struct wctdm), GFP_KERNEL);
2694
 
                if (wc) {
2695
 
                        ifaces[x] = wc;
2696
 
                        memset(wc, 0, sizeof(struct wctdm));
2697
 
                        spin_lock_init(&wc->reglock);
2698
 
                        wc->curcard = -1;
2699
 
                        wc->cards = NUM_CARDS;
2700
 
                        wc->iobase = pci_resource_start(pdev, 0);
2701
 
                        wc->dev = pdev;
2702
 
                        wc->pos = x;
2703
 
                        wc->variety = d->name;
2704
 
                        for (y=0;y<NUM_CARDS;y++)
2705
 
                                wc->flags[y] = d->flags;
2706
 
                        /* Keep track of whether we need to free the region */
2707
 
                        if (request_region(wc->iobase, 0xff, "wctdm")) 
2708
 
                                wc->freeregion = 1;
2709
 
 
2710
 
                        /* Allocate enough memory for two zt chunks, receive and transmit.  Each sample uses
2711
 
                           32 bits.  Allocate an extra set just for control too */
2712
 
                        wc->writechunk = (int *)pci_alloc_consistent(pdev, PCI_WINDOW_SIZE, &wc->writedma);
2713
 
                        if (!wc->writechunk) {
2714
 
                                printk("wctdm: Unable to allocate DMA-able memory\n");
2715
 
                                if (wc->freeregion)
2716
 
                                        release_region(wc->iobase, 0xff);
2717
 
                                return -ENOMEM;
2718
 
                        }
2719
 
 
2720
 
                        wc->readchunk = wc->writechunk + SFRAME_SIZE / 2;       /* in doublewords */
2721
 
                        wc->readdma = wc->writedma + SFRAME_SIZE * 2;           /* in bytes */
2722
 
 
2723
 
                        wc->descripchunk = wc->readchunk + SFRAME_SIZE / 2;     /* in doublewords */
2724
 
                        wc->descripdma = wc->readdma + SFRAME_SIZE * 2;         /* in bytes */
2725
 
 
2726
 
                        /* Initialize Write/Buffers to all blank data */
2727
 
                        memset((void *)wc->writechunk,0x00, SFRAME_SIZE * 2);
2728
 
                        memset((void *)wc->readchunk, 0x00, SFRAME_SIZE * 2);
2729
 
 
2730
 
                        init_waitqueue_head(&wc->regq);
2731
 
 
2732
 
                        if (wctdm_initialize(wc)) {
2733
 
                                printk("wctdm: Unable to intialize FXS\n");
2734
 
                                /* Set Reset Low */
2735
 
                                wctdm_stop_dma(wc);
2736
 
                                /* Free Resources */
2737
 
                                free_irq(pdev->irq, wc);
2738
 
                                if (wc->freeregion)
2739
 
                                        release_region(wc->iobase, 0xff);
2740
 
                                pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma);
2741
 
                                kfree(wc);
2742
 
                                return -EIO;
2743
 
                        }
2744
 
 
2745
 
                        /* Enable bus mastering */
2746
 
                        pci_set_master(pdev);
2747
 
 
2748
 
                        /* Keep track of which device we are */
2749
 
                        pci_set_drvdata(pdev, wc);
2750
 
 
2751
 
                        if (request_irq(pdev->irq, wctdm_interrupt, SA_SHIRQ, "wctdm24xxp", wc)) {
2752
 
                                printk("wctdm: Unable to request IRQ %d\n", pdev->irq);
2753
 
                                if (wc->freeregion)
2754
 
                                        release_region(wc->iobase, 0xff);
2755
 
                                pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma);
2756
 
                                pci_set_drvdata(pdev, NULL);
2757
 
                                kfree(wc);
2758
 
                                return -EIO;
2759
 
                        }
2760
 
 
2761
 
 
2762
 
                        if (wctdm_hardware_init(wc)) {
2763
 
                                /* Set Reset Low */
2764
 
                                wctdm_stop_dma(wc);
2765
 
                                /* Free Resources */
2766
 
                                free_irq(pdev->irq, wc);
2767
 
                                if (wc->freeregion)
2768
 
                                        release_region(wc->iobase, 0xff);
2769
 
                                pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma);
2770
 
                                pci_set_drvdata(pdev, NULL);
2771
 
                                zt_unregister(&wc->span);
2772
 
                                kfree(wc);
2773
 
                                return -EIO;
2774
 
 
2775
 
                        }
2776
 
 
2777
 
 
2778
 
                        /* Enable interrupts */
2779
 
                        wctdm_enable_interrupts(wc);
2780
 
 
2781
 
                        /* Start DMA */
2782
 
                        wctdm_start_dma(wc);
2783
 
                        
2784
 
                        /* Now track down what modules are installed */
2785
 
                        wctdm_locate_modules(wc);
2786
 
 
2787
 
                        /* Final initialization */
2788
 
                        wctdm_post_initialize(wc);
2789
 
 
2790
 
                        printk("Found a Wildcard TDM: %s (%d modules)\n", wc->variety, wc->cards);
2791
 
                        res = 0;
2792
 
                } else
2793
 
                        res = -ENOMEM;
2794
 
        }
2795
 
        return res;
2796
 
}
2797
 
 
2798
 
static void wctdm_release(struct wctdm *wc)
2799
 
{
2800
 
        zt_unregister(&wc->span);
2801
 
        if (wc->freeregion)
2802
 
                release_region(wc->iobase, 0xff);
2803
 
        kfree(wc);
2804
 
        printk("Freed a Wildcard\n");
2805
 
}
2806
 
 
2807
 
static void __devexit wctdm_remove_one(struct pci_dev *pdev)
2808
 
{
2809
 
        struct wctdm *wc = pci_get_drvdata(pdev);
2810
 
        if (wc) {
2811
 
 
2812
 
                /* Stop any DMA */
2813
 
                wctdm_stop_dma(wc);
2814
 
 
2815
 
                /* In case hardware is still there */
2816
 
                wctdm_disable_interrupts(wc);
2817
 
                
2818
 
                /* Immediately free resources */
2819
 
                pci_free_consistent(pdev, PCI_WINDOW_SIZE, (void *)wc->writechunk, wc->writedma);
2820
 
                free_irq(pdev->irq, wc);
2821
 
 
2822
 
                /* Release span, possibly delayed */
2823
 
                if (!wc->usecount)
2824
 
                        wctdm_release(wc);
2825
 
                else
2826
 
                        wc->dead = 1;
2827
 
        }
2828
 
}
2829
 
 
2830
 
static struct pci_device_id wctdm_pci_tbl[] = {
2831
 
        { 0xd161, 0x2400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm },
2832
 
        { 0 }
2833
 
};
2834
 
 
2835
 
MODULE_DEVICE_TABLE(pci, wctdm_pci_tbl);
2836
 
 
2837
 
static struct pci_driver wctdm_driver = {
2838
 
        name:   "wctdm24xxp",
2839
 
        probe:  wctdm_init_one,
2840
 
#ifdef LINUX26
2841
 
        remove: __devexit_p(wctdm_remove_one),
2842
 
#else
2843
 
        remove: wctdm_remove_one,
2844
 
#endif
2845
 
        suspend: NULL,
2846
 
        resume: NULL,
2847
 
        id_table: wctdm_pci_tbl,
2848
 
};
2849
 
 
2850
 
static int __init wctdm_init(void)
2851
 
{
2852
 
        int res;
2853
 
        int x;
2854
 
        for (x=0;x<(sizeof(fxo_modes) / sizeof(fxo_modes[0])); x++) {
2855
 
                if (!strcmp(fxo_modes[x].name, opermode))
2856
 
                        break;
2857
 
        }
2858
 
        if (x < sizeof(fxo_modes) / sizeof(fxo_modes[0])) {
2859
 
                _opermode = x;
2860
 
        } else {
2861
 
                printk("Invalid/unknown operating mode '%s' specified.  Please choose one of:\n", opermode);
2862
 
                for (x=0;x<sizeof(fxo_modes) / sizeof(fxo_modes[0]); x++)
2863
 
                        printk("  %s\n", fxo_modes[x].name);
2864
 
                printk("Note this option is CASE SENSITIVE!\n");
2865
 
                return -ENODEV;
2866
 
        }
2867
 
 
2868
 
        res = pci_module_init(&wctdm_driver);
2869
 
        if (res)
2870
 
                return -ENODEV;
2871
 
        return 0;
2872
 
}
2873
 
 
2874
 
static void __exit wctdm_cleanup(void)
2875
 
{
2876
 
        pci_unregister_driver(&wctdm_driver);
2877
 
}
2878
 
 
2879
 
#ifdef LINUX26
2880
 
module_param(debug, int, 0600);
2881
 
module_param(loopcurrent, int, 0600);
2882
 
module_param(robust, int, 0600);
2883
 
module_param(_opermode, int, 0600);
2884
 
module_param(opermode, charp, 0600);
2885
 
module_param(timingonly, int, 0600);
2886
 
module_param(lowpower, int, 0600);
2887
 
module_param(boostringer, int, 0600);
2888
 
module_param(fastringer, int, 0600);
2889
 
module_param(fxshonormode, int, 0600);
2890
 
module_param(battdebounce, int, 0600);
2891
 
module_param(battthresh, int, 0600);
2892
 
module_param(alawoverride, int, 0600);
2893
 
#ifdef VPM_SUPPORT
2894
 
module_param(vpmsupport, int, 0600);
2895
 
module_param(vpmdtmfsupport, int, 0600);
2896
 
module_param(vpmspans, int, 0600);
2897
 
module_param(dtmfthreshold, int, 0600);
2898
 
#endif
2899
 
#else
2900
 
MODULE_PARM(debug, "i");
2901
 
MODULE_PARM(loopcurrent, "i");
2902
 
MODULE_PARM(robust, "i");
2903
 
MODULE_PARM(_opermode, "i");
2904
 
MODULE_PARM(opermode, "s");
2905
 
MODULE_PARM(timingonly, "i");
2906
 
MODULE_PARM(lowpower, "i");
2907
 
MODULE_PARM(boostringer, "i");
2908
 
MODULE_PARM(fastringer, "i");
2909
 
MODULE_PARM(fxshonormode, "i");
2910
 
MODULE_PARM(battdebounce, "i");
2911
 
MODULE_PARM(battthresh, "i");
2912
 
MODULE_PARM(alawoverride, "i");
2913
 
#ifdef VPM_SUPPORT
2914
 
MODULE_PARM(vpmsupport, "i");
2915
 
MODULE_PARM(vpmdtmfsupport, "i");
2916
 
MODULE_PARM(vpmspans, "i");
2917
 
MODULE_PARM(dtmfthreshold, "i");
2918
 
#endif
2919
 
#endif
2920
 
MODULE_DESCRIPTION("Wildcard TDM2400P Zaptel Driver");
2921
 
MODULE_AUTHOR("Mark Spencer <markster@digium.com>");
2922
 
#ifdef MODULE_LICENSE
2923
 
MODULE_LICENSE("GPL");
2924
 
#endif
2925
 
 
2926
 
module_init(wctdm_init);
2927
 
module_exit(wctdm_cleanup);
2928
 
 
2929
 
 
2930