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

« back to all changes in this revision

Viewing changes to vzaphfc/fifo.c

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

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * fifo.c - HFC FIFO management routines
3
 
 *
4
 
 * Copyright (C) 2006 headissue GmbH; Jens Wilke
5
 
 * Copyright (C) 2004 Daniele Orlandi
6
 
 * Copyright (C) 2002, 2003, 2004, Junghanns.NET GmbH
7
 
 *
8
 
 * Original author of this code is
9
 
 * Daniele "Vihai" Orlandi <daniele@orlandi.com>
10
 
 *
11
 
 * This program is free software and may be modified and
12
 
 * distributed under the terms of the GNU Public License.
13
 
 *
14
 
 */
15
 
 
16
 
#include <linux/kernel.h>
17
 
 
18
 
#include "../zaptel.h"
19
 
 
20
 
#include "fifo.h"
21
 
 
22
 
static void hfc_fifo_mem_read(struct hfc_chan_simplex *chan,
23
 
        int z_start,
24
 
        void *data, int size)
25
 
{
26
 
        int bytes_to_boundary = chan->z_max - z_start + 1;
27
 
        if (bytes_to_boundary >= size) {
28
 
                memcpy(data,
29
 
                        chan->z_base + z_start,
30
 
                        size);
31
 
        } else {
32
 
                // Buffer wrap
33
 
                memcpy(data,
34
 
                        chan->z_base + z_start,
35
 
                        bytes_to_boundary);
36
 
 
37
 
                memcpy(data + bytes_to_boundary,
38
 
                        chan->fifo_base,
39
 
                        size - bytes_to_boundary);
40
 
        }
41
 
}
42
 
 
43
 
static void hfc_fifo_mem_write(struct hfc_chan_simplex *chan,
44
 
        void *data, int size)
45
 
{
46
 
        int bytes_to_boundary = chan->z_max - *Z1_F1(chan) + 1;
47
 
        if (bytes_to_boundary >= size) {
48
 
                memcpy(chan->z_base + *Z1_F1(chan),
49
 
                        data,
50
 
                        size);
51
 
        } else {
52
 
                // FIFO wrap
53
 
 
54
 
                memcpy(chan->z_base + *Z1_F1(chan),
55
 
                        data,
56
 
                        bytes_to_boundary);
57
 
 
58
 
                memcpy(chan->fifo_base,
59
 
                        data + bytes_to_boundary,
60
 
                        size - bytes_to_boundary);
61
 
        }
62
 
}
63
 
 
64
 
int hfc_fifo_get(struct hfc_chan_simplex *chan,
65
 
                void *data, int size)
66
 
{
67
 
        int available_bytes;
68
 
 
69
 
        // Some useless statistic
70
 
        chan->bytes += size;
71
 
 
72
 
        available_bytes = hfc_fifo_used_rx(chan);
73
 
 
74
 
        if (available_bytes < size && !chan->fifo_underrun++) {
75
 
                // print the warning only once
76
 
                printk(KERN_WARNING hfc_DRIVER_PREFIX
77
 
                        "card %d: "
78
 
                        "chan %s: "
79
 
                        "RX FIFO not enough (%d) bytes to receive!\n",
80
 
                        chan->chan->card->cardnum,
81
 
                        chan->chan->name,
82
 
                        available_bytes);
83
 
                return -1;
84
 
        }
85
 
 
86
 
        hfc_fifo_mem_read(chan, *Z2_F2(chan), data, size);
87
 
        *Z2_F2(chan) = Z_inc(chan, *Z2_F2(chan), size);
88
 
        return available_bytes - size;
89
 
}
90
 
 
91
 
/*
92
 
static void hfc_fifo_drop(struct hfc_chan_simplex *chan, int size)
93
 
{
94
 
        int available_bytes = hfc_fifo_used_rx(chan);
95
 
        if (available_bytes + 1 < size) {
96
 
                printk(KERN_WARNING hfc_DRIVER_PREFIX
97
 
                        "card %d: "
98
 
                        "chan %s: "
99
 
                        "RX FIFO not enough (%d) bytes to drop!\n",
100
 
                        chan->chan->card->cardnum,
101
 
                        chan->chan->name,
102
 
                        available_bytes);
103
 
 
104
 
                return;
105
 
        }
106
 
 
107
 
        *Z2_F2(chan) = Z_inc(chan, *Z2_F2(chan), size);
108
 
}
109
 
*/
110
 
 
111
 
void hfc_fifo_put(struct hfc_chan_simplex *chan,
112
 
                        void *data, int size)
113
 
