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

« back to all changes in this revision

Viewing changes to kernel/wctdm24xxp/GpakCust.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
 * Copyright (c) 2005, Adaptive Digital Technologies, Inc.
 
3
 *
 
4
 * File Name: GpakCust.c
 
5
 *
 
6
 * Description:
 
7
 *   This file contains host system dependent functions to support generic
 
8
 *   G.PAK API functions. The file is integrated into the host processor
 
9
 *   connected to C55x G.PAK DSPs via a Host Port Interface.
 
10
 *
 
11
 *   Note: This file needs to be modified by the G.PAK system integrator.
 
12
 *
 
13
 * Version: 1.0
 
14
 *
 
15
 * Revision History:
 
16
 *   06/15/05 - Initial release.
 
17
 *
 
18
 * This program has been released under the terms of the GPL version 2 by
 
19
 * permission of Adaptive Digital Technologies, Inc.  The standard
 
20
 * GPL disclaimer is given inline below for your convenience.
 
21
 *
 
22
 * This program is free software; you can redistribute it and/or modify
 
23
 * it under the terms of the GNU General Public License as published by
 
24
 * the Free Software Foundation; either version 2 of the License, or
 
25
 * (at your option) any later version.
 
26
 * 
 
27
 * This program is distributed in the hope that it will be useful,
 
28
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
29
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
30
 * GNU General Public License for more details.
 
31
 * 
 
32
 * You should have received a copy of the GNU General Public License
 
33
 * along with this program; if not, write to the Free Software
 
34
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 
35
 *
 
36
 */
 
37
 
 
38
#include <linux/version.h>
 
39
#include <linux/delay.h>
 
40
#include <asm/semaphore.h>
 
41
 
 
42
#include "zaptel.h"
 
43
#include "wctdm24xxp.h"
 
44
#include "GpakCust.h"
 
45
 
 
46
char vpm150mtone_to_zaptone(GpakToneCodes_t tone)
 
47
{
 
48
        switch (tone) {
 
49
                case DtmfDigit0:
 
50
                        return '0';
 
51
                case DtmfDigit1:
 
52
                        return '1';
 
53
                case DtmfDigit2:
 
54
                        return '2';
 
55
                case DtmfDigit3:
 
56
                        return '3';
 
57
                case DtmfDigit4:
 
58
                        return '4';
 
59
                case DtmfDigit5:
 
60
                        return '5';
 
61
                case DtmfDigit6:
 
62
                        return '6';
 
63
                case DtmfDigit7:
 
64
                        return '7';
 
65
                case DtmfDigit8:
 
66
                        return '8';
 
67
                case DtmfDigit9:
 
68
                        return '9';
 
69
                case DtmfDigitPnd:
 
70
                        return '#';
 
71
                case DtmfDigitSt:
 
72
                        return '*';
 
73
                case DtmfDigitA:
 
74
                        return 'A';
 
75
                case DtmfDigitB:
 
76
                        return 'B';
 
77
                case DtmfDigitC:
 
78
                        return 'C';
 
79
                case DtmfDigitD:
 
80
                        return 'D';
 
81
                case EndofCngDigit:
 
82
                        return 'f';
 
83
                default:
 
84
                        return 0;
 
85
        }
 
86
}
 
87
 
 
88
static inline struct wctdm * wc_find_iface(unsigned short dspid)
 
89
{
 
90
        int i;
 
91
        struct wctdm *ret = NULL;
 
92
        unsigned long flags;
 
93
 
 
94
        spin_lock_irqsave(&ifacelock, flags);
 
95
        for (i = 0; i < WC_MAX_IFACES; i++)
 
96
                if (ifaces[i] && ifaces[i]->vpm150m && (ifaces[i]->vpm150m->dspid == dspid))
 
97
                        ret = ifaces[i];
 
98
        spin_unlock_irqrestore(&ifacelock, flags);
 
99
 
 
100
        return ret;
 
101
}
 
