linux/drivers/isdn/mISDN/dsp_cmx.c
<<
>>
Prefs
   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
 144static inline int
 145count_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 */
 158void
 159dsp_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 */
 197static struct dsp_conf *
 198dsp_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 */
 219static int
 220dsp_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 */
 264int
 265dsp_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 */
 308static 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 */
 336int
 337dsp_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 */
 360static void
 361dsp_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 */
 383void
 384dsp_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 */
1063int
1064dsp_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
1159int delaycount;
1160static void
1161showdelay(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 */
1181void
1182dsp_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 */
1308static void
1309dsp_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
1574send_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
1621static u32      jittercount; /* counter for jitter check */
1622struct timer_list dsp_spl_tl;
1623unsigned long   dsp_spl_jiffies; /* calculate the next time to fire */
1624static u16      dsp_count; /* last sample count */
1625static int      dsp_count_valid; /* if we have last sample count */
1626
1627void
1628dsp_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 */
1859void
1860dsp_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 */
1915void
1916dsp_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}
1961