linux/drivers/isdn/capi/capidrv.c
<<
>>
Prefs
   1/* $Id: capidrv.c,v 1.1.2.2 2004/01/12 23:17:24 keil Exp $
   2 *
   3 * ISDN4Linux Driver, using capi20 interface (kernelcapi)
   4 *
   5 * Copyright 1997 by Carsten Paeth <calle@calle.de>
   6 *
   7 * This software may be used and distributed according to the terms
   8 * of the GNU General Public License, incorporated herein by reference.
   9 *
  10 */
  11
  12#include <linux/module.h>
  13#include <linux/errno.h>
  14#include <linux/kernel.h>
  15#include <linux/major.h>
  16#include <linux/slab.h>
  17#include <linux/fcntl.h>
  18#include <linux/fs.h>
  19#include <linux/signal.h>
  20#include <linux/mm.h>
  21#include <linux/timer.h>
  22#include <linux/wait.h>
  23#include <linux/skbuff.h>
  24#include <linux/isdn.h>
  25#include <linux/isdnif.h>
  26#include <linux/proc_fs.h>
  27#include <linux/seq_file.h>
  28#include <linux/capi.h>
  29#include <linux/kernelcapi.h>
  30#include <linux/ctype.h>
  31#include <linux/init.h>
  32#include <linux/moduleparam.h>
  33
  34#include <linux/isdn/capiutil.h>
  35#include <linux/isdn/capicmd.h>
  36#include "capidrv.h"
  37
  38static int debugmode = 0;
  39
  40MODULE_DESCRIPTION("CAPI4Linux: Interface to ISDN4Linux");
  41MODULE_AUTHOR("Carsten Paeth");
  42MODULE_LICENSE("GPL");
  43module_param(debugmode, uint, S_IRUGO|S_IWUSR);
  44
  45/* -------- type definitions ----------------------------------------- */
  46
  47
  48struct capidrv_contr {
  49
  50        struct capidrv_contr *next;
  51        struct module *owner;
  52        u32 contrnr;
  53        char name[20];
  54
  55        /*
  56         * for isdn4linux
  57         */
  58        isdn_if interface;
  59        int myid;
  60
  61        /*
  62         * LISTEN state
  63         */
  64        int state;
  65        u32 cipmask;
  66        u32 cipmask2;
  67        struct timer_list listentimer;
  68
  69        /*
  70         * ID of capi message sent
  71         */
  72        u16 msgid;
  73
  74        /*
  75         * B-Channels
  76         */
  77        int nbchan;
  78        struct capidrv_bchan {
  79                struct capidrv_contr *contr;
  80                u8 msn[ISDN_MSNLEN];
  81                int l2;
  82                int l3;
  83                u8 num[ISDN_MSNLEN];
  84                u8 mynum[ISDN_MSNLEN];
  85                int si1;
  86                int si2;
  87                int incoming;
  88                int disconnecting;
  89                struct capidrv_plci {
  90                        struct capidrv_plci *next;
  91                        u32 plci;
  92                        u32 ncci;       /* ncci for CONNECT_ACTIVE_IND */
  93                        u16 msgid;      /* to identfy CONNECT_CONF */
  94                        int chan;
  95                        int state;
  96                        int leasedline;
  97                        struct capidrv_ncci {
  98                                struct capidrv_ncci *next;
  99                                struct capidrv_plci *plcip;
 100                                u32 ncci;
 101                                u16 msgid;      /* to identfy CONNECT_B3_CONF */
 102                                int chan;
 103                                int state;
 104                                int oldstate;
 105                                /* */
 106                                u16 datahandle;
 107                                struct ncci_datahandle_queue {
 108                                    struct ncci_datahandle_queue *next;
 109                                    u16                         datahandle;
 110                                    int                           len;
 111                                } *ackqueue;
 112                        } *ncci_list;
 113                } *plcip;
 114                struct capidrv_ncci *nccip;
 115        } *bchans;
 116
 117        struct capidrv_plci *plci_list;
 118
 119        /* for q931 data */
 120        u8  q931_buf[4096];
 121        u8 *q931_read;
 122        u8 *q931_write;
 123        u8 *q931_end;
 124};
 125
 126
 127struct capidrv_data {
 128        struct capi20_appl ap;
 129        int ncontr;
 130        struct capidrv_contr *contr_list;
 131};
 132
 133typedef struct capidrv_plci capidrv_plci;
 134typedef struct capidrv_ncci capidrv_ncci;
 135typedef struct capidrv_contr capidrv_contr;
 136typedef struct capidrv_data capidrv_data;
 137typedef struct capidrv_bchan capidrv_bchan;
 138
 139/* -------- data definitions ----------------------------------------- */
 140
 141static capidrv_data global;
 142static DEFINE_SPINLOCK(global_lock);
 143
 144static void handle_dtrace_data(capidrv_contr *card,
 145        int send, int level2, u8 *data, u16 len);
 146
 147/* -------- convert functions ---------------------------------------- */
 148
 149static inline u32 b1prot(int l2, int l3)
 150{
 151        switch (l2) {
 152        case ISDN_PROTO_L2_X75I:
 153        case ISDN_PROTO_L2_X75UI:
 154        case ISDN_PROTO_L2_X75BUI:
 155                return 0;
 156        case ISDN_PROTO_L2_HDLC:
 157        default:
 158                return 0;
 159        case ISDN_PROTO_L2_TRANS:
 160                return 1;
 161        case ISDN_PROTO_L2_V11096:
 162        case ISDN_PROTO_L2_V11019:
 163        case ISDN_PROTO_L2_V11038:
 164                return 2;
 165        case ISDN_PROTO_L2_FAX:
 166                return 4;
 167        case ISDN_PROTO_L2_MODEM:
 168                return 8;
 169        }
 170}
 171
 172static inline u32 b2prot(int l2, int l3)
 173{
 174        switch (l2) {
 175        case ISDN_PROTO_L2_X75I:
 176        case ISDN_PROTO_L2_X75UI:
 177        case ISDN_PROTO_L2_X75BUI:
 178        default:
 179                return 0;
 180        case ISDN_PROTO_L2_HDLC:
 181        case ISDN_PROTO_L2_TRANS:
 182        case ISDN_PROTO_L2_V11096:
 183        case ISDN_PROTO_L2_V11019:
 184        case ISDN_PROTO_L2_V11038:
 185        case ISDN_PROTO_L2_MODEM:
 186                return 1;
 187        case ISDN_PROTO_L2_FAX:
 188                return 4;
 189        }
 190}
 191
 192static inline u32 b3prot(int l2, int l3)
 193{
 194        switch (l2) {
 195        case ISDN_PROTO_L2_X75I:
 196        case ISDN_PROTO_L2_X75UI:
 197        case ISDN_PROTO_L2_X75BUI:
 198        case ISDN_PROTO_L2_HDLC:
 199        case ISDN_PROTO_L2_TRANS:
 200        case ISDN_PROTO_L2_V11096:
 201        case ISDN_PROTO_L2_V11019:
 202        case ISDN_PROTO_L2_V11038:
 203        case ISDN_PROTO_L2_MODEM:
 204        default:
 205                return 0;
 206        case ISDN_PROTO_L2_FAX:
 207                return 4;
 208        }
 209}
 210
 211static _cstruct b1config_async_v110(u16 rate)
 212{
 213        /* CAPI-Spec "B1 Configuration" */
 214        static unsigned char buf[9];
 215        buf[0] = 8; /* len */
 216        /* maximum bitrate */
 217        buf[1] = rate & 0xff; buf[2] = (rate >> 8) & 0xff;
 218        buf[3] = 8; buf[4] = 0; /* 8 bits per character */
 219        buf[5] = 0; buf[6] = 0; /* parity none */
 220        buf[7] = 0; buf[8] = 0; /* 1 stop bit */
 221        return buf;
 222}
 223
 224static _cstruct b1config(int l2, int l3)
 225{
 226        switch (l2) {
 227        case ISDN_PROTO_L2_X75I:
 228        case ISDN_PROTO_L2_X75UI:
 229        case ISDN_PROTO_L2_X75BUI:
 230        case ISDN_PROTO_L2_HDLC:
 231        case ISDN_PROTO_L2_TRANS:
 232        default:
 233                return NULL;
 234        case ISDN_PROTO_L2_V11096:
 235            return b1config_async_v110(9600);
 236        case ISDN_PROTO_L2_V11019:
 237            return b1config_async_v110(19200);
 238        case ISDN_PROTO_L2_V11038:
 239            return b1config_async_v110(38400);
 240        }
 241}
 242
 243static inline u16 si2cip(u8 si1, u8 si2)
 244{
 245        static const u8 cip[17][5] =
 246        {
 247        /*  0  1  2  3  4  */
 248                {0, 0, 0, 0, 0},        /*0 */
 249                {16, 16, 4, 26, 16},    /*1 */
 250                {17, 17, 17, 4, 4},     /*2 */
 251                {2, 2, 2, 2, 2},        /*3 */
 252                {18, 18, 18, 18, 18},   /*4 */
 253                {2, 2, 2, 2, 2},        /*5 */
 254                {0, 0, 0, 0, 0},        /*6 */
 255                {2, 2, 2, 2, 2},        /*7 */
 256                {2, 2, 2, 2, 2},        /*8 */
 257                {21, 21, 21, 21, 21},   /*9 */
 258                {19, 19, 19, 19, 19},   /*10 */
 259                {0, 0, 0, 0, 0},        /*11 */
 260                {0, 0, 0, 0, 0},        /*12 */
 261                {0, 0, 0, 0, 0},        /*13 */
 262                {0, 0, 0, 0, 0},        /*14 */
 263                {22, 22, 22, 22, 22},   /*15 */
 264                {27, 27, 27, 28, 27}    /*16 */
 265        };
 266        if (si1 > 16)
 267                si1 = 0;
 268        if (si2 > 4)
 269                si2 = 0;
 270
 271        return (u16) cip[si1][si2];
 272}
 273
 274static inline u8 cip2si1(u16 cipval)
 275{
 276        static const u8 si[32] =
 277        {7, 1, 7, 7, 1, 1, 7, 7,        /*0-7 */
 278         7, 1, 0, 0, 0, 0, 0, 0,        /*8-15 */
 279         1, 2, 4, 10, 9, 9, 15, 7,      /*16-23 */
 280         7, 7, 1, 16, 16, 0, 0, 0};     /*24-31 */
 281
 282        if (cipval > 31)
 283                cipval = 0;     /* .... */
 284        return si[cipval];
 285}
 286
 287static inline u8 cip2si2(u16 cipval)
 288{
 289        static const u8 si[32] =
 290        {0, 0, 0, 0, 2, 3, 0, 0,        /*0-7 */
 291         0, 3, 0, 0, 0, 0, 0, 0,        /*8-15 */
 292         1, 2, 0, 0, 9, 0, 0, 0,        /*16-23 */
 293         0, 0, 3, 2, 3, 0, 0, 0};       /*24-31 */
 294
 295        if (cipval > 31)
 296                cipval = 0;     /* .... */
 297        return si[cipval];
 298}
 299
 300
 301/* -------- controller management ------------------------------------- */
 302
 303static inline capidrv_contr *findcontrbydriverid(int driverid)
 304{
 305        unsigned long flags;
 306        capidrv_contr *p;
 307
 308        spin_lock_irqsave(&global_lock, flags);
 309        for (p = global.contr_list; p; p = p->next)
 310                if (p->myid == driverid)
 311                        break;
 312        spin_unlock_irqrestore(&global_lock, flags);
 313        return p;
 314}
 315
 316static capidrv_contr *findcontrbynumber(u32 contr)
 317{
 318        unsigned long flags;
 319        capidrv_contr *p = global.contr_list;
 320
 321        spin_lock_irqsave(&global_lock, flags);
 322        for (p = global.contr_list; p; p = p->next)
 323                if (p->contrnr == contr)
 324                        break;
 325        spin_unlock_irqrestore(&global_lock, flags);
 326        return p;
 327}
 328
 329
 330/* -------- plci management ------------------------------------------ */
 331
 332static capidrv_plci *new_plci(capidrv_contr * card, int chan)
 333{
 334        capidrv_plci *plcip;
 335
 336        plcip = kzalloc(sizeof(capidrv_plci), GFP_ATOMIC);
 337
 338        if (plcip == NULL)
 339                return NULL;
 340
 341        plcip->state = ST_PLCI_NONE;
 342        plcip->plci = 0;
 343        plcip->msgid = 0;
 344        plcip->chan = chan;
 345        plcip->next = card->plci_list;
 346        card->plci_list = plcip;
 347        card->bchans[chan].plcip = plcip;
 348
 349        return plcip;
 350}
 351
 352static capidrv_plci *find_plci_by_plci(capidrv_contr * card, u32 plci)
 353{
 354        capidrv_plci *p;
 355        for (p = card->plci_list; p; p = p->next)
 356                if (p->plci == plci)
 357                        return p;
 358        return NULL;
 359}
 360
 361static capidrv_plci *find_plci_by_msgid(capidrv_contr * card, u16 msgid)
 362{
 363        capidrv_plci *p;
 364        for (p = card->plci_list; p; p = p->next)
 365                if (p->msgid == msgid)
 366                        return p;
 367        return NULL;
 368}
 369
 370static capidrv_plci *find_plci_by_ncci(capidrv_contr * card, u32 ncci)
 371{
 372        capidrv_plci *p;
 373        for (p = card->plci_list; p; p = p->next)
 374                if (p->plci == (ncci & 0xffff))
 375                        return p;
 376        return NULL;
 377}
 378
 379static void free_plci(capidrv_contr * card, capidrv_plci * plcip)
 380{
 381        capidrv_plci **pp;
 382
 383        for (pp = &card->plci_list; *pp; pp = &(*pp)->next) {
 384                if (*pp == plcip) {
 385                        *pp = (*pp)->next;
 386                        card->bchans[plcip->chan].plcip = NULL;
 387                        card->bchans[plcip->chan].disconnecting = 0;
 388                        card->bchans[plcip->chan].incoming = 0;
 389                        kfree(plcip);
 390                        return;
 391                }
 392        }
 393        printk(KERN_ERR "capidrv-%d: free_plci %p (0x%x) not found, Huh?\n",
 394               card->contrnr, plcip, plcip->plci);
 395}
 396
 397/* -------- ncci management ------------------------------------------ */
 398
 399static inline capidrv_ncci *new_ncci(capidrv_contr * card,
 400                                     capidrv_plci * plcip,
 401                                     u32 ncci)
 402{
 403        capidrv_ncci *nccip;
 404
 405        nccip = kzalloc(sizeof(capidrv_ncci), GFP_ATOMIC);
 406
 407        if (nccip == NULL)
 408                return NULL;
 409
 410        nccip->ncci = ncci;
 411        nccip->state = ST_NCCI_NONE;
 412        nccip->plcip = plcip;
 413        nccip->chan = plcip->chan;
 414        nccip->datahandle = 0;
 415
 416        nccip->next = plcip->ncci_list;
 417        plcip->ncci_list = nccip;
 418
 419        card->bchans[plcip->chan].nccip = nccip;
 420
 421        return nccip;
 422}
 423
 424static inline capidrv_ncci *find_ncci(capidrv_contr * card, u32 ncci)
 425{
 426        capidrv_plci *plcip;
 427        capidrv_ncci *p;
 428
 429        if ((plcip = find_plci_by_ncci(card, ncci)) == NULL)
 430                return NULL;
 431
 432        for (p = plcip->ncci_list; p; p = p->next)
 433                if (p->ncci == ncci)
 434                        return p;
 435        return NULL;
 436}
 437
 438static inline capidrv_ncci *find_ncci_by_msgid(capidrv_contr * card,
 439                                               u32 ncci, u16 msgid)
 440{
 441        capidrv_plci *plcip;
 442        capidrv_ncci *p;
 443
 444        if ((plcip = find_plci_by_ncci(card, ncci)) == NULL)
 445                return NULL;
 446
 447        for (p = plcip->ncci_list; p; p = p->next)
 448                if (p->msgid == msgid)
 449                        return p;
 450        return NULL;
 451}
 452
 453static void free_ncci(capidrv_contr * card, struct capidrv_ncci *nccip)
 454{
 455        struct capidrv_ncci **pp;
 456
 457        for (pp = &(nccip->plcip->ncci_list); *pp; pp = &(*pp)->next) {
 458                if (*pp == nccip) {
 459                        *pp = (*pp)->next;
 460                        break;
 461                }
 462        }
 463        card->bchans[nccip->chan].nccip = NULL;
 464        kfree(nccip);
 465}
 466
 467static int capidrv_add_ack(struct capidrv_ncci *nccip,
 468                           u16 datahandle, int len)
 469{
 470        struct ncci_datahandle_queue *n, **pp;
 471
 472        n = (struct ncci_datahandle_queue *)
 473                kmalloc(sizeof(struct ncci_datahandle_queue), GFP_ATOMIC);
 474        if (!n) {
 475           printk(KERN_ERR "capidrv: kmalloc ncci_datahandle failed\n");
 476           return -1;
 477        }
 478        n->next = NULL;
 479        n->datahandle = datahandle;
 480        n->len = len;
 481        for (pp = &nccip->ackqueue; *pp; pp = &(*pp)->next) ;
 482        *pp = n;
 483        return 0;
 484}
 485
 486static int capidrv_del_ack(struct capidrv_ncci *nccip, u16 datahandle)
 487{
 488        struct ncci_datahandle_queue **pp, *p;
 489        int len;
 490
 491        for (pp = &nccip->ackqueue; *pp; pp = &(*pp)->next) {
 492                if ((*pp)->datahandle == datahandle) {
 493                        p = *pp;
 494                        len = p->len;
 495                        *pp = (*pp)->next;
 496                        kfree(p);
 497                        return len;
 498                }
 499        }
 500        return -1;
 501}
 502
 503/* -------- convert and send capi message ---------------------------- */
 504
 505static void send_message(capidrv_contr * card, _cmsg * cmsg)
 506{
 507        struct sk_buff *skb;
 508        size_t len;
 509
 510        capi_cmsg2message(cmsg, cmsg->buf);
 511        len = CAPIMSG_LEN(cmsg->buf);
 512        skb = alloc_skb(len, GFP_ATOMIC);
 513        if (!skb) {
 514                printk(KERN_ERR "capidrv::send_message: can't allocate mem\n");
 515                return;
 516        }
 517        memcpy(skb_put(skb, len), cmsg->buf, len);
 518        if (capi20_put_message(&global.ap, skb) != CAPI_NOERROR)
 519                kfree_skb(skb);
 520}
 521
 522/* -------- state machine -------------------------------------------- */
 523
 524struct listenstatechange {
 525        int actstate;
 526        int nextstate;
 527        int event;
 528};
 529
 530static struct listenstatechange listentable[] =
 531{
 532  {ST_LISTEN_NONE, ST_LISTEN_WAIT_CONF, EV_LISTEN_REQ},
 533  {ST_LISTEN_ACTIVE, ST_LISTEN_ACTIVE_WAIT_CONF, EV_LISTEN_REQ},
 534  {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_ERROR},
 535  {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_ERROR},
 536  {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY},
 537  {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY},
 538  {ST_LISTEN_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK},
 539  {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK},
 540  {},
 541};
 542
 543static void listen_change_state(capidrv_contr * card, int event)
 544{
 545        struct listenstatechange *p = listentable;
 546        while (p->event) {
 547                if (card->state == p->actstate && p->event == event) {
 548                        if (debugmode)
 549                                printk(KERN_DEBUG "capidrv-%d: listen_change_state %d -> %d\n",
 550                                       card->contrnr, card->state, p->nextstate);
 551                        card->state = p->nextstate;
 552                        return;
 553                }
 554                p++;
 555        }
 556        printk(KERN_ERR "capidrv-%d: listen_change_state state=%d event=%d ????\n",
 557               card->contrnr, card->state, event);
 558
 559}
 560
 561/* ------------------------------------------------------------------ */
 562
 563static void p0(capidrv_contr * card, capidrv_plci * plci)
 564{
 565        isdn_ctrl cmd;
 566
 567        card->bchans[plci->chan].contr = NULL;
 568        cmd.command = ISDN_STAT_DHUP;
 569        cmd.driver = card->myid;
 570        cmd.arg = plci->chan;
 571        card->interface.statcallb(&cmd);
 572        free_plci(card, plci);
 573}
 574
 575/* ------------------------------------------------------------------ */
 576
 577struct plcistatechange {
 578        int actstate;
 579        int nextstate;
 580        int event;
 581        void (*changefunc) (capidrv_contr * card, capidrv_plci * plci);
 582};
 583
 584static struct plcistatechange plcitable[] =
 585{
 586  /* P-0 */
 587  {ST_PLCI_NONE, ST_PLCI_OUTGOING, EV_PLCI_CONNECT_REQ, NULL},
 588  {ST_PLCI_NONE, ST_PLCI_ALLOCATED, EV_PLCI_FACILITY_IND_UP, NULL},
 589  {ST_PLCI_NONE, ST_PLCI_INCOMING, EV_PLCI_CONNECT_IND, NULL},
 590  {ST_PLCI_NONE, ST_PLCI_RESUMEING, EV_PLCI_RESUME_REQ, NULL},
 591  /* P-0.1 */
 592  {ST_PLCI_OUTGOING, ST_PLCI_NONE, EV_PLCI_CONNECT_CONF_ERROR, p0},
 593  {ST_PLCI_OUTGOING, ST_PLCI_ALLOCATED, EV_PLCI_CONNECT_CONF_OK, NULL},
 594  /* P-1 */
 595  {ST_PLCI_ALLOCATED, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, NULL},
 596  {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, NULL},
 597  {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, NULL},
 598  {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, NULL},
 599  /* P-ACT */
 600  {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, NULL},
 601  {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, NULL},
 602  {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, NULL},
 603  {ST_PLCI_ACTIVE, ST_PLCI_HELD, EV_PLCI_HOLD_IND, NULL},
 604  {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_SUSPEND_IND, NULL},
 605  /* P-2 */
 606  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, NULL},
 607  {ST_PLCI_INCOMING, ST_PLCI_FACILITY_IND, EV_PLCI_FACILITY_IND_UP, NULL},
 608  {ST_PLCI_INCOMING, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_RESP, NULL},
 609  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, NULL},
 610  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, NULL},
 611  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, NULL},
 612  {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CD_IND, NULL},
 613  /* P-3 */
 614  {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, NULL},
 615  {ST_PLCI_FACILITY_IND, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_ACTIVE_IND, NULL},
 616  {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, NULL},
 617  {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, NULL},
 618  {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, NULL},
 619  /* P-4 */
 620  {ST_PLCI_ACCEPTING, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, NULL},
 621  {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, NULL},
 622  {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, NULL},
 623  {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, NULL},
 624  /* P-5 */
 625  {ST_PLCI_DISCONNECTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, NULL},
 626  /* P-6 */
 627  {ST_PLCI_DISCONNECTED, ST_PLCI_NONE, EV_PLCI_DISCONNECT_RESP, p0},
 628  /* P-0.Res */
 629  {ST_PLCI_RESUMEING, ST_PLCI_NONE, EV_PLCI_RESUME_CONF_ERROR, p0},
 630  {ST_PLCI_RESUMEING, ST_PLCI_RESUME, EV_PLCI_RESUME_CONF_OK, NULL},
 631  /* P-RES */
 632  {ST_PLCI_RESUME, ST_PLCI_ACTIVE, EV_PLCI_RESUME_IND, NULL},
 633  /* P-HELD */
 634  {ST_PLCI_HELD, ST_PLCI_ACTIVE, EV_PLCI_RETRIEVE_IND, NULL},
 635  {},
 636};
 637
 638static void plci_change_state(capidrv_contr * card, capidrv_plci * plci, int event)
 639{
 640        struct plcistatechange *p = plcitable;
 641        while (p->event) {
 642                if (plci->state == p->actstate && p->event == event) {
 643                        if (debugmode)
 644                                printk(KERN_DEBUG "capidrv-%d: plci_change_state:0x%x %d -> %d\n",
 645                                  card->contrnr, plci->plci, plci->state, p->nextstate);
 646                        plci->state = p->nextstate;
 647                        if (p->changefunc)
 648                                p->changefunc(card, plci);
 649                        return;
 650                }
 651                p++;
 652        }
 653        printk(KERN_ERR "capidrv-%d: plci_change_state:0x%x state=%d event=%d ????\n",
 654               card->contrnr, plci->plci, plci->state, event);
 655}
 656
 657/* ------------------------------------------------------------------ */
 658
 659static _cmsg cmsg;
 660
 661static void n0(capidrv_contr * card, capidrv_ncci * ncci)
 662{
 663        isdn_ctrl cmd;
 664
 665        capi_fill_DISCONNECT_REQ(&cmsg,
 666                                 global.ap.applid,
 667                                 card->msgid++,
 668                                 ncci->plcip->plci,
 669                                 NULL,  /* BChannelinformation */
 670                                 NULL,  /* Keypadfacility */
 671                                 NULL,  /* Useruserdata */   /* $$$$ */
 672                                 NULL   /* Facilitydataarray */
 673        );
 674        plci_change_state(card, ncci->plcip, EV_PLCI_DISCONNECT_REQ);
 675        send_message(card, &cmsg);
 676
 677        cmd.command = ISDN_STAT_BHUP;
 678        cmd.driver = card->myid;
 679        cmd.arg = ncci->chan;
 680        card->interface.statcallb(&cmd);
 681        free_ncci(card, ncci);
 682}
 683
 684/* ------------------------------------------------------------------ */
 685
 686struct nccistatechange {
 687        int actstate;
 688        int nextstate;
 689        int event;
 690        void (*changefunc) (capidrv_contr * card, capidrv_ncci * ncci);
 691};
 692
 693static struct nccistatechange nccitable[] =
 694{
 695  /* N-0 */
 696  {ST_NCCI_NONE, ST_NCCI_OUTGOING, EV_NCCI_CONNECT_B3_REQ, NULL},
 697  {ST_NCCI_NONE, ST_NCCI_INCOMING, EV_NCCI_CONNECT_B3_IND, NULL},
 698  /* N-0.1 */
 699  {ST_NCCI_OUTGOING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_CONF_OK, NULL},
 700  {ST_NCCI_OUTGOING, ST_NCCI_NONE, EV_NCCI_CONNECT_B3_CONF_ERROR, n0},
 701  /* N-1 */
 702  {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_CONNECT_B3_REJECT, NULL},
 703  {ST_NCCI_INCOMING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_RESP, NULL},
 704  {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, NULL},
 705  {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, NULL},
 706  /* N-2 */
 707  {ST_NCCI_ALLOCATED, ST_NCCI_ACTIVE, EV_NCCI_CONNECT_B3_ACTIVE_IND, NULL},
 708  {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, NULL},
 709  {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, NULL},
 710  /* N-ACT */
 711  {ST_NCCI_ACTIVE, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, NULL},
 712  {ST_NCCI_ACTIVE, ST_NCCI_RESETING, EV_NCCI_RESET_B3_REQ, NULL},
 713  {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, NULL},
 714  {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, NULL},
 715  /* N-3 */
 716  {ST_NCCI_RESETING, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, NULL},
 717  {ST_NCCI_RESETING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, NULL},
 718  {ST_NCCI_RESETING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, NULL},
 719  /* N-4 */
 720  {ST_NCCI_DISCONNECTING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, NULL},
 721  {ST_NCCI_DISCONNECTING, ST_NCCI_PREVIOUS, EV_NCCI_DISCONNECT_B3_CONF_ERROR,NULL},
 722  /* N-5 */
 723  {ST_NCCI_DISCONNECTED, ST_NCCI_NONE, EV_NCCI_DISCONNECT_B3_RESP, n0},
 724  {},
 725};
 726
 727static void ncci_change_state(capidrv_contr * card, capidrv_ncci * ncci, int event)
 728{
 729        struct nccistatechange *p = nccitable;
 730        while (p->event) {
 731                if (ncci->state == p->actstate && p->event == event) {
 732                        if (debugmode)
 733                                printk(KERN_DEBUG "capidrv-%d: ncci_change_state:0x%x %d -> %d\n",
 734                                  card->contrnr, ncci->ncci, ncci->state, p->nextstate);
 735                        if (p->nextstate == ST_NCCI_PREVIOUS) {
 736                                ncci->state = ncci->oldstate;
 737                                ncci->oldstate = p->actstate;
 738                        } else {
 739                                ncci->oldstate = p->actstate;
 740                                ncci->state = p->nextstate;
 741                        }
 742                        if (p->changefunc)
 743                                p->changefunc(card, ncci);
 744                        return;
 745                }
 746                p++;
 747        }
 748        printk(KERN_ERR "capidrv-%d: ncci_change_state:0x%x state=%d event=%d ????\n",
 749               card->contrnr, ncci->ncci, ncci->state, event);
 750}
 751
 752/* ------------------------------------------------------------------- */
 753
 754static inline int new_bchan(capidrv_contr * card)
 755{
 756        int i;
 757        for (i = 0; i < card->nbchan; i++) {
 758                if (card->bchans[i].plcip == NULL) {
 759                        card->bchans[i].disconnecting = 0;
 760                        return i;
 761                }
 762        }
 763        return -1;
 764}
 765
 766/* ------------------------------------------------------------------- */
 767
 768static void handle_controller(_cmsg * cmsg)
 769{
 770        capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f);
 771
 772        if (!card) {
 773                printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n",
 774                       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 775                       cmsg->adr.adrController & 0x7f);
 776                return;
 777        }
 778        switch (CAPICMD(cmsg->Command, cmsg->Subcommand)) {
 779
 780        case CAPI_LISTEN_CONF:  /* Controller */
 781                if (debugmode)
 782                        printk(KERN_DEBUG "capidrv-%d: listenconf Info=0x%4x (%s) cipmask=0x%x\n",
 783                               card->contrnr, cmsg->Info, capi_info2str(cmsg->Info), card->cipmask);
 784                if (cmsg->Info) {
 785                        listen_change_state(card, EV_LISTEN_CONF_ERROR);
 786                } else if (card->cipmask == 0) {
 787                        listen_change_state(card, EV_LISTEN_CONF_EMPTY);
 788                } else {
 789                        listen_change_state(card, EV_LISTEN_CONF_OK);
 790                }
 791                break;
 792
 793        case CAPI_MANUFACTURER_IND:     /* Controller */
 794                if (   cmsg->ManuID == 0x214D5641
 795                    && cmsg->Class == 0
 796                    && cmsg->Function == 1) {
 797                   u8  *data = cmsg->ManuData+3;
 798                   u16  len = cmsg->ManuData[0];
 799                   u16 layer;
 800                   int direction;
 801                   if (len == 255) {
 802                      len = (cmsg->ManuData[1] | (cmsg->ManuData[2] << 8));
 803                      data += 2;
 804                   }
 805                   len -= 2;
 806                   layer = ((*(data-1)) << 8) | *(data-2);
 807                   if (layer & 0x300)
 808                        direction = (layer & 0x200) ? 0 : 1;
 809                   else direction = (layer & 0x800) ? 0 : 1;
 810                   if (layer & 0x0C00) {
 811                        if ((layer & 0xff) == 0x80) {
 812                           handle_dtrace_data(card, direction, 1, data, len);
 813                           break;
 814                        }
 815                   } else if ((layer & 0xff) < 0x80) {
 816                      handle_dtrace_data(card, direction, 0, data, len);
 817                      break;
 818                   }
 819                   printk(KERN_INFO "capidrv-%d: %s from controller 0x%x layer 0x%x, ignored\n",
 820                        card->contrnr, 
 821                        capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 822                        cmsg->adr.adrController, layer);
 823                   break;
 824                }
 825                goto ignored;
 826        case CAPI_MANUFACTURER_CONF:    /* Controller */
 827                if (cmsg->ManuID == 0x214D5641) {
 828                   char *s = NULL;
 829                   switch (cmsg->Class) {
 830                      case 0: break;
 831                      case 1: s = "unknown class"; break;
 832                      case 2: s = "unknown function"; break;
 833                      default: s = "unknown error"; break;
 834                   }
 835                   if (s)
 836                   printk(KERN_INFO "capidrv-%d: %s from controller 0x%x function %d: %s\n",
 837                        card->contrnr,
 838                        capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 839                        cmsg->adr.adrController,
 840                        cmsg->Function, s);
 841                   break;
 842                }
 843                goto ignored;
 844        case CAPI_FACILITY_IND: /* Controller/plci/ncci */
 845                goto ignored;
 846        case CAPI_FACILITY_CONF:        /* Controller/plci/ncci */
 847                goto ignored;
 848        case CAPI_INFO_IND:     /* Controller/plci */
 849                goto ignored;
 850        case CAPI_INFO_CONF:    /* Controller/plci */
 851                goto ignored;
 852
 853        default:
 854                printk(KERN_ERR "capidrv-%d: got %s from controller 0x%x ???",
 855                       card->contrnr,
 856                       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 857                       cmsg->adr.adrController);
 858        }
 859        return;
 860
 861      ignored:
 862        printk(KERN_INFO "capidrv-%d: %s from controller 0x%x ignored\n",
 863               card->contrnr,
 864               capi_cmd2str(cmsg->Command, cmsg->Subcommand),
 865               cmsg->adr.adrController);
 866}
 867
 868static void handle_incoming_call(capidrv_contr * card, _cmsg * cmsg)
 869{
 870        capidrv_plci *plcip;
 871        capidrv_bchan *bchan;
 872        isdn_ctrl cmd;
 873        int chan;
 874
 875        if ((chan = new_bchan(card)) == -1) {
 876                printk(KERN_ERR "capidrv-%d: incoming call on not existing bchan ?\n", card->contrnr);
 877                return;
 878        }
 879        bchan = &card->bchans[chan];
 880        if ((plcip = new_plci(card, chan)) == NULL) {
 881                printk(KERN_ERR "capidrv-%d: incoming call: no memory, sorry.\n", card->contrnr);
 882                return;
 883        }
 884        bchan->incoming = 1;
 885        plcip->plci = cmsg->adr.adrPLCI;
 886        plci_change_state(card, plcip, EV_PLCI_CONNECT_IND);
 887
 888        cmd.command = ISDN_STAT_ICALL;
 889        cmd.driver = card->myid;
 890        cmd.arg = chan;
 891        memset(&cmd.parm.setup, 0, sizeof(cmd.parm.setup));
 892        strncpy(cmd.parm.setup.phone,
 893                cmsg->CallingPartyNumber + 3,
 894                cmsg->CallingPartyNumber[0] - 2);
 895        strncpy(cmd.parm.setup.eazmsn,
 896                cmsg->CalledPartyNumber + 2,
 897                cmsg->CalledPartyNumber[0] - 1);
 898        cmd.parm.setup.si1 = cip2si1(cmsg->CIPValue);
 899        cmd.parm.setup.si2 = cip2si2(cmsg->CIPValue);
 900        cmd.parm.setup.plan = cmsg->CallingPartyNumber[1];
 901        cmd.parm.setup.screen = cmsg->CallingPartyNumber[2];
 902
 903        printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s\n", 
 904                        card->contrnr,
 905                        cmd.parm.setup.phone,
 906                        cmd.parm.setup.si1,
 907                        cmd.parm.setup.si2,
 908                        cmd.parm.setup.eazmsn);
 909
 910        if (cmd.parm.setup.si1 == 1 && cmd.parm.setup.si2 != 0) {
 911                printk(KERN_INFO "capidrv-%d: patching si2=%d to 0 for VBOX\n", 
 912                        card->contrnr,
 913                        cmd.parm.setup.si2);
 914                cmd.parm.setup.si2 = 0;
 915        }
 916
 917        switch (card->interface.statcallb(&cmd)) {
 918        case 0:
 919        case 3:
 920                /* No device matching this call.
 921                 * and isdn_common.c has send a HANGUP command
 922                 * which is ignored in state ST_PLCI_INCOMING,
 923                 * so we send RESP to ignore the call
 924                 */
 925                capi_cmsg_answer(cmsg);
 926                cmsg->Reject = 1;       /* ignore */
 927                plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
 928                send_message(card, cmsg);
 929                printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s ignored\n",
 930                        card->contrnr,
 931                        cmd.parm.setup.phone,
 932                        cmd.parm.setup.si1,
 933                        cmd.parm.setup.si2,
 934                        cmd.parm.setup.eazmsn);
 935                break;
 936        case 1:
 937                /* At least one device matching this call (RING on ttyI)
 938                 * HL-driver may send ALERTING on the D-channel in this
 939                 * case.
 940                 * really means: RING on ttyI or a net interface
 941                 * accepted this call already.
 942                 *
 943                 * If the call was accepted, state has already changed,
 944                 * and CONNECT_RESP already sent.
 945                 */
 946                if (plcip->state == ST_PLCI_INCOMING) {
 947                        printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s tty alerting\n",
 948                                card->contrnr,
 949                                cmd.parm.setup.phone,
 950                                cmd.parm.setup.si1,
 951                                cmd.parm.setup.si2,
 952                                cmd.parm.setup.eazmsn);
 953                        capi_fill_ALERT_REQ(cmsg,
 954                                            global.ap.applid,
 955                                            card->msgid++,
 956                                            plcip->plci,        /* adr */
 957                                            NULL,/* BChannelinformation */
 958                                            NULL,/* Keypadfacility */
 959                                            NULL,/* Useruserdata */
 960                                            NULL /* Facilitydataarray */
 961                        );
 962                        plcip->msgid = cmsg->Messagenumber;
 963                        send_message(card, cmsg);
 964                } else {
 965                        printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s on netdev\n",
 966                                card->contrnr,
 967                                cmd.parm.setup.phone,
 968                                cmd.parm.setup.si1,
 969                                cmd.parm.setup.si2,
 970                                cmd.parm.setup.eazmsn);
 971                }
 972                break;
 973
 974        case 2:         /* Call will be rejected. */
 975                capi_cmsg_answer(cmsg);
 976                cmsg->Reject = 2;       /* reject call, normal call clearing */
 977                plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
 978                send_message(card, cmsg);
 979                break;
 980
 981        default:
 982                /* An error happened. (Invalid parameters for example.) */
 983                capi_cmsg_answer(cmsg);
 984                cmsg->Reject = 8;       /* reject call,
 985                                           destination out of order */
 986                plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
 987                send_message(card, cmsg);
 988                break;
 989        }
 990        return;
 991}
 992
 993static void handle_plci(_cmsg * cmsg)
 994{
 995        capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f);
 996        capidrv_plci *plcip;
 997        isdn_ctrl cmd;
 998        _cdebbuf *cdb;
 999