102
 
 
103
static inline struct vpm150m_cmd * vpm150m_empty_slot(struct wctdm *wc)
 
104
{
 
105
        int x;
 
106
 
 
107
        for (x = 0; x < VPM150M_MAX_COMMANDS; x++)
 
108
                if (!wc->vpm150m->cmdq[x].desc) {
 
109
                        return &wc->vpm150m->cmdq[x];
 
110
                }
 
111
        return NULL;
 
112
}
 
113
 
 
114
/* Wait for any outstanding commands to be completed. */
 
115
static inline int vpm150m_io_wait(struct wctdm *wc)
 
116
{
 
117
        int x;
 
118
        int ret=0;
 
119
        for (x=0; x < VPM150M_MAX_COMMANDS;) {
 
120
                if (wc->vpm150m->cmdq[x].desc) {
 
121
                        if ((ret=schluffen(&wc->regq))) {
 
122
                                return ret;
 
123
                        }
 
124
                        x=0;
 
125
                }
 
126
                else {
 
127
                        ++x;
 
128
                }
 
129
        }
 
130
        return ret;
 
131
}
 
132
 
 
133
int wctdm_vpm150m_getreg_full_async(struct wctdm *wc, int pagechange, unsigned int len, 
 
134
        unsigned short addr, unsigned short *outbuf, struct vpm150m_cmd **hit_p)
 
135
{
 
136
        int ret=0;
 
137
        unsigned long flags;
 
138
        BUG_ON(!hit_p);
 
139
        spin_lock_irqsave(&wc->reglock, flags);
 
140
        (*hit_p) = vpm150m_empty_slot(wc);
 
141
        if (*hit_p) {
 
142
                (*hit_p)->desc = __VPM150M_RD;
 
143
                if (pagechange) {
 
144
                        (*hit_p)->desc |= __VPM150M_RWPAGE;
 
145
                }
 
146
                (*hit_p)->datalen = len;
 
147
                (*hit_p)->addr = addr;
 
148
                memset((*hit_p)->data, 0, len*sizeof(outbuf[0]));
 
149
        }
 
150
        else {
 
151
                ret = -EBUSY;
 
152
        }
 
153
        spin_unlock_irqrestore(&wc->reglock, flags);
 
154
        return ret;
 
155
}
 
156
 
 
157
int wctdm_vpm150m_getreg_full_return(struct wctdm *wc, int pagechange, unsigned int len,
 
158
        unsigned short addr, unsigned short *outbuf, struct vpm150m_cmd **hit_p)
 
159
{
 
160
        int ret = 0;
 
161
        unsigned long flags;
 
162
        BUG_ON(!hit_p);
 
163
        spin_lock_irqsave(&wc->reglock, flags);
 
164
        do {
 
165
                if ((*hit_p)->desc & __VPM150M_FIN) {
 
166
                        memcpy(outbuf, (*hit_p)->data, len*(sizeof(outbuf[0])));
 
167
                        (*hit_p)->desc = 0;
 
168
                        (*hit_p) = NULL;
 
169
                        ret = 0;
 
170
                }
 
171
                else {
 
172
                        spin_unlock_irqrestore(&wc->reglock, flags);
 
173
                        if ((ret=schluffen(&wc->regq))) {
 
174
                                return ret;
 
175
                        }
 
176
                        spin_lock_irqsave(&wc->reglock, flags);
 
177
                        ret = -EBUSY;
 
178
                }
 
179
        } while (-EBUSY == ret);
 
180
        spin_unlock_irqrestore(&wc->reglock, flags);
 
181
        return ret;
 
182
}
 
183
 
 
184
int wctdm_vpm150m_getreg_full(struct wctdm *wc, int pagechange, unsigned int len, unsigned short addr, unsigned short *outbuf)
 
