Review Board 1.7.16


Generate VMWI neon pulses from FXS module to light NEON lamp on older 'non intellegent phones'

Review Request #1144 - Created March 16, 2011 and updated

Alec Davis
dahdi/linux
14261
Reviewers
asterisk-dev
sruffell
DAHDI
Implement same code as for wcdtm
13/04/12
Tested with mwisendtype=lrev,hvac
at 2 different phones on same FXS port, one a real neon phone, and another a led+zener phone.
Left messages, and neon would flash as expected.

Diff revision 3

This is not the most recent revision of the diff. The latest diff is revision 7. See what's changed.

1 2 3 4 5 6 7
1 2 3 4 5 6 7

  1. linux/team/sruffell/wctdm24xxp-cmdlist/drivers/dahdi/wctdm24xxp/base.c: Loading...
  2. linux/team/sruffell/wctdm24xxp-cmdlist/drivers/dahdi/wctdm24xxp/wctdm24xxp.h: Loading...
linux/team/sruffell/wctdm24xxp-cmdlist/drivers/dahdi/wctdm24xxp/base.c
Revision 9867 New Change
1
/*
1
/*
2
 * Wildcard TDM2400P TDM FXS/FXO Interface Driver for DAHDI Telephony interface
2
 * Wildcard TDM2400P TDM FXS/FXO Interface Driver for DAHDI Telephony interface
3
 *
3
 *
4
 * Written by Mark Spencer <markster@digium.com>
4
 * Written by Mark Spencer <markster@digium.com>
5
 * Support for TDM800P and VPM150M by Matthew Fredrickson <creslin@digium.com>
5
 * Support for TDM800P and VPM150M by Matthew Fredrickson <creslin@digium.com>
6
 *
6
 *
7
 * Support for Hx8 by Andrew Kohlsmith <akohlsmith@mixdown.ca> and Matthew
7
 * Support for Hx8 by Andrew Kohlsmith <akohlsmith@mixdown.ca> and Matthew
8
 * Fredrickson <creslin@digium.com>
8
 * Fredrickson <creslin@digium.com>
9
 *
9
 *
10
 * Copyright (C) 2005 - 2010 Digium, Inc.
10
 * Copyright (C) 2005 - 2010 Digium, Inc.
11
 * All rights reserved.
11
 * All rights reserved.
12
 *
12
 *
13
 * Sections for QRV cards written by Jim Dixon <jim@lambdatel.com>
13
 * Sections for QRV cards written by Jim Dixon <jim@lambdatel.com>
14
 * Copyright (C) 2006, Jim Dixon and QRV Communications
14
 * Copyright (C) 2006, Jim Dixon and QRV Communications
15
 * All rights reserved.
15
 * All rights reserved.
16
 *
16
 *
17
 */
17
 */
18

    
   
18

   
19
/*
19
/*
20
 * See http://www.asterisk.org for more information about
20
 * See http://www.asterisk.org for more information about
21
 * the Asterisk project. Please do not directly contact
21
 * the Asterisk project. Please do not directly contact
22
 * any of the maintainers of this project for assistance;
22
 * any of the maintainers of this project for assistance;
23
 * the project provides a web site, mailing lists and IRC
23
 * the project provides a web site, mailing lists and IRC
24
 * channels for your use.
24
 * channels for your use.
25
 *
25
 *
26
 * This program is free software, distributed under the terms of
26
 * This program is free software, distributed under the terms of
27
 * the GNU General Public License Version 2 as published by the
27
 * the GNU General Public License Version 2 as published by the
28
 * Free Software Foundation. See the LICENSE file included with
28
 * Free Software Foundation. See the LICENSE file included with
29
 * this program for more details.
29
 * this program for more details.
30
 */
30
 */
31

    
   
31

   
32
/* For QRV DRI cards, gain is signed short, expressed in hundredths of
32
/* For QRV DRI cards, gain is signed short, expressed in hundredths of
33
db (in reference to 1v Peak @ 1000Hz) , as follows:
33
db (in reference to 1v Peak @ 1000Hz) , as follows:
34

    
   
34

   
35
Rx Gain: -11.99 to 15.52 db
35
Rx Gain: -11.99 to 15.52 db
36
Tx Gain - No Pre-Emphasis: -35.99 to 12.00 db
36
Tx Gain - No Pre-Emphasis: -35.99 to 12.00 db
37
Tx Gain - W/Pre-Emphasis: -23.99 to 0.00 db
37
Tx Gain - W/Pre-Emphasis: -23.99 to 0.00 db
38
*/
38
*/
39

    
   
39

   
40
#include <linux/version.h>
40
#include <linux/version.h>
41
#include <linux/kernel.h>
41
#include <linux/kernel.h>
42
#include <linux/errno.h>
42
#include <linux/errno.h>
43
#include <linux/module.h>
43
#include <linux/module.h>
44
#include <linux/init.h>
44
#include <linux/init.h>
45
#include <linux/pci.h>
45
#include <linux/pci.h>
46
#include <linux/sched.h>
46
#include <linux/sched.h>
47
#include <linux/interrupt.h>
47
#include <linux/interrupt.h>
48
#include <linux/workqueue.h>
48
#include <linux/workqueue.h>
49
#include <linux/delay.h>
49
#include <linux/delay.h>
50
#include <linux/moduleparam.h>
50
#include <linux/moduleparam.h>
51
#include <linux/firmware.h>
51
#include <linux/firmware.h>
52
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
52
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
53
#include <linux/semaphore.h>
53
#include <linux/semaphore.h>
54
#else
54
#else
55
#include <asm/semaphore.h>
55
#include <asm/semaphore.h>
56
#endif
56
#endif
57
#include <linux/crc32.h>
57
#include <linux/crc32.h>
58

    
   
58

   
59
#include <stdbool.h>
59
#include <stdbool.h>
60

    
   
60

   
61
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
61
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
62
/* Define this if you would like to load the modules in parallel.  While this
62
/* Define this if you would like to load the modules in parallel.  While this
63
 * can speed up loads when multiple cards handled by this driver are installed,
63
 * can speed up loads when multiple cards handled by this driver are installed,
64
 * it also makes it impossible to abort module loads with ctrl-c */
64
 * it also makes it impossible to abort module loads with ctrl-c */
65
#define USE_ASYNC_INIT
65
#define USE_ASYNC_INIT
66
#include <linux/async.h>
66
#include <linux/async.h>
67
#else
67
#else
68
#undef USE_ASYNC_INIT
68
#undef USE_ASYNC_INIT
69
#endif
69
#endif
70

    
   
70

   
71
#include <dahdi/kernel.h>
71
#include <dahdi/kernel.h>
72
#include <dahdi/wctdm_user.h>
72
#include <dahdi/wctdm_user.h>
73

    
   
73

   
74
#include "proslic.h"
74
#include "proslic.h"
75

    
   
75

   
76
#include "wctdm24xxp.h"
76
#include "wctdm24xxp.h"
77
#include "xhfc.h"
77
#include "xhfc.h"
78

    
   
78

   
79
#include "adt_lec.h"
79
#include "adt_lec.h"
80

    
   
80

   
81
#include "voicebus/GpakCust.h"
81
#include "voicebus/GpakCust.h"
82
#include "voicebus/GpakApi.h"
82
#include "voicebus/GpakApi.h"
83

    
   
83

   
84
#if VOICEBUS_SFRAME_SIZE != SFRAME_SIZE
84
#if VOICEBUS_SFRAME_SIZE != SFRAME_SIZE
85
#error SFRAME_SIZE must match the VOICEBUS_SFRAME_SIZE
85
#error SFRAME_SIZE must match the VOICEBUS_SFRAME_SIZE
86
#endif
86
#endif
87

    
   
87

   
88
/*
88
/*
89
  Experimental max loop current limit for the proslic
89
  Experimental max loop current limit for the proslic
90
  Loop current limit is from 20 mA to 41 mA in steps of 3
90
  Loop current limit is from 20 mA to 41 mA in steps of 3
91
  (according to datasheet)
91
  (according to datasheet)
92
  So set the value below to:
92
  So set the value below to:
93
  0x00 : 20mA (default)
93
  0x00 : 20mA (default)
94
  0x01 : 23mA
94
  0x01 : 23mA
95
  0x02 : 26mA
95
  0x02 : 26mA
96
  0x03 : 29mA
96
  0x03 : 29mA
97
  0x04 : 32mA
97
  0x04 : 32mA
98
  0x05 : 35mA
98
  0x05 : 35mA
99
  0x06 : 37mA
99
  0x06 : 37mA
100
  0x07 : 41mA
100
  0x07 : 41mA
101
*/
101
*/
102
static int loopcurrent = 20;
102
static int loopcurrent = 20;
103

    
   
103

   
104
/* Following define is a logical exclusive OR to determine if the polarity of an fxs line is to be reversed.
104
/* Following define is a logical exclusive OR to determine if the polarity of an fxs line is to be reversed.
105
 * 	The items taken into account are:
105
 * 	The items taken into account are:
106
 * 	overall polarity reversal for the module,
106
 * 	overall polarity reversal for the module,
107
 * 	polarity reversal for the port,
107
 * 	polarity reversal for the port,
108
 * 	and the state of the line reversal MWI indicator
108
 * 	and the state of the line reversal MWI indicator
109
 */
109
 */
110
#define POLARITY_XOR(fxs) \
110
#define POLARITY_XOR(fxs) \
111
	((reversepolarity != 0) ^ ((fxs)->reversepolarity != 0) ^ \
111
	((reversepolarity != 0) ^ ((fxs)->reversepolarity != 0) ^ \
112
	((fxs)->vmwi_linereverse != 0))
112
	((fxs)->vmwi_linereverse != 0) ^ (((fxs)->vmwisetting.vmwi_type & DAHDI_VMWI_HVAC) != 0))
113

    
   
113

   
114
static int reversepolarity = 0;
114
static int reversepolarity = 0;
115

    
   
115

   
116
static alpha  indirect_regs[] =
116
static alpha  indirect_regs[] =
117
{
117
{
118
{0,255,"DTMF_ROW_0_PEAK",0x55C2},
118
{0,255,"DTMF_ROW_0_PEAK",0x55C2},
119
{1,255,"DTMF_ROW_1_PEAK",0x51E6},
119
{1,255,"DTMF_ROW_1_PEAK",0x51E6},
120
{2,255,"DTMF_ROW2_PEAK",0x4B85},
120
{2,255,"DTMF_ROW2_PEAK",0x4B85},
121
{3,255,"DTMF_ROW3_PEAK",0x4937},
121
{3,255,"DTMF_ROW3_PEAK",0x4937},
122
{4,255,"DTMF_COL1_PEAK",0x3333},
122
{4,255,"DTMF_COL1_PEAK",0x3333},
123
{5,255,"DTMF_FWD_TWIST",0x0202},
123
{5,255,"DTMF_FWD_TWIST",0x0202},
124
{6,255,"DTMF_RVS_TWIST",0x0202},
124
{6,255,"DTMF_RVS_TWIST",0x0202},
125
{7,255,"DTMF_ROW_RATIO_TRES",0x0198},
125
{7,255,"DTMF_ROW_RATIO_TRES",0x0198},
126
{8,255,"DTMF_COL_RATIO_TRES",0x0198},
126
{8,255,"DTMF_COL_RATIO_TRES",0x0198},
127
{9,255,"DTMF_ROW_2ND_ARM",0x0611},
127
{9,255,"DTMF_ROW_2ND_ARM",0x0611},
128
{10,255,"DTMF_COL_2ND_ARM",0x0202},
128
{10,255,"DTMF_COL_2ND_ARM",0x0202},
129
{11,255,"DTMF_PWR_MIN_TRES",0x00E5},
129
{11,255,"DTMF_PWR_MIN_TRES",0x00E5},
130
{12,255,"DTMF_OT_LIM_TRES",0x0A1C},
130
{12,255,"DTMF_OT_LIM_TRES",0x0A1C},
131
{13,0,"OSC1_COEF",0x7B30},
131
{13,0,"OSC1_COEF",0x7B30},
132
{14,1,"OSC1X",0x0063},
132
{14,1,"OSC1X",0x0063},
133
{15,2,"OSC1Y",0x0000},
133
{15,2,"OSC1Y",0x0000},
134
{16,3,"OSC2_COEF",0x7870},
134
{16,3,"OSC2_COEF",0x7870},
135
{17,4,"OSC2X",0x007D},
135
{17,4,"OSC2X",0x007D},
136
{18,5,"OSC2Y",0x0000},
136
{18,5,"OSC2Y",0x0000},
137
{19,6,"RING_V_OFF",0x0000},
137
{19,6,"RING_V_OFF",0x0000},
138
{20,7,"RING_OSC",0x7EF0},
138
{20,7,"RING_OSC",0x7EF0},
139
{21,8,"RING_X",0x0160},
139
{21,8,"RING_X",0x0160},
140
{22,9,"RING_Y",0x0000},
140
{22,9,"RING_Y",0x0000},
141
{23,255,"PULSE_ENVEL",0x2000},
141
{23,255,"PULSE_ENVEL",0x2000},
142
{24,255,"PULSE_X",0x2000},
142
{24,255,"PULSE_X",0x2000},
143
{25,255,"PULSE_Y",0x0000},
143
{25,255,"PULSE_Y",0x0000},
144
//{26,13,"RECV_DIGITAL_GAIN",0x4000},	// playback volume set lower
144
//{26,13,"RECV_DIGITAL_GAIN",0x4000},	// playback volume set lower
145
{26,13,"RECV_DIGITAL_GAIN",0x2000},	// playback volume set lower
145
{26,13,"RECV_DIGITAL_GAIN",0x2000},	// playback volume set lower
146
{27,14,"XMIT_DIGITAL_GAIN",0x4000},
146
{27,14,"XMIT_DIGITAL_GAIN",0x4000},
147
//{27,14,"XMIT_DIGITAL_GAIN",0x2000},
147
//{27,14,"XMIT_DIGITAL_GAIN",0x2000},
148
{28,15,"LOOP_CLOSE_TRES",0x1000},
148
{28,15,"LOOP_CLOSE_TRES",0x1000},
149
{29,16,"RING_TRIP_TRES",0x3600},
149
{29,16,"RING_TRIP_TRES",0x3600},
150
{30,17,"COMMON_MIN_TRES",0x1000},
150
{30,17,"COMMON_MIN_TRES",0x1000},
151
{31,18,"COMMON_MAX_TRES",0x0200},
151
{31,18,"COMMON_MAX_TRES",0x0200},
152
{32,19,"PWR_ALARM_Q1Q2",0x07C0},
152
{32,19,"PWR_ALARM_Q1Q2",0x07C0},
153
{33,20,"PWR_ALARM_Q3Q4", 0x4C00 /* 0x2600 */},
153
{33,20,"PWR_ALARM_Q3Q4", 0x4C00 /* 0x2600 */},
154
{34,21,"PWR_ALARM_Q5Q6",0x1B80},
154
{34,21,"PWR_ALARM_Q5Q6",0x1B80},
155
{35,22,"LOOP_CLOSURE_FILTER",0x8000},
155
{35,22,"LOOP_CLOSURE_FILTER",0x8000},
156
{36,23,"RING_TRIP_FILTER",0x0320},
156
{36,23,"RING_TRIP_FILTER",0x0320},
157
{37,24,"TERM_LP_POLE_Q1Q2",0x008C},
157
{37,24,"TERM_LP_POLE_Q1Q2",0x008C},
158
{38,25,"TERM_LP_POLE_Q3Q4",0x0100},
158
{38,25,"TERM_LP_POLE_Q3Q4",0x0100},
159
{39,26,"TERM_LP_POLE_Q5Q6",0x0010},
159
{39,26,"TERM_LP_POLE_Q5Q6",0x0010},
160
{40,27,"CM_BIAS_RINGING",0x0C00},
160
{40,27,"CM_BIAS_RINGING",0x0C00},
161
{41,64,"DCDC_MIN_V",0x0C00},
161
{41,64,"DCDC_MIN_V",0x0C00},
162
{42,255,"DCDC_XTRA",0x1000},
162
{42,255,"DCDC_XTRA",0x1000},
163
{43,66,"LOOP_CLOSE_TRES_LOW",0x1000},
163
{43,66,"LOOP_CLOSE_TRES_LOW",0x1000},
164
};
164
};
165

    
   
165

   
166
/* names of HWEC modules */
166
/* names of HWEC modules */
167
static const char *vpmadt032_name = "VPMADT032";
167
static const char *vpmadt032_name = "VPMADT032";
168
static const char *noec_name = "NONE";
168
static const char *noec_name = "NONE";
169

    
   
169

   
170
/* Undefine to enable Power alarm / Transistor debug -- note: do not
170
/* Undefine to enable Power alarm / Transistor debug -- note: do not
171
   enable for normal operation! */
171
   enable for normal operation! */
172
/* #define PAQ_DEBUG */
172
/* #define PAQ_DEBUG */
173

    
   
173

   
174
#define DEBUG_CARD (1 << 0)
174
#define DEBUG_CARD (1 << 0)
175
#define DEBUG_ECHOCAN (1 << 1)
175
#define DEBUG_ECHOCAN (1 << 1)
176

    
   
176

   
177
#include "fxo_modes.h"
177
#include "fxo_modes.h"
178

    
   
178

   
179
struct wctdm_desc {
179
struct wctdm_desc {
180
	const char *name;
180
	const char *name;
181
	const int flags;
181
	const int flags;
182
	const int ports;
182
	const int ports;
183
};
183
};
184

    
   
184

   
185
static const struct wctdm_desc wctdm2400 = { "Wildcard TDM2400P", 0, 24 };
185
static const struct wctdm_desc wctdm2400 = { "Wildcard TDM2400P", 0, 24 };
186
static const struct wctdm_desc wctdm800 = { "Wildcard TDM800P", 0, 8 };
186
static const struct wctdm_desc wctdm800 = { "Wildcard TDM800P", 0, 8 };
187
static const struct wctdm_desc wctdm410 = { "Wildcard TDM410P", 0, 4 };
187
static const struct wctdm_desc wctdm410 = { "Wildcard TDM410P", 0, 4 };
188
static const struct wctdm_desc wcaex2400 = { "Wildcard AEX2400", FLAG_EXPRESS, 24 };
188
static const struct wctdm_desc wcaex2400 = { "Wildcard AEX2400", FLAG_EXPRESS, 24 };
189
static const struct wctdm_desc wcaex800 = { "Wildcard AEX800", FLAG_EXPRESS, 8 };
189
static const struct wctdm_desc wcaex800 = { "Wildcard AEX800", FLAG_EXPRESS, 8 };
190
static const struct wctdm_desc wcaex410 = { "Wildcard AEX410", FLAG_EXPRESS, 4 };
190
static const struct wctdm_desc wcaex410 = { "Wildcard AEX410", FLAG_EXPRESS, 4 };
191
static const struct wctdm_desc wcha80000 = { "HA8-0000", 0, 8 };
191
static const struct wctdm_desc wcha80000 = { "HA8-0000", 0, 8 };
192
static const struct wctdm_desc wchb80000 = { "HB8-0000", FLAG_EXPRESS, 8 };
192
static const struct wctdm_desc wchb80000 = { "HB8-0000", FLAG_EXPRESS, 8 };
193

    
   
193

   
194
/**
194
/**
195
 * Returns true if the card is one of the Hybrid Digital Analog Cards.
195
 * Returns true if the card is one of the Hybrid Digital Analog Cards.
196
 */
196
 */
197
static inline bool is_hx8(const struct wctdm *wc)
197
static inline bool is_hx8(const struct wctdm *wc)
198
{
198
{
199
	return (&wcha80000 == wc->desc) || (&wchb80000 == wc->desc);
199
	return (&wcha80000 == wc->desc) || (&wchb80000 == wc->desc);
200
}
200
}
201

    
   
201

   
202
struct wctdm *ifaces[WC_MAX_IFACES];
202
struct wctdm *ifaces[WC_MAX_IFACES];
203
DEFINE_SEMAPHORE(ifacelock);
203
DEFINE_SEMAPHORE(ifacelock);
204

    
   
204

   
205
static void wctdm_release(struct wctdm *wc);
205
static void wctdm_release(struct wctdm *wc);
206

    
   
206

   
207
static int fxovoltage = 0;
207
static int fxovoltage = 0;
208
static unsigned int battdebounce;
208
static unsigned int battdebounce;
209
static unsigned int battalarm;
209
static unsigned int battalarm;
210
static unsigned int battthresh;
210
static unsigned int battthresh;
211
static int debug = 0;
211
static int debug = 0;
212
#ifdef DEBUG
212
#ifdef DEBUG
213
static int robust = 0;
213
static int robust = 0;
214
static int digitalloopback;
214
static int digitalloopback;
215
#endif
215
#endif
216
static int lowpower = 0;
216
static int lowpower = 0;
217
static int boostringer = 0;
217
static int boostringer = 0;
218
static int fastringer = 0;
218
static int fastringer = 0;
219
static int _opermode = 0;
219
static int _opermode = 0;
220
static char *opermode = "FCC";
220
static char *opermode = "FCC";
221
static int fxshonormode = 0;
221
static int fxshonormode = 0;
222
static int alawoverride = 0;
222
static int alawoverride = 0;
223
static char *companding = "auto";
223
static char *companding = "auto";
224
static int fxotxgain = 0;
224
static int fxotxgain = 0;
225
static int fxorxgain = 0;
225
static int fxorxgain = 0;
226
static int fxstxgain = 0;
226
static int fxstxgain = 0;
227
static int fxsrxgain = 0;
227
static int fxsrxgain = 0;
228
static int nativebridge = 0;
228
static int nativebridge = 0;
229
static int ringdebounce = DEFAULT_RING_DEBOUNCE;
229
static int ringdebounce = DEFAULT_RING_DEBOUNCE;
230
static int fwringdetect = 0;
230
static int fwringdetect = 0;
231
static int latency = VOICEBUS_DEFAULT_LATENCY;
231
static int latency = VOICEBUS_DEFAULT_LATENCY;
232
static unsigned int max_latency = VOICEBUS_DEFAULT_MAXLATENCY;
232
static unsigned int max_latency = VOICEBUS_DEFAULT_MAXLATENCY;
233
static int forceload;
233
static int forceload;
234

    
   