1000        if (!card) {
1001                printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n",
1002                       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1003                       cmsg->adr.adrController & 0x7f);
1004                return;
1005        }
1006        switch (CAPICMD(cmsg->Command, cmsg->Subcommand)) {
1007
1008        case CAPI_DISCONNECT_IND:       /* plci */
1009                if (cmsg->Reason) {
1010                        printk(KERN_INFO "capidrv-%d: %s reason 0x%x (%s) for plci 0x%x\n",
1011                           card->contrnr,
1012                           capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1013                               cmsg->Reason, capi_info2str(cmsg->Reason), cmsg->adr.adrPLCI);
1014                }
1015                if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI))) {
1016                        capi_cmsg_answer(cmsg);
1017                        send_message(card, cmsg);
1018                        goto notfound;
1019                }
1020                card->bchans[plcip->chan].disconnecting = 1;
1021                plci_change_state(card, plcip, EV_PLCI_DISCONNECT_IND);
1022                capi_cmsg_answer(cmsg);
1023                plci_change_state(card, plcip, EV_PLCI_DISCONNECT_RESP);
1024                send_message(card, cmsg);
1025                break;
1026
1027        case CAPI_DISCONNECT_CONF:      /* plci */
1028                if (cmsg->Info) {
1029                        printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n",
1030                           card->contrnr,
1031                           capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1032                               cmsg->Info, capi_info2str(cmsg->Info), 
1033                               cmsg->adr.adrPLCI);
1034                }
1035                if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI)))
1036                        goto notfound;
1037
1038                card->bchans[plcip->chan].disconnecting = 1;
1039                break;
1040
1041        case CAPI_ALERT_CONF:   /* plci */
1042                if (cmsg->Info) {
1043                        printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n",
1044                           card->contrnr,
1045                           capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1046                               cmsg->Info, capi_info2str(cmsg->Info), 
1047                               cmsg->adr.adrPLCI);
1048                }
1049                break;
1050
1051        case CAPI_CONNECT_IND:  /* plci */
1052                handle_incoming_call(card, cmsg);
1053                break;
1054
1055        case CAPI_CONNECT_CONF: /* plci */
1056                if (cmsg->Info) {
1057                        printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n",
1058                           card->contrnr,
1059                           capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1060                               cmsg->Info, capi_info2str(cmsg->Info), 
1061                               cmsg->adr.adrPLCI);
1062                }
1063                if (!(plcip = find_plci_by_msgid(card, cmsg->Messagenumber)))
1064                        goto notfound;
1065
1066                plcip->plci = cmsg->adr.adrPLCI;
1067                if (cmsg->Info) {
1068                        plci_change_state(card, plcip, EV_PLCI_CONNECT_CONF_ERROR);
1069                } else {
1070                        plci_change_state(card, plcip, EV_PLCI_CONNECT_CONF_OK);
1071                }
1072                break;
1073
1074        case CAPI_CONNECT_ACTIVE_IND:   /* plci */
1075
1076                if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI)))
1077                        goto notfound;
1078
1079                if (card->bchans[plcip->chan].incoming) {
1080                        capi_cmsg_answer(cmsg);
1081                        plci_change_state(card, plcip, EV_PLCI_CONNECT_ACTIVE_IND);
1082                        send_message(card, cmsg);
1083                } else {
1084                        capidrv_ncci *nccip;
1085                        capi_cmsg_answer(cmsg);
1086                        send_message(card, cmsg);
1087
1088                        nccip = new_ncci(card, plcip, cmsg->adr.adrPLCI);
1089
1090                        if (!nccip) {
1091                                printk(KERN_ERR "capidrv-%d: no mem for ncci, sorry\n", card->contrnr);
1092                                break;  /* $$$$ */
1093                        }
1094                        capi_fill_CONNECT_B3_REQ(cmsg,
1095                                                 global.ap.applid,
1096                                                 card->msgid++,
1097                                                 plcip->plci,   /* adr */
1098                                                 NULL   /* NCPI */
1099                        );
1100                        nccip->msgid = cmsg->Messagenumber;
1101                        plci_change_state(card, plcip,
1102                                          EV_PLCI_CONNECT_ACTIVE_IND);
1103                        ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_REQ);
1104                        send_message(card, cmsg);
1105                        cmd.command = ISDN_STAT_DCONN;
1106                        cmd.driver = card->myid;
1107                        cmd.arg = plcip->chan;
1108                        card->interface.statcallb(&cmd);
1109                }
1110                break;
1111
1112        case CAPI_INFO_IND:     /* Controller/plci */
1113
1114                if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI)))
1115                        goto notfound;
1116
1117                if (cmsg->InfoNumber == 0x4000) {
1118                        if (cmsg->InfoElement[0] == 4) {
1119                                cmd.command = ISDN_STAT_CINF;
1120                                cmd.driver = card->myid;
1121                                cmd.arg = plcip->chan;
1122                                sprintf(cmd.parm.num, "%lu",
1123                                        (unsigned long)
1124                                        ((u32) cmsg->InfoElement[1]
1125                                  | ((u32) (cmsg->InfoElement[2]) << 8)
1126                                 | ((u32) (cmsg->InfoElement[3]) << 16)
1127                                         | ((u32) (cmsg->InfoElement[4]) << 24)));
1128                                card->interface.statcallb(&cmd);
1129                                break;
1130                        }
1131                }
1132                cdb = capi_cmsg2str(cmsg);
1133                if (cdb) {
1134                        printk(KERN_WARNING "capidrv-%d: %s\n",
1135                                card->contrnr, cdb->buf);
1136                        cdebbuf_free(cdb);
1137                } else
1138                        printk(KERN_WARNING "capidrv-%d: CAPI_INFO_IND InfoNumber %x not handled\n",
1139                                card->contrnr, cmsg->InfoNumber);
1140
1141                break;
1142
1143        case CAPI_CONNECT_ACTIVE_CONF:          /* plci */
1144                goto ignored;
1145        case CAPI_SELECT_B_PROTOCOL_CONF:       /* plci */
1146                goto ignored;
1147        case CAPI_FACILITY_IND: /* Controller/plci/ncci */
1148                goto ignored;
1149        case CAPI_FACILITY_CONF:        /* Controller/plci/ncci */
1150                goto ignored;
1151
1152        case CAPI_INFO_CONF:    /* Controller/plci */
1153                goto ignored;
1154
1155        default:
1156                printk(KERN_ERR "capidrv-%d: got %s for plci 0x%x ???",
1157                       card->contrnr,
1158                       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1159                       cmsg->adr.adrPLCI);
1160        }
1161        return;
1162      ignored:
1163        printk(KERN_INFO "capidrv-%d: %s for plci 0x%x ignored\n",
1164               card->contrnr,
1165               capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1166               cmsg->adr.adrPLCI);
1167        return;
1168      notfound:
1169        printk(KERN_ERR "capidrv-%d: %s: plci 0x%x not found\n",
1170               card->contrnr,
1171               capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1172               cmsg->adr.adrPLCI);
1173        return;
1174}
1175
1176static void handle_ncci(_cmsg * cmsg)
1177{
1178        capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f);
1179        capidrv_plci *plcip;
1180        capidrv_ncci *nccip;
1181        isdn_ctrl cmd;
1182        int len;
1183
1184        if (!card) {
1185                printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n",
1186                       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1187                       cmsg->adr.adrController & 0x7f);
1188                return;
1189        }
1190        switch (CAPICMD(cmsg->Command, cmsg->Subcommand)) {
1191
1192        case CAPI_CONNECT_B3_ACTIVE_IND:        /* ncci */
1193                if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
1194                        goto notfound;
1195
1196                capi_cmsg_answer(cmsg);
1197                ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_ACTIVE_IND);
1198                send_message(card, cmsg);
1199
1200                cmd.command = ISDN_STAT_BCONN;
1201                cmd.driver = card->myid;
1202                cmd.arg = nccip->chan;
1203                card->interface.statcallb(&cmd);
1204
1205                printk(KERN_INFO "capidrv-%d: chan %d up with ncci 0x%x\n",
1206                       card->contrnr, nccip->chan, nccip->ncci);
1207                break;
1208
1209        case CAPI_CONNECT_B3_ACTIVE_CONF:       /* ncci */
1210                goto ignored;
1211
1212        case CAPI_CONNECT_B3_IND:       /* ncci */
1213
1214                plcip = find_plci_by_ncci(card, cmsg->adr.adrNCCI);
1215                if (plcip) {
1216                        nccip = new_ncci(card, plcip, cmsg->adr.adrNCCI);
1217                        if (nccip) {
1218                                ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_IND);
1219                                capi_fill_CONNECT_B3_RESP(cmsg,
1220                                                          global.ap.applid,
1221                                                          card->msgid++,
1222                                                          nccip->ncci,  /* adr */
1223                                                          0,    /* Reject */
1224                                                          NULL  /* NCPI */
1225                                );
1226                                ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_RESP);
1227                                send_message(card, cmsg);
1228                                break;
1229                        }
1230                        printk(KERN_ERR "capidrv-%d: no mem for ncci, sorry\n",                                                 card->contrnr);
1231                } else {
1232                        printk(KERN_ERR "capidrv-%d: %s: plci for ncci 0x%x not found\n",
1233                           card->contrnr,
1234                           capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1235                               cmsg->adr.adrNCCI);
1236                }
1237                capi_fill_CONNECT_B3_RESP(cmsg,
1238                                          global.ap.applid,
1239                                          card->msgid++,
1240                                          cmsg->adr.adrNCCI,
1241                                          2,    /* Reject */
1242                                          NULL  /* NCPI */
1243                );
1244                send_message(card, cmsg);
1245                break;
1246
1247        case CAPI_CONNECT_B3_CONF:      /* ncci */
1248
1249                if (!(nccip = find_ncci_by_msgid(card,
1250                                                 cmsg->adr.adrNCCI,
1251                                                 cmsg->Messagenumber)))
1252                        goto notfound;
1253
1254                nccip->ncci = cmsg->adr.adrNCCI;
1255                if (cmsg->Info) {
1256                        printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for ncci 0x%x\n",
1257                           card->contrnr,
1258                           capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1259                               cmsg->Info, capi_info2str(cmsg->Info), 
1260                               cmsg->adr.adrNCCI);
1261                }
1262
1263                if (cmsg->Info)
1264                        ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_CONF_ERROR);
1265                else
1266                        ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_CONF_OK);
1267                break;
1268
1269        case CAPI_CONNECT_B3_T90_ACTIVE_IND:    /* ncci */
1270                capi_cmsg_answer(cmsg);
1271                send_message(card, cmsg);
1272                break;
1273
1274        case CAPI_DATA_B3_IND:  /* ncci */
1275                /* handled in handle_data() */
1276                goto ignored;
1277
1278        case CAPI_DATA_B3_CONF: /* ncci */
1279                if (cmsg->Info) {
1280                        printk(KERN_WARNING "CAPI_DATA_B3_CONF: Info %x - %s\n",
1281                                cmsg->Info, capi_info2str(cmsg->Info));
1282                }
1283                if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
1284                        goto notfound;
1285
1286                len = capidrv_del_ack(nccip, cmsg->DataHandle);
1287                if (len < 0)
1288                        break;
1289                cmd.command = ISDN_STAT_BSENT;
1290                cmd.driver = card->myid;
1291                cmd.arg = nccip->chan;
1292                cmd.parm.length = len;
1293                card->interface.statcallb(&cmd);
1294                break;
1295
1296        case CAPI_DISCONNECT_B3_IND:    /* ncci */
1297                if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
1298                        goto notfound;
1299
1300                card->bchans[nccip->chan].disconnecting = 1;
1301                ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_IND);
1302                capi_cmsg_answer(cmsg);
1303                ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_RESP);
1304                send_message(card, cmsg);
1305                break;
1306
1307        case CAPI_DISCONNECT_B3_CONF:   /* ncci */
1308                if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
1309                        goto notfound;
1310                if (cmsg->Info) {
1311                        printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for ncci 0x%x\n",
1312                           card->contrnr,
1313                           capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1314                               cmsg->Info, capi_info2str(cmsg->Info), 
1315                               cmsg->adr.adrNCCI);
1316                        ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_CONF_ERROR);
1317                }
1318                break;
1319
1320        case CAPI_RESET_B3_IND: /* ncci */
1321                if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
1322                        goto notfound;
1323                ncci_change_state(card, nccip, EV_NCCI_RESET_B3_IND);
1324                capi_cmsg_answer(cmsg);
1325                send_message(card, cmsg);
1326                break;
1327
1328        case CAPI_RESET_B3_CONF:        /* ncci */
1329                goto ignored;   /* $$$$ */
1330
1331        case CAPI_FACILITY_IND: /* Controller/plci/ncci */
1332                goto ignored;
1333        case CAPI_FACILITY_CONF:        /* Controller/plci/ncci */
1334                goto ignored;
1335
1336        default:
1337                printk(KERN_ERR "capidrv-%d: got %s for ncci 0x%x ???",
1338                       card->contrnr,
1339                       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1340                       cmsg->adr.adrNCCI);
1341        }
1342        return;
1343      ignored:
1344        printk(KERN_INFO "capidrv-%d: %s for ncci 0x%x ignored\n",
1345               card->contrnr,
1346               capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1347               cmsg->adr.adrNCCI);
1348        return;
1349      notfound:
1350        printk(KERN_ERR "capidrv-%d: %s: ncci 0x%x not found\n",
1351               card->contrnr,
1352               capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1353               cmsg->adr.adrNCCI);
1354}
1355
1356
1357static void handle_data(_cmsg * cmsg, struct sk_buff *skb)
1358{
1359        capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f);
1360        capidrv_ncci *nccip;
1361
1362        if (!card) {
1363                printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n",
1364                       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1365                       cmsg->adr.adrController & 0x7f);
1366                kfree_skb(skb);
1367                return;
1368        }
1369        if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI))) {
1370                printk(KERN_ERR "capidrv-%d: %s: ncci 0x%x not found\n",
1371                       card->contrnr,
1372                       capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1373                       cmsg->adr.adrNCCI);
1374                kfree_skb(skb);
1375                return;
1376        }
1377        (void) skb_pull(skb, CAPIMSG_LEN(skb->data));
1378        card->interface.rcvcallb_skb(card->myid, nccip->chan, skb);
1379        capi_cmsg_answer(cmsg);
1380        send_message(card, cmsg);
1381}
1382
1383static _cmsg s_cmsg;
1384
1385static void capidrv_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
1386{
1387        capi_message2cmsg(&s_cmsg, skb->data);
1388        if (debugmode > 3) {
1389                _cdebbuf *cdb = capi_cmsg2str(&s_cmsg);
1390
1391                if (cdb) {
1392                        printk(KERN_DEBUG "%s: applid=%d %s\n", __func__,
1393                                ap->applid, cdb->buf);
1394                        cdebbuf_free(cdb);
1395                } else
1396                        printk(KERN_DEBUG "%s: applid=%d %s not traced\n",
1397                                __func__, ap->applid,
1398                                capi_cmd2str(s_cmsg.Command, s_cmsg.Subcommand));
1399        }
1400        if (s_cmsg.Command == CAPI_DATA_B3
1401            && s_cmsg.Subcommand == CAPI_IND) {
1402                handle_data(&s_cmsg, skb);
1403                return;
1404        }
1405        if ((s_cmsg.adr.adrController & 0xffffff00) == 0)
1406                handle_controller(&s_cmsg);
1407        else if ((s_cmsg.adr.adrPLCI & 0xffff0000) == 0)
1408                handle_plci(&s_cmsg);
1409        else
1410                handle_ncci(&s_cmsg);
1411        /*
1412         * data of skb used in s_cmsg,
1413         * free data when s_cmsg is not used again
1414         * thanks to Lars Heete <hel@admin.de>
1415         */
1416        kfree_skb(skb);
1417}
1418
1419/* ------------------------------------------------------------------- */
1420
1421#define PUTBYTE_TO_STATUS(card, byte) \
1422        do { \
1423                *(card)->q931_write++ = (byte); \
1424                if ((card)->q931_write > (card)->q931_end) \
1425                        (card)->q931_write = (card)->q931_buf; \
1426        } while (0)
1427
1428static void handle_dtrace_data(capidrv_contr *card,
1429                             int send, int level2, u8 *data, u16 len)
1430{
1431        u8 *p, *end;
1432        isdn_ctrl cmd;
1433
1434        if (!len) {
1435                printk(KERN_DEBUG "capidrv-%d: avmb1_q931_data: len == %d\n",
1436                                card->contrnr, len);
1437                return;
1438        }
1439
1440        if (level2) {
1441                PUTBYTE_TO_STATUS(card, 'D');
1442                PUTBYTE_TO_STATUS(card, '2');
1443                PUTBYTE_TO_STATUS(card, send ? '>' : '<');
1444                PUTBYTE_TO_STATUS(card, ':');
1445        } else {
1446                PUTBYTE_TO_STATUS(card, 'D');
1447                PUTBYTE_TO_STATUS(card, '3');
1448                PUTBYTE_TO_STATUS(card, send ? '>' : '<');
1449                PUTBYTE_TO_STATUS(card, ':');
1450        }
1451
1452        for (p = data, end = data+len; p < end; p++) {
1453                PUTBYTE_TO_STATUS(card, ' ');
1454                PUTBYTE_TO_STATUS(card, hex_asc_hi(*p));
1455                PUTBYTE_TO_STATUS(card, hex_asc_lo(*p));
1456        }
1457        PUTBYTE_TO_STATUS(card, '\n');
1458
1459        cmd.command = ISDN_STAT_STAVAIL;
1460        cmd.driver = card->myid;
1461        cmd.arg = len*3+5;
1462        card->interface.statcallb(&cmd);
1463}
1464
1465/* ------------------------------------------------------------------- */
1466
1467static _cmsg cmdcmsg;
1468
1469static int capidrv_ioctl(isdn_ctrl * c, capidrv_contr * card)
1470{
1471        switch (c->arg) {
1472        case 1:
1473                debugmode = (int)(*((unsigned int *)c->parm.num));
1474                printk(KERN_DEBUG "capidrv-%d: debugmode=%d\n",
1475                                card->contrnr, debugmode);
1476                return 0;
1477        default:
1478                printk(KERN_DEBUG "capidrv-%d: capidrv_ioctl(%ld) called ??\n",
1479                                card->contrnr, c->arg);
1480                return -EINVAL;
1481        }
1482        return -EINVAL;
1483}
1484
1485/*
1486 * Handle leased lines (CAPI-Bundling)
1487 */
1488
1489struct internal_bchannelinfo {
1490   unsigned short channelalloc;
1491   unsigned short operation;
1492   unsigned char  cmask[31];
1493};
1494
1495static int decodeFVteln(char *teln, unsigned long *bmaskp, int *activep)
1496{
1497        unsigned long bmask = 0;
1498        int active = !0;
1499        char *s;
1500        int i;
1501
1502        if (strncmp(teln, "FV:", 3) != 0)
1503                return 1;
1504        s = teln + 3;
1505        while (*s && *s == ' ') s++;
1506        if (!*s) return -2;
1507        if (*s == 'p' || *s == 'P') {
1508                active = 0;
1509                s++;
1510        }
1511        if (*s == 'a' || *s == 'A') {
1512                active = !0;
1513                s++;
1514        }
1515        while (*s) {
1516                int digit1 = 0;
1517                int digit2 = 0;
1518                char *endp;
1519
1520                digit1 = simple_strtoul(s, &endp, 10);
1521                if (s == endp)
1522                        return -3;
1523                s = endp;
1524
1525                if (digit1 <= 0 || digit1 > 30) return -4;
1526                if (*s == 0 || *s == ',' || *s == ' ') {
1527                        bmask |= (1 << digit1);
1528                        digit1 = 0;
1529                        if (*s) s++;
1530                        continue;
1531                }
1532                if (*s != '-') return -5;
1533                s++;
1534
1535                digit2 = simple_strtoul(s, &endp, 10);
1536                if (s == endp)
1537                        return -3;
1538                s = endp;
1539
1540                if (digit2 <= 0 || digit2 > 30) return -4;
1541                if (*s == 0 || *s == ',' || *s == ' ') {
1542                        if (digit1 > digit2)
1543                                for (i = digit2; i <= digit1 ; i++)
1544                                        bmask |= (1 << i);
1545                        else 
1546                                for (i = digit1; i <= digit2 ; i++)
1547                                        bmask |= (1 << i);
1548                        digit1 = digit2 = 0;
1549                        if (*s) s++;
1550                        continue;
1551                }
1552                return -6;
1553        }
1554        if (activep) *activep = active;
1555        if (bmaskp) *bmaskp = bmask;
1556        return 0;
1557}
1558
1559static int FVteln2capi20(char *teln, u8 AdditionalInfo[1+2+2+31])
1560{
1561        unsigned long bmask;
1562        int active;
1563        int rc, i;
1564   
1565        rc = decodeFVteln(teln, &bmask, &active);
1566        if (rc) return rc;
1567        /* Length */
1568        AdditionalInfo[0] = 2+2+31;
1569        /* Channel: 3 => use channel allocation */
1570        AdditionalInfo[1] = 3; AdditionalInfo[2] = 0;
1571        /* Operation: 0 => DTE mode, 1 => DCE mode */
1572        if (active) {
1573                AdditionalInfo[3] = 0; AdditionalInfo[4] = 0;
1574        } else {
1575                AdditionalInfo[3] = 1; AdditionalInfo[4] = 0;
1576        }
1577        /* Channel mask array */
1578        AdditionalInfo[5] = 0; /* no D-Channel */
1579        for (i=1; i <= 30; i++)
1580                AdditionalInfo[5+i] = (bmask & (1 << i)) ? 0xff : 0;
1581        return 0;
1582}
1583
1584static int capidrv_command(isdn_ctrl * c, capidrv_contr * card)
1585{
1586        isdn_ctrl cmd;
1587        struct capidrv_bchan *bchan;
1588        struct capidrv_plci *plcip;
1589        u8 AdditionalInfo[1+2+2+31];
1590        int rc, isleasedline = 0;
1591
1592        if (c->command == ISDN_CMD_IOCTL)
1593                return capidrv_ioctl(c, card);
1594
1595        switch (c->command) {
1596        case ISDN_CMD_DIAL:{
1597                        u8 calling[ISDN_MSNLEN + 3];
1598                        u8 called[ISDN_MSNLEN + 2];
1599
1600                        if (debugmode)
1601                                printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_DIAL(ch=%ld,\"%s,%d,%d,%s\")\n",
1602                                        card->contrnr,
1603                                        c->arg,
1604                                        c->parm.setup.phone,
1605                                        c->parm.setup.si1,
1606                                        c->parm.setup.si2,
1607                                        c->parm.setup.eazmsn);
1608
1609                        bchan = &card->bchans[c->arg % card->nbchan];
1610
1611                        if (bchan->plcip) {
1612                                printk(KERN_ERR "capidrv-%d: dail ch=%ld,\"%s,%d,%d,%s\" in use (plci=0x%x)\n",
1613                                        card->contrnr,
1614                                        c->arg, 
1615                                        c->parm.setup.phone,
1616                                        c->parm.setup.si1,
1617                                        c->parm.setup.si2,
1618                                        c->parm.setup.eazmsn,
1619                                        bchan->plcip->plci);
1620                                return 0;
1621                        }
1622                        bchan->si1 = c->parm.setup.si1;
1623                        bchan->si2 = c->parm.setup.si2;
1624
1625                        strncpy(bchan->num, c->parm.setup.phone, sizeof(bchan->num));
1626                        strncpy(bchan->mynum, c->parm.setup.eazmsn, sizeof(bchan->mynum));
1627                        rc = FVteln2capi20(bchan->num, AdditionalInfo);
1628                        isleasedline = (rc == 0);
1629                        if (rc < 0)
1630                                printk(KERN_ERR "capidrv-%d: WARNING: invalid leased linedefinition \"%s\"\n", card->contrnr, bchan->num);
1631
1632                        if (isleasedline) {
1633                                calling[0] = 0;
1634                                called[0] = 0;
1635                                if (debugmode)
1636                                        printk(KERN_DEBUG "capidrv-%d: connecting leased line\n", card->contrnr);
1637                        } else {
1638                                calling[0] = strlen(bchan->mynum) + 2;
1639                                calling[1] = 0;
1640                                calling[2] = 0x80;
1641                                strncpy(calling + 3, bchan->mynum, ISDN_MSNLEN);
1642                                called[0] = strlen(bchan->num) + 1;
1643                                called[1] = 0x80;
1644                                strncpy(called + 2, bchan->num, ISDN_MSNLEN);
1645                        }
1646
1647                        capi_fill_CONNECT_REQ(&cmdcmsg,
1648                                              global.ap.applid,
1649                                              card->msgid++,
1650                                              card->contrnr,    /* adr */
1651                                          si2cip(bchan->si1, bchan->si2),       /* cipvalue */
1652                                              called,   /* CalledPartyNumber */
1653                                              calling,  /* CallingPartyNumber */
1654                                              NULL,     /* CalledPartySubaddress */
1655                                              NULL,     /* CallingPartySubaddress */
1656                                            b1prot(bchan->l2, bchan->l3),       /* B1protocol */
1657                                            b2prot(bchan->l2, bchan->l3),       /* B2protocol */
1658                                            b3prot(bchan->l2, bchan->l3),       /* B3protocol */
1659                                            b1config(bchan->l2, bchan->l3),     /* B1configuration */
1660                                              NULL,     /* B2configuration */
1661                                              NULL,     /* B3configuration */
1662                                              NULL,     /* BC */
1663                                              NULL,     /* LLC */
1664                                              NULL,     /* HLC */
1665                                              /* BChannelinformation */
1666                                              isleasedline ? AdditionalInfo : NULL,
1667                                              NULL,     /* Keypadfacility */
1668                                              NULL,     /* Useruserdata */
1669                                              NULL      /* Facilitydataarray */
1670                            );
1671                        if ((plcip = new_plci(card, (c->arg % card->nbchan))) == NULL) {
1672                                cmd.command = ISDN_STAT_DHUP;
1673                                cmd.driver = card->myid;
1674                                cmd.arg = (c->arg % card->nbchan);
1675                                card->interface.statcallb(&cmd);
1676                                return -1;
1677                        }
1678                        plcip->msgid = cmdcmsg.Messagenumber;
1679                        plcip->leasedline = isleasedline;
1680                        plci_change_state(card, plcip, EV_PLCI_CONNECT_REQ);
1681                        send_message(card, &cmdcmsg);
1682                        return 0;
1683                }
1684
1685        case ISDN_CMD_ACCEPTD:
1686
1687                bchan = &card->bchans[c->arg % card->nbchan];
1688                if (debugmode)
1689                        printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_ACCEPTD(ch=%ld) l2=%d l3=%d\n",
1690                               card->contrnr,
1691                               c->arg, bchan->l2, bchan->l3);
1692
1693                capi_fill_CONNECT_RESP(&cmdcmsg,
1694                                       global.ap.applid,
1695                                       card->msgid++,
1696                                       bchan->plcip->plci,      /* adr */
1697                                       0,       /* Reject */
1698                                       b1prot(bchan->l2, bchan->l3),    /* B1protocol */
1699                                       b2prot(bchan->l2, bchan->l3),    /* B2protocol */
1700                                       b3prot(bchan->l2, bchan->l3),    /* B3protocol */
1701                                       b1config(bchan->l2, bchan->l3),  /* B1configuration */
1702                                       NULL,    /* B2configuration */
1703                                       NULL,    /* B3configuration */
1704                                       NULL,    /* ConnectedNumber */
1705                                       NULL,    /* ConnectedSubaddress */
1706                                       NULL,    /* LLC */
1707                                       NULL,    /* BChannelinformation */
1708                                       NULL,    /* Keypadfacility */
1709                                       NULL,    /* Useruserdata */
1710                                       NULL     /* Facilitydataarray */
1711                );
1712                capi_cmsg2message(&cmdcmsg, cmdcmsg.buf);
1713                plci_change_state(card, bchan->plcip, EV_PLCI_CONNECT_RESP);
1714                send_message(card, &cmdcmsg);
1715                return 0;
1716
1717        case ISDN_CMD_ACCEPTB:
1718                if (debugmode)
1719                        printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_ACCEPTB(ch=%ld)\n",
1720                               card->contrnr,
1721                               c->arg);
1722                return -ENOSYS;
1723
1724        case ISDN_CMD_HANGUP:
1725                if (debugmode)
1726                        printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_HANGUP(ch=%ld)\n",
1727                               card->contrnr,
1728                               c->arg);
1729                bchan = &card->bchans[c->arg % card->nbchan];
1730
1731                if (bchan->disconnecting) {
1732                        if (debugmode)
1733                                printk(KERN_DEBUG "capidrv-%d: chan %ld already disconnecting ...\n",
1734                                       card->contrnr,
1735                                       c->arg);
1736                        return 0;
1737                }
1738                if (bchan->nccip) {
1739                        bchan->disconnecting = 1;
1740                        capi_fill_DISCONNECT_B3_REQ(&cmdcmsg,
1741                                                    global.ap.applid,
1742                                                    card->msgid++,
1743                                                    bchan->nccip->ncci,
1744                                                    NULL        /* NCPI */
1745                        );
1746                        ncci_change_state(card, bchan->nccip, EV_NCCI_DISCONNECT_B3_REQ);
1747                        send_message(card, &cmdcmsg);
1748                        return 0;
1749                } else if (bchan->plcip) {
1750                        if (bchan->plcip->state == ST_PLCI_INCOMING) {
1751                                /*
1752                                 * just ignore, we a called from
1753                                 * isdn_status_callback(),
1754                                 * which will return 0 or 2, this is handled
1755                                 * by the CONNECT_IND handler
1756                                 */
1757                                bchan->disconnecting = 1;
1758                                return 0;
1759                        } else if (bchan->plcip->plci) {
1760                                bchan->disconnecting = 1;
1761                                capi_fill_DISCONNECT_REQ(&cmdcmsg,
1762                                                         global.ap.applid,
1763                                                         card->msgid++,
1764                                                      bchan->plcip->plci,
1765                                                         NULL,  /* BChannelinformation */
1766                                                         NULL,  /* Keypadfacility */
1767                                                         NULL,  /* Useruserdata */
1768                                                         NULL   /* Facilitydataarray */
1769                                );
1770                                plci_change_state(card, bchan->plcip, EV_PLCI_DISCONNECT_REQ);
1771                                send_message(card, &cmdcmsg);
1772                                return 0;
1773                        } else {
1774                                printk(KERN_ERR "capidrv-%d: chan %ld disconnect request while waiting for CONNECT_CONF\n",
1775                                       card->contrnr,
1776                                       c->arg);
1777                                return -EINVAL;
1778                        }
1779                }
1780                printk(KERN_ERR "capidrv-%d: chan %ld disconnect request on free channel\n",
1781                                       card->contrnr,
1782                                       c->arg);
1783                return -EINVAL;
1784/* ready */
1785
1786        case ISDN_CMD_SETL2:
1787                if (debugmode)
1788                        printk(KERN_DEBUG "capidrv-%d: set L2 on chan %ld to %ld\n",
1789                               card->contrnr,
1790                               (c->arg & 0xff), (c->arg >> 8));
1791                bchan = &card->bchans[(c->arg & 0xff) % card->nbchan];
1792                bchan->l2 = (c->arg >> 8);
1793                return 0;
1794
1795        case ISDN_CMD_SETL3:
1796                if (debugmode)
1797                        printk(KERN_DEBUG "capidrv-%d: set L3 on chan %ld to %ld\n",
1798                               card->contrnr,
1799                               (c->arg & 0xff), (c->arg >> 8));
1800                bchan = &card->bchans[(c->arg & 0xff) % card->nbchan];
1801                bchan->l3 = (c->arg >> 8);
1802                return 0;
1803
1804        case ISDN_CMD_SETEAZ:
1805                if (debugmode)
1806                        printk(KERN_DEBUG "capidrv-%d: set EAZ \"%s\" on chan %ld\n",
1807                               card->contrnr,
1808                               c->parm.num, c->arg);
1809                bchan = &card->bchans[c->arg % card->nbchan];
1810                strncpy(bchan->msn, c->parm.num, ISDN_MSNLEN);
1811                return 0;
1812
1813        case ISDN_CMD_CLREAZ:
1814                if (debugmode)
1815                        printk(KERN_DEBUG "capidrv-%d: clearing EAZ on chan %ld\n",
1816                                        card->contrnr, c->arg);
1817                bchan = &card->bchans[c->arg % card->nbchan];
1818                bchan->msn[0] = 0;
1819                return 0;
1820
1821        default:
1822                printk(KERN_ERR "capidrv-%d: ISDN_CMD_%d, Huh?\n",
1823                                        card->contrnr, c->command);
1824                return -EINVAL;
1825        }
1826        return 0;
1827}
1828
1829static int if_command(isdn_ctrl * c)
1830{
1831        capidrv_contr *card = findcontrbydriverid(c->driver);
1832
1833        if (card)
1834                return capidrv_command(c, card);
1835
1836        printk(KERN_ERR
1837             "capidrv: if_command %d called with invalid driverId %d!\n",
1838                                                c->command, c->driver);
1839        return -ENODEV;
1840}
1841
1842static _cmsg sendcmsg;
1843
1844static int if_sendbuf(int id, int channel, int doack, struct sk_buff *skb)
1845{
1846        capidrv_contr *card = findcontrbydriverid(id);
1847        capidrv_bchan *bchan;
1848        capidrv_ncci *nccip;
1849        int len = skb->len;
1850        int msglen;
1851        u16 errcode;
1852        u16 datahandle;
1853        u32 data;
1854
1855        if (!card) {
1856                printk(KERN_ERR "capidrv: if_sendbuf called with invalid driverId %d!\n",
1857                       id);
1858                return 0;
1859        }
1860        if (debugmode > 4)
1861                printk(KERN_DEBUG "capidrv-%d: sendbuf len=%d skb=%p doack=%d\n",
1862                                        card->contrnr, len, skb, doack);
1863        bchan = &card->bchans[channel % card->nbchan];
1864        nccip = bchan->nccip;
1865        if (!nccip || nccip->state != ST_NCCI_ACTIVE) {
1866                printk(KERN_ERR "capidrv-%d: if_sendbuf: %s:%d: chan not up!\n",
1867                       card->contrnr, card->name, channel);
1868                return 0;
1869        }
1870        datahandle = nccip->datahandle;
1871
1872        /*
1873         * Here we copy pointer skb->data into the 32-bit 'Data' field.
1874         * The 'Data' field is not used in practice in linux kernel
1875         * (neither in 32 or 64 bit), but should have some value,
1876         * since a CAPI message trace will display it.
1877         *
1878         * The correct value in the 32 bit case is the address of the
1879         * data, in 64 bit it makes no sense, we use 0 there.
1880         */
1881
1882#ifdef CONFIG_64BIT
1883        data = 0;
1884#else
1885        data = (unsigned long) skb->data;
1886#endif
1887
1888        capi_fill_DATA_B3_REQ(&sendcmsg, global.ap.applid, card->msgid++,
1889                              nccip->ncci,      /* adr */
1890                              data,             /* Data */
1891                              skb->len,         /* DataLength */
1892                              datahandle,       /* DataHandle */
1893                              0 /* Flags */
1894            );
1895
1896        if (capidrv_add_ack(nccip, datahandle, doack ? (int)skb->len : -1) < 0)
1897           return 0;
1898
1899        capi_cmsg2message(&sendcmsg, sendcmsg.buf);
1900        msglen = CAPIMSG_LEN(sendcmsg.buf);
1901        if (skb_headroom(skb) < msglen) {
1902                struct sk_buff *nskb = skb_realloc_headroom(skb, msglen);
1903                if (!nskb) {
1904                        printk(KERN_ERR "capidrv-%d: if_sendbuf: no memory\n",
1905                                card->contrnr);
1906                        (void)capidrv_del_ack(nccip, datahandle);
1907                        return 0;
1908                }
1909                printk(KERN_DEBUG "capidrv-%d: only %d bytes headroom, need %d\n",
1910                       card->contrnr, skb_headroom(skb), msglen);
1911                memcpy(skb_push(nskb, msglen), sendcmsg.buf, msglen);
1912                errcode = capi20_put_message(&global.ap, nskb);
1913                if (errcode == CAPI_NOERROR) {
1914                        dev_kfree_skb(skb);
1915                        nccip->datahandle++;
1916                        return len;
1917                }
1918                if (debugmode > 3)
1919                        printk(KERN_DEBUG "capidrv-%d: sendbuf putmsg ret(%x) - %s\n",
1920                                card->contrnr, errcode, capi_info2str(errcode));
1921                (void)capidrv_del_ack(nccip, datahandle);
1922                dev_kfree_skb(nskb);
1923                return errcode == CAPI_SENDQUEUEFULL ? 0 : -1;
1924        } else {
1925                memcpy(skb_push(skb, msglen), sendcmsg.buf, msglen);
1926                errcode = capi20_put_message(&global.ap, skb);
1927                if (errcode == CAPI_NOERROR) {
1928                        nccip->datahandle++;
1929                        return len;
1930                }
1931                if (debugmode > 3)
1932                        printk(KERN_DEBUG "capidrv-%d: sendbuf putmsg ret(%x) - %s\n",
1933                                card->contrnr, errcode, capi_info2str(errcode));
1934                skb_pull(skb, msglen);
1935                (void)capidrv_del_ack(nccip, datahandle);
1936                return errcode == CAPI_SENDQUEUEFULL ? 0 : -1;
1937        }
1938}
1939
1940static int if_readstat(u8 __user *buf, int len, int id, int channel)
1941{
1942        capidrv_contr *card = findcontrbydriverid(id);
1943        int count;
1944        u8 __user *p;
1945
1946        if (!card) {
1947                printk(KERN_ERR "capidrv: if_readstat called with invalid driverId %d!\n",
1948                       id);
1949                return -ENODEV;
1950        }
1951
1952        for (p=buf, count=0; count < len; p++, count++) {
1953                if (put_user(*card->q931_read++, p))
1954                        return -EFAULT;
1955                if (card->q931_read > card->q931_end)
1956                        card->q931_read = card->q931_buf;
1957        }
1958        return count;
1959
1960}
1961
1962static void enable_dchannel_trace(capidrv_contr *card)
1963{
1964        u8 manufacturer[CAPI_MANUFACTURER_LEN];
1965        capi_version version;
1966        u16 contr = card->contrnr;
1967        u16 errcode;
1968        u16 avmversion[3];
1969
1970        errcode = capi20_get_manufacturer(contr, manufacturer);
1971        if (errcode != CAPI_NOERROR) {
1972           printk(KERN_ERR "%s: can't get manufacturer (0x%x)\n",
1973                        card->name, errcode);
1974           return;
1975        }
1976        if (strstr(manufacturer, "AVM") == NULL) {
1977           printk(KERN_ERR "%s: not from AVM, no d-channel trace possible (%s)\n",
1978                        card->name, manufacturer);
1979           return;
1980        }
1981        errcode = capi20_get_version(contr, &version);
1982        if (errcode != CAPI_NOERROR) {
1983           printk(KERN_ERR "%s: can't get version (0x%x)\n",
1984                        card->name, errcode);
1985           return;
1986        }
1987        avmversion[0] = (version.majormanuversion >> 4) & 0x0f;
1988        avmversion[1] = (version.majormanuversion << 4) & 0xf0;
1989        avmversion[1] |= (version.minormanuversion >> 4) & 0x0f;
1990        avmversion[2] |= version.minormanuversion & 0x0f;
1991
1992        if (avmversion[0] > 3 || (avmversion[0] == 3 && avmversion[1] > 5)) {
1993                printk(KERN_INFO "%s: D2 trace enabled\n", card->name);
1994                capi_fill_MANUFACTURER_REQ(&cmdcmsg, global.ap.applid,
1995                                           card->msgid++,
1996                                           contr,
1997                                           0x214D5641,  /* ManuID */
1998                                           0,           /* Class */
1999                                           1,           /* Function */
2000                                           (_cstruct)"\004\200\014\000\000");
2001        } else {
2002                printk(KERN_INFO "%s: D3 trace enabled\n", card->name);
2003                capi_fill_MANUFACTURER_REQ(&cmdcmsg, global.ap.applid,
2004                                           card->msgid++,
2005                                           contr,
2006                                           0x214D5641,  /* ManuID */
2007                                           0,           /* Class */
2008                                           1,           /* Function */
2009                                           (_cstruct)"\004\002\003\000\000");
2010        }
2011        send_message(card, &cmdcmsg);
2012}
2013
2014
2015static void send_listen(capidrv_contr *card)
2016{
2017        capi_fill_LISTEN_REQ(&cmdcmsg, global.ap.applid,
2018                             card->msgid++,
2019                             card->contrnr, /* controller */
2020                             1 << 6,    /* Infomask */
2021                             card->cipmask,
2022                             card->cipmask2,
2023                             NULL, NULL);
2024        listen_change_state(card, EV_LISTEN_REQ);
2025        send_message(card, &cmdcmsg);
2026}
2027
2028static void listentimerfunc(unsigned long x)
2029{
2030        capidrv_contr *card = (capidrv_contr *)x;
2031        if (card->state != ST_LISTEN_NONE && card->state != ST_LISTEN_ACTIVE)
2032                printk(KERN_ERR "%s: controller dead ??\n", card->name);
2033        send_listen(card);
2034        mod_timer(&card->listentimer, jiffies + 60*HZ);
2035}
2036
2037
2038static int capidrv_addcontr(u16 contr, struct capi_profile *profp)
2039{
2040        capidrv_contr *card;
2041        unsigned long flags;
2042        isdn_ctrl cmd;
2043        char id[20];
2044        int i;
2045
2046        sprintf(id, "capidrv-%d", contr);
2047        if (!try_module_get(THIS_MODULE)) {
2048                printk(KERN_WARNING "capidrv: (%s) Could not reserve module\n", id);
2049                return -1;
2050        }
2051        if (!(card = kzalloc(sizeof(capidrv_contr), GFP_ATOMIC))) {
2052                printk(KERN_WARNING
2053                 "capidrv: (%s) Could not allocate contr-struct.\n", id);
2054                return -1;
2055        }
2056        card->owner = THIS_MODULE;
2057        init_timer(&card->listentimer);
2058        strcpy(card->name, id);
2059        card->contrnr = contr;
2060        card->nbchan = profp->nbchannel;
2061        card->bchans = kmalloc(sizeof(capidrv_bchan) * card->nbchan, GFP_ATOMIC);
2062        if (!card->bchans) {
2063                printk(KERN_WARNING
2064                "capidrv: (%s) Could not allocate bchan-structs.\n", id);
2065                module_put(card->owner);
2066                kfree(card);
2067                return -1;
2068        }
2069        card->interface.channels = profp->nbchannel;
2070        card->interface.maxbufsize = 2048;
2071        card->interface.command = if_command;
2072        card->interface.writebuf_skb = if_sendbuf;
2073        card->interface.writecmd = NULL;
2074        card->interface.readstat = if_readstat;
2075        card->interface.features = ISDN_FEATURE_L2_HDLC |
2076                                   ISDN_FEATURE_L2_TRANS |
2077                                   ISDN_FEATURE_L3_TRANS |
2078                                   ISDN_FEATURE_P_UNKNOWN |
2079                                   ISDN_FEATURE_L2_X75I |
2080                                   ISDN_FEATURE_L2_X75UI |
2081                                   ISDN_FEATURE_L2_X75BUI;
2082        if (profp->support1 & (1<<2))
2083                card->interface.features |= ISDN_FEATURE_L2_V11096 |
2084                                            ISDN_FEATURE_L2_V11019 |
2085                                            ISDN_FEATURE_L2_V11038;
2086        if (profp->support1 & (1<<8))
2087                card->interface.features |= ISDN_FEATURE_L2_MODEM;
2088        card->interface.hl_hdrlen = 22; /* len of DATA_B3_REQ */
2089        strncpy(card->interface.id, id, sizeof(card->interface.id) - 1);
2090
2091
2092        card->q931_read = card->q931_buf;
2093        card->q931_write = card->q931_buf;
2094        card->q931_end = card->q931_buf + sizeof(card->q931_buf) - 1;
2095
2096        if (!register_isdn(&card->interface)) {
2097                printk(KERN_ERR "capidrv: Unable to register contr %s\n", id);
2098                kfree(card->bchans);
2099                module_put(card->owner);
2100                kfree(card);
2101                return -1;
2102        }
2103        card->myid = card->interface.channels;
2104        memset(card->bchans, 0, sizeof(capidrv_bchan) * card->nbchan);
2105        for (i = 0; i < card->nbchan; i++) {
2106                card->bchans[i].contr = card;
2107        }
2108
2109        spin_lock_irqsave(&global_lock, flags);
2110        card->next = global.contr_list;
2111        global.contr_list = card;
2112        global.ncontr++;
2113        spin_unlock_irqrestore(&global_lock, flags);
2114
2115        cmd.command = ISDN_STAT_RUN;
2116        cmd.driver = card->myid;
2117        card->interface.statcallb(&cmd);
2118
2119        card->cipmask = 0x1FFF03FF;     /* any */
2120        card->cipmask2 = 0;
2121
2122        card->listentimer.data = (unsigned long)card;
2123        card->listentimer.function = listentimerfunc;
2124        send_listen(card);
2125        mod_timer(&card->listentimer, jiffies + 60*HZ);
2126
2127        printk(KERN_INFO "%s: now up (%d B channels)\n",
2128                card->name, card->nbchan);
2129
2130        enable_dchannel_trace(card);
2131
2132        return 0;
2133}
2134
2135static int capidrv_delcontr(u16 contr)
2136{
2137        capidrv_contr **pp, *card;
2138        unsigned long flags;
2139        isdn_ctrl cmd;
2140
2141        spin_lock_irqsave(&global_lock, flags);
2142        for (card = global.contr_list; card; card = card->next) {
2143                if (card->contrnr == contr)
2144                        break;
2145        }
2146        if (!card) {
2147                spin_unlock_irqrestore(&global_lock, flags);
2148                printk(KERN_ERR "capidrv: delcontr: no contr %u\n", contr);
2149                return -1;
2150        }
2151
2152        /* FIXME: maybe a race condition the card should be removed
2153         * here from global list /kkeil
2154         */
2155        spin_unlock_irqrestore(&global_lock, flags);
2156
2157        del_timer(&card->listentimer);
2158
2159        if (debugmode)
2160                printk(KERN_DEBUG "capidrv-%d: id=%d unloading\n",
2161                                        card->contrnr, card->myid);
2162
2163        cmd.command = ISDN_STAT_STOP;
2164        cmd.driver = card->myid;
2165        card->interface.statcallb(&cmd);
2166
2167        while (card->nbchan) {
2168
2169                cmd.command = ISDN_STAT_DISCH;
2170                cmd.driver = card->myid;
2171                cmd.arg = card->nbchan-1;
2172                cmd.parm.num[0] = 0;
2173                if (debugmode)
2174                        printk(KERN_DEBUG "capidrv-%d: id=%d disable chan=%ld\n",
2175                                        card->contrnr, card->myid, cmd.arg);
2176                card->interface.statcallb(&cmd);
2177
2178                if (card->bchans[card->nbchan-1].nccip)
2179                        free_ncci(card, card->bchans[card->nbchan-1].nccip);
2180                if (card->bchans[card->nbchan-1].plcip)
2181                        free_plci(card, card->bchans[card->nbchan-1].plcip);
2182                if (card->plci_list)
2183                        printk(KERN_ERR "capidrv: bug in free_plci()\n");
2184                card->nbchan--;
2185        }
2186        kfree(card->bchans);
2187        card->bchans = NULL;
2188
2189        if (debugmode)
2190                printk(KERN_DEBUG "capidrv-%d: id=%d isdn unload\n",
2191                                        card->contrnr, card->myid);
2192
2193        cmd.command = ISDN_STAT_UNLOAD;
2194        cmd.driver = card->myid;
2195        card->interface.statcallb(&cmd);
2196
2197        if (debugmode)
2198                printk(KERN_DEBUG "capidrv-%d: id=%d remove contr from list\n",
2199                                        card->contrnr, card->myid);
2200
2201        spin_lock_irqsave(&global_lock, flags);
2202        for (pp = &global.contr_list; *pp; pp = &(*pp)->next) {
2203                if (*pp == card) {
2204                        *pp = (*pp)->next;
2205                        card->next = NULL;
2206                        global.ncontr--;
2207                        break;
2208                }
2209        }
2210        spin_unlock_irqrestore(&global_lock, flags);
2211
2212        module_put(card->owner);
2213        printk(KERN_INFO "%s: now down.\n", card->name);
2214        kfree(card);
2215        return 0;
2216}
2217
2218
2219static int
2220lower_callback(struct notifier_block *nb, unsigned long val, void *v)
2221{
2222        capi_profile profile;
2223        u32 contr = (long)v;
2224
2225        switch (val) {
2226        case CAPICTR_UP:
2227                printk(KERN_INFO "capidrv: controller %hu up\n", contr);
2228                if (capi20_get_profile(contr, &profile) == CAPI_NOERROR)
2229                        (void) capidrv_addcontr(contr, &profile);
2230                break;
2231        case CAPICTR_DOWN:
2232                printk(KERN_INFO "capidrv: controller %hu down\n", contr);
2233                (void) capidrv_delcontr(contr);
2234                break;
2235        }
2236        return NOTIFY_OK;
2237}
2238
2239/*
2240 * /proc/capi/capidrv:
2241 * nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt
2242 */
2243static int capidrv_proc_show(struct seq_file *m, void *v)
2244{
2245        seq_printf(m, "%lu %lu %lu %lu\n",
2246                        global.ap.nrecvctlpkt,
2247                        global.ap.nrecvdatapkt,
2248                        global.ap.nsentctlpkt,
2249                        global.ap.nsentdatapkt);
2250        return 0;
2251}
2252
2253static int capidrv_proc_open(struct inode *inode, struct file *file)
2254{
2255        return single_open(file, capidrv_proc_show, NULL);
2256}
2257
2258static const struct file_operations capidrv_proc_fops = {
2259        .owner          = THIS_MODULE,
2260        .open           = capidrv_proc_open,
2261        .read           = seq_read,
2262        .llseek         = seq_lseek,
2263        .release        = single_release,
2264};
2265
2266static void __init proc_init(void)
2267{
2268        proc_create("capi/capidrv", 0, NULL, &capidrv_proc_fops);
2269}
2270
2271static void __exit proc_exit(void)
2272{
2273        remove_proc_entry("capi/capidrv", NULL);
2274}
2275
2276static struct notifier_block capictr_nb = {
2277        .notifier_call = lower_callback,
2278};
2279
2280static int __init capidrv_init(void)
2281{
2282        capi_profile profile;
2283        u32 ncontr, contr;
2284        u16 errcode;
2285
2286        global.ap.rparam.level3cnt = -2;  /* number of bchannels twice */
2287        global.ap.rparam.datablkcnt = 16;
2288        global.ap.rparam.datablklen = 2048;
2289
2290        global.ap.recv_message = capidrv_recv_message;
2291        errcode = capi20_register(&global.ap);
2292        if (errcode) {
2293                return -EIO;
2294        }
2295
2296        register_capictr_notifier(&capictr_nb);
2297
2298        errcode = capi20_get_profile(0, &profile);
2299        if (errcode != CAPI_NOERROR) {
2300                unregister_capictr_notifier(&capictr_nb);
2301                capi20_release(&global.ap);
2302                return -EIO;
2303        }
2304
2305        ncontr = profile.ncontroller;
2306        for (contr = 1; contr <= ncontr; contr++) {
2307                errcode = capi20_get_profile(contr, &profile);
2308                if (errcode != CAPI_NOERROR)
2309                        continue;
2310                (void) capidrv_addcontr(contr, &profile);
2311        }
2312        proc_init();
2313
2314        return 0;
2315}
2316
2317static void __exit capidrv_exit(void)
2318{
2319        unregister_capictr_notifier(&capictr_nb);
2320        capi20_release(&global.ap);
2321
2322        proc_exit();
2323}
2324
2325module_init(capidrv_init);
2326module_exit(capidrv_exit);
2327