Committer: Michael Beasley <mike@snafu.setup>
[mikesnafu-overlay.git] / drivers / isdn / hardware / eicon / capifunc.c
blob4d425c644d413b7d4080ea36dd0bdb1b0f694b6d
1 /* $Id: capifunc.c,v 1.61.4.7 2005/02/11 19:40:25 armin Exp $
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.
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"
22 #define DBG_MINIMUM (DL_LOG + DL_FTL + DL_ERR)
23 #define DBG_DEFAULT (DBG_MINIMUM + DL_XLOG + DL_REG)
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;
31 byte UnMapController(byte);
32 char DRIVERRELEASE_CAPI[32];
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 *);
41 static diva_os_spin_lock_t api_lock;
43 static LIST_HEAD(cards);
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];
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 *);
60 extern void DIVA_DIDD_Read(DESCRIPTOR *, int);
63 * debug
65 static void no_printf(unsigned char *, ...);
66 #include "debuglib.c"
67 static void xlog(char *x, ...)
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);
80 va_end(ap);
82 #endif
86 * info for proc
88 static char *diva_procinfo(struct capi_ctr *ctrl)
90 return (ctrl->serial);
94 * stop debugging
96 static void stop_dbg(void)
98 DbgDeregister();
99 memset(&MAdapter, 0, sizeof(MAdapter));
100 dprintf = no_printf;
104 * dummy debug function
106 static void no_printf(unsigned char *x, ...)
111 * Controller mapping
113 byte MapController(byte Controller)
115 byte i;
116 byte MappedController = 0;
117 byte ctrl = Controller & 0x7f; /* mask external controller bit off */
119 for (i = 1; i < max_adapter + 1; i++) {
120 if (ctrl == ControllerMap[i]) {
121 MappedController = (byte) i;
122 break;
125 if (i > max_adapter) {
126 ControllerMap[0] = ctrl;
127 MappedController = 0;
129 return (MappedController | (Controller & 0x80)); /* put back external controller bit */
133 * Controller unmapping
135 byte UnMapController(byte MappedController)
137 byte Controller;
138 byte ctrl = MappedController & 0x7f; /* mask external controller bit off */
140 if (ctrl <= max_adapter) {
141 Controller = ControllerMap[ctrl];
142 } else {
143 Controller = 0;
146 return (Controller | (MappedController & 0x80)); /* put back external controller bit */
150 * find a new free id
152 static int find_free_id(void)
154 int num = 0;
155 DIVA_CAPI_ADAPTER *a;
157 while (num < MAX_DESCRIPTORS) {
158 a = &adapter[num];
159 if (!a->Id)
160 break;
161 num++;
163 return(num + 1);
167 * find a card structure by controller number
169 static diva_card *find_card_by_ctrl(word controller)
171 struct list_head *tmp;
172 diva_card *card;
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);
182 return (diva_card *) 0;
186 * Buffer RX/TX
188 void *TransmitBufferSet(APPL * appl, dword ref)
190 appl->xbuffer_used[ref] = true;
191 DBG_PRV1(("%d:xbuf_used(%d)", appl->Id, ref + 1))
192 return (void *)(long)ref;
195 void *TransmitBufferGet(APPL * appl, void *p)
197 if (appl->xbuffer_internal[(dword)(long)p])
198 return appl->xbuffer_internal[(dword)(long)p];
200 return appl->xbuffer_ptr[(dword)(long)p];
203 void TransmitBufferFree(APPL * appl, void *p)
205 appl->xbuffer_used[(dword)(long)p] = false;
206 DBG_PRV1(("%d:xbuf_free(%d)", appl->Id, ((dword)(long)p) + 1))
209 void *ReceiveBufferGet(APPL * appl, int Num)
211 return &appl->ReceiveBuffer[Num * appl->MaxDataLength];
215 * api_remove_start/complete for cleanup
217 void api_remove_complete(void)
219 DBG_PRV1(("api_remove_complete"))
223 * main function called by message.c
225 void sendf(APPL * appl, word command, dword Id, word Number, byte * format, ...)
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;
237 if (!appl)
238 return;
240 DBG_PRV1(("sendf(a=%d,cmd=%x,format=%s)",
241 appl->Id, command, (byte *) format))
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);
249 PUT_DWORD(&msg.header.controller, Id);
250 write = (byte *) & msg;
251 write += 12;
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;
283 va_end(ap);
285 PUT_WORD(&msg.header.length, length);
286 msg.header.controller = UnMapController(msg.header.controller);
288 if (command == _DATA_B3_I)
289 dlength = GET_WORD(
290 ((byte *) & msg.info.data_b3_ind.Data_Length));
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;
298 /* copy msg header to sk_buff */
299 memcpy(write, (byte *) & msg, length);
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);
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 */
327 break;
330 #endif
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;
339 /* send capi msg to capi layer */
340 capi_ctr_handle_message(&card->capi_ctrl, appl->Id, dmb);
344 * cleanup adapter
346 static void clean_adapter(int id, struct list_head *free_mem_q)
348 DIVA_CAPI_ADAPTER *a;
349 int i, k;
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;
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);
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;
379 if (a->plci)
380 list_add((struct list_head *)a->plci, free_mem_q);
382 memset(a, 0x00, sizeof(DIVA_CAPI_ADAPTER));
383 while ((max_adapter != 0) && !adapter[max_adapter - 1].request)
384 max_adapter--;
388 * remove a card, but ensures consistent state of LI tables
389 * in the time adapter is removed
391 static void divacapi_remove_card(DESCRIPTOR * d)
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;
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.
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;
413 diva_os_leave_spin_lock(&api_lock, &old_irql, "remove card");
415 if (card) {
417 * Detach CAPI. Sendf cannot call to CAPI any more.
418 * After detach no call to send_message() is done too.
420 detach_capi_ctr(&card->capi_ctrl);
423 * Now get API lock (to ensure stable state of LI tables)
424 * and update the adapter map/LI table.
426 diva_os_enter_spin_lock(&api_lock, &old_irql, "remove card");
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");
436 /* After releasing the lock, we can free the memory */
437 diva_os_free (0, card);
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);
448 * remove cards
450 static void divacapi_remove_cards(void)
452 DESCRIPTOR d;
453 struct list_head *tmp;
454 diva_card *card;
455 diva_os_spin_lock_magic_t old_irql;
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;
466 diva_os_leave_spin_lock(&api_lock, &old_irql, "remove cards");
470 * sync_callback
472 static void sync_callback(ENTITY * e)
474 diva_os_spin_lock_magic_t old_irql;
476 DBG_TRC(("cb:Id=%x,Rc=%x,Ind=%x", e->Id, e->Rc, e->Ind))
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");
484 * add a new card
486 static int diva_add_card(DESCRIPTOR * d)
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;
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);
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);
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);
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");
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);
543 serial[CAPI_SERIAL_LEN - 1] = 0;
544 strlcpy(ctrl->serial, serial, sizeof(ctrl->serial));
546 a = &adapter[card->Id - 1];
547 card->adapter = a;
548 a->os_card = card;
549 ControllerMap[card->Id] = (byte) (ctrl->cnr);
551 DBG_TRC(("AddAdapterMap (%d) -> (%d)", ctrl->cnr, card->Id))
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);
572 memset(a->plci, 0, sizeof(PLCI) * a->max_plci);
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;
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;
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;
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);
632 /* Prevent access to line interconnect table in process update */
633 diva_os_enter_spin_lock(&api_lock, &old_irql, "add card");
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);
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));
670 j++;
673 li_total_channels = k;
675 mem_to_free = li_config_table;
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;
683 if (a == &adapter[max_adapter])
684 max_adapter++;
686 list_add(&(card->list), &cards);
687 AutomaticLaw(a);
689 diva_os_leave_spin_lock(&api_lock, &old_irql, "add card");
691 if (mem_to_free) {
692 diva_os_free (0, mem_to_free);
695 i = 0;
696 while (i++ < 30) {
697 if (a->automatic_law > 3)
698 break;
699 diva_os_sleep(10);
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;
715 capi_ctr_ready(ctrl);
717 DBG_TRC(("adapter added, max_adapter=%d", max_adapter));
718 return (1);
722 * register appl
724 static void diva_register_appl(struct capi_ctr *ctrl, __u16 appl,
725 capi_register_params * rp)
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;
738 if (diva_os_in_irq()) {
739 DBG_ERR(("CAPI_REGISTER - in irq context !"))
740 return;
743 DBG_TRC(("application register Id=%d", appl))
745 if (appl > MAX_APPL) {
746 DBG_ERR(("CAPI_REGISTER - appl.Id exceeds MAX_APPL"))
747 return;
750 if (nconn <= 0)
751 nconn = ctrl->profile.nbchannel * -nconn;
753 if (nconn == 0)
754 nconn = ctrl->profile.nbchannel;
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))
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;
769 if (application[appl - 1].Id == appl) {
770 DBG_LOG(("CAPI_REGISTER - appl already registered"))
771 return; /* appl already registered */
774 /* alloc memory */
776 bnum = nconn * rp->datablkcnt;
777 xnum = nconn * MAX_DATA_B3;
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] */
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;
792 memset(p, 0, mem_len);
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;
811 /* initialize application data */
812 diva_os_enter_spin_lock(&api_lock, &old_irql, "register_appl");
814 this = &application[appl - 1];
815 memset(this, 0, sizeof(APPL));
817 this->Id = appl;
819 for (i = 0; i < max_adapter; i++) {
820 adapter[i].CIP_Mask[appl - 1] = 0;
823 this->queue_size = 1000;
825 this->MaxNCCI = (byte) nconn;
826 this->MaxNCCIData = (byte) rp->datablkcnt;
827 this->MaxBuffer = bnum;
828 this->MaxDataLength = rp->datablklen;
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];
840 CapiRegister(this->Id);
841 diva_os_leave_spin_lock(&api_lock, &old_irql, "register_appl");
846 * release appl
848 static void diva_release_appl(struct capi_ctr *ctrl, __u16 appl)
850 diva_os_spin_lock_magic_t old_irql;
851 APPL *this = &application[appl - 1];
852 void *mem_to_free = NULL;
854 DBG_TRC(("application %d(%d) cleanup", this->Id, appl))
856 if (diva_os_in_irq()) {
857 DBG_ERR(("CAPI_RELEASE - in irq context !"))
858 return;
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;
868 diva_os_leave_spin_lock(&api_lock, &old_irql, "release_appl");
870 if (mem_to_free)
871 diva_os_free(0, mem_to_free);
876 * send message
878 static u16 diva_send_message(struct capi_ctr *ctrl,
879 diva_os_message_buffer_s * dmb)
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;
892 if (diva_os_in_irq()) {
893 DBG_ERR(("CAPI_SEND_MSG - in irq context !"))
894 return CAPI_REGOSRESOURCEERR;
896 DBG_PRV1(("Write - appl = %d, cmd = 0x%x", this->Id, command))
898 if (card->remove_in_progress) {
899 DBG_ERR(("CAPI_SEND_MSG - remove in progress!"))
900 return CAPI_REGOSRESOURCEERR;
903 diva_os_enter_spin_lock(&api_lock, &old_irql, "send message");
905 if (!this->Id) {
906 diva_os_leave_spin_lock(&api_lock, &old_irql, "send message");
907 return CAPI_ILLAPPNR;
910 /* patch controller number */
911 msg->header.controller = ControllerMap[card->Id]
912 | (msg->header.controller & 0x80); /* preserve external controller bit */
914 switch (command) {
915 default:
916 xlog("\x00\x02", msg, 0x80, clength);
917 break;
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;
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
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;
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;
951 msg->info.data_b3_req.Data = i;
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));
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 */
971 #endif
972 break;
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);
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;
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;
1008 * cards request function
1010 static void DIRequest(ENTITY * e)
1012 DIVA_CAPI_ADAPTER *a = &(adapter[(byte) e->user[0]]);
1013 diva_card *os_card = (diva_card *) a->os_card;
1015 if (e->Req && (a->FlowControlIdTable[e->ReqCh] == e->Id)) {
1016 a->FlowControlSkipTable[e->ReqCh] = 1;
1019 (*(os_card->d.request)) (e);
1023 * callback function from didd
1025 static void didd_callback(void *context, DESCRIPTOR * adapter, int removal)
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);
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);
1045 return;
1049 * connect to didd
1051 static int divacapi_connect_didd(void)
1053 int x = 0;
1054 int dadapter = 0;
1055 IDI_SYNC_REQ req;
1056 DESCRIPTOR DIDD_Table[MAX_DESCRIPTORS];
1058 DIVA_DIDD_Read(DIDD_Table, sizeof(DIDD_Table));
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;
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);
1082 notify_handle = req.didd_notify.info.handle;
1084 else if ((DIDD_Table[x].type > 0) && (DIDD_Table[x].type < 16)) { /* IDI Adapter found */
1085 diva_add_card(&DIDD_Table[x]);
1089 if (!dadapter) {
1090 stop_dbg();
1093 return (dadapter);
1097 * diconnect from didd
1099 static void divacapi_disconnect_didd(void)
1101 IDI_SYNC_REQ req;
1103 stop_dbg();
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);
1112 * we do not provide date/time here,
1113 * the application should do this.
1115 int fax_head_line_time(char *buffer)
1117 return (0);
1121 * init (alloc) main structures
1123 static int DIVA_INIT_FUNCTION init_main_structs(void)
1125 if (!(mapped_msg = (CAPI_MSG *) diva_os_malloc(0, MAX_MSG_SIZE))) {
1126 DBG_ERR(("init: failed alloc mapped_msg."))
1127 return 0;
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;
1135 memset(adapter, 0, sizeof(DIVA_CAPI_ADAPTER) * MAX_DESCRIPTORS);
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;
1143 memset(application, 0, sizeof(APPL) * MAX_APPL);
1145 return (1);
1149 * remove (free) main structures
1151 static void remove_main_structs(void)
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);
1162 * api_remove_start
1164 static void do_api_remove_start(void)
1166 diva_os_spin_lock_magic_t old_irql;
1167 int ret = 1, count = 100;
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");
1174 diva_os_sleep(10);
1175 } while (ret && count--);
1177 if (ret)
1178 DBG_ERR(("could not remove signaling ID's"))
1182 * init
1184 int DIVA_INIT_FUNCTION init_capifunc(void)
1186 diva_os_initialize_spin_lock(&api_lock, "capifunc");
1187 memset(ControllerMap, 0, MAX_DESCRIPTORS + 1);
1188 max_adapter = 0;
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);
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);
1206 return (1);
1210 * finit
1212 void DIVA_EXIT_FUNCTION finit_capifunc(void)
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");