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