234

   
235
#define MS_PER_HOOKCHECK	(1)
235
#define MS_PER_HOOKCHECK	(1)
236
#define NEONMWI_ON_DEBOUNCE	(100/MS_PER_HOOKCHECK)
236
#define NEONMWI_ON_DEBOUNCE	(100/MS_PER_HOOKCHECK)
237
static int neonmwi_monitor = 0; 	/* Note: this causes use of full wave ring detect */
237
static int neonmwi_monitor = 0; 	/* Note: this causes use of full wave ring detect */
238
static int neonmwi_level = 75;		/* neon mwi trip voltage */
238
static int neonmwi_level = 75;		/* neon mwi trip voltage */
239
static int neonmwi_envelope = 10;
239
static int neonmwi_envelope = 10;
240
static int neonmwi_offlimit = 16000;  /* Time in milliseconds the monitor is checked before saying no message is waiting */
240
static int neonmwi_offlimit = 16000;  /* Time in milliseconds the monitor is checked before saying no message is waiting */
241
static int neonmwi_offlimit_cycles;  /* Time in milliseconds the monitor is checked before saying no message is waiting */
241
static int neonmwi_offlimit_cycles;  /* Time in milliseconds the monitor is checked before saying no message is waiting */
242

    
   
242

   
243
static int vpmsupport = 1;
243
static int vpmsupport = 1;
244

    
   
244

   
245
static int vpmnlptype = DEFAULT_NLPTYPE;
245
static int vpmnlptype = DEFAULT_NLPTYPE;
246
static int vpmnlpthresh = DEFAULT_NLPTHRESH;
246
static int vpmnlpthresh = DEFAULT_NLPTHRESH;
247
static int vpmnlpmaxsupp = DEFAULT_NLPMAXSUPP;
247
static int vpmnlpmaxsupp = DEFAULT_NLPMAXSUPP;
248

    
   
248

   
249
static void echocan_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec);
249
static void echocan_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec);
250

    
   
250

   
251
static const struct dahdi_echocan_features vpm_ec_features = {
251
static const struct dahdi_echocan_features vpm_ec_features = {
252
	.NLP_automatic = 1,
252
	.NLP_automatic = 1,
253
	.CED_tx_detect = 1,
253
	.CED_tx_detect = 1,
254
	.CED_rx_detect = 1,
254
	.CED_rx_detect = 1,
255
};
255
};
256

    
   
256

   
257
static const struct dahdi_echocan_ops vpm_ec_ops = {
257
static const struct dahdi_echocan_ops vpm_ec_ops = {
258
	.echocan_free = echocan_free,
258
	.echocan_free = echocan_free,
259
};
259
};
260

    
   
260

   
261
static int
261
static int
262
wctdm_init_proslic(struct wctdm *wc, struct wctdm_module *const mod, int fast,
262
wctdm_init_proslic(struct wctdm *wc, struct wctdm_module *const mod, int fast,
263
		   int manual, int sane);
263
		   int manual, int sane);
264

    
   
264

   

    
   
265
static int wctdm_init_ring_generator_mode(struct wctdm *wc, struct wctdm_module *const mod);

    
   
266
static int wctdm_set_ring_generator_mode(struct wctdm *wc, struct wctdm_module *const mod, int mode);

    
   
267

   
265
static void set_offsets(struct wctdm_module *const mod, int altcs)
268
static void set_offsets(struct wctdm_module *const mod, int altcs)
266
{
269
{
267
	int card = mod->card;
270
	int card = mod->card;
268
	int bit;
271
	int bit;
269

    
   
272

   
270
	mod->subaddr = (altcs) ? 0 : (mod->card & 0x3);
273
	mod->subaddr = (altcs) ? 0 : (mod->card & 0x3);
271

    
   
274

   
272
	for (bit = 0; bit < ARRAY_SIZE(mod->offsets); ++bit) {
275
	for (bit = 0; bit < ARRAY_SIZE(mod->offsets); ++bit) {
273
		/* Let's add some trickery to make the TDM410 work */
276
		/* Let's add some trickery to make the TDM410 work */
274
		if (altcs == 3) {
277
		if (altcs == 3) {
275
			if (card == 2) {
278
			if (card == 2) {
276
				card = 4;
279
				card = 4;
277
				altcs = 0;
280
				altcs = 0;
278
			} else if (card == 3) {
281
			} else if (card == 3) {
279
				card = 5;
282
				card = 5;
280
				altcs = 2;
283
				altcs = 2;
281
			}
284
			}
282
		}
285
		}
283
		mod->offsets[bit] = ((((card & 0x3) * 3 + bit) * 7) +
286
		mod->offsets[bit] = ((((card & 0x3) * 3 + bit) * 7) +
284
					(card >> 2) + altcs +
287
					(card >> 2) + altcs +
285
					((altcs) ? -21 : 0));
288
					((altcs) ? -21 : 0));
286
	}
289
	}
287
}
290
}
288

    
   
291

   
289
static inline __attribute_const__ int
292
static inline __attribute_const__ int
290
CMD_BYTE(const struct wctdm_module *const mod, const int bit)
293
CMD_BYTE(const struct wctdm_module *const mod, const int bit)
291
{
294
{
292
	return mod->offsets[bit];
295
	return mod->offsets[bit];
293
}
296
}
294

    
   
297

   
295
static inline __attribute_const__ int VPM_CMD_BYTE(int timeslot, int bit)
298
static inline __attribute_const__ int VPM_CMD_BYTE(int timeslot, int bit)
296
{
299
{
297
	return ((((timeslot) & 0x3) * 3 + (bit)) * 7) + ((timeslot) >> 2);
300
	return ((((timeslot) & 0x3) * 3 + (bit)) * 7) + ((timeslot) >> 2);
298
}
301
}
299

    
   
302

   
300
typedef int (*bg_work_func_t)(struct wctdm *wc, unsigned long data);
303
typedef int (*bg_work_func_t)(struct wctdm *wc, unsigned long data);
301

    
   
304

   
302
struct bg {
305
struct bg {
303
	struct workqueue_struct *wq;
306
	struct workqueue_struct *wq;
304
	struct work_struct	work;
307
	struct work_struct	work;
305
	struct completion	complete;
308
	struct completion	complete;
306
	struct wctdm		*wc;
309
	struct wctdm		*wc;
307
	bg_work_func_t		fn;
310
	bg_work_func_t		fn;
308
	unsigned long		param;
311
	unsigned long		param;
309
	int			ret;
312
	int			ret;
310
};
313
};
311

    
   
