linux/drivers/isdn/i4l/isdn_common.c
<<
>>
Prefs
   1/* $Id: isdn_common.c,v 1.1.2.3 2004/02/10 01:07:13 keil Exp $
   2 *
   3 * Linux ISDN subsystem, common used functions (linklevel).
   4 *
   5 * Copyright 1994-1999  by Fritz Elfert (fritz@isdn4linux.de)
   6 * Copyright 1995,96    Thinking Objects Software GmbH Wuerzburg
   7 * Copyright 1995,96    by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
   8 *
   9 * This software may be used and distributed according to the terms
  10 * of the GNU General Public License, incorporated herein by reference.
  11 *
  12 */
  13
  14#include <linux/module.h>
  15#include <linux/init.h>
  16#include <linux/poll.h>
  17#include <linux/vmalloc.h>
  18#include <linux/isdn.h>
  19#include <linux/smp_lock.h>
  20#include "isdn_common.h"
  21#include "isdn_tty.h"
  22#include "isdn_net.h"
  23#include "isdn_ppp.h"
  24#ifdef CONFIG_ISDN_AUDIO
  25#include "isdn_audio.h"
  26#endif
  27#ifdef CONFIG_ISDN_DIVERSION_MODULE
  28#define CONFIG_ISDN_DIVERSION
  29#endif
  30#ifdef CONFIG_ISDN_DIVERSION
  31#include <linux/isdn_divertif.h>
  32#endif /* CONFIG_ISDN_DIVERSION */
  33#include "isdn_v110.h"
  34
  35/* Debugflags */
  36#undef ISDN_DEBUG_STATCALLB
  37
  38MODULE_DESCRIPTION("ISDN4Linux: link layer");
  39MODULE_AUTHOR("Fritz Elfert");
  40MODULE_LICENSE("GPL");
  41
  42isdn_dev *dev;
  43
  44static char *isdn_revision = "$Revision: 1.1.2.3 $";
  45
  46extern char *isdn_net_revision;
  47extern char *isdn_tty_revision;
  48#ifdef CONFIG_ISDN_PPP
  49extern char *isdn_ppp_revision;
  50#else
  51static char *isdn_ppp_revision = ": none $";
  52#endif
  53#ifdef CONFIG_ISDN_AUDIO
  54extern char *isdn_audio_revision;
  55#else
  56static char *isdn_audio_revision = ": none $";
  57#endif
  58extern char *isdn_v110_revision;
  59
  60#ifdef CONFIG_ISDN_DIVERSION
  61static isdn_divert_if *divert_if; /* = NULL */
  62#endif /* CONFIG_ISDN_DIVERSION */
  63
  64
  65static int isdn_writebuf_stub(int, int, const u_char __user *, int);
  66static void set_global_features(void);
  67static int isdn_wildmat(char *s, char *p);
  68static int isdn_add_channels(isdn_driver_t *d, int drvidx, int n, int adding);
  69
  70static inline void
  71isdn_lock_driver(isdn_driver_t *drv)
  72{
  73        try_module_get(drv->interface->owner);
  74        drv->locks++;
  75}
  76
  77void
  78isdn_lock_drivers(void)
  79{
  80        int i;
  81
  82        for (i = 0; i < ISDN_MAX_DRIVERS; i++) {
  83                if (!dev->drv[i])
  84                        continue;
  85                isdn_lock_driver(dev->drv[i]);
  86        }
  87}
  88
  89static inline void
  90isdn_unlock_driver(isdn_driver_t *drv)
  91{
  92        if (drv->locks > 0) {
  93                drv->locks--;
  94                module_put(drv->interface->owner);
  95        }
  96}
  97
  98void
  99isdn_unlock_drivers(void)
 100{
 101        int i;
 102
 103        for (i = 0; i < ISDN_MAX_DRIVERS; i++) {
 104                if (!dev->drv[i])
 105                        continue;
 106                isdn_unlock_driver(dev->drv[i]);
 107        }
 108}
 109
 110#if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
 111void
 112isdn_dumppkt(char *s, u_char * p, int len, int dumplen)
 113{
 114        int dumpc;
 115
 116        printk(KERN_DEBUG "%s(%d) ", s, len);
 117        for (dumpc = 0; (dumpc < dumplen) && (len); len--, dumpc++)
 118                printk(" %02x", *p++);
 119        printk("\n");
 120}
 121#endif
 122
 123/*
 124 * I picked the pattern-matching-functions from an old GNU-tar version (1.10)
 125 * It was originally written and put to PD by rs@mirror.TMC.COM (Rich Salz)
 126 */
 127static int
 128isdn_star(char *s, char *p)
 129{
 130        while (isdn_wildmat(s, p)) {
 131                if (*++s == '\0')
 132                        return (2);
 133        }
 134        return (0);
 135}
 136
 137/*
 138 * Shell-type Pattern-matching for incoming caller-Ids
 139 * This function gets a string in s and checks, if it matches the pattern
 140 * given in p.
 141 *
 142 * Return:
 143 *   0 = match.
 144 *   1 = no match.
 145 *   2 = no match. Would eventually match, if s would be longer.
 146 *
 147 * Possible Patterns:
 148 *
 149 * '?'     matches one character
 150 * '*'     matches zero or more characters
 151 * [xyz]   matches the set of characters in brackets.
 152 * [^xyz]  matches any single character not in the set of characters
 153 */
 154
 155static int
 156isdn_wildmat(char *s, char *p)
 157{
 158        register int last;
 159        register int matched;
 160        register int reverse;
 161        register int nostar = 1;
 162
 163        if (!(*s) && !(*p))
 164                return(1);
 165        for (; *p; s++, p++)
 166                switch (*p) {
 167                        case '\\':
 168                                /*
 169                                 * Literal match with following character,
 170                                 * fall through.
 171                                 */
 172                                p++;
 173                        default:
 174                                if (*s != *p)
 175                                        return (*s == '\0')?2:1;
 176                                continue;
 177                        case '?':
 178                                /* Match anything. */
 179                                if (*s == '\0')
 180                                        return (2);
 181                                continue;
 182                        case '*':
 183                                nostar = 0;     
 184                                /* Trailing star matches everything. */
 185                                return (*++p ? isdn_star(s, p) : 0);
 186                        case '[':
 187                                /* [^....] means inverse character class. */
 188                                if ((reverse = (p[1] == '^')))
 189                                        p++;
 190                                for (last = 0, matched = 0; *++p && (*p != ']'); last = *p)
 191                                        /* This next line requires a good C compiler. */
 192                                        if (*p == '-' ? *s <= *++p && *s >= last : *s == *p)
 193                                                matched = 1;
 194                                if (matched == reverse)
 195                                        return (1);
 196                                continue;
 197                }
 198        return (*s == '\0')?0:nostar;
 199}
 200
 201int isdn_msncmp( const char * msn1, const char * msn2 )
 202{
 203        char TmpMsn1[ ISDN_MSNLEN ];
 204        char TmpMsn2[ ISDN_MSNLEN ];
 205        char *p;
 206
 207        for ( p = TmpMsn1; *msn1 && *msn1 != ':'; )  // Strip off a SPID
 208                *p++ = *msn1++;
 209        *p = '\0';
 210
 211        for ( p = TmpMsn2; *msn2 && *msn2 != ':'; )  // Strip off a SPID
 212                *p++ = *msn2++;
 213        *p = '\0';
 214
 215        return isdn_wildmat( TmpMsn1, TmpMsn2 );
 216}
 217
 218int
 219isdn_dc2minor(int di, int ch)
 220{
 221        int i;
 222        for (i = 0; i < ISDN_MAX_CHANNELS; i++)
 223                if (dev->chanmap[i] == ch && dev->drvmap[i] == di)
 224                        return i;
 225        return -1;
 226}
 227
 228static int isdn_timer_cnt1 = 0;
 229static int isdn_timer_cnt2 = 0;
 230static int isdn_timer_cnt3 = 0;
 231
 232static void
 233isdn_timer_funct(ulong dummy)
 234{
 235        int tf = dev->tflags;
 236        if (tf & ISDN_TIMER_FAST) {
 237                if (tf & ISDN_TIMER_MODEMREAD)
 238                        isdn_tty_readmodem();
 239                if (tf & ISDN_TIMER_MODEMPLUS)
 240                        isdn_tty_modem_escape();
 241                if (tf & ISDN_TIMER_MODEMXMIT)
 242                        isdn_tty_modem_xmit();
 243        }
 244        if (tf & ISDN_TIMER_SLOW) {
 245                if (++isdn_timer_cnt1 >= ISDN_TIMER_02SEC) {
 246                        isdn_timer_cnt1 = 0;
 247                        if (tf & ISDN_TIMER_NETDIAL)
 248                                isdn_net_dial();
 249                }
 250                if (++isdn_timer_cnt2 >= ISDN_TIMER_1SEC) {
 251                        isdn_timer_cnt2 = 0;
 252                        if (tf & ISDN_TIMER_NETHANGUP)
 253                                isdn_net_autohup();
 254                        if (++isdn_timer_cnt3 >= ISDN_TIMER_RINGING) {
 255                                isdn_timer_cnt3 = 0;
 256                                if (tf & ISDN_TIMER_MODEMRING)
 257                                        isdn_tty_modem_ring();
 258                        }
 259                        if (tf & ISDN_TIMER_CARRIER)
 260                                isdn_tty_carrier_timeout();
 261                }
 262        }
 263        if (tf) 
 264                mod_timer(&dev->timer, jiffies+ISDN_TIMER_RES);
 265}
 266
 267void
 268isdn_timer_ctrl(int tf, int onoff)
 269{
 270        unsigned long flags;
 271        int old_tflags;
 272
 273        spin_lock_irqsave(&dev->timerlock, flags);
 274        if ((tf & ISDN_TIMER_SLOW) && (!(dev->tflags & ISDN_TIMER_SLOW))) {
 275                /* If the slow-timer wasn't activated until now */
 276                isdn_timer_cnt1 = 0;
 277                isdn_timer_cnt2 = 0;
 278        }
 279        old_tflags = dev->tflags;
 280        if (onoff)
 281                dev->tflags |= tf;
 282        else
 283                dev->tflags &= ~tf;
 284        if (dev->tflags && !old_tflags)
 285                mod_timer(&dev->timer, jiffies+ISDN_TIMER_RES);
 286        spin_unlock_irqrestore(&dev->timerlock, flags);
 287}
 288
 289/*
 290 * Receive a packet from B-Channel. (Called from low-level-module)
 291 */
 292static void
 293isdn_receive_skb_callback(int di, int channel, struct sk_buff *skb)
 294{
 295        int i;
 296
 297        if ((i = isdn_dc2minor(di, channel)) == -1) {
 298                dev_kfree_skb(skb);
 299                return;
 300        }
 301        /* Update statistics */
 302        dev->ibytes[i] += skb->len;
 303        
 304        /* First, try to deliver data to network-device */
 305        if (isdn_net_rcv_skb(i, skb))
 306                return;
 307
 308        /* V.110 handling
 309         * makes sense for async streams only, so it is
 310         * called after possible net-device delivery.
 311         */
 312        if (dev->v110[i]) {
 313                atomic_inc(&dev->v110use[i]);
 314                skb = isdn_v110_decode(dev->v110[i], skb);
 315                atomic_dec(&dev->v110use[i]);
 316                if (!skb)
 317                        return;
 318        }
 319
 320        /* No network-device found, deliver to tty or raw-channel */
 321        if (skb->len) {
 322                if (isdn_tty_rcv_skb(i, di, channel, skb))
 323                        return;
 324                wake_up_interruptible(&dev->drv[di]->rcv_waitq[channel]);
 325        } else
 326                dev_kfree_skb(skb);
 327}
 328
 329/*
 330 * Intercept command from Linklevel to Lowlevel.
 331 * If layer 2 protocol is V.110 and this is not supported by current
 332 * lowlevel-driver, use driver's transparent mode and handle V.110 in
 333 * linklevel instead.
 334 */
 335int
 336isdn_command(isdn_ctrl *cmd)
 337{
 338        if (cmd->driver == -1) {
 339                printk(KERN_WARNING "isdn_command command(%x) driver -1\n", cmd->command);
 340                return(1);
 341        }
 342        if (!dev->drv[cmd->driver]) {
 343                printk(KERN_WARNING "isdn_command command(%x) dev->drv[%d] NULL\n",
 344                        cmd->command, cmd->driver);
 345                return(1);
 346        }
 347        if (!dev->drv[cmd->driver]->interface) {
 348                printk(KERN_WARNING "isdn_command command(%x) dev->drv[%d]->interface NULL\n",
 349                        cmd->command, cmd->driver);
 350                return(1);
 351        }
 352        if (cmd->command == ISDN_CMD_SETL2) {
 353                int idx = isdn_dc2minor(cmd->driver, cmd->arg & 255);
 354                unsigned long l2prot = (cmd->arg >> 8) & 255;
 355                unsigned long features = (dev->drv[cmd->driver]->interface->features
 356                                                >> ISDN_FEATURE_L2_SHIFT) &
 357                                                ISDN_FEATURE_L2_MASK;
 358                unsigned long l2_feature = (1 << l2prot);
 359
 360                switch (l2prot) {
 361                        case ISDN_PROTO_L2_V11096:
 362                        case ISDN_PROTO_L2_V11019:
 363                        case ISDN_PROTO_L2_V11038:
 364                        /* If V.110 requested, but not supported by
 365                         * HL-driver, set emulator-flag and change
 366                         * Layer-2 to transparent
 367                         */
 368                                if (!(features & l2_feature)) {
 369                                        dev->v110emu[idx] = l2prot;
 370                                        cmd->arg = (cmd->arg & 255) |
 371                                                (ISDN_PROTO_L2_TRANS << 8);
 372                                } else
 373                                        dev->v110emu[idx] = 0;
 374                }
 375        }
 376        return dev->drv[cmd->driver]->interface->command(cmd);
 377}
 378
 379void
 380isdn_all_eaz(int di, int ch)
 381{
 382        isdn_ctrl cmd;
 383
 384        if (di < 0)
 385                return;
 386        cmd.driver = di;
 387        cmd.arg = ch;
 388        cmd.command = ISDN_CMD_SETEAZ;
 389        cmd.parm.num[0] = '\0';
 390        isdn_command(&cmd);
 391}
 392
 393/*
 394 * Begin of a CAPI like LL<->HL interface, currently used only for 
 395 * supplementary service (CAPI 2.0 part III)
 396 */
 397#include <linux/isdn/capicmd.h>
 398
 399static int
 400isdn_capi_rec_hl_msg(capi_msg *cm) {
 401        
 402        int di;
 403        int ch;
 404        
 405        di = (cm->adr.Controller & 0x7f) -1;
 406        ch = isdn_dc2minor(di, (cm->adr.Controller>>8)& 0x7f);
 407        switch(cm->Command) {
 408                case CAPI_FACILITY:
 409                        /* in the moment only handled in tty */
 410                        return(isdn_tty_capi_facility(cm));
 411                default:
 412                        return(-1);
 413        }
 414}
 415
 416static int
 417isdn_status_callback(isdn_ctrl * c)
 418{
 419        int di;
 420        u_long flags;
 421        int i;
 422        int r;
 423        int retval = 0;
 424        isdn_ctrl cmd;
 425        isdn_net_dev *p;
 426
 427        di = c->driver;
 428        i = isdn_dc2minor(di, c->arg);
 429        switch (c->command) {
 430                case ISDN_STAT_BSENT:
 431                        if (i < 0)
 432                                return -1;
 433                        if (dev->global_flags & ISDN_GLOBAL_STOPPED)
 434                                return 0;
 435                        if (isdn_net_stat_callback(i, c))
 436                                return 0;
 437                        if (isdn_v110_stat_callback(i, c))
 438                                return 0;
 439                        if (isdn_tty_stat_callback(i, c))
 440                                return 0;
 441                        wake_up_interruptible(&dev->drv[di]->snd_waitq[c->arg]);
 442                        break;
 443                case ISDN_STAT_STAVAIL:
 444                        dev->drv[di]->stavail += c->arg;
 445                        wake_up_interruptible(&dev->drv[di]->st_waitq);
 446                        break;
 447                case ISDN_STAT_RUN:
 448                        dev->drv[di]->flags |= DRV_FLAG_RUNNING;
 449                        for (i = 0; i < ISDN_MAX_CHANNELS; i++)
 450                                if (dev->drvmap[i] == di)
 451                                        isdn_all_eaz(di, dev->chanmap[i]);
 452                        set_global_features();
 453                        break;
 454                case ISDN_STAT_STOP:
 455                        dev->drv[di]->flags &= ~DRV_FLAG_RUNNING;
 456                        break;
 457                case ISDN_STAT_ICALL:
 458                        if (i < 0)
 459                                return -1;
 460#ifdef ISDN_DEBUG_STATCALLB
 461                        printk(KERN_DEBUG "ICALL (net): %d %ld %s\n", di, c->arg, c->parm.num);
 462#endif
 463                        if (dev->global_flags & ISDN_GLOBAL_STOPPED) {
 464                                cmd.driver = di;
 465                                cmd.arg = c->arg;
 466                                cmd.command = ISDN_CMD_HANGUP;
 467                                isdn_command(&cmd);
 468                                return 0;
 469                        }
 470                        /* Try to find a network-interface which will accept incoming call */
 471                        r = ((c->command == ISDN_STAT_ICALLW) ? 0 : isdn_net_find_icall(di, c->arg, i, &c->parm.setup));
 472                        switch (r) {
 473                                case 0:
 474                                        /* No network-device replies.
 475                                         * Try ttyI's.
 476                                         * These return 0 on no match, 1 on match and
 477                                         * 3 on eventually match, if CID is longer.
 478                                         */
 479                                        if (c->command == ISDN_STAT_ICALL)
 480                                          if ((retval = isdn_tty_find_icall(di, c->arg, &c->parm.setup))) return(retval);
 481#ifdef CONFIG_ISDN_DIVERSION 
 482                                         if (divert_if)
 483                                          if ((retval = divert_if->stat_callback(c))) 
 484                                            return(retval); /* processed */
 485#endif /* CONFIG_ISDN_DIVERSION */                       
 486                                        if ((!retval) && (dev->drv[di]->flags & DRV_FLAG_REJBUS)) {
 487                                                /* No tty responding */
 488                                                cmd.driver = di;
 489                                                cmd.arg = c->arg;
 490                                                cmd.command = ISDN_CMD_HANGUP;
 491                                                isdn_command(&cmd);
 492                                                retval = 2;
 493                                        }
 494                                        break;
 495                                case 1:
 496                                        /* Schedule connection-setup */
 497                                        isdn_net_dial();
 498                                        cmd.driver = di;
 499                                        cmd.arg = c->arg;
 500                                        cmd.command = ISDN_CMD_ACCEPTD;
 501                                        for ( p = dev->netdev; p; p = p->next )
 502                                                if ( p->local->isdn_channel == cmd.arg )
 503                                                {
 504                                                        strcpy( cmd.parm.setup.eazmsn, p->local->msn );
 505                                                        isdn_command(&cmd);
 506                                                        retval = 1;
 507                                                        break;
 508                                                }
 509                                        break;
 510
 511                                case 2: /* For calling back, first reject incoming call ... */
 512                                case 3: /* Interface found, but down, reject call actively  */
 513                                        retval = 2;
 514                                        printk(KERN_INFO "isdn: Rejecting Call\n");
 515                                        cmd.driver = di;
 516                                        cmd.arg = c->arg;
 517                                        cmd.command = ISDN_CMD_HANGUP;
 518                                        isdn_command(&cmd);
 519                                        if (r == 3)
 520                                                break;
 521                                        /* Fall through */
 522                                case 4:
 523                                        /* ... then start callback. */
 524                                        isdn_net_dial();
 525                                        break;
 526                                case 5:
 527                                        /* Number would eventually match, if longer */
 528                                        retval = 3;
 529                                        break;
 530                        }
 531#ifdef ISDN_DEBUG_STATCALLB
 532                        printk(KERN_DEBUG "ICALL: ret=%d\n", retval);
 533#endif
 534                        return retval;
 535                        break;
 536                case ISDN_STAT_CINF:
 537                        if (i < 0)
 538                                return -1;
 539#ifdef ISDN_DEBUG_STATCALLB
 540                        printk(KERN_DEBUG "CINF: %ld %s\n", c->arg, c->parm.num);
 541#endif
 542                        if (dev->global_flags & ISDN_GLOBAL_STOPPED)
 543                                return 0;
 544                        if (strcmp(c->parm.num, "0"))
 545                                isdn_net_stat_callback(i, c);
 546                        isdn_tty_stat_callback(i, c);
 547                        break;
 548                case ISDN_STAT_CAUSE:
 549#ifdef ISDN_DEBUG_STATCALLB
 550                        printk(KERN_DEBUG "CAUSE: %ld %s\n", c->arg, c->parm.num);
 551#endif
 552                        printk(KERN_INFO "isdn: %s,ch%ld cause: %s\n",
 553                               dev->drvid[di], c->arg, c->parm.num);
 554                        isdn_tty_stat_callback(i, c);
 555#ifdef CONFIG_ISDN_DIVERSION
 556                        if (divert_if)
 557                         divert_if->stat_callback(c); 
 558#endif /* CONFIG_ISDN_DIVERSION */
 559                        break;
 560                case ISDN_STAT_DISPLAY:
 561#ifdef ISDN_DEBUG_STATCALLB
 562                        printk(KERN_DEBUG "DISPLAY: %ld %s\n", c->arg, c->parm.display);
 563#endif
 564                        isdn_tty_stat_callback(i, c);
 565#ifdef CONFIG_ISDN_DIVERSION
 566                        if (divert_if)
 567                         divert_if->stat_callback(c); 
 568#endif /* CONFIG_ISDN_DIVERSION */
 569                        break;
 570                case ISDN_STAT_DCONN:
 571                        if (i < 0)
 572                                return -1;
 573#ifdef ISDN_DEBUG_STATCALLB
 574                        printk(KERN_DEBUG "DCONN: %ld\n", c->arg);
 575#endif
 576                        if (dev->global_flags & ISDN_GLOBAL_STOPPED)
 577                                return 0;
 578                        /* Find any net-device, waiting for D-channel setup */
 579                        if (isdn_net_stat_callback(i, c))
 580                                break;
 581                        isdn_v110_stat_callback(i, c);
 582                        /* Find any ttyI, waiting for D-channel setup */
 583                        if (isdn_tty_stat_callback(i, c)) {
 584                                cmd.driver = di;
 585                                cmd.arg = c->arg;
 586                                cmd.command = ISDN_CMD_ACCEPTB;
 587                                isdn_command(&cmd);
 588                                break;
 589                        }
 590                        break;
 591                case ISDN_STAT_DHUP:
 592                        if (i < 0)
 593                                return -1;
 594#ifdef ISDN_DEBUG_STATCALLB
 595                        printk(KERN_DEBUG "DHUP: %ld\n", c->arg);
 596#endif
 597                        if (dev->global_flags & ISDN_GLOBAL_STOPPED)
 598                                return 0;
 599                        dev->drv[di]->online &= ~(1 << (c->arg));
 600                        isdn_info_update();
 601                        /* Signal hangup to network-devices */
 602                        if (isdn_net_stat_callback(i, c))
 603                                break;
 604                        isdn_v110_stat_callback(i, c);
 605                        if (isdn_tty_stat_callback(i, c))
 606                                break;
 607#ifdef CONFIG_ISDN_DIVERSION
 608                        if (divert_if)
 609                         divert_if->stat_callback(c); 
 610#endif /* CONFIG_ISDN_DIVERSION */
 611                        break;
 612                        break;
 613                case ISDN_STAT_BCONN:
 614                        if (i < 0)
 615                                return -1;
 616#ifdef ISDN_DEBUG_STATCALLB
 617                        printk(KERN_DEBUG "BCONN: %ld\n", c->arg);
 618#endif
 619                        /* Signal B-channel-connect to network-devices */
 620                        if (dev->global_flags & ISDN_GLOBAL_STOPPED)
 621                                return 0;
 622                        dev->drv[di]->online |= (1 << (c->arg));
 623                        isdn_info_update();
 624                        if (isdn_net_stat_callback(i, c))
 625                                break;
 626                        isdn_v110_stat_callback(i, c);
 627                        if (isdn_tty_stat_callback(i, c))
 628                                break;
 629                        break;
 630                case ISDN_STAT_BHUP:
 631                        if (i < 0)
 632                                return -1;
 633#ifdef ISDN_DEBUG_STATCALLB
 634                        printk(KERN_DEBUG "BHUP: %ld\n", c->arg);
 635#endif
 636                        if (dev->global_flags & ISDN_GLOBAL_STOPPED)
 637                                return 0;
 638                        dev->drv[di]->online &= ~(1 << (c->arg));
 639                        isdn_info_update();
 640#ifdef CONFIG_ISDN_X25
 641                        /* Signal hangup to network-devices */
 642                        if (isdn_net_stat_callback(i, c))
 643                                break;
 644#endif
 645                        isdn_v110_stat_callback(i, c);
 646                        if (isdn_tty_stat_callback(i, c))
 647                                break;
 648                        break;
 649                case ISDN_STAT_NODCH:
 650                        if (i < 0)
 651                                return -1;
 652#ifdef ISDN_DEBUG_STATCALLB
 653                        printk(KERN_DEBUG "NODCH: %ld\n", c->arg);
 654#endif
 655                        if (dev->global_flags & ISDN_GLOBAL_STOPPED)
 656                                return 0;
 657                        if (isdn_net_stat_callback(i, c))
 658                                break;
 659                        if (isdn_tty_stat_callback(i, c))
 660                                break;
 661                        break;
 662                case ISDN_STAT_ADDCH:
 663                        spin_lock_irqsave(&dev->lock, flags);
 664                        if (isdn_add_channels(dev->drv[di], di, c->arg, 1)) {
 665                                spin_unlock_irqrestore(&dev->lock, flags);
 666                                return -1;
 667                        }
 668                        spin_unlock_irqrestore(&dev->lock, flags);
 669                        isdn_info_update();
 670                        break;
 671                case ISDN_STAT_DISCH:
 672                        spin_lock_irqsave(&dev->lock, flags);
 673                        for (i = 0; i < ISDN_MAX_CHANNELS; i++)
 674                                if ((dev->drvmap[i] == di) &&
 675                                    (dev->chanmap[i] == c->arg)) {
 676                                    if (c->parm.num[0])
 677                                      dev->usage[i] &= ~ISDN_USAGE_DISABLED;
 678                                    else
 679                                      if (USG_NONE(dev->usage[i])) {
 680                                        dev->usage[i] |= ISDN_USAGE_DISABLED;
 681                                      }
 682                                      else 
 683                                        retval = -1;
 684                                    break;
 685                                }
 686                        spin_unlock_irqrestore(&dev->lock, flags);
 687                        isdn_info_update();
 688                        break;
 689                case ISDN_STAT_UNLOAD:
 690                        while (dev->drv[di]->locks > 0) {
 691                                isdn_unlock_driver(dev->drv[di]);
 692                        }
 693                        spin_lock_irqsave(&dev->lock, flags);
 694                        isdn_tty_stat_callback(i, c);
 695                        for (i = 0; i < ISDN_MAX_CHANNELS; i++)
 696                                if (dev->drvmap[i] == di) {
 697                                        dev->drvmap[i] = -1;
 698                                        dev->chanmap[i] = -1;
 699                                        dev->usage[i] &= ~ISDN_USAGE_DISABLED;
 700                                }
 701                        dev->drivers--;
 702                        dev->channels -= dev->drv[di]->channels;
 703                        kfree(dev->drv[di]->rcverr);
 704                        kfree(dev->drv[di]->rcvcount);
 705                        for (i = 0; i < dev->drv[di]->channels; i++)
 706                                skb_queue_purge(&dev->drv[di]->rpqueue[i]);
 707                        kfree(dev->drv[di]->rpqueue);
 708                        kfree(dev->drv[di]->rcv_waitq);
 709                        kfree(dev->drv[di]);
 710                        dev->drv[di] = NULL;
 711                        dev->drvid[di][0] = '\0';
 712                        isdn_info_update();
 713                        set_global_features();
 714                        spin_unlock_irqrestore(&dev->lock, flags);
 715                        return 0;
 716                case ISDN_STAT_L1ERR:
 717                        break;
 718                case CAPI_PUT_MESSAGE:
 719                        return(isdn_capi_rec_hl_msg(&c->parm.cmsg));
 720#ifdef CONFIG_ISDN_TTY_FAX
 721                case ISDN_STAT_FAXIND:
 722                        isdn_tty_stat_callback(i, c);
 723                        break;
 724#endif
 725#ifdef CONFIG_ISDN_AUDIO
 726                case ISDN_STAT_AUDIO:
 727                        isdn_tty_stat_callback(i, c);
 728                        break;
 729#endif
 730#ifdef CONFIG_ISDN_DIVERSION
 731                case ISDN_STAT_PROT:
 732                case ISDN_STAT_REDIR:
 733                        if (divert_if)
 734                          return(divert_if->stat_callback(c));
 735#endif /* CONFIG_ISDN_DIVERSION */
 736                default:
 737                        return -1;
 738        }
 739        return 0;
 740}
 741
 742/*
 743 * Get integer from char-pointer, set pointer to end of number
 744 */
 745int
 746isdn_getnum(char **p)
 747{
 748        int v = -1;
 749
 750        while (*p[0] >= '0' && *p[0] <= '9')
 751                v = ((v < 0) ? 0 : (v * 10)) + (int) ((*p[0]++) - '0');
 752        return v;
 753}
 754
 755#define DLE 0x10
 756
 757/*
 758 * isdn_readbchan() tries to get data from the read-queue.
 759 * It MUST be called with interrupts off.
 760 *
 761 * Be aware that this is not an atomic operation when sleep != 0, even though 
 762 * interrupts are turned off! Well, like that we are currently only called
 763 * on behalf of a read system call on raw device files (which are documented
 764 * to be dangerous and for debugging purpose only). The inode semaphore
 765 * takes care that this is not called for the same minor device number while
 766 * we are sleeping, but access is not serialized against simultaneous read()
 767 * from the corresponding ttyI device. Can other ugly events, like changes
 768 * of the mapping (di,ch)<->minor, happen during the sleep? --he 
 769 */
 770int
 771isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_queue_head_t *sleep)
 772{
 773        int count;
 774        int count_pull;
 775        int count_put;
 776        int dflag;
 777        struct sk_buff *skb;
 778        u_char *cp;
 779
 780        if (!dev->drv[di])
 781                return 0;
 782        if (skb_queue_empty(&dev->drv[di]->rpqueue[channel])) {
 783                if (sleep)
 784                        interruptible_sleep_on(sleep);
 785                else
 786                        return 0;
 787        }
 788        if (len > dev->drv[di]->rcvcount[channel])
 789                len = dev->drv[di]->rcvcount[channel];
 790        cp = buf;
 791        count = 0;
 792        while (len) {
 793                if (!(skb = skb_peek(&dev->drv[di]->rpqueue[channel])))
 794                        break;
 795#ifdef CONFIG_ISDN_AUDIO
 796                if (ISDN_AUDIO_SKB_LOCK(skb))
 797                        break;
 798                ISDN_AUDIO_SKB_LOCK(skb) = 1;
 799                if ((ISDN_AUDIO_SKB_DLECOUNT(skb)) || (dev->drv[di]->DLEflag & (1 << channel))) {
 800                        char *p = skb->data;
 801                        unsigned long DLEmask = (1 << channel);
 802
 803                        dflag = 0;
 804                        count_pull = count_put = 0;
 805                        while ((count_pull < skb->len) && (len > 0)) {
 806                                len--;
 807                                if (dev->drv[di]->DLEflag & DLEmask) {
 808                                        *cp++ = DLE;
 809                                        dev->drv[di]->DLEflag &= ~DLEmask;
 810                                } else {
 811                                        *cp++ = *p;
 812                                        if (*p == DLE) {
 813                                                dev->drv[di]->DLEflag |= DLEmask;
 814                                                (ISDN_AUDIO_SKB_DLECOUNT(skb))--;
 815                                        }
 816                                        p++;
 817                                        count_pull++;
 818                                }
 819                                count_put++;
 820                        }
 821                        if (count_pull >= skb->len)
 822                                dflag = 1;
 823                } else {
 824#endif
 825                        /* No DLE's in buff, so simply copy it */
 826                        dflag = 1;
 827                        if ((count_pull = skb->len) > len) {
 828                                count_pull = len;
 829                                dflag = 0;
 830                        }
 831                        count_put = count_pull;
 832                        skb_copy_from_linear_data(skb, cp, count_put);
 833                        cp += count_put;
 834                        len -= count_put;
 835#ifdef CONFIG_ISDN_AUDIO
 836                }
 837#endif
 838                count += count_put;
 839                if (fp) {
 840                        memset(fp, 0, count_put);
 841                        fp += count_put;
 842                }
 843                if (dflag) {
 844                        /* We got all the data in this buff.
 845                         * Now we can dequeue it.
 846                         */
 847                        if (fp)
 848                                *(fp - 1) = 0xff;
 849#ifdef CONFIG_ISDN_AUDIO
 850                        ISDN_AUDIO_SKB_LOCK(skb) = 0;
 851#endif
 852                        skb = skb_dequeue(&dev->drv[di]->rpqueue[channel]);
 853                        dev_kfree_skb(skb);
 854                } else {
 855                        /* Not yet emptied this buff, so it
 856                         * must stay in the queue, for further calls
 857                         * but we pull off the data we got until now.
 858                         */
 859                        skb_pull(skb, count_pull);
 860#ifdef CONFIG_ISDN_AUDIO
 861                        ISDN_AUDIO_SKB_LOCK(skb) = 0;
 862#endif
 863                }
 864                dev->drv[di]->rcvcount[channel] -= count_put;
 865        }
 866        return count;
 867}
 868
 869/*
 870 * isdn_readbchan_tty() tries to get data from the read-queue.
 871 * It MUST be called with interrupts off.
 872 *
 873 * Be aware that this is not an atomic operation when sleep != 0, even though
 874 * interrupts are turned off! Well, like that we are currently only called
 875 * on behalf of a read system call on raw device files (which are documented
 876 * to be dangerous and for debugging purpose only). The inode semaphore
 877 * takes care that this is not called for the same minor device number while
 878 * we are sleeping, but access is not serialized against simultaneous read()
 879 * from the corresponding ttyI device. Can other ugly events, like changes
 880 * of the mapping (di,ch)<->minor, happen during the sleep? --he
 881 */
 882int
 883isdn_readbchan_tty(int di, int channel, struct tty_struct *tty, int cisco_hack)
 884{
 885        int count;
 886        int count_pull;
 887        int count_put;
 888        int dflag;
 889        struct sk_buff *skb;
 890        char last = 0;
 891        int len;
 892
 893        if (!dev->drv[di])
 894                return 0;
 895        if (skb_queue_empty(&dev->drv[di]->rpqueue[channel]))
 896                        return 0;
 897
 898        len = tty_buffer_request_room(tty, dev->drv[di]->rcvcount[channel]);
 899        if(len == 0)
 900                return len;
 901
 902        count = 0;
 903        while (len) {
 904                if (!(skb = skb_peek(&dev->drv[di]->rpqueue[channel])))
 905                        break;
 906#ifdef CONFIG_ISDN_AUDIO
 907                if (ISDN_AUDIO_SKB_LOCK(skb))
 908                        break;
 909                ISDN_AUDIO_SKB_LOCK(skb) = 1;
 910                if ((ISDN_AUDIO_SKB_DLECOUNT(skb)) || (dev->drv[di]->DLEflag & (1 << channel))) {
 911                        char *p = skb->data;
 912                        unsigned long DLEmask = (1 << channel);
 913
 914                        dflag = 0;
 915                        count_pull = count_put = 0;
 916                        while ((count_pull < skb->len) && (len > 0)) {
 917                                /* push every character but the last to the tty buffer directly */
 918                                if ( count_put )
 919                                        tty_insert_flip_char(tty, last, TTY_NORMAL);
 920                                len--;
 921                                if (dev->drv[di]->DLEflag & DLEmask) {
 922                                        last = DLE;
 923                                        dev->drv[di]->DLEflag &= ~DLEmask;
 924                                } else {
 925                                        last = *p;
 926                                        if (last == DLE) {
 927                                                dev->drv[di]->DLEflag |= DLEmask;
 928                                                (ISDN_AUDIO_SKB_DLECOUNT(skb))--;
 929                                        }
 930                                        p++;
 931                                        count_pull++;
 932                                }
 933                                count_put++;
 934                        }
 935                        if (count_pull >= skb->len)
 936                                dflag = 1;
 937                } else {
 938#endif
 939                        /* No DLE's in buff, so simply copy it */
 940                        dflag = 1;
 941                        if ((count_pull = skb->len) > len) {
 942                                count_pull = len;
 943                                dflag = 0;
 944                        }
 945                        count_put = count_pull;
 946                        if(count_put > 1)
 947                                tty_insert_flip_string(tty, skb->data, count_put - 1);
 948                        last = skb->data[count_put - 1];
 949                        len -= count_put;
 950#ifdef CONFIG_ISDN_AUDIO
 951                }
 952#endif
 953                count += count_put;
 954                if (dflag) {
 955                        /* We got all the data in this buff.
 956                         * Now we can dequeue it.
 957                         */
 958                        if(cisco_hack)
 959                                tty_insert_flip_char(tty, last, 0xFF);
 960                        else
 961                                tty_insert_flip_char(tty, last, TTY_NORMAL);
 962#ifdef CONFIG_ISDN_AUDIO
 963                        ISDN_AUDIO_SKB_LOCK(skb) = 0;
 964#endif
 965                        skb = skb_dequeue(&dev->drv[di]->rpqueue[channel]);
 966                        dev_kfree_skb(skb);
 967                } else {
 968                        tty_insert_flip_char(tty, last, TTY_NORMAL);
 969                        /* Not yet emptied this buff, so it
 970                         * must stay in the queue, for further calls
 971                         * but we pull off the data we got until now.
 972                         */
 973                        skb_pull(skb, count_pull);
 974#ifdef CONFIG_ISDN_AUDIO
 975                        ISDN_AUDIO_SKB_LOCK(skb) = 0;
 976#endif
 977                }
 978                dev->drv[di]->rcvcount[channel] -= count_put;
 979        }
 980        return count;
 981}
 982
 983
 984static inline int
 985isdn_minor2drv(int minor)
 986{
 987        return (dev->drvmap[minor]);
 988}
 989
 990static inline int
 991isdn_minor2chan(int minor)
 992{
 993        return (dev->chanmap[minor]);
 994}
 995
 996static char *
 997isdn_statstr(void)
 998{
 999        static char istatbuf[2048];
1000        char *p;
1001        int i;
1002
1003        sprintf(istatbuf, "idmap:\t");
1004        p = istatbuf + strlen(istatbuf);
1005        for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1006                sprintf(p, "%s ", (dev->drvmap[i] < 0) ? "-" : dev->drvid[dev->drvmap[i]]);
1007                p = istatbuf + strlen(istatbuf);
1008        }
1009        sprintf(p, "\nchmap:\t");
1010        p = istatbuf + strlen(istatbuf);
1011        for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1012                sprintf(p, "%d ", dev->chanmap[i]);
1013                p = istatbuf + strlen(istatbuf);
1014        }
1015        sprintf(p, "\ndrmap:\t");
1016        p = istatbuf + strlen(istatbuf);
1017        for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1018                sprintf(p, "%d ", dev->drvmap[i]);
1019                p = istatbuf + strlen(istatbuf);
1020        }
1021        sprintf(p, "\nusage:\t");
1022        p = istatbuf + strlen(istatbuf);
1023        for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1024                sprintf(p, "%d ", dev->usage[i]);
1025                p = istatbuf + strlen(istatbuf);
1026        }
1027        sprintf(p, "\nflags:\t");
1028        p = istatbuf + strlen(istatbuf);
1029        for (i = 0; i < ISDN_MAX_DRIVERS; i++) {
1030                if (dev->drv[i]) {
1031                        sprintf(p, "%ld ", dev->drv[i]->online);
1032                        p = istatbuf + strlen(istatbuf);
1033                } else {
1034                        sprintf(p, "? ");
1035                        p = istatbuf + strlen(istatbuf);
1036                }
1037        }
1038        sprintf(p, "\nphone:\t");
1039        p = istatbuf + strlen(istatbuf);
1040        for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1041                sprintf(p, "%s ", dev->num[i]);
1042                p = istatbuf + strlen(istatbuf);
1043        }
1044        sprintf(p, "\n");
1045        return istatbuf;
1046}
1047
1048/* Module interface-code */
1049
1050void
1051isdn_info_update(void)
1052{
1053        infostruct *p = dev->infochain;
1054
1055        while (p) {
1056                *(p->private) = 1;
1057                p = (infostruct *) p->next;
1058        }
1059        wake_up_interruptible(&(dev->info_waitq));
1060}
1061
1062static ssize_t
1063isdn_read(struct file *file, char __user *buf, size_t count, loff_t * off)
1064{
1065        uint minor = iminor(file->f_path.dentry->d_inode);
1066        int len = 0;
1067        int drvidx;
1068        int chidx;
1069        int retval;
1070        char *p;
1071
1072        lock_kernel();
1073        if (minor == ISDN_MINOR_STATUS) {
1074                if (!file->private_data) {
1075                        if (file->f_flags & O_NONBLOCK) {
1076                                retval = -EAGAIN;
1077                                goto out;
1078                        }
1079                        interruptible_sleep_on(&(dev->info_waitq));
1080                }
1081                p = isdn_statstr();
1082                file->private_data = NULL;
1083                if ((len = strlen(p)) <= count) {
1084                        if (copy_to_user(buf, p, len)) {
1085                                retval = -EFAULT;
1086                                goto out;
1087                        }
1088                        *off += len;
1089                        retval = len;
1090                        goto out;
1091                }
1092                retval = 0;
1093                goto out;
1094        }
1095        if (!dev->drivers) {
1096                retval = -ENODEV;
1097                goto out;
1098        }
1099        if (minor <= ISDN_MINOR_BMAX) {
1100                printk(KERN_WARNING "isdn_read minor %d obsolete!\n", minor);
1101                drvidx = isdn_minor2drv(minor);
1102                if (drvidx < 0) {
1103                        retval = -ENODEV;
1104                        goto out;
1105                }
1106                if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) {
1107                        retval = -ENODEV;
1108                        goto out;
1109                }
1110                chidx = isdn_minor2chan(minor);
1111                if (!(p = kmalloc(count, GFP_KERNEL))) {
1112                        retval = -ENOMEM;
1113                        goto out;
1114                }
1115                len = isdn_readbchan(drvidx, chidx, p, NULL, count,
1116                                     &dev->drv[drvidx]->rcv_waitq[chidx]);
1117                *off += len;
1118                if (copy_to_user(buf,p,len)) 
1119                        len = -EFAULT;
1120                kfree(p);
1121                retval = len;
1122                goto out;
1123        }
1124        if (minor <= ISDN_MINOR_CTRLMAX) {
1125                drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
1126                if (drvidx < 0) {
1127                        retval = -ENODEV;
1128                        goto out;
1129                }
1130                if (!dev->drv[drvidx]->stavail) {
1131                        if (file->f_flags & O_NONBLOCK) {
1132                                retval = -EAGAIN;
1133                                goto out;
1134                        }
1135                        interruptible_sleep_on(&(dev->drv[drvidx]->st_waitq));
1136                }
1137                if (dev->drv[drvidx]->interface->readstat) {
1138                        if (count > dev->drv[drvidx]->stavail)
1139                                count = dev->drv[drvidx]->stavail;
1140                        len = dev->drv[drvidx]->interface->readstat(buf, count,
1141                                drvidx, isdn_minor2chan(minor - ISDN_MINOR_CTRL));
1142                        if (len < 0) {
1143                                retval = len;
1144                                goto out;
1145                        }
1146                } else {
1147                        len = 0;
1148                }
1149                if (len)
1150                        dev->drv[drvidx]->stavail -= len;
1151                else
1152                        dev->drv[drvidx]->stavail = 0;
1153                *off += len;
1154                retval = len;
1155                goto out;
1156        }
1157#ifdef CONFIG_ISDN_PPP
1158        if (minor <= ISDN_MINOR_PPPMAX) {
1159                retval = isdn_ppp_read(minor - ISDN_MINOR_PPP, file, buf, count);
1160                goto out;
1161        }
1162#endif
1163        retval = -ENODEV;
1164 out:
1165        unlock_kernel();
1166        return retval;
1167}
1168
1169static ssize_t
1170isdn_write(struct file *file, const char __user *buf, size_t count, loff_t * off)
1171{
1172        uint minor = iminor(file->f_path.dentry->d_inode);
1173        int drvidx;
1174        int chidx;
1175        int retval;
1176
1177        if (minor == ISDN_MINOR_STATUS)
1178                return -EPERM;
1179        if (!dev->drivers)
1180                return -ENODEV;
1181
1182        lock_kernel();
1183        if (minor <= ISDN_MINOR_BMAX) {
1184                printk(KERN_WARNING "isdn_write minor %d obsolete!\n", minor);
1185                drvidx = isdn_minor2drv(minor);
1186                if (drvidx < 0) {
1187                        retval = -ENODEV;
1188                        goto out;
1189                }
1190                if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) {
1191                        retval = -ENODEV;
1192                        goto out;
1193                }
1194                chidx = isdn_minor2chan(minor);
1195                while ((retval = isdn_writebuf_stub(drvidx, chidx, buf, count)) == 0)
1196                        interruptible_sleep_on(&dev->drv[drvidx]->snd_waitq[chidx]);
1197                goto out;
1198        }
1199        if (minor <= ISDN_MINOR_CTRLMAX) {
1200                drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
1201                if (drvidx < 0) {
1202                        retval = -ENODEV;
1203                        goto out;
1204                }
1205                /*
1206                 * We want to use the isdnctrl device to load the firmware
1207                 *
1208                 if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
1209                 return -ENODEV;
1210                 */
1211                if (dev->drv[drvidx]->interface->writecmd)
1212                        retval = dev->drv[drvidx]->interface->
1213                                writecmd(buf, count, drvidx,
1214                                isdn_minor2chan(minor - ISDN_MINOR_CTRL));
1215                else
1216                        retval = count;
1217                goto out;
1218        }
1219#ifdef CONFIG_ISDN_PPP
1220        if (minor <= ISDN_MINOR_PPPMAX) {
1221                retval = isdn_ppp_write(minor - ISDN_MINOR_PPP, file, buf, count);
1222                goto out;
1223        }
1224#endif
1225        retval = -ENODEV;
1226 out:
1227        unlock_kernel();
1228        return retval;
1229}
1230
1231static unsigned int
1232isdn_poll(struct file *file, poll_table * wait)
1233{
1234        unsigned int mask = 0;
1235        unsigned int minor = iminor(file->f_path.dentry->d_inode);
1236        int drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
1237
1238        lock_kernel();
1239        if (minor == ISDN_MINOR_STATUS) {
1240                poll_wait(file, &(dev->info_waitq), wait);
1241                /* mask = POLLOUT | POLLWRNORM; */
1242                if (file->private_data) {
1243                        mask |= POLLIN | POLLRDNORM;
1244                }
1245                goto out;
1246        }
1247        if (minor >= ISDN_MINOR_CTRL && minor <= ISDN_MINOR_CTRLMAX) {
1248                if (drvidx < 0) {
1249                        /* driver deregistered while file open */
1250                        mask = POLLHUP;
1251                        goto out;
1252                }
1253                poll_wait(file, &(dev->drv[drvidx]->st_waitq), wait);
1254                mask = POLLOUT | POLLWRNORM;
1255                if (dev->drv[drvidx]->stavail) {
1256                        mask |= POLLIN | POLLRDNORM;
1257                }
1258                goto out;
1259        }
1260#ifdef CONFIG_ISDN_PPP
1261        if (minor <= ISDN_MINOR_PPPMAX) {
1262                mask = isdn_ppp_poll(file, wait);
1263                goto out;
1264        }
1265#endif
1266        mask = POLLERR;
1267 out:
1268        unlock_kernel();
1269        return mask;
1270}
1271
1272
1273static int
1274isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
1275{
1276        uint minor = iminor(inode);
1277        isdn_ctrl c;
1278        int drvidx;
1279        int chidx;
1280        int ret;
1281        int i;
1282        char __user *p;
1283        char *s;
1284        union iocpar {
1285                char name[10];
1286                char bname[22];
1287                isdn_ioctl_struct iocts;
1288                isdn_net_ioctl_phone phone;
1289                isdn_net_ioctl_cfg cfg;
1290        } iocpar;
1291        void __user *argp = (void __user *)arg;
1292
1293#define name  iocpar.name
1294#define bname iocpar.bname
1295#define iocts iocpar.iocts
1296#define phone iocpar.phone
1297#define cfg   iocpar.cfg
1298
1299        if (minor == ISDN_MINOR_STATUS) {
1300                switch (cmd) {
1301                        case IIOCGETDVR:
1302                                return (TTY_DV +
1303                                        (NET_DV << 8) +
1304                                        (INF_DV << 16));
1305                        case IIOCGETCPS:
1306                                if (arg) {
1307                                        ulong __user *p = argp;
1308                                        int i;
1309                                        if (!access_ok(VERIFY_WRITE, p,
1310                                                        sizeof(ulong) * ISDN_MAX_CHANNELS * 2))
1311                                                return -EFAULT;
1312                                        for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1313                                                put_user(dev->ibytes[i], p++);
1314                                                put_user(dev->obytes[i], p++);
1315                                        }
1316                                        return 0;
1317                                } else
1318                                        return -EINVAL;
1319                                break;
1320#ifdef CONFIG_NETDEVICES
1321                        case IIOCNETGPN:
1322                                /* Get peer phone number of a connected 
1323                                 * isdn network interface */
1324                                if (arg) {
1325                                        if (copy_from_user(&phone, argp, sizeof(phone)))
1326                                                return -EFAULT;
1327                                        return isdn_net_getpeer(&phone, argp);
1328                                } else
1329                                        return -EINVAL;
1330#endif
1331                        default:
1332                                return -EINVAL;
1333                }
1334        }
1335        if (!dev->drivers)
1336                return -ENODEV;
1337        if (minor <= ISDN_MINOR_BMAX) {
1338                drvidx = isdn_minor2drv(minor);
1339                if (drvidx < 0)
1340                        return -ENODEV;
1341                chidx = isdn_minor2chan(minor);
1342                if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
1343                        return -ENODEV;
1344                return 0;
1345        }
1346        if (minor <= ISDN_MINOR_CTRLMAX) {
1347/*
1348 * isdn net devices manage lots of configuration variables as linked lists.
1349 * Those lists must only be manipulated from user space. Some of the ioctl's
1350 * service routines access user space and are not atomic. Therefor, ioctl's
1351 * manipulating the lists and ioctl's sleeping while accessing the lists
1352 * are serialized by means of a semaphore.
1353 */
1354                switch (cmd) {
1355                        case IIOCNETDWRSET:
1356                                printk(KERN_INFO "INFO: ISDN_DW_ABC_EXTENSION not enabled\n");
1357                                return(-EINVAL);
1358                        case IIOCNETLCR:
1359                                printk(KERN_INFO "INFO: ISDN_ABC_LCR_SUPPORT not enabled\n");
1360                                return -ENODEV;
1361#ifdef CONFIG_NETDEVICES
1362                        case IIOCNETAIF:
1363                                /* Add a network-interface */
1364                                if (arg) {
1365                                        if (copy_from_user(name, argp, sizeof(name)))
1366                                                return -EFAULT;
1367                                        s = name;
1368                                } else {
1369                                        s = NULL;
1370                                }
1371                                ret = mutex_lock_interruptible(&dev->mtx);
1372                                if( ret ) return ret;
1373                                if ((s = isdn_net_new(s, NULL))) {
1374                                        if (copy_to_user(argp, s, strlen(s) + 1)){
1375                                                ret = -EFAULT;
1376                                        } else {
1377                                                ret = 0;
1378                                        }
1379                                } else
1380                                        ret = -ENODEV;
1381                                mutex_unlock(&dev->mtx);
1382                                return ret;
1383                        case IIOCNETASL:
1384                                /* Add a slave to a network-interface */
1385                                if (arg) {
1386                                        if (copy_from_user(bname, argp, sizeof(bname) - 1))
1387                                                return -EFAULT;
1388                                } else
1389                                        return -EINVAL;
1390                                ret = mutex_lock_interruptible(&dev->mtx);
1391                                if( ret ) return ret;
1392                                if ((s = isdn_net_newslave(bname))) {
1393                                        if (copy_to_user(argp, s, strlen(s) + 1)){
1394                                                ret = -EFAULT;
1395                                        } else {
1396                                                ret = 0;
1397                                        }
1398                                } else
1399                                        ret = -ENODEV;
1400                                mutex_unlock(&dev->mtx);
1401                                return ret;
1402                        case IIOCNETDIF:
1403                                /* Delete a network-interface */
1404                                if (arg) {
1405                                        if (copy_from_user(name, argp, sizeof(name)))
1406                                                return -EFAULT;
1407                                        ret = mutex_lock_interruptible(&dev->mtx);
1408                                        if( ret ) return ret;
1409                                        ret = isdn_net_rm(name);
1410                                        mutex_unlock(&dev->mtx);
1411                                        return ret;
1412                                } else
1413                                        return -EINVAL;
1414                        case IIOCNETSCF:
1415                                /* Set configurable parameters of a network-interface */
1416                                if (arg) {
1417                                        if (copy_from_user(&cfg, argp, sizeof(cfg)))
1418                                                return -EFAULT;
1419                                        return isdn_net_setcfg(&cfg);
1420                                } else
1421                                        return -EINVAL;
1422                        case IIOCNETGCF:
1423                                /* Get configurable parameters of a network-interface */
1424                                if (arg) {
1425                                        if (copy_from_user(&cfg, argp, sizeof(cfg)))
1426                                                return -EFAULT;
1427                                        if (!(ret = isdn_net_getcfg(&cfg))) {
1428                                                if (copy_to_user(argp, &cfg, sizeof(cfg)))
1429                                                        return -EFAULT;
1430                                        }
1431                                        return ret;
1432                                } else
1433                                        return -EINVAL;
1434                        case IIOCNETANM:
1435                                /* Add a phone-number to a network-interface */
1436                                if (arg) {
1437                                        if (copy_from_user(&phone, argp, sizeof(phone)))
1438                                                return -EFAULT;
1439                                        ret = mutex_lock_interruptible(&dev->mtx);
1440                                        if( ret ) return ret;
1441                                        ret = isdn_net_addphone(&phone);
1442                                        mutex_unlock(&dev->mtx);
1443                                        return ret;
1444                                } else
1445                                        return -EINVAL;
1446                        case IIOCNETGNM:
1447                                /* Get list of phone-numbers of a network-interface */
1448                                if (arg) {
1449                                        if (copy_from_user(&phone, argp, sizeof(phone)))
1450                                                return -EFAULT;
1451                                        ret = mutex_lock_interruptible(&dev->mtx);
1452                                        if( ret ) return ret;
1453                                        ret = isdn_net_getphones(&phone, argp);
1454                                        mutex_unlock(&dev->mtx);
1455                                        return ret;
1456                                } else
1457                                        return -EINVAL;
1458                        case IIOCNETDNM:
1459                                /* Delete a phone-number of a network-interface */
1460                                if (arg) {
1461                                        if (copy_from_user(&phone, argp, sizeof(phone)))
1462                                                return -EFAULT;
1463                                        ret = mutex_lock_interruptible(&dev->mtx);
1464                                        if( ret ) return ret;
1465                                        ret = isdn_net_delphone(&phone);
1466                                        mutex_unlock(&dev->mtx);
1467                                        return ret;
1468                                } else
1469                                        return -EINVAL;
1470                        case IIOCNETDIL:
1471                                /* Force dialing of a network-interface */
1472                                if (arg) {
1473                                        if (copy_from_user(name, argp, sizeof(name)))
1474                                                return -EFAULT;
1475                                        return isdn_net_force_dial(name);
1476                                } else
1477                                        return -EINVAL;
1478#ifdef CONFIG_ISDN_PPP
1479                        case IIOCNETALN:
1480                                if (!arg)
1481                                        return -EINVAL;
1482                                if (copy_from_user(name, argp, sizeof(name)))
1483                                        return -EFAULT;
1484                                return isdn_ppp_dial_slave(name);
1485                        case IIOCNETDLN:
1486                                if (!arg)
1487                                        return -EINVAL;
1488                                if (copy_from_user(name, argp, sizeof(name)))
1489                                        return -EFAULT;
1490                                return isdn_ppp_hangup_slave(name);
1491#endif
1492                        case IIOCNETHUP:
1493                                /* Force hangup of a network-interface */
1494                                if (!arg)
1495                                        return -EINVAL;
1496                                if (copy_from_user(name, argp, sizeof(name)))
1497                                        return -EFAULT;
1498                                return isdn_net_force_hangup(name);
1499                                break;
1500#endif                          /* CONFIG_NETDEVICES */
1501                        case IIOCSETVER:
1502                                dev->net_verbose = arg;
1503                                printk(KERN_INFO "isdn: Verbose-Level is %d\n", dev->net_verbose);
1504                                return 0;
1505                        case IIOCSETGST:
1506                                if (arg)
1507                                        dev->global_flags |= ISDN_GLOBAL_STOPPED;
1508                                else
1509                                        dev->global_flags &= ~ISDN_GLOBAL_STOPPED;
1510                                printk(KERN_INFO "isdn: Global Mode %s\n",
1511                                       (dev->global_flags & ISDN_GLOBAL_STOPPED) ? "stopped" : "running");
1512                                return 0;
1513                        case IIOCSETBRJ:
1514                                drvidx = -1;
1515                                if (arg) {
1516                                        int i;
1517                                        char *p;
1518                                        if (copy_from_user(&iocts, argp,
1519                                             sizeof(isdn_ioctl_struct)))
1520                                                return -EFAULT;
1521                                        iocts.drvid[sizeof(iocts.drvid)-1] = 0;
1522                                        if (strlen(iocts.drvid)) {
1523                                                if ((p = strchr(iocts.drvid, ',')))
1524                                                        *p = 0;
1525                                                drvidx = -1;
1526                                                for (i = 0; i < ISDN_MAX_DRIVERS; i++)
1527                                                        if (!(strcmp(dev->drvid[i], iocts.drvid))) {
1528                                                                drvidx = i;
1529                                                                break;
1530                                                        }
1531                                        }
1532                                }
1533                                if (drvidx == -1)
1534                                        return -ENODEV;
1535                                if (iocts.arg)
1536                                        dev->drv[drvidx]->flags |= DRV_FLAG_REJBUS;
1537                                else
1538                                        dev->drv[drvidx]->flags &= ~DRV_FLAG_REJBUS;
1539                                return 0;
1540                        case IIOCSIGPRF:
1541                                dev->profd = current;
1542                                return 0;
1543                                break;
1544                        case IIOCGETPRF:
1545                                /* Get all Modem-Profiles */
1546                                if (arg) {
1547                                        char __user *p = argp;
1548                                        int i;
1549
1550                                        if (!access_ok(VERIFY_WRITE, argp,
1551                                        (ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN)
1552                                                   * ISDN_MAX_CHANNELS))
1553                                                return -EFAULT;
1554
1555                                        for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1556                                                if (copy_to_user(p, dev->mdm.info[i].emu.profile,
1557                                                      ISDN_MODEM_NUMREG))
1558                                                        return -EFAULT;
1559                                                p += ISDN_MODEM_NUMREG;
1560                                                if (copy_to_user(p, dev->mdm.info[i].emu.pmsn, ISDN_MSNLEN))
1561                                                        return -EFAULT;
1562                                                p += ISDN_MSNLEN;
1563                                                if (copy_to_user(p, dev->mdm.info[i].emu.plmsn, ISDN_LMSNLEN))
1564                                                        return -EFAULT;
1565                                                p += ISDN_LMSNLEN;
1566                                        }
1567                                        return (ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN) * ISDN_MAX_CHANNELS;
1568                                } else
1569                                        return -EINVAL;
1570                                break;
1571                        case IIOCSETPRF:
1572                                /* Set all Modem-Profiles */
1573                                if (arg) {
1574                                        char __user *p = argp;
1575                                        int i;
1576
1577                                        if (!access_ok(VERIFY_READ, argp,
1578                                        (ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN)
1579                                                   * ISDN_MAX_CHANNELS))
1580                                                return -EFAULT;
1581
1582                                        for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1583                                                if (copy_from_user(dev->mdm.info[i].emu.profile, p,
1584                                                     ISDN_MODEM_NUMREG))
1585                                                        return -EFAULT;
1586                                                p += ISDN_MODEM_NUMREG;
1587                                                if (copy_from_user(dev->mdm.info[i].emu.plmsn, p, ISDN_LMSNLEN))
1588                                                        return -EFAULT;
1589                                                p += ISDN_LMSNLEN;
1590                                                if (copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN))
1591                                                        return -EFAULT;
1592                                                p += ISDN_MSNLEN;
1593                                        }
1594                                        return 0;
1595                                } else
1596                                        return -EINVAL;
1597                                break;
1598                        case IIOCSETMAP:
1599                        case IIOCGETMAP:
1600                                /* Set/Get MSN->EAZ-Mapping for a driver */
1601                                if (arg) {
1602
1603                                        if (copy_from_user(&iocts, argp,
1604                                             sizeof(isdn_ioctl_struct)))
1605                                                return -EFAULT;
1606                                        iocts.drvid[sizeof(iocts.drvid)-1] = 0;
1607                                        if (strlen(iocts.drvid)) {
1608                                                drvidx = -1;
1609                                                for (i = 0; i < ISDN_MAX_DRIVERS; i++)
1610                                                        if (!(strcmp(dev->drvid[i], iocts.drvid))) {
1611                                                                drvidx = i;
1612                                                                break;
1613                                                        }
1614                                        } else
1615                                                drvidx = 0;
1616                                        if (drvidx == -1)
1617                                                return -ENODEV;
1618                                        if (cmd == IIOCSETMAP) {
1619                                                int loop = 1;
1620
1621                                                p = (char __user *) iocts.arg;
1622                                                i = 0;
1623                                                while (loop) {
1624                                                        int j = 0;
1625
1626                                                        while (1) {
1627                                                                if (!access_ok(VERIFY_READ, p, 1))
1628                                                                        return -EFAULT;
1629                                                                get_user(bname[j], p++);
1630                                                                switch (bname[j]) {
1631                                                                        case '\0':
1632                                                                                loop = 0;
1633                                                                                /* Fall through */
1634                                                                        case ',':
1635                                                                                bname[j] = '\0';
1636                                                                                strcpy(dev->drv[drvidx]->msn2eaz[i], bname);
1637                                                                                j = ISDN_MSNLEN;
1638                                                                                break;
1639                                                                        default:
1640                                                                                j++;
1641                                                                }
1642                                                                if (j >= ISDN_MSNLEN)
1643                                                                        break;
1644                                                        }
1645                                                        if (++i > 9)
1646                                                                break;
1647                                                }
1648                                        } else {
1649                                                p = (char __user *) iocts.arg;
1650                                                for (i = 0; i < 10; i++) {
1651                                                        snprintf(bname, sizeof(bname), "%s%s",
1652                                                                strlen(dev->drv[drvidx]->msn2eaz[i]) ?
1653                                                                dev->drv[drvidx]->msn2eaz[i] : "_",
1654                                                                (i < 9) ? "," : "\0");
1655                                                        if (copy_to_user(p, bname, strlen(bname) + 1))
1656                                                                return -EFAULT;
1657                                                        p += strlen(bname);
1658                                                }
1659                                        }
1660                                        return 0;
1661                                } else
1662                                        return -EINVAL;
1663                        case IIOCDBGVAR:
1664                                if (arg) {
1665                                        if (copy_to_user(argp, &dev, sizeof(ulong)))
1666                                                return -EFAULT;
1667                                        return 0;
1668                                } else
1669                                        return -EINVAL;
1670                                break;
1671                        default:
1672                                if ((cmd & IIOCDRVCTL) == IIOCDRVCTL)
1673                                        cmd = ((cmd >> _IOC_NRSHIFT) & _IOC_NRMASK) & ISDN_DRVIOCTL_MASK;
1674                                else
1675                                        return -EINVAL;
1676                                if (arg) {
1677                                        int i;
1678                                        char *p;
1679                                        if (copy_from_user(&iocts, argp, sizeof(isdn_ioctl_struct)))
1680                                                return -EFAULT;
1681                                        iocts.drvid[sizeof(iocts.drvid)-1] = 0;
1682                                        if (strlen(iocts.drvid)) {
1683                                                if ((p = strchr(iocts.drvid, ',')))
1684                                                        *p = 0;
1685                                                drvidx = -1;
1686                                                for (i = 0; i < ISDN_MAX_DRIVERS; i++)
1687                                                        if (!(strcmp(dev->drvid[i], iocts.drvid))) {
1688                                                                drvidx = i;
1689                                                                break;
1690                                                        }
1691                                        } else
1692                                                drvidx = 0;
1693                                        if (drvidx == -1)
1694                                                return -ENODEV;
1695                                        if (!access_ok(VERIFY_WRITE, argp,
1696                                             sizeof(isdn_ioctl_struct)))
1697                                                return -EFAULT;
1698                                        c.driver = drvidx;
1699                                        c.command = ISDN_CMD_IOCTL;
1700                                        c.arg = cmd;
1701                                        memcpy(c.parm.num, &iocts.arg, sizeof(ulong));
1702                                        ret = isdn_command(&c);
1703                                        memcpy(&iocts.arg, c.parm.num, sizeof(ulong));
1704                                        if (copy_to_user(argp, &iocts, sizeof(isdn_ioctl_struct)))
1705                                                return -EFAULT;
1706                                        return ret;
1707                                } else
1708                                        return -EINVAL;
1709                }
1710        }
1711#ifdef CONFIG_ISDN_PPP
1712        if (minor <= ISDN_MINOR_PPPMAX)
1713                return (isdn_ppp_ioctl(minor - ISDN_MINOR_PPP, file, cmd, arg));
1714#endif
1715        return -ENODEV;
1716
1717#undef name
1718#undef bname
1719#undef iocts
1720#undef phone
1721#undef cfg
1722}
1723
1724/*
1725 * Open the device code.
1726 */
1727static int
1728isdn_open(struct inode *ino, struct file *filep)
1729{
1730        uint minor = iminor(ino);
1731        int drvidx;
1732        int chidx;
1733        int retval = -ENODEV;
1734
1735        lock_kernel();
1736        if (minor == ISDN_MINOR_STATUS) {
1737                infostruct *p;
1738
1739                if ((p = kmalloc(sizeof(infostruct), GFP_KERNEL))) {
1740                        p->next = (char *) dev->infochain;
1741                        p->private = (char *) &(filep->private_data);
1742                        dev->infochain = p;
1743                        /* At opening we allow a single update */
1744                        filep->private_data = (char *) 1;
1745                        retval = 0;
1746                        goto out;
1747                } else {
1748                        retval = -ENOMEM;
1749                        goto out;
1750                }
1751        }
1752        if (!dev->channels)
1753                goto out;
1754        if (minor <= ISDN_MINOR_BMAX) {
1755                printk(KERN_WARNING "isdn_open minor %d obsolete!\n", minor);
1756                drvidx = isdn_minor2drv(minor);
1757                if (drvidx < 0)
1758                        goto out;
1759                chidx = isdn_minor2chan(minor);
1760                if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
1761                        goto out;
1762                if (!(dev->drv[drvidx]->online & (1 << chidx)))
1763                        goto out;
1764                isdn_lock_drivers();
1765                retval = 0;
1766                goto out;
1767        }
1768        if (minor <= ISDN_MINOR_CTRLMAX) {
1769                drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
1770                if (drvidx < 0)
1771                        goto out;
1772                isdn_lock_drivers();
1773                retval = 0;
1774                goto out;
1775        }
1776#ifdef CONFIG_ISDN_PPP
1777        if (minor <= ISDN_MINOR_PPPMAX) {
1778                retval = isdn_ppp_open(minor - ISDN_MINOR_PPP, filep);
1779                if (retval == 0)
1780                        isdn_lock_drivers();
1781                goto out;
1782        }
1783#endif
1784 out:
1785        nonseekable_open(ino, filep);
1786        unlock_kernel();
1787        return retval;
1788}
1789
1790static int
1791isdn_close(struct inode *ino, struct file *filep)
1792{
1793        uint minor = iminor(ino);
1794
1795        lock_kernel();
1796        if (minor == ISDN_MINOR_STATUS) {
1797                infostruct *p = dev->infochain;
1798                infostruct *q = NULL;
1799
1800                while (p) {
1801                        if (p->private == (char *) &(filep->private_data)) {
1802                                if (q)
1803                                        q->next = p->next;
1804                                else
1805                                        dev->infochain = (infostruct *) (p->next);
1806                                kfree(p);
1807                                goto out;
1808                        }
1809                        q = p;
1810                        p = (infostruct *) (p->next);
1811                }
1812                printk(KERN_WARNING "isdn: No private data while closing isdnctrl\n");
1813                goto out;
1814        }
1815        isdn_unlock_drivers();
1816        if (minor <= ISDN_MINOR_BMAX)
1817                goto out;
1818        if (minor <= ISDN_MINOR_CTRLMAX) {
1819                if (dev->profd == current)
1820                        dev->profd = NULL;
1821                goto out;
1822        }
1823#ifdef CONFIG_ISDN_PPP
1824        if (minor <= ISDN_MINOR_PPPMAX)
1825                isdn_ppp_release(minor - ISDN_MINOR_PPP, filep);
1826#endif
1827
1828 out:
1829        unlock_kernel();
1830        return 0;
1831}
1832
1833static const struct file_operations isdn_fops =
1834{
1835        .owner          = THIS_MODULE,
1836        .llseek         = no_llseek,
1837        .read           = isdn_read,
1838        .write          = isdn_write,
1839        .poll           = isdn_poll,
1840        .ioctl          = isdn_ioctl,
1841        .open           = isdn_open,
1842        .release        = isdn_close,
1843};
1844
1845char *
1846isdn_map_eaz2msn(char *msn, int di)
1847{
1848        isdn_driver_t *this = dev->drv[di];
1849        int i;
1850
1851        if (strlen(msn) == 1) {
1852                i = msn[0] - '0';
1853                if ((i >= 0) && (i <= 9))
1854                        if (strlen(this->msn2eaz[i]))
1855                                return (this->msn2eaz[i]);
1856        }
1857        return (msn);
1858}
1859
1860/*
1861 * Find an unused ISDN-channel, whose feature-flags match the
1862 * given L2- and L3-protocols.
1863 */
1864#define L2V (~(ISDN_FEATURE_L2_V11096|ISDN_FEATURE_L2_V11019|ISDN_FEATURE_L2_V11038))
1865
1866/*
1867 * This function must be called with holding the dev->lock.
1868 */
1869int
1870isdn_get_free_channel(int usage, int l2_proto, int l3_proto, int pre_dev
1871                      ,int pre_chan, char *msn)
1872{
1873        int i;
1874        ulong features;
1875        ulong vfeatures;
1876
1877        features = ((1 << l2_proto) | (0x10000 << l3_proto));
1878        vfeatures = (((1 << l2_proto) | (0x10000 << l3_proto)) &
1879                     ~(ISDN_FEATURE_L2_V11096|ISDN_FEATURE_L2_V11019|ISDN_FEATURE_L2_V11038));
1880        /* If Layer-2 protocol is V.110, accept drivers with
1881         * transparent feature even if these don't support V.110
1882         * because we can emulate this in linklevel.
1883         */
1884        for (i = 0; i < ISDN_MAX_CHANNELS; i++)
1885                if (USG_NONE(dev->usage[i]) &&
1886                    (dev->drvmap[i] != -1)) {
1887                        int d = dev->drvmap[i];
1888                        if ((dev->usage[i] & ISDN_USAGE_EXCLUSIVE) &&
1889                        ((pre_dev != d) || (pre_chan != dev->chanmap[i])))
1890                                continue;
1891                        if (!strcmp(isdn_map_eaz2msn(msn, d), "-"))
1892                                continue;
1893                        if (dev->usage[i] & ISDN_USAGE_DISABLED)
1894                                continue; /* usage not allowed */
1895                        if (dev->drv[d]->flags & DRV_FLAG_RUNNING) {
1896                                if (((dev->drv[d]->interface->features & features) == features) ||
1897                                    (((dev->drv[d]->interface->features & vfeatures) == vfeatures) &&
1898                                     (dev->drv[d]->interface->features & ISDN_FEATURE_L2_TRANS))) {
1899                                        if ((pre_dev < 0) || (pre_chan < 0)) {
1900                                                dev->usage[i] &= ISDN_USAGE_EXCLUSIVE;
1901                                                dev->usage[i] |= usage;
1902                                                isdn_info_update();
1903                                                return i;
1904                                        } else {
1905                                                if ((pre_dev == d) && (pre_chan == dev->chanmap[i])) {
1906                                                        dev->usage[i] &= ISDN_USAGE_EXCLUSIVE;
1907                                                        dev->usage[i] |= usage;
1908                                                        isdn_info_update();
1909                                                        return i;
1910                                                }
1911                                        }
1912                                }
1913                        }
1914                }
1915        return -1;
1916}
1917
1918/*
1919 * Set state of ISDN-channel to 'unused'
1920 */
1921void
1922isdn_free_channel(int di, int ch, int usage)
1923{
1924        int i;
1925
1926        if ((di < 0) || (ch < 0)) {
1927                printk(KERN_WARNING "%s: called with invalid drv(%d) or channel(%d)\n",
1928                        __func__, di, ch);
1929                return;
1930        }
1931        for (i = 0; i < ISDN_MAX_CHANNELS; i++)
1932                if (((!usage) || ((dev->usage[i] & ISDN_USAGE_MASK) == usage)) &&
1933                    (dev->drvmap[i] == di) &&
1934                    (dev->chanmap[i] == ch)) {
1935                        dev->usage[i] &= (ISDN_USAGE_NONE | ISDN_USAGE_EXCLUSIVE);
1936                        strcpy(dev->num[i], "???");
1937                        dev->ibytes[i] = 0;
1938                        dev->obytes[i] = 0;
1939// 20.10.99 JIM, try to reinitialize v110 !
1940                        dev->v110emu[i] = 0;
1941                        atomic_set(&(dev->v110use[i]), 0);
1942                        isdn_v110_close(dev->v110[i]);
1943                        dev->v110[i] = NULL;
1944// 20.10.99 JIM, try to reinitialize v110 !
1945                        isdn_info_update();
1946                        if (dev->drv[di])
1947                                skb_queue_purge(&dev->drv[di]->rpqueue[ch]);
1948                }
1949}
1950
1951/*
1952 * Cancel Exclusive-Flag for ISDN-channel
1953 */
1954void
1955isdn_unexclusive_channel(int di, int ch)
1956{
1957        int i;
1958
1959        for (i = 0; i < ISDN_MAX_CHANNELS; i++)
1960                if ((dev->drvmap[i] == di) &&
1961                    (dev->chanmap[i] == ch)) {
1962                        dev->usage[i] &= ~ISDN_USAGE_EXCLUSIVE;
1963                        isdn_info_update();
1964                        return;
1965                }
1966}
1967
1968/*
1969 *  writebuf replacement for SKB_ABLE drivers
1970 */
1971static int
1972isdn_writebuf_stub(int drvidx, int chan, const u_char __user * buf, int len)
1973{
1974        int ret;
1975        int hl = dev->drv[drvidx]->interface->hl_hdrlen;
1976        struct sk_buff *skb = alloc_skb(hl + len, GFP_ATOMIC);
1977
1978        if (!skb)
1979                return -ENOMEM;
1980        skb_reserve(skb, hl);
1981        if (copy_from_user(skb_put(skb, len), buf, len)) {
1982                dev_kfree_skb(skb);
1983                return -EFAULT;
1984        }
1985        ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, 1, skb);
1986        if (ret <= 0)
1987                dev_kfree_skb(skb);
1988        if (ret > 0)
1989                dev->obytes[isdn_dc2minor(drvidx, chan)] += ret;
1990        return ret;
1991}
1992
1993/*
1994 * Return: length of data on success, -ERRcode on failure.
1995 */
1996int
1997isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb)
1998{
1999        int ret;
2000        struct sk_buff *nskb = NULL;
2001        int v110_ret = skb->len;
2002        int idx = isdn_dc2minor(drvidx, chan);
2003
2004        if (dev->v110[idx]) {
2005                atomic_inc(&dev->v110use[idx]);
2006                nskb = isdn_v110_encode(dev->v110[idx], skb);
2007                atomic_dec(&dev->v110use[idx]);
2008                if (!nskb)
2009                        return 0;
2010                v110_ret = *((int *)nskb->data);
2011                skb_pull(nskb, sizeof(int));
2012                if (!nskb->len) {
2013                        dev_kfree_skb(nskb);
2014                        return v110_ret;
2015                }
2016                /* V.110 must always be acknowledged */
2017                ack = 1;
2018                ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, nskb);
2019        } else {
2020                int hl = dev->drv[drvidx]->interface->hl_hdrlen;
2021
2022                if( skb_headroom(skb) < hl ){
2023                        /* 
2024                         * This should only occur when new HL driver with
2025                         * increased hl_hdrlen was loaded after netdevice
2026                         * was created and connected to the new driver.
2027                         *
2028                         * The V.110 branch (re-allocates on its own) does
2029                         * not need this
2030                         */
2031                        struct sk_buff * skb_tmp;
2032
2033                        skb_tmp = skb_realloc_headroom(skb, hl);
2034                        printk(KERN_DEBUG "isdn_writebuf_skb_stub: reallocating headroom%s\n", skb_tmp ? "" : " failed");
2035                        if (!skb_tmp) return -ENOMEM; /* 0 better? */
2036                        ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, skb_tmp);
2037                        if( ret > 0 ){
2038                                dev_kfree_skb(skb);
2039                        } else {
2040                                dev_kfree_skb(skb_tmp);
2041                        }
2042                } else {
2043                        ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, skb);
2044                }
2045        }
2046        if (ret > 0) {
2047                dev->obytes[idx] += ret;
2048                if (dev->v110[idx]) {
2049                        atomic_inc(&dev->v110use[idx]);
2050                        dev->v110[idx]->skbuser++;
2051                        atomic_dec(&dev->v110use[idx]);
2052                        /* For V.110 return unencoded data length */
2053                        ret = v110_ret;
2054                        /* if the complete frame was send we free the skb;
2055                           if not upper function will requeue the skb */ 
2056                        if (ret == skb->len)
2057                                dev_kfree_skb(skb);
2058                }
2059        } else
2060                if (dev->v110[idx])
2061                        dev_kfree_skb(nskb);
2062        return ret;
2063}
2064
2065static int
2066isdn_add_channels(isdn_driver_t *d, int drvidx, int n, int adding)
2067{
2068        int j, k, m;
2069
2070        init_waitqueue_head(&d->st_waitq);
2071        if (d->flags & DRV_FLAG_RUNNING)
2072                return -1;
2073        if (n < 1) return 0;
2074
2075        m = (adding) ? d->channels + n : n;
2076
2077        if (dev->channels + n > ISDN_MAX_CHANNELS) {
2078                printk(KERN_WARNING "register_isdn: Max. %d channels supported\n",
2079                       ISDN_MAX_CHANNELS);
2080                return -1;
2081        }
2082
2083        if ((adding) && (d->rcverr))
2084                kfree(d->rcverr);
2085        if (!(d->rcverr = kzalloc(sizeof(int) * m, GFP_ATOMIC))) {
2086                printk(KERN_WARNING "register_isdn: Could not alloc rcverr\n");
2087                return -1;
2088        }
2089
2090        if ((adding) && (d->rcvcount))
2091                kfree(d->rcvcount);
2092        if (!(d->rcvcount = kzalloc(sizeof(int) * m, GFP_ATOMIC))) {
2093                printk(KERN_WARNING "register_isdn: Could not alloc rcvcount\n");
2094                if (!adding)
2095                        kfree(d->rcverr);
2096                return -1;
2097        }
2098
2099        if ((adding) && (d->rpqueue)) {
2100                for (j = 0; j < d->channels; j++)
2101                        skb_queue_purge(&d->rpqueue[j]);
2102                kfree(d->rpqueue);
2103        }
2104        if (!(d->rpqueue = kmalloc(sizeof(struct sk_buff_head) * m, GFP_ATOMIC))) {
2105                printk(KERN_WARNING "register_isdn: Could not alloc rpqueue\n");
2106                if (!adding) {
2107                        kfree(d->rcvcount);
2108                        kfree(d->rcverr);
2109                }
2110                return -1; 
2111        }
2112        for (j = 0; j < m; j++) {
2113                skb_queue_head_init(&d->rpqueue[j]);
2114        }
2115
2116        if ((adding) && (d->rcv_waitq))
2117                kfree(d->rcv_waitq);
2118        d->rcv_waitq = kmalloc(sizeof(wait_queue_head_t) * 2 * m, GFP_ATOMIC);
2119        if (!d->rcv_waitq) {
2120                printk(KERN_WARNING "register_isdn: Could not alloc rcv_waitq\n");
2121                if (!adding) {
2122                        kfree(d->rpqueue);
2123                        kfree(d->rcvcount);
2124                        kfree(d->rcverr);
2125                }
2126                return -1;
2127        }
2128        d->snd_waitq = d->rcv_waitq + m;
2129        for (j = 0; j < m; j++) {
2130                init_waitqueue_head(&d->rcv_waitq[j]);
2131                init_waitqueue_head(&d->snd_waitq[j]);
2132        }
2133
2134        dev->channels += n;
2135        for (j = d->channels; j < m; j++)
2136                for (k = 0; k < ISDN_MAX_CHANNELS; k++)
2137                        if (dev->chanmap[k] < 0) {
2138                                dev->chanmap[k] = j;
2139                                dev->drvmap[k] = drvidx;
2140                                break;
2141                        }
2142        d->channels = m;
2143        return 0;
2144}
2145
2146/*
2147 * Low-level-driver registration
2148 */
2149
2150static void
2151set_global_features(void)
2152{
2153        int drvidx;
2154
2155        dev->global_features = 0;
2156        for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++) {
2157                if (!dev->drv[drvidx])
2158                        continue;
2159                if (dev->drv[drvidx]->interface)
2160                        dev->global_features |= dev->drv[drvidx]->interface->features;
2161        }
2162}
2163
2164#ifdef CONFIG_ISDN_DIVERSION
2165
2166static char *map_drvname(int di)
2167{
2168  if ((di < 0) || (di >= ISDN_MAX_DRIVERS)) 
2169    return(NULL);
2170  return(dev->drvid[di]); /* driver name */
2171} /* map_drvname */
2172
2173static int map_namedrv(char *id)
2174{  int i;
2175
2176   for (i = 0; i < ISDN_MAX_DRIVERS; i++)
2177    { if (!strcmp(dev->drvid[i],id)) 
2178        return(i);
2179    }
2180   return(-1);
2181} /* map_namedrv */
2182
2183int DIVERT_REG_NAME(isdn_divert_if *i_div)
2184{
2185  if (i_div->if_magic != DIVERT_IF_MAGIC) 
2186    return(DIVERT_VER_ERR);
2187  switch (i_div->cmd)
2188    {
2189      case DIVERT_CMD_REL:
2190        if (divert_if != i_div) 
2191          return(DIVERT_REL_ERR);
2192        divert_if = NULL; /* free interface */
2193        return(DIVERT_NO_ERR);
2194
2195      case DIVERT_CMD_REG:
2196        if (divert_if) 
2197          return(DIVERT_REG_ERR);
2198        i_div->ll_cmd = isdn_command; /* set command function */
2199        i_div->drv_to_name = map_drvname; 
2200        i_div->name_to_drv = map_namedrv; 
2201        divert_if = i_div; /* remember interface */
2202        return(DIVERT_NO_ERR);
2203
2204      default:
2205        return(DIVERT_CMD_ERR);   
2206    }
2207} /* DIVERT_REG_NAME */
2208
2209EXPORT_SYMBOL(DIVERT_REG_NAME);
2210
2211#endif /* CONFIG_ISDN_DIVERSION */
2212
2213
2214EXPORT_SYMBOL(register_isdn);
2215#ifdef CONFIG_ISDN_PPP
2216EXPORT_SYMBOL(isdn_ppp_register_compressor);
2217EXPORT_SYMBOL(isdn_ppp_unregister_compressor);
2218#endif
2219
2220int
2221register_isdn(isdn_if * i)
2222{
2223        isdn_driver_t *d;
2224        int j;
2225        ulong flags;
2226        int drvidx;
2227
2228        if (dev->drivers >= ISDN_MAX_DRIVERS) {
2229                printk(KERN_WARNING "register_isdn: Max. %d drivers supported\n",
2230                       ISDN_MAX_DRIVERS);
2231                return 0;
2232        }
2233        if (!i->writebuf_skb) {
2234                printk(KERN_WARNING "register_isdn: No write routine given.\n");
2235                return 0;
2236        }
2237        if (!(d = kzalloc(sizeof(isdn_driver_t), GFP_KERNEL))) {
2238                printk(KERN_WARNING "register_isdn: Could not alloc driver-struct\n");
2239                return 0;
2240        }
2241
2242        d->maxbufsize = i->maxbufsize;
2243        d->pktcount = 0;
2244        d->stavail = 0;
2245        d->flags = DRV_FLAG_LOADED;
2246        d->online = 0;
2247        d->interface = i;
2248        d->channels = 0;
2249        spin_lock_irqsave(&dev->lock, flags);
2250        for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++)
2251                if (!dev->drv[drvidx])
2252                        break;
2253        if (isdn_add_channels(d, drvidx, i->channels, 0)) {
2254                spin_unlock_irqrestore(&dev->lock, flags);
2255                kfree(d);
2256                return 0;
2257        }
2258        i->channels = drvidx;
2259        i->rcvcallb_skb = isdn_receive_skb_callback;
2260        i->statcallb = isdn_status_callback;
2261        if (!strlen(i->id))
2262                sprintf(i->id, "line%d", drvidx);
2263        for (j = 0; j < drvidx; j++)
2264                if (!strcmp(i->id, dev->drvid[j]))
2265                        sprintf(i->id, "line%d", drvidx);
2266        dev->drv[drvidx] = d;
2267        strcpy(dev->drvid[drvidx], i->id);
2268        isdn_info_update();
2269        dev->drivers++;
2270        set_global_features();
2271        spin_unlock_irqrestore(&dev->lock, flags);
2272        return 1;
2273}
2274
2275/*
2276 *****************************************************************************
2277 * And now the modules code.
2278 *****************************************************************************
2279 */
2280
2281static char *
2282isdn_getrev(const char *revision)
2283{
2284        char *rev;
2285        char *p;
2286
2287        if ((p = strchr(revision, ':'))) {
2288                rev = p + 2;
2289                p = strchr(rev, '$');
2290                *--p = 0;
2291        } else
2292                rev = "???";
2293        return rev;
2294}
2295
2296/*
2297 * Allocate and initialize all data, register modem-devices
2298 */
2299static int __init isdn_init(void)
2300{
2301        int i;
2302        char tmprev[50];
2303
2304        if (!(dev = vmalloc(sizeof(isdn_dev)))) {
2305                printk(KERN_WARNING "isdn: Could not allocate device-struct.\n");
2306                return -EIO;
2307        }
2308        memset((char *) dev, 0, sizeof(isdn_dev));
2309        init_timer(&dev->timer);
2310        dev->timer.function = isdn_timer_funct;
2311        spin_lock_init(&dev->lock);
2312        spin_lock_init(&dev->timerlock);
2313#ifdef MODULE
2314        dev->owner = THIS_MODULE;
2315#endif
2316        mutex_init(&dev->mtx);
2317        init_waitqueue_head(&dev->info_waitq);
2318        for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
2319                dev->drvmap[i] = -1;
2320                dev->chanmap[i] = -1;
2321                dev->m_idx[i] = -1;
2322                strcpy(dev->num[i], "???");
2323                init_waitqueue_head(&dev->mdm.info[i].open_wait);
2324                init_waitqueue_head(&dev->mdm.info[i].close_wait);
2325        }
2326        if (register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops)) {
2327                printk(KERN_WARNING "isdn: Could not register control devices\n");
2328                vfree(dev);
2329                return -EIO;
2330        }
2331        if ((isdn_tty_modem_init()) < 0) {
2332                printk(KERN_WARNING "isdn: Could not register tty devices\n");
2333                vfree(dev);
2334                unregister_chrdev(ISDN_MAJOR, "isdn");
2335                return -EIO;
2336        }
2337#ifdef CONFIG_ISDN_PPP
2338        if (isdn_ppp_init() < 0) {
2339                printk(KERN_WARNING "isdn: Could not create PPP-device-structs\n");
2340                isdn_tty_exit();
2341                unregister_chrdev(ISDN_MAJOR, "isdn");
2342                vfree(dev);
2343                return -EIO;
2344        }
2345#endif                          /* CONFIG_ISDN_PPP */
2346
2347        strcpy(tmprev, isdn_revision);
2348        printk(KERN_NOTICE "ISDN subsystem Rev: %s/", isdn_getrev(tmprev));
2349        strcpy(tmprev, isdn_tty_revision);
2350        printk("%s/", isdn_getrev(tmprev));
2351        strcpy(tmprev, isdn_net_revision);
2352        printk("%s/", isdn_getrev(tmprev));
2353        strcpy(tmprev, isdn_ppp_revision);
2354        printk("%s/", isdn_getrev(tmprev));
2355        strcpy(tmprev, isdn_audio_revision);
2356        printk("%s/", isdn_getrev(tmprev));
2357        strcpy(tmprev, isdn_v110_revision);
2358        printk("%s", isdn_getrev(tmprev));
2359
2360#ifdef MODULE
2361        printk(" loaded\n");
2362#else
2363        printk("\n");
2364#endif
2365        isdn_info_update();
2366        return 0;
2367}
2368
2369/*
2370 * Unload module
2371 */
2372static void __exit isdn_exit(void)
2373{
2374#ifdef CONFIG_ISDN_PPP
2375        isdn_ppp_cleanup();
2376#endif
2377        if (isdn_net_rmall() < 0) {
2378                printk(KERN_WARNING "isdn: net-device busy, remove cancelled\n");
2379                return;
2380        }
2381        isdn_tty_exit();
2382        unregister_chrdev(ISDN_MAJOR, "isdn");
2383        del_timer(&dev->timer);
2384        /* call vfree with interrupts enabled, else it will hang */
2385        vfree(dev);
2386        printk(KERN_NOTICE "ISDN-subsystem unloaded\n");
2387}
2388
2389module_init(isdn_init);
2390module_exit(isdn_exit);
2391