linux/drivers/isdn/capi/kcapi.c
<<
>>
Prefs
   1/* $Id: kcapi.c,v 1.1.2.8 2004/03/26 19:57:20 armin Exp $
   2 * 
   3 * Kernel CAPI 2.0 Module
   4 * 
   5 * Copyright 1999 by Carsten Paeth <calle@calle.de>
   6 * Copyright 2002 by Kai Germaschewski <kai@germaschewski.name>
   7 * 
   8 * This software may be used and distributed according to the terms
   9 * of the GNU General Public License, incorporated herein by reference.
  10 *
  11 */
  12
  13#define AVMB1_COMPAT
  14
  15#include "kcapi.h"
  16#include <linux/module.h>
  17#include <linux/mm.h>
  18#include <linux/interrupt.h>
  19#include <linux/ioport.h>
  20#include <linux/proc_fs.h>
  21#include <linux/seq_file.h>
  22#include <linux/skbuff.h>
  23#include <linux/workqueue.h>
  24#include <linux/capi.h>
  25#include <linux/kernelcapi.h>
  26#include <linux/init.h>
  27#include <linux/moduleparam.h>
  28#include <linux/delay.h>
  29#include <asm/uaccess.h>
  30#include <linux/isdn/capicmd.h>
  31#include <linux/isdn/capiutil.h>
  32#ifdef AVMB1_COMPAT
  33#include <linux/b1lli.h>
  34#endif
  35#include <linux/mutex.h>
  36
  37static char *revision = "$Revision: 1.1.2.8 $";
  38
  39/* ------------------------------------------------------------- */
  40
  41static int showcapimsgs = 0;
  42
  43MODULE_DESCRIPTION("CAPI4Linux: kernel CAPI layer");
  44MODULE_AUTHOR("Carsten Paeth");
  45MODULE_LICENSE("GPL");
  46module_param(showcapimsgs, uint, 0);
  47
  48/* ------------------------------------------------------------- */
  49
  50struct capi_notifier {
  51        struct work_struct work;
  52        unsigned int cmd;
  53        u32 controller;
  54        u16 applid;
  55        u32 ncci;
  56};
  57
  58/* ------------------------------------------------------------- */
  59
  60static struct capi_version driver_version = {2, 0, 1, 1<<4};
  61static char driver_serial[CAPI_SERIAL_LEN] = "0004711";
  62static char capi_manufakturer[64] = "AVM Berlin";
  63
  64#define NCCI2CTRL(ncci)    (((ncci) >> 24) & 0x7f)
  65
  66LIST_HEAD(capi_drivers);
  67DEFINE_RWLOCK(capi_drivers_list_lock);
  68
  69static DEFINE_RWLOCK(application_lock);
  70static DEFINE_MUTEX(controller_mutex);
  71
  72struct capi20_appl *capi_applications[CAPI_MAXAPPL];
  73struct capi_ctr *capi_cards[CAPI_MAXCONTR];
  74
  75static int ncards;
  76
  77/* -------- controller ref counting -------------------------------------- */
  78
  79static inline struct capi_ctr *
  80capi_ctr_get(struct capi_ctr *card)
  81{
  82        if (!try_module_get(card->owner))
  83                return NULL;
  84        return card;
  85}
  86
  87static inline void
  88capi_ctr_put(struct capi_ctr *card)
  89{
  90        module_put(card->owner);
  91}
  92
  93/* ------------------------------------------------------------- */
  94
  95static inline struct capi_ctr *get_capi_ctr_by_nr(u16 contr)
  96{
  97        if (contr - 1 >= CAPI_MAXCONTR)
  98                return NULL;
  99
 100        return capi_cards[contr - 1];
 101}
 102
 103static inline struct capi20_appl *get_capi_appl_by_nr(u16 applid)
 104{
 105        if (applid - 1 >= CAPI_MAXAPPL)
 106                return NULL;
 107
 108        return capi_applications[applid - 1];
 109}
 110
 111/* -------- util functions ------------------------------------ */
 112
 113static inline int capi_cmd_valid(u8 cmd)
 114{
 115        switch (cmd) {
 116        case CAPI_ALERT:
 117        case CAPI_CONNECT:
 118        case CAPI_CONNECT_ACTIVE:
 119        case CAPI_CONNECT_B3_ACTIVE:
 120        case CAPI_CONNECT_B3:
 121        case CAPI_CONNECT_B3_T90_ACTIVE:
 122        case CAPI_DATA_B3:
 123        case CAPI_DISCONNECT_B3:
 124        case CAPI_DISCONNECT:
 125        case CAPI_FACILITY:
 126        case CAPI_INFO:
 127        case CAPI_LISTEN:
 128        case CAPI_MANUFACTURER:
 129        case CAPI_RESET_B3:
 130        case CAPI_SELECT_B_PROTOCOL:
 131                return 1;
 132        }
 133        return 0;
 134}
 135
 136static inline int capi_subcmd_valid(u8 subcmd)
 137{
 138        switch (subcmd) {
 139        case CAPI_REQ:
 140        case CAPI_CONF:
 141        case CAPI_IND:
 142        case CAPI_RESP:
 143                return 1;
 144        }
 145        return 0;
 146}
 147
 148/* ------------------------------------------------------------ */
 149
 150static void register_appl(struct capi_ctr *card, u16 applid, capi_register_params *rparam)
 151{
 152        card = capi_ctr_get(card);
 153
 154        if (card)
 155                card->register_appl(card, applid, rparam);
 156        else
 157                printk(KERN_WARNING "%s: cannot get card resources\n", __func__);
 158}
 159
 160
 161static void release_appl(struct capi_ctr *card, u16 applid)
 162{
 163        DBG("applid %#x", applid);
 164        
 165        card->release_appl(card, applid);
 166        capi_ctr_put(card);
 167}
 168
 169/* -------- KCI_CONTRUP --------------------------------------- */
 170
 171static void notify_up(u32 contr)
 172{
 173        struct capi_ctr *card = get_capi_ctr_by_nr(contr);
 174        struct capi20_appl *ap;
 175        u16 applid;
 176
 177        if (showcapimsgs & 1) {
 178                printk(KERN_DEBUG "kcapi: notify up contr %d\n", contr);
 179        }
 180        if (!card) {
 181                printk(KERN_WARNING "%s: invalid contr %d\n", __func__, contr);
 182                return;
 183        }
 184        for (applid = 1; applid <= CAPI_MAXAPPL; applid++) {
 185                ap = get_capi_appl_by_nr(applid);
 186                if (!ap || ap->release_in_progress) continue;
 187                register_appl(card, applid, &ap->rparam);
 188                if (ap->callback && !ap->release_in_progress)
 189                        ap->callback(KCI_CONTRUP, contr, &card->profile);
 190        }
 191}
 192
 193/* -------- KCI_CONTRDOWN ------------------------------------- */
 194
 195static void notify_down(u32 contr)
 196{
 197        struct capi20_appl *ap;
 198        u16 applid;
 199
 200        if (showcapimsgs & 1) {
 201                printk(KERN_DEBUG "kcapi: notify down contr %d\n", contr);
 202        }
 203
 204        for (applid = 1; applid <= CAPI_MAXAPPL; applid++) {
 205                ap = get_capi_appl_by_nr(applid);
 206                if (ap && ap->callback && !ap->release_in_progress)
 207                        ap->callback(KCI_CONTRDOWN, contr, NULL);
 208        }
 209}
 210
 211static void notify_handler(struct work_struct *work)
 212{
 213        struct capi_notifier *np =
 214                container_of(work, struct capi_notifier, work);
 215
 216        switch (np->cmd) {
 217        case KCI_CONTRUP:
 218                notify_up(np->controller);
 219                break;
 220        case KCI_CONTRDOWN:
 221                notify_down(np->controller);
 222                break;
 223        }
 224
 225        kfree(np);
 226}
 227
 228/*
 229 * The notifier will result in adding/deleteing of devices. Devices can
 230 * only removed in user process, not in bh.
 231 */
 232static int notify_push(unsigned int cmd, u32 controller, u16 applid, u32 ncci)
 233{
 234        struct capi_notifier *np = kmalloc(sizeof(*np), GFP_ATOMIC);
 235
 236        if (!np)
 237                return -ENOMEM;
 238
 239        INIT_WORK(&np->work, notify_handler);
 240        np->cmd = cmd;
 241        np->controller = controller;
 242        np->applid = applid;
 243        np->ncci = ncci;
 244
 245        schedule_work(&np->work);
 246        return 0;
 247}
 248
 249        
 250/* -------- Receiver ------------------------------------------ */
 251
 252static void recv_handler(struct work_struct *work)
 253{
 254        struct sk_buff *skb;
 255        struct capi20_appl *ap =
 256                container_of(work, struct capi20_appl, recv_work);
 257
 258        if ((!ap) || (ap->release_in_progress))
 259                return;
 260
 261        mutex_lock(&ap->recv_mtx);
 262        while ((skb = skb_dequeue(&ap->recv_queue))) {
 263                if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_IND)
 264                        ap->nrecvdatapkt++;
 265                else
 266                        ap->nrecvctlpkt++;
 267
 268                ap->recv_message(ap, skb);
 269        }
 270        mutex_unlock(&ap->recv_mtx);
 271}
 272
 273void capi_ctr_handle_message(struct capi_ctr * card, u16 appl, struct sk_buff *skb)
 274{
 275        struct capi20_appl *ap;
 276        int showctl = 0;
 277        u8 cmd, subcmd;
 278        unsigned long flags;
 279        _cdebbuf *cdb;
 280
 281        if (card->cardstate != CARD_RUNNING) {
 282                cdb = capi_message2str(skb->data);
 283                if (cdb) {
 284                        printk(KERN_INFO "kcapi: controller [%03d] not active, got: %s",
 285                                card->cnr, cdb->buf);
 286                        cdebbuf_free(cdb);
 287                } else
 288                        printk(KERN_INFO "kcapi: controller [%03d] not active, cannot trace\n",
 289                                card->cnr);
 290                goto error;
 291        }
 292
 293        cmd = CAPIMSG_COMMAND(skb->data);
 294        subcmd = CAPIMSG_SUBCOMMAND(skb->data);
 295        if (cmd == CAPI_DATA_B3 && subcmd == CAPI_IND) {
 296                card->nrecvdatapkt++;
 297                if (card->traceflag > 2) showctl |= 2;
 298        } else {
 299                card->nrecvctlpkt++;
 300                if (card->traceflag) showctl |= 2;
 301        }
 302        showctl |= (card->traceflag & 1);
 303        if (showctl & 2) {
 304                if (showctl & 1) {
 305                        printk(KERN_DEBUG "kcapi: got [%03d] id#%d %s len=%u\n",
 306                               card->cnr, CAPIMSG_APPID(skb->data),
 307                               capi_cmd2str(cmd, subcmd),
 308                               CAPIMSG_LEN(skb->data));
 309                } else {
 310                        cdb = capi_message2str(skb->data);
 311                        if (cdb) {
 312                                printk(KERN_DEBUG "kcapi: got [%03d] %s\n",
 313                                        card->cnr, cdb->buf);
 314                                cdebbuf_free(cdb);
 315                        } else
 316                                printk(KERN_DEBUG "kcapi: got [%03d] id#%d %s len=%u, cannot trace\n",
 317                                        card->cnr, CAPIMSG_APPID(skb->data),
 318                                        capi_cmd2str(cmd, subcmd),
 319                                        CAPIMSG_LEN(skb->data));
 320                }
 321
 322        }
 323
 324        read_lock_irqsave(&application_lock, flags);
 325        ap = get_capi_appl_by_nr(CAPIMSG_APPID(skb->data));
 326        if ((!ap) || (ap->release_in_progress)) {
 327                read_unlock_irqrestore(&application_lock, flags);
 328                cdb = capi_message2str(skb->data);
 329                if (cdb) {
 330                        printk(KERN_ERR "kcapi: handle_message: applid %d state released (%s)\n",
 331                        CAPIMSG_APPID(skb->data), cdb->buf);
 332                        cdebbuf_free(cdb);
 333                } else
 334                        printk(KERN_ERR "kcapi: handle_message: applid %d state released (%s) cannot trace\n",
 335                                CAPIMSG_APPID(skb->data),
 336                                capi_cmd2str(cmd, subcmd));
 337                goto error;
 338        }
 339        skb_queue_tail(&ap->recv_queue, skb);
 340        schedule_work(&ap->recv_work);
 341        read_unlock_irqrestore(&application_lock, flags);
 342
 343        return;
 344
 345error:
 346        kfree_skb(skb);
 347}
 348
 349EXPORT_SYMBOL(capi_ctr_handle_message);
 350
 351void capi_ctr_ready(struct capi_ctr * card)
 352{
 353        card->cardstate = CARD_RUNNING;
 354
 355        printk(KERN_NOTICE "kcapi: card [%03d] \"%s\" ready.\n",
 356               card->cnr, card->name);
 357
 358        notify_push(KCI_CONTRUP, card->cnr, 0, 0);
 359}
 360
 361EXPORT_SYMBOL(capi_ctr_ready);
 362
 363void capi_ctr_reseted(struct capi_ctr * card)
 364{
 365        u16 appl;
 366
 367        DBG("");
 368
 369        if (card->cardstate == CARD_DETECTED)
 370                return;
 371
 372        card->cardstate = CARD_DETECTED;
 373
 374        memset(card->manu, 0, sizeof(card->manu));
 375        memset(&card->version, 0, sizeof(card->version));
 376        memset(&card->profile, 0, sizeof(card->profile));
 377        memset(card->serial, 0, sizeof(card->serial));
 378
 379        for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
 380                struct capi20_appl *ap = get_capi_appl_by_nr(appl);
 381                if (!ap || ap->release_in_progress)
 382                        continue;
 383
 384                capi_ctr_put(card);
 385        }
 386
 387        printk(KERN_NOTICE "kcapi: card [%03d] down.\n", card->cnr);
 388
 389        notify_push(KCI_CONTRDOWN, card->cnr, 0, 0);
 390}
 391
 392EXPORT_SYMBOL(capi_ctr_reseted);
 393
 394void capi_ctr_suspend_output(struct capi_ctr *card)
 395{
 396        if (!card->blocked) {
 397                printk(KERN_DEBUG "kcapi: card [%03d] suspend\n", card->cnr);
 398                card->blocked = 1;
 399        }
 400}
 401
 402EXPORT_SYMBOL(capi_ctr_suspend_output);
 403
 404void capi_ctr_resume_output(struct capi_ctr *card)
 405{
 406        if (card->blocked) {
 407                printk(KERN_DEBUG "kcapi: card [%03d] resume\n", card->cnr);
 408                card->blocked = 0;
 409        }
 410}
 411
 412EXPORT_SYMBOL(capi_ctr_resume_output);
 413
 414/* ------------------------------------------------------------- */
 415
 416int
 417attach_capi_ctr(struct capi_ctr *card)
 418{
 419        int i;
 420
 421        mutex_lock(&controller_mutex);
 422
 423        for (i = 0; i < CAPI_MAXCONTR; i++) {
 424                if (capi_cards[i] == NULL)
 425                        break;
 426        }
 427        if (i == CAPI_MAXCONTR) {
 428                mutex_unlock(&controller_mutex);
 429                printk(KERN_ERR "kcapi: out of controller slots\n");
 430                return -EBUSY;
 431        }
 432        capi_cards[i] = card;
 433
 434        mutex_unlock(&controller_mutex);
 435
 436        card->nrecvctlpkt = 0;
 437        card->nrecvdatapkt = 0;
 438        card->nsentctlpkt = 0;
 439        card->nsentdatapkt = 0;
 440        card->cnr = i + 1;
 441        card->cardstate = CARD_DETECTED;
 442        card->blocked = 0;
 443        card->traceflag = showcapimsgs;
 444
 445        sprintf(card->procfn, "capi/controllers/%d", card->cnr);
 446        card->procent = create_proc_entry(card->procfn, 0, NULL);
 447        if (card->procent) {
 448           card->procent->read_proc = 
 449                (int (*)(char *,char **,off_t,int,int *,void *))
 450                        card->ctr_read_proc;
 451           card->procent->data = card;
 452        }
 453
 454        ncards++;
 455        printk(KERN_NOTICE "kcapi: Controller [%03d]: %s attached\n",
 456                        card->cnr, card->name);
 457        return 0;
 458}
 459
 460EXPORT_SYMBOL(attach_capi_ctr);
 461
 462int detach_capi_ctr(struct capi_ctr *card)
 463{
 464        if (card->cardstate != CARD_DETECTED)
 465                capi_ctr_reseted(card);
 466
 467        ncards--;
 468
 469        if (card->procent) {
 470           remove_proc_entry(card->procfn, NULL);
 471           card->procent = NULL;
 472        }
 473        capi_cards[card->cnr - 1] = NULL;
 474        printk(KERN_NOTICE "kcapi: Controller [%03d]: %s unregistered\n",
 475                        card->cnr, card->name);
 476
 477        return 0;
 478}
 479
 480EXPORT_SYMBOL(detach_capi_ctr);
 481
 482void register_capi_driver(struct capi_driver *driver)
 483{
 484        unsigned long flags;
 485
 486        write_lock_irqsave(&capi_drivers_list_lock, flags);
 487        list_add_tail(&driver->list, &capi_drivers);
 488        write_unlock_irqrestore(&capi_drivers_list_lock, flags);
 489}
 490
 491EXPORT_SYMBOL(register_capi_driver);
 492
 493void unregister_capi_driver(struct capi_driver *driver)
 494{
 495        unsigned long flags;
 496
 497        write_lock_irqsave(&capi_drivers_list_lock, flags);
 498        list_del(&driver->list);
 499        write_unlock_irqrestore(&capi_drivers_list_lock, flags);
 500}
 501
 502EXPORT_SYMBOL(unregister_capi_driver);
 503
 504/* ------------------------------------------------------------- */
 505/* -------- CAPI2.0 Interface ---------------------------------- */
 506/* ------------------------------------------------------------- */
 507
 508u16 capi20_isinstalled(void)
 509{
 510        int i;
 511        for (i = 0; i < CAPI_MAXCONTR; i++) {
 512                if (capi_cards[i] && capi_cards[i]->cardstate == CARD_RUNNING)
 513                        return CAPI_NOERROR;
 514        }
 515        return CAPI_REGNOTINSTALLED;
 516}
 517
 518EXPORT_SYMBOL(capi20_isinstalled);
 519
 520u16 capi20_register(struct capi20_appl *ap)
 521{
 522        int i;
 523        u16 applid;
 524        unsigned long flags;
 525
 526        DBG("");
 527
 528        if (ap->rparam.datablklen < 128)
 529                return CAPI_LOGBLKSIZETOSMALL;
 530
 531        write_lock_irqsave(&application_lock, flags);
 532
 533        for (applid = 1; applid <= CAPI_MAXAPPL; applid++) {
 534                if (capi_applications[applid - 1] == NULL)
 535                        break;
 536        }
 537        if (applid > CAPI_MAXAPPL) {
 538                write_unlock_irqrestore(&application_lock, flags);
 539                return CAPI_TOOMANYAPPLS;
 540        }
 541
 542        ap->applid = applid;
 543        capi_applications[applid - 1] = ap;
 544
 545        ap->nrecvctlpkt = 0;
 546        ap->nrecvdatapkt = 0;
 547        ap->nsentctlpkt = 0;
 548        ap->nsentdatapkt = 0;
 549        ap->callback = NULL;
 550        mutex_init(&ap->recv_mtx);
 551        skb_queue_head_init(&ap->recv_queue);
 552        INIT_WORK(&ap->recv_work, recv_handler);
 553        ap->release_in_progress = 0;
 554
 555        write_unlock_irqrestore(&application_lock, flags);
 556        
 557        mutex_lock(&controller_mutex);
 558        for (i = 0; i < CAPI_MAXCONTR; i++) {
 559                if (!capi_cards[i] || capi_cards[i]->cardstate != CARD_RUNNING)
 560                        continue;
 561                register_appl(capi_cards[i], applid, &ap->rparam);
 562        }
 563        mutex_unlock(&controller_mutex);
 564
 565        if (showcapimsgs & 1) {
 566                printk(KERN_DEBUG "kcapi: appl %d up\n", applid);
 567        }
 568
 569        return CAPI_NOERROR;
 570}
 571
 572EXPORT_SYMBOL(capi20_register);
 573
 574u16 capi20_release(struct capi20_appl *ap)
 575{
 576        int i;
 577        unsigned long flags;
 578
 579        DBG("applid %#x", ap->applid);
 580
 581        write_lock_irqsave(&application_lock, flags);
 582        ap->release_in_progress = 1;
 583        capi_applications[ap->applid - 1] = NULL;
 584        write_unlock_irqrestore(&application_lock, flags);
 585
 586        mutex_lock(&controller_mutex);
 587        for (i = 0; i < CAPI_MAXCONTR; i++) {
 588                if (!capi_cards[i] || capi_cards[i]->cardstate != CARD_RUNNING)
 589                        continue;
 590                release_appl(capi_cards[i], ap->applid);
 591        }
 592        mutex_unlock(&controller_mutex);
 593
 594        flush_scheduled_work();
 595        skb_queue_purge(&ap->recv_queue);
 596
 597        if (showcapimsgs & 1) {
 598                printk(KERN_DEBUG "kcapi: appl %d down\n", ap->applid);
 599        }
 600
 601        return CAPI_NOERROR;
 602}
 603
 604EXPORT_SYMBOL(capi20_release);
 605
 606u16 capi20_put_message(struct capi20_appl *ap, struct sk_buff *skb)
 607{
 608        struct capi_ctr *card;
 609        int showctl = 0;
 610        u8 cmd, subcmd;
 611
 612        DBG("applid %#x", ap->applid);
 613 
 614        if (ncards == 0)
 615                return CAPI_REGNOTINSTALLED;
 616        if ((ap->applid == 0) || ap->release_in_progress)
 617                return CAPI_ILLAPPNR;
 618        if (skb->len < 12
 619            || !capi_cmd_valid(CAPIMSG_COMMAND(skb->data))
 620            || !capi_subcmd_valid(CAPIMSG_SUBCOMMAND(skb->data)))
 621                return CAPI_ILLCMDORSUBCMDORMSGTOSMALL;
 622        card = get_capi_ctr_by_nr(CAPIMSG_CONTROLLER(skb->data));
 623        if (!card || card->cardstate != CARD_RUNNING) {
 624                card = get_capi_ctr_by_nr(1); // XXX why?
 625                if (!card || card->cardstate != CARD_RUNNING) 
 626                        return CAPI_REGNOTINSTALLED;
 627        }
 628        if (card->blocked)
 629                return CAPI_SENDQUEUEFULL;
 630
 631        cmd = CAPIMSG_COMMAND(skb->data);
 632        subcmd = CAPIMSG_SUBCOMMAND(skb->data);
 633
 634        if (cmd == CAPI_DATA_B3 && subcmd== CAPI_REQ) {
 635                card->nsentdatapkt++;
 636                ap->nsentdatapkt++;
 637                if (card->traceflag > 2) showctl |= 2;
 638        } else {
 639                card->nsentctlpkt++;
 640                ap->nsentctlpkt++;
 641                if (card->traceflag) showctl |= 2;
 642        }
 643        showctl |= (card->traceflag & 1);
 644        if (showctl & 2) {
 645                if (showctl & 1) {
 646                        printk(KERN_DEBUG "kcapi: put [%03d] id#%d %s len=%u\n",
 647                               CAPIMSG_CONTROLLER(skb->data),
 648                               CAPIMSG_APPID(skb->data),
 649                               capi_cmd2str(cmd, subcmd),
 650                               CAPIMSG_LEN(skb->data));
 651                } else {
 652                        _cdebbuf *cdb = capi_message2str(skb->data);
 653                        if (cdb) {
 654                                printk(KERN_DEBUG "kcapi: put [%03d] %s\n",
 655                                        CAPIMSG_CONTROLLER(skb->data),
 656                                        cdb->buf);
 657                                cdebbuf_free(cdb);
 658                        } else
 659                                printk(KERN_DEBUG "kcapi: put [%03d] id#%d %s len=%u cannot trace\n",
 660                                        CAPIMSG_CONTROLLER(skb->data),
 661                                        CAPIMSG_APPID(skb->data),
 662                                        capi_cmd2str(cmd, subcmd),
 663                                        CAPIMSG_LEN(skb->data));
 664                }
 665        }
 666        return card->send_message(card, skb);
 667}
 668
 669EXPORT_SYMBOL(capi20_put_message);
 670
 671u16 capi20_get_manufacturer(u32 contr, u8 *buf)
 672{
 673        struct capi_ctr *card;
 674
 675        if (contr == 0) {
 676                strlcpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN);
 677                return CAPI_NOERROR;
 678        }
 679        card = get_capi_ctr_by_nr(contr);
 680        if (!card || card->cardstate != CARD_RUNNING) 
 681                return CAPI_REGNOTINSTALLED;
 682        strlcpy(buf, card->manu, CAPI_MANUFACTURER_LEN);
 683        return CAPI_NOERROR;
 684}
 685
 686EXPORT_SYMBOL(capi20_get_manufacturer);
 687
 688u16 capi20_get_version(u32 contr, struct capi_version *verp)
 689{
 690        struct capi_ctr *card;
 691
 692        if (contr == 0) {
 693                *verp = driver_version;
 694                return CAPI_NOERROR;
 695        }
 696        card = get_capi_ctr_by_nr(contr);
 697        if (!card || card->cardstate != CARD_RUNNING) 
 698                return CAPI_REGNOTINSTALLED;
 699
 700        memcpy((void *) verp, &card->version, sizeof(capi_version));
 701        return CAPI_NOERROR;
 702}
 703
 704EXPORT_SYMBOL(capi20_get_version);
 705
 706u16 capi20_get_serial(u32 contr, u8 *serial)
 707{
 708        struct capi_ctr *card;
 709
 710        if (contr == 0) {
 711                strlcpy(serial, driver_serial, CAPI_SERIAL_LEN);
 712                return CAPI_NOERROR;
 713        }
 714        card = get_capi_ctr_by_nr(contr);
 715        if (!card || card->cardstate != CARD_RUNNING) 
 716                return CAPI_REGNOTINSTALLED;
 717
 718        strlcpy((void *) serial, card->serial, CAPI_SERIAL_LEN);
 719        return CAPI_NOERROR;
 720}
 721
 722EXPORT_SYMBOL(capi20_get_serial);
 723
 724u16 capi20_get_profile(u32 contr, struct capi_profile *profp)
 725{
 726        struct capi_ctr *card;
 727
 728        if (contr == 0) {
 729                profp->ncontroller = ncards;
 730                return CAPI_NOERROR;
 731        }
 732        card = get_capi_ctr_by_nr(contr);
 733        if (!card || card->cardstate != CARD_RUNNING) 
 734                return CAPI_REGNOTINSTALLED;
 735
 736        memcpy((void *) profp, &card->profile,
 737                        sizeof(struct capi_profile));
 738        return CAPI_NOERROR;
 739}
 740
 741EXPORT_SYMBOL(capi20_get_profile);
 742
 743#ifdef AVMB1_COMPAT
 744static int old_capi_manufacturer(unsigned int cmd, void __user *data)
 745{
 746        avmb1_loadandconfigdef ldef;
 747        avmb1_extcarddef cdef;
 748        avmb1_resetdef rdef;
 749        capicardparams cparams;
 750        struct capi_ctr *card;
 751        struct capi_driver *driver = NULL;
 752        capiloaddata ldata;
 753        struct list_head *l;
 754        unsigned long flags;
 755        int retval;
 756
 757        switch (cmd) {
 758        case AVMB1_ADDCARD:
 759        case AVMB1_ADDCARD_WITH_TYPE:
 760                if (cmd == AVMB1_ADDCARD) {
 761                   if ((retval = copy_from_user(&cdef, data,
 762                                            sizeof(avmb1_carddef))))
 763                           return retval;
 764                   cdef.cardtype = AVM_CARDTYPE_B1;
 765                } else {
 766                   if ((retval = copy_from_user(&cdef, data,
 767                                            sizeof(avmb1_extcarddef))))
 768                           return retval;
 769                }
 770                cparams.port = cdef.port;
 771                cparams.irq = cdef.irq;
 772                cparams.cardnr = cdef.cardnr;
 773
 774                read_lock_irqsave(&capi_drivers_list_lock, flags);
 775                switch (cdef.cardtype) {
 776                        case AVM_CARDTYPE_B1:
 777                                list_for_each(l, &capi_drivers) {
 778                                        driver = list_entry(l, struct capi_driver, list);
 779                                        if (strcmp(driver->name, "b1isa") == 0)
 780                                                break;
 781                                }
 782                                break;
 783                        case AVM_CARDTYPE_T1:
 784                                list_for_each(l, &capi_drivers) {
 785                                        driver = list_entry(l, struct capi_driver, list);
 786                                        if (strcmp(driver->name, "t1isa") == 0)
 787                                                break;
 788                                }
 789                                break;
 790                        default:
 791                                driver = NULL;
 792                                break;
 793                }
 794                if (!driver) {
 795                        read_unlock_irqrestore(&capi_drivers_list_lock, flags);
 796                        printk(KERN_ERR "kcapi: driver not loaded.\n");
 797                        return -EIO;
 798                }
 799                if (!driver->add_card) {
 800                        read_unlock_irqrestore(&capi_drivers_list_lock, flags);
 801                        printk(KERN_ERR "kcapi: driver has no add card function.\n");
 802                        return -EIO;
 803                }
 804
 805                retval = driver->add_card(driver, &cparams);
 806                read_unlock_irqrestore(&capi_drivers_list_lock, flags);
 807                return retval;
 808
 809        case AVMB1_LOAD:
 810        case AVMB1_LOAD_AND_CONFIG:
 811
 812                if (cmd == AVMB1_LOAD) {
 813                        if (copy_from_user(&ldef, data,
 814                                           sizeof(avmb1_loaddef)))
 815                                return -EFAULT;
 816                        ldef.t4config.len = 0;
 817                        ldef.t4config.data = NULL;
 818                } else {
 819                        if (copy_from_user(&ldef, data,
 820                                           sizeof(avmb1_loadandconfigdef)))
 821                                return -EFAULT;
 822                }
 823                card = get_capi_ctr_by_nr(ldef.contr);
 824                if (!card)
 825                        return -EINVAL;
 826                card = capi_ctr_get(card);
 827                if (!card)
 828                        return -ESRCH;
 829                if (card->load_firmware == NULL) {
 830                        printk(KERN_DEBUG "kcapi: load: no load function\n");
 831                        capi_ctr_put(card);
 832                        return -ESRCH;
 833                }
 834
 835                if (ldef.t4file.len <= 0) {
 836                        printk(KERN_DEBUG "kcapi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len);
 837                        capi_ctr_put(card);
 838                        return -EINVAL;
 839                }
 840                if (ldef.t4file.data == NULL) {
 841                        printk(KERN_DEBUG "kcapi: load: invalid parameter: dataptr is 0\n");
 842                        capi_ctr_put(card);
 843                        return -EINVAL;
 844                }
 845
 846                ldata.firmware.user = 1;
 847                ldata.firmware.data = ldef.t4file.data;
 848                ldata.firmware.len = ldef.t4file.len;
 849                ldata.configuration.user = 1;
 850                ldata.configuration.data = ldef.t4config.data;
 851                ldata.configuration.len = ldef.t4config.len;
 852
 853                if (card->cardstate != CARD_DETECTED) {
 854                        printk(KERN_INFO "kcapi: load: contr=%d not in detect state\n", ldef.contr);
 855                        capi_ctr_put(card);
 856                        return -EBUSY;
 857                }
 858                card->cardstate = CARD_LOADING;
 859
 860                retval = card->load_firmware(card, &ldata);
 861
 862                if (retval) {
 863                        card->cardstate = CARD_DETECTED;
 864                        capi_ctr_put(card);
 865                        return retval;
 866                }
 867
 868                while (card->cardstate != CARD_RUNNING) {
 869
 870                        msleep_interruptible(100);      /* 0.1 sec */
 871
 872                        if (signal_pending(current)) {
 873                                capi_ctr_put(card);
 874                                return -EINTR;
 875                        }
 876                }
 877                capi_ctr_put(card);
 878                return 0;
 879
 880        case AVMB1_RESETCARD:
 881                if (copy_from_user(&rdef, data, sizeof(avmb1_resetdef)))
 882                        return -EFAULT;
 883                card = get_capi_ctr_by_nr(rdef.contr);
 884                if (!card)
 885                        return -ESRCH;
 886
 887                if (card->cardstate == CARD_DETECTED)
 888                        return 0;
 889
 890                card->reset_ctr(card);
 891
 892                while (card->cardstate > CARD_DETECTED) {
 893
 894                        msleep_interruptible(100);      /* 0.1 sec */
 895
 896                        if (signal_pending(current))
 897                                return -EINTR;
 898                }
 899                return 0;
 900
 901        }
 902        return -EINVAL;
 903}
 904#endif
 905
 906int capi20_manufacturer(unsigned int cmd, void __user *data)
 907{
 908        struct capi_ctr *card;
 909
 910        switch (cmd) {
 911#ifdef AVMB1_COMPAT
 912        case AVMB1_LOAD:
 913        case AVMB1_LOAD_AND_CONFIG:
 914        case AVMB1_RESETCARD:
 915        case AVMB1_GET_CARDINFO:
 916        case AVMB1_REMOVECARD:
 917                return old_capi_manufacturer(cmd, data);
 918#endif
 919        case KCAPI_CMD_TRACE:
 920        {
 921                kcapi_flagdef fdef;
 922
 923                if (copy_from_user(&fdef, data, sizeof(kcapi_flagdef)))
 924                        return -EFAULT;
 925
 926                card = get_capi_ctr_by_nr(fdef.contr);
 927                if (!card)
 928                        return -ESRCH;
 929
 930                card->traceflag = fdef.flag;
 931                printk(KERN_INFO "kcapi: contr [%03d] set trace=%d\n",
 932                        card->cnr, card->traceflag);
 933                return 0;
 934        }
 935        case KCAPI_CMD_ADDCARD:
 936        {
 937                struct list_head *l;
 938                struct capi_driver *driver = NULL;
 939                capicardparams cparams;
 940                kcapi_carddef cdef;
 941                int retval;
 942
 943                if ((retval = copy_from_user(&cdef, data, sizeof(cdef))))
 944                        return retval;
 945
 946                cparams.port = cdef.port;
 947                cparams.irq = cdef.irq;
 948                cparams.membase = cdef.membase;
 949                cparams.cardnr = cdef.cardnr;
 950                cparams.cardtype = 0;
 951                cdef.driver[sizeof(cdef.driver)-1] = 0;
 952
 953                list_for_each(l, &capi_drivers) {
 954                        driver = list_entry(l, struct capi_driver, list);
 955                        if (strcmp(driver->name, cdef.driver) == 0)
 956                                break;
 957                }
 958                if (driver == NULL) {
 959                        printk(KERN_ERR "kcapi: driver \"%s\" not loaded.\n",
 960                                        cdef.driver);
 961                        return -ESRCH;
 962                }
 963
 964                if (!driver->add_card) {
 965                        printk(KERN_ERR "kcapi: driver \"%s\" has no add card function.\n", cdef.driver);
 966                        return -EIO;
 967                }
 968
 969                return driver->add_card(driver, &cparams);
 970        }
 971
 972        default:
 973                printk(KERN_ERR "kcapi: manufacturer command %d unknown.\n",
 974                                        cmd);
 975                break;
 976
 977        }
 978        return -EINVAL;
 979}
 980
 981EXPORT_SYMBOL(capi20_manufacturer);
 982
 983/* temporary hack */
 984void capi20_set_callback(struct capi20_appl *ap,
 985                         void (*callback) (unsigned int cmd, __u32 contr, void *data))
 986{
 987        ap->callback = callback;
 988}
 989
 990EXPORT_SYMBOL(capi20_set_callback);
 991
 992/* ------------------------------------------------------------- */
 993/* -------- Init & Cleanup ------------------------------------- */
 994/* ------------------------------------------------------------- */
 995
 996/*
 997 * init / exit functions
 998 */
 999
1000static int __init kcapi_init(void)
1001{
1002        char *p;
1003        char rev[32];
1004        int ret;
1005
1006        ret = cdebug_init();
1007        if (ret)
1008                return ret;
1009        kcapi_proc_init();
1010
1011        if ((p = strchr(revision, ':')) != NULL && p[1]) {
1012                strlcpy(rev, p + 2, sizeof(rev));
1013                if ((p = strchr(rev, '$')) != NULL && p > rev)
1014                   *(p-1) = 0;
1015        } else
1016                strcpy(rev, "1.0");
1017
1018        printk(KERN_NOTICE "CAPI Subsystem Rev %s\n", rev);
1019
1020        return 0;
1021}
1022
1023static void __exit kcapi_exit(void)
1024{
1025        kcapi_proc_exit();
1026
1027        /* make sure all notifiers are finished */
1028        flush_scheduled_work();
1029        cdebug_exit();
1030}
1031
1032module_init(kcapi_init);
1033module_exit(kcapi_exit);
1034