GNU Linux-libre 4.9.311-gnu1
[releases.git] / drivers / isdn / hardware / eicon / capifunc.c
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"
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  */
88 static char *diva_procinfo(struct capi_ctr *ctrl)
89 {
90         return (ctrl->serial);
91 }
92
93 /*
94  * stop debugging
95  */
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  */
106 static void no_printf(unsigned char *x, ...)
107 {
108 }
109
110 /*
111  * Controller mapping
112  */
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  */
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  */
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  */
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  */
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
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
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
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  */
217 void api_remove_complete(void)
218 {
219         DBG_PRV1(("api_remove_complete"))
220                 }
221
222 /*
223  * main function called by message.c
224  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
1115 int fax_head_line_time(char *buffer)
1116 {
1117         return (0);
1118 }
1119
1120 /*
1121  * init (alloc) main structures
1122  */
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  */
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  */
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  */
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  */
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 }