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 
25 DIVA_CAPI_ADAPTER *adapter = (DIVA_CAPI_ADAPTER *) NULL;
26 APPL *application = (APPL *) NULL;
27 byte max_appl = MAX_APPL;
28 byte max_adapter = 0;
29 static CAPI_MSG *mapped_msg = (CAPI_MSG *) NULL;
30 
31 byte UnMapController(byte);
32 char DRIVERRELEASE_CAPI[32];
33 
34 extern void AutomaticLaw(DIVA_CAPI_ADAPTER *);
35 extern void callback(ENTITY *);
36 extern word api_remove_start(void);
37 extern word CapiRelease(word);
38 extern word CapiRegister(word);
39 extern word api_put(APPL *, CAPI_MSG *);
40 
41 static diva_os_spin_lock_t api_lock;
42 
43 static LIST_HEAD(cards);
44 
45 static dword notify_handle;
46 static void DIRequest(ENTITY *e);
47 static DESCRIPTOR MAdapter;
48 static DESCRIPTOR DAdapter;
49 static byte ControllerMap[MAX_DESCRIPTORS + 1];
50 
51 
52 static void diva_register_appl(struct capi_ctr *, __u16,
53 			       capi_register_params *);
54 static void diva_release_appl(struct capi_ctr *, __u16);
55 static char *diva_procinfo(struct capi_ctr *);
56 static u16 diva_send_message(struct capi_ctr *,
57 			     diva_os_message_buffer_s *);
58 extern void diva_os_set_controller_struct(struct capi_ctr *);
59 
60 extern void DIVA_DIDD_Read(DESCRIPTOR *, int);
61 
62 /*
63  * debug
64  */
65 static void no_printf(unsigned char *, ...);
66 #include "debuglib.c"
xlog(char * x,...)67 static 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  */
diva_procinfo(struct capi_ctr * ctrl)88 static char *diva_procinfo(struct capi_ctr *ctrl)
89 {
90 	return (ctrl->serial);
91 }
92 
93 /*
94  * stop debugging
95  */
stop_dbg(void)96 static 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  */
no_printf(unsigned char * x,...)106 static void no_printf(unsigned char *x, ...)
107 {
108 }
109 
110 /*
111  * Controller mapping
112  */
MapController(byte Controller)113 byte 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  */
UnMapController(byte MappedController)135 byte 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  */
find_free_id(void)152 static 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  */
find_card_by_ctrl(word controller)169 static 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  */
TransmitBufferSet(APPL * appl,dword ref)188 void *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 
TransmitBufferGet(APPL * appl,void * p)195 void *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 
TransmitBufferFree(APPL * appl,void * p)203 void 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 
ReceiveBufferGet(APPL * appl,int Num)209 void *ReceiveBufferGet(APPL *appl, int Num)
210 {
211 	return &appl->ReceiveBuffer[Num * appl->MaxDataLength];
212 }
213 
214 /*
215  * api_remove_start/complete for cleanup
216  */
api_remove_complete(void)217 void api_remove_complete(void)
218 {
219 	DBG_PRV1(("api_remove_complete"))
220 		}
221 
222 /*
223  * main function called by message.c
224  */
sendf(APPL * appl,word command,dword Id,word Number,byte * format,...)225 void 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  */
clean_adapter(int id,struct list_head * free_mem_q)346 static 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  */
divacapi_remove_card(DESCRIPTOR * d)391 static 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  */
divacapi_remove_cards(void)450 static 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 
457 rescan:
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  */
sync_callback(ENTITY * e)472 static 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  */
diva_add_card(DESCRIPTOR * d)486 static 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  */
diva_register_appl(struct capi_ctr * ctrl,__u16 appl,capi_register_params * rp)724 static 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  */
diva_release_appl(struct capi_ctr * ctrl,__u16 appl)848 static 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  */
diva_send_message(struct capi_ctr * ctrl,diva_os_message_buffer_s * dmb)878 static 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 
999 write_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  */
DIRequest(ENTITY * e)1010 static 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  */
didd_callback(void * context,DESCRIPTOR * adapter,int removal)1025 static 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  */
divacapi_connect_didd(void)1051 static 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  */
divacapi_disconnect_didd(void)1099 static 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  */
fax_head_line_time(char * buffer)1115 int fax_head_line_time(char *buffer)
1116 {
1117 	return (0);
1118 }
1119 
1120 /*
1121  * init (alloc) main structures
1122  */
init_main_structs(void)1123 static 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  */
remove_main_structs(void)1151 static 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  */
do_api_remove_start(void)1164 static 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  */
init_capifunc(void)1184 int __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  */
finit_capifunc(void)1212 void __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