185
{
 
186
        struct vpm150m_cmd *hit = 0;
 
187
        int ret = 0;
 
188
        do {
 
189
                ret = wctdm_vpm150m_getreg_full_async(wc, pagechange, len, addr, outbuf, &hit);
 
190
                if (!hit) {
 
191
                        if ( -EBUSY == ret ) {
 
192
                                if ((ret = schluffen(&wc->regq))) 
 
193
                                        return ret;
 
194
                        }
 
195
                        BUG_ON(0 != ret);
 
196
                }
 
197
        } while (!hit);
 
198
        ret = wctdm_vpm150m_getreg_full_return(wc, pagechange, len, addr, outbuf, &hit);
 
199
        return ret;
 
200
}
 
201
 
 
202
int wctdm_vpm150m_setreg_full(struct wctdm *wc, int pagechange, unsigned int len, unsigned int addr, unsigned short *data)
 
203
{
 
204
        unsigned long flags;
 
205
        struct vpm150m_cmd *hit;
 
206
        int ret, i;
 
207
        do {
 
208
                spin_lock_irqsave(&wc->reglock, flags);
 
209
                hit = vpm150m_empty_slot(wc);
 
210
                if (hit) {
 
211
                        hit->desc = __VPM150M_WR;
 
212
                        if (pagechange)
 
213
                                hit->desc |= __VPM150M_RWPAGE;
 
214
                        hit->addr = addr;
 
215
                        hit->datalen = len;
 
216
                        for (i = 0; i < len; i++)
 
217
                                hit->data[i] = data[i];
 
218
                }
 
219
                spin_unlock_irqrestore(&wc->reglock, flags);
 
220
                if (!hit) {
 
221
                        if ((ret = schluffen(&wc->regq)))
 
222
                                return ret;
 
223
                }
 
224
        } while (!hit);
 
225
        return (hit) ? 0 : -1;
 
226
}
 
227
 
 
228
int wctdm_vpm150m_setpage(struct wctdm *wc, unsigned short addr)
 
229
{
 
230
        addr &= 0xf;
 
231
        /* Let's optimize this a little bit */
 
232
        if (wc->vpm150m->curpage == addr)
 
233
                return 0;
 
234
        else {
 
235
                wc->vpm150m->curpage = addr;
 
236
        }
 
237
 
 
238
        return wctdm_vpm150m_setreg_full(wc, 1, 1, 0, &addr);
 
239
}
 
240
 
 
241
unsigned char wctdm_vpm150m_getpage(struct wctdm *wc)
 
242
{
 
243
        unsigned short res;
 
244
        wctdm_vpm150m_getreg_full(wc, 1, 1, 0, &res);
 
245
        return res;
 
246
}
 
247
 
 
248
unsigned short wctdm_vpm150m_getreg(struct wctdm *wc, unsigned int len, unsigned int addr, unsigned short *data)
 
249
{
 
250
        unsigned short res;
 
251
        wctdm_vpm150m_setpage(wc, addr >> 16);
 
252
        if ((addr >> 16) != ((addr + len) >> 16))
 
253
                printk("getreg: You found it!\n");
 
254
        res = wctdm_vpm150m_getreg_full(wc, 0, len, addr & 0xffff, data);
 
255
        return res;
 
256
}
 
257
 
 
258
int wctdm_vpm150m_setreg(struct wctdm *wc, unsigned int len, unsigned int addr, unsigned short *data)
 
259
{
 
260
        int res;
 
261
        wctdm_vpm150m_setpage(wc, addr >> 16);
 
262
        if ((addr >> 16) != ((addr + len) >> 16))
 
263
                printk("getreg: You found it!\n");
 
264
        res = wctdm_vpm150m_setreg_full(wc, 0, len, addr & 0xffff, data);
 
265
        return res;
 
266
}
 
267
 
 
268
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
269
 * gpakReadDspMemory - Read DSP memory.
 
270
 *
 
271
 * FUNCTION
 
272
 *  This function reads a contiguous block of words from DSP memory starting at
 
273
 *  the specified address.
 
274
 *
 