314

   
312
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
315
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
313
static void bg_work_func(void *data)
316
static void bg_work_func(void *data)
314
{
317
{
315
	struct bg *bg = data;
318
	struct bg *bg = data;
316
#else
319
#else
317
static void bg_work_func(struct work_struct *work)
320
static void bg_work_func(struct work_struct *work)
318
{
321
{
319
	struct bg *bg = container_of(work, struct bg, work);
322
	struct bg *bg = container_of(work, struct bg, work);
320
#endif
323
#endif
321
	bg->ret = bg->fn(bg->wc, bg->param);
324
	bg->ret = bg->fn(bg->wc, bg->param);
322
	complete(&bg->complete);
325
	complete(&bg->complete);
323
}
326
}
324

    
   
327

   
325
/**
328
/**
326
 * bg_create - Call a function running in a background thread.
329
 * bg_create - Call a function running in a background thread.
327
 * @wc:		The board structure passed to fn
330
 * @wc:		The board structure passed to fn
328
 * @fn:		The function to run in it's own thread.
331
 * @fn:		The function to run in it's own thread.
329
 * @parma:	An extra parameter to pass to the fn.
332
 * @parma:	An extra parameter to pass to the fn.
330
 *
333
 *
331
 * Returns NULL if the thread could not be created, otherwise a pointer to be
334
 * Returns NULL if the thread could not be created, otherwise a pointer to be
332
 * passed to bg_join in order to get the return value.
335
 * passed to bg_join in order to get the return value.
333
 *
336
 *
334
 * The function 'fn' will be run in a new thread. The return value is the
337
 * The function 'fn' will be run in a new thread. The return value is the
335
 * return from the bg_join function.
338
 * return from the bg_join function.
336
 *
339
 *
337
 * This would probably be best served by concurrency managed workqueues before
340
 * This would probably be best served by concurrency managed workqueues before
338
 * merging, but this will at least work on the older kernels tht DAHDI
341
 * merging, but this will at least work on the older kernels tht DAHDI
339
 * supports.
342
 * supports.
340
 */
343
 */
341
static struct bg *
344
static struct bg *
342
bg_create(struct wctdm *wc, bg_work_func_t fn, unsigned long param)
345
bg_create(struct wctdm *wc, bg_work_func_t fn, unsigned long param)
343
{
346
{
344
	struct bg *bg;
347
	struct bg *bg;
345

    
   
348

   
346
	bg = kzalloc(sizeof(*bg), GFP_KERNEL);
349
	bg = kzalloc(sizeof(*bg), GFP_KERNEL);
347
	if (!bg)
350
	if (!bg)
348
		return NULL;
351
		return NULL;
349

    
   
352

   
350
	bg->wq = create_singlethread_workqueue("wctdm_bg");
353
	bg->wq = create_singlethread_workqueue("wctdm_bg");
351
	if (!bg->wq) {
354
	if (!bg->wq) {
352
		kfree(bg);
355
		kfree(bg);
353
		return NULL;
356
		return NULL;
354
	}
357
	}
355

    
   
358

   
356
	init_completion(&bg->complete);
359
	init_completion(&bg->complete);
357
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
360
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
358
	INIT_WORK(&bg->work, bg_work_func, bg);
361
	INIT_WORK(&bg->work, bg_work_func, bg);
359
#else
362
#else
360
	INIT_WORK(&bg->work, bg_work_func);
363
	INIT_WORK(&bg->work, bg_work_func);
361
#endif
364
#endif
362

    
   
365

   
363
	bg->wc = wc;
366
	bg->wc = wc;
364
	bg->fn = fn;
367
	bg->fn = fn;
365
	bg->param = param;
368
	bg->param = param;
366

    
   
369

   
367
	queue_work(bg->wq, &bg->work);
370
	queue_work(bg->wq, &bg->work);
368

    
   
371

   
369
	return bg;
372
	return bg;
370
}
373
}
371

    
   
374

   
372
/**
375
/**
373
 * bg_join - Wait for a background function to complete and get the result.
376
 * bg_join - Wait for a background function to complete and get the result.
374
 * @bg:		Pointer returned from the bg_create call.
377
 * @bg:		Pointer returned from the bg_create call.
375
 *
378
 *
376
 * Returns the result of the function passed to bg_create.
379
 * Returns the result of the function passed to bg_create.
377
 */
380
 */
378
static int bg_join(struct bg *bg)
381
static int bg_join(struct bg *bg)
379
{
382
{
380
	int ret = -ERESTARTSYS;
383
	int ret = -ERESTARTSYS;
381

    
   
384

   
382
	if (unlikely(!bg))
385
	if (unlikely(!bg))
383
		return -EINVAL;
386
		return -EINVAL;
384

    
   
387

   
385
	while (ret)
388
	while (ret)
386
		ret = wait_for_completion_interruptible(&bg->complete);
389
		ret = wait_for_completion_interruptible(&bg->complete);
387

    
   
390

   
388
	ret = bg->ret;
391
	ret = bg->ret;
389
	destroy_workqueue(bg->wq);
392
	destroy_workqueue(bg->wq);
390
	kfree(bg);
393
	kfree(bg);
391

    
   
394

   
392
	return ret;
395
	return ret;
393
}
396
}
394

    
   
397

   
395
static void
398
static void
396
setchanconfig_from_state(struct vpmadt032 *vpm, int channel,
399
setchanconfig_from_state(struct vpmadt032 *vpm, int channel,
397
			 GpakChannelConfig_t *chanconfig)
400
			 GpakChannelConfig_t *chanconfig)
398
{
401
{
399
	const struct vpmadt032_options *options;
402
	const struct vpmadt032_options *options;
400
	GpakEcanParms_t *p;
403
	GpakEcanParms_t *p;
401

    
   
404

   
402
	BUG_ON(!vpm);
405
	BUG_ON(!vpm);
403

    
   
406

   
404
	options = &vpm->options;
407
	options = &vpm->options;
405

    
   
408

   
406
	chanconfig->PcmInPortA = 3;
409
	chanconfig->PcmInPortA = 3;
407
	chanconfig->PcmInSlotA = channel;
410
	chanconfig->PcmInSlotA = channel;
408
	chanconfig->PcmOutPortA = SerialPortNull;
411
	chanconfig->PcmOutPortA = SerialPortNull;
409
	chanconfig->PcmOutSlotA = channel;
412
	chanconfig->PcmOutSlotA = channel;
410
	chanconfig->PcmInPortB = 2;
413
	chanconfig->PcmInPortB = 2;
411
	chanconfig->PcmInSlotB = channel;
414
	chanconfig->PcmInSlotB = channel;
412
	chanconfig->PcmOutPortB = 3;
415
	chanconfig->PcmOutPortB = 3;
413
	chanconfig->PcmOutSlotB = channel;
416
	chanconfig->PcmOutSlotB = channel;
414
	chanconfig->ToneTypesA = Null_tone;
417
	chanconfig->ToneTypesA = Null_tone;
415
	chanconfig->MuteToneA = Disabled;
418
	chanconfig->MuteToneA = Disabled;
416
	chanconfig->FaxCngDetA = Disabled;
419
	chanconfig->FaxCngDetA = Disabled;
417
	chanconfig->ToneTypesB = Null_tone;
420
	chanconfig->ToneTypesB = Null_tone;
418
	chanconfig->EcanEnableA = Enabled;
421
	chanconfig->EcanEnableA = Enabled;
419
	chanconfig->EcanEnableB = Disabled;
422
	chanconfig->EcanEnableB = Disabled;
420
	chanconfig->MuteToneB = Disabled;
423
	chanconfig->MuteToneB = Disabled;
421
	chanconfig->FaxCngDetB = Disabled;
424
	chanconfig->FaxCngDetB = Disabled;
422

    
   
425

   
423
	/* The software companding will be overridden on a channel by channel
426
	/* The software companding will be overridden on a channel by channel
424
	 * basis when the channel is enabled. */
427
	 * basis when the channel is enabled. */
425
	chanconfig->SoftwareCompand = cmpPCMU;
428
	chanconfig->SoftwareCompand = cmpPCMU;
426

    
   
429

   
427
	chanconfig->FrameRate = rate2ms;
430
	chanconfig->FrameRate = rate2ms;
428
	p = &chanconfig->EcanParametersA;
431
	p = &chanconfig->EcanParametersA;
429

    
   
432

   
430
	vpmadt032_get_default_parameters(p);
433
	vpmadt032_get_default_parameters(p);
431

    
   
434

   
432
	p->EcanNlpType = vpm->curecstate[channel].nlp_type;
435
	p->EcanNlpType = vpm->curecstate[channel].nlp_type;
433
	p->EcanNlpThreshold = vpm->curecstate[channel].nlp_threshold;
436
	p->EcanNlpThreshold = vpm->curecstate[channel].nlp_threshold;
434
	p->EcanNlpMaxSuppress = vpm->curecstate[channel].nlp_max_suppress;
437
	p->EcanNlpMaxSuppress = vpm->curecstate[channel].nlp_max_suppress;
435

    
   
438

   
436
	memcpy(&chanconfig->EcanParametersB,
439
	memcpy(&chanconfig->EcanParametersB,
437
		&chanconfig->EcanParametersA,
440
		&chanconfig->EcanParametersA,
438
		sizeof(chanconfig->EcanParametersB));
441
		sizeof(chanconfig->EcanParametersB));
439
}
442
}
440

    
   
443

   
441
struct vpmadt032_channel_setup {
444
struct vpmadt032_channel_setup {
442
	struct work_struct	work;
445
	struct work_struct	work;
443
	struct wctdm		*wc;
446
	struct wctdm		*wc;
444
};
447
};
445

    
   
448

   
446
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
449
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
447
static void vpm_setup_work_func(void *data)
450
static void vpm_setup_work_func(void *data)
448
{
451
{
449
	struct vpmadt032_channel_setup *setup = data;
452
	struct vpmadt032_channel_setup *setup = data;
450
#else
453
#else
451
static void vpm_setup_work_func(struct work_struct *work)
454
static void vpm_setup_work_func(struct work_struct *work)
452
{
455
{
453
	struct vpmadt032_channel_setup *setup =
456
	struct vpmadt032_channel_setup *setup =
454
		container_of(work, struct vpmadt032_channel_setup, work);
457
		container_of(work, struct vpmadt032_channel_setup, work);
455
#endif
458
#endif
456
	int i;
459
	int i;
457
	int res;
460
	int res;
458
	GpakChannelConfig_t chanconfig;
461
	GpakChannelConfig_t chanconfig;
459
	GPAK_ChannelConfigStat_t cstatus;
462
	GPAK_ChannelConfigStat_t cstatus;
460
	GPAK_AlgControlStat_t algstatus;
463
	GPAK_AlgControlStat_t algstatus;
461
	GpakPortConfig_t portconfig = {0};
464
	GpakPortConfig_t portconfig = {0};
462
	gpakConfigPortStatus_t configportstatus;
465
	gpakConfigPortStatus_t configportstatus;
463
	GPAK_PortConfigStat_t pstatus;
466
	GPAK_PortConfigStat_t pstatus;
464
	struct vpmadt032 *vpm;
467
	struct vpmadt032 *vpm;
465
	struct wctdm *const wc = setup->wc;
468
	struct wctdm *const wc = setup->wc;
466

    
   
469

   
467
	WARN_ON(!wc);
470
	WARN_ON(!wc);
468
	WARN_ON(!wc->vpmadt032);
471
	WARN_ON(!wc->vpmadt032);
469
	if (unlikely(!wc || !wc->vpmadt032))
472
	if (unlikely(!wc || !wc->vpmadt032))
470
		return;
473
		return;
471
	vpm = wc->vpmadt032;
474
	vpm = wc->vpmadt032;
472

    
   
475

   
473
	/* First Serial Port config */
476
	/* First Serial Port config */
474
	portconfig.SlotsSelect1 = SlotCfgNone;
477
	portconfig.SlotsSelect1 = SlotCfgNone;
475
	portconfig.FirstBlockNum1 = 0;
478
	portconfig.FirstBlockNum1 = 0;
476
	portconfig.FirstSlotMask1 = 0x0000;
479
	portconfig.FirstSlotMask1 = 0x0000;
477
	portconfig.SecBlockNum1 = 1;
480
	portconfig.SecBlockNum1 = 1;
478
	portconfig.SecSlotMask1 = 0x0000;
481
	portconfig.SecSlotMask1 = 0x0000;
479
	portconfig.SerialWordSize1 = SerWordSize8;
482
	portconfig.SerialWordSize1 = SerWordSize8;
480
	portconfig.CompandingMode1 = cmpNone;
483
	portconfig.CompandingMode1 = cmpNone;
481
	portconfig.TxFrameSyncPolarity1 = FrameSyncActHigh;
484
	portconfig.TxFrameSyncPolarity1 = FrameSyncActHigh;
482
	portconfig.RxFrameSyncPolarity1 = FrameSyncActHigh;
485
	portconfig.RxFrameSyncPolarity1 = FrameSyncActHigh;
483
	portconfig.TxClockPolarity1 = SerClockActHigh;
486
	portconfig.TxClockPolarity1 = SerClockActHigh;
484
	portconfig.RxClockPolarity1 = SerClockActHigh;
487
	portconfig.RxClockPolarity1 = SerClockActHigh;
485
	portconfig.TxDataDelay1 = DataDelay0;
488
	portconfig.TxDataDelay1 = DataDelay0;
486
	portconfig.RxDataDelay1 = DataDelay0;
489
	portconfig.RxDataDelay1 = DataDelay0;
487
	portconfig.DxDelay1 = Disabled;
490
	portconfig.DxDelay1 = Disabled;
488
	portconfig.ThirdSlotMask1 = 0x0000;
491
	portconfig.ThirdSlotMask1 = 0x0000;
489
	portconfig.FouthSlotMask1 = 0x0000;
492
	portconfig.FouthSlotMask1 = 0x0000;
490
	portconfig.FifthSlotMask1 = 0x0000;
493
	portconfig.FifthSlotMask1 = 0x0000;
491
	portconfig.SixthSlotMask1 = 0x0000;
494
	portconfig.SixthSlotMask1 = 0x0000;
492
	portconfig.SevenSlotMask1 = 0x0000;
495
	portconfig.SevenSlotMask1 = 0x0000;
493
	portconfig.EightSlotMask1 = 0x0000;
496
	portconfig.EightSlotMask1 = 0x0000;
494

    
   
497

   
495
	/* Second Serial Port config */
498
	/* Second Serial Port config */
496
	portconfig.SlotsSelect2 = SlotCfg2Groups;
499
	portconfig.SlotsSelect2 = SlotCfg2Groups;
497
	portconfig.FirstBlockNum2 = 0;
500
	portconfig.FirstBlockNum2 = 0;
498
	portconfig.FirstSlotMask2 = 0xffff;
501
	portconfig.FirstSlotMask2 = 0xffff;
499
	portconfig.SecBlockNum2 = 1;
502
	portconfig.SecBlockNum2 = 1;
500
	portconfig.SecSlotMask2 = 0xffff;
503
	portconfig.SecSlotMask2 = 0xffff;
501
	portconfig.SerialWordSize2 = SerWordSize8;
504
	portconfig.SerialWordSize2 = SerWordSize8;
502
	portconfig.CompandingMode2 = cmpNone;
505
	portconfig.CompandingMode2 = cmpNone;
503
	portconfig.TxFrameSyncPolarity2 = FrameSyncActHigh;
506
	portconfig.TxFrameSyncPolarity2 = FrameSyncActHigh;
504
	portconfig.RxFrameSyncPolarity2 = FrameSyncActHigh;
507
	portconfig.RxFrameSyncPolarity2 = FrameSyncActHigh;
505
	portconfig.TxClockPolarity2 = SerClockActHigh;
508
	portconfig.TxClockPolarity2 = SerClockActHigh;
506
	portconfig.RxClockPolarity2 = SerClockActLow;
509
	portconfig.RxClockPolarity2 = SerClockActLow;
507
	portconfig.TxDataDelay2 = DataDelay0;
510
	portconfig.TxDataDelay2 = DataDelay0;
508
	portconfig.RxDataDelay2 = DataDelay0;
511
	portconfig.RxDataDelay2 = DataDelay0;
509
	portconfig.DxDelay2 = Disabled;
512
	portconfig.DxDelay2 = Disabled;
510
	portconfig.ThirdSlotMask2 = 0x0000;
513
	portconfig.ThirdSlotMask2 = 0x0000;
511
	portconfig.FouthSlotMask2 = 0x0000;
514
	portconfig.FouthSlotMask2 = 0x0000;
512
	portconfig.FifthSlotMask2 = 0x0000;
515
	portconfig.FifthSlotMask2 = 0x0000;
513
	portconfig.SixthSlotMask2 = 0x0000;
516
	portconfig.SixthSlotMask2 = 0x0000;
514
	portconfig.SevenSlotMask2 = 0x0000;
517
	portconfig.SevenSlotMask2 = 0x0000;
515
	portconfig.EightSlotMask2 = 0x0000;
518
	portconfig.EightSlotMask2 = 0x0000;
516

    
   
519

   
517
	/* Third Serial Port Config */
520
	/* Third Serial Port Config */
518
	portconfig.SlotsSelect3 = SlotCfg2Groups;
521
	portconfig.SlotsSelect3 = SlotCfg2Groups;
519
	portconfig.FirstBlockNum3 = 0;
522
	portconfig.FirstBlockNum3 = 0;
520
	portconfig.FirstSlotMask3 = 0xffff;
523
	portconfig.FirstSlotMask3 = 0xffff;
521
	portconfig.SecBlockNum3 = 1;
524
	portconfig.SecBlockNum3 = 1;
522
	portconfig.SecSlotMask3 = 0xffff;
525
	portconfig.SecSlotMask3 = 0xffff;
523
	portconfig.SerialWordSize3 = SerWordSize8;
526
	portconfig.SerialWordSize3 = SerWordSize8;
524
	portconfig.CompandingMode3 = cmpNone;
527
	portconfig.CompandingMode3 = cmpNone;
525
	portconfig.TxFrameSyncPolarity3 = FrameSyncActHigh;
528
	portconfig.TxFrameSyncPolarity3 = FrameSyncActHigh;
526
	portconfig.RxFrameSyncPolarity3 = FrameSyncActHigh;
529
	portconfig.RxFrameSyncPolarity3 = FrameSyncActHigh;
527
	portconfig.TxClockPolarity3 = SerClockActHigh;
530
	portconfig.TxClockPolarity3 = SerClockActHigh;
528
	portconfig.RxClockPolarity3 = SerClockActLow;
531
	portconfig.RxClockPolarity3 = SerClockActLow;
529
	portconfig.TxDataDelay3 = DataDelay0;
532
	portconfig.TxDataDelay3 = DataDelay0;
530
	portconfig.RxDataDelay3 = DataDelay0;
533
	portconfig.RxDataDelay3 = DataDelay0;
531
	portconfig.DxDelay3 = Disabled;
534
	portconfig.DxDelay3 = Disabled;
532
	portconfig.ThirdSlotMask3 = 0x0000;
535
	portconfig.ThirdSlotMask3 = 0x0000;
533
	portconfig.FouthSlotMask3 = 0x0000;
536
	portconfig.FouthSlotMask3 = 0x0000;
534
	portconfig.FifthSlotMask3 = 0x0000;
537
	portconfig.FifthSlotMask3 = 0x0000;
535
	portconfig.SixthSlotMask3 = 0x0000;
538
	portconfig.SixthSlotMask3 = 0x0000;
536
	portconfig.SevenSlotMask3 = 0x0000;
539
	portconfig.SevenSlotMask3 = 0x0000;
537
	portconfig.EightSlotMask3 = 0x0000;
540
	portconfig.EightSlotMask3 = 0x0000;
538

    
   
541

   
539
	if ((configportstatus = gpakConfigurePorts(vpm->dspid, &portconfig, &pstatus))) {
542
	if ((configportstatus = gpakConfigurePorts(vpm->dspid, &portconfig, &pstatus))) {
540
		dev_notice(&wc->vb.pdev->dev, "Configuration of ports failed (%d)!\n", configportstatus);
543
		dev_notice(&wc->vb.pdev->dev, "Configuration of ports failed (%d)!\n", configportstatus);
541
		return;
544
		return;
542
	} else {
545
	} else {
543
		if (vpm->options.debug & DEBUG_ECHOCAN)
546
		if (vpm->options.debug & DEBUG_ECHOCAN)
544
			dev_info(&wc->vb.pdev->dev, "Configured McBSP ports successfully\n");
547
			dev_info(&wc->vb.pdev->dev, "Configured McBSP ports successfully\n");
545
	}
548
	}
546

    
   
549

   
547
	if ((res = gpakPingDsp(vpm->dspid, &vpm->version))) {
550
	if ((res = gpakPingDsp(vpm->dspid, &vpm->version))) {
548
		dev_notice(&wc->vb.pdev->dev, "Error pinging DSP (%d)\n", res);
551
		dev_notice(&wc->vb.pdev->dev, "Error pinging DSP (%d)\n", res);
549
		return;
552
		return;
550
	}
553
	}
551

    
   
554

   
552
	for (i = 0; i < vpm->options.channels; ++i) {
555
	for (i = 0; i < vpm->options.channels; ++i) {
553
		vpm->curecstate[i].tap_length = 0;
556
		vpm->curecstate[i].tap_length = 0;
554
		vpm->curecstate[i].nlp_type = vpm->options.vpmnlptype;
557
		vpm->curecstate[i].nlp_type = vpm->options.vpmnlptype;
555
		vpm->curecstate[i].nlp_threshold = vpm->options.vpmnlpthresh;
558
		vpm->curecstate[i].nlp_threshold = vpm->options.vpmnlpthresh;
556
		vpm->curecstate[i].nlp_max_suppress =
559
		vpm->curecstate[i].nlp_max_suppress =
557
						vpm->options.vpmnlpmaxsupp;
560
						vpm->options.vpmnlpmaxsupp;
558
		vpm->curecstate[i].companding = ADT_COMP_ULAW;
561
		vpm->curecstate[i].companding = ADT_COMP_ULAW;
559
		vpm->setchanconfig_from_state(vpm, i, &chanconfig);
562
		vpm->setchanconfig_from_state(vpm, i, &chanconfig);
560

    
   
563

   
561
		res = gpakConfigureChannel(vpm->dspid, i, tdmToTdm,
564
		res = gpakConfigureChannel(vpm->dspid, i, tdmToTdm,
562
					   &chanconfig, &cstatus);
565
					   &chanconfig, &cstatus);
563
		if (res) {
566
		if (res) {
564
			dev_notice(&wc->vb.pdev->dev,
567
			dev_notice(&wc->vb.pdev->dev,
565
				   "Unable to configure channel #%d (%d)",
568
				   "Unable to configure channel #%d (%d)",
566
				   i, res);
569
				   i, res);
567
			if (res == 1)
570
			if (res == 1)
568
				printk(KERN_CONT ", reason %d", cstatus);
571
				printk(KERN_CONT ", reason %d", cstatus);
569
			printk(KERN_CONT "\n");
572
			printk(KERN_CONT "\n");
570
			goto exit;
573
			goto exit;
571
		}
574
		}
572

    
   
575

   
573
		res = gpakAlgControl(vpm->dspid, i, BypassEcanA, &algstatus);
576
		res = gpakAlgControl(vpm->dspid, i, BypassEcanA, &algstatus);
574
		if (res) {
577
		if (res) {
575
			dev_notice(&wc->vb.pdev->dev,
578
			dev_notice(&wc->vb.pdev->dev,
576
				   "Unable to disable echo can on channel %d "
579
				   "Unable to disable echo can on channel %d "
577
				   "(reason %d:%d)\n", i + 1, res, algstatus);
580
				   "(reason %d:%d)\n", i + 1, res, algstatus);
578
			goto exit;
581
			goto exit;
579
		}
582
		}
580

    
   
583

   
581
		res = gpakAlgControl(vpm->dspid, i,
584
		res = gpakAlgControl(vpm->dspid, i,
582
				     BypassSwCompanding, &algstatus);
585
				     BypassSwCompanding, &algstatus);
583
		if (res) {
586
		if (res) {
584
			dev_notice(&wc->vb.pdev->dev,
587
			dev_notice(&wc->vb.pdev->dev,
585
				   "Unable to disable echo can on channel %d "
588
				   "Unable to disable echo can on channel %d "
586
				   "(reason %d:%d)\n", i + 1, res, algstatus);
589
				   "(reason %d:%d)\n", i + 1, res, algstatus);
587
			goto exit;
590
			goto exit;
588
		}
591
		}
589
	}
592
	}
590

    
   
593

   
591
	res = gpakPingDsp(vpm->dspid, &vpm->version);
594
	res = gpakPingDsp(vpm->dspid, &vpm->version);
592
	if (res) {
595
	if (res) {
593
		dev_notice(&wc->vb.pdev->dev, "Error pinging DSP (%d)\n", res);
596
		dev_notice(&wc->vb.pdev->dev, "Error pinging DSP (%d)\n", res);
594
		goto exit;
597
		goto exit;
595
	}
598
	}
596

    
   
599

   
597
	set_bit(VPM150M_ACTIVE, &vpm->control);
600
	set_bit(VPM150M_ACTIVE, &vpm->control);
598

    
   
601

   
599
exit:
602
exit:
600
	kfree(setup);
603
	kfree(setup);
601
}
604
}
602

    
   
605

   
603
static int config_vpmadt032(struct vpmadt032 *vpm, struct wctdm *wc)
606
static int config_vpmadt032(struct vpmadt032 *vpm, struct wctdm *wc)
604
{
607
{
605
	struct vpmadt032_channel_setup *setup;
608
	struct vpmadt032_channel_setup *setup;
606

    
   
609

   
607
	/* Because the channel configuration can take such a long time, let's
610
	/* Because the channel configuration can take such a long time, let's
608
	 * move this out onto the VPM workqueue so the system can proceeded
611
	 * move this out onto the VPM workqueue so the system can proceeded
609
	 * with startup. */
612
	 * with startup. */
610

    
   
613

   
611
	setup = kzalloc(sizeof(*setup), GFP_KERNEL);
614
	setup = kzalloc(sizeof(*setup), GFP_KERNEL);
612
	if (!setup)
615
	if (!setup)
613
		return -ENOMEM;
616
		return -ENOMEM;
614

    
   
617

   
615
	setup->wc = wc;
618
	setup->wc = wc;
616

    
   
619

   
617
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
620
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
618
	INIT_WORK(&setup->work, vpm_setup_work_func, setup);
621
	INIT_WORK(&setup->work, vpm_setup_work_func, setup);
619
#else
622
#else
620
	INIT_WORK(&setup->work, vpm_setup_work_func);
623
	INIT_WORK(&setup->work, vpm_setup_work_func);
621
#endif
624
#endif
622

    
   
625

   
623
	queue_work(vpm->wq, &setup->work);
626
	queue_work(vpm->wq, &setup->work);
624

    
   
627

   
625
	return 0;
628
	return 0;
626
}
629
}
627

    
   
630

   
628
/**
631
/**
629
 * is_good_frame() - Whether the SFRAME received was one sent.
632
 * is_good_frame() - Whether the SFRAME received was one sent.
630
 *
633
 *
631
 */
634
 */
632
static inline bool is_good_frame(const u8 *sframe)
635
static inline bool is_good_frame(const u8 *sframe)
633
{
636
{
634
        const u8 a = sframe[0*(EFRAME_SIZE+EFRAME_GAP) + (EFRAME_SIZE+1)];
637
        const u8 a = sframe[0*(EFRAME_SIZE+EFRAME_GAP) + (EFRAME_SIZE+1)];
635
        const u8 b = sframe[1*(EFRAME_SIZE+EFRAME_GAP) + (EFRAME_SIZE+1)];
638
        const u8 b = sframe[1*(EFRAME_SIZE+EFRAME_GAP) + (EFRAME_SIZE+1)];
636
        return a != b;
639
        return a != b;
637
}
640
}
638

    
   
641

   
639
static void cmd_dequeue_vpmadt032(struct wctdm *wc, u8 *eframe)
642
static void cmd_dequeue_vpmadt032(struct wctdm *wc, u8 *eframe)
640
{
643
{
641
	struct vpmadt032_cmd *curcmd = NULL;
644
	struct vpmadt032_cmd *curcmd = NULL;
642
	struct vpmadt032 *vpmadt032 = wc->vpmadt032;
645
	struct vpmadt032 *vpmadt032 = wc->vpmadt032;
643
	int x;
646
	int x;
644
	unsigned char leds = ~((wc->intcount / 1000) % 8) & 0x7;
647
	unsigned char leds = ~((wc->intcount / 1000) % 8) & 0x7;
645

    
   
648

   
646
	/* Skip audio */
649
	/* Skip audio */
647
	eframe += 24;
650
	eframe += 24;
648

    
   
651

   
649
	if (test_bit(VPM150M_HPIRESET, &vpmadt032->control)) {
652
	if (test_bit(VPM150M_HPIRESET, &vpmadt032->control)) {
650
		if (debug & DEBUG_ECHOCAN)
653
		if (debug & DEBUG_ECHOCAN)
651
			dev_info(&wc->vb.pdev->dev, "HW Resetting VPMADT032...\n");
654
			dev_info(&wc->vb.pdev->dev, "HW Resetting VPMADT032...\n");
652
		for (x = 24; x < 28; x++) {
655
		for (x = 24; x < 28; x++) {
653
			if (x == 24) {
656
			if (x == 24) {
654
				if (test_and_clear_bit(VPM150M_HPIRESET,
657
				if (test_and_clear_bit(VPM150M_HPIRESET,
655
						       &vpmadt032->control)) {
658
						       &vpmadt032->control)) {
656
					eframe[VPM_CMD_BYTE(x, 0)] = 0x0b;
659
					eframe[VPM_CMD_BYTE(x, 0)] = 0x0b;
657
				} else {
660
				} else {
658
					eframe[VPM_CMD_BYTE(x, 0)] = leds;
661
					eframe[VPM_CMD_BYTE(x, 0)] = leds;
659
				}
662
				}
660
			} else {
663
			} else {
661
				eframe[VPM_CMD_BYTE(x, 0)] = leds;
664
				eframe[VPM_CMD_BYTE(x, 0)] = leds;
662
			}
665
			}
663
			eframe[VPM_CMD_BYTE(x, 1)] = 0;
666
			eframe[VPM_CMD_BYTE(x, 1)] = 0;
664
			eframe[VPM_CMD_BYTE(x, 2)] = 0x00;
667
			eframe[VPM_CMD_BYTE(x, 2)] = 0x00;
665
		}
668
		}
666
		return;
669
		return;
667
	}
670
	}
668

    
   
671

   
669
	if ((curcmd = vpmadt032_get_ready_cmd(vpmadt032))) {
672
	if ((curcmd = vpmadt032_get_ready_cmd(vpmadt032))) {
670
		curcmd->txident = wc->txident;
673
		curcmd->txident = wc->txident;
671
#if 0
674
#if 0
672
		// if (printk_ratelimit()) 
675
		// if (printk_ratelimit()) 
673
			dev_info(&wc->vb.pdev->dev, "Transmitting txident = %d, desc = 0x%x, addr = 0x%x, data = 0x%x\n", curcmd->txident, curcmd->desc, curcmd->address, curcmd->data);
676
			dev_info(&wc->vb.pdev->dev, "Transmitting txident = %d, desc = 0x%x, addr = 0x%x, data = 0x%x\n", curcmd->txident, curcmd->desc, curcmd->address, curcmd->data);
674
#endif
677
#endif
675
		if (curcmd->desc & __VPM150M_RWPAGE) {
678
		if (curcmd->desc & __VPM150M_RWPAGE) {
676
			/* Set CTRL access to page*/
679
			/* Set CTRL access to page*/
677
			eframe[VPM_CMD_BYTE(24, 0)] = (0x8 << 4);
680
			eframe[VPM_CMD_BYTE(24, 0)] = (0x8 << 4);
678
			eframe[VPM_CMD_BYTE(24, 1)] = 0;
681
			eframe[VPM_CMD_BYTE(24, 1)] = 0;
679
			eframe[VPM_CMD_BYTE(24, 2)] = 0x20;
682
			eframe[VPM_CMD_BYTE(24, 2)] = 0x20;
680

    
   
683

   
681
			/* Do a page write */
684
			/* Do a page write */
682
			if (curcmd->desc & __VPM150M_WR)
685
			if (curcmd->desc & __VPM150M_WR)
683
				eframe[VPM_CMD_BYTE(25, 0)] = ((0x8 | 0x4) << 4);
686
				eframe[VPM_CMD_BYTE(25, 0)] = ((0x8 | 0x4) << 4);
684
			else
687
			else
685
				eframe[VPM_CMD_BYTE(25, 0)] = ((0x8 | 0x4 | 0x1) << 4);
688
				eframe[VPM_CMD_BYTE(25, 0)] = ((0x8 | 0x4 | 0x1) << 4);
686
			eframe[VPM_CMD_BYTE(25, 1)] = 0;
689
			eframe[VPM_CMD_BYTE(25, 1)] = 0;
687
			if (curcmd->desc & __VPM150M_WR)
690
			if (curcmd->desc & __VPM150M_WR)
688
				eframe[VPM_CMD_BYTE(25, 2)] = curcmd->data & 0xf;
691
				eframe[VPM_CMD_BYTE(25, 2)] = curcmd->data & 0xf;
689
			else
692
			else
690
				eframe[VPM_CMD_BYTE(25, 2)] = 0;
693
				eframe[VPM_CMD_BYTE(25, 2)] = 0;
691

    
   
694

   
692
			/* Clear XADD */
695
			/* Clear XADD */
693
			eframe[VPM_CMD_BYTE(26, 0)] = (0x8 << 4);
696
			eframe[VPM_CMD_BYTE(26, 0)] = (0x8 << 4);
694
			eframe[VPM_CMD_BYTE(26, 1)] = 0;
697
			eframe[VPM_CMD_BYTE(26, 1)] = 0;
695
			eframe[VPM_CMD_BYTE(26, 2)] = 0;
698
			eframe[VPM_CMD_BYTE(26, 2)] = 0;
696

    
   
699

   
697
			/* Fill in to buffer to size */
700
			/* Fill in to buffer to size */
698
			eframe[VPM_CMD_BYTE(27, 0)] = 0;
701
			eframe[VPM_CMD_BYTE(27, 0)] = 0;
699
			eframe[VPM_CMD_BYTE(27, 1)] = 0;
702
			eframe[VPM_CMD_BYTE(27, 1)] = 0;
700
			eframe[VPM_CMD_BYTE(27, 2)] = 0;
703
			eframe[VPM_CMD_BYTE(27, 2)] = 0;
701

    
   
704

   
702
		} else {
705
		} else {
703
			/* Set address */
706
			/* Set address */
704
			eframe[VPM_CMD_BYTE(24, 0)] = ((0x8 | 0x4) << 4);
707
			eframe[VPM_CMD_BYTE(24, 0)] = ((0x8 | 0x4) << 4);
705
			eframe[VPM_CMD_BYTE(24, 1)] = (curcmd->address >> 8) & 0xff;
708
			eframe[VPM_CMD_BYTE(24, 1)] = (curcmd->address >> 8) & 0xff;
706
			eframe[VPM_CMD_BYTE(24, 2)] = curcmd->address & 0xff;
709
			eframe[VPM_CMD_BYTE(24, 2)] = curcmd->address & 0xff;
707

    
   
710

   
708
			/* Send/Get our data */
711
			/* Send/Get our data */
709
			eframe[VPM_CMD_BYTE(25, 0)] = (curcmd->desc & __VPM150M_WR) ?
712
			eframe[VPM_CMD_BYTE(25, 0)] = (curcmd->desc & __VPM150M_WR) ?
710
				((0x8 | (0x3 << 1)) << 4) : ((0x8 | (0x3 << 1) | 0x1) << 4);
713
				((0x8 | (0x3 << 1)) << 4) : ((0x8 | (0x3 << 1) | 0x1) << 4);
711
			eframe[VPM_CMD_BYTE(25, 1)] = (curcmd->data >> 8) & 0xff;
714
			eframe[VPM_CMD_BYTE(25, 1)] = (curcmd->data >> 8) & 0xff;
712
			eframe[VPM_CMD_BYTE(25, 2)] = curcmd->data & 0xff;
715
			eframe[VPM_CMD_BYTE(25, 2)] = curcmd->data & 0xff;
713
			
716
			
714
			eframe[VPM_CMD_BYTE(26, 0)] = 0;
717
			eframe[VPM_CMD_BYTE(26, 0)] = 0;
715
			eframe[VPM_CMD_BYTE(26, 1)] = 0;
718
			eframe[VPM_CMD_BYTE(26, 1)] = 0;
716
			eframe[VPM_CMD_BYTE(26, 2)] = 0;
719
			eframe[VPM_CMD_BYTE(26, 2)] = 0;
717

    
   
720

   
718
			/* Fill in the rest */
721
			/* Fill in the rest */
719
			eframe[VPM_CMD_BYTE(27, 0)] = 0;
722
			eframe[VPM_CMD_BYTE(27, 0)] = 0;
720
			eframe[VPM_CMD_BYTE(27, 1)] = 0;
723
			eframe[VPM_CMD_BYTE(27, 1)] = 0;
721
			eframe[VPM_CMD_BYTE(27, 2)] = 0;
724
			eframe[VPM_CMD_BYTE(27, 2)] = 0;
722
		}
725
		}
723
	} else if (test_and_clear_bit(VPM150M_SWRESET, &vpmadt032->control)) {
726
	} else if (test_and_clear_bit(VPM150M_SWRESET, &vpmadt032->control)) {
724
		for (x = 24; x < 28; x++) {
727
		for (x = 24; x < 28; x++) {
725
			if (x == 24)
728
			if (x == 24)
726
				eframe[VPM_CMD_BYTE(x, 0)] = (0x8 << 4);
729
				eframe[VPM_CMD_BYTE(x, 0)] = (0x8 << 4);
727
			else
730
			else
728
				eframe[VPM_CMD_BYTE(x, 0)] = 0x00;
731
				eframe[VPM_CMD_BYTE(x, 0)] = 0x00;
729
			eframe[VPM_CMD_BYTE(x, 1)] = 0;
732
			eframe[VPM_CMD_BYTE(x, 1)] = 0;
730
			if (x == 24)
733
			if (x == 24)
731
				eframe[VPM_CMD_BYTE(x, 2)] = 0x01;
734
				eframe[VPM_CMD_BYTE(x, 2)] = 0x01;
732
			else
735
			else
733
				eframe[VPM_CMD_BYTE(x, 2)] = 0x00;
736
				eframe[VPM_CMD_BYTE(x, 2)] = 0x00;
734
		}
737
		}
735
	} else {
738
	} else {
736
		for (x = 24; x < 28; x++) {
739
		for (x = 24; x < 28; x++) {
737
			eframe[VPM_CMD_BYTE(x, 0)] = 0x00;
740
			eframe[VPM_CMD_BYTE(x, 0)] = 0x00;
738
			eframe[VPM_CMD_BYTE(x, 1)] = 0x00;
741
			eframe[VPM_CMD_BYTE(x, 1)] = 0x00;
739
			eframe[VPM_CMD_BYTE(x, 2)] = 0x00;
742
			eframe[VPM_CMD_BYTE(x, 2)] = 0x00;
740
		}
743
		}
741
	}
744
	}
742

    
   
745

   
743
	/* Add our leds in */
746
	/* Add our leds in */
744
	for (x = 24; x < 28; x++) {
747
	for (x = 24; x < 28; x++) {
745
		eframe[VPM_CMD_BYTE(x, 0)] |= leds;
748
		eframe[VPM_CMD_BYTE(x, 0)] |= leds;
746
	}
749
	}
747
}
750
}
748

    
   
751

   
749
/* Call with wc->reglock held and local interrupts disabled */
752
/* Call with wc->reglock held and local interrupts disabled */
750
static void _cmd_dequeue(struct wctdm *wc, u8 *eframe, int card, int pos)
753
static void _cmd_dequeue(struct wctdm *wc, u8 *eframe, int card, int pos)
751
{
754
{
752
	struct wctdm_module *const mod = &wc->mods[card];
755
	struct wctdm_module *const mod = &wc->mods[card];
753
	unsigned int curcmd=0;
756
	unsigned int curcmd=0;
754

    
   
757

   
755
	/* QRV only use commands relating to the first channel */
758
	/* QRV only use commands relating to the first channel */
756
	if ((card & 0x03) && (mod->type == QRV))
759
	if ((card & 0x03) && (mod->type == QRV))
757
		return;
760
		return;
758

    
   
761

   
759
	/* Skip audio */
762
	/* Skip audio */
760
	eframe += 24;
763
	eframe += 24;
761
	/* Search for something waiting to transmit */
764
	/* Search for something waiting to transmit */
762
	if (pos) {
765
	if (pos) {
763
		if (!list_empty(&mod->pending_cmds)) {
766
		if (!list_empty(&mod->pending_cmds)) {
764
			struct wctdm_cmd *const cmd =
767
			struct wctdm_cmd *const cmd =
765
				list_entry(mod->pending_cmds.next,
768
				list_entry(mod->pending_cmds.next,
766
					   struct wctdm_cmd, node);
769
					   struct wctdm_cmd, node);
767
			curcmd = cmd->cmd;
770
			curcmd = cmd->cmd;
768
			cmd->ident = wc->txident;
771
			cmd->ident = wc->txident;
769
			list_move_tail(&cmd->node, &mod->active_cmds);
772
			list_move_tail(&cmd->node, &mod->active_cmds);
770
		}
773
		}
771
	}
774
	}
772

    
   
775

   
773
	if (!curcmd) {
776
	if (!curcmd) {
774
		/* If nothing else, use filler */
777
		/* If nothing else, use filler */
775
		switch (mod->type) {
778
		switch (mod->type) {
776
		case FXS:
779
		case FXS:
777
			curcmd = CMD_RD(LINE_STATE);
780
			curcmd = CMD_RD(LINE_STATE);
778
			break;
781
			break;
779
		case FXO:
782
		case FXO:
780
			curcmd = CMD_RD(12);
783
			curcmd = CMD_RD(12);
781
			break;
784
			break;
782
		case BRI:
785
		case BRI:
783
			curcmd = 0x101010;
786
			curcmd = 0x101010;
784
			break;
787
			break;
785
		case QRV:
788
		case QRV:
786
			curcmd = CMD_RD(3);
789
			curcmd = CMD_RD(3);
787
			break;
790
			break;
788
		default:
791
		default:
789
			break;
792
			break;
790
		}
793
		}
791
	}
794
	}
792

    
   
795

   
793
	switch (mod->type) {
796
	switch (mod->type) {
794
	case FXS:
797
	case FXS:
795
		eframe[CMD_BYTE(mod, 0)] = (1 << (mod->subaddr));
798
		eframe[CMD_BYTE(mod, 0)] = (1 << (mod->subaddr));
796
		if (curcmd & __CMD_WR)
799
		if (curcmd & __CMD_WR)
797
			eframe[CMD_BYTE(mod, 1)] = (curcmd >> 8) & 0x7f;
800
			eframe[CMD_BYTE(mod, 1)] = (curcmd >> 8) & 0x7f;
798
		else
801
		else
799
			eframe[CMD_BYTE(mod, 1)] = 0x80 | ((curcmd >> 8) & 0x7f);
802
			eframe[CMD_BYTE(mod, 1)] = 0x80 | ((curcmd >> 8) & 0x7f);
800
		eframe[CMD_BYTE(mod, 2)] = curcmd & 0xff;
803
		eframe[CMD_BYTE(mod, 2)] = curcmd & 0xff;
801
		break;
804
		break;
802

    
   
805

   
803
	case FXO:
806
	case FXO:
804
	{
807
	{
805
		static const int ADDRS[4] = {0x00, 0x08, 0x04, 0x0c};
808
		static const int ADDRS[4] = {0x00, 0x08, 0x04, 0x0c};
806
		if (curcmd & __CMD_WR)
809
		if (curcmd & __CMD_WR)
807
			eframe[CMD_BYTE(mod, 0)] = 0x20 | ADDRS[mod->subaddr];
810
			eframe[CMD_BYTE(mod, 0)] = 0x20 | ADDRS[mod->subaddr];
808
		else
811
		else
809
			eframe[CMD_BYTE(mod, 0)] = 0x60 | ADDRS[mod->subaddr];
812
			eframe[CMD_BYTE(mod, 0)] = 0x60 | ADDRS[mod->subaddr];
810
		eframe[CMD_BYTE(mod, 1)] = (curcmd >> 8) & 0xff;
813
		eframe[CMD_BYTE(mod, 1)] = (curcmd >> 8) & 0xff;
811
		eframe[CMD_BYTE(mod, 2)] = curcmd & 0xff;
814
		eframe[CMD_BYTE(mod, 2)] = curcmd & 0xff;
812
		break;
815
		break;
813
	}
816
	}
814
	case FXSINIT:
817
	case FXSINIT:
815
		/* Special case, we initialize the FXS's into the three-byte command mode then
818
		/* Special case, we initialize the FXS's into the three-byte command mode then
816
		   switch to the regular mode.  To send it into thee byte mode, treat the path as
819
		   switch to the regular mode.  To send it into thee byte mode, treat the path as
817
		   6 two-byte commands and in the last one we initialize register 0 to 0x80. All modules
820
		   6 two-byte commands and in the last one we initialize register 0 to 0x80. All modules
818
		   read this as the command to switch to daisy chain mode and we're done.  */
821
		   read this as the command to switch to daisy chain mode and we're done.  */
819
		eframe[CMD_BYTE(mod, 0)] = 0x00;
822
		eframe[CMD_BYTE(mod, 0)] = 0x00;
820
		eframe[CMD_BYTE(mod, 1)] = 0x00;
823
		eframe[CMD_BYTE(mod, 1)] = 0x00;
821
		if ((card & 0x1) == 0x1) 
824
		if ((card & 0x1) == 0x1) 
822
			eframe[CMD_BYTE(mod, 2)] = 0x80;
825
			eframe[CMD_BYTE(mod, 2)] = 0x80;
823
		else
826
		else
824
			eframe[CMD_BYTE(mod, 2)] = 0x00;
827
			eframe[CMD_BYTE(mod, 2)] = 0x00;
825
		break;
828
		break;
826

    
   
829

   
827
	case BRI:
830
	case BRI:
828
		if (unlikely((curcmd != 0x101010) && (curcmd & 0x1010) == 0x1010)) /* b400m CPLD */
831
		if (unlikely((curcmd != 0x101010) && (curcmd & 0x1010) == 0x1010)) /* b400m CPLD */
829
			eframe[CMD_BYTE(mod, 0)] = 0x55;
832
			eframe[CMD_BYTE(mod, 0)] = 0x55;
830
		else /* xhfc */
833
		else /* xhfc */
831
			eframe[CMD_BYTE(mod, 0)] = 0x10;
834
			eframe[CMD_BYTE(mod, 0)] = 0x10;
832
		eframe[CMD_BYTE(mod, 1)] = (curcmd >> 8) & 0xff;
835
		eframe[CMD_BYTE(mod, 1)] = (curcmd >> 8) & 0xff;
833
		eframe[CMD_BYTE(mod, 2)] = curcmd & 0xff;
836
		eframe[CMD_BYTE(mod, 2)] = curcmd & 0xff;
834
		break;
837
		break;
835

    
   
838

   
836
	case QRV:
839
	case QRV:
837
		eframe[CMD_BYTE(mod, 0)] = 0x00;
840
		eframe[CMD_BYTE(mod, 0)] = 0x00;
838
		if (!curcmd) {
841
		if (!curcmd) {
839
			eframe[CMD_BYTE(mod, 1)] = 0x00;
842
			eframe[CMD_BYTE(mod, 1)] = 0x00;
840
			eframe[CMD_BYTE(mod, 2)] = 0x00;
843
			eframe[CMD_BYTE(mod, 2)] = 0x00;
841
		} else {
844
		} else {
842
			if (curcmd & __CMD_WR)
845
			if (curcmd & __CMD_WR)
843
				eframe[CMD_BYTE(mod, 1)] = 0x40 | ((curcmd >> 8) & 0x3f);
846
				eframe[CMD_BYTE(mod, 1)] = 0x40 | ((curcmd >> 8) & 0x3f);
844
			else
847
			else
845
				eframe[CMD_BYTE(mod, 1)] = 0xc0 | ((curcmd >> 8) & 0x3f);
848
				eframe[CMD_BYTE(mod, 1)] = 0xc0 | ((curcmd >> 8) & 0x3f);
846
			eframe[CMD_BYTE(mod, 2)] = curcmd & 0xff;
849
			eframe[CMD_BYTE(mod, 2)] = curcmd & 0xff;
847
		}
850
		}
848
		break;
851
		break;
849

    
   
852

   
850
	case NONE:
853
	case NONE:
851
		eframe[CMD_BYTE(mod, 0)] = 0x10;
854
		eframe[CMD_BYTE(mod, 0)] = 0x10;
852
		eframe[CMD_BYTE(mod, 1)] = 0x10;
855
		eframe[CMD_BYTE(mod, 1)] = 0x10;
853
		eframe[CMD_BYTE(mod, 2)] = 0x10;
856
		eframe[CMD_BYTE(mod, 2)] = 0x10;
854
		break;
857
		break;
855
	}
858
	}
856
}
859
}
857

    
   
860

   
858
static inline void cmd_decipher_vpmadt032(struct wctdm *wc, const u8 *eframe)
861
static inline void cmd_decipher_vpmadt032(struct wctdm *wc, const u8 *eframe)
859
{
862
{
860
	struct vpmadt032 *const vpm = wc->vpmadt032;
863
	struct vpmadt032 *const vpm = wc->vpmadt032;
861
	struct vpmadt032_cmd *cmd;
864
	struct vpmadt032_cmd *cmd;
862

    
   
865

   
863
	BUG_ON(!vpm);
866
	BUG_ON(!vpm);
864

    
   
867

   
865
	/* If the hardware is not processing any commands currently, then
868
	/* If the hardware is not processing any commands currently, then
866
	 * there is nothing for us to do here. */
869
	 * there is nothing for us to do here. */
867
	if (list_empty(&vpm->active_cmds)) {
870
	if (list_empty(&vpm->active_cmds)) {
868
		return;
871
		return;
869
	}
872
	}
870

    
   
873

   
871
	spin_lock(&vpm->list_lock);
874
	spin_lock(&vpm->list_lock);
872
	cmd = list_entry(vpm->active_cmds.next, struct vpmadt032_cmd, node);
875
	cmd = list_entry(vpm->active_cmds.next, struct vpmadt032_cmd, node);
873
	if (wc->rxident == cmd->txident) {
876
	if (wc->rxident == cmd->txident) {
874
		list_del_init(&cmd->node);
877
		list_del_init(&cmd->node);
875
	} else {
878
	} else {
876
		cmd = NULL;
879
		cmd = NULL;
877
	}
880
	}
878
	spin_unlock(&vpm->list_lock);
881
	spin_unlock(&vpm->list_lock);
879

    
   
882

   
880
	if (!cmd)
883
	if (!cmd)
881
		return;
884
		return;
882

    
   
885

   
883
	/* Skip audio */
886
	/* Skip audio */
884
	eframe += 24;
887
	eframe += 24;
885

    
   
888

   
886
	/* Store result */
889
	/* Store result */
887
	cmd->data = (0xff & eframe[VPM_CMD_BYTE(25, 1)]) << 8;
890
	cmd->data = (0xff & eframe[VPM_CMD_BYTE(25, 1)]) << 8;
888
	cmd->data |= eframe[VPM_CMD_BYTE(25, 2)];
891
	cmd->data |= eframe[VPM_CMD_BYTE(25, 2)];
889
	if (cmd->desc & __VPM150M_WR) {
892
	if (cmd->desc & __VPM150M_WR) {
890
		kfree(cmd);
893
		kfree(cmd);
891
	} else {
894
	} else {
892
		cmd->desc |= __VPM150M_FIN;
895
		cmd->desc |= __VPM150M_FIN;
893
		complete(&cmd->complete);
896
		complete(&cmd->complete);
894
	}
897
	}
895
}
898
}
896

    
   
899

   
897
/**
900
/**
898
 * Call with the reglock held and local interrupts disabled
901
 * Call with the reglock held and local interrupts disabled
899
 */
902
 */
900
static void _cmd_decipher(struct wctdm *wc, const u8 *eframe, int card)
903
static void _cmd_decipher(struct wctdm *wc, const u8 *eframe, int card)
901
{
904
{
902
	enum { TDM_BYTES = 24, };
905
	enum { TDM_BYTES = 24, };
903
	struct wctdm_module *const mod = &wc->mods[card];
906
	struct wctdm_module *const mod = &wc->mods[card];
904
	struct wctdm_cmd *cmd;
907
	struct wctdm_cmd *cmd;
905
	u8 address;
908
	u8 address;
906
	u8 value;
909
	u8 value;
907

    
   
910

   
908
	if (list_empty(&mod->active_cmds))
911
	if (list_empty(&mod->active_cmds))
909
		return;
912
		return;
910

    
   
913

   
911
	cmd = list_entry(mod->active_cmds.next, struct wctdm_cmd, node);
914
	cmd = list_entry(mod->active_cmds.next, struct wctdm_cmd, node);
912
	if (cmd->ident != wc->rxident)
915
	if (cmd->ident != wc->rxident)
913
		return;
916
		return;
914

    
   
917

   
915
	list_del(&cmd->node);
918
	list_del(&cmd->node);
916

    
   
919

   
917
	if (cmd->cmd & __CMD_WR) {
920
	if (cmd->cmd & __CMD_WR) {
918
		kfree(cmd);
921
		kfree(cmd);
919
		return;
922
		return;
920
	}
923
	}
921

    
   
924

   
922
	address = (cmd->cmd >> 8) & 0xff;
925
	address = (cmd->cmd >> 8) & 0xff;
923

    
   
926

   
924
	cmd->cmd = eframe[TDM_BYTES + CMD_BYTE(mod, 2)];
927
	cmd->cmd = eframe[TDM_BYTES + CMD_BYTE(mod, 2)];
925

    
   
928

   
926
	value = (cmd->cmd & 0xff);
929
	value = (cmd->cmd & 0xff);
927

    
   
930

   
928
	if (cmd->complete) {
931
	if (cmd->complete) {
929
		complete(cmd->complete);
932
		complete(cmd->complete);
930
		return;
933
		return;
931
	}
934
	}
932

    
   
935

   
933
	switch (mod->type) {
936
	switch (mod->type) {
934
	case FXS:
937
	case FXS:
935
		mod->isrshadow[(68 == address) ? 0 : 1] = value;
938
		mod->isrshadow[(68 == address) ? 0 : 1] = value;
936
		break;
939
		break;
937
	case FXO:
940
	case FXO:
938
		/* 5 = Hook/Ring  29 = Battery */
941
		/* 5 = Hook/Ring  29 = Battery */
939
		mod->isrshadow[(5 == address) ? 0 : 1] = value;
942
		mod->isrshadow[(5 == address) ? 0 : 1] = value;
940
		break;
943
		break;
941
	case QRV:
944
	case QRV:
942
		/* wctdm_isr_getreg(wc, mod, 3); */ /* COR/CTCSS state */
945
		/* wctdm_isr_getreg(wc, mod, 3); */ /* COR/CTCSS state */
943
		/* TODO: This looks broken to me, but I have no way to
946
		/* TODO: This looks broken to me, but I have no way to
944
		 * resolved it. */
947
		 * resolved it. */
945
		/* wc->mods[card & 0xfc].cmds[USER_COMMANDS + 1] = CMD_RD(3); */
948
		/* wc->mods[card & 0xfc].cmds[USER_COMMANDS + 1] = CMD_RD(3); */
946
		break;
949
		break;
947
	default:
950
	default:
948
		break;
951
		break;
949
	}
952
	}
950

    
   
953

   
951
	kfree(cmd);
954
	kfree(cmd);
952
}
955
}
953

    
   
956

   
954
/* Call with wc.reglock held and local interrupts disabled. */
957
/* Call with wc.reglock held and local interrupts disabled. */
955
static void
958
static void
956
wctdm_isr_getreg(struct wctdm *wc, struct wctdm_module *const mod, u8 address)
959
wctdm_isr_getreg(struct wctdm *wc, struct wctdm_module *const mod, u8 address)
957
{
960
{
958
	struct wctdm_cmd *cmd;
961
	struct wctdm_cmd *cmd;
959

    
   
962

   
960
	cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC);
963
	cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC);
961
	if (unlikely(!cmd))
964
	if (unlikely(!cmd))
962
		return;
965
		return;
963

    
   
966

   
964
	cmd->cmd = CMD_RD(address);
967
	cmd->cmd = CMD_RD(address);
965
	cmd->complete = NULL;
968
	cmd->complete = NULL;
966

    
   
969

   
967
	list_add(&cmd->node, &mod->pending_cmds);
970
	list_add(&cmd->node, &mod->pending_cmds);
968
}
971
}
969

    
   
972

   
970
static inline void
973
static inline void
971
wctdm_setreg_intr(struct wctdm *wc, struct wctdm_module *mod,
974
wctdm_setreg_intr(struct wctdm *wc, struct wctdm_module *mod,
972
		  int addr, int val);
975
		  int addr, int val);
973

    
   
976

   
974
static void cmd_checkisr(struct wctdm *wc, struct wctdm_module *const mod)
977
static void cmd_checkisr(struct wctdm *wc, struct wctdm_module *const mod)
975
{
978
{
976
	if (mod->sethook) {
979
	if (mod->sethook) {
977
		wctdm_setreg_intr(wc, mod, ((mod->sethook >> 8) & 0xff),
980
		wctdm_setreg_intr(wc, mod, ((mod->sethook >> 8) & 0xff),
978
				  mod->sethook & 0xff);
981
				  mod->sethook & 0xff);
979
		mod->sethook = 0;
982
		mod->sethook = 0;
980
		return;
983
		return;
981
	}
984
	}
982

    
   
985

   
983
	switch (mod->type) {
986
	switch (mod->type) {
984
	case FXS:
987
	case FXS:
985
		wctdm_isr_getreg(wc, mod, 68); /* Hook state */
988
		wctdm_isr_getreg(wc, mod, 68); /* Hook state */
986
#ifdef PAQ_DEBUG
989
#ifdef PAQ_DEBUG
987
		wctdm_isr_getreg(wc, mod, 19); /* Transistor interrupts */
990
		wctdm_isr_getreg(wc, mod, 19); /* Transistor interrupts */
988
#else
991
#else
989
		wctdm_isr_getreg(wc, mod, LINE_STATE);
992
		wctdm_isr_getreg(wc, mod, LINE_STATE);
990
#endif
993
#endif
991
		break;
994
		break;
992
	case FXO:
995
	case FXO:
993
		wctdm_isr_getreg(wc, mod, 5);  /* Hook/Ring state */
996
		wctdm_isr_getreg(wc, mod, 5);  /* Hook/Ring state */
994
		wctdm_isr_getreg(wc, mod, 29); /* Battery */
997
		wctdm_isr_getreg(wc, mod, 29); /* Battery */
995
		break;
998
		break;
996
	case QRV:
999
	case QRV:
997
		wctdm_isr_getreg(wc, mod, 3); /* COR/CTCSS state */
1000
		wctdm_isr_getreg(wc, mod, 3); /* COR/CTCSS state */
998
		/* TODO: This looks broken to me, but I have no way to
1001
		/* TODO: This looks broken to me, but I have no way to
999
		 * resolved it. */
1002
		 * resolved it. */
1000
		/* wc->mods[card & 0xfc].cmds[USER_COMMANDS + 1] = CMD_RD(3); */
1003
		/* wc->mods[card & 0xfc].cmds[USER_COMMANDS + 1] = CMD_RD(3); */
1001
		break;
1004
		break;
1002
	case BRI:
1005
	case BRI:
1003
		/* TODO: Two calls needed here? */
1006
		/* TODO: Two calls needed here? */
1004
		wctdm_bri_checkisr(wc, mod, 0);
1007
		wctdm_bri_checkisr(wc, mod, 0);
1005
		wctdm_bri_checkisr(wc, mod, 1);
1008
		wctdm_bri_checkisr(wc, mod, 1);
1006
		break;
1009
		break;
1007
	default:
1010
	default:
1008
		break;
1011
		break;
1009
	}
1012
	}
1010
}
1013
}
1011

    
   
1014

   
1012
/**
1015
/**
1013
 * insert_tdm_data() - Move TDM data from channels to sframe.
1016
 * insert_tdm_data() - Move TDM data from channels to sframe.
1014
 *
1017
 *
1015
 */
1018
 */
1016
static void insert_tdm_data(const struct wctdm *wc, u8 *sframe)
1019
static void insert_tdm_data(const struct wctdm *wc, u8 *sframe)
1017
{
1020
{
1018
	int i;
1021
	int i;
1019
	register u8 *chanchunk;
1022
	register u8 *chanchunk;
1020

    
   
1023

   
1021
	for (i = 0; i < wc->avchannels; i += 4) {
1024
	for (i = 0; i < wc->avchannels; i += 4) {
1022
		chanchunk = &wc->mods[0 + i].chan->chan.writechunk[0];
1025
		chanchunk = &wc->mods[0 + i].chan->chan.writechunk[0];
1023
		sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*0] = chanchunk[0];
1026
		sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*0] = chanchunk[0];
1024
		sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*1] = chanchunk[1];
1027
		sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*1] = chanchunk[1];
1025
		sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*2] = chanchunk[2];
1028
		sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*2] = chanchunk[2];
