linux/drivers/isdn/capi/capi.c
<<
>>
Prefs
   1/* $Id: capi.c,v 1.1.2.7 2004/04/28 09:48:59 armin Exp $
   2 *
   3 * CAPI 2.0 Interface for Linux
   4 *
   5 * Copyright 1996 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/sched.h>
  17#include <linux/slab.h>
  18#include <linux/fcntl.h>
  19#include <linux/fs.h>
  20#include <linux/signal.h>
  21#include <linux/mutex.h>
  22#include <linux/mm.h>
  23#include <linux/smp_lock.h>
  24#include <linux/timer.h>
  25#include <linux/wait.h>
  26#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
  27#include <linux/tty.h>
  28#ifdef CONFIG_PPP
  29#include <linux/netdevice.h>
  30#include <linux/ppp_defs.h>
  31#include <linux/if_ppp.h>
  32#endif /* CONFIG_PPP */
  33#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
  34#include <linux/skbuff.h>
  35#include <linux/proc_fs.h>
  36#include <linux/poll.h>
  37#include <linux/capi.h>
  38#include <linux/kernelcapi.h>
  39#include <linux/init.h>
  40#include <linux/device.h>
  41#include <linux/moduleparam.h>
  42#include <linux/isdn/capiutil.h>
  43#include <linux/isdn/capicmd.h>
  44#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE)
  45#include "capifs.h"
  46#endif
  47
  48static char *revision = "$Revision: 1.1.2.7 $";
  49
  50MODULE_DESCRIPTION("CAPI4Linux: Userspace /dev/capi20 interface");
  51MODULE_AUTHOR("Carsten Paeth");
  52MODULE_LICENSE("GPL");
  53
  54#undef _DEBUG_REFCOUNT          /* alloc/free and open/close debug */
  55#undef _DEBUG_TTYFUNCS          /* call to tty_driver */
  56#undef _DEBUG_DATAFLOW          /* data flow */
  57
  58/* -------- driver information -------------------------------------- */
  59
  60static struct class *capi_class;
  61
  62static int capi_major = 68;             /* allocated */
  63#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
  64#define CAPINC_NR_PORTS 32
  65#define CAPINC_MAX_PORTS        256
  66static int capi_ttymajor = 191;
  67static int capi_ttyminors = CAPINC_NR_PORTS;
  68#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
  69
  70module_param_named(major, capi_major, uint, 0);
  71#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
  72module_param_named(ttymajor, capi_ttymajor, uint, 0);
  73module_param_named(ttyminors, capi_ttyminors, uint, 0);
  74#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
  75
  76/* -------- defines ------------------------------------------------- */
  77
  78#define CAPINC_MAX_RECVQUEUE    10
  79#define CAPINC_MAX_SENDQUEUE    10
  80#define CAPI_MAX_BLKSIZE        2048
  81
  82/* -------- data structures ----------------------------------------- */
  83
  84struct capidev;
  85struct capincci;
  86#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
  87struct capiminor;
  88
  89struct datahandle_queue {
  90        struct list_head        list;
  91        u16                     datahandle;
  92};
  93
  94struct capiminor {
  95        struct list_head list;
  96        struct capincci  *nccip;
  97        unsigned int      minor;
  98
  99        struct capi20_appl *ap;
 100        u32              ncci;
 101        u16              datahandle;
 102        u16              msgid;
 103
 104        struct tty_struct *tty;
 105        int                ttyinstop;
 106        int                ttyoutstop;
 107        struct sk_buff    *ttyskb;
 108        atomic_t           ttyopencount;
 109
 110        struct sk_buff_head inqueue;
 111        int                 inbytes;
 112        struct sk_buff_head outqueue;
 113        int                 outbytes;
 114
 115        /* transmit path */
 116        struct list_head ackqueue;
 117        int nack;
 118        spinlock_t ackqlock;
 119};
 120#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 121
 122/* FIXME: The following lock is a sledgehammer-workaround to a
 123 * locking issue with the capiminor (and maybe other) data structure(s).
 124 * Access to this data is done in a racy way and crashes the machine with
 125 * a FritzCard DSL driver; sooner or later. This is a workaround
 126 * which trades scalability vs stability, so it doesn't crash the kernel anymore.
 127 * The correct (and scalable) fix for the issue seems to require
 128 * an API change to the drivers... . */
 129static DEFINE_SPINLOCK(workaround_lock);
 130
 131struct capincci {
 132        struct capincci *next;
 133        u32              ncci;
 134        struct capidev  *cdev;
 135#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 136        struct capiminor *minorp;
 137#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 138};
 139
 140struct capidev {
 141        struct list_head list;
 142        struct capi20_appl ap;
 143        u16             errcode;
 144        unsigned        userflags;
 145
 146        struct sk_buff_head recvqueue;
 147        wait_queue_head_t recvwait;
 148
 149        struct capincci *nccis;
 150
 151        struct mutex ncci_list_mtx;
 152};
 153
 154/* -------- global variables ---------------------------------------- */
 155
 156static DEFINE_RWLOCK(capidev_list_lock);
 157static LIST_HEAD(capidev_list);
 158
 159#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 160static DEFINE_RWLOCK(capiminor_list_lock);
 161static LIST_HEAD(capiminor_list);
 162#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 163
 164#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 165/* -------- datahandles --------------------------------------------- */
 166
 167static int capincci_add_ack(struct capiminor *mp, u16 datahandle)
 168{
 169        struct datahandle_queue *n;
 170        unsigned long flags;
 171
 172        n = kmalloc(sizeof(*n), GFP_ATOMIC);
 173        if (unlikely(!n)) {
 174                printk(KERN_ERR "capi: alloc datahandle failed\n");
 175                return -1;
 176        }
 177        n->datahandle = datahandle;
 178        INIT_LIST_HEAD(&n->list);
 179        spin_lock_irqsave(&mp->ackqlock, flags);
 180        list_add_tail(&n->list, &mp->ackqueue);
 181        mp->nack++;
 182        spin_unlock_irqrestore(&mp->ackqlock, flags);
 183        return 0;
 184}
 185
 186static int capiminor_del_ack(struct capiminor *mp, u16 datahandle)
 187{
 188        struct datahandle_queue *p, *tmp;
 189        unsigned long flags;
 190
 191        spin_lock_irqsave(&mp->ackqlock, flags);
 192        list_for_each_entry_safe(p, tmp, &mp->ackqueue, list) {
 193                if (p->datahandle == datahandle) {
 194                        list_del(&p->list);
 195                        kfree(p);
 196                        mp->nack--;
 197                        spin_unlock_irqrestore(&mp->ackqlock, flags);
 198                        return 0;
 199                }
 200        }
 201        spin_unlock_irqrestore(&mp->ackqlock, flags);
 202        return -1;
 203}
 204
 205static void capiminor_del_all_ack(struct capiminor *mp)
 206{
 207        struct datahandle_queue *p, *tmp;
 208        unsigned long flags;
 209
 210        spin_lock_irqsave(&mp->ackqlock, flags);
 211        list_for_each_entry_safe(p, tmp, &mp->ackqueue, list) {
 212                list_del(&p->list);
 213                kfree(p);
 214                mp->nack--;
 215        }
 216        spin_unlock_irqrestore(&mp->ackqlock, flags);
 217}
 218
 219
 220/* -------- struct capiminor ---------------------------------------- */
 221
 222static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci)
 223{
 224        struct capiminor *mp, *p;
 225        unsigned int minor = 0;
 226        unsigned long flags;
 227
 228        mp = kzalloc(sizeof(*mp), GFP_ATOMIC);
 229        if (!mp) {
 230                printk(KERN_ERR "capi: can't alloc capiminor\n");
 231                return NULL;
 232        }
 233
 234        mp->ap = ap;
 235        mp->ncci = ncci;
 236        mp->msgid = 0;
 237        atomic_set(&mp->ttyopencount,0);
 238        INIT_LIST_HEAD(&mp->ackqueue);
 239        spin_lock_init(&mp->ackqlock);
 240
 241        skb_queue_head_init(&mp->inqueue);
 242        skb_queue_head_init(&mp->outqueue);
 243
 244        /* Allocate the least unused minor number.
 245         */
 246        write_lock_irqsave(&capiminor_list_lock, flags);
 247        if (list_empty(&capiminor_list))
 248                list_add(&mp->list, &capiminor_list);
 249        else {
 250                list_for_each_entry(p, &capiminor_list, list) {
 251                        if (p->minor > minor)
 252                                break;
 253                        minor++;
 254                }
 255                
 256                if (minor < capi_ttyminors) {
 257                        mp->minor = minor;
 258                        list_add(&mp->list, p->list.prev);
 259                }
 260        }
 261                write_unlock_irqrestore(&capiminor_list_lock, flags);
 262
 263        if (!(minor < capi_ttyminors)) {
 264                printk(KERN_NOTICE "capi: out of minors\n");
 265                        kfree(mp);
 266                return NULL;
 267        }
 268
 269        return mp;
 270}
 271
 272static void capiminor_free(struct capiminor *mp)
 273{
 274        unsigned long flags;
 275
 276        write_lock_irqsave(&capiminor_list_lock, flags);
 277        list_del(&mp->list);
 278        write_unlock_irqrestore(&capiminor_list_lock, flags);
 279
 280        kfree_skb(mp->ttyskb);
 281        mp->ttyskb = NULL;
 282        skb_queue_purge(&mp->inqueue);
 283        skb_queue_purge(&mp->outqueue);
 284        capiminor_del_all_ack(mp);
 285        kfree(mp);
 286}
 287
 288static struct capiminor *capiminor_find(unsigned int minor)
 289{
 290        struct list_head *l;
 291        struct capiminor *p = NULL;
 292
 293        read_lock(&capiminor_list_lock);
 294        list_for_each(l, &capiminor_list) {
 295                p = list_entry(l, struct capiminor, list);
 296                if (p->minor == minor)
 297                        break;
 298        }
 299        read_unlock(&capiminor_list_lock);
 300        if (l == &capiminor_list)
 301                return NULL;
 302
 303        return p;
 304}
 305#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 306
 307/* -------- struct capincci ----------------------------------------- */
 308
 309static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci)
 310{
 311        struct capincci *np, **pp;
 312#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 313        struct capiminor *mp = NULL;
 314#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 315
 316        np = kzalloc(sizeof(*np), GFP_ATOMIC);
 317        if (!np)
 318                return NULL;
 319        np->ncci = ncci;
 320        np->cdev = cdev;
 321#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 322        mp = NULL;
 323        if (cdev->userflags & CAPIFLAG_HIGHJACKING)
 324                mp = np->minorp = capiminor_alloc(&cdev->ap, ncci);
 325        if (mp) {
 326                mp->nccip = np;
 327#ifdef _DEBUG_REFCOUNT
 328                printk(KERN_DEBUG "set mp->nccip\n");
 329#endif
 330#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE)
 331                capifs_new_ncci(mp->minor, MKDEV(capi_ttymajor, mp->minor));
 332#endif
 333        }
 334#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 335        for (pp=&cdev->nccis; *pp; pp = &(*pp)->next)
 336                ;
 337        *pp = np;
 338        return np;
 339}
 340
 341static void capincci_free(struct capidev *cdev, u32 ncci)
 342{
 343        struct capincci *np, **pp;
 344#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 345        struct capiminor *mp;
 346#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 347
 348        pp=&cdev->nccis;
 349        while (*pp) {
 350                np = *pp;
 351                if (ncci == 0xffffffff || np->ncci == ncci) {
 352                        *pp = (*pp)->next;
 353#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 354                        if ((mp = np->minorp) != NULL) {
 355#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE)
 356                                capifs_free_ncci(mp->minor);
 357#endif
 358                                if (mp->tty) {
 359                                        mp->nccip = NULL;
 360#ifdef _DEBUG_REFCOUNT
 361                                        printk(KERN_DEBUG "reset mp->nccip\n");
 362#endif
 363                                        tty_hangup(mp->tty);
 364                                } else {
 365                                        capiminor_free(mp);
 366                                }
 367                        }
 368#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 369                        kfree(np);
 370                        if (*pp == NULL) return;
 371                } else {
 372                        pp = &(*pp)->next;
 373                }
 374        }
 375}
 376
 377static struct capincci *capincci_find(struct capidev *cdev, u32 ncci)
 378{
 379        struct capincci *p;
 380
 381        for (p=cdev->nccis; p ; p = p->next) {
 382                if (p->ncci == ncci)
 383                        break;
 384        }
 385        return p;
 386}
 387
 388/* -------- struct capidev ------------------------------------------ */
 389
 390static struct capidev *capidev_alloc(void)
 391{
 392        struct capidev *cdev;
 393        unsigned long flags;
 394
 395        cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
 396        if (!cdev)
 397                return NULL;
 398
 399        mutex_init(&cdev->ncci_list_mtx);
 400        skb_queue_head_init(&cdev->recvqueue);
 401        init_waitqueue_head(&cdev->recvwait);
 402        write_lock_irqsave(&capidev_list_lock, flags);
 403        list_add_tail(&cdev->list, &capidev_list);
 404        write_unlock_irqrestore(&capidev_list_lock, flags);
 405        return cdev;
 406}
 407
 408static void capidev_free(struct capidev *cdev)
 409{
 410        unsigned long flags;
 411
 412        if (cdev->ap.applid) {
 413                capi20_release(&cdev->ap);
 414                cdev->ap.applid = 0;
 415        }
 416        skb_queue_purge(&cdev->recvqueue);
 417
 418        mutex_lock(&cdev->ncci_list_mtx);
 419        capincci_free(cdev, 0xffffffff);
 420        mutex_unlock(&cdev->ncci_list_mtx);
 421
 422        write_lock_irqsave(&capidev_list_lock, flags);
 423        list_del(&cdev->list);
 424        write_unlock_irqrestore(&capidev_list_lock, flags);
 425        kfree(cdev);
 426}
 427
 428#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 429/* -------- handle data queue --------------------------------------- */
 430
 431static struct sk_buff *
 432gen_data_b3_resp_for(struct capiminor *mp, struct sk_buff *skb)
 433{
 434        struct sk_buff *nskb;
 435        nskb = alloc_skb(CAPI_DATA_B3_RESP_LEN, GFP_ATOMIC);
 436        if (nskb) {
 437                u16 datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4+4+2);
 438                unsigned char *s = skb_put(nskb, CAPI_DATA_B3_RESP_LEN);
 439                capimsg_setu16(s, 0, CAPI_DATA_B3_RESP_LEN);
 440                capimsg_setu16(s, 2, mp->ap->applid);
 441                capimsg_setu8 (s, 4, CAPI_DATA_B3);
 442                capimsg_setu8 (s, 5, CAPI_RESP);
 443                capimsg_setu16(s, 6, mp->msgid++);
 444                capimsg_setu32(s, 8, mp->ncci);
 445                capimsg_setu16(s, 12, datahandle);
 446        }
 447        return nskb;
 448}
 449
 450static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb)
 451{
 452        struct sk_buff *nskb;
 453        int datalen;
 454        u16 errcode, datahandle;
 455        struct tty_ldisc *ld;
 456        
 457        datalen = skb->len - CAPIMSG_LEN(skb->data);
 458        if (mp->tty == NULL)
 459        {
 460#ifdef _DEBUG_DATAFLOW
 461                printk(KERN_DEBUG "capi: currently no receiver\n");
 462#endif
 463                return -1;
 464        }
 465        
 466        ld = tty_ldisc_ref(mp->tty);
 467        if (ld == NULL)
 468                return -1;
 469        if (ld->ops->receive_buf == NULL) {
 470#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
 471                printk(KERN_DEBUG "capi: ldisc has no receive_buf function\n");
 472#endif
 473                goto bad;
 474        }
 475        if (mp->ttyinstop) {
 476#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
 477                printk(KERN_DEBUG "capi: recv tty throttled\n");
 478#endif
 479                goto bad;
 480        }
 481        if (mp->tty->receive_room < datalen) {
 482#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
 483                printk(KERN_DEBUG "capi: no room in tty\n");
 484#endif
 485                goto bad;
 486        }
 487        if ((nskb = gen_data_b3_resp_for(mp, skb)) == NULL) {
 488                printk(KERN_ERR "capi: gen_data_b3_resp failed\n");
 489                goto bad;
 490        }
 491        datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4);
 492        errcode = capi20_put_message(mp->ap, nskb);
 493        if (errcode != CAPI_NOERROR) {
 494                printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n",
 495                                errcode);
 496                kfree_skb(nskb);
 497                goto bad;
 498        }
 499        (void)skb_pull(skb, CAPIMSG_LEN(skb->data));
 500#ifdef _DEBUG_DATAFLOW
 501        printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ldisc\n",
 502                                datahandle, skb->len);
 503#endif
 504        ld->ops->receive_buf(mp->tty, skb->data, NULL, skb->len);
 505        kfree_skb(skb);
 506        tty_ldisc_deref(ld);
 507        return 0;
 508bad:
 509        tty_ldisc_deref(ld);
 510        return -1;
 511}
 512
 513static void handle_minor_recv(struct capiminor *mp)
 514{
 515        struct sk_buff *skb;
 516        while ((skb = skb_dequeue(&mp->inqueue)) != NULL) {
 517                unsigned int len = skb->len;
 518                mp->inbytes -= len;
 519                if (handle_recv_skb(mp, skb) < 0) {
 520                        skb_queue_head(&mp->inqueue, skb);
 521                        mp->inbytes += len;
 522                        return;
 523                }
 524        }
 525}
 526
 527static int handle_minor_send(struct capiminor *mp)
 528{
 529        struct sk_buff *skb;
 530        u16 len;
 531        int count = 0;
 532        u16 errcode;
 533        u16 datahandle;
 534
 535        if (mp->tty && mp->ttyoutstop) {
 536#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
 537                printk(KERN_DEBUG "capi: send: tty stopped\n");
 538#endif
 539                return 0;
 540        }
 541
 542        while ((skb = skb_dequeue(&mp->outqueue)) != NULL) {
 543                datahandle = mp->datahandle;
 544                len = (u16)skb->len;
 545                skb_push(skb, CAPI_DATA_B3_REQ_LEN);
 546                memset(skb->data, 0, CAPI_DATA_B3_REQ_LEN);
 547                capimsg_setu16(skb->data, 0, CAPI_DATA_B3_REQ_LEN);
 548                capimsg_setu16(skb->data, 2, mp->ap->applid);
 549                capimsg_setu8 (skb->data, 4, CAPI_DATA_B3);
 550                capimsg_setu8 (skb->data, 5, CAPI_REQ);
 551                capimsg_setu16(skb->data, 6, mp->msgid++);
 552                capimsg_setu32(skb->data, 8, mp->ncci); /* NCCI */
 553                capimsg_setu32(skb->data, 12, (u32)(long)skb->data);/* Data32 */
 554                capimsg_setu16(skb->data, 16, len);     /* Data length */
 555                capimsg_setu16(skb->data, 18, datahandle);
 556                capimsg_setu16(skb->data, 20, 0);       /* Flags */
 557
 558                if (capincci_add_ack(mp, datahandle) < 0) {
 559                        skb_pull(skb, CAPI_DATA_B3_REQ_LEN);
 560                        skb_queue_head(&mp->outqueue, skb);
 561                        return count;
 562                }
 563                errcode = capi20_put_message(mp->ap, skb);
 564                if (errcode == CAPI_NOERROR) {
 565                        mp->datahandle++;
 566                        count++;
 567                        mp->outbytes -= len;
 568#ifdef _DEBUG_DATAFLOW
 569                        printk(KERN_DEBUG "capi: DATA_B3_REQ %u len=%u\n",
 570                                                        datahandle, len);
 571#endif
 572                        continue;
 573                }
 574                capiminor_del_ack(mp, datahandle);
 575
 576                if (errcode == CAPI_SENDQUEUEFULL) {
 577                        skb_pull(skb, CAPI_DATA_B3_REQ_LEN);
 578                        skb_queue_head(&mp->outqueue, skb);
 579                        break;
 580                }
 581
 582                /* ups, drop packet */
 583                printk(KERN_ERR "capi: put_message = %x\n", errcode);
 584                mp->outbytes -= len;
 585                kfree_skb(skb);
 586        }
 587        return count;
 588}
 589
 590#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 591/* -------- function called by lower level -------------------------- */
 592
 593static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
 594{
 595        struct capidev *cdev = ap->private;
 596#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 597        struct capiminor *mp;
 598        u16 datahandle;
 599#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 600        struct capincci *np;
 601        u32 ncci;
 602        unsigned long flags;
 603
 604        if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_CONF) {
 605                u16 info = CAPIMSG_U16(skb->data, 12); // Info field
 606                if ((info & 0xff00) == 0) {
 607                        mutex_lock(&cdev->ncci_list_mtx);
 608                        capincci_alloc(cdev, CAPIMSG_NCCI(skb->data));
 609                        mutex_unlock(&cdev->ncci_list_mtx);
 610                }
 611        }
 612        if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_IND) {
 613                mutex_lock(&cdev->ncci_list_mtx);
 614                capincci_alloc(cdev, CAPIMSG_NCCI(skb->data));
 615                mutex_unlock(&cdev->ncci_list_mtx);
 616        }
 617        spin_lock_irqsave(&workaround_lock, flags);
 618        if (CAPIMSG_COMMAND(skb->data) != CAPI_DATA_B3) {
 619                skb_queue_tail(&cdev->recvqueue, skb);
 620                wake_up_interruptible(&cdev->recvwait);
 621                spin_unlock_irqrestore(&workaround_lock, flags);
 622                return;
 623        }
 624        ncci = CAPIMSG_CONTROL(skb->data);
 625        for (np = cdev->nccis; np && np->ncci != ncci; np = np->next)
 626                ;
 627        if (!np) {
 628                printk(KERN_ERR "BUG: capi_signal: ncci not found\n");
 629                skb_queue_tail(&cdev->recvqueue, skb);
 630                wake_up_interruptible(&cdev->recvwait);
 631                spin_unlock_irqrestore(&workaround_lock, flags);
 632                return;
 633        }
 634#ifndef CONFIG_ISDN_CAPI_MIDDLEWARE
 635        skb_queue_tail(&cdev->recvqueue, skb);
 636        wake_up_interruptible(&cdev->recvwait);
 637#else /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 638        mp = np->minorp;
 639        if (!mp) {
 640                skb_queue_tail(&cdev->recvqueue, skb);
 641                wake_up_interruptible(&cdev->recvwait);
 642                spin_unlock_irqrestore(&workaround_lock, flags);
 643                return;
 644        }
 645
 646
 647        if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) {
 648                
 649                datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+4+2);
 650#ifdef _DEBUG_DATAFLOW
 651                printk(KERN_DEBUG "capi_signal: DATA_B3_IND %u len=%d\n",
 652                                datahandle, skb->len-CAPIMSG_LEN(skb->data));
 653#endif
 654                skb_queue_tail(&mp->inqueue, skb);
 655                mp->inbytes += skb->len;
 656                handle_minor_recv(mp);
 657
 658        } else if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_CONF) {
 659
 660                datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4);
 661#ifdef _DEBUG_DATAFLOW
 662                printk(KERN_DEBUG "capi_signal: DATA_B3_CONF %u 0x%x\n",
 663                                datahandle,
 664                                CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+2));
 665#endif
 666                kfree_skb(skb);
 667                (void)capiminor_del_ack(mp, datahandle);
 668                if (mp->tty)
 669                        tty_wakeup(mp->tty);
 670                (void)handle_minor_send(mp);
 671
 672        } else {
 673                /* ups, let capi application handle it :-) */
 674                skb_queue_tail(&cdev->recvqueue, skb);
 675                wake_up_interruptible(&cdev->recvwait);
 676        }
 677#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 678        spin_unlock_irqrestore(&workaround_lock, flags);
 679}
 680
 681/* -------- file_operations for capidev ----------------------------- */
 682
 683static ssize_t
 684capi_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 685{
 686        struct capidev *cdev = (struct capidev *)file->private_data;
 687        struct sk_buff *skb;
 688        size_t copied;
 689
 690        if (!cdev->ap.applid)
 691                return -ENODEV;
 692
 693        if ((skb = skb_dequeue(&cdev->recvqueue)) == NULL) {
 694
 695                if (file->f_flags & O_NONBLOCK)
 696                        return -EAGAIN;
 697
 698                for (;;) {
 699                        interruptible_sleep_on(&cdev->recvwait);
 700                        if ((skb = skb_dequeue(&cdev->recvqueue)) != NULL)
 701                                break;
 702                        if (signal_pending(current))
 703                                break;
 704                }
 705                if (skb == NULL)
 706                        return -ERESTARTNOHAND;
 707        }
 708        if (skb->len > count) {
 709                skb_queue_head(&cdev->recvqueue, skb);
 710                return -EMSGSIZE;
 711        }
 712        if (copy_to_user(buf, skb->data, skb->len)) {
 713                skb_queue_head(&cdev->recvqueue, skb);
 714                return -EFAULT;
 715        }
 716        copied = skb->len;
 717
 718        kfree_skb(skb);
 719
 720        return copied;
 721}
 722
 723static ssize_t
 724capi_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 725{
 726        struct capidev *cdev = (struct capidev *)file->private_data;
 727        struct sk_buff *skb;
 728        u16 mlen;
 729
 730        if (!cdev->ap.applid)
 731                return -ENODEV;
 732
 733        skb = alloc_skb(count, GFP_USER);
 734        if (!skb)
 735                return -ENOMEM;
 736
 737        if (copy_from_user(skb_put(skb, count), buf, count)) {
 738                kfree_skb(skb);
 739                return -EFAULT;
 740        }
 741        mlen = CAPIMSG_LEN(skb->data);
 742        if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) {
 743                if ((size_t)(mlen + CAPIMSG_DATALEN(skb->data)) != count) {
 744                        kfree_skb(skb);
 745                        return -EINVAL;
 746                }
 747        } else {
 748                if (mlen != count) {
 749                        kfree_skb(skb);
 750                        return -EINVAL;
 751                }
 752        }
 753        CAPIMSG_SETAPPID(skb->data, cdev->ap.applid);
 754
 755        if (CAPIMSG_CMD(skb->data) == CAPI_DISCONNECT_B3_RESP) {
 756                mutex_lock(&cdev->ncci_list_mtx);
 757                capincci_free(cdev, CAPIMSG_NCCI(skb->data));
 758                mutex_unlock(&cdev->ncci_list_mtx);
 759        }
 760
 761        cdev->errcode = capi20_put_message(&cdev->ap, skb);
 762
 763        if (cdev->errcode) {
 764                kfree_skb(skb);
 765                return -EIO;
 766        }
 767        return count;
 768}
 769
 770static unsigned int
 771capi_poll(struct file *file, poll_table * wait)
 772{
 773        struct capidev *cdev = (struct capidev *)file->private_data;
 774        unsigned int mask = 0;
 775
 776        if (!cdev->ap.applid)
 777                return POLLERR;
 778
 779        poll_wait(file, &(cdev->recvwait), wait);
 780        mask = POLLOUT | POLLWRNORM;
 781        if (!skb_queue_empty(&cdev->recvqueue))
 782                mask |= POLLIN | POLLRDNORM;
 783        return mask;
 784}
 785
 786static int
 787capi_ioctl(struct inode *inode, struct file *file,
 788           unsigned int cmd, unsigned long arg)
 789{
 790        struct capidev *cdev = file->private_data;
 791        struct capi20_appl *ap = &cdev->ap;
 792        capi_ioctl_struct data;
 793        int retval = -EINVAL;
 794        void __user *argp = (void __user *)arg;
 795
 796        switch (cmd) {
 797        case CAPI_REGISTER:
 798                {
 799                        if (ap->applid)
 800                                return -EEXIST;
 801
 802                        if (copy_from_user(&cdev->ap.rparam, argp,
 803                                           sizeof(struct capi_register_params)))
 804                                return -EFAULT;
 805                        
 806                        cdev->ap.private = cdev;
 807                        cdev->ap.recv_message = capi_recv_message;
 808                        cdev->errcode = capi20_register(ap);
 809                        if (cdev->errcode) {
 810                                ap->applid = 0;
 811                                return -EIO;
 812                        }
 813                }
 814                return (int)ap->applid;
 815
 816        case CAPI_GET_VERSION:
 817                {
 818                        if (copy_from_user(&data.contr, argp,
 819                                                sizeof(data.contr)))
 820                                return -EFAULT;
 821                        cdev->errcode = capi20_get_version(data.contr, &data.version);
 822                        if (cdev->errcode)
 823                                return -EIO;
 824                        if (copy_to_user(argp, &data.version,
 825                                         sizeof(data.version)))
 826                                return -EFAULT;
 827                }
 828                return 0;
 829
 830        case CAPI_GET_SERIAL:
 831                {
 832                        if (copy_from_user(&data.contr, argp,
 833                                           sizeof(data.contr)))
 834                                return -EFAULT;
 835                        cdev->errcode = capi20_get_serial (data.contr, data.serial);
 836                        if (cdev->errcode)
 837                                return -EIO;
 838                        if (copy_to_user(argp, data.serial,
 839                                         sizeof(data.serial)))
 840                                return -EFAULT;
 841                }
 842                return 0;
 843        case CAPI_GET_PROFILE:
 844                {
 845                        if (copy_from_user(&data.contr, argp,
 846                                           sizeof(data.contr)))
 847                                return -EFAULT;
 848
 849                        if (data.contr == 0) {
 850                                cdev->errcode = capi20_get_profile(data.contr, &data.profile);
 851                                if (cdev->errcode)
 852                                        return -EIO;
 853
 854                                retval = copy_to_user(argp,
 855                                      &data.profile.ncontroller,
 856                                       sizeof(data.profile.ncontroller));
 857
 858                        } else {
 859                                cdev->errcode = capi20_get_profile(data.contr, &data.profile);
 860                                if (cdev->errcode)
 861                                        return -EIO;
 862
 863                                retval = copy_to_user(argp, &data.profile,
 864                                                   sizeof(data.profile));
 865                        }
 866                        if (retval)
 867                                return -EFAULT;
 868                }
 869                return 0;
 870
 871        case CAPI_GET_MANUFACTURER:
 872                {
 873                        if (copy_from_user(&data.contr, argp,
 874                                           sizeof(data.contr)))
 875                                return -EFAULT;
 876                        cdev->errcode = capi20_get_manufacturer(data.contr, data.manufacturer);
 877                        if (cdev->errcode)
 878                                return -EIO;
 879
 880                        if (copy_to_user(argp, data.manufacturer,
 881                                         sizeof(data.manufacturer)))
 882                                return -EFAULT;
 883
 884                }
 885                return 0;
 886        case CAPI_GET_ERRCODE:
 887                data.errcode = cdev->errcode;
 888                cdev->errcode = CAPI_NOERROR;
 889                if (arg) {
 890                        if (copy_to_user(argp, &data.errcode,
 891                                         sizeof(data.errcode)))
 892                                return -EFAULT;
 893                }
 894                return data.errcode;
 895
 896        case CAPI_INSTALLED:
 897                if (capi20_isinstalled() == CAPI_NOERROR)
 898                        return 0;
 899                return -ENXIO;
 900
 901        case CAPI_MANUFACTURER_CMD:
 902                {
 903                        struct capi_manufacturer_cmd mcmd;
 904                        if (!capable(CAP_SYS_ADMIN))
 905                                return -EPERM;
 906                        if (copy_from_user(&mcmd, argp, sizeof(mcmd)))
 907                                return -EFAULT;
 908                        return capi20_manufacturer(mcmd.cmd, mcmd.data);
 909                }
 910                return 0;
 911
 912        case CAPI_SET_FLAGS:
 913        case CAPI_CLR_FLAGS:
 914                {
 915                        unsigned userflags;
 916                        if (copy_from_user(&userflags, argp,
 917                                           sizeof(userflags)))
 918                                return -EFAULT;
 919                        if (cmd == CAPI_SET_FLAGS)
 920                                cdev->userflags |= userflags;
 921                        else
 922                                cdev->userflags &= ~userflags;
 923                }
 924                return 0;
 925
 926        case CAPI_GET_FLAGS:
 927                if (copy_to_user(argp, &cdev->userflags,
 928                                 sizeof(cdev->userflags)))
 929                        return -EFAULT;
 930                return 0;
 931
 932        case CAPI_NCCI_OPENCOUNT:
 933                {
 934                        struct capincci *nccip;
 935#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 936                        struct capiminor *mp;
 937#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 938                        unsigned ncci;
 939                        int count = 0;
 940                        if (copy_from_user(&ncci, argp, sizeof(ncci)))
 941                                return -EFAULT;
 942
 943                        mutex_lock(&cdev->ncci_list_mtx);
 944                        if ((nccip = capincci_find(cdev, (u32) ncci)) == NULL) {
 945                                mutex_unlock(&cdev->ncci_list_mtx);
 946                                return 0;
 947                        }
 948#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 949                        if ((mp = nccip->minorp) != NULL) {
 950                                count += atomic_read(&mp->ttyopencount);
 951                        }
 952#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 953                        mutex_unlock(&cdev->ncci_list_mtx);
 954                        return count;
 955                }
 956                return 0;
 957
 958#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 959        case CAPI_NCCI_GETUNIT:
 960                {
 961                        struct capincci *nccip;
 962                        struct capiminor *mp;
 963                        unsigned ncci;
 964                        int unit = 0;
 965                        if (copy_from_user(&ncci, argp,
 966                                           sizeof(ncci)))
 967                                return -EFAULT;
 968                        mutex_lock(&cdev->ncci_list_mtx);
 969                        nccip = capincci_find(cdev, (u32) ncci);
 970                        if (!nccip || (mp = nccip->minorp) == NULL) {
 971                                mutex_unlock(&cdev->ncci_list_mtx);
 972                                return -ESRCH;
 973                        }
 974                        unit = mp->minor;
 975                        mutex_unlock(&cdev->ncci_list_mtx);
 976                        return unit;
 977                }
 978                return 0;
 979#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 980        }
 981        return -EINVAL;
 982}
 983
 984static int
 985capi_open(struct inode *inode, struct file *file)
 986{
 987        int ret;
 988        
 989        lock_kernel();
 990        if (file->private_data)
 991                ret = -EEXIST;
 992        else if ((file->private_data = capidev_alloc()) == NULL)
 993                ret = -ENOMEM;
 994        else
 995                ret = nonseekable_open(inode, file);
 996        unlock_kernel();
 997        return ret;
 998}
 999