275
 * RETURNS
 
276
 *  nothing
 
277
 *
 
278
 */
 
279
void gpakReadDspMemory(
 
280
    unsigned short int DspId,   /* DSP Identifier (0 to MAX_DSP_CORES-1) */
 
281
    DSP_ADDRESS DspAddress,     /* DSP's memory address of first word */
 
282
    unsigned int NumWords,      /* number of contiguous words to read */
 
283
    DSP_WORD *pWordValues       /* pointer to array of word values variable */
 
284
    )
 
285
{
 
286
        struct wctdm *wc = wc_find_iface(DspId);
 
287
        int i;
 
288
        int transcount;
 
289
        int ret;
 
290
 
 
291
        vpm150m_io_wait(wc);
 
292
        if ( NumWords < VPM150M_MAX_COMMANDS ) {
 
293
                struct vpm150m_cmd* cmds[VPM150M_MAX_COMMANDS] = {0};
 
294
                wctdm_vpm150m_setpage(wc, DspAddress >> 16);
 
295
                DspAddress &= 0xffff;
 
296
                for (i=0; i < NumWords; ++i) {
 
297
                        ret = wctdm_vpm150m_getreg_full_async(wc,0,1,DspAddress+i,&pWordValues[i],
 
298
                                &cmds[i]);
 
299
                        if (0 != ret) {
 
300
                                return;
 
301
                        }
 
302
                }
 
303
                for (i=NumWords-1; i >=0; --i) {
 
304
                        ret = wctdm_vpm150m_getreg_full_return(wc,0,1,DspAddress+i,&pWordValues[i],
 
305
                                &cmds[i]);
 
306
                        if (0 != ret) {
 
307
                                return;
 
308
                        }
 
309
                }
 
310
        }
 
311
        else {
 
312
                for (i = 0; i < NumWords;) {
 
313
                        if ((NumWords - i) > VPM150M_MAX_DATA)
 
314
                                transcount = VPM150M_MAX_DATA;
 
315
                        else
 
316
                                transcount = NumWords - i;
 
317
                        wctdm_vpm150m_getreg(wc, transcount, DspAddress + i, &pWordValues[i]);
 
318
                        i += transcount;
 
319
                }
 
320
        }
 
321
        return;
 
322
}
 
323
 
 
324
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
325
 * gpakWriteDspMemory - Write DSP memory.
 
326
 *
 
327
 * FUNCTION
 
328
 *  This function writes a contiguous block of words to DSP memory starting at
 
329
 *  the specified address.
 
330
 *
 
331
 * RETURNS
 
332
 *  nothing
 
333
 *
 
334
 */
 
335
void gpakWriteDspMemory(
 
336
    unsigned short int DspId,   /* DSP Identifier (0 to MAX_DSP_CORES-1) */
 
337
    DSP_ADDRESS DspAddress,     /* DSP's memory address of first word */
 
338
    unsigned int NumWords,      /* number of contiguous words to write */
 
339
    DSP_WORD *pWordValues       /* pointer to array of word values to write */
 
340
    )
 
341
{
 
342
 
 
343
        struct wctdm *wc = wc_find_iface(DspId);
 
344
        int i;
 
345
        int transcount;
 
346
 
 
347
        //printk("Writing %d words to memory\n", NumWords);
 
348
        if (wc && wc->vpm150m) {
 
349
                for (i = 0; i < NumWords;) {
 
350
                        if ((NumWords - i) > VPM150M_MAX_DATA)
 
351
                                transcount = VPM150M_MAX_DATA;
 
352
                        else
 
353
                                transcount = NumWords - i;
 
354
 
 
355
                        wctdm_vpm150m_setreg(wc, transcount, DspAddress + i, &pWordValues[i]);
 
356
                        i += transcount;
 
357
                }
 
358
#if 0
 
359
                for (i = 0; i < NumWords; i++) {
 
360
                        if (wctdm_vpm150m_getreg(wc, DspAddress + i) != pWordValues[i]) {
 
361
                                printk("Error in write.  Address %x is not %x\n", DspAddress + i, pWordValues[i]);
 
362
                        }
 
363
                }
 
364
#endif
 
365
        }
 
366
        return;
 
367
 
 
368
}
 