1026
		sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*3] = chanchunk[3];
1029
		sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*3] = chanchunk[3];
1027
		sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*4] = chanchunk[4];
1030
		sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*4] = chanchunk[4];
1028
		sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*5] = chanchunk[5];
1031
		sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*5] = chanchunk[5];
1029
		sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*6] = chanchunk[6];
1032
		sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*6] = chanchunk[6];
1030
		sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*7] = chanchunk[7];
1033
		sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*7] = chanchunk[7];
1031

    
   
1034

   
1032
		chanchunk = &wc->mods[1 + i].chan->chan.writechunk[0];
1035
		chanchunk = &wc->mods[1 + i].chan->chan.writechunk[0];
1033
		sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*0] = chanchunk[0];
1036
		sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*0] = chanchunk[0];
1034
		sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*1] = chanchunk[1];
1037
		sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*1] = chanchunk[1];
1035
		sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*2] = chanchunk[2];
1038
		sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*2] = chanchunk[2];
1036
		sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*3] = chanchunk[3];
1039
		sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*3] = chanchunk[3];
1037
		sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*4] = chanchunk[4];
1040
		sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*4] = chanchunk[4];
1038
		sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*5] = chanchunk[5];
1041
		sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*5] = chanchunk[5];
1039
		sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*6] = chanchunk[6];
