root/drivers/isdn/mISDN/dsp_cmx.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. count_list_member
  2. dsp_cmx_debug
  3. dsp_cmx_search_conf
  4. dsp_cmx_add_conf_member
  5. dsp_cmx_del_conf_member
  6. dsp_cmx_new_conf
  7. dsp_cmx_del_conf
  8. dsp_cmx_hw_message
  9. dsp_cmx_hardware
  10. dsp_cmx_conf
  11. showdelay
  12. dsp_cmx_receive
  13. dsp_cmx_send_member
  14. dsp_cmx_send
  15. dsp_cmx_transmit
  16. dsp_cmx_hdlc

   1 /*
   2  * Audio crossconnecting/conferrencing (hardware level).
   3  *
   4  * Copyright 2002 by Andreas Eversberg (jolly@eversberg.eu)
   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 jiffie 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 static inline int
 145 count_list_member(struct list_head *head)
 146 {
 147         int                     cnt = 0;
 148         struct list_head        *m;
 149 
 150         list_for_each(m, head)
 151                 cnt++;
 152         return cnt;
 153 }
 154 
 155 /*
 156  * debug cmx memory structure
 157  */
 158 void
 159 dsp_cmx_debug(struct dsp *dsp)
 160 {
 161         struct dsp_conf *conf;
 162         struct dsp_conf_member  *member;
 163         struct dsp              *odsp;
 164 
 165         printk(KERN_DEBUG "-----Current DSP\n");
 166         list_for_each_entry(odsp, &dsp_ilist, list) {
 167                 printk(KERN_DEBUG "* %s hardecho=%d softecho=%d txmix=%d",
 168                        odsp->name, odsp->echo.hardware, odsp->echo.software,
 169                        odsp->tx_mix);
 170                 if (odsp->conf)
 171                         printk(" (Conf %d)", odsp->conf->id);
 172                 if (dsp == odsp)
 173                         printk(" *this*");
 174                 printk("\n");
 175         }
 176         printk(KERN_DEBUG "-----Current Conf:\n");
 177         list_for_each_entry(conf, &conf_ilist, list) {
 178                 printk(KERN_DEBUG "* Conf %d (%p)\n", conf->id, conf);
 179                 list_for_each_entry(member, &conf->mlist, list) {
 180                         printk(KERN_DEBUG
 181                                "  - member = %s (slot_tx %d, bank_tx %d, "
 182                                "slot_rx %d, bank_rx %d hfc_conf %d "
 183                                "tx_data %d rx_is_off %d)%s\n",
 184                                member->dsp->name, member->dsp->pcm_slot_tx,
 185                                member->dsp->pcm_bank_tx, member->dsp->pcm_slot_rx,
 186                                member->dsp->pcm_bank_rx, member->dsp->hfc_conf,
 187                                member->dsp->tx_data, member->dsp->rx_is_off,
 188                                (member->dsp == dsp) ? " *this*" : "");
 189                 }
 190         }
 191         printk(KERN_DEBUG "-----end\n");
 192 }
 193 
 194 /*
 195  * search conference
 196  */
 197 static struct dsp_conf *
 198 dsp_cmx_search_conf(u32 id)
 199 {
 200         struct dsp_conf *conf;
 201 
 202         if (!id) {
 203                 printk(KERN_WARNING "%s: conference ID is 0.\n", __func__);
 204                 return NULL;
 205         }
 206 
 207         /* search conference */
 208         list_for_each_entry(conf, &conf_ilist, list)
 209                 if (conf->id == id)
 210                         return conf;
 211 
 212         return NULL;
 213 }
 214 
 215 
 216 /*
 217  * add member to conference
 218  */
 219 static int
 220 dsp_cmx_add_conf_member(struct dsp *dsp, struct dsp_conf *conf)
 221 {
 222         struct dsp_conf_member *member;
 223 
 224         if (!conf || !dsp) {
 225                 printk(KERN_WARNING "%s: conf or dsp is 0.\n", __func__);
 226                 return -EINVAL;
 227         }
 228         if (dsp->member) {
 229                 printk(KERN_WARNING "%s: dsp is already member in a conf.\n",
 230                        __func__);
 231                 return -EINVAL;
 232         }
 233 
 234         if (dsp->conf) {
 235                 printk(KERN_WARNING "%s: dsp is already in a conf.\n",
 236                        __func__);
 237                 return -EINVAL;
 238         }
 239 
 240         member = kzalloc(sizeof(struct dsp_conf_member), GFP_ATOMIC);
 241         if (!member) {
 242                 printk(KERN_ERR "kzalloc struct dsp_conf_member failed\n");
 243                 return -ENOMEM;
 244         }
 245         member->dsp = dsp;
 246         /* clear rx buffer */
 247         memset(dsp->rx_buff, dsp_silence, sizeof(dsp->rx_buff));
 248         dsp->rx_init = 1; /* rx_W and rx_R will be adjusted on first frame */
 249         dsp->rx_W = 0;
 250         dsp->rx_R = 0;
 251 
 252         list_add_tail(&member->list, &conf->mlist);
 253 
 254         dsp->conf = conf;
 255         dsp->member = member;
 256 
 257         return 0;
 258 }
 259 
 260 
 261 /*
 262  * del member from conference
 263  */
 264 int
 265 dsp_cmx_del_conf_member(struct dsp *dsp)
 266 {
 267         struct dsp_conf_member *member;
 268 
 269         if (!dsp) {
 270                 printk(KERN_WARNING "%s: dsp is 0.\n",
 271                        __func__);
 272                 return -EINVAL;
 273         }
 274 
 275         if (!dsp->conf) {
 276                 printk(KERN_WARNING "%s: dsp is not in a conf.\n",
 277                        __func__);
 278                 return -EINVAL;
 279         }
 280 
 281         if (list_empty(&dsp->conf->mlist)) {
 282                 printk(KERN_WARNING "%s: dsp has linked an empty conf.\n",
 283                        __func__);
 284                 return -EINVAL;
 285         }
 286 
 287         /* find us in conf */
 288         list_for_each_entry(member, &dsp->conf->mlist, list) {
 289                 if (member->dsp == dsp) {
 290                         list_del(&member->list);
 291                         dsp->conf = NULL;
 292                         dsp->member = NULL;
 293                         kfree(member);
 294                         return 0;
 295                 }
 296         }
 297         printk(KERN_WARNING
 298                "%s: dsp is not present in its own conf_member list.\n",
 299                __func__);
 300 
 301         return -EINVAL;
 302 }
 303 
 304 
 305 /*
 306  * new conference
 307  */
 308 static struct dsp_conf
 309 *dsp_cmx_new_conf(u32 id)
 310 {
 311         struct dsp_conf *conf;
 312 
 313         if (!id) {
 314                 printk(KERN_WARNING "%s: id is 0.\n",
 315                        __func__);
 316                 return NULL;
 317         }
 318 
 319         conf = kzalloc(sizeof(struct dsp_conf), GFP_ATOMIC);
 320         if (!conf) {
 321                 printk(KERN_ERR "kzalloc struct dsp_conf failed\n");
 322                 return NULL;
 323         }
 324         INIT_LIST_HEAD(&conf->mlist);
 325         conf->id = id;
 326 
 327         list_add_tail(&conf->list, &conf_ilist);
 328 
 329         return conf;
 330 }
 331 
 332 
 333 /*
 334  * del conference
 335  */
 336 int
 337 dsp_cmx_del_conf(struct dsp_conf *conf)
 338 {
 339         if (!conf) {
 340                 printk(KERN_WARNING "%s: conf is null.\n",
 341                        __func__);
 342                 return -EINVAL;
 343         }
 344 
 345         if (!list_empty(&conf->mlist)) {
 346                 printk(KERN_WARNING "%s: conf not empty.\n",
 347                        __func__);
 348                 return -EINVAL;
 349         }
 350         list_del(&conf->list);
 351         kfree(conf);
 352 
 353         return 0;
 354 }
 355 
 356 
 357 /*
 358  * send HW message to hfc card
 359  */
 360 static void
 361 dsp_cmx_hw_message(struct dsp *dsp, u32 message, u32 param1, u32 param2,
 362                    u32 param3, u32 param4)
 363 {
 364         struct mISDN_ctrl_req cq;
 365 
 366         memset(&cq, 0, sizeof(cq));
 367         cq.op = message;
 368         cq.p1 = param1 | (param2 << 8);
 369         cq.p2 = param3 | (param4 << 8);
 370         if (dsp->ch.peer)
 371                 dsp->ch.peer->ctrl(dsp->ch.peer, CONTROL_CHANNEL, &cq);
 372 }
 373 
 374 
 375 /*
 376  * do hardware update and set the software/hardware flag
 377  *
 378  * either a conference or a dsp instance can be given
 379  * if only dsp instance is given, the instance is not associated with a conf
 380  * and therefore removed. if a conference is given, the dsp is expected to
 381  * be member of that conference.
 382  */
 383 void
 384 dsp_cmx_hardware(struct dsp_conf *conf, struct dsp *dsp)
 385 {
 386         struct dsp_conf_member  *member, *nextm;
 387         struct dsp              *finddsp;
 388         int             memb = 0, i, ii, i1, i2;
 389         int             freeunits[8];
 390         u_char          freeslots[256];
 391         int             same_hfc = -1, same_pcm = -1, current_conf = -1,
 392                 all_conf = 1, tx_data = 0;
 393 
 394         /* dsp gets updated (no conf) */
 395         if (!conf) {
 396                 if (!dsp)
 397                         return;
 398                 if (dsp_debug & DEBUG_DSP_CMX)
 399                         printk(KERN_DEBUG "%s checking dsp %s\n",
 400                                __func__, dsp->name);
 401         one_member:
 402                 /* remove HFC conference if enabled */
 403                 if (dsp->hfc_conf >= 0) {
 404                         if (dsp_debug & DEBUG_DSP_CMX)
 405                                 printk(KERN_DEBUG
 406                                        "%s removing %s from HFC conf %d "
 407                                        "because dsp is split\n", __func__,
 408                                        dsp->name, dsp->hfc_conf);
 409                         dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_CONF_SPLIT,
 410                                            0, 0, 0, 0);
 411                         dsp->hfc_conf = -1;
 412                 }
 413                 /* process hw echo */
 414                 if (dsp->features.pcm_banks < 1)
 415                         return;
 416                 if (!dsp->echo.software && !dsp->echo.hardware) {
 417                         /* NO ECHO: remove PCM slot if assigned */
 418                         if (dsp->pcm_slot_tx >= 0 || dsp->pcm_slot_rx >= 0) {
 419                                 if (dsp_debug & DEBUG_DSP_CMX)
 420                                         printk(KERN_DEBUG "%s removing %s from"
 421                                                " PCM slot %d (TX) %d (RX) because"
 422                                                " dsp is split (no echo)\n",
 423                                                __func__, dsp->name,
 424                                                dsp->pcm_slot_tx, dsp->pcm_slot_rx);
 425                                 dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_PCM_DISC,
 426                                                    0, 0, 0, 0);
 427                                 dsp->pcm_slot_tx = -1;
 428                                 dsp->pcm_bank_tx = -1;
 429                                 dsp->pcm_slot_rx = -1;
 430                                 dsp->pcm_bank_rx = -1;
 431                         }
 432                         return;
 433                 }
 434                 /* echo is enabled, find out if we use soft or hardware */
 435                 dsp->echo.software = dsp->tx_data;
 436                 dsp->echo.hardware = 0;
 437                 /* ECHO: already echo */
 438                 if (dsp->pcm_slot_tx >= 0 && dsp->pcm_slot_rx < 0 &&
 439                     dsp->pcm_bank_tx == 2 && dsp->pcm_bank_rx == 2) {
 440                         dsp->echo.hardware = 1;
 441                         return;
 442                 }
 443                 /* ECHO: if slot already assigned */
 444                 if (dsp->pcm_slot_tx >= 0) {
 445                         dsp->pcm_slot_rx = dsp->pcm_slot_tx;
 446                         dsp->pcm_bank_tx = 2; /* 2 means loop */
 447                         dsp->pcm_bank_rx = 2;
 448                         if (dsp_debug & DEBUG_DSP_CMX)
 449                                 printk(KERN_DEBUG
 450                                        "%s refresh %s for echo using slot %d\n",
 451                                        __func__, dsp->name,
 452                                        dsp->pcm_slot_tx);
 453                         dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_PCM_CONN,
 454                                            dsp->pcm_slot_tx, 2, dsp->pcm_slot_rx, 2);
 455                         dsp->echo.hardware = 1;
 456                         return;
 457                 }
 458                 /* ECHO: find slot */
 459                 dsp->pcm_slot_tx = -1;
 460                 dsp->pcm_slot_rx = -1;
 461                 memset(freeslots, 1, sizeof(freeslots));
 462                 list_for_each_entry(finddsp, &dsp_ilist, list) {
 463                         if (finddsp->features.pcm_id == dsp->features.pcm_id) {
 464                                 if (finddsp->pcm_slot_rx >= 0 &&
 465                                     finddsp->pcm_slot_rx < sizeof(freeslots))
 466                                         freeslots[finddsp->pcm_slot_rx] = 0;
 467                                 if (finddsp->pcm_slot_tx >= 0 &&
 468                                     finddsp->pcm_slot_tx < sizeof(freeslots))
 469                                         freeslots[finddsp->pcm_slot_tx] = 0;
 470                         }
 471                 }
 472                 i = 0;
 473                 ii = dsp->features.pcm_slots;
 474                 while (i < ii) {
 475                         if (freeslots[i])
 476                                 break;
 477                         i++;
 478                 }
 479                 if (i == ii) {
 480                         if (dsp_debug & DEBUG_DSP_CMX)
 481                                 printk(KERN_DEBUG
 482                                        "%s no slot available for echo\n",
 483                                        __func__);
 484                         /* no more slots available */
 485                         dsp->echo.software = 1;
 486                         return;
 487                 }
 488                 /* assign free slot */
 489                 dsp->pcm_slot_tx = i;
 490                 dsp->pcm_slot_rx = i;
 491                 dsp->pcm_bank_tx = 2; /* loop */
 492                 dsp->pcm_bank_rx = 2;
 493                 if (dsp_debug & DEBUG_DSP_CMX)
 494                         printk(KERN_DEBUG
 495                                "%s assign echo for %s using slot %d\n",
 496                                __func__, dsp->name, dsp->pcm_slot_tx);
 497                 dsp_cmx_hw_message(dsp, MISDN_CTRL_HFC_PCM_CONN,
 498                                    dsp->pcm_slot_tx, 2, dsp->pcm_slot_rx, 2);
 499                 dsp->echo.hardware = 1;
 500                 return;
 501         }
 502 
 503         /* conf gets updated (all members) */
 504         if (dsp_debug & DEBUG_DSP_CMX)
 505                 printk(KERN_DEBUG "%s checking conference %d\n",
 506                        __func__, conf->id);
 507 
 508         if (list_empty(&conf->mlist)) {
 509                 printk(KERN_ERR "%s: conference without members\n",
 510                        __func__);
 511                 return;
 512         }
 513         member = list_entry(conf->mlist.next, struct dsp_conf_member, list);
 514         same_hfc = member->dsp->features.hfc_id;
 515         same_pcm = member->dsp->features.pcm_id;
 516         /* check all members in our conference */
 517         list_for_each_entry(member, &conf->mlist, list) {
 518                 /* check if member uses mixing */
 519                 if (member->dsp->tx_mix) {
 520                         if (dsp_debug & DEBUG_DSP_CMX)
 521                                 printk(KERN_DEBUG
 522                                        "%s dsp %s cannot form a conf, because "
 523                                        "tx_mix is turned on\n", __func__,
 524                                        member->dsp->name);
 525                 conf_software:
 526                         list_for_each_entry(member, &conf->mlist, list) {
 527                                 dsp = member->dsp;
 528                                 /* remove HFC conference if enabled */
 529                                 if (dsp->hfc_conf >= 0) {
 530                                         if (dsp_debug & DEBUG_DSP_CMX)
 531                                                 printk(KERN_DEBUG
 532                                                        "%s removing %s from HFC "
 533                                                        "conf %d because not "
 534                                                        "possible with hardware\n",
 535                                                        __func__,
 536                                                        dsp->name,
 537                                                        dsp->hfc_conf);
 538                                         dsp_cmx_hw_message(dsp,
 539                                                            MISDN_CTRL_HFC_CONF_SPLIT,
 540                                                            0, 0, 0, 0);
 541                                         dsp->hfc_conf = -1;
 542                                 }
 543                                 /* remove PCM slot if assigned */
 544                                 if (dsp->pcm_slot_tx >= 0 ||
 545                                     dsp->pcm_slot_rx >= 0) {
 546                                         if (dsp_debug & DEBUG_DSP_CMX)
 547                                                 printk(KERN_DEBUG "%s removing "
 548                                                        "%s from PCM slot %d (TX)"
 549                                                        " slot %d (RX) because not"
 550                                                        " possible with hardware\n",
 551                                                        __func__,
 552                                                        dsp->name,
 553                                                        dsp->pcm_slot_tx,
 554                                                        dsp->pcm_slot_rx);
 555                                         dsp_cmx_hw_message(dsp,
 556                                                            MISDN_CTRL_HFC_PCM_DISC,
 557                                                            0, 0, 0, 0);
 558                                         dsp->pcm_slot_tx = -1;
 559                                         dsp->pcm_bank_tx = -1;
 560                                         dsp->pcm_slot_rx = -1;
 561                                         dsp->pcm_bank_rx = -1;
 562                                 }
 563                         }
 564                         conf->hardware = 0;
 565                         conf->software = 1;
 566                         return;
 567                 }
 568                 /* check if member has echo turned on */
 569                 if (member->dsp->echo.hardware || member->dsp->echo.software) {
 570                         if (dsp_debug & DEBUG_DSP_CMX)
 571                                 printk(KERN_DEBUG
 572                                        "%s dsp %s cannot form a conf, because "
 573                                        "echo is turned on\n", __func__,
 574                                        member->dsp->name);
 575                         goto conf_software;
 576                 }
 577                 /* check if member has tx_mix turned on */
 578                 if (member->dsp->tx_mix) {
 579                         if (dsp_debug & DEBUG_DSP_CMX)
 580                                 printk(KERN_DEBUG
 581                                        "%s dsp %s cannot form a conf, because "
 582                                        "tx_mix is turned on\n",
 583                                        __func__, member->dsp->name);
 584                         goto conf_software;
 585                 }
 586                 /* check if member changes volume at an not suppoted level */
 587                 if (member->dsp->tx_volume) {
 588                         if (dsp_debug & DEBUG_DSP_CMX)
 589                                 printk(KERN_DEBUG
 590                                        "%s dsp %s cannot form a conf, because "
 591                                        "tx_volume is changed\n",
 592                                        __func__, member->dsp->name);
 593                         goto conf_software;
 594                 }
 595                 if (member->dsp->rx_volume) {
 596                         if (dsp_debug & DEBUG_DSP_CMX)
 597                                 printk(KERN_DEBUG
 598                                        "%s dsp %s cannot form a conf, because "
 599                                        "rx_volume is changed\n",
 600                                        __func__, member->dsp->name);
 601                         goto conf_software;
 602                 }
 603                 /* check if tx-data turned on */
 604                 if (member->dsp->tx_data) {
 605                         if (dsp_debug & DEBUG_DSP_CMX)
 606                                 printk(KERN_DEBUG
 607                                        "%s dsp %s tx_data is turned on\n",
 608                                        __func__, member->dsp->name);
 609                         tx_data = 1;
 610                 }
 611                 /* check if pipeline exists */
 612                 if (member->dsp->pipeline.inuse) {
 613                         if (dsp_debug & DEBUG_DSP_CMX)
 614                                 printk(KERN_DEBUG
 615                                        "%s dsp %s cannot form a conf, because "
 616                                        "pipeline exists\n", __func__,
 617                                        member->dsp->name);
 618                         goto conf_software;
 619                 }
 620                 /* check if encryption is enabled */
 621                 if (member->dsp->bf_enable) {
 622                         if (dsp_debug & DEBUG_DSP_CMX)
 623                                 printk(KERN_DEBUG "%s dsp %s cannot form a "
 624                                        "conf, because encryption is enabled\n",
 625                                        __func__, member->dsp->name);
 626                         goto conf_software;
 627                 }
 628                 /* check if member is on a card with PCM support */
 629                 if (member->dsp->features.pcm_id < 0) {
 630                         if (dsp_debug & DEBUG_DSP_CMX)
 631                                 printk(KERN_DEBUG
 632                                        "%s dsp %s cannot form a conf, because "
 633                                        "dsp has no PCM bus\n",
 634                                        __func__, member->dsp->name);
 635                         goto conf_software;
 636                 }
 637                 /* check if relations are on the same PCM bus */
 638                 if (member->dsp->features.pcm_id != same_pcm) {
 639                         if (dsp_debug & DEBUG_DSP_CMX)
 640                                 printk(KERN_DEBUG
 641                                        "%s dsp %s cannot form a conf, because "
 642                                        "dsp is on a different PCM bus than the "
 643                                        "first dsp\n",
 644                                        __func__, member->dsp->name);
 645                         goto conf_software;
 646                 }
 647                 /* determine if members are on the same hfc chip */
 648                 if (same_hfc != member->dsp->features.hfc_id)
 649                         same_hfc = -1;
 650                 /* if there are members already in a conference */
 651                 if (current_conf < 0 && member->dsp->hfc_conf >= 0)
 652                         current_conf = member->dsp->hfc_conf;
 653                 /* if any member is not in a conference */
 654                 if (member->dsp->hfc_conf < 0)
 655                         all_conf = 0;
 656 
 657                 memb++;
 658         }
 659 
 660         /* if no member, this is an error */
 661         if (memb < 1)
 662                 return;
 663 
 664         /* one member */
 665         if (memb == 1) {
 666                 if (dsp_debug & DEBUG_DSP_CMX)
 667                         printk(KERN_DEBUG
 668                                "%s conf %d cannot form a HW conference, "
 669                                "because dsp is alone\n", __func__, conf->id);
 670                 conf->hardware = 0;
 671                 conf->software = 0;
 672                 member = list_entry(conf->mlist.next, struct dsp_conf_member,
 673                                     list);
 674                 dsp = member->dsp;
 675                 goto one_member;
 676         }
 677 
 678         /*
 679          * ok, now we are sure that all members are on the same pcm.
 680          * now we will see if we have only two members, so we can do
 681          * crossconnections, which don't have any limitations.
 682          */
 683 
 684         /* if we have only two members */
 685         if (memb == 2) {
 686                 member = list_entry(conf->mlist.next, struct dsp_conf_member,
 687                                     list);
 688                 nextm = list_entry(member->list.next, struct dsp_conf_member,
 689                                    list);
 690                 /* remove HFC conference if enabled */
 691                 if (member->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__, member->dsp->name,
 697                                        member->dsp->hfc_conf);
 698                         dsp_cmx_hw_message(member->dsp,
 699                                            MISDN_CTRL_HFC_CONF_SPLIT, 0, 0, 0, 0);
 700                         member->dsp->hfc_conf = -1;
 701                 }
 702                 if (nextm->dsp->hfc_conf >= 0) {
 703                         if (dsp_debug & DEBUG_DSP_CMX)
 704                                 printk(KERN_DEBUG
 705                                        "%s removing %s from HFC conf %d because "
 706                                        "two parties require only a PCM slot\n",
 707                                        __func__, nextm->dsp->name,
 708                                        nextm->dsp->hfc_conf);
 709                         dsp_cmx_hw_message(nextm->dsp,
 710                                            MISDN_CTRL_HFC_CONF_SPLIT, 0, 0, 0, 0);
 711                         nextm->dsp->hfc_conf = -1;
 712                 }
 713                 /* if members have two banks (and not on the same chip) */
 714                 if (member->dsp->features.pcm_banks > 1 &&
 715                     nextm->dsp->features.pcm_banks > 1 &&
 716                     member->dsp->features.hfc_id !=
 717                     nextm->dsp->features.hfc_id) {
 718                         /* if both members have same slots with crossed banks */
 719                         if (member->dsp->pcm_slot_tx >= 0 &&
 720                             member->dsp->pcm_slot_rx >= 0 &&
 721                             nextm->dsp->pcm_slot_tx >= 0 &&
 722                             nextm->dsp->pcm_slot_rx >= 0 &&
 723                             nextm->dsp->pcm_slot_tx ==
 724                             member->dsp->pcm_slot_rx &&
 725                             nextm->dsp->pcm_slot_rx ==
 726                             member->dsp->pcm_slot_tx &&
 727                             nextm->dsp->pcm_slot_tx ==
 728                             member->dsp->pcm_slot_tx &&
 729                             member->dsp->pcm_bank_tx !=
 730                             member->dsp->pcm_bank_rx &&
 731                             nextm->dsp->pcm_bank_tx !=
 732                             nextm->dsp->pcm_bank_rx) {
 733                                 /* all members have same slot */
 734                                 if (dsp_debug & DEBUG_DSP_CMX)
 735                                         printk(KERN_DEBUG
 736                                                "%s dsp %s & %s stay joined on "
 737                                                "PCM slot %d bank %d (TX) bank %d "
 738                                                "(RX) (on different chips)\n",
 739                                                __func__,
 740                                                member->dsp->name,
 741                                                nextm->dsp->name,
 742                                                member->dsp->pcm_slot_tx,
 743                                                member->dsp->pcm_bank_tx,
 744                                                member->dsp->pcm_bank_rx);
 745                                 conf->hardware = 1;
 746                                 conf->software = tx_data;
 747                                 return;
 748                         }
 749                         /* find a new slot */
 750                         memset(freeslots, 1, sizeof(freeslots));
 751                         list_for_each_entry(dsp, &dsp_ilist, list) {
 752                                 if (dsp != member->dsp &&
 753                                     dsp != nextm->dsp &&
 754                                     member->dsp->features.pcm_id ==
 755                                     dsp->features.pcm_id) {
 756                                         if (dsp->pcm_slot_rx >= 0 &&
 757                                             dsp->pcm_slot_rx <
 758                                             sizeof(freeslots))
 759                                                 freeslots[dsp->pcm_slot_rx] = 0;
 760                                         if (dsp->pcm_slot_tx >= 0 &&
 761                                             dsp->pcm_slot_tx <
 762                                             sizeof(freeslots))
 763                                                 freeslots[dsp->pcm_slot_tx] = 0;
 764                                 }
 765                         }
 766                         i = 0;
 767                         ii = member->dsp->features.pcm_slots;
 768                         while (i < ii) {
 769                                 if (freeslots[i])
 770                                         break;
 771                                 i++;
 772                         }
 773                         if (i == ii) {
 774                                 if (dsp_debug & DEBUG_DSP_CMX)
 775                                         printk(KERN_DEBUG
 776                                                "%s no slot available for "
 777                                                "%s & %s\n", __func__,
 778                                                member->dsp->name,
 779                                                nextm->dsp->name);
 780                                 /* no more slots available */
 781                                 goto conf_software;
 782                         }
 783                         /* assign free slot */
 784                         member->dsp->pcm_slot_tx = i;
 785                         member->dsp->pcm_slot_rx = i;
 786                         nextm->dsp->pcm_slot_tx = i;
 787                         nextm->dsp->pcm_slot_rx = i;
 788                         member->dsp->pcm_bank_rx = 0;
 789                         member->dsp->pcm_bank_tx = 1;
 790                         nextm->dsp->pcm_bank_rx = 1;
 791                         nextm->dsp->pcm_bank_tx = 0;
 792                         if (dsp_debug & DEBUG_DSP_CMX)
 793                                 printk(KERN_DEBUG
 794                                        "%s adding %s & %s to new PCM slot %d "
 795                                        "(TX and RX on different chips) because "
 796                                        "both members have not same slots\n",
 797                                        __func__,
 798                                        member->dsp->name,
 799                                        nextm->dsp->name,
 800                                        member->dsp->pcm_slot_tx);
 801                         dsp_cmx_hw_message(member->dsp, MISDN_CTRL_HFC_PCM_CONN,
 802                                            member->dsp->pcm_slot_tx, member->dsp->pcm_bank_tx,
 803                                            member->dsp->pcm_slot_rx, member->dsp->pcm_bank_rx);
 804                         dsp_cmx_hw_message(nextm->dsp, MISDN_CTRL_HFC_PCM_CONN,
 805                                            nextm->dsp->pcm_slot_tx, nextm->dsp->pcm_bank_tx,
 806                                            nextm->dsp->pcm_slot_rx, nextm->dsp->pcm_bank_rx);
 807                         conf->hardware = 1;
 808                         conf->software = tx_data;
 809                         return;
 810                         /* if members have one bank (or on the same chip) */
 811                 } else {
 812                         /* if both members have different crossed slots */
 813                         if (member->dsp->pcm_slot_tx >= 0 &&
 814                             member->dsp->pcm_slot_rx >= 0 &&
 815                             nextm->dsp->pcm_slot_tx >= 0 &&
 816                             nextm->dsp->pcm_slot_rx >= 0 &&
 817                             nextm->dsp->pcm_slot_tx ==
 818                             member->dsp->pcm_slot_rx &&
 819                             nextm->dsp->pcm_slot_rx ==
 820                             member->dsp->pcm_slot_tx &&
 821                             member->dsp->pcm_slot_tx !=
 822                             member->dsp->pcm_slot_rx &&
 823                             member->dsp->pcm_bank_tx == 0 &&
 824                             member->dsp->pcm_bank_rx == 0 &&
 825                             nextm->dsp->pcm_bank_tx == 0 &&
 826                             nextm->dsp->pcm_bank_rx == 0) {
 827                                 /* all members have same slot */
 828                                 if (dsp_debug & DEBUG_DSP_CMX)
 829                                         printk(KERN_DEBUG
 830                                                "%s dsp %s & %s stay joined on PCM "
 831                                                "slot %d (TX) %d (RX) on same chip "
 832                                                "or one bank PCM)\n", __func__,
 833                                                member->dsp->name,
 834                                                nextm->dsp->name,
 835                                                member->dsp->pcm_slot_tx,
 836                                                member->dsp->pcm_slot_rx);
 837                                 conf->hardware = 1;
 838                                 conf->software = tx_data;
 839                                 return;
 840                         }
 841                         /* find two new slot */
 842                         memset(freeslots, 1, sizeof(freeslots));
 843                         list_for_each_entry(dsp, &dsp_ilist, list) {
 844                                 if (dsp != member->dsp &&
 845                                     dsp != nextm->dsp &&
 846                                     member->dsp->features.pcm_id ==
 847                                     dsp->features.pcm_id) {
 848                                         if (dsp->pcm_slot_rx >= 0 &&
 849                                             dsp->pcm_slot_rx <
 850                                             sizeof(freeslots))
 851                                                 freeslots[dsp->pcm_slot_rx] = 0;
 852                                         if (dsp->pcm_slot_tx >= 0 &&
 853                                             dsp->pcm_slot_tx <
 854                                             sizeof(freeslots))
 855                                                 freeslots[dsp->pcm_slot_tx] = 0;
 856                                 }
 857                         }
 858                         i1 = 0;
 859                         ii = member->dsp->features.pcm_slots;
 860                         while (i1 < ii) {
 861                                 if (freeslots[i1])
 862                                         break;
 863                                 i1++;
 864                         }
 865                         if (i1 == ii) {
 866                                 if (dsp_debug & DEBUG_DSP_CMX)
 867                                         printk(KERN_DEBUG
 868                                                "%s no slot available "
 869                                                "for %s & %s\n", __func__,
 870                                                member->dsp->name,
 871                                                nextm->dsp->name);
 872                                 /* no more slots available */
 873                                 goto conf_software;
 874                         }
 875                         i2 = i1 + 1;
 876                         while (i2 < ii) {
 877                                 if (freeslots[i2])
 878                                         break;
 879                                 i2++;
 880                         }
 881                         if (i2 == ii) {
 882                                 if (dsp_debug & DEBUG_DSP_CMX)
 883                                         printk(KERN_DEBUG
 884                                                "%s no slot available "
 885                                                "for %s & %s\n",
 886                                                __func__,
 887                                                member->dsp->name,
 888                                                nextm->dsp->name);
 889                                 /* no more slots available */
 890                                 goto conf_software;
 891                         }
 892                         /* assign free slots */
 893                         member->dsp->pcm_slot_tx = i1;
 894                         member->dsp->pcm_slot_rx = i2;
 895                         nextm->dsp->pcm_slot_tx = i2;
 896                         nextm->dsp->pcm_slot_rx = i1;
 897                         member->dsp->pcm_bank_rx = 0;
 898                         member->dsp->pcm_bank_tx = 0;
 899                         nextm->dsp->pcm_bank_rx = 0;
 900                         nextm->dsp->pcm_bank_tx = 0;
 901                         if (dsp_debug & DEBUG_DSP_CMX)
 902                                 printk(KERN_DEBUG
 903                                        "%s adding %s & %s to new PCM slot %d "
 904                                        "(TX) %d (RX) on same chip or one bank "
 905                                        "PCM, because both members have not "
 906                                        "crossed slots\n", __func__,
 907                                        member->dsp->name,
 908                                        nextm->dsp->name,
 909                                        member->dsp->pcm_slot_tx,
 910                                        member->dsp->pcm_slot_rx);
 911                         dsp_cmx_hw_message(member->dsp, MISDN_CTRL_HFC_PCM_CONN,
 912                                            member->dsp->pcm_slot_tx, member->dsp->pcm_bank_tx,
 913                                            member->dsp->pcm_slot_rx, member->dsp->pcm_bank_rx);
 914                         dsp_cmx_hw_message(nextm->dsp, MISDN_CTRL_HFC_PCM_CONN,
 915                                            nextm->dsp->pcm_slot_tx, nextm->dsp->pcm_bank_tx,
 916                                            nextm->dsp->pcm_slot_rx, nextm->dsp->pcm_bank_rx);
 917                         conf->hardware = 1;
 918                         conf->software = tx_data;
 919                         return;
 920                 }
 921         }
 922 
 923         /*
 924          * if we have more than two, we may check if we have a conference
 925          * unit available on the chip. also all members must be on the same
 926          */
 927 
 928         /* if not the same HFC chip */
 929         if (same_hfc < 0) {
 930                 if (dsp_debug & DEBUG_DSP_CMX)
 931                         printk(KERN_DEBUG
 932                                "%s conference %d cannot be formed, because "
 933                                "members are on different chips or not "
 934                                "on HFC chip\n",
 935                                __func__, conf->id);
 936                 goto conf_software;
 937         }
 938 
 939         /* for more than two members.. */
 940 
 941         /* if all members already have the same conference */
 942         if (all_conf) {
 943                 conf->hardware = 1;
 944                 conf->software = tx_data;
 945                 return;
 946         }
 947 
 948         /*
 949          * if there is an existing conference, but not all members have joined
 950          */
 951         if (current_conf >= 0) {
 952         join_members:
 953                 list_for_each_entry(member, &conf->mlist, list) {
 954                         /* if no conference engine on our chip, change to
 955                          * software */
 956                         if (!member->dsp->features.hfc_conf)
 957                                 goto conf_software;
 958                         /* in case of hdlc, change to software */
 959                         if (member->dsp->hdlc)
 960                                 goto conf_software;
 961                         /* join to current conference */
 962                         if (member->dsp->hfc_conf == current_conf)
 963                                 continue;
 964                         /* get a free timeslot first */
 965                         memset(freeslots, 1, sizeof(freeslots));
 966                         list_for_each_entry(dsp, &dsp_ilist, list) {
 967                                 /*
 968                                  * not checking current member, because
 969                                  * slot will be overwritten.
 970                                  */
 971                                 if (
 972                                         dsp != member->dsp &&
 973                                         /* dsp must be on the same PCM */
 974                                         member->dsp->features.pcm_id ==
 975                                         dsp->features.pcm_id) {
 976                                         /* dsp must be on a slot */
 977                                         if (dsp->pcm_slot_tx >= 0 &&
 978                                             dsp->pcm_slot_tx <
 979                                             sizeof(freeslots))
 980                                                 freeslots[dsp->pcm_slot_tx] = 0;
 981                                         if (dsp->pcm_slot_rx >= 0 &&
 982                                             dsp->pcm_slot_rx <
 983                                             sizeof(freeslots))
 984                                                 freeslots[dsp->pcm_slot_rx] = 0;
 985                                 }
 986                         }
 987                         i = 0;
 988                         ii = member->dsp->features.pcm_slots;
 989                         while (i < ii) {
 990                                 if (freeslots[i])
 991                                         break;
 992                                 i++;
 993                         }
 994                         if (i == ii) {
 995                                 /* no more slots available */
 996                                 if (dsp_debug & DEBUG_DSP_CMX)
 997                                         printk(KERN_DEBUG
 998                                                "%s conference %d cannot be formed,"
 999                                                " 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 }

/* [<][>][^][v][top][bottom][index][help] */