1/* $Id: capifunc.c,v 1.61.4.7 2005/02/11 19:40:25 armin Exp $ 2 * 3 * ISDN interface module for Eicon active cards DIVA. 4 * CAPI Interface common functions 5 * 6 * Copyright 2000-2003 by Armin Schindler (mac@melware.de) 7 * Copyright 2000-2003 Cytronics & Melware (info@melware.de) 8 * 9 * This software may be used and distributed according to the terms 10 * of the GNU General Public License, incorporated herein by reference. 11 * 12 */ 13 14#include "platform.h" 15#include "os_capi.h" 16#include "di_defs.h" 17#include "capi20.h" 18#include "divacapi.h" 19#include "divasync.h" 20#include "capifunc.h" 21 22#define DBG_MINIMUM (DL_LOG + DL_FTL + DL_ERR) 23#define DBG_DEFAULT (DBG_MINIMUM + DL_XLOG + DL_REG) 24 25DIVA_CAPI_ADAPTER *adapter = (DIVA_CAPI_ADAPTER *) NULL; 26APPL *application = (APPL *) NULL; 27byte max_appl = MAX_APPL; 28byte max_adapter = 0; 29static CAPI_MSG *mapped_msg = (CAPI_MSG *) NULL; 30 31byte UnMapController(byte); 32char DRIVERRELEASE_CAPI[32]; 33 34extern void AutomaticLaw(DIVA_CAPI_ADAPTER *); 35extern void callback(ENTITY *); 36extern word api_remove_start(void); 37extern word CapiRelease(word); 38extern word CapiRegister(word); 39extern word api_put(APPL *, CAPI_MSG *); 40 41static diva_os_spin_lock_t api_lock; 42 43static LIST_HEAD(cards); 44 45static dword notify_handle; 46static void DIRequest(ENTITY *e); 47static DESCRIPTOR MAdapter; 48static DESCRIPTOR DAdapter; 49static byte ControllerMap[MAX_DESCRIPTORS + 1]; 50 51 52static void diva_register_appl(struct capi_ctr *, __u16, 53 capi_register_params *); 54static void diva_release_appl(struct capi_ctr *, __u16); 55static char *diva_procinfo(struct capi_ctr *); 56static u16 diva_send_message(struct capi_ctr *, 57 diva_os_message_buffer_s *); 58extern void diva_os_set_controller_struct(struct capi_ctr *); 59 60extern void DIVA_DIDD_Read(DESCRIPTOR *, int); 61 62/* 63 * debug 64 */ 65static void no_printf(unsigned char *, ...); 66#include "debuglib.c" 67static 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 */ 88static char *diva_procinfo(struct capi_ctr *ctrl) 89{ 90 return (ctrl->serial); 91} 92 93/* 94 * stop debugging 95 */ 96static 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 */ 106static void no_printf(unsigned char *x, ...) 107{ 108} 109 110/* 111 * Controller mapping 112 */ 113byte 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 */ 135byte 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 */ 152static 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 */ 169static 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 */ 188void *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 195void *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 203void 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 209void *ReceiveBufferGet(APPL *appl, int Num) 210{ 211 return &appl->ReceiveBuffer[Num * appl->MaxDataLength]; 212} 213 214/* 215 * api_remove_start/complete for cleanup 216 */ 217void api_remove_complete(void) 218{ 219 DBG_PRV1(("api_remove_complete")) 220 } 221 222/* 223 * main function called by message.c 224 */ 225void 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 */ 346static 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 */ 391static 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 */ 450static 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 457rescan: 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 */ 472static 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 */ 486static 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 */ 724static 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 */ 848static 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 */ 878static 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 999write_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 */ 1010static 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 */ 1025static 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 */ 1051static 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 */ 1099static 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 */ 1115int fax_head_line_time(char *buffer) 1116{ 1117 return (0); 1118} 1119 1120/* 1121 * init (alloc) main structures 1122 */ 1123static 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 */ 1151static 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 */ 1164static 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 */ 1184int __init init_capifunc(void) 1185{ 1186 diva_os_initialize_spin_lock(&api_lock, "capifunc"); 1187 memset(ControllerMap, 0, MAX_DESCRIPTORS + 1); 1188 max_adapter = 0; 1189 1190 1191 if (!init_main_structs()) { 1192 DBG_ERR(("init: failed to init main structs.")) 1193 diva_os_destroy_spin_lock(&api_lock, "capifunc"); 1194 return (0); 1195 } 1196 1197 if (!divacapi_connect_didd()) { 1198 DBG_ERR(("init: failed to connect to DIDD.")) 1199 do_api_remove_start(); 1200 divacapi_remove_cards(); 1201 remove_main_structs(); 1202 diva_os_destroy_spin_lock(&api_lock, "capifunc"); 1203 return (0); 1204 } 1205 1206 return (1); 1207} 1208 1209/* 1210 * finit 1211 */ 1212void __exit finit_capifunc(void) 1213{ 1214 do_api_remove_start(); 1215 divacapi_disconnect_didd(); 1216 divacapi_remove_cards(); 1217 remove_main_structs(); 1218 diva_os_destroy_spin_lock(&api_lock, "capifunc"); 1219} 1220