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/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_meber 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);
 401one_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 whithout 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);
 525conf_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 = 0;
 746                                conf->software = 1;
 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 = 0;
 838                                conf->software = 1;
 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                return;
 944
 945        /*
 946         * if there is an existing conference, but not all members have joined
 947         */
 948        if (current_conf >= 0) {
 949join_members:
 950                list_for_each_entry(member, &conf->mlist, list) {
 951                        /* if no conference engine on our chip, change to
 952                         * software */
 953                        if (!member->dsp->features.hfc_conf)
 954                                goto conf_software;
 955                        /* in case of hdlc, change to software */
 956                        if (member->dsp->hdlc)
 957                                goto conf_software;
 958                        /* join to current conference */
 959                        if (member->dsp->hfc_conf == current_conf)
 960                                continue;
 961                        /* get a free timeslot first */
 962                        memset(freeslots, 1, sizeof(freeslots));
 963                        list_for_each_entry(dsp, &dsp_ilist, list) {
 964                                /*
 965                                 * not checking current member, because
 966                                 * slot will be overwritten.
 967                                 */
 968                                if (
 969                                    dsp != member->dsp &&
 970                                /* dsp must be on the same PCM */
 971                                    member->dsp->features.pcm_id ==
 972                                    dsp->features.pcm_id) {
 973                                        /* dsp must be on a slot */
 974                                        if (dsp->pcm_slot_tx >= 0 &&
 975                                            dsp->pcm_slot_tx <
 976                                            sizeof(freeslots))
 977                                                freeslots[dsp->pcm_slot_tx] = 0;
 978                                        if (dsp->pcm_slot_rx >= 0 &&
 979                                            dsp->pcm_slot_rx <
 980                                            sizeof(freeslots))
 981                                                freeslots[dsp->pcm_slot_rx] = 0;
 982                                }
 983                        }
 984                        i = 0;
 985                        ii = member->dsp->features.pcm_slots;
 986                        while (i < ii) {
 987                                if (freeslots[i])
 988                                        break;
 989                                i++;
 990                        }
 991                        if (i == ii) {
 992                                /* no more slots available */
 993                                if (dsp_debug & DEBUG_DSP_CMX)
 994                                        printk(KERN_DEBUG
 995                                            "%s conference %d cannot be formed,"
 996                                            " because no slot free\n",
 997                                            __func__, conf->id);
 998                                goto conf_software;
 999                        }
1000                        if (dsp_debug & DEBUG_DSP_CMX)
1001                                printk(KERN_DEBUG
1002                                    "%s changing dsp %s to HW conference "
1003                                    "%d slot %d\n", __func__,
1004                                    member->dsp->name, current_conf, i);
1005                        /* assign free slot & set PCM & join conf */
1006                        member->dsp->pcm_slot_tx = i;
1007                        member->dsp->pcm_slot_rx = i;
1008                        member->dsp->pcm_bank_tx = 2; /* loop */
1009                        member->dsp->pcm_bank_rx = 2;
1010                        member->dsp->hfc_conf = current_conf;
1011                        dsp_cmx_hw_message(member->dsp, MISDN_CTRL_HFC_PCM_CONN,
1012                            i, 2, i, 2);
1013                        dsp_cmx_hw_message(member->dsp,
1014                            MISDN_CTRL_HFC_CONF_JOIN, current_conf, 0, 0, 0);
1015                }
1016                return;
1017        }
1018
1019        /*
1020         * no member is in a conference yet, so we find a free one
1021         */
1022        memset(freeunits, 1, sizeof(freeunits));
1023        list_for_each_entry(dsp, &dsp_ilist, list) {
1024                /* dsp must be on the same chip */
1025                if (dsp->features.hfc_id == same_hfc &&
1026                    /* dsp must have joined a HW conference */
1027                    dsp->hfc_conf >= 0 &&
1028                    /* slot must be within range */
1029                    dsp->hfc_conf < 8)
1030                        freeunits[dsp->hfc_conf] = 0;
1031        }
1032        i = 0;
1033        ii = 8;
1034        while (i < ii) {
1035                if (freeunits[i])
1036                        break;
1037                i++;
1038        }
1039        if (i == ii) {
1040                /* no more conferences available */
1041                if (dsp_debug & DEBUG_DSP_CMX)
1042                        printk(KERN_DEBUG
1043                            "%s conference %d cannot be formed, because "
1044                            "no conference number free\n",
1045                            __func__, conf->id);
1046                goto conf_software;
1047        }
1048        /* join all members */
1049        current_conf = i;
1050        goto join_members;
1051}
1052
1053
1054/*
1055 * conf_id != 0: join or change conference
1056 * conf_id == 0: split from conference if not already
1057 */
1058int
1059dsp_cmx_conf(struct dsp *dsp, u32 conf_id)
1060{
1061        int err;
1062        struct dsp_conf *conf;
1063        struct dsp_conf_member  *member;
1064
1065        /* if conference doesn't change */
1066        if (dsp->conf_id == conf_id)
1067                return 0;
1068
1069        /* first remove us from current conf */
1070        if (dsp->conf_id) {
1071                if (dsp_debug & DEBUG_DSP_CMX)
1072                        printk(KERN_DEBUG "removing us from conference %d\n",
1073                                dsp->conf->id);
1074                /* remove us from conf */
1075                conf = dsp->conf;
1076                err = dsp_cmx_del_conf_member(dsp);
1077                if (err)
1078                        return err;
1079                dsp->conf_id = 0;
1080
1081                /* update hardware */
1082                dsp_cmx_hardware(NULL, dsp);
1083
1084                /* conf now empty? */
1085                if (list_empty(&conf->mlist)) {
1086                        if (dsp_debug & DEBUG_DSP_CMX)
1087                                printk(KERN_DEBUG
1088                                    "conference is empty, so we remove it.\n");
1089                        err = dsp_cmx_del_conf(conf);
1090                        if (err)
1091                                return err;
1092                } else {
1093                        /* update members left on conf */
1094                        dsp_cmx_hardware(conf, NULL);
1095                }
1096        }
1097
1098        /* if split */
1099        if (!conf_id)
1100                return 0;
1101
1102        /* now add us to conf */
1103        if (dsp_debug & DEBUG_DSP_CMX)
1104                printk(KERN_DEBUG "searching conference %d\n",
1105                        conf_id);
1106        conf = dsp_cmx_search_conf(conf_id);
1107        if (!conf) {
1108                if (dsp_debug & DEBUG_DSP_CMX)
1109                        printk(KERN_DEBUG
1110                            "conference doesn't exist yet, creating.\n");
1111                /* the conference doesn't exist, so we create */
1112                conf = dsp_cmx_new_conf(conf_id);
1113                if (!conf)
1114                        return -EINVAL;
1115        } else if (!list_empty(&conf->mlist)) {
1116                member = list_entry(conf->mlist.next, struct dsp_conf_member,
1117                        list);
1118                if (dsp->hdlc && !member->dsp->hdlc) {
1119                        if (dsp_debug & DEBUG_DSP_CMX)
1120                                printk(KERN_DEBUG
1121                                    "cannot join transparent conference.\n");
1122                        return -EINVAL;
1123                }
1124                if (!dsp->hdlc && member->dsp->hdlc) {
1125                        if (dsp_debug & DEBUG_DSP_CMX)
1126                                printk(KERN_DEBUG
1127                                    "cannot join hdlc conference.\n");
1128                        return -EINVAL;
1129                }
1130        }
1131        /* add conference member */
1132        err = dsp_cmx_add_conf_member(dsp, conf);
1133        if (err)
1134                return err;
1135        dsp->conf_id = conf_id;
1136
1137        /* if we are alone, we do nothing! */
1138        if (list_empty(&conf->mlist)) {
1139                if (dsp_debug & DEBUG_DSP_CMX)
1140                        printk(KERN_DEBUG
1141                            "we are alone in this conference, so exit.\n");
1142                /* update hardware */
1143                dsp_cmx_hardware(NULL, dsp);
1144                return 0;
1145        }
1146
1147        /* update members on conf */
1148        dsp_cmx_hardware(conf, NULL);
1149
1150        return 0;
1151}
1152
1153#ifdef CMX_DELAY_DEBUG
1154int delaycount;
1155static void
1156showdelay(struct dsp *dsp, int samples, int delay)
1157{
1158        char bar[] = "--------------------------------------------------|";
1159        int sdelay;
1160
1161        delaycount += samples;
1162        if (delaycount < 8000)
1163                return;
1164        delaycount = 0;
1165
1166        sdelay = delay * 50 / (dsp_poll << 2);
1167
1168        printk(KERN_DEBUG "DELAY (%s) %3d >%s\n", dsp->name, delay,
1169                sdelay > 50 ? "..." : bar + 50 - sdelay);
1170}
1171#endif
1172
1173/*
1174 * audio data is received from card
1175 */
1176void
1177dsp_cmx_receive(struct dsp *dsp, struct sk_buff *skb)
1178{
1179        u8 *d, *p;
1180        int len = skb->len;
1181        struct mISDNhead *hh = mISDN_HEAD_P(skb);
1182        int w, i, ii;
1183
1184        /* check if we have sompen */
1185        if (len < 1)
1186                return;
1187
1188        /* half of the buffer should be larger than maximum packet size */
1189        if (len >= CMX_BUFF_HALF) {
1190                printk(KERN_ERR
1191                    "%s line %d: packet from card is too large (%d bytes). "
1192                    "please make card send smaller packets OR increase "
1193                    "CMX_BUFF_SIZE\n", __FILE__, __LINE__, len);
1194                return;
1195        }
1196
1197        /*
1198         * initialize pointers if not already -
1199         * also add delay if requested by PH_SIGNAL
1200         */
1201        if (dsp->rx_init) {
1202                dsp->rx_init = 0;
1203                if (dsp->features.unordered) {
1204                        dsp->rx_R = (hh->id & CMX_BUFF_MASK);
1205                        if (dsp->cmx_delay)
1206                                dsp->rx_W = (dsp->rx_R + dsp->cmx_delay)
1207                                        & CMX_BUFF_MASK;
1208                        else
1209                                dsp->rx_W = (dsp->rx_R + (dsp_poll >> 1))
1210                                        & CMX_BUFF_MASK;
1211                } else {
1212                        dsp->rx_R = 0;
1213                        if (dsp->cmx_delay)
1214                                dsp->rx_W = dsp->cmx_delay;
1215                        else
1216                                dsp->rx_W = dsp_poll >> 1;
1217                }
1218        }
1219        /* if frame contains time code, write directly */
1220        if (dsp->features.unordered) {
1221                dsp->rx_W = (hh->id & CMX_BUFF_MASK);
1222                /* printk(KERN_DEBUG "%s %08x\n", dsp->name, hh->id); */
1223        }
1224        /*
1225         * if we underrun (or maybe overrun),
1226         * we set our new read pointer, and write silence to buffer
1227         */
1228        if (((dsp->rx_W-dsp->rx_R) & CMX_BUFF_MASK) >= CMX_BUFF_HALF) {
1229                if (dsp_debug & DEBUG_DSP_CLOCK)
1230                        printk(KERN_DEBUG
1231                            "cmx_receive(dsp=%lx): UNDERRUN (or overrun the "
1232                            "maximum delay), adjusting read pointer! "
1233                            "(inst %s)\n", (u_long)dsp, dsp->name);
1234                /* flush rx buffer and set delay to dsp_poll / 2 */
1235                if (dsp->features.unordered) {
1236                        dsp->rx_R = (hh->id & CMX_BUFF_MASK);
1237                        if (dsp->cmx_delay)
1238                                dsp->rx_W = (dsp->rx_R + dsp->cmx_delay)
1239                                        & CMX_BUFF_MASK;
1240                                dsp->rx_W = (dsp->rx_R + (dsp_poll >> 1))
1241                                        & CMX_BUFF_MASK;
1242                } else {
1243                        dsp->rx_R = 0;
1244                        if (dsp->cmx_delay)
1245                                dsp->rx_W = dsp->cmx_delay;
1246                        else
1247                                dsp->rx_W = dsp_poll >> 1;
1248                }
1249                memset(dsp->rx_buff, dsp_silence, sizeof(dsp->rx_buff));
1250        }
1251        /* if we have reached double delay, jump back to middle */
1252        if (dsp->cmx_delay)
1253                if (((dsp->rx_W - dsp->rx_R) & CMX_BUFF_MASK) >=
1254                    (dsp->cmx_delay << 1)) {
1255                        if (dsp_debug & DEBUG_DSP_CLOCK)
1256                                printk(KERN_DEBUG
1257                                    "cmx_receive(dsp=%lx): OVERRUN (because "
1258                                    "twice the delay is reached), adjusting "
1259                                    "read pointer! (inst %s)\n",
1260                                    (u_long)dsp, dsp->name);
1261                /* flush buffer */
1262                if (dsp->features.unordered) {
1263                        dsp->rx_R = (hh->id & CMX_BUFF_MASK);
1264                        dsp->rx_W = (dsp->rx_R + dsp->cmx_delay)
1265                                & CMX_BUFF_MASK;
1266                } else {
1267                        dsp->rx_R = 0;
1268                        dsp->rx_W = dsp->cmx_delay;
1269                }
1270                memset(dsp->rx_buff, dsp_silence, sizeof(dsp->rx_buff));
1271        }
1272
1273        /* show where to write */
1274#ifdef CMX_DEBUG
1275        printk(KERN_DEBUG
1276            "cmx_receive(dsp=%lx): rx_R(dsp)=%05x rx_W(dsp)=%05x len=%d %s\n",
1277            (u_long)dsp, dsp->rx_R, dsp->rx_W, len, dsp->name);
1278#endif
1279
1280        /* write data into rx_buffer */
1281        p = skb->data;
1282        d = dsp->rx_buff;
1283        w = dsp->rx_W;
1284        i = 0;
1285        ii = len;
1286        while (i < ii) {
1287                d[w++ & CMX_BUFF_MASK] = *p++;
1288                i++;
1289        }
1290
1291        /* increase write-pointer */
1292        dsp->rx_W = ((dsp->rx_W+len) & CMX_BUFF_MASK);
1293#ifdef CMX_DELAY_DEBUG
1294        showdelay(dsp, len, (dsp->rx_W-dsp->rx_R) & CMX_BUFF_MASK);
1295#endif
1296}
1297
1298
1299/*
1300 * send (mixed) audio data to card and control jitter
1301 */
1302static void
1303dsp_cmx_send_member(struct dsp *dsp, int len, s32 *c, int members)
1304{
1305        struct dsp_conf *conf = dsp->conf;
1306        struct dsp *member, *other;
1307        register s32 sample;
1308        u8 *d, *p, *q, *o_q;
1309        struct sk_buff *nskb, *txskb;
1310        int r, rr, t, tt, o_r, o_rr;
1311        int preload = 0;
1312        struct mISDNhead *hh, *thh;
1313        int tx_data_only = 0;
1314
1315        /* don't process if: */
1316        if (!dsp->b_active) { /* if not active */
1317                dsp->last_tx = 0;
1318                return;
1319        }
1320        if (((dsp->conf && dsp->conf->hardware) || /* hardware conf */
1321            dsp->echo.hardware) && /* OR hardware echo */
1322            dsp->tx_R == dsp->tx_W && /* AND no tx-data */
1323            !(dsp->tone.tone && dsp->tone.software)) { /* AND not soft tones */
1324                if (!dsp->tx_data) { /* no tx_data for user space required */
1325                        dsp->last_tx = 0;
1326                        return;
1327                }
1328                if (dsp->conf && dsp->conf->software && dsp->conf->hardware)
1329                        tx_data_only = 1;
1330                if (dsp->conf->software && dsp->echo.hardware)
1331                        tx_data_only = 1;
1332        }
1333
1334#ifdef CMX_DEBUG
1335        printk(KERN_DEBUG
1336            "SEND members=%d dsp=%s, conf=%p, rx_R=%05x rx_W=%05x\n",
1337            members, dsp->name, conf, dsp->rx_R, dsp->rx_W);
1338#endif
1339
1340        /* preload if we have delay set */
1341        if (dsp->cmx_delay && !dsp->last_tx) {
1342                preload = len;
1343                if (preload < 128)
1344                        preload = 128;
1345        }
1346
1347        /* PREPARE RESULT */
1348        nskb = mI_alloc_skb(len + preload, GFP_ATOMIC);
1349        if (!nskb) {
1350                printk(KERN_ERR
1351                    "FATAL ERROR in mISDN_dsp.o: cannot alloc %d bytes\n",
1352                    len + preload);
1353                return;
1354        }
1355        hh = mISDN_HEAD_P(nskb);
1356        hh->prim = PH_DATA_REQ;
1357        hh->id = 0;
1358        dsp->last_tx = 1;
1359
1360        /* set pointers, indexes and stuff */
1361        member = dsp;
1362        p = dsp->tx_buff; /* transmit data */
1363        q = dsp->rx_buff; /* received data */
1364        d = skb_put(nskb, preload + len); /* result */
1365        t = dsp->tx_R; /* tx-pointers */
1366        tt = dsp->tx_W;
1367        r = dsp->rx_R; /* rx-pointers */
1368        rr = (r + len) & CMX_BUFF_MASK;
1369
1370        /* preload with silence, if required */
1371        if (preload) {
1372                memset(d, dsp_silence, preload);
1373                d += preload;
1374        }
1375
1376        /* PROCESS TONES/TX-DATA ONLY */
1377        if (dsp->tone.tone && dsp->tone.software) {
1378                /* -> copy tone */
1379                dsp_tone_copy(dsp, d, len);
1380                dsp->tx_R = 0; /* clear tx buffer */
1381                dsp->tx_W = 0;
1382                goto send_packet;
1383        }
1384        /* if we have tx-data but do not use mixing */
1385        if (!dsp->tx_mix && t != tt) {
1386                /* -> send tx-data and continue when not enough */
1387#ifdef CMX_TX_DEBUG
1388        sprintf(debugbuf, "TX sending (%04x-%04x)%p: ", t, tt, p);
1389#endif
1390                while (r != rr && t != tt) {
1391#ifdef CMX_TX_DEBUG
1392                        if (strlen(debugbuf) < 48)
1393                                sprintf(debugbuf+strlen(debugbuf), " %02x",
1394                                    p[t]);
1395#endif
1396                        *d++ = p[t]; /* write tx_buff */
1397                        t = (t+1) & CMX_BUFF_MASK;
1398                        r = (r+1) & CMX_BUFF_MASK;
1399                }
1400                if (r == rr) {
1401                        dsp->tx_R = t;
1402#ifdef CMX_TX_DEBUG
1403        printk(KERN_DEBUG "%s\n", debugbuf);
1404#endif
1405                        goto send_packet;
1406                }
1407        }
1408#ifdef CMX_TX_DEBUG
1409        printk(KERN_DEBUG "%s\n", debugbuf);
1410#endif
1411
1412        /* PROCESS DATA (one member / no conf) */
1413        if (!conf || members <= 1) {
1414                /* -> if echo is NOT enabled */
1415                if (!dsp->echo.software) {
1416                        /* -> send tx-data if available or use 0-volume */
1417                        while (r != rr && t != tt) {
1418                                *d++ = p[t]; /* write tx_buff */
1419                                t = (t+1) & CMX_BUFF_MASK;
1420                                r = (r+1) & CMX_BUFF_MASK;
1421                        }
1422                        if (r != rr) {
1423                                if (dsp_debug & DEBUG_DSP_CLOCK)
1424                                        printk(KERN_DEBUG "%s: RX empty\n",
1425                                                __func__);
1426                                memset(d, dsp_silence, (rr-r)&CMX_BUFF_MASK);
1427                        }
1428                /* -> if echo is enabled */
1429                } else {
1430                        /*
1431                         * -> mix tx-data with echo if available,
1432                         * or use echo only
1433                         */
1434                        while (r != rr && t != tt) {
1435                                *d++ = dsp_audio_mix_law[(p[t]<<8)|q[r]];
1436                                t = (t+1) & CMX_BUFF_MASK;
1437                                r = (r+1) & CMX_BUFF_MASK;
1438                        }
1439                        while (r != rr) {
1440                                *d++ = q[r]; /* echo */
1441                                r = (r+1) & CMX_BUFF_MASK;
1442                        }
1443                }
1444                dsp->tx_R = t;
1445                goto send_packet;
1446        }
1447        /* PROCESS DATA (two members) */
1448#ifdef CMX_CONF_DEBUG
1449        if (0) {
1450#else
1451        if (members == 2) {
1452#endif
1453                /* "other" becomes other party */
1454                other = (list_entry(conf->mlist.next,
1455                    struct dsp_conf_member, list))->dsp;
1456                if (other == member)
1457                        other = (list_entry(conf->mlist.prev,
1458                            struct dsp_conf_member, list))->dsp;
1459                o_q = other->rx_buff; /* received data */
1460                o_rr = (other->rx_R + len) & CMX_BUFF_MASK;
1461                        /* end of rx-pointer */
1462                o_r = (o_rr - rr + r) & CMX_BUFF_MASK;
1463                        /* start rx-pointer at current read position*/
1464                /* -> if echo is NOT enabled */
1465                if (!dsp->echo.software) {
1466                        /*
1467                         * -> copy other member's rx-data,
1468                         * if tx-data is available, mix
1469                         */
1470                        while (o_r != o_rr && t != tt) {
1471                                *d++ = dsp_audio_mix_law[(p[t]<<8)|o_q[o_r]];
1472                                t = (t+1) & CMX_BUFF_MASK;
1473                                o_r = (o_r+1) & CMX_BUFF_MASK;
1474                        }
1475                        while (o_r != o_rr) {
1476                                *d++ = o_q[o_r];
1477                                o_r = (o_r+1) & CMX_BUFF_MASK;
1478                        }
1479                /* -> if echo is enabled */
1480                } else {
1481                        /*
1482                         * -> mix other member's rx-data with echo,
1483                         * if tx-data is available, mix
1484                         */
1485                        while (r != rr && t != tt) {
1486                                sample = dsp_audio_law_to_s32[p[t]] +
1487                                    dsp_audio_law_to_s32[q[r]] +
1488                                    dsp_audio_law_to_s32[o_q[o_r]];
1489                                if (sample < -32768)
1490                                        sample = -32768;
1491                                else if (sample > 32767)
1492                                        sample = 32767;
1493                                *d++ = dsp_audio_s16_to_law[sample & 0xffff];
1494                                    /* tx-data + rx_data + echo */
1495                                t = (t+1) & CMX_BUFF_MASK;
1496                                r = (r+1) & CMX_BUFF_MASK;
1497                                o_r = (o_r+1) & CMX_BUFF_MASK;
1498                        }
1499                        while (r != rr) {
1500                                *d++ = dsp_audio_mix_law[(q[r]<<8)|o_q[o_r]];
1501                                r = (r+1) & CMX_BUFF_MASK;
1502                                o_r = (o_r+1) & CMX_BUFF_MASK;
1503                        }
1504                }
1505                dsp->tx_R = t;
1506                goto send_packet;
1507        }
1508#ifdef DSP_NEVER_DEFINED
1509        }
1510#endif
1511        /* PROCESS DATA (three or more members) */
1512        /* -> if echo is NOT enabled */
1513        if (!dsp->echo.software) {
1514                /*
1515                 * -> substract rx-data from conf-data,
1516                 * if tx-data is available, mix
1517                 */
1518                while (r != rr && t != tt) {
1519                        sample = dsp_audio_law_to_s32[p[t]] + *c++ -
1520                            dsp_audio_law_to_s32[q[r]];
1521                        if (sample < -32768)
1522                                sample = -32768;
1523                        else if (sample > 32767)
1524                                sample = 32767;
1525                        *d++ = dsp_audio_s16_to_law[sample & 0xffff];
1526                            /* conf-rx+tx */
1527                        r = (r+1) & CMX_BUFF_MASK;
1528                        t = (t+1) & CMX_BUFF_MASK;
1529                }
1530                while (r != rr) {
1531                        sample = *c++ - dsp_audio_law_to_s32[q[r]];
1532                        if (sample < -32768)
1533                                sample = -32768;
1534                        else if (sample > 32767)
1535                                sample = 32767;
1536                        *d++ = dsp_audio_s16_to_law[sample & 0xffff];
1537                            /* conf-rx */
1538                        r = (r+1) & CMX_BUFF_MASK;
1539                }
1540        /* -> if echo is enabled */
1541        } else {
1542                /*
1543                 * -> encode conf-data, if tx-data
1544                 * is available, mix
1545                 */
1546                while (r != rr && t != tt) {
1547                        sample = dsp_audio_law_to_s32[p[t]] + *c++;
1548                        if (sample < -32768)
1549                                sample = -32768;
1550                        else if (sample > 32767)
1551                                sample = 32767;
1552                        *d++ = dsp_audio_s16_to_law[sample & 0xffff];
1553                            /* conf(echo)+tx */
1554                        t = (t+1) & CMX_BUFF_MASK;
1555                        r = (r+1) & CMX_BUFF_MASK;
1556                }
1557                while (r != rr) {
1558                        sample = *c++;
1559                        if (sample < -32768)
1560                                sample = -32768;
1561                        else if (sample > 32767)
1562                                sample = 32767;
1563                        *d++ = dsp_audio_s16_to_law[sample & 0xffff];
1564                            /* conf(echo) */
1565                        r = (r+1) & CMX_BUFF_MASK;
1566                }
1567        }
1568        dsp->tx_R = t;
1569        goto send_packet;
1570
1571send_packet:
1572        /*
1573         * send tx-data if enabled - don't filter,
1574         * becuase we want what we send, not what we filtered
1575         */
1576        if (dsp->tx_data) {
1577                if (tx_data_only) {
1578                        hh->prim = DL_DATA_REQ;
1579                        hh->id = 0;
1580                        /* queue and trigger */
1581                        skb_queue_tail(&dsp->sendq, nskb);
1582                        schedule_work(&dsp->workq);
1583                        /* exit because only tx_data is used */
1584                        return;
1585                } else {
1586                        txskb = mI_alloc_skb(len, GFP_ATOMIC);
1587                        if (!txskb) {
1588                                printk(KERN_ERR
1589                                    "FATAL ERROR in mISDN_dsp.o: "
1590                                    "cannot alloc %d bytes\n", len);
1591                        } else {
1592                                thh = mISDN_HEAD_P(txskb);
1593                                thh->prim = DL_DATA_REQ;
1594                                thh->id = 0;
1595                                memcpy(skb_put(txskb, len), nskb->data+preload,
1596                                        len);
1597                                /* queue (trigger later) */
1598                                skb_queue_tail(&dsp->sendq, txskb);
1599                        }
1600                }
1601        }
1602
1603        /* send data only to card, if we don't just calculated tx_data */
1604        /* adjust volume */
1605        if (dsp->tx_volume)
1606                dsp_change_volume(nskb, dsp->tx_volume);
1607        /* pipeline */
1608        if (dsp->pipeline.inuse)
1609                dsp_pipeline_process_tx(&dsp->pipeline, nskb->data,
1610                        nskb->len);
1611        /* crypt */
1612        if (dsp->bf_enable)
1613                dsp_bf_encrypt(dsp, nskb->data, nskb->len);
1614        /* queue and trigger */
1615        skb_queue_tail(&dsp->sendq, nskb);
1616        schedule_work(&dsp->workq);
1617}
1618
1619static u32      jittercount; /* counter for jitter check */
1620struct timer_list dsp_spl_tl;
1621u32     dsp_spl_jiffies; /* calculate the next time to fire */
1622static u16      dsp_count; /* last sample count */
1623static int      dsp_count_valid ; /* if we have last sample count */
1624
1625void
1626dsp_cmx_send(void *arg)
1627{
1628        struct dsp_conf *conf;
1629        struct dsp_conf_member *member;
1630        struct dsp *dsp;
1631        int mustmix, members;
1632        static s32 mixbuffer[MAX_POLL+100];
1633        s32 *c;
1634        u8 *p, *q;
1635        int r, rr;
1636        int jittercheck = 0, delay, i;
1637        u_long flags;
1638        u16 length, count;
1639
1640        /* lock */
1641        spin_lock_irqsave(&dsp_lock, flags);
1642
1643        if (!dsp_count_valid) {
1644                dsp_count = mISDN_clock_get();
1645                length = dsp_poll;
1646                dsp_count_valid = 1;
1647        } else {
1648                count = mISDN_clock_get();
1649                length = count - dsp_count;
1650                dsp_count = count;
1651        }
1652        if (length > MAX_POLL + 100)
1653                length = MAX_POLL + 100;
1654        /* printk(KERN_DEBUG "len=%d dsp_count=0x%x\n", length, dsp_count); */
1655
1656        /*
1657         * check if jitter needs to be checked (this is every second)
1658         */
1659        jittercount += length;
1660        if (jittercount >= 8000) {
1661                jittercount -= 8000;
1662                jittercheck = 1;
1663        }
1664
1665        /* loop all members that do not require conference mixing */
1666        list_for_each_entry(dsp, &dsp_ilist, list) {
1667                if (dsp->hdlc)
1668                        continue;
1669                conf = dsp->conf;
1670                mustmix = 0;
1671                members = 0;
1672                if (conf) {
1673                        members = count_list_member(&conf->mlist);
1674#ifdef CMX_CONF_DEBUG
1675                        if (conf->software && members > 1)
1676#else
1677                        if (conf->software && members > 2)
1678#endif
1679                                mustmix = 1;
1680                }
1681
1682                /* transmission required */
1683                if (!mustmix) {
1684                        dsp_cmx_send_member(dsp, length, mixbuffer, members);
1685
1686                        /*
1687                         * unused mixbuffer is given to prevent a
1688                         * potential null-pointer-bug
1689                         */
1690                }
1691        }
1692
1693        /* loop all members that require conference mixing */
1694        list_for_each_entry(conf, &conf_ilist, list) {
1695                /* count members and check hardware */
1696                members = count_list_member(&conf->mlist);
1697#ifdef CMX_CONF_DEBUG
1698                if (conf->software && members > 1) {
1699#else
1700                if (conf->software && members > 2) {
1701#endif
1702                        /* check for hdlc conf */
1703                        member = list_entry(conf->mlist.next,
1704                                struct dsp_conf_member, list);
1705                        if (member->dsp->hdlc)
1706                                continue;
1707                        /* mix all data */
1708                        memset(mixbuffer, 0, length*sizeof(s32));
1709                        list_for_each_entry(member, &conf->mlist, list) {
1710                                dsp = member->dsp;
1711                                /* get range of data to mix */
1712                                c = mixbuffer;
1713                                q = dsp->rx_buff;
1714                                r = dsp->rx_R;
1715                                rr = (r + length) & CMX_BUFF_MASK;
1716                                /* add member's data */
1717                                while (r != rr) {
1718                                        *c++ += dsp_audio_law_to_s32[q[r]];
1719                                        r = (r+1) & CMX_BUFF_MASK;
1720                                }
1721                        }
1722
1723                        /* process each member */
1724                        list_for_each_entry(member, &conf->mlist, list) {
1725                                /* transmission */
1726                                dsp_cmx_send_member(member->dsp, length,
1727                                    mixbuffer, members);
1728                        }
1729                }
1730        }
1731
1732        /* delete rx-data, increment buffers, change pointers */
1733        list_for_each_entry(dsp, &dsp_ilist, list) {
1734                if (dsp->hdlc)
1735                        continue;
1736                p = dsp->rx_buff;
1737                q = dsp->tx_buff;
1738                r = dsp->rx_R;
1739                /* move receive pointer when receiving */
1740                if (!dsp->rx_is_off) {
1741                        rr = (r + length) & CMX_BUFF_MASK;
1742                        /* delete rx-data */
1743                        while (r != rr) {
1744                                p[r] = dsp_silence;
1745                                r = (r+1) & CMX_BUFF_MASK;
1746                        }
1747                        /* increment rx-buffer pointer */
1748                        dsp->rx_R = r; /* write incremented read pointer */
1749                }
1750
1751                /* check current rx_delay */
1752                delay = (dsp->rx_W-dsp->rx_R) & CMX_BUFF_MASK;
1753                if (delay >= CMX_BUFF_HALF)
1754                        delay = 0; /* will be the delay before next write */
1755                /* check for lower delay */
1756                if (delay < dsp->rx_delay[0])
1757                        dsp->rx_delay[0] = delay;
1758                /* check current tx_delay */
1759                delay = (dsp->tx_W-dsp->tx_R) & CMX_BUFF_MASK;
1760                if (delay >= CMX_BUFF_HALF)
1761                        delay = 0; /* will be the delay before next write */
1762                /* check for lower delay */
1763                if (delay < dsp->tx_delay[0])
1764                        dsp->tx_delay[0] = delay;
1765                if (jittercheck) {
1766                        /* find the lowest of all rx_delays */
1767                        delay = dsp->rx_delay[0];
1768                        i = 1;
1769                        while (i < MAX_SECONDS_JITTER_CHECK) {
1770                                if (delay > dsp->rx_delay[i])
1771                                        delay = dsp->rx_delay[i];
1772                                i++;
1773                        }
1774                        /*
1775                         * remove rx_delay only if we have delay AND we
1776                         * have not preset cmx_delay AND
1777                         * the delay is greater dsp_poll
1778                         */
1779                        if (delay > dsp_poll && !dsp->cmx_delay) {
1780                                if (dsp_debug & DEBUG_DSP_CLOCK)
1781                                        printk(KERN_DEBUG
1782                                            "%s lowest rx_delay of %d bytes for"
1783                                            " dsp %s are now removed.\n",
1784                                            __func__, delay,
1785                                            dsp->name);
1786                                r = dsp->rx_R;
1787                                rr = (r + delay - (dsp_poll >> 1))
1788                                        & CMX_BUFF_MASK;
1789                                /* delete rx-data */
1790                                while (r != rr) {
1791                                        p[r] = dsp_silence;
1792                                        r = (r+1) & CMX_BUFF_MASK;
1793                                }
1794                                /* increment rx-buffer pointer */
1795                                dsp->rx_R = r;
1796                                    /* write incremented read pointer */
1797                        }
1798                        /* find the lowest of all tx_delays */
1799                        delay = dsp->tx_delay[0];
1800                        i = 1;
1801                        while (i < MAX_SECONDS_JITTER_CHECK) {
1802                                if (delay > dsp->tx_delay[i])
1803                                        delay = dsp->tx_delay[i];
1804                                i++;
1805                        }
1806                        /*
1807                         * remove delay only if we have delay AND we
1808                         * have enabled tx_dejitter
1809                         */
1810                        if (delay > dsp_poll && dsp->tx_dejitter) {
1811                                if (dsp_debug & DEBUG_DSP_CLOCK)
1812                                        printk(KERN_DEBUG
1813                                            "%s lowest tx_delay of %d bytes for"
1814                                            " dsp %s are now removed.\n",
1815                                            __func__, delay,
1816                                            dsp->name);
1817                                r = dsp->tx_R;
1818                                rr = (r + delay - (dsp_poll >> 1))
1819                                        & CMX_BUFF_MASK;
1820                                /* delete tx-data */
1821                                while (r != rr) {
1822                                        q[r] = dsp_silence;
1823                                        r = (r+1) & CMX_BUFF_MASK;
1824                                }
1825                                /* increment rx-buffer pointer */
1826                                dsp->tx_R = r;
1827                                    /* write incremented read pointer */
1828                        }
1829                        /* scroll up delays */
1830                        i = MAX_SECONDS_JITTER_CHECK - 1;
1831                        while (i) {
1832                                dsp->rx_delay[i] = dsp->rx_delay[i-1];
1833                                dsp->tx_delay[i] = dsp->tx_delay[i-1];
1834                                i--;
1835                        }
1836                        dsp->tx_delay[0] = CMX_BUFF_HALF; /* (infinite) delay */
1837                        dsp->rx_delay[0] = CMX_BUFF_HALF; /* (infinite) delay */
1838                }
1839        }
1840
1841        /* if next event would be in the past ... */
1842        if ((s32)(dsp_spl_jiffies+dsp_tics-jiffies) <= 0)
1843                dsp_spl_jiffies = jiffies + 1;
1844        else
1845                dsp_spl_jiffies += dsp_tics;
1846
1847        dsp_spl_tl.expires = dsp_spl_jiffies;
1848        add_timer(&dsp_spl_tl);
1849
1850        /* unlock */
1851        spin_unlock_irqrestore(&dsp_lock, flags);
1852}
1853
1854/*
1855 * audio data is transmitted from upper layer to the dsp
1856 */
1857void
1858dsp_cmx_transmit(struct dsp *dsp, struct sk_buff *skb)
1859{
1860        u_int w, ww;
1861        u8 *d, *p;
1862        int space; /* todo: , l = skb->len; */
1863#ifdef CMX_TX_DEBUG
1864        char debugbuf[256] = "";
1865#endif
1866
1867        /* check if there is enough space, and then copy */
1868        w = dsp->tx_W;
1869        ww = dsp->tx_R;
1870        p = dsp->tx_buff;
1871        d = skb->data;
1872        space = (ww - w - 1) & CMX_BUFF_MASK;
1873        /* write-pointer should not overrun nor reach read pointer */
1874        if (space < skb->len) {
1875                /* write to the space we have left */
1876                ww = (ww - 1) & CMX_BUFF_MASK; /* end one byte prior tx_R */
1877                if (dsp_debug & DEBUG_DSP_CLOCK)
1878                        printk(KERN_DEBUG "%s: TX overflow space=%d skb->len="
1879                            "%d, w=0x%04x, ww=0x%04x\n", __func__, space,
1880                            skb->len, w, ww);
1881        } else
1882                /* write until all byte are copied */
1883                ww = (w + skb->len) & CMX_BUFF_MASK;
1884        dsp->tx_W = ww;
1885
1886        /* show current buffer */
1887#ifdef CMX_DEBUG
1888        printk(KERN_DEBUG
1889            "cmx_transmit(dsp=%lx) %d bytes to 0x%x-0x%x. %s\n",
1890            (u_long)dsp, (ww-w)&CMX_BUFF_MASK, w, ww, dsp->name);
1891#endif
1892
1893        /* copy transmit data to tx-buffer */
1894#ifdef CMX_TX_DEBUG
1895        sprintf(debugbuf, "TX getting (%04x-%04x)%p: ", w, ww, p);
1896#endif
1897        while (w != ww) {
1898#ifdef CMX_TX_DEBUG
1899                if (strlen(debugbuf) < 48)
1900                        sprintf(debugbuf+strlen(debugbuf), " %02x", *d);
1901#endif
1902                p[w] = *d++;
1903                w = (w+1) & CMX_BUFF_MASK;
1904        }
1905#ifdef CMX_TX_DEBUG
1906        printk(KERN_DEBUG "%s\n", debugbuf);
1907#endif
1908
1909}
1910
1911/*
1912 * hdlc data is received from card and sent to all members.
1913 */
1914void
1915dsp_cmx_hdlc(struct dsp *dsp, struct sk_buff *skb)
1916{
1917        struct sk_buff *nskb = NULL;
1918        struct dsp_conf_member *member;
1919        struct mISDNhead *hh;
1920
1921        /* not if not active */
1922        if (!dsp->b_active)
1923                return;
1924
1925        /* check if we have sompen */
1926        if (skb->len < 1)
1927                return;
1928
1929        /* no conf */
1930        if (!dsp->conf) {
1931                /* in case of software echo */
1932                if (dsp->echo.software) {
1933                        nskb = skb_clone(skb, GFP_ATOMIC);
1934                        if (nskb) {
1935                                hh = mISDN_HEAD_P(nskb);
1936                                hh->prim = PH_DATA_REQ;
1937                                hh->id = 0;
1938                                skb_queue_tail(&dsp->sendq, nskb);
1939                                schedule_work(&dsp->workq);
1940                        }
1941                }
1942                return;
1943        }
1944        /* in case of hardware conference */
1945        if (dsp->conf->hardware)
1946                return;
1947        list_for_each_entry(member, &dsp->conf->mlist, list) {
1948                if (dsp->echo.software || member->dsp != dsp) {
1949                        nskb = skb_clone(skb, GFP_ATOMIC);
1950                        if (nskb) {
1951                                hh = mISDN_HEAD_P(nskb);
1952                                hh->prim = PH_DATA_REQ;
1953                                hh->id = 0;
1954                                skb_queue_tail(&member->dsp->sendq, nskb);
1955                                schedule_work(&member->dsp->workq);
1956                        }
1957                }
1958        }
1959}
1960
1961
1962
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.