369
 
 
370
 
 
371
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
372
 * gpakHostDelay - Delay for a fixed time interval.
 
373
 *
 
374
 * FUNCTION
 
375
 *  This function delays for a fixed time interval before returning. The time
 
376
 *  interval is the Host Port Interface sampling period when polling a DSP for
 
377
 *  replies to command messages.
 
378
 *
 
379
 * RETURNS
 
380
 *  nothing
 
381
 *
 
382
 */
 
383
void gpakHostDelay(void)
 
384
{
 
385
}
 
386
 
 
387
 
 
388
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
389
 * gpakLockAccess - Lock access to the specified DSP.
 
390
 *
 
391
 * FUNCTION
 
392
 *  This function aquires exclusive access to the specified DSP.
 
393
 *
 
394
 * RETURNS
 
395
 *  nothing
 
396
 *
 
397
 */
 
398
void gpakLockAccess(unsigned short DspId)
 
399
{
 
400
        struct wctdm *wc;
 
401
 
 
402
        wc = wc_find_iface(DspId);
 
403
 
 
404
        if (wc) {
 
405
                struct vpm150m *vpm = wc->vpm150m;
 
406
 
 
407
                if (vpm)
 
408
                        down_interruptible(&vpm->sem);
 
409
        }
 
410
}
 
411
 
 
412
 
 
413
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
414
 * gpakUnlockAccess - Unlock access to the specified DSP.
 
415
 *
 
416
 * FUNCTION
 
417
 *  This function releases exclusive access to the specified DSP.
 
418
 *
 
419
 * RETURNS
 
420
 *  nothing
 
421
 *
 
422
 */
 
423
void gpakUnlockAccess(unsigned short DspId)
 
424
{
 
425
        struct wctdm *wc;
 
426
 
 
427
        wc = wc_find_iface(DspId);
 
428
 
 
429
        if (wc) {
 
430
                struct vpm150m *vpm = wc->vpm150m;
 
431
 
 
432
                if (vpm)
 
433
                        up(&vpm->sem);
 
434
        }
 
435
}
 
436
 
 
437
 
 
438
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
439
 * gpakReadFile - Read a block of bytes from a G.PAK Download file.
 
440
 *
 
441
 * FUNCTION
 
442
 *  This function reads a contiguous block of bytes from a G.PAK Download file
 
443
 *  starting at the current file position.
 
444
 *
 
445
 * RETURNS
 
446
 *  The number of bytes read from the file.
 
447
 *   -1 indicates an error occurred.
 
448
 *    0 indicates all bytes have been read (end of file)
 
449
 *
 
450
 */
 
451
int gpakReadFile(
 
452
    GPAK_FILE_ID FileId,        /* G.PAK Download File Identifier */
 
453
    unsigned char *pBuffer,     /* pointer to buffer for storing bytes */
 
454
    unsigned int NumBytes       /* number of bytes to read */
 
455
    )
 
456
{
 
457
#ifdef VPM150M_SUPPORT
 
458
        struct wctdm_firmware *fw = FileId;
 
459
        unsigned int i, count;
 
460
 
 
461
        if (!fw || !fw->fw)
 
462
                return -1;
 
463
 
 
464
        if (NumBytes > (fw->fw->size - fw->offset))
 
465
                count = fw->fw->size - fw->offset;
 
466
        else
 
467
                count = NumBytes;
 
468
 
 
469
        for (i = 0; i < count; i++)
 
470
                pBuffer[i] = fw->fw->data[fw->offset + i];
 
471
 
 
472
        fw->offset += count;
 
473
 
 
474
        return count;
 
475
#endif
 
476
}