Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Audio crossconnecting/conferrencing (hardware level).
0003  *
0004  * Copyright 2002 by Andreas Eversberg (jolly@eversberg.eu)
0005  *
0006  * This software may be used and distributed according to the terms
0007  * of the GNU General Public License, incorporated herein by reference.
0008  *
0009  */
0010 
0011 /*
0012  * The process of adding and removing parties to/from a conference:
0013  *
0014  * There is a chain of struct dsp_conf which has one or more members in a chain
0015  * of struct dsp_conf_member.
0016  *
0017  * After a party is added, the conference is checked for hardware capability.
0018  * Also if a party is removed, the conference is checked again.
0019  *
0020  * There are 3 different solutions: -1 = software, 0 = hardware-crossconnect
0021  * 1-n = hardware-conference. The n will give the conference number.
0022  *
0023  * Depending on the change after removal or insertion of a party, hardware
0024  * commands are given.
0025  *
0026  * The current solution is stored within the struct dsp_conf entry.
0027  */
0028 
0029 /*
0030  * HOW THE CMX WORKS:
0031  *
0032  * There are 3 types of interaction: One member is alone, in this case only
0033  * data flow from upper to lower layer is done.
0034  * Two members will also exchange their data so they are crossconnected.
0035  * Three or more members will be added in a conference and will hear each
0036  * other but will not receive their own speech (echo) if not enabled.
0037  *
0038  * Features of CMX are:
0039  *  - Crossconnecting or even conference, if more than two members are together.
0040  *  - Force mixing of transmit data with other crossconnect/conference members.
0041  *  - Echo generation to benchmark the delay of audio processing.
0042  *  - Use hardware to minimize cpu load, disable FIFO load and minimize delay.
0043  *  - Dejittering and clock generation.
0044  *
0045  * There are 2 buffers:
0046  *
0047  *
0048  * RX-Buffer
0049  *                 R             W
0050  *                 |             |
0051  * ----------------+-------------+-------------------
0052  *
0053  * The rx-buffer is a ring buffer used to store the received data for each
0054  * individual member. This is only the case if data needs to be dejittered
0055  * or in case of a conference where different clocks require reclocking.
0056  * The transmit-clock (R) will read the buffer.
0057  * If the clock overruns the write-pointer, we will have a buffer underrun.
0058  * If the write pointer always has a certain distance from the transmit-
0059  * clock, we will have a delay. The delay will dynamically be increased and
0060  * reduced.
0061  *
0062  *
0063  * TX-Buffer
0064  *                  R        W
0065  *                  |        |
0066  * -----------------+--------+-----------------------
0067  *
0068  * The tx-buffer is a ring buffer to queue the transmit data from user space
0069  * until it will be mixed or sent. There are two pointers, R and W. If the write
0070  * pointer W would reach or overrun R, the buffer would overrun. In this case
0071  * (some) data is dropped so that it will not overrun.
0072  * Additionally a dynamic dejittering can be enabled. this allows data from
0073  * user space that have jitter and different clock source.
0074  *
0075  *
0076  * Clock:
0077  *
0078  * A Clock is not required, if the data source has exactly one clock. In this
0079  * case the data source is forwarded to the destination.
0080  *
0081  * A Clock is required, because the data source
0082  *  - has multiple clocks.
0083  *  - has no usable clock due to jitter or packet loss (VoIP).
0084  * In this case the system's clock is used. The clock resolution depends on
0085  * the jiffie resolution.
0086  *
0087  * If a member joins a conference:
0088  *
0089  * - If a member joins, its rx_buff is set to silence and change read pointer
0090  *   to transmit clock.
0091  *
0092  * The procedure of received data from card is explained in cmx_receive.
0093  * The procedure of received data from user space is explained in cmx_transmit.
0094  * The procedure of transmit data to card is cmx_send.
0095  *
0096  *
0097  * Interaction with other features:
0098  *
0099  * DTMF:
0100  * DTMF decoding is done before the data is crossconnected.
0101  *
0102  * Volume change:
0103  * Changing rx-volume is done before the data is crossconnected. The tx-volume
0104  * must be changed whenever data is transmitted to the card by the cmx.
0105  *
0106  * Tones:
0107  * If a tone is enabled, it will be processed whenever data is transmitted to
0108  * the card. It will replace the tx-data from the user space.
0109  * If tones are generated by hardware, this conference member is removed for
0110  * this time.
0111  *
0112  * Disable rx-data:
0113  * If cmx is realized in hardware, rx data will be disabled if requested by
0114  * the upper layer. If dtmf decoding is done by software and enabled, rx data
0115  * will not be disabled but blocked to the upper layer.
0116  *
0117  * HFC conference engine:
0118  * If it is possible to realize all features using hardware, hardware will be
0119  * used if not forbidden by control command. Disabling rx-data provides
0120  * absolutely traffic free audio processing. (except for the quick 1-frame
0121  * upload of a tone loop, only once for a new tone)
0122  *
0123  */
0124 
0125 /* delay.h is required for hw_lock.h */
0126 
0127 #include <linux/slab.h>
0128 #include <linux/delay.h>
0129 #include <linux/mISDNif.h>
0130 #include <linux/mISDNdsp.h>
0131 #include "core.h"
0132 #include "dsp.h"
0133 /*
0134  * debugging of multi party conference,
0135  * by using conference even with two members
0136  */
0137 
0138 /* #define CMX_CONF_DEBUG */
0139 
0140 /*#define CMX_DEBUG * massive read/write pointer output */
0141 /*#define CMX_DELAY_DEBUG * gives rx-buffer delay overview */
0142 /*#define CMX_TX_DEBUG * massive read/write on tx-buffer with content */
0143 
0144 static inline int
0145 count_list_member(struct list_head *head)
0146 {
0147     int         cnt = 0;
0148     struct list_head    *m;
0149 
0150     list_for_each(m, head)
0151         cnt++;
0152     return cnt;
0153 }
0154 
0155 /*
0156  * debug cmx memory structure
0157  */
0158 void
0159 dsp_cmx_debug(struct dsp *dsp)
0160 {
0161     struct dsp_conf *conf;
0162     struct dsp_conf_member  *member;
0163     struct dsp      *odsp;
0164 
0165     printk(KERN_DEBUG "-----Current DSP\n");
0166     list_for_each_entry(odsp, &dsp_ilist, list) {
0167         printk(KERN_DEBUG "* %s hardecho=%d softecho=%d txmix=%d",
0168                odsp->name, odsp->echo.hardware, odsp->echo.software,
0169                odsp->tx_mix);
0170         if (odsp->conf)
0171             printk(" (Conf %d)", odsp->conf->id);
0172         if (dsp == odsp)
0173             printk(" *this*");
0174         printk("\n");
0175     }
0176     printk(KERN_DEBUG "-----Current Conf:\n");
0177     list_for_each_entry(conf, &conf_ilist, list) {
0178         printk(KERN_DEBUG "* Conf %d (%p)\n", conf->id, conf);
0179         list_for_each_entry(member, &conf->mlist, list) {
0180             printk(KERN_DEBUG
0181                    "  - member = %s (slot_tx %d, bank_tx %d, "
0182                    "slot_rx %d, bank_rx %d hfc_conf %d "
0183                    "tx_data %d rx_is_off %d)%s\n",
0184                    member->dsp->name, member->dsp->pcm_slot_tx,
0185                    member->dsp->pcm_bank_tx, member->dsp->pcm_slot_rx,
0186                    member->dsp->pcm_bank_rx, member->dsp->hfc_conf,
0187                    member->dsp->tx_data, member->dsp->rx_is_off,
0188                    (member->dsp == dsp) ? " *this*" : "");
0189         }
0190     }
0191     printk(KERN_DEBUG "-----end\n");
0192 }
0193 
0194 /*
0195  * search conference
0196  */
0197 static struct dsp_conf *
0198 dsp_cmx_search_conf(u32 id)
0199 {
0200     struct dsp_conf *conf;
0201 
0202     if (!id) {
0203         printk(KERN_WARNING "%s: conference ID is 0.\n", __func__);
0204         return NULL;
0205     }
0206 
0207     /* search conference */
0208     list_for_each_entry(conf, &conf_ilist, list)
0209         if (conf->id == id)
0210             return conf;
0211 
0212     return NULL;
0213 }
0214 
0215 
0216 /*
0217  * add member to conference
0218  */
0219 static int
0220 dsp_cmx_add_conf_member(struct dsp *dsp, struct dsp_conf *conf)
0221 {
0222     struct dsp_conf_member *member;
0223 
0224     if (!conf || !dsp) {
0225         printk(KERN_WARNING "%s: conf or dsp is 0.\n", __func__);
0226         return -EINVAL;
0227     }
0228     if (dsp->member) {
0229         printk(KERN_WARNING "%s: dsp is already member in a conf.\n",
0230                __func__);
0231         return -EINVAL;
0232     }
0233 
0234     if (dsp->conf) {
0235         printk(KERN_WARNING "%s: dsp is already in a conf.\n",
0236                __func__);
0237         return -EINVAL;
0238     }
0239 
0240     member = kzalloc(sizeof(struct dsp_conf_member), GFP_ATOMIC);
0241     if (!member) {
0242         printk(KERN_ERR "kzalloc struct dsp_conf_member failed\n");
0243         return -ENOMEM;
0244     }
0245     member->dsp = dsp;
0246     /* clear rx buffer */
0247     memset(dsp->rx_buff, dsp_silence, sizeof(dsp->rx_buff));
0248     dsp->rx_init = 1; /* rx_W and rx_R will be adjusted on first frame */
0249     dsp->rx_W = 0;
0250     dsp->rx_R = 0;
0251 
0252     list_add_tail(&member->list, &conf->mlist);
0253 
0254     dsp->conf = conf;
0255     dsp->member = member;
0256 
0257     return 0;
0258 }
0259 
0260 
0261 /*
0262  * del member from conference
0263  */
0264 int
0265 dsp_cmx_del_conf_member(struct dsp *dsp)
0266 {
0267     struct dsp_conf_member *member;
0268 
0269     if (!dsp) {
0270         printk(KERN_WARNING "%s: dsp is 0.\n",
0271                __func__);
0272         return -EINVAL;
0273     }
0274 
0275     if (!dsp->conf) {
0276         printk(KERN_WARNING "%s: dsp is not in a conf.\n",
0277                __func__);
0278         return -EINVAL;
0279     }
0280 
0281     if (list_empty(&dsp->conf->mlist)) {
0282         printk(KERN_WARNING "%s: dsp has linked an empty conf.\n",
0283                __func__);
0284         return -EINVAL;
0285     }
0286 
0287     /* find us in conf */
0288     list_for_each_entry(member, &dsp->conf->mlist, list) {
0289         if (member->dsp == dsp) {
0290             list_del(&member->list);
0291             dsp->conf = NULL;
0292             dsp->member = NULL;
0293             kfree(member);
0294             return 0;
0295         }
0296     }
0297     printk(KERN_WARNING
0298            "%s: dsp is not present in its own conf_member list.\n",
0299            __func__);
0300 
0301     return -EINVAL;
0302 }
0303 
0304 
0305 /*
0306  * new conference
0307  */
0308 static struct dsp_conf
0309 *dsp_cmx_new_conf(u32 id)
0310 {
0311     struct dsp_conf *conf;
0312 
0313     if (!id) {
0314         printk(KERN_WARNING "%s: id is 0.\n",
0315                __func__);
0316         return NULL;
0317     }
0318 
0319     conf = kzalloc(sizeof(struct dsp_conf), GFP_ATOMIC);
0320     if (!conf) {
0321         printk(KERN_ERR "kzalloc struct dsp_conf failed\n");
0322         return NULL;
0323     }
0324     INIT_LIST_HEAD(&conf->mlist);
0325     conf->id = id;
0326 
0327     list_add_tail(&conf->list, &conf_ilist);
0328 
0329     return conf;
0330 }
0331 
0332 
0333 /*
0334  * del conference
0335  */
0336 int
0337 dsp_cmx_del_conf(struct dsp_conf *conf)
0338 {
0339     if (!conf) {
0340         printk(KERN_WARNING "%s: conf is null.\n",
0341                __func__);
0342         return -EINVAL;
0343     }
0344 
0345     if (!list_empty(&conf->mlist)) {
0346         printk(KERN_WARNING "%s: conf not empty.\n",
0347                __func__);
0348         return -EINVAL;
0349     }
0350     list_del(&conf->list);
0351     kfree(conf);
0352 
0353     return 0;
0354 }
0355 
0356 
0357 /*
0358  * send HW message to hfc card
0359  */
0360 static void
0361 dsp_cmx_hw_message(struct dsp *dsp, u32 message, u32 param1, u32 param2,
0362            u32 param3, u32 param4)
0363 {
0364     struct mISDN_ctrl_req cq;
0365 
0366     memset(&cq, 0, sizeof(cq));
0367     cq.op = message;
0368     cq.p1 = param1 | (param2 << 8);
0369     cq.p2 = param3 | (param4 << 8);
0370     if (dsp->ch.peer)
0371         dsp->ch.peer->ctrl(dsp->ch.peer, CONTROL_CHANNEL, &cq);
0372 }
0373 
0374 
0375 /*
0376  * do hardware update and set the software/hardware flag
0377  *
0378  * either a conference or a dsp instance can be given
0379  * if only dsp instance is given, the instance is not associated with a conf
0380  * and therefore removed. if a conference is given, the dsp is expected to
0381  * be member of that conference.
0382  */
0383 void
0384 dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp)
0385 {
0386     struct dsp_conf_member  *member, *nextm;
0387     struct dsp      *finddsp;
0388     int     memb = 0, i, ii, i1, i2;
0389     int     freeunits[8];
0390     u_char      freeslots[256];
0391     int     same_hfc = -1, same_pcm = -1, current_conf = -1,
0392         all_conf = 1, tx_data = 0;
0393 
0394     /* dsp gets updated (no conf) */
0395     if (!conf) {
0396         if (!dsp)
0397             return;
0398         if (dsp_debug & DEBUG_DSP_CMX)
0399             printk(KERN_DEBUG "%s checking dsp %s\n",
0400                    __func__, dsp->name);
0401     one_member:
0402         /* remove HFC conference if enabled */
0403         if (dsp->hfc_conf >= 0) {
0404             if (dsp_debug & DEBUG_DSP_CMX)
0405                 printk(KERN_DEBUG
0406                        "%s removing %s from HFC conf %d "
0407                        "because dsp is split\n", __func__,
0408                        dsp->name, dsp->hfc_conf);
0409             dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_CONF_SPLIT,
0410                        0, 0, 0, 0);
0411             dsp->hfc_conf = -1;
0412         }
0413         /* process hw echo */
0414         if (dsp->features.pcm_banks < 1)
0415             return;
0416         if (!dsp->echo.software && !dsp->echo.hardware) {
0417             /* NO ECHO: remove PCM slot if assigned */
0418             if (dsp->pcm_slot_tx >= 0 || dsp->pcm_slot_rx >= 0) {
0419                 if (dsp_debug & DEBUG_DSP_CMX)
0420                     printk(KERN_DEBUG "%s removing %s from"
0421                            " PCM slot %d (TX) %d (RX) because"
0422                            " dsp is split (no echo)\n",
0423                            __func__, dsp->name,
0424                            dsp->pcm_slot_tx, dsp->pcm_slot_rx);
0425                 dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_PCM_DISC,
0426                            0, 0, 0, 0);
0427                 dsp->pcm_slot_tx = -1;
0428                 dsp->pcm_bank_tx = -1;
0429                 dsp->pcm_slot_rx = -1;
0430                 dsp->pcm_bank_rx = -1;
0431             }
0432             return;
0433         }
0434         /* echo is enabled, find out if we use soft or hardware */
0435         dsp->echo.software = dsp->tx_data;
0436         dsp->echo.hardware = 0;
0437         /* ECHO: already echo */
0438         if (dsp->pcm_slot_tx >= 0 && dsp->pcm_slot_rx < 0 &&
0439             dsp->pcm_bank_tx == 2 && dsp->pcm_bank_rx == 2) {
0440             dsp->echo.hardware = 1;
0441             return;
0442         }
0443         /* ECHO: if slot already assigned */
0444         if (dsp->pcm_slot_tx >= 0) {
0445             dsp->pcm_slot_rx = dsp->pcm_slot_tx;
0446             dsp->pcm_bank_tx = 2; /* 2 means loop */
0447             dsp->pcm_bank_rx = 2;
0448             if (dsp_debug & DEBUG_DSP_CMX)
0449                 printk(KERN_DEBUG
0450                        "%s refresh %s for echo using slot %d\n",
0451                        __func__, dsp->name,
0452                        dsp->pcm_slot_tx);
0453             dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_PCM_CONN,
0454                        dsp->pcm_slot_tx, 2, dsp->pcm_slot_rx, 2);
0455             dsp->echo.hardware = 1;
0456             return;
0457         }
0458         /* ECHO: find slot */
0459         dsp->pcm_slot_tx = -1;
0460         dsp->pcm_slot_rx = -1;
0461         memset(freeslots, 1, sizeof(freeslots));
0462         list_for_each_entry(finddsp, &dsp_ilist, list) {
0463             if (finddsp->features.pcm_id == dsp->features.pcm_id) {
0464                 if (finddsp->pcm_slot_rx >= 0 &&
0465                     finddsp->pcm_slot_rx < sizeof(freeslots))
0466                     freeslots[finddsp->pcm_slot_rx] = 0;
0467                 if (finddsp->pcm_slot_tx >= 0 &&
0468                     finddsp->pcm_slot_tx < sizeof(freeslots))
0469                     freeslots[finddsp->pcm_slot_tx] = 0;
0470             }
0471         }
0472         i = 0;
0473         ii = dsp->features.pcm_slots;
0474         while (i < ii) {
0475             if (freeslots[i])
0476                 break;
0477             i++;
0478         }
0479         if (i == ii) {
0480             if (dsp_debug & DEBUG_DSP_CMX)
0481                 printk(KERN_DEBUG
0482                        "%s no slot available for echo\n",
0483                        __func__);
0484             /* no more slots available */
0485             dsp->echo.software = 1;
0486             return;
0487         }
0488         /* assign free slot */
0489         dsp->pcm_slot_tx = i;
0490         dsp->pcm_slot_rx = i;
0491         dsp->pcm_bank_tx = 2; /* loop */
0492         dsp->pcm_bank_rx = 2;
0493         if (dsp_debug & DEBUG_DSP_CMX)
0494             printk(KERN_DEBUG
0495                    "%s assign echo for %s using slot %d\n",
0496                    __func__, dsp->name, dsp->pcm_slot_tx);
0497         dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_PCM_CONN,
0498                    dsp->pcm_slot_tx, 2, dsp->pcm_slot_rx, 2);
0499         dsp->echo.hardware = 1;
0500         return;
0501     }
0502 
0503     /* conf gets updated (all members) */
0504     if (dsp_debug & DEBUG_DSP_CMX)
0505         printk(KERN_DEBUG "%s checking conference %d\n",
0506                __func__, conf->id);
0507 
0508     if (list_empty(&conf->mlist)) {
0509         printk(KERN_ERR "%s: conference without members\n",
0510                __func__);
0511         return;
0512     }
0513     member = list_entry(conf->mlist.next, struct dsp_conf_member, list);
0514     same_hfc = member->dsp->features.hfc_id;
0515     same_pcm = member->dsp->features.pcm_id;
0516     /* check all members in our conference */
0517     list_for_each_entry(member, &conf->mlist, list) {
0518         /* check if member uses mixing */
0519         if (member->dsp->tx_mix) {
0520             if (dsp_debug & DEBUG_DSP_CMX)
0521                 printk(KERN_DEBUG
0522                        "%s dsp %s cannot form a conf, because "
0523                        "tx_mix is turned on\n", __func__,
0524                        member->dsp->name);
0525         conf_software:
0526             list_for_each_entry(member, &conf->mlist, list) {
0527                 dsp = member->dsp;
0528                 /* remove HFC conference if enabled */
0529                 if (dsp->hfc_conf >= 0) {
0530                     if (dsp_debug & DEBUG_DSP_CMX)
0531                         printk(KERN_DEBUG
0532                                "%s removing %s from HFC "
0533                                "conf %d because not "
0534                                "possible with hardware\n",
0535                                __func__,
0536                                dsp->name,
0537                                dsp->hfc_conf);
0538                     dsp_cmx_hw_message(dsp,
0539                                MISDN_CTRL_HFC_CONF_SPLIT,
0540                                0, 0, 0, 0);
0541                     dsp->hfc_conf = -1;
0542                 }
0543                 /* remove PCM slot if assigned */
0544                 if (dsp->pcm_slot_tx >= 0 ||
0545                     dsp->pcm_slot_rx >= 0) {
0546                     if (dsp_debug & DEBUG_DSP_CMX)
0547                         printk(KERN_DEBUG "%s removing "
0548                                "%s from PCM slot %d (TX)"
0549                                " slot %d (RX) because not"
0550                                " possible with hardware\n",
0551                                __func__,
0552                                dsp->name,
0553                                dsp->pcm_slot_tx,
0554                                dsp->pcm_slot_rx);
0555                     dsp_cmx_hw_message(dsp,
0556                                MISDN_CTRL_HFC_PCM_DISC,
0557                                0, 0, 0, 0);
0558                     dsp->pcm_slot_tx = -1;
0559                     dsp->pcm_bank_tx = -1;
0560                     dsp->pcm_slot_rx = -1;
0561                     dsp->pcm_bank_rx = -1;
0562                 }
0563             }
0564             conf->hardware = 0;
0565             conf->software = 1;
0566             return;
0567         }
0568         /* check if member has echo turned on */
0569         if (member->dsp->echo.hardware || member->dsp->echo.software) {
0570             if (dsp_debug & DEBUG_DSP_CMX)
0571                 printk(KERN_DEBUG
0572                        "%s dsp %s cannot form a conf, because "
0573                        "echo is turned on\n", __func__,
0574                        member->dsp->name);
0575             goto conf_software;
0576         }
0577         /* check if member has tx_mix turned on */
0578         if (member->dsp->tx_mix) {
0579             if (dsp_debug & DEBUG_DSP_CMX)
0580                 printk(KERN_DEBUG
0581                        "%s dsp %s cannot form a conf, because "
0582                        "tx_mix is turned on\n",
0583                        __func__, member->dsp->name);
0584             goto conf_software;
0585         }
0586         /* check if member changes volume at an not suppoted level */
0587         if (member->dsp->tx_volume) {
0588             if (dsp_debug & DEBUG_DSP_CMX)
0589                 printk(KERN_DEBUG
0590                        "%s dsp %s cannot form a conf, because "
0591                        "tx_volume is changed\n",
0592                        __func__, member->dsp->name);
0593             goto conf_software;
0594         }
0595         if (member->dsp->rx_volume) {
0596             if (dsp_debug & DEBUG_DSP_CMX)
0597                 printk(KERN_DEBUG
0598                        "%s dsp %s cannot form a conf, because "
0599                        "rx_volume is changed\n",
0600                        __func__, member->dsp->name);
0601             goto conf_software;
0602         }
0603         /* check if tx-data turned on */
0604         if (member->dsp->tx_data) {
0605             if (dsp_debug & DEBUG_DSP_CMX)
0606                 printk(KERN_DEBUG
0607                        "%s dsp %s tx_data is turned on\n",
0608                        __func__, member->dsp->name);
0609             tx_data = 1;
0610         }
0611         /* check if pipeline exists */
0612         if (member->dsp->pipeline.inuse) {
0613             if (dsp_debug & DEBUG_DSP_CMX)
0614                 printk(KERN_DEBUG
0615                        "%s dsp %s cannot form a conf, because "
0616                        "pipeline exists\n", __func__,
0617                        member->dsp->name);
0618             goto conf_software;
0619         }
0620         /* check if encryption is enabled */
0621         if (member->dsp->bf_enable) {
0622             if (dsp_debug & DEBUG_DSP_CMX)
0623                 printk(KERN_DEBUG "%s dsp %s cannot form a "
0624                        "conf, because encryption is enabled\n",
0625                        __func__, member->dsp->name);
0626             goto conf_software;
0627         }
0628         /* check if member is on a card with PCM support */
0629         if (member->dsp->features.pcm_id < 0) {
0630             if (dsp_debug & DEBUG_DSP_CMX)
0631                 printk(KERN_DEBUG
0632                        "%s dsp %s cannot form a conf, because "
0633                        "dsp has no PCM bus\n",
0634                        __func__, member->dsp->name);
0635             goto conf_software;
0636         }
0637         /* check if relations are on the same PCM bus */
0638         if (member->dsp->features.pcm_id != same_pcm) {
0639             if (dsp_debug & DEBUG_DSP_CMX)
0640                 printk(KERN_DEBUG
0641                        "%s dsp %s cannot form a conf, because "
0642                        "dsp is on a different PCM bus than the "
0643                        "first dsp\n",
0644                        __func__, member->dsp->name);
0645             goto conf_software;
0646         }
0647         /* determine if members are on the same hfc chip */
0648         if (same_hfc != member->dsp->features.hfc_id)
0649             same_hfc = -1;
0650         /* if there are members already in a conference */
0651         if (current_conf < 0 && member->dsp->hfc_conf >= 0)
0652             current_conf = member->dsp->hfc_conf;
0653         /* if any member is not in a conference */
0654         if (member->dsp->hfc_conf < 0)
0655             all_conf = 0;
0656 
0657         memb++;
0658     }
0659 
0660     /* if no member, this is an error */
0661     if (memb < 1)
0662         return;
0663 
0664     /* one member */
0665     if (memb == 1) {
0666         if (dsp_debug & DEBUG_DSP_CMX)
0667             printk(KERN_DEBUG
0668                    "%s conf %d cannot form a HW conference, "
0669                    "because dsp is alone\n", __func__, conf->id);
0670         conf->hardware = 0;
0671         conf->software = 0;
0672         member = list_entry(conf->mlist.next, struct dsp_conf_member,
0673                     list);
0674         dsp = member->dsp;
0675         goto one_member;
0676     }
0677 
0678     /*
0679      * ok, now we are sure that all members are on the same pcm.
0680      * now we will see if we have only two members, so we can do
0681      * crossconnections, which don't have any limitations.
0682      */
0683 
0684     /* if we have only two members */
0685     if (memb == 2) {
0686         member = list_entry(conf->mlist.next, struct dsp_conf_member,
0687                     list);
0688         nextm = list_entry(member->list.next, struct dsp_conf_member,
0689                    list);
0690         /* remove HFC conference if enabled */
0691         if (member->dsp->hfc_conf >= 0) {
0692             if (dsp_debug & DEBUG_DSP_CMX)
0693                 printk(KERN_DEBUG
0694                        "%s removing %s from HFC conf %d because "
0695                        "two parties require only a PCM slot\n",
0696                        __func__, member->dsp->name,
0697                        member->dsp->hfc_conf);
0698             dsp_cmx_hw_message(member->dsp,
0699                        MISDN_CTRL_HFC_CONF_SPLIT, 0, 0, 0, 0);
0700             member->dsp->hfc_conf = -1;
0701         }
0702         if (nextm->dsp->hfc_conf >= 0) {
0703             if (dsp_debug & DEBUG_DSP_CMX)
0704                 printk(KERN_DEBUG
0705                        "%s removing %s from HFC conf %d because "
0706                        "two parties require only a PCM slot\n",
0707                        __func__, nextm->dsp->name,
0708                        nextm->dsp->hfc_conf);
0709             dsp_cmx_hw_message(nextm->dsp,
0710                        MISDN_CTRL_HFC_CONF_SPLIT, 0, 0, 0, 0);
0711             nextm->dsp->hfc_conf = -1;
0712         }
0713         /* if members have two banks (and not on the same chip) */
0714         if (member->dsp->features.pcm_banks > 1 &&
0715             nextm->dsp->features.pcm_banks > 1 &&
0716             member->dsp->features.hfc_id !=
0717             nextm->dsp->features.hfc_id) {
0718             /* if both members have same slots with crossed banks */
0719             if (member->dsp->pcm_slot_tx >= 0 &&
0720                 member->dsp->pcm_slot_rx >= 0 &&
0721                 nextm->dsp->pcm_slot_tx >= 0 &&
0722                 nextm->dsp->pcm_slot_rx >= 0 &&
0723                 nextm->dsp->pcm_slot_tx ==
0724                 member->dsp->pcm_slot_rx &&
0725                 nextm->dsp->pcm_slot_rx ==
0726                 member->dsp->pcm_slot_tx &&
0727                 nextm->dsp->pcm_slot_tx ==
0728                 member->dsp->pcm_slot_tx &&
0729                 member->dsp->pcm_bank_tx !=
0730                 member->dsp->pcm_bank_rx &&
0731                 nextm->dsp->pcm_bank_tx !=
0732                 nextm->dsp->pcm_bank_rx) {
0733                 /* all members have same slot */
0734                 if (dsp_debug & DEBUG_DSP_CMX)
0735                     printk(KERN_DEBUG
0736                            "%s dsp %s & %s stay joined on "
0737                            "PCM slot %d bank %d (TX) bank %d "
0738                            "(RX) (on different chips)\n",
0739                            __func__,
0740                            member->dsp->name,
0741                            nextm->dsp->name,
0742                            member->dsp->pcm_slot_tx,
0743                            member->dsp->pcm_bank_tx,
0744                            member->dsp->pcm_bank_rx);
0745                 conf->hardware = 1;
0746                 conf->software = tx_data;
0747                 return;
0748             }
0749             /* find a new slot */
0750             memset(freeslots, 1, sizeof(freeslots));
0751             list_for_each_entry(dsp, &dsp_ilist, list) {
0752                 if (dsp != member->dsp &&
0753                     dsp != nextm->dsp &&
0754                     member->dsp->features.pcm_id ==
0755                     dsp->features.pcm_id) {
0756                     if (dsp->pcm_slot_rx >= 0 &&
0757                         dsp->pcm_slot_rx <
0758                         sizeof(freeslots))
0759                         freeslots[dsp->pcm_slot_rx] = 0;
0760                     if (dsp->pcm_slot_tx >= 0 &&
0761                         dsp->pcm_slot_tx <
0762                         sizeof(freeslots))
0763                         freeslots[dsp->pcm_slot_tx] = 0;
0764                 }
0765             }
0766             i = 0;
0767             ii = member->dsp->features.pcm_slots;
0768             while (i < ii) {
0769                 if (freeslots[i])
0770                     break;
0771                 i++;
0772             }
0773             if (i == ii) {
0774                 if (dsp_debug & DEBUG_DSP_CMX)
0775                     printk(KERN_DEBUG
0776                            "%s no slot available for "
0777                            "%s & %s\n", __func__,
0778                            member->dsp->name,
0779                            nextm->dsp->name);
0780                 /* no more slots available */
0781                 goto conf_software;
0782             }
0783             /* assign free slot */
0784             member->dsp->pcm_slot_tx = i;
0785             member->dsp->pcm_slot_rx = i;
0786             nextm->dsp->pcm_slot_tx = i;
0787             nextm->dsp->pcm_slot_rx = i;
0788             member->dsp->pcm_bank_rx = 0;
0789             member->dsp->pcm_bank_tx = 1;
0790             nextm->dsp->pcm_bank_rx = 1;
0791             nextm->dsp->pcm_bank_tx = 0;
0792             if (dsp_debug & DEBUG_DSP_CMX)
0793                 printk(KERN_DEBUG
0794                        "%s adding %s & %s to new PCM slot %d "
0795                        "(TX and RX on different chips) because "
0796                        "both members have not same slots\n",
0797                        __func__,
0798                        member->dsp->name,
0799                        nextm->dsp->name,
0800                        member->dsp->pcm_slot_tx);
0801             dsp_cmx_hw_message(member->dsp, MISDN_CTRL_HFC_PCM_CONN,
0802                        member->dsp->pcm_slot_tx, member->dsp->pcm_bank_tx,
0803                        member->dsp->pcm_slot_rx, member->dsp->pcm_bank_rx);
0804             dsp_cmx_hw_message(nextm->dsp, MISDN_CTRL_HFC_PCM_CONN,
0805                        nextm->dsp->pcm_slot_tx, nextm->dsp->pcm_bank_tx,
0806                        nextm->dsp->pcm_slot_rx, nextm->dsp->pcm_bank_rx);
0807             conf->hardware = 1;
0808             conf->software = tx_data;
0809             return;
0810             /* if members have one bank (or on the same chip) */
0811         } else {
0812             /* if both members have different crossed slots */
0813             if (member->dsp->pcm_slot_tx >= 0 &&
0814                 member->dsp->pcm_slot_rx >= 0 &&
0815                 nextm->dsp->pcm_slot_tx >= 0 &&
0816                 nextm->dsp->pcm_slot_rx >= 0 &&
0817                 nextm->dsp->pcm_slot_tx ==
0818                 member->dsp->pcm_slot_rx &&
0819                 nextm->dsp->pcm_slot_rx ==
0820                 member->dsp->pcm_slot_tx &&
0821                 member->dsp->pcm_slot_tx !=
0822                 member->dsp->pcm_slot_rx &&
0823                 member->dsp->pcm_bank_tx == 0 &&
0824                 member->dsp->pcm_bank_rx == 0 &&
0825                 nextm->dsp->pcm_bank_tx == 0 &&
0826                 nextm->dsp->pcm_bank_rx == 0) {
0827                 /* all members have same slot */
0828                 if (dsp_debug & DEBUG_DSP_CMX)
0829                     printk(KERN_DEBUG
0830                            "%s dsp %s & %s stay joined on PCM "
0831                            "slot %d (TX) %d (RX) on same chip "
0832                            "or one bank PCM)\n", __func__,
0833                            member->dsp->name,
0834                            nextm->dsp->name,
0835                            member->dsp->pcm_slot_tx,
0836                            member->dsp->pcm_slot_rx);
0837                 conf->hardware = 1;
0838                 conf->software = tx_data;
0839                 return;
0840             }
0841             /* find two new slot */
0842             memset(freeslots, 1, sizeof(freeslots));
0843             list_for_each_entry(dsp, &dsp_ilist, list) {
0844                 if (dsp != member->dsp &&
0845                     dsp != nextm->dsp &&
0846                     member->dsp->features.pcm_id ==
0847                     dsp->features.pcm_id) {
0848                     if (dsp->pcm_slot_rx >= 0 &&
0849                         dsp->pcm_slot_rx <
0850                         sizeof(freeslots))
0851                         freeslots[dsp->pcm_slot_rx] = 0;
0852                     if (dsp->pcm_slot_tx >= 0 &&
0853                         dsp->pcm_slot_tx <
0854                         sizeof(freeslots))
0855                         freeslots[dsp->pcm_slot_tx] = 0;
0856                 }
0857             }
0858             i1 = 0;
0859             ii = member->dsp->features.pcm_slots;
0860             while (i1 < ii) {
0861                 if (freeslots[i1])
0862                     break;
0863                 i1++;
0864             }
0865             if (i1 == ii) {
0866                 if (dsp_debug & DEBUG_DSP_CMX)
0867                     printk(KERN_DEBUG
0868                            "%s no slot available "
0869                            "for %s & %s\n", __func__,
0870                            member->dsp->name,
0871                            nextm->dsp->name);
0872                 /* no more slots available */
0873                 goto conf_software;
0874             }
0875             i2 = i1 + 1;
0876             while (i2 < ii) {
0877                 if (freeslots[i2])
0878                     break;
0879                 i2++;
0880             }
0881             if (i2 == ii) {
0882                 if (dsp_debug & DEBUG_DSP_CMX)
0883                     printk(KERN_DEBUG
0884                            "%s no slot available "
0885                            "for %s & %s\n",
0886                            __func__,
0887                            member->dsp->name,
0888                            nextm->dsp->name);
0889                 /* no more slots available */
0890                 goto conf_software;
0891             }
0892             /* assign free slots */
0893             member->dsp->pcm_slot_tx = i1;
0894             member->dsp->pcm_slot_rx = i2;
0895             nextm->dsp->pcm_slot_tx = i2;
0896             nextm->dsp->pcm_slot_rx = i1;
0897             member->dsp->pcm_bank_rx = 0;
0898             member->dsp->pcm_bank_tx = 0;
0899             nextm->dsp->pcm_bank_rx = 0;
0900             nextm->dsp->pcm_bank_tx = 0;
0901             if (dsp_debug & DEBUG_DSP_CMX)
0902                 printk(KERN_DEBUG
0903                        "%s adding %s & %s to new PCM slot %d "
0904                        "(TX) %d (RX) on same chip or one bank "
0905                        "PCM, because both members have not "
0906                        "crossed slots\n", __func__,
0907                        member->dsp->name,
0908                        nextm->dsp->name,
0909                        member->dsp->pcm_slot_tx,
0910                        member->dsp->pcm_slot_rx);
0911             dsp_cmx_hw_message(member->dsp, MISDN_CTRL_HFC_PCM_CONN,
0912                        member->dsp->pcm_slot_tx, member->dsp->pcm_bank_tx,
0913                        member->dsp->pcm_slot_rx, member->dsp->pcm_bank_rx);
0914             dsp_cmx_hw_message(nextm->dsp, MISDN_CTRL_HFC_PCM_CONN,
0915                        nextm->dsp->pcm_slot_tx, nextm->dsp->pcm_bank_tx,
0916                        nextm->dsp->pcm_slot_rx, nextm->dsp->pcm_bank_rx);
0917             conf->hardware = 1;
0918             conf->software = tx_data;
0919             return;
0920         }
0921     }
0922 
0923     /*
0924      * if we have more than two, we may check if we have a conference
0925      * unit available on the chip. also all members must be on the same
0926      */
0927 
0928     /* if not the same HFC chip */
0929     if (same_hfc < 0) {
0930         if (dsp_debug & DEBUG_DSP_CMX)
0931             printk(KERN_DEBUG
0932                    "%s conference %d cannot be formed, because "
0933                    "members are on different chips or not "
0934                    "on HFC chip\n",
0935                    __func__, conf->id);
0936         goto conf_software;
0937     }
0938 
0939     /* for more than two members.. */
0940 
0941     /* if all members already have the same conference */
0942     if (all_conf) {
0943         conf->hardware = 1;
0944         conf->software = tx_data;
0945         return;
0946     }
0947 
0948     /*
0949      * if there is an existing conference, but not all members have joined
0950      */
0951     if (current_conf >= 0) {
0952     join_members:
0953         list_for_each_entry(member, &conf->mlist, list) {
0954             /* if no conference engine on our chip, change to
0955              * software */
0956             if (!member->dsp->features.hfc_conf)
0957                 goto conf_software;
0958             /* in case of hdlc, change to software */
0959             if (member->dsp->hdlc)
0960                 goto conf_software;
0961             /* join to current conference */
0962             if (member->dsp->hfc_conf == current_conf)
0963                 continue;
0964             /* get a free timeslot first */
0965             memset(freeslots, 1, sizeof(freeslots));
0966             list_for_each_entry(dsp, &dsp_ilist, list) {
0967                 /*
0968                  * not checking current member, because
0969                  * slot will be overwritten.
0970                  */
0971                 if (
0972                     dsp != member->dsp &&
0973                     /* dsp must be on the same PCM */
0974                     member->dsp->features.pcm_id ==
0975                     dsp->features.pcm_id) {
0976                     /* dsp must be on a slot */
0977                     if (dsp->pcm_slot_tx >= 0 &&
0978                         dsp->pcm_slot_tx <
0979                         sizeof(freeslots))
0980                         freeslots[dsp->pcm_slot_tx] = 0;
0981                     if (dsp->pcm_slot_rx >= 0 &&
0982                         dsp->pcm_slot_rx <
0983                         sizeof(freeslots))
0984                         freeslots[dsp->pcm_slot_rx] = 0;
0985                 }
0986             }
0987             i = 0;
0988             ii = member->dsp->features.pcm_slots;
0989             while (i < ii) {
0990                 if (freeslots[i])
0991                     break;
0992                 i++;
0993             }
0994             if (i == ii) {
0995                 /* no more slots available */
0996                 if (dsp_debug & DEBUG_DSP_CMX)
0997                     printk(KERN_DEBUG
0998                            "%s conference %d cannot be formed,"
0999                            " because no slot free\n",
1000                            __func__, conf->id);
1001                 goto conf_software;
1002             }
1003             if (dsp_debug & DEBUG_DSP_CMX)
1004                 printk(KERN_DEBUG
1005                        "%s changing dsp %s to HW conference "
1006                        "%d slot %d\n", __func__,
1007                        member->dsp->name, current_conf, i);
1008             /* assign free slot & set PCM & join conf */
1009             member->dsp->pcm_slot_tx = i;
1010             member->dsp->pcm_slot_rx = i;
1011             member->dsp->pcm_bank_tx = 2; /* loop */
1012             member->dsp->pcm_bank_rx = 2;
1013             member->dsp->hfc_conf = current_conf;
1014             dsp_cmx_hw_message(member->dsp, MISDN_CTRL_HFC_PCM_CONN,
1015                        i, 2, i, 2);
1016             dsp_cmx_hw_message(member->dsp,
1017                        MISDN_CTRL_HFC_CONF_JOIN, current_conf, 0, 0, 0);
1018         }
1019         conf->hardware = 1;
1020         conf->software = tx_data;
1021         return;
1022     }
1023 
1024     /*
1025      * no member is in a conference yet, so we find a free one
1026      */
1027     memset(freeunits, 1, sizeof(freeunits));
1028     list_for_each_entry(dsp, &dsp_ilist, list) {
1029         /* dsp must be on the same chip */
1030         if (dsp->features.hfc_id == same_hfc &&
1031             /* dsp must have joined a HW conference */
1032             dsp->hfc_conf >= 0 &&
1033             /* slot must be within range */
1034             dsp->hfc_conf < 8)
1035             freeunits[dsp->hfc_conf] = 0;
1036     }
1037     i = 0;
1038     ii = 8;
1039     while (i < ii) {
1040         if (freeunits[i])
1041             break;
1042         i++;
1043     }
1044     if (i == ii) {
1045         /* no more conferences available */
1046         if (dsp_debug & DEBUG_DSP_CMX)
1047             printk(KERN_DEBUG
1048                    "%s conference %d cannot be formed, because "
1049                    "no conference number free\n",
1050                    __func__, conf->id);
1051         goto conf_software;
1052     }
1053     /* join all members */
1054     current_conf = i;
1055     goto join_members;
1056 }
1057 
1058 
1059 /*
1060  * conf_id != 0: join or change conference
1061  * conf_id == 0: split from conference if not already
1062  */
1063 int
1064 dsp_cmx_conf(struct dsp *dsp, u32 conf_id)
1065 {
1066     int err;
1067     struct dsp_conf *conf;
1068     struct dsp_conf_member  *member;
1069 
1070     /* if conference doesn't change */
1071     if (dsp->conf_id == conf_id)
1072         return 0;
1073 
1074     /* first remove us from current conf */
1075     if (dsp->conf_id) {
1076         if (dsp_debug & DEBUG_DSP_CMX)
1077             printk(KERN_DEBUG "removing us from conference %d\n",
1078                    dsp->conf->id);
1079         /* remove us from conf */
1080         conf = dsp->conf;
1081         err = dsp_cmx_del_conf_member(dsp);
1082         if (err)
1083             return err;
1084         dsp->conf_id = 0;
1085 
1086         /* update hardware */
1087         dsp_cmx_hardware(NULL, dsp);
1088 
1089         /* conf now empty? */
1090         if (list_empty(&conf->mlist)) {
1091             if (dsp_debug & DEBUG_DSP_CMX)
1092                 printk(KERN_DEBUG
1093                        "conference is empty, so we remove it.\n");
1094             err = dsp_cmx_del_conf(conf);
1095             if (err)
1096                 return err;
1097         } else {
1098             /* update members left on conf */
1099             dsp_cmx_hardware(conf, NULL);
1100         }
1101     }
1102 
1103     /* if split */
1104     if (!conf_id)
1105         return 0;
1106 
1107     /* now add us to conf */
1108     if (dsp_debug & DEBUG_DSP_CMX)
1109         printk(KERN_DEBUG "searching conference %d\n",
1110                conf_id);
1111     conf = dsp_cmx_search_conf(conf_id);
1112     if (!conf) {
1113         if (dsp_debug & DEBUG_DSP_CMX)
1114             printk(KERN_DEBUG
1115                    "conference doesn't exist yet, creating.\n");
1116         /* the conference doesn't exist, so we create */
1117         conf = dsp_cmx_new_conf(conf_id);
1118         if (!conf)
1119             return -EINVAL;
1120     } else if (!list_empty(&conf->mlist)) {
1121         member = list_entry(conf->mlist.next, struct dsp_conf_member,
1122                     list);
1123         if (dsp->hdlc && !member->dsp->hdlc) {
1124             if (dsp_debug & DEBUG_DSP_CMX)
1125                 printk(KERN_DEBUG
1126                        "cannot join transparent conference.\n");
1127             return -EINVAL;
1128         }
1129         if (!dsp->hdlc && member->dsp->hdlc) {
1130             if (dsp_debug & DEBUG_DSP_CMX)
1131                 printk(KERN_DEBUG
1132                        "cannot join hdlc conference.\n");
1133             return -EINVAL;
1134         }
1135     }
1136     /* add conference member */
1137     err = dsp_cmx_add_conf_member(dsp, conf);
1138     if (err)
1139         return err;
1140     dsp->conf_id = conf_id;
1141 
1142     /* if we are alone, we do nothing! */
1143     if (list_empty(&conf->mlist)) {
1144         if (dsp_debug & DEBUG_DSP_CMX)
1145             printk(KERN_DEBUG
1146                    "we are alone in this conference, so exit.\n");
1147         /* update hardware */
1148         dsp_cmx_hardware(NULL, dsp);
1149         return 0;
1150     }
1151 
1152     /* update members on conf */
1153     dsp_cmx_hardware(conf, NULL);
1154 
1155     return 0;
1156 }
1157 
1158 #ifdef CMX_DELAY_DEBUG
1159 int delaycount;
1160 static void
1161 showdelay(struct dsp *dsp, int samples, int delay)
1162 {
1163     char bar[] = "--------------------------------------------------|";
1164     int sdelay;
1165 
1166     delaycount += samples;
1167     if (delaycount < 8000)
1168         return;
1169     delaycount = 0;
1170 
1171     sdelay = delay * 50 / (dsp_poll << 2);
1172 
1173     printk(KERN_DEBUG "DELAY (%s) %3d >%s\n", dsp->name, delay,
1174            sdelay > 50 ? "..." : bar + 50 - sdelay);
1175 }
1176 #endif
1177 
1178 /*
1179  * audio data is received from card
1180  */
1181 void
1182 dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb)
1183 {
1184     u8 *d, *p;
1185     int len = skb->len;
1186     struct mISDNhead *hh = mISDN_HEAD_P(skb);
1187     int w, i, ii;
1188 
1189     /* check if we have sompen */
1190     if (len < 1)
1191         return;
1192 
1193     /* half of the buffer should be larger than maximum packet size */
1194     if (len >= CMX_BUFF_HALF) {
1195         printk(KERN_ERR
1196                "%s line %d: packet from card is too large (%d bytes). "
1197                "please make card send smaller packets OR increase "
1198                "CMX_BUFF_SIZE\n", __FILE__, __LINE__, len);
1199         return;
1200     }
1201 
1202     /*
1203      * initialize pointers if not already -
1204      * also add delay if requested by PH_SIGNAL
1205      */
1206     if (dsp->rx_init) {
1207         dsp->rx_init = 0;
1208         if (dsp->features.unordered) {
1209             dsp->rx_R = (hh->id & CMX_BUFF_MASK);
1210             if (dsp->cmx_delay)
1211                 dsp->rx_W = (dsp->rx_R + dsp->cmx_delay)
1212                     & CMX_BUFF_MASK;
1213             else
1214                 dsp->rx_W = (dsp->rx_R + (dsp_poll >> 1))
1215                     & CMX_BUFF_MASK;
1216         } else {
1217             dsp->rx_R = 0;
1218             if (dsp->cmx_delay)
1219                 dsp->rx_W = dsp->cmx_delay;
1220             else
1221                 dsp->rx_W = dsp_poll >> 1;
1222         }
1223     }
1224     /* if frame contains time code, write directly */
1225     if (dsp->features.unordered) {
1226         dsp->rx_W = (hh->id & CMX_BUFF_MASK);
1227         /* printk(KERN_DEBUG "%s %08x\n", dsp->name, hh->id); */
1228     }
1229     /*
1230      * if we underrun (or maybe overrun),
1231      * we set our new read pointer, and write silence to buffer
1232      */
1233     if (((dsp->rx_W-dsp->rx_R) & CMX_BUFF_MASK) >= CMX_BUFF_HALF) {
1234         if (dsp_debug & DEBUG_DSP_CLOCK)
1235             printk(KERN_DEBUG
1236                    "cmx_receive(dsp=%lx): UNDERRUN (or overrun the "
1237                    "maximum delay), adjusting read pointer! "
1238                    "(inst %s)\n", (u_long)dsp, dsp->name);
1239         /* flush rx buffer and set delay to dsp_poll / 2 */
1240         if (dsp->features.unordered) {
1241             dsp->rx_R = (hh->id & CMX_BUFF_MASK);
1242             if (dsp->cmx_delay)
1243                 dsp->rx_W = (dsp->rx_R + dsp->cmx_delay)
1244                     & CMX_BUFF_MASK;
1245             else
1246                 dsp->rx_W = (dsp->rx_R + (dsp_poll >> 1))
1247                     & CMX_BUFF_MASK;
1248         } else {
1249             dsp->rx_R = 0;
1250             if (dsp->cmx_delay)
1251                 dsp->rx_W = dsp->cmx_delay;
1252             else
1253                 dsp->rx_W = dsp_poll >> 1;
1254         }
1255         memset(dsp->rx_buff, dsp_silence, sizeof(dsp->rx_buff));
1256     }
1257     /* if we have reached double delay, jump back to middle */
1258     if (dsp->cmx_delay)
1259         if (((dsp->rx_W - dsp->rx_R) & CMX_BUFF_MASK) >=
1260             (dsp->cmx_delay << 1)) {
1261             if (dsp_debug & DEBUG_DSP_CLOCK)
1262                 printk(KERN_DEBUG
1263                        "cmx_receive(dsp=%lx): OVERRUN (because "
1264                        "twice the delay is reached), adjusting "
1265                        "read pointer! (inst %s)\n",
1266                        (u_long)dsp, dsp->name);
1267             /* flush buffer */
1268             if (dsp->features.unordered) {
1269                 dsp->rx_R = (hh->id & CMX_BUFF_MASK);
1270                 dsp->rx_W = (dsp->rx_R + dsp->cmx_delay)
1271                     & CMX_BUFF_MASK;
1272             } else {
1273                 dsp->rx_R = 0;
1274                 dsp->rx_W = dsp->cmx_delay;
1275             }
1276             memset(dsp->rx_buff, dsp_silence, sizeof(dsp->rx_buff));
1277         }
1278 
1279     /* show where to write */
1280 #ifdef CMX_DEBUG
1281     printk(KERN_DEBUG
1282            "cmx_receive(dsp=%lx): rx_R(dsp)=%05x rx_W(dsp)=%05x len=%d %s\n",
1283            (u_long)dsp, dsp->rx_R, dsp->rx_W, len, dsp->name);
1284 #endif
1285 
1286     /* write data into rx_buffer */
1287     p = skb->data;
1288     d = dsp->rx_buff;
1289     w = dsp->rx_W;
1290     i = 0;
1291     ii = len;
1292     while (i < ii) {
1293         d[w++ & CMX_BUFF_MASK] = *p++;
1294         i++;
1295     }
1296 
1297     /* increase write-pointer */
1298     dsp->rx_W = ((dsp->rx_W + len) & CMX_BUFF_MASK);
1299 #ifdef CMX_DELAY_DEBUG
1300     showdelay(dsp, len, (dsp->rx_W-dsp->rx_R) & CMX_BUFF_MASK);
1301 #endif
1302 }
1303 
1304 
1305 /*
1306  * send (mixed) audio data to card and control jitter
1307  */
1308 static void
1309 dsp_cmx_send_member(struct dsp *dsp, int len, s32 *c, int members)
1310 {
1311     struct dsp_conf *conf = dsp->conf;
1312     struct dsp *member, *other;
1313     register s32 sample;
1314     u8 *d, *p, *q, *o_q;
1315     struct sk_buff *nskb, *txskb;
1316     int r, rr, t, tt, o_r, o_rr;
1317     int preload = 0;
1318     struct mISDNhead *hh, *thh;
1319     int tx_data_only = 0;
1320 
1321     /* don't process if: */
1322     if (!dsp->b_active) { /* if not active */
1323         dsp->last_tx = 0;
1324         return;
1325     }
1326     if (((dsp->conf && dsp->conf->hardware) || /* hardware conf */
1327          dsp->echo.hardware) && /* OR hardware echo */
1328         dsp->tx_R == dsp->tx_W && /* AND no tx-data */
1329         !(dsp->tone.tone && dsp->tone.software)) { /* AND not soft tones */
1330         if (!dsp->tx_data) { /* no tx_data for user space required */
1331             dsp->last_tx = 0;
1332             return;
1333         }
1334         if (dsp->conf && dsp->conf->software && dsp->conf->hardware)
1335             tx_data_only = 1;
1336         if (dsp->echo.software && dsp->echo.hardware)
1337             tx_data_only = 1;
1338     }
1339 
1340 #ifdef CMX_DEBUG
1341     printk(KERN_DEBUG
1342            "SEND members=%d dsp=%s, conf=%p, rx_R=%05x rx_W=%05x\n",
1343            members, dsp->name, conf, dsp->rx_R, dsp->rx_W);
1344 #endif
1345 
1346     /* preload if we have delay set */
1347     if (dsp->cmx_delay && !dsp->last_tx) {
1348         preload = len;
1349         if (preload < 128)
1350             preload = 128;
1351     }
1352 
1353     /* PREPARE RESULT */
1354     nskb = mI_alloc_skb(len + preload, GFP_ATOMIC);
1355     if (!nskb) {
1356         printk(KERN_ERR
1357                "FATAL ERROR in mISDN_dsp.o: cannot alloc %d bytes\n",
1358                len + preload);
1359         return;
1360     }
1361     hh = mISDN_HEAD_P(nskb);
1362     hh->prim = PH_DATA_REQ;
1363     hh->id = 0;
1364     dsp->last_tx = 1;
1365 
1366     /* set pointers, indexes and stuff */
1367     member = dsp;
1368     p = dsp->tx_buff; /* transmit data */
1369     q = dsp->rx_buff; /* received data */
1370     d = skb_put(nskb, preload + len); /* result */
1371     t = dsp->tx_R; /* tx-pointers */
1372     tt = dsp->tx_W;
1373     r = dsp->rx_R; /* rx-pointers */
1374     rr = (r + len) & CMX_BUFF_MASK;
1375 
1376     /* preload with silence, if required */
1377     if (preload) {
1378         memset(d, dsp_silence, preload);
1379         d += preload;
1380     }
1381 
1382     /* PROCESS TONES/TX-DATA ONLY */
1383     if (dsp->tone.tone && dsp->tone.software) {
1384         /* -> copy tone */
1385         dsp_tone_copy(dsp, d, len);
1386         dsp->tx_R = 0; /* clear tx buffer */
1387         dsp->tx_W = 0;
1388         goto send_packet;
1389     }
1390     /* if we have tx-data but do not use mixing */
1391     if (!dsp->tx_mix && t != tt) {
1392         /* -> send tx-data and continue when not enough */
1393 #ifdef CMX_TX_DEBUG
1394         sprintf(debugbuf, "TX sending (%04x-%04x)%p: ", t, tt, p);
1395 #endif
1396         while (r != rr && t != tt) {
1397 #ifdef CMX_TX_DEBUG
1398             if (strlen(debugbuf) < 48)
1399                 sprintf(debugbuf + strlen(debugbuf), " %02x",
1400                     p[t]);
1401 #endif
1402             *d++ = p[t]; /* write tx_buff */
1403             t = (t + 1) & CMX_BUFF_MASK;
1404             r = (r + 1) & CMX_BUFF_MASK;
1405         }
1406         if (r == rr) {
1407             dsp->tx_R = t;
1408 #ifdef CMX_TX_DEBUG
1409             printk(KERN_DEBUG "%s\n", debugbuf);
1410 #endif
1411             goto send_packet;
1412         }
1413     }
1414 #ifdef CMX_TX_DEBUG
1415     printk(KERN_DEBUG "%s\n", debugbuf);
1416 #endif
1417 
1418     /* PROCESS DATA (one member / no conf) */
1419     if (!conf || members <= 1) {
1420         /* -> if echo is NOT enabled */
1421         if (!dsp->echo.software) {
1422             /* -> send tx-data if available or use 0-volume */
1423             while (r != rr && t != tt) {
1424                 *d++ = p[t]; /* write tx_buff */
1425                 t = (t + 1) & CMX_BUFF_MASK;
1426                 r = (r + 1) & CMX_BUFF_MASK;
1427             }
1428             if (r != rr) {
1429                 if (dsp_debug & DEBUG_DSP_CLOCK)
1430                     printk(KERN_DEBUG "%s: RX empty\n",
1431                            __func__);
1432                 memset(d, dsp_silence, (rr - r) & CMX_BUFF_MASK);
1433             }
1434             /* -> if echo is enabled */
1435         } else {
1436             /*
1437              * -> mix tx-data with echo if available,
1438              * or use echo only
1439              */
1440             while (r != rr && t != tt) {
1441                 *d++ = dsp_audio_mix_law[(p[t] << 8) | q[r]];
1442                 t = (t + 1) & CMX_BUFF_MASK;
1443                 r = (r + 1) & CMX_BUFF_MASK;
1444             }
1445             while (r != rr) {
1446                 *d++ = q[r]; /* echo */
1447                 r = (r + 1) & CMX_BUFF_MASK;
1448             }
1449         }
1450         dsp->tx_R = t;
1451         goto send_packet;
1452     }
1453     /* PROCESS DATA (two members) */
1454 #ifdef CMX_CONF_DEBUG
1455     if (0) {
1456 #else
1457     if (members == 2) {
1458 #endif
1459         /* "other" becomes other party */
1460         other = (list_entry(conf->mlist.next,
1461                     struct dsp_conf_member, list))->dsp;
1462         if (other == member)
1463             other = (list_entry(conf->mlist.prev,
1464                     struct dsp_conf_member, list))->dsp;
1465         o_q = other->rx_buff; /* received data */
1466         o_rr = (other->rx_R + len) & CMX_BUFF_MASK;
1467         /* end of rx-pointer */
1468         o_r = (o_rr - rr + r) & CMX_BUFF_MASK;
1469         /* start rx-pointer at current read position*/
1470         /* -> if echo is NOT enabled */
1471         if (!dsp->echo.software) {
1472             /*
1473              * -> copy other member's rx-data,
1474              * if tx-data is available, mix
1475              */
1476             while (o_r != o_rr && t != tt) {
1477                 *d++ = dsp_audio_mix_law[(p[t] << 8) | o_q[o_r]];
1478                 t = (t + 1) & CMX_BUFF_MASK;
1479                 o_r = (o_r + 1) & CMX_BUFF_MASK;
1480             }
1481             while (o_r != o_rr) {
1482                 *d++ = o_q[o_r];
1483                 o_r = (o_r + 1) & CMX_BUFF_MASK;
1484             }
1485             /* -> if echo is enabled */
1486         } else {
1487             /*
1488              * -> mix other member's rx-data with echo,
1489              * if tx-data is available, mix
1490              */
1491             while (r != rr && t != tt) {
1492                 sample = dsp_audio_law_to_s32[p[t]] +
1493                     dsp_audio_law_to_s32[q[r]] +
1494                     dsp_audio_law_to_s32[o_q[o_r]];
1495                 if (sample < -32768)
1496                     sample = -32768;
1497                 else if (sample > 32767)
1498                     sample = 32767;
1499                 *d++ = dsp_audio_s16_to_law[sample & 0xffff];
1500                 /* tx-data + rx_data + echo */
1501                 t = (t + 1) & CMX_BUFF_MASK;
1502                 r = (r + 1) & CMX_BUFF_MASK;
1503                 o_r = (o_r + 1) & CMX_BUFF_MASK;
1504             }
1505             while (r != rr) {
1506                 *d++ = dsp_audio_mix_law[(q[r] << 8) | o_q[o_r]];
1507                 r = (r + 1) & CMX_BUFF_MASK;
1508                 o_r = (o_r + 1) & CMX_BUFF_MASK;
1509             }
1510         }
1511         dsp->tx_R = t;
1512         goto send_packet;
1513     }
1514     /* PROCESS DATA (three or more members) */
1515     /* -> if echo is NOT enabled */
1516     if (!dsp->echo.software) {
1517         /*
1518          * -> subtract rx-data from conf-data,
1519          * if tx-data is available, mix
1520          */
1521         while (r != rr && t != tt) {
1522             sample = dsp_audio_law_to_s32[p[t]] + *c++ -
1523                 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+tx */
1530             r = (r + 1) & CMX_BUFF_MASK;
1531             t = (t + 1) & CMX_BUFF_MASK;
1532         }
1533         while (r != rr) {
1534             sample = *c++ - dsp_audio_law_to_s32[q[r]];
1535             if (sample < -32768)
1536                 sample = -32768;
1537             else if (sample > 32767)
1538                 sample = 32767;
1539             *d++ = dsp_audio_s16_to_law[sample & 0xffff];
1540             /* conf-rx */
1541             r = (r + 1) & CMX_BUFF_MASK;
1542         }
1543         /* -> if echo is enabled */
1544     } else {
1545         /*
1546          * -> encode conf-data, if tx-data
1547          * is available, mix
1548          */
1549         while (r != rr && t != tt) {
1550             sample = dsp_audio_law_to_s32[p[t]] + *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)+tx */
1557             t = (t + 1) & CMX_BUFF_MASK;
1558             r = (r + 1) & CMX_BUFF_MASK;
1559         }
1560         while (r != rr) {
1561             sample = *c++;
1562             if (sample < -32768)
1563                 sample = -32768;
1564             else if (sample > 32767)
1565                 sample = 32767;
1566             *d++ = dsp_audio_s16_to_law[sample & 0xffff];
1567             /* conf(echo) */
1568             r = (r + 1) & CMX_BUFF_MASK;
1569         }
1570     }
1571     dsp->tx_R = t;
1572     goto send_packet;
1573 
1574 send_packet:
1575     /*
1576      * send tx-data if enabled - don't filter,
1577      * because we want what we send, not what we filtered
1578      */
1579     if (dsp->tx_data) {
1580         if (tx_data_only) {
1581             hh->prim = DL_DATA_REQ;
1582             hh->id = 0;
1583             /* queue and trigger */
1584             skb_queue_tail(&dsp->sendq, nskb);
1585             schedule_work(&dsp->workq);
1586             /* exit because only tx_data is used */
1587             return;
1588         } else {
1589             txskb = mI_alloc_skb(len, GFP_ATOMIC);
1590             if (!txskb) {
1591                 printk(KERN_ERR
1592                        "FATAL ERROR in mISDN_dsp.o: "
1593                        "cannot alloc %d bytes\n", len);
1594             } else {
1595                 thh = mISDN_HEAD_P(txskb);
1596                 thh->prim = DL_DATA_REQ;
1597                 thh->id = 0;
1598                 skb_put_data(txskb, nskb->data + preload, len);
1599                 /* queue (trigger later) */
1600                 skb_queue_tail(&dsp->sendq, txskb);
1601             }
1602         }
1603     }
1604 
1605     /* send data only to card, if we don't just calculated tx_data */
1606     /* adjust volume */
1607     if (dsp->tx_volume)
1608         dsp_change_volume(nskb, dsp->tx_volume);
1609     /* pipeline */
1610     if (dsp->pipeline.inuse)
1611         dsp_pipeline_process_tx(&dsp->pipeline, nskb->data,
1612                     nskb->len);
1613     /* crypt */
1614     if (dsp->bf_enable)
1615         dsp_bf_encrypt(dsp, nskb->data, nskb->len);
1616     /* queue and trigger */
1617     skb_queue_tail(&dsp->sendq, nskb);
1618     schedule_work(&dsp->workq);
1619 }
1620 
1621 static u32  jittercount; /* counter for jitter check */
1622 struct timer_list dsp_spl_tl;
1623 unsigned long   dsp_spl_jiffies; /* calculate the next time to fire */
1624 static u16  dsp_count; /* last sample count */
1625 static int  dsp_count_valid; /* if we have last sample count */
1626 
1627 void
1628 dsp_cmx_send(void *arg)
1629 {
1630     struct dsp_conf *conf;
1631     struct dsp_conf_member *member;
1632     struct dsp *dsp;
1633     int mustmix, members;
1634     static s32 mixbuffer[MAX_POLL + 100];
1635     s32 *c;
1636     u8 *p, *q;
1637     int r, rr;
1638     int jittercheck = 0, delay, i;
1639     u_long flags;
1640     u16 length, count;
1641 
1642     /* lock */
1643     spin_lock_irqsave(&dsp_lock, flags);
1644 
1645     if (!dsp_count_valid) {
1646         dsp_count = mISDN_clock_get();
1647         length = dsp_poll;
1648         dsp_count_valid = 1;
1649     } else {
1650         count = mISDN_clock_get();
1651         length = count - dsp_count;
1652         dsp_count = count;
1653     }
1654     if (length > MAX_POLL + 100)
1655         length = MAX_POLL + 100;
1656     /* printk(KERN_DEBUG "len=%d dsp_count=0x%x\n", length, dsp_count); */
1657 
1658     /*
1659      * check if jitter needs to be checked (this is every second)
1660      */
1661     jittercount += length;
1662     if (jittercount >= 8000) {
1663         jittercount -= 8000;
1664         jittercheck = 1;
1665     }
1666 
1667     /* loop all members that do not require conference mixing */
1668     list_for_each_entry(dsp, &dsp_ilist, list) {
1669         if (dsp->hdlc)
1670             continue;
1671         conf = dsp->conf;
1672         mustmix = 0;
1673         members = 0;
1674         if (conf) {
1675             members = count_list_member(&conf->mlist);
1676 #ifdef CMX_CONF_DEBUG
1677             if (conf->software && members > 1)
1678 #else
1679             if (conf->software && members > 2)
1680 #endif
1681                 mustmix = 1;
1682         }
1683 
1684         /* transmission required */
1685         if (!mustmix) {
1686             dsp_cmx_send_member(dsp, length, mixbuffer, members);
1687 
1688             /*
1689              * unused mixbuffer is given to prevent a
1690              * potential null-pointer-bug
1691              */
1692         }
1693     }
1694 
1695     /* loop all members that require conference mixing */
1696     list_for_each_entry(conf, &conf_ilist, list) {
1697         /* count members and check hardware */
1698         members = count_list_member(&conf->mlist);
1699 #ifdef CMX_CONF_DEBUG
1700         if (conf->software && members > 1) {
1701 #else
1702         if (conf->software && members > 2) {
1703 #endif
1704             /* check for hdlc conf */
1705             member = list_entry(conf->mlist.next,
1706                         struct dsp_conf_member, list);
1707             if (member->dsp->hdlc)
1708                 continue;
1709             /* mix all data */
1710             memset(mixbuffer, 0, length * sizeof(s32));
1711             list_for_each_entry(member, &conf->mlist, list) {
1712                 dsp = member->dsp;
1713                 /* get range of data to mix */
1714                 c = mixbuffer;
1715                 q = dsp->rx_buff;
1716                 r = dsp->rx_R;
1717                 rr = (r + length) & CMX_BUFF_MASK;
1718                 /* add member's data */
1719                 while (r != rr) {
1720                     *c++ += dsp_audio_law_to_s32[q[r]];
1721                     r = (r + 1) & CMX_BUFF_MASK;
1722                 }
1723             }
1724 
1725             /* process each member */
1726             list_for_each_entry(member, &conf->mlist, list) {
1727                 /* transmission */
1728                 dsp_cmx_send_member(member->dsp, length,
1729                             mixbuffer, members);
1730             }
1731         }
1732     }
1733 
1734     /* delete rx-data, increment buffers, change pointers */
1735     list_for_each_entry(dsp, &dsp_ilist, list) {
1736         if (dsp->hdlc)
1737             continue;
1738         p = dsp->rx_buff;
1739         q = dsp->tx_buff;
1740         r = dsp->rx_R;
1741         /* move receive pointer when receiving */
1742         if (!dsp->rx_is_off) {
1743             rr = (r + length) & CMX_BUFF_MASK;
1744             /* delete rx-data */
1745             while (r != rr) {
1746                 p[r] = dsp_silence;
1747                 r = (r + 1) & CMX_BUFF_MASK;
1748             }
1749             /* increment rx-buffer pointer */
1750             dsp->rx_R = r; /* write incremented read pointer */
1751         }
1752 
1753         /* check current rx_delay */
1754         delay = (dsp->rx_W-dsp->rx_R) & CMX_BUFF_MASK;
1755         if (delay >= CMX_BUFF_HALF)
1756             delay = 0; /* will be the delay before next write */
1757         /* check for lower delay */
1758         if (delay < dsp->rx_delay[0])
1759             dsp->rx_delay[0] = delay;
1760         /* check current tx_delay */
1761         delay = (dsp->tx_W-dsp->tx_R) & CMX_BUFF_MASK;
1762         if (delay >= CMX_BUFF_HALF)
1763             delay = 0; /* will be the delay before next write */
1764         /* check for lower delay */
1765         if (delay < dsp->tx_delay[0])
1766             dsp->tx_delay[0] = delay;
1767         if (jittercheck) {
1768             /* find the lowest of all rx_delays */
1769             delay = dsp->rx_delay[0];
1770             i = 1;
1771             while (i < MAX_SECONDS_JITTER_CHECK) {
1772                 if (delay > dsp->rx_delay[i])
1773                     delay = dsp->rx_delay[i];
1774                 i++;
1775             }
1776             /*
1777              * remove rx_delay only if we have delay AND we
1778              * have not preset cmx_delay AND
1779              * the delay is greater dsp_poll
1780              */
1781             if (delay > dsp_poll && !dsp->cmx_delay) {
1782                 if (dsp_debug & DEBUG_DSP_CLOCK)
1783                     printk(KERN_DEBUG
1784                            "%s lowest rx_delay of %d bytes for"
1785                            " dsp %s are now removed.\n",
1786                            __func__, delay,
1787                            dsp->name);
1788                 r = dsp->rx_R;
1789                 rr = (r + delay - (dsp_poll >> 1))
1790                     & CMX_BUFF_MASK;
1791                 /* delete rx-data */
1792                 while (r != rr) {
1793                     p[r] = dsp_silence;
1794                     r = (r + 1) & CMX_BUFF_MASK;
1795                 }
1796                 /* increment rx-buffer pointer */
1797                 dsp->rx_R = r;
1798                 /* write incremented read pointer */
1799             }
1800             /* find the lowest of all tx_delays */
1801             delay = dsp->tx_delay[0];
1802             i = 1;
1803             while (i < MAX_SECONDS_JITTER_CHECK) {
1804                 if (delay > dsp->tx_delay[i])
1805                     delay = dsp->tx_delay[i];
1806                 i++;
1807             }
1808             /*
1809              * remove delay only if we have delay AND we
1810              * have enabled tx_dejitter
1811              */
1812             if (delay > dsp_poll && dsp->tx_dejitter) {
1813                 if (dsp_debug & DEBUG_DSP_CLOCK)
1814                     printk(KERN_DEBUG
1815                            "%s lowest tx_delay of %d bytes for"
1816                            " dsp %s are now removed.\n",
1817                            __func__, delay,
1818                            dsp->name);
1819                 r = dsp->tx_R;
1820                 rr = (r + delay - (dsp_poll >> 1))
1821                     & CMX_BUFF_MASK;
1822                 /* delete tx-data */
1823                 while (r != rr) {
1824                     q[r] = dsp_silence;
1825                     r = (r + 1) & CMX_BUFF_MASK;
1826                 }
1827                 /* increment rx-buffer pointer */
1828                 dsp->tx_R = r;
1829                 /* write incremented read pointer */
1830             }
1831             /* scroll up delays */
1832             i = MAX_SECONDS_JITTER_CHECK - 1;
1833             while (i) {
1834                 dsp->rx_delay[i] = dsp->rx_delay[i - 1];
1835                 dsp->tx_delay[i] = dsp->tx_delay[i - 1];
1836                 i--;
1837             }
1838             dsp->tx_delay[0] = CMX_BUFF_HALF; /* (infinite) delay */
1839             dsp->rx_delay[0] = CMX_BUFF_HALF; /* (infinite) delay */
1840         }
1841     }
1842 
1843     /* if next event would be in the past ... */
1844     if ((s32)(dsp_spl_jiffies + dsp_tics-jiffies) <= 0)
1845         dsp_spl_jiffies = jiffies + 1;
1846     else
1847         dsp_spl_jiffies += dsp_tics;
1848 
1849     dsp_spl_tl.expires = dsp_spl_jiffies;
1850     add_timer(&dsp_spl_tl);
1851 
1852     /* unlock */
1853     spin_unlock_irqrestore(&dsp_lock, flags);
1854 }
1855 
1856 /*
1857  * audio data is transmitted from upper layer to the dsp
1858  */
1859 void
1860 dsp_cmx_transmit(struct dsp *dsp, struct sk_buff *skb)
1861 {
1862     u_int w, ww;
1863     u8 *d, *p;
1864     int space; /* todo: , l = skb->len; */
1865 #ifdef CMX_TX_DEBUG
1866     char debugbuf[256] = "";
1867 #endif
1868 
1869     /* check if there is enough space, and then copy */
1870     w = dsp->tx_W;
1871     ww = dsp->tx_R;
1872     p = dsp->tx_buff;
1873     d = skb->data;
1874     space = (ww - w - 1) & CMX_BUFF_MASK;
1875     /* write-pointer should not overrun nor reach read pointer */
1876     if (space < skb->len) {
1877         /* write to the space we have left */
1878         ww = (ww - 1) & CMX_BUFF_MASK; /* end one byte prior tx_R */
1879         if (dsp_debug & DEBUG_DSP_CLOCK)
1880             printk(KERN_DEBUG "%s: TX overflow space=%d skb->len="
1881                    "%d, w=0x%04x, ww=0x%04x\n", __func__, space,
1882                    skb->len, w, ww);
1883     } else
1884         /* write until all byte are copied */
1885         ww = (w + skb->len) & CMX_BUFF_MASK;
1886     dsp->tx_W = ww;
1887         /* show current buffer */
1888 #ifdef CMX_DEBUG
1889     printk(KERN_DEBUG
1890            "cmx_transmit(dsp=%lx) %d bytes to 0x%x-0x%x. %s\n",
1891            (u_long)dsp, (ww - w) & CMX_BUFF_MASK, w, ww, dsp->name);
1892 #endif
1893 
1894     /* copy transmit data to tx-buffer */
1895 #ifdef CMX_TX_DEBUG
1896     sprintf(debugbuf, "TX getting (%04x-%04x)%p: ", w, ww, p);
1897 #endif
1898     while (w != ww) {
1899 #ifdef CMX_TX_DEBUG
1900         if (strlen(debugbuf) < 48)
1901             sprintf(debugbuf + strlen(debugbuf), " %02x", *d);
1902 #endif
1903         p[w] = *d++;
1904         w = (w + 1) & CMX_BUFF_MASK;
1905     }
1906 #ifdef CMX_TX_DEBUG
1907     printk(KERN_DEBUG "%s\n", debugbuf);
1908 #endif
1909 
1910 }
1911 
1912 /*
1913  * hdlc data is received from card and sent to all members.
1914  */
1915 void
1916 dsp_cmx_hdlc(struct dsp *dsp, struct sk_buff *skb)
1917 {
1918     struct sk_buff *nskb = NULL;
1919     struct dsp_conf_member *member;
1920     struct mISDNhead *hh;
1921 
1922     /* not if not active */
1923     if (!dsp->b_active)
1924         return;
1925 
1926     /* check if we have sompen */
1927     if (skb->len < 1)
1928         return;
1929 
1930     /* no conf */
1931     if (!dsp->conf) {
1932         /* in case of software echo */
1933         if (dsp->echo.software) {
1934             nskb = skb_clone(skb, GFP_ATOMIC);
1935             if (nskb) {
1936                 hh = mISDN_HEAD_P(nskb);
1937                 hh->prim = PH_DATA_REQ;
1938                 hh->id = 0;
1939                 skb_queue_tail(&dsp->sendq, nskb);
1940                 schedule_work(&dsp->workq);
1941             }
1942         }
1943         return;
1944     }
1945     /* in case of hardware conference */
1946     if (dsp->conf->hardware)
1947         return;
1948     list_for_each_entry(member, &dsp->conf->mlist, list) {
1949         if (dsp->echo.software || member->dsp != dsp) {
1950             nskb = skb_clone(skb, GFP_ATOMIC);
1951             if (nskb) {
1952                 hh = mISDN_HEAD_P(nskb);
1953                 hh->prim = PH_DATA_REQ;
1954                 hh->id = 0;
1955                 skb_queue_tail(&member->dsp->sendq, nskb);
1956                 schedule_work(&member->dsp->workq);
1957             }
1958         }
1959     }
1960 }