Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
capifunc.c
Go to the documentation of this file.
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 ([email protected])
7  * Copyright 2000-2003 Cytronics & Melware ([email protected])
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 
29 static CAPI_MSG *mapped_msg = (CAPI_MSG *) NULL;
30 
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,
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 *,
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;
72  va_start(ap, x);
75  DLI_XLOG, x, ap);
76  } else if (myDriverDebugHandle.dbg_old) {
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  */
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 {
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;
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  */
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;
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
309  switch (command) {
310  default:
311  xlog("\x00\x02", &msg, 0x81, length);
312  break;
313  case _DATA_B3_R | CONFIRM:
315  xlog("\x00\x02", &msg, 0x81, length);
316  break;
317  case _DATA_B3_I:
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))
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))
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 {
349  int i, k;
350 
351  a = &adapter[id];
353  if (k == 0) {
354  if (li_config_table) {
355  list_add((struct list_head *)li_config_table, free_mem_q);
357  }
358  } else {
359  if (a->li_base < k) {
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],
366  k - a->li_base);
368  coef_table[a->li_base],
370  k - a->li_base);
371  }
372  }
373  }
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;
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 =
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."))
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  }
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,
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,
880 {
881  int i = 0;
882  word ret = 0;
883  diva_os_spin_lock_magic_t old_irql;
885  APPL *this = &application[GET_WORD(&msg->header.appl_id) - 1];
886  diva_card *card = ctrl->driverdata;
888  word clength = GET_WORD(&msg->header.length);
889  word command = GET_WORD(&msg->header.command);
891 
892  if (diva_os_in_irq()) {
893  DBG_ERR(("CAPI_SEND_MSG - in irq context !"))
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
922  xlog("\x00\x02", msg, 0x80, clength);
923 #endif
924  break;
925 
926  case _DATA_B3_R:
927 #ifndef DIVA_NO_DEBUGLIB
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"))
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
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)
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;
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;
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 =
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;
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  */
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  */
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  */
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 }