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