{
114
 
        struct hfc_card *card = chan->chan->card;
115
 
        int used_bytes = hfc_fifo_used_tx(chan);
116
 
        int free_bytes = hfc_fifo_free_tx(chan);
117
 
 
118
 
        if (!used_bytes && !chan->fifo_underrun++) {
119
 
                // print warning only once, to make timing not worse
120
 
                printk(KERN_WARNING hfc_DRIVER_PREFIX
121
 
                        "card %d: "
122
 
                        "chan %s: "
123
 
                        "TX FIFO has become empty\n",
124
 
                        card->cardnum,
125
 
                        chan->chan->name);
126
 
        }
127
 
        if (free_bytes < size) {
128
 
                printk(KERN_CRIT hfc_DRIVER_PREFIX
129
 
                        "card %d: "
130
 
                        "chan %s: "
131
 
                        "TX FIFO full!\n",
132
 
                        chan->chan->card->cardnum,
133
 
                        chan->chan->name);
134
 
                chan->fifo_full++;
135
 
                hfc_clear_fifo_tx(chan);
136
 
        }
137
 
 
138
 
        hfc_fifo_mem_write(chan, data, size);
139
 
        chan->bytes += size;
140
 
        *Z1_F1(chan) = Z_inc(chan, *Z1_F1(chan), size);
141
 
}
142
 
 
143
 
int hfc_fifo_get_frame(struct hfc_chan_simplex *chan, void *data, int max_size)
144
 
{
145
 
        int frame_size;
146
 
        u16 newz2 ;
147
 
        
148
 
        if (*chan->f1 == *chan->f2) {
149
 
                // nothing received, strange uh?
150
 
                printk(KERN_WARNING hfc_DRIVER_PREFIX
151
 
                        "card %d: "
152
 
                        "chan %s: "
153
 
                        "get_frame called with no frame in FIFO.\n",
154
 
                        chan->chan->card->cardnum,
155
 
                        chan->chan->name);
156
 
 
157
 
                return -1;
158
 
        }
159
 
 
160
 
        // frame_size includes CRC+CRC+STAT
161
 
        frame_size = hfc_fifo_get_frame_size(chan);
162
 
 
163
 
#ifdef DEBUG
164
 
        if(debug_level == 3) {
165
 
                printk(KERN_DEBUG hfc_DRIVER_PREFIX
166
 
                        "card %d: "
167
 
                        "chan %s: "
168
 
                        "RX len %2d: ",
169
 
                        chan->chan->card->cardnum,
170
 
                        chan->chan->name,
171
 
                        frame_size);
172
 
        } else if(debug_level >= 4) {
173
 
                printk(KERN_DEBUG hfc_DRIVER_PREFIX
174
 
                        "card %d: "
175
 
                        "chan %s: "
176
 
                        "RX (f1=%02x, f2=%02x, z1=%04x, z2=%04x) len %2d: ",
177
 
                        chan->chan->card->cardnum,
178
 
                        chan->chan->name,
179
 
                        *chan->f1, *chan->f2, *Z1_F2(chan), *Z2_F2(chan),
180
 
                        frame_size);
181
 
        }
182
 
 
183
 
        if(debug_level >= 3) {
184
 
                int i;
185
 
                for (i=0; i < frame_size; i++) {
186
 
                        printk("%02x", hfc_fifo_u8(chan,
187
 
                                Z_inc(chan, *Z2_F2(chan), i)));
188
 
                }
189
 
 
190
 
                printk("\n"); 
191
 
        }
192
 
#endif
193
 
 
194
 
        if (frame_size <= 0) {
195
 
#ifdef DEBUG
196
 
                if (debug_level >= 2) {
197
 
                        printk(KERN_DEBUG hfc_DRIVER_PREFIX
198
 
                                "card %d: "
199
 
                                "chan %s: "
200
 
                                "invalid (empty) frame received.\n",
201
 
                                chan->chan->card->cardnum,
202
 
                                chan->chan->name);
203
 
                }
204
 
#endif
205
 
 
206
 
                hfc_fifo_drop_frame(chan);
207
 
                return -1;
208
 
        }
209
 
 
210
 
        // STAT is not really received
211
 
        chan->bytes += frame_size - 1;
212
 
 
213
 
        // Calculate beginning of the next frame
214
 
        newz2 = Z_inc(chan, *Z2_F2(chan), frame_size);
215
 
 
216
 
        // We cannot use hfc_fifo_get because of different semantic of
217
 
        // "available bytes" and to avoid useless increment of Z2
218
 
        hfc_fifo_mem_read(chan, *Z2_F2(chan), data,
219
 
                frame_size < max_size ? frame_size : max_size);
220
 
 
221
 
        if (hfc_fifo_u8(chan, Z_inc(chan, *Z2_F2(chan),
222
 
                frame_size - 1)) != 0x00) {
223
 
                // CRC not ok, frame broken, skipping
224
 
#ifdef DEBUG
225
 
                if(debug_level >= 2) {
226
 
                        printk(KERN_WARNING hfc_DRIVER_PREFIX
227
 
                                "card %d: "
228
 
                                "chan %s: "
229
 
                                "Received frame with wrong CRC\n",
230
 
                                chan->chan->card->cardnum,
231
 
                                chan->chan->name);
232
 
                }
233
 
#endif
234
 
 
235
 
                chan->crc++;
236
 
                chan->chan->net_device_stats.rx_errors++;
237
 
 
238
 
                hfc_fifo_drop_frame(chan);
239
 
                return -1;
240
 
        }
241
 
 
242
 
        chan->frames++;
243
 
 
244
 
        *chan->f2 = F_inc(chan, *chan->f2, 1);
245
 
 
246
 
        // Set Z2 for the next frame we're going to receive
247
 
        *Z2_F2(chan) = newz2;
248
 
 
249
 
        return frame_size;
250
 
}
251
 
 
252
 