1042
		sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*6] = chanchunk[6];
1040
		sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*7] = chanchunk[7];
1043
		sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*7] = chanchunk[7];
1041

    
   
1044

   
1042
		chanchunk = &wc->mods[2 + i].chan->chan.writechunk[0];
1045
		chanchunk = &wc->mods[2 + i].chan->chan.writechunk[0];
1043
		sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*0] = chanchunk[0];
1046
		sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*0] = chanchunk[0];
1044
		sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*1] = chanchunk[1];
1047
		sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*1] = chanchunk[1];
1045
		sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*2] = chanchunk[2];
1048
		sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*2] = chanchunk[2];
1046
		sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*3] = chanchunk[3];
1049
		sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*3] = chanchunk[3];
1047
		sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*4] = chanchunk[4];
1050
		sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*4] = chanchunk[4];
1048
		sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*5] = chanchunk[5];
1051
		sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*5] = chanchunk[5];
1049
		sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*6] = chanchunk[6];
1052
		sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*6] = chanchunk[6];
1050
		sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*7] = chanchunk[7];
1053
		sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*7] = chanchunk[7];
1051

    
   
1054

   
1052
		chanchunk = &wc->mods[3 + i].chan->chan.writechunk[0];
1055
		chanchunk = &wc->mods[3 + i].chan->chan.writechunk[0];
1053
		sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*0] = chanchunk[0];
1056
		sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*0] = chanchunk[0];
1054
		sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*1] = chanchunk[1];
1057
		sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*1] = chanchunk[1];
1055
		sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*2] = chanchunk[2];
1058
		sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*2] = chanchunk[2];
1056
		sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*3] = chanchunk[3];
1059
		sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*3] = chanchunk[3];
1057
		sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*4] = chanchunk[4];
1060
		sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*4] = chanchunk[4];
1058
		sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*5] = chanchunk[5];
1061
		sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*5] = chanchunk[5];
1059
		sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*6] = chanchunk[6];
1062
		sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*6] = chanchunk[6];
1060
		sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*7] = chanchunk[7];
1063
		sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*7] = chanchunk[7];
1061
	}
1064
	}
1062
}
1065
}
1063

    
   
1066

   
1064
static inline void wctdm_transmitprep(struct wctdm *wc, unsigned char *sframe)
1067
static inline void wctdm_transmitprep(struct wctdm *wc, unsigned char *sframe)
1065
{
1068
{
1066
	int x, y;
1069
	int x, y;
1067
	struct dahdi_span *s;
1070
	struct dahdi_span *s;
1068
	unsigned char *eframe = sframe;
1071
	unsigned char *eframe = sframe;
1069

    
   
1072

   
1070
	/* Calculate Transmission */
1073
	/* Calculate Transmission */
1071
	if (likely(wc->initialized)) {
1074
	if (likely(wc->initialized)) {
1072
		for (x = 0; x < MAX_SPANS; x++) {
1075
		for (x = 0; x < MAX_SPANS; x++) {
1073
			if (wc->spans[x]) {
1076
			if (wc->spans[x]) {
1074
				s = &wc->spans[x]->span;
1077
				s = &wc->spans[x]->span;
1075
				_dahdi_transmit(s);
1078
				_dahdi_transmit(s);
1076
			}
1079
			}
1077
		}
1080
		}
1078
		insert_tdm_data(wc, sframe);
1081
		insert_tdm_data(wc, sframe);
1079
#ifdef CONFIG_VOICEBUS_ECREFERENCE
1082
#ifdef CONFIG_VOICEBUS_ECREFERENCE
1080
		for (x = 0; x < wc->avchannels; ++x) {
1083
		for (x = 0; x < wc->avchannels; ++x) {
1081
			__dahdi_fifo_put(wc->ec_reference[x],
1084
			__dahdi_fifo_put(wc->ec_reference[x],
1082
					 wc->chans[x]->chan.writechunk,
1085
					 wc->chans[x]->chan.writechunk,
1083
					 DAHDI_CHUNKSIZE);
1086
					 DAHDI_CHUNKSIZE);
1084
		}
1087
		}
1085
#endif
1088
#endif
1086
	}
1089
	}
1087

    
   
1090

   
1088
	spin_lock(&wc->reglock);
1091
	spin_lock(&wc->reglock);
1089
	for (x = 0; x < DAHDI_CHUNKSIZE; x++) {
1092
	for (x = 0; x < DAHDI_CHUNKSIZE; x++) {
1090
		/* Send a sample, as a 32-bit word */
1093
		/* Send a sample, as a 32-bit word */
1091

    
   
1094

   
1092
		/* TODO: ABK: hmm, this was originally mods_per_board, but we
1095
		/* TODO: ABK: hmm, this was originally mods_per_board, but we
1093
		 * need to worry about all the active "voice" timeslots, since
1096
		 * need to worry about all the active "voice" timeslots, since
1094
		 * BRI modules have a different number of TDM channels than
1097
		 * BRI modules have a different number of TDM channels than
1095
		 * installed modules. */
1098
		 * installed modules. */
1096
		for (y = 0; y < wc->avchannels; y++) {
1099
		for (y = 0; y < wc->avchannels; y++) {
1097
			if (!x && y < wc->mods_per_board)
1100
			if (!x && y < wc->mods_per_board)
1098
				cmd_checkisr(wc, &wc->mods[y]);
1101
				cmd_checkisr(wc, &wc->mods[y]);
1099

    
   
1102

   
1100
			if (y < wc->mods_per_board)
1103
			if (y < wc->mods_per_board)
1101
				_cmd_dequeue(wc, eframe, y, x);
1104
				_cmd_dequeue(wc, eframe, y, x);
1102
		}
1105
		}
1103

    
   
1106

   
1104
		if (wc->vpmadt032) {
1107
		if (wc->vpmadt032) {
1105
			cmd_dequeue_vpmadt032(wc, eframe);
1108
			cmd_dequeue_vpmadt032(wc, eframe);
1106
		} else if (wc->vpmadt032) {
1109
		} else if (wc->vpmadt032) {
1107
			cmd_dequeue_vpmadt032(wc, eframe);
1110
			cmd_dequeue_vpmadt032(wc, eframe);
1108
		}
1111
		}
1109

    
   
1112

   
1110
		if (x < DAHDI_CHUNKSIZE - 1) {
1113
		if (x < DAHDI_CHUNKSIZE - 1) {
1111
			eframe[EFRAME_SIZE] = wc->ctlreg;
1114
			eframe[EFRAME_SIZE] = wc->ctlreg;
1112
			eframe[EFRAME_SIZE + 1] = wc->txident++;
1115
			eframe[EFRAME_SIZE + 1] = wc->txident++;
1113
			if (4 == wc->desc->ports)
1116
			if (4 == wc->desc->ports)
1114
				eframe[EFRAME_SIZE + 2] = wc->tdm410leds;
1117
				eframe[EFRAME_SIZE + 2] = wc->tdm410leds;
1115
		}
1118
		}
1116
		eframe += (EFRAME_SIZE + EFRAME_GAP);
1119
		eframe += (EFRAME_SIZE + EFRAME_GAP);
1117
	}
1120
	}
1118
	spin_unlock(&wc->reglock);
1121
	spin_unlock(&wc->reglock);
1119
}
1122
}
1120

    
   
1123

   
1121
/* Must be called with wc.reglock held and local interrupts disabled */
1124
/* Must be called with wc.reglock held and local interrupts disabled */
1122
static inline void
1125
static inline void
1123
wctdm_setreg_intr(struct wctdm *wc, struct wctdm_module *mod, int addr, int val)
1126
wctdm_setreg_intr(struct wctdm *wc, struct wctdm_module *mod, int addr, int val)
1124
{
1127
{
1125
	struct wctdm_cmd *cmd;
1128
	struct wctdm_cmd *cmd;
1126

    
   
1129

   
1127
	cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC);
1130
	cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC);
1128
	if (unlikely(!cmd))
1131
	if (unlikely(!cmd))
1129
		return;
1132
		return;
1130

    
   
1133

   
1131
	cmd->complete = NULL;
1134
	cmd->complete = NULL;
1132
	cmd->cmd = CMD_WR(addr, val);
1135
	cmd->cmd = CMD_WR(addr, val);
1133

    
   
1136

   
1134
	list_add_tail(&cmd->node, &mod->pending_cmds);
1137
	list_add_tail(&cmd->node, &mod->pending_cmds);
1135
}
1138
}
1136

    
   
1139

   
1137
int wctdm_setreg(struct wctdm *wc, struct wctdm_module *mod, int addr, int val)
1140
int wctdm_setreg(struct wctdm *wc, struct wctdm_module *mod, int addr, int val)
1138
{
1141
{
1139
	struct wctdm_cmd *cmd;
1142
	struct wctdm_cmd *cmd;
1140
	unsigned long flags;
1143
	unsigned long flags;
1141

    
   
1144

   
1142
#if 0 /* TODO */
1145
#if 0 /* TODO */
1143
	/* QRV and BRI cards are only addressed at their first "port" */
1146
	/* QRV and BRI cards are only addressed at their first "port" */
1144
	if ((card & 0x03) && ((wc->mods[card].type ==  QRV) ||
1147
	if ((card & 0x03) && ((wc->mods[card].type ==  QRV) ||
1145
	    (wc->mods[card].type ==  BRI)))
1148
	    (wc->mods[card].type ==  BRI)))
1146
		return 0;
1149
		return 0;
1147
#endif
1150
#endif
1148

    
   
1151

   
1149
	cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
1152
	cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
1150
	if (unlikely(!cmd))
1153
	if (unlikely(!cmd))
1151
		return -ENOMEM;
1154
		return -ENOMEM;
1152

    
   
1155

   
1153
	cmd->complete = NULL;
1156
	cmd->complete = NULL;
1154
	cmd->cmd = CMD_WR(addr, val);
1157
	cmd->cmd = CMD_WR(addr, val);
1155

    
   
1158

   
1156
	spin_lock_irqsave(&wc->reglock, flags);
1159
	spin_lock_irqsave(&wc->reglock, flags);
1157
	list_add_tail(&cmd->node, &mod->pending_cmds);
1160
	list_add_tail(&cmd->node, &mod->pending_cmds);
1158
	spin_unlock_irqrestore(&wc->reglock, flags);
1161
	spin_unlock_irqrestore(&wc->reglock, flags);
1159

    
   
1162

   
1160
	return 0;
1163
	return 0;
1161
}
1164
}
1162

    
   
1165

   
1163
int wctdm_getreg(struct wctdm *wc, struct wctdm_module *const mod, int addr)
1166
int wctdm_getreg(struct wctdm *wc, struct wctdm_module *const mod, int addr)
1164
{
1167
{
1165
	unsigned long flags;
1168
	unsigned long flags;
1166
	struct wctdm_cmd *cmd;
1169
	struct wctdm_cmd *cmd;
1167
	int val;
1170
	int val;
1168

    
   
1171

   
1169
#if 0 /* TODO */
1172
#if 0 /* TODO */
1170
	/* if a QRV card, use only its first channel */  
1173
	/* if a QRV card, use only its first channel */  
1171
	if (wc->mods[card].type ==  QRV) {
1174
	if (wc->mods[card].type ==  QRV) {
1172
		if (card & 3)
1175
		if (card & 3)
1173
			return 0;
1176
			return 0;
1174
	}
1177
	}
1175
#endif
1178
#endif
1176

    
   
1179

   
1177
	cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
1180
	cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
1178
	if (!cmd)
1181
	if (!cmd)
1179
		return -ENOMEM;
1182
		return -ENOMEM;
1180

    
   
1183

   
1181
	cmd->complete = kmalloc(sizeof(*cmd->complete), GFP_KERNEL);
1184
	cmd->complete = kmalloc(sizeof(*cmd->complete), GFP_KERNEL);
1182
	if (!cmd->complete) {
1185
	if (!cmd->complete) {
1183
		kfree(cmd);
1186
		kfree(cmd);
1184
		return -ENOMEM;
1187
		return -ENOMEM;
1185
	}
1188
	}
1186

    
   
1189

   
1187
	init_completion(cmd->complete);
1190
	init_completion(cmd->complete);
1188

    
   
1191

   
1189
	cmd->cmd = CMD_RD(addr);
1192
	cmd->cmd = CMD_RD(addr);
1190

    
   
1193

   
1191
	spin_lock_irqsave(&wc->reglock, flags);
1194
	spin_lock_irqsave(&wc->reglock, flags);
1192
	list_add_tail(&cmd->node, &mod->pending_cmds);
1195
	list_add_tail(&cmd->node, &mod->pending_cmds);
1193
	spin_unlock_irqrestore(&wc->reglock, flags);
1196
	spin_unlock_irqrestore(&wc->reglock, flags);
1194

    
   
1197

   
1195
	wait_for_completion(cmd->complete);
1198
	wait_for_completion(cmd->complete);
1196
	val = cmd->cmd & 0xff;
1199
	val = cmd->cmd & 0xff;
1197

    
   
1200

   
1198
	kfree(cmd->complete);
1201
	kfree(cmd->complete);
1199
	kfree(cmd);
1202
	kfree(cmd);
1200

    
   
1203

   
1201
	return val;
1204
	return val;
1202
}
1205
}
1203

    
   
1206

   
1204
static int wctdm_getregs(struct wctdm *wc, struct wctdm_module *const mod,
1207
static int wctdm_getregs(struct wctdm *wc, struct wctdm_module *const mod,
1205
			 int *const addresses, const size_t count)
1208
			 int *const addresses, const size_t count)
1206
{
1209
{
1207
	int x;
1210
	int x;
1208
	unsigned long flags;
1211
	unsigned long flags;
1209
	struct wctdm_cmd *cmd;
1212
	struct wctdm_cmd *cmd;
1210
	struct wctdm_cmd *cmds[count];
1213
	struct wctdm_cmd *cmds[count];
1211

    
   
1214

   
1212
	for (x = 0; x < count; ++x) {
1215
	for (x = 0; x < count; ++x) {
1213
		cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
1216
		cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
1214
		if (!cmd)
1217
		if (!cmd)
1215
			return -ENOMEM;
1218
			return -ENOMEM;
1216

    
   
1219

   
1217
		cmd->complete = kmalloc(sizeof(*cmd->complete), GFP_KERNEL);
1220
		cmd->complete = kmalloc(sizeof(*cmd->complete), GFP_KERNEL);
1218
		if (!cmd->complete) {
1221
		if (!cmd->complete) {
1219
			kfree(cmd);
1222
			kfree(cmd);
1220
			return -ENOMEM;
1223
			return -ENOMEM;
1221
		}
1224
		}
1222

    
   
1225

   
1223
		init_completion(cmd->complete);
1226
		init_completion(cmd->complete);
1224

    
   
1227

   
1225
		cmd->cmd = CMD_RD(addresses[x]);
1228
		cmd->cmd = CMD_RD(addresses[x]);
1226

    
   
1229

   
1227
		spin_lock_irqsave(&wc->reglock, flags);
1230
		spin_lock_irqsave(&wc->reglock, flags);
1228
		list_add_tail(&cmd->node, &mod->pending_cmds);
1231
		list_add_tail(&cmd->node, &mod->pending_cmds);
1229
		spin_unlock_irqrestore(&wc->reglock, flags);
1232
		spin_unlock_irqrestore(&wc->reglock, flags);
1230

    
   
1233

   
1231
		cmds[x] = cmd;
1234
		cmds[x] = cmd;
1232
	}
1235
	}
1233

    
   
1236

   
1234
	for (x = count - 1; x >= 0; --x) {
1237
	for (x = count - 1; x >= 0; --x) {
1235
		cmd = cmds[x];
1238
		cmd = cmds[x];
1236
		wait_for_completion(cmd->complete);
1239
		wait_for_completion(cmd->complete);
1237
		addresses[x] = cmd->cmd & 0xff;
1240
		addresses[x] = cmd->cmd & 0xff;
1238
		kfree(cmd->complete);
1241
		kfree(cmd->complete);
1239
		kfree(cmd);
1242
		kfree(cmd);
1240
	}
1243
	}
1241

    
   
1244

   
1242
	return 0;
1245
	return 0;
1243
}
1246
}
1244

    
   
1247

   
1245
/**
1248
/**
1246
 * call with wc->reglock held and interrupts disabled.
1249
 * call with wc->reglock held and interrupts disabled.
1247
 */
1250
 */
1248
static void cmd_retransmit(struct wctdm *wc)
1251
static void cmd_retransmit(struct wctdm *wc)
1249
{
1252
{
1250
	int x;
1253
	int x;
1251

    
   
1254

   
1252
	for (x = 0; x < wc->mods_per_board; x++) {
1255
	for (x = 0; x < wc->mods_per_board; x++) {
1253
		struct wctdm_module *const mod = &wc->mods[x];
1256
		struct wctdm_module *const mod = &wc->mods[x];
1254
		if (mod->type == BRI)
1257
		if (mod->type == BRI)
1255
			continue;
1258
			continue;
1256
		list_splice_init(&mod->active_cmds, &mod->pending_cmds);
1259
		list_splice_init(&mod->active_cmds, &mod->pending_cmds);
1257
	}
1260
	}
1258

    
   
1261

   
1259
#ifdef VPM_SUPPORT
1262
#ifdef VPM_SUPPORT
1260
	if (wc->vpmadt032)
1263
	if (wc->vpmadt032)
1261
		vpmadt032_resend(wc->vpmadt032);
1264
		vpmadt032_resend(wc->vpmadt032);
1262
#endif
1265
#endif
1263
}
1266
}
1264

    
   
1267

   
1265
/**
1268
/**
1266
 * extract_tdm_data() - Move TDM data from sframe to channels.
1269
 * extract_tdm_data() - Move TDM data from sframe to channels.
1267
 *
1270
 *
1268
 */
1271
 */
1269
static void extract_tdm_data(struct wctdm *wc, const u8 *sframe)
1272
static void extract_tdm_data(struct wctdm *wc, const u8 *sframe)
1270
{
1273
{
1271
	int i;
1274
	int i;
1272
	register u8 *chanchunk;
1275
	register u8 *chanchunk;
1273

    
   
1276

   
1274
	for (i = 0; i < wc->avchannels; i += 4) {
1277
	for (i = 0; i < wc->avchannels; i += 4) {
1275
		chanchunk = &wc->mods[0 + i].chan->chan.readchunk[0];
1278
		chanchunk = &wc->mods[0 + i].chan->chan.readchunk[0];
1276
		chanchunk[0] = sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*0];
1279
		chanchunk[0] = sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*0];
1277
		chanchunk[1] = sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*1];
1280
		chanchunk[1] = sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*1];
