1 /* $Id: capifunc.c,v 1.61.4.7 2005/02/11 19:40:25 armin Exp $
3 * ISDN interface module for Eicon active cards DIVA.
4 * CAPI Interface common functions
6 * Copyright 2000-2003 by Armin Schindler (mac@melware.de)
7 * Copyright 2000-2003 Cytronics & Melware (info@melware.de)
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
22 #define DBG_MINIMUM (DL_LOG + DL_FTL + DL_ERR)
23 #define DBG_DEFAULT (DBG_MINIMUM + DL_XLOG + DL_REG)
25 DIVA_CAPI_ADAPTER
*adapter
= (DIVA_CAPI_ADAPTER
*) NULL
;
26 APPL
*application
= (APPL
*) NULL
;
27 byte max_appl
= MAX_APPL
;
29 static CAPI_MSG
*mapped_msg
= (CAPI_MSG
*) NULL
;
31 byte
UnMapController(byte
);
32 char DRIVERRELEASE_CAPI
[32];
34 extern void AutomaticLaw(DIVA_CAPI_ADAPTER
*);
35 extern void callback(ENTITY
*);
36 extern word
api_remove_start(void);
37 extern word
CapiRelease(word
);
38 extern word
CapiRegister(word
);
39 extern word
api_put(APPL
*, CAPI_MSG
*);
41 static diva_os_spin_lock_t api_lock
;
43 static LIST_HEAD(cards
);
45 static dword notify_handle
;
46 static void DIRequest(ENTITY
* e
);
47 static DESCRIPTOR MAdapter
;
48 static DESCRIPTOR DAdapter
;
49 static byte ControllerMap
[MAX_DESCRIPTORS
+ 1];
52 static void diva_register_appl(struct capi_ctr
*, __u16
,
53 capi_register_params
*);
54 static void diva_release_appl(struct capi_ctr
*, __u16
);
55 static char *diva_procinfo(struct capi_ctr
*);
56 static u16
diva_send_message(struct capi_ctr
*,
57 diva_os_message_buffer_s
*);
58 extern void diva_os_set_controller_struct(struct capi_ctr
*);
60 extern void DIVA_DIDD_Read(DESCRIPTOR
*, int);
65 static void no_printf(unsigned char *, ...);
67 static void xlog(char *x
, ...)
69 #ifndef DIVA_NO_DEBUGLIB
71 if (myDriverDebugHandle
.dbgMask
& DL_XLOG
) {
73 if (myDriverDebugHandle
.dbg_irq
) {
74 myDriverDebugHandle
.dbg_irq(myDriverDebugHandle
.id
,
76 } else if (myDriverDebugHandle
.dbg_old
) {
77 myDriverDebugHandle
.dbg_old(myDriverDebugHandle
.id
,
88 static char *diva_procinfo(struct capi_ctr
*ctrl
)
90 return (ctrl
->serial
);
96 static void stop_dbg(void)
99 memset(&MAdapter
, 0, sizeof(MAdapter
));
104 * dummy debug function
106 static void no_printf(unsigned char *x
, ...)
113 byte
MapController(byte Controller
)
116 byte MappedController
= 0;
117 byte ctrl
= Controller
& 0x7f; /* mask external controller bit off */
119 for (i
= 1; i
< max_adapter
+ 1; i
++) {
120 if (ctrl
== ControllerMap
[i
]) {
121 MappedController
= (byte
) i
;
125 if (i
> max_adapter
) {
126 ControllerMap
[0] = ctrl
;
127 MappedController
= 0;
129 return (MappedController
| (Controller
& 0x80)); /* put back external controller bit */
133 * Controller unmapping
135 byte
UnMapController(byte MappedController
)
138 byte ctrl
= MappedController
& 0x7f; /* mask external controller bit off */
140 if (ctrl
<= max_adapter
) {
141 Controller
= ControllerMap
[ctrl
];
146 return (Controller
| (MappedController
& 0x80)); /* put back external controller bit */
152 static int find_free_id(void)
155 DIVA_CAPI_ADAPTER
*a
;
157 while (num
< MAX_DESCRIPTORS
) {
167 * find a card structure by controller number
169 static diva_card
*find_card_by_ctrl(word controller
)
171 struct list_head
*tmp
;
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
)
182 return (diva_card
*) 0;
188 void *TransmitBufferSet(APPL
* appl
, dword ref
)
190 appl
->xbuffer_used
[ref
] = TRUE
;
191 DBG_PRV1(("%d:xbuf_used(%d)", appl
->Id
, ref
+ 1))
195 void *TransmitBufferGet(APPL
* appl
, void *p
)
197 if (appl
->xbuffer_internal
[(dword
) p
])
198 return appl
->xbuffer_internal
[(dword
) p
];
200 return appl
->xbuffer_ptr
[(dword
) p
];
203 void TransmitBufferFree(APPL
* appl
, void *p
)
205 appl
->xbuffer_used
[(dword
) p
] = FALSE
;
206 DBG_PRV1(("%d:xbuf_free(%d)", appl
->Id
, ((dword
) p
) + 1))
209 void *ReceiveBufferGet(APPL
* appl
, int Num
)
211 return &appl
->ReceiveBuffer
[Num
* appl
->MaxDataLength
];
215 * api_remove_start/complete for cleanup
217 void api_remove_complete(void)
219 DBG_PRV1(("api_remove_complete"))
223 * main function called by message.c
225 void sendf(APPL
* appl
, word command
, dword Id
, word Number
, byte
* format
, ...)
228 word length
= 12, dlength
= 0;
233 diva_os_message_buffer_s
*dmb
;
234 diva_card
*card
= NULL
;
240 DBG_PRV1(("sendf(a=%d,cmd=%x,format=%s)",
241 appl
->Id
, command
, (byte
*) format
))
243 PUT_WORD(&msg
.header
.appl_id
, appl
->Id
);
244 PUT_WORD(&msg
.header
.command
, command
);
245 if ((byte
) (command
>> 8) == 0x82)
246 Number
= appl
->Number
++;
247 PUT_WORD(&msg
.header
.number
, Number
);
249 PUT_DWORD(&msg
.header
.controller
, Id
);
250 write
= (byte
*) & msg
;
253 va_start(ap
, format
);
254 for (i
= 0; format
[i
]; i
++) {
257 tmp
= va_arg(ap
, dword
);
258 *(byte
*) write
= (byte
) (tmp
& 0xff);
263 tmp
= va_arg(ap
, dword
);
264 PUT_WORD(write
, (tmp
& 0xffff));
269 tmp
= va_arg(ap
, dword
);
270 PUT_DWORD(write
, tmp
);
276 string
= va_arg(ap
, byte
*);
277 length
+= string
[0] + 1;
278 for (j
= 0; j
<= string
[0]; j
++)
279 *write
++ = string
[j
];
285 PUT_WORD(&msg
.header
.length
, length
);
286 msg
.header
.controller
= UnMapController(msg
.header
.controller
);
288 if (command
== _DATA_B3_I
)
290 ((byte
*) & msg
.info
.data_b3_ind
.Data_Length
));
292 if (!(dmb
= diva_os_alloc_message_buffer(length
+ dlength
,
293 (void **) &write
))) {
294 DBG_ERR(("sendf: alloc_message_buffer failed, incoming msg dropped."))
298 /* copy msg header to sk_buff */
299 memcpy(write
, (byte
*) & msg
, length
);
301 /* if DATA_B3_IND, copy data too */
302 if (command
== _DATA_B3_I
) {
303 dword data
= GET_DWORD(&msg
.info
.data_b3_ind
.Data
);
304 memcpy(write
+ length
, (void *) data
, dlength
);
307 #ifndef DIVA_NO_DEBUGLIB
308 if (myDriverDebugHandle
.dbgMask
& DL_XLOG
) {
311 xlog("\x00\x02", &msg
, 0x81, length
);
313 case _DATA_B3_R
| CONFIRM
:
314 if (myDriverDebugHandle
.dbgMask
& DL_BLK
)
315 xlog("\x00\x02", &msg
, 0x81, length
);
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 *) 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 explicitely requested */
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",
336 diva_os_free_message_buffer(dmb
);
339 /* send capi msg to capi layer */
340 capi_ctr_handle_message(&card
->capi_ctrl
, appl
->Id
, dmb
);
346 static void clean_adapter(int id
, struct list_head
*free_mem_q
)
348 DIVA_CAPI_ADAPTER
*a
;
352 k
= li_total_channels
- a
->li_channels
;
354 if (li_config_table
) {
355 list_add((struct list_head
*)li_config_table
, free_mem_q
);
356 li_config_table
= NULL
;
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
],
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
],
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
;
380 list_add((struct list_head
*)a
->plci
, free_mem_q
);
382 memset(a
, 0x00, sizeof(DIVA_CAPI_ADAPTER
));
383 while ((max_adapter
!= 0) && !adapter
[max_adapter
- 1].request
)
388 * remove a card, but ensures consistent state of LI tables
389 * in the time adapter is removed
391 static void divacapi_remove_card(DESCRIPTOR
* d
)
393 diva_card
*card
= NULL
;
394 diva_os_spin_lock_magic_t old_irql
;
395 LIST_HEAD(free_mem_q
);
396 struct list_head
*link
;
397 struct list_head
*tmp
;
400 * Set "remove in progress flag".
401 * Ensures that there is no call from sendf to CAPI in
402 * the time CAPI controller is about to be removed.
404 diva_os_enter_spin_lock(&api_lock
, &old_irql
, "remove card");
405 list_for_each(tmp
, &cards
) {
406 card
= list_entry(tmp
, diva_card
, list
);
407 if (card
->d
.request
== d
->request
) {
408 card
->remove_in_progress
= 1;
413 diva_os_leave_spin_lock(&api_lock
, &old_irql
, "remove card");
417 * Detach CAPI. Sendf cannot call to CAPI any more.
418 * After detach no call to send_message() is done too.
420 detach_capi_ctr(&card
->capi_ctrl
);
423 * Now get API lock (to ensure stable state of LI tables)
424 * and update the adapter map/LI table.
426 diva_os_enter_spin_lock(&api_lock
, &old_irql
, "remove card");
428 clean_adapter(card
->Id
- 1, &free_mem_q
);
429 DBG_TRC(("DelAdapterMap (%d) -> (%d)",
430 ControllerMap
[card
->Id
], card
->Id
))
431 ControllerMap
[card
->Id
] = 0;
432 DBG_TRC(("adapter remove, max_adapter=%d",
434 diva_os_leave_spin_lock(&api_lock
, &old_irql
, "remove card");
436 /* After releasing the lock, we can free the memory */
437 diva_os_free (0, card
);
440 /* free queued memory areas */
441 list_for_each_safe(link
, tmp
, &free_mem_q
) {
443 diva_os_free(0, link
);
450 static void divacapi_remove_cards(void)
453 struct list_head
*tmp
;
455 diva_os_spin_lock_magic_t old_irql
;
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
);
466 diva_os_leave_spin_lock(&api_lock
, &old_irql
, "remove cards");
472 static void sync_callback(ENTITY
* e
)
474 diva_os_spin_lock_magic_t old_irql
;
476 DBG_TRC(("cb:Id=%x,Rc=%x,Ind=%x", e
->Id
, e
->Rc
, e
->Ind
))
478 diva_os_enter_spin_lock(&api_lock
, &old_irql
, "sync_callback");
480 diva_os_leave_spin_lock(&api_lock
, &old_irql
, "sync_callback");
486 static int diva_add_card(DESCRIPTOR
* d
)
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
;
496 LI_CONFIG
*new_li_config_table
;
499 if (!(card
= (diva_card
*) diva_os_malloc(0, sizeof(diva_card
)))) {
500 DBG_ERR(("diva_add_card: failed to allocate card struct."))
503 memset((char *) card
, 0x00, sizeof(diva_card
));
504 memcpy(&card
->d
, d
, sizeof(DESCRIPTOR
));
505 sync_req
.GetName
.Req
= 0;
506 sync_req
.GetName
.Rc
= IDI_SYNC_REQ_GET_NAME
;
507 card
->d
.request((ENTITY
*) & sync_req
);
508 strlcpy(card
->name
, sync_req
.GetName
.name
, sizeof(card
->name
));
509 ctrl
= &card
->capi_ctrl
;
510 strcpy(ctrl
->name
, card
->name
);
511 ctrl
->register_appl
= diva_register_appl
;
512 ctrl
->release_appl
= diva_release_appl
;
513 ctrl
->send_message
= diva_send_message
;
514 ctrl
->procinfo
= diva_procinfo
;
515 ctrl
->driverdata
= card
;
516 diva_os_set_controller_struct(ctrl
);
518 if (attach_capi_ctr(ctrl
)) {
519 DBG_ERR(("diva_add_card: failed to attach controller."))
520 diva_os_free(0, card
);
524 diva_os_enter_spin_lock(&api_lock
, &old_irql
, "find id");
525 card
->Id
= find_free_id();
526 diva_os_leave_spin_lock(&api_lock
, &old_irql
, "find id");
528 strlcpy(ctrl
->manu
, M_COMPANY
, sizeof(ctrl
->manu
));
529 ctrl
->version
.majorversion
= 2;
530 ctrl
->version
.minorversion
= 0;
531 ctrl
->version
.majormanuversion
= DRRELMAJOR
;
532 ctrl
->version
.minormanuversion
= DRRELMINOR
;
533 sync_req
.GetSerial
.Req
= 0;
534 sync_req
.GetSerial
.Rc
= IDI_SYNC_REQ_GET_SERIAL
;
535 sync_req
.GetSerial
.serial
= 0;
536 card
->d
.request((ENTITY
*) & sync_req
);
537 if ((i
= ((sync_req
.GetSerial
.serial
& 0xff000000) >> 24))) {
538 sprintf(serial
, "%ld-%d",
539 sync_req
.GetSerial
.serial
& 0x00ffffff, i
+ 1);
541 sprintf(serial
, "%ld", sync_req
.GetSerial
.serial
);
543 serial
[CAPI_SERIAL_LEN
- 1] = 0;
544 strlcpy(ctrl
->serial
, serial
, sizeof(ctrl
->serial
));
546 a
= &adapter
[card
->Id
- 1];
549 ControllerMap
[card
->Id
] = (byte
) (ctrl
->cnr
);
551 DBG_TRC(("AddAdapterMap (%d) -> (%d)", ctrl
->cnr
, card
->Id
))
553 sync_req
.xdi_capi_prms
.Req
= 0;
554 sync_req
.xdi_capi_prms
.Rc
= IDI_SYNC_REQ_XDI_GET_CAPI_PARAMS
;
555 sync_req
.xdi_capi_prms
.info
.structure_length
=
556 sizeof(diva_xdi_get_capi_parameters_t
);
557 card
->d
.request((ENTITY
*) & sync_req
);
558 a
->flag_dynamic_l1_down
=
559 sync_req
.xdi_capi_prms
.info
.flag_dynamic_l1_down
;
560 a
->group_optimization_enabled
=
561 sync_req
.xdi_capi_prms
.info
.group_optimization_enabled
;
562 a
->request
= DIRequest
; /* card->d.request; */
563 a
->max_plci
= card
->d
.channels
+ 30;
564 a
->max_listen
= (card
->d
.channels
> 2) ? 8 : 2;
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
));
572 memset(a
->plci
, 0, sizeof(PLCI
) * a
->max_plci
);
574 for (k
= 0; k
< a
->max_plci
; k
++) {
575 a
->Id
= (byte
) card
->Id
;
576 a
->plci
[k
].Sig
.callback
= sync_callback
;
577 a
->plci
[k
].Sig
.XNum
= 1;
578 a
->plci
[k
].Sig
.X
= a
->plci
[k
].XData
;
579 a
->plci
[k
].Sig
.user
[0] = (word
) (card
->Id
- 1);
580 a
->plci
[k
].Sig
.user
[1] = (word
) k
;
581 a
->plci
[k
].NL
.callback
= sync_callback
;
582 a
->plci
[k
].NL
.XNum
= 1;
583 a
->plci
[k
].NL
.X
= a
->plci
[k
].XData
;
584 a
->plci
[k
].NL
.user
[0] = (word
) ((card
->Id
- 1) | 0x8000);
585 a
->plci
[k
].NL
.user
[1] = (word
) k
;
586 a
->plci
[k
].adapter
= a
;
589 a
->profile
.Number
= card
->Id
;
590 a
->profile
.Channels
= card
->d
.channels
;
591 if (card
->d
.features
& DI_FAX3
) {
592 a
->profile
.Global_Options
= 0x71;
593 if (card
->d
.features
& DI_CODEC
)
594 a
->profile
.Global_Options
|= 0x6;
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
;
607 a
->profile
.Global_Options
= 0x71;
608 if (card
->d
.features
& DI_CODEC
)
609 a
->profile
.Global_Options
|= 0x2;
610 a
->profile
.B1_Protocols
= 0x43;
611 a
->profile
.B2_Protocols
= 0x1f0f;
612 a
->profile
.B3_Protocols
= 0x07;
613 a
->manufacturer_features
= 0;
616 a
->li_pri
= (a
->profile
.Channels
> 2);
617 a
->li_channels
= a
->li_pri
? MIXER_CHANNELS_PRI
: MIXER_CHANNELS_BRI
;
619 for (i
= 0; &adapter
[i
] != a
; i
++) {
620 if (adapter
[i
].request
)
621 a
->li_base
= adapter
[i
].li_base
+ adapter
[i
].li_channels
;
623 k
= li_total_channels
+ a
->li_channels
;
624 new_li_config_table
=
625 (LI_CONFIG
*) diva_os_malloc(0, ((k
* sizeof(LI_CONFIG
) + 3) & ~3) + (2 * k
) * ((k
+ 3) & ~3));
626 if (new_li_config_table
== NULL
) {
627 DBG_ERR(("diva_add_card: failed alloc li_config table."))
628 memset(a
, 0, sizeof(DIVA_CAPI_ADAPTER
));
632 /* Prevent access to line interconnect table in process update */
633 diva_os_enter_spin_lock(&api_lock
, &old_irql
, "add card");
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
));
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
);
650 if (a
->li_base
!= 0) {
651 memcpy(&new_li_config_table
[i
].flag_table
[0],
652 &li_config_table
[j
].flag_table
[0],
654 memcpy(&new_li_config_table
[i
].coef_table
[0],
655 &li_config_table
[j
].coef_table
[0],
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
+
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
+
667 &li_config_table
[j
].coef_table
[a
->li_base
],
668 k
- (a
->li_base
+ a
->li_channels
));
673 li_total_channels
= k
;
675 mem_to_free
= li_config_table
;
677 li_config_table
= new_li_config_table
;
678 for (i
= card
->Id
; i
< max_adapter
; i
++) {
679 if (adapter
[i
].request
)
680 adapter
[i
].li_base
+= a
->li_channels
;
683 if (a
== &adapter
[max_adapter
])
686 list_add(&(card
->list
), &cards
);
689 diva_os_leave_spin_lock(&api_lock
, &old_irql
, "add card");
692 diva_os_free (0, mem_to_free
);
697 if (a
->automatic_law
> 3)
702 /* profile information */
703 PUT_WORD(&ctrl
->profile
.nbchannel
, card
->d
.channels
);
704 ctrl
->profile
.goptions
= a
->profile
.Global_Options
;
705 ctrl
->profile
.support1
= a
->profile
.B1_Protocols
;
706 ctrl
->profile
.support2
= a
->profile
.B2_Protocols
;
707 ctrl
->profile
.support3
= a
->profile
.B3_Protocols
;
708 /* manufacturer profile information */
709 ctrl
->profile
.manu
[0] = a
->man_profile
.private_options
;
710 ctrl
->profile
.manu
[1] = a
->man_profile
.rtp_primary_payloads
;
711 ctrl
->profile
.manu
[2] = a
->man_profile
.rtp_additional_payloads
;
712 ctrl
->profile
.manu
[3] = 0;
713 ctrl
->profile
.manu
[4] = 0;
715 capi_ctr_ready(ctrl
);
717 DBG_TRC(("adapter added, max_adapter=%d", max_adapter
));
724 static void diva_register_appl(struct capi_ctr
*ctrl
, __u16 appl
,
725 capi_register_params
* rp
)
731 void *DataNCCI
, *DataFlags
, *ReceiveBuffer
, *xbuffer_used
;
732 void **xbuffer_ptr
, **xbuffer_internal
;
733 diva_os_spin_lock_magic_t old_irql
;
734 unsigned int mem_len
;
735 int nconn
= rp
->level3cnt
;
738 if (diva_os_in_irq()) {
739 DBG_ERR(("CAPI_REGISTER - in irq context !"))
743 DBG_TRC(("application register Id=%d", appl
))
745 if (appl
> MAX_APPL
) {
746 DBG_ERR(("CAPI_REGISTER - appl.Id exceeds MAX_APPL"))
751 nconn
= ctrl
->profile
.nbchannel
* -nconn
;
754 nconn
= ctrl
->profile
.nbchannel
;
756 DBG_LOG(("CAPI_REGISTER - Id = %d", appl
))
757 DBG_LOG((" MaxLogicalConnections = %d(%d)", nconn
, rp
->level3cnt
))
758 DBG_LOG((" MaxBDataBuffers = %d", rp
->datablkcnt
))
759 DBG_LOG((" MaxBDataLength = %d", rp
->datablklen
))
763 rp
->datablklen
< 80 ||
764 rp
->datablklen
> 2150 || rp
->datablkcnt
> 255) {
765 DBG_ERR(("CAPI_REGISTER - invalid parameters"))
769 if (application
[appl
- 1].Id
== appl
) {
770 DBG_LOG(("CAPI_REGISTER - appl already registered"))
771 return; /* appl already registered */
776 bnum
= nconn
* rp
->datablkcnt
;
777 xnum
= nconn
* MAX_DATA_B3
;
779 mem_len
= bnum
* sizeof(word
); /* DataNCCI */
780 mem_len
+= bnum
* sizeof(word
); /* DataFlags */
781 mem_len
+= bnum
* rp
->datablklen
; /* ReceiveBuffer */
782 mem_len
+= xnum
; /* xbuffer_used */
783 mem_len
+= xnum
* sizeof(void *); /* xbuffer_ptr */
784 mem_len
+= xnum
* sizeof(void *); /* xbuffer_internal */
785 mem_len
+= xnum
* rp
->datablklen
; /* xbuffer_ptr[xnum] */
787 DBG_LOG((" Allocated Memory = %d", mem_len
))
788 if (!(p
= diva_os_malloc(0, mem_len
))) {
789 DBG_ERR(("CAPI_REGISTER - memory allocation failed"))
792 memset(p
, 0, mem_len
);
794 DataNCCI
= (void *)p
;
795 p
+= bnum
* sizeof(word
);
796 DataFlags
= (void *)p
;
797 p
+= bnum
* sizeof(word
);
798 ReceiveBuffer
= (void *)p
;
799 p
+= bnum
* rp
->datablklen
;
800 xbuffer_used
= (void *)p
;
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
;
811 /* initialize application data */
812 diva_os_enter_spin_lock(&api_lock
, &old_irql
, "register_appl");
814 this = &application
[appl
- 1];
815 memset(this, 0, sizeof(APPL
));
819 for (i
= 0; i
< max_adapter
; i
++) {
820 adapter
[i
].CIP_Mask
[appl
- 1] = 0;
823 this->queue_size
= 1000;
825 this->MaxNCCI
= (byte
) nconn
;
826 this->MaxNCCIData
= (byte
) rp
->datablkcnt
;
827 this->MaxBuffer
= bnum
;
828 this->MaxDataLength
= rp
->datablklen
;
830 this->DataNCCI
= DataNCCI
;
831 this->DataFlags
= DataFlags
;
832 this->ReceiveBuffer
= ReceiveBuffer
;
833 this->xbuffer_used
= xbuffer_used
;
834 this->xbuffer_ptr
= xbuffer_ptr
;
835 this->xbuffer_internal
= xbuffer_internal
;
836 for (i
= 0; i
< xnum
; i
++) {
837 this->xbuffer_ptr
[i
] = xbuffer_ptr
[i
];
840 CapiRegister(this->Id
);
841 diva_os_leave_spin_lock(&api_lock
, &old_irql
, "register_appl");
848 static void diva_release_appl(struct capi_ctr
*ctrl
, __u16 appl
)
850 diva_os_spin_lock_magic_t old_irql
;
851 APPL
*this = &application
[appl
- 1];
852 void *mem_to_free
= NULL
;
854 DBG_TRC(("application %d(%d) cleanup", this->Id
, appl
))
856 if (diva_os_in_irq()) {
857 DBG_ERR(("CAPI_RELEASE - in irq context !"))
861 diva_os_enter_spin_lock(&api_lock
, &old_irql
, "release_appl");
863 CapiRelease(this->Id
);
864 mem_to_free
= this->DataNCCI
;
865 this->DataNCCI
= NULL
;
868 diva_os_leave_spin_lock(&api_lock
, &old_irql
, "release_appl");
871 diva_os_free(0, mem_to_free
);
878 static u16
diva_send_message(struct capi_ctr
*ctrl
,
879 diva_os_message_buffer_s
* dmb
)
883 diva_os_spin_lock_magic_t old_irql
;
884 CAPI_MSG
*msg
= (CAPI_MSG
*) DIVA_MESSAGE_BUFFER_DATA(dmb
);
885 APPL
*this = &application
[GET_WORD(&msg
->header
.appl_id
) - 1];
886 diva_card
*card
= ctrl
->driverdata
;
887 __u32 length
= DIVA_MESSAGE_BUFFER_LEN(dmb
);
888 word clength
= GET_WORD(&msg
->header
.length
);
889 word command
= GET_WORD(&msg
->header
.command
);
890 u16 retval
= CAPI_NOERROR
;
892 if (diva_os_in_irq()) {
893 DBG_ERR(("CAPI_SEND_MSG - in irq context !"))
894 return CAPI_REGOSRESOURCEERR
;
896 DBG_PRV1(("Write - appl = %d, cmd = 0x%x", this->Id
, command
))
898 if (card
->remove_in_progress
) {
899 DBG_ERR(("CAPI_SEND_MSG - remove in progress!"))
900 return CAPI_REGOSRESOURCEERR
;
903 diva_os_enter_spin_lock(&api_lock
, &old_irql
, "send message");
906 diva_os_leave_spin_lock(&api_lock
, &old_irql
, "send message");
907 return CAPI_ILLAPPNR
;
910 /* patch controller number */
911 msg
->header
.controller
= ControllerMap
[card
->Id
]
912 | (msg
->header
.controller
& 0x80); /* preserve external controller bit */
916 xlog("\x00\x02", msg
, 0x80, clength
);
919 case _DATA_B3_I
| RESPONSE
:
920 #ifndef DIVA_NO_DEBUGLIB
921 if (myDriverDebugHandle
.dbgMask
& DL_BLK
)
922 xlog("\x00\x02", msg
, 0x80, clength
);
927 #ifndef DIVA_NO_DEBUGLIB
928 if (myDriverDebugHandle
.dbgMask
& DL_BLK
)
929 xlog("\x00\x02", msg
, 0x80, clength
);
933 clength
= 22; /* workaround for PPcom bug */
934 /* header is always 22 */
935 if (GET_WORD(&msg
->info
.data_b3_req
.Data_Length
) >
937 || GET_WORD(&msg
->info
.data_b3_req
.Data_Length
) >
938 (length
- clength
)) {
939 DBG_ERR(("Write - invalid message size"))
940 retval
= CAPI_ILLCMDORSUBCMDORMSGTOSMALL
;
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
;
951 msg
->info
.data_b3_req
.Data
= i
;
953 this->xbuffer_internal
[i
] = NULL
;
954 memcpy(this->xbuffer_ptr
[i
], &((__u8
*) msg
)[clength
],
955 GET_WORD(&msg
->info
.data_b3_req
.Data_Length
));
957 #ifndef DIVA_NO_DEBUGLIB
958 if ((myDriverDebugHandle
.dbgMask
& DL_BLK
)
959 && (myDriverDebugHandle
.dbgMask
& DL_XLOG
)) {
962 GET_WORD(&msg
->info
.data_b3_req
.Data_Length
);
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 explicitely requested */
975 memcpy(mapped_msg
, msg
, (__u32
) clength
);
976 mapped_msg
->header
.controller
= MapController(mapped_msg
->header
.controller
);
977 mapped_msg
->header
.length
= clength
;
978 mapped_msg
->header
.command
= command
;
979 mapped_msg
->header
.number
= GET_WORD(&msg
->header
.number
);
981 ret
= api_put(this, mapped_msg
);
986 DBG_ERR(("Write - bad message"))
987 retval
= CAPI_ILLCMDORSUBCMDORMSGTOSMALL
;
990 DBG_ERR(("Write - queue full"))
991 retval
= CAPI_SENDQUEUEFULL
;
994 DBG_ERR(("Write - api_put returned unknown error"))
995 retval
= CAPI_UNKNOWNNOTPAR
;
1000 diva_os_leave_spin_lock(&api_lock
, &old_irql
, "send message");
1001 if (retval
== CAPI_NOERROR
)
1002 diva_os_free_message_buffer(dmb
);
1008 * cards request function
1010 static void DIRequest(ENTITY
* e
)
1012 DIVA_CAPI_ADAPTER
*a
= &(adapter
[(byte
) e
->user
[0]]);
1013 diva_card
*os_card
= (diva_card
*) a
->os_card
;
1015 if (e
->Req
&& (a
->FlowControlIdTable
[e
->ReqCh
] == e
->Id
)) {
1016 a
->FlowControlSkipTable
[e
->ReqCh
] = 1;
1019 (*(os_card
->d
.request
)) (e
);
1023 * callback function from didd
1025 static void didd_callback(void *context
, DESCRIPTOR
* adapter
, int removal
)
1027 if (adapter
->type
== IDI_DADAPTER
) {
1028 DBG_ERR(("Notification about IDI_DADAPTER change ! Oops."));
1030 } else if (adapter
->type
== IDI_DIMAINT
) {
1034 memcpy(&MAdapter
, adapter
, sizeof(MAdapter
));
1035 dprintf
= (DIVA_DI_PRINTF
) MAdapter
.request
;
1036 DbgRegister("CAPI20", DRIVERRELEASE_CAPI
, DBG_DEFAULT
);
1038 } else if ((adapter
->type
> 0) && (adapter
->type
< 16)) { /* IDI Adapter */
1040 divacapi_remove_card(adapter
);
1042 diva_add_card(adapter
);
1051 static int divacapi_connect_didd(void)
1056 DESCRIPTOR DIDD_Table
[MAX_DESCRIPTORS
];
1058 DIVA_DIDD_Read(DIDD_Table
, sizeof(DIDD_Table
));
1060 for (x
= 0; x
< MAX_DESCRIPTORS
; x
++) {
1061 if (DIDD_Table
[x
].type
== IDI_DIMAINT
) { /* MAINT found */
1062 memcpy(&MAdapter
, &DIDD_Table
[x
], sizeof(DAdapter
));
1063 dprintf
= (DIVA_DI_PRINTF
) MAdapter
.request
;
1064 DbgRegister("CAPI20", DRIVERRELEASE_CAPI
, DBG_DEFAULT
);
1068 for (x
= 0; x
< MAX_DESCRIPTORS
; x
++) {
1069 if (DIDD_Table
[x
].type
== IDI_DADAPTER
) { /* DADAPTER found */
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) {
1082 notify_handle
= req
.didd_notify
.info
.handle
;
1084 else if ((DIDD_Table
[x
].type
> 0) && (DIDD_Table
[x
].type
< 16)) { /* IDI Adapter found */
1085 diva_add_card(&DIDD_Table
[x
]);
1097 * diconnect from didd
1099 static void divacapi_disconnect_didd(void)
1105 req
.didd_notify
.e
.Req
= 0;
1106 req
.didd_notify
.e
.Rc
= IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY
;
1107 req
.didd_notify
.info
.handle
= notify_handle
;
1108 DAdapter
.request((ENTITY
*) & req
);
1112 * we do not provide date/time here,
1113 * the application should do this.
1115 int fax_head_line_time(char *buffer
)
1121 * init (alloc) main structures
1123 static int DIVA_INIT_FUNCTION
init_main_structs(void)
1125 if (!(mapped_msg
= (CAPI_MSG
*) diva_os_malloc(0, MAX_MSG_SIZE
))) {
1126 DBG_ERR(("init: failed alloc mapped_msg."))
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
);
1135 memset(adapter
, 0, sizeof(DIVA_CAPI_ADAPTER
) * MAX_DESCRIPTORS
);
1137 if (!(application
= diva_os_malloc(0, sizeof(APPL
) * MAX_APPL
))) {
1138 DBG_ERR(("init: failed alloc application struct."))
1139 diva_os_free(0, mapped_msg
);
1140 diva_os_free(0, adapter
);
1143 memset(application
, 0, sizeof(APPL
) * MAX_APPL
);
1149 * remove (free) main structures
1151 static void remove_main_structs(void)
1154 diva_os_free(0, application
);
1156 diva_os_free(0, adapter
);
1158 diva_os_free(0, mapped_msg
);
1164 static void do_api_remove_start(void)
1166 diva_os_spin_lock_magic_t old_irql
;
1167 int ret
= 1, count
= 100;
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");
1175 } while (ret
&& count
--);
1178 DBG_ERR(("could not remove signaling ID's"))
1184 int DIVA_INIT_FUNCTION
init_capifunc(void)
1186 diva_os_initialize_spin_lock(&api_lock
, "capifunc");
1187 memset(ControllerMap
, 0, MAX_DESCRIPTORS
+ 1);
1191 if (!init_main_structs()) {
1192 DBG_ERR(("init: failed to init main structs."))
1193 diva_os_destroy_spin_lock(&api_lock
, "capifunc");
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");
1212 void DIVA_EXIT_FUNCTION
finit_capifunc(void)
1214 do_api_remove_start();
1215 divacapi_disconnect_didd();
1216 divacapi_remove_cards();
1217 remove_main_structs();
1218 diva_os_destroy_spin_lock(&api_lock
, "capifunc");