linux/drivers/isdn/hardware/eicon/capifunc.c
<<
>>
Prefs
   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