1278
		chanchunk[2] = sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*2];
1281
		chanchunk[2] = sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*2];
1279
		chanchunk[3] = sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*3];
1282
		chanchunk[3] = sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*3];
1280
		chanchunk[4] = sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*4];
1283
		chanchunk[4] = sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*4];
1281
		chanchunk[5] = sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*5];
1284
		chanchunk[5] = sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*5];
1282
		chanchunk[6] = sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*6];
1285
		chanchunk[6] = sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*6];
1283
		chanchunk[7] = sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*7];
1286
		chanchunk[7] = sframe[0 + i + (EFRAME_SIZE + EFRAME_GAP)*7];
1284

    
   
1287

   
1285
		chanchunk = &wc->mods[1 + i].chan->chan.readchunk[0];
1288
		chanchunk = &wc->mods[1 + i].chan->chan.readchunk[0];
1286
		chanchunk[0] = sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*0];
1289
		chanchunk[0] = sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*0];
1287
		chanchunk[1] = sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*1];
1290
		chanchunk[1] = sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*1];
1288
		chanchunk[2] = sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*2];
1291
		chanchunk[2] = sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*2];
1289
		chanchunk[3] = sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*3];
1292
		chanchunk[3] = sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*3];
1290
		chanchunk[4] = sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*4];
1293
		chanchunk[4] = sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*4];
1291
		chanchunk[5] = sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*5];
1294
		chanchunk[5] = sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*5];
1292
		chanchunk[6] = sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*6];
1295
		chanchunk[6] = sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*6];
1293
		chanchunk[7] = sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*7];
1296
		chanchunk[7] = sframe[1 + i + (EFRAME_SIZE + EFRAME_GAP)*7];
1294

    
   
1297

   
1295
		chanchunk = &wc->mods[2 + i].chan->chan.readchunk[0];
1298
		chanchunk = &wc->mods[2 + i].chan->chan.readchunk[0];
1296
		chanchunk[0] = sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*0];
1299
		chanchunk[0] = sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*0];
1297
		chanchunk[1] = sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*1];
1300
		chanchunk[1] = sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*1];
1298
		chanchunk[2] = sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*2];
1301
		chanchunk[2] = sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*2];
1299
		chanchunk[3] = sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*3];
1302
		chanchunk[3] = sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*3];
1300
		chanchunk[4] = sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*4];
1303
		chanchunk[4] = sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*4];
1301
		chanchunk[5] = sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*5];
1304
		chanchunk[5] = sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*5];
1302
		chanchunk[6] = sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*6];
1305
		chanchunk[6] = sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*6];
1303
		chanchunk[7] = sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*7];
1306
		chanchunk[7] = sframe[2 + i + (EFRAME_SIZE + EFRAME_GAP)*7];
1304

    
   
1307

   
1305
		chanchunk = &wc->mods[3 + i].chan->chan.readchunk[0];
1308
		chanchunk = &wc->mods[3 + i].chan->chan.readchunk[0];
1306
		chanchunk[0] = sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*0];
1309
		chanchunk[0] = sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*0];
1307
		chanchunk[1] = sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*1];
1310
		chanchunk[1] = sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*1];
1308
		chanchunk[2] = sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*2];
1311
		chanchunk[2] = sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*2];
1309
		chanchunk[3] = sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*3];
1312
		chanchunk[3] = sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*3];
1310
		chanchunk[4] = sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*4];
1313
		chanchunk[4] = sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*4];
1311
		chanchunk[5] = sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*5];
1314
		chanchunk[5] = sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*5];
1312
		chanchunk[6] = sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*6];
1315
		chanchunk[6] = sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*6];
1313
		chanchunk[7] = sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*7];
1316
		chanchunk[7] = sframe[3 + i + (EFRAME_SIZE + EFRAME_GAP)*7];
1314
	}
1317
	}
1315
}
1318
}
1316

    
   
1319

   
1317
static inline void wctdm_receiveprep(struct wctdm *wc, const u8 *sframe)
1320
static inline void wctdm_receiveprep(struct wctdm *wc, const u8 *sframe)
1318
{
1321
{
1319
	int x, y;
1322
	int x, y;
1320
	bool irqmiss = false;
1323
	bool irqmiss = false;
1321
	unsigned char expected;
1324
	unsigned char expected;
1322
	const u8 *eframe = sframe;
1325
	const u8 *eframe = sframe;
1323

    
   
1326

   
1324
	if (unlikely(!is_good_frame(sframe)))
1327
	if (unlikely(!is_good_frame(sframe)))
1325
		return;
1328
		return;
1326

    
   
1329

   
1327
	if (likely(wc->initialized))
1330
	if (likely(wc->initialized))
1328
		extract_tdm_data(wc, sframe);
1331
		extract_tdm_data(wc, sframe);
1329

    
   
1332

   
1330
	spin_lock(&wc->reglock);
1333
	spin_lock(&wc->reglock);
1331
	for (x = 0; x < DAHDI_CHUNKSIZE; x++) {
1334
	for (x = 0; x < DAHDI_CHUNKSIZE; x++) {
1332
		if (x < DAHDI_CHUNKSIZE - 1) {
1335
		if (x < DAHDI_CHUNKSIZE - 1) {
1333
			expected = wc->rxident + 1;
1336
			expected = wc->rxident + 1;
1334
			wc->rxident = eframe[EFRAME_SIZE + 1];
1337
			wc->rxident = eframe[EFRAME_SIZE + 1];
1335
			if (wc->rxident != expected) {
1338
			if (wc->rxident != expected) {
1336
				irqmiss = true;
1339
				irqmiss = true;
1337
				cmd_retransmit(wc);
1340
				cmd_retransmit(wc);
1338
			}
1341
			}
1339
		}
1342
		}
1340

    
   
1343

   
1341
		for (y = 0; y < wc->avchannels; y++)
1344
		for (y = 0; y < wc->avchannels; y++)
1342
			_cmd_decipher(wc, eframe, y);
1345
			_cmd_decipher(wc, eframe, y);
1343
		if (wc->vpmadt032)
1346
		if (wc->vpmadt032)
1344
			cmd_decipher_vpmadt032(wc, eframe);
1347
			cmd_decipher_vpmadt032(wc, eframe);
1345

    
   
1348

   
1346
		eframe += (EFRAME_SIZE + EFRAME_GAP);
1349
		eframe += (EFRAME_SIZE + EFRAME_GAP);
1347
	}
1350
	}
1348
	spin_unlock(&wc->reglock);
1351
	spin_unlock(&wc->reglock);
1349

    
   
1352

   
1350
	/* XXX We're wasting 8 taps.  We should get closer :( */
1353
	/* XXX We're wasting 8 taps.  We should get closer :( */
1351
	if (likely(wc->initialized)) {
1354
	if (likely(wc->initialized)) {
1352
		for (x = 0; x < wc->avchannels; x++) {
1355
		for (x = 0; x < wc->avchannels; x++) {
1353
			struct dahdi_chan *c = &wc->mods[x].chan->chan;
1356
			struct dahdi_chan *c = &wc->mods[x].chan->chan;
1354
#ifdef CONFIG_VOICEBUS_ECREFERENCE
1357
#ifdef CONFIG_VOICEBUS_ECREFERENCE
1355
			unsigned char buffer[DAHDI_CHUNKSIZE];
1358
			unsigned char buffer[DAHDI_CHUNKSIZE];
1356
			__dahdi_fifo_get(wc->ec_reference[x], buffer,
1359
			__dahdi_fifo_get(wc->ec_reference[x], buffer,
1357
				    ARRAY_SIZE(buffer));
1360
				    ARRAY_SIZE(buffer));
1358
			_dahdi_ec_chunk(c, c->readchunk, buffer);
1361
			_dahdi_ec_chunk(c, c->readchunk, buffer);
1359
#else
1362
#else
1360
			_dahdi_ec_chunk(c, c->readchunk, c->writechunk);
1363
			_dahdi_ec_chunk(c, c->readchunk, c->writechunk);
1361
#endif
1364
#endif
1362
		}
1365
		}
1363

    
   
1366

   
1364
		for (x = 0; x < MAX_SPANS; x++) {
1367
		for (x = 0; x < MAX_SPANS; x++) {
1365
			if (wc->spans[x]) {
1368
			if (wc->spans[x]) {
1366
				struct dahdi_span *s = &wc->spans[x]->span;
1369
				struct dahdi_span *s = &wc->spans[x]->span;
1367
#if 1
1370
#if 1
1368
				/* Check for digital spans */
1371
				/* Check for digital spans */
1369
				if (s->ops->chanconfig == b400m_chanconfig) {
1372
				if (s->ops->chanconfig == b400m_chanconfig) {
1370
					BUG_ON(!is_hx8(wc));
1373
					BUG_ON(!is_hx8(wc));
1371
					if (s->flags & DAHDI_FLAG_RUNNING)
1374
					if (s->flags & DAHDI_FLAG_RUNNING)
1372
						b400m_dchan(s);
1375
						b400m_dchan(s);
1373

    
   
1376

   
1374
				}
1377
				}
1375
#endif
1378
#endif
1376
				_dahdi_receive(s);
1379
				_dahdi_receive(s);
1377
				if (unlikely(irqmiss))
1380
				if (unlikely(irqmiss))
1378
					++s->irqmisses;
1381
					++s->irqmisses;
1379
			}
1382
			}
1380
		}
1383
		}
1381
	}
1384
	}
1382
}
1385
}
1383

    
   
1386

   
1384
static int wait_access(struct wctdm *wc, struct wctdm_module *const mod)
1387
static int wait_access(struct wctdm *wc, struct wctdm_module *const mod)
1385
{
1388
{
1386
	unsigned char data = 0;
1389
	unsigned char data = 0;
1387
	int count = 0;
1390
	int count = 0;
1388

    
   
1391

   
1389
	#define MAX 10 /* attempts */
1392
	#define MAX 10 /* attempts */
1390

    
   
1393

   
1391
	/* Wait for indirect access */
1394
	/* Wait for indirect access */
1392
	while (count++ < MAX) {
1395
	while (count++ < MAX) {
1393
		data = wctdm_getreg(wc, mod, I_STATUS);
1396
		data = wctdm_getreg(wc, mod, I_STATUS);
1394
		if (!data)
1397
		if (!data)
1395
			return 0;
1398
			return 0;
1396
	}
1399
	}
1397

    
   
1400

   
1398
	if (count > (MAX-1)) {
1401
	if (count > (MAX-1)) {
1399
		dev_notice(&wc->vb.pdev->dev,
1402
		dev_notice(&wc->vb.pdev->dev,
1400
			   " ##### Loop error (%02x) #####\n", data);
1403
			   " ##### Loop error (%02x) #####\n", data);
1401
	}
1404
	}
1402

    
   
1405

   
1403
	return 0;
1406
	return 0;
1404
}
1407
}
1405

    
   
1408

   
1406
static unsigned char translate_3215(unsigned char address)
1409
static unsigned char translate_3215(unsigned char address)
1407
{
1410
{
1408
	int x;
1411
	int x;
1409
	for (x = 0; x < ARRAY_SIZE(indirect_regs); x++) {
1412
	for (x = 0; x < ARRAY_SIZE(indirect_regs); x++) {
1410
		if (indirect_regs[x].address == address) {
1413
		if (indirect_regs[x].address == address) {
1411
			address = indirect_regs[x].altaddr;
1414
			address = indirect_regs[x].altaddr;
1412
			break;
1415
			break;
1413
		}
1416
		}
1414
	}
1417
	}
1415
	return address;
1418
	return address;
1416
}
1419
}
1417

    
   
1420

   
1418
static int
1421
static int
1419
wctdm_proslic_setreg_indirect(struct wctdm *wc, struct wctdm_module *const mod,
1422
wctdm_proslic_setreg_indirect(struct wctdm *wc, struct wctdm_module *const mod,
1420
			      unsigned char address, unsigned short data)
1423
			      unsigned char address, unsigned short data)
1421
{
1424
{
1422
	int res = -1;
1425
	int res = -1;
1423

    
   
1426

   
1424
	address = translate_3215(address);
1427
	address = translate_3215(address);
1425
	if (address == 255)
1428
	if (address == 255)
1426
		return 0;
1429
		return 0;
1427

    
   
1430

   
1428
	if (!wait_access(wc, mod)) {
1431
	if (!wait_access(wc, mod)) {
1429
		wctdm_setreg(wc, mod, IDA_LO, (u8)(data & 0xFF));
1432
		wctdm_setreg(wc, mod, IDA_LO, (u8)(data & 0xFF));
1430
		wctdm_setreg(wc, mod, IDA_HI, (u8)((data & 0xFF00)>>8));
1433
		wctdm_setreg(wc, mod, IDA_HI, (u8)((data & 0xFF00)>>8));
1431
		wctdm_setreg(wc, mod, IAA, address);
1434
		wctdm_setreg(wc, mod, IAA, address);
1432
		res = 0;
1435
		res = 0;
1433
	};
1436
	};
1434
	return res;
1437
	return res;
1435
}
1438
}
1436

    
   
1439

   
1437
static int
1440
static int

    
   
1441
wctdm_proslic_setreg_indirect_intr(struct wctdm *wc, struct wctdm_module *const mod,

    
   
1442
			      unsigned char address, unsigned short data)

    
   
1443
{

    
   
1444
	int res = -1;

    
   
1445

   

    
   
1446
	address = translate_3215(address);

    
   
1447
	if (address == 255)

    
   
1448
		return 0;

    
   
1449

   

    
   
1450
//	if (!wait_access(wc, mod)) {

    
   
1451
		wctdm_setreg_intr(wc, mod, IDA_LO, (u8)(data & 0xFF));

    
   
1452
		wctdm_setreg_intr(wc, mod, IDA_HI, (u8)((data & 0xFF00)>>8));

    
   
1453
		wctdm_setreg_intr(wc, mod, IAA, address);

    
   
1454
		res = 0;

    
   
1455
//	};

    
   
1456
	return res;

    
   
1457
}

    
   
1458

   

    
   
1459
static int
1438
wctdm_proslic_getreg_indirect(struct wctdm *wc, struct wctdm_module *const mod,
1460
wctdm_proslic_getreg_indirect(struct wctdm *wc, struct wctdm_module *const mod,
1439
			      unsigned char address)
1461
			      unsigned char address)
1440
{ 
1462
{ 
1441
	int res = -1;
1463
	int res = -1;
1442
	char *p=NULL;
1464
	char *p=NULL;
1443

    
   
1465

   
1444
	address = translate_3215(address);
1466
	address = translate_3215(address);
1445
	if (address == 255)
1467
	if (address == 255)
1446
		return 0;
1468
		return 0;
1447

    
   
1469

   
1448
	if (!wait_access(wc, mod)) {
1470
	if (!wait_access(wc, mod)) {
1449
		wctdm_setreg(wc, mod, IAA, address);
1471
		wctdm_setreg(wc, mod, IAA, address);
1450
		if (!wait_access(wc, mod)) {
1472
		if (!wait_access(wc, mod)) {
1451
			int addresses[2] = {IDA_LO, IDA_HI};
1473
			int addresses[2] = {IDA_LO, IDA_HI};
1452
			wctdm_getregs(wc, mod, addresses,
1474
			wctdm_getregs(wc, mod, addresses,
1453
				      ARRAY_SIZE(addresses));
1475
				      ARRAY_SIZE(addresses));
1454
			res = addresses[0] | (addresses[1] << 8);
1476
			res = addresses[0] | (addresses[1] << 8);
1455
		} else
1477
		} else
1456
			p = "Failed to wait inside\n";
1478
			p = "Failed to wait inside\n";
1457
	} else
1479
	} else
1458
		p = "failed to wait\n";
1480
		p = "failed to wait\n";
1459
	if (p)
1481
	if (p)
1460
		dev_notice(&wc->vb.pdev->dev, "%s", p);
1482
		dev_notice(&wc->vb.pdev->dev, "%s", p);
1461
	return res;
1483
	return res;
1462
}
1484
}
1463

    
   
1485

   
1464
static int
1486
static int
1465
wctdm_proslic_init_indirect_regs(struct wctdm *wc, struct wctdm_module *mod)
1487
wctdm_proslic_init_indirect_regs(struct wctdm *wc, struct wctdm_module *mod)
1466
{
1488
{
1467
	unsigned char i;
1489
	unsigned char i;
1468

    
   
1490

   
1469
	for (i = 0; i < ARRAY_SIZE(indirect_regs); i++) {
1491
	for (i = 0; i < ARRAY_SIZE(indirect_regs); i++) {
1470
		if (wctdm_proslic_setreg_indirect(wc, mod,
1492
		if (wctdm_proslic_setreg_indirect(wc, mod,
1471
				indirect_regs[i].address,
1493
				indirect_regs[i].address,
1472
				indirect_regs[i].initial))
1494
				indirect_regs[i].initial))
1473
			return -1;
1495
			return -1;
1474
	}
1496
	}
1475

    
   
1497

   
1476
	return 0;
1498
	return 0;
1477
}
1499
}
1478

    
   
1500

   
1479
static int
1501
static int
1480
wctdm_proslic_verify_indirect_regs(struct wctdm *wc, struct wctdm_module *mod)
1502
wctdm_proslic_verify_indirect_regs(struct wctdm *wc, struct wctdm_module *mod)
1481
{ 
1503
{ 
1482
	int passed = 1;
1504
	int passed = 1;
1483
	unsigned short i, initial;
1505
	unsigned short i, initial;
1484
	int j;
1506
	int j;
1485

    
   
1507

   
1486
	for (i = 0; i < ARRAY_SIZE(indirect_regs); i++) {
1508
	for (i = 0; i < ARRAY_SIZE(indirect_regs); i++) {
1487
		j = wctdm_proslic_getreg_indirect(wc, mod,
1509
		j = wctdm_proslic_getreg_indirect(wc, mod,
1488
						(u8)indirect_regs[i].address);
1510
						(u8)indirect_regs[i].address);
1489
		if (j < 0) {
1511
		if (j < 0) {
1490
			dev_notice(&wc->vb.pdev->dev, "Failed to read indirect register %d\n", i);
1512
			dev_notice(&wc->vb.pdev->dev, "Failed to read indirect register %d\n", i);
1491
			return -1;
1513
			return -1;
1492
		}
1514
		}
1493
		initial = indirect_regs[i].initial;
1515
		initial = indirect_regs[i].initial;
1494

    
   
1516

   
1495
		if ((j != initial) && (indirect_regs[i].altaddr != 255)) {
1517
		if ((j != initial) && (indirect_regs[i].altaddr != 255)) {
1496
			dev_notice(&wc->vb.pdev->dev,
1518
			dev_notice(&wc->vb.pdev->dev,
1497
				   "!!!!!!! %s  iREG %X = %X  should be %X\n",
1519
				   "!!!!!!! %s  iREG %X = %X  should be %X\n",
1498
				   indirect_regs[i].name,
1520
				   indirect_regs[i].name,
1499
				   indirect_regs[i].address, j, initial);
1521
				   indirect_regs[i].address, j, initial);
1500
			 passed = 0;
1522
			 passed = 0;
1501
		}	
1523
		}	
1502
	}
1524
	}
1503

    
   
1525

   
1504
	if (passed) {
1526
	if (passed) {
1505
		if (debug & DEBUG_CARD) {
1527
		if (debug & DEBUG_CARD) {
1506
			dev_info(&wc->vb.pdev->dev,
1528
			dev_info(&wc->vb.pdev->dev,
1507
			 "Init Indirect Registers completed successfully.\n");
1529
			 "Init Indirect Registers completed successfully.\n");
1508
		}
1530
		}
1509
	} else {
1531
	} else {
1510
		dev_notice(&wc->vb.pdev->dev,
1532
		dev_notice(&wc->vb.pdev->dev,
1511
			" !!!!! Init Indirect Registers UNSUCCESSFULLY.\n");
1533
			" !!!!! Init Indirect Registers UNSUCCESSFULLY.\n");
1512
		return -1;
1534
		return -1;
1513
	}
1535
	}
1514
	return 0;
1536
	return 0;
1515
}
1537
}
1516

    
   
