Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/isdn/hardware/eicon/capifunc.c
15115 views
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
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 DIVA_INIT_FUNCTION 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 DIVA_INIT_FUNCTION 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 DIVA_EXIT_FUNCTION finit_capifunc(void)
1213
{
1214
do_api_remove_start();
1215
divacapi_disconnect_didd();
1216
divacapi_remove_cards();
1217
remove_main_structs();
1218
diva_os_destroy_spin_lock(&api_lock, "capifunc");
1219
}
1220
1221