1/* $Id: capifunc.c,v 1.61.4.7 2005/02/11 19:40:25 armin Exp $
2 *
3 * ISDN interface module for Eicon active cards DIVA.
4 * CAPI Interface common functions
5 *
6 * Copyright 2000-2003 by Armin Schindler (mac@melware.de)
7 * Copyright 2000-2003 Cytronics & Melware (info@melware.de)
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 *
12 */
13
14#include "platform.h"
15#include "os_capi.h"
16#include "di_defs.h"
17#include "capi20.h"
18#include "divacapi.h"
19#include "divasync.h"
20#include "capifunc.h"
21
22#define DBG_MINIMUM  (DL_LOG + DL_FTL + DL_ERR)
23#define DBG_DEFAULT  (DBG_MINIMUM + DL_XLOG + DL_REG)
24
25DIVA_CAPI_ADAPTER *adapter = (DIVA_CAPI_ADAPTER *) NULL;
26APPL *application = (APPL *) NULL;
27byte max_appl = MAX_APPL;
28byte max_adapter = 0;
29static CAPI_MSG *mapped_msg = (CAPI_MSG *) NULL;
30
31byte UnMapController(byte);
32char DRIVERRELEASE_CAPI[32];
33
34extern void AutomaticLaw(DIVA_CAPI_ADAPTER *);
35extern void callback(ENTITY *);
36extern word api_remove_start(void);
37extern word CapiRelease(word);
38extern word CapiRegister(word);
39extern word api_put(APPL *, CAPI_MSG *);
40
41static diva_os_spin_lock_t api_lock;
42
43static LIST_HEAD(cards);
44
45static dword notify_handle;
46static void DIRequest(ENTITY *e);
47static DESCRIPTOR MAdapter;
48static DESCRIPTOR DAdapter;
49static byte ControllerMap[MAX_DESCRIPTORS + 1];
50
51
52static void diva_register_appl(struct capi_ctr *, __u16,
53			       capi_register_params *);
54static void diva_release_appl(struct capi_ctr *, __u16);
55static char *diva_procinfo(struct capi_ctr *);
56static u16 diva_send_message(struct capi_ctr *,
57			     diva_os_message_buffer_s *);
58extern void diva_os_set_controller_struct(struct capi_ctr *);
59
60extern void DIVA_DIDD_Read(DESCRIPTOR *, int);
61
62/*
63 * debug
64 */
65static void no_printf(unsigned char *, ...);
66#include "debuglib.c"
67static void xlog(char *x, ...)
68{
69#ifndef DIVA_NO_DEBUGLIB
70	va_list ap;
71	if (myDriverDebugHandle.dbgMask & DL_XLOG) {
72		va_start(ap, x);
73		if (myDriverDebugHandle.dbg_irq) {
74			myDriverDebugHandle.dbg_irq(myDriverDebugHandle.id,
75						    DLI_XLOG, x, ap);
76		} else if (myDriverDebugHandle.dbg_old) {
77			myDriverDebugHandle.dbg_old(myDriverDebugHandle.id,
78						    x, ap);
79		}
80		va_end(ap);
81	}
82#endif
83}
84
85/*
86 * info for proc
87 */
88static char *diva_procinfo(struct capi_ctr *ctrl)
89{
90	return (ctrl->serial);
91}
92
93/*
94 * stop debugging
95 */
96static void stop_dbg(void)
97{
98	DbgDeregister();
99	memset(&MAdapter, 0, sizeof(MAdapter));
100	dprintf = no_printf;
101}
102
103/*
104 * dummy debug function
105 */
106static void no_printf(unsigned char *x, ...)
107{
108}
109
110/*
111 * Controller mapping
112 */
113byte MapController(byte Controller)
114{
115	byte i;
116	byte MappedController = 0;
117	byte ctrl = Controller & 0x7f;	/* mask external controller bit off */
118
119	for (i = 1; i < max_adapter + 1; i++) {
120		if (ctrl == ControllerMap[i]) {
121			MappedController = (byte) i;
122			break;
123		}
124	}
125	if (i > max_adapter) {
126		ControllerMap[0] = ctrl;
127		MappedController = 0;
128	}
129	return (MappedController | (Controller & 0x80));	/* put back external controller bit */
130}
131
132/*
133 * Controller unmapping
134 */
135byte UnMapController(byte MappedController)
136{
137	byte Controller;
138	byte ctrl = MappedController & 0x7f;	/* mask external controller bit off */
139
140	if (ctrl <= max_adapter) {
141		Controller = ControllerMap[ctrl];
142	} else {
143		Controller = 0;
144	}
145
146	return (Controller | (MappedController & 0x80));	/* put back external controller bit */
147}
148
149/*
150 * find a new free id
151 */
152static int find_free_id(void)
153{
154	int num = 0;
155	DIVA_CAPI_ADAPTER *a;
156
157	while (num < MAX_DESCRIPTORS) {
158		a = &adapter[num];
159		if (!a->Id)
160			break;
161		num++;
162	}
163	return (num + 1);
164}
165
166/*
167 * find a card structure by controller number
168 */
169static diva_card *find_card_by_ctrl(word controller)
170{
171	struct list_head *tmp;
172	diva_card *card;
173
174	list_for_each(tmp, &cards) {
175		card = list_entry(tmp, diva_card, list);
176		if (ControllerMap[card->Id] == controller) {
177			if (card->remove_in_progress)
178				card = NULL;
179			return (card);
180		}
181	}
182	return (diva_card *) 0;
183}
184
185/*
186 * Buffer RX/TX
187 */
188void *TransmitBufferSet(APPL *appl, dword ref)
189{
190	appl->xbuffer_used[ref] = true;
191	DBG_PRV1(("%d:xbuf_used(%d)", appl->Id, ref + 1))
192		return (void *)(long)ref;
193}
194
195void *TransmitBufferGet(APPL *appl, void *p)
196{
197	if (appl->xbuffer_internal[(dword)(long)p])
198		return appl->xbuffer_internal[(dword)(long)p];
199
200	return appl->xbuffer_ptr[(dword)(long)p];
201}
202
203void TransmitBufferFree(APPL *appl, void *p)
204{
205	appl->xbuffer_used[(dword)(long)p] = false;
206	DBG_PRV1(("%d:xbuf_free(%d)", appl->Id, ((dword)(long)p) + 1))
207		}
208
209void *ReceiveBufferGet(APPL *appl, int Num)
210{
211	return &appl->ReceiveBuffer[Num * appl->MaxDataLength];
212}
213
214/*
215 * api_remove_start/complete for cleanup
216 */
217void api_remove_complete(void)
218{
219	DBG_PRV1(("api_remove_complete"))
220		}
221
222/*
223 * main function called by message.c
224 */
225void sendf(APPL *appl, word command, dword Id, word Number, byte *format, ...)
226{
227	word i, j;
228	word length = 12, dlength = 0;
229	byte *write;
230	CAPI_MSG msg;
231	byte *string = NULL;
232	va_list ap;
233	diva_os_message_buffer_s *dmb;
234	diva_card *card = NULL;
235	dword tmp;
236
237	if (!appl)
238		return;
239
240	DBG_PRV1(("sendf(a=%d,cmd=%x,format=%s)",
241		  appl->Id, command, (byte *) format))
242
243		PUT_WORD(&msg.header.appl_id, appl->Id);
244	PUT_WORD(&msg.header.command, command);
245	if ((byte) (command >> 8) == 0x82)
246		Number = appl->Number++;
247	PUT_WORD(&msg.header.number, Number);
248
249	PUT_DWORD(&msg.header.controller, Id);
250	write = (byte *)&msg;
251	write += 12;
252
253	va_start(ap, format);
254	for (i = 0; format[i]; i++) {
255		switch (format[i]) {
256		case 'b':
257			tmp = va_arg(ap, dword);
258			*(byte *) write = (byte) (tmp & 0xff);
259			write += 1;
260			length += 1;
261			break;
262		case 'w':
263			tmp = va_arg(ap, dword);
264			PUT_WORD(write, (tmp & 0xffff));
265			write += 2;
266			length += 2;
267			break;
268		case 'd':
269			tmp = va_arg(ap, dword);
270			PUT_DWORD(write, tmp);
271			write += 4;
272			length += 4;
273			break;
274		case 's':
275		case 'S':
276			string = va_arg(ap, byte *);
277			length += string[0] + 1;
278			for (j = 0; j <= string[0]; j++)
279				*write++ = string[j];
280			break;
281		}
282	}
283	va_end(ap);
284
285	PUT_WORD(&msg.header.length, length);
286	msg.header.controller = UnMapController(msg.header.controller);
287
288	if (command == _DATA_B3_I)
289		dlength = GET_WORD(
290			((byte *)&msg.info.data_b3_ind.Data_Length));
291
292	if (!(dmb = diva_os_alloc_message_buffer(length + dlength,
293						 (void **) &write))) {
294		DBG_ERR(("sendf: alloc_message_buffer failed, incoming msg dropped."))
295			return;
296	}
297
298	/* copy msg header to sk_buff */
299	memcpy(write, (byte *)&msg, length);
300
301	/* if DATA_B3_IND, copy data too */
302	if (command == _DATA_B3_I) {
303		dword data = GET_DWORD(&msg.info.data_b3_ind.Data);
304		memcpy(write + length, (void *)(long)data, dlength);
305	}
306
307#ifndef DIVA_NO_DEBUGLIB
308	if (myDriverDebugHandle.dbgMask & DL_XLOG) {
309		switch (command) {
310		default:
311			xlog("\x00\x02", &msg, 0x81, length);
312			break;
313		case _DATA_B3_R | CONFIRM:
314			if (myDriverDebugHandle.dbgMask & DL_BLK)
315				xlog("\x00\x02", &msg, 0x81, length);
316			break;
317		case _DATA_B3_I:
318			if (myDriverDebugHandle.dbgMask & DL_BLK) {
319				xlog("\x00\x02", &msg, 0x81, length);
320				for (i = 0; i < dlength; i += 256) {
321					DBG_BLK((((char *)(long)GET_DWORD(&msg.info.data_b3_ind.Data)) + i,
322						 ((dlength - i) < 256) ? (dlength - i) : 256))
323						if (!(myDriverDebugHandle.dbgMask & DL_PRV0))
324							break; /* not more if not explicitly requested */
325				}
326			}
327			break;
328		}
329	}
330#endif
331
332	/* find the card structure for this controller */
333	if (!(card = find_card_by_ctrl(write[8] & 0x7f))) {
334		DBG_ERR(("sendf - controller %d not found, incoming msg dropped",
335			 write[8] & 0x7f))
336			diva_os_free_message_buffer(dmb);
337		return;
338	}
339	/* send capi msg to capi layer */
340	capi_ctr_handle_message(&card->capi_ctrl, appl->Id, dmb);
341}
342
343/*
344 * cleanup adapter
345 */
346static void clean_adapter(int id, struct list_head *free_mem_q)
347{
348	DIVA_CAPI_ADAPTER *a;
349	int i, k;
350
351	a = &adapter[id];
352	k = li_total_channels - a->li_channels;
353	if (k == 0) {
354		if (li_config_table) {
355			list_add((struct list_head *)li_config_table, free_mem_q);
356			li_config_table = NULL;
357		}
358	} else {
359		if (a->li_base < k) {
360			memmove(&li_config_table[a->li_base],
361				&li_config_table[a->li_base + a->li_channels],
362				(k - a->li_base) * sizeof(LI_CONFIG));
363			for (i = 0; i < k; i++) {
364				memmove(&li_config_table[i].flag_table[a->li_base],
365					&li_config_table[i].flag_table[a->li_base + a->li_channels],
366					k - a->li_base);
367				memmove(&li_config_table[i].
368					coef_table[a->li_base],
369					&li_config_table[i].coef_table[a->li_base + a->li_channels],
370					k - a->li_base);
371			}
372		}
373	}
374	li_total_channels = k;
375	for (i = id; i < max_adapter; i++) {
376		if (adapter[i].request)
377			adapter[i].li_base -= a->li_channels;
378	}
379	if (a->plci)
380		list_add((struct list_head *)a->plci, free_mem_q);
381
382	memset(a, 0x00, sizeof(DIVA_CAPI_ADAPTER));
383	while ((max_adapter != 0) && !adapter[max_adapter - 1].request)
384		max_adapter--;
385}
386
387/*
388 * remove a card, but ensures consistent state of LI tables
389 * in the time adapter is removed
390 */
391static void divacapi_remove_card(DESCRIPTOR *d)
392{
393	diva_card *card = NULL;
394	diva_os_spin_lock_magic_t old_irql;
395	LIST_HEAD(free_mem_q);
396	struct list_head *link;
397	struct list_head *tmp;
398
399	/*
400	 * Set "remove in progress flag".
401	 * Ensures that there is no call from sendf to CAPI in
402	 * the time CAPI controller is about to be removed.
403	 */
404	diva_os_enter_spin_lock(&api_lock, &old_irql, "remove card");
405	list_for_each(tmp, &cards) {
406		card = list_entry(tmp, diva_card, list);
407		if (card->d.request == d->request) {
408			card->remove_in_progress = 1;
409			list_del(tmp);
410			break;
411		}
412	}
413	diva_os_leave_spin_lock(&api_lock, &old_irql, "remove card");
414
415	if (card) {
416		/*
417		 * Detach CAPI. Sendf cannot call to CAPI any more.
418		 * After detach no call to send_message() is done too.
419		 */
420		detach_capi_ctr(&card->capi_ctrl);
421
422		/*
423		 * Now get API lock (to ensure stable state of LI tables)
424		 * and update the adapter map/LI table.
425		 */
426		diva_os_enter_spin_lock(&api_lock, &old_irql, "remove card");
427
428		clean_adapter(card->Id - 1, &free_mem_q);
429		DBG_TRC(("DelAdapterMap (%d) -> (%d)",
430			 ControllerMap[card->Id], card->Id))
431			ControllerMap[card->Id] = 0;
432		DBG_TRC(("adapter remove, max_adapter=%d",
433			 max_adapter));
434		diva_os_leave_spin_lock(&api_lock, &old_irql, "remove card");
435
436		/* After releasing the lock, we can free the memory */
437		diva_os_free(0, card);
438	}
439
440	/* free queued memory areas */
441	list_for_each_safe(link, tmp, &free_mem_q) {
442		list_del(link);
443		diva_os_free(0, link);
444	}
445}
446
447/*
448 * remove cards
449 */
450static void divacapi_remove_cards(void)
451{
452	DESCRIPTOR d;
453	struct list_head *tmp;
454	diva_card *card;
455	diva_os_spin_lock_magic_t old_irql;
456
457rescan:
458	diva_os_enter_spin_lock(&api_lock, &old_irql, "remove cards");
459	list_for_each(tmp, &cards) {
460		card = list_entry(tmp, diva_card, list);
461		diva_os_leave_spin_lock(&api_lock, &old_irql, "remove cards");
462		d.request = card->d.request;
463		divacapi_remove_card(&d);
464		goto rescan;
465	}
466	diva_os_leave_spin_lock(&api_lock, &old_irql, "remove cards");
467}
468
469/*
470 * sync_callback
471 */
472static void sync_callback(ENTITY *e)
473{
474	diva_os_spin_lock_magic_t old_irql;
475
476	DBG_TRC(("cb:Id=%x,Rc=%x,Ind=%x", e->Id, e->Rc, e->Ind))
477
478		diva_os_enter_spin_lock(&api_lock, &old_irql, "sync_callback");
479	callback(e);
480	diva_os_leave_spin_lock(&api_lock, &old_irql, "sync_callback");
481}
482
483/*
484 * add a new card
485 */
486static int diva_add_card(DESCRIPTOR *d)
487{
488	int k = 0, i = 0;
489	diva_os_spin_lock_magic_t old_irql;
490	diva_card *card = NULL;
491	struct capi_ctr *ctrl = NULL;
492	DIVA_CAPI_ADAPTER *a = NULL;
493	IDI_SYNC_REQ sync_req;
494	char serial[16];
495	void *mem_to_free;
496	LI_CONFIG *new_li_config_table;
497	int j;
498
499	if (!(card = (diva_card *) diva_os_malloc(0, sizeof(diva_card)))) {
500		DBG_ERR(("diva_add_card: failed to allocate card struct."))
501			return (0);
502	}
503	memset((char *) card, 0x00, sizeof(diva_card));
504	memcpy(&card->d, d, sizeof(DESCRIPTOR));
505	sync_req.GetName.Req = 0;
506	sync_req.GetName.Rc = IDI_SYNC_REQ_GET_NAME;
507	card->d.request((ENTITY *)&sync_req);
508	strlcpy(card->name, sync_req.GetName.name, sizeof(card->name));
509	ctrl = &card->capi_ctrl;
510	strcpy(ctrl->name, card->name);
511	ctrl->register_appl = diva_register_appl;
512	ctrl->release_appl = diva_release_appl;
513	ctrl->send_message = diva_send_message;
514	ctrl->procinfo = diva_procinfo;
515	ctrl->driverdata = card;
516	diva_os_set_controller_struct(ctrl);
517
518	if (attach_capi_ctr(ctrl)) {
519		DBG_ERR(("diva_add_card: failed to attach controller."))
520			diva_os_free(0, card);
521		return (0);
522	}
523
524	diva_os_enter_spin_lock(&api_lock, &old_irql, "find id");
525	card->Id = find_free_id();
526	diva_os_leave_spin_lock(&api_lock, &old_irql, "find id");
527
528	strlcpy(ctrl->manu, M_COMPANY, sizeof(ctrl->manu));
529	ctrl->version.majorversion = 2;
530	ctrl->version.minorversion = 0;
531	ctrl->version.majormanuversion = DRRELMAJOR;
532	ctrl->version.minormanuversion = DRRELMINOR;
533	sync_req.GetSerial.Req = 0;
534	sync_req.GetSerial.Rc = IDI_SYNC_REQ_GET_SERIAL;
535	sync_req.GetSerial.serial = 0;
536	card->d.request((ENTITY *)&sync_req);
537	if ((i = ((sync_req.GetSerial.serial & 0xff000000) >> 24))) {
538		sprintf(serial, "%ld-%d",
539			sync_req.GetSerial.serial & 0x00ffffff, i + 1);
540	} else {
541		sprintf(serial, "%ld", sync_req.GetSerial.serial);
542	}
543	serial[CAPI_SERIAL_LEN - 1] = 0;
544	strlcpy(ctrl->serial, serial, sizeof(ctrl->serial));
545
546	a = &adapter[card->Id - 1];
547	card->adapter = a;
548	a->os_card = card;
549	ControllerMap[card->Id] = (byte) (ctrl->cnr);
550
551	DBG_TRC(("AddAdapterMap (%d) -> (%d)", ctrl->cnr, card->Id))
552
553		sync_req.xdi_capi_prms.Req = 0;
554	sync_req.xdi_capi_prms.Rc = IDI_SYNC_REQ_XDI_GET_CAPI_PARAMS;
555	sync_req.xdi_capi_prms.info.structure_length =
556		sizeof(diva_xdi_get_capi_parameters_t);
557	card->d.request((ENTITY *)&sync_req);
558	a->flag_dynamic_l1_down =
559		sync_req.xdi_capi_prms.info.flag_dynamic_l1_down;
560	a->group_optimization_enabled =
561		sync_req.xdi_capi_prms.info.group_optimization_enabled;
562	a->request = DIRequest;	/* card->d.request; */
563	a->max_plci = card->d.channels + 30;
564	a->max_listen = (card->d.channels > 2) ? 8 : 2;
565	if (!
566	    (a->plci =
567	     (PLCI *) diva_os_malloc(0, sizeof(PLCI) * a->max_plci))) {
568		DBG_ERR(("diva_add_card: failed alloc plci struct."))
569			memset(a, 0, sizeof(DIVA_CAPI_ADAPTER));
570		return (0);
571	}
572	memset(a->plci, 0, sizeof(PLCI) * a->max_plci);
573
574	for (k = 0; k < a->max_plci; k++) {
575		a->Id = (byte) card->Id;
576		a->plci[k].Sig.callback = sync_callback;
577		a->plci[k].Sig.XNum = 1;
578		a->plci[k].Sig.X = a->plci[k].XData;
579		a->plci[k].Sig.user[0] = (word) (card->Id - 1);
580		a->plci[k].Sig.user[1] = (word) k;
581		a->plci[k].NL.callback = sync_callback;
582		a->plci[k].NL.XNum = 1;
583		a->plci[k].NL.X = a->plci[k].XData;
584		a->plci[k].NL.user[0] = (word) ((card->Id - 1) | 0x8000);
585		a->plci[k].NL.user[1] = (word) k;
586		a->plci[k].adapter = a;
587	}
588
589	a->profile.Number = card->Id;
590	a->profile.Channels = card->d.channels;
591	if (card->d.features & DI_FAX3) {
592		a->profile.Global_Options = 0x71;
593		if (card->d.features & DI_CODEC)
594			a->profile.Global_Options |= 0x6;
595#if IMPLEMENT_DTMF
596		a->profile.Global_Options |= 0x8;
597#endif				/* IMPLEMENT_DTMF */
598		a->profile.Global_Options |= 0x80; /* Line Interconnect */
599#if IMPLEMENT_ECHO_CANCELLER
600		a->profile.Global_Options |= 0x100;
601#endif				/* IMPLEMENT_ECHO_CANCELLER */
602		a->profile.B1_Protocols = 0xdf;
603		a->profile.B2_Protocols = 0x1fdb;
604		a->profile.B3_Protocols = 0xb7;
605		a->manufacturer_features = MANUFACTURER_FEATURE_HARDDTMF;
606	} else {
607		a->profile.Global_Options = 0x71;
608		if (card->d.features & DI_CODEC)
609			a->profile.Global_Options |= 0x2;
610		a->profile.B1_Protocols = 0x43;
611		a->profile.B2_Protocols = 0x1f0f;
612		a->profile.B3_Protocols = 0x07;
613		a->manufacturer_features = 0;
614	}
615
616	a->li_pri = (a->profile.Channels > 2);
617	a->li_channels = a->li_pri ? MIXER_CHANNELS_PRI : MIXER_CHANNELS_BRI;
618	a->li_base = 0;
619	for (i = 0; &adapter[i] != a; i++) {
620		if (adapter[i].request)
621			a->li_base = adapter[i].li_base + adapter[i].li_channels;
622	}
623	k = li_total_channels + a->li_channels;
624	new_li_config_table =
625		(LI_CONFIG *) diva_os_malloc(0, ((k * sizeof(LI_CONFIG) + 3) & ~3) + (2 * k) * ((k + 3) & ~3));
626	if (new_li_config_table == NULL) {
627		DBG_ERR(("diva_add_card: failed alloc li_config table."))
628			memset(a, 0, sizeof(DIVA_CAPI_ADAPTER));
629		return (0);
630	}
631
632	/* Prevent access to line interconnect table in process update */
633	diva_os_enter_spin_lock(&api_lock, &old_irql, "add card");
634
635	j = 0;
636	for (i = 0; i < k; i++) {
637		if ((i >= a->li_base) && (i < a->li_base + a->li_channels))
638			memset(&new_li_config_table[i], 0, sizeof(LI_CONFIG));
639		else
640			memcpy(&new_li_config_table[i], &li_config_table[j], sizeof(LI_CONFIG));
641		new_li_config_table[i].flag_table =
642			((byte *) new_li_config_table) + (((k * sizeof(LI_CONFIG) + 3) & ~3) + (2 * i) * ((k + 3) & ~3));
643		new_li_config_table[i].coef_table =
644			((byte *) new_li_config_table) + (((k * sizeof(LI_CONFIG) + 3) & ~3) + (2 * i + 1) * ((k + 3) & ~3));
645		if ((i >= a->li_base) && (i < a->li_base + a->li_channels)) {
646			new_li_config_table[i].adapter = a;
647			memset(&new_li_config_table[i].flag_table[0], 0, k);
648			memset(&new_li_config_table[i].coef_table[0], 0, k);
649		} else {
650			if (a->li_base != 0) {
651				memcpy(&new_li_config_table[i].flag_table[0],
652				       &li_config_table[j].flag_table[0],
653				       a->li_base);
654				memcpy(&new_li_config_table[i].coef_table[0],
655				       &li_config_table[j].coef_table[0],
656				       a->li_base);
657			}
658			memset(&new_li_config_table[i].flag_table[a->li_base], 0, a->li_channels);
659			memset(&new_li_config_table[i].coef_table[a->li_base], 0, a->li_channels);
660			if (a->li_base + a->li_channels < k) {
661				memcpy(&new_li_config_table[i].flag_table[a->li_base +
662									  a->li_channels],
663				       &li_config_table[j].flag_table[a->li_base],
664				       k - (a->li_base + a->li_channels));
665				memcpy(&new_li_config_table[i].coef_table[a->li_base +
666									  a->li_channels],
667				       &li_config_table[j].coef_table[a->li_base],
668				       k - (a->li_base + a->li_channels));
669			}
670			j++;
671		}
672	}
673	li_total_channels = k;
674
675	mem_to_free = li_config_table;
676
677	li_config_table = new_li_config_table;
678	for (i = card->Id; i < max_adapter; i++) {
679		if (adapter[i].request)
680			adapter[i].li_base += a->li_channels;
681	}
682
683	if (a == &adapter[max_adapter])
684		max_adapter++;
685
686	list_add(&(card->list), &cards);
687	AutomaticLaw(a);
688
689	diva_os_leave_spin_lock(&api_lock, &old_irql, "add card");
690
691	if (mem_to_free) {
692		diva_os_free(0, mem_to_free);
693	}
694
695	i = 0;
696	while (i++ < 30) {
697		if (a->automatic_law > 3)
698			break;
699		diva_os_sleep(10);
700	}
701
702	/* profile information */
703	PUT_WORD(&ctrl->profile.nbchannel, card->d.channels);
704	ctrl->profile.goptions = a->profile.Global_Options;
705	ctrl->profile.support1 = a->profile.B1_Protocols;
706	ctrl->profile.support2 = a->profile.B2_Protocols;
707	ctrl->profile.support3 = a->profile.B3_Protocols;
708	/* manufacturer profile information */
709	ctrl->profile.manu[0] = a->man_profile.private_options;
710	ctrl->profile.manu[1] = a->man_profile.rtp_primary_payloads;
711	ctrl->profile.manu[2] = a->man_profile.rtp_additional_payloads;
712	ctrl->profile.manu[3] = 0;
713	ctrl->profile.manu[4] = 0;
714
715	capi_ctr_ready(ctrl);
716
717	DBG_TRC(("adapter added, max_adapter=%d", max_adapter));
718	return (1);
719}
720
721/*
722 *  register appl
723 */
724static void diva_register_appl(struct capi_ctr *ctrl, __u16 appl,
725			       capi_register_params *rp)
726{
727	APPL *this;
728	word bnum, xnum;
729	int i = 0;
730	unsigned char *p;
731	void *DataNCCI, *DataFlags, *ReceiveBuffer, *xbuffer_used;
732	void **xbuffer_ptr, **xbuffer_internal;
733	diva_os_spin_lock_magic_t old_irql;
734	unsigned int mem_len;
735	int nconn = rp->level3cnt;
736
737
738	if (diva_os_in_irq()) {
739		DBG_ERR(("CAPI_REGISTER - in irq context !"))
740			return;
741	}
742
743	DBG_TRC(("application register Id=%d", appl))
744
745		if (appl > MAX_APPL) {
746			DBG_ERR(("CAPI_REGISTER - appl.Id exceeds MAX_APPL"))
747				return;
748		}
749
750	if (nconn <= 0)
751		nconn = ctrl->profile.nbchannel * -nconn;
752
753	if (nconn == 0)
754		nconn = ctrl->profile.nbchannel;
755
756	DBG_LOG(("CAPI_REGISTER - Id = %d", appl))
757		DBG_LOG(("  MaxLogicalConnections = %d(%d)", nconn, rp->level3cnt))
758		DBG_LOG(("  MaxBDataBuffers       = %d", rp->datablkcnt))
759		DBG_LOG(("  MaxBDataLength        = %d", rp->datablklen))
760
761		if (nconn < 1 ||
762		    nconn > 255 ||
763		    rp->datablklen < 80 ||
764		    rp->datablklen > 2150 || rp->datablkcnt > 255) {
765			DBG_ERR(("CAPI_REGISTER - invalid parameters"))
766				return;
767		}
768
769	if (application[appl - 1].Id == appl) {
770		DBG_LOG(("CAPI_REGISTER - appl already registered"))
771			return;	/* appl already registered */
772	}
773
774	/* alloc memory */
775
776	bnum = nconn * rp->datablkcnt;
777	xnum = nconn * MAX_DATA_B3;
778
779	mem_len  = bnum * sizeof(word);		/* DataNCCI */
780	mem_len += bnum * sizeof(word);		/* DataFlags */
781	mem_len += bnum * rp->datablklen;	/* ReceiveBuffer */
782	mem_len += xnum;			/* xbuffer_used */
783	mem_len += xnum * sizeof(void *);	/* xbuffer_ptr */
784	mem_len += xnum * sizeof(void *);	/* xbuffer_internal */
785	mem_len += xnum * rp->datablklen;	/* xbuffer_ptr[xnum] */
786
787	DBG_LOG(("  Allocated Memory      = %d", mem_len))
788		if (!(p = diva_os_malloc(0, mem_len))) {
789			DBG_ERR(("CAPI_REGISTER - memory allocation failed"))
790				return;
791		}
792	memset(p, 0, mem_len);
793
794	DataNCCI = (void *)p;
795	p += bnum * sizeof(word);
796	DataFlags = (void *)p;
797	p += bnum * sizeof(word);
798	ReceiveBuffer = (void *)p;
799	p += bnum * rp->datablklen;
800	xbuffer_used = (void *)p;
801	p += xnum;
802	xbuffer_ptr = (void **)p;
803	p += xnum * sizeof(void *);
804	xbuffer_internal = (void **)p;
805	p += xnum * sizeof(void *);
806	for (i = 0; i < xnum; i++) {
807		xbuffer_ptr[i] = (void *)p;
808		p += rp->datablklen;
809	}
810
811	/* initialize application data */
812	diva_os_enter_spin_lock(&api_lock, &old_irql, "register_appl");
813
814	this = &application[appl - 1];
815	memset(this, 0, sizeof(APPL));
816
817	this->Id = appl;
818
819	for (i = 0; i < max_adapter; i++) {
820		adapter[i].CIP_Mask[appl - 1] = 0;
821	}
822
823	this->queue_size = 1000;
824
825	this->MaxNCCI = (byte) nconn;
826	this->MaxNCCIData = (byte) rp->datablkcnt;
827	this->MaxBuffer = bnum;
828	this->MaxDataLength = rp->datablklen;
829
830	this->DataNCCI = DataNCCI;
831	this->DataFlags = DataFlags;
832	this->ReceiveBuffer = ReceiveBuffer;
833	this->xbuffer_used = xbuffer_used;
834	this->xbuffer_ptr = xbuffer_ptr;
835	this->xbuffer_internal = xbuffer_internal;
836	for (i = 0; i < xnum; i++) {
837		this->xbuffer_ptr[i] = xbuffer_ptr[i];
838	}
839
840	CapiRegister(this->Id);
841	diva_os_leave_spin_lock(&api_lock, &old_irql, "register_appl");
842
843}
844
845/*
846 *  release appl
847 */
848static void diva_release_appl(struct capi_ctr *ctrl, __u16 appl)
849{
850	diva_os_spin_lock_magic_t old_irql;
851	APPL *this = &application[appl - 1];
852	void *mem_to_free = NULL;
853
854	DBG_TRC(("application %d(%d) cleanup", this->Id, appl))
855
856		if (diva_os_in_irq()) {
857			DBG_ERR(("CAPI_RELEASE - in irq context !"))
858				return;
859		}
860
861	diva_os_enter_spin_lock(&api_lock, &old_irql, "release_appl");
862	if (this->Id) {
863		CapiRelease(this->Id);
864		mem_to_free = this->DataNCCI;
865		this->DataNCCI = NULL;
866		this->Id = 0;
867	}
868	diva_os_leave_spin_lock(&api_lock, &old_irql, "release_appl");
869
870	if (mem_to_free)
871		diva_os_free(0, mem_to_free);
872
873}
874
875/*
876 *  send message
877 */
878static u16 diva_send_message(struct capi_ctr *ctrl,
879			     diva_os_message_buffer_s *dmb)
880{
881	int i = 0;
882	word ret = 0;
883	diva_os_spin_lock_magic_t old_irql;
884	CAPI_MSG *msg = (CAPI_MSG *) DIVA_MESSAGE_BUFFER_DATA(dmb);
885	APPL *this = &application[GET_WORD(&msg->header.appl_id) - 1];
886	diva_card *card = ctrl->driverdata;
887	__u32 length = DIVA_MESSAGE_BUFFER_LEN(dmb);
888	word clength = GET_WORD(&msg->header.length);
889	word command = GET_WORD(&msg->header.command);
890	u16 retval = CAPI_NOERROR;
891
892	if (diva_os_in_irq()) {
893		DBG_ERR(("CAPI_SEND_MSG - in irq context !"))
894			return CAPI_REGOSRESOURCEERR;
895	}
896	DBG_PRV1(("Write - appl = %d, cmd = 0x%x", this->Id, command))
897
898		if (card->remove_in_progress) {
899			DBG_ERR(("CAPI_SEND_MSG - remove in progress!"))
900				return CAPI_REGOSRESOURCEERR;
901		}
902
903	diva_os_enter_spin_lock(&api_lock, &old_irql, "send message");
904
905	if (!this->Id) {
906		diva_os_leave_spin_lock(&api_lock, &old_irql, "send message");
907		return CAPI_ILLAPPNR;
908	}
909
910	/* patch controller number */
911	msg->header.controller = ControllerMap[card->Id]
912		| (msg->header.controller & 0x80);	/* preserve external controller bit */
913
914	switch (command) {
915	default:
916		xlog("\x00\x02", msg, 0x80, clength);
917		break;
918
919	case _DATA_B3_I | RESPONSE:
920#ifndef DIVA_NO_DEBUGLIB
921		if (myDriverDebugHandle.dbgMask & DL_BLK)
922			xlog("\x00\x02", msg, 0x80, clength);
923#endif
924		break;
925
926	case _DATA_B3_R:
927#ifndef DIVA_NO_DEBUGLIB
928		if (myDriverDebugHandle.dbgMask & DL_BLK)
929			xlog("\x00\x02", msg, 0x80, clength);
930#endif
931
932		if (clength == 24)
933			clength = 22;	/* workaround for PPcom bug */
934		/* header is always 22      */
935		if (GET_WORD(&msg->info.data_b3_req.Data_Length) >
936		    this->MaxDataLength
937		    || GET_WORD(&msg->info.data_b3_req.Data_Length) >
938		    (length - clength)) {
939			DBG_ERR(("Write - invalid message size"))
940				retval = CAPI_ILLCMDORSUBCMDORMSGTOSMALL;
941			goto write_end;
942		}
943
944		for (i = 0; i < (MAX_DATA_B3 * this->MaxNCCI)
945			     && this->xbuffer_used[i]; i++);
946		if (i == (MAX_DATA_B3 * this->MaxNCCI)) {
947			DBG_ERR(("Write - too many data pending"))
948				retval = CAPI_SENDQUEUEFULL;
949			goto write_end;
950		}
951		msg->info.data_b3_req.Data = i;
952
953		this->xbuffer_internal[i] = NULL;
954		memcpy(this->xbuffer_ptr[i], &((__u8 *) msg)[clength],
955		       GET_WORD(&msg->info.data_b3_req.Data_Length));
956
957#ifndef DIVA_NO_DEBUGLIB
958		if ((myDriverDebugHandle.dbgMask & DL_BLK)
959		    && (myDriverDebugHandle.dbgMask & DL_XLOG)) {
960			int j;
961			for (j = 0; j <
962				     GET_WORD(&msg->info.data_b3_req.Data_Length);
963			     j += 256) {
964				DBG_BLK((((char *) this->xbuffer_ptr[i]) + j,
965					 ((GET_WORD(&msg->info.data_b3_req.Data_Length) - j) <
966					  256) ? (GET_WORD(&msg->info.data_b3_req.Data_Length) - j) : 256))
967					if (!(myDriverDebugHandle.dbgMask & DL_PRV0))
968						break;	/* not more if not explicitly requested */
969			}
970		}
971#endif
972		break;
973	}
974
975	memcpy(mapped_msg, msg, (__u32) clength);
976	mapped_msg->header.controller = MapController(mapped_msg->header.controller);
977	mapped_msg->header.length = clength;
978	mapped_msg->header.command = command;
979	mapped_msg->header.number = GET_WORD(&msg->header.number);
980
981	ret = api_put(this, mapped_msg);
982	switch (ret) {
983	case 0:
984		break;
985	case _BAD_MSG:
986		DBG_ERR(("Write - bad message"))
987			retval = CAPI_ILLCMDORSUBCMDORMSGTOSMALL;
988		break;
989	case _QUEUE_FULL:
990		DBG_ERR(("Write - queue full"))
991			retval = CAPI_SENDQUEUEFULL;
992		break;
993	default:
994		DBG_ERR(("Write - api_put returned unknown error"))
995			retval = CAPI_UNKNOWNNOTPAR;
996		break;
997	}
998
999write_end:
1000	diva_os_leave_spin_lock(&api_lock, &old_irql, "send message");
1001	if (retval == CAPI_NOERROR)
1002		diva_os_free_message_buffer(dmb);
1003	return retval;
1004}
1005
1006
1007/*
1008 * cards request function
1009 */
1010static void DIRequest(ENTITY *e)
1011{
1012	DIVA_CAPI_ADAPTER *a = &(adapter[(byte) e->user[0]]);
1013	diva_card *os_card = (diva_card *) a->os_card;
1014
1015	if (e->Req && (a->FlowControlIdTable[e->ReqCh] == e->Id)) {
1016		a->FlowControlSkipTable[e->ReqCh] = 1;
1017	}
1018
1019	(*(os_card->d.request)) (e);
1020}
1021
1022/*
1023 * callback function from didd
1024 */
1025static void didd_callback(void *context, DESCRIPTOR *adapter, int removal)
1026{
1027	if (adapter->type == IDI_DADAPTER) {
1028		DBG_ERR(("Notification about IDI_DADAPTER change ! Oops."));
1029		return;
1030	} else if (adapter->type == IDI_DIMAINT) {
1031		if (removal) {
1032			stop_dbg();
1033		} else {
1034			memcpy(&MAdapter, adapter, sizeof(MAdapter));
1035			dprintf = (DIVA_DI_PRINTF) MAdapter.request;
1036			DbgRegister("CAPI20", DRIVERRELEASE_CAPI, DBG_DEFAULT);
1037		}
1038	} else if ((adapter->type > 0) && (adapter->type < 16)) {	/* IDI Adapter */
1039		if (removal) {
1040			divacapi_remove_card(adapter);
1041		} else {
1042			diva_add_card(adapter);
1043		}
1044	}
1045	return;
1046}
1047
1048/*
1049 * connect to didd
1050 */
1051static int divacapi_connect_didd(void)
1052{
1053	int x = 0;
1054	int dadapter = 0;
1055	IDI_SYNC_REQ req;
1056	DESCRIPTOR DIDD_Table[MAX_DESCRIPTORS];
1057
1058	DIVA_DIDD_Read(DIDD_Table, sizeof(DIDD_Table));
1059
1060	for (x = 0; x < MAX_DESCRIPTORS; x++) {
1061		if (DIDD_Table[x].type == IDI_DIMAINT) {	/* MAINT found */
1062			memcpy(&MAdapter, &DIDD_Table[x], sizeof(DAdapter));
1063			dprintf = (DIVA_DI_PRINTF) MAdapter.request;
1064			DbgRegister("CAPI20", DRIVERRELEASE_CAPI, DBG_DEFAULT);
1065			break;
1066		}
1067	}
1068	for (x = 0; x < MAX_DESCRIPTORS; x++) {
1069		if (DIDD_Table[x].type == IDI_DADAPTER) {	/* DADAPTER found */
1070			dadapter = 1;
1071			memcpy(&DAdapter, &DIDD_Table[x], sizeof(DAdapter));
1072			req.didd_notify.e.Req = 0;
1073			req.didd_notify.e.Rc =
1074				IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY;
1075			req.didd_notify.info.callback = (void *)didd_callback;
1076			req.didd_notify.info.context = NULL;
1077			DAdapter.request((ENTITY *)&req);
1078			if (req.didd_notify.e.Rc != 0xff) {
1079				stop_dbg();
1080				return (0);
1081			}
1082			notify_handle = req.didd_notify.info.handle;
1083		}
1084		else if ((DIDD_Table[x].type > 0) && (DIDD_Table[x].type < 16)) {	/* IDI Adapter found */
1085			diva_add_card(&DIDD_Table[x]);
1086		}
1087	}
1088
1089	if (!dadapter) {
1090		stop_dbg();
1091	}
1092
1093	return (dadapter);
1094}
1095
1096/*
1097 * diconnect from didd
1098 */
1099static void divacapi_disconnect_didd(void)
1100{
1101	IDI_SYNC_REQ req;
1102
1103	stop_dbg();
1104
1105	req.didd_notify.e.Req = 0;
1106	req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY;
1107	req.didd_notify.info.handle = notify_handle;
1108	DAdapter.request((ENTITY *)&req);
1109}
1110
1111/*
1112 * we do not provide date/time here,
1113 * the application should do this.
1114 */
1115int fax_head_line_time(char *buffer)
1116{
1117	return (0);
1118}
1119
1120/*
1121 * init (alloc) main structures
1122 */
1123static int __init init_main_structs(void)
1124{
1125	if (!(mapped_msg = (CAPI_MSG *) diva_os_malloc(0, MAX_MSG_SIZE))) {
1126		DBG_ERR(("init: failed alloc mapped_msg."))
1127			return 0;
1128	}
1129
1130	if (!(adapter = diva_os_malloc(0, sizeof(DIVA_CAPI_ADAPTER) * MAX_DESCRIPTORS))) {
1131		DBG_ERR(("init: failed alloc adapter struct."))
1132			diva_os_free(0, mapped_msg);
1133		return 0;
1134	}
1135	memset(adapter, 0, sizeof(DIVA_CAPI_ADAPTER) * MAX_DESCRIPTORS);
1136
1137	if (!(application = diva_os_malloc(0, sizeof(APPL) * MAX_APPL))) {
1138		DBG_ERR(("init: failed alloc application struct."))
1139			diva_os_free(0, mapped_msg);
1140		diva_os_free(0, adapter);
1141		return 0;
1142	}
1143	memset(application, 0, sizeof(APPL) * MAX_APPL);
1144
1145	return (1);
1146}
1147
1148/*
1149 * remove (free) main structures
1150 */
1151static void remove_main_structs(void)
1152{
1153	if (application)
1154		diva_os_free(0, application);
1155	if (adapter)
1156		diva_os_free(0, adapter);
1157	if (mapped_msg)
1158		diva_os_free(0, mapped_msg);
1159}
1160
1161/*
1162 * api_remove_start
1163 */
1164static void do_api_remove_start(void)
1165{
1166	diva_os_spin_lock_magic_t old_irql;
1167	int ret = 1, count = 100;
1168
1169	do {
1170		diva_os_enter_spin_lock(&api_lock, &old_irql, "api remove start");
1171		ret = api_remove_start();
1172		diva_os_leave_spin_lock(&api_lock, &old_irql, "api remove start");
1173
1174		diva_os_sleep(10);
1175	} while (ret && count--);
1176
1177	if (ret)
1178		DBG_ERR(("could not remove signaling ID's"))
1179			}
1180
1181/*
1182 * init
1183 */
1184int __init init_capifunc(void)
1185{
1186	diva_os_initialize_spin_lock(&api_lock, "capifunc");
1187	memset(ControllerMap, 0, MAX_DESCRIPTORS + 1);
1188	max_adapter = 0;
1189
1190
1191	if (!init_main_structs()) {
1192		DBG_ERR(("init: failed to init main structs."))
1193			diva_os_destroy_spin_lock(&api_lock, "capifunc");
1194		return (0);
1195	}
1196
1197	if (!divacapi_connect_didd()) {
1198		DBG_ERR(("init: failed to connect to DIDD."))
1199			do_api_remove_start();
1200		divacapi_remove_cards();
1201		remove_main_structs();
1202		diva_os_destroy_spin_lock(&api_lock, "capifunc");
1203		return (0);
1204	}
1205
1206	return (1);
1207}
1208
1209/*
1210 * finit
1211 */
1212void __exit finit_capifunc(void)
1213{
1214	do_api_remove_start();
1215	divacapi_disconnect_didd();
1216	divacapi_remove_cards();
1217	remove_main_structs();
1218	diva_os_destroy_spin_lock(&api_lock, "capifunc");
1219}
1220