void hfc_fifo_drop_frame(struct hfc_chan_simplex *chan)
253
 
{
254
 
        int available_bytes;
255
 
        u16 newz2;
256
 
 
257
 
        if (*chan->f1 == *chan->f2) {
258
 
                // nothing received, strange eh?
259
 
                printk(KERN_WARNING hfc_DRIVER_PREFIX
260
 
                        "card %d: "
261
 
                        "chan %s: "
262
 
                        "skip_frame called with no frame in FIFO.\n",
263
 
                        chan->chan->card->cardnum,
264
 
                        chan->chan->name);
265
 
 
266
 
                return;
267
 
        }
268
 
 
269
 
//      chan->drops++;
270
 
 
271
 
        available_bytes = hfc_fifo_used_rx(chan) + 1;
272
 
 
273
 
        // Calculate beginning of the next frame
274
 
        newz2 = Z_inc(chan, *Z2_F2(chan), available_bytes);
275
 
 
276
 
        *chan->f2 = F_inc(chan, *chan->f2, 1);
277
 
 
278
 
        // Set Z2 for the next frame we're going to receive
279
 
        *Z2_F2(chan) = newz2;
280
 
}
281
 
 
282
 
void hfc_fifo_put_frame(struct hfc_chan_simplex *chan,
283
 
                 void *data, int size)
284
 
{
285
 
        u16 newz1;
286
 
        int available_frames;
287
 
 
288
 
#ifdef DEBUG
289
 
        if (debug_level == 3) {
290
 
                printk(KERN_DEBUG hfc_DRIVER_PREFIX
291
 
                        "card %d: "
292
 
                        "chan %s: "
293
 
                        "TX len %2d: ",
294
 
                        chan->chan->card->cardnum,
295
 
                        chan->chan->name,
296
 
                        size);
297
 
        } else if (debug_level >= 4) {
298
 
                printk(KERN_DEBUG hfc_DRIVER_PREFIX
299
 
                        "card %d: "
300
 
                        "chan %s: "
301
 
                        "TX (f1=%02x, f2=%02x, z1=%04x, z2=%04x) len %2d: ",
302
 
                        chan->chan->card->cardnum,
303
 
                        chan->chan->name,
304
 
                        *chan->f1, *chan->f2, *Z1_F1(chan), *Z2_F1(chan),
305
 
                        size);
306
 
        }
307
 
 
308
 
        if (debug_level >= 3) {
309
 
                int i;
310
 
                for (i=0; i<size; i++)
311
 
                        printk("%02x",((u8 *)data)[i]);
312
 
 
313
 
                printk("\n");
314
 
        }
315
 
#endif
316
 
 
317
 
        available_frames = hfc_fifo_free_frames(chan);
318
 
 
319
 
        if (available_frames >= chan->f_num) {
320
 
                printk(KERN_CRIT hfc_DRIVER_PREFIX
321
 
                        "card %d: "
322
 
                        "chan %s: "
323
 
                        "TX FIFO total number of frames exceeded!\n",
324
 
                        chan->chan->card->cardnum,
325
 
                        chan->chan->name);
326
 
 
327
 
                chan->fifo_full++;
328
 
 
329
 
                return;
330
 
        }
331
 
 
332
 
        hfc_fifo_put(chan, data, size);
333
 
 
334
 
        newz1 = *Z1_F1(chan);
335
 
 
336
 
        *chan->f1 = F_inc(chan, *chan->f1, 1);
337
 
 
338
 
        *Z1_F1(chan) = newz1;
339
 
 
340
 
        chan->frames++;
341
 
}
342
 
 
343
 
void hfc_clear_fifo_rx(struct hfc_chan_simplex *chan)
344
 
{
345
 
        *chan->f2 = *chan->f1;
346
 
        *Z2_F2(chan) = *Z1_F2(chan);
347
 
}
348
 
 
349
 
void hfc_clear_fifo_tx(struct hfc_chan_simplex *chan)
350
 
{
351
 
        *chan->f1 = *chan->f2;
352
 
        *Z1_F1(chan) = *Z2_F1(chan);
353
 
 
354
 
        if (chan->chan->status == open_voice) {
355
 
                // Make sure that at least hfc_TX_FIFO_PRELOAD bytes are
356
 
                // present in the TX FIFOs
357
 
 
358
 
                // Create hfc_TX_FIFO_PRELOAD bytes of empty data
359
 
                // (0x7f is mute audio)
360
 
                u8 empty_fifo[hfc_TX_FIFO_PRELOAD + ZT_CHUNKSIZE + hfc_RX_FIFO_PRELOAD];
361
 
                memset(empty_fifo, 0x7f, sizeof(empty_fifo));
362
 
 
363
 
                hfc_fifo_put(chan, empty_fifo, sizeof(empty_fifo));
364
 
        }
365
 
}
366