1538

   
1517
/* 1ms interrupt */
1539
/* 1ms interrupt */
1518
static void
1540
static void
1519
wctdm_proslic_check_oppending(struct wctdm *wc, struct wctdm_module *const mod)
1541
wctdm_proslic_check_oppending(struct wctdm *wc, struct wctdm_module *const mod)
1520
{
1542
{
1521
	struct fxs *const fxs = &mod->mod.fxs;
1543
	struct fxs *const fxs = &mod->mod.fxs;
1522
	unsigned long flags;
1544
	unsigned long flags;
1523
	int res;
1545
	int res;
1524

    
   
1546

   
1525
	if (!(fxs->lasttxhook & SLIC_LF_OPPENDING))
1547
	if (!(fxs->lasttxhook & SLIC_LF_OPPENDING))
1526
		return;
1548
		return;
1527

    
   
1549

   
1528
	/* Monitor the Pending LF state change, for the next 100ms */
1550
	/* Monitor the Pending LF state change, for the next 100ms */
1529
	spin_lock_irqsave(&fxs->lasttxhooklock, flags);
1551
	spin_lock_irqsave(&fxs->lasttxhooklock, flags);
1530

    
   
1552

   
1531
	if (!(fxs->lasttxhook & SLIC_LF_OPPENDING)) {
1553
	if (!(fxs->lasttxhook & SLIC_LF_OPPENDING)) {
1532
		spin_unlock_irqrestore(&fxs->lasttxhooklock, flags);
1554
		spin_unlock_irqrestore(&fxs->lasttxhooklock, flags);
1533
		return;
1555
		return;
1534
	}
1556
	}
1535

    
   
1557

   
1536
	res = mod->isrshadow[1];
1558
	res = mod->isrshadow[1];
1537
	if ((res & SLIC_LF_SETMASK) == (fxs->lasttxhook & SLIC_LF_SETMASK)) {
1559
	if ((res & SLIC_LF_SETMASK) == (fxs->lasttxhook & SLIC_LF_SETMASK)) {
1538
		fxs->lasttxhook &= SLIC_LF_SETMASK;
1560
		fxs->lasttxhook &= SLIC_LF_SETMASK;
1539
		fxs->oppending_ms = 0;
1561
		fxs->oppending_ms = 0;
1540
		if (debug & DEBUG_CARD) {
1562
		if (debug & DEBUG_CARD) {
1541
			dev_info(&wc->vb.pdev->dev,
1563
			dev_info(&wc->vb.pdev->dev,
1542
				 "SLIC_LF OK: card=%d shadow=%02x "
1564
				 "SLIC_LF OK: card=%d shadow=%02x "
1543
				 "lasttxhook=%02x intcount=%d\n", mod->card,
1565
				 "lasttxhook=%02x intcount=%d\n", mod->card,
1544
				 res, fxs->lasttxhook, wc->intcount);
1566
				 res, fxs->lasttxhook, wc->intcount);
1545
		}
1567
		}
1546
	} else if (fxs->oppending_ms && (--fxs->oppending_ms == 0)) {
1568
	} else if (fxs->oppending_ms && (--fxs->oppending_ms == 0)) {
1547
		wctdm_setreg_intr(wc, mod, LINE_STATE, fxs->lasttxhook);
1569
		wctdm_setreg_intr(wc, mod, LINE_STATE, fxs->lasttxhook);
1548
		if (debug & DEBUG_CARD) {
1570
		if (debug & DEBUG_CARD) {
1549
			dev_info(&wc->vb.pdev->dev,
1571
			dev_info(&wc->vb.pdev->dev,
1550
				 "SLIC_LF RETRY: card=%d shadow=%02x "
1572
				 "SLIC_LF RETRY: card=%d shadow=%02x "
1551
				 "lasttxhook=%02x intcount=%d\n", mod->card,
1573
				 "lasttxhook=%02x intcount=%d\n", mod->card,
1552
				 res, fxs->lasttxhook, wc->intcount);
1574
				 res, fxs->lasttxhook, wc->intcount);
1553
		}
1575
		}
1554
	} else { /* Start 100ms Timeout */
1576
	} else { /* Start 100ms Timeout */
1555
		fxs->oppending_ms = 100;
1577
		fxs->oppending_ms = 100;
1556
	}
1578
	}
1557
	spin_unlock_irqrestore(&fxs->lasttxhooklock, flags);
1579
	spin_unlock_irqrestore(&fxs->lasttxhooklock, flags);
1558
}
1580
}
1559

    
   
1581

   
1560
/* 256ms interrupt */
1582
/* 256ms interrupt */
1561
static void
1583
static void
1562
wctdm_proslic_recheck_sanity(struct wctdm *wc, struct wctdm_module *const mod)
1584
wctdm_proslic_recheck_sanity(struct wctdm *wc, struct wctdm_module *const mod)
1563
{
1585
{
1564
	struct fxs *const fxs = &mod->mod.fxs;
1586
	struct fxs *const fxs = &mod->mod.fxs;
1565
	int res;
1587
	int res;
1566
	unsigned long flags;
1588
	unsigned long flags;
1567
#ifdef PAQ_DEBUG
1589
#ifdef PAQ_DEBUG
1568
	res = mod->isrshadow[1];
1590
	res = mod->isrshadow[1];
1569
	res &= ~0x3;
1591
	res &= ~0x3;
1570
	if (res) {
1592
	if (res) {
1571
		mod->isrshadow[1] = 0;
1593
		mod->isrshadow[1] = 0;
1572
		fxs->palarms++;
1594
		fxs->palarms++;
1573
		if (fxs->palarms < MAX_ALARMS) {
1595
		if (fxs->palarms < MAX_ALARMS) {
1574
			dev_notice(&wc->vb.pdev->dev, "Power alarm (%02x) on module %d, resetting!\n", res, card + 1);
1596
			dev_notice(&wc->vb.pdev->dev, "Power alarm (%02x) on module %d, resetting!\n", res, card + 1);
1575
			mod->sethook = CMD_WR(19, res);
1597
			mod->sethook = CMD_WR(19, res);
1576
			/* Update shadow register to avoid extra power alarms until next read */
1598
			/* Update shadow register to avoid extra power alarms until next read */
1577
			mod->isrshadow[1] = 0;
1599
			mod->isrshadow[1] = 0;
1578
		} else {
1600
		} else {
1579
			if (fxs->palarms == MAX_ALARMS)
1601
			if (fxs->palarms == MAX_ALARMS)
1580
				dev_notice(&wc->vb.pdev->dev, "Too many power alarms on card %d, NOT resetting!\n", card + 1);
1602
				dev_notice(&wc->vb.pdev->dev, "Too many power alarms on card %d, NOT resetting!\n", card + 1);
1581
		}
1603
		}
1582
	}
1604
	}
1583
#else
1605
#else
1584
	spin_lock_irqsave(&fxs->lasttxhooklock, flags);
1606
	spin_lock_irqsave(&fxs->lasttxhooklock, flags);
1585
	res = mod->isrshadow[1];
1607
	res = mod->isrshadow[1];
1586

    
   
1608

   
1587
#if 0
1609
#if 0
1588
	/* This makes sure the lasthook was put in reg 64 the linefeed reg */
1610
	/* This makes sure the lasthook was put in reg 64 the linefeed reg */
1589
	if (fxs->lasttxhook & SLIC_LF_OPPENDING) {
1611
	if (fxs->lasttxhook & SLIC_LF_OPPENDING) {
1590
		if ((res & SLIC_LF_SETMASK) == (fxs->lasttxhook & SLIC_LF_SETMASK)) {
1612
		if ((res & SLIC_LF_SETMASK) == (fxs->lasttxhook & SLIC_LF_SETMASK)) {
1591
			fxs->lasttxhook &= SLIC_LF_SETMASK;
1613
			fxs->lasttxhook &= SLIC_LF_SETMASK;
1592
			if (debug & DEBUG_CARD) {
1614
			if (debug & DEBUG_CARD) {
1593
				dev_info(&wc->vb.pdev->dev, "SLIC_LF OK: intcount=%d channel=%d shadow=%02x lasttxhook=%02x\n", wc->intcount, card, res, fxs->lasttxhook);
1615
				dev_info(&wc->vb.pdev->dev, "SLIC_LF OK: intcount=%d channel=%d shadow=%02x lasttxhook=%02x\n", wc->intcount, card, res, fxs->lasttxhook);
1594
			}
1616
			}
1595
		} else if (!(wc->intcount & 0x03)) {
1617
		} else if (!(wc->intcount & 0x03)) {
1596
			mod->sethook = CMD_WR(LINE_STATE, fxs->lasttxhook);
1618
			mod->sethook = CMD_WR(LINE_STATE, fxs->lasttxhook);
1597
			if (debug & DEBUG_CARD) {
1619
			if (debug & DEBUG_CARD) {
1598
				dev_info(&wc->vb.pdev->dev, "SLIC_LF RETRY: intcount=%d channel=%d shadow=%02x lasttxhook=%02x\n", wc->intcount, card, res, fxs->lasttxhook);
1620
				dev_info(&wc->vb.pdev->dev, "SLIC_LF RETRY: intcount=%d channel=%d shadow=%02x lasttxhook=%02x\n", wc->intcount, card, res, fxs->lasttxhook);
1599
			}
1621
			}
1600
		}
1622
		}
1601
	}
1623
	}
1602
	if (debug & DEBUG_CARD) {
1624
	if (debug & DEBUG_CARD) {
1603
		if (!(wc->intcount % 100)) {
1625
		if (!(wc->intcount % 100)) {
1604
			dev_info(&wc->vb.pdev->dev, "SLIC_LF DEBUG: intcount=%d channel=%d shadow=%02x lasttxhook=%02x\n", wc->intcount, card, res, fxs->lasttxhook);
1626
			dev_info(&wc->vb.pdev->dev, "SLIC_LF DEBUG: intcount=%d channel=%d shadow=%02x lasttxhook=%02x\n", wc->intcount, card, res, fxs->lasttxhook);
1605
		}
1627
		}
1606
	}
1628
	}
1607
#endif
1629
#endif
1608

    
   
1630

   
1609
	res = !res &&    /* reg 64 has to be zero at last isr read */
1631
	res = !res &&    /* reg 64 has to be zero at last isr read */
1610
		!(fxs->lasttxhook & SLIC_LF_OPPENDING) && /* not a transition */
1632
		!(fxs->lasttxhook & SLIC_LF_OPPENDING) && /* not a transition */
1611
		fxs->lasttxhook; /* not an intended zero */
1633
		fxs->lasttxhook; /* not an intended zero */
1612
	spin_unlock_irqrestore(&fxs->lasttxhooklock, flags);
1634
	spin_unlock_irqrestore(&fxs->lasttxhooklock, flags);
1613
	
1635
	
1614
	if (res) {
1636
	if (res) {
1615
		fxs->palarms++;
1637
		fxs->palarms++;
1616
		if (fxs->palarms < MAX_ALARMS) {
1638
		if (fxs->palarms < MAX_ALARMS) {
1617
			dev_notice(&wc->vb.pdev->dev,
1639
			dev_notice(&wc->vb.pdev->dev,
1618
				   "Power alarm on module %d, resetting!\n",
1640
				   "Power alarm on module %d, resetting!\n",
1619
				   mod->card + 1);
1641
				   mod->card + 1);
1620
			spin_lock_irqsave(&fxs->lasttxhooklock, flags);
1642
			spin_lock_irqsave(&fxs->lasttxhooklock, flags);
1621
			if (fxs->lasttxhook == SLIC_LF_RINGING) {
1643
			if (fxs->lasttxhook == SLIC_LF_RINGING) {
1622
				fxs->lasttxhook = POLARITY_XOR(fxs) ?
1644
				fxs->lasttxhook = POLARITY_XOR(fxs) ?
1623
							SLIC_LF_ACTIVE_REV :
1645
							SLIC_LF_ACTIVE_REV :
1624
							SLIC_LF_ACTIVE_FWD;;
1646
							SLIC_LF_ACTIVE_FWD;
1625
			}
1647
			}
1626
			fxs->lasttxhook |= SLIC_LF_OPPENDING;
1648
			fxs->lasttxhook |= SLIC_LF_OPPENDING;
1627
			mod->sethook = CMD_WR(LINE_STATE, fxs->lasttxhook);
1649
			mod->sethook = CMD_WR(LINE_STATE, fxs->lasttxhook);
1628
			spin_unlock_irqrestore(&fxs->lasttxhooklock, flags);
1650
			spin_unlock_irqrestore(&fxs->lasttxhooklock, flags);
1629

    
   
1651

   
1630
			/* Update shadow register to avoid extra power alarms until next read */
1652
			/* Update shadow register to avoid extra power alarms until next read */
1631
			mod->isrshadow[1] = fxs->lasttxhook;
1653
			mod->isrshadow[1] = fxs->lasttxhook;
1632
		} else {
1654
		} else {
1633
			if (fxs->palarms == MAX_ALARMS) {
1655
			if (fxs->palarms == MAX_ALARMS) {
1634
				dev_notice(&wc->vb.pdev->dev,
1656
				dev_notice(&wc->vb.pdev->dev,
1635
					   "Too many power alarms on card %d, "
1657
					   "Too many power alarms on card %d, "
1636
					   "NOT resetting!\n", mod->card + 1);
1658
					   "NOT resetting!\n", mod->card + 1);
1637
			}
1659
			}
1638
		}
1660
		}
1639
	}
1661
	}
1640
#endif
1662
#endif
1641
}
1663
}
1642

    
   
1664

   
1643
static void wctdm_qrvdri_check_hook(struct wctdm *wc, int card)
1665
static void wctdm_qrvdri_check_hook(struct wctdm *wc, int card)
1644
{
1666
{
1645
	signed char b,b1;
1667
	signed char b,b1;
1646
	int qrvcard = card & 0xfc;
1668
	int qrvcard = card & 0xfc;
1647

    
   
1669

   
1648
	if (wc->mods[card].mod.qrv.debtime >= 2)
1670
	if (wc->mods[card].mod.qrv.debtime >= 2)
1649
		wc->mods[card].mod.qrv.debtime--;
1671
		wc->mods[card].mod.qrv.debtime--;
1650
	b = wc->mods[qrvcard].isrshadow[0]; /* Hook/Ring state */
1672
	b = wc->mods[qrvcard].isrshadow[0]; /* Hook/Ring state */
1651
	b &= 0xcc; /* use bits 3-4 and 6-7 only */
1673
	b &= 0xcc; /* use bits 3-4 and 6-7 only */
1652

    
   
1674

   
1653
	if (wc->mods[qrvcard].mod.qrv.radmode & RADMODE_IGNORECOR)
1675
	if (wc->mods[qrvcard].mod.qrv.radmode & RADMODE_IGNORECOR)
1654
		b &= ~4;
1676
		b &= ~4;
1655
	else if (!(wc->mods[qrvcard].mod.qrv.radmode & RADMODE_INVERTCOR))
1677
	else if (!(wc->mods[qrvcard].mod.qrv.radmode & RADMODE_INVERTCOR))
1656
		b ^= 4;
1678
		b ^= 4;
1657
	if (wc->mods[qrvcard + 1].mod.qrv.radmode | RADMODE_IGNORECOR)
1679
	if (wc->mods[qrvcard + 1].mod.qrv.radmode | RADMODE_IGNORECOR)
1658
		b &= ~0x40;
1680
		b &= ~0x40;
1659
	else if (!(wc->mods[qrvcard + 1].mod.qrv.radmode | RADMODE_INVERTCOR))
1681
	else if (!(wc->mods[qrvcard + 1].mod.qrv.radmode | RADMODE_INVERTCOR))
1660
		b ^= 0x40;
1682
		b ^= 0x40;
1661

    
   
1683

   
1662
	if ((wc->mods[qrvcard].mod.qrv.radmode & RADMODE_IGNORECT) ||
1684
	if ((wc->mods[qrvcard].mod.qrv.radmode & RADMODE_IGNORECT) ||
1663
	    (!(wc->mods[qrvcard].mod.qrv.radmode & RADMODE_EXTTONE)))
1685
	    (!(wc->mods[qrvcard].mod.qrv.radmode & RADMODE_EXTTONE)))
1664
		b &= ~8;
1686
		b &= ~8;
1665
	else if (!(wc->mods[qrvcard].mod.qrv.radmode & RADMODE_EXTINVERT))
1687
	else if (!(wc->mods[qrvcard].mod.qrv.radmode & RADMODE_EXTINVERT))
1666
		b ^= 8;
1688
		b ^= 8;
1667
	if ((wc->mods[qrvcard + 1].mod.qrv.radmode & RADMODE_IGNORECT) ||
1689
	if ((wc->mods[qrvcard + 1].mod.qrv.radmode & RADMODE_IGNORECT) ||
1668
	    (!(wc->mods[qrvcard + 1].mod.qrv.radmode & RADMODE_EXTTONE)))
1690
	    (!(wc->mods[qrvcard + 1].mod.qrv.radmode & RADMODE_EXTTONE)))
1669
		b &= ~0x80;
1691
		b &= ~0x80;
1670
	else if (!(wc->mods[qrvcard + 1].mod.qrv.radmode & RADMODE_EXTINVERT))
1692
	else if (!(wc->mods[qrvcard + 1].mod.qrv.radmode & RADMODE_EXTINVERT))
1671
		b ^= 0x80;
1693
		b ^= 0x80;
1672
	/* now b & MASK should be zero, if its active */
1694
	/* now b & MASK should be zero, if its active */
1673
	/* check for change in chan 0 */
1695
	/* check for change in chan 0 */
1674
	if ((!(b & 0xc)) != wc->mods[qrvcard + 2].mod.qrv.hook)
1696
	if ((!(b & 0xc)) != wc->mods[qrvcard + 2].mod.qrv.hook)
1675
	{
1697
	{
1676
		wc->mods[qrvcard].mod.qrv.debtime = wc->mods[qrvcard].mod.qrv.debouncetime;
1698
		wc->mods[qrvcard].mod.qrv.debtime = wc->mods[qrvcard].mod.qrv.debouncetime;
1677
		wc->mods[qrvcard + 2].mod.qrv.hook = !(b & 0xc);
1699
		wc->mods[qrvcard + 2].mod.qrv.hook = !(b & 0xc);
1678
	} 
1700
	} 
1679
	/* if timed-out and ready */
1701
	/* if timed-out and ready */
1680
	if (wc->mods[qrvcard].mod.qrv.debtime == 1) {
1702
	if (wc->mods[qrvcard].mod.qrv.debtime == 1) {
1681
		b1 = wc->mods[qrvcard + 2].mod.qrv.hook;
1703
		b1 = wc->mods[qrvcard + 2].mod.qrv.hook;
1682
		if (debug) {
1704
		if (debug) {
1683
			dev_info(&wc->vb.pdev->dev,
1705
			dev_info(&wc->vb.pdev->dev,
1684
				 "QRV channel %d rx state changed to %d\n",
1706
				 "QRV channel %d rx state changed to %d\n",
1685
				 qrvcard, wc->mods[qrvcard + 2].mod.qrv.hook);
1707
				 qrvcard, wc->mods[qrvcard + 2].mod.qrv.hook);
1686
		}
1708
		}
1687
		dahdi_hooksig(wc->aspan->span.chans[qrvcard],
1709
		dahdi_hooksig(wc->aspan->span.chans[qrvcard],
1688
			(b1) ? DAHDI_RXSIG_OFFHOOK : DAHDI_RXSIG_ONHOOK);
1710
			(b1) ? DAHDI_RXSIG_OFFHOOK : DAHDI_RXSIG_ONHOOK);
1689
		wc->mods[card].mod.qrv.debtime = 0;
1711
		wc->mods[card].mod.qrv.debtime = 0;
1690
	}
1712
	}
1691
	/* check for change in chan 1 */
1713
	/* check for change in chan 1 */
1692
	if ((!(b & 0xc0)) != wc->mods[qrvcard + 3].mod.qrv.hook)
1714
	if ((!(b & 0xc0)) != wc->mods[qrvcard + 3].mod.qrv.hook)
1693
	{
1715
	{
1694
		wc->mods[qrvcard + 1].mod.qrv.debtime = QRV_DEBOUNCETIME;
1716
		wc->mods[qrvcard + 1].mod.qrv.debtime = QRV_DEBOUNCETIME;
1695
		wc->mods[qrvcard + 3].mod.qrv.hook = !(b & 0xc0);
1717
		wc->mods[qrvcard + 3].mod.qrv.hook = !(b & 0xc0);
1696
	}
1718
	}
1697
	if (wc->mods[qrvcard + 1].mod.qrv.debtime == 1) {
1719
	if (wc->mods[qrvcard + 1].mod.qrv.debtime == 1) {
1698
		b1 = wc->mods[qrvcard + 3].mod.qrv.hook;
1720
		b1 = wc->mods[qrvcard + 3].mod.qrv.hook;
1699
		if (debug) {
1721
		if (debug) {
1700
			dev_info(&wc->vb.pdev->dev,
1722
			dev_info(&wc->vb.pdev->dev,
1701
				 "QRV channel %d rx state changed to %d\n",
1723
				 "QRV channel %d rx state changed to %d\n",
1702
				 qrvcard + 1, wc->mods[qrvcard + 3].mod.qrv.hook);
1724
				 qrvcard + 1, wc->mods[qrvcard + 3].mod.qrv.hook);
1703
		}
1725
		}
1704
		dahdi_hooksig(wc->aspan->span.chans[qrvcard + 1],
1726
		dahdi_hooksig(wc->aspan->span.chans[qrvcard + 1],
1705
			(b1) ? DAHDI_RXSIG_OFFHOOK : DAHDI_RXSIG_ONHOOK);
1727
			(b1) ? DAHDI_RXSIG_OFFHOOK : DAHDI_RXSIG_ONHOOK);
1706
		wc->mods[card].mod.qrv.debtime = 0;
1728
		wc->mods[card].mod.qrv.debtime = 0;
1707
	}
1729
	}
1708
	return;
1730
	return;
1709
}
1731
}
1710

    
   
