]> Git Repo - linux.git/blob - drivers/isdn/mISDN/dsp_cmx.c
Linux 6.14-rc3
[linux.git] / drivers / isdn / mISDN / dsp_cmx.c
1 /*
2  * Audio crossconnecting/conferrencing (hardware level).
3  *
4  * Copyright 2002 by Andreas Eversberg ([email protected])
5  *
6  * This software may be used and distributed according to the terms
7  * of the GNU General Public License, incorporated herein by reference.
8  *
9  */
10
11 /*
12  * The process of adding and removing parties to/from a conference:
13  *
14  * There is a chain of struct dsp_conf which has one or more members in a chain
15  * of struct dsp_conf_member.
16  *
17  * After a party is added, the conference is checked for hardware capability.
18  * Also if a party is removed, the conference is checked again.
19  *
20  * There are 3 different solutions: -1 = software, 0 = hardware-crossconnect
21  * 1-n = hardware-conference. The n will give the conference number.
22  *
23  * Depending on the change after removal or insertion of a party, hardware
24  * commands are given.
25  *
26  * The current solution is stored within the struct dsp_conf entry.
27  */
28
29 /*
30  * HOW THE CMX WORKS:
31  *
32  * There are 3 types of interaction: One member is alone, in this case only
33  * data flow from upper to lower layer is done.
34  * Two members will also exchange their data so they are crossconnected.
35  * Three or more members will be added in a conference and will hear each
36  * other but will not receive their own speech (echo) if not enabled.
37  *
38  * Features of CMX are:
39  *  - Crossconnecting or even conference, if more than two members are together.
40  *  - Force mixing of transmit data with other crossconnect/conference members.
41  *  - Echo generation to benchmark the delay of audio processing.
42  *  - Use hardware to minimize cpu load, disable FIFO load and minimize delay.
43  *  - Dejittering and clock generation.
44  *
45  * There are 2 buffers:
46  *
47  *
48  * RX-Buffer
49  *                 R             W
50  *                 |             |
51  * ----------------+-------------+-------------------
52  *
53  * The rx-buffer is a ring buffer used to store the received data for each
54  * individual member. This is only the case if data needs to be dejittered
55  * or in case of a conference where different clocks require reclocking.
56  * The transmit-clock (R) will read the buffer.
57  * If the clock overruns the write-pointer, we will have a buffer underrun.
58  * If the write pointer always has a certain distance from the transmit-
59  * clock, we will have a delay. The delay will dynamically be increased and
60  * reduced.
61  *
62  *
63  * TX-Buffer
64  *                  R        W
65  *                  |        |
66  * -----------------+--------+-----------------------
67  *
68  * The tx-buffer is a ring buffer to queue the transmit data from user space
69  * until it will be mixed or sent. There are two pointers, R and W. If the write
70  * pointer W would reach or overrun R, the buffer would overrun. In this case
71  * (some) data is dropped so that it will not overrun.
72  * Additionally a dynamic dejittering can be enabled. this allows data from
73  * user space that have jitter and different clock source.
74  *
75  *
76  * Clock:
77  *
78  * A Clock is not required, if the data source has exactly one clock. In this
79  * case the data source is forwarded to the destination.
80  *
81  * A Clock is required, because the data source
82  *  - has multiple clocks.
83  *  - has no usable clock due to jitter or packet loss (VoIP).
84  * In this case the system's clock is used. The clock resolution depends on
85  * the jiffy resolution.
86  *
87  * If a member joins a conference:
88  *
89  * - If a member joins, its rx_buff is set to silence and change read pointer
90  *   to transmit clock.
91  *
92  * The procedure of received data from card is explained in cmx_receive.
93  * The procedure of received data from user space is explained in cmx_transmit.
94  * The procedure of transmit data to card is cmx_send.
95  *
96  *
97  * Interaction with other features:
98  *
99  * DTMF:
100  * DTMF decoding is done before the data is crossconnected.
101  *
102  * Volume change:
103  * Changing rx-volume is done before the data is crossconnected. The tx-volume
104  * must be changed whenever data is transmitted to the card by the cmx.
105  *
106  * Tones:
107  * If a tone is enabled, it will be processed whenever data is transmitted to
108  * the card. It will replace the tx-data from the user space.
109  * If tones are generated by hardware, this conference member is removed for
110  * this time.
111  *
112  * Disable rx-data:
113  * If cmx is realized in hardware, rx data will be disabled if requested by
114  * the upper layer. If dtmf decoding is done by software and enabled, rx data
115  * will not be disabled but blocked to the upper layer.
116  *
117  * HFC conference engine:
118  * If it is possible to realize all features using hardware, hardware will be
119  * used if not forbidden by control command. Disabling rx-data provides
120  * absolutely traffic free audio processing. (except for the quick 1-frame
121  * upload of a tone loop, only once for a new tone)
122  *
123  */
124
125 /* delay.h is required for hw_lock.h */
126
127 #include <linux/slab.h>
128 #include <linux/delay.h>
129 #include <linux/mISDNif.h>
130 #include <linux/mISDNdsp.h>
131 #include "core.h"
132 #include "dsp.h"
133 /*
134  * debugging of multi party conference,
135  * by using conference even with two members
136  */
137
138 /* #define CMX_CONF_DEBUG */
139
140 /*#define CMX_DEBUG * massive read/write pointer output */
141 /*#define CMX_DELAY_DEBUG * gives rx-buffer delay overview */
142 /*#define CMX_TX_DEBUG * massive read/write on tx-buffer with content */
143
144 /*
145  * debug cmx memory structure
146  */
147 void
148 dsp_cmx_debug(struct dsp *dsp)
149 {
150         struct dsp_conf *conf;
151         struct dsp_conf_member  *member;
152         struct dsp              *odsp;
153
154         printk(KERN_DEBUG "-----Current DSP\n");
155         list_for_each_entry(odsp, &dsp_ilist, list) {
156                 printk(KERN_DEBUG "* %s hardecho=%d softecho=%d txmix=%d",
157                        odsp->name, odsp->echo.hardware, odsp->echo.software,
158                        odsp->tx_mix);
159                 if (odsp->conf)
160                         printk(" (Conf %d)", odsp->conf->id);
161                 if (dsp == odsp)
162                         printk(" *this*");
163                 printk("\n");
164         }
165         printk(KERN_DEBUG "-----Current Conf:\n");
166         list_for_each_entry(conf, &conf_ilist, list) {
167                 printk(KERN_DEBUG "* Conf %d (%p)\n", conf->id, conf);
168                 list_for_each_entry(member, &conf->mlist, list) {
169                         printk(KERN_DEBUG
170                                "  - member = %s (slot_tx %d, bank_tx %d, "
171                                "slot_rx %d, bank_rx %d hfc_conf %d "
172                                "tx_data %d rx_is_off %d)%s\n",
173                                member->dsp->name, member->dsp->pcm_slot_tx,
174                                member->dsp->pcm_bank_tx, member->dsp->pcm_slot_rx,
175                                member->dsp->pcm_bank_rx, member->dsp->hfc_conf,
176                                member->dsp->tx_data, member->dsp->rx_is_off,
177                                (member->dsp == dsp) ? " *this*" : "");
178                 }
179         }
180         printk(KERN_DEBUG "-----end\n");
181 }
182
183 /*
184  * search conference
185  */
186 static struct dsp_conf *
187 dsp_cmx_search_conf(u32 id)
188 {
189         struct dsp_conf *conf;
190
191         if (!id) {
192                 printk(KERN_WARNING "%s: conference ID is 0.\n", __func__);
193                 return NULL;
194         }
195
196         /* search conference */
197         list_for_each_entry(conf, &conf_ilist, list)
198                 if (conf->id == id)
199                         return conf;
200
201         return NULL;
202 }
203
204
205 /*
206  * add member to conference
207  */
208 static int
209 dsp_cmx_add_conf_member(struct dsp *dsp, struct dsp_conf *conf)
210 {
211         struct dsp_conf_member *member;
212
213         if (!conf || !dsp) {
214                 printk(KERN_WARNING "%s: conf or dsp is 0.\n", __func__);
215                 return -EINVAL;
216         }
217         if (dsp->member) {
218                 printk(KERN_WARNING "%s: dsp is already member in a conf.\n",
219                        __func__);
220                 return -EINVAL;
221         }
222
223         if (dsp->conf) {
224                 printk(KERN_WARNING "%s: dsp is already in a conf.\n",
225                        __func__);
226                 return -EINVAL;
227         }
228
229         member = kzalloc(sizeof(struct dsp_conf_member), GFP_ATOMIC);
230         if (!member) {
231                 printk(KERN_ERR "kzalloc struct dsp_conf_member failed\n");
232                 return -ENOMEM;
233         }
234         member->dsp = dsp;
235         /* clear rx buffer */
236         memset(dsp->rx_buff, dsp_silence, sizeof(dsp->rx_buff));
237         dsp->rx_init = 1; /* rx_W and rx_R will be adjusted on first frame */
238         dsp->rx_W = 0;
239         dsp->rx_R = 0;
240
241         list_add_tail(&member->list, &conf->mlist);
242
243         dsp->conf = conf;
244         dsp->member = member;
245
246         return 0;
247 }
248
249
250 /*
251  * del member from conference
252  */
253 int
254 dsp_cmx_del_conf_member(struct dsp *dsp)
255 {
256         struct dsp_conf_member *member;
257
258         if (!dsp) {
259                 printk(KERN_WARNING "%s: dsp is 0.\n",
260                        __func__);
261                 return -EINVAL;
262         }
263
264         if (!dsp->conf) {
265                 printk(KERN_WARNING "%s: dsp is not in a conf.\n",
266                        __func__);
267                 return -EINVAL;
268         }
269
270         if (list_empty(&dsp->conf->mlist)) {
271                 printk(KERN_WARNING "%s: dsp has linked an empty conf.\n",
272                        __func__);
273                 return -EINVAL;
274         }
275
276         /* find us in conf */
277         list_for_each_entry(member, &dsp->conf->mlist, list) {
278                 if (member->dsp == dsp) {
279                         list_del(&member->list);
280                         dsp->conf = NULL;
281                         dsp->member = NULL;
282                         kfree(member);
283                         return 0;
284                 }
285         }
286         printk(KERN_WARNING
287                "%s: dsp is not present in its own conf_member list.\n",
288                __func__);
289
290         return -EINVAL;
291 }
292
293
294 /*
295  * new conference
296  */
297 static struct dsp_conf
298 *dsp_cmx_new_conf(u32 id)
299 {
300         struct dsp_conf *conf;
301
302         if (!id) {
303                 printk(KERN_WARNING "%s: id is 0.\n",
304                        __func__);
305                 return NULL;
306         }
307
308         conf = kzalloc(sizeof(struct dsp_conf), GFP_ATOMIC);
309         if (!conf) {
310                 printk(KERN_ERR "kzalloc struct dsp_conf failed\n");
311                 return NULL;
312         }
313         INIT_LIST_HEAD(&conf->mlist);
314         conf->id = id;
315
316         list_add_tail(&conf->list, &conf_ilist);
317
318         return conf;
319 }
320
321
322 /*
323  * del conference
324  */
325 int
326 dsp_cmx_del_conf(struct dsp_conf *conf)
327 {
328         if (!conf) {
329                 printk(KERN_WARNING "%s: conf is null.\n",
330                        __func__);
331                 return -EINVAL;
332         }
333
334         if (!list_empty(&conf->mlist)) {
335                 printk(KERN_WARNING "%s: conf not empty.\n",
336                        __func__);
337                 return -EINVAL;
338         }
339         list_del(&conf->list);
340         kfree(conf);
341
342         return 0;
343 }
344
345
346 /*
347  * send HW message to hfc card
348  */
349 static void
350 dsp_cmx_hw_message(struct dsp *dsp, u32 message, u32 param1, u32 param2,
351                    u32 param3, u32 param4)
352 {
353         struct mISDN_ctrl_req cq;
354
355         memset(&cq, 0, sizeof(cq));
356         cq.op = message;
357         cq.p1 = param1 | (param2 << 8);
358         cq.p2 = param3 | (param4 << 8);
359         if (dsp->ch.peer)
360                 dsp->ch.peer->ctrl(dsp->ch.peer, CONTROL_CHANNEL, &cq);
361 }
362
363
364 /*
365  * do hardware update and set the software/hardware flag
366  *
367  * either a conference or a dsp instance can be given
368  * if only dsp instance is given, the instance is not associated with a conf
369  * and therefore removed. if a conference is given, the dsp is expected to
370  * be member of that conference.
371  */
372 void
373 dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp)
374 {
375         struct dsp_conf_member  *member, *nextm;
376         struct dsp              *finddsp;
377         int             memb = 0, i, ii, i1, i2;
378         int             freeunits[8];
379         u_char          freeslots[256];
380         int             same_hfc = -1, same_pcm = -1, current_conf = -1,
381                 all_conf = 1, tx_data = 0;
382
383         /* dsp gets updated (no conf) */
384         if (!conf) {
385                 if (!dsp)
386                         return;
387                 if (dsp_debug & DEBUG_DSP_CMX)
388                         printk(KERN_DEBUG "%s checking dsp %s\n",
389                                __func__, dsp->name);
390         one_member:
391                 /* remove HFC conference if enabled */
392                 if (dsp->hfc_conf >= 0) {
393                         if (dsp_debug & DEBUG_DSP_CMX)
394                                 printk(KERN_DEBUG
395                                        "%s removing %s from HFC conf %d "
396                                        "because dsp is split\n", __func__,
397                                        dsp->name, dsp->hfc_conf);
398                         dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_CONF_SPLIT,
399                                            0, 0, 0, 0);
400                         dsp->hfc_conf = -1;
401                 }
402                 /* process hw echo */
403                 if (dsp->features.pcm_banks < 1)
404                         return;
405                 if (!dsp->echo.software && !dsp->echo.hardware) {
406                         /* NO ECHO: remove PCM slot if assigned */
407                         if (dsp->pcm_slot_tx >= 0 || dsp->pcm_slot_rx >= 0) {
408                                 if (dsp_debug & DEBUG_DSP_CMX)
409                                         printk(KERN_DEBUG "%s removing %s from"
410                                                " PCM slot %d (TX) %d (RX) because"
411                                                " dsp is split (no echo)\n",
412                                                __func__, dsp->name,
413                                                dsp->pcm_slot_tx, dsp->pcm_slot_rx);
414                                 dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_PCM_DISC,
415                                                    0, 0, 0, 0);
416                                 dsp->pcm_slot_tx = -1;
417                                 dsp->pcm_bank_tx = -1;
418                                 dsp->pcm_slot_rx = -1;
419                                 dsp->pcm_bank_rx = -1;
420                         }
421                         return;
422                 }
423                 /* echo is enabled, find out if we use soft or hardware */
424                 dsp->echo.software = dsp->tx_data;
425                 dsp->echo.hardware = 0;
426                 /* ECHO: already echo */
427                 if (dsp->pcm_slot_tx >= 0 && dsp->pcm_slot_rx < 0 &&
428                     dsp->pcm_bank_tx == 2 && dsp->pcm_bank_rx == 2) {
429                         dsp->echo.hardware = 1;
430                         return;
431                 }
432                 /* ECHO: if slot already assigned */
433                 if (dsp->pcm_slot_tx >= 0) {
434                         dsp->pcm_slot_rx = dsp->pcm_slot_tx;
435                         dsp->pcm_bank_tx = 2; /* 2 means loop */
436                         dsp->pcm_bank_rx = 2;
437                         if (dsp_debug & DEBUG_DSP_CMX)
438                                 printk(KERN_DEBUG
439                                        "%s refresh %s for echo using slot %d\n",
440                                        __func__, dsp->name,
441                                        dsp->pcm_slot_tx);
442                         dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_PCM_CONN,
443                                            dsp->pcm_slot_tx, 2, dsp->pcm_slot_rx, 2);
444                         dsp->echo.hardware = 1;
445                         return;
446                 }
447                 /* ECHO: find slot */
448                 dsp->pcm_slot_tx = -1;
449                 dsp->pcm_slot_rx = -1;
450                 memset(freeslots, 1, sizeof(freeslots));
451                 list_for_each_entry(finddsp, &dsp_ilist, list) {
452                         if (finddsp->features.pcm_id == dsp->features.pcm_id) {
453                                 if (finddsp->pcm_slot_rx >= 0 &&
454                                     finddsp->pcm_slot_rx < sizeof(freeslots))
455                                         freeslots[finddsp->pcm_slot_rx] = 0;
456                                 if (finddsp->pcm_slot_tx >= 0 &&
457                                     finddsp->pcm_slot_tx < sizeof(freeslots))
458                                         freeslots[finddsp->pcm_slot_tx] = 0;
459                         }
460                 }
461                 i = 0;
462                 ii = dsp->features.pcm_slots;
463                 while (i < ii) {
464                         if (freeslots[i])
465                                 break;
466                         i++;
467                 }
468                 if (i == ii) {
469                         if (dsp_debug & DEBUG_DSP_CMX)
470                                 printk(KERN_DEBUG
471                                        "%s no slot available for echo\n",
472                                        __func__);
473                         /* no more slots available */
474                         dsp->echo.software = 1;
475                         return;
476                 }
477                 /* assign free slot */
478                 dsp->pcm_slot_tx = i;
479                 dsp->pcm_slot_rx = i;
480                 dsp->pcm_bank_tx = 2; /* loop */
481                 dsp->pcm_bank_rx = 2;
482                 if (dsp_debug & DEBUG_DSP_CMX)
483                         printk(KERN_DEBUG
484                                "%s assign echo for %s using slot %d\n",
485                                __func__, dsp->name, dsp->pcm_slot_tx);
486                 dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_PCM_CONN,
487                                    dsp->pcm_slot_tx, 2, dsp->pcm_slot_rx, 2);
488                 dsp->echo.hardware = 1;
489                 return;
490         }
491
492         /* conf gets updated (all members) */
493         if (dsp_debug & DEBUG_DSP_CMX)
494                 printk(KERN_DEBUG "%s checking conference %d\n",
495                        __func__, conf->id);
496
497         if (list_empty(&conf->mlist)) {
498                 printk(KERN_ERR "%s: conference without members\n",
499                        __func__);
500                 return;
501         }
502         member = list_entry(conf->mlist.next, struct dsp_conf_member, list);
503         same_hfc = member->dsp->features.hfc_id;
504         same_pcm = member->dsp->features.pcm_id;
505         /* check all members in our conference */
506         list_for_each_entry(member, &conf->mlist, list) {
507                 /* check if member uses mixing */
508                 if (member->dsp->tx_mix) {
509                         if (dsp_debug & DEBUG_DSP_CMX)
510                                 printk(KERN_DEBUG
511                                        "%s dsp %s cannot form a conf, because "
512                                        "tx_mix is turned on\n", __func__,
513                                        member->dsp->name);
514                 conf_software:
515                         list_for_each_entry(member, &conf->mlist, list) {
516                                 dsp = member->dsp;
517                                 /* remove HFC conference if enabled */
518                                 if (dsp->hfc_conf >= 0) {
519                                         if (dsp_debug & DEBUG_DSP_CMX)
520                                                 printk(KERN_DEBUG
521                                                        "%s removing %s from HFC "
522                                                        "conf %d because not "
523                                                        "possible with hardware\n",
524                                                        __func__,
525                                                        dsp->name,
526                                                        dsp->hfc_conf);
527                                         dsp_cmx_hw_message(dsp,
528                                                            MISDN_CTRL_HFC_CONF_SPLIT,
529                                                            0, 0, 0, 0);
530                                         dsp->hfc_conf = -1;
531                                 }
532                                 /* remove PCM slot if assigned */
533                                 if (dsp->pcm_slot_tx >= 0 ||
534                                     dsp->pcm_slot_rx >= 0) {
535                                         if (dsp_debug & DEBUG_DSP_CMX)
536                                                 printk(KERN_DEBUG "%s removing "
537                                                        "%s from PCM slot %d (TX)"
538                                                        " slot %d (RX) because not"
539                                                        " possible with hardware\n",
540                                                        __func__,
541                                                        dsp->name,
542                                                        dsp->pcm_slot_tx,
543                                                        dsp->pcm_slot_rx);
544                                         dsp_cmx_hw_message(dsp,
545                                                            MISDN_CTRL_HFC_PCM_DISC,
546                                                            0, 0, 0, 0);
547                                         dsp->pcm_slot_tx = -1;
548                                         dsp->pcm_bank_tx = -1;
549                                         dsp->pcm_slot_rx = -1;
550                                         dsp->pcm_bank_rx = -1;
551                                 }
552                         }
553                         conf->hardware = 0;
554                         conf->software = 1;
555                         return;
556                 }
557                 /* check if member has echo turned on */
558                 if (member->dsp->echo.hardware || member->dsp->echo.software) {
559                         if (dsp_debug & DEBUG_DSP_CMX)
560                                 printk(KERN_DEBUG
561                                        "%s dsp %s cannot form a conf, because "
562                                        "echo is turned on\n", __func__,
563                                        member->dsp->name);
564                         goto conf_software;
565                 }
566                 /* check if member has tx_mix turned on */
567                 if (member->dsp->tx_mix) {
568                         if (dsp_debug & DEBUG_DSP_CMX)
569                                 printk(KERN_DEBUG
570                                        "%s dsp %s cannot form a conf, because "
571                                        "tx_mix is turned on\n",
572                                        __func__, member->dsp->name);
573                         goto conf_software;
574                 }
575                 /* check if member changes volume at an not suppoted level */
576                 if (member->dsp->tx_volume) {
577                         if (dsp_debug & DEBUG_DSP_CMX)
578                                 printk(KERN_DEBUG
579                                        "%s dsp %s cannot form a conf, because "
580                                        "tx_volume is changed\n",
581                                        __func__, member->dsp->name);
582                         goto conf_software;
583                 }
584                 if (member->dsp->rx_volume) {
585                         if (dsp_debug & DEBUG_DSP_CMX)
586                                 printk(KERN_DEBUG
587                                        "%s dsp %s cannot form a conf, because "
588                                        "rx_volume is changed\n",
589                                        __func__, member->dsp->name);
590                         goto conf_software;
591                 }
592                 /* check if tx-data turned on */
593                 if (member->dsp->tx_data) {
594                         if (dsp_debug & DEBUG_DSP_CMX)
595                                 printk(KERN_DEBUG
596                                        "%s dsp %s tx_data is turned on\n",
597                                        __func__, member->dsp->name);
598                         tx_data = 1;
599                 }
600                 /* check if pipeline exists */
601                 if (member->dsp->pipeline.inuse) {
602                         if (dsp_debug & DEBUG_DSP_CMX)
603                                 printk(KERN_DEBUG
604                                        "%s dsp %s cannot form a conf, because "
605                                        "pipeline exists\n", __func__,
606                                        member->dsp->name);
607                         goto conf_software;
608                 }
609                 /* check if encryption is enabled */
610                 if (member->dsp->bf_enable) {
611                         if (dsp_debug & DEBUG_DSP_CMX)
612                                 printk(KERN_DEBUG "%s dsp %s cannot form a "
613                                        "conf, because encryption is enabled\n",
614                                        __func__, member->dsp->name);
615                         goto conf_software;
616                 }
617                 /* check if member is on a card with PCM support */
618                 if (member->dsp->features.pcm_id < 0) {
619                         if (dsp_debug & DEBUG_DSP_CMX)
620                                 printk(KERN_DEBUG
621                                        "%s dsp %s cannot form a conf, because "
622                                        "dsp has no PCM bus\n",
623                                        __func__, member->dsp->name);
624                         goto conf_software;
625                 }
626                 /* check if relations are on the same PCM bus */
627                 if (member->dsp->features.pcm_id != same_pcm) {
628                         if (dsp_debug & DEBUG_DSP_CMX)
629                                 printk(KERN_DEBUG
630                                        "%s dsp %s cannot form a conf, because "
631                                        "dsp is on a different PCM bus than the "
632                                        "first dsp\n",
633                                        __func__, member->dsp->name);
634                         goto conf_software;
635                 }
636                 /* determine if members are on the same hfc chip */
637                 if (same_hfc != member->dsp->features.hfc_id)
638                         same_hfc = -1;
639                 /* if there are members already in a conference */
640                 if (current_conf < 0 && member->dsp->hfc_conf >= 0)
641                         current_conf = member->dsp->hfc_conf;
642                 /* if any member is not in a conference */
643                 if (member->dsp->hfc_conf < 0)
644                         all_conf = 0;
645
646                 memb++;
647         }
648
649         /* if no member, this is an error */
650         if (memb < 1)
651                 return;
652
653         /* one member */
654         if (memb == 1) {
655                 if (dsp_debug & DEBUG_DSP_CMX)
656                         printk(KERN_DEBUG
657                                "%s conf %d cannot form a HW conference, "
658                                "because dsp is alone\n", __func__, conf->id);
659                 conf->hardware = 0;
660                 conf->software = 0;
661                 member = list_entry(conf->mlist.next, struct dsp_conf_member,
662                                     list);
663                 dsp = member->dsp;
664                 goto one_member;
665         }
666
667         /*
668          * ok, now we are sure that all members are on the same pcm.
669          * now we will see if we have only two members, so we can do
670          * crossconnections, which don't have any limitations.
671          */
672
673         /* if we have only two members */
674         if (memb == 2) {
675                 member = list_entry(conf->mlist.next, struct dsp_conf_member,
676                                     list);
677                 nextm = list_entry(member->list.next, struct dsp_conf_member,
678                                    list);
679                 /* remove HFC conference if enabled */
680                 if (member->dsp->hfc_conf >= 0) {
681                         if (dsp_debug & DEBUG_DSP_CMX)
682                                 printk(KERN_DEBUG
683                                        "%s removing %s from HFC conf %d because "
684                                        "two parties require only a PCM slot\n",
685                                        __func__, member->dsp->name,
686                                        member->dsp->hfc_conf);
687                         dsp_cmx_hw_message(member->dsp,
688                                            MISDN_CTRL_HFC_CONF_SPLIT, 0, 0, 0, 0);
689                         member->dsp->hfc_conf = -1;
690                 }
691                 if (nextm->dsp->hfc_conf >= 0) {
692                         if (dsp_debug & DEBUG_DSP_CMX)
693                                 printk(KERN_DEBUG
694                                        "%s removing %s from HFC conf %d because "
695                                        "two parties require only a PCM slot\n",
696                                        __func__, nextm->dsp->name,
697                                        nextm->dsp->hfc_conf);
698                         dsp_cmx_hw_message(nextm->dsp,
699                                            MISDN_CTRL_HFC_CONF_SPLIT, 0, 0, 0, 0);
700                         nextm->dsp->hfc_conf = -1;
701                 }
702                 /* if members have two banks (and not on the same chip) */
703                 if (member->dsp->features.pcm_banks > 1 &&
704                     nextm->dsp->features.pcm_banks > 1 &&
705                     member->dsp->features.hfc_id !=
706                     nextm->dsp->features.hfc_id) {
707                         /* if both members have same slots with crossed banks */
708                         if (member->dsp->pcm_slot_tx >= 0 &&
709                             member->dsp->pcm_slot_rx >= 0 &&
710                             nextm->dsp->pcm_slot_tx >= 0 &&
711                             nextm->dsp->pcm_slot_rx >= 0 &&
712                             nextm->dsp->pcm_slot_tx ==
713                             member->dsp->pcm_slot_rx &&
714                             nextm->dsp->pcm_slot_rx ==
715                             member->dsp->pcm_slot_tx &&
716                             nextm->dsp->pcm_slot_tx ==
717                             member->dsp->pcm_slot_tx &&
718                             member->dsp->pcm_bank_tx !=
719                             member->dsp->pcm_bank_rx &&
720                             nextm->dsp->pcm_bank_tx !=
721                             nextm->dsp->pcm_bank_rx) {
722                                 /* all members have same slot */
723                                 if (dsp_debug & DEBUG_DSP_CMX)
724                                         printk(KERN_DEBUG
725                                                "%s dsp %s & %s stay joined on "
726                                                "PCM slot %d bank %d (TX) bank %d "
727                                                "(RX) (on different chips)\n",
728                                                __func__,
729                                                member->dsp->name,
730                                                nextm->dsp->name,
731                                                member->dsp->pcm_slot_tx,
732                                                member->dsp->pcm_bank_tx,
733                                                member->dsp->pcm_bank_rx);
734                                 conf->hardware = 1;
735                                 conf->software = tx_data;
736                                 return;
737                         }
738                         /* find a new slot */
739                         memset(freeslots, 1, sizeof(freeslots));
740                         list_for_each_entry(dsp, &dsp_ilist, list) {
741                                 if (dsp != member->dsp &&
742                                     dsp != nextm->dsp &&
743                                     member->dsp->features.pcm_id ==
744                                     dsp->features.pcm_id) {
745                                         if (dsp->pcm_slot_rx >= 0 &&
746                                             dsp->pcm_slot_rx <
747                                             sizeof(freeslots))
748                                                 freeslots[dsp->pcm_slot_rx] = 0;
749                                         if (dsp->pcm_slot_tx >= 0 &&
750                                             dsp->pcm_slot_tx <
751                                             sizeof(freeslots))
752                                                 freeslots[dsp->pcm_slot_tx] = 0;
753                                 }
754                         }
755                         i = 0;
756                         ii = member->dsp->features.pcm_slots;
757                         while (i < ii) {
758                                 if (freeslots[i])
759                                         break;
760                                 i++;
761                         }
762                         if (i == ii) {
763                                 if (dsp_debug & DEBUG_DSP_CMX)
764                                         printk(KERN_DEBUG
765                                                "%s no slot available for "
766                                                "%s & %s\n", __func__,
767                                                member->dsp->name,
768                                                nextm->dsp->name);
769                                 /* no more slots available */
770                                 goto conf_software;
771                         }
772                         /* assign free slot */
773                         member->dsp->pcm_slot_tx = i;
774                         member->dsp->pcm_slot_rx = i;
775                         nextm->dsp->pcm_slot_tx = i;
776                         nextm->dsp->pcm_slot_rx = i;
777                         member->dsp->pcm_bank_rx = 0;
778                         member->dsp->pcm_bank_tx = 1;
779                         nextm->dsp->pcm_bank_rx = 1;
780                         nextm->dsp->pcm_bank_tx = 0;
781                         if (dsp_debug & DEBUG_DSP_CMX)
782                                 printk(KERN_DEBUG
783                                        "%s adding %s & %s to new PCM slot %d "
784                                        "(TX and RX on different chips) because "
785                                        "both members have not same slots\n",
786                                        __func__,
787                                        member->dsp->name,
788                                        nextm->dsp->name,
789                                        member->dsp->pcm_slot_tx);
790                         dsp_cmx_hw_message(member->dsp, MISDN_CTRL_HFC_PCM_CONN,
791                                            member->dsp->pcm_slot_tx, member->dsp->pcm_bank_tx,
792                                            member->dsp->pcm_slot_rx, member->dsp->pcm_bank_rx);
793                         dsp_cmx_hw_message(nextm->dsp, MISDN_CTRL_HFC_PCM_CONN,
794                                            nextm->dsp->pcm_slot_tx, nextm->dsp->pcm_bank_tx,
795                                            nextm->dsp->pcm_slot_rx, nextm->dsp->pcm_bank_rx);
796                         conf->hardware = 1;
797                         conf->software = tx_data;
798                         return;
799                         /* if members have one bank (or on the same chip) */
800                 } else {
801                         /* if both members have different crossed slots */
802                         if (member->dsp->pcm_slot_tx >= 0 &&
803                             member->dsp->pcm_slot_rx >= 0 &&
804                             nextm->dsp->pcm_slot_tx >= 0 &&
805                             nextm->dsp->pcm_slot_rx >= 0 &&
806                             nextm->dsp->pcm_slot_tx ==
807                             member->dsp->pcm_slot_rx &&
808                             nextm->dsp->pcm_slot_rx ==
809                             member->dsp->pcm_slot_tx &&
810                             member->dsp->pcm_slot_tx !=
811                             member->dsp->pcm_slot_rx &&
812                             member->dsp->pcm_bank_tx == 0 &&
813                             member->dsp->pcm_bank_rx == 0 &&
814                             nextm->dsp->pcm_bank_tx == 0 &&
815                             nextm->dsp->pcm_bank_rx == 0) {
816                                 /* all members have same slot */
817                                 if (dsp_debug & DEBUG_DSP_CMX)
818                                         printk(KERN_DEBUG
819                                                "%s dsp %s & %s stay joined on PCM "
820                                                "slot %d (TX) %d (RX) on same chip "
821                                                "or one bank PCM)\n", __func__,
822                                                member->dsp->name,
823                                                nextm->dsp->name,
824                                                member->dsp->pcm_slot_tx,
825                                                member->dsp->pcm_slot_rx);
826                                 conf->hardware = 1;
827                                 conf->software = tx_data;
828                                 return;
829                         }
830                         /* find two new slot */
831                         memset(freeslots, 1, sizeof(freeslots));
832                         list_for_each_entry(dsp, &dsp_ilist, list) {
833                                 if (dsp != member->dsp &&
834                                     dsp != nextm->dsp &&
835                                     member->dsp->features.pcm_id ==
836                                     dsp->features.pcm_id) {
837                                         if (dsp->pcm_slot_rx >= 0 &&
838                                             dsp->pcm_slot_rx <
839                                             sizeof(freeslots))
840                                                 freeslots[dsp->pcm_slot_rx] = 0;
841                                         if (dsp->pcm_slot_tx >= 0 &&
842                                             dsp->pcm_slot_tx <
843                                             sizeof(freeslots))
844                                                 freeslots[dsp->pcm_slot_tx] = 0;
845                                 }
846                         }
847                         i1 = 0;
848                         ii = member->dsp->features.pcm_slots;
849                         while (i1 < ii) {
850                                 if (freeslots[i1])
851                                         break;
852                                 i1++;
853                         }
854                         if (i1 == ii) {
855                                 if (dsp_debug & DEBUG_DSP_CMX)
856                                         printk(KERN_DEBUG
857                                                "%s no slot available "
858                                                "for %s & %s\n", __func__,
859                                                member->dsp->name,
860                                                nextm->dsp->name);
861                                 /* no more slots available */
862                                 goto conf_software;
863                         }
864                         i2 = i1 + 1;
865                         while (i2 < ii) {
866                                 if (freeslots[i2])
867                                         break;
868                                 i2++;
869                         }
870                         if (i2 == ii) {
871                                 if (dsp_debug & DEBUG_DSP_CMX)
872                                         printk(KERN_DEBUG
873                                                "%s no slot available "
874                                                "for %s & %s\n",
875                                                __func__,
876                                                member->dsp->name,
877                                                nextm->dsp->name);
878                                 /* no more slots available */
879                                 goto conf_software;
880                         }
881                         /* assign free slots */
882                         member->dsp->pcm_slot_tx = i1;
883                         member->dsp->pcm_slot_rx = i2;
884                         nextm->dsp->pcm_slot_tx = i2;
885                         nextm->dsp->pcm_slot_rx = i1;
886                         member->dsp->pcm_bank_rx = 0;
887                         member->dsp->pcm_bank_tx = 0;
888                         nextm->dsp->pcm_bank_rx = 0;
889                         nextm->dsp->pcm_bank_tx = 0;
890                         if (dsp_debug & DEBUG_DSP_CMX)
891                                 printk(KERN_DEBUG
892                                        "%s adding %s & %s to new PCM slot %d "
893                                        "(TX) %d (RX) on same chip or one bank "
894                                        "PCM, because both members have not "
895                                        "crossed slots\n", __func__,
896                                        member->dsp->name,
897                                        nextm->dsp->name,
898                                        member->dsp->pcm_slot_tx,
899                                        member->dsp->pcm_slot_rx);
900                         dsp_cmx_hw_message(member->dsp, MISDN_CTRL_HFC_PCM_CONN,
901                                            member->dsp->pcm_slot_tx, member->dsp->pcm_bank_tx,
902                                            member->dsp->pcm_slot_rx, member->dsp->pcm_bank_rx);
903                         dsp_cmx_hw_message(nextm->dsp, MISDN_CTRL_HFC_PCM_CONN,
904                                            nextm->dsp->pcm_slot_tx, nextm->dsp->pcm_bank_tx,
905                                            nextm->dsp->pcm_slot_rx, nextm->dsp->pcm_bank_rx);
906                         conf->hardware = 1;
907                         conf->software = tx_data;
908                         return;
909                 }
910         }
911
912         /*
913          * if we have more than two, we may check if we have a conference
914          * unit available on the chip. also all members must be on the same
915          */
916
917         /* if not the same HFC chip */
918         if (same_hfc < 0) {
919                 if (dsp_debug & DEBUG_DSP_CMX)
920                         printk(KERN_DEBUG
921                                "%s conference %d cannot be formed, because "
922                                "members are on different chips or not "
923                                "on HFC chip\n",
924                                __func__, conf->id);
925                 goto conf_software;
926         }
927
928         /* for more than two members.. */
929
930         /* if all members already have the same conference */
931         if (all_conf) {
932                 conf->hardware = 1;
933                 conf->software = tx_data;
934                 return;
935         }
936
937         /*
938          * if there is an existing conference, but not all members have joined
939          */
940         if (current_conf >= 0) {
941         join_members:
942                 list_for_each_entry(member, &conf->mlist, list) {
943                         /* if no conference engine on our chip, change to
944                          * software */
945                         if (!member->dsp->features.hfc_conf)
946                                 goto conf_software;
947                         /* in case of hdlc, change to software */
948                         if (member->dsp->hdlc)
949                                 goto conf_software;
950                         /* join to current conference */
951                         if (member->dsp->hfc_conf == current_conf)
952                                 continue;
953                         /* get a free timeslot first */
954                         memset(freeslots, 1, sizeof(freeslots));
955                         list_for_each_entry(dsp, &dsp_ilist, list) {
956                                 /*
957                                  * not checking current member, because
958                                  * slot will be overwritten.
959                                  */
960                                 if (
961                                         dsp != member->dsp &&
962                                         /* dsp must be on the same PCM */
963                                         member->dsp->features.pcm_id ==
964                                         dsp->features.pcm_id) {
965                                         /* dsp must be on a slot */
966                                         if (dsp->pcm_slot_tx >= 0 &&
967                                             dsp->pcm_slot_tx <
968                                             sizeof(freeslots))
969                                                 freeslots[dsp->pcm_slot_tx] = 0;
970                                         if (dsp->pcm_slot_rx >= 0 &&
971                                             dsp->pcm_slot_rx <
972                                             sizeof(freeslots))
973                                                 freeslots[dsp->pcm_slot_rx] = 0;
974                                 }
975                         }
976                         i = 0;
977                         ii = member->dsp->features.pcm_slots;
978                         while (i < ii) {
979                                 if (freeslots[i])
980                                         break;
981                                 i++;
982                         }
983                         if (i == ii) {
984                                 /* no more slots available */
985                                 if (dsp_debug & DEBUG_DSP_CMX)
986                                         printk(KERN_DEBUG
987                                                "%s conference %d cannot be formed,"
988                                                " because no slot free\n",
989                                                __func__, conf->id);
990                                 goto conf_software;
991                         }
992                         if (dsp_debug & DEBUG_DSP_CMX)
993                                 printk(KERN_DEBUG
994                                        "%s changing dsp %s to HW conference "
995                                        "%d slot %d\n", __func__,
996                                        member->dsp->name, current_conf, i);
997                         /* assign free slot & set PCM & join conf */
998                         member->dsp->pcm_slot_tx = i;
999                         member->dsp->pcm_slot_rx = i;
1000                         member->dsp->pcm_bank_tx = 2; /* loop */
1001                         member->dsp->pcm_bank_rx = 2;
1002                         member->dsp->hfc_conf = current_conf;
1003                         dsp_cmx_hw_message(member->dsp, MISDN_CTRL_HFC_PCM_CONN,
1004                                            i, 2, i, 2);
1005                         dsp_cmx_hw_message(member->dsp,
1006                                            MISDN_CTRL_HFC_CONF_JOIN, current_conf, 0, 0, 0);
1007                 }
1008                 conf->hardware = 1;
1009                 conf->software = tx_data;
1010                 return;
1011         }
1012
1013         /*
1014          * no member is in a conference yet, so we find a free one
1015          */
1016         memset(freeunits, 1, sizeof(freeunits));
1017         list_for_each_entry(dsp, &dsp_ilist, list) {
1018                 /* dsp must be on the same chip */
1019                 if (dsp->features.hfc_id == same_hfc &&
1020                     /* dsp must have joined a HW conference */
1021                     dsp->hfc_conf >= 0 &&
1022                     /* slot must be within range */
1023                     dsp->hfc_conf < 8)
1024                         freeunits[dsp->hfc_conf] = 0;
1025         }
1026         i = 0;
1027         ii = 8;
1028         while (i < ii) {
1029                 if (freeunits[i])
1030                         break;
1031                 i++;
1032         }
1033         if (i == ii) {
1034                 /* no more conferences available */
1035                 if (dsp_debug & DEBUG_DSP_CMX)
1036                         printk(KERN_DEBUG
1037                                "%s conference %d cannot be formed, because "
1038                                "no conference number free\n",
1039                                __func__, conf->id);
1040                 goto conf_software;
1041         }
1042         /* join all members */
1043         current_conf = i;
1044         goto join_members;
1045 }
1046
1047
1048 /*
1049  * conf_id != 0: join or change conference
1050  * conf_id == 0: split from conference if not already
1051  */
1052 int
1053 dsp_cmx_conf(struct dsp *dsp, u32 conf_id)
1054 {
1055         int err;
1056         struct dsp_conf *conf;
1057         struct dsp_conf_member  *member;
1058
1059         /* if conference doesn't change */
1060         if (dsp->conf_id == conf_id)
1061                 return 0;
1062
1063         /* first remove us from current conf */
1064         if (dsp->conf_id) {
1065                 if (dsp_debug & DEBUG_DSP_CMX)
1066                         printk(KERN_DEBUG "removing us from conference %d\n",
1067                                dsp->conf->id);
1068                 /* remove us from conf */
1069                 conf = dsp->conf;
1070                 err = dsp_cmx_del_conf_member(dsp);
1071                 if (err)
1072                         return err;
1073                 dsp->conf_id = 0;
1074
1075                 /* update hardware */
1076                 dsp_cmx_hardware(NULL, dsp);
1077
1078                 /* conf now empty? */
1079                 if (list_empty(&conf->mlist)) {
1080                         if (dsp_debug & DEBUG_DSP_CMX)
1081                                 printk(KERN_DEBUG
1082                                        "conference is empty, so we remove it.\n");
1083                         err = dsp_cmx_del_conf(conf);
1084                         if (err)
1085                                 return err;
1086                 } else {
1087                         /* update members left on conf */
1088                         dsp_cmx_hardware(conf, NULL);
1089                 }
1090         }
1091
1092         /* if split */
1093         if (!conf_id)
1094                 return 0;
1095
1096         /* now add us to conf */
1097         if (dsp_debug & DEBUG_DSP_CMX)
1098                 printk(KERN_DEBUG "searching conference %d\n",
1099                        conf_id);
1100         conf = dsp_cmx_search_conf(conf_id);
1101         if (!conf) {
1102                 if (dsp_debug & DEBUG_DSP_CMX)
1103                         printk(KERN_DEBUG
1104                                "conference doesn't exist yet, creating.\n");
1105                 /* the conference doesn't exist, so we create */
1106                 conf = dsp_cmx_new_conf(conf_id);
1107                 if (!conf)
1108                         return -EINVAL;
1109         } else if (!list_empty(&conf->mlist)) {
1110                 member = list_entry(conf->mlist.next, struct dsp_conf_member,
1111                                     list);
1112                 if (dsp->hdlc && !member->dsp->hdlc) {
1113                         if (dsp_debug & DEBUG_DSP_CMX)
1114                                 printk(KERN_DEBUG
1115                                        "cannot join transparent conference.\n");
1116                         return -EINVAL;
1117                 }
1118                 if (!dsp->hdlc && member->dsp->hdlc) {
1119                         if (dsp_debug & DEBUG_DSP_CMX)
1120                                 printk(KERN_DEBUG
1121                                        "cannot join hdlc conference.\n");
1122                         return -EINVAL;
1123                 }
1124         }
1125         /* add conference member */
1126         err = dsp_cmx_add_conf_member(dsp, conf);
1127         if (err)
1128                 return err;
1129         dsp->conf_id = conf_id;
1130
1131         /* if we are alone, we do nothing! */
1132         if (list_empty(&conf->mlist)) {
1133                 if (dsp_debug & DEBUG_DSP_CMX)
1134                         printk(KERN_DEBUG
1135                                "we are alone in this conference, so exit.\n");
1136                 /* update hardware */
1137                 dsp_cmx_hardware(NULL, dsp);
1138                 return 0;
1139         }
1140
1141         /* update members on conf */
1142         dsp_cmx_hardware(conf, NULL);
1143
1144         return 0;
1145 }
1146
1147 #ifdef CMX_DELAY_DEBUG
1148 int delaycount;
1149 static void
1150 showdelay(struct dsp *dsp, int samples, int delay)
1151 {
1152         char bar[] = "--------------------------------------------------|";
1153         int sdelay;
1154
1155         delaycount += samples;
1156         if (delaycount < 8000)
1157                 return;
1158         delaycount = 0;
1159
1160         sdelay = delay * 50 / (dsp_poll << 2);
1161
1162         printk(KERN_DEBUG "DELAY (%s) %3d >%s\n", dsp->name, delay,
1163                sdelay > 50 ? "..." : bar + 50 - sdelay);
1164 }
1165 #endif
1166
1167 /*
1168  * audio data is received from card
1169  */
1170 void
1171 dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb)
1172 {
1173         u8 *d, *p;
1174         int len = skb->len;
1175         struct mISDNhead *hh = mISDN_HEAD_P(skb);
1176         int w, i, ii;
1177
1178         /* check if we have sompen */
1179         if (len < 1)
1180                 return;
1181
1182         /* half of the buffer should be larger than maximum packet size */
1183         if (len >= CMX_BUFF_HALF) {
1184                 printk(KERN_ERR
1185                        "%s line %d: packet from card is too large (%d bytes). "
1186                        "please make card send smaller packets OR increase "
1187                        "CMX_BUFF_SIZE\n", __FILE__, __LINE__, len);
1188                 return;
1189         }
1190
1191         /*
1192          * initialize pointers if not already -
1193          * also add delay if requested by PH_SIGNAL
1194          */
1195         if (dsp->rx_init) {
1196                 dsp->rx_init = 0;
1197                 if (dsp->features.unordered) {
1198                         dsp->rx_R = (hh->id & CMX_BUFF_MASK);
1199                         if (dsp->cmx_delay)
1200                                 dsp->rx_W = (dsp->rx_R + dsp->cmx_delay)
1201                                         & CMX_BUFF_MASK;
1202                         else
1203                                 dsp->rx_W = (dsp->rx_R + (dsp_poll >> 1))
1204                                         & CMX_BUFF_MASK;
1205                 } else {
1206                         dsp->rx_R = 0;
1207                         if (dsp->cmx_delay)
1208                                 dsp->rx_W = dsp->cmx_delay;
1209                         else
1210                                 dsp->rx_W = dsp_poll >> 1;
1211                 }
1212         }
1213         /* if frame contains time code, write directly */
1214         if (dsp->features.unordered) {
1215                 dsp->rx_W = (hh->id & CMX_BUFF_MASK);
1216                 /* printk(KERN_DEBUG "%s %08x\n", dsp->name, hh->id); */
1217         }
1218         /*
1219          * if we underrun (or maybe overrun),
1220          * we set our new read pointer, and write silence to buffer
1221          */
1222         if (((dsp->rx_W-dsp->rx_R) & CMX_BUFF_MASK) >= CMX_BUFF_HALF) {
1223                 if (dsp_debug & DEBUG_DSP_CLOCK)
1224                         printk(KERN_DEBUG
1225                                "cmx_receive(dsp=%lx): UNDERRUN (or overrun the "
1226                                "maximum delay), adjusting read pointer! "
1227                                "(inst %s)\n", (u_long)dsp, dsp->name);
1228                 /* flush rx buffer and set delay to dsp_poll / 2 */
1229                 if (dsp->features.unordered) {
1230                         dsp->rx_R = (hh->id & CMX_BUFF_MASK);
1231                         if (dsp->cmx_delay)
1232                                 dsp->rx_W = (dsp->rx_R + dsp->cmx_delay)
1233                                         & CMX_BUFF_MASK;
1234                         else
1235                                 dsp->rx_W = (dsp->rx_R + (dsp_poll >> 1))
1236                                         & CMX_BUFF_MASK;
1237                 } else {
1238                         dsp->rx_R = 0;
1239                         if (dsp->cmx_delay)
1240                                 dsp->rx_W = dsp->cmx_delay;
1241                         else
1242                                 dsp->rx_W = dsp_poll >> 1;
1243                 }
1244                 memset(dsp->rx_buff, dsp_silence, sizeof(dsp->rx_buff));
1245         }
1246         /* if we have reached double delay, jump back to middle */
1247         if (dsp->cmx_delay)
1248                 if (((dsp->rx_W - dsp->rx_R) & CMX_BUFF_MASK) >=
1249                     (dsp->cmx_delay << 1)) {
1250                         if (dsp_debug & DEBUG_DSP_CLOCK)
1251                                 printk(KERN_DEBUG
1252                                        "cmx_receive(dsp=%lx): OVERRUN (because "
1253                                        "twice the delay is reached), adjusting "
1254                                        "read pointer! (inst %s)\n",
1255                                        (u_long)dsp, dsp->name);
1256                         /* flush buffer */
1257                         if (dsp->features.unordered) {
1258                                 dsp->rx_R = (hh->id & CMX_BUFF_MASK);
1259                                 dsp->rx_W = (dsp->rx_R + dsp->cmx_delay)
1260                                         & CMX_BUFF_MASK;
1261                         } else {
1262                                 dsp->rx_R = 0;
1263                                 dsp->rx_W = dsp->cmx_delay;
1264                         }
1265                         memset(dsp->rx_buff, dsp_silence, sizeof(dsp->rx_buff));
1266                 }
1267
1268         /* show where to write */
1269 #ifdef CMX_DEBUG
1270         printk(KERN_DEBUG
1271                "cmx_receive(dsp=%lx): rx_R(dsp)=%05x rx_W(dsp)=%05x len=%d %s\n",
1272                (u_long)dsp, dsp->rx_R, dsp->rx_W, len, dsp->name);
1273 #endif
1274
1275         /* write data into rx_buffer */
1276         p = skb->data;
1277         d = dsp->rx_buff;
1278         w = dsp->rx_W;
1279         i = 0;
1280         ii = len;
1281         while (i < ii) {
1282                 d[w++ & CMX_BUFF_MASK] = *p++;
1283                 i++;
1284         }
1285
1286         /* increase write-pointer */
1287         dsp->rx_W = ((dsp->rx_W + len) & CMX_BUFF_MASK);
1288 #ifdef CMX_DELAY_DEBUG
1289         showdelay(dsp, len, (dsp->rx_W-dsp->rx_R) & CMX_BUFF_MASK);
1290 #endif
1291 }
1292
1293
1294 /*
1295  * send (mixed) audio data to card and control jitter
1296  */
1297 static void
1298 dsp_cmx_send_member(struct dsp *dsp, int len, s32 *c, int members)
1299 {
1300         struct dsp_conf *conf = dsp->conf;
1301         struct dsp *member, *other;
1302         register s32 sample;
1303         u8 *d, *p, *q, *o_q;
1304         struct sk_buff *nskb, *txskb;
1305         int r, rr, t, tt, o_r, o_rr;
1306         int preload = 0;
1307         struct mISDNhead *hh, *thh;
1308         int tx_data_only = 0;
1309
1310         /* don't process if: */
1311         if (!dsp->b_active) { /* if not active */
1312                 dsp->last_tx = 0;
1313                 return;
1314         }
1315         if (((dsp->conf && dsp->conf->hardware) || /* hardware conf */
1316              dsp->echo.hardware) && /* OR hardware echo */
1317             dsp->tx_R == dsp->tx_W && /* AND no tx-data */
1318             !(dsp->tone.tone && dsp->tone.software)) { /* AND not soft tones */
1319                 if (!dsp->tx_data) { /* no tx_data for user space required */
1320                         dsp->last_tx = 0;
1321                         return;
1322                 }
1323                 if (dsp->conf && dsp->conf->software && dsp->conf->hardware)
1324                         tx_data_only = 1;
1325                 if (dsp->echo.software && dsp->echo.hardware)
1326                         tx_data_only = 1;
1327         }
1328
1329 #ifdef CMX_DEBUG
1330         printk(KERN_DEBUG
1331                "SEND members=%d dsp=%s, conf=%p, rx_R=%05x rx_W=%05x\n",
1332                members, dsp->name, conf, dsp->rx_R, dsp->rx_W);
1333 #endif
1334
1335         /* preload if we have delay set */
1336         if (dsp->cmx_delay && !dsp->last_tx) {
1337                 preload = len;
1338                 if (preload < 128)
1339                         preload = 128;
1340         }
1341
1342         /* PREPARE RESULT */
1343         nskb = mI_alloc_skb(len + preload, GFP_ATOMIC);
1344         if (!nskb) {
1345                 printk(KERN_ERR
1346                        "FATAL ERROR in mISDN_dsp.o: cannot alloc %d bytes\n",
1347                        len + preload);
1348                 return;
1349         }
1350         hh = mISDN_HEAD_P(nskb);
1351         hh->prim = PH_DATA_REQ;
1352         hh->id = 0;
1353         dsp->last_tx = 1;
1354
1355         /* set pointers, indexes and stuff */
1356         member = dsp;
1357         p = dsp->tx_buff; /* transmit data */
1358         q = dsp->rx_buff; /* received data */
1359         d = skb_put(nskb, preload + len); /* result */
1360         t = dsp->tx_R; /* tx-pointers */
1361         tt = dsp->tx_W;
1362         r = dsp->rx_R; /* rx-pointers */
1363         rr = (r + len) & CMX_BUFF_MASK;
1364
1365         /* preload with silence, if required */
1366         if (preload) {
1367                 memset(d, dsp_silence, preload);
1368                 d += preload;
1369         }
1370
1371         /* PROCESS TONES/TX-DATA ONLY */
1372         if (dsp->tone.tone && dsp->tone.software) {
1373                 /* -> copy tone */
1374                 dsp_tone_copy(dsp, d, len);
1375                 dsp->tx_R = 0; /* clear tx buffer */
1376                 dsp->tx_W = 0;
1377                 goto send_packet;
1378         }
1379         /* if we have tx-data but do not use mixing */
1380         if (!dsp->tx_mix && t != tt) {
1381                 /* -> send tx-data and continue when not enough */
1382 #ifdef CMX_TX_DEBUG
1383                 sprintf(debugbuf, "TX sending (%04x-%04x)%p: ", t, tt, p);
1384 #endif
1385                 while (r != rr && t != tt) {
1386 #ifdef CMX_TX_DEBUG
1387                         if (strlen(debugbuf) < 48)
1388                                 sprintf(debugbuf + strlen(debugbuf), " %02x",
1389                                         p[t]);
1390 #endif
1391                         *d++ = p[t]; /* write tx_buff */
1392                         t = (t + 1) & CMX_BUFF_MASK;
1393                         r = (r + 1) & CMX_BUFF_MASK;
1394                 }
1395                 if (r == rr) {
1396                         dsp->tx_R = t;
1397 #ifdef CMX_TX_DEBUG
1398                         printk(KERN_DEBUG "%s\n", debugbuf);
1399 #endif
1400                         goto send_packet;
1401                 }
1402         }
1403 #ifdef CMX_TX_DEBUG
1404         printk(KERN_DEBUG "%s\n", debugbuf);
1405 #endif
1406
1407         /* PROCESS DATA (one member / no conf) */
1408         if (!conf || members <= 1) {
1409                 /* -> if echo is NOT enabled */
1410                 if (!dsp->echo.software) {
1411                         /* -> send tx-data if available or use 0-volume */
1412                         while (r != rr && t != tt) {
1413                                 *d++ = p[t]; /* write tx_buff */
1414                                 t = (t + 1) & CMX_BUFF_MASK;
1415                                 r = (r + 1) & CMX_BUFF_MASK;
1416                         }
1417                         if (r != rr) {
1418                                 if (dsp_debug & DEBUG_DSP_CLOCK)
1419                                         printk(KERN_DEBUG "%s: RX empty\n",
1420                                                __func__);
1421                                 memset(d, dsp_silence, (rr - r) & CMX_BUFF_MASK);
1422                         }
1423                         /* -> if echo is enabled */
1424                 } else {
1425                         /*
1426                          * -> mix tx-data with echo if available,
1427                          * or use echo only
1428                          */
1429                         while (r != rr && t != tt) {
1430                                 *d++ = dsp_audio_mix_law[(p[t] << 8) | q[r]];
1431                                 t = (t + 1) & CMX_BUFF_MASK;
1432                                 r = (r + 1) & CMX_BUFF_MASK;
1433                         }
1434                         while (r != rr) {
1435                                 *d++ = q[r]; /* echo */
1436                                 r = (r + 1) & CMX_BUFF_MASK;
1437                         }
1438                 }
1439                 dsp->tx_R = t;
1440                 goto send_packet;
1441         }
1442         /* PROCESS DATA (two members) */
1443 #ifdef CMX_CONF_DEBUG
1444         if (0) {
1445 #else
1446         if (members == 2) {
1447 #endif
1448                 /* "other" becomes other party */
1449                 other = (list_entry(conf->mlist.next,
1450                                     struct dsp_conf_member, list))->dsp;
1451                 if (other == member)
1452                         other = (list_entry(conf->mlist.prev,
1453                                     struct dsp_conf_member, list))->dsp;
1454                 o_q = other->rx_buff; /* received data */
1455                 o_rr = (other->rx_R + len) & CMX_BUFF_MASK;
1456                 /* end of rx-pointer */
1457                 o_r = (o_rr - rr + r) & CMX_BUFF_MASK;
1458                 /* start rx-pointer at current read position*/
1459                 /* -> if echo is NOT enabled */
1460                 if (!dsp->echo.software) {
1461                         /*
1462                          * -> copy other member's rx-data,
1463                          * if tx-data is available, mix
1464                          */
1465                         while (o_r != o_rr && t != tt) {
1466                                 *d++ = dsp_audio_mix_law[(p[t] << 8) | o_q[o_r]];
1467                                 t = (t + 1) & CMX_BUFF_MASK;
1468                                 o_r = (o_r + 1) & CMX_BUFF_MASK;
1469                         }
1470                         while (o_r != o_rr) {
1471                                 *d++ = o_q[o_r];
1472                                 o_r = (o_r + 1) & CMX_BUFF_MASK;
1473                         }
1474                         /* -> if echo is enabled */
1475                 } else {
1476                         /*
1477                          * -> mix other member's rx-data with echo,
1478                          * if tx-data is available, mix
1479                          */
1480                         while (r != rr && t != tt) {
1481                                 sample = dsp_audio_law_to_s32[p[t]] +
1482                                         dsp_audio_law_to_s32[q[r]] +
1483                                         dsp_audio_law_to_s32[o_q[o_r]];
1484                                 if (sample < -32768)
1485                                         sample = -32768;
1486                                 else if (sample > 32767)
1487                                         sample = 32767;
1488                                 *d++ = dsp_audio_s16_to_law[sample & 0xffff];
1489                                 /* tx-data + rx_data + echo */
1490                                 t = (t + 1) & CMX_BUFF_MASK;
1491                                 r = (r + 1) & CMX_BUFF_MASK;
1492                                 o_r = (o_r + 1) & CMX_BUFF_MASK;
1493                         }
1494                         while (r != rr) {
1495                                 *d++ = dsp_audio_mix_law[(q[r] << 8) | o_q[o_r]];
1496                                 r = (r + 1) & CMX_BUFF_MASK;
1497                                 o_r = (o_r + 1) & CMX_BUFF_MASK;
1498                         }
1499                 }
1500                 dsp->tx_R = t;
1501                 goto send_packet;
1502         }
1503         /* PROCESS DATA (three or more members) */
1504         /* -> if echo is NOT enabled */
1505         if (!dsp->echo.software) {
1506                 /*
1507                  * -> subtract rx-data from conf-data,
1508                  * if tx-data is available, mix
1509                  */
1510                 while (r != rr && t != tt) {
1511                         sample = dsp_audio_law_to_s32[p[t]] + *c++ -
1512                                 dsp_audio_law_to_s32[q[r]];
1513                         if (sample < -32768)
1514                                 sample = -32768;
1515                         else if (sample > 32767)
1516                                 sample = 32767;
1517                         *d++ = dsp_audio_s16_to_law[sample & 0xffff];
1518                         /* conf-rx+tx */
1519                         r = (r + 1) & CMX_BUFF_MASK;
1520                         t = (t + 1) & CMX_BUFF_MASK;
1521                 }
1522                 while (r != rr) {
1523                         sample = *c++ - dsp_audio_law_to_s32[q[r]];
1524                         if (sample < -32768)
1525                                 sample = -32768;
1526                         else if (sample > 32767)
1527                                 sample = 32767;
1528                         *d++ = dsp_audio_s16_to_law[sample & 0xffff];
1529                         /* conf-rx */
1530                         r = (r + 1) & CMX_BUFF_MASK;
1531                 }
1532                 /* -> if echo is enabled */
1533         } else {
1534                 /*
1535                  * -> encode conf-data, if tx-data
1536                  * is available, mix
1537                  */
1538                 while (r != rr && t != tt) {
1539                         sample = dsp_audio_law_to_s32[p[t]] + *c++;
1540                         if (sample < -32768)
1541                                 sample = -32768;
1542                         else if (sample > 32767)
1543                                 sample = 32767;
1544                         *d++ = dsp_audio_s16_to_law[sample & 0xffff];
1545                         /* conf(echo)+tx */
1546                         t = (t + 1) & CMX_BUFF_MASK;
1547                         r = (r + 1) & CMX_BUFF_MASK;
1548                 }
1549                 while (r != rr) {
1550                         sample = *c++;
1551                         if (sample < -32768)
1552                                 sample = -32768;
1553                         else if (sample > 32767)
1554                                 sample = 32767;
1555                         *d++ = dsp_audio_s16_to_law[sample & 0xffff];
1556                         /* conf(echo) */
1557                         r = (r + 1) & CMX_BUFF_MASK;
1558                 }
1559         }
1560         dsp->tx_R = t;
1561         goto send_packet;
1562
1563 send_packet:
1564         /*
1565          * send tx-data if enabled - don't filter,
1566          * because we want what we send, not what we filtered
1567          */
1568         if (dsp->tx_data) {
1569                 if (tx_data_only) {
1570                         hh->prim = DL_DATA_REQ;
1571                         hh->id = 0;
1572                         /* queue and trigger */
1573                         skb_queue_tail(&dsp->sendq, nskb);
1574                         schedule_work(&dsp->workq);
1575                         /* exit because only tx_data is used */
1576                         return;
1577                 } else {
1578                         txskb = mI_alloc_skb(len, GFP_ATOMIC);
1579                         if (!txskb) {
1580                                 printk(KERN_ERR
1581                                        "FATAL ERROR in mISDN_dsp.o: "
1582                                        "cannot alloc %d bytes\n", len);
1583                         } else {
1584                                 thh = mISDN_HEAD_P(txskb);
1585                                 thh->prim = DL_DATA_REQ;
1586                                 thh->id = 0;
1587                                 skb_put_data(txskb, nskb->data + preload, len);
1588                                 /* queue (trigger later) */
1589                                 skb_queue_tail(&dsp->sendq, txskb);
1590                         }
1591                 }
1592         }
1593
1594         /* send data only to card, if we don't just calculated tx_data */
1595         /* adjust volume */
1596         if (dsp->tx_volume)
1597                 dsp_change_volume(nskb, dsp->tx_volume);
1598         /* pipeline */
1599         if (dsp->pipeline.inuse)
1600                 dsp_pipeline_process_tx(&dsp->pipeline, nskb->data,
1601                                         nskb->len);
1602         /* crypt */
1603         if (dsp->bf_enable)
1604                 dsp_bf_encrypt(dsp, nskb->data, nskb->len);
1605         /* queue and trigger */
1606         skb_queue_tail(&dsp->sendq, nskb);
1607         schedule_work(&dsp->workq);
1608 }
1609
1610 static u32      jittercount; /* counter for jitter check */
1611 struct timer_list dsp_spl_tl;
1612 unsigned long   dsp_spl_jiffies; /* calculate the next time to fire */
1613 static u16      dsp_count; /* last sample count */
1614 static int      dsp_count_valid; /* if we have last sample count */
1615
1616 void
1617 dsp_cmx_send(struct timer_list *arg)
1618 {
1619         struct dsp_conf *conf;
1620         struct dsp_conf_member *member;
1621         struct dsp *dsp;
1622         int mustmix, members;
1623         static s32 mixbuffer[MAX_POLL + 100];
1624         s32 *c;
1625         u8 *p, *q;
1626         int r, rr;
1627         int jittercheck = 0, delay, i;
1628         u_long flags;
1629         u16 length, count;
1630
1631         /* lock */
1632         spin_lock_irqsave(&dsp_lock, flags);
1633
1634         if (!dsp_count_valid) {
1635                 dsp_count = mISDN_clock_get();
1636                 length = dsp_poll;
1637                 dsp_count_valid = 1;
1638         } else {
1639                 count = mISDN_clock_get();
1640                 length = count - dsp_count;
1641                 dsp_count = count;
1642         }
1643         if (length > MAX_POLL + 100)
1644                 length = MAX_POLL + 100;
1645         /* printk(KERN_DEBUG "len=%d dsp_count=0x%x\n", length, dsp_count); */
1646
1647         /*
1648          * check if jitter needs to be checked (this is every second)
1649          */
1650         jittercount += length;
1651         if (jittercount >= 8000) {
1652                 jittercount -= 8000;
1653                 jittercheck = 1;
1654         }
1655
1656         /* loop all members that do not require conference mixing */
1657         list_for_each_entry(dsp, &dsp_ilist, list) {
1658                 if (dsp->hdlc)
1659                         continue;
1660                 conf = dsp->conf;
1661                 mustmix = 0;
1662                 members = 0;
1663                 if (conf) {
1664                         members = list_count_nodes(&conf->mlist);
1665 #ifdef CMX_CONF_DEBUG
1666                         if (conf->software && members > 1)
1667 #else
1668                         if (conf->software && members > 2)
1669 #endif
1670                                 mustmix = 1;
1671                 }
1672
1673                 /* transmission required */
1674                 if (!mustmix) {
1675                         dsp_cmx_send_member(dsp, length, mixbuffer, members);
1676
1677                         /*
1678                          * unused mixbuffer is given to prevent a
1679                          * potential null-pointer-bug
1680                          */
1681                 }
1682         }
1683
1684         /* loop all members that require conference mixing */
1685         list_for_each_entry(conf, &conf_ilist, list) {
1686                 /* count members and check hardware */
1687                 members = list_count_nodes(&conf->mlist);
1688 #ifdef CMX_CONF_DEBUG
1689                 if (conf->software && members > 1) {
1690 #else
1691                 if (conf->software && members > 2) {
1692 #endif
1693                         /* check for hdlc conf */
1694                         member = list_entry(conf->mlist.next,
1695                                             struct dsp_conf_member, list);
1696                         if (member->dsp->hdlc)
1697                                 continue;
1698                         /* mix all data */
1699                         memset(mixbuffer, 0, length * sizeof(s32));
1700                         list_for_each_entry(member, &conf->mlist, list) {
1701                                 dsp = member->dsp;
1702                                 /* get range of data to mix */
1703                                 c = mixbuffer;
1704                                 q = dsp->rx_buff;
1705                                 r = dsp->rx_R;
1706                                 rr = (r + length) & CMX_BUFF_MASK;
1707                                 /* add member's data */
1708                                 while (r != rr) {
1709                                         *c++ += dsp_audio_law_to_s32[q[r]];
1710                                         r = (r + 1) & CMX_BUFF_MASK;
1711                                 }
1712                         }
1713
1714                         /* process each member */
1715                         list_for_each_entry(member, &conf->mlist, list) {
1716                                 /* transmission */
1717                                 dsp_cmx_send_member(member->dsp, length,
1718                                                     mixbuffer, members);
1719                         }
1720                 }
1721         }
1722
1723         /* delete rx-data, increment buffers, change pointers */
1724         list_for_each_entry(dsp, &dsp_ilist, list) {
1725                 if (dsp->hdlc)
1726                         continue;
1727                 p = dsp->rx_buff;
1728                 q = dsp->tx_buff;
1729                 r = dsp->rx_R;
1730                 /* move receive pointer when receiving */
1731                 if (!dsp->rx_is_off) {
1732                         rr = (r + length) & CMX_BUFF_MASK;
1733                         /* delete rx-data */
1734                         while (r != rr) {
1735                                 p[r] = dsp_silence;
1736                                 r = (r + 1) & CMX_BUFF_MASK;
1737                         }
1738                         /* increment rx-buffer pointer */
1739                         dsp->rx_R = r; /* write incremented read pointer */
1740                 }
1741
1742                 /* check current rx_delay */
1743                 delay = (dsp->rx_W-dsp->rx_R) & CMX_BUFF_MASK;
1744                 if (delay >= CMX_BUFF_HALF)
1745                         delay = 0; /* will be the delay before next write */
1746                 /* check for lower delay */
1747                 if (delay < dsp->rx_delay[0])
1748                         dsp->rx_delay[0] = delay;
1749                 /* check current tx_delay */
1750                 delay = (dsp->tx_W-dsp->tx_R) & CMX_BUFF_MASK;
1751                 if (delay >= CMX_BUFF_HALF)
1752                         delay = 0; /* will be the delay before next write */
1753                 /* check for lower delay */
1754                 if (delay < dsp->tx_delay[0])
1755                         dsp->tx_delay[0] = delay;
1756                 if (jittercheck) {
1757                         /* find the lowest of all rx_delays */
1758                         delay = dsp->rx_delay[0];
1759                         i = 1;
1760                         while (i < MAX_SECONDS_JITTER_CHECK) {
1761                                 if (delay > dsp->rx_delay[i])
1762                                         delay = dsp->rx_delay[i];
1763                                 i++;
1764                         }
1765                         /*
1766                          * remove rx_delay only if we have delay AND we
1767                          * have not preset cmx_delay AND
1768                          * the delay is greater dsp_poll
1769                          */
1770                         if (delay > dsp_poll && !dsp->cmx_delay) {
1771                                 if (dsp_debug & DEBUG_DSP_CLOCK)
1772                                         printk(KERN_DEBUG
1773                                                "%s lowest rx_delay of %d bytes for"
1774                                                " dsp %s are now removed.\n",
1775                                                __func__, delay,
1776                                                dsp->name);
1777                                 r = dsp->rx_R;
1778                                 rr = (r + delay - (dsp_poll >> 1))
1779                                         & CMX_BUFF_MASK;
1780                                 /* delete rx-data */
1781                                 while (r != rr) {
1782                                         p[r] = dsp_silence;
1783                                         r = (r + 1) & CMX_BUFF_MASK;
1784                                 }
1785                                 /* increment rx-buffer pointer */
1786                                 dsp->rx_R = r;
1787                                 /* write incremented read pointer */
1788                         }
1789                         /* find the lowest of all tx_delays */
1790                         delay = dsp->tx_delay[0];
1791                         i = 1;
1792                         while (i < MAX_SECONDS_JITTER_CHECK) {
1793                                 if (delay > dsp->tx_delay[i])
1794                                         delay = dsp->tx_delay[i];
1795                                 i++;
1796                         }
1797                         /*
1798                          * remove delay only if we have delay AND we
1799                          * have enabled tx_dejitter
1800                          */
1801                         if (delay > dsp_poll && dsp->tx_dejitter) {
1802                                 if (dsp_debug & DEBUG_DSP_CLOCK)
1803                                         printk(KERN_DEBUG
1804                                                "%s lowest tx_delay of %d bytes for"
1805                                                " dsp %s are now removed.\n",
1806                                                __func__, delay,
1807                                                dsp->name);
1808                                 r = dsp->tx_R;
1809                                 rr = (r + delay - (dsp_poll >> 1))
1810                                         & CMX_BUFF_MASK;
1811                                 /* delete tx-data */
1812                                 while (r != rr) {
1813                                         q[r] = dsp_silence;
1814                                         r = (r + 1) & CMX_BUFF_MASK;
1815                                 }
1816                                 /* increment rx-buffer pointer */
1817                                 dsp->tx_R = r;
1818                                 /* write incremented read pointer */
1819                         }
1820                         /* scroll up delays */
1821                         i = MAX_SECONDS_JITTER_CHECK - 1;
1822                         while (i) {
1823                                 dsp->rx_delay[i] = dsp->rx_delay[i - 1];
1824                                 dsp->tx_delay[i] = dsp->tx_delay[i - 1];
1825                                 i--;
1826                         }
1827                         dsp->tx_delay[0] = CMX_BUFF_HALF; /* (infinite) delay */
1828                         dsp->rx_delay[0] = CMX_BUFF_HALF; /* (infinite) delay */
1829                 }
1830         }
1831
1832         /* if next event would be in the past ... */
1833         if ((s32)(dsp_spl_jiffies + dsp_tics-jiffies) <= 0)
1834                 dsp_spl_jiffies = jiffies + 1;
1835         else
1836                 dsp_spl_jiffies += dsp_tics;
1837
1838         dsp_spl_tl.expires = dsp_spl_jiffies;
1839         add_timer(&dsp_spl_tl);
1840
1841         /* unlock */
1842         spin_unlock_irqrestore(&dsp_lock, flags);
1843 }
1844
1845 /*
1846  * audio data is transmitted from upper layer to the dsp
1847  */
1848 void
1849 dsp_cmx_transmit(struct dsp *dsp, struct sk_buff *skb)
1850 {
1851         u_int w, ww;
1852         u8 *d, *p;
1853         int space; /* todo: , l = skb->len; */
1854 #ifdef CMX_TX_DEBUG
1855         char debugbuf[256] = "";
1856 #endif
1857
1858         /* check if there is enough space, and then copy */
1859         w = dsp->tx_W;
1860         ww = dsp->tx_R;
1861         p = dsp->tx_buff;
1862         d = skb->data;
1863         space = (ww - w - 1) & CMX_BUFF_MASK;
1864         /* write-pointer should not overrun nor reach read pointer */
1865         if (space < skb->len) {
1866                 /* write to the space we have left */
1867                 ww = (ww - 1) & CMX_BUFF_MASK; /* end one byte prior tx_R */
1868                 if (dsp_debug & DEBUG_DSP_CLOCK)
1869                         printk(KERN_DEBUG "%s: TX overflow space=%d skb->len="
1870                                "%d, w=0x%04x, ww=0x%04x\n", __func__, space,
1871                                skb->len, w, ww);
1872         } else
1873                 /* write until all byte are copied */
1874                 ww = (w + skb->len) & CMX_BUFF_MASK;
1875         dsp->tx_W = ww;
1876                 /* show current buffer */
1877 #ifdef CMX_DEBUG
1878         printk(KERN_DEBUG
1879                "cmx_transmit(dsp=%lx) %d bytes to 0x%x-0x%x. %s\n",
1880                (u_long)dsp, (ww - w) & CMX_BUFF_MASK, w, ww, dsp->name);
1881 #endif
1882
1883         /* copy transmit data to tx-buffer */
1884 #ifdef CMX_TX_DEBUG
1885         sprintf(debugbuf, "TX getting (%04x-%04x)%p: ", w, ww, p);
1886 #endif
1887         while (w != ww) {
1888 #ifdef CMX_TX_DEBUG
1889                 if (strlen(debugbuf) < 48)
1890                         sprintf(debugbuf + strlen(debugbuf), " %02x", *d);
1891 #endif
1892                 p[w] = *d++;
1893                 w = (w + 1) & CMX_BUFF_MASK;
1894         }
1895 #ifdef CMX_TX_DEBUG
1896         printk(KERN_DEBUG "%s\n", debugbuf);
1897 #endif
1898
1899 }
1900
1901 /*
1902  * hdlc data is received from card and sent to all members.
1903  */
1904 void
1905 dsp_cmx_hdlc(struct dsp *dsp, struct sk_buff *skb)
1906 {
1907         struct sk_buff *nskb = NULL;
1908         struct dsp_conf_member *member;
1909         struct mISDNhead *hh;
1910
1911         /* not if not active */
1912         if (!dsp->b_active)
1913                 return;
1914
1915         /* check if we have sompen */
1916         if (skb->len < 1)
1917                 return;
1918
1919         /* no conf */
1920         if (!dsp->conf) {
1921                 /* in case of software echo */
1922                 if (dsp->echo.software) {
1923                         nskb = skb_clone(skb, GFP_ATOMIC);
1924                         if (nskb) {
1925                                 hh = mISDN_HEAD_P(nskb);
1926                                 hh->prim = PH_DATA_REQ;
1927                                 hh->id = 0;
1928                                 skb_queue_tail(&dsp->sendq, nskb);
1929                                 schedule_work(&dsp->workq);
1930                         }
1931                 }
1932                 return;
1933         }
1934         /* in case of hardware conference */
1935         if (dsp->conf->hardware)
1936                 return;
1937         list_for_each_entry(member, &dsp->conf->mlist, list) {
1938                 if (dsp->echo.software || member->dsp != dsp) {
1939                         nskb = skb_clone(skb, GFP_ATOMIC);
1940                         if (nskb) {
1941                                 hh = mISDN_HEAD_P(nskb);
1942                                 hh->prim = PH_DATA_REQ;
1943                                 hh->id = 0;
1944                                 skb_queue_tail(&member->dsp->sendq, nskb);
1945                                 schedule_work(&member->dsp->workq);
1946                         }
1947                 }
1948         }
1949 }
This page took 0.149785 seconds and 4 git commands to generate.