brintos

brintos / linux-shallow public Read only

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