1732

   
1711
static void
1733
static void
1712
wctdm_voicedaa_check_hook(struct wctdm *wc, struct wctdm_module *const mod)
1734
wctdm_voicedaa_check_hook(struct wctdm *wc, struct wctdm_module *const mod)
1713
{
1735
{
1714
#define MS_PER_CHECK_HOOK 1
1736
#define MS_PER_CHECK_HOOK 1
1715

    
   
1737

   
1716
	unsigned char res;
1738
	unsigned char res;
1717
	signed char b;
1739
	signed char b;
1718
	unsigned int abs_voltage;
1740
	unsigned int abs_voltage;
1719
	struct fxo *const fxo = &mod->mod.fxo;
1741
	struct fxo *const fxo = &mod->mod.fxo;
1720

    
   
1742

   
1721
	/* Try to track issues that plague slot one FXO's */
1743
	/* Try to track issues that plague slot one FXO's */
1722
	b = mod->isrshadow[0];	/* Hook/Ring state */
1744
	b = mod->isrshadow[0];	/* Hook/Ring state */
1723
	b &= 0x9b;
1745
	b &= 0x9b;
1724
	if (fxo->offhook) {
1746
	if (fxo->offhook) {
1725
		if (b != 0x9)
1747
		if (b != 0x9)
1726
			wctdm_setreg_intr(wc, mod, 5, 0x9);
1748
			wctdm_setreg_intr(wc, mod, 5, 0x9);
1727
	} else {
1749
	} else {
1728
		if (b != 0x8)
1750
		if (b != 0x8)
1729
			wctdm_setreg_intr(wc, mod, 5, 0x8);
1751
			wctdm_setreg_intr(wc, mod, 5, 0x8);
1730
	}
1752
	}
1731
	if (!fxo->offhook) {
1753
	if (!fxo->offhook) {
1732
		if (fwringdetect || neonmwi_monitor) {
1754
		if (fwringdetect || neonmwi_monitor) {
1733
			/* Look for ring status bits (Ring Detect Signal Negative and
1755
			/* Look for ring status bits (Ring Detect Signal Negative and
1734
			* Ring Detect Signal Positive) to transition back and forth
1756
			* Ring Detect Signal Positive) to transition back and forth
1735
			* some number of times to indicate that a ring is occurring.
1757
			* some number of times to indicate that a ring is occurring.
1736
			* Provide some number of samples to allow for the transitions
1758
			* Provide some number of samples to allow for the transitions
1737
			* to occur before ginving up.
1759
			* to occur before ginving up.
1738
			* NOTE: neon mwi voltages will trigger one of these bits to go active
1760
			* NOTE: neon mwi voltages will trigger one of these bits to go active
1739
			* but not to have transitions between the two bits (i.e. no negative
1761
			* but not to have transitions between the two bits (i.e. no negative
1740
			* to positive or positive to negative transversals )
1762
			* to positive or positive to negative transversals )
1741
			*/
1763
			*/
1742
			res =  mod->isrshadow[0] & 0x60;
1764
			res =  mod->isrshadow[0] & 0x60;
1743
			if (0 == fxo->wasringing) {
1765
			if (0 == fxo->wasringing) {
1744
				if (res) {
1766
				if (res) {
1745
					/* Look for positive/negative crossings in ring status reg */
1767
					/* Look for positive/negative crossings in ring status reg */
1746
					fxo->wasringing = 2;
1768
					fxo->wasringing = 2;
1747
					fxo->ringdebounce = ringdebounce /16;
1769
					fxo->ringdebounce = ringdebounce /16;
1748
					fxo->lastrdtx = res;
1770
					fxo->lastrdtx = res;
1749
					fxo->lastrdtx_count = 0;
1771
					fxo->lastrdtx_count = 0;
1750
				}
1772
				}
1751
			} else if (2 == fxo->wasringing) {
1773
			} else if (2 == fxo->wasringing) {
1752
				/* If ring detect signal has transversed */
1774
				/* If ring detect signal has transversed */
1753
				if (res && res != fxo->lastrdtx) {
1775
				if (res && res != fxo->lastrdtx) {
1754
					/* if there are at least 3 ring polarity transversals */
1776
					/* if there are at least 3 ring polarity transversals */
1755
					if (++fxo->lastrdtx_count >= 2) {
1777
					if (++fxo->lastrdtx_count >= 2) {
1756
						fxo->wasringing = 1;
1778
						fxo->wasringing = 1;
1757
						if (debug)
1779
						if (debug)
1758
							dev_info(&wc->vb.pdev->dev, "FW RING on %d/%d!\n", wc->aspan->span.spanno, mod->card + 1);
1780
							dev_info(&wc->vb.pdev->dev, "FW RING on %d/%d!\n", wc->aspan->span.spanno, mod->card + 1);
1759
						dahdi_hooksig(&mod->chan->chan, DAHDI_RXSIG_RING);
1781
						dahdi_hooksig(&mod->chan->chan, DAHDI_RXSIG_RING);
1760
						fxo->ringdebounce = ringdebounce / 16;
1782
						fxo->ringdebounce = ringdebounce / 16;
1761
					} else {
1783
					} else {
1762
						fxo->lastrdtx = res;
1784
						fxo->lastrdtx = res;
1763
						fxo->ringdebounce = ringdebounce / 16;
1785
						fxo->ringdebounce = ringdebounce / 16;
1764
					}
1786
					}
1765
					/* ring indicator (positve or negative) has not transitioned, check debounce count */
1787
					/* ring indicator (positve or negative) has not transitioned, check debounce count */
1766
				} else if (--fxo->ringdebounce == 0) {
1788
				} else if (--fxo->ringdebounce == 0) {
1767
					fxo->wasringing = 0;
1789
					fxo->wasringing = 0;
1768
				}
1790
				}
1769
			} else {  /* I am in ring state */
1791
			} else {  /* I am in ring state */
1770
				if (res) { /* If any ringdetect bits are still active */
1792
				if (res) { /* If any ringdetect bits are still active */
1771
					fxo->ringdebounce = ringdebounce / 16;
1793
					fxo->ringdebounce = ringdebounce / 16;
1772
				} else if (--fxo->ringdebounce == 0) {
1794
				} else if (--fxo->ringdebounce == 0) {
1773
					fxo->wasringing = 0;
1795
					fxo->wasringing = 0;
1774
					if (debug)
1796
					if (debug)
1775
						dev_info(&wc->vb.pdev->dev, "FW NO RING on %d/%d!\n", wc->aspan->span.spanno, mod->card + 1);
1797
						dev_info(&wc->vb.pdev->dev, "FW NO RING on %d/%d!\n", wc->aspan->span.spanno, mod->card + 1);
1776
					dahdi_hooksig(&mod->chan->chan, DAHDI_RXSIG_OFFHOOK);
1798
					dahdi_hooksig(&mod->chan->chan, DAHDI_RXSIG_OFFHOOK);
1777
				}
1799
				}
1778
			}
1800
			}
1779
		} else {
1801
		} else {
1780
			res =  mod->isrshadow[0];
1802
			res =  mod->isrshadow[0];
1781
			if ((res & 0x60) && (fxo->battery == BATTERY_PRESENT)) {
1803
			if ((res & 0x60) && (fxo->battery == BATTERY_PRESENT)) {
1782
				fxo->ringdebounce += (DAHDI_CHUNKSIZE * 16);
1804
				fxo->ringdebounce += (DAHDI_CHUNKSIZE * 16);
1783
				if (fxo->ringdebounce >= DAHDI_CHUNKSIZE * ringdebounce) {
1805
				if (fxo->ringdebounce >= DAHDI_CHUNKSIZE * ringdebounce) {
1784
					if (!fxo->wasringing) {
1806
					if (!fxo->wasringing) {
1785
						fxo->wasringing = 1;
1807
						fxo->wasringing = 1;
1786
						dahdi_hooksig(&mod->chan->chan, DAHDI_RXSIG_RING);
1808
						dahdi_hooksig(&mod->chan->chan, DAHDI_RXSIG_RING);
1787
						if (debug)
1809
						if (debug)
1788
							dev_info(&wc->vb.pdev->dev, "RING on %d/%d!\n", wc->aspan->span.spanno, mod->card + 1);
1810
							dev_info(&wc->vb.pdev->dev, "RING on %d/%d!\n", wc->aspan->span.spanno, mod->card + 1);
1789
					}
1811
					}
1790
					fxo->ringdebounce = DAHDI_CHUNKSIZE * ringdebounce;
1812
					fxo->ringdebounce = DAHDI_CHUNKSIZE * ringdebounce;
1791
				}
1813
				}
1792
			} else {
1814
			} else {
1793
				fxo->ringdebounce -= DAHDI_CHUNKSIZE * 4;
1815
				fxo->ringdebounce -= DAHDI_CHUNKSIZE * 4;
1794
				if (fxo->ringdebounce <= 0) {
1816
				if (fxo->ringdebounce <= 0) {
1795
					if (fxo->wasringing) {
1817
					if (fxo->wasringing) {
1796
						fxo->wasringing = 0;
1818
						fxo->wasringing = 0;
1797
						dahdi_hooksig(&mod->chan->chan, DAHDI_RXSIG_OFFHOOK);
1819
						dahdi_hooksig(&mod->chan->chan, DAHDI_RXSIG_OFFHOOK);
1798
						if (debug)
1820
						if (debug)
1799
							dev_info(&wc->vb.pdev->dev, "NO RING on %d/%d!\n", wc->aspan->span.spanno, mod->card + 1);
1821
							dev_info(&wc->vb.pdev->dev, "NO RING on %d/%d!\n", wc->aspan->span.spanno, mod->card + 1);
1800
					}
1822
					}
1801
					fxo->ringdebounce = 0;
1823
					fxo->ringdebounce = 0;
1802
				}
1824
				}
1803
					
1825
					
1804
			}
1826
			}
1805
		}
1827
		}
1806
	}
1828
	}
1807

    
   
1829

   
1808
	b = mod->isrshadow[1]; /* Voltage */
1830
	b = mod->isrshadow[1]; /* Voltage */
1809
	abs_voltage = abs(b);
1831
	abs_voltage = abs(b);
1810

    
   
1832

   
1811
	if (fxovoltage) {
1833
	if (fxovoltage) {
1812
		if (!(wc->intcount % 100)) {
1834
		if (!(wc->intcount % 100)) {
1813
			dev_info(&wc->vb.pdev->dev, "Port %d: Voltage: %d  Debounce %d\n", mod->card + 1, b, fxo->battdebounce);
1835
			dev_info(&wc->vb.pdev->dev, "Port %d: Voltage: %d  Debounce %d\n", mod->card + 1, b, fxo->battdebounce);
1814
		}
1836
		}
1815
	}
1837
	}
1816

    
   
1838

   
1817
	if (unlikely(DAHDI_RXSIG_INITIAL == mod->chan->chan.rxhooksig)) {
1839
	if (unlikely(DAHDI_RXSIG_INITIAL == mod->chan->chan.rxhooksig)) {
1818
		/*
1840
		/*
1819
		 * dahdi-base will set DAHDI_RXSIG_INITIAL after a
1841
		 * dahdi-base will set DAHDI_RXSIG_INITIAL after a
1820
		 * DAHDI_STARTUP or DAHDI_CHANCONFIG ioctl so that new events
1842
		 * DAHDI_STARTUP or DAHDI_CHANCONFIG ioctl so that new events
1821
		 * will be queued on the channel with the current received
1843
		 * will be queued on the channel with the current received
1822
		 * hook state.  Channels that use robbed-bit signalling always
1844
		 * hook state.  Channels that use robbed-bit signalling always
1823
		 * report the current received state via the dahdi_rbsbits
1845
		 * report the current received state via the dahdi_rbsbits
1824
		 * call. Since we only call dahdi_hooksig when we've detected
1846
		 * call. Since we only call dahdi_hooksig when we've detected
1825
		 * a change to report, let's forget our current state in order
1847
		 * a change to report, let's forget our current state in order
1826
		 * to force us to report it again via dahdi_hooksig.
1848
		 * to force us to report it again via dahdi_hooksig.
1827
		 *
1849
		 *
1828
		 */
1850
		 */
1829
		fxo->battery = BATTERY_UNKNOWN;
1851
		fxo->battery = BATTERY_UNKNOWN;
1830
	}
1852
	}
1831

    
   
1853

   
1832
	if (abs_voltage < battthresh) {
1854
	if (abs_voltage < battthresh) {
1833
		/* possible existing states:
1855
		/* possible existing states:
1834
		   battery lost, no debounce timer
1856
		   battery lost, no debounce timer
1835
		   battery lost, debounce timer (going to battery present)
1857
		   battery lost, debounce timer (going to battery present)
1836
		   battery present or unknown, no debounce timer
1858
		   battery present or unknown, no debounce timer
1837
		   battery present or unknown, debounce timer (going to battery lost)
1859
		   battery present or unknown, debounce timer (going to battery lost)
1838
		*/
1860
		*/
1839

    
   
1861

   
1840
		if (fxo->battery == BATTERY_LOST) {
1862
		if (fxo->battery == BATTERY_LOST) {
1841
			if (fxo->battdebounce) {
1863
			if (fxo->battdebounce) {
1842
				/* we were going to BATTERY_PRESENT, but battery was lost again,
1864
				/* we were going to BATTERY_PRESENT, but battery was lost again,
1843
				   so clear the debounce timer */
1865
				   so clear the debounce timer */
1844
				fxo->battdebounce = 0;
1866
				fxo->battdebounce = 0;
1845
			}
1867
			}
1846
		} else {
1868
		} else {
1847
			if (fxo->battdebounce) {
1869
			if (fxo->battdebounce) {
1848
				/* going to BATTERY_LOST, see if we are there yet */
1870
				/* going to BATTERY_LOST, see if we are there yet */
1849
				if (--fxo->battdebounce == 0) {
1871
				if (--fxo->battdebounce == 0) {
1850
					fxo->battery = BATTERY_LOST;
1872
					fxo->battery = BATTERY_LOST;
1851
					if (debug)
1873
					if (debug)
1852
						dev_info(&wc->vb.pdev->dev, "NO BATTERY on %d/%d!\n", wc->aspan->span.spanno, mod->card + 1);
1874
						dev_info(&wc->vb.pdev->dev, "NO BATTERY on %d/%d!\n", wc->aspan->span.spanno, mod->card + 1);
1853
#ifdef	JAPAN
1875
#ifdef	JAPAN
1854
					if (!wc->ohdebounce && wc->offhook) {
1876
					if (!wc->ohdebounce && wc->offhook) {
1855
						dahdi_hooksig(wc->aspan->chans[card], DAHDI_RXSIG_ONHOOK);
1877
						dahdi_hooksig(wc->aspan->chans[card], DAHDI_RXSIG_ONHOOK);
1856
						if (debug)
1878
						if (debug)
1857
							dev_info(&wc->vb.pdev->dev, "Signalled On Hook\n");
1879
							dev_info(&wc->vb.pdev->dev, "Signalled On Hook\n");
1858
#ifdef	ZERO_BATT_RING
1880
#ifdef	ZERO_BATT_RING
1859
						wc->onhook++;
1881
						wc->onhook++;
1860
#endif
1882
#endif
1861
					}
1883
					}
1862
#else
1884
#else
1863
					dahdi_hooksig(&mod->chan->chan, DAHDI_RXSIG_ONHOOK);
1885
					dahdi_hooksig(&mod->chan->chan, DAHDI_RXSIG_ONHOOK);
1864
					/* set the alarm timer, taking into account that part of its time
1886
					/* set the alarm timer, taking into account that part of its time
1865
					   period has already passed while debouncing occurred */
1887
					   period has already passed while debouncing occurred */
1866
					fxo->battalarm = (battalarm - battdebounce) / MS_PER_CHECK_HOOK;
1888
					fxo->battalarm = (battalarm - battdebounce) / MS_PER_CHECK_HOOK;
1867
#endif
1889
#endif
1868
				}
1890
				}
1869
			} else {
1891
			} else {
1870
				/* start the debounce timer to verify that battery has been lost */
1892
				/* start the debounce timer to verify that battery has been lost */
1871
				fxo->battdebounce = battdebounce / MS_PER_CHECK_HOOK;
1893
				fxo->battdebounce = battdebounce / MS_PER_CHECK_HOOK;
1872
			}
1894
			}
1873
		}
1895
		}
1874
	} else {
1896
	} else {
1875
		/* possible existing states:
1897
		/* possible existing states:
1876
		   battery lost or unknown, no debounce timer
1898
		   battery lost or unknown, no debounce timer
1877
		   battery lost or unknown, debounce timer (going to battery present)
1899
		   battery lost or unknown, debounce timer (going to battery present)
1878
		   battery present, no debounce timer
1900
		   battery present, no debounce timer
1879
		   battery present, debounce timer (going to battery lost)
1901
		   battery present, debounce timer (going to battery lost)
1880
		*/
1902
		*/
1881

    
   
1903

   
1882
		if (fxo->battery == BATTERY_PRESENT) {
1904
		if (fxo->battery == BATTERY_PRESENT) {
1883
			if (fxo->battdebounce) {
1905
			if (fxo->battdebounce) {
1884
				/* we were going to BATTERY_LOST, but battery appeared again,
1906
				/* we were going to BATTERY_LOST, but battery appeared again,
1885
				   so clear the debounce timer */
1907
				   so clear the debounce timer */
1886
				fxo->battdebounce = 0;
1908
				fxo->battdebounce = 0;
1887
			}
1909
			}
1888
		} else {
1910
		} else {
1889
			if (fxo->battdebounce) {
1911
			if (fxo->battdebounce) {
1890
				/* going to BATTERY_PRESENT, see if we are there yet */
1912
				/* going to BATTERY_PRESENT, see if we are there yet */
1891
				if (--fxo->battdebounce == 0) {
1913
				if (--fxo->battdebounce == 0) {
1892
					fxo->battery = BATTERY_PRESENT;
1914
					fxo->battery = BATTERY_PRESENT;
1893
					if (debug) {
1915
					if (debug) {
1894
						dev_info(&wc->vb.pdev->dev,
1916
						dev_info(&wc->vb.pdev->dev,
1895
							 "BATTERY on %d/%d (%s)!\n",
1917
							 "BATTERY on %d/%d (%s)!\n",
1896
							 wc->aspan->span.spanno,
1918
							 wc->aspan->span.spanno,
1897
							 mod->card + 1,
1919
							 mod->card + 1,
1898
							 (b < 0) ? "-" : "+");
1920
							 (b < 0) ? "-" : "+");
1899
					}
1921
					}
1900
#ifdef	ZERO_BATT_RING
1922
#ifdef	ZERO_BATT_RING
1901
					if (wc->onhook) {
1923
					if (wc->onhook) {
1902
						wc->onhook = 0;
1924
						wc->onhook = 0;
1903
						dahdi_hooksig(wc->aspan->chans[card], DAHDI_RXSIG_OFFHOOK);
1925
						dahdi_hooksig(wc->aspan->chans[card], DAHDI_RXSIG_OFFHOOK);
1904
						if (debug)
1926
						if (debug)
1905
							dev_info(&wc->vb.pdev->dev, "Signalled Off Hook\n");
1927
							dev_info(&wc->vb.pdev->dev, "Signalled Off Hook\n");
1906
					}
1928
					}
1907
#else
1929
#else
1908
					dahdi_hooksig(&mod->chan->chan, DAHDI_RXSIG_OFFHOOK);
1930
					dahdi_hooksig(&mod->chan->chan, DAHDI_RXSIG_OFFHOOK);
1909
#endif
1931
#endif
1910
					/* set the alarm timer, taking into account that part of its time
1932
					/* set the alarm timer, taking into account that part of its time
1911
					   period has already passed while debouncing occurred */
1933
					   period has already passed while debouncing occurred */
1912
					fxo->battalarm = (battalarm - battdebounce) / MS_PER_CHECK_HOOK;
1934
					fxo->battalarm = (battalarm - battdebounce) / MS_PER_CHECK_HOOK;
1913
				}
1935
				}
1914
			} else {
1936
			} else {
1915
				/* start the debounce timer to verify that battery has appeared */
1937
				/* start the debounce timer to verify that battery has appeared */
1916
				fxo->battdebounce = battdebounce / MS_PER_CHECK_HOOK;
1938
				fxo->battdebounce = battdebounce / MS_PER_CHECK_HOOK;
1917
			}
1939
			}
1918
		}
1940
		}
1919

    
   
1941

   
1920
		if (fxo->lastpol >= 0) {
1942
		if (fxo->lastpol >= 0) {
1921
			if (b < 0) {
1943
			if (b < 0) {
1922
				fxo->lastpol = -1;
1944
				fxo->lastpol = -1;
1923
				fxo->polaritydebounce = POLARITY_DEBOUNCE / MS_PER_CHECK_HOOK;
1945
				fxo->polaritydebounce = POLARITY_DEBOUNCE / MS_PER_CHECK_HOOK;
1924
			}
1946
			}
1925
		} 
1947
		} 
1926
		if (fxo->lastpol <= 0) {
1948
		if (fxo->lastpol <= 0) {
1927
			if (b > 0) {
1949
			if (b > 0) {
1928
				fxo->lastpol = 1;
1950
				fxo->lastpol = 1;
1929
				fxo->polaritydebounce = POLARITY_DEBOUNCE / MS_PER_CHECK_HOOK;
1951
				fxo->polaritydebounce = POLARITY_DEBOUNCE / MS_PER_CHECK_HOOK;
1930
			}
1952
			}
1931
		}
1953
		}
1932
	}
1954
	}
1933

    
   
1955

   
1934
	if (fxo->battalarm) {
1956
	if (fxo->battalarm) {
1935
		if (--fxo->battalarm == 0) {
1957
		if (--fxo->battalarm == 0) {
1936
			/* the alarm timer has expired, so update the battery alarm state
1958
			/* the alarm timer has expired, so update the battery alarm state
1937
			   for this channel */
1959
			   for this channel */
1938
			dahdi_alarm_channel(&mod->chan->chan,
1960
			dahdi_alarm_channel(&mod->chan->chan,
1939
					    (fxo->battery == BATTERY_LOST) ?
1961
					    (fxo->battery == BATTERY_LOST) ?
1940
						DAHDI_ALARM_RED :
1962
						DAHDI_ALARM_RED :
1941
						DAHDI_ALARM_NONE);
1963
						DAHDI_ALARM_NONE);
1942
		}
1964
		}
1943
	}
1965
	}
1944

    
   
1966

   
1945
	if (fxo->polaritydebounce) {
1967
	if (fxo->polaritydebounce) {
1946
	        fxo->polaritydebounce--;
1968
	        fxo->polaritydebounce--;
1947
		if (fxo->polaritydebounce < 1) {
1969
		if (fxo->polaritydebounce < 1) {
1948
		    if (fxo->lastpol != fxo->polarity) {
1970
		    if (fxo->lastpol != fxo->polarity) {
1949
			if (debug & DEBUG_CARD)
1971
			if (debug & DEBUG_CARD)
1950
				dev_info(&wc->vb.pdev->dev, "%lu Polarity reversed (%d -> %d)\n", jiffies, 
1972
				dev_info(&wc->vb.pdev->dev, "%lu Polarity reversed (%d -> %d)\n", jiffies, 
1951
				       fxo->polarity, 
1973
				       fxo->polarity, 
1952
				       fxo->lastpol);
1974
				       fxo->lastpol);
1953
			if (fxo->polarity)
1975
			if (fxo->polarity)
1954
				dahdi_qevent_lock(&mod->chan->chan, DAHDI_EVENT_POLARITY);
1976
				dahdi_qevent_lock(&mod->chan->chan, DAHDI_EVENT_POLARITY);
1955
			fxo->polarity = fxo->lastpol;
1977
			fxo->polarity = fxo->lastpol;
1956
		    }
1978
		    }
1957
		}
1979
		}
1958
	}
1980
	}
1959
	/* Look for neon mwi pulse */
1981
	/* Look for neon mwi pulse */
1960
	if (neonmwi_monitor && !fxo->offhook) {
1982
	if (neonmwi_monitor &&