1000static int
1001capi_release(struct inode *inode, struct file *file)
1002{
1003        struct capidev *cdev = (struct capidev *)file->private_data;
1004
1005        capidev_free(cdev);
1006        file->private_data = NULL;
1007        
1008        return 0;
1009}
1010
1011static const struct file_operations capi_fops =
1012{
1013        .owner          = THIS_MODULE,
1014        .llseek         = no_llseek,
1015        .read           = capi_read,
1016        .write          = capi_write,
1017        .poll           = capi_poll,
1018        .ioctl          = capi_ioctl,
1019        .open           = capi_open,
1020        .release        = capi_release,
1021};
1022
1023#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
1024/* -------- tty_operations for capincci ----------------------------- */
1025
1026static int capinc_tty_open(struct tty_struct * tty, struct file * file)
1027{
1028        struct capiminor *mp;
1029        unsigned long flags;
1030
1031        if ((mp = capiminor_find(iminor(file->f_path.dentry->d_inode))) == NULL)
1032                return -ENXIO;
1033        if (mp->nccip == NULL)
1034                return -ENXIO;
1035
1036        tty->driver_data = (void *)mp;
1037
1038        spin_lock_irqsave(&workaround_lock, flags);
1039        if (atomic_read(&mp->ttyopencount) == 0)
1040                mp->tty = tty;
1041        atomic_inc(&mp->ttyopencount);
1042#ifdef _DEBUG_REFCOUNT
1043        printk(KERN_DEBUG "capinc_tty_open ocount=%d\n", atomic_read(&mp->ttyopencount));
1044#endif
1045        handle_minor_recv(mp);
1046        spin_unlock_irqrestore(&workaround_lock, flags);
1047        return 0;
1048}
1049
1050static void capinc_tty_close(struct tty_struct * tty, struct file * file)
1051{
1052        struct capiminor *mp;
1053
1054        mp = (struct capiminor *)tty->driver_data;
1055        if (mp) {
1056                if (atomic_dec_and_test(&mp->ttyopencount)) {
1057#ifdef _DEBUG_REFCOUNT
1058                        printk(KERN_DEBUG "capinc_tty_close lastclose\n");
1059#endif
1060                        tty->driver_data = NULL;
1061                        mp->tty = NULL;
1062                }
1063#ifdef _DEBUG_REFCOUNT
1064                printk(KERN_DEBUG "capinc_tty_close ocount=%d\n", atomic_read(&mp->ttyopencount));
1065#endif
1066                if (mp->nccip == NULL)
1067                        capiminor_free(mp);
1068        }
1069
1070#ifdef _DEBUG_REFCOUNT
1071        printk(KERN_DEBUG "capinc_tty_close\n");
1072#endif
1073}
1074
1075static int capinc_tty_write(struct tty_struct * tty,
1076                            const unsigned char *buf, int count)
1077{
1078        struct capiminor *mp = (struct capiminor *)tty->driver_data;
1079        struct sk_buff *skb;
1080        unsigned long flags;
1081
1082#ifdef _DEBUG_TTYFUNCS
1083        printk(KERN_DEBUG "capinc_tty_write(count=%d)\n", count);
1084#endif
1085
1086        if (!mp || !mp->nccip) {
1087#ifdef _DEBUG_TTYFUNCS
1088                printk(KERN_DEBUG "capinc_tty_write: mp or mp->ncci NULL\n");
1089#endif
1090                return 0;
1091        }
1092
1093        spin_lock_irqsave(&workaround_lock, flags);
1094        skb = mp->ttyskb;
1095        if (skb) {
1096                mp->ttyskb = NULL;
1097                skb_queue_tail(&mp->outqueue, skb);
1098                mp->outbytes += skb->len;
1099        }
1100
1101        skb = alloc_skb(CAPI_DATA_B3_REQ_LEN+count, GFP_ATOMIC);
1102        if (!skb) {
1103                printk(KERN_ERR "capinc_tty_write: alloc_skb failed\n");
1104                spin_unlock_irqrestore(&workaround_lock, flags);
1105                return -ENOMEM;
1106        }
1107
1108        skb_reserve(skb, CAPI_DATA_B3_REQ_LEN);
1109        memcpy(skb_put(skb, count), buf, count);
1110
1111        skb_queue_tail(&mp->outqueue, skb);
1112        mp->outbytes += skb->len;
1113        (void)handle_minor_send(mp);
1114        (void)handle_minor_recv(mp);
1115        spin_unlock_irqrestore(&workaround_lock, flags);
1116        return count;
1117}
1118
1119static int capinc_tty_put_char(struct tty_struct *tty, unsigned char ch)
1120{
1121        struct capiminor *mp = (struct capiminor *)tty->driver_data;
1122        struct sk_buff *skb;
1123        unsigned long flags;
1124        int ret = 1;
1125
1126#ifdef _DEBUG_TTYFUNCS
1127        printk(KERN_DEBUG "capinc_put_char(%u)\n", ch);
1128#endif
1129
1130        if (!mp || !mp->nccip) {
1131#ifdef _DEBUG_TTYFUNCS
1132                printk(KERN_DEBUG "capinc_tty_put_char: mp or mp->ncci NULL\n");
1133#endif
1134                return 0;
1135        }
1136
1137        spin_lock_irqsave(&workaround_lock, flags);
1138        skb = mp->ttyskb;
1139        if (skb) {
1140                if (skb_tailroom(skb) > 0) {
1141                        *(skb_put(skb, 1)) = ch;
1142                        spin_unlock_irqrestore(&workaround_lock, flags);
1143                        return 1;
1144                }
1145                mp->ttyskb = NULL;
1146                skb_queue_tail(&mp->outqueue, skb);
1147                mp->outbytes += skb->len;
1148                (void)handle_minor_send(mp);
1149        }
1150        skb = alloc_skb(CAPI_DATA_B3_REQ_LEN+CAPI_MAX_BLKSIZE, GFP_ATOMIC);
1151        if (skb) {
1152                skb_reserve(skb, CAPI_DATA_B3_REQ_LEN);
1153                *(skb_put(skb, 1)) = ch;
1154                mp->ttyskb = skb;
1155        } else {
1156                printk(KERN_ERR "capinc_put_char: char %u lost\n", ch);
1157                ret = 0;
1158        }
1159        spin_unlock_irqrestore(&workaround_lock, flags);
1160        return ret;
1161}
1162
1163static void capinc_tty_flush_chars(struct tty_struct *tty)
1164{
1165        struct capiminor *mp = (struct capiminor *)tty->driver_data;
1166        struct sk_buff *skb;
1167        unsigned long flags;
1168
1169#ifdef _DEBUG_TTYFUNCS
1170        printk(KERN_DEBUG "capinc_tty_flush_chars\n");
1171#endif
1172
1173        if (!mp || !mp->nccip) {
1174#ifdef _DEBUG_TTYFUNCS
1175                printk(KERN_DEBUG "capinc_tty_flush_chars: mp or mp->ncci NULL\n");
1176#endif
1177                return;
1178        }
1179
1180        spin_lock_irqsave(&workaround_lock, flags);
1181        skb = mp->ttyskb;
1182        if (skb) {
1183                mp->ttyskb = NULL;
1184                skb_queue_tail(&mp->outqueue, skb);
1185                mp->outbytes += skb->len;
1186                (void)handle_minor_send(mp);
1187        }
1188        (void)handle_minor_recv(mp);
1189        spin_unlock_irqrestore(&workaround_lock, flags);
1190}
1191
1192static int capinc_tty_write_room(struct tty_struct *tty)
1193{
1194        struct capiminor *mp = (struct capiminor *)tty->driver_data;
1195        int room;
1196        if (!mp || !mp->nccip) {
1197#ifdef _DEBUG_TTYFUNCS
1198                printk(KERN_DEBUG "capinc_tty_write_room: mp or mp->ncci NULL\n");
1199#endif
1200                return 0;
1201        }
1202        room = CAPINC_MAX_SENDQUEUE-skb_queue_len(&mp->outqueue);
1203        room *= CAPI_MAX_BLKSIZE;
1204#ifdef _DEBUG_TTYFUNCS
1205        printk(KERN_DEBUG "capinc_tty_write_room = %d\n", room);
1206#endif
1207        return room;
1208}
1209
1210static int capinc_tty_chars_in_buffer(struct tty_struct *tty)
1211{
1212        struct capiminor *mp = (struct capiminor *)tty->driver_data;
1213        if (!mp || !mp->nccip) {
1214#ifdef _DEBUG_TTYFUNCS
1215                printk(KERN_DEBUG "capinc_tty_chars_in_buffer: mp or mp->ncci NULL\n");
1216#endif
1217                return 0;
1218        }
1219#ifdef _DEBUG_TTYFUNCS
1220        printk(KERN_DEBUG "capinc_tty_chars_in_buffer = %d nack=%d sq=%d rq=%d\n",
1221                        mp->outbytes, mp->nack,
1222                        skb_queue_len(&mp->outqueue),
1223                        skb_queue_len(&mp->inqueue));
1224#endif
1225        return mp->outbytes;
1226}
1227
1228static int capinc_tty_ioctl(struct tty_struct *tty, struct file * file,
1229                    unsigned int cmd, unsigned long arg)
1230{
1231        int error = 0;
1232        switch (cmd) {
1233        default:
1234                error = n_tty_ioctl_helper(tty, file, cmd, arg);
1235                break;
1236        }
1237        return error;
1238}
1239
1240static void capinc_tty_set_termios(struct tty_struct *tty, struct ktermios * old)
1241{
1242#ifdef _DEBUG_TTYFUNCS
1243        printk(KERN_DEBUG "capinc_tty_set_termios\n");
1244#endif
1245}
1246
1247static void capinc_tty_throttle(struct tty_struct * tty)
1248{
1249        struct capiminor *mp = (struct capiminor *)tty->driver_data;
1250#ifdef _DEBUG_TTYFUNCS
1251        printk(KERN_DEBUG "capinc_tty_throttle\n");
1252#endif
1253        if (mp)
1254                mp->ttyinstop = 1;
1255}
1256
1257static void capinc_tty_unthrottle(struct tty_struct * tty)
1258{
1259        struct capiminor *mp = (struct capiminor *)tty->driver_data;
1260        unsigned long flags;
1261#ifdef _DEBUG_TTYFUNCS
1262        printk(KERN_DEBUG "capinc_tty_unthrottle\n");
1263#endif
1264        if (mp) {
1265                spin_lock_irqsave(&workaround_lock, flags);
1266                mp->ttyinstop = 0;
1267                handle_minor_recv(mp);
1268                spin_unlock_irqrestore(&workaround_lock, flags);
1269        }
1270}
1271
1272static void capinc_tty_stop(struct tty_struct *tty)
1273{
1274        struct capiminor *mp = (struct capiminor *)tty->driver_data;
1275#ifdef _DEBUG_TTYFUNCS
1276        printk(KERN_DEBUG "capinc_tty_stop\n");
1277#endif
1278        if (mp) {
1279                mp->ttyoutstop = 1;
1280        }
1281}
1282
1283static void capinc_tty_start(struct tty_struct *tty)
1284{
1285        struct capiminor *mp = (struct capiminor *)tty->driver_data;
1286        unsigned long flags;
1287#ifdef _DEBUG_TTYFUNCS
1288        printk(KERN_DEBUG "capinc_tty_start\n");
1289#endif
1290        if (mp) {
1291                spin_lock_irqsave(&workaround_lock, flags);
1292                mp->ttyoutstop = 0;
1293                (void)handle_minor_send(mp);
1294                spin_unlock_irqrestore(&workaround_lock, flags);
1295        }
1296}
1297
1298static void capinc_tty_hangup(struct tty_struct *tty)
1299{
1300#ifdef _DEBUG_TTYFUNCS
1301        printk(KERN_DEBUG "capinc_tty_hangup\n");
1302#endif
1303}
1304
1305static int capinc_tty_break_ctl(struct tty_struct *tty, int state)
1306{
1307#ifdef _DEBUG_TTYFUNCS
1308        printk(KERN_DEBUG "capinc_tty_break_ctl(%d)\n", state);
1309#endif
1310        return 0;
1311}
1312
1313static void capinc_tty_flush_buffer(struct tty_struct *tty)
1314{
1315#ifdef _DEBUG_TTYFUNCS
1316        printk(KERN_DEBUG "capinc_tty_flush_buffer\n");
1317#endif
1318}
1319
1320static void capinc_tty_set_ldisc(struct tty_struct *tty)
1321{
1322#ifdef _DEBUG_TTYFUNCS
1323        printk(KERN_DEBUG "capinc_tty_set_ldisc\n");
1324#endif
1325}
1326
1327static void capinc_tty_send_xchar(struct tty_struct *tty, char ch)
1328{
1329#ifdef _DEBUG_TTYFUNCS
1330        printk(KERN_DEBUG "capinc_tty_send_xchar(%d)\n", ch);
1331#endif
1332}
1333
1334static struct tty_driver *capinc_tty_driver;
1335
1336static const struct tty_operations capinc_ops = {
1337        .open = capinc_tty_open,
1338        .close = capinc_tty_close,
1339        .write = capinc_tty_write,
1340        .put_char = capinc_tty_put_char,
1341        .flush_chars = capinc_tty_flush_chars,
1342        .write_room = capinc_tty_write_room,
1343        .chars_in_buffer = capinc_tty_chars_in_buffer,
1344        .ioctl = capinc_tty_ioctl,
1345        .set_termios = capinc_tty_set_termios,
1346        .throttle = capinc_tty_throttle,
1347        .unthrottle = capinc_tty_unthrottle,
1348        .stop = capinc_tty_stop,
1349        .start = capinc_tty_start,
1350        .hangup = capinc_tty_hangup,
1351        .break_ctl = capinc_tty_break_ctl,
1352        .flush_buffer = capinc_tty_flush_buffer,
1353        .set_ldisc = capinc_tty_set_ldisc,
1354        .send_xchar = capinc_tty_send_xchar,
1355};
1356
1357static int capinc_tty_init(void)
1358{
1359        struct tty_driver *drv;
1360        
1361        if (capi_ttyminors > CAPINC_MAX_PORTS)
1362                capi_ttyminors = CAPINC_MAX_PORTS;
1363        if (capi_ttyminors <= 0)
1364                capi_ttyminors = CAPINC_NR_PORTS;
1365
1366        drv = alloc_tty_driver(capi_ttyminors);
1367        if (!drv)
1368                return -ENOMEM;
1369
1370        drv->owner = THIS_MODULE;
1371        drv->driver_name = "capi_nc";
1372        drv->name = "capi";
1373        drv->major = capi_ttymajor;
1374        drv->minor_start = 0;
1375        drv->type = TTY_DRIVER_TYPE_SERIAL;
1376        drv->subtype = SERIAL_TYPE_NORMAL;
1377        drv->init_termios = tty_std_termios;
1378        drv->init_termios.c_iflag = ICRNL;
1379        drv->init_termios.c_oflag = OPOST | ONLCR;
1380        drv->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
1381        drv->init_termios.c_lflag = 0;
1382        drv->flags = TTY_DRIVER_REAL_RAW|TTY_DRIVER_RESET_TERMIOS;
1383        tty_set_operations(drv, &capinc_ops);
1384        if (tty_register_driver(drv)) {
1385                put_tty_driver(drv);
1386                printk(KERN_ERR "Couldn't register capi_nc driver\n");
1387                return -1;
1388        }
1389        capinc_tty_driver = drv;
1390        return 0;
1391}
1392
1393static void capinc_tty_exit(void)
1394{
1395        struct tty_driver *drv = capinc_tty_driver;
1396        int retval;
1397        if ((retval = tty_unregister_driver(drv)))
1398                printk(KERN_ERR "capi: failed to unregister capi_nc driver (%d)\n", retval);
1399        put_tty_driver(drv);
1400}
1401
1402#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
1403
1404/* -------- /proc functions ----------------------------------------- */
1405
1406/*
1407 * /proc/capi/capi20:
1408 *  minor applid nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt
1409 */
1410static int proc_capidev_read_proc(char *page, char **start, off_t off,
1411                                       int count, int *eof, void *data)
1412{
1413        struct capidev *cdev;
1414        struct list_head *l;
1415        int len = 0;
1416
1417        read_lock(&capidev_list_lock);
1418        list_for_each(l, &capidev_list) {
1419                cdev = list_entry(l, struct capidev, list);
1420                len += sprintf(page+len, "0 %d %lu %lu %lu %lu\n",
1421                        cdev->ap.applid,
1422                        cdev->ap.nrecvctlpkt,
1423                        cdev->ap.nrecvdatapkt,
1424                        cdev->ap.nsentctlpkt,
1425                        cdev->ap.nsentdatapkt);
1426                if (len <= off) {
1427                        off -= len;
1428                        len = 0;
1429                } else {
1430                        if (len-off > count)
1431                                goto endloop;
1432                }
1433        }
1434
1435endloop:
1436        read_unlock(&capidev_list_lock);
1437        if (len < count)
1438                *eof = 1;
1439        if (len > count) len = count;
1440        if (len < 0) len = 0;
1441        return len;
1442}
1443
1444/*
1445 * /proc/capi/capi20ncci:
1446 *  applid ncci
1447 */
1448static int proc_capincci_read_proc(char *page, char **start, off_t off,
1449                                       int count, int *eof, void *data)
1450{
1451        struct capidev *cdev;
1452        struct capincci *np;
1453        struct list_head *l;
1454        int len = 0;
1455
1456        read_lock(&capidev_list_lock);
1457        list_for_each(l, &capidev_list) {
1458                cdev = list_entry(l, struct capidev, list);
1459                for (np=cdev->nccis; np; np = np->next) {
1460                        len += sprintf(page+len, "%d 0x%x\n",
1461                                       cdev->ap.applid,
1462                                       np->ncci);
1463                        if (len <= off) {
1464                                off -= len;
1465                                len = 0;
1466                        } else {
1467                                if (len-off > count)
1468                                        goto endloop;
1469                        }
1470                }
1471        }
1472endloop:
1473        read_unlock(&capidev_list_lock);
1474        *start = page+off;
1475        if (len < count)
1476                *eof = 1;
1477        if (len>count) len = count;
1478        if (len<0) len = 0;
1479        return len;
1480}
1481
1482static struct procfsentries {
1483  char *name;
1484  mode_t mode;
1485  int (*read_proc)(char *page, char **start, off_t off,
1486                                       int count, int *eof, void *data);
1487  struct proc_dir_entry *procent;
1488} procfsentries[] = {
1489   /* { "capi",           S_IFDIR, 0 }, */
1490   { "capi/capi20",       0      , proc_capidev_read_proc },
1491   { "capi/capi20ncci",   0      , proc_capincci_read_proc },
1492};
1493
1494static void __init proc_init(void)
1495{
1496    int nelem = ARRAY_SIZE(procfsentries);
1497    int i;
1498
1499    for (i=0; i < nelem; i++) {
1500        struct procfsentries *p = procfsentries + i;
1501        p->procent = create_proc_entry(p->name, p->mode, NULL);
1502        if (p->procent) p->procent->read_proc = p->read_proc;
1503    }
1504}
1505
1506static void __exit proc_exit(void)
1507{
1508    int nelem = ARRAY_SIZE(procfsentries);
1509    int i;
1510
1511    for (i=nelem-1; i >= 0; i--) {
1512        struct procfsentries *p = procfsentries + i;
1513        if (p->procent) {
1514           remove_proc_entry(p->name, NULL);
1515           p->procent = NULL;
1516        }
1517    }
1518}
1519
1520/* -------- init function and module interface ---------------------- */
1521
1522
1523static char rev[32];
1524
1525static int __init capi_init(void)
1526{
1527        char *p;
1528        char *compileinfo;
1529        int major_ret;
1530
1531        if ((p = strchr(revision, ':')) != NULL && p[1]) {
1532                strlcpy(rev, p + 2, sizeof(rev));
1533                if ((p = strchr(rev, '$')) != NULL && p > rev)
1534                   *(p-1) = 0;
1535        } else
1536                strcpy(rev, "1.0");
1537
1538        major_ret = register_chrdev(capi_major, "capi20", &capi_fops);
1539        if (major_ret < 0) {
1540                printk(KERN_ERR "capi20: unable to get major %d\n", capi_major);
1541                return major_ret;
1542        }
1543        capi_class = class_create(THIS_MODULE, "capi");
1544        if (IS_ERR(capi_class)) {
1545                unregister_chrdev(capi_major, "capi20");
1546                return PTR_ERR(capi_class);
1547        }
1548
1549        device_create(capi_class, NULL, MKDEV(capi_major, 0), NULL, "capi");
1550
1551#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
1552        if (capinc_tty_init() < 0) {
1553                device_destroy(capi_class, MKDEV(capi_major, 0));
1554                class_destroy(capi_class);
1555                unregister_chrdev(capi_major, "capi20");
1556                return -ENOMEM;
1557        }
1558#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
1559
1560        proc_init();
1561
1562#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
1563#if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE)
1564        compileinfo = " (middleware+capifs)";
1565#else
1566        compileinfo = " (no capifs)";
1567#endif
1568#else
1569        compileinfo = " (no middleware)";
1570#endif
1571        printk(KERN_NOTICE "capi20: Rev %s: started up with major %d%s\n",
1572                                rev, capi_major, compileinfo);
1573
1574        return 0;
1575}
1576
1577static void __exit capi_exit(void)
1578{
1579        proc_exit();
1580
1581        device_destroy(capi_class, MKDEV(capi_major, 0));
1582        class_destroy(capi_class);
1583        unregister_chrdev(capi_major, "capi20");
1584
1585#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
1586        capinc_tty_exit();
1587#endif
1588        printk(KERN_NOTICE "capi: Rev %s: unloaded\n", rev);
1589}
1590
1591module_init(capi_init);
1592module_exit(capi_exit);
1593