+++ /dev/null
-$Id: INTERFACE,v 1.15.8.2 2001/03/13 16:17:07 kai Exp $
-
-Description of the Interface between Linklevel and Hardwarelevel
-  of isdn4linux:
-
-
-  The Communication between Linklevel (LL) and Hardwarelevel (HL)
-  is based on the struct isdn_if (defined in isdnif.h).
-
-  An HL-driver can register itself at LL by calling the function
-  register_isdn() with a pointer to that struct. Prior to that, it has
-  to preset some of the fields of isdn_if. The LL sets the rest of
-  the fields. All further communication is done via callbacks using
-  the function-pointers defined in isdn_if.
-
-  Changes/Version numbering:
-
-  During development of the ISDN subsystem, several changes have been
-  made to the interface. Before it went into kernel, the package
-  had a unique version number. The last version, distributed separately
-  was 0.7.4. When the subsystem went into kernel, every functional unit
-  got a separate version number. These numbers are shown at initialization,
-  separated by slashes:
-
-     c.c/t.t/n.n/p.p/a.a/v.v
-
-  where
-
-   c.c is the revision of the common code.
-   t.t is the revision of the tty related code.
-   n.n is the revision of the network related code.
-   p.p is the revision of the ppp related code.
-   a.a is the revision of the audio related code.
-   v.v is the revision of the V.110 related code.
-
-  Changes in this document are marked with '***CHANGEx' where x representing
-  the version number. If that number starts with 0, it refers to the old,
-  separately distributed package. If it starts with one of the letters
-  above, it refers to the revision of the corresponding module. 
-  ***CHANGEIx refers to the revision number of the isdnif.h  
-
-1. Description of the fields of isdn_if:
-
-  int channels;
-
-    This field has to be set by the HL-driver to the number of channels
-    supported prior to calling register_isdn(). Upon return of the call,
-    the LL puts an id there, which has to be used by the HL-driver when
-    invoking the other callbacks.
-
-  int maxbufsize;
-
-    ***CHANGE0.6: New since this version.
-
-    Also to be preset by the HL-driver. With this value the HL-driver
-    tells the LL the maximum size of a data-packet it will accept. 
-
-  unsigned long features;
-
-    To be preset by the HL-driver. Using this field, the HL-driver
-    announces the features supported. At the moment this is limited to
-    report the supported layer2 and layer3-protocols. For setting this
-    field the constants ISDN_FEATURE..., declared in isdnif.h have to be
-    used.
-
-    ***CHANGE0.7.1: The line type (1TR6, EDSS1) has to be set.
-
-  unsigned short hl_hdrlen;
-
-    ***CHANGE0.7.4: New field.
-
-    To be preset by the HL-driver, if it supports sk_buff's. The driver
-    should put here the amount of additional space needed in sk_buff's for
-    its internal purposes. Drivers not supporting sk_buff's should 
-    initialize this field to 0.
-
-  void (*rcvcallb_skb)(int, int, struct sk_buff *)
-
-    ***CHANGE0.7.4: New field.
-
-    This field will be set by LL. The HL-driver delivers received data-
-    packets by calling this function. Upon calling, the HL-driver must
-    already have its private data pulled off the head of the sk_buff.
-
-    Parameter:
-      int              driver-Id
-      int              Channel-number locally to the driver. (starting with 0)
-      struct sk_buff * Pointer to sk_buff, containing received data.
-
-  int (*statcallb)(isdn_ctrl*);
-
-    This field will be set by LL. This function has to be called by the
-    HL-driver for signaling status-changes or other events to the LL.
-
-    Parameter:
-      isdn_ctrl*
-
-      The struct isdn_ctrl also defined in isdn_if. The exact meanings of its
-      fields are described together with the descriptions of the possible
-      events. Here is only a short description of the fields:
-
-        driver  = driver Id.
-        command = event-type. (one of the constants ISDN_STAT_...)
-        arg     = depends on event-type.
-        num     = depends on event-type.
-
-    Returnvalue:
-      0 on success, else -1
-
-  int (*command)(isdn_ctrl*);
-
-    This field has to be preset by the HL-driver. It points to a function,
-    to be called by LL to perform functions like dialing, B-channel
-    setup, etc. The exact meaning of the parameters is described with the
-    descriptions of the possible commands.
-
-    Parameter:
-      isdn_ctrl*
-        driver  = driver-Id
-        command = command to perform. (one of the constants ISDN_CMD_...)
-        arg     = depends on command.
-        num     = depends on command.
-    
-    Returnvalue:
-      >=0 on success, else error-code (-ENODEV etc.)
-
-  int (*writebuf_skb)(int, int, int, struct sk_buff *)
-
-    ***CHANGE0.7.4: New field.
-    ***CHANGEI.1.21: New field.
-
-    This field has to be preset by the HL-driver. The given function will
-    be called by the LL for delivering data to be send via B-Channel.
-
- 
-    Parameter:
-      int              driver-Id ***CHANGE0.7.4: New parameter.
-      int              channel-number locally to the HL-driver. (starts with 0)
-      int             ack ***ChangeI1.21: New parameter
-                      If this is !0, the driver has to signal the delivery
-                      by sending an ISDN_STAT_BSENT. If this is 0, the driver
-                      MUST NOT send an ISDN_STAT_BSENT.
-      struct sk_buff * Pointer to sk_buff containing data to be send via
-                       B-channel.
-
-    Returnvalue:
-      Length of data accepted on success, else error-code (-EINVAL on
-      oversized packets etc.)
-
-  int (*writecmd)(u_char*, int, int, int, int);
-
-    This field has to be preset by the HL-driver. The given function will be
-    called to perform write-requests on /dev/isdnctrl (i.e. sending commands
-    to the card) The data-format is hardware-specific. This function is
-    intended for debugging only. It is not necessary for normal operation
-    and never will be called by the tty-emulation- or network-code. If
-    this function is not supported, the driver has to set NULL here.
-
-    Parameter:
-      u_char* pointer to data.
-      int     length of data.
-      int     flag: 0 = call from within kernel-space. (HL-driver must use
-                        memcpy, may NOT use schedule())
-                    1 = call from user-space. (HL-driver must use
-                        memcpy_fromfs, use of schedule() allowed)
-      int     driver-Id.
-      int     channel-number locally to the HL-driver. (starts with 0)
-
-***CHANGEI1.14: The driver-Id and channel-number are new since this revision.
-
-    Returnvalue:
-      Length of data accepted on success, else error-code (-EINVAL etc.)
-
-  int (*readstat)(u_char*, int, int, int, int);
-
-    This field has to be preset by the HL-driver. The given function will be
-    called to perform read-requests on /dev/isdnctrl (i.e. reading replies
-    from the card) The data-format is hardware-specific. This function is
-    intended for debugging only. It is not necessary for normal operation
-    and never will be called by the tty-emulation- or network-code. If
-    this function is not supported, the driver has to set NULL here.
-
-    Parameter:
-      u_char* pointer to data.
-      int     length of data.
-      int     flag: 0 = call from within kernel-space. (HL-driver must use
-                        memcpy, may NOT use schedule())
-                    1 = call from user-space. (HL-driver must use
-                        memcpy_fromfs, use of schedule() allowed)
-      int     driver-Id.
-      int     channel-number locally to the HL-driver. (starts with 0)
-
-***CHANGEI1.14: The driver-Id and channel-number are new since this revision.
-
-    Returnvalue:
-      Length of data on success, else error-code (-EINVAL etc.)
-
-  char id[20];
-       ***CHANGE0.7: New since this version.
-
-   This string has to be preset by the HL-driver. Its purpose is for
-   identification of the driver by the user. Eg.: it is shown in the
-   status-info of /dev/isdninfo. Furthermore it is used as Id for binding
-   net-interfaces to a specific channel. If a string of length zero is
-   given, upon return, isdn4linux will replace it by a generic name. (line0,
-   line1 etc.) It is recommended to make this string configurable during
-   module-load-time. (copy a global variable to this string.) For doing that,
-   modules 1.2.8 or newer are necessary.
-
-2. Description of the commands, a HL-driver has to support:
-
-   All commands will be performed by calling the function command() described
-   above from within the LL. The field command of the struct-parameter will
-   contain the desired command, the field driver is always set to the
-   appropriate driver-Id.
-
-   Until now, the following commands are defined:
-
-***CHANGEI1.34: The parameter "num" has been replaced by a union "parm" containing
-                the old "num" and a new setup_type struct used for ISDN_CMD_DIAL
-                and ISDN_STAT_ICALL callback.
-
-   ISDN_CMD_IOCTL:
-
-     This command is intended for performing ioctl-calls for configuring
-     hardware or similar purposes (setting port-addresses, loading firmware
-     etc.) For this purpose, in the LL all ioctl-calls with an argument
-     >= IIOCDRVCTL (0x100) will be handed transparently to this
-     function after subtracting 0x100 and placing the result in arg.
-     Example:
-       If a userlevel-program calls ioctl(0x101,...) the function gets
-       called with the field command set to 1.
-
-     Parameter:
-       driver   = driver-Id.
-       command  = ISDN_CMD_IOCTL
-       arg      = Original ioctl-cmd - IIOCDRVCTL
-       parm.num = first bytes filled with (unsigned long)arg
-   
-     Returnvalue:
-       Depending on driver.
-
-  
-  ISDN_CMD_DIAL:
-
-    This command is used to tell the HL-driver it should dial a given
-    number.
-
-    Parameter:
-      driver      = driver-Id.
-      command     = ISDN_CMD_DIAL
-      arg         = channel-number locally to the driver. (starting with 0)
-      
-      parm.setup.phone  = An ASCII-String containing the number to dial.
-      parm.setup.eazmsn = An ASCII-Sting containing the own EAZ or MSN.
-      parm.setup.si1    = The Service-Indicator.
-      parm.setup.si2    = Additional Service-Indicator.
-
-                    If the Line has been designed as SPV (a special german
-                    feature, meaning semi-leased-line) the phone has to
-                    start with an "S".
-      ***CHANGE0.6: In previous versions the EAZ has been given in the
-                    highbyte of arg.
-    ***CHANGE0.7.1: New since this version: ServiceIndicator and AddInfo.
-
-  ISDN_CMD_ACCEPTD:
-
-    With this command, the HL-driver is told to accept a D-Channel-setup.
-    (Response to an incoming call)
-
-    Parameter:
-      driver      = driver-Id.
-      command     = ISDN_CMD_ACCEPTD
-      arg         = channel-number locally to the driver. (starting with 0)
-      parm        = unused.
-
-  ISDN_CMD_ACCEPTB:
-
-    With this command, the HL-driver is told to perform a B-Channel-setup.
-    (after establishing D-Channel-Connection)
-
-    Parameter:
-      driver      = driver-Id.
-      command     = ISDN_CMD_ACCEPTB
-      arg         = channel-number locally to the driver. (starting with 0)
-      parm        = unused.
-
-  ISDN_CMD_HANGUP:
-
-    With this command, the HL-driver is told to hangup (B-Channel if
-    established first, then D-Channel). This command is also used for
-    actively rejecting an incoming call.
-
-    Parameter:
-      driver      = driver-Id.
-      command     = ISDN_CMD_HANGUP
-      arg         = channel-number locally to the driver. (starting with 0)
-      parm        = unused.
-
-  ISDN_CMD_CLREAZ:
-
-    With this command, the HL-driver is told not to signal incoming
-    calls to the LL.
-
-    Parameter:
-      driver      = driver-Id.
-      command     = ISDN_CMD_CLREAZ
-      arg         = channel-number locally to the driver. (starting with 0)
-      parm        = unused.
-
-  ISDN_CMD_SETEAZ:
-
-    With this command, the HL-driver is told to signal incoming calls for
-    the given EAZs/MSNs to the LL.
-
-    Parameter:
-      driver      = driver-Id.
-      command     = ISDN_CMD_SETEAZ
-      arg         = channel-number locally to the driver. (starting with 0)
-      parm.num    = ASCII-String, containing the desired EAZ's/MSN's
-                    (comma-separated). If an empty String is given, the
-                    HL-driver should respond to ALL incoming calls,
-                    regardless of the destination-address.
-      ***CHANGE0.6: New since this version the "empty-string"-feature.
-
-  ISDN_CMD_GETEAZ: (currently unused)
-
-    With this command, the HL-driver is told to report the current setting
-    given with ISDN_CMD_SETEAZ.
-
-    Parameter:
-      driver      = driver-Id.
-      command     = ISDN_CMD_GETEAZ
-      arg         = channel-number locally to the driver. (starting with 0)
-      parm.num    = ASCII-String, containing the current EAZ's/MSN's
-
-  ISDN_CMD_SETSIL: (currently unused)
-
-    With this command, the HL-driver is told to signal only incoming
-    calls with the given Service-Indicators.
-
-    Parameter:
-      driver      = driver-Id.
-      command     = ISDN_CMD_SETSIL
-      arg         = channel-number locally to the driver. (starting with 0)
-      parm.num    = ASCII-String, containing the desired Service-Indicators.
-
-  ISDN_CMD_GETSIL: (currently unused)
-
-    With this command, the HL-driver is told to return the current
-    Service-Indicators it will respond to.
-
-    Parameter:
-      driver      = driver-Id.
-      command     = ISDN_CMD_SETSIL
-      arg         = channel-number locally to the driver. (starting with 0)
-      parm.num    = ASCII-String, containing the current Service-Indicators.
-
-  ISDN_CMD_SETL2:
-
-    With this command, the HL-driver is told to select the given Layer-2-
-    protocol. This command is issued by the LL prior to ISDN_CMD_DIAL or
-    ISDN_CMD_ACCEPTD.
-
-
-    Parameter:
-      driver      = driver-Id.
-      command     = ISDN_CMD_SETL2
-      arg         = channel-number locally to the driver. (starting with 0)
-                    logical or'ed with (protocol-Id << 8)
-                    protocol-Id is one of the constants ISDN_PROTO_L2...
-      parm        = unused.
-
-  ISDN_CMD_GETL2: (currently unused)
-
-    With this command, the HL-driver is told to return the current
-    setting of the Layer-2-protocol.
-
-    Parameter:
-      driver      = driver-Id.
-      command     = ISDN_CMD_GETL2
-      arg         = channel-number locally to the driver. (starting with 0)
-      parm        = unused.
-    Returnvalue:
-      current protocol-Id (one of the constants ISDN_L2_PROTO)
-
-  ISDN_CMD_SETL3:
-
-    With this command, the HL-driver is told to select the given Layer-3-
-    protocol. This command is issued by the LL prior to ISDN_CMD_DIAL or
-    ISDN_CMD_ACCEPTD.
-
-
-    Parameter:
-      driver      = driver-Id.
-      command     = ISDN_CMD_SETL3
-      arg         = channel-number locally to the driver. (starting with 0)
-                    logical or'ed with (protocol-Id << 8)
-                    protocol-Id is one of the constants ISDN_PROTO_L3...
-      parm.fax    = Pointer to T30_s fax struct. (fax usage only)
-
-  ISDN_CMD_GETL2: (currently unused)
-
-    With this command, the HL-driver is told to return the current
-    setting of the Layer-3-protocol.
-
-    Parameter:
-      driver      = driver-Id.
-      command     = ISDN_CMD_GETL3
-      arg         = channel-number locally to the driver. (starting with 0)
-      parm        = unused.
-    Returnvalue:
-      current protocol-Id (one of the constants ISDN_L3_PROTO)
-
-  ISDN_CMD_PROCEED: 
-
-    With this command, the HL-driver is told to proceed with a incoming call.
-
-    Parameter:
-      driver      = driver-Id.
-      command     = ISDN_CMD_PROCEED
-      arg         = channel-number locally to the driver. (starting with 0)
-      setup.eazmsn= empty string or string send as uus1 in DSS1 with 
-                    PROCEED message
-
-  ISDN_CMD_ALERT: 
-
-    With this command, the HL-driver is told to alert a proceeding call.
-
-    Parameter:
-      driver      = driver-Id.
-      command     = ISDN_CMD_ALERT
-      arg         = channel-number locally to the driver. (starting with 0)
-      setup.eazmsn= empty string or string send as uus1 in DSS1 with 
-                    ALERT message
-
-  ISDN_CMD_REDIR: 
-
-    With this command, the HL-driver is told to redirect a call in proceeding
-    or alerting state.  
-
-    Parameter:
-      driver      = driver-Id.
-      command     = ISDN_CMD_REDIR
-      arg         = channel-number locally to the driver. (starting with 0)
-      setup.eazmsn= empty string or string send as uus1 in DSS1 protocol
-      setup.screen= screening indicator
-      setup.phone = redirected to party number
-
-  ISDN_CMD_PROT_IO:
-
-    With this call, the LL-driver invokes protocol specific features through
-    the LL.
-    The call is not implicitely bound to a connection.
-
-    Parameter:
-      driver      = driver-Id
-      command     = ISDN_CMD_PROT_IO
-      arg         = The lower 8 Bits define the addressed protocol as defined
-                    in ISDN_PTYPE..., the upper bits are used to differentiate
-                    the protocol specific CMD.  
-      
-      para        = protocol and function specific. See isdnif.h for detail.
-
-
-  ISDN_CMD_FAXCMD:
-
-    With this command the HL-driver receives a fax sub-command.
-    For details refer to INTERFACE.fax
-
-    Parameter:
-      driver      = driver-Id.
-      command     = ISDN_CMD_FAXCMD
-      arg         = channel-number locally to the driver. (starting with 0)
-      parm        = unused.
-
-
-3. Description of the events to be signaled by the HL-driver to the LL.
-
-  All status-changes are signaled via calling the previously described
-  function statcallb(). The field command of the struct isdn_cmd has
-  to be set by the HL-driver with the appropriate Status-Id (event-number).
-  The field arg has to be set to the channel-number (locally to the driver,
-  starting with 0) to which this event applies. (Exception: STAVAIL-event)
-
-  Until now, the following Status-Ids are defined:
-
-  ISDN_STAT_AVAIL:
-
-    With this call, the HL-driver signals the availability of new data
-    for readstat(). Used only for debugging-purposes, see description
-    of readstat().
-
-    Parameter:
-      driver      = driver-Id
-      command     = ISDN_STAT_STAVAIL
-      arg         = length of available data.
-      parm        = unused.
-
-  ISDN_STAT_ICALL:
-  ISDN_STAT_ICALLW:
-
-    With this call, the HL-driver signals an incoming call to the LL.
-    If ICALLW is signalled the incoming call is a waiting call without
-    a available B-chan.
-
-    Parameter:
-      driver            = driver-Id
-      command           = ISDN_STAT_ICALL
-      arg               = channel-number, locally to the driver. (starting with 0)
-      para.setup.phone  = Callernumber.
-      para.setup.eazmsn = CalledNumber.
-      para.setup.si1    = Service Indicator.
-      para.setup.si2    = Additional Service Indicator.
-      para.setup.plan   = octet 3 from Calling party number Information Element.
-      para.setup.screen = octet 3a from Calling party number Information Element.
-
-    Return:
-      0           = No device matching this call.
-      1           = At least one device matching this call (RING on ttyI).
-                    HL-driver may send ALERTING on the D-channel in this case.
-      2           = Call will be rejected.
-      3           = Incoming called party number is currently incomplete.
-                    Additional digits are required. 
-                    Used for signalling with PtP connections.
-      4                  = Call will be held in a proceeding state 
-                    (HL driver sends PROCEEDING)
-                    Used when a user space prog needs time to interpret a call
-                   para.setup.eazmsn may be filled with an uus1 message of
-                   30 octets maximum. Empty string if no uus. 
-      5           = Call will be actively deflected to another party
-                    Only available in DSS1/EURO protocol
-                   para.setup.phone must be set to destination party number
-                   para.setup.eazmsn may be filled with an uus1 message of
-                   30 octets maximum. Empty string if no uus. 
-      -1          = An error happened. (Invalid parameters for example.)
-  The keypad support now is included in the dial command.              
-
-
-  ISDN_STAT_RUN:
-
-    With this call, the HL-driver signals availability of the ISDN-card.
-    (after initializing, loading firmware)
-
-    Parameter:
-      driver      = driver-Id
-      command     = ISDN_STAT_RUN
-      arg         = unused.
-      parm        = unused.
-
-  ISDN_STAT_STOP:
-
-    With this call, the HL-driver signals unavailability of the ISDN-card.
-    (before unloading, while resetting/reconfiguring the card)
-
-    Parameter:
-      driver      = driver-Id
-      command     = ISDN_STAT_STOP
-      arg         = unused.
-      parm        = unused.
-
-  ISDN_STAT_DCONN:
-
-   With this call, the HL-driver signals the successful establishment of
-   a D-Channel-connection. (Response to ISDN_CMD_ACCEPTD or ISDN_CMD_DIAL)
-
-    Parameter:
-      driver      = driver-Id
-      command     = ISDN_STAT_DCONN
-      arg         = channel-number, locally to the driver. (starting with 0)
-      parm        = unused.
-
-  ISDN_STAT_BCONN:
-
-   With this call, the HL-driver signals the successful establishment of
-   a B-Channel-connection. (Response to ISDN_CMD_ACCEPTB or because the
-   remote-station has initiated establishment)
-
-   The HL driver should call this when the logical l2/l3 protocol 
-   connection on top of the physical B-channel is established.
-
-    Parameter:
-      driver      = driver-Id
-      command     = ISDN_STAT_BCONN
-      arg         = channel-number, locally to the driver. (starting with 0)
-      parm.num    = ASCII-String, containing type of connection (for analog
-                   modem only). This will be appended to the CONNECT message
-                   e.g. 14400/V.32bis
-
-  ISDN_STAT_DHUP:
-
-   With this call, the HL-driver signals the shutdown of a
-   D-Channel-connection. This could be a response to a prior ISDN_CMD_HANGUP,
-   or caused by a remote-hangup or if the remote-station has actively
-   rejected a call.
-
-    Parameter:
-      driver      = driver-Id
-      command     = ISDN_STAT_DHUP
-      arg         = channel-number, locally to the driver. (starting with 0)
-      parm        = unused.
-
-  ISDN_STAT_BHUP:
-
-   With this call, the HL-driver signals the shutdown of a
-   B-Channel-connection. This could be a response to a prior ISDN_CMD_HANGUP,
-   or caused by a remote-hangup.
-
-   The HL driver should call this as soon as the logical l2/l3 protocol 
-   connection on top of the physical B-channel is released.
-
-    Parameter:
-      driver      = driver-Id
-      command     = ISDN_STAT_BHUP
-      arg         = channel-number, locally to the driver. (starting with 0)
-      parm        = unused.
-
-  ISDN_STAT_CINF:
-
-   With this call, the HL-driver delivers charge-unit information to the
-   LL.
-
-    Parameter:
-      driver      = driver-Id
-      command     = ISDN_STAT_CINF
-      arg         = channel-number, locally to the driver. (starting with 0)
-      parm.num    = ASCII string containing charge-units (digits only).
-
-  ISDN_STAT_LOAD: (currently unused)
-
-  ISDN_STAT_UNLOAD:
-
-   With this call, the HL-driver signals that it will be unloaded now. This
-   tells the LL to release all corresponding data-structures.
-
-    Parameter:
-      driver      = driver-Id
-      command     = ISDN_STAT_UNLOAD
-      arg         = unused.
-      parm        = unused.
-
-  ISDN_STAT_BSENT:
-
-    With this call the HL-driver signals the delivery of a data-packet.
-    This callback is used by the network-interfaces only, tty-Emulation
-    does not need this call.
-
-    Parameter:
-      driver      = driver-Id
-      command     = ISDN_STAT_BSENT
-      arg         = channel-number, locally to the driver. (starting with 0)
-      parm.length = ***CHANGEI.1.21: New field.
-                   the driver has to set this to the original length
-                   of the skb at the time of receiving it from the linklevel.
-
-  ISDN_STAT_NODCH:
-
-    With this call, the driver has to respond to a prior ISDN_CMD_DIAL, if
-    no D-Channel is available.
-
-    Parameter:
-      driver      = driver-Id
-      command     = ISDN_STAT_NODCH
-      arg         = channel-number, locally to the driver. (starting with 0)
-      parm        = unused.
-
-  ISDN_STAT_ADDCH: 
-
-    This call is for HL-drivers, which are unable to check card-type
-    or numbers of supported channels before they have loaded any firmware
-    using ioctl. Those HL-driver simply set the channel-parameter to a
-    minimum channel-number when registering, and later if they know
-    the real amount, perform this call, allocating additional channels.
-
-    Parameter:
-      driver      = driver-Id
-      command     = ISDN_STAT_ADDCH
-      arg         = number of channels to be added.
-      parm        = unused.
-
-  ISDN_STAT_CAUSE:
-
-    With this call, the HL-driver delivers CAUSE-messages to the LL.
-    Currently the LL does not use this messages. Their contents is simply
-    logged via kernel-messages. Therefore, currently the format of the
-    messages is completely free. However they should be printable.
-
-    Parameter:
-      driver      = driver-Id
-      command     = ISDN_STAT_NODCH
-      arg         = channel-number, locally to the driver. (starting with 0)
-      parm.num    = ASCII string containing CAUSE-message.
-
-  ISDN_STAT_DISPLAY:
-
-    With this call, the HL-driver delivers DISPLAY-messages to the LL.
-    Currently the LL does not use this messages. 
-
-    Parameter:
-      driver      = driver-Id
-      command     = ISDN_STAT_DISPLAY
-      arg         = channel-number, locally to the driver. (starting with 0)
-      para.display= string containing DISPLAY-message.
-
-  ISDN_STAT_PROT:
-
-    With this call, the HL-driver delivers protocol specific infos to the LL.
-    The call is not implicitely bound to a connection.
-
-    Parameter:
-      driver      = driver-Id
-      command     = ISDN_STAT_PROT
-      arg         = The lower 8 Bits define the addressed protocol as defined
-                    in ISDN_PTYPE..., the upper bits are used to differentiate
-                    the protocol specific STAT.  
-      
-      para        = protocol and function specific. See isdnif.h for detail.
-
-  ISDN_STAT_DISCH:
-
-    With this call, the HL-driver signals the LL to disable or enable the
-    use of supplied channel and driver.
-    The call may be used to reduce the available number of B-channels after
-    loading the driver. The LL has to ignore a disabled channel when searching
-    for free channels. The HL driver itself never delivers STAT callbacks for
-    disabled channels.             
-    The LL returns a nonzero code if the operation was not successful or the
-    selected channel is actually regarded as busy.
-
-    Parameter:
-      driver      = driver-Id
-      command     = ISDN_STAT_DISCH
-      arg         = channel-number, locally to the driver. (starting with 0)
-      parm.num[0] = 0 if channel shall be disabled, else enabled.
-
-  ISDN_STAT_L1ERR:
-
-    ***CHANGEI1.21 new status message.
-    A signal can be sent to the linklevel if an Layer1-error results in
-    packet-loss on receive or send. The field errcode of the cmd.parm
-    union describes the error more precisely.
-
-    Parameter:
-      driver      = driver-Id
-      command     = ISDN_STAT_L1ERR
-      arg         = channel-number, locally to the driver. (starting with 0)
-      parm.errcode= ISDN_STAT_L1ERR_SEND:     Packet lost while sending.
-                   ISDN_STAT_L1ERR_RECV:     Packet lost while receiving.
-  ISDN_STAT_FAXIND:
-
-    With this call the HL-driver signals a fax sub-command to the LL.
-    For details refer to INTERFACE.fax
-
-    Parameter:
-      driver      = driver-Id.
-      command     = ISDN_STAT_FAXIND
-      arg         = channel-number, locally to the driver. (starting with 0)
-      parm        = unused.
-
 
+++ /dev/null
-$Id: INTERFACE.fax,v 1.2 2000/08/06 09:22:50 armin Exp $
-
-
-Description of the fax-subinterface between linklevel and hardwarelevel of 
-  isdn4linux. 
-
-  The communication between linklevel (LL) and hardwarelevel (HL) for fax
-  is based on the struct T30_s (defined in isdnif.h).
-  This struct is allocated in the LL.  
-  In order to use fax, the LL provides the pointer to this struct with the 
-  command ISDN_CMD_SETL3 (parm.fax). This pointer expires in case of hangup 
-  and when a new channel to a new connection is assigned. 
-
-
-Data handling:
-  In send-mode the HL-driver has to handle the <DLE> codes and the bit-order 
-  conversion by itself. 
-  In receive-mode the LL-driver takes care of the bit-order conversion
-  (specified by +FBOR)
-
-Structure T30_s description:
-
-  This structure stores the values (set by AT-commands), the remote-
-  capability-values and the command-codes between LL and HL.
-
-  If the HL-driver receives ISDN_CMD_FAXCMD, all needed information
-  is in this struct set by the LL.
-  To signal information to the LL, the HL-driver has to set the 
-  parameters and use ISDN_STAT_FAXIND.
-  (Please refer to INTERFACE)
-
-Structure T30_s:
-
-  All members are 8-bit unsigned (__u8)
-
-  -  resolution     
-  -  rate
-  -  width
-  -  length
-  -  compression
-  -  ecm
-  -  binary
-  -  scantime
-  -  id[]
-  Local faxmachine's parameters, set by +FDIS, +FDCS, +FLID, ...
-
-  -  r_resolution
-  -  r_rate
-  -  r_width
-  -  r_length
-  -  r_compression
-  -  r_ecm
-  -  r_binary
-  -  r_scantime
-  -  r_id[]
-  Remote faxmachine's parameters. To be set by HL-driver.
-
-  -  phase      
-  Defines the actual state of fax connection. Set by HL or LL
-  depending on progress and type of connection.
-  If the phase changes because of an AT command, the LL driver
-  changes this value. Otherwise the HL-driver takes care of it, but
-  only necessary on call establishment (from IDLE to PHASE_A).
-  (one of the constants ISDN_FAX_PHASE_[IDLE,A,B,C,D,E])
-
-  -  direction
-  Defines outgoing/send or incoming/receive connection.
-  (ISDN_TTY_FAX_CONN_[IN,OUT])
-
-  -  code
-  Commands from LL to HL; possible constants : 
-      ISDN_TTY_FAX_DR        signals +FDR command to HL
-
-      ISDN_TTY_FAX_DT        signals +FDT command to HL 
-
-      ISDN_TTY_FAX_ET        signals +FET command to HL
-
-
-  Other than that the "code" is set with the hangup-code value at
-  the end of connection for the +FHNG message.
-        
-  -  r_code 
-  Commands from HL to LL; possible constants :
-      ISDN_TTY_FAX_CFR       output of +FCFR message. 
-
-      ISDN_TTY_FAX_RID       output of remote ID set in r_id[]
-                             (+FCSI/+FTSI on send/receive)
-
-      ISDN_TTY_FAX_DCS       output of +FDCS and CONNECT message,
-                             switching to phase C.
-
-      ISDN_TTY_FAX_ET        signals end of data,
-                             switching to phase D.
-
-      ISDN_TTY_FAX_FCON      signals the established, outgoing connection,
-                             switching to phase B.
-
-      ISDN_TTY_FAX_FCON_I    signals the established, incoming connection,
-                             switching to phase B.
-
-      ISDN_TTY_FAX_DIS       output of +FDIS message and values.
-
-      ISDN_TTY_FAX_SENT      signals that all data has been sent 
-                             and <DLE><ETX> is acknowledged,
-                             OK message will be sent.
-
-      ISDN_TTY_FAX_PTS       signals a msg-confirmation (page sent successful),
-                             depending on fet value:
-                             0: output OK message (more pages follow)
-                             1: switching to phase B (next document)
-
-      ISDN_TTY_FAX_TRAIN_OK  output of +FDCS and OK message (for receive mode).
-
-      ISDN_TTY_FAX_EOP       signals end of data in receive mode,
-                             switching to phase D.
-
-      ISDN_TTY_FAX_HNG       output of the +FHNG and value set by code and
-                             OK message, switching to phase E.
-
-
-  -  badlin
-  Value of +FBADLIN  
-
-  -  badmul
-  Value of +FBADMUL
-
-  -  bor
-  Value of +FBOR
-
-  -  fet
-  Value of +FET command in send-mode.
-  Set by HL in receive-mode for +FET message.
-
-  -  pollid[]  
-  ID-string, set by +FCIG
-
-  -  cq
-  Value of +FCQ
-
-  -  cr
-  Value of +FCR
-
-  -  ctcrty
-  Value of +FCTCRTY
-
-  -  minsp
-  Value of +FMINSP
-
-  -  phcto
-  Value of +FPHCTO
-
-  -  rel
-  Value of +FREL
-
-  -  nbc
-  Value of +FNBC (0,1)
-  (+FNBC is not a known class 2 fax command, I added this to change the
-   automatic "best capabilities" connection in the eicon HL-driver)
-
-  
-Armin
-mac@melware.de
-
 
+++ /dev/null
-README for the ISDN-subsystem
-
-1. Preface
-
-  1.1 Introduction
-
-  This README describes how to set up and how to use the different parts
-  of the ISDN-subsystem.
-
-  For using the ISDN-subsystem, some additional userlevel programs are
-  necessary. Those programs and some contributed utilities are available
-  at
-
-   ftp.isdn4linux.de
-
-   /pub/isdn4linux/isdn4k-utils-<VersionNumber>.tar.gz
-
-
-  We also have set up a mailing-list:
-
-   The isdn4linux-project originates in Germany, and therefore by historical
-   reasons, the mailing-list's primary language is german. However mails
-   written in english have been welcome all the time.
-
-   to subscribe: write a email to majordomo@listserv.isdn4linux.de,
-   Subject irrelevant, in the message body:
-   subscribe isdn4linux <your_email_address>
-
-   To write to the mailing-list, write to isdn4linux@listserv.isdn4linux.de
-
-   This mailinglist is bidirectionally gated to the newsgroup
-
-     de.alt.comm.isdn4linux
-
-  There is also a well maintained FAQ in English available at
-     https://www.mhessler.de/i4lfaq/
-  It can be viewed online, or downloaded in sgml/text/html format.
-  The FAQ can also be viewed online at
-     https://www.isdn4linux.de/faq/i4lfaq.html
-  or downloaded from
-     ftp://ftp.isdn4linux.de/pub/isdn4linux/FAQ/
-
-  1.1 Technical details
-
-  In the following Text, the terms MSN and EAZ are used.
-
-  MSN is the abbreviation for (M)ultiple(S)ubscriber(N)umber, and applies
-  to Euro(EDSS1)-type lines. Usually it is simply the phone number.
-
-  EAZ is the abbreviation of (E)ndgeraete(A)uswahl(Z)iffer and
-  applies to German 1TR6-type lines. This is a one-digit string,
-  simply appended to the base phone number
-
-  The internal handling is nearly identical, so replace the appropriate
-  term to that one, which applies to your local ISDN-environment.
-
-  When the link-level-module isdn.o is loaded, it supports up to 16
-  low-level-modules with up to 64 channels. (The number 64 is arbitrarily
-  chosen and can be configured at compile-time --ISDN_MAX in isdn.h).
-  A low-level-driver can register itself through an interface (which is
-  defined in isdnif.h) and gets assigned a slot.
-  The following char-devices are made available for each channel:
-
-  A raw-control-device with the following functions:
-     write: raw D-channel-messages (format: depends on driver).
-     read:  raw D-channel-messages (format: depends on driver).
-     ioctl: depends on driver, i.e. for the ICN-driver, the base-address of
-            the ports and the shared memory on the card can be set and read
-            also the boot-code and the protocol software can be loaded into
-            the card.
-
-   O N L Y !!!  for debugging (no locking against other devices):
-   One raw-data-device with the following functions:
-     write: data to B-channel.
-     read:  data from B-channel.
-
-   In addition the following devices are made available:
-
-   128 tty-devices (64 cuix and 64 ttyIx) with integrated modem-emulator:
-   The functionality is almost the same as that of a serial device
-   (the line-discs are handled by the kernel), which lets you run
-   SLIP, CSLIP and asynchronous PPP through the devices. We have tested
-   Seyon, minicom, CSLIP (uri-dip) PPP, mgetty, XCept and Hylafax. 
-
-   The modem-emulation supports the following:
-           1.3.1 Commands:
-
-               ATA      Answer incoming call.
-               ATD<No.> Dial, the number may contain:
-                        [0-9] and [,#.*WPT-S]
-                        the latter are ignored until 'S'.
-                        The 'S' must precede the number, if
-                        the line is a SPV (German 1TR6).
-               ATE0     Echo off.
-               ATE1     Echo on (default).
-               ATH      Hang-up.
-               ATH1     Off hook (ignored).
-               ATH0     Hang-up.
-               ATI      Return "ISDN for Linux...".
-               ATI0        "
-               ATI1        "
-               ATI2     Report of last connection.
-               ATO      On line (data mode).
-               ATQ0     Enable result codes (default).
-               ATQ1     Disable result codes (default).
-               ATSx=y   Set register x to y.
-               ATSx?    Show contents of register x.
-               ATV0     Numeric responses.
-               ATV1     English responses (default).
-               ATZ      Load registers and EAZ/MSN from Profile.
-               AT&Bx    Set Send-Packet-size to x (max. 4000)
-                        The real packet-size may be limited by the
-                        low-level-driver used. e.g. the HiSax-Module-
-                        limit is 2000. You will get NO Error-Message,
-                        if you set it to higher values, because at the
-                        time of giving this command the corresponding
-                        driver may not be selected (see "Automatic
-                        Assignment") however the size of outgoing packets
-                        will be limited correctly.
-               AT&D0    Ignore DTR
-               AT&D2    DTR-low-edge: Hang up and return to
-                        command mode (default).
-               AT&D3    Same as AT&D2 but also resets all registers.
-               AT&Ex    Set the EAZ/MSN for this channel to x.
-               AT&F     Reset all registers and profile to "factory-defaults"
-               AT&Lx    Set list of phone numbers to listen on.  x is a
-                        list of wildcard patterns separated by semicolon.
-                        If this is set, it has precedence over the MSN set
-                        by AT&E.
-               AT&Rx    Select V.110 bitrate adaption.
-                        This command enables V.110 protocol with 9600 baud
-                        (x=9600), 19200 baud (x=19200) or 38400 baud
-                        (x=38400). A value of x=0 disables V.110 switching
-                        back to default X.75. This command sets the following
-                        Registers:
-                          Reg 14 (Layer-2 protocol):
-                            x = 0:     0
-                            x = 9600:  7
-                            x = 19200: 8
-                            x = 38400: 9
-                          Reg 18.2 = 1
-                          Reg 19 (Additional Service Indicator):
-                            x = 0:       0
-                            x = 9600:  197
-                            x = 19200: 199
-                            x = 38400: 198
-                          Note on value in Reg 19:
-                            There is _NO_ common convention for 38400 baud.
-                            The value 198 is chosen arbitrarily. Users
-                            _MUST_ negotiate this value before establishing
-                            a connection.
-               AT&Sx    Set window-size (x = 1..8) (not yet implemented)
-               AT&V     Show all settings.
-               AT&W0    Write registers and EAZ/MSN to profile. See also
-                        iprofd (5.c in this README).
-               AT&X0    BTX-mode and T.70-mode off (default)
-               AT&X1    BTX-mode on. (S13.1=1, S13.5=0 S14=0, S16=7, S18=7, S19=0)
-               AT&X2    T.70-mode on. (S13.1=1, S13.5=1, S14=0, S16=7, S18=7, S19=0)
-               AT+Rx    Resume a suspended call with CallID x (x = 1,2,3...)
-               AT+Sx    Suspend a call with CallID x (x = 1,2,3...)
-
-           For voice-mode commands refer to README.audio
-
-           1.3.2 Escape sequence:
-               During a connection, the emulation reacts just like
-               a normal modem to the escape sequence <DELAY>+++<DELAY>.
-               (The escape character - default '+' - can be set in the
-               register 2).
-               The DELAY must at least be 1.5 seconds long and delay
-               between the escape characters must not exceed 0.5 seconds.
-
-           1.3.3 Registers:
-
-              Nr.  Default  Description
-              0    0        Answer on ring number.
-                            (no auto-answer if S0=0).
-              1    0        Count of rings.
-              2    43       Escape character.
-                            (a value >= 128 disables the escape sequence).
-              3    13       Carriage return character (ASCII).
-              4    10       Line feed character (ASCII).
-              5    8        Backspace character (ASCII).
-              6    3        Delay in seconds before dialing.
-              7    60       Wait for carrier.
-              8    2        Pause time for comma (ignored)
-              9    6        Carrier detect time (ignored)
-             10    7        Carrier loss to disconnect time (ignored).
-             11    70       Touch tone timing (ignored).
-             12    69       Bit coded register:
-                            Bit 0:    0 = Suppress response messages.
-                                      1 = Show response messages.
-                            Bit 1:    0 = English response messages.
-                                      1 = Numeric response messages.
-                            Bit 2:    0 = Echo off.
-                                      1 = Echo on.
-                            Bit 3     0 = DCD always on.
-                                      1 = DCD follows carrier.
-                            Bit 4     0 = CTS follows RTS
-                                      1 = Ignore RTS, CTS always on.
-                            Bit 5     0 = return to command mode on DTR low.
-                                      1 = Same as 0 but also resets all
-                                          registers.
-                                      See also register 13, bit 2
-                            Bit 6     0 = DSR always on.
-                                      1 = DSR only on if channel is available.
-                            Bit 7     0 = Cisco-PPP-flag-hack off (default).
-                                      1 = Cisco-PPP-flag-hack on.
-             13   0         Bit coded register:
-                            Bit 0:    0 = Use delayed tty-send-algorithm
-                                      1 = Direct tty-send.
-                            Bit 1:    0 = T.70 protocol (Only for BTX!) off
-                                      1 = T.70 protocol (Only for BTX!) on
-                            Bit 2:    0 = Don't hangup on DTR low.
-                                      1 = Hangup on DTR low.
-                            Bit 3:    0 = Standard response messages
-                                      1 = Extended response messages
-                            Bit 4:    0 = CALLER NUMBER before every RING.
-                                      1 = CALLER NUMBER after first RING.
-                            Bit 5:    0 = T.70 extended protocol off
-                                      1 = T.70 extended protocol on
-                            Bit 6:    0 = Special RUNG Message off
-                                      1 = Special RUNG Message on
-                                          "RUNG" is delivered on a ttyI, if
-                                          an incoming call happened (RING) and
-                                          the remote party hung up before any
-                                          local ATA was given.
-                           Bit 7:    0 = Don't show display messages from net
-                                      1 = Show display messages from net
-                                         (S12 Bit 1 must be 0 too)      
-             14   0         Layer-2 protocol:
-                                      0 = X75/LAPB with I-frames
-                                      1 = X75/LAPB with UI-frames
-                                      2 = X75/LAPB with BUI-frames
-                                      3 = HDLC
-                                      4 = Transparent (audio)
-                                      7 = V.110, 9600 baud
-                                      8 = V.110, 19200 baud
-                                      9 = V.110, 38400 baud
-                                     10 = Analog Modem (only if hardware supports this)
-                                     11 = Fax G3 (only if hardware supports this)
-             15   0         Layer-3 protocol:
-                                      0 = transparent
-                                      1 = transparent with audio features (e.g. DSP)
-                                      2 = Fax G3 Class 2 commands (S14 has to be set to 11)
-                                      3 = Fax G3 Class 1 commands (S14 has to be set to 11)
-             16   250       Send-Packet-size/16
-             17   8         Window-size (not yet implemented)
-             18   4         Bit coded register, Service-Octet-1 to accept,
-                            or to be used on dialout:
-                            Bit 0:    Service 1 (audio) when set.
-                            Bit 1:    Service 5 (BTX) when set.
-                            Bit 2:    Service 7 (data) when set.
-                            Note: It is possible to set more than one
-                                  bit. In this case, on incoming calls
-                                  the selected services are accepted,
-                                  and if the service is "audio", the
-                                  Layer-2-protocol is automatically
-                                  changed to 4 regardless of the setting
-                                  of register 14. On outgoing calls,
-                                  the most significant 1-bit is chosen to
-                                  select the outgoing service octet.
-             19   0         Service-Octet-2
-             20   0         Bit coded register (readonly)
-                            Service-Octet-1 of last call.
-                            Bit mapping is the same as register 18
-             21   0         Bit coded register (readonly)
-                            Set on incoming call (during RING) to
-                            octet 3 of calling party number IE (Numbering plan)
-                            See section 4.5.10 of ITU Q.931
-             22   0         Bit coded register (readonly)
-                            Set on incoming call (during RING) to
-                            octet 3a of calling party number IE (Screening info)
-                            See section 4.5.10 of ITU Q.931
-             23   0         Bit coded register:
-                            Bit 0:    0 = Add CPN to RING message off
-                                      1 = Add CPN to RING message on
-                            Bit 1:    0 = Add CPN to FCON message off
-                                      1 = Add CPN to FCON message on
-                            Bit 2:    0 = Add CDN to RING/FCON message off
-                                      1 = Add CDN to RING/FCON message on
-
-  Last but not least a (at the moment fairly primitive) device to request
-  the line-status (/dev/isdninfo) is made available.
-
-  Automatic assignment of devices to lines:
-
-  All inactive physical lines are listening to all EAZs for incoming
-  calls and are NOT assigned to a specific tty or network interface.
-  When an incoming call is detected, the driver looks first for a network
-  interface and then for an opened tty which:
-
-  1. is configured for the same EAZ.
-  2. has the same protocol settings for the B-channel.
-  3. (only for network interfaces if the security flag is set)
-     contains the caller number in its access list.
-  4. Either the channel is not bound exclusively to another Net-interface, or
-     it is bound AND the other checks apply to exactly this interface.
-     (For usage of the bind-features, refer to the isdnctrl-man-page)
-
-  Only when a matching interface or tty is found is the call accepted
-  and the "connection" between the low-level-layer and the link-level-layer
-  is established and kept until the end of the connection.
-  In all other cases no connection is established. Isdn4linux can be
-  configured to either do NOTHING in this case (which is useful, if
-  other, external devices with the same EAZ/MSN are connected to the bus)
-  or to reject the call actively. (isdnctrl busreject ...)
-
-  For an outgoing call, the inactive physical lines are searched.
-  The call is placed on the first physical line, which supports the
-  requested protocols for the B-channel. If a net-interface, however
-  is pre-bound to a channel, this channel is used directly.
-
-  This makes it possible to configure several network interfaces and ttys
-  for one EAZ, if the network interfaces are set to secure operation.
-  If an incoming call matches one network interface, it gets connected to it.
-  If another incoming call for the same EAZ arrives, which does not match
-  a network interface, the first tty gets a "RING" and so on.
-
-2 System prerequisites:
-
-  ATTENTION!
-
-  Always use the latest module utilities. The current version is
-  named in Documentation/Changes. Some old versions of insmod
-  are not capable of setting the driver-Ids correctly.
-
-3. Lowlevel-driver configuration.
-
-   Configuration depends on how the drivers are built. See the
-   README.<yourDriver> for information on driver-specific setup.
-
-4. Device-inodes
-
-   The major and minor numbers and their names are described in
-   Documentation/admin-guide/devices.rst. The major numbers are:
-
-     43 for the ISDN-tty's.
-     44 for the ISDN-callout-tty's.
-     45 for control/info/debug devices.
-
-5. Application
-
-   a) For some card-types, firmware has to be loaded into the cards, before
-      proceeding with device-independent setup. See README.<yourDriver>
-      for how to do that.
-
-   b) If you only intend to use ttys, you are nearly ready now.
-
-   c) If you want to have really permanent "Modem"-settings on disk, you
-      can start the daemon iprofd. Give it a path to a file at the command-
-      line. It will store the profile-settings in this file every time
-      an AT&W0 is performed on any ISDN-tty. If the file already exists,
-      all profiles are initialized from this file. If you want to unload
-      any of the modules, kill iprofd first.
-
-   d) For networking, continue: Create an interface:
-       isdnctrl addif isdn0
-
-   e) Set the EAZ (or MSN for Euro-ISDN):
-       isdnctrl eaz isdn0 2
-
-     (For 1TR6 a single digit is allowed, for Euro-ISDN the number is your
-      real MSN e.g.: Phone-Number)
-
-   f) Set the number for outgoing calls on the interface:
-       isdnctrl addphone isdn0 out 1234567
-       ... (this can be executed more than once, all assigned numbers are
-            tried in order)
-      and the number(s) for incoming calls:
-       isdnctrl addphone isdn0 in 1234567
-
-   g) Set the timeout for hang-up:
-       isdnctrl huptimeout isdn0 <timeout_in_seconds>
-
-   h) additionally you may activate charge-hang-up (= Hang up before
-      next charge-info, this only works, if your isdn-provider transmits
-      the charge-info during and after the connection):
-       isdnctrl chargehup isdn0 on
-
-   i) Set the dial mode of the interface:
-       isdnctrl dialmode isdn0 auto
-      "off" means that you (or the system) cannot make any connection
-        (neither incoming or outgoing connections are possible). Use
-        this if you want to be sure that no connections will be made.
-      "auto" means that the interface is in auto-dial mode, and will
-        attempt to make a connection whenever a network data packet needs
-        the interface's link. Note that this can cause unexpected dialouts,
-        and lead to a high phone bill! Some daemons or other pc's that use
-        this interface can cause this.
-        Incoming connections are also possible.
-      "manual" is a dial mode created to prevent the unexpected dialouts.
-        In this mode, the interface will never make any connections on its
-        own. You must explicitly initiate a connection with "isdnctrl dial
-        isdn0". However, after an idle time of no traffic as configured for
-       the huptimeout value with isdnctrl, the connection _will_ be ended.
-       If you don't want any automatic hangup, set the huptimeout value to 0.
-        "manual" is the default.
-
-   j) Setup the interface with ifconfig as usual, and set a route to it.
-
-   k) (optional) If you run X11 and have Tcl/Tk-wish version 4.0, you can use
-     the script tools/tcltk/isdnmon. You can add actions for line-status
-     changes. See the comments at the beginning of the script for how to
-     do that. There are other tty-based tools in the tools-subdirectory
-     contributed by Michael Knigge (imon), Volker Götz (imontty) and
-     Andreas Kool (isdnmon).
-
-   l) For initial testing, you can set the verbose-level to 2 (default: 0).
-      Then all incoming calls are logged, even if they are not addressed
-      to one of the configured net-interfaces:
-      isdnctrl verbose 2
-
-  Now you are ready! A ping to the set address should now result in an
-  automatic dial-out (look at syslog kernel-messages).
-  The phone numbers and EAZs can be assigned at any time with isdnctrl.
-  You can add as many interfaces as you like with addif following the
-  directions above. Of course, there may be some limitations. But we have
-  tested as many as 20 interfaces without any problem. However, if you
-  don't give an interface name to addif, the  kernel will assign a name
-  which starts with "eth". The number of "eth"-interfaces is limited by
-  the kernel.
-
-5. Additional options for isdnctrl:
-
-   "isdnctrl secure <InterfaceName> on"
-   Only incoming calls, for which the caller-id is listed in the access
-   list of the interface are accepted. You can add caller-id's With the
-   command "isdnctrl addphone <InterfaceName> in <caller-id>"
-   Euro-ISDN does not transmit the leading '0' of the caller-id for an
-   incoming call, therefore you should configure it accordingly.
-   If the real number for the dialout e.g. is "09311234567" the number
-   to configure here is "9311234567". The pattern-match function
-   works similar to the shell mechanism.
-
-     ?     one arbitrary digit
-     *     zero or arbitrary many digits
-     [123] one of the digits in the list
-     [1-5] one digit between '1' and '5'
-           a '^' as the first character in a list inverts the list
-
-
-   "isdnctrl secure <InterfaceName> off"
-   Switch off secure operation (default).
-
-   "isdnctrl ihup <InterfaceName> [on|off]"
-   Switch the hang-up-timer for incoming calls on or off.
-
-   "isdnctrl eaz <InterfaceName>"
-   Returns the EAZ of an interface.
-
-   "isdnctrl delphone <InterfaceName> in|out <number>"
-   Deletes a number from one of the access-lists of the interface.
-
-   "isdnctrl delif <InterfaceName>"
-   Removes the interface (and possible slaves) from the kernel.
-   (You have to unregister it with "ifconfig <InterfaceName> down" before).
-
-   "isdnctrl callback <InterfaceName> [on|off]"
-   Switches an interface to callback-mode. In this mode, an incoming call
-   will be rejected and after this the remote-station will be called. If
-   you test this feature by using ping, some routers will re-dial very
-   quickly, so that the callback from isdn4linux may not be recognized.
-   In this case use ping with the option -i <sec> to increase the interval
-   between echo-packets.
-
-   "isdnctrl cbdelay <InterfaceName> [seconds]"
-   Sets the delay (default 5 sec) between an incoming call and start of
-   dialing when callback is enabled.
-
-   "isdnctrl cbhup <InterfaceName> [on|off]"
-   This enables (default) or disables an active hangup (reject) when getting an
-   incoming call for an interface which is configured for callback.
-
-   "isdnctrl encap <InterfaceName> <EncapType>"
-   Selects the type of packet-encapsulation. The encapsulation can be changed
-   only while an interface is down.
-
-   At the moment the following values are supported:
-
-   rawip    (Default) Selects raw-IP-encapsulation. This means, MAC-headers
-            are stripped off.
-   ip       IP with type-field. Same as IP but the type-field of the MAC-header
-            is preserved.
-   x25iface X.25 interface encapsulation (first byte semantics as defined in
-            ../networking/x25-iface.txt). Use this for running the linux
-            X.25 network protocol stack (AF_X25 sockets) on top of isdn.
-   cisco-h  A special-mode for communicating with a Cisco, which is configured
-            to do "hdlc"
-   ethernet No stripping. Packets are sent with full MAC-header.
-            The Ethernet-address of the interface is faked, from its
-            IP-address: fc:fc:i1:i2:i3:i4, where i1-4 are the IP-addr.-values.
-   syncppp  Synchronous PPP
-
-   uihdlc   HDLC with UI-frame-header (for use with DOS ISPA, option -h1)
-
-
-   NOTE:    x25iface encapsulation is currently experimental. Please
-            read README.x25 for further details
-
-
-   Watching packets, using standard-tcpdump will fail for all encapsulations
-   except ethernet because tcpdump does not know how to handle packets
-   without MAC-header. A patch for tcpdump is included in the utility-package
-   mentioned above.
-
-   "isdnctrl l2_prot <InterfaceName> <L2-ProtocolName>"
-   Selects a layer-2-protocol.
-   (With the ICN-driver and the HiSax-driver, "x75i" and "hdlc" is available.
-   With other drivers, "x75ui", "x75bui", "x25dte", "x25dce" may be
-   possible too. See README.x25 for x25 related l2 protocols.)
-
-   isdnctrl l3_prot <InterfaceName> <L3-ProtocolName>
-   The same for layer-3. (At the moment only "trans" is allowed)
-
-   "isdnctrl list <InterfaceName>"
-   Shows all parameters of an interface and the charge-info.
-   Try "all" as the interface name.
-
-   "isdnctrl hangup <InterfaceName>"
-   Forces hangup of an interface.
-
-   "isdnctrl bind <InterfaceName> <DriverId>,<ChannelNumber> [exclusive]"
-   If you are using more than one ISDN card, it is sometimes necessary to
-   dial out using a specific card or even preserve a specific channel for
-   dialout of a specific net-interface. This can be done with the above
-   command. Replace <DriverId> by whatever you assigned while loading the
-   module. The <ChannelNumber> is counted from zero. The upper limit
-   depends on the card used. At the moment no card supports more than
-   2 channels, so the upper limit is one.
-
-   "isdnctrl unbind <InterfaceName>"
-   unbinds a previously bound interface.
-
-   "isdnctrl busreject <DriverId> on|off"
-   If switched on, isdn4linux replies a REJECT to incoming calls, it
-   cannot match to any configured interface.
-   If switched off, nothing happens in this case.
-   You normally should NOT enable this feature, if the ISDN adapter is not
-   the only device connected to the S0-bus. Otherwise it could happen that
-   isdn4linux rejects an incoming call, which belongs to another device on
-   the bus.
-
-   "isdnctrl addslave <InterfaceName> <SlaveName>
-   Creates a slave interface for channel-bundling. Slave interfaces are
-   not seen by the kernel, but their ISDN-part can be configured with
-   isdnctrl as usual. (Phone numbers, EAZ/MSN, timeouts etc.) If more
-   than two channels are to be bundled, feel free to create as many as you
-   want. InterfaceName must be a real interface, NOT a slave. Slave interfaces
-   start dialing, if the master interface resp. the previous slave interface
-   has a load of more than 7000 cps. They hangup if the load goes under 7000
-   cps, according to their "huptimeout"-parameter.
-
-   "isdnctrl sdelay <InterfaceName> secs."
-   This sets the minimum time an Interface has to be fully loaded, until
-   it sends a dial-request to its slave.
-
-   "isdnctrl dial <InterfaceName>"
-   Forces an interface to start dialing even if no packets are to be
-   transferred.
-
-   "isdnctrl mapping <DriverId> MSN0,MSN1,MSN2,...MSN9"
-   This installs a mapping table for EAZ<->MSN-mapping for a single line.
-   Missing MSN's have to be given as "-" or can be omitted, if at the end
-   of the commandline.
-   With this command, it's now possible to have an interface listening to
-   mixed 1TR6- and Euro-Type lines. In this case, the interface has to be
-   configured to a 1TR6-type EAZ (one digit). The mapping is also valid
-   for tty-emulation. Seen from the interface/tty-level the mapping
-   CAN be used, however it's possible to use single tty's/interfaces with
-   real MSN's (more digits) also, in which case the mapping will be ignored.
-   Here is an example:
-
-   You have a 1TR6-type line with base-nr. 1234567 and a Euro-line with
-   MSN's 987654, 987655 and 987656. The DriverId for the Euro-line is "EURO".
-
-   isdnctrl mapping EURO -,987654,987655,987656,-,987655
-   ...
-   isdnctrl eaz isdn0 1      # listen on 12345671(1tr6) and 987654(euro)
-   ...
-   isdnctrl eaz isdn1 4      # listen on 12345674(1tr6) only.
-   ...
-   isdnctrl eaz isdn2 987654 # listen on 987654(euro) only.
-
-   Same scheme is used with AT&E...  at the tty's.
-
-6. If you want to write a new low-level-driver, you are welcome.
-   The interface to the link-level-module is described in the file INTERFACE.
-   If the interface should be expanded for any reason, don't do it
-   on your own, send me a mail containing the proposed changes and
-   some reasoning about them.
-   If other drivers will not be affected, I will include the changes
-   in the next release.
-   For developers only, there is a second mailing-list. Write to me
-   (fritz@isdn4linux.de), if you want to join that list.
-
-Have fun!
-
- -Fritz
-
 
+++ /dev/null
-
-The FAQ for isdn4linux
-======================
-
-Please note that there is a big FAQ available in the isdn4k-utils.
-You find it in:
- isdn4k-utils/FAQ/i4lfaq.sgml
-
-In case you just want to see the FAQ online, or download the newest version,
-you can have a look at my website:
-https://www.mhessler.de/i4lfaq/ (view + download)
-or:
-https://www.isdn4linux.de/faq/4lfaq.html (view)
-
-As the extension tells, the FAQ is in SGML format, and you can convert it
-into text/html/... format by using the sgml2txt/sgml2html/... tools.
-Alternatively, you can also do a 'configure; make all' in the FAQ directory.
-
-
-Please have a look at the FAQ before posting anything in the Mailinglist,
-or the newsgroup!
-
-
-Matthias Hessler
-hessler@isdn4linux.de
-
 
+++ /dev/null
-$Id: README.audio,v 1.8 1999/07/11 17:17:29 armin Exp $
-
-ISDN subsystem for Linux.
-  Description of audio mode.
-
-When enabled during kernel configuration, the tty emulator of the ISDN
-subsystem is capable of a reduced set of commands to support audio.
-This document describes the commands supported and the format of
-audio data.
-
-Commands for enabling/disabling audio mode:
-
-        AT+FCLASS=8      Enable audio mode.
-                         This affects the following registers:
-                           S18: Bits 0 and 2 are set.
-                           S16: Set to 48 and any further change to
-                                larger values is blocked.
-        AT+FCLASS=0      Disable audio mode.
-                         Register 18 is set to 4.
-        AT+FCLASS=?      Show possible modes.
-        AT+FCLASS?       Report current mode (0 or 8).
-
-Commands supported in audio mode:
-
-All audio mode commands have one of the following forms:
-
-        AT+Vxx?          Show current setting.
-        AT+Vxx=?         Show possible settings.
-        AT+Vxx=v         Set simple parameter.
-        AT+Vxx=v,v ...   Set complex parameter.
-
-where xx is a two-character code and v are alphanumerical parameters.
-The following commands are supported:
-
-        AT+VNH=x         Auto hangup setting. NO EFFECT, supported
-                         for compatibility only.
-        AT+VNH?          Always reporting "1"
-        AT+VNH=?         Always reporting "1"
-
-        AT+VIP           Reset all audio parameters.
-
-        AT+VLS=x         Line select. x is one of the following:
-                           0 = No device.
-                           2 = Phone line.
-        AT+VLS=?         Always reporting "0,2"
-        AT+VLS?          Show current line.
-
-        AT+VRX           Start recording. Emulator responds with
-                         CONNECT and starts sending audio data to
-                         the application. See below for data format
-
-        AT+VSD=x,y       Set silence-detection parameters.
-                         Possible parameters:
-                           x = 0 ... 31  sensitivity threshold level.
-                                         (default 0 , deactivated)
-                           y = 0 ... 255 range of interval in units
-                                         of 0.1 second. (default 70)
-        AT+VSD=?         Report possible parameters.
-        AT+VSD?          Show current parameters.
-
-        AT+VDD=x,y       Set DTMF-detection parameters.
-                         Only possible if online and during this connection.
-                         Possible parameters:
-                           x = 0 ... 15  sensitivity threshold level.
-                                         (default 0 , I4L soft-decode)
-                                         (1-15 soft-decode off, hardware on)
-                           y = 0 ... 255 tone duration in units of 5ms.
-                                         Not for I4L soft decode (default 8, 40ms)
-        AT+VDD=?         Report possible parameters.
-        AT+VDD?          Show current parameters.
-
-        AT+VSM=x         Select audio data format.
-                         Possible parameters:
-                           2 = ADPCM-2
-                           3 = ADPCM-3
-                           4 = ADPCM-4
-                           5 = aLAW
-                           6 = uLAW
-        AT+VSM=?         Show possible audio formats.
-
-        AT+VTX           Start audio playback. Emulator responds
-                         with CONNECT and starts sending audio data
-                         received from the application via phone line.
-General behavior and description of data formats/protocol.
-    when a connection is made:
-
-      On incoming calls, if the application responds to a RING
-      with ATA, depending on the calling service, the emulator
-      responds with either CONNECT (data call) or VCON (voice call).
-      
-      On outgoing voice calls, the emulator responds with VCON
-      upon connection setup.
-
-  Audio recording.
-
-    When receiving audio data, a kind of bisync protocol is used.
-    Upon AT+VRX command, the emulator responds with CONNECT, and
-    starts sending audio data to the application. There are several
-    escape sequences defined, all using DLE (0x10) as Escape char:
-
-    <DLE><ETX>              End of audio data. (i.e. caused by a
-                            hangup of the remote side) Emulator stops
-                            recording, responding with VCON.
-    <DLE><DC4>             Abort recording, (send by appl.) Emulator
-                           stops recording, sends DLE,ETX.
-    <DLE><DLE>              Escape sequence for DLE in data stream.
-    <DLE>0                  Touchtone "0" received.
-         ...
-    <DLE>9                  Touchtone "9" received.
-    <DLE>#                  Touchtone "#" received.
-    <DLE>*                  Touchtone "*" received.
-    <DLE>A                  Touchtone "A" received.
-    <DLE>B                  Touchtone "B" received.
-    <DLE>C                  Touchtone "C" received.
-    <DLE>D                  Touchtone "D" received.
-
-    <DLE>q                  quiet. Silence detected after non-silence.
-    <DLE>s                  silence. Silence detected from the
-                            start of recording.
-
-    Currently unsupported DLE sequences:
-
-    <DLE>c                  FAX calling tone received.
-    <DLE>b                  busy tone received.
-
-  Audio playback.
-
-    When sending audio data, upon AT+VTX command, emulator responds with
-    CONNECT, and starts transferring data from application to the phone line.
-    The same DLE sequences apply to this mode.
-
-  Full-Duplex-Audio:
-
-    When _both_ commands for recording and playback are given in _one_
-    AT-command-line (i.e.: "AT+VTX+VRX"), full-duplex-mode is selected.
-       In this mode, the only way to stop recording is sending <DLE><DC4>
-    and the only way to stop playback is to send <DLE><ETX>.
-
 
+++ /dev/null
-Description of the "concap" encapsulation protocol interface
-============================================================
-
-The "concap" interface is intended to be used by network device
-drivers that need to process an encapsulation protocol. 
-It is assumed that the protocol interacts with a linux network device by
-- data transmission
-- connection control (establish, release)
-Thus, the mnemonic: "CONnection CONtrolling eNCAPsulation Protocol".
-
-This is currently only used inside the isdn subsystem. But it might
-also be useful to other kinds of network devices. Thus, if you want
-to suggest changes that improve usability or performance of the
-interface, please let me know. I'm willing to include them in future
-releases (even if I needed to adapt the current isdn code to the
-changed interface).
-
-
-Why is this useful?
-===================
-
-The encapsulation protocol used on top of WAN connections or permanent
-point-to-point links are frequently chosen upon bilateral agreement.
-Thus, a device driver for a certain type of hardware must support
-several different encapsulation protocols at once.
-
-The isdn device driver did already support several different
-encapsulation protocols. The encapsulation protocol is configured by a
-user space utility (isdnctrl). The isdn network interface code then
-uses several case statements which select appropriate actions
-depending on the currently configured encapsulation protocol.
-
-In contrast, LAN network interfaces always used a single encapsulation
-protocol which is unique to the hardware type of the interface. The LAN
-encapsulation is usually done by just sticking a header on the data. Thus,
-traditional linux network device drivers used to process the
-encapsulation protocol directly (usually by just providing a hard_header()
-method in the device structure) using some hardware type specific support
-functions. This is simple, direct and efficient. But it doesn't fit all
-the requirements for complex WAN encapsulations. 
-
-
-   The configurability of the encapsulation protocol to be used
-   makes isdn network interfaces more flexible, but also much more
-   complex than traditional lan network interfaces.
-
-
-Many Encapsulation protocols used on top of WAN connections will not just
-stick a header on the data. They also might need to set up or release
-the WAN connection. They also might want to send other data for their
-private purpose over the wire, e.g. ppp does a lot of link level
-negotiation before the first piece of user data can be transmitted.
-Such encapsulation protocols for WAN devices are typically more complex
-than encapsulation protocols for lan devices. Thus, network interface
-code for typical WAN devices also tends to be more complex.
-
-
-In order to support Linux' x25 PLP implementation on top of
-isdn network interfaces I could have introduced yet another branch to
-the various case statements inside drivers/isdn/isdn_net.c.
-This eventually made isdn_net.c even more complex. In addition, it made
-isdn_net.c harder to maintain. Thus, by identifying an abstract
-interface between the network interface code and the encapsulation
-protocol, complexity could be reduced and maintainability could be
-increased.
-
-
-Likewise, a similar encapsulation protocol will frequently be needed by
-several different interfaces of even different hardware type, e.g. the
-synchronous ppp implementation used by the isdn driver and the
-asynchronous ppp implementation used by the ppp driver have a lot of
-similar code in them. By cleanly separating the encapsulation protocol
-from the hardware specific interface stuff such code could be shared
-better in future.
-
-
-When operating over dial-up-connections (e.g. telephone lines via modem,
-non-permanent virtual circuits of wide area networks, ISDN) many
-encapsulation protocols will need to control the connection. Therefore,
-some basic connection control primitives are supported. The type and
-semantics of the connection (i.e the ISO layer where connection service
-is provided) is outside our scope and might be different depending on
-the encapsulation protocol used, e.g. for a ppp module using our service
-on top of a modem connection a connect_request will result in dialing
-a (somewhere else configured) remote phone number. For an X25-interface
-module (LAPB semantics, as defined in Documentation/networking/x25-iface.txt)
-a connect_request will ask for establishing a reliable lapb
-datalink connection.
-
-
-The encapsulation protocol currently provides the following
-service primitives to the network device.
-
-- create a new encapsulation protocol instance
-- delete encapsulation protocol instance and free all its resources
-- initialize (open) the encapsulation protocol instance for use.
-- deactivate (close) an encapsulation protocol instance.
-- process (xmit) data handed down by upper protocol layer
-- receive data from lower (hardware) layer
-- process connect indication from lower (hardware) layer
-- process disconnect indication from lower (hardware) layer
-
-
-The network interface driver accesses those primitives via callbacks
-provided by the encapsulation protocol instance within a
-struct concap_proto_ops.
-
-struct concap_proto_ops{
-
-       /* create a new encapsulation protocol instance of same type */
-       struct concap_proto *  (*proto_new) (void);
-
-       /* delete encapsulation protocol instance and free all its resources.
-          cprot may no longer be referenced after calling this */
-       void (*proto_del)(struct concap_proto *cprot);
-
-       /* initialize the protocol's data. To be called at interface startup
-          or when the device driver resets the interface. All services of the
-          encapsulation protocol may be used after this*/
-       int (*restart)(struct concap_proto *cprot, 
-                      struct net_device *ndev,
-                      struct concap_device_ops *dops);
-
-       /* deactivate an encapsulation protocol instance. The encapsulation
-          protocol may not call any *dops methods after this. */
-       int (*close)(struct concap_proto *cprot);
-
-       /* process a frame handed down to us by upper layer */
-       int (*encap_and_xmit)(struct concap_proto *cprot, struct sk_buff *skb);
-
-       /* to be called for each data entity received from lower layer*/ 
-       int (*data_ind)(struct concap_proto *cprot, struct sk_buff *skb);
-
-       /* to be called when a connection was set up/down.
-          Protocols that don't process these primitives might fill in
-          dummy methods here */
-       int (*connect_ind)(struct concap_proto *cprot);
-       int (*disconn_ind)(struct concap_proto *cprot);
-};
-
-
-The data structures are defined in the header file include/linux/concap.h.
-
-
-A Network interface using encapsulation protocols must also provide
-some service primitives to the encapsulation protocol:
-
-- request data being submitted by lower layer (device hardware) 
-- request a connection being set up by lower layer 
-- request a connection being released by lower layer
-
-The encapsulation protocol accesses those primitives via callbacks
-provided by the network interface within a struct concap_device_ops.
-
-struct concap_device_ops{
-
-       /* to request data be submitted by device */ 
-       int (*data_req)(struct concap_proto *, struct sk_buff *);
-
-       /* Control methods must be set to NULL by devices which do not
-          support connection control. */
-       /* to request a connection be set up */ 
-       int (*connect_req)(struct concap_proto *);
-
-       /* to request a connection be released */
-       int (*disconn_req)(struct concap_proto *);      
-};
-
-The network interface does not explicitly provide a receive service
-because the encapsulation protocol directly calls netif_rx(). 
-
-
-
-
-An encapsulation protocol itself is actually the
-struct concap_proto{
-       struct net_device *net_dev;             /* net device using our service  */
-       struct concap_device_ops *dops; /* callbacks provided by device */
-       struct concap_proto_ops  *pops; /* callbacks provided by us */
-       int flags;
-       void *proto_data;               /* protocol specific private data, to
-                                          be accessed via *pops methods only*/
-       /*
-         :
-         whatever 
-         :
-         */
-};
-
-Most of this is filled in when the device requests the protocol to 
-be reset (opend). The network interface must provide the net_dev and
-dops pointers. Other concap_proto members should be considered private
-data that are only accessed by the pops callback functions. Likewise,
-a concap proto should access the network device's private data
-only by means of the callbacks referred to by the dops pointer.
-
-
-A possible extended device structure which uses the connection controlling
-encapsulation services could look like this:
-
-struct concap_device{
-       struct net_device net_dev;
-       struct my_priv  /* device->local stuff */
-                       /* the my_priv struct might contain a 
-                          struct concap_device_ops *dops;
-                          to provide the device specific callbacks
-                       */
-       struct concap_proto *cprot;        /* callbacks provided by protocol */
-};
-
-
-
-Misc Thoughts
-=============
-
-The concept of the concap proto might help to reuse protocol code and
-reduce the complexity of certain network interface implementations.
-The trade off is that it introduces yet another procedure call layer
-when processing the protocol. This has of course some impact on
-performance. However, typically the concap interface will be used by
-devices attached to slow lines (like telephone, isdn, leased synchronous
-lines). For such slow lines, the overhead is probably negligible.
-This might no longer hold for certain high speed WAN links (like
-ATM).
-
-
-If general linux network interfaces explicitly supported concap
-protocols (e.g. by a member struct concap_proto* in struct net_device)
-then the interface of the service function could be changed
-by passing a pointer of type (struct net_device*) instead of
-type (struct concap_proto*). Doing so would make many of the service
-functions compatible to network device support functions.
-
-e.g. instead of the concap protocol's service function
-
-  int (*encap_and_xmit)(struct concap_proto *cprot, struct sk_buff *skb);
-
-we could have
-
-  int (*encap_and_xmit)(struct net_device *ndev, struct sk_buff *skb);
-
-As this is compatible to the dev->hard_start_xmit() method, the device
-driver could directly register the concap protocol's encap_and_xmit()
-function as its hard_start_xmit() method. This would eliminate one
-procedure call layer.
-
-
-The device's data request function could also be defined as
- 
-  int (*data_req)(struct net_device *ndev, struct sk_buff *skb);
-
-This might even allow for some protocol stacking. And the network
-interface might even register the same data_req() function directly
-as its hard_start_xmit() method when a zero layer encapsulation
-protocol is configured. Thus, eliminating the performance penalty
-of the concap interface when a trivial concap protocol is used.
-Nevertheless, the device remains able to support encapsulation
-protocol configuration.
-
 
+++ /dev/null
-The isdn diversion services are a supporting module working together with
-the isdn4linux and the HiSax module for passive cards. 
-Active cards, TAs and cards using a own or other driver than the HiSax 
-module need to be adapted to the HL<->LL interface described in a separate 
-document. The diversion services may be used with all cards supported by 
-the HiSax driver.
-The diversion kernel interface and controlling tool divertctrl were written
-by Werner Cornelius (werner@isdn4linux.de or werner@titro.de) under the
-GNU General Public License.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-Table of contents
-=================
-
-1. Features of the i4l diversion services 
-   (Or what can the i4l diversion services do for me)
-
-2. Required hard- and software
-
-3. Compiling, installing and loading/unloading the module  
-   Tracing calling and diversion information 
-
-4. Tracing calling and diversion information
- 
-5. Format of the divert device ASCII output
- 
-
-1. Features of the i4l diversion services 
-   (Or what can the i4l diversion services do for me)
-
-   The i4l diversion services offers call forwarding and logging normally 
-   only supported by isdn phones. Incoming calls may be diverted 
-   unconditionally (CFU), when not reachable (CFNR) or on busy condition 
-   (CFB). 
-   The diversions may be invoked statically in the providers exchange
-   as normally done by isdn phones. In this case all incoming calls
-   with a special (or all) service identifiers are forwarded if the 
-   forwarding reason is met. Activated static services may also be 
-   interrogated (queried).
-   The i4l diversion services additionally offers a dynamic version of
-   call forwarding which is not preprogrammed inside the providers exchange
-   but dynamically activated by i4l.
-   In this case all incoming calls are checked by rules that may be
-   compared to the mechanism of ipfwadm or ipchains. If a given rule matches
-   the checking process is finished and the rule matching will be applied
-   to the call.
-   The rules include primary and secondary service identifiers, called 
-   number and subaddress, callers number and subaddress and whether the rule
-   matches to all filtered calls or only those when all B-channel resources
-   are exhausted.
-   Actions that may be invoked by a rule are ignore, proceed, reject, 
-   direct divert or delayed divert of a call.
-   All incoming calls matching a rule except the ignore rule a reported and
-   logged as ASCII via the proc filesystem (/proc/net/isdn/divert). If proceed
-   is selected the call will be held in a proceeding state (without ringing)
-   for a certain amount of time to let an external program or client decide
-   how to handle the call. 
-            
-
-2. Required hard- and software
-   
-   For using the i4l diversion services the isdn line must be of a EURO/DSS1
-   type. Additionally the i4l services only work together with the HiSax 
-   driver for passive isdn cards. All HiSax supported cards may be used for
-   the diversion purposes.
-   The static diversion services require the provider having static services
-   CFU, CFNR, CFB activated on an MSN-line. The static services may not be 
-   used on a point-to-point connection. Further the static services are only
-   available in some countries (for example germany). Countries requiring the 
-   keypad protocol for activating static diversions (like the netherlands) are
-   not supported but may use the tty devices for this purpose.
-   The dynamic diversion services may be used in all countries if the provider
-   enables the feature CF (call forwarding). This should work on both MSN- and
-   point-to-point lines.
-   To add and delete rules the additional divertctrl program is needed. This
-   program is part of the isdn4kutils package.   
-
-3. Compiling, installing and loading/unloading the module  
-   Tracing calling and diversion information 
-
-
-   To compile the i4l code with diversion support you need to say yes to the 
-   DSS1 diversion services when selecting the i4l options in the kernel 
-   config (menuconfig or config).
-   After having properly activated a make modules and make modules_install all
-   required modules will be correctly installed in the needed modules dirs.
-   As the diversion services are currently not included in the scripts of most
-   standard distributions you will have to add a "insmod dss1_divert" after
-   having loaded the global isdn module.
-   The module can be loaded without any command line parameters.
-   If the module is actually loaded and active may be checked with a 
-   "cat /proc/modules" or "ls /proc/net/isdn/divert". The divert file is 
-   dynamically created by the diversion module and removed when the module is
-   unloaded.
-
-
-4. Tracing calling and diversion information
- 
-   You also may put a "cat /proc/net/isdn/divert" in the background with the
-   output redirected to a file. Then all actions of the module are logged.
-   The divert file in the proc system may be opened more than once, so in 
-   conjunction with inetd and a small remote client on other machines inside
-   your network incoming calls and reactions by the module may be shown on 
-   every listening machine. 
-   If a call is reported as proceeding an external program or client may 
-   specify during a certain amount of time (normally 4 to 10 seconds) what
-   to do with that call.      
-   To unload the module all open files to the device in the proc system must
-   be closed. Otherwise the module (and isdn.o) may not be unloaded. 
-
-5. Format of the divert device ASCII output
- 
-   To be done later
-
 
+++ /dev/null
-
-Fax with isdn4linux
-===================
-
-When enabled during kernel configuration, the tty emulator
-of the ISDN subsystem is capable of the Fax Class 2 commands.
-
-This only makes sense under the following conditions :
-
-- You need the commands as dummy, because you are using
-  hylafax (with patch) for AVM capi.
-- You want to use the fax capabilities of your isdn-card.
-  (supported cards are listed below)
-
-
-NOTE: This implementation does *not* support fax with passive
-      ISDN-cards (known as softfax). The low-level driver of
-      the ISDN-card and/or the card itself must support this.
-
-
-Supported ISDN-Cards
---------------------
-
-Eicon DIVA Server BRI/PCI
-       - full support with both B-channels.
-
-Eicon DIVA Server 4BRI/PCI
-       - full support with all B-channels.
-
-Eicon DIVA Server PRI/PCI
-       - full support on amount of B-channels
-               depending on DSPs on board.
-
-
-
-The command set is known as Class 2 (not Class 2.0) and
-can be activated by AT+FCLASS=2
-
-
-The interface between the link-level-module and the hardware-level driver
-is described in the files INTERFACE.fax and INTERFACE.
-
-Armin
-mac@melware.de
-
 
+++ /dev/null
-The driver for the HFC-PCI and HFC-PCI-A chips from CCD may be used
-for many OEM cards using this chips.
-Additionally the driver has a special feature which makes it possible
-to read the echo-channel of the isdn bus. So all frames in both directions
-may be logged.
-When the echo logging feature is used the number of available B-channels
-for a HFC-PCI card is reduced to 1. Of course this is only relevant to
-the card, not to the isdn line.
-To activate the echo mode the following ioctls must be entered:
-
-hisaxctrl <driver/cardname> 10 1
-
-This reduces the available channels to 1. There must not be open connections
-through this card when entering the command.
-And then:
-
-hisaxctrl <driver/cardname> 12 1
-
-This enables the echo mode. If Hex logging is activated the isdnctrlx 
-devices show a output with a line beginning of HEX: for the providers
-exchange and ECHO: for isdn devices sending to the provider.
-
-If more than one HFC-PCI cards are installed, a specific card may be selected
-at the hisax module load command line. Supply the load command with the desired
-IO-address of the desired card. 
-Example:
-There tree cards installed in your machine at IO-base addresses 0xd000, 0xd400 
-and 0xdc00
-If you want to use the card at 0xd400 standalone you should supply the insmod
-or depmod with type=35 io=0xd400.
-If you want to use all three cards, but the order needs to be at 0xdc00,0xd400,
-0xd000 you may give the parameters type=35,35,35 io=0xdc00,0xd400,0xd00 
-Then the desired card will be the initialised in the desired order.
-If the io parameter is used the io addresses of all used cards should be 
-supplied else the parameter is assumed 0 and a auto search for a free card is
-invoked which may not give the wanted result. 
-
-Comments and reports to werner@isdn4linux.de or werner@isdn-development.de
-
-
-
 
+++ /dev/null
-Some additional information for setting up a syncPPP
-connection using network interfaces.
----------------------------------------------------------------
-
-You need one thing beside the isdn4linux package:
-
-  a patched pppd .. (I called it ipppd to show the difference)
-
-Compiling isdn4linux with sync PPP:
------------------------------------
-To compile isdn4linux with the sync PPP part, you have
-to answer the appropriate question when doing a "make config"
-Don't forget to load the slhc.o
-module before the isdn.o module, if VJ-compression support
-is not compiled into your kernel. (e.g if you have no PPP or
-CSLIP in the kernel)
-
-Using isdn4linux with sync PPP:
--------------------------------
-Sync PPP is just another encapsulation for isdn4linux. The
-name to enable sync PPP encapsulation is 'syncppp' .. e.g:
-
-  /sbin/isdnctrl encap ippp0 syncppp
-
-The name of the interface is here 'ippp0'. You need 
-one interface with the name 'ippp0' to saturate the
-ipppd, which checks the ppp version via this interface.
-Currently, all devices must have the name ipppX where
-'X' is a decimal value.
-
-To set up a PPP connection you need the ipppd .. You must start 
-the ipppd once after installing the modules. The ipppd 
-communicates with the isdn4linux link-level driver using the
-/dev/ippp0 to /dev/ippp15 devices. One ipppd can handle
-all devices at once. If you want to use two PPP connections
-at the same time, you have to connect the ipppd to two
-devices .. and so on. 
-I've implemented one additional option for the ipppd:
- 'useifip' will get (if set to not 0.0.0.0) the IP address 
- for the negotiation from the attached network-interface. 
-(also: ipppd will try to negotiate pointopoint IP as remote IP)
-You must disable BSD-compression, this implementation can't
-handle compressed packets.
-
-Check the etc/rc.isdn.syncppp in the isdn4kernel-util package
-for an example setup script.
-
-To use the MPPP stuff, you must configure a slave device
-with isdn4linux. Now call the ipppd with the '+mp' option.
-To increase the number of links, you must use the
-'addlink' option of the isdnctrl tool. (rc.isdn.syncppp.MPPP is
-an example script)
-
-enjoy it,
-    michael
-     
-
-
 
+++ /dev/null
-  
-X.25 support within isdn4linux
-==============================
-
-This is alpha/beta test code. Use it completely at your own risk.
-As new versions appear, the stuff described here might suddenly change
-or become invalid without notice.
-
-Keep in mind:
-
-You are using several new parts of the 2.2.x kernel series which
-have not been tested in a large scale. Therefore, you might encounter
-more bugs as usual.
-
-- If you connect to an X.25 neighbour not operated by yourself, ASK the
-  other side first. Be prepared that bugs in the protocol implementation
-  might result in problems.
-
-- This implementation has never wiped out my whole hard disk yet. But as
-  this is experimental code, don't blame me if that happened to you.
-  Backing up important data will never harm.
-
-- Monitor your isdn connections while using this software. This should
-  prevent you from undesired phone bills in case of driver problems.
-  
- 
-
-
-How to configure the kernel
-===========================
- 
-The ITU-T (former CCITT) X.25 network protocol layer has been implemented
-in the Linux source tree since version 2.1.16. The isdn subsystem might be 
-useful to run X.25 on top of ISDN. If you want to try it, select
-
-   "CCITT X.25 Packet Layer"
-
-from the networking options as well as
-
-   "ISDN Support" and "X.25 PLP on Top of ISDN"
-
-from the ISDN subsystem options when you configure your kernel for
-compilation. You currently also need to enable
-"Prompt for development and/or incomplete code/drivers" from the
-"Code maturity level options" menu. For the x25trace utility to work
-you also need to enable "Packet socket".
-
-For local testing it is also recommended to enable the isdnloop driver
-from the isdn subsystem's configuration menu.
-
-For testing, it is recommended that all isdn drivers and the X.25 PLP
-protocol are compiled as loadable modules. Like this, you can recover
-from certain errors by simply unloading and reloading the modules.
-
-
-
-What's it for? How to use it?
-=============================
-
-X.25 on top of isdn might be useful with two different scenarios:
-
-- You might want to access a public X.25 data network from your Linux box.
-  You can use i4l if you were physically connected to the X.25 switch
-  by an ISDN B-channel (leased line as well as dial up connection should
-  work).
-
-  This corresponds to ITU-T recommendation X.31 Case A (circuit-mode
-  access to PSPDN [packet switched public data network]).
-
-  NOTE: X.31 also covers a Case B (access to PSPDN via virtual
-  circuit / packet mode service). The latter mode (which in theory
-  also allows using the D-channel) is not supported by isdn4linux.
-  It should however be possible to establish such packet mode connections
-  with certain active isdn cards provided that the firmware supports X.31
-  and the driver exports this functionality to the user. Currently, 
-  the AVM B1 driver is the only driver which does so. (It should be
-  possible to access D-channel X.31 with active AVM cards using the
-  CAPI interface of the AVM-B1 driver).
-
-- Or you might want to operate certain ISDN teleservices on your linux
-  box. A lot of those teleservices run on top of the ISO-8208
-  (DTE-DTE mode) network layer protocol. ISO-8208 is essentially the
-  same as ITU-T X.25.
-
-  Popular candidates of such teleservices are EUROfile transfer or any
-  teleservice applying ITU-T recommendation T.90.
-
-To use the X.25 protocol on top of isdn, just create an isdn network
-interface as usual, configure your own and/or peer's ISDN numbers,
-and choose x25iface encapsulation by
-
-   isdnctrl encap <iface-name> x25iface.
-
-Once encap is set like this, the device can be used by the X.25 packet layer.
-
-All the stuff needed for X.25 is implemented inside the isdn link
-level (mainly isdn_net.c and some new source files). Thus, it should
-work with every existing HL driver. I was able to successfully open X.25
-connections on top of the isdnloop driver and the hisax driver.
-"x25iface"-encapsulation bypasses demand dialing. Dialing will be
-initiated when the upper (X.25 packet) layer requests the lapb datalink to
-be established. But hangup timeout is still active. Whenever a hangup
-occurs, all existing X.25 connections on that link will be cleared
-It is recommended to use sufficiently large hangup-timeouts for the
-isdn interfaces.
-
-
-In order to set up a conforming protocol stack you also need to
-specify the proper l2_prot parameter:
-
-To operate in ISO-8208  X.25 DTE-DTE mode, use
-
-   isdnctrl l2_prot <iface-name> x75i
-
-To access an X.25 network switch via isdn (your linux box is the DTE), use
-
-   isdnctrl l2_prot <iface-name> x25dte
-
-To mimic an X.25 network switch (DCE side of the connection), use
-
-   isdnctrl l2_prot <iface-name> x25dce
-
-However, x25dte or x25dce is currently not supported by any real HL
-level driver. The main difference between x75i and x25dte/dce is that
-x25d[tc]e uses fixed lap_b addresses. With x75i, the side which
-initiates the isdn connection uses the DTE's lap_b address while the
-called side used the DCE's lap_b address. Thus, l2_prot x75i might
-probably work if you access a public X.25 network as long as the
-corresponding isdn connection is set up by you. At least one test
-was successful to connect via isdn4linux to an X.25 switch using this
-trick. At the switch side, a terminal adapter X.21 was used to connect
-it to the isdn.
-
-
-How to set up a test installation?
-==================================
-
-To test X.25 on top of isdn, you need to get
-
-- a recent version of the "isdnctrl" program that supports setting the new
-  X.25 specific parameters.
-
-- the x25-utils-2.X package from 
-  ftp://ftp.hes.iki.fi/pub/ham/linux/ax25/x25utils-*
-  (don't confuse the x25-utils with the ax25-utils)
-
-- an application program that uses linux PF_X25 sockets (some are
-  contained in the x25-util package).
-
-Before compiling the user level utilities make sure that the compiler/
-preprocessor will fetch the proper kernel header files of this kernel
-source tree. Either make /usr/include/linux a symbolic link pointing to 
-this kernel's include/linux directory or set the appropriate compiler flags.
-
-When all drivers and interfaces are loaded and configured you need to
-ifconfig the network interfaces up and add X.25-routes to them. Use
-the usual ifconfig tool.
-
-ifconfig <iface-name> up
-
-But a special x25route tool (distributed with the x25-util package)
-is needed to set up X.25 routes. I.e. 
-
-x25route add 01 <iface-name>
-
-will cause all x.25 connections to the destination X.25-address
-"01" to be routed to your created isdn network interface.
-
-There are currently no real X.25 applications available. However, for
-tests, the x25-utils package contains a modified version of telnet
-and telnetd that uses X.25 sockets instead of tcp/ip sockets. You can
-use those for your first tests. Furthermore, you might check
-ftp://ftp.hamburg.pop.de/pub/LOCAL/linux/i4l-eft/ which contains some
-alpha-test implementation ("eftp4linux") of the EUROfile transfer
-protocol.
-
-The scripts distributed with the eftp4linux test releases might also
-provide useful examples for setting up X.25 on top of isdn.
-
-The x25-utility package also contains an x25trace tool that can be
-used to monitor X.25 packets received by the network interfaces.
-The /proc/net/x25* files also contain useful information. 
-
-- Henner
 
+++ /dev/null
-simple isdn4linux PPP FAQ .. to be continued .. not 'debugged' 
--------------------------------------------------------------------
-
-Q01: what's pppd, ipppd, syncPPP, asyncPPP ??
-Q02: error message "this system lacks PPP support"
-Q03: strange information using 'ifconfig'
-Q04: MPPP?? What's that and how can I use it ...
-Q05: I tried MPPP but it doesn't work 
-Q06: can I use asynchronous PPP encapsulation with network devices
-Q07: A SunISDN machine can't connect to my i4l system
-Q08: I wanna talk to several machines, which need different configs
-Q09: Starting the ipppd, I get only error messages from i4l
-Q10: I wanna use dynamic IP address assignment 
-Q11: I can't connect. How can I check where the problem is.
-Q12: How can I reduce login delay? 
-
--------------------------------------------------------------------
-
-Q01: pppd, ipppd, syncPPP, asyncPPP .. what is that ?
-   what should I use?
-A: The pppd is for asynchronous PPP .. asynchronous means
-   here, the framing is character based. (e.g when
-   using ttyI* or tty* devices)
-
-   The ipppd handles PPP packets coming in HDLC
-   frames (bit based protocol) ... The PPP driver
-   in isdn4linux pushes all IP packets direct
-   to the network layer and all PPP protocol
-   frames to the /dev/ippp* device. 
-   So, the ipppd is a simple external network
-   protocol handler.
-
-   If you login into a remote machine using the
-   /dev/ttyI* devices and then enable PPP on the
-   remote terminal server -> use the 'old' pppd
-
-   If your remote side immediately starts to send
-   frames ... you probably connect to a 
-   syncPPP machine .. use the network device part
-   of isdn4linux with the 'syncppp' encapsulation
-   and make sure, that the ipppd is running and 
-   connected to at least one /dev/ippp*. Check the 
-   isdn4linux manual on how to configure a network device.
-
---
-
-Q02: when I start the ipppd .. I only get the
-   error message "this system lacks PPP support"
-A: check that at least the device 'ippp0' exists.
-   (you can check this e.g with the program 'ifconfig')
-   The ipppd NEEDS this device under THIS name .. 
-   If this device doesn't exists, use:
-       isdnctrl addif ippp0
-       isdnctrl encap ippp0 syncppp
-       ... (see isdn4linux doc for more) ...
-A: Maybe you have compiled the ipppd with another
-   kernel source tree than the kernel you currently
-   run ... 
-
---
-
-Q03: when I list the netdevices with ifconfig I see, that
-   my ISDN interface has a HWaddr and IRQ=0 and Base 
-   address = 0 
-A: The device is a fake ethernet device .. ignore IRQ and baseaddr
-   You need the HWaddr only for ethernet encapsulation.
-   
---
-
-Q04: MPPP?? What's that and how can I use it ...
-
-A: MPPP or MP or MPP (Warning: MP is also an 
-   acronym for 'Multi Processor') stands for
-   Multi Point to Point and means bundling
-   of several channels to one logical stream.
-   To enable MPPP negotiation you must call the
-   ipppd with the '+mp' option. 
-   You must also configure a slave device for
-   every additional channel. (see the i4l manual
-   for more)
-   To use channel bundling you must first activate
-   the 'master' or initial call. Now you can add 
-   the slave channels with the command:
-       isdnctrl addlink <device>
-   e.g:
-       isdnctrl addlink ippp0
-   This is different from other encapsulations of
-   isdn4linux! With syncPPP, there is no automatic
-   activation of slave devices.
-
---
-
-Q05: I tried MPPP but it doesn't work .. the ipppd
-   writes in the debug log something like:
-   .. rcvd [0][proto=0x3d] c0 00 00 00 80 fd 01 01 00 0a ...
-   .. sent [0][LCP ProtRej id=0x2 00 3d c0 00 00 00 80 fd 01 ...
-
-A: you forgot to compile MPPP/RFC1717 support into the
-   ISDN Subsystem. Recompile with this option enabled.
-
---
-
-Q06: can I use asynchronous PPP encapsulation
-   over the network interface of isdn4linux ..
-
-A: No .. that's not possible .. Use the standard
-   PPP package over the /dev/ttyI* devices. You
-   must not use the ipppd for this.
-   
---
-
-Q07: A SunISDN machine tries to connect my i4l system,
-   which doesn't work.
-   Checking the debug log I just saw garbage like:
-!![ ... fill in the line ... ]!!
-
-A: The Sun tries to talk asynchronous PPP ... i4l
-   can't understand this ... try to use the ttyI*
-   devices with the standard PPP/pppd package
-
-A: (from Alexanter Strauss: )
-!![ ... fill in mail ]!!
-
---
-
-Q08: I wanna talk to remote machines, which need
-   a different configuration. The only way
-   I found to do this is to kill the ipppd and
-   start a new one with another config to connect
-   to the second machine. 
-
-A: you must bind a network interface explicitly to
-   an ippp device, where you can connect a (for this
-   interface) individually configured ipppd.
-
---
-
-Q09: When I start the ipppd I only get error messages
-   from the i4l driver .. 
-
-A: When starting, the ipppd calls functions which may 
-   trigger a network packet. (e.g gethostbyname()).
-   Without the ipppd (at this moment, it is not
-   fully started) we can't handle this network request.
-   Try to configure hostnames necessary for the ipppd
-   in your local /etc/hosts file or in a way, that
-   your system can resolve it without using an
-   isdn/ippp network-interface.
-
---
-
-Q10: I wanna use dynamic IP address assignment ... How 
-   must I configure the network device.
-
-A: At least you must have a route which forwards
-   a packet to the ippp network-interface to trigger
-   the dial-on-demand.
-   A default route to the ippp-interface will work.
-   Now you must choose a dummy IP address for your
-   interface.
-   If for some reason you can't set the default
-   route to the ippp interface, you may take any 
-   address of the subnet from which you expect your
-   dynamic IP number and set a 'network route' for
-   this subnet to the ippp interface.
-   To allow overriding of the dummy address you
-   must call the ipppd with the 'ipcp-accept-local' option.
-
-A: You must know, how the ipppd gets the addresses it wanna
-   configure. If you don't give any option, the ipppd
-   tries to negotiate the local host address!
-   With the option 'noipdefault' it requests an address
-   from the remote machine. With 'useifip' it gets the
-   addresses from the net interface. Or you set the address
-   on the option line with the <a.b.c.d:e.f.g.h> option.
-   Note: the IP address of the remote machine must be configured
-   locally or the remote machine must send it in an IPCP request.
-   If your side doesn't know the IP address after negotiation, it
-   closes the connection!
-   You must allow overriding of address with the 'ipcp-accept-*'
-   options, if you have set your own or the remote address 
-   explicitly.
-
-A: Maybe you try these options .. e.g:   
-
-    /sbin/ipppd :$REMOTE noipdefault /dev/ippp0
-
-   where REMOTE must be the address of the remote machine (the
-   machine, which gives you your address)
-
---
-
-Q11: I can't connect. How can I check where the problem is.
-
-A: A good help log is the debug output from the ipppd...
-   Check whether you can find there:
-   - only a few LCP-conf-req SENT messages (less then 10)
-     and then a Term-REQ:
-     -> check whether your ISDN card is well configured
-        it seems, that your machine doesn't dial
-        (IRQ,IO,Proto, etc problems)
-        Configure your ISDN card to print debug messages and
-        check the /dev/isdnctrl output next time. There
-        you can see, whether there is activity on the card/line.
-   - there are at least a few RECV messages in the log:
-     -> fine: your card is dialing and your remote machine
-        tries to talk with you. Maybe only a missing 
-        authentication. Check your ipppd configuration again.
-   - the ipppd exits for some reason:
-     -> not good ... check /var/adm/syslog and /var/adm/daemon.
-        Could be a bug in the ipppd.
-
---
-
-Q12: How can I reduce login delay?
-
-A: Log a login session ('debug' log) and check which options 
-  your remote side rejects. Next time configure your ipppd
-  to not negotiate these options. Another 'side effect' is, that
-  this increases redundancy. (e.g your remote side is buggy and
-  rejects options in a wrong way).
-
-
-
 
 
 Again, keep in mind that this list assumes you are already functionally
 running a Linux kernel.  Also, not all tools are necessary on all
-systems; obviously, if you don't have any ISDN hardware, for example,
-you probably needn't concern yourself with isdn4k-utils.
+systems; obviously, if you don't have any PC Card hardware, for example,
+you probably needn't concern yourself with pcmciautils.
 
 ====================== ===============  ========================================
         Program        Minimal version       Command to check the version
 pcmciautils            004              pccardctl -V
 quota-tools            3.09             quota -V
 PPP                    2.4.0            pppd --version
-isdn4k-utils           3.1pre1          isdnctrl 2>&1|grep version
 nfs-utils              1.0.5            showmount --version
 procps                 3.2.0            ps --version
 oprofile               0.9              oprofiled --version
 
 as root.
 
-Isdn4k-utils
-------------
-
-Due to changes in the length of the phone number field, isdn4k-utils
-needs to be recompiled or (preferably) upgraded.
-
 NFS-utils
 ---------
 
 
 - <ftp://ftp.samba.org/pub/ppp/>
 
-Isdn4k-utils
-------------
-
-- <ftp://ftp.isdn4linux.de/pub/isdn4linux/utils/>
-
 NFS-utils
 ---------
 
 
 S:     Maintained
 F:     Documentation/isdn/
 F:     drivers/isdn/
-F:     include/linux/isdn.h
 F:     include/linux/isdn/
-F:     include/uapi/linux/isdn.h
 F:     include/uapi/linux/isdn/
 
 IT87 HARDWARE MONITORING DRIVER
 
 
 if ISDN
 
-menuconfig ISDN_I4L
-       tristate "Old ISDN4Linux (deprecated)"
-       depends on TTY
-       ---help---
-         This driver allows you to use an ISDN adapter for networking
-         connections and as dialin/out device.  The isdn-tty's have a built
-         in AT-compatible modem emulator.  Network devices support autodial,
-         channel-bundling, callback and caller-authentication without having
-         a daemon running.  A reduced T.70 protocol is supported with tty's
-         suitable for German BTX.  On D-Channel, the protocols EDSS1
-         (Euro-ISDN) and 1TR6 (German style) are supported.  See
-         <file:Documentation/isdn/README> for more information.
-
-         ISDN support in the linux kernel is moving towards a new API,
-         called CAPI (Common ISDN Application Programming Interface).
-         Therefore the old ISDN4Linux layer will eventually become obsolete.
-         It is still available, though, for use with adapters that are not
-         supported by the new CAPI subsystem yet.
-
-source "drivers/isdn/i4l/Kconfig"
-
 menuconfig ISDN_CAPI
        tristate "CAPI 2.0 subsystem"
        help
 
 source "drivers/isdn/mISDN/Kconfig"
 
-config ISDN_HDLC
-       tristate
-       select CRC_CCITT
-       select BITREVERSE
-
 endif # ISDN
 
 obj-$(CONFIG_ISDN_CAPI)                        += capi/
 obj-$(CONFIG_MISDN)                    += mISDN/
 obj-$(CONFIG_ISDN)                     += hardware/
-obj-$(CONFIG_ISDN_DIVERSION)           += divert/
-obj-$(CONFIG_ISDN_DRV_LOOP)            += isdnloop/
 obj-$(CONFIG_HYSDN)                    += hysdn/
 obj-$(CONFIG_ISDN_DRV_GIGASET)         += gigaset/
 
          device.  If you want to use pppd with pppdcapiplugin to dial up to
          your ISP, say Y here.
 
-config ISDN_CAPI_CAPIDRV
-       tristate "CAPI2.0 capidrv interface support"
-       depends on ISDN_I4L
-       help
-         This option provides the glue code to hook up CAPI driven cards to
-         the legacy isdn4linux link layer.  If you have a card which is
-         supported by a CAPI driver, but still want to use old features like
-         ippp interfaces or ttyI emulation, say Y/M here.
-
 config ISDN_CAPI_CAPIDRV_VERBOSE
        bool "Verbose reason code reporting"
        depends on ISDN_CAPI_CAPIDRV
 
+++ /dev/null
-/* $Id: capidrv.c,v 1.1.2.2 2004/01/12 23:17:24 keil Exp $
- *
- * ISDN4Linux Driver, using capi20 interface (kernelcapi)
- *
- * Copyright 1997 by Carsten Paeth <calle@calle.de>
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#include <linux/compiler.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-#include <linux/fcntl.h>
-#include <linux/fs.h>
-#include <linux/signal.h>
-#include <linux/mm.h>
-#include <linux/timer.h>
-#include <linux/wait.h>
-#include <linux/skbuff.h>
-#include <linux/isdn.h>
-#include <linux/isdnif.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/capi.h>
-#include <linux/kernelcapi.h>
-#include <linux/ctype.h>
-#include <linux/init.h>
-#include <linux/moduleparam.h>
-
-#include <linux/isdn/capiutil.h>
-#include <linux/isdn/capicmd.h>
-#include "capidrv.h"
-
-static int debugmode = 0;
-
-MODULE_DESCRIPTION("CAPI4Linux: Interface to ISDN4Linux");
-MODULE_AUTHOR("Carsten Paeth");
-MODULE_LICENSE("GPL");
-module_param(debugmode, uint, S_IRUGO | S_IWUSR);
-
-/* -------- type definitions ----------------------------------------- */
-
-
-struct capidrv_contr {
-
-       struct capidrv_contr *next;
-       struct module *owner;
-       u32 contrnr;
-       char name[20];
-
-       /*
-        * for isdn4linux
-        */
-       isdn_if interface;
-       int myid;
-
-       /*
-        * LISTEN state
-        */
-       int state;
-       u32 cipmask;
-       u32 cipmask2;
-       struct timer_list listentimer;
-
-       /*
-        * ID of capi message sent
-        */
-       u16 msgid;
-
-       /*
-        * B-Channels
-        */
-       int nbchan;
-       struct capidrv_bchan {
-               struct capidrv_contr *contr;
-               u8 msn[ISDN_MSNLEN];
-               int l2;
-               int l3;
-               u8 num[ISDN_MSNLEN];
-               u8 mynum[ISDN_MSNLEN];
-               int si1;
-               int si2;
-               int incoming;
-               int disconnecting;
-               struct capidrv_plci {
-                       struct capidrv_plci *next;
-                       u32 plci;
-                       u32 ncci;       /* ncci for CONNECT_ACTIVE_IND */
-                       u16 msgid;      /* to identfy CONNECT_CONF */
-                       int chan;
-                       int state;
-                       int leasedline;
-                       struct capidrv_ncci {
-                               struct capidrv_ncci *next;
-                               struct capidrv_plci *plcip;
-                               u32 ncci;
-                               u16 msgid;      /* to identfy CONNECT_B3_CONF */
-                               int chan;
-                               int state;
-                               int oldstate;
-                               /* */
-                               u16 datahandle;
-                               struct ncci_datahandle_queue {
-                                       struct ncci_datahandle_queue *next;
-                                       u16                         datahandle;
-                                       int                           len;
-                               } *ackqueue;
-                       } *ncci_list;
-               } *plcip;
-               struct capidrv_ncci *nccip;
-       } *bchans;
-
-       struct capidrv_plci *plci_list;
-
-       /* for q931 data */
-       u8  q931_buf[4096];
-       u8 *q931_read;
-       u8 *q931_write;
-       u8 *q931_end;
-};
-
-
-struct capidrv_data {
-       struct capi20_appl ap;
-       int ncontr;
-       struct capidrv_contr *contr_list;
-};
-
-typedef struct capidrv_plci capidrv_plci;
-typedef struct capidrv_ncci capidrv_ncci;
-typedef struct capidrv_contr capidrv_contr;
-typedef struct capidrv_data capidrv_data;
-typedef struct capidrv_bchan capidrv_bchan;
-
-/* -------- data definitions ----------------------------------------- */
-
-static capidrv_data global;
-static DEFINE_SPINLOCK(global_lock);
-
-static void handle_dtrace_data(capidrv_contr *card,
-                              int send, int level2, u8 *data, u16 len);
-
-/* -------- convert functions ---------------------------------------- */
-
-static inline u32 b1prot(int l2, int l3)
-{
-       switch (l2) {
-       case ISDN_PROTO_L2_X75I:
-       case ISDN_PROTO_L2_X75UI:
-       case ISDN_PROTO_L2_X75BUI:
-               return 0;
-       case ISDN_PROTO_L2_HDLC:
-       default:
-               return 0;
-       case ISDN_PROTO_L2_TRANS:
-               return 1;
-       case ISDN_PROTO_L2_V11096:
-       case ISDN_PROTO_L2_V11019:
-       case ISDN_PROTO_L2_V11038:
-               return 2;
-       case ISDN_PROTO_L2_FAX:
-               return 4;
-       case ISDN_PROTO_L2_MODEM:
-               return 8;
-       }
-}
-
-static inline u32 b2prot(int l2, int l3)
-{
-       switch (l2) {
-       case ISDN_PROTO_L2_X75I:
-       case ISDN_PROTO_L2_X75UI:
-       case ISDN_PROTO_L2_X75BUI:
-       default:
-               return 0;
-       case ISDN_PROTO_L2_HDLC:
-       case ISDN_PROTO_L2_TRANS:
-       case ISDN_PROTO_L2_V11096:
-       case ISDN_PROTO_L2_V11019:
-       case ISDN_PROTO_L2_V11038:
-       case ISDN_PROTO_L2_MODEM:
-               return 1;
-       case ISDN_PROTO_L2_FAX:
-               return 4;
-       }
-}
-
-static inline u32 b3prot(int l2, int l3)
-{
-       switch (l2) {
-       case ISDN_PROTO_L2_X75I:
-       case ISDN_PROTO_L2_X75UI:
-       case ISDN_PROTO_L2_X75BUI:
-       case ISDN_PROTO_L2_HDLC:
-       case ISDN_PROTO_L2_TRANS:
-       case ISDN_PROTO_L2_V11096:
-       case ISDN_PROTO_L2_V11019:
-       case ISDN_PROTO_L2_V11038:
-       case ISDN_PROTO_L2_MODEM:
-       default:
-               return 0;
-       case ISDN_PROTO_L2_FAX:
-               return 4;
-       }
-}
-
-static _cstruct b1config_async_v110(u16 rate)
-{
-       /* CAPI-Spec "B1 Configuration" */
-       static unsigned char buf[9];
-       buf[0] = 8; /* len */
-       /* maximum bitrate */
-       buf[1] = rate & 0xff; buf[2] = (rate >> 8) & 0xff;
-       buf[3] = 8; buf[4] = 0; /* 8 bits per character */
-       buf[5] = 0; buf[6] = 0; /* parity none */
-       buf[7] = 0; buf[8] = 0; /* 1 stop bit */
-       return buf;
-}
-
-static _cstruct b1config(int l2, int l3)
-{
-       switch (l2) {
-       case ISDN_PROTO_L2_X75I:
-       case ISDN_PROTO_L2_X75UI:
-       case ISDN_PROTO_L2_X75BUI:
-       case ISDN_PROTO_L2_HDLC:
-       case ISDN_PROTO_L2_TRANS:
-       default:
-               return NULL;
-       case ISDN_PROTO_L2_V11096:
-               return b1config_async_v110(9600);
-       case ISDN_PROTO_L2_V11019:
-               return b1config_async_v110(19200);
-       case ISDN_PROTO_L2_V11038:
-               return b1config_async_v110(38400);
-       }
-}
-
-static inline u16 si2cip(u8 si1, u8 si2)
-{
-       static const u8 cip[17][5] =
-               {
-                       /*  0  1  2  3  4  */
-                       {0, 0, 0, 0, 0},        /*0 */
-                       {16, 16, 4, 26, 16},    /*1 */
-                       {17, 17, 17, 4, 4},     /*2 */
-                       {2, 2, 2, 2, 2},        /*3 */
-                       {18, 18, 18, 18, 18},   /*4 */
-                       {2, 2, 2, 2, 2},        /*5 */
-                       {0, 0, 0, 0, 0},        /*6 */
-                       {2, 2, 2, 2, 2},        /*7 */
-                       {2, 2, 2, 2, 2},        /*8 */
-                       {21, 21, 21, 21, 21},   /*9 */
-                       {19, 19, 19, 19, 19},   /*10 */
-                       {0, 0, 0, 0, 0},        /*11 */
-                       {0, 0, 0, 0, 0},        /*12 */
-                       {0, 0, 0, 0, 0},        /*13 */
-                       {0, 0, 0, 0, 0},        /*14 */
-                       {22, 22, 22, 22, 22},   /*15 */
-                       {27, 27, 27, 28, 27}    /*16 */
-               };
-       if (si1 > 16)
-               si1 = 0;
-       if (si2 > 4)
-               si2 = 0;
-
-       return (u16) cip[si1][si2];
-}
-
-static inline u8 cip2si1(u16 cipval)
-{
-       static const u8 si[32] =
-               {7, 1, 7, 7, 1, 1, 7, 7,        /*0-7 */
-                7, 1, 0, 0, 0, 0, 0, 0,        /*8-15 */
-                1, 2, 4, 10, 9, 9, 15, 7,      /*16-23 */
-                7, 7, 1, 16, 16, 0, 0, 0};     /*24-31 */
-
-       if (cipval > 31)
-               cipval = 0;     /* .... */
-       return si[cipval];
-}
-
-static inline u8 cip2si2(u16 cipval)
-{
-       static const u8 si[32] =
-               {0, 0, 0, 0, 2, 3, 0, 0,        /*0-7 */
-                0, 3, 0, 0, 0, 0, 0, 0,        /*8-15 */
-                1, 2, 0, 0, 9, 0, 0, 0,        /*16-23 */
-                0, 0, 3, 2, 3, 0, 0, 0};       /*24-31 */
-
-       if (cipval > 31)
-               cipval = 0;     /* .... */
-       return si[cipval];
-}
-
-
-/* -------- controller management ------------------------------------- */
-
-static inline capidrv_contr *findcontrbydriverid(int driverid)
-{
-       unsigned long flags;
-       capidrv_contr *p;
-
-       spin_lock_irqsave(&global_lock, flags);
-       for (p = global.contr_list; p; p = p->next)
-               if (p->myid == driverid)
-                       break;
-       spin_unlock_irqrestore(&global_lock, flags);
-       return p;
-}
-
-static capidrv_contr *findcontrbynumber(u32 contr)
-{
-       unsigned long flags;
-       capidrv_contr *p = global.contr_list;
-
-       spin_lock_irqsave(&global_lock, flags);
-       for (p = global.contr_list; p; p = p->next)
-               if (p->contrnr == contr)
-                       break;
-       spin_unlock_irqrestore(&global_lock, flags);
-       return p;
-}
-
-
-/* -------- plci management ------------------------------------------ */
-
-static capidrv_plci *new_plci(capidrv_contr *card, int chan)
-{
-       capidrv_plci *plcip;
-
-       plcip = kzalloc(sizeof(capidrv_plci), GFP_ATOMIC);
-
-       if (plcip == NULL)
-               return NULL;
-
-       plcip->state = ST_PLCI_NONE;
-       plcip->plci = 0;
-       plcip->msgid = 0;
-       plcip->chan = chan;
-       plcip->next = card->plci_list;
-       card->plci_list = plcip;
-       card->bchans[chan].plcip = plcip;
-
-       return plcip;
-}
-
-static capidrv_plci *find_plci_by_plci(capidrv_contr *card, u32 plci)
-{
-       capidrv_plci *p;
-       for (p = card->plci_list; p; p = p->next)
-               if (p->plci == plci)
-                       return p;
-       return NULL;
-}
-
-static capidrv_plci *find_plci_by_msgid(capidrv_contr *card, u16 msgid)
-{
-       capidrv_plci *p;
-       for (p = card->plci_list; p; p = p->next)
-               if (p->msgid == msgid)
-                       return p;
-       return NULL;
-}
-
-static capidrv_plci *find_plci_by_ncci(capidrv_contr *card, u32 ncci)
-{
-       capidrv_plci *p;
-       for (p = card->plci_list; p; p = p->next)
-               if (p->plci == (ncci & 0xffff))
-                       return p;
-       return NULL;
-}
-
-static void free_plci(capidrv_contr *card, capidrv_plci *plcip)
-{
-       capidrv_plci **pp;
-
-       for (pp = &card->plci_list; *pp; pp = &(*pp)->next) {
-               if (*pp == plcip) {
-                       *pp = (*pp)->next;
-                       card->bchans[plcip->chan].plcip = NULL;
-                       card->bchans[plcip->chan].disconnecting = 0;
-                       card->bchans[plcip->chan].incoming = 0;
-                       kfree(plcip);
-                       return;
-               }
-       }
-       printk(KERN_ERR "capidrv-%d: free_plci %p (0x%x) not found, Huh?\n",
-              card->contrnr, plcip, plcip->plci);
-}
-
-/* -------- ncci management ------------------------------------------ */
-
-static inline capidrv_ncci *new_ncci(capidrv_contr *card,
-                                    capidrv_plci *plcip,
-                                    u32 ncci)
-{
-       capidrv_ncci *nccip;
-
-       nccip = kzalloc(sizeof(capidrv_ncci), GFP_ATOMIC);
-
-       if (nccip == NULL)
-               return NULL;
-
-       nccip->ncci = ncci;
-       nccip->state = ST_NCCI_NONE;
-       nccip->plcip = plcip;
-       nccip->chan = plcip->chan;
-       nccip->datahandle = 0;
-
-       nccip->next = plcip->ncci_list;
-       plcip->ncci_list = nccip;
-
-       card->bchans[plcip->chan].nccip = nccip;
-
-       return nccip;
-}
-
-static inline capidrv_ncci *find_ncci(capidrv_contr *card, u32 ncci)
-{
-       capidrv_plci *plcip;
-       capidrv_ncci *p;
-
-       if ((plcip = find_plci_by_ncci(card, ncci)) == NULL)
-               return NULL;
-
-       for (p = plcip->ncci_list; p; p = p->next)
-               if (p->ncci == ncci)
-                       return p;
-       return NULL;
-}
-
-static inline capidrv_ncci *find_ncci_by_msgid(capidrv_contr *card,
-                                              u32 ncci, u16 msgid)
-{
-       capidrv_plci *plcip;
-       capidrv_ncci *p;
-
-       if ((plcip = find_plci_by_ncci(card, ncci)) == NULL)
-               return NULL;
-
-       for (p = plcip->ncci_list; p; p = p->next)
-               if (p->msgid == msgid)
-                       return p;
-       return NULL;
-}
-
-static void free_ncci(capidrv_contr *card, struct capidrv_ncci *nccip)
-{
-       struct capidrv_ncci **pp;
-
-       for (pp = &(nccip->plcip->ncci_list); *pp; pp = &(*pp)->next) {
-               if (*pp == nccip) {
-                       *pp = (*pp)->next;
-                       break;
-               }
-       }
-       card->bchans[nccip->chan].nccip = NULL;
-       kfree(nccip);
-}
-
-static int capidrv_add_ack(struct capidrv_ncci *nccip,
-                          u16 datahandle, int len)
-{
-       struct ncci_datahandle_queue *n, **pp;
-
-       n = kmalloc(sizeof(struct ncci_datahandle_queue), GFP_ATOMIC);
-       if (!n) {
-               printk(KERN_ERR "capidrv: kmalloc ncci_datahandle failed\n");
-               return -1;
-       }
-       n->next = NULL;
-       n->datahandle = datahandle;
-       n->len = len;
-       for (pp = &nccip->ackqueue; *pp; pp = &(*pp)->next);
-       *pp = n;
-       return 0;
-}
-
-static int capidrv_del_ack(struct capidrv_ncci *nccip, u16 datahandle)
-{
-       struct ncci_datahandle_queue **pp, *p;
-       int len;
-
-       for (pp = &nccip->ackqueue; *pp; pp = &(*pp)->next) {
-               if ((*pp)->datahandle == datahandle) {
-                       p = *pp;
-                       len = p->len;
-                       *pp = (*pp)->next;
-                       kfree(p);
-                       return len;
-               }
-       }
-       return -1;
-}
-
-/* -------- convert and send capi message ---------------------------- */
-
-static void send_message(capidrv_contr *card, _cmsg *cmsg)
-{
-       struct sk_buff *skb;
-       size_t len;
-
-       if (capi_cmsg2message(cmsg, cmsg->buf)) {
-               printk(KERN_ERR "capidrv::send_message: parser failure\n");
-               return;
-       }
-       len = CAPIMSG_LEN(cmsg->buf);
-       skb = alloc_skb(len, GFP_ATOMIC);
-       if (!skb) {
-               printk(KERN_ERR "capidrv::send_message: can't allocate mem\n");
-               return;
-       }
-       skb_put_data(skb, cmsg->buf, len);
-       if (capi20_put_message(&global.ap, skb) != CAPI_NOERROR)
-               kfree_skb(skb);
-}
-
-/* -------- state machine -------------------------------------------- */
-
-struct listenstatechange {
-       int actstate;
-       int nextstate;
-       int event;
-};
-
-static struct listenstatechange listentable[] =
-{
-       {ST_LISTEN_NONE, ST_LISTEN_WAIT_CONF, EV_LISTEN_REQ},
-       {ST_LISTEN_ACTIVE, ST_LISTEN_ACTIVE_WAIT_CONF, EV_LISTEN_REQ},
-       {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_ERROR},
-       {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_ERROR},
-       {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY},
-       {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY},
-       {ST_LISTEN_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK},
-       {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK},
-       {},
-};
-
-static void listen_change_state(capidrv_contr *card, int event)
-{
-       struct listenstatechange *p = listentable;
-       while (p->event) {
-               if (card->state == p->actstate && p->event == event) {
-                       if (debugmode)
-                               printk(KERN_DEBUG "capidrv-%d: listen_change_state %d -> %d\n",
-                                      card->contrnr, card->state, p->nextstate);
-                       card->state = p->nextstate;
-                       return;
-               }
-               p++;
-       }
-       printk(KERN_ERR "capidrv-%d: listen_change_state state=%d event=%d ????\n",
-              card->contrnr, card->state, event);
-
-}
-
-/* ------------------------------------------------------------------ */
-
-static void p0(capidrv_contr *card, capidrv_plci *plci)
-{
-       isdn_ctrl cmd;
-
-       card->bchans[plci->chan].contr = NULL;
-       cmd.command = ISDN_STAT_DHUP;
-       cmd.driver = card->myid;
-       cmd.arg = plci->chan;
-       card->interface.statcallb(&cmd);
-       free_plci(card, plci);
-}
-
-/* ------------------------------------------------------------------ */
-
-struct plcistatechange {
-       int actstate;
-       int nextstate;
-       int event;
-       void (*changefunc)(capidrv_contr *card, capidrv_plci *plci);
-};
-
-static struct plcistatechange plcitable[] =
-{
-       /* P-0 */
-       {ST_PLCI_NONE, ST_PLCI_OUTGOING, EV_PLCI_CONNECT_REQ, NULL},
-       {ST_PLCI_NONE, ST_PLCI_ALLOCATED, EV_PLCI_FACILITY_IND_UP, NULL},
-       {ST_PLCI_NONE, ST_PLCI_INCOMING, EV_PLCI_CONNECT_IND, NULL},
-       {ST_PLCI_NONE, ST_PLCI_RESUMEING, EV_PLCI_RESUME_REQ, NULL},
-       /* P-0.1 */
-       {ST_PLCI_OUTGOING, ST_PLCI_NONE, EV_PLCI_CONNECT_CONF_ERROR, p0},
-       {ST_PLCI_OUTGOING, ST_PLCI_ALLOCATED, EV_PLCI_CONNECT_CONF_OK, NULL},
-       /* P-1 */
-       {ST_PLCI_ALLOCATED, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, NULL},
-       {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, NULL},
-       {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, NULL},
-       {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, NULL},
-       /* P-ACT */
-       {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, NULL},
-       {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, NULL},
-       {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, NULL},
-       {ST_PLCI_ACTIVE, ST_PLCI_HELD, EV_PLCI_HOLD_IND, NULL},
-       {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_SUSPEND_IND, NULL},
-       /* P-2 */
-       {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, NULL},
-       {ST_PLCI_INCOMING, ST_PLCI_FACILITY_IND, EV_PLCI_FACILITY_IND_UP, NULL},
-       {ST_PLCI_INCOMING, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_RESP, NULL},
-       {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, NULL},
-       {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, NULL},
-       {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, NULL},
-       {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CD_IND, NULL},
-       /* P-3 */
-       {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, NULL},
-       {ST_PLCI_FACILITY_IND, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_ACTIVE_IND, NULL},
-       {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, NULL},
-       {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, NULL},
-       {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, NULL},
-       /* P-4 */
-       {ST_PLCI_ACCEPTING, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, NULL},
-       {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, NULL},
-       {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, NULL},
-       {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, NULL},
-       /* P-5 */
-       {ST_PLCI_DISCONNECTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, NULL},
-       /* P-6 */
-       {ST_PLCI_DISCONNECTED, ST_PLCI_NONE, EV_PLCI_DISCONNECT_RESP, p0},
-       /* P-0.Res */
-       {ST_PLCI_RESUMEING, ST_PLCI_NONE, EV_PLCI_RESUME_CONF_ERROR, p0},
-       {ST_PLCI_RESUMEING, ST_PLCI_RESUME, EV_PLCI_RESUME_CONF_OK, NULL},
-       /* P-RES */
-       {ST_PLCI_RESUME, ST_PLCI_ACTIVE, EV_PLCI_RESUME_IND, NULL},
-       /* P-HELD */
-       {ST_PLCI_HELD, ST_PLCI_ACTIVE, EV_PLCI_RETRIEVE_IND, NULL},
-       {},
-};
-
-static void plci_change_state(capidrv_contr *card, capidrv_plci *plci, int event)
-{
-       struct plcistatechange *p = plcitable;
-       while (p->event) {
-               if (plci->state == p->actstate && p->event == event) {
-                       if (debugmode)
-                               printk(KERN_DEBUG "capidrv-%d: plci_change_state:0x%x %d -> %d\n",
-                                      card->contrnr, plci->plci, plci->state, p->nextstate);
-                       plci->state = p->nextstate;
-                       if (p->changefunc)
-                               p->changefunc(card, plci);
-                       return;
-               }
-               p++;
-       }
-       printk(KERN_ERR "capidrv-%d: plci_change_state:0x%x state=%d event=%d ????\n",
-              card->contrnr, plci->plci, plci->state, event);
-}
-
-/* ------------------------------------------------------------------ */
-
-static _cmsg cmsg;
-
-static void n0(capidrv_contr *card, capidrv_ncci *ncci)
-{
-       isdn_ctrl cmd;
-
-       capi_fill_DISCONNECT_REQ(&cmsg,
-                                global.ap.applid,
-                                card->msgid++,
-                                ncci->plcip->plci,
-                                NULL,  /* BChannelinformation */
-                                NULL,  /* Keypadfacility */
-                                NULL,  /* Useruserdata */   /* $$$$ */
-                                NULL   /* Facilitydataarray */
-               );
-       plci_change_state(card, ncci->plcip, EV_PLCI_DISCONNECT_REQ);
-       send_message(card, &cmsg);
-
-       cmd.command = ISDN_STAT_BHUP;
-       cmd.driver = card->myid;
-       cmd.arg = ncci->chan;
-       card->interface.statcallb(&cmd);
-       free_ncci(card, ncci);
-}
-
-/* ------------------------------------------------------------------ */
-
-struct nccistatechange {
-       int actstate;
-       int nextstate;
-       int event;
-       void (*changefunc)(capidrv_contr *card, capidrv_ncci *ncci);
-};
-
-static struct nccistatechange nccitable[] =
-{
-       /* N-0 */
-       {ST_NCCI_NONE, ST_NCCI_OUTGOING, EV_NCCI_CONNECT_B3_REQ, NULL},
-       {ST_NCCI_NONE, ST_NCCI_INCOMING, EV_NCCI_CONNECT_B3_IND, NULL},
-       /* N-0.1 */
-       {ST_NCCI_OUTGOING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_CONF_OK, NULL},
-       {ST_NCCI_OUTGOING, ST_NCCI_NONE, EV_NCCI_CONNECT_B3_CONF_ERROR, n0},
-       /* N-1 */
-       {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_CONNECT_B3_REJECT, NULL},
-       {ST_NCCI_INCOMING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_RESP, NULL},
-       {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, NULL},
-       {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, NULL},
-       /* N-2 */
-       {ST_NCCI_ALLOCATED, ST_NCCI_ACTIVE, EV_NCCI_CONNECT_B3_ACTIVE_IND, NULL},
-       {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, NULL},
-       {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, NULL},
-       /* N-ACT */
-       {ST_NCCI_ACTIVE, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, NULL},
-       {ST_NCCI_ACTIVE, ST_NCCI_RESETING, EV_NCCI_RESET_B3_REQ, NULL},
-       {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, NULL},
-       {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, NULL},
-       /* N-3 */
-       {ST_NCCI_RESETING, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, NULL},
-       {ST_NCCI_RESETING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, NULL},
-       {ST_NCCI_RESETING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, NULL},
-       /* N-4 */
-       {ST_NCCI_DISCONNECTING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, NULL},
-       {ST_NCCI_DISCONNECTING, ST_NCCI_PREVIOUS, EV_NCCI_DISCONNECT_B3_CONF_ERROR, NULL},
-       /* N-5 */
-       {ST_NCCI_DISCONNECTED, ST_NCCI_NONE, EV_NCCI_DISCONNECT_B3_RESP, n0},
-       {},
-};
-
-static void ncci_change_state(capidrv_contr *card, capidrv_ncci *ncci, int event)
-{
-       struct nccistatechange *p = nccitable;
-       while (p->event) {
-               if (ncci->state == p->actstate && p->event == event) {
-                       if (debugmode)
-                               printk(KERN_DEBUG "capidrv-%d: ncci_change_state:0x%x %d -> %d\n",
-                                      card->contrnr, ncci->ncci, ncci->state, p->nextstate);
-                       if (p->nextstate == ST_NCCI_PREVIOUS) {
-                               ncci->state = ncci->oldstate;
-                               ncci->oldstate = p->actstate;
-                       } else {
-                               ncci->oldstate = p->actstate;
-                               ncci->state = p->nextstate;
-                       }
-                       if (p->changefunc)
-                               p->changefunc(card, ncci);
-                       return;
-               }
-               p++;
-       }
-       printk(KERN_ERR "capidrv-%d: ncci_change_state:0x%x state=%d event=%d ????\n",
-              card->contrnr, ncci->ncci, ncci->state, event);
-}
-
-/* ------------------------------------------------------------------- */
-
-static inline int new_bchan(capidrv_contr *card)
-{
-       int i;
-       for (i = 0; i < card->nbchan; i++) {
-               if (card->bchans[i].plcip == NULL) {
-                       card->bchans[i].disconnecting = 0;
-                       return i;
-               }
-       }
-       return -1;
-}
-
-/* ------------------------------------------------------------------- */
-static char *capi_info2str(u16 reason)
-{
-#ifndef CONFIG_ISDN_CAPI_CAPIDRV_VERBOSE
-       return "..";
-#else
-       switch (reason) {
-
-/*-- informative values (corresponding message was processed) -----*/
-       case 0x0001:
-               return "NCPI not supported by current protocol, NCPI ignored";
-       case 0x0002:
-               return "Flags not supported by current protocol, flags ignored";
-       case 0x0003:
-               return "Alert already sent by another application";
-
-/*-- error information concerning CAPI_REGISTER -----*/
-       case 0x1001:
-               return "Too many applications";
-       case 0x1002:
-               return "Logical block size too small, must be at least 128 Bytes";
-       case 0x1003:
-               return "Buffer exceeds 64 kByte";
-       case 0x1004:
-               return "Message buffer size too small, must be at least 1024 Bytes";
-       case 0x1005:
-               return "Max. number of logical connections not supported";
-       case 0x1006:
-               return "Reserved";
-       case 0x1007:
-               return "The message could not be accepted because of an internal busy condition";
-       case 0x1008:
-               return "OS resource error (no memory ?)";
-       case 0x1009:
-               return "CAPI not installed";
-       case 0x100A:
-               return "Controller does not support external equipment";
-       case 0x100B:
-               return "Controller does only support external equipment";
-
-/*-- error information concerning message exchange functions -----*/
-       case 0x1101:
-               return "Illegal application number";
-       case 0x1102:
-               return "Illegal command or subcommand or message length less than 12 bytes";
-       case 0x1103:
-               return "The message could not be accepted because of a queue full condition !! The error code does not imply that CAPI cannot receive messages directed to another controller, PLCI or NCCI";
-       case 0x1104:
-               return "Queue is empty";
-       case 0x1105:
-               return "Queue overflow, a message was lost !! This indicates a configuration error. The only recovery from this error is to perform a CAPI_RELEASE";
-       case 0x1106:
-               return "Unknown notification parameter";
-       case 0x1107:
-               return "The Message could not be accepted because of an internal busy condition";
-       case 0x1108:
-               return "OS Resource error (no memory ?)";
-       case 0x1109:
-               return "CAPI not installed";
-       case 0x110A:
-               return "Controller does not support external equipment";
-       case 0x110B:
-               return "Controller does only support external equipment";
-
-/*-- error information concerning resource / coding problems -----*/
-       case 0x2001:
-               return "Message not supported in current state";
-       case 0x2002:
-               return "Illegal Controller / PLCI / NCCI";
-       case 0x2003:
-               return "Out of PLCI";
-       case 0x2004:
-               return "Out of NCCI";
-       case 0x2005:
-               return "Out of LISTEN";
-       case 0x2006:
-               return "Out of FAX resources (protocol T.30)";
-       case 0x2007:
-               return "Illegal message parameter coding";
-
-/*-- error information concerning requested services  -----*/
-       case 0x3001:
-               return "B1 protocol not supported";
-       case 0x3002:
-               return "B2 protocol not supported";
-       case 0x3003:
-               return "B3 protocol not supported";
-       case 0x3004:
-               return "B1 protocol parameter not supported";
-       case 0x3005:
-               return "B2 protocol parameter not supported";
-       case 0x3006:
-               return "B3 protocol parameter not supported";
-       case 0x3007:
-               return "B protocol combination not supported";
-       case 0x3008:
-               return "NCPI not supported";
-       case 0x3009:
-               return "CIP Value unknown";
-       case 0x300A:
-               return "Flags not supported (reserved bits)";
-       case 0x300B:
-               return "Facility not supported";
-       case 0x300C:
-               return "Data length not supported by current protocol";
-       case 0x300D:
-               return "Reset procedure not supported by current protocol";
-
-/*-- informations about the clearing of a physical connection -----*/
-       case 0x3301:
-               return "Protocol error layer 1 (broken line or B-channel removed by signalling protocol)";
-       case 0x3302:
-               return "Protocol error layer 2";
-       case 0x3303:
-               return "Protocol error layer 3";
-       case 0x3304:
-               return "Another application got that call";
-/*-- T.30 specific reasons -----*/
-       case 0x3311:
-               return "Connecting not successful (remote station is no FAX G3 machine)";
-       case 0x3312:
-               return "Connecting not successful (training error)";
-       case 0x3313:
-               return "Disconnected before transfer (remote station does not support transfer mode, e.g. resolution)";
-       case 0x3314:
-               return "Disconnected during transfer (remote abort)";
-       case 0x3315:
-               return "Disconnected during transfer (remote procedure error, e.g. unsuccessful repetition of T.30 commands)";
-       case 0x3316:
-               return "Disconnected during transfer (local tx data underrun)";
-       case 0x3317:
-               return "Disconnected during transfer (local rx data overflow)";
-       case 0x3318:
-               return "Disconnected during transfer (local abort)";
-       case 0x3319:
-               return "Illegal parameter coding (e.g. SFF coding error)";
-
-/*-- disconnect causes from the network according to ETS 300 102-1/Q.931 -----*/
-       case 0x3481: return "Unallocated (unassigned) number";
-       case 0x3482: return "No route to specified transit network";
-       case 0x3483: return "No route to destination";
-       case 0x3486: return "Channel unacceptable";
-       case 0x3487:
-               return "Call awarded and being delivered in an established channel";
-       case 0x3490: return "Normal call clearing";
-       case 0x3491: return "User busy";
-       case 0x3492: return "No user responding";
-       case 0x3493: return "No answer from user (user alerted)";
-       case 0x3495: return "Call rejected";
-       case 0x3496: return "Number changed";
-       case 0x349A: return "Non-selected user clearing";
-       case 0x349B: return "Destination out of order";
-       case 0x349C: return "Invalid number format";
-       case 0x349D: return "Facility rejected";
-       case 0x349E: return "Response to STATUS ENQUIRY";
-       case 0x349F: return "Normal, unspecified";
-       case 0x34A2: return "No circuit / channel available";
-       case 0x34A6: return "Network out of order";
-       case 0x34A9: return "Temporary failure";
-       case 0x34AA: return "Switching equipment congestion";
-       case 0x34AB: return "Access information discarded";
-       case 0x34AC: return "Requested circuit / channel not available";
-       case 0x34AF: return "Resources unavailable, unspecified";
-       case 0x34B1: return "Quality of service unavailable";
-       case 0x34B2: return "Requested facility not subscribed";
-       case 0x34B9: return "Bearer capability not authorized";
-       case 0x34BA: return "Bearer capability not presently available";
-       case 0x34BF: return "Service or option not available, unspecified";
-       case 0x34C1: return "Bearer capability not implemented";
-       case 0x34C2: return "Channel type not implemented";
-       case 0x34C5: return "Requested facility not implemented";
-       case 0x34C6: return "Only restricted digital information bearer capability is available";
-       case 0x34CF: return "Service or option not implemented, unspecified";
-       case 0x34D1: return "Invalid call reference value";
-       case 0x34D2: return "Identified channel does not exist";
-       case 0x34D3: return "A suspended call exists, but this call identity does not";
-       case 0x34D4: return "Call identity in use";
-       case 0x34D5: return "No call suspended";
-       case 0x34D6: return "Call having the requested call identity has been cleared";
-       case 0x34D8: return "Incompatible destination";
-       case 0x34DB: return "Invalid transit network selection";
-       case 0x34DF: return "Invalid message, unspecified";
-       case 0x34E0: return "Mandatory information element is missing";
-       case 0x34E1: return "Message type non-existent or not implemented";
-       case 0x34E2: return "Message not compatible with call state or message type non-existent or not implemented";
-       case 0x34E3: return "Information element non-existent or not implemented";
-       case 0x34E4: return "Invalid information element contents";
-       case 0x34E5: return "Message not compatible with call state";
-       case 0x34E6: return "Recovery on timer expiry";
-       case 0x34EF: return "Protocol error, unspecified";
-       case 0x34FF: return "Interworking, unspecified";
-
-       default: return "No additional information";
-       }
-#endif
-}
-
-static void handle_controller(_cmsg *cmsg)
-{
-       capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f);
-
-       if (!card) {
-               printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n",
-                      capi_cmd2str(cmsg->Command, cmsg->Subcommand),
-                      cmsg->adr.adrController & 0x7f);
-               return;
-       }
-       switch (CAPICMD(cmsg->Command, cmsg->Subcommand)) {
-
-       case CAPI_LISTEN_CONF:  /* Controller */
-               if (debugmode)
-                       printk(KERN_DEBUG "capidrv-%d: listenconf Info=0x%4x (%s) cipmask=0x%x\n",
-                              card->contrnr, cmsg->Info, capi_info2str(cmsg->Info), card->cipmask);
-               if (cmsg->Info) {
-                       listen_change_state(card, EV_LISTEN_CONF_ERROR);
-               } else if (card->cipmask == 0) {
-                       listen_change_state(card, EV_LISTEN_CONF_EMPTY);
-               } else {
-                       listen_change_state(card, EV_LISTEN_CONF_OK);
-               }
-               break;
-
-       case CAPI_MANUFACTURER_IND:     /* Controller */
-               if (cmsg->ManuID == 0x214D5641
-                   && cmsg->Class == 0
-                   && cmsg->Function == 1) {
-                       u8  *data = cmsg->ManuData + 3;
-                       u16  len = cmsg->ManuData[0];
-                       u16 layer;
-                       int direction;
-                       if (len == 255) {
-                               len = (cmsg->ManuData[1] | (cmsg->ManuData[2] << 8));
-                               data += 2;
-                       }
-                       len -= 2;
-                       layer = ((*(data - 1)) << 8) | *(data - 2);
-                       if (layer & 0x300)
-                               direction = (layer & 0x200) ? 0 : 1;
-                       else direction = (layer & 0x800) ? 0 : 1;
-                       if (layer & 0x0C00) {
-                               if ((layer & 0xff) == 0x80) {
-                                       handle_dtrace_data(card, direction, 1, data, len);
-                                       break;
-                               }
-                       } else if ((layer & 0xff) < 0x80) {
-                               handle_dtrace_data(card, direction, 0, data, len);
-                               break;
-                       }
-                       printk(KERN_INFO "capidrv-%d: %s from controller 0x%x layer 0x%x, ignored\n",
-                              card->contrnr,
-                              capi_cmd2str(cmsg->Command, cmsg->Subcommand),
-                              cmsg->adr.adrController, layer);
-                       break;
-               }
-               goto ignored;
-       case CAPI_MANUFACTURER_CONF:    /* Controller */
-               if (cmsg->ManuID == 0x214D5641) {
-                       char *s = NULL;
-                       switch (cmsg->Class) {
-                       case 0: break;
-                       case 1: s = "unknown class"; break;
-                       case 2: s = "unknown function"; break;
-                       default: s = "unknown error"; break;
-                       }
-                       if (s)
-                               printk(KERN_INFO "capidrv-%d: %s from controller 0x%x function %d: %s\n",
-                                      card->contrnr,
-                                      capi_cmd2str(cmsg->Command, cmsg->Subcommand),
-                                      cmsg->adr.adrController,
-                                      cmsg->Function, s);
-                       break;
-               }
-               goto ignored;
-       case CAPI_FACILITY_IND: /* Controller/plci/ncci */
-               goto ignored;
-       case CAPI_FACILITY_CONF:        /* Controller/plci/ncci */
-               goto ignored;
-       case CAPI_INFO_IND:     /* Controller/plci */
-               goto ignored;
-       case CAPI_INFO_CONF:    /* Controller/plci */
-               goto ignored;
-
-       default:
-               printk(KERN_ERR "capidrv-%d: got %s from controller 0x%x ???",
-                      card->contrnr,
-                      capi_cmd2str(cmsg->Command, cmsg->Subcommand),
-                      cmsg->adr.adrController);
-       }
-       return;
-
-ignored:
-       printk(KERN_INFO "capidrv-%d: %s from controller 0x%x ignored\n",
-              card->contrnr,
-              capi_cmd2str(cmsg->Command, cmsg->Subcommand),
-              cmsg->adr.adrController);
-}
-
-static void handle_incoming_call(capidrv_contr *card, _cmsg *cmsg)
-{
-       capidrv_plci *plcip;
-       capidrv_bchan *bchan;
-       isdn_ctrl cmd;
-       int chan;
-
-       if ((chan = new_bchan(card)) == -1) {
-               printk(KERN_ERR "capidrv-%d: incoming call on not existing bchan ?\n", card->contrnr);
-               return;
-       }
-       bchan = &card->bchans[chan];
-       if ((plcip = new_plci(card, chan)) == NULL) {
-               printk(KERN_ERR "capidrv-%d: incoming call: no memory, sorry.\n", card->contrnr);
-               return;
-       }
-       bchan->incoming = 1;
-       plcip->plci = cmsg->adr.adrPLCI;
-       plci_change_state(card, plcip, EV_PLCI_CONNECT_IND);
-
-       cmd.command = ISDN_STAT_ICALL;
-       cmd.driver = card->myid;
-       cmd.arg = chan;
-       memset(&cmd.parm.setup, 0, sizeof(cmd.parm.setup));
-       strncpy(cmd.parm.setup.phone,
-               cmsg->CallingPartyNumber + 3,
-               cmsg->CallingPartyNumber[0] - 2);
-       strncpy(cmd.parm.setup.eazmsn,
-               cmsg->CalledPartyNumber + 2,
-               cmsg->CalledPartyNumber[0] - 1);
-       cmd.parm.setup.si1 = cip2si1(cmsg->CIPValue);
-       cmd.parm.setup.si2 = cip2si2(cmsg->CIPValue);
-       cmd.parm.setup.plan = cmsg->CallingPartyNumber[1];
-       cmd.parm.setup.screen = cmsg->CallingPartyNumber[2];
-
-       printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s\n",
-              card->contrnr,
-              cmd.parm.setup.phone,
-              cmd.parm.setup.si1,
-              cmd.parm.setup.si2,
-              cmd.parm.setup.eazmsn);
-
-       if (cmd.parm.setup.si1 == 1 && cmd.parm.setup.si2 != 0) {
-               printk(KERN_INFO "capidrv-%d: patching si2=%d to 0 for VBOX\n",
-                      card->contrnr,
-                      cmd.parm.setup.si2);
-               cmd.parm.setup.si2 = 0;
-       }
-
-       switch (card->interface.statcallb(&cmd)) {
-       case 0:
-       case 3:
-               /* No device matching this call.
-                * and isdn_common.c has send a HANGUP command
-                * which is ignored in state ST_PLCI_INCOMING,
-                * so we send RESP to ignore the call
-                */
-               capi_cmsg_answer(cmsg);
-               cmsg->Reject = 1;       /* ignore */
-               plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
-               send_message(card, cmsg);
-               printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s ignored\n",
-                      card->contrnr,
-                      cmd.parm.setup.phone,
-                      cmd.parm.setup.si1,
-                      cmd.parm.setup.si2,
-                      cmd.parm.setup.eazmsn);
-               break;
-       case 1:
-               /* At least one device matching this call (RING on ttyI)
-                * HL-driver may send ALERTING on the D-channel in this
-                * case.
-                * really means: RING on ttyI or a net interface
-                * accepted this call already.
-                *
-                * If the call was accepted, state has already changed,
-                * and CONNECT_RESP already sent.
-                */
-               if (plcip->state == ST_PLCI_INCOMING) {
-                       printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s tty alerting\n",
-                              card->contrnr,
-                              cmd.parm.setup.phone,
-                              cmd.parm.setup.si1,
-                              cmd.parm.setup.si2,
-                              cmd.parm.setup.eazmsn);
-                       capi_fill_ALERT_REQ(cmsg,
-                                           global.ap.applid,
-                                           card->msgid++,
-                                           plcip->plci,        /* adr */
-                                           NULL,/* BChannelinformation */
-                                           NULL,/* Keypadfacility */
-                                           NULL,/* Useruserdata */
-                                           NULL /* Facilitydataarray */
-                               );
-                       plcip->msgid = cmsg->Messagenumber;
-                       send_message(card, cmsg);
-               } else {
-                       printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s on netdev\n",
-                              card->contrnr,
-                              cmd.parm.setup.phone,
-                              cmd.parm.setup.si1,
-                              cmd.parm.setup.si2,
-                              cmd.parm.setup.eazmsn);
-               }
-               break;
-
-       case 2:         /* Call will be rejected. */
-               capi_cmsg_answer(cmsg);
-               cmsg->Reject = 2;       /* reject call, normal call clearing */
-               plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
-               send_message(card, cmsg);
-               break;
-
-       default:
-               /* An error happened. (Invalid parameters for example.) */
-               capi_cmsg_answer(cmsg);
-               cmsg->Reject = 8;       /* reject call,
-                                          destination out of order */
-               plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
-               send_message(card, cmsg);
-               break;
-       }
-       return;
-}
-
-static void handle_plci(_cmsg *cmsg)
-{
-       capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f);
-       capidrv_plci *plcip;
-       isdn_ctrl cmd;
-       _cdebbuf *cdb;
-
-       if (!card) {
-               printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n",
-                      capi_cmd2str(cmsg->Command, cmsg->Subcommand),
-                      cmsg->adr.adrController & 0x7f);
-               return;
-       }
-       switch (CAPICMD(cmsg->Command, cmsg->Subcommand)) {
-
-       case CAPI_DISCONNECT_IND:       /* plci */
-               if (cmsg->Reason) {
-                       printk(KERN_INFO "capidrv-%d: %s reason 0x%x (%s) for plci 0x%x\n",
-                              card->contrnr,
-                              capi_cmd2str(cmsg->Command, cmsg->Subcommand),
-                              cmsg->Reason, capi_info2str(cmsg->Reason), cmsg->adr.adrPLCI);
-               }
-               if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI))) {
-                       capi_cmsg_answer(cmsg);
-                       send_message(card, cmsg);
-                       goto notfound;
-               }
-               card->bchans[plcip->chan].disconnecting = 1;
-               plci_change_state(card, plcip, EV_PLCI_DISCONNECT_IND);
-               capi_cmsg_answer(cmsg);
-               plci_change_state(card, plcip, EV_PLCI_DISCONNECT_RESP);
-               send_message(card, cmsg);
-               break;
-
-       case CAPI_DISCONNECT_CONF:      /* plci */
-               if (cmsg->Info) {
-                       printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n",
-                              card->contrnr,
-                              capi_cmd2str(cmsg->Command, cmsg->Subcommand),
-                              cmsg->Info, capi_info2str(cmsg->Info),
-                              cmsg->adr.adrPLCI);
-               }
-               if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI)))
-                       goto notfound;
-
-               card->bchans[plcip->chan].disconnecting = 1;
-               break;
-
-       case CAPI_ALERT_CONF:   /* plci */
-               if (cmsg->Info) {
-                       printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n",
-                              card->contrnr,
-                              capi_cmd2str(cmsg->Command, cmsg->Subcommand),
-                              cmsg->Info, capi_info2str(cmsg->Info),
-                              cmsg->adr.adrPLCI);
-               }
-               break;
-
-       case CAPI_CONNECT_IND:  /* plci */
-               handle_incoming_call(card, cmsg);
-               break;
-
-       case CAPI_CONNECT_CONF: /* plci */
-               if (cmsg->Info) {
-                       printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n",
-                              card->contrnr,
-                              capi_cmd2str(cmsg->Command, cmsg->Subcommand),
-                              cmsg->Info, capi_info2str(cmsg->Info),
-                              cmsg->adr.adrPLCI);
-               }
-               if (!(plcip = find_plci_by_msgid(card, cmsg->Messagenumber)))
-                       goto notfound;
-
-               plcip->plci = cmsg->adr.adrPLCI;
-               if (cmsg->Info) {
-                       plci_change_state(card, plcip, EV_PLCI_CONNECT_CONF_ERROR);
-               } else {
-                       plci_change_state(card, plcip, EV_PLCI_CONNECT_CONF_OK);
-               }
-               break;
-
-       case CAPI_CONNECT_ACTIVE_IND:   /* plci */
-
-               if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI)))
-                       goto notfound;
-
-               if (card->bchans[plcip->chan].incoming) {
-                       capi_cmsg_answer(cmsg);
-                       plci_change_state(card, plcip, EV_PLCI_CONNECT_ACTIVE_IND);
-                       send_message(card, cmsg);
-               } else {
-                       capidrv_ncci *nccip;
-                       capi_cmsg_answer(cmsg);
-                       send_message(card, cmsg);
-
-                       nccip = new_ncci(card, plcip, cmsg->adr.adrPLCI);
-
-                       if (!nccip) {
-                               printk(KERN_ERR "capidrv-%d: no mem for ncci, sorry\n", card->contrnr);
-                               break;  /* $$$$ */
-                       }
-                       capi_fill_CONNECT_B3_REQ(cmsg,
-                                                global.ap.applid,
-                                                card->msgid++,
-                                                plcip->plci,   /* adr */
-                                                NULL   /* NCPI */
-                               );
-                       nccip->msgid = cmsg->Messagenumber;
-                       plci_change_state(card, plcip,
-                                         EV_PLCI_CONNECT_ACTIVE_IND);
-                       ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_REQ);
-                       send_message(card, cmsg);
-                       cmd.command = ISDN_STAT_DCONN;
-                       cmd.driver = card->myid;
-                       cmd.arg = plcip->chan;
-                       card->interface.statcallb(&cmd);
-               }
-               break;
-
-       case CAPI_INFO_IND:     /* Controller/plci */
-
-               if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI)))
-                       goto notfound;
-
-               if (cmsg->InfoNumber == 0x4000) {
-                       if (cmsg->InfoElement[0] == 4) {
-                               cmd.command = ISDN_STAT_CINF;
-                               cmd.driver = card->myid;
-                               cmd.arg = plcip->chan;
-                               sprintf(cmd.parm.num, "%lu",
-                                       (unsigned long)
-                                       ((u32) cmsg->InfoElement[1]
-                                        | ((u32) (cmsg->InfoElement[2]) << 8)
-                                        | ((u32) (cmsg->InfoElement[3]) << 16)
-                                        | ((u32) (cmsg->InfoElement[4]) << 24)));
-                               card->interface.statcallb(&cmd);
-                               break;
-                       }
-               }
-               cdb = capi_cmsg2str(cmsg);
-               if (cdb) {
-                       printk(KERN_WARNING "capidrv-%d: %s\n",
-                              card->contrnr, cdb->buf);
-                       cdebbuf_free(cdb);
-               } else
-                       printk(KERN_WARNING "capidrv-%d: CAPI_INFO_IND InfoNumber %x not handled\n",
-                              card->contrnr, cmsg->InfoNumber);
-
-               break;
-
-       case CAPI_CONNECT_ACTIVE_CONF:          /* plci */
-               goto ignored;
-       case CAPI_SELECT_B_PROTOCOL_CONF:       /* plci */
-               goto ignored;
-       case CAPI_FACILITY_IND: /* Controller/plci/ncci */
-               goto ignored;
-       case CAPI_FACILITY_CONF:        /* Controller/plci/ncci */
-               goto ignored;
-
-       case CAPI_INFO_CONF:    /* Controller/plci */
-               goto ignored;
-
-       default:
-               printk(KERN_ERR "capidrv-%d: got %s for plci 0x%x ???",
-                      card->contrnr,
-                      capi_cmd2str(cmsg->Command, cmsg->Subcommand),
-                      cmsg->adr.adrPLCI);
-       }
-       return;
-ignored:
-       printk(KERN_INFO "capidrv-%d: %s for plci 0x%x ignored\n",
-              card->contrnr,
-              capi_cmd2str(cmsg->Command, cmsg->Subcommand),
-              cmsg->adr.adrPLCI);
-       return;
-notfound:
-       printk(KERN_ERR "capidrv-%d: %s: plci 0x%x not found\n",
-              card->contrnr,
-              capi_cmd2str(cmsg->Command, cmsg->Subcommand),
-              cmsg->adr.adrPLCI);
-       return;
-}
-
-static void handle_ncci(_cmsg *cmsg)
-{
-       capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f);
-       capidrv_plci *plcip;
-       capidrv_ncci *nccip;
-       isdn_ctrl cmd;
-       int len;
-
-       if (!card) {
-               printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n",
-                      capi_cmd2str(cmsg->Command, cmsg->Subcommand),
-                      cmsg->adr.adrController & 0x7f);
-               return;
-       }
-       switch (CAPICMD(cmsg->Command, cmsg->Subcommand)) {
-
-       case CAPI_CONNECT_B3_ACTIVE_IND:        /* ncci */
-               if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
-                       goto notfound;
-
-               capi_cmsg_answer(cmsg);
-               ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_ACTIVE_IND);
-               send_message(card, cmsg);
-
-               cmd.command = ISDN_STAT_BCONN;
-               cmd.driver = card->myid;
-               cmd.arg = nccip->chan;
-               card->interface.statcallb(&cmd);
-
-               printk(KERN_INFO "capidrv-%d: chan %d up with ncci 0x%x\n",
-                      card->contrnr, nccip->chan, nccip->ncci);
-               break;
-
-       case CAPI_CONNECT_B3_ACTIVE_CONF:       /* ncci */
-               goto ignored;
-
-       case CAPI_CONNECT_B3_IND:       /* ncci */
-
-               plcip = find_plci_by_ncci(card, cmsg->adr.adrNCCI);
-               if (plcip) {
-                       nccip = new_ncci(card, plcip, cmsg->adr.adrNCCI);
-                       if (nccip) {
-                               ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_IND);
-                               capi_fill_CONNECT_B3_RESP(cmsg,
-                                                         global.ap.applid,
-                                                         card->msgid++,
-                                                         nccip->ncci,  /* adr */
-                                                         0,    /* Reject */
-                                                         NULL  /* NCPI */
-                                       );
-                               ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_RESP);
-                               send_message(card, cmsg);
-                               break;
-                       }
-                       printk(KERN_ERR "capidrv-%d: no mem for ncci, sorry\n",                                                 card->contrnr);
-               } else {
-                       printk(KERN_ERR "capidrv-%d: %s: plci for ncci 0x%x not found\n",
-                              card->contrnr,
-                              capi_cmd2str(cmsg->Command, cmsg->Subcommand),
-                              cmsg->adr.adrNCCI);
-               }
-               capi_fill_CONNECT_B3_RESP(cmsg,
-                                         global.ap.applid,
-                                         card->msgid++,
-                                         cmsg->adr.adrNCCI,
-                                         2,    /* Reject */
-                                         NULL  /* NCPI */
-                       );
-               send_message(card, cmsg);
-               break;
-
-       case CAPI_CONNECT_B3_CONF:      /* ncci */
-
-               if (!(nccip = find_ncci_by_msgid(card,
-                                                cmsg->adr.adrNCCI,
-                                                cmsg->Messagenumber)))
-                       goto notfound;
-
-               nccip->ncci = cmsg->adr.adrNCCI;
-               if (cmsg->Info) {
-                       printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for ncci 0x%x\n",
-                              card->contrnr,
-                              capi_cmd2str(cmsg->Command, cmsg->Subcommand),
-                              cmsg->Info, capi_info2str(cmsg->Info),
-                              cmsg->adr.adrNCCI);
-               }
-
-               if (cmsg->Info)
-                       ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_CONF_ERROR);
-               else
-                       ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_CONF_OK);
-               break;
-
-       case CAPI_CONNECT_B3_T90_ACTIVE_IND:    /* ncci */
-               capi_cmsg_answer(cmsg);
-               send_message(card, cmsg);
-               break;
-
-       case CAPI_DATA_B3_IND:  /* ncci */
-               /* handled in handle_data() */
-               goto ignored;
-
-       case CAPI_DATA_B3_CONF: /* ncci */
-               if (cmsg->Info) {
-                       printk(KERN_WARNING "CAPI_DATA_B3_CONF: Info %x - %s\n",
-                              cmsg->Info, capi_info2str(cmsg->Info));
-               }
-               if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
-                       goto notfound;
-
-               len = capidrv_del_ack(nccip, cmsg->DataHandle);
-               if (len < 0)
-                       break;
-               cmd.command = ISDN_STAT_BSENT;
-               cmd.driver = card->myid;
-               cmd.arg = nccip->chan;
-               cmd.parm.length = len;
-               card->interface.statcallb(&cmd);
-               break;
-
-       case CAPI_DISCONNECT_B3_IND:    /* ncci */
-               if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
-                       goto notfound;
-
-               card->bchans[nccip->chan].disconnecting = 1;
-               ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_IND);
-               capi_cmsg_answer(cmsg);
-               ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_RESP);
-               send_message(card, cmsg);
-               break;
-
-       case CAPI_DISCONNECT_B3_CONF:   /* ncci */
-               if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
-                       goto notfound;
-               if (cmsg->Info) {
-                       printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for ncci 0x%x\n",
-                              card->contrnr,
-                              capi_cmd2str(cmsg->Command, cmsg->Subcommand),
-                              cmsg->Info, capi_info2str(cmsg->Info),
-                              cmsg->adr.adrNCCI);
-                       ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_CONF_ERROR);
-               }
-               break;
-
-       case CAPI_RESET_B3_IND: /* ncci */
-               if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
-                       goto notfound;
-               ncci_change_state(card, nccip, EV_NCCI_RESET_B3_IND);
-               capi_cmsg_answer(cmsg);
-               send_message(card, cmsg);
-               break;
-
-       case CAPI_RESET_B3_CONF:        /* ncci */
-               goto ignored;   /* $$$$ */
-
-       case CAPI_FACILITY_IND: /* Controller/plci/ncci */
-               goto ignored;
-       case CAPI_FACILITY_CONF:        /* Controller/plci/ncci */
-               goto ignored;
-
-       default:
-               printk(KERN_ERR "capidrv-%d: got %s for ncci 0x%x ???",
-                      card->contrnr,
-                      capi_cmd2str(cmsg->Command, cmsg->Subcommand),
-                      cmsg->adr.adrNCCI);
-       }
-       return;
-ignored:
-       printk(KERN_INFO "capidrv-%d: %s for ncci 0x%x ignored\n",
-              card->contrnr,
-              capi_cmd2str(cmsg->Command, cmsg->Subcommand),
-              cmsg->adr.adrNCCI);
-       return;
-notfound:
-       printk(KERN_ERR "capidrv-%d: %s: ncci 0x%x not found\n",
-              card->contrnr,
-              capi_cmd2str(cmsg->Command, cmsg->Subcommand),
-              cmsg->adr.adrNCCI);
-}
-
-
-static void handle_data(_cmsg *cmsg, struct sk_buff *skb)
-{
-       capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f);
-       capidrv_ncci *nccip;
-
-       if (!card) {
-               printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n",
-                      capi_cmd2str(cmsg->Command, cmsg->Subcommand),
-                      cmsg->adr.adrController & 0x7f);
-               kfree_skb(skb);
-               return;
-       }
-       if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI))) {
-               printk(KERN_ERR "capidrv-%d: %s: ncci 0x%x not found\n",
-                      card->contrnr,
-                      capi_cmd2str(cmsg->Command, cmsg->Subcommand),
-                      cmsg->adr.adrNCCI);
-               kfree_skb(skb);
-               return;
-       }
-       (void) skb_pull(skb, CAPIMSG_LEN(skb->data));
-       card->interface.rcvcallb_skb(card->myid, nccip->chan, skb);
-       capi_cmsg_answer(cmsg);
-       send_message(card, cmsg);
-}
-
-static _cmsg s_cmsg;
-
-static void capidrv_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
-{
-       if (capi_message2cmsg(&s_cmsg, skb->data)) {
-               printk(KERN_ERR "capidrv: applid=%d: received invalid message\n",
-                      ap->applid);
-               kfree_skb(skb);
-               return;
-       }
-       if (debugmode > 3) {
-               _cdebbuf *cdb = capi_cmsg2str(&s_cmsg);
-
-               if (cdb) {
-                       printk(KERN_DEBUG "%s: applid=%d %s\n", __func__,
-                              ap->applid, cdb->buf);
-                       cdebbuf_free(cdb);
-               } else
-                       printk(KERN_DEBUG "%s: applid=%d %s not traced\n",
-                              __func__, ap->applid,
-                              capi_cmd2str(s_cmsg.Command, s_cmsg.Subcommand));
-       }
-       if (s_cmsg.Command == CAPI_DATA_B3
-           && s_cmsg.Subcommand == CAPI_IND) {
-               handle_data(&s_cmsg, skb);
-               return;
-       }
-       if ((s_cmsg.adr.adrController & 0xffffff00) == 0)
-               handle_controller(&s_cmsg);
-       else if ((s_cmsg.adr.adrPLCI & 0xffff0000) == 0)
-               handle_plci(&s_cmsg);
-       else
-               handle_ncci(&s_cmsg);
-       /*
-        * data of skb used in s_cmsg,
-        * free data when s_cmsg is not used again
-        * thanks to Lars Heete <hel@admin.de>
-        */
-       kfree_skb(skb);
-}
-
-/* ------------------------------------------------------------------- */
-
-#define PUTBYTE_TO_STATUS(card, byte)                          \
-       do {                                                    \
-               *(card)->q931_write++ = (byte);                 \
-               if ((card)->q931_write > (card)->q931_end)      \
-                       (card)->q931_write = (card)->q931_buf;  \
-       } while (0)
-
-static void handle_dtrace_data(capidrv_contr *card,
-                              int send, int level2, u8 *data, u16 len)
-{
-       u8 *p, *end;
-       isdn_ctrl cmd;
-
-       if (!len) {
-               printk(KERN_DEBUG "capidrv-%d: avmb1_q931_data: len == %d\n",
-                      card->contrnr, len);
-               return;
-       }
-
-       if (level2) {
-               PUTBYTE_TO_STATUS(card, 'D');
-               PUTBYTE_TO_STATUS(card, '2');
-               PUTBYTE_TO_STATUS(card, send ? '>' : '<');
-               PUTBYTE_TO_STATUS(card, ':');
-       } else {
-               PUTBYTE_TO_STATUS(card, 'D');
-               PUTBYTE_TO_STATUS(card, '3');
-               PUTBYTE_TO_STATUS(card, send ? '>' : '<');
-               PUTBYTE_TO_STATUS(card, ':');
-       }
-
-       for (p = data, end = data + len; p < end; p++) {
-               PUTBYTE_TO_STATUS(card, ' ');
-               PUTBYTE_TO_STATUS(card, hex_asc_hi(*p));
-               PUTBYTE_TO_STATUS(card, hex_asc_lo(*p));
-       }
-       PUTBYTE_TO_STATUS(card, '\n');
-
-       cmd.command = ISDN_STAT_STAVAIL;
-       cmd.driver = card->myid;
-       cmd.arg = len * 3 + 5;
-       card->interface.statcallb(&cmd);
-}
-
-/* ------------------------------------------------------------------- */
-
-static _cmsg cmdcmsg;
-
-static int capidrv_ioctl(isdn_ctrl *c, capidrv_contr *card)
-{
-       switch (c->arg) {
-       case 1:
-               debugmode = (int)(*((unsigned int *)c->parm.num));
-               printk(KERN_DEBUG "capidrv-%d: debugmode=%d\n",
-                      card->contrnr, debugmode);
-               return 0;
-       default:
-               printk(KERN_DEBUG "capidrv-%d: capidrv_ioctl(%ld) called ??\n",
-                      card->contrnr, c->arg);
-               return -EINVAL;
-       }
-       return -EINVAL;
-}
-
-/*
- * Handle leased lines (CAPI-Bundling)
- */
-
-struct internal_bchannelinfo {
-       unsigned short channelalloc;
-       unsigned short operation;
-       unsigned char  cmask[31];
-};
-
-static int decodeFVteln(char *teln, unsigned long *bmaskp, int *activep)
-{
-       unsigned long bmask = 0;
-       int active = !0;
-       char *s;
-       int i;
-
-       if (strncmp(teln, "FV:", 3) != 0)
-               return 1;
-       s = teln + 3;
-       while (*s && *s == ' ') s++;
-       if (!*s) return -2;
-       if (*s == 'p' || *s == 'P') {
-               active = 0;
-               s++;
-       }
-       if (*s == 'a' || *s == 'A') {
-               active = !0;
-               s++;
-       }
-       while (*s) {
-               int digit1 = 0;
-               int digit2 = 0;
-               char *endp;
-
-               digit1 = simple_strtoul(s, &endp, 10);
-               if (s == endp)
-                       return -3;
-               s = endp;
-
-               if (digit1 <= 0 || digit1 > 30) return -4;
-               if (*s == 0 || *s == ',' || *s == ' ') {
-                       bmask |= (1 << digit1);
-                       digit1 = 0;
-                       if (*s) s++;
-                       continue;
-               }
-               if (*s != '-') return -5;
-               s++;
-
-               digit2 = simple_strtoul(s, &endp, 10);
-               if (s == endp)
-                       return -3;
-               s = endp;
-
-               if (digit2 <= 0 || digit2 > 30) return -4;
-               if (*s == 0 || *s == ',' || *s == ' ') {
-                       if (digit1 > digit2)
-                               for (i = digit2; i <= digit1; i++)
-                                       bmask |= (1 << i);
-                       else
-                               for (i = digit1; i <= digit2; i++)
-                                       bmask |= (1 << i);
-                       digit1 = digit2 = 0;
-                       if (*s) s++;
-                       continue;
-               }
-               return -6;
-       }
-       if (activep) *activep = active;
-       if (bmaskp) *bmaskp = bmask;
-       return 0;
-}
-
-static int FVteln2capi20(char *teln, u8 AdditionalInfo[1 + 2 + 2 + 31])
-{
-       unsigned long bmask;
-       int active;
-       int rc, i;
-
-       rc = decodeFVteln(teln, &bmask, &active);
-       if (rc) return rc;
-       /* Length */
-       AdditionalInfo[0] = 2 + 2 + 31;
-       /* Channel: 3 => use channel allocation */
-       AdditionalInfo[1] = 3; AdditionalInfo[2] = 0;
-       /* Operation: 0 => DTE mode, 1 => DCE mode */
-       if (active) {
-               AdditionalInfo[3] = 0; AdditionalInfo[4] = 0;
-       } else {
-               AdditionalInfo[3] = 1; AdditionalInfo[4] = 0;
-       }
-       /* Channel mask array */
-       AdditionalInfo[5] = 0; /* no D-Channel */
-       for (i = 1; i <= 30; i++)
-               AdditionalInfo[5 + i] = (bmask & (1 << i)) ? 0xff : 0;
-       return 0;
-}
-
-static int capidrv_command(isdn_ctrl *c, capidrv_contr *card)
-{
-       isdn_ctrl cmd;
-       struct capidrv_bchan *bchan;
-       struct capidrv_plci *plcip;
-       u8 AdditionalInfo[1 + 2 + 2 + 31];
-       int rc, isleasedline = 0;
-
-       if (c->command == ISDN_CMD_IOCTL)
-               return capidrv_ioctl(c, card);
-
-       switch (c->command) {
-       case ISDN_CMD_DIAL: {
-               u8 calling[ISDN_MSNLEN + 3];
-               u8 called[ISDN_MSNLEN + 2];
-
-               if (debugmode)
-                       printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_DIAL(ch=%ld,\"%s,%d,%d,%s\")\n",
-                              card->contrnr,
-                              c->arg,
-                              c->parm.setup.phone,
-                              c->parm.setup.si1,
-                              c->parm.setup.si2,
-                              c->parm.setup.eazmsn);
-
-               bchan = &card->bchans[c->arg % card->nbchan];
-
-               if (bchan->plcip) {
-                       printk(KERN_ERR "capidrv-%d: dail ch=%ld,\"%s,%d,%d,%s\" in use (plci=0x%x)\n",
-                              card->contrnr,
-                              c->arg,
-                              c->parm.setup.phone,
-                              c->parm.setup.si1,
-                              c->parm.setup.si2,
-                              c->parm.setup.eazmsn,
-                              bchan->plcip->plci);
-                       return 0;
-               }
-               bchan->si1 = c->parm.setup.si1;
-               bchan->si2 = c->parm.setup.si2;
-
-               strncpy(bchan->num, c->parm.setup.phone, sizeof(bchan->num));
-               strncpy(bchan->mynum, c->parm.setup.eazmsn, sizeof(bchan->mynum));
-               rc = FVteln2capi20(bchan->num, AdditionalInfo);
-               isleasedline = (rc == 0);
-               if (rc < 0)
-                       printk(KERN_ERR "capidrv-%d: WARNING: invalid leased linedefinition \"%s\"\n", card->contrnr, bchan->num);
-
-               if (isleasedline) {
-                       calling[0] = 0;
-                       called[0] = 0;
-                       if (debugmode)
-                               printk(KERN_DEBUG "capidrv-%d: connecting leased line\n", card->contrnr);
-               } else {
-                       calling[0] = strlen(bchan->mynum) + 2;
-                       calling[1] = 0;
-                       calling[2] = 0x80;
-                       strncpy(calling + 3, bchan->mynum, ISDN_MSNLEN);
-                       called[0] = strlen(bchan->num) + 1;
-                       called[1] = 0x80;
-                       strncpy(called + 2, bchan->num, ISDN_MSNLEN);
-               }
-
-               capi_fill_CONNECT_REQ(&cmdcmsg,
-                                     global.ap.applid,
-                                     card->msgid++,
-                                     card->contrnr,    /* adr */
-                                     si2cip(bchan->si1, bchan->si2),   /* cipvalue */
-                                     called,   /* CalledPartyNumber */
-                                     calling,  /* CallingPartyNumber */
-                                     NULL,     /* CalledPartySubaddress */
-                                     NULL,     /* CallingPartySubaddress */
-                                     b1prot(bchan->l2, bchan->l3),     /* B1protocol */
-                                     b2prot(bchan->l2, bchan->l3),     /* B2protocol */
-                                     b3prot(bchan->l2, bchan->l3),     /* B3protocol */
-                                     b1config(bchan->l2, bchan->l3),   /* B1configuration */
-                                     NULL,     /* B2configuration */
-                                     NULL,     /* B3configuration */
-                                     NULL,     /* BC */
-                                     NULL,     /* LLC */
-                                     NULL,     /* HLC */
-                                     /* BChannelinformation */
-                                     isleasedline ? AdditionalInfo : NULL,
-                                     NULL,     /* Keypadfacility */
-                                     NULL,     /* Useruserdata */
-                                     NULL      /* Facilitydataarray */
-                       );
-               if ((plcip = new_plci(card, (c->arg % card->nbchan))) == NULL) {
-                       cmd.command = ISDN_STAT_DHUP;
-                       cmd.driver = card->myid;
-                       cmd.arg = (c->arg % card->nbchan);
-                       card->interface.statcallb(&cmd);
-                       return -1;
-               }
-               plcip->msgid = cmdcmsg.Messagenumber;
-               plcip->leasedline = isleasedline;
-               plci_change_state(card, plcip, EV_PLCI_CONNECT_REQ);
-               send_message(card, &cmdcmsg);
-               return 0;
-       }
-
-       case ISDN_CMD_ACCEPTD:
-
-               bchan = &card->bchans[c->arg % card->nbchan];
-               if (debugmode)
-                       printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_ACCEPTD(ch=%ld) l2=%d l3=%d\n",
-                              card->contrnr,
-                              c->arg, bchan->l2, bchan->l3);
-
-               capi_fill_CONNECT_RESP(&cmdcmsg,
-                                      global.ap.applid,
-                                      card->msgid++,
-                                      bchan->plcip->plci,      /* adr */
-                                      0,       /* Reject */
-                                      b1prot(bchan->l2, bchan->l3),    /* B1protocol */
-                                      b2prot(bchan->l2, bchan->l3),    /* B2protocol */
-                                      b3prot(bchan->l2, bchan->l3),    /* B3protocol */
-                                      b1config(bchan->l2, bchan->l3),  /* B1configuration */
-                                      NULL,    /* B2configuration */
-                                      NULL,    /* B3configuration */
-                                      NULL,    /* ConnectedNumber */
-                                      NULL,    /* ConnectedSubaddress */
-                                      NULL,    /* LLC */
-                                      NULL,    /* BChannelinformation */
-                                      NULL,    /* Keypadfacility */
-                                      NULL,    /* Useruserdata */
-                                      NULL     /* Facilitydataarray */
-                       );
-               if (capi_cmsg2message(&cmdcmsg, cmdcmsg.buf)) {
-                       printk(KERN_ERR "capidrv-%d: capidrv_command: parser failure\n",
-                              card->contrnr);
-                       return -EINVAL;
-               }
-               plci_change_state(card, bchan->plcip, EV_PLCI_CONNECT_RESP);
-               send_message(card, &cmdcmsg);
-               return 0;
-
-       case ISDN_CMD_ACCEPTB:
-               if (debugmode)
-                       printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_ACCEPTB(ch=%ld)\n",
-                              card->contrnr,
-                              c->arg);
-               return -ENOSYS;
-
-       case ISDN_CMD_HANGUP:
-               if (debugmode)
-                       printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_HANGUP(ch=%ld)\n",
-                              card->contrnr,
-                              c->arg);
-               bchan = &card->bchans[c->arg % card->nbchan];
-
-               if (bchan->disconnecting) {
-                       if (debugmode)
-                               printk(KERN_DEBUG "capidrv-%d: chan %ld already disconnecting ...\n",
-                                      card->contrnr,
-                                      c->arg);
-                       return 0;
-               }
-               if (bchan->nccip) {
-                       bchan->disconnecting = 1;
-                       capi_fill_DISCONNECT_B3_REQ(&cmdcmsg,
-                                                   global.ap.applid,
-                                                   card->msgid++,
-                                                   bchan->nccip->ncci,
-                                                   NULL        /* NCPI */
-                               );
-                       ncci_change_state(card, bchan->nccip, EV_NCCI_DISCONNECT_B3_REQ);
-                       send_message(card, &cmdcmsg);
-                       return 0;
-               } else if (bchan->plcip) {
-                       if (bchan->plcip->state == ST_PLCI_INCOMING) {
-                               /*
-                                * just ignore, we a called from
-                                * isdn_status_callback(),
-                                * which will return 0 or 2, this is handled
-                                * by the CONNECT_IND handler
-                                */
-                               bchan->disconnecting = 1;
-                               return 0;
-                       } else if (bchan->plcip->plci) {
-                               bchan->disconnecting = 1;
-                               capi_fill_DISCONNECT_REQ(&cmdcmsg,
-                                                        global.ap.applid,
-                                                        card->msgid++,
-                                                        bchan->plcip->plci,
-                                                        NULL,  /* BChannelinformation */
-                                                        NULL,  /* Keypadfacility */
-                                                        NULL,  /* Useruserdata */
-                                                        NULL   /* Facilitydataarray */
-                                       );
-                               plci_change_state(card, bchan->plcip, EV_PLCI_DISCONNECT_REQ);
-                               send_message(card, &cmdcmsg);
-                               return 0;
-                       } else {
-                               printk(KERN_ERR "capidrv-%d: chan %ld disconnect request while waiting for CONNECT_CONF\n",
-                                      card->contrnr,
-                                      c->arg);
-                               return -EINVAL;
-                       }
-               }
-               printk(KERN_ERR "capidrv-%d: chan %ld disconnect request on free channel\n",
-                      card->contrnr,
-                      c->arg);
-               return -EINVAL;
-/* ready */
-
-       case ISDN_CMD_SETL2:
-               if (debugmode)
-                       printk(KERN_DEBUG "capidrv-%d: set L2 on chan %ld to %ld\n",
-                              card->contrnr,
-                              (c->arg & 0xff), (c->arg >> 8));
-               bchan = &card->bchans[(c->arg & 0xff) % card->nbchan];
-               bchan->l2 = (c->arg >> 8);
-               return 0;
-
-       case ISDN_CMD_SETL3:
-               if (debugmode)
-                       printk(KERN_DEBUG "capidrv-%d: set L3 on chan %ld to %ld\n",
-                              card->contrnr,
-                              (c->arg & 0xff), (c->arg >> 8));
-               bchan = &card->bchans[(c->arg & 0xff) % card->nbchan];
-               bchan->l3 = (c->arg >> 8);
-               return 0;
-
-       case ISDN_CMD_SETEAZ:
-               if (debugmode)
-                       printk(KERN_DEBUG "capidrv-%d: set EAZ \"%s\" on chan %ld\n",
-                              card->contrnr,
-                              c->parm.num, c->arg);
-               bchan = &card->bchans[c->arg % card->nbchan];
-               strncpy(bchan->msn, c->parm.num, ISDN_MSNLEN);
-               return 0;
-
-       case ISDN_CMD_CLREAZ:
-               if (debugmode)
-                       printk(KERN_DEBUG "capidrv-%d: clearing EAZ on chan %ld\n",
-                              card->contrnr, c->arg);
-               bchan = &card->bchans[c->arg % card->nbchan];
-               bchan->msn[0] = 0;
-               return 0;
-
-       default:
-               printk(KERN_ERR "capidrv-%d: ISDN_CMD_%d, Huh?\n",
-                      card->contrnr, c->command);
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int if_command(isdn_ctrl *c)
-{
-       capidrv_contr *card = findcontrbydriverid(c->driver);
-
-       if (card)
-               return capidrv_command(c, card);
-
-       printk(KERN_ERR
-              "capidrv: if_command %d called with invalid driverId %d!\n",
-              c->command, c->driver);
-       return -ENODEV;
-}
-
-static _cmsg sendcmsg;
-
-static int if_sendbuf(int id, int channel, int doack, struct sk_buff *skb)
-{
-       capidrv_contr *card = findcontrbydriverid(id);
-       capidrv_bchan *bchan;
-       capidrv_ncci *nccip;
-       int len = skb->len;
-       int msglen;
-       u16 errcode;
-       u16 datahandle;
-       u32 data;
-
-       if (!card) {
-               printk(KERN_ERR "capidrv: if_sendbuf called with invalid driverId %d!\n",
-                      id);
-               return 0;
-       }
-       if (debugmode > 4)
-               printk(KERN_DEBUG "capidrv-%d: sendbuf len=%d skb=%p doack=%d\n",
-                      card->contrnr, len, skb, doack);
-       bchan = &card->bchans[channel % card->nbchan];
-       nccip = bchan->nccip;
-       if (!nccip || nccip->state != ST_NCCI_ACTIVE) {
-               printk(KERN_ERR "capidrv-%d: if_sendbuf: %s:%d: chan not up!\n",
-                      card->contrnr, card->name, channel);
-               return 0;
-       }
-       datahandle = nccip->datahandle;
-
-       /*
-        * Here we copy pointer skb->data into the 32-bit 'Data' field.
-        * The 'Data' field is not used in practice in linux kernel
-        * (neither in 32 or 64 bit), but should have some value,
-        * since a CAPI message trace will display it.
-        *
-        * The correct value in the 32 bit case is the address of the
-        * data, in 64 bit it makes no sense, we use 0 there.
-        */
-
-#ifdef CONFIG_64BIT
-       data = 0;
-#else
-       data = (unsigned long) skb->data;
-#endif
-
-       capi_fill_DATA_B3_REQ(&sendcmsg, global.ap.applid, card->msgid++,
-                             nccip->ncci,      /* adr */
-                             data,             /* Data */
-                             skb->len,         /* DataLength */
-                             datahandle,       /* DataHandle */
-                             0 /* Flags */
-               );
-
-       if (capidrv_add_ack(nccip, datahandle, doack ? (int)skb->len : -1) < 0)
-               return 0;
-
-       if (capi_cmsg2message(&sendcmsg, sendcmsg.buf)) {
-               printk(KERN_ERR "capidrv-%d: if_sendbuf: parser failure\n",
-                      card->contrnr);
-               return -EINVAL;
-       }
-       msglen = CAPIMSG_LEN(sendcmsg.buf);
-       if (skb_headroom(skb) < msglen) {
-               struct sk_buff *nskb = skb_realloc_headroom(skb, msglen);
-               if (!nskb) {
-                       printk(KERN_ERR "capidrv-%d: if_sendbuf: no memory\n",
-                              card->contrnr);
-                       (void)capidrv_del_ack(nccip, datahandle);
-                       return 0;
-               }
-               printk(KERN_DEBUG "capidrv-%d: only %d bytes headroom, need %d\n",
-                      card->contrnr, skb_headroom(skb), msglen);
-               memcpy(skb_push(nskb, msglen), sendcmsg.buf, msglen);
-               errcode = capi20_put_message(&global.ap, nskb);
-               if (errcode == CAPI_NOERROR) {
-                       dev_kfree_skb(skb);
-                       nccip->datahandle++;
-                       return len;
-               }
-               if (debugmode > 3)
-                       printk(KERN_DEBUG "capidrv-%d: sendbuf putmsg ret(%x) - %s\n",
-                              card->contrnr, errcode, capi_info2str(errcode));
-               (void)capidrv_del_ack(nccip, datahandle);
-               dev_kfree_skb(nskb);
-               return errcode == CAPI_SENDQUEUEFULL ? 0 : -1;
-       } else {
-               memcpy(skb_push(skb, msglen), sendcmsg.buf, msglen);
-               errcode = capi20_put_message(&global.ap, skb);
-               if (errcode == CAPI_NOERROR) {
-                       nccip->datahandle++;
-                       return len;
-               }
-               if (debugmode > 3)
-                       printk(KERN_DEBUG "capidrv-%d: sendbuf putmsg ret(%x) - %s\n",
-                              card->contrnr, errcode, capi_info2str(errcode));
-               skb_pull(skb, msglen);
-               (void)capidrv_del_ack(nccip, datahandle);
-               return errcode == CAPI_SENDQUEUEFULL ? 0 : -1;
-       }
-}
-
-static int if_readstat(u8 __user *buf, int len, int id, int channel)
-{
-       capidrv_contr *card = findcontrbydriverid(id);
-       int count;
-       u8 __user *p;
-
-       if (!card) {
-               printk(KERN_ERR "capidrv: if_readstat called with invalid driverId %d!\n",
-                      id);
-               return -ENODEV;
-       }
-
-       for (p = buf, count = 0; count < len; p++, count++) {
-               if (put_user(*card->q931_read++, p))
-                       return -EFAULT;
-               if (card->q931_read > card->q931_end)
-                       card->q931_read = card->q931_buf;
-       }
-       return count;
-
-}
-
-static void enable_dchannel_trace(capidrv_contr *card)
-{
-       u8 manufacturer[CAPI_MANUFACTURER_LEN];
-       capi_version version;
-       u16 contr = card->contrnr;
-       u16 errcode;
-       u16 avmversion[3];
-
-       errcode = capi20_get_manufacturer(contr, manufacturer);
-       if (errcode != CAPI_NOERROR) {
-               printk(KERN_ERR "%s: can't get manufacturer (0x%x)\n",
-                      card->name, errcode);
-               return;
-       }
-       if (strstr(manufacturer, "AVM") == NULL) {
-               printk(KERN_ERR "%s: not from AVM, no d-channel trace possible (%s)\n",
-                      card->name, manufacturer);
-               return;
-       }
-       errcode = capi20_get_version(contr, &version);
-       if (errcode != CAPI_NOERROR) {
-               printk(KERN_ERR "%s: can't get version (0x%x)\n",
-                      card->name, errcode);
-               return;
-       }
-       avmversion[0] = (version.majormanuversion >> 4) & 0x0f;
-       avmversion[1] = (version.majormanuversion << 4) & 0xf0;
-       avmversion[1] |= (version.minormanuversion >> 4) & 0x0f;
-       avmversion[2] |= version.minormanuversion & 0x0f;
-
-       if (avmversion[0] > 3 || (avmversion[0] == 3 && avmversion[1] > 5)) {
-               printk(KERN_INFO "%s: D2 trace enabled\n", card->name);
-               capi_fill_MANUFACTURER_REQ(&cmdcmsg, global.ap.applid,
-                                          card->msgid++,
-                                          contr,
-                                          0x214D5641,  /* ManuID */
-                                          0,           /* Class */
-                                          1,           /* Function */
-                                          (_cstruct)"\004\200\014\000\000");
-       } else {
-               printk(KERN_INFO "%s: D3 trace enabled\n", card->name);
-               capi_fill_MANUFACTURER_REQ(&cmdcmsg, global.ap.applid,
-                                          card->msgid++,
-                                          contr,
-                                          0x214D5641,  /* ManuID */
-                                          0,           /* Class */
-                                          1,           /* Function */
-                                          (_cstruct)"\004\002\003\000\000");
-       }
-       send_message(card, &cmdcmsg);
-}
-
-
-static void send_listen(capidrv_contr *card)
-{
-       capi_fill_LISTEN_REQ(&cmdcmsg, global.ap.applid,
-                            card->msgid++,
-                            card->contrnr, /* controller */
-                            1 << 6,    /* Infomask */
-                            card->cipmask,
-                            card->cipmask2,
-                            NULL, NULL);
-       listen_change_state(card, EV_LISTEN_REQ);
-       send_message(card, &cmdcmsg);
-}
-
-static void listentimerfunc(struct timer_list *t)
-{
-       capidrv_contr *card = from_timer(card, t, listentimer);
-       if (card->state != ST_LISTEN_NONE && card->state != ST_LISTEN_ACTIVE)
-               printk(KERN_ERR "%s: controller dead ??\n", card->name);
-       send_listen(card);
-       mod_timer(&card->listentimer, jiffies + 60 * HZ);
-}
-
-
-static int capidrv_addcontr(u16 contr, struct capi_profile *profp)
-{
-       capidrv_contr *card;
-       unsigned long flags;
-       isdn_ctrl cmd;
-       char id[20];
-       int i;
-
-       sprintf(id, "capidrv-%d", contr);
-       if (!try_module_get(THIS_MODULE)) {
-               printk(KERN_WARNING "capidrv: (%s) Could not reserve module\n", id);
-               return -1;
-       }
-       if (!(card = kzalloc(sizeof(capidrv_contr), GFP_ATOMIC))) {
-               printk(KERN_WARNING
-                      "capidrv: (%s) Could not allocate contr-struct.\n", id);
-               return -1;
-       }
-       card->owner = THIS_MODULE;
-       timer_setup(&card->listentimer, listentimerfunc, 0);
-       strcpy(card->name, id);
-       card->contrnr = contr;
-       card->nbchan = profp->nbchannel;
-       card->bchans = kmalloc_array(card->nbchan, sizeof(capidrv_bchan),
-                                    GFP_ATOMIC);
-       if (!card->bchans) {
-               printk(KERN_WARNING
-                      "capidrv: (%s) Could not allocate bchan-structs.\n", id);
-               module_put(card->owner);
-               kfree(card);
-               return -1;
-       }
-       card->interface.channels = profp->nbchannel;
-       card->interface.maxbufsize = 2048;
-       card->interface.command = if_command;
-       card->interface.writebuf_skb = if_sendbuf;
-       card->interface.writecmd = NULL;
-       card->interface.readstat = if_readstat;
-       card->interface.features =
-               ISDN_FEATURE_L2_HDLC |
-               ISDN_FEATURE_L2_TRANS |
-               ISDN_FEATURE_L3_TRANS |
-               ISDN_FEATURE_P_UNKNOWN |
-               ISDN_FEATURE_L2_X75I |
-               ISDN_FEATURE_L2_X75UI |
-               ISDN_FEATURE_L2_X75BUI;
-       if (profp->support1 & (1 << 2))
-               card->interface.features |=
-                       ISDN_FEATURE_L2_V11096 |
-                       ISDN_FEATURE_L2_V11019 |
-                       ISDN_FEATURE_L2_V11038;
-       if (profp->support1 & (1 << 8))
-               card->interface.features |= ISDN_FEATURE_L2_MODEM;
-       card->interface.hl_hdrlen = 22; /* len of DATA_B3_REQ */
-       strncpy(card->interface.id, id, sizeof(card->interface.id) - 1);
-
-
-       card->q931_read = card->q931_buf;
-       card->q931_write = card->q931_buf;
-       card->q931_end = card->q931_buf + sizeof(card->q931_buf) - 1;
-
-       if (!register_isdn(&card->interface)) {
-               printk(KERN_ERR "capidrv: Unable to register contr %s\n", id);
-               kfree(card->bchans);
-               module_put(card->owner);
-               kfree(card);
-               return -1;
-       }
-       card->myid = card->interface.channels;
-       memset(card->bchans, 0, sizeof(capidrv_bchan) * card->nbchan);
-       for (i = 0; i < card->nbchan; i++) {
-               card->bchans[i].contr = card;
-       }
-
-       spin_lock_irqsave(&global_lock, flags);
-       card->next = global.contr_list;
-       global.contr_list = card;
-       global.ncontr++;
-       spin_unlock_irqrestore(&global_lock, flags);
-
-       cmd.command = ISDN_STAT_RUN;
-       cmd.driver = card->myid;
-       card->interface.statcallb(&cmd);
-
-       card->cipmask = 0x1FFF03FF;     /* any */
-       card->cipmask2 = 0;
-
-       send_listen(card);
-       mod_timer(&card->listentimer, jiffies + 60 * HZ);
-
-       printk(KERN_INFO "%s: now up (%d B channels)\n",
-              card->name, card->nbchan);
-
-       enable_dchannel_trace(card);
-
-       return 0;
-}
-
-static int capidrv_delcontr(u16 contr)
-{
-       capidrv_contr **pp, *card;
-       unsigned long flags;
-       isdn_ctrl cmd;
-
-       spin_lock_irqsave(&global_lock, flags);
-       for (card = global.contr_list; card; card = card->next) {
-               if (card->contrnr == contr)
-                       break;
-       }
-       if (!card) {
-               spin_unlock_irqrestore(&global_lock, flags);
-               printk(KERN_ERR "capidrv: delcontr: no contr %u\n", contr);
-               return -1;
-       }
-
-       /* FIXME: maybe a race condition the card should be removed
-        * here from global list /kkeil
-        */
-       spin_unlock_irqrestore(&global_lock, flags);
-
-       del_timer(&card->listentimer);
-
-       if (debugmode)
-               printk(KERN_DEBUG "capidrv-%d: id=%d unloading\n",
-                      card->contrnr, card->myid);
-
-       cmd.command = ISDN_STAT_STOP;
-       cmd.driver = card->myid;
-       card->interface.statcallb(&cmd);
-
-       while (card->nbchan) {
-
-               cmd.command = ISDN_STAT_DISCH;
-               cmd.driver = card->myid;
-               cmd.arg = card->nbchan - 1;
-               cmd.parm.num[0] = 0;
-               if (debugmode)
-                       printk(KERN_DEBUG "capidrv-%d: id=%d disable chan=%ld\n",
-                              card->contrnr, card->myid, cmd.arg);
-               card->interface.statcallb(&cmd);
-
-               if (card->bchans[card->nbchan - 1].nccip)
-                       free_ncci(card, card->bchans[card->nbchan - 1].nccip);
-               if (card->bchans[card->nbchan - 1].plcip)
-                       free_plci(card, card->bchans[card->nbchan - 1].plcip);
-               if (card->plci_list)
-                       printk(KERN_ERR "capidrv: bug in free_plci()\n");
-               card->nbchan--;
-       }
-       kfree(card->bchans);
-       card->bchans = NULL;
-
-       if (debugmode)
-               printk(KERN_DEBUG "capidrv-%d: id=%d isdn unload\n",
-                      card->contrnr, card->myid);
-
-       cmd.command = ISDN_STAT_UNLOAD;
-       cmd.driver = card->myid;
-       card->interface.statcallb(&cmd);
-
-       if (debugmode)
-               printk(KERN_DEBUG "capidrv-%d: id=%d remove contr from list\n",
-                      card->contrnr, card->myid);
-
-       spin_lock_irqsave(&global_lock, flags);
-       for (pp = &global.contr_list; *pp; pp = &(*pp)->next) {
-               if (*pp == card) {
-                       *pp = (*pp)->next;
-                       card->next = NULL;
-                       global.ncontr--;
-                       break;
-               }
-       }
-       spin_unlock_irqrestore(&global_lock, flags);
-
-       module_put(card->owner);
-       printk(KERN_INFO "%s: now down.\n", card->name);
-       kfree(card);
-       return 0;
-}
-
-
-static int
-lower_callback(struct notifier_block *nb, unsigned long val, void *v)
-{
-       capi_profile profile;
-       u32 contr = (long)v;
-
-       switch (val) {
-       case CAPICTR_UP:
-               printk(KERN_INFO "capidrv: controller %hu up\n", contr);
-               if (capi20_get_profile(contr, &profile) == CAPI_NOERROR)
-                       (void) capidrv_addcontr(contr, &profile);
-               break;
-       case CAPICTR_DOWN:
-               printk(KERN_INFO "capidrv: controller %hu down\n", contr);
-               (void) capidrv_delcontr(contr);
-               break;
-       }
-       return NOTIFY_OK;
-}
-
-/*
- * /proc/capi/capidrv:
- * nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt
- */
-static int __maybe_unused capidrv_proc_show(struct seq_file *m, void *v)
-{
-       seq_printf(m, "%lu %lu %lu %lu\n",
-                  global.ap.nrecvctlpkt,
-                  global.ap.nrecvdatapkt,
-                  global.ap.nsentctlpkt,
-                  global.ap.nsentdatapkt);
-       return 0;
-}
-
-static void __init proc_init(void)
-{
-       proc_create_single("capi/capidrv", 0, NULL, capidrv_proc_show);
-}
-
-static void __exit proc_exit(void)
-{
-       remove_proc_entry("capi/capidrv", NULL);
-}
-
-static struct notifier_block capictr_nb = {
-       .notifier_call = lower_callback,
-};
-
-static int __init capidrv_init(void)
-{
-       capi_profile profile;
-       u32 ncontr, contr;
-       u16 errcode;
-
-       global.ap.rparam.level3cnt = -2;  /* number of bchannels twice */
-       global.ap.rparam.datablkcnt = 16;
-       global.ap.rparam.datablklen = 2048;
-
-       global.ap.recv_message = capidrv_recv_message;
-       errcode = capi20_register(&global.ap);
-       if (errcode) {
-               return -EIO;
-       }
-
-       register_capictr_notifier(&capictr_nb);
-
-       errcode = capi20_get_profile(0, &profile);
-       if (errcode != CAPI_NOERROR) {
-               unregister_capictr_notifier(&capictr_nb);
-               capi20_release(&global.ap);
-               return -EIO;
-       }
-
-       ncontr = profile.ncontroller;
-       for (contr = 1; contr <= ncontr; contr++) {
-               errcode = capi20_get_profile(contr, &profile);
-               if (errcode != CAPI_NOERROR)
-                       continue;
-               (void) capidrv_addcontr(contr, &profile);
-       }
-       proc_init();
-
-       return 0;
-}
-
-static void __exit capidrv_exit(void)
-{
-       unregister_capictr_notifier(&capictr_nb);
-       capi20_release(&global.ap);
-
-       proc_exit();
-}
-
-module_init(capidrv_init);
-module_exit(capidrv_exit);
 
+++ /dev/null
-/* $Id: capidrv.h,v 1.2.8.2 2001/09/23 22:24:33 kai Exp $
- *
- * ISDN4Linux Driver, using capi20 interface (kernelcapi)
- *
- * Copyright 1997 by Carsten Paeth <calle@calle.de>
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#ifndef __CAPIDRV_H__
-#define __CAPIDRV_H__
-
-/*
- * LISTEN state machine
- */
-#define ST_LISTEN_NONE                 0       /* L-0 */
-#define ST_LISTEN_WAIT_CONF            1       /* L-0.1 */
-#define ST_LISTEN_ACTIVE               2       /* L-1 */
-#define ST_LISTEN_ACTIVE_WAIT_CONF     3       /* L-1.1 */
-
-
-#define EV_LISTEN_REQ                  1       /* L-0 -> L-0.1
-                                                  L-1 -> L-1.1 */
-#define EV_LISTEN_CONF_ERROR           2       /* L-0.1 -> L-0
-                                                  L-1.1 -> L-1 */
-#define EV_LISTEN_CONF_EMPTY           3       /* L-0.1 -> L-0
-                                                  L-1.1 -> L-0 */
-#define EV_LISTEN_CONF_OK              4       /* L-0.1 -> L-1
-                                                  L-1.1 -> L.1 */
-
-/*
- * per plci state machine
- */
-#define ST_PLCI_NONE                   0       /* P-0 */
-#define ST_PLCI_OUTGOING               1       /* P-0.1 */
-#define ST_PLCI_ALLOCATED              2       /* P-1 */
-#define ST_PLCI_ACTIVE                 3       /* P-ACT */
-#define ST_PLCI_INCOMING               4       /* P-2 */
-#define ST_PLCI_FACILITY_IND           5       /* P-3 */
-#define ST_PLCI_ACCEPTING              6       /* P-4 */
-#define ST_PLCI_DISCONNECTING          7       /* P-5 */
-#define ST_PLCI_DISCONNECTED           8       /* P-6 */
-#define ST_PLCI_RESUMEING              9       /* P-0.Res */
-#define ST_PLCI_RESUME                 10      /* P-Res */
-#define ST_PLCI_HELD                   11      /* P-HELD */
-
-#define EV_PLCI_CONNECT_REQ            1       /* P-0 -> P-0.1
-                                                */
-#define EV_PLCI_CONNECT_CONF_ERROR     2       /* P-0.1 -> P-0
-                                                */
-#define EV_PLCI_CONNECT_CONF_OK                3       /* P-0.1 -> P-1
-                                                */
-#define EV_PLCI_FACILITY_IND_UP                4       /* P-0 -> P-1
-                                                */
-#define EV_PLCI_CONNECT_IND            5       /* P-0 -> P-2
-                                                */
-#define EV_PLCI_CONNECT_ACTIVE_IND     6       /* P-1 -> P-ACT
-                                                */
-#define EV_PLCI_CONNECT_REJECT         7       /* P-2 -> P-5
-                                                  P-3 -> P-5
-                                               */
-#define EV_PLCI_DISCONNECT_REQ         8       /* P-1 -> P-5
-                                                  P-2 -> P-5
-                                                  P-3 -> P-5
-                                                  P-4 -> P-5
-                                                  P-ACT -> P-5
-                                                  P-Res -> P-5 (*)
-                                                  P-HELD -> P-5 (*)
-                                               */
-#define EV_PLCI_DISCONNECT_IND         9       /* P-1 -> P-6
-                                                  P-2 -> P-6
-                                                  P-3 -> P-6
-                                                  P-4 -> P-6
-                                                  P-5 -> P-6
-                                                  P-ACT -> P-6
-                                                  P-Res -> P-6 (*)
-                                                  P-HELD -> P-6 (*)
-                                               */
-#define EV_PLCI_FACILITY_IND_DOWN      10      /* P-0.1 -> P-5
-                                                  P-1 -> P-5
-                                                  P-ACT -> P-5
-                                                  P-2 -> P-5
-                                                  P-3 -> P-5
-                                                  P-4 -> P-5
-                                               */
-#define EV_PLCI_DISCONNECT_RESP                11      /* P-6 -> P-0
-                                                */
-#define EV_PLCI_CONNECT_RESP           12      /* P-6 -> P-0
-                                                */
-
-#define EV_PLCI_RESUME_REQ             13      /* P-0 -> P-0.Res
-                                                */
-#define EV_PLCI_RESUME_CONF_OK         14      /* P-0.Res -> P-Res
-                                                */
-#define EV_PLCI_RESUME_CONF_ERROR      15      /* P-0.Res -> P-0
-                                                */
-#define EV_PLCI_RESUME_IND             16      /* P-Res -> P-ACT
-                                                */
-#define EV_PLCI_HOLD_IND               17      /* P-ACT -> P-HELD
-                                                */
-#define EV_PLCI_RETRIEVE_IND           18      /* P-HELD -> P-ACT
-                                                */
-#define EV_PLCI_SUSPEND_IND            19      /* P-ACT -> P-5
-                                                */
-#define EV_PLCI_CD_IND                 20      /* P-2 -> P-5
-                                                */
-
-/*
- * per ncci state machine
- */
-#define ST_NCCI_PREVIOUS                       -1
-#define ST_NCCI_NONE                           0       /* N-0 */
-#define ST_NCCI_OUTGOING                       1       /* N-0.1 */
-#define ST_NCCI_INCOMING                       2       /* N-1 */
-#define ST_NCCI_ALLOCATED                      3       /* N-2 */
-#define ST_NCCI_ACTIVE                         4       /* N-ACT */
-#define ST_NCCI_RESETING                       5       /* N-3 */
-#define ST_NCCI_DISCONNECTING                  6       /* N-4 */
-#define ST_NCCI_DISCONNECTED                   7       /* N-5 */
-
-#define EV_NCCI_CONNECT_B3_REQ                 1       /* N-0 -> N-0.1 */
-#define EV_NCCI_CONNECT_B3_IND                 2       /* N-0 -> N.1 */
-#define EV_NCCI_CONNECT_B3_CONF_OK             3       /* N-0.1 -> N.2 */
-#define EV_NCCI_CONNECT_B3_CONF_ERROR          4       /* N-0.1 -> N.0 */
-#define EV_NCCI_CONNECT_B3_REJECT              5       /* N-1 -> N-4 */
-#define EV_NCCI_CONNECT_B3_RESP                        6       /* N-1 -> N-2 */
-#define EV_NCCI_CONNECT_B3_ACTIVE_IND          7       /* N-2 -> N-ACT */
-#define EV_NCCI_RESET_B3_REQ                   8       /* N-ACT -> N-3 */
-#define EV_NCCI_RESET_B3_IND                   9       /* N-3 -> N-ACT */
-#define EV_NCCI_DISCONNECT_B3_IND              10      /* N-4 -> N.5 */
-#define EV_NCCI_DISCONNECT_B3_CONF_ERROR       11      /* N-4 -> previous */
-#define EV_NCCI_DISCONNECT_B3_REQ              12      /* N-1 -> N-4
-                                                          N-2 -> N-4
-                                                          N-3 -> N-4
-                                                          N-ACT -> N-4 */
-#define EV_NCCI_DISCONNECT_B3_RESP             13      /* N-5 -> N-0 */
-
-#endif                         /* __CAPIDRV_H__ */
 
+++ /dev/null
-# SPDX-License-Identifier: GPL-2.0-only
-# Makefile for the dss1_divert ISDN module
-
-# Each configuration option enables a list of files.
-
-obj-$(CONFIG_ISDN_DIVERSION)   += dss1_divert.o
-
-# Multipart objects.
-
-dss1_divert-y                  := isdn_divert.o divert_procfs.o divert_init.o
 
+++ /dev/null
-/* $Id divert_init.c,v 1.5.6.2 2001/01/24 22:18:17 kai Exp $
- *
- * Module init for DSS1 diversion services for i4l.
- *
- * Copyright 1999       by Werner Cornelius (werner@isdn4linux.de)
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-
-#include "isdn_divert.h"
-
-MODULE_DESCRIPTION("ISDN4Linux: Call diversion support");
-MODULE_AUTHOR("Werner Cornelius");
-MODULE_LICENSE("GPL");
-
-/****************************************/
-/* structure containing interface to hl */
-/****************************************/
-isdn_divert_if divert_if = {
-       DIVERT_IF_MAGIC,        /* magic value */
-       DIVERT_CMD_REG,         /* register cmd */
-       ll_callback,            /* callback routine from ll */
-       NULL,                   /* command still not specified */
-       NULL,                   /* drv_to_name */
-       NULL,                   /* name_to_drv */
-};
-
-/*************************/
-/* Module interface code */
-/* no cmd line parms     */
-/*************************/
-static int __init divert_init(void)
-{
-       int i;
-
-       if (divert_dev_init()) {
-               printk(KERN_WARNING "dss1_divert: cannot install device, not loaded\n");
-               return (-EIO);
-       }
-       if ((i = DIVERT_REG_NAME(&divert_if)) != DIVERT_NO_ERR) {
-               divert_dev_deinit();
-               printk(KERN_WARNING "dss1_divert: error %d registering module, not loaded\n", i);
-               return (-EIO);
-       }
-       printk(KERN_INFO "dss1_divert module successfully installed\n");
-       return (0);
-}
-
-/**********************/
-/* Module deinit code */
-/**********************/
-static void __exit divert_exit(void)
-{
-       unsigned long flags;
-       int i;
-
-       spin_lock_irqsave(&divert_lock, flags);
-       divert_if.cmd = DIVERT_CMD_REL; /* release */
-       if ((i = DIVERT_REG_NAME(&divert_if)) != DIVERT_NO_ERR) {
-               printk(KERN_WARNING "dss1_divert: error %d releasing module\n", i);
-               spin_unlock_irqrestore(&divert_lock, flags);
-               return;
-       }
-       if (divert_dev_deinit()) {
-               printk(KERN_WARNING "dss1_divert: device busy, remove cancelled\n");
-               spin_unlock_irqrestore(&divert_lock, flags);
-               return;
-       }
-       spin_unlock_irqrestore(&divert_lock, flags);
-       deleterule(-1); /* delete all rules and free mem */
-       deleteprocs();
-       printk(KERN_INFO "dss1_divert module successfully removed \n");
-}
-
-module_init(divert_init);
-module_exit(divert_exit);
 
+++ /dev/null
-/* $Id: divert_procfs.c,v 1.11.6.2 2001/09/23 22:24:36 kai Exp $
- *
- * Filesystem handling for the diversion supplementary services.
- *
- * Copyright 1998       by Werner Cornelius (werner@isdn4linux.de)
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#include <linux/module.h>
-#include <linux/poll.h>
-#include <linux/slab.h>
-#ifdef CONFIG_PROC_FS
-#include <linux/proc_fs.h>
-#else
-#include <linux/fs.h>
-#endif
-#include <linux/sched.h>
-#include <linux/isdnif.h>
-#include <net/net_namespace.h>
-#include <linux/mutex.h>
-#include "isdn_divert.h"
-
-
-/*********************************/
-/* Variables for interface queue */
-/*********************************/
-ulong if_used = 0;             /* number of interface users */
-static DEFINE_MUTEX(isdn_divert_mutex);
-static struct divert_info *divert_info_head = NULL;    /* head of queue */
-static struct divert_info *divert_info_tail = NULL;    /* pointer to last entry */
-static DEFINE_SPINLOCK(divert_info_lock);/* lock for queue */
-static wait_queue_head_t rd_queue;
-
-/*********************************/
-/* put an info buffer into queue */
-/*********************************/
-void
-put_info_buffer(char *cp)
-{
-       struct divert_info *ib;
-       unsigned long flags;
-
-       if (if_used <= 0)
-               return;
-       if (!cp)
-               return;
-       if (!*cp)
-               return;
-       if (!(ib = kmalloc(sizeof(struct divert_info) + strlen(cp), GFP_ATOMIC)))
-               return; /* no memory */
-       strcpy(ib->info_start, cp);     /* set output string */
-       ib->next = NULL;
-       spin_lock_irqsave(&divert_info_lock, flags);
-       ib->usage_cnt = if_used;
-       if (!divert_info_head)
-               divert_info_head = ib;  /* new head */
-       else
-               divert_info_tail->next = ib;    /* follows existing messages */
-       divert_info_tail = ib;  /* new tail */
-
-       /* delete old entrys */
-       while (divert_info_head->next) {
-               if ((divert_info_head->usage_cnt <= 0) &&
-                   (divert_info_head->next->usage_cnt <= 0)) {
-                       ib = divert_info_head;
-                       divert_info_head = divert_info_head->next;
-                       kfree(ib);
-               } else
-                       break;
-       }                       /* divert_info_head->next */
-       spin_unlock_irqrestore(&divert_info_lock, flags);
-       wake_up_interruptible(&(rd_queue));
-}                              /* put_info_buffer */
-
-#ifdef CONFIG_PROC_FS
-
-/**********************************/
-/* deflection device read routine */
-/**********************************/
-static ssize_t
-isdn_divert_read(struct file *file, char __user *buf, size_t count, loff_t *off)
-{
-       struct divert_info *inf;
-       int len;
-
-       if (!(inf = *((struct divert_info **) file->private_data))) {
-               if (file->f_flags & O_NONBLOCK)
-                       return -EAGAIN;
-               wait_event_interruptible(rd_queue, (inf =
-                       *((struct divert_info **) file->private_data)));
-       }
-       if (!inf)
-               return (0);
-
-       inf->usage_cnt--;       /* new usage count */
-       file->private_data = &inf->next;        /* next structure */
-       if ((len = strlen(inf->info_start)) <= count) {
-               if (copy_to_user(buf, inf->info_start, len))
-                       return -EFAULT;
-               *off += len;
-               return (len);
-       }
-       return (0);
-}                              /* isdn_divert_read */
-
-/**********************************/
-/* deflection device write routine */
-/**********************************/
-static ssize_t
-isdn_divert_write(struct file *file, const char __user *buf, size_t count, loff_t *off)
-{
-       return (-ENODEV);
-}                              /* isdn_divert_write */
-
-
-/***************************************/
-/* select routines for various kernels */
-/***************************************/
-static __poll_t
-isdn_divert_poll(struct file *file, poll_table *wait)
-{
-       __poll_t mask = 0;
-
-       poll_wait(file, &(rd_queue), wait);
-       /* mask = EPOLLOUT | EPOLLWRNORM; */
-       if (*((struct divert_info **) file->private_data)) {
-               mask |= EPOLLIN | EPOLLRDNORM;
-       }
-       return mask;
-}                              /* isdn_divert_poll */
-
-/****************/
-/* Open routine */
-/****************/
-static int
-isdn_divert_open(struct inode *ino, struct file *filep)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&divert_info_lock, flags);
-       if_used++;
-       if (divert_info_head)
-               filep->private_data = &(divert_info_tail->next);
-       else
-               filep->private_data = &divert_info_head;
-       spin_unlock_irqrestore(&divert_info_lock, flags);
-       /*  start_divert(); */
-       return nonseekable_open(ino, filep);
-}                              /* isdn_divert_open */
-
-/*******************/
-/* close routine   */
-/*******************/
-static int
-isdn_divert_close(struct inode *ino, struct file *filep)
-{
-       struct divert_info *inf;
-       unsigned long flags;
-
-       spin_lock_irqsave(&divert_info_lock, flags);
-       if_used--;
-       inf = *((struct divert_info **) filep->private_data);
-       while (inf) {
-               inf->usage_cnt--;
-               inf = inf->next;
-       }
-       if (if_used <= 0)
-               while (divert_info_head) {
-                       inf = divert_info_head;
-                       divert_info_head = divert_info_head->next;
-                       kfree(inf);
-               }
-       spin_unlock_irqrestore(&divert_info_lock, flags);
-       return (0);
-}                              /* isdn_divert_close */
-
-/*********/
-/* IOCTL */
-/*********/
-static int isdn_divert_ioctl_unlocked(struct file *file, uint cmd, ulong arg)
-{
-       divert_ioctl dioctl;
-       int i;
-       unsigned long flags;
-       divert_rule *rulep;
-       char *cp;
-
-       if (copy_from_user(&dioctl, (void __user *) arg, sizeof(dioctl)))
-               return -EFAULT;
-
-       switch (cmd) {
-       case IIOCGETVER:
-               dioctl.drv_version = DIVERT_IIOC_VERSION;       /* set version */
-               break;
-
-       case IIOCGETDRV:
-               if ((dioctl.getid.drvid = divert_if.name_to_drv(dioctl.getid.drvnam)) < 0)
-                       return (-EINVAL);
-               break;
-
-       case IIOCGETNAM:
-               cp = divert_if.drv_to_name(dioctl.getid.drvid);
-               if (!cp)
-                       return (-EINVAL);
-               if (!*cp)
-                       return (-EINVAL);
-               strcpy(dioctl.getid.drvnam, cp);
-               break;
-
-       case IIOCGETRULE:
-               if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx)))
-                       return (-EINVAL);
-               dioctl.getsetrule.rule = *rulep;        /* copy data */
-               break;
-
-       case IIOCMODRULE:
-               if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx)))
-                       return (-EINVAL);
-               spin_lock_irqsave(&divert_lock, flags);
-               *rulep = dioctl.getsetrule.rule;        /* copy data */
-               spin_unlock_irqrestore(&divert_lock, flags);
-               return (0);     /* no copy required */
-               break;
-
-       case IIOCINSRULE:
-               return (insertrule(dioctl.getsetrule.ruleidx, &dioctl.getsetrule.rule));
-               break;
-
-       case IIOCDELRULE:
-               return (deleterule(dioctl.getsetrule.ruleidx));
-               break;
-
-       case IIOCDODFACT:
-               return (deflect_extern_action(dioctl.fwd_ctrl.subcmd,
-                                             dioctl.fwd_ctrl.callid,
-                                             dioctl.fwd_ctrl.to_nr));
-
-       case IIOCDOCFACT:
-       case IIOCDOCFDIS:
-       case IIOCDOCFINT:
-               if (!divert_if.drv_to_name(dioctl.cf_ctrl.drvid))
-                       return (-EINVAL);       /* invalid driver */
-               if (strnlen(dioctl.cf_ctrl.msn, sizeof(dioctl.cf_ctrl.msn)) ==
-                   sizeof(dioctl.cf_ctrl.msn))
-                       return -EINVAL;
-               if (strnlen(dioctl.cf_ctrl.fwd_nr, sizeof(dioctl.cf_ctrl.fwd_nr)) ==
-                   sizeof(dioctl.cf_ctrl.fwd_nr))
-                       return -EINVAL;
-               if ((i = cf_command(dioctl.cf_ctrl.drvid,
-                                   (cmd == IIOCDOCFACT) ? 1 : (cmd == IIOCDOCFDIS) ? 0 : 2,
-                                   dioctl.cf_ctrl.cfproc,
-                                   dioctl.cf_ctrl.msn,
-                                   dioctl.cf_ctrl.service,
-                                   dioctl.cf_ctrl.fwd_nr,
-                                   &dioctl.cf_ctrl.procid)))
-                       return (i);
-               break;
-
-       default:
-               return (-EINVAL);
-       }                       /* switch cmd */
-       return copy_to_user((void __user *)arg, &dioctl, sizeof(dioctl)) ? -EFAULT : 0;
-}                              /* isdn_divert_ioctl */
-
-static long isdn_divert_ioctl(struct file *file, uint cmd, ulong arg)
-{
-       long ret;
-
-       mutex_lock(&isdn_divert_mutex);
-       ret = isdn_divert_ioctl_unlocked(file, cmd, arg);
-       mutex_unlock(&isdn_divert_mutex);
-
-       return ret;
-}
-
-static const struct file_operations isdn_fops =
-{
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .read           = isdn_divert_read,
-       .write          = isdn_divert_write,
-       .poll           = isdn_divert_poll,
-       .unlocked_ioctl = isdn_divert_ioctl,
-       .open           = isdn_divert_open,
-       .release        = isdn_divert_close,
-};
-
-/****************************/
-/* isdn subdir in /proc/net */
-/****************************/
-static struct proc_dir_entry *isdn_proc_entry = NULL;
-static struct proc_dir_entry *isdn_divert_entry = NULL;
-#endif /* CONFIG_PROC_FS */
-
-/***************************************************************************/
-/* divert_dev_init must be called before the proc filesystem may be used   */
-/***************************************************************************/
-int
-divert_dev_init(void)
-{
-
-       init_waitqueue_head(&rd_queue);
-
-#ifdef CONFIG_PROC_FS
-       isdn_proc_entry = proc_mkdir("isdn", init_net.proc_net);
-       if (!isdn_proc_entry)
-               return (-1);
-       isdn_divert_entry = proc_create("divert", S_IFREG | S_IRUGO,
-                                       isdn_proc_entry, &isdn_fops);
-       if (!isdn_divert_entry) {
-               remove_proc_entry("isdn", init_net.proc_net);
-               return (-1);
-       }
-#endif /* CONFIG_PROC_FS */
-
-       return (0);
-}                              /* divert_dev_init */
-
-/***************************************************************************/
-/* divert_dev_deinit must be called before leaving isdn when included as   */
-/* a module.                                                               */
-/***************************************************************************/
-int
-divert_dev_deinit(void)
-{
-
-#ifdef CONFIG_PROC_FS
-       remove_proc_entry("divert", isdn_proc_entry);
-       remove_proc_entry("isdn", init_net.proc_net);
-#endif /* CONFIG_PROC_FS */
-
-       return (0);
-}                              /* divert_dev_deinit */
 
+++ /dev/null
-/* $Id: isdn_divert.c,v 1.6.6.3 2001/09/23 22:24:36 kai Exp $
- *
- * DSS1 main diversion supplementary handling for i4l.
- *
- * Copyright 1999       by Werner Cornelius (werner@isdn4linux.de)
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#include <linux/proc_fs.h>
-#include <linux/slab.h>
-#include <linux/timer.h>
-#include <linux/jiffies.h>
-
-#include "isdn_divert.h"
-
-/**********************************/
-/* structure keeping calling info */
-/**********************************/
-struct call_struc {
-       isdn_ctrl ics; /* delivered setup + driver parameters */
-       ulong divert_id; /* Id delivered to user */
-       unsigned char akt_state; /* actual state */
-       char deflect_dest[35]; /* deflection destination */
-       struct timer_list timer; /* timer control structure */
-       char info[90]; /* device info output */
-       struct call_struc *next; /* pointer to next entry */
-       struct call_struc *prev;
-};
-
-
-/********************************************/
-/* structure keeping deflection table entry */
-/********************************************/
-struct deflect_struc {
-       struct deflect_struc *next, *prev;
-       divert_rule rule; /* used rule */
-};
-
-
-/*****************************************/
-/* variables for main diversion services */
-/*****************************************/
-/* diversion/deflection processes */
-static struct call_struc *divert_head = NULL; /* head of remembered entrys */
-static ulong next_id = 1; /* next info id */
-static struct deflect_struc *table_head = NULL;
-static struct deflect_struc *table_tail = NULL;
-static unsigned char extern_wait_max = 4; /* maximum wait in s for external process */
-
-DEFINE_SPINLOCK(divert_lock);
-
-/***************************/
-/* timer callback function */
-/***************************/
-static void deflect_timer_expire(struct timer_list *t)
-{
-       unsigned long flags;
-       struct call_struc *cs = from_timer(cs, t, timer);
-
-       spin_lock_irqsave(&divert_lock, flags);
-       del_timer(&cs->timer); /* delete active timer */
-       spin_unlock_irqrestore(&divert_lock, flags);
-
-       switch (cs->akt_state) {
-       case DEFLECT_PROCEED:
-               cs->ics.command = ISDN_CMD_HANGUP; /* cancel action */
-               divert_if.ll_cmd(&cs->ics);
-               spin_lock_irqsave(&divert_lock, flags);
-               cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
-               cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
-               add_timer(&cs->timer);
-               spin_unlock_irqrestore(&divert_lock, flags);
-               break;
-
-       case DEFLECT_ALERT:
-               cs->ics.command = ISDN_CMD_REDIR; /* protocol */
-               strlcpy(cs->ics.parm.setup.phone, cs->deflect_dest, sizeof(cs->ics.parm.setup.phone));
-               strcpy(cs->ics.parm.setup.eazmsn, "Testtext delayed");
-               divert_if.ll_cmd(&cs->ics);
-               spin_lock_irqsave(&divert_lock, flags);
-               cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
-               cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
-               add_timer(&cs->timer);
-               spin_unlock_irqrestore(&divert_lock, flags);
-               break;
-
-       case DEFLECT_AUTODEL:
-       default:
-               spin_lock_irqsave(&divert_lock, flags);
-               if (cs->prev)
-                       cs->prev->next = cs->next; /* forward link */
-               else
-                       divert_head = cs->next;
-               if (cs->next)
-                       cs->next->prev = cs->prev; /* back link */
-               spin_unlock_irqrestore(&divert_lock, flags);
-               kfree(cs);
-               return;
-
-       } /* switch */
-} /* deflect_timer_func */
-
-
-/*****************************************/
-/* handle call forwarding de/activations */
-/* 0 = deact, 1 = act, 2 = interrogate   */
-/*****************************************/
-int cf_command(int drvid, int mode,
-              u_char proc, char *msn,
-              u_char service, char *fwd_nr, ulong *procid)
-{
-       unsigned long flags;
-       int retval, msnlen;
-       int fwd_len;
-       char *p, *ielenp, tmp[60];
-       struct call_struc *cs;
-
-       if (strchr(msn, '.')) return (-EINVAL); /* subaddress not allowed in msn */
-       if ((proc & 0x7F) > 2) return (-EINVAL);
-       proc &= 3;
-       p = tmp;
-       *p++ = 0x30; /* enumeration */
-       ielenp = p++; /* remember total length position */
-       *p++ = 0xa; /* proc tag */
-       *p++ = 1;   /* length */
-       *p++ = proc & 0x7F; /* procedure to de/activate/interrogate */
-       *p++ = 0xa; /* service tag */
-       *p++ = 1;   /* length */
-       *p++ = service; /* service to handle */
-
-       if (mode == 1) {
-               if (!*fwd_nr) return (-EINVAL); /* destination missing */
-               if (strchr(fwd_nr, '.')) return (-EINVAL); /* subaddress not allowed */
-               fwd_len = strlen(fwd_nr);
-               *p++ = 0x30; /* number enumeration */
-               *p++ = fwd_len + 2; /* complete forward to len */
-               *p++ = 0x80; /* fwd to nr */
-               *p++ = fwd_len; /* length of number */
-               strcpy(p, fwd_nr); /* copy number */
-               p += fwd_len; /* pointer beyond fwd */
-       } /* activate */
-
-       msnlen = strlen(msn);
-       *p++ = 0x80; /* msn number */
-       if (msnlen > 1) {
-               *p++ = msnlen; /* length */
-               strcpy(p, msn);
-               p += msnlen;
-       } else
-               *p++ = 0;
-
-       *ielenp = p - ielenp - 1; /* set total IE length */
-
-       /* allocate mem for information struct */
-       if (!(cs = kmalloc(sizeof(struct call_struc), GFP_ATOMIC)))
-               return (-ENOMEM); /* no memory */
-       timer_setup(&cs->timer, deflect_timer_expire, 0);
-       cs->info[0] = '\0';
-       cs->ics.driver = drvid;
-       cs->ics.command = ISDN_CMD_PROT_IO; /* protocol specific io */
-       cs->ics.arg = DSS1_CMD_INVOKE; /* invoke supplementary service */
-       cs->ics.parm.dss1_io.proc = (mode == 1) ? 7 : (mode == 2) ? 11 : 8; /* operation */
-       cs->ics.parm.dss1_io.timeout = 4000; /* from ETS 300 207-1 */
-       cs->ics.parm.dss1_io.datalen = p - tmp; /* total len */
-       cs->ics.parm.dss1_io.data = tmp; /* start of buffer */
-
-       spin_lock_irqsave(&divert_lock, flags);
-       cs->ics.parm.dss1_io.ll_id = next_id++; /* id for callback */
-       spin_unlock_irqrestore(&divert_lock, flags);
-       *procid = cs->ics.parm.dss1_io.ll_id;
-
-       sprintf(cs->info, "%d 0x%lx %s%s 0 %s %02x %d%s%s\n",
-               (!mode) ? DIVERT_DEACTIVATE : (mode == 1) ? DIVERT_ACTIVATE : DIVERT_REPORT,
-               cs->ics.parm.dss1_io.ll_id,
-               (mode != 2) ? "" : "0 ",
-               divert_if.drv_to_name(cs->ics.driver),
-               msn,
-               service & 0xFF,
-               proc,
-               (mode != 1) ? "" : " 0 ",
-               (mode != 1) ? "" : fwd_nr);
-
-       retval = divert_if.ll_cmd(&cs->ics); /* execute command */
-
-       if (!retval) {
-               cs->prev = NULL;
-               spin_lock_irqsave(&divert_lock, flags);
-               cs->next = divert_head;
-               divert_head = cs;
-               spin_unlock_irqrestore(&divert_lock, flags);
-       } else
-               kfree(cs);
-       return (retval);
-} /* cf_command */
-
-
-/****************************************/
-/* handle a external deflection command */
-/****************************************/
-int deflect_extern_action(u_char cmd, ulong callid, char *to_nr)
-{
-       struct call_struc *cs;
-       isdn_ctrl ic;
-       unsigned long flags;
-       int i;
-
-       if ((cmd & 0x7F) > 2) return (-EINVAL); /* invalid command */
-       cs = divert_head; /* start of parameter list */
-       while (cs) {
-               if (cs->divert_id == callid) break; /* found */
-               cs = cs->next;
-       } /* search entry */
-       if (!cs) return (-EINVAL); /* invalid callid */
-
-       ic.driver = cs->ics.driver;
-       ic.arg = cs->ics.arg;
-       i = -EINVAL;
-       if (cs->akt_state == DEFLECT_AUTODEL) return (i); /* no valid call */
-       switch (cmd & 0x7F) {
-       case 0: /* hangup */
-               del_timer(&cs->timer);
-               ic.command = ISDN_CMD_HANGUP;
-               i = divert_if.ll_cmd(&ic);
-               spin_lock_irqsave(&divert_lock, flags);
-               cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
-               cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
-               add_timer(&cs->timer);
-               spin_unlock_irqrestore(&divert_lock, flags);
-               break;
-
-       case 1: /* alert */
-               if (cs->akt_state == DEFLECT_ALERT) return (0);
-               cmd &= 0x7F; /* never wait */
-               del_timer(&cs->timer);
-               ic.command = ISDN_CMD_ALERT;
-               if ((i = divert_if.ll_cmd(&ic))) {
-                       spin_lock_irqsave(&divert_lock, flags);
-                       cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
-                       cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
-                       add_timer(&cs->timer);
-                       spin_unlock_irqrestore(&divert_lock, flags);
-               } else
-                       cs->akt_state = DEFLECT_ALERT;
-               break;
-
-       case 2: /* redir */
-               del_timer(&cs->timer);
-               strlcpy(cs->ics.parm.setup.phone, to_nr, sizeof(cs->ics.parm.setup.phone));
-               strcpy(cs->ics.parm.setup.eazmsn, "Testtext manual");
-               ic.command = ISDN_CMD_REDIR;
-               if ((i = divert_if.ll_cmd(&ic))) {
-                       spin_lock_irqsave(&divert_lock, flags);
-                       cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
-                       cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
-                       add_timer(&cs->timer);
-                       spin_unlock_irqrestore(&divert_lock, flags);
-               } else
-                       cs->akt_state = DEFLECT_ALERT;
-               break;
-
-       } /* switch */
-       return (i);
-} /* deflect_extern_action */
-
-/********************************/
-/* insert a new rule before idx */
-/********************************/
-int insertrule(int idx, divert_rule *newrule)
-{
-       struct deflect_struc *ds, *ds1 = NULL;
-       unsigned long flags;
-
-       if (!(ds = kmalloc(sizeof(struct deflect_struc), GFP_KERNEL)))
-               return (-ENOMEM); /* no memory */
-
-       ds->rule = *newrule; /* set rule */
-
-       spin_lock_irqsave(&divert_lock, flags);
-
-       if (idx >= 0) {
-               ds1 = table_head;
-               while ((ds1) && (idx > 0))
-               { idx--;
-                       ds1 = ds1->next;
-               }
-               if (!ds1) idx = -1;
-       }
-
-       if (idx < 0) {
-               ds->prev = table_tail; /* previous entry */
-               ds->next = NULL; /* end of chain */
-               if (ds->prev)
-                       ds->prev->next = ds; /* last forward */
-               else
-                       table_head = ds; /* is first entry */
-               table_tail = ds; /* end of queue */
-       } else {
-               ds->next = ds1; /* next entry */
-               ds->prev = ds1->prev; /* prev entry */
-               ds1->prev = ds; /* backward chain old element */
-               if (!ds->prev)
-                       table_head = ds; /* first element */
-       }
-
-       spin_unlock_irqrestore(&divert_lock, flags);
-       return (0);
-} /* insertrule */
-
-/***********************************/
-/* delete the rule at position idx */
-/***********************************/
-int deleterule(int idx)
-{
-       struct deflect_struc *ds, *ds1;
-       unsigned long flags;
-
-       if (idx < 0) {
-               spin_lock_irqsave(&divert_lock, flags);
-               ds = table_head;
-               table_head = NULL;
-               table_tail = NULL;
-               spin_unlock_irqrestore(&divert_lock, flags);
-               while (ds) {
-                       ds1 = ds;
-                       ds = ds->next;
-                       kfree(ds1);
-               }
-               return (0);
-       }
-
-       spin_lock_irqsave(&divert_lock, flags);
-       ds = table_head;
-
-       while ((ds) && (idx > 0)) {
-               idx--;
-               ds = ds->next;
-       }
-
-       if (!ds) {
-               spin_unlock_irqrestore(&divert_lock, flags);
-               return (-EINVAL);
-       }
-
-       if (ds->next)
-               ds->next->prev = ds->prev; /* backward chain */
-       else
-               table_tail = ds->prev; /* end of chain */
-
-       if (ds->prev)
-               ds->prev->next = ds->next; /* forward chain */
-       else
-               table_head = ds->next; /* start of chain */
-
-       spin_unlock_irqrestore(&divert_lock, flags);
-       kfree(ds);
-       return (0);
-} /* deleterule */
-
-/*******************************************/
-/* get a pointer to a specific rule number */
-/*******************************************/
-divert_rule *getruleptr(int idx)
-{
-       struct deflect_struc *ds = table_head;
-
-       if (idx < 0) return (NULL);
-       while ((ds) && (idx >= 0)) {
-               if (!(idx--)) {
-                       return (&ds->rule);
-                       break;
-               }
-               ds = ds->next;
-       }
-       return (NULL);
-} /* getruleptr */
-
-/*************************************************/
-/* called from common module on an incoming call */
-/*************************************************/
-static int isdn_divert_icall(isdn_ctrl *ic)
-{
-       int retval = 0;
-       unsigned long flags;
-       struct call_struc *cs = NULL;
-       struct deflect_struc *dv;
-       char *p, *p1;
-       u_char accept;
-
-       /* first check the internal deflection table */
-       for (dv = table_head; dv; dv = dv->next) {
-               /* scan table */
-               if (((dv->rule.callopt == 1) && (ic->command == ISDN_STAT_ICALLW)) ||
-                   ((dv->rule.callopt == 2) && (ic->command == ISDN_STAT_ICALL)))
-                       continue; /* call option check */
-               if (!(dv->rule.drvid & (1L << ic->driver)))
-                       continue; /* driver not matching */
-               if ((dv->rule.si1) && (dv->rule.si1 != ic->parm.setup.si1))
-                       continue; /* si1 not matching */
-               if ((dv->rule.si2) && (dv->rule.si2 != ic->parm.setup.si2))
-                       continue; /* si2 not matching */
-
-               p = dv->rule.my_msn;
-               p1 = ic->parm.setup.eazmsn;
-               accept = 0;
-               while (*p) {
-                       /* complete compare */
-                       if (*p == '-') {
-                               accept = 1; /* call accepted */
-                               break;
-                       }
-                       if (*p++ != *p1++)
-                               break; /* not accepted */
-                       if ((!*p) && (!*p1))
-                               accept = 1;
-               } /* complete compare */
-               if (!accept) continue; /* not accepted */
-
-               if ((strcmp(dv->rule.caller, "0")) ||
-                   (ic->parm.setup.phone[0])) {
-                       p = dv->rule.caller;
-                       p1 = ic->parm.setup.phone;
-                       accept = 0;
-                       while (*p) {
-                               /* complete compare */
-                               if (*p == '-') {
-                                       accept = 1; /* call accepted */
-                                       break;
-                               }
-                               if (*p++ != *p1++)
-                                       break; /* not accepted */
-                               if ((!*p) && (!*p1))
-                                       accept = 1;
-                       } /* complete compare */
-                       if (!accept) continue; /* not accepted */
-               }
-
-               switch (dv->rule.action) {
-               case DEFLECT_IGNORE:
-                       return 0;
-
-               case DEFLECT_ALERT:
-               case DEFLECT_PROCEED:
-               case DEFLECT_REPORT:
-               case DEFLECT_REJECT:
-                       if (dv->rule.action == DEFLECT_PROCEED)
-                               if ((!if_used) || ((!extern_wait_max) && (!dv->rule.waittime)))
-                                       return (0); /* no external deflection needed */
-                       if (!(cs = kmalloc(sizeof(struct call_struc), GFP_ATOMIC)))
-                               return (0); /* no memory */
-                       timer_setup(&cs->timer, deflect_timer_expire, 0);
-                       cs->info[0] = '\0';
-
-                       cs->ics = *ic; /* copy incoming data */
-                       if (!cs->ics.parm.setup.phone[0]) strcpy(cs->ics.parm.setup.phone, "0");
-                       if (!cs->ics.parm.setup.eazmsn[0]) strcpy(cs->ics.parm.setup.eazmsn, "0");
-                       cs->ics.parm.setup.screen = dv->rule.screen;
-                       if (dv->rule.waittime)
-                               cs->timer.expires = jiffies + (HZ * dv->rule.waittime);
-                       else if (dv->rule.action == DEFLECT_PROCEED)
-                               cs->timer.expires = jiffies + (HZ * extern_wait_max);
-                       else
-                               cs->timer.expires = 0;
-                       cs->akt_state = dv->rule.action;
-                       spin_lock_irqsave(&divert_lock, flags);
-                       cs->divert_id = next_id++; /* new sequence number */
-                       spin_unlock_irqrestore(&divert_lock, flags);
-                       cs->prev = NULL;
-                       if (cs->akt_state == DEFLECT_ALERT) {
-                               strcpy(cs->deflect_dest, dv->rule.to_nr);
-                               if (!cs->timer.expires) {
-                                       strcpy(ic->parm.setup.eazmsn,
-                                              "Testtext direct");
-                                       ic->parm.setup.screen = dv->rule.screen;
-                                       strlcpy(ic->parm.setup.phone, dv->rule.to_nr, sizeof(ic->parm.setup.phone));
-                                       cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
-                                       cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
-                                       retval = 5;
-                               } else
-                                       retval = 1; /* alerting */
-                       } else {
-                               cs->deflect_dest[0] = '\0';
-                               retval = 4; /* only proceed */
-                       }
-                       snprintf(cs->info, sizeof(cs->info),
-                                "%d 0x%lx %s %s %s %s 0x%x 0x%x %d %d %s\n",
-                                cs->akt_state,
-                                cs->divert_id,
-                                divert_if.drv_to_name(cs->ics.driver),
-                                (ic->command == ISDN_STAT_ICALLW) ? "1" : "0",
-                                cs->ics.parm.setup.phone,
-                                cs->ics.parm.setup.eazmsn,
-                                cs->ics.parm.setup.si1,
-                                cs->ics.parm.setup.si2,
-                                cs->ics.parm.setup.screen,
-                                dv->rule.waittime,
-                                cs->deflect_dest);
-                       if ((dv->rule.action == DEFLECT_REPORT) ||
-                           (dv->rule.action == DEFLECT_REJECT)) {
-                               put_info_buffer(cs->info);
-                               kfree(cs); /* remove */
-                               return ((dv->rule.action == DEFLECT_REPORT) ? 0 : 2); /* nothing to do */
-                       }
-                       break;
-
-               default:
-                       return 0; /* ignore call */
-               } /* switch action */
-               break; /* will break the 'for' looping */
-       } /* scan_table */
-
-       if (cs) {
-               cs->prev = NULL;
-               spin_lock_irqsave(&divert_lock, flags);
-               cs->next = divert_head;
-               divert_head = cs;
-               if (cs->timer.expires) add_timer(&cs->timer);
-               spin_unlock_irqrestore(&divert_lock, flags);
-
-               put_info_buffer(cs->info);
-               return (retval);
-       } else
-               return (0);
-} /* isdn_divert_icall */
-
-
-void deleteprocs(void)
-{
-       struct call_struc *cs, *cs1;
-       unsigned long flags;
-
-       spin_lock_irqsave(&divert_lock, flags);
-       cs = divert_head;
-       divert_head = NULL;
-       while (cs) {
-               del_timer(&cs->timer);
-               cs1 = cs;
-               cs = cs->next;
-               kfree(cs1);
-       }
-       spin_unlock_irqrestore(&divert_lock, flags);
-} /* deleteprocs */
-
-/****************************************************/
-/* put a address including address type into buffer */
-/****************************************************/
-static int put_address(char *st, u_char *p, int len)
-{
-       u_char retval = 0;
-       u_char adr_typ = 0; /* network standard */
-
-       if (len < 2) return (retval);
-       if (*p == 0xA1) {
-               retval = *(++p) + 2; /* total length */
-               if (retval > len) return (0); /* too short */
-               len = retval - 2; /* remaining length */
-               if (len < 3) return (0);
-               if ((*(++p) != 0x0A) || (*(++p) != 1)) return (0);
-               adr_typ = *(++p);
-               len -= 3;
-               p++;
-               if (len < 2) return (0);
-               if (*p++ != 0x12) return (0);
-               if (*p > len) return (0); /* check number length */
-               len = *p++;
-       } else if (*p == 0x80) {
-               retval = *(++p) + 2; /* total length */
-               if (retval > len) return (0);
-               len = retval - 2;
-               p++;
-       } else
-               return (0); /* invalid address information */
-
-       sprintf(st, "%d ", adr_typ);
-       st += strlen(st);
-       if (!len)
-               *st++ = '-';
-       else
-               while (len--)
-                       *st++ = *p++;
-       *st = '\0';
-       return (retval);
-} /* put_address */
-
-/*************************************/
-/* report a successful interrogation */
-/*************************************/
-static int interrogate_success(isdn_ctrl *ic, struct call_struc *cs)
-{
-       char *src = ic->parm.dss1_io.data;
-       int restlen = ic->parm.dss1_io.datalen;
-       int cnt = 1;
-       u_char n, n1;
-       char st[90], *p, *stp;
-
-       if (restlen < 2) return (-100); /* frame too short */
-       if (*src++ != 0x30) return (-101);
-       if ((n = *src++) > 0x81) return (-102); /* invalid length field */
-       restlen -= 2; /* remaining bytes */
-       if (n == 0x80) {
-               if (restlen < 2) return (-103);
-               if ((*(src + restlen - 1)) || (*(src + restlen - 2))) return (-104);
-               restlen -= 2;
-       } else if (n == 0x81) {
-               n = *src++;
-               restlen--;
-               if (n > restlen) return (-105);
-               restlen = n;
-       } else if (n > restlen)
-               return (-106);
-       else
-               restlen = n; /* standard format */
-       if (restlen < 3) return (-107); /* no procedure */
-       if ((*src++ != 2) || (*src++ != 1) || (*src++ != 0x0B)) return (-108);
-       restlen -= 3;
-       if (restlen < 2) return (-109); /* list missing */
-       if (*src == 0x31) {
-               src++;
-               if ((n = *src++) > 0x81) return (-110); /* invalid length field */
-               restlen -= 2; /* remaining bytes */
-               if (n == 0x80) {
-                       if (restlen < 2) return (-111);
-                       if ((*(src + restlen - 1)) || (*(src + restlen - 2))) return (-112);
-                       restlen -= 2;
-               } else if (n == 0x81) {
-                       n = *src++;
-                       restlen--;
-                       if (n > restlen) return (-113);
-                       restlen = n;
-               } else if (n > restlen)
-                       return (-114);
-               else
-                       restlen = n; /* standard format */
-       } /* result list header */
-
-       while (restlen >= 2) {
-               stp = st;
-               sprintf(stp, "%d 0x%lx %d %s ", DIVERT_REPORT, ic->parm.dss1_io.ll_id,
-                       cnt++, divert_if.drv_to_name(ic->driver));
-               stp += strlen(stp);
-               if (*src++ != 0x30) return (-115); /* invalid enum */
-               n = *src++;
-               restlen -= 2;
-               if (n > restlen) return (-116); /* enum length wrong */
-               restlen -= n;
-               p = src; /* one entry */
-               src += n;
-               if (!(n1 = put_address(stp, p, n & 0xFF))) continue;
-               stp += strlen(stp);
-               p += n1;
-               n -= n1;
-               if (n < 6) continue; /* no service and proc */
-               if ((*p++ != 0x0A) || (*p++ != 1)) continue;
-               sprintf(stp, " 0x%02x ", (*p++) & 0xFF);
-               stp += strlen(stp);
-               if ((*p++ != 0x0A) || (*p++ != 1)) continue;
-               sprintf(stp, "%d ", (*p++) & 0xFF);
-               stp += strlen(stp);
-               n -= 6;
-               if (n > 2) {
-                       if (*p++ != 0x30) continue;
-                       if (*p > (n - 2)) continue;
-                       n = *p++;
-                       if (!(n1 = put_address(stp, p, n & 0xFF))) continue;
-                       stp += strlen(stp);
-               }
-               sprintf(stp, "\n");
-               put_info_buffer(st);
-       } /* while restlen */
-       if (restlen) return (-117);
-       return (0);
-} /* interrogate_success */
-
-/*********************************************/
-/* callback for protocol specific extensions */
-/*********************************************/
-static int prot_stat_callback(isdn_ctrl *ic)
-{
-       struct call_struc *cs, *cs1;
-       int i;
-       unsigned long flags;
-
-       cs = divert_head; /* start of list */
-       cs1 = NULL;
-       while (cs) {
-               if (ic->driver == cs->ics.driver) {
-                       switch (cs->ics.arg) {
-                       case DSS1_CMD_INVOKE:
-                               if ((cs->ics.parm.dss1_io.ll_id == ic->parm.dss1_io.ll_id) &&
-                                   (cs->ics.parm.dss1_io.hl_id == ic->parm.dss1_io.hl_id)) {
-                                       switch (ic->arg) {
-                                       case DSS1_STAT_INVOKE_ERR:
-                                               sprintf(cs->info, "128 0x%lx 0x%x\n",
-                                                       ic->parm.dss1_io.ll_id,
-                                                       ic->parm.dss1_io.timeout);
-                                               put_info_buffer(cs->info);
-                                               break;
-
-                                       case DSS1_STAT_INVOKE_RES:
-                                               switch (cs->ics.parm.dss1_io.proc) {
-                                               case  7:
-                                               case  8:
-                                                       put_info_buffer(cs->info);
-                                                       break;
-
-                                               case  11:
-                                                       i = interrogate_success(ic, cs);
-                                                       if (i)
-                                                               sprintf(cs->info, "%d 0x%lx %d\n", DIVERT_REPORT,
-                                                                       ic->parm.dss1_io.ll_id, i);
-                                                       put_info_buffer(cs->info);
-                                                       break;
-
-                                               default:
-                                                       printk(KERN_WARNING "dss1_divert: unknown proc %d\n", cs->ics.parm.dss1_io.proc);
-                                                       break;
-                                               }
-
-                                               break;
-
-                                       default:
-                                               printk(KERN_WARNING "dss1_divert unknown invoke answer %lx\n", ic->arg);
-                                               break;
-                                       }
-                                       cs1 = cs; /* remember structure */
-                                       cs = NULL;
-                                       continue; /* abort search */
-                               } /* id found */
-                               break;
-
-                       case DSS1_CMD_INVOKE_ABORT:
-                               printk(KERN_WARNING "dss1_divert unhandled invoke abort\n");
-                               break;
-
-                       default:
-                               printk(KERN_WARNING "dss1_divert unknown cmd 0x%lx\n", cs->ics.arg);
-                               break;
-                       } /* switch ics.arg */
-                       cs = cs->next;
-               } /* driver ok */
-       }
-
-       if (!cs1) {
-               printk(KERN_WARNING "dss1_divert unhandled process\n");
-               return (0);
-       }
-
-       if (cs1->ics.driver == -1) {
-               spin_lock_irqsave(&divert_lock, flags);
-               del_timer(&cs1->timer);
-               if (cs1->prev)
-                       cs1->prev->next = cs1->next; /* forward link */
-               else
-                       divert_head = cs1->next;
-               if (cs1->next)
-                       cs1->next->prev = cs1->prev; /* back link */
-               spin_unlock_irqrestore(&divert_lock, flags);
-               kfree(cs1);
-       }
-
-       return (0);
-} /* prot_stat_callback */
-
-
-/***************************/
-/* status callback from HL */
-/***************************/
-static int isdn_divert_stat_callback(isdn_ctrl *ic)
-{
-       struct call_struc *cs, *cs1;
-       unsigned long flags;
-       int retval;
-
-       retval = -1;
-       cs = divert_head; /* start of list */
-       while (cs) {
-               if ((ic->driver == cs->ics.driver) &&
-                   (ic->arg == cs->ics.arg)) {
-                       switch (ic->command) {
-                       case ISDN_STAT_DHUP:
-                               sprintf(cs->info, "129 0x%lx\n", cs->divert_id);
-                               del_timer(&cs->timer);
-                               cs->ics.driver = -1;
-                               break;
-
-                       case ISDN_STAT_CAUSE:
-                               sprintf(cs->info, "130 0x%lx %s\n", cs->divert_id, ic->parm.num);
-                               break;
-
-                       case ISDN_STAT_REDIR:
-                               sprintf(cs->info, "131 0x%lx\n", cs->divert_id);
-                               del_timer(&cs->timer);
-                               cs->ics.driver = -1;
-                               break;
-
-                       default:
-                               sprintf(cs->info, "999 0x%lx 0x%x\n", cs->divert_id, (int)(ic->command));
-                               break;
-                       }
-                       put_info_buffer(cs->info);
-                       retval = 0;
-               }
-               cs1 = cs;
-               cs = cs->next;
-               if (cs1->ics.driver == -1) {
-                       spin_lock_irqsave(&divert_lock, flags);
-                       if (cs1->prev)
-                               cs1->prev->next = cs1->next; /* forward link */
-                       else
-                               divert_head = cs1->next;
-                       if (cs1->next)
-                               cs1->next->prev = cs1->prev; /* back link */
-                       spin_unlock_irqrestore(&divert_lock, flags);
-                       kfree(cs1);
-               }
-       }
-       return (retval); /* not found */
-} /* isdn_divert_stat_callback */
-
-
-/********************/
-/* callback from ll */
-/********************/
-int ll_callback(isdn_ctrl *ic)
-{
-       switch (ic->command) {
-       case ISDN_STAT_ICALL:
-       case ISDN_STAT_ICALLW:
-               return (isdn_divert_icall(ic));
-               break;
-
-       case ISDN_STAT_PROT:
-               if ((ic->arg & 0xFF) == ISDN_PTYPE_EURO) {
-                       if (ic->arg != DSS1_STAT_INVOKE_BRD)
-                               return (prot_stat_callback(ic));
-                       else
-                               return (0); /* DSS1 invoke broadcast */
-               } else
-                       return (-1); /* protocol not euro */
-
-       default:
-               return (isdn_divert_stat_callback(ic));
-       }
-} /* ll_callback */
 
+++ /dev/null
-/* $Id: isdn_divert.h,v 1.5.6.1 2001/09/23 22:24:36 kai Exp $
- *
- * Header for the diversion supplementary ioctl interface.
- *
- * Copyright 1998       by Werner Cornelius (werner@ikt.de)
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#include <linux/ioctl.h>
-#include <linux/types.h>
-
-/******************************************/
-/* IOCTL codes for interface to user prog */
-/******************************************/
-#define DIVERT_IIOC_VERSION 0x01 /* actual version */
-#define IIOCGETVER   _IO('I', 1)  /* get version of interface */
-#define IIOCGETDRV   _IO('I', 2)  /* get driver number */
-#define IIOCGETNAM   _IO('I', 3)  /* get driver name */
-#define IIOCGETRULE  _IO('I', 4)  /* read one rule */
-#define IIOCMODRULE  _IO('I', 5)  /* modify/replace a rule */
-#define IIOCINSRULE  _IO('I', 6)  /* insert/append one rule */
-#define IIOCDELRULE  _IO('I', 7)  /* delete a rule */
-#define IIOCDODFACT  _IO('I', 8)  /* hangup/reject/alert/immediately deflect a call */
-#define IIOCDOCFACT  _IO('I', 9)  /* activate control forwarding in PBX */
-#define IIOCDOCFDIS  _IO('I', 10)  /* deactivate control forwarding in PBX */
-#define IIOCDOCFINT  _IO('I', 11)  /* interrogate control forwarding in PBX */
-
-/*************************************/
-/* states reported through interface */
-/*************************************/
-#define DEFLECT_IGNORE    0  /* ignore incoming call */
-#define DEFLECT_REPORT    1  /* only report */
-#define DEFLECT_PROCEED   2  /* deflect when externally triggered */
-#define DEFLECT_ALERT     3  /* alert and deflect after delay */
-#define DEFLECT_REJECT    4  /* reject immediately */
-#define DIVERT_ACTIVATE   5  /* diversion activate */
-#define DIVERT_DEACTIVATE 6  /* diversion deactivate */
-#define DIVERT_REPORT     7  /* interrogation result */
-#define DEFLECT_AUTODEL 255  /* only for internal use */
-
-#define DEFLECT_ALL_IDS   0xFFFFFFFF /* all drivers selected */
-
-typedef struct {
-       ulong drvid;     /* driver ids, bit mapped */
-       char my_msn[35]; /* desired msn, subaddr allowed */
-       char caller[35]; /* caller id, partial string with * + subaddr allowed */
-       char to_nr[35];  /* deflected to number incl. subaddress */
-       u_char si1, si2;  /* service indicators, si1=bitmask, si1+2 0 = all */
-       u_char screen;   /* screening: 0 = no info, 1 = info, 2 = nfo with nr */
-       u_char callopt;  /* option for call handling:
-                           0 = all calls
-                           1 = only non waiting calls
-                           2 = only waiting calls */
-       u_char action;   /* desired action:
-                           0 = don't report call -> ignore
-                           1 = report call, do not allow/proceed for deflection
-                           2 = report call, send proceed, wait max waittime secs
-                           3 = report call, alert and deflect after waittime
-                           4 = report call, reject immediately
-                           actions 1-2 only take place if interface is opened
-                        */
-       u_char waittime; /* maximum wait time for proceeding */
-} divert_rule;
-
-typedef union {
-       int drv_version; /* return of driver version */
-       struct {
-               int drvid;              /* id of driver */
-               char drvnam[30];        /* name of driver */
-       } getid;
-       struct {
-               int ruleidx;    /* index of rule */
-               divert_rule rule;       /* rule parms */
-       } getsetrule;
-       struct {
-               u_char subcmd;  /* 0 = hangup/reject,
-                            1 = alert,
-                            2 = deflect */
-               ulong callid;   /* id of call delivered by ascii output */
-               char to_nr[35]; /* destination when deflect,
-                                  else uus1 string (maxlen 31),
-                                  data from rule used if empty */
-       } fwd_ctrl;
-       struct {
-               int drvid;      /* id of driver */
-               u_char cfproc;  /* cfu = 0, cfb = 1, cfnr = 2 */
-               ulong procid;   /* process id returned when no error */
-               u_char service; /* basically coded service, 0 = all */
-               char msn[25];   /* desired msn, empty = all */
-               char fwd_nr[35];/* forwarded to number + subaddress */
-       } cf_ctrl;
-} divert_ioctl;
-
-#ifdef __KERNEL__
-
-#include <linux/isdnif.h>
-#include <linux/isdn_divertif.h>
-
-#define AUTODEL_TIME 30 /* timeout in s to delete internal entries */
-
-/**************************************************/
-/* structure keeping ascii info for device output */
-/**************************************************/
-struct divert_info {
-       struct divert_info *next;
-       ulong usage_cnt; /* number of files still to work */
-       char info_start[2]; /* info string start */
-};
-
-
-/**************/
-/* Prototypes */
-/**************/
-extern spinlock_t divert_lock;
-
-extern ulong if_used; /* number of interface users */
-extern int divert_dev_deinit(void);
-extern int divert_dev_init(void);
-extern void put_info_buffer(char *);
-extern int ll_callback(isdn_ctrl *);
-extern isdn_divert_if divert_if;
-extern divert_rule *getruleptr(int);
-extern int insertrule(int, divert_rule *);
-extern int deleterule(int);
-extern void deleteprocs(void);
-extern int deflect_extern_action(u_char, ulong, char *);
-extern int cf_command(int, int, u_char, char *, u_char, char *, ulong *);
-
-#endif /* __KERNEL__ */
 
+++ /dev/null
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# Old ISDN4Linux config
-#
-
-if ISDN_I4L
-
-config ISDN_PPP
-       bool "Support synchronous PPP"
-       depends on INET
-       select SLHC
-       help
-         Over digital connections such as ISDN, there is no need to
-         synchronize sender and recipient's clocks with start and stop bits
-         as is done over analog telephone lines. Instead, one can use
-         "synchronous PPP". Saying Y here will include this protocol. This
-         protocol is used by Cisco and Sun for example. So you want to say Y
-         here if the other end of your ISDN connection supports it. You will
-         need a special version of pppd (called ipppd) for using this
-         feature. See <file:Documentation/isdn/README.syncppp> and
-         <file:Documentation/isdn/syncPPP.FAQ> for more information.
-
-config ISDN_PPP_VJ
-       bool "Use VJ-compression with synchronous PPP"
-       depends on ISDN_PPP
-       help
-         This enables Van Jacobson header compression for synchronous PPP.
-         Say Y if the other end of the connection supports it.
-
-config ISDN_MPP
-       bool "Support generic MP (RFC 1717)"
-       depends on ISDN_PPP
-       help
-         With synchronous PPP enabled, it is possible to increase throughput
-         by bundling several ISDN-connections, using this protocol. See
-         <file:Documentation/isdn/README.syncppp> for more information.
-
-config IPPP_FILTER
-       bool "Filtering for synchronous PPP"
-       depends on ISDN_PPP
-       help
-         Say Y here if you want to be able to filter the packets passing over
-         IPPP interfaces.  This allows you to control which packets count as
-         activity (i.e. which packets will reset the idle timer or bring up
-         a demand-dialled link) and which packets are to be dropped entirely.
-         You need to say Y here if you wish to use the pass-filter and
-         active-filter options to ipppd.
-
-config ISDN_PPP_BSDCOMP
-       tristate "Support BSD compression"
-       depends on ISDN_PPP
-       help
-         Support for the BSD-Compress compression method for PPP, which uses
-         the LZW compression method to compress each PPP packet before it is
-         sent over the wire. The machine at the other end of the PPP link
-         (usually your ISP) has to support the BSD-Compress compression
-         method as well for this to be useful. Even if they don't support it,
-         it is safe to say Y here.
-
-config ISDN_AUDIO
-       bool "Support audio via ISDN"
-       help
-         If you say Y here, the modem-emulator will support a subset of the
-         EIA Class 8 Voice commands. Using a getty with voice-support
-         (mgetty+sendfax by <gert@greenie.muc.de> with an extension, available
-         with the ISDN utility package for example), you will be able to use
-         your Linux box as an ISDN-answering machine. Of course, this must be
-         supported by the lowlevel driver also. Currently, the HiSax driver
-         is the only voice-supporting driver. See
-         <file:Documentation/isdn/README.audio> for more information.
-
-config ISDN_TTY_FAX
-       bool "Support AT-Fax Class 1 and 2 commands"
-       depends on ISDN_AUDIO
-       help
-         If you say Y here, the modem-emulator will support a subset of the
-         Fax Class 1 and 2 commands. Using a getty with fax-support
-         (mgetty+sendfax, hylafax), you will be able to use your Linux box as
-         an ISDN-fax-machine. This must be supported by the lowlevel driver
-         also. See <file:Documentation/isdn/README.fax> for more information.
-
-config ISDN_X25
-       bool "X.25 PLP on top of ISDN"
-       depends on X25
-       help
-         This feature provides the X.25 protocol over ISDN connections.
-         See <file:Documentation/isdn/README.x25> for more information
-         if you are thinking about using this.
-
-
-menu "ISDN feature submodules"
-
-config ISDN_DRV_LOOP
-       tristate "isdnloop support"
-       depends on BROKEN_ON_SMP
-       help
-         This driver provides a virtual ISDN card. Its primary purpose is
-         testing of linklevel features or configuration without getting
-         charged by your service-provider for lots of phone calls.
-         You need will need the loopctrl utility from the latest isdn4k-utils
-         package to set up this driver.
-
-config ISDN_DIVERSION
-       tristate "Support isdn diversion services"
-       help
-         This option allows you to use some supplementary diversion
-         services in conjunction with the HiSax driver on an EURO/DSS1
-         line.
-
-         Supported options are CD (call deflection), CFU (Call forward
-         unconditional), CFB (Call forward when busy) and CFNR (call forward
-         not reachable). Additionally the actual CFU, CFB and CFNR state may
-         be interrogated.
-
-         The use of CFU, CFB, CFNR and interrogation may be limited to some
-         countries. The keypad protocol is still not implemented. CD should
-         work in all countries if the service has been subscribed to.
-
-         Please read the file <file:Documentation/isdn/README.diversion>.
-
-endmenu
-
-comment "ISDN4Linux hardware drivers"
-
-# end ISDN_I4L
-endif
-
 
 
 # Each configuration option enables a list of files.
 
-obj-$(CONFIG_ISDN_I4L)         += isdn.o
-obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o
 obj-$(CONFIG_ISDN_HDLC)                += isdnhdlc.o
-
-# Multipart objects.
-
-isdn-y                         := isdn_net.o isdn_tty.o isdn_v110.o isdn_common.o
-
-# Optional parts of multipart objects.
-
-isdn-$(CONFIG_ISDN_PPP)                += isdn_ppp.o
-isdn-$(CONFIG_ISDN_X25)                += isdn_concap.o isdn_x25iface.o
-isdn-$(CONFIG_ISDN_AUDIO)              += isdn_audio.o
-isdn-$(CONFIG_ISDN_TTY_FAX)    += isdn_ttyfax.o
-
 
+++ /dev/null
-/* $Id: isdn_audio.c,v 1.1.2.2 2004/01/12 22:37:18 keil Exp $
- *
- * Linux ISDN subsystem, audio conversion and compression (linklevel).
- *
- * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
- * DTMF code (c) 1996 by Christian Mock (cm@kukuruz.ping.at)
- * Silence detection (c) 1998 by Armin Schindler (mac@gismo.telekom.de)
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#include <linux/isdn.h>
-#include <linux/slab.h>
-#include "isdn_audio.h"
-#include "isdn_common.h"
-
-char *isdn_audio_revision = "$Revision: 1.1.2.2 $";
-
-/*
- * Misc. lookup-tables.
- */
-
-/* ulaw -> signed 16-bit */
-static short isdn_audio_ulaw_to_s16[] =
-{
-       0x8284, 0x8684, 0x8a84, 0x8e84, 0x9284, 0x9684, 0x9a84, 0x9e84,
-       0xa284, 0xa684, 0xaa84, 0xae84, 0xb284, 0xb684, 0xba84, 0xbe84,
-       0xc184, 0xc384, 0xc584, 0xc784, 0xc984, 0xcb84, 0xcd84, 0xcf84,
-       0xd184, 0xd384, 0xd584, 0xd784, 0xd984, 0xdb84, 0xdd84, 0xdf84,
-       0xe104, 0xe204, 0xe304, 0xe404, 0xe504, 0xe604, 0xe704, 0xe804,
-       0xe904, 0xea04, 0xeb04, 0xec04, 0xed04, 0xee04, 0xef04, 0xf004,
-       0xf0c4, 0xf144, 0xf1c4, 0xf244, 0xf2c4, 0xf344, 0xf3c4, 0xf444,
-       0xf4c4, 0xf544, 0xf5c4, 0xf644, 0xf6c4, 0xf744, 0xf7c4, 0xf844,
-       0xf8a4, 0xf8e4, 0xf924, 0xf964, 0xf9a4, 0xf9e4, 0xfa24, 0xfa64,
-       0xfaa4, 0xfae4, 0xfb24, 0xfb64, 0xfba4, 0xfbe4, 0xfc24, 0xfc64,
-       0xfc94, 0xfcb4, 0xfcd4, 0xfcf4, 0xfd14, 0xfd34, 0xfd54, 0xfd74,
-       0xfd94, 0xfdb4, 0xfdd4, 0xfdf4, 0xfe14, 0xfe34, 0xfe54, 0xfe74,
-       0xfe8c, 0xfe9c, 0xfeac, 0xfebc, 0xfecc, 0xfedc, 0xfeec, 0xfefc,
-       0xff0c, 0xff1c, 0xff2c, 0xff3c, 0xff4c, 0xff5c, 0xff6c, 0xff7c,
-       0xff88, 0xff90, 0xff98, 0xffa0, 0xffa8, 0xffb0, 0xffb8, 0xffc0,
-       0xffc8, 0xffd0, 0xffd8, 0xffe0, 0xffe8, 0xfff0, 0xfff8, 0x0000,
-       0x7d7c, 0x797c, 0x757c, 0x717c, 0x6d7c, 0x697c, 0x657c, 0x617c,
-       0x5d7c, 0x597c, 0x557c, 0x517c, 0x4d7c, 0x497c, 0x457c, 0x417c,
-       0x3e7c, 0x3c7c, 0x3a7c, 0x387c, 0x367c, 0x347c, 0x327c, 0x307c,
-       0x2e7c, 0x2c7c, 0x2a7c, 0x287c, 0x267c, 0x247c, 0x227c, 0x207c,
-       0x1efc, 0x1dfc, 0x1cfc, 0x1bfc, 0x1afc, 0x19fc, 0x18fc, 0x17fc,
-       0x16fc, 0x15fc, 0x14fc, 0x13fc, 0x12fc, 0x11fc, 0x10fc, 0x0ffc,
-       0x0f3c, 0x0ebc, 0x0e3c, 0x0dbc, 0x0d3c, 0x0cbc, 0x0c3c, 0x0bbc,
-       0x0b3c, 0x0abc, 0x0a3c, 0x09bc, 0x093c, 0x08bc, 0x083c, 0x07bc,
-       0x075c, 0x071c, 0x06dc, 0x069c, 0x065c, 0x061c, 0x05dc, 0x059c,
-       0x055c, 0x051c, 0x04dc, 0x049c, 0x045c, 0x041c, 0x03dc, 0x039c,
-       0x036c, 0x034c, 0x032c, 0x030c, 0x02ec, 0x02cc, 0x02ac, 0x028c,
-       0x026c, 0x024c, 0x022c, 0x020c, 0x01ec, 0x01cc, 0x01ac, 0x018c,
-       0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104,
-       0x00f4, 0x00e4, 0x00d4, 0x00c4, 0x00b4, 0x00a4, 0x0094, 0x0084,
-       0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040,
-       0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000
-};
-
-/* alaw -> signed 16-bit */
-static short isdn_audio_alaw_to_s16[] =
-{
-       0x13fc, 0xec04, 0x0144, 0xfebc, 0x517c, 0xae84, 0x051c, 0xfae4,
-       0x0a3c, 0xf5c4, 0x0048, 0xffb8, 0x287c, 0xd784, 0x028c, 0xfd74,
-       0x1bfc, 0xe404, 0x01cc, 0xfe34, 0x717c, 0x8e84, 0x071c, 0xf8e4,
-       0x0e3c, 0xf1c4, 0x00c4, 0xff3c, 0x387c, 0xc784, 0x039c, 0xfc64,
-       0x0ffc, 0xf004, 0x0104, 0xfefc, 0x417c, 0xbe84, 0x041c, 0xfbe4,
-       0x083c, 0xf7c4, 0x0008, 0xfff8, 0x207c, 0xdf84, 0x020c, 0xfdf4,
-       0x17fc, 0xe804, 0x018c, 0xfe74, 0x617c, 0x9e84, 0x061c, 0xf9e4,
-       0x0c3c, 0xf3c4, 0x0084, 0xff7c, 0x307c, 0xcf84, 0x030c, 0xfcf4,
-       0x15fc, 0xea04, 0x0164, 0xfe9c, 0x597c, 0xa684, 0x059c, 0xfa64,
-       0x0b3c, 0xf4c4, 0x0068, 0xff98, 0x2c7c, 0xd384, 0x02cc, 0xfd34,
-       0x1dfc, 0xe204, 0x01ec, 0xfe14, 0x797c, 0x8684, 0x07bc, 0xf844,
-       0x0f3c, 0xf0c4, 0x00e4, 0xff1c, 0x3c7c, 0xc384, 0x03dc, 0xfc24,
-       0x11fc, 0xee04, 0x0124, 0xfedc, 0x497c, 0xb684, 0x049c, 0xfb64,
-       0x093c, 0xf6c4, 0x0028, 0xffd8, 0x247c, 0xdb84, 0x024c, 0xfdb4,
-       0x19fc, 0xe604, 0x01ac, 0xfe54, 0x697c, 0x9684, 0x069c, 0xf964,
-       0x0d3c, 0xf2c4, 0x00a4, 0xff5c, 0x347c, 0xcb84, 0x034c, 0xfcb4,
-       0x12fc, 0xed04, 0x0134, 0xfecc, 0x4d7c, 0xb284, 0x04dc, 0xfb24,
-       0x09bc, 0xf644, 0x0038, 0xffc8, 0x267c, 0xd984, 0x026c, 0xfd94,
-       0x1afc, 0xe504, 0x01ac, 0xfe54, 0x6d7c, 0x9284, 0x06dc, 0xf924,
-       0x0dbc, 0xf244, 0x00b4, 0xff4c, 0x367c, 0xc984, 0x036c, 0xfc94,
-       0x0f3c, 0xf0c4, 0x00f4, 0xff0c, 0x3e7c, 0xc184, 0x03dc, 0xfc24,
-       0x07bc, 0xf844, 0x0008, 0xfff8, 0x1efc, 0xe104, 0x01ec, 0xfe14,
-       0x16fc, 0xe904, 0x0174, 0xfe8c, 0x5d7c, 0xa284, 0x05dc, 0xfa24,
-       0x0bbc, 0xf444, 0x0078, 0xff88, 0x2e7c, 0xd184, 0x02ec, 0xfd14,
-       0x14fc, 0xeb04, 0x0154, 0xfeac, 0x557c, 0xaa84, 0x055c, 0xfaa4,
-       0x0abc, 0xf544, 0x0058, 0xffa8, 0x2a7c, 0xd584, 0x02ac, 0xfd54,
-       0x1cfc, 0xe304, 0x01cc, 0xfe34, 0x757c, 0x8a84, 0x075c, 0xf8a4,
-       0x0ebc, 0xf144, 0x00d4, 0xff2c, 0x3a7c, 0xc584, 0x039c, 0xfc64,
-       0x10fc, 0xef04, 0x0114, 0xfeec, 0x457c, 0xba84, 0x045c, 0xfba4,
-       0x08bc, 0xf744, 0x0018, 0xffe8, 0x227c, 0xdd84, 0x022c, 0xfdd4,
-       0x18fc, 0xe704, 0x018c, 0xfe74, 0x657c, 0x9a84, 0x065c, 0xf9a4,
-       0x0cbc, 0xf344, 0x0094, 0xff6c, 0x327c, 0xcd84, 0x032c, 0xfcd4
-};
-
-/* alaw -> ulaw */
-static char isdn_audio_alaw_to_ulaw[] =
-{
-       0xab, 0x2b, 0xe3, 0x63, 0x8b, 0x0b, 0xc9, 0x49,
-       0xba, 0x3a, 0xf6, 0x76, 0x9b, 0x1b, 0xd7, 0x57,
-       0xa3, 0x23, 0xdd, 0x5d, 0x83, 0x03, 0xc1, 0x41,
-       0xb2, 0x32, 0xeb, 0x6b, 0x93, 0x13, 0xcf, 0x4f,
-       0xaf, 0x2f, 0xe7, 0x67, 0x8f, 0x0f, 0xcd, 0x4d,
-       0xbe, 0x3e, 0xfe, 0x7e, 0x9f, 0x1f, 0xdb, 0x5b,
-       0xa7, 0x27, 0xdf, 0x5f, 0x87, 0x07, 0xc5, 0x45,
-       0xb6, 0x36, 0xef, 0x6f, 0x97, 0x17, 0xd3, 0x53,
-       0xa9, 0x29, 0xe1, 0x61, 0x89, 0x09, 0xc7, 0x47,
-       0xb8, 0x38, 0xf2, 0x72, 0x99, 0x19, 0xd5, 0x55,
-       0xa1, 0x21, 0xdc, 0x5c, 0x81, 0x01, 0xbf, 0x3f,
-       0xb0, 0x30, 0xe9, 0x69, 0x91, 0x11, 0xce, 0x4e,
-       0xad, 0x2d, 0xe5, 0x65, 0x8d, 0x0d, 0xcb, 0x4b,
-       0xbc, 0x3c, 0xfa, 0x7a, 0x9d, 0x1d, 0xd9, 0x59,
-       0xa5, 0x25, 0xde, 0x5e, 0x85, 0x05, 0xc3, 0x43,
-       0xb4, 0x34, 0xed, 0x6d, 0x95, 0x15, 0xd1, 0x51,
-       0xac, 0x2c, 0xe4, 0x64, 0x8c, 0x0c, 0xca, 0x4a,
-       0xbb, 0x3b, 0xf8, 0x78, 0x9c, 0x1c, 0xd8, 0x58,
-       0xa4, 0x24, 0xde, 0x5e, 0x84, 0x04, 0xc2, 0x42,
-       0xb3, 0x33, 0xec, 0x6c, 0x94, 0x14, 0xd0, 0x50,
-       0xb0, 0x30, 0xe8, 0x68, 0x90, 0x10, 0xce, 0x4e,
-       0xbf, 0x3f, 0xfe, 0x7e, 0xa0, 0x20, 0xdc, 0x5c,
-       0xa8, 0x28, 0xe0, 0x60, 0x88, 0x08, 0xc6, 0x46,
-       0xb7, 0x37, 0xf0, 0x70, 0x98, 0x18, 0xd4, 0x54,
-       0xaa, 0x2a, 0xe2, 0x62, 0x8a, 0x0a, 0xc8, 0x48,
-       0xb9, 0x39, 0xf4, 0x74, 0x9a, 0x1a, 0xd6, 0x56,
-       0xa2, 0x22, 0xdd, 0x5d, 0x82, 0x02, 0xc0, 0x40,
-       0xb1, 0x31, 0xea, 0x6a, 0x92, 0x12, 0xcf, 0x4f,
-       0xae, 0x2e, 0xe6, 0x66, 0x8e, 0x0e, 0xcc, 0x4c,
-       0xbd, 0x3d, 0xfc, 0x7c, 0x9e, 0x1e, 0xda, 0x5a,
-       0xa6, 0x26, 0xdf, 0x5f, 0x86, 0x06, 0xc4, 0x44,
-       0xb5, 0x35, 0xee, 0x6e, 0x96, 0x16, 0xd2, 0x52
-};
-
-/* ulaw -> alaw */
-static char isdn_audio_ulaw_to_alaw[] =
-{
-       0xab, 0x55, 0xd5, 0x15, 0x95, 0x75, 0xf5, 0x35,
-       0xb5, 0x45, 0xc5, 0x05, 0x85, 0x65, 0xe5, 0x25,
-       0xa5, 0x5d, 0xdd, 0x1d, 0x9d, 0x7d, 0xfd, 0x3d,
-       0xbd, 0x4d, 0xcd, 0x0d, 0x8d, 0x6d, 0xed, 0x2d,
-       0xad, 0x51, 0xd1, 0x11, 0x91, 0x71, 0xf1, 0x31,
-       0xb1, 0x41, 0xc1, 0x01, 0x81, 0x61, 0xe1, 0x21,
-       0x59, 0xd9, 0x19, 0x99, 0x79, 0xf9, 0x39, 0xb9,
-       0x49, 0xc9, 0x09, 0x89, 0x69, 0xe9, 0x29, 0xa9,
-       0xd7, 0x17, 0x97, 0x77, 0xf7, 0x37, 0xb7, 0x47,
-       0xc7, 0x07, 0x87, 0x67, 0xe7, 0x27, 0xa7, 0xdf,
-       0x9f, 0x7f, 0xff, 0x3f, 0xbf, 0x4f, 0xcf, 0x0f,
-       0x8f, 0x6f, 0xef, 0x2f, 0x53, 0x13, 0x73, 0x33,
-       0xb3, 0x43, 0xc3, 0x03, 0x83, 0x63, 0xe3, 0x23,
-       0xa3, 0x5b, 0xdb, 0x1b, 0x9b, 0x7b, 0xfb, 0x3b,
-       0xbb, 0xbb, 0x4b, 0x4b, 0xcb, 0xcb, 0x0b, 0x0b,
-       0x8b, 0x8b, 0x6b, 0x6b, 0xeb, 0xeb, 0x2b, 0x2b,
-       0xab, 0x54, 0xd4, 0x14, 0x94, 0x74, 0xf4, 0x34,
-       0xb4, 0x44, 0xc4, 0x04, 0x84, 0x64, 0xe4, 0x24,
-       0xa4, 0x5c, 0xdc, 0x1c, 0x9c, 0x7c, 0xfc, 0x3c,
-       0xbc, 0x4c, 0xcc, 0x0c, 0x8c, 0x6c, 0xec, 0x2c,
-       0xac, 0x50, 0xd0, 0x10, 0x90, 0x70, 0xf0, 0x30,
-       0xb0, 0x40, 0xc0, 0x00, 0x80, 0x60, 0xe0, 0x20,
-       0x58, 0xd8, 0x18, 0x98, 0x78, 0xf8, 0x38, 0xb8,
-       0x48, 0xc8, 0x08, 0x88, 0x68, 0xe8, 0x28, 0xa8,
-       0xd6, 0x16, 0x96, 0x76, 0xf6, 0x36, 0xb6, 0x46,
-       0xc6, 0x06, 0x86, 0x66, 0xe6, 0x26, 0xa6, 0xde,
-       0x9e, 0x7e, 0xfe, 0x3e, 0xbe, 0x4e, 0xce, 0x0e,
-       0x8e, 0x6e, 0xee, 0x2e, 0x52, 0x12, 0x72, 0x32,
-       0xb2, 0x42, 0xc2, 0x02, 0x82, 0x62, 0xe2, 0x22,
-       0xa2, 0x5a, 0xda, 0x1a, 0x9a, 0x7a, 0xfa, 0x3a,
-       0xba, 0xba, 0x4a, 0x4a, 0xca, 0xca, 0x0a, 0x0a,
-       0x8a, 0x8a, 0x6a, 0x6a, 0xea, 0xea, 0x2a, 0x2a
-};
-
-#define NCOEFF            8     /* number of frequencies to be analyzed       */
-#define DTMF_TRESH     4000     /* above this is dtmf                         */
-#define SILENCE_TRESH   200     /* below this is silence                      */
-#define AMP_BITS          9     /* bits per sample, reduced to avoid overflow */
-#define LOGRP             0
-#define HIGRP             1
-
-/* For DTMF recognition:
- * 2 * cos(2 * PI * k / N) precalculated for all k
- */
-static int cos2pik[NCOEFF] =
-{
-       55813, 53604, 51193, 48591, 38114, 33057, 25889, 18332
-};
-
-static char dtmf_matrix[4][4] =
-{
-       {'1', '2', '3', 'A'},
-       {'4', '5', '6', 'B'},
-       {'7', '8', '9', 'C'},
-       {'*', '0', '#', 'D'}
-};
-
-static inline void
-isdn_audio_tlookup(const u_char *table, u_char *buff, unsigned long n)
-{
-#ifdef __i386__
-       unsigned long d0, d1, d2, d3;
-       __asm__ __volatile__(
-               "cld\n"
-               "1:\tlodsb\n\t"
-               "xlatb\n\t"
-               "stosb\n\t"
-               "loop 1b\n\t"
-               :       "=&b"(d0), "=&c"(d1), "=&D"(d2), "=&S"(d3)
-               :       "0"((long) table), "1"(n), "2"((long) buff), "3"((long) buff)
-               :       "memory", "ax");
-#else
-       while (n--)
-               *buff = table[*(unsigned char *)buff], buff++;
-#endif
-}
-
-void
-isdn_audio_ulaw2alaw(unsigned char *buff, unsigned long len)
-{
-       isdn_audio_tlookup(isdn_audio_ulaw_to_alaw, buff, len);
-}
-
-void
-isdn_audio_alaw2ulaw(unsigned char *buff, unsigned long len)
-{
-       isdn_audio_tlookup(isdn_audio_alaw_to_ulaw, buff, len);
-}
-
-/*
- * linear <-> adpcm conversion stuff
- * Most parts from the mgetty-package.
- * (C) by Gert Doering and Klaus Weidner
- * Used by permission of Gert Doering
- */
-
-
-#define ZEROTRAP                /* turn on the trap as per the MIL-STD */
-#undef ZEROTRAP
-#define BIAS 0x84               /* define the add-in bias for 16 bit samples */
-#define CLIP 32635
-
-static unsigned char
-isdn_audio_linear2ulaw(int sample)
-{
-       static int exp_lut[256] =
-               {
-                       0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
-                       4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-                       5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-                       5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
-                       6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-                       6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-                       6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-                       6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-                       7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-                       7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-                       7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-                       7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-                       7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-                       7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-                       7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-                       7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
-               };
-       int sign,
-               exponent,
-               mantissa;
-       unsigned char ulawbyte;
-
-       /* Get the sample into sign-magnitude. */
-       sign = (sample >> 8) & 0x80;    /* set aside the sign  */
-       if (sign != 0)
-               sample = -sample;       /* get magnitude       */
-       if (sample > CLIP)
-               sample = CLIP;  /* clip the magnitude  */
-
-       /* Convert from 16 bit linear to ulaw. */
-       sample = sample + BIAS;
-       exponent = exp_lut[(sample >> 7) & 0xFF];
-       mantissa = (sample >> (exponent + 3)) & 0x0F;
-       ulawbyte = ~(sign | (exponent << 4) | mantissa);
-#ifdef ZEROTRAP
-       /* optional CCITT trap */
-       if (ulawbyte == 0)
-               ulawbyte = 0x02;
-#endif
-       return (ulawbyte);
-}
-
-
-static int Mx[3][8] =
-{
-       {0x3800, 0x5600, 0, 0, 0, 0, 0, 0},
-       {0x399a, 0x3a9f, 0x4d14, 0x6607, 0, 0, 0, 0},
-       {0x3556, 0x3556, 0x399A, 0x3A9F, 0x4200, 0x4D14, 0x6607, 0x6607},
-};
-
-static int bitmask[9] =
-{
-       0, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff
-};
-
-static int
-isdn_audio_get_bits(adpcm_state *s, unsigned char **in, int *len)
-{
-       while (s->nleft < s->nbits) {
-               int d = *((*in)++);
-               (*len)--;
-               s->word = (s->word << 8) | d;
-               s->nleft += 8;
-       }
-       s->nleft -= s->nbits;
-       return (s->word >> s->nleft) & bitmask[s->nbits];
-}
-
-static void
-isdn_audio_put_bits(int data, int nbits, adpcm_state *s,
-                   unsigned char **out, int *len)
-{
-       s->word = (s->word << nbits) | (data & bitmask[nbits]);
-       s->nleft += nbits;
-       while (s->nleft >= 8) {
-               int d = (s->word >> (s->nleft - 8));
-               *(out[0]++) = d & 255;
-               (*len)++;
-               s->nleft -= 8;
-       }
-}
-
-adpcm_state *
-isdn_audio_adpcm_init(adpcm_state *s, int nbits)
-{
-       if (!s)
-               s = kmalloc(sizeof(adpcm_state), GFP_ATOMIC);
-       if (s) {
-               s->a = 0;
-               s->d = 5;
-               s->word = 0;
-               s->nleft = 0;
-               s->nbits = nbits;
-       }
-       return s;
-}
-
-dtmf_state *
-isdn_audio_dtmf_init(dtmf_state *s)
-{
-       if (!s)
-               s = kmalloc(sizeof(dtmf_state), GFP_ATOMIC);
-       if (s) {
-               s->idx = 0;
-               s->last = ' ';
-       }
-       return s;
-}
-
-/*
- * Decompression of adpcm data to a/u-law
- *
- */
-
-int
-isdn_audio_adpcm2xlaw(adpcm_state *s, int fmt, unsigned char *in,
-                     unsigned char *out, int len)
-{
-       int a = s->a;
-       int d = s->d;
-       int nbits = s->nbits;
-       int olen = 0;
-
-       while (len) {
-               int e = isdn_audio_get_bits(s, &in, &len);
-               int sign;
-
-               if (nbits == 4 && e == 0)
-                       d = 4;
-               sign = (e >> (nbits - 1)) ? -1 : 1;
-               e &= bitmask[nbits - 1];
-               a += sign * ((e << 1) + 1) * d >> 1;
-               if (d & 1)
-                       a++;
-               if (fmt)
-                       *out++ = isdn_audio_ulaw_to_alaw[
-                               isdn_audio_linear2ulaw(a << 2)];
-               else
-                       *out++ = isdn_audio_linear2ulaw(a << 2);
-               olen++;
-               d = (d * Mx[nbits - 2][e] + 0x2000) >> 14;
-               if (d < 5)
-                       d = 5;
-       }
-       s->a = a;
-       s->d = d;
-       return olen;
-}
-
-int
-isdn_audio_xlaw2adpcm(adpcm_state *s, int fmt, unsigned char *in,
-                     unsigned char *out, int len)
-{
-       int a = s->a;
-       int d = s->d;
-       int nbits = s->nbits;
-       int olen = 0;
-
-       while (len--) {
-               int e = 0,
-                       nmax = 1 << (nbits - 1);
-               int sign,
-                       delta;
-
-               if (fmt)
-                       delta = (isdn_audio_alaw_to_s16[*in++] >> 2) - a;
-               else
-                       delta = (isdn_audio_ulaw_to_s16[*in++] >> 2) - a;
-               if (delta < 0) {
-                       e = nmax;
-                       delta = -delta;
-               }
-               while (--nmax && delta > d) {
-                       delta -= d;
-                       e++;
-               }
-               if (nbits == 4 && ((e & 0x0f) == 0))
-                       e = 8;
-               isdn_audio_put_bits(e, nbits, s, &out, &olen);
-               sign = (e >> (nbits - 1)) ? -1 : 1;
-               e &= bitmask[nbits - 1];
-
-               a += sign * ((e << 1) + 1) * d >> 1;
-               if (d & 1)
-                       a++;
-               d = (d * Mx[nbits - 2][e] + 0x2000) >> 14;
-               if (d < 5)
-                       d = 5;
-       }
-       s->a = a;
-       s->d = d;
-       return olen;
-}
-
-/*
- * Goertzel algorithm.
- * See http://ptolemy.eecs.berkeley.edu/papers/96/dtmf_ict/
- * for more info.
- * Result is stored into an sk_buff and queued up for later
- * evaluation.
- */
-static void
-isdn_audio_goertzel(int *sample, modem_info *info)
-{
-       int sk,
-               sk1,
-               sk2;
-       int k,
-               n;
-       struct sk_buff *skb;
-       int *result;
-
-       skb = dev_alloc_skb(sizeof(int) * NCOEFF);
-       if (!skb) {
-               printk(KERN_WARNING
-                      "isdn_audio: Could not alloc DTMF result for ttyI%d\n",
-                      info->line);
-               return;
-       }
-       result = skb_put(skb, sizeof(int) * NCOEFF);
-       for (k = 0; k < NCOEFF; k++) {
-               sk = sk1 = sk2 = 0;
-               for (n = 0; n < DTMF_NPOINTS; n++) {
-                       sk = sample[n] + ((cos2pik[k] * sk1) >> 15) - sk2;
-                       sk2 = sk1;
-                       sk1 = sk;
-               }
-               /* Avoid overflows */
-               sk >>= 1;
-               sk2 >>= 1;
-               /* compute |X(k)|**2 */
-               /* report overflows. This should not happen. */
-               /* Comment this out if desired */
-               if (sk < -32768 || sk > 32767)
-                       printk(KERN_DEBUG
-                              "isdn_audio: dtmf goertzel overflow, sk=%d\n", sk);
-               if (sk2 < -32768 || sk2 > 32767)
-                       printk(KERN_DEBUG
-                              "isdn_audio: dtmf goertzel overflow, sk2=%d\n", sk2);
-               result[k] =
-                       ((sk * sk) >> AMP_BITS) -
-                       ((((cos2pik[k] * sk) >> 15) * sk2) >> AMP_BITS) +
-                       ((sk2 * sk2) >> AMP_BITS);
-       }
-       skb_queue_tail(&info->dtmf_queue, skb);
-       isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
-}
-
-void
-isdn_audio_eval_dtmf(modem_info *info)
-{
-       struct sk_buff *skb;
-       int *result;
-       dtmf_state *s;
-       int silence;
-       int i;
-       int di;
-       int ch;
-       int grp[2];
-       char what;
-       char *p;
-       int thresh;
-
-       while ((skb = skb_dequeue(&info->dtmf_queue))) {
-               result = (int *) skb->data;
-               s = info->dtmf_state;
-               grp[LOGRP] = grp[HIGRP] = -1;
-               silence = 0;
-               thresh = 0;
-               for (i = 0; i < NCOEFF; i++) {
-                       if (result[i] > DTMF_TRESH) {
-                               if (result[i] > thresh)
-                                       thresh = result[i];
-                       }
-                       else if (result[i] < SILENCE_TRESH)
-                               silence++;
-               }
-               if (silence == NCOEFF)
-                       what = ' ';
-               else {
-                       if (thresh > 0) {
-                               thresh = thresh >> 4;  /* touchtones must match within 12 dB */
-                               for (i = 0; i < NCOEFF; i++) {
-                                       if (result[i] < thresh)
-                                               continue;  /* ignore */
-                                       /* good level found. This is allowed only one time per group */
-                                       if (i < NCOEFF / 2) {
-                                               /* lowgroup*/
-                                               if (grp[LOGRP] >= 0) {
-                                                       // Bad. Another tone found. */
-                                                       grp[LOGRP] = -1;
-                                                       break;
-                                               }
-                                               else
-                                                       grp[LOGRP] = i;
-                                       }
-                                       else { /* higroup */
-                                               if (grp[HIGRP] >= 0) { // Bad. Another tone found. */
-                                                       grp[HIGRP] = -1;
-                                                       break;
-                                               }
-                                               else
-                                                       grp[HIGRP] = i - NCOEFF/2;
-                                       }
-                               }
-                               if ((grp[LOGRP] >= 0) && (grp[HIGRP] >= 0)) {
-                                       what = dtmf_matrix[grp[LOGRP]][grp[HIGRP]];
-                                       if (s->last != ' ' && s->last != '.')
-                                               s->last = what; /* min. 1 non-DTMF between DTMF */
-                               } else
-                                       what = '.';
-                       }
-                       else
-                               what = '.';
-               }
-               if ((what != s->last) && (what != ' ') && (what != '.')) {
-                       printk(KERN_DEBUG "dtmf: tt='%c'\n", what);
-                       p = skb->data;
-                       *p++ = 0x10;
-                       *p = what;
-                       skb_trim(skb, 2);
-                       ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
-                       ISDN_AUDIO_SKB_LOCK(skb) = 0;
-                       di = info->isdn_driver;
-                       ch = info->isdn_channel;
-                       __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
-                       dev->drv[di]->rcvcount[ch] += 2;
-                       /* Schedule dequeuing */
-                       if ((dev->modempoll) && (info->rcvsched))
-                               isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
-                       wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
-               } else
-                       kfree_skb(skb);
-               s->last = what;
-       }
-}
-
-/*
- * Decode DTMF tones, queue result in separate sk_buf for
- * later examination.
- * Parameters:
- *   s    = pointer to state-struct.
- *   buf  = input audio data
- *   len  = size of audio data.
- *   fmt  = audio data format (0 = ulaw, 1 = alaw)
- */
-void
-isdn_audio_calc_dtmf(modem_info *info, unsigned char *buf, int len, int fmt)
-{
-       dtmf_state *s = info->dtmf_state;
-       int i;
-       int c;
-
-       while (len) {
-               c = DTMF_NPOINTS - s->idx;
-               if (c > len)
-                       c = len;
-               if (c <= 0)
-                       break;
-               for (i = 0; i < c; i++) {
-                       if (fmt)
-                               s->buf[s->idx++] =
-                                       isdn_audio_alaw_to_s16[*buf++] >> (15 - AMP_BITS);
-                       else
-                               s->buf[s->idx++] =
-                                       isdn_audio_ulaw_to_s16[*buf++] >> (15 - AMP_BITS);
-               }
-               if (s->idx == DTMF_NPOINTS) {
-                       isdn_audio_goertzel(s->buf, info);
-                       s->idx = 0;
-               }
-               len -= c;
-       }
-}
-
-silence_state *
-isdn_audio_silence_init(silence_state *s)
-{
-       if (!s)
-               s = kmalloc(sizeof(silence_state), GFP_ATOMIC);
-       if (s) {
-               s->idx = 0;
-               s->state = 0;
-       }
-       return s;
-}
-
-void
-isdn_audio_calc_silence(modem_info *info, unsigned char *buf, int len, int fmt)
-{
-       silence_state *s = info->silence_state;
-       int i;
-       signed char c;
-
-       if (!info->emu.vpar[1]) return;
-
-       for (i = 0; i < len; i++) {
-               if (fmt)
-                       c = isdn_audio_alaw_to_ulaw[*buf++];
-               else
-                       c = *buf++;
-
-               if (c > 0) c -= 128;
-               c = abs(c);
-
-               if (c > (info->emu.vpar[1] * 4)) {
-                       s->idx = 0;
-                       s->state = 1;
-               } else {
-                       if (s->idx < 210000) s->idx++;
-               }
-       }
-}
-
-void
-isdn_audio_put_dle_code(modem_info *info, u_char code)
-{
-       struct sk_buff *skb;
-       int di;
-       int ch;
-       char *p;
-
-       skb = dev_alloc_skb(2);
-       if (!skb) {
-               printk(KERN_WARNING
-                      "isdn_audio: Could not alloc skb for ttyI%d\n",
-                      info->line);
-               return;
-       }
-       p = skb_put(skb, 2);
-       p[0] = 0x10;
-       p[1] = code;
-       ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
-       ISDN_AUDIO_SKB_LOCK(skb) = 0;
-       di = info->isdn_driver;
-       ch = info->isdn_channel;
-       __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
-       dev->drv[di]->rcvcount[ch] += 2;
-       /* Schedule dequeuing */
-       if ((dev->modempoll) && (info->rcvsched))
-               isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
-       wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
-}
-
-void
-isdn_audio_eval_silence(modem_info *info)
-{
-       silence_state *s = info->silence_state;
-       char what;
-
-       what = ' ';
-
-       if (s->idx > (info->emu.vpar[2] * 800)) {
-               s->idx = 0;
-               if (!s->state) {        /* silence from beginning of rec */
-                       what = 's';
-               } else {
-                       what = 'q';
-               }
-       }
-       if ((what == 's') || (what == 'q')) {
-               printk(KERN_DEBUG "ttyI%d: %s\n", info->line,
-                      (what == 's') ? "silence" : "quiet");
-               isdn_audio_put_dle_code(info, what);
-       }
-}
 
+++ /dev/null
-/* $Id: isdn_audio.h,v 1.1.2.2 2004/01/12 22:37:18 keil Exp $
- *
- * Linux ISDN subsystem, audio conversion and compression (linklevel).
- *
- * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#define DTMF_NPOINTS 205        /* Number of samples for DTMF recognition */
-typedef struct adpcm_state {
-       int a;
-       int d;
-       int word;
-       int nleft;
-       int nbits;
-} adpcm_state;
-
-typedef struct dtmf_state {
-       char last;
-       char llast;
-       int idx;
-       int buf[DTMF_NPOINTS];
-} dtmf_state;
-
-typedef struct silence_state {
-       int state;
-       unsigned int idx;
-} silence_state;
-
-extern void isdn_audio_ulaw2alaw(unsigned char *, unsigned long);
-extern void isdn_audio_alaw2ulaw(unsigned char *, unsigned long);
-extern adpcm_state *isdn_audio_adpcm_init(adpcm_state *, int);
-extern int isdn_audio_adpcm2xlaw(adpcm_state *, int, unsigned char *, unsigned char *, int);
-extern int isdn_audio_xlaw2adpcm(adpcm_state *, int, unsigned char *, unsigned char *, int);
-extern void isdn_audio_calc_dtmf(modem_info *, unsigned char *, int, int);
-extern void isdn_audio_eval_dtmf(modem_info *);
-dtmf_state *isdn_audio_dtmf_init(dtmf_state *);
-extern void isdn_audio_calc_silence(modem_info *, unsigned char *, int, int);
-extern void isdn_audio_eval_silence(modem_info *);
-silence_state *isdn_audio_silence_init(silence_state *);
-extern void isdn_audio_put_dle_code(modem_info *, u_char);
 
+++ /dev/null
-/*
- * BSD compression module
- *
- * Patched version for ISDN syncPPP written 1997/1998 by Michael Hipp
- * The whole module is now SKB based.
- *
- */
-
-/*
- * Update: The Berkeley copyright was changed, and the change
- * is retroactive to all "true" BSD software (ie everything
- * from UCB as opposed to other peoples code that just carried
- * the same license). The new copyright doesn't clash with the
- * GPL, so the module-only restriction has been removed..
- */
-
-/*
- * Original copyright notice:
- *
- * Copyright (c) 1985, 1986 The Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * James A. Woods, derived from original work by Spencer Thomas
- * and Joseph Orost.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/slab.h>
-#include <linux/tty.h>
-#include <linux/errno.h>
-#include <linux/string.h>      /* used in new tty drivers */
-#include <linux/signal.h>      /* used in new tty drivers */
-#include <linux/bitops.h>
-
-#include <asm/byteorder.h>
-#include <asm/types.h>
-
-#include <linux/if.h>
-
-#include <linux/if_ether.h>
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include <linux/inet.h>
-#include <linux/ioctl.h>
-#include <linux/vmalloc.h>
-
-#include <linux/ppp_defs.h>
-
-#include <linux/isdn.h>
-#include <linux/isdn_ppp.h>
-#include <linux/ip.h>
-#include <linux/tcp.h>
-#include <linux/if_arp.h>
-#include <linux/ppp-comp.h>
-
-#include "isdn_ppp.h"
-
-MODULE_DESCRIPTION("ISDN4Linux: BSD Compression for PPP over ISDN");
-MODULE_LICENSE("Dual BSD/GPL");
-
-#define BSD_VERSION(x) ((x) >> 5)
-#define BSD_NBITS(x)   ((x) & 0x1F)
-
-#define BSD_CURRENT_VERSION    1
-
-#define DEBUG 1
-
-/*
- * A dictionary for doing BSD compress.
- */
-
-struct bsd_dict {
-       u32 fcode;
-       u16 codem1;             /* output of hash table -1 */
-       u16 cptr;               /* map code to hash table entry */
-};
-
-struct bsd_db {
-       int            totlen;          /* length of this structure */
-       unsigned int   hsize;           /* size of the hash table */
-       unsigned char  hshift;          /* used in hash function */
-       unsigned char  n_bits;          /* current bits/code */
-       unsigned char  maxbits;         /* maximum bits/code */
-       unsigned char  debug;           /* non-zero if debug desired */
-       unsigned char  unit;            /* ppp unit number */
-       u16 seqno;                      /* sequence # of next packet */
-       unsigned int   mru;             /* size of receive (decompress) bufr */
-       unsigned int   maxmaxcode;      /* largest valid code */
-       unsigned int   max_ent;         /* largest code in use */
-       unsigned int   in_count;        /* uncompressed bytes, aged */
-       unsigned int   bytes_out;       /* compressed bytes, aged */
-       unsigned int   ratio;           /* recent compression ratio */
-       unsigned int   checkpoint;      /* when to next check the ratio */
-       unsigned int   clear_count;     /* times dictionary cleared */
-       unsigned int   incomp_count;    /* incompressible packets */
-       unsigned int   incomp_bytes;    /* incompressible bytes */
-       unsigned int   uncomp_count;    /* uncompressed packets */
-       unsigned int   uncomp_bytes;    /* uncompressed bytes */
-       unsigned int   comp_count;      /* compressed packets */
-       unsigned int   comp_bytes;      /* compressed bytes */
-       unsigned short  *lens;          /* array of lengths of codes */
-       struct bsd_dict *dict;          /* dictionary */
-       int xmit;
-};
-
-#define BSD_OVHD       2               /* BSD compress overhead/packet */
-#define MIN_BSD_BITS   9
-#define BSD_INIT_BITS  MIN_BSD_BITS
-#define MAX_BSD_BITS   15
-
-/*
- * the next two codes should not be changed lightly, as they must not
- * lie within the contiguous general code space.
- */
-#define CLEAR  256                     /* table clear output code */
-#define FIRST  257                     /* first free entry */
-#define LAST   255
-
-#define MAXCODE(b)     ((1 << (b)) - 1)
-#define BADCODEM1      MAXCODE(MAX_BSD_BITS)
-
-#define BSD_HASH(prefix, suffix, hshift) ((((unsigned long)(suffix)) << (hshift)) \
-                                         ^ (unsigned long)(prefix))
-#define BSD_KEY(prefix, suffix)                ((((unsigned long)(suffix)) << 16) \
-                                        + (unsigned long)(prefix))
-
-#define CHECK_GAP      10000           /* Ratio check interval */
-
-#define RATIO_SCALE_LOG        8
-#define RATIO_SCALE    (1 << RATIO_SCALE_LOG)
-#define RATIO_MAX      (0x7fffffff >> RATIO_SCALE_LOG)
-
-/*
- * clear the dictionary
- */
-
-static void bsd_clear(struct bsd_db *db)
-{
-       db->clear_count++;
-       db->max_ent      = FIRST - 1;
-       db->n_bits       = BSD_INIT_BITS;
-       db->bytes_out    = 0;
-       db->in_count     = 0;
-       db->incomp_count = 0;
-       db->ratio            = 0;
-       db->checkpoint   = CHECK_GAP;
-}
-
-/*
- * If the dictionary is full, then see if it is time to reset it.
- *
- * Compute the compression ratio using fixed-point arithmetic
- * with 8 fractional bits.
- *
- * Since we have an infinite stream instead of a single file,
- * watch only the local compression ratio.
- *
- * Since both peers must reset the dictionary at the same time even in
- * the absence of CLEAR codes (while packets are incompressible), they
- * must compute the same ratio.
- */
-static int bsd_check(struct bsd_db *db)        /* 1=output CLEAR */
-{
-       unsigned int new_ratio;
-
-       if (db->in_count >= db->checkpoint)
-       {
-               /* age the ratio by limiting the size of the counts */
-               if (db->in_count >= RATIO_MAX || db->bytes_out >= RATIO_MAX)
-               {
-                       db->in_count  -= (db->in_count  >> 2);
-                       db->bytes_out -= (db->bytes_out >> 2);
-               }
-
-               db->checkpoint = db->in_count + CHECK_GAP;
-
-               if (db->max_ent >= db->maxmaxcode)
-               {
-                       /* Reset the dictionary only if the ratio is worse,
-                        * or if it looks as if it has been poisoned
-                        * by incompressible data.
-                        *
-                        * This does not overflow, because
-                        *      db->in_count <= RATIO_MAX.
-                        */
-
-                       new_ratio = db->in_count << RATIO_SCALE_LOG;
-                       if (db->bytes_out != 0)
-                       {
-                               new_ratio /= db->bytes_out;
-                       }
-
-                       if (new_ratio < db->ratio || new_ratio < 1 * RATIO_SCALE)
-                       {
-                               bsd_clear(db);
-                               return 1;
-                       }
-                       db->ratio = new_ratio;
-               }
-       }
-       return 0;
-}
-
-/*
- * Return statistics.
- */
-
-static void bsd_stats(void *state, struct compstat *stats)
-{
-       struct bsd_db *db = (struct bsd_db *) state;
-
-       stats->unc_bytes    = db->uncomp_bytes;
-       stats->unc_packets  = db->uncomp_count;
-       stats->comp_bytes   = db->comp_bytes;
-       stats->comp_packets = db->comp_count;
-       stats->inc_bytes    = db->incomp_bytes;
-       stats->inc_packets  = db->incomp_count;
-       stats->in_count     = db->in_count;
-       stats->bytes_out    = db->bytes_out;
-}
-
-/*
- * Reset state, as on a CCP ResetReq.
- */
-static void bsd_reset(void *state, unsigned char code, unsigned char id,
-                     unsigned char *data, unsigned len,
-                     struct isdn_ppp_resetparams *rsparm)
-{
-       struct bsd_db *db = (struct bsd_db *) state;
-
-       bsd_clear(db);
-       db->seqno       = 0;
-       db->clear_count = 0;
-}
-
-/*
- * Release the compression structure
- */
-static void bsd_free(void *state)
-{
-       struct bsd_db *db = (struct bsd_db *) state;
-
-       if (db) {
-               /*
-                * Release the dictionary
-                */
-               vfree(db->dict);
-               db->dict = NULL;
-
-               /*
-                * Release the string buffer
-                */
-               vfree(db->lens);
-               db->lens = NULL;
-
-               /*
-                * Finally release the structure itself.
-                */
-               kfree(db);
-       }
-}
-
-
-/*
- * Allocate space for a (de) compressor.
- */
-static void *bsd_alloc(struct isdn_ppp_comp_data *data)
-{
-       int bits;
-       unsigned int hsize, hshift, maxmaxcode;
-       struct bsd_db *db;
-       int decomp;
-
-       static unsigned int htab[][2] = {
-               { 5003 , 4 } , { 5003 , 4 } , { 5003 , 4 } , { 5003 , 4 } ,
-               { 9001 , 5 } , { 18013 , 6 } , { 35023 , 7 } , { 69001 , 8 }
-       };
-
-       if (data->optlen != 1 || data->num != CI_BSD_COMPRESS
-           || BSD_VERSION(data->options[0]) != BSD_CURRENT_VERSION)
-               return NULL;
-
-       bits = BSD_NBITS(data->options[0]);
-
-       if (bits < 9 || bits > 15)
-               return NULL;
-
-       hsize = htab[bits - 9][0];
-       hshift = htab[bits - 9][1];
-
-       /*
-        * Allocate the main control structure for this instance.
-        */
-       maxmaxcode = MAXCODE(bits);
-       db = kzalloc(sizeof(struct bsd_db), GFP_KERNEL);
-       if (!db)
-               return NULL;
-
-       db->xmit = data->flags & IPPP_COMP_FLAG_XMIT;
-       decomp = db->xmit ? 0 : 1;
-
-       /*
-        * Allocate space for the dictionary. This may be more than one page in
-        * length.
-        */
-       db->dict = vmalloc(array_size(hsize, sizeof(struct bsd_dict)));
-       if (!db->dict) {
-               bsd_free(db);
-               return NULL;
-       }
-
-       /*
-        * If this is the compression buffer then there is no length data.
-        * For decompression, the length information is needed as well.
-        */
-       if (!decomp)
-               db->lens = NULL;
-       else {
-               db->lens = vmalloc(array_size(sizeof(db->lens[0]),
-                                             maxmaxcode + 1));
-               if (!db->lens) {
-                       bsd_free(db);
-                       return (NULL);
-               }
-       }
-
-       /*
-        * Initialize the data information for the compression code
-        */
-       db->totlen = sizeof(struct bsd_db) + (sizeof(struct bsd_dict) * hsize);
-       db->hsize = hsize;
-       db->hshift = hshift;
-       db->maxmaxcode = maxmaxcode;
-       db->maxbits = bits;
-
-       return (void *)db;
-}
-
-/*
- * Initialize the database.
- */
-static int bsd_init(void *state, struct isdn_ppp_comp_data *data, int unit, int debug)
-{
-       struct bsd_db *db = state;
-       int indx;
-       int decomp;
-
-       if (!state || !data) {
-               printk(KERN_ERR "isdn_bsd_init: [%d] ERR, state %lx data %lx\n", unit, (long)state, (long)data);
-               return 0;
-       }
-
-       decomp = db->xmit ? 0 : 1;
-
-       if (data->optlen != 1 || data->num != CI_BSD_COMPRESS
-           || (BSD_VERSION(data->options[0]) != BSD_CURRENT_VERSION)
-           || (BSD_NBITS(data->options[0]) != db->maxbits)
-           || (decomp && db->lens == NULL)) {
-               printk(KERN_ERR "isdn_bsd: %d %d %d %d %lx\n", data->optlen, data->num, data->options[0], decomp, (unsigned long)db->lens);
-               return 0;
-       }
-
-       if (decomp)
-               for (indx = LAST; indx >= 0; indx--)
-                       db->lens[indx] = 1;
-
-       indx = db->hsize;
-       while (indx-- != 0) {
-               db->dict[indx].codem1 = BADCODEM1;
-               db->dict[indx].cptr   = 0;
-       }
-
-       db->unit = unit;
-       db->mru  = 0;
-
-       db->debug = 1;
-
-       bsd_reset(db, 0, 0, NULL, 0, NULL);
-
-       return 1;
-}
-
-/*
- * Obtain pointers to the various structures in the compression tables
- */
-
-#define dict_ptrx(p, idx) &(p->dict[idx])
-#define lens_ptrx(p, idx) &(p->lens[idx])
-
-#ifdef DEBUG
-static unsigned short *lens_ptr(struct bsd_db *db, int idx)
-{
-       if ((unsigned int) idx > (unsigned int) db->maxmaxcode) {
-               printk(KERN_DEBUG "<9>ppp: lens_ptr(%d) > max\n", idx);
-               idx = 0;
-       }
-       return lens_ptrx(db, idx);
-}
-
-static struct bsd_dict *dict_ptr(struct bsd_db *db, int idx)
-{
-       if ((unsigned int) idx >= (unsigned int) db->hsize) {
-               printk(KERN_DEBUG "<9>ppp: dict_ptr(%d) > max\n", idx);
-               idx = 0;
-       }
-       return dict_ptrx(db, idx);
-}
-
-#else
-#define lens_ptr(db, idx) lens_ptrx(db, idx)
-#define dict_ptr(db, idx) dict_ptrx(db, idx)
-#endif
-
-/*
- * compress a packet
- */
-static int bsd_compress(void *state, struct sk_buff *skb_in, struct sk_buff *skb_out, int proto)
-{
-       struct bsd_db *db;
-       int hshift;
-       unsigned int max_ent;
-       unsigned int n_bits;
-       unsigned int bitno;
-       unsigned long accm;
-       int ent;
-       unsigned long fcode;
-       struct bsd_dict *dictp;
-       unsigned char c;
-       int hval, disp, ilen, mxcode;
-       unsigned char *rptr = skb_in->data;
-       int isize = skb_in->len;
-
-#define OUTPUT(ent)                                                    \
-       {                                                               \
-               bitno -= n_bits;                                        \
-               accm |= ((ent) << bitno);                               \
-               do      {                                               \
-                       if (skb_out && skb_tailroom(skb_out) > 0)       \
-                               skb_put_u8(skb_out, (u8)(accm >> 24));  \
-                       accm <<= 8;                                     \
-                       bitno += 8;                                     \
-               } while (bitno <= 24);                                  \
-       }
-
-       /*
-        * If the protocol is not in the range we're interested in,
-        * just return without compressing the packet.  If it is,
-        * the protocol becomes the first byte to compress.
-        */
-       printk(KERN_DEBUG "bsd_compress called with %x\n", proto);
-
-       ent = proto;
-       if (proto < 0x21 || proto > 0xf9 || !(proto & 0x1))
-               return 0;
-
-       db      = (struct bsd_db *) state;
-       hshift  = db->hshift;
-       max_ent = db->max_ent;
-       n_bits  = db->n_bits;
-       bitno   = 32;
-       accm    = 0;
-       mxcode  = MAXCODE(n_bits);
-
-       /* This is the PPP header information */
-       if (skb_out && skb_tailroom(skb_out) >= 2) {
-               char *v = skb_put(skb_out, 2);
-               /* we only push our own data on the header,
-                  AC,PC and protos is pushed by caller  */
-               v[0] = db->seqno >> 8;
-               v[1] = db->seqno;
-       }
-
-       ilen = ++isize; /* This is off by one, but that is what is in draft! */
-
-       while (--ilen > 0) {
-               c = *rptr++;
-               fcode = BSD_KEY(ent, c);
-               hval = BSD_HASH(ent, c, hshift);
-               dictp = dict_ptr(db, hval);
-
-               /* Validate and then check the entry. */
-               if (dictp->codem1 >= max_ent)
-                       goto nomatch;
-
-               if (dictp->fcode == fcode) {
-                       ent = dictp->codem1 + 1;
-                       continue;       /* found (prefix,suffix) */
-               }
-
-               /* continue probing until a match or invalid entry */
-               disp = (hval == 0) ? 1 : hval;
-
-               do {
-                       hval += disp;
-                       if (hval >= db->hsize)
-                               hval -= db->hsize;
-                       dictp = dict_ptr(db, hval);
-                       if (dictp->codem1 >= max_ent)
-                               goto nomatch;
-               } while (dictp->fcode != fcode);
-
-               ent = dictp->codem1 + 1;        /* finally found (prefix,suffix) */
-               continue;
-
-       nomatch:
-               OUTPUT(ent);            /* output the prefix */
-
-               /* code -> hashtable */
-               if (max_ent < db->maxmaxcode) {
-                       struct bsd_dict *dictp2;
-                       struct bsd_dict *dictp3;
-                       int indx;
-
-                       /* expand code size if needed */
-                       if (max_ent >= mxcode) {
-                               db->n_bits = ++n_bits;
-                               mxcode = MAXCODE(n_bits);
-                       }
-
-                       /*
-                        * Invalidate old hash table entry using
-                        * this code, and then take it over.
-                        */
-                       dictp2 = dict_ptr(db, max_ent + 1);
-                       indx   = dictp2->cptr;
-                       dictp3 = dict_ptr(db, indx);
-
-                       if (dictp3->codem1 == max_ent)
-                               dictp3->codem1 = BADCODEM1;
-
-                       dictp2->cptr   = hval;
-                       dictp->codem1  = max_ent;
-                       dictp->fcode = fcode;
-                       db->max_ent    = ++max_ent;
-
-                       if (db->lens) {
-                               unsigned short *len1 = lens_ptr(db, max_ent);
-                               unsigned short *len2 = lens_ptr(db, ent);
-                               *len1 = *len2 + 1;
-                       }
-               }
-               ent = c;
-       }
-
-       OUTPUT(ent);            /* output the last code */
-
-       if (skb_out)
-               db->bytes_out    += skb_out->len; /* Do not count bytes from here */
-       db->uncomp_bytes += isize;
-       db->in_count     += isize;
-       ++db->uncomp_count;
-       ++db->seqno;
-
-       if (bitno < 32)
-               ++db->bytes_out; /* must be set before calling bsd_check */
-
-       /*
-        * Generate the clear command if needed
-        */
-
-       if (bsd_check(db))
-               OUTPUT(CLEAR);
-
-       /*
-        * Pad dribble bits of last code with ones.
-        * Do not emit a completely useless byte of ones.
-        */
-       if (bitno < 32 && skb_out && skb_tailroom(skb_out) > 0)
-               skb_put_u8(skb_out,
-                          (unsigned char)((accm | (0xff << (bitno - 8))) >> 24));
-
-       /*
-        * Increase code size if we would have without the packet
-        * boundary because the decompressor will do so.
-        */
-       if (max_ent >= mxcode && max_ent < db->maxmaxcode)
-               db->n_bits++;
-
-       /* If output length is too large then this is an incompressible frame. */
-       if (!skb_out || skb_out->len >= skb_in->len) {
-               ++db->incomp_count;
-               db->incomp_bytes += isize;
-               return 0;
-       }
-
-       /* Count the number of compressed frames */
-       ++db->comp_count;
-       db->comp_bytes += skb_out->len;
-       return skb_out->len;
-
-#undef OUTPUT
-}
-
-/*
- * Update the "BSD Compress" dictionary on the receiver for
- * incompressible data by pretending to compress the incoming data.
- */
-static void bsd_incomp(void *state, struct sk_buff *skb_in, int proto)
-{
-       bsd_compress(state, skb_in, NULL, proto);
-}
-
-/*
- * Decompress "BSD Compress".
- */
-static int bsd_decompress(void *state, struct sk_buff *skb_in, struct sk_buff *skb_out,
-                         struct isdn_ppp_resetparams *rsparm)
-{
-       struct bsd_db *db;
-       unsigned int max_ent;
-       unsigned long accm;
-       unsigned int bitno;             /* 1st valid bit in accm */
-       unsigned int n_bits;
-       unsigned int tgtbitno;  /* bitno when we have a code */
-       struct bsd_dict *dictp;
-       int seq;
-       unsigned int incode;
-       unsigned int oldcode;
-       unsigned int finchar;
-       unsigned char *p, *ibuf;
-       int ilen;
-       int codelen;
-       int extra;
-
-       db       = (struct bsd_db *) state;
-       max_ent  = db->max_ent;
-       accm     = 0;
-       bitno    = 32;          /* 1st valid bit in accm */
-       n_bits   = db->n_bits;
-       tgtbitno = 32 - n_bits; /* bitno when we have a code */
-
-       printk(KERN_DEBUG "bsd_decompress called\n");
-
-       if (!skb_in || !skb_out) {
-               printk(KERN_ERR "bsd_decompress called with NULL parameter\n");
-               return DECOMP_ERROR;
-       }
-
-       /*
-        * Get the sequence number.
-        */
-       if ((p = skb_pull(skb_in, 2)) == NULL) {
-               return DECOMP_ERROR;
-       }
-       p -= 2;
-       seq = (p[0] << 8) + p[1];
-       ilen = skb_in->len;
-       ibuf = skb_in->data;
-
-       /*
-        * Check the sequence number and give up if it differs from
-        * the value we're expecting.
-        */
-       if (seq != db->seqno) {
-               if (db->debug) {
-                       printk(KERN_DEBUG "bsd_decomp%d: bad sequence # %d, expected %d\n",
-                              db->unit, seq, db->seqno - 1);
-               }
-               return DECOMP_ERROR;
-       }
-
-       ++db->seqno;
-       db->bytes_out += ilen;
-
-       if (skb_tailroom(skb_out) > 0)
-               skb_put_u8(skb_out, 0);
-       else
-               return DECOMP_ERR_NOMEM;
-
-       oldcode = CLEAR;
-
-       /*
-        * Keep the checkpoint correctly so that incompressible packets
-        * clear the dictionary at the proper times.
-        */
-
-       for (;;) {
-               if (ilen-- <= 0) {
-                       db->in_count += (skb_out->len - 1); /* don't count the header */
-                       break;
-               }
-
-               /*
-                * Accumulate bytes until we have a complete code.
-                * Then get the next code, relying on the 32-bit,
-                * unsigned accm to mask the result.
-                */
-
-               bitno -= 8;
-               accm  |= *ibuf++ << bitno;
-               if (tgtbitno < bitno)
-                       continue;
-
-               incode = accm >> tgtbitno;
-               accm <<= n_bits;
-               bitno += n_bits;
-
-               /*
-                * The dictionary must only be cleared at the end of a packet.
-                */
-
-               if (incode == CLEAR) {
-                       if (ilen > 0) {
-                               if (db->debug)
-                                       printk(KERN_DEBUG "bsd_decomp%d: bad CLEAR\n", db->unit);
-                               return DECOMP_FATALERROR;       /* probably a bug */
-                       }
-                       bsd_clear(db);
-                       break;
-               }
-
-               if ((incode > max_ent + 2) || (incode > db->maxmaxcode)
-                   || (incode > max_ent && oldcode == CLEAR)) {
-                       if (db->debug) {
-                               printk(KERN_DEBUG "bsd_decomp%d: bad code 0x%x oldcode=0x%x ",
-                                      db->unit, incode, oldcode);
-                               printk(KERN_DEBUG "max_ent=0x%x skb->Len=%d seqno=%d\n",
-                                      max_ent, skb_out->len, db->seqno);
-                       }
-                       return DECOMP_FATALERROR;       /* probably a bug */
-               }
-
-               /* Special case for KwKwK string. */
-               if (incode > max_ent) {
-                       finchar = oldcode;
-                       extra   = 1;
-               } else {
-                       finchar = incode;
-                       extra   = 0;
-               }
-
-               codelen = *(lens_ptr(db, finchar));
-               if (skb_tailroom(skb_out) < codelen + extra) {
-                       if (db->debug) {
-                               printk(KERN_DEBUG "bsd_decomp%d: ran out of mru\n", db->unit);
-#ifdef DEBUG
-                               printk(KERN_DEBUG "  len=%d, finchar=0x%x, codelen=%d,skblen=%d\n",
-                                      ilen, finchar, codelen, skb_out->len);
-#endif
-                       }
-                       return DECOMP_FATALERROR;
-               }
-
-               /*
-                * Decode this code and install it in the decompressed buffer.
-                */
-
-               p = skb_put(skb_out, codelen);
-               p += codelen;
-               while (finchar > LAST) {
-                       struct bsd_dict *dictp2 = dict_ptr(db, finchar);
-
-                       dictp = dict_ptr(db, dictp2->cptr);
-
-#ifdef DEBUG
-                       if (--codelen <= 0 || dictp->codem1 != finchar - 1) {
-                               if (codelen <= 0) {
-                                       printk(KERN_ERR "bsd_decomp%d: fell off end of chain ", db->unit);
-                                       printk(KERN_ERR "0x%x at 0x%x by 0x%x, max_ent=0x%x\n", incode, finchar, dictp2->cptr, max_ent);
-                               } else {
-                                       if (dictp->codem1 != finchar - 1) {
-                                               printk(KERN_ERR "bsd_decomp%d: bad code chain 0x%x finchar=0x%x ", db->unit, incode, finchar);
-                                               printk(KERN_ERR "oldcode=0x%x cptr=0x%x codem1=0x%x\n", oldcode, dictp2->cptr, dictp->codem1);
-                                       }
-                               }
-                               return DECOMP_FATALERROR;
-                       }
-#endif
-
-                       {
-                               u32 fcode = dictp->fcode;
-                               *--p    = (fcode >> 16) & 0xff;
-                               finchar = fcode & 0xffff;
-                       }
-               }
-               *--p = finchar;
-
-#ifdef DEBUG
-               if (--codelen != 0)
-                       printk(KERN_ERR "bsd_decomp%d: short by %d after code 0x%x, max_ent=0x%x\n", db->unit, codelen, incode, max_ent);
-#endif
-
-               if (extra)              /* the KwKwK case again */
-                       skb_put_u8(skb_out, finchar);
-
-               /*
-                * If not first code in a packet, and
-                * if not out of code space, then allocate a new code.
-                *
-                * Keep the hash table correct so it can be used
-                * with uncompressed packets.
-                */
-               if (oldcode != CLEAR && max_ent < db->maxmaxcode) {
-                       struct bsd_dict *dictp2, *dictp3;
-                       u16 *lens1, *lens2;
-                       unsigned long fcode;
-                       int hval, disp, indx;
-
-                       fcode = BSD_KEY(oldcode, finchar);
-                       hval  = BSD_HASH(oldcode, finchar, db->hshift);
-                       dictp = dict_ptr(db, hval);
-
-                       /* look for a free hash table entry */
-                       if (dictp->codem1 < max_ent) {
-                               disp = (hval == 0) ? 1 : hval;
-                               do {
-                                       hval += disp;
-                                       if (hval >= db->hsize)
-                                               hval -= db->hsize;
-                                       dictp = dict_ptr(db, hval);
-                               } while (dictp->codem1 < max_ent);
-                       }
-
-                       /*
-                        * Invalidate previous hash table entry
-                        * assigned this code, and then take it over
-                        */
-
-                       dictp2 = dict_ptr(db, max_ent + 1);
-                       indx   = dictp2->cptr;
-                       dictp3 = dict_ptr(db, indx);
-
-                       if (dictp3->codem1 == max_ent)
-                               dictp3->codem1 = BADCODEM1;
-
-                       dictp2->cptr   = hval;
-                       dictp->codem1  = max_ent;
-                       dictp->fcode = fcode;
-                       db->max_ent    = ++max_ent;
-
-                       /* Update the length of this string. */
-                       lens1  = lens_ptr(db, max_ent);
-                       lens2  = lens_ptr(db, oldcode);
-                       *lens1 = *lens2 + 1;
-
-                       /* Expand code size if needed. */
-                       if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode) {
-                               db->n_bits = ++n_bits;
-                               tgtbitno   = 32-n_bits;
-                       }
-               }
-               oldcode = incode;
-       }
-
-       ++db->comp_count;
-       ++db->uncomp_count;
-       db->comp_bytes   += skb_in->len - BSD_OVHD;
-       db->uncomp_bytes += skb_out->len;
-
-       if (bsd_check(db)) {
-               if (db->debug)
-                       printk(KERN_DEBUG "bsd_decomp%d: peer should have cleared dictionary on %d\n",
-                              db->unit, db->seqno - 1);
-       }
-       return skb_out->len;
-}
-
-/*************************************************************
- * Table of addresses for the BSD compression module
- *************************************************************/
-
-static struct isdn_ppp_compressor ippp_bsd_compress = {
-       .owner          = THIS_MODULE,
-       .num            = CI_BSD_COMPRESS,
-       .alloc          = bsd_alloc,
-       .free           = bsd_free,
-       .init           = bsd_init,
-       .reset          = bsd_reset,
-       .compress       = bsd_compress,
-       .decompress     = bsd_decompress,
-       .incomp         = bsd_incomp,
-       .stat           = bsd_stats,
-};
-
-/*************************************************************
- * Module support routines
- *************************************************************/
-
-static int __init isdn_bsdcomp_init(void)
-{
-       int answer = isdn_ppp_register_compressor(&ippp_bsd_compress);
-       if (answer == 0)
-               printk(KERN_INFO "PPP BSD Compression module registered\n");
-       return answer;
-}
-
-static void __exit isdn_bsdcomp_exit(void)
-{
-       isdn_ppp_unregister_compressor(&ippp_bsd_compress);
-}
-
-module_init(isdn_bsdcomp_init);
-module_exit(isdn_bsdcomp_exit);
 
+++ /dev/null
-/* $Id: isdn_common.c,v 1.1.2.3 2004/02/10 01:07:13 keil Exp $
- *
- * Linux ISDN subsystem, common used functions (linklevel).
- *
- * Copyright 1994-1999  by Fritz Elfert (fritz@isdn4linux.de)
- * Copyright 1995,96    Thinking Objects Software GmbH Wuerzburg
- * Copyright 1995,96    by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/poll.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/isdn.h>
-#include <linux/mutex.h>
-#include "isdn_common.h"
-#include "isdn_tty.h"
-#include "isdn_net.h"
-#include "isdn_ppp.h"
-#ifdef CONFIG_ISDN_AUDIO
-#include "isdn_audio.h"
-#endif
-#ifdef CONFIG_ISDN_DIVERSION_MODULE
-#define CONFIG_ISDN_DIVERSION
-#endif
-#ifdef CONFIG_ISDN_DIVERSION
-#include <linux/isdn_divertif.h>
-#endif /* CONFIG_ISDN_DIVERSION */
-#include "isdn_v110.h"
-
-/* Debugflags */
-#undef ISDN_DEBUG_STATCALLB
-
-MODULE_DESCRIPTION("ISDN4Linux: link layer");
-MODULE_AUTHOR("Fritz Elfert");
-MODULE_LICENSE("GPL");
-
-isdn_dev *dev;
-
-static DEFINE_MUTEX(isdn_mutex);
-static char *isdn_revision = "$Revision: 1.1.2.3 $";
-
-extern char *isdn_net_revision;
-#ifdef CONFIG_ISDN_PPP
-extern char *isdn_ppp_revision;
-#else
-static char *isdn_ppp_revision = ": none $";
-#endif
-#ifdef CONFIG_ISDN_AUDIO
-extern char *isdn_audio_revision;
-#else
-static char *isdn_audio_revision = ": none $";
-#endif
-extern char *isdn_v110_revision;
-
-#ifdef CONFIG_ISDN_DIVERSION
-static isdn_divert_if *divert_if; /* = NULL */
-#endif /* CONFIG_ISDN_DIVERSION */
-
-
-static int isdn_writebuf_stub(int, int, const u_char __user *, int);
-static void set_global_features(void);
-static int isdn_wildmat(char *s, char *p);
-static int isdn_add_channels(isdn_driver_t *d, int drvidx, int n, int adding);
-
-static inline void
-isdn_lock_driver(isdn_driver_t *drv)
-{
-       try_module_get(drv->interface->owner);
-       drv->locks++;
-}
-
-void
-isdn_lock_drivers(void)
-{
-       int i;
-
-       for (i = 0; i < ISDN_MAX_DRIVERS; i++) {
-               if (!dev->drv[i])
-                       continue;
-               isdn_lock_driver(dev->drv[i]);
-       }
-}
-
-static inline void
-isdn_unlock_driver(isdn_driver_t *drv)
-{
-       if (drv->locks > 0) {
-               drv->locks--;
-               module_put(drv->interface->owner);
-       }
-}
-
-void
-isdn_unlock_drivers(void)
-{
-       int i;
-
-       for (i = 0; i < ISDN_MAX_DRIVERS; i++) {
-               if (!dev->drv[i])
-                       continue;
-               isdn_unlock_driver(dev->drv[i]);
-       }
-}
-
-#if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
-void
-isdn_dumppkt(char *s, u_char *p, int len, int dumplen)
-{
-       int dumpc;
-
-       printk(KERN_DEBUG "%s(%d) ", s, len);
-       for (dumpc = 0; (dumpc < dumplen) && (len); len--, dumpc++)
-               printk(" %02x", *p++);
-       printk("\n");
-}
-#endif
-
-/*
- * I picked the pattern-matching-functions from an old GNU-tar version (1.10)
- * It was originally written and put to PD by rs@mirror.TMC.COM (Rich Salz)
- */
-static int
-isdn_star(char *s, char *p)
-{
-       while (isdn_wildmat(s, p)) {
-               if (*++s == '\0')
-                       return (2);
-       }
-       return (0);
-}
-
-/*
- * Shell-type Pattern-matching for incoming caller-Ids
- * This function gets a string in s and checks, if it matches the pattern
- * given in p.
- *
- * Return:
- *   0 = match.
- *   1 = no match.
- *   2 = no match. Would eventually match, if s would be longer.
- *
- * Possible Patterns:
- *
- * '?'     matches one character
- * '*'     matches zero or more characters
- * [xyz]   matches the set of characters in brackets.
- * [^xyz]  matches any single character not in the set of characters
- */
-
-static int
-isdn_wildmat(char *s, char *p)
-{
-       register int last;
-       register int matched;
-       register int reverse;
-       register int nostar = 1;
-
-       if (!(*s) && !(*p))
-               return (1);
-       for (; *p; s++, p++)
-               switch (*p) {
-               case '\\':
-                       /* Literal match with following character. */
-                       p++;
-                       /* fall through */
-               default:
-                       if (*s != *p)
-                               return (*s == '\0') ? 2 : 1;
-                                       continue;
-               case '?':
-                       /* Match anything. */
-                       if (*s == '\0')
-                               return (2);
-                       continue;
-               case '*':
-                       nostar = 0;
-                       /* Trailing star matches everything. */
-                       return (*++p ? isdn_star(s, p) : 0);
-               case '[':
-                       /* [^....] means inverse character class. */
-                       if ((reverse = (p[1] == '^')))
-                               p++;
-                       for (last = 0, matched = 0; *++p && (*p != ']'); last = *p)
-                               /* This next line requires a good C compiler. */
-                               if (*p == '-' ? *s <= *++p && *s >= last : *s == *p)
-                                       matched = 1;
-                       if (matched == reverse)
-                               return (1);
-                       continue;
-               }
-       return (*s == '\0') ? 0 : nostar;
-}
-
-int isdn_msncmp(const char *msn1, const char *msn2)
-{
-       char TmpMsn1[ISDN_MSNLEN];
-       char TmpMsn2[ISDN_MSNLEN];
-       char *p;
-
-       for (p = TmpMsn1; *msn1 && *msn1 != ':';)  // Strip off a SPID
-               *p++ = *msn1++;
-       *p = '\0';
-
-       for (p = TmpMsn2; *msn2 && *msn2 != ':';)  // Strip off a SPID
-               *p++ = *msn2++;
-       *p = '\0';
-
-       return isdn_wildmat(TmpMsn1, TmpMsn2);
-}
-
-int
-isdn_dc2minor(int di, int ch)
-{
-       int i;
-       for (i = 0; i < ISDN_MAX_CHANNELS; i++)
-               if (dev->chanmap[i] == ch && dev->drvmap[i] == di)
-                       return i;
-       return -1;
-}
-
-static int isdn_timer_cnt1 = 0;
-static int isdn_timer_cnt2 = 0;
-static int isdn_timer_cnt3 = 0;
-
-static void
-isdn_timer_funct(struct timer_list *unused)
-{
-       int tf = dev->tflags;
-       if (tf & ISDN_TIMER_FAST) {
-               if (tf & ISDN_TIMER_MODEMREAD)
-                       isdn_tty_readmodem();
-               if (tf & ISDN_TIMER_MODEMPLUS)
-                       isdn_tty_modem_escape();
-               if (tf & ISDN_TIMER_MODEMXMIT)
-                       isdn_tty_modem_xmit();
-       }
-       if (tf & ISDN_TIMER_SLOW) {
-               if (++isdn_timer_cnt1 >= ISDN_TIMER_02SEC) {
-                       isdn_timer_cnt1 = 0;
-                       if (tf & ISDN_TIMER_NETDIAL)
-                               isdn_net_dial();
-               }
-               if (++isdn_timer_cnt2 >= ISDN_TIMER_1SEC) {
-                       isdn_timer_cnt2 = 0;
-                       if (tf & ISDN_TIMER_NETHANGUP)
-                               isdn_net_autohup();
-                       if (++isdn_timer_cnt3 >= ISDN_TIMER_RINGING) {
-                               isdn_timer_cnt3 = 0;
-                               if (tf & ISDN_TIMER_MODEMRING)
-                                       isdn_tty_modem_ring();
-                       }
-                       if (tf & ISDN_TIMER_CARRIER)
-                               isdn_tty_carrier_timeout();
-               }
-       }
-       if (tf)
-               mod_timer(&dev->timer, jiffies + ISDN_TIMER_RES);
-}
-
-void
-isdn_timer_ctrl(int tf, int onoff)
-{
-       unsigned long flags;
-       int old_tflags;
-
-       spin_lock_irqsave(&dev->timerlock, flags);
-       if ((tf & ISDN_TIMER_SLOW) && (!(dev->tflags & ISDN_TIMER_SLOW))) {
-               /* If the slow-timer wasn't activated until now */
-               isdn_timer_cnt1 = 0;
-               isdn_timer_cnt2 = 0;
-       }
-       old_tflags = dev->tflags;
-       if (onoff)
-               dev->tflags |= tf;
-       else
-               dev->tflags &= ~tf;
-       if (dev->tflags && !old_tflags)
-               mod_timer(&dev->timer, jiffies + ISDN_TIMER_RES);
-       spin_unlock_irqrestore(&dev->timerlock, flags);
-}
-
-/*
- * Receive a packet from B-Channel. (Called from low-level-module)
- */
-static void
-isdn_receive_skb_callback(int di, int channel, struct sk_buff *skb)
-{
-       int i;
-
-       if ((i = isdn_dc2minor(di, channel)) == -1) {
-               dev_kfree_skb(skb);
-               return;
-       }
-       /* Update statistics */
-       dev->ibytes[i] += skb->len;
-
-       /* First, try to deliver data to network-device */
-       if (isdn_net_rcv_skb(i, skb))
-               return;
-
-       /* V.110 handling
-        * makes sense for async streams only, so it is
-        * called after possible net-device delivery.
-        */
-       if (dev->v110[i]) {
-               atomic_inc(&dev->v110use[i]);
-               skb = isdn_v110_decode(dev->v110[i], skb);
-               atomic_dec(&dev->v110use[i]);
-               if (!skb)
-                       return;
-       }
-
-       /* No network-device found, deliver to tty or raw-channel */
-       if (skb->len) {
-               if (isdn_tty_rcv_skb(i, di, channel, skb))
-                       return;
-               wake_up_interruptible(&dev->drv[di]->rcv_waitq[channel]);
-       } else
-               dev_kfree_skb(skb);
-}
-
-/*
- * Intercept command from Linklevel to Lowlevel.
- * If layer 2 protocol is V.110 and this is not supported by current
- * lowlevel-driver, use driver's transparent mode and handle V.110 in
- * linklevel instead.
- */
-int
-isdn_command(isdn_ctrl *cmd)
-{
-       if (cmd->driver == -1) {
-               printk(KERN_WARNING "isdn_command command(%x) driver -1\n", cmd->command);
-               return (1);
-       }
-       if (!dev->drv[cmd->driver]) {
-               printk(KERN_WARNING "isdn_command command(%x) dev->drv[%d] NULL\n",
-                      cmd->command, cmd->driver);
-               return (1);
-       }
-       if (!dev->drv[cmd->driver]->interface) {
-               printk(KERN_WARNING "isdn_command command(%x) dev->drv[%d]->interface NULL\n",
-                      cmd->command, cmd->driver);
-               return (1);
-       }
-       if (cmd->command == ISDN_CMD_SETL2) {
-               int idx = isdn_dc2minor(cmd->driver, cmd->arg & 255);
-               unsigned long l2prot = (cmd->arg >> 8) & 255;
-               unsigned long features = (dev->drv[cmd->driver]->interface->features
-                                         >> ISDN_FEATURE_L2_SHIFT) &
-                       ISDN_FEATURE_L2_MASK;
-               unsigned long l2_feature = (1 << l2prot);
-
-               switch (l2prot) {
-               case ISDN_PROTO_L2_V11096:
-               case ISDN_PROTO_L2_V11019:
-               case ISDN_PROTO_L2_V11038:
-                       /* If V.110 requested, but not supported by
-                        * HL-driver, set emulator-flag and change
-                        * Layer-2 to transparent
-                        */
-                       if (!(features & l2_feature)) {
-                               dev->v110emu[idx] = l2prot;
-                               cmd->arg = (cmd->arg & 255) |
-                                       (ISDN_PROTO_L2_TRANS << 8);
-                       } else
-                               dev->v110emu[idx] = 0;
-               }
-       }
-       return dev->drv[cmd->driver]->interface->command(cmd);
-}
-
-void
-isdn_all_eaz(int di, int ch)
-{
-       isdn_ctrl cmd;
-
-       if (di < 0)
-               return;
-       cmd.driver = di;
-       cmd.arg = ch;
-       cmd.command = ISDN_CMD_SETEAZ;
-       cmd.parm.num[0] = '\0';
-       isdn_command(&cmd);
-}
-
-/*
- * Begin of a CAPI like LL<->HL interface, currently used only for
- * supplementary service (CAPI 2.0 part III)
- */
-#include <linux/isdn/capicmd.h>
-
-static int
-isdn_capi_rec_hl_msg(capi_msg *cm)
-{
-       switch (cm->Command) {
-       case CAPI_FACILITY:
-               /* in the moment only handled in tty */
-               return (isdn_tty_capi_facility(cm));
-       default:
-               return (-1);
-       }
-}
-
-static int
-isdn_status_callback(isdn_ctrl *c)
-{
-       int di;
-       u_long flags;
-       int i;
-       int r;
-       int retval = 0;
-       isdn_ctrl cmd;
-       isdn_net_dev *p;
-
-       di = c->driver;
-       i = isdn_dc2minor(di, c->arg);
-       switch (c->command) {
-       case ISDN_STAT_BSENT:
-               if (i < 0)
-                       return -1;
-               if (dev->global_flags & ISDN_GLOBAL_STOPPED)
-                       return 0;
-               if (isdn_net_stat_callback(i, c))
-                       return 0;
-               if (isdn_v110_stat_callback(i, c))
-                       return 0;
-               if (isdn_tty_stat_callback(i, c))
-                       return 0;
-               wake_up_interruptible(&dev->drv[di]->snd_waitq[c->arg]);
-               break;
-       case ISDN_STAT_STAVAIL:
-               dev->drv[di]->stavail += c->arg;
-               wake_up_interruptible(&dev->drv[di]->st_waitq);
-               break;
-       case ISDN_STAT_RUN:
-               dev->drv[di]->flags |= DRV_FLAG_RUNNING;
-               for (i = 0; i < ISDN_MAX_CHANNELS; i++)
-                       if (dev->drvmap[i] == di)
-                               isdn_all_eaz(di, dev->chanmap[i]);
-               set_global_features();
-               break;
-       case ISDN_STAT_STOP:
-               dev->drv[di]->flags &= ~DRV_FLAG_RUNNING;
-               break;
-       case ISDN_STAT_ICALL:
-               if (i < 0)
-                       return -1;
-#ifdef ISDN_DEBUG_STATCALLB
-               printk(KERN_DEBUG "ICALL (net): %d %ld %s\n", di, c->arg, c->parm.num);
-#endif
-               if (dev->global_flags & ISDN_GLOBAL_STOPPED) {
-                       cmd.driver = di;
-                       cmd.arg = c->arg;
-                       cmd.command = ISDN_CMD_HANGUP;
-                       isdn_command(&cmd);
-                       return 0;
-               }
-               /* Try to find a network-interface which will accept incoming call */
-               r = ((c->command == ISDN_STAT_ICALLW) ? 0 : isdn_net_find_icall(di, c->arg, i, &c->parm.setup));
-               switch (r) {
-               case 0:
-                       /* No network-device replies.
-                        * Try ttyI's.
-                        * These return 0 on no match, 1 on match and
-                        * 3 on eventually match, if CID is longer.
-                        */
-                       if (c->command == ISDN_STAT_ICALL)
-                               if ((retval = isdn_tty_find_icall(di, c->arg, &c->parm.setup))) return (retval);
-#ifdef CONFIG_ISDN_DIVERSION
-                       if (divert_if)
-                               if ((retval = divert_if->stat_callback(c)))
-                                       return (retval); /* processed */
-#endif /* CONFIG_ISDN_DIVERSION */
-                       if ((!retval) && (dev->drv[di]->flags & DRV_FLAG_REJBUS)) {
-                               /* No tty responding */
-                               cmd.driver = di;
-                               cmd.arg = c->arg;
-                               cmd.command = ISDN_CMD_HANGUP;
-                               isdn_command(&cmd);
-                               retval = 2;
-                       }
-                       break;
-               case 1:
-                       /* Schedule connection-setup */
-                       isdn_net_dial();
-                       cmd.driver = di;
-                       cmd.arg = c->arg;
-                       cmd.command = ISDN_CMD_ACCEPTD;
-                       for (p = dev->netdev; p; p = p->next)
-                               if (p->local->isdn_channel == cmd.arg)
-                               {
-                                       strcpy(cmd.parm.setup.eazmsn, p->local->msn);
-                                       isdn_command(&cmd);
-                                       retval = 1;
-                                       break;
-                               }
-                       break;
-
-               case 2: /* For calling back, first reject incoming call ... */
-               case 3: /* Interface found, but down, reject call actively  */
-                       retval = 2;
-                       printk(KERN_INFO "isdn: Rejecting Call\n");
-                       cmd.driver = di;
-                       cmd.arg = c->arg;
-                       cmd.command = ISDN_CMD_HANGUP;
-                       isdn_command(&cmd);
-                       if (r == 3)
-                               break;
-                       /* Fall through */
-               case 4:
-                       /* ... then start callback. */
-                       isdn_net_dial();
-                       break;
-               case 5:
-                       /* Number would eventually match, if longer */
-                       retval = 3;
-                       break;
-               }
-#ifdef ISDN_DEBUG_STATCALLB
-               printk(KERN_DEBUG "ICALL: ret=%d\n", retval);
-#endif
-               return retval;
-               break;
-       case ISDN_STAT_CINF:
-               if (i < 0)
-                       return -1;
-#ifdef ISDN_DEBUG_STATCALLB
-               printk(KERN_DEBUG "CINF: %ld %s\n", c->arg, c->parm.num);
-#endif
-               if (dev->global_flags & ISDN_GLOBAL_STOPPED)
-                       return 0;
-               if (strcmp(c->parm.num, "0"))
-                       isdn_net_stat_callback(i, c);
-               isdn_tty_stat_callback(i, c);
-               break;
-       case ISDN_STAT_CAUSE:
-#ifdef ISDN_DEBUG_STATCALLB
-               printk(KERN_DEBUG "CAUSE: %ld %s\n", c->arg, c->parm.num);
-#endif
-               printk(KERN_INFO "isdn: %s,ch%ld cause: %s\n",
-                      dev->drvid[di], c->arg, c->parm.num);
-               isdn_tty_stat_callback(i, c);
-#ifdef CONFIG_ISDN_DIVERSION
-               if (divert_if)
-                       divert_if->stat_callback(c);
-#endif /* CONFIG_ISDN_DIVERSION */
-               break;
-       case ISDN_STAT_DISPLAY:
-#ifdef ISDN_DEBUG_STATCALLB
-               printk(KERN_DEBUG "DISPLAY: %ld %s\n", c->arg, c->parm.display);
-#endif
-               isdn_tty_stat_callback(i, c);
-#ifdef CONFIG_ISDN_DIVERSION
-               if (divert_if)
-                       divert_if->stat_callback(c);
-#endif /* CONFIG_ISDN_DIVERSION */
-               break;
-       case ISDN_STAT_DCONN:
-               if (i < 0)
-                       return -1;
-#ifdef ISDN_DEBUG_STATCALLB
-               printk(KERN_DEBUG "DCONN: %ld\n", c->arg);
-#endif
-               if (dev->global_flags & ISDN_GLOBAL_STOPPED)
-                       return 0;
-               /* Find any net-device, waiting for D-channel setup */
-               if (isdn_net_stat_callback(i, c))
-                       break;
-               isdn_v110_stat_callback(i, c);
-               /* Find any ttyI, waiting for D-channel setup */
-               if (isdn_tty_stat_callback(i, c)) {
-                       cmd.driver = di;
-                       cmd.arg = c->arg;
-                       cmd.command = ISDN_CMD_ACCEPTB;
-                       isdn_command(&cmd);
-                       break;
-               }
-               break;
-       case ISDN_STAT_DHUP:
-               if (i < 0)
-                       return -1;
-#ifdef ISDN_DEBUG_STATCALLB
-               printk(KERN_DEBUG "DHUP: %ld\n", c->arg);
-#endif
-               if (dev->global_flags & ISDN_GLOBAL_STOPPED)
-                       return 0;
-               dev->drv[di]->online &= ~(1 << (c->arg));
-               isdn_info_update();
-               /* Signal hangup to network-devices */
-               if (isdn_net_stat_callback(i, c))
-                       break;
-               isdn_v110_stat_callback(i, c);
-               if (isdn_tty_stat_callback(i, c))
-                       break;
-#ifdef CONFIG_ISDN_DIVERSION
-               if (divert_if)
-                       divert_if->stat_callback(c);
-#endif /* CONFIG_ISDN_DIVERSION */
-               break;
-               break;
-       case ISDN_STAT_BCONN:
-               if (i < 0)
-                       return -1;
-#ifdef ISDN_DEBUG_STATCALLB
-               printk(KERN_DEBUG "BCONN: %ld\n", c->arg);
-#endif
-               /* Signal B-channel-connect to network-devices */
-               if (dev->global_flags & ISDN_GLOBAL_STOPPED)
-                       return 0;
-               dev->drv[di]->online |= (1 << (c->arg));
-               isdn_info_update();
-               if (isdn_net_stat_callback(i, c))
-                       break;
-               isdn_v110_stat_callback(i, c);
-               if (isdn_tty_stat_callback(i, c))
-                       break;
-               break;
-       case ISDN_STAT_BHUP:
-               if (i < 0)
-                       return -1;
-#ifdef ISDN_DEBUG_STATCALLB
-               printk(KERN_DEBUG "BHUP: %ld\n", c->arg);
-#endif
-               if (dev->global_flags & ISDN_GLOBAL_STOPPED)
-                       return 0;
-               dev->drv[di]->online &= ~(1 << (c->arg));
-               isdn_info_update();
-#ifdef CONFIG_ISDN_X25
-               /* Signal hangup to network-devices */
-               if (isdn_net_stat_callback(i, c))
-                       break;
-#endif
-               isdn_v110_stat_callback(i, c);
-               if (isdn_tty_stat_callback(i, c))
-                       break;
-               break;
-       case ISDN_STAT_NODCH:
-               if (i < 0)
-                       return -1;
-#ifdef ISDN_DEBUG_STATCALLB
-               printk(KERN_DEBUG "NODCH: %ld\n", c->arg);
-#endif
-               if (dev->global_flags & ISDN_GLOBAL_STOPPED)
-                       return 0;
-               if (isdn_net_stat_callback(i, c))
-                       break;
-               if (isdn_tty_stat_callback(i, c))
-                       break;
-               break;
-       case ISDN_STAT_ADDCH:
-               spin_lock_irqsave(&dev->lock, flags);
-               if (isdn_add_channels(dev->drv[di], di, c->arg, 1)) {
-                       spin_unlock_irqrestore(&dev->lock, flags);
-                       return -1;
-               }
-               spin_unlock_irqrestore(&dev->lock, flags);
-               isdn_info_update();
-               break;
-       case ISDN_STAT_DISCH:
-               spin_lock_irqsave(&dev->lock, flags);
-               for (i = 0; i < ISDN_MAX_CHANNELS; i++)
-                       if ((dev->drvmap[i] == di) &&
-                           (dev->chanmap[i] == c->arg)) {
-                               if (c->parm.num[0])
-                                       dev->usage[i] &= ~ISDN_USAGE_DISABLED;
-                               else
-                                       if (USG_NONE(dev->usage[i])) {
-                                               dev->usage[i] |= ISDN_USAGE_DISABLED;
-                                       }
-                                       else
-                                               retval = -1;
-                               break;
-                       }
-               spin_unlock_irqrestore(&dev->lock, flags);
-               isdn_info_update();
-               break;
-       case ISDN_STAT_UNLOAD:
-               while (dev->drv[di]->locks > 0) {
-                       isdn_unlock_driver(dev->drv[di]);
-               }
-               spin_lock_irqsave(&dev->lock, flags);
-               isdn_tty_stat_callback(i, c);
-               for (i = 0; i < ISDN_MAX_CHANNELS; i++)
-                       if (dev->drvmap[i] == di) {
-                               dev->drvmap[i] = -1;
-                               dev->chanmap[i] = -1;
-                               dev->usage[i] &= ~ISDN_USAGE_DISABLED;
-                       }
-               dev->drivers--;
-               dev->channels -= dev->drv[di]->channels;
-               kfree(dev->drv[di]->rcverr);
-               kfree(dev->drv[di]->rcvcount);
-               for (i = 0; i < dev->drv[di]->channels; i++)
-                       skb_queue_purge(&dev->drv[di]->rpqueue[i]);
-               kfree(dev->drv[di]->rpqueue);
-               kfree(dev->drv[di]->rcv_waitq);
-               kfree(dev->drv[di]);
-               dev->drv[di] = NULL;
-               dev->drvid[di][0] = '\0';
-               isdn_info_update();
-               set_global_features();
-               spin_unlock_irqrestore(&dev->lock, flags);
-               return 0;
-       case ISDN_STAT_L1ERR:
-               break;
-       case CAPI_PUT_MESSAGE:
-               return (isdn_capi_rec_hl_msg(&c->parm.cmsg));
-#ifdef CONFIG_ISDN_TTY_FAX
-       case ISDN_STAT_FAXIND:
-               isdn_tty_stat_callback(i, c);
-               break;
-#endif
-#ifdef CONFIG_ISDN_AUDIO
-       case ISDN_STAT_AUDIO:
-               isdn_tty_stat_callback(i, c);
-               break;
-#endif
-#ifdef CONFIG_ISDN_DIVERSION
-       case ISDN_STAT_PROT:
-       case ISDN_STAT_REDIR:
-               if (divert_if)
-                       return (divert_if->stat_callback(c));
-#endif /* CONFIG_ISDN_DIVERSION */
-               /* fall through */
-       default:
-               return -1;
-       }
-       return 0;
-}
-
-/*
- * Get integer from char-pointer, set pointer to end of number
- */
-int
-isdn_getnum(char **p)
-{
-       int v = -1;
-
-       while (*p[0] >= '0' && *p[0] <= '9')
-               v = ((v < 0) ? 0 : (v * 10)) + (int) ((*p[0]++) - '0');
-       return v;
-}
-
-#define DLE 0x10
-
-/*
- * isdn_readbchan() tries to get data from the read-queue.
- * It MUST be called with interrupts off.
- *
- * Be aware that this is not an atomic operation when sleep != 0, even though
- * interrupts are turned off! Well, like that we are currently only called
- * on behalf of a read system call on raw device files (which are documented
- * to be dangerous and for debugging purpose only). The inode semaphore
- * takes care that this is not called for the same minor device number while
- * we are sleeping, but access is not serialized against simultaneous read()
- * from the corresponding ttyI device. Can other ugly events, like changes
- * of the mapping (di,ch)<->minor, happen during the sleep? --he
- */
-int
-isdn_readbchan(int di, int channel, u_char *buf, u_char *fp, int len, wait_queue_head_t *sleep)
-{
-       int count;
-       int count_pull;
-       int count_put;
-       int dflag;
-       struct sk_buff *skb;
-       u_char *cp;
-
-       if (!dev->drv[di])
-               return 0;
-       if (skb_queue_empty(&dev->drv[di]->rpqueue[channel])) {
-               if (sleep)
-                       wait_event_interruptible(*sleep,
-                               !skb_queue_empty(&dev->drv[di]->rpqueue[channel]));
-               else
-                       return 0;
-       }
-       if (len > dev->drv[di]->rcvcount[channel])
-               len = dev->drv[di]->rcvcount[channel];
-       cp = buf;
-       count = 0;
-       while (len) {
-               if (!(skb = skb_peek(&dev->drv[di]->rpqueue[channel])))
-                       break;
-#ifdef CONFIG_ISDN_AUDIO
-               if (ISDN_AUDIO_SKB_LOCK(skb))
-                       break;
-               ISDN_AUDIO_SKB_LOCK(skb) = 1;
-               if ((ISDN_AUDIO_SKB_DLECOUNT(skb)) || (dev->drv[di]->DLEflag & (1 << channel))) {
-                       char *p = skb->data;
-                       unsigned long DLEmask = (1 << channel);
-
-                       dflag = 0;
-                       count_pull = count_put = 0;
-                       while ((count_pull < skb->len) && (len > 0)) {
-                               len--;
-                               if (dev->drv[di]->DLEflag & DLEmask) {
-                                       *cp++ = DLE;
-                                       dev->drv[di]->DLEflag &= ~DLEmask;
-                               } else {
-                                       *cp++ = *p;
-                                       if (*p == DLE) {
-                                               dev->drv[di]->DLEflag |= DLEmask;
-                                               (ISDN_AUDIO_SKB_DLECOUNT(skb))--;
-                                       }
-                                       p++;
-                                       count_pull++;
-                               }
-                               count_put++;
-                       }
-                       if (count_pull >= skb->len)
-                               dflag = 1;
-               } else {
-#endif
-                       /* No DLE's in buff, so simply copy it */
-                       dflag = 1;
-                       if ((count_pull = skb->len) > len) {
-                               count_pull = len;
-                               dflag = 0;
-                       }
-                       count_put = count_pull;
-                       skb_copy_from_linear_data(skb, cp, count_put);
-                       cp += count_put;
-                       len -= count_put;
-#ifdef CONFIG_ISDN_AUDIO
-               }
-#endif
-               count += count_put;
-               if (fp) {
-                       memset(fp, 0, count_put);
-                       fp += count_put;
-               }
-               if (dflag) {
-                       /* We got all the data in this buff.
-                        * Now we can dequeue it.
-                        */
-                       if (fp)
-                               *(fp - 1) = 0xff;
-#ifdef CONFIG_ISDN_AUDIO
-                       ISDN_AUDIO_SKB_LOCK(skb) = 0;
-#endif
-                       skb = skb_dequeue(&dev->drv[di]->rpqueue[channel]);
-                       dev_kfree_skb(skb);
-               } else {
-                       /* Not yet emptied this buff, so it
-                        * must stay in the queue, for further calls
-                        * but we pull off the data we got until now.
-                        */
-                       skb_pull(skb, count_pull);
-#ifdef CONFIG_ISDN_AUDIO
-                       ISDN_AUDIO_SKB_LOCK(skb) = 0;
-#endif
-               }
-               dev->drv[di]->rcvcount[channel] -= count_put;
-       }
-       return count;
-}
-
-/*
- * isdn_readbchan_tty() tries to get data from the read-queue.
- * It MUST be called with interrupts off.
- *
- * Be aware that this is not an atomic operation when sleep != 0, even though
- * interrupts are turned off! Well, like that we are currently only called
- * on behalf of a read system call on raw device files (which are documented
- * to be dangerous and for debugging purpose only). The inode semaphore
- * takes care that this is not called for the same minor device number while
- * we are sleeping, but access is not serialized against simultaneous read()
- * from the corresponding ttyI device. Can other ugly events, like changes
- * of the mapping (di,ch)<->minor, happen during the sleep? --he
- */
-int
-isdn_readbchan_tty(int di, int channel, struct tty_port *port, int cisco_hack)
-{
-       int count;
-       int count_pull;
-       int count_put;
-       int dflag;
-       struct sk_buff *skb;
-       char last = 0;
-       int len;
-
-       if (!dev->drv[di])
-               return 0;
-       if (skb_queue_empty(&dev->drv[di]->rpqueue[channel]))
-               return 0;
-
-       len = tty_buffer_request_room(port, dev->drv[di]->rcvcount[channel]);
-       if (len == 0)
-               return len;
-
-       count = 0;
-       while (len) {
-               if (!(skb = skb_peek(&dev->drv[di]->rpqueue[channel])))
-                       break;
-#ifdef CONFIG_ISDN_AUDIO
-               if (ISDN_AUDIO_SKB_LOCK(skb))
-                       break;
-               ISDN_AUDIO_SKB_LOCK(skb) = 1;
-               if ((ISDN_AUDIO_SKB_DLECOUNT(skb)) || (dev->drv[di]->DLEflag & (1 << channel))) {
-                       char *p = skb->data;
-                       unsigned long DLEmask = (1 << channel);
-
-                       dflag = 0;
-                       count_pull = count_put = 0;
-                       while ((count_pull < skb->len) && (len > 0)) {
-                               /* push every character but the last to the tty buffer directly */
-                               if (count_put)
-                                       tty_insert_flip_char(port, last, TTY_NORMAL);
-                               len--;
-                               if (dev->drv[di]->DLEflag & DLEmask) {
-                                       last = DLE;
-                                       dev->drv[di]->DLEflag &= ~DLEmask;
-                               } else {
-                                       last = *p;
-                                       if (last == DLE) {
-                                               dev->drv[di]->DLEflag |= DLEmask;
-                                               (ISDN_AUDIO_SKB_DLECOUNT(skb))--;
-                                       }
-                                       p++;
-                                       count_pull++;
-                               }
-                               count_put++;
-                       }
-                       if (count_pull >= skb->len)
-                               dflag = 1;
-               } else {
-#endif
-                       /* No DLE's in buff, so simply copy it */
-                       dflag = 1;
-                       if ((count_pull = skb->len) > len) {
-                               count_pull = len;
-                               dflag = 0;
-                       }
-                       count_put = count_pull;
-                       if (count_put > 1)
-                               tty_insert_flip_string(port, skb->data, count_put - 1);
-                       last = skb->data[count_put - 1];
-                       len -= count_put;
-#ifdef CONFIG_ISDN_AUDIO
-               }
-#endif
-               count += count_put;
-               if (dflag) {
-                       /* We got all the data in this buff.
-                        * Now we can dequeue it.
-                        */
-                       if (cisco_hack)
-                               tty_insert_flip_char(port, last, 0xFF);
-                       else
-                               tty_insert_flip_char(port, last, TTY_NORMAL);
-#ifdef CONFIG_ISDN_AUDIO
-                       ISDN_AUDIO_SKB_LOCK(skb) = 0;
-#endif
-                       skb = skb_dequeue(&dev->drv[di]->rpqueue[channel]);
-                       dev_kfree_skb(skb);
-               } else {
-                       tty_insert_flip_char(port, last, TTY_NORMAL);
-                       /* Not yet emptied this buff, so it
-                        * must stay in the queue, for further calls
-                        * but we pull off the data we got until now.
-                        */
-                       skb_pull(skb, count_pull);
-#ifdef CONFIG_ISDN_AUDIO
-                       ISDN_AUDIO_SKB_LOCK(skb) = 0;
-#endif
-               }
-               dev->drv[di]->rcvcount[channel] -= count_put;
-       }
-       return count;
-}
-
-
-static inline int
-isdn_minor2drv(int minor)
-{
-       return (dev->drvmap[minor]);
-}
-
-static inline int
-isdn_minor2chan(int minor)
-{
-       return (dev->chanmap[minor]);
-}
-
-static char *
-isdn_statstr(void)
-{
-       static char istatbuf[2048];
-       char *p;
-       int i;
-
-       sprintf(istatbuf, "idmap:\t");
-       p = istatbuf + strlen(istatbuf);
-       for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-               sprintf(p, "%s ", (dev->drvmap[i] < 0) ? "-" : dev->drvid[dev->drvmap[i]]);
-               p = istatbuf + strlen(istatbuf);
-       }
-       sprintf(p, "\nchmap:\t");
-       p = istatbuf + strlen(istatbuf);
-       for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-               sprintf(p, "%d ", dev->chanmap[i]);
-               p = istatbuf + strlen(istatbuf);
-       }
-       sprintf(p, "\ndrmap:\t");
-       p = istatbuf + strlen(istatbuf);
-       for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-               sprintf(p, "%d ", dev->drvmap[i]);
-               p = istatbuf + strlen(istatbuf);
-       }
-       sprintf(p, "\nusage:\t");
-       p = istatbuf + strlen(istatbuf);
-       for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-               sprintf(p, "%d ", dev->usage[i]);
-               p = istatbuf + strlen(istatbuf);
-       }
-       sprintf(p, "\nflags:\t");
-       p = istatbuf + strlen(istatbuf);
-       for (i = 0; i < ISDN_MAX_DRIVERS; i++) {
-               if (dev->drv[i]) {
-                       sprintf(p, "%ld ", dev->drv[i]->online);
-                       p = istatbuf + strlen(istatbuf);
-               } else {
-                       sprintf(p, "? ");
-                       p = istatbuf + strlen(istatbuf);
-               }
-       }
-       sprintf(p, "\nphone:\t");
-       p = istatbuf + strlen(istatbuf);
-       for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-               sprintf(p, "%s ", dev->num[i]);
-               p = istatbuf + strlen(istatbuf);
-       }
-       sprintf(p, "\n");
-       return istatbuf;
-}
-
-/* Module interface-code */
-
-void
-isdn_info_update(void)
-{
-       infostruct *p = dev->infochain;
-
-       while (p) {
-               *(p->private) = 1;
-               p = (infostruct *) p->next;
-       }
-       wake_up_interruptible(&(dev->info_waitq));
-}
-
-static ssize_t
-isdn_read(struct file *file, char __user *buf, size_t count, loff_t *off)
-{
-       uint minor = iminor(file_inode(file));
-       int len = 0;
-       int drvidx;
-       int chidx;
-       int retval;
-       char *p;
-
-       mutex_lock(&isdn_mutex);
-       if (minor == ISDN_MINOR_STATUS) {
-               if (!file->private_data) {
-                       if (file->f_flags & O_NONBLOCK) {
-                               retval = -EAGAIN;
-                               goto out;
-                       }
-                       wait_event_interruptible(dev->info_waitq,
-                                                file->private_data);
-               }
-               p = isdn_statstr();
-               file->private_data = NULL;
-               if ((len = strlen(p)) <= count) {
-                       if (copy_to_user(buf, p, len)) {
-                               retval = -EFAULT;
-                               goto out;
-                       }
-                       *off += len;
-                       retval = len;
-                       goto out;
-               }
-               retval = 0;
-               goto out;
-       }
-       if (!dev->drivers) {
-               retval = -ENODEV;
-               goto out;
-       }
-       if (minor <= ISDN_MINOR_BMAX) {
-               printk(KERN_WARNING "isdn_read minor %d obsolete!\n", minor);
-               drvidx = isdn_minor2drv(minor);
-               if (drvidx < 0) {
-                       retval = -ENODEV;
-                       goto out;
-               }
-               if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) {
-                       retval = -ENODEV;
-                       goto out;
-               }
-               chidx = isdn_minor2chan(minor);
-               if (!(p = kmalloc(count, GFP_KERNEL))) {
-                       retval = -ENOMEM;
-                       goto out;
-               }
-               len = isdn_readbchan(drvidx, chidx, p, NULL, count,
-                                    &dev->drv[drvidx]->rcv_waitq[chidx]);
-               *off += len;
-               if (copy_to_user(buf, p, len))
-                       len = -EFAULT;
-               kfree(p);
-               retval = len;
-               goto out;
-       }
-       if (minor <= ISDN_MINOR_CTRLMAX) {
-               drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
-               if (drvidx < 0) {
-                       retval = -ENODEV;
-                       goto out;
-               }
-               if (!dev->drv[drvidx]->stavail) {
-                       if (file->f_flags & O_NONBLOCK) {
-                               retval = -EAGAIN;
-                               goto out;
-                       }
-                       wait_event_interruptible(dev->drv[drvidx]->st_waitq,
-                                                dev->drv[drvidx]->stavail);
-               }
-               if (dev->drv[drvidx]->interface->readstat) {
-                       if (count > dev->drv[drvidx]->stavail)
-                               count = dev->drv[drvidx]->stavail;
-                       len = dev->drv[drvidx]->interface->readstat(buf, count,
-                                                                   drvidx, isdn_minor2chan(minor - ISDN_MINOR_CTRL));
-                       if (len < 0) {
-                               retval = len;
-                               goto out;
-                       }
-               } else {
-                       len = 0;
-               }
-               if (len)
-                       dev->drv[drvidx]->stavail -= len;
-               else
-                       dev->drv[drvidx]->stavail = 0;
-               *off += len;
-               retval = len;
-               goto out;
-       }
-#ifdef CONFIG_ISDN_PPP
-       if (minor <= ISDN_MINOR_PPPMAX) {
-               retval = isdn_ppp_read(minor - ISDN_MINOR_PPP, file, buf, count);
-               goto out;
-       }
-#endif
-       retval = -ENODEV;
-out:
-       mutex_unlock(&isdn_mutex);
-       return retval;
-}
-
-static ssize_t
-isdn_write(struct file *file, const char __user *buf, size_t count, loff_t *off)
-{
-       uint minor = iminor(file_inode(file));
-       int drvidx;
-       int chidx;
-       int retval;
-
-       if (minor == ISDN_MINOR_STATUS)
-               return -EPERM;
-       if (!dev->drivers)
-               return -ENODEV;
-
-       mutex_lock(&isdn_mutex);
-       if (minor <= ISDN_MINOR_BMAX) {
-               printk(KERN_WARNING "isdn_write minor %d obsolete!\n", minor);
-               drvidx = isdn_minor2drv(minor);
-               if (drvidx < 0) {
-                       retval = -ENODEV;
-                       goto out;
-               }
-               if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) {
-                       retval = -ENODEV;
-                       goto out;
-               }
-               chidx = isdn_minor2chan(minor);
-               wait_event_interruptible(dev->drv[drvidx]->snd_waitq[chidx],
-                       (retval = isdn_writebuf_stub(drvidx, chidx, buf, count)));
-               goto out;
-       }
-       if (minor <= ISDN_MINOR_CTRLMAX) {
-               drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
-               if (drvidx < 0) {
-                       retval = -ENODEV;
-                       goto out;
-               }
-               /*
-                * We want to use the isdnctrl device to load the firmware
-                *
-                if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
-                return -ENODEV;
-               */
-               if (dev->drv[drvidx]->interface->writecmd)
-                       retval = dev->drv[drvidx]->interface->
-                               writecmd(buf, count, drvidx,
-                                        isdn_minor2chan(minor - ISDN_MINOR_CTRL));
-               else
-                       retval = count;
-               goto out;
-       }
-#ifdef CONFIG_ISDN_PPP
-       if (minor <= ISDN_MINOR_PPPMAX) {
-               retval = isdn_ppp_write(minor - ISDN_MINOR_PPP, file, buf, count);
-               goto out;
-       }
-#endif
-       retval = -ENODEV;
-out:
-       mutex_unlock(&isdn_mutex);
-       return retval;
-}
-
-static __poll_t
-isdn_poll(struct file *file, poll_table *wait)
-{
-       __poll_t mask = 0;
-       unsigned int minor = iminor(file_inode(file));
-       int drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
-
-       mutex_lock(&isdn_mutex);
-       if (minor == ISDN_MINOR_STATUS) {
-               poll_wait(file, &(dev->info_waitq), wait);
-               /* mask = EPOLLOUT | EPOLLWRNORM; */
-               if (file->private_data) {
-                       mask |= EPOLLIN | EPOLLRDNORM;
-               }
-               goto out;
-       }
-       if (minor >= ISDN_MINOR_CTRL && minor <= ISDN_MINOR_CTRLMAX) {
-               if (drvidx < 0) {
-                       /* driver deregistered while file open */
-                       mask = EPOLLHUP;
-                       goto out;
-               }
-               poll_wait(file, &(dev->drv[drvidx]->st_waitq), wait);
-               mask = EPOLLOUT | EPOLLWRNORM;
-               if (dev->drv[drvidx]->stavail) {
-                       mask |= EPOLLIN | EPOLLRDNORM;
-               }
-               goto out;
-       }
-#ifdef CONFIG_ISDN_PPP
-       if (minor <= ISDN_MINOR_PPPMAX) {
-               mask = isdn_ppp_poll(file, wait);
-               goto out;
-       }
-#endif
-       mask = EPOLLERR;
-out:
-       mutex_unlock(&isdn_mutex);
-       return mask;
-}
-
-
-static int
-isdn_ioctl(struct file *file, uint cmd, ulong arg)
-{
-       uint minor = iminor(file_inode(file));
-       isdn_ctrl c;
-       int drvidx;
-       int ret;
-       int i;
-       char __user *p;
-       char *s;
-       union iocpar {
-               char name[10];
-               char bname[22];
-               isdn_ioctl_struct iocts;
-               isdn_net_ioctl_phone phone;
-               isdn_net_ioctl_cfg cfg;
-       } iocpar;
-       void __user *argp = (void __user *)arg;
-
-#define name  iocpar.name
-#define bname iocpar.bname
-#define iocts iocpar.iocts
-#define phone iocpar.phone
-#define cfg   iocpar.cfg
-
-       if (minor == ISDN_MINOR_STATUS) {
-               switch (cmd) {
-               case IIOCGETDVR:
-                       return (TTY_DV +
-                               (NET_DV << 8) +
-                               (INF_DV << 16));
-               case IIOCGETCPS:
-                       if (arg) {
-                               ulong __user *p = argp;
-                               int i;
-                               for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-                                       put_user(dev->ibytes[i], p++);
-                                       put_user(dev->obytes[i], p++);
-                               }
-                               return 0;
-                       } else
-                               return -EINVAL;
-                       break;
-               case IIOCNETGPN:
-                       /* Get peer phone number of a connected
-                        * isdn network interface */
-                       if (arg) {
-                               if (copy_from_user(&phone, argp, sizeof(phone)))
-                                       return -EFAULT;
-                               return isdn_net_getpeer(&phone, argp);
-                       } else
-                               return -EINVAL;
-               default:
-                       return -EINVAL;
-               }
-       }
-       if (!dev->drivers)
-               return -ENODEV;
-       if (minor <= ISDN_MINOR_BMAX) {
-               drvidx = isdn_minor2drv(minor);
-               if (drvidx < 0)
-                       return -ENODEV;
-               if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
-                       return -ENODEV;
-               return 0;
-       }
-       if (minor <= ISDN_MINOR_CTRLMAX) {
-/*
- * isdn net devices manage lots of configuration variables as linked lists.
- * Those lists must only be manipulated from user space. Some of the ioctl's
- * service routines access user space and are not atomic. Therefore, ioctl's
- * manipulating the lists and ioctl's sleeping while accessing the lists
- * are serialized by means of a semaphore.
- */
-               switch (cmd) {
-               case IIOCNETDWRSET:
-                       printk(KERN_INFO "INFO: ISDN_DW_ABC_EXTENSION not enabled\n");
-                       return (-EINVAL);
-               case IIOCNETLCR:
-                       printk(KERN_INFO "INFO: ISDN_ABC_LCR_SUPPORT not enabled\n");
-                       return -ENODEV;
-               case IIOCNETAIF:
-                       /* Add a network-interface */
-                       if (arg) {
-                               if (copy_from_user(name, argp, sizeof(name)))
-                                       return -EFAULT;
-                               s = name;
-                       } else {
-                               s = NULL;
-                       }
-                       ret = mutex_lock_interruptible(&dev->mtx);
-                       if (ret) return ret;
-                       if ((s = isdn_net_new(s, NULL))) {
-                               if (copy_to_user(argp, s, strlen(s) + 1)) {
-                                       ret = -EFAULT;
-                               } else {
-                                       ret = 0;
-                               }
-                       } else
-                               ret = -ENODEV;
-                       mutex_unlock(&dev->mtx);
-                       return ret;
-               case IIOCNETASL:
-                       /* Add a slave to a network-interface */
-                       if (arg) {
-                               if (copy_from_user(bname, argp, sizeof(bname) - 1))
-                                       return -EFAULT;
-                               bname[sizeof(bname)-1] = 0;
-                       } else
-                               return -EINVAL;
-                       ret = mutex_lock_interruptible(&dev->mtx);
-                       if (ret) return ret;
-                       if ((s = isdn_net_newslave(bname))) {
-                               if (copy_to_user(argp, s, strlen(s) + 1)) {
-                                       ret = -EFAULT;
-                               } else {
-                                       ret = 0;
-                               }
-                       } else
-                               ret = -ENODEV;
-                       mutex_unlock(&dev->mtx);
-                       return ret;
-               case IIOCNETDIF:
-                       /* Delete a network-interface */
-                       if (arg) {
-                               if (copy_from_user(name, argp, sizeof(name)))
-                                       return -EFAULT;
-                               ret = mutex_lock_interruptible(&dev->mtx);
-                               if (ret) return ret;
-                               ret = isdn_net_rm(name);
-                               mutex_unlock(&dev->mtx);
-                               return ret;
-                       } else
-                               return -EINVAL;
-               case IIOCNETSCF:
-                       /* Set configurable parameters of a network-interface */
-                       if (arg) {
-                               if (copy_from_user(&cfg, argp, sizeof(cfg)))
-                                       return -EFAULT;
-                               return isdn_net_setcfg(&cfg);
-                       } else
-                               return -EINVAL;
-               case IIOCNETGCF:
-                       /* Get configurable parameters of a network-interface */
-                       if (arg) {
-                               if (copy_from_user(&cfg, argp, sizeof(cfg)))
-                                       return -EFAULT;
-                               if (!(ret = isdn_net_getcfg(&cfg))) {
-                                       if (copy_to_user(argp, &cfg, sizeof(cfg)))
-                                               return -EFAULT;
-                               }
-                               return ret;
-                       } else
-                               return -EINVAL;
-               case IIOCNETANM:
-                       /* Add a phone-number to a network-interface */
-                       if (arg) {
-                               if (copy_from_user(&phone, argp, sizeof(phone)))
-                                       return -EFAULT;
-                               ret = mutex_lock_interruptible(&dev->mtx);
-                               if (ret) return ret;
-                               ret = isdn_net_addphone(&phone);
-                               mutex_unlock(&dev->mtx);
-                               return ret;
-                       } else
-                               return -EINVAL;
-               case IIOCNETGNM:
-                       /* Get list of phone-numbers of a network-interface */
-                       if (arg) {
-                               if (copy_from_user(&phone, argp, sizeof(phone)))
-                                       return -EFAULT;
-                               ret = mutex_lock_interruptible(&dev->mtx);
-                               if (ret) return ret;
-                               ret = isdn_net_getphones(&phone, argp);
-                               mutex_unlock(&dev->mtx);
-                               return ret;
-                       } else
-                               return -EINVAL;
-               case IIOCNETDNM:
-                       /* Delete a phone-number of a network-interface */
-                       if (arg) {
-                               if (copy_from_user(&phone, argp, sizeof(phone)))
-                                       return -EFAULT;
-                               ret = mutex_lock_interruptible(&dev->mtx);
-                               if (ret) return ret;
-                               ret = isdn_net_delphone(&phone);
-                               mutex_unlock(&dev->mtx);
-                               return ret;
-                       } else
-                               return -EINVAL;
-               case IIOCNETDIL:
-                       /* Force dialing of a network-interface */
-                       if (arg) {
-                               if (copy_from_user(name, argp, sizeof(name)))
-                                       return -EFAULT;
-                               return isdn_net_force_dial(name);
-                       } else
-                               return -EINVAL;
-#ifdef CONFIG_ISDN_PPP
-               case IIOCNETALN:
-                       if (!arg)
-                               return -EINVAL;
-                       if (copy_from_user(name, argp, sizeof(name)))
-                               return -EFAULT;
-                       return isdn_ppp_dial_slave(name);
-               case IIOCNETDLN:
-                       if (!arg)
-                               return -EINVAL;
-                       if (copy_from_user(name, argp, sizeof(name)))
-                               return -EFAULT;
-                       return isdn_ppp_hangup_slave(name);
-#endif
-               case IIOCNETHUP:
-                       /* Force hangup of a network-interface */
-                       if (!arg)
-                               return -EINVAL;
-                       if (copy_from_user(name, argp, sizeof(name)))
-                               return -EFAULT;
-                       return isdn_net_force_hangup(name);
-                       break;
-               case IIOCSETVER:
-                       dev->net_verbose = arg;
-                       printk(KERN_INFO "isdn: Verbose-Level is %d\n", dev->net_verbose);
-                       return 0;
-               case IIOCSETGST:
-                       if (arg)
-                               dev->global_flags |= ISDN_GLOBAL_STOPPED;
-                       else
-                               dev->global_flags &= ~ISDN_GLOBAL_STOPPED;
-                       printk(KERN_INFO "isdn: Global Mode %s\n",
-                              (dev->global_flags & ISDN_GLOBAL_STOPPED) ? "stopped" : "running");
-                       return 0;
-               case IIOCSETBRJ:
-                       drvidx = -1;
-                       if (arg) {
-                               int i;
-                               char *p;
-                               if (copy_from_user(&iocts, argp,
-                                                  sizeof(isdn_ioctl_struct)))
-                                       return -EFAULT;
-                               iocts.drvid[sizeof(iocts.drvid) - 1] = 0;
-                               if (strlen(iocts.drvid)) {
-                                       if ((p = strchr(iocts.drvid, ',')))
-                                               *p = 0;
-                                       drvidx = -1;
-                                       for (i = 0; i < ISDN_MAX_DRIVERS; i++)
-                                               if (!(strcmp(dev->drvid[i], iocts.drvid))) {
-                                                       drvidx = i;
-                                                       break;
-                                               }
-                               }
-                       }
-                       if (drvidx == -1)
-                               return -ENODEV;
-                       if (iocts.arg)
-                               dev->drv[drvidx]->flags |= DRV_FLAG_REJBUS;
-                       else
-                               dev->drv[drvidx]->flags &= ~DRV_FLAG_REJBUS;
-                       return 0;
-               case IIOCSIGPRF:
-                       dev->profd = current;
-                       return 0;
-                       break;
-               case IIOCGETPRF:
-                       /* Get all Modem-Profiles */
-                       if (arg) {
-                               char __user *p = argp;
-                               int i;
-
-                               for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-                                       if (copy_to_user(p, dev->mdm.info[i].emu.profile,
-                                                        ISDN_MODEM_NUMREG))
-                                               return -EFAULT;
-                                       p += ISDN_MODEM_NUMREG;
-                                       if (copy_to_user(p, dev->mdm.info[i].emu.pmsn, ISDN_MSNLEN))
-                                               return -EFAULT;
-                                       p += ISDN_MSNLEN;
-                                       if (copy_to_user(p, dev->mdm.info[i].emu.plmsn, ISDN_LMSNLEN))
-                                               return -EFAULT;
-                                       p += ISDN_LMSNLEN;
-                               }
-                               return (ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN) * ISDN_MAX_CHANNELS;
-                       } else
-                               return -EINVAL;
-                       break;
-               case IIOCSETPRF:
-                       /* Set all Modem-Profiles */
-                       if (arg) {
-                               char __user *p = argp;
-                               int i;
-
-                               for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-                                       if (copy_from_user(dev->mdm.info[i].emu.profile, p,
-                                                          ISDN_MODEM_NUMREG))
-                                               return -EFAULT;
-                                       p += ISDN_MODEM_NUMREG;
-                                       if (copy_from_user(dev->mdm.info[i].emu.plmsn, p, ISDN_LMSNLEN))
-                                               return -EFAULT;
-                                       p += ISDN_LMSNLEN;
-                                       if (copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN))
-                                               return -EFAULT;
-                                       p += ISDN_MSNLEN;
-                               }
-                               return 0;
-                       } else
-                               return -EINVAL;
-                       break;
-               case IIOCSETMAP:
-               case IIOCGETMAP:
-                       /* Set/Get MSN->EAZ-Mapping for a driver */
-                       if (arg) {
-
-                               if (copy_from_user(&iocts, argp,
-                                                  sizeof(isdn_ioctl_struct)))
-                                       return -EFAULT;
-                               iocts.drvid[sizeof(iocts.drvid) - 1] = 0;
-                               if (strlen(iocts.drvid)) {
-                                       drvidx = -1;
-                                       for (i = 0; i < ISDN_MAX_DRIVERS; i++)
-                                               if (!(strcmp(dev->drvid[i], iocts.drvid))) {
-                                                       drvidx = i;
-                                                       break;
-                                               }
-                               } else
-                                       drvidx = 0;
-                               if (drvidx == -1)
-                                       return -ENODEV;
-                               if (cmd == IIOCSETMAP) {
-                                       int loop = 1;
-
-                                       p = (char __user *) iocts.arg;
-                                       i = 0;
-                                       while (loop) {
-                                               int j = 0;
-
-                                               while (1) {
-                                                       get_user(bname[j], p++);
-                                                       switch (bname[j]) {
-                                                       case '\0':
-                                                               loop = 0;
-                                                               /* Fall through */
-                                                       case ',':
-                                                               bname[j] = '\0';
-                                                               strcpy(dev->drv[drvidx]->msn2eaz[i], bname);
-                                                               j = ISDN_MSNLEN;
-                                                               break;
-                                                       default:
-                                                               j++;
-                                                       }
-                                                       if (j >= ISDN_MSNLEN)
-                                                               break;
-                                               }
-                                               if (++i > 9)
-                                                       break;
-                                       }
-                               } else {
-                                       p = (char __user *) iocts.arg;
-                                       for (i = 0; i < 10; i++) {
-                                               snprintf(bname, sizeof(bname), "%s%s",
-                                                        strlen(dev->drv[drvidx]->msn2eaz[i]) ?
-                                                        dev->drv[drvidx]->msn2eaz[i] : "_",
-                                                        (i < 9) ? "," : "\0");
-                                               if (copy_to_user(p, bname, strlen(bname) + 1))
-                                                       return -EFAULT;
-                                               p += strlen(bname);
-                                       }
-                               }
-                               return 0;
-                       } else
-                               return -EINVAL;
-               case IIOCDBGVAR:
-                       return -EINVAL;
-               default:
-                       if ((cmd & IIOCDRVCTL) == IIOCDRVCTL)
-                               cmd = ((cmd >> _IOC_NRSHIFT) & _IOC_NRMASK) & ISDN_DRVIOCTL_MASK;
-                       else
-                               return -EINVAL;
-                       if (arg) {
-                               int i;
-                               char *p;
-                               if (copy_from_user(&iocts, argp, sizeof(isdn_ioctl_struct)))
-                                       return -EFAULT;
-                               iocts.drvid[sizeof(iocts.drvid) - 1] = 0;
-                               if (strlen(iocts.drvid)) {
-                                       if ((p = strchr(iocts.drvid, ',')))
-                                               *p = 0;
-                                       drvidx = -1;
-                                       for (i = 0; i < ISDN_MAX_DRIVERS; i++)
-                                               if (!(strcmp(dev->drvid[i], iocts.drvid))) {
-                                                       drvidx = i;
-                                                       break;
-                                               }
-                               } else
-                                       drvidx = 0;
-                               if (drvidx == -1)
-                                       return -ENODEV;
-                               c.driver = drvidx;
-                               c.command = ISDN_CMD_IOCTL;
-                               c.arg = cmd;
-                               memcpy(c.parm.num, &iocts.arg, sizeof(ulong));
-                               ret = isdn_command(&c);
-                               memcpy(&iocts.arg, c.parm.num, sizeof(ulong));
-                               if (copy_to_user(argp, &iocts, sizeof(isdn_ioctl_struct)))
-                                       return -EFAULT;
-                               return ret;
-                       } else
-                               return -EINVAL;
-               }
-       }
-#ifdef CONFIG_ISDN_PPP
-       if (minor <= ISDN_MINOR_PPPMAX)
-               return (isdn_ppp_ioctl(minor - ISDN_MINOR_PPP, file, cmd, arg));
-#endif
-       return -ENODEV;
-
-#undef name
-#undef bname
-#undef iocts
-#undef phone
-#undef cfg
-}
-
-static long
-isdn_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-       int ret;
-
-       mutex_lock(&isdn_mutex);
-       ret = isdn_ioctl(file, cmd, arg);
-       mutex_unlock(&isdn_mutex);
-
-       return ret;
-}
-
-/*
- * Open the device code.
- */
-static int
-isdn_open(struct inode *ino, struct file *filep)
-{
-       uint minor = iminor(ino);
-       int drvidx;
-       int chidx;
-       int retval = -ENODEV;
-
-       mutex_lock(&isdn_mutex);
-       if (minor == ISDN_MINOR_STATUS) {
-               infostruct *p;
-
-               if ((p = kmalloc(sizeof(infostruct), GFP_KERNEL))) {
-                       p->next = (char *) dev->infochain;
-                       p->private = (char *) &(filep->private_data);
-                       dev->infochain = p;
-                       /* At opening we allow a single update */
-                       filep->private_data = (char *) 1;
-                       retval = 0;
-                       goto out;
-               } else {
-                       retval = -ENOMEM;
-                       goto out;
-               }
-       }
-       if (!dev->channels)
-               goto out;
-       if (minor <= ISDN_MINOR_BMAX) {
-               printk(KERN_WARNING "isdn_open minor %d obsolete!\n", minor);
-               drvidx = isdn_minor2drv(minor);
-               if (drvidx < 0)
-                       goto out;
-               chidx = isdn_minor2chan(minor);
-               if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
-                       goto out;
-               if (!(dev->drv[drvidx]->online & (1 << chidx)))
-                       goto out;
-               isdn_lock_drivers();
-               retval = 0;
-               goto out;
-       }
-       if (minor <= ISDN_MINOR_CTRLMAX) {
-               drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
-               if (drvidx < 0)
-                       goto out;
-               isdn_lock_drivers();
-               retval = 0;
-               goto out;
-       }
-#ifdef CONFIG_ISDN_PPP
-       if (minor <= ISDN_MINOR_PPPMAX) {
-               retval = isdn_ppp_open(minor - ISDN_MINOR_PPP, filep);
-               if (retval == 0)
-                       isdn_lock_drivers();
-               goto out;
-       }
-#endif
-out:
-       nonseekable_open(ino, filep);
-       mutex_unlock(&isdn_mutex);
-       return retval;
-}
-
-static int
-isdn_close(struct inode *ino, struct file *filep)
-{
-       uint minor = iminor(ino);
-
-       mutex_lock(&isdn_mutex);
-       if (minor == ISDN_MINOR_STATUS) {
-               infostruct *p = dev->infochain;
-               infostruct *q = NULL;
-
-               while (p) {
-                       if (p->private == (char *) &(filep->private_data)) {
-                               if (q)
-                                       q->next = p->next;
-                               else
-                                       dev->infochain = (infostruct *) (p->next);
-                               kfree(p);
-                               goto out;
-                       }
-                       q = p;
-                       p = (infostruct *) (p->next);
-               }
-               printk(KERN_WARNING "isdn: No private data while closing isdnctrl\n");
-               goto out;
-       }
-       isdn_unlock_drivers();
-       if (minor <= ISDN_MINOR_BMAX)
-               goto out;
-       if (minor <= ISDN_MINOR_CTRLMAX) {
-               if (dev->profd == current)
-                       dev->profd = NULL;
-               goto out;
-       }
-#ifdef CONFIG_ISDN_PPP
-       if (minor <= ISDN_MINOR_PPPMAX)
-               isdn_ppp_release(minor - ISDN_MINOR_PPP, filep);
-#endif
-
-out:
-       mutex_unlock(&isdn_mutex);
-       return 0;
-}
-
-static const struct file_operations isdn_fops =
-{
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .read           = isdn_read,
-       .write          = isdn_write,
-       .poll           = isdn_poll,
-       .unlocked_ioctl = isdn_unlocked_ioctl,
-       .open           = isdn_open,
-       .release        = isdn_close,
-};
-
-char *
-isdn_map_eaz2msn(char *msn, int di)
-{
-       isdn_driver_t *this = dev->drv[di];
-       int i;
-
-       if (strlen(msn) == 1) {
-               i = msn[0] - '0';
-               if ((i >= 0) && (i <= 9))
-                       if (strlen(this->msn2eaz[i]))
-                               return (this->msn2eaz[i]);
-       }
-       return (msn);
-}
-
-/*
- * Find an unused ISDN-channel, whose feature-flags match the
- * given L2- and L3-protocols.
- */
-#define L2V (~(ISDN_FEATURE_L2_V11096 | ISDN_FEATURE_L2_V11019 | ISDN_FEATURE_L2_V11038))
-
-/*
- * This function must be called with holding the dev->lock.
- */
-int
-isdn_get_free_channel(int usage, int l2_proto, int l3_proto, int pre_dev
-                     , int pre_chan, char *msn)
-{
-       int i;
-       ulong features;
-       ulong vfeatures;
-
-       features = ((1 << l2_proto) | (0x10000 << l3_proto));
-       vfeatures = (((1 << l2_proto) | (0x10000 << l3_proto)) &
-                    ~(ISDN_FEATURE_L2_V11096 | ISDN_FEATURE_L2_V11019 | ISDN_FEATURE_L2_V11038));
-       /* If Layer-2 protocol is V.110, accept drivers with
-        * transparent feature even if these don't support V.110
-        * because we can emulate this in linklevel.
-        */
-       for (i = 0; i < ISDN_MAX_CHANNELS; i++)
-               if (USG_NONE(dev->usage[i]) &&
-                   (dev->drvmap[i] != -1)) {
-                       int d = dev->drvmap[i];
-                       if ((dev->usage[i] & ISDN_USAGE_EXCLUSIVE) &&
-                           ((pre_dev != d) || (pre_chan != dev->chanmap[i])))
-                               continue;
-                       if (!strcmp(isdn_map_eaz2msn(msn, d), "-"))
-                               continue;
-                       if (dev->usage[i] & ISDN_USAGE_DISABLED)
-                               continue; /* usage not allowed */
-                       if (dev->drv[d]->flags & DRV_FLAG_RUNNING) {
-                               if (((dev->drv[d]->interface->features & features) == features) ||
-                                   (((dev->drv[d]->interface->features & vfeatures) == vfeatures) &&
-                                    (dev->drv[d]->interface->features & ISDN_FEATURE_L2_TRANS))) {
-                                       if ((pre_dev < 0) || (pre_chan < 0)) {
-                                               dev->usage[i] &= ISDN_USAGE_EXCLUSIVE;
-                                               dev->usage[i] |= usage;
-                                               isdn_info_update();
-                                               return i;
-                                       } else {
-                                               if ((pre_dev == d) && (pre_chan == dev->chanmap[i])) {
-                                                       dev->usage[i] &= ISDN_USAGE_EXCLUSIVE;
-                                                       dev->usage[i] |= usage;
-                                                       isdn_info_update();
-                                                       return i;
-                                               }
-                                       }
-                               }
-                       }
-               }
-       return -1;
-}
-
-/*
- * Set state of ISDN-channel to 'unused'
- */
-void
-isdn_free_channel(int di, int ch, int usage)
-{
-       int i;
-
-       if ((di < 0) || (ch < 0)) {
-               printk(KERN_WARNING "%s: called with invalid drv(%d) or channel(%d)\n",
-                      __func__, di, ch);
-               return;
-       }
-       for (i = 0; i < ISDN_MAX_CHANNELS; i++)
-               if (((!usage) || ((dev->usage[i] & ISDN_USAGE_MASK) == usage)) &&
-                   (dev->drvmap[i] == di) &&
-                   (dev->chanmap[i] == ch)) {
-                       dev->usage[i] &= (ISDN_USAGE_NONE | ISDN_USAGE_EXCLUSIVE);
-                       strcpy(dev->num[i], "???");
-                       dev->ibytes[i] = 0;
-                       dev->obytes[i] = 0;
-// 20.10.99 JIM, try to reinitialize v110 !
-                       dev->v110emu[i] = 0;
-                       atomic_set(&(dev->v110use[i]), 0);
-                       isdn_v110_close(dev->v110[i]);
-                       dev->v110[i] = NULL;
-// 20.10.99 JIM, try to reinitialize v110 !
-                       isdn_info_update();
-                       if (dev->drv[di])
-                               skb_queue_purge(&dev->drv[di]->rpqueue[ch]);
-               }
-}
-
-/*
- * Cancel Exclusive-Flag for ISDN-channel
- */
-void
-isdn_unexclusive_channel(int di, int ch)
-{
-       int i;
-
-       for (i = 0; i < ISDN_MAX_CHANNELS; i++)
-               if ((dev->drvmap[i] == di) &&
-                   (dev->chanmap[i] == ch)) {
-                       dev->usage[i] &= ~ISDN_USAGE_EXCLUSIVE;
-                       isdn_info_update();
-                       return;
-               }
-}
-
-/*
- *  writebuf replacement for SKB_ABLE drivers
- */
-static int
-isdn_writebuf_stub(int drvidx, int chan, const u_char __user *buf, int len)
-{
-       int ret;
-       int hl = dev->drv[drvidx]->interface->hl_hdrlen;
-       struct sk_buff *skb = alloc_skb(hl + len, GFP_ATOMIC);
-
-       if (!skb)
-               return -ENOMEM;
-       skb_reserve(skb, hl);
-       if (copy_from_user(skb_put(skb, len), buf, len)) {
-               dev_kfree_skb(skb);
-               return -EFAULT;
-       }
-       ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, 1, skb);
-       if (ret <= 0)
-               dev_kfree_skb(skb);
-       if (ret > 0)
-               dev->obytes[isdn_dc2minor(drvidx, chan)] += ret;
-       return ret;
-}
-
-/*
- * Return: length of data on success, -ERRcode on failure.
- */
-int
-isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb)
-{
-       int ret;
-       struct sk_buff *nskb = NULL;
-       int v110_ret = skb->len;
-       int idx = isdn_dc2minor(drvidx, chan);
-
-       if (dev->v110[idx]) {
-               atomic_inc(&dev->v110use[idx]);
-               nskb = isdn_v110_encode(dev->v110[idx], skb);
-               atomic_dec(&dev->v110use[idx]);
-               if (!nskb)
-                       return 0;
-               v110_ret = *((int *)nskb->data);
-               skb_pull(nskb, sizeof(int));
-               if (!nskb->len) {
-                       dev_kfree_skb(nskb);
-                       return v110_ret;
-               }
-               /* V.110 must always be acknowledged */
-               ack = 1;
-               ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, nskb);
-       } else {
-               int hl = dev->drv[drvidx]->interface->hl_hdrlen;
-
-               if (skb_headroom(skb) < hl) {
-                       /*
-                        * This should only occur when new HL driver with
-                        * increased hl_hdrlen was loaded after netdevice
-                        * was created and connected to the new driver.
-                        *
-                        * The V.110 branch (re-allocates on its own) does
-                        * not need this
-                        */
-                       struct sk_buff *skb_tmp;
-
-                       skb_tmp = skb_realloc_headroom(skb, hl);
-                       printk(KERN_DEBUG "isdn_writebuf_skb_stub: reallocating headroom%s\n", skb_tmp ? "" : " failed");
-                       if (!skb_tmp) return -ENOMEM; /* 0 better? */
-                       ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, skb_tmp);
-                       if (ret > 0) {
-                               dev_kfree_skb(skb);
-                       } else {
-                               dev_kfree_skb(skb_tmp);
-                       }
-               } else {
-                       ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, skb);
-               }
-       }
-       if (ret > 0) {
-               dev->obytes[idx] += ret;
-               if (dev->v110[idx]) {
-                       atomic_inc(&dev->v110use[idx]);
-                       dev->v110[idx]->skbuser++;
-                       atomic_dec(&dev->v110use[idx]);
-                       /* For V.110 return unencoded data length */
-                       ret = v110_ret;
-                       /* if the complete frame was send we free the skb;
-                          if not upper function will requeue the skb */
-                       if (ret == skb->len)
-                               dev_kfree_skb(skb);
-               }
-       } else
-               if (dev->v110[idx])
-                       dev_kfree_skb(nskb);
-       return ret;
-}
-
-static int
-isdn_add_channels(isdn_driver_t *d, int drvidx, int n, int adding)
-{
-       int j, k, m;
-
-       init_waitqueue_head(&d->st_waitq);
-       if (d->flags & DRV_FLAG_RUNNING)
-               return -1;
-       if (n < 1) return 0;
-
-       m = (adding) ? d->channels + n : n;
-
-       if (dev->channels + n > ISDN_MAX_CHANNELS) {
-               printk(KERN_WARNING "register_isdn: Max. %d channels supported\n",
-                      ISDN_MAX_CHANNELS);
-               return -1;
-       }
-
-       if ((adding) && (d->rcverr))
-               kfree(d->rcverr);
-       if (!(d->rcverr = kcalloc(m, sizeof(int), GFP_ATOMIC))) {
-               printk(KERN_WARNING "register_isdn: Could not alloc rcverr\n");
-               return -1;
-       }
-
-       if ((adding) && (d->rcvcount))
-               kfree(d->rcvcount);
-       if (!(d->rcvcount = kcalloc(m, sizeof(int), GFP_ATOMIC))) {
-               printk(KERN_WARNING "register_isdn: Could not alloc rcvcount\n");
-               if (!adding)
-                       kfree(d->rcverr);
-               return -1;
-       }
-
-       if ((adding) && (d->rpqueue)) {
-               for (j = 0; j < d->channels; j++)
-                       skb_queue_purge(&d->rpqueue[j]);
-               kfree(d->rpqueue);
-       }
-       d->rpqueue = kmalloc_array(m, sizeof(struct sk_buff_head), GFP_ATOMIC);
-       if (!d->rpqueue) {
-               printk(KERN_WARNING "register_isdn: Could not alloc rpqueue\n");
-               if (!adding) {
-                       kfree(d->rcvcount);
-                       kfree(d->rcverr);
-               }
-               return -1;
-       }
-       for (j = 0; j < m; j++) {
-               skb_queue_head_init(&d->rpqueue[j]);
-       }
-
-       if ((adding) && (d->rcv_waitq))
-               kfree(d->rcv_waitq);
-       d->rcv_waitq = kmalloc(array3_size(sizeof(wait_queue_head_t), 2, m),
-                              GFP_ATOMIC);
-       if (!d->rcv_waitq) {
-               printk(KERN_WARNING "register_isdn: Could not alloc rcv_waitq\n");
-               if (!adding) {
-                       kfree(d->rpqueue);
-                       kfree(d->rcvcount);
-                       kfree(d->rcverr);
-               }
-               return -1;
-       }
-       d->snd_waitq = d->rcv_waitq + m;
-       for (j = 0; j < m; j++) {
-               init_waitqueue_head(&d->rcv_waitq[j]);
-               init_waitqueue_head(&d->snd_waitq[j]);
-       }
-
-       dev->channels += n;
-       for (j = d->channels; j < m; j++)
-               for (k = 0; k < ISDN_MAX_CHANNELS; k++)
-                       if (dev->chanmap[k] < 0) {
-                               dev->chanmap[k] = j;
-                               dev->drvmap[k] = drvidx;
-                               break;
-                       }
-       d->channels = m;
-       return 0;
-}
-
-/*
- * Low-level-driver registration
- */
-
-static void
-set_global_features(void)
-{
-       int drvidx;
-
-       dev->global_features = 0;
-       for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++) {
-               if (!dev->drv[drvidx])
-                       continue;
-               if (dev->drv[drvidx]->interface)
-                       dev->global_features |= dev->drv[drvidx]->interface->features;
-       }
-}
-
-#ifdef CONFIG_ISDN_DIVERSION
-
-static char *map_drvname(int di)
-{
-       if ((di < 0) || (di >= ISDN_MAX_DRIVERS))
-               return (NULL);
-       return (dev->drvid[di]); /* driver name */
-} /* map_drvname */
-
-static int map_namedrv(char *id)
-{  int i;
-
-       for (i = 0; i < ISDN_MAX_DRIVERS; i++)
-       { if (!strcmp(dev->drvid[i], id))
-                       return (i);
-       }
-       return (-1);
-} /* map_namedrv */
-
-int DIVERT_REG_NAME(isdn_divert_if *i_div)
-{
-       if (i_div->if_magic != DIVERT_IF_MAGIC)
-               return (DIVERT_VER_ERR);
-       switch (i_div->cmd)
-       {
-       case DIVERT_CMD_REL:
-               if (divert_if != i_div)
-                       return (DIVERT_REL_ERR);
-               divert_if = NULL; /* free interface */
-               return (DIVERT_NO_ERR);
-
-       case DIVERT_CMD_REG:
-               if (divert_if)
-                       return (DIVERT_REG_ERR);
-               i_div->ll_cmd = isdn_command; /* set command function */
-               i_div->drv_to_name = map_drvname;
-               i_div->name_to_drv = map_namedrv;
-               divert_if = i_div; /* remember interface */
-               return (DIVERT_NO_ERR);
-
-       default:
-               return (DIVERT_CMD_ERR);
-       }
-} /* DIVERT_REG_NAME */
-
-EXPORT_SYMBOL(DIVERT_REG_NAME);
-
-#endif /* CONFIG_ISDN_DIVERSION */
-
-
-EXPORT_SYMBOL(register_isdn);
-#ifdef CONFIG_ISDN_PPP
-EXPORT_SYMBOL(isdn_ppp_register_compressor);
-EXPORT_SYMBOL(isdn_ppp_unregister_compressor);
-#endif
-
-int
-register_isdn(isdn_if *i)
-{
-       isdn_driver_t *d;
-       int j;
-       ulong flags;
-       int drvidx;
-
-       if (dev->drivers >= ISDN_MAX_DRIVERS) {
-               printk(KERN_WARNING "register_isdn: Max. %d drivers supported\n",
-                      ISDN_MAX_DRIVERS);
-               return 0;
-       }
-       if (!i->writebuf_skb) {
-               printk(KERN_WARNING "register_isdn: No write routine given.\n");
-               return 0;
-       }
-       if (!(d = kzalloc(sizeof(isdn_driver_t), GFP_KERNEL))) {
-               printk(KERN_WARNING "register_isdn: Could not alloc driver-struct\n");
-               return 0;
-       }
-
-       d->maxbufsize = i->maxbufsize;
-       d->pktcount = 0;
-       d->stavail = 0;
-       d->flags = DRV_FLAG_LOADED;
-       d->online = 0;
-       d->interface = i;
-       d->channels = 0;
-       spin_lock_irqsave(&dev->lock, flags);
-       for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++)
-               if (!dev->drv[drvidx])
-                       break;
-       if (isdn_add_channels(d, drvidx, i->channels, 0)) {
-               spin_unlock_irqrestore(&dev->lock, flags);
-               kfree(d);
-               return 0;
-       }
-       i->channels = drvidx;
-       i->rcvcallb_skb = isdn_receive_skb_callback;
-       i->statcallb = isdn_status_callback;
-       if (!strlen(i->id))
-               sprintf(i->id, "line%d", drvidx);
-       for (j = 0; j < drvidx; j++)
-               if (!strcmp(i->id, dev->drvid[j]))
-                       sprintf(i->id, "line%d", drvidx);
-       dev->drv[drvidx] = d;
-       strcpy(dev->drvid[drvidx], i->id);
-       isdn_info_update();
-       dev->drivers++;
-       set_global_features();
-       spin_unlock_irqrestore(&dev->lock, flags);
-       return 1;
-}
-
-/*
-*****************************************************************************
-* And now the modules code.
-*****************************************************************************
-*/
-
-static char *
-isdn_getrev(const char *revision)
-{
-       char *rev;
-       char *p;
-
-       if ((p = strchr(revision, ':'))) {
-               rev = p + 2;
-               p = strchr(rev, '$');
-               *--p = 0;
-       } else
-               rev = "???";
-       return rev;
-}
-
-/*
- * Allocate and initialize all data, register modem-devices
- */
-static int __init isdn_init(void)
-{
-       int i;
-       char tmprev[50];
-
-       dev = vzalloc(sizeof(isdn_dev));
-       if (!dev) {
-               printk(KERN_WARNING "isdn: Could not allocate device-struct.\n");
-               return -EIO;
-       }
-       timer_setup(&dev->timer, isdn_timer_funct, 0);
-       spin_lock_init(&dev->lock);
-       spin_lock_init(&dev->timerlock);
-#ifdef MODULE
-       dev->owner = THIS_MODULE;
-#endif
-       mutex_init(&dev->mtx);
-       init_waitqueue_head(&dev->info_waitq);
-       for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-               dev->drvmap[i] = -1;
-               dev->chanmap[i] = -1;
-               dev->m_idx[i] = -1;
-               strcpy(dev->num[i], "???");
-       }
-       if (register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops)) {
-               printk(KERN_WARNING "isdn: Could not register control devices\n");
-               vfree(dev);
-               return -EIO;
-       }
-       if ((isdn_tty_modem_init()) < 0) {
-               printk(KERN_WARNING "isdn: Could not register tty devices\n");
-               vfree(dev);
-               unregister_chrdev(ISDN_MAJOR, "isdn");
-               return -EIO;
-       }
-#ifdef CONFIG_ISDN_PPP
-       if (isdn_ppp_init() < 0) {
-               printk(KERN_WARNING "isdn: Could not create PPP-device-structs\n");
-               isdn_tty_exit();
-               unregister_chrdev(ISDN_MAJOR, "isdn");
-               vfree(dev);
-               return -EIO;
-       }
-#endif                          /* CONFIG_ISDN_PPP */
-
-       strcpy(tmprev, isdn_revision);
-       printk(KERN_NOTICE "ISDN subsystem Rev: %s/", isdn_getrev(tmprev));
-       strcpy(tmprev, isdn_net_revision);
-       printk("%s/", isdn_getrev(tmprev));
-       strcpy(tmprev, isdn_ppp_revision);
-       printk("%s/", isdn_getrev(tmprev));
-       strcpy(tmprev, isdn_audio_revision);
-       printk("%s/", isdn_getrev(tmprev));
-       strcpy(tmprev, isdn_v110_revision);
-       printk("%s", isdn_getrev(tmprev));
-
-#ifdef MODULE
-       printk(" loaded\n");
-#else
-       printk("\n");
-#endif
-       isdn_info_update();
-       return 0;
-}
-
-/*
- * Unload module
- */
-static void __exit isdn_exit(void)
-{
-#ifdef CONFIG_ISDN_PPP
-       isdn_ppp_cleanup();
-#endif
-       if (isdn_net_rmall() < 0) {
-               printk(KERN_WARNING "isdn: net-device busy, remove cancelled\n");
-               return;
-       }
-       isdn_tty_exit();
-       unregister_chrdev(ISDN_MAJOR, "isdn");
-       del_timer_sync(&dev->timer);
-       /* call vfree with interrupts enabled, else it will hang */
-       vfree(dev);
-       printk(KERN_NOTICE "ISDN-subsystem unloaded\n");
-}
-
-module_init(isdn_init);
-module_exit(isdn_exit);
 
+++ /dev/null
-/* $Id: isdn_common.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
- *
- * header for Linux ISDN subsystem
- * common used functions and debugging-switches (linklevel).
- *
- * Copyright 1994-1999  by Fritz Elfert (fritz@isdn4linux.de)
- * Copyright 1995,96    by Thinking Objects Software GmbH Wuerzburg
- * Copyright 1995,96    by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#undef  ISDN_DEBUG_MODEM_OPEN
-#undef  ISDN_DEBUG_MODEM_IOCTL
-#undef  ISDN_DEBUG_MODEM_WAITSENT
-#undef  ISDN_DEBUG_MODEM_HUP
-#undef  ISDN_DEBUG_MODEM_ICALL
-#undef  ISDN_DEBUG_MODEM_DUMP
-#undef  ISDN_DEBUG_MODEM_VOICE
-#undef  ISDN_DEBUG_AT
-#undef  ISDN_DEBUG_NET_DUMP
-#undef  ISDN_DEBUG_NET_DIAL
-#undef  ISDN_DEBUG_NET_ICALL
-
-/* Prototypes */
-extern void isdn_lock_drivers(void);
-extern void isdn_unlock_drivers(void);
-extern void isdn_free_channel(int di, int ch, int usage);
-extern void isdn_all_eaz(int di, int ch);
-extern int isdn_command(isdn_ctrl *);
-extern int isdn_dc2minor(int di, int ch);
-extern void isdn_info_update(void);
-extern char *isdn_map_eaz2msn(char *msn, int di);
-extern void isdn_timer_ctrl(int tf, int onoff);
-extern void isdn_unexclusive_channel(int di, int ch);
-extern int isdn_getnum(char **);
-extern int isdn_readbchan(int, int, u_char *, u_char *, int, wait_queue_head_t *);
-extern int isdn_readbchan_tty(int, int, struct tty_port *, int);
-extern int isdn_get_free_channel(int, int, int, int, int, char *);
-extern int isdn_writebuf_skb_stub(int, int, int, struct sk_buff *);
-extern int register_isdn(isdn_if *i);
-extern int isdn_msncmp(const char *,  const char *);
-#if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
-extern void isdn_dumppkt(char *, u_char *, int, int);
-#endif
 
+++ /dev/null
-/* $Id: isdn_concap.c,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
- *
- * Linux ISDN subsystem, protocol encapsulation
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-/* Stuff to support the concap_proto by isdn4linux. isdn4linux - specific
- * stuff goes here. Stuff that depends only on the concap protocol goes to
- * another -- protocol specific -- source file.
- *
- */
-
-
-#include <linux/isdn.h>
-#include "isdn_x25iface.h"
-#include "isdn_net.h"
-#include <linux/concap.h>
-#include "isdn_concap.h"
-
-
-/* The following set of device service operations are for encapsulation
-   protocols that require for reliable datalink semantics. That means:
-
-   - before any data is to be submitted the connection must explicitly
-   be set up.
-   - after the successful set up of the connection is signalled the
-   connection is considered to be reliably up.
-
-   Auto-dialing ist not compatible with this requirements. Thus, auto-dialing
-   is completely bypassed.
-
-   It might be possible to implement a (non standardized) datalink protocol
-   that provides a reliable data link service while using some auto dialing
-   mechanism. Such a protocol would need an auxiliary channel (i.e. user-user-
-   signaling on the D-channel) while the B-channel is down.
-*/
-
-
-static int isdn_concap_dl_data_req(struct concap_proto *concap, struct sk_buff *skb)
-{
-       struct net_device *ndev = concap->net_dev;
-       isdn_net_dev *nd = ((isdn_net_local *) netdev_priv(ndev))->netdev;
-       isdn_net_local *lp = isdn_net_get_locked_lp(nd);
-
-       IX25DEBUG("isdn_concap_dl_data_req: %s \n", concap->net_dev->name);
-       if (!lp) {
-               IX25DEBUG("isdn_concap_dl_data_req: %s : isdn_net_send_skb returned %d\n", concap->net_dev->name, 1);
-               return 1;
-       }
-       lp->huptimer = 0;
-       isdn_net_writebuf_skb(lp, skb);
-       spin_unlock_bh(&lp->xmit_lock);
-       IX25DEBUG("isdn_concap_dl_data_req: %s : isdn_net_send_skb returned %d\n", concap->net_dev->name, 0);
-       return 0;
-}
-
-
-static int isdn_concap_dl_connect_req(struct concap_proto *concap)
-{
-       struct net_device *ndev = concap->net_dev;
-       isdn_net_local *lp = netdev_priv(ndev);
-       int ret;
-       IX25DEBUG("isdn_concap_dl_connect_req: %s \n", ndev->name);
-
-       /* dial ... */
-       ret = isdn_net_dial_req(lp);
-       if (ret) IX25DEBUG("dialing failed\n");
-       return ret;
-}
-
-static int isdn_concap_dl_disconn_req(struct concap_proto *concap)
-{
-       IX25DEBUG("isdn_concap_dl_disconn_req: %s \n", concap->net_dev->name);
-
-       isdn_net_hangup(concap->net_dev);
-       return 0;
-}
-
-struct concap_device_ops isdn_concap_reliable_dl_dops = {
-       .data_req = &isdn_concap_dl_data_req,
-       .connect_req = &isdn_concap_dl_connect_req,
-       .disconn_req = &isdn_concap_dl_disconn_req
-};
-
-/* The following should better go into a dedicated source file such that
-   this sourcefile does not need to include any protocol specific header
-   files. For now:
-*/
-struct concap_proto *isdn_concap_new(int encap)
-{
-       switch (encap) {
-       case ISDN_NET_ENCAP_X25IFACE:
-               return isdn_x25iface_proto_new();
-       }
-       return NULL;
-}
 
+++ /dev/null
-/* $Id: isdn_concap.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
- *
- * Linux ISDN subsystem, protocol encapsulation
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-extern struct concap_device_ops isdn_concap_reliable_dl_dops;
-extern struct concap_proto *isdn_concap_new(int);
 
+++ /dev/null
-/* $Id: isdn_net.c,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
- *
- * Linux ISDN subsystem, network interfaces and related functions (linklevel).
- *
- * Copyright 1994-1998  by Fritz Elfert (fritz@isdn4linux.de)
- * Copyright 1995,96    by Thinking Objects Software GmbH Wuerzburg
- * Copyright 1995,96    by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- * Data Over Voice (DOV) support added - Guy Ellis 23-Mar-02
- *                                       guy@traverse.com.au
- * Outgoing calls - looks for a 'V' in first char of dialed number
- * Incoming calls - checks first character of eaz as follows:
- *   Numeric - accept DATA only - original functionality
- *   'V'     - accept VOICE (DOV) only
- *   'B'     - accept BOTH DATA and DOV types
- *
- * Jan 2001: fix CISCO HDLC      Bjoern A. Zeeb <i4l@zabbadoz.net>
- *           for info on the protocol, see
- *           http://i4l.zabbadoz.net/i4l/cisco-hdlc.txt
- */
-
-#include <linux/isdn.h>
-#include <linux/slab.h>
-#include <net/arp.h>
-#include <net/dst.h>
-#include <net/pkt_sched.h>
-#include <linux/inetdevice.h>
-#include "isdn_common.h"
-#include "isdn_net.h"
-#ifdef CONFIG_ISDN_PPP
-#include "isdn_ppp.h"
-#endif
-#ifdef CONFIG_ISDN_X25
-#include <linux/concap.h>
-#include "isdn_concap.h"
-#endif
-
-
-/*
- * Outline of new tbusy handling:
- *
- * Old method, roughly spoken, consisted of setting tbusy when entering
- * isdn_net_start_xmit() and at several other locations and clearing
- * it from isdn_net_start_xmit() thread when sending was successful.
- *
- * With 2.3.x multithreaded network core, to prevent problems, tbusy should
- * only be set by the isdn_net_start_xmit() thread and only when a tx-busy
- * condition is detected. Other threads (in particular isdn_net_stat_callb())
- * are only allowed to clear tbusy.
- *
- * -HE
- */
-
-/*
- * About SOFTNET:
- * Most of the changes were pretty obvious and basically done by HE already.
- *
- * One problem of the isdn net device code is that it uses struct net_device
- * for masters and slaves. However, only master interface are registered to
- * the network layer, and therefore, it only makes sense to call netif_*
- * functions on them.
- *
- * --KG
- */
-
-/*
- * Find out if the netdevice has been ifup-ed yet.
- * For slaves, look at the corresponding master.
- */
-static __inline__ int isdn_net_device_started(isdn_net_dev *n)
-{
-       isdn_net_local *lp = n->local;
-       struct net_device *dev;
-
-       if (lp->master)
-               dev = lp->master;
-       else
-               dev = n->dev;
-       return netif_running(dev);
-}
-
-/*
- * wake up the network -> net_device queue.
- * For slaves, wake the corresponding master interface.
- */
-static __inline__ void isdn_net_device_wake_queue(isdn_net_local *lp)
-{
-       if (lp->master)
-               netif_wake_queue(lp->master);
-       else
-               netif_wake_queue(lp->netdev->dev);
-}
-
-/*
- * stop the network -> net_device queue.
- * For slaves, stop the corresponding master interface.
- */
-static __inline__ void isdn_net_device_stop_queue(isdn_net_local *lp)
-{
-       if (lp->master)
-               netif_stop_queue(lp->master);
-       else
-               netif_stop_queue(lp->netdev->dev);
-}
-
-/*
- * find out if the net_device which this lp belongs to (lp can be
- * master or slave) is busy. It's busy iff all (master and slave)
- * queues are busy
- */
-static __inline__ int isdn_net_device_busy(isdn_net_local *lp)
-{
-       isdn_net_local *nlp;
-       isdn_net_dev *nd;
-       unsigned long flags;
-
-       if (!isdn_net_lp_busy(lp))
-               return 0;
-
-       if (lp->master)
-               nd = ISDN_MASTER_PRIV(lp)->netdev;
-       else
-               nd = lp->netdev;
-
-       spin_lock_irqsave(&nd->queue_lock, flags);
-       nlp = lp->next;
-       while (nlp != lp) {
-               if (!isdn_net_lp_busy(nlp)) {
-                       spin_unlock_irqrestore(&nd->queue_lock, flags);
-                       return 0;
-               }
-               nlp = nlp->next;
-       }
-       spin_unlock_irqrestore(&nd->queue_lock, flags);
-       return 1;
-}
-
-static __inline__ void isdn_net_inc_frame_cnt(isdn_net_local *lp)
-{
-       atomic_inc(&lp->frame_cnt);
-       if (isdn_net_device_busy(lp))
-               isdn_net_device_stop_queue(lp);
-}
-
-static __inline__ void isdn_net_dec_frame_cnt(isdn_net_local *lp)
-{
-       atomic_dec(&lp->frame_cnt);
-
-       if (!(isdn_net_device_busy(lp))) {
-               if (!skb_queue_empty(&lp->super_tx_queue)) {
-                       schedule_work(&lp->tqueue);
-               } else {
-                       isdn_net_device_wake_queue(lp);
-               }
-       }
-}
-
-static __inline__ void isdn_net_zero_frame_cnt(isdn_net_local *lp)
-{
-       atomic_set(&lp->frame_cnt, 0);
-}
-
-/* For 2.2.x we leave the transmitter busy timeout at 2 secs, just
- * to be safe.
- * For 2.3.x we push it up to 20 secs, because call establishment
- * (in particular callback) may take such a long time, and we
- * don't want confusing messages in the log. However, there is a slight
- * possibility that this large timeout will break other things like MPPP,
- * which might rely on the tx timeout. If so, we'll find out this way...
- */
-
-#define ISDN_NET_TX_TIMEOUT (20 * HZ)
-
-/* Prototypes */
-
-static int isdn_net_force_dial_lp(isdn_net_local *);
-static netdev_tx_t isdn_net_start_xmit(struct sk_buff *,
-                                      struct net_device *);
-
-static void isdn_net_ciscohdlck_connected(isdn_net_local *lp);
-static void isdn_net_ciscohdlck_disconnected(isdn_net_local *lp);
-
-char *isdn_net_revision = "$Revision: 1.1.2.2 $";
-
-/*
- * Code for raw-networking over ISDN
- */
-
-static void
-isdn_net_unreachable(struct net_device *dev, struct sk_buff *skb, char *reason)
-{
-       if (skb) {
-
-               u_short proto = ntohs(skb->protocol);
-
-               printk(KERN_DEBUG "isdn_net: %s: %s, signalling dst_link_failure %s\n",
-                      dev->name,
-                      (reason != NULL) ? reason : "unknown",
-                      (proto != ETH_P_IP) ? "Protocol != ETH_P_IP" : "");
-
-               dst_link_failure(skb);
-       }
-       else {  /* dial not triggered by rawIP packet */
-               printk(KERN_DEBUG "isdn_net: %s: %s\n",
-                      dev->name,
-                      (reason != NULL) ? reason : "reason unknown");
-       }
-}
-
-static void
-isdn_net_reset(struct net_device *dev)
-{
-#ifdef CONFIG_ISDN_X25
-       struct concap_device_ops *dops =
-               ((isdn_net_local *)netdev_priv(dev))->dops;
-       struct concap_proto *cprot =
-               ((isdn_net_local *)netdev_priv(dev))->netdev->cprot;
-#endif
-#ifdef CONFIG_ISDN_X25
-       if (cprot && cprot->pops && dops)
-               cprot->pops->restart(cprot, dev, dops);
-#endif
-}
-
-/* Open/initialize the board. */
-static int
-isdn_net_open(struct net_device *dev)
-{
-       int i;
-       struct net_device *p;
-       struct in_device *in_dev;
-
-       /* moved here from isdn_net_reset, because only the master has an
-          interface associated which is supposed to be started. BTW:
-          we need to call netif_start_queue, not netif_wake_queue here */
-       netif_start_queue(dev);
-
-       isdn_net_reset(dev);
-       /* Fill in the MAC-level header (not needed, but for compatibility... */
-       for (i = 0; i < ETH_ALEN - sizeof(u32); i++)
-               dev->dev_addr[i] = 0xfc;
-       if ((in_dev = dev->ip_ptr) != NULL) {
-               /*
-                *      Any address will do - we take the first
-                */
-               struct in_ifaddr *ifa = in_dev->ifa_list;
-               if (ifa != NULL)
-                       memcpy(dev->dev_addr + 2, &ifa->ifa_local, 4);
-       }
-
-       /* If this interface has slaves, start them also */
-       p = MASTER_TO_SLAVE(dev);
-       if (p) {
-               while (p) {
-                       isdn_net_reset(p);
-                       p = MASTER_TO_SLAVE(p);
-               }
-       }
-       isdn_lock_drivers();
-       return 0;
-}
-
-/*
- * Assign an ISDN-channel to a net-interface
- */
-static void
-isdn_net_bind_channel(isdn_net_local *lp, int idx)
-{
-       lp->flags |= ISDN_NET_CONNECTED;
-       lp->isdn_device = dev->drvmap[idx];
-       lp->isdn_channel = dev->chanmap[idx];
-       dev->rx_netdev[idx] = lp->netdev;
-       dev->st_netdev[idx] = lp->netdev;
-}
-
-/*
- * unbind a net-interface (resets interface after an error)
- */
-static void
-isdn_net_unbind_channel(isdn_net_local *lp)
-{
-       skb_queue_purge(&lp->super_tx_queue);
-
-       if (!lp->master) {      /* reset only master device */
-               /* Moral equivalent of dev_purge_queues():
-                  BEWARE! This chunk of code cannot be called from hardware
-                  interrupt handler. I hope it is true. --ANK
-               */
-               qdisc_reset_all_tx(lp->netdev->dev);
-       }
-       lp->dialstate = 0;
-       dev->rx_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL;
-       dev->st_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL;
-       if (lp->isdn_device != -1 && lp->isdn_channel != -1)
-               isdn_free_channel(lp->isdn_device, lp->isdn_channel,
-                                 ISDN_USAGE_NET);
-       lp->flags &= ~ISDN_NET_CONNECTED;
-       lp->isdn_device = -1;
-       lp->isdn_channel = -1;
-}
-
-/*
- * Perform auto-hangup and cps-calculation for net-interfaces.
- *
- * auto-hangup:
- * Increment idle-counter (this counter is reset on any incoming or
- * outgoing packet), if counter exceeds configured limit either do a
- * hangup immediately or - if configured - wait until just before the next
- * charge-info.
- *
- * cps-calculation (needed for dynamic channel-bundling):
- * Since this function is called every second, simply reset the
- * byte-counter of the interface after copying it to the cps-variable.
- */
-static unsigned long last_jiffies = -HZ;
-
-void
-isdn_net_autohup(void)
-{
-       isdn_net_dev *p = dev->netdev;
-       int anymore;
-
-       anymore = 0;
-       while (p) {
-               isdn_net_local *l = p->local;
-               if (jiffies == last_jiffies)
-                       l->cps = l->transcount;
-               else
-                       l->cps = (l->transcount * HZ) / (jiffies - last_jiffies);
-               l->transcount = 0;
-               if (dev->net_verbose > 3)
-                       printk(KERN_DEBUG "%s: %d bogocps\n", p->dev->name, l->cps);
-               if ((l->flags & ISDN_NET_CONNECTED) && (!l->dialstate)) {
-                       anymore = 1;
-                       l->huptimer++;
-                       /*
-                        * if there is some dialmode where timeout-hangup
-                        * should _not_ be done, check for that here
-                        */
-                       if ((l->onhtime) &&
-                           (l->huptimer > l->onhtime))
-                       {
-                               if (l->hupflags & ISDN_MANCHARGE &&
-                                   l->hupflags & ISDN_CHARGEHUP) {
-                                       while (time_after(jiffies, l->chargetime + l->chargeint))
-                                               l->chargetime += l->chargeint;
-                                       if (time_after(jiffies, l->chargetime + l->chargeint - 2 * HZ))
-                                               if (l->outgoing || l->hupflags & ISDN_INHUP)
-                                                       isdn_net_hangup(p->dev);
-                               } else if (l->outgoing) {
-                                       if (l->hupflags & ISDN_CHARGEHUP) {
-                                               if (l->hupflags & ISDN_WAITCHARGE) {
-                                                       printk(KERN_DEBUG "isdn_net: Hupflags of %s are %X\n",
-                                                              p->dev->name, l->hupflags);
-                                                       isdn_net_hangup(p->dev);
-                                               } else if (time_after(jiffies, l->chargetime + l->chargeint)) {
-                                                       printk(KERN_DEBUG
-                                                              "isdn_net: %s: chtime = %lu, chint = %d\n",
-                                                              p->dev->name, l->chargetime, l->chargeint);
-                                                       isdn_net_hangup(p->dev);
-                                               }
-                                       } else
-                                               isdn_net_hangup(p->dev);
-                               } else if (l->hupflags & ISDN_INHUP)
-                                       isdn_net_hangup(p->dev);
-                       }
-
-                       if (dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*l) == ISDN_NET_DM_OFF)) {
-                               isdn_net_hangup(p->dev);
-                               break;
-                       }
-               }
-               p = (isdn_net_dev *) p->next;
-       }
-       last_jiffies = jiffies;
-       isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, anymore);
-}
-
-static void isdn_net_lp_disconnected(isdn_net_local *lp)
-{
-       isdn_net_rm_from_bundle(lp);
-}
-
-/*
- * Handle status-messages from ISDN-interfacecard.
- * This function is called from within the main-status-dispatcher
- * isdn_status_callback, which itself is called from the low-level driver.
- * Return: 1 = Event handled, 0 = not for us or unknown Event.
- */
-int
-isdn_net_stat_callback(int idx, isdn_ctrl *c)
-{
-       isdn_net_dev *p = dev->st_netdev[idx];
-       int cmd = c->command;
-
-       if (p) {
-               isdn_net_local *lp = p->local;
-#ifdef CONFIG_ISDN_X25
-               struct concap_proto *cprot = lp->netdev->cprot;
-               struct concap_proto_ops *pops = cprot ? cprot->pops : NULL;
-#endif
-               switch (cmd) {
-               case ISDN_STAT_BSENT:
-                       /* A packet has successfully been sent out */
-                       if ((lp->flags & ISDN_NET_CONNECTED) &&
-                           (!lp->dialstate)) {
-                               isdn_net_dec_frame_cnt(lp);
-                               lp->stats.tx_packets++;
-                               lp->stats.tx_bytes += c->parm.length;
-                       }
-                       return 1;
-               case ISDN_STAT_DCONN:
-                       /* D-Channel is up */
-                       switch (lp->dialstate) {
-                       case 4:
-                       case 7:
-                       case 8:
-                               lp->dialstate++;
-                               return 1;
-                       case 12:
-                               lp->dialstate = 5;
-                               return 1;
-                       }
-                       break;
-               case ISDN_STAT_DHUP:
-                       /* Either D-Channel-hangup or error during dialout */
-#ifdef CONFIG_ISDN_X25
-                       /* If we are not connencted then dialing had
-                          failed. If there are generic encap protocol
-                          receiver routines signal the closure of
-                          the link*/
-
-                       if (!(lp->flags & ISDN_NET_CONNECTED)
-                           && pops && pops->disconn_ind)
-                               pops->disconn_ind(cprot);
-#endif /* CONFIG_ISDN_X25 */
-                       if ((!lp->dialstate) && (lp->flags & ISDN_NET_CONNECTED)) {
-                               if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK)
-                                       isdn_net_ciscohdlck_disconnected(lp);
-#ifdef CONFIG_ISDN_PPP
-                               if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
-                                       isdn_ppp_free(lp);
-#endif
-                               isdn_net_lp_disconnected(lp);
-                               isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
-                               printk(KERN_INFO "%s: remote hangup\n", p->dev->name);
-                               printk(KERN_INFO "%s: Chargesum is %d\n", p->dev->name,
-                                      lp->charge);
-                               isdn_net_unbind_channel(lp);
-                               return 1;
-                       }
-                       break;
-#ifdef CONFIG_ISDN_X25
-               case ISDN_STAT_BHUP:
-                       /* B-Channel-hangup */
-                       /* try if there are generic encap protocol
-                          receiver routines and signal the closure of
-                          the link */
-                       if (pops && pops->disconn_ind) {
-                               pops->disconn_ind(cprot);
-                               return 1;
-                       }
-                       break;
-#endif /* CONFIG_ISDN_X25 */
-               case ISDN_STAT_BCONN:
-                       /* B-Channel is up */
-                       isdn_net_zero_frame_cnt(lp);
-                       switch (lp->dialstate) {
-                       case 5:
-                       case 6:
-                       case 7:
-                       case 8:
-                       case 9:
-                       case 10:
-                       case 12:
-                               if (lp->dialstate <= 6) {
-                                       dev->usage[idx] |= ISDN_USAGE_OUTGOING;
-                                       isdn_info_update();
-                               } else
-                                       dev->rx_netdev[idx] = p;
-                               lp->dialstate = 0;
-                               isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 1);
-                               if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK)
-                                       isdn_net_ciscohdlck_connected(lp);
-                               if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP) {
-                                       if (lp->master) { /* is lp a slave? */
-                                               isdn_net_dev *nd = ISDN_MASTER_PRIV(lp)->netdev;
-                                               isdn_net_add_to_bundle(nd, lp);
-                                       }
-                               }
-                               printk(KERN_INFO "isdn_net: %s connected\n", p->dev->name);
-                               /* If first Chargeinfo comes before B-Channel connect,
-                                * we correct the timestamp here.
-                                */
-                               lp->chargetime = jiffies;
-
-                               /* reset dial-timeout */
-                               lp->dialstarted = 0;
-                               lp->dialwait_timer = 0;
-
-#ifdef CONFIG_ISDN_PPP
-                               if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
-                                       isdn_ppp_wakeup_daemon(lp);
-#endif
-#ifdef CONFIG_ISDN_X25
-                               /* try if there are generic concap receiver routines */
-                               if (pops)
-                                       if (pops->connect_ind)
-                                               pops->connect_ind(cprot);
-#endif /* CONFIG_ISDN_X25 */
-                               /* ppp needs to do negotiations first */
-                               if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP)
-                                       isdn_net_device_wake_queue(lp);
-                               return 1;
-                       }
-                       break;
-               case ISDN_STAT_NODCH:
-                       /* No D-Channel avail. */
-                       if (lp->dialstate == 4) {
-                               lp->dialstate--;
-                               return 1;
-                       }
-                       break;
-               case ISDN_STAT_CINF:
-                       /* Charge-info from TelCo. Calculate interval between
-                        * charge-infos and set timestamp for last info for
-                        * usage by isdn_net_autohup()
-                        */
-                       lp->charge++;
-                       if (lp->hupflags & ISDN_HAVECHARGE) {
-                               lp->hupflags &= ~ISDN_WAITCHARGE;
-                               lp->chargeint = jiffies - lp->chargetime - (2 * HZ);
-                       }
-                       if (lp->hupflags & ISDN_WAITCHARGE)
-                               lp->hupflags |= ISDN_HAVECHARGE;
-                       lp->chargetime = jiffies;
-                       printk(KERN_DEBUG "isdn_net: Got CINF chargetime of %s now %lu\n",
-                              p->dev->name, lp->chargetime);
-                       return 1;
-               }
-       }
-       return 0;
-}
-
-/*
- * Perform dialout for net-interfaces and timeout-handling for
- * D-Channel-up and B-Channel-up Messages.
- * This function is initially called from within isdn_net_start_xmit() or
- * or isdn_net_find_icall() after initializing the dialstate for an
- * interface. If further calls are needed, the function schedules itself
- * for a timer-callback via isdn_timer_function().
- * The dialstate is also affected by incoming status-messages from
- * the ISDN-Channel which are handled in isdn_net_stat_callback() above.
- */
-void
-isdn_net_dial(void)
-{
-       isdn_net_dev *p = dev->netdev;
-       int anymore = 0;
-       int i;
-       isdn_ctrl cmd;
-       u_char *phone_number;
-
-       while (p) {
-               isdn_net_local *lp = p->local;
-
-#ifdef ISDN_DEBUG_NET_DIAL
-               if (lp->dialstate)
-                       printk(KERN_DEBUG "%s: dialstate=%d\n", p->dev->name, lp->dialstate);
-#endif
-               switch (lp->dialstate) {
-               case 0:
-                       /* Nothing to do for this interface */
-                       break;
-               case 1:
-                       /* Initiate dialout. Set phone-number-pointer to first number
-                        * of interface.
-                        */
-                       lp->dial = lp->phone[1];
-                       if (!lp->dial) {
-                               printk(KERN_WARNING "%s: phone number deleted?\n",
-                                      p->dev->name);
-                               isdn_net_hangup(p->dev);
-                               break;
-                       }
-                       anymore = 1;
-
-                       if (lp->dialtimeout > 0)
-                               if (lp->dialstarted == 0 || time_after(jiffies, lp->dialstarted + lp->dialtimeout + lp->dialwait)) {
-                                       lp->dialstarted = jiffies;
-                                       lp->dialwait_timer = 0;
-                               }
-
-                       lp->dialstate++;
-                       /* Fall through */
-               case 2:
-                       /* Prepare dialing. Clear EAZ, then set EAZ. */
-                       cmd.driver = lp->isdn_device;
-                       cmd.arg = lp->isdn_channel;
-                       cmd.command = ISDN_CMD_CLREAZ;
-                       isdn_command(&cmd);
-                       sprintf(cmd.parm.num, "%s", isdn_map_eaz2msn(lp->msn, cmd.driver));
-                       cmd.command = ISDN_CMD_SETEAZ;
-                       isdn_command(&cmd);
-                       lp->dialretry = 0;
-                       anymore = 1;
-                       lp->dialstate++;
-                       /* Fall through */
-               case 3:
-                       /* Setup interface, dial current phone-number, switch to next number.
-                        * If list of phone-numbers is exhausted, increment
-                        * retry-counter.
-                        */
-                       if (dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF)) {
-                               char *s;
-                               if (dev->global_flags & ISDN_GLOBAL_STOPPED)
-                                       s = "dial suppressed: isdn system stopped";
-                               else
-                                       s = "dial suppressed: dialmode `off'";
-                               isdn_net_unreachable(p->dev, NULL, s);
-                               isdn_net_hangup(p->dev);
-                               break;
-                       }
-                       cmd.driver = lp->isdn_device;
-                       cmd.command = ISDN_CMD_SETL2;
-                       cmd.arg = lp->isdn_channel + (lp->l2_proto << 8);
-                       isdn_command(&cmd);
-                       cmd.driver = lp->isdn_device;
-                       cmd.command = ISDN_CMD_SETL3;
-                       cmd.arg = lp->isdn_channel + (lp->l3_proto << 8);
-                       isdn_command(&cmd);
-                       cmd.driver = lp->isdn_device;
-                       cmd.arg = lp->isdn_channel;
-                       if (!lp->dial) {
-                               printk(KERN_WARNING "%s: phone number deleted?\n",
-                                      p->dev->name);
-                               isdn_net_hangup(p->dev);
-                               break;
-                       }
-                       if (!strncmp(lp->dial->num, "LEASED", strlen("LEASED"))) {
-                               lp->dialstate = 4;
-                               printk(KERN_INFO "%s: Open leased line ...\n", p->dev->name);
-                       } else {
-                               if (lp->dialtimeout > 0)
-                                       if (time_after(jiffies, lp->dialstarted + lp->dialtimeout)) {
-                                               lp->dialwait_timer = jiffies + lp->dialwait;
-                                               lp->dialstarted = 0;
-                                               isdn_net_unreachable(p->dev, NULL, "dial: timed out");
-                                               isdn_net_hangup(p->dev);
-                                               break;
-                                       }
-
-                               cmd.driver = lp->isdn_device;
-                               cmd.command = ISDN_CMD_DIAL;
-                               cmd.parm.setup.si2 = 0;
-
-                               /* check for DOV */
-                               phone_number = lp->dial->num;
-                               if ((*phone_number == 'v') ||
-                                   (*phone_number == 'V')) { /* DOV call */
-                                       cmd.parm.setup.si1 = 1;
-                               } else { /* DATA call */
-                                       cmd.parm.setup.si1 = 7;
-                               }
-
-                               strcpy(cmd.parm.setup.phone, phone_number);
-                               /*
-                                * Switch to next number or back to start if at end of list.
-                                */
-                               if (!(lp->dial = (isdn_net_phone *) lp->dial->next)) {
-                                       lp->dial = lp->phone[1];
-                                       lp->dialretry++;
-
-                                       if (lp->dialretry > lp->dialmax) {
-                                               if (lp->dialtimeout == 0) {
-                                                       lp->dialwait_timer = jiffies + lp->dialwait;
-                                                       lp->dialstarted = 0;
-                                                       isdn_net_unreachable(p->dev, NULL, "dial: tried all numbers dialmax times");
-                                               }
-                                               isdn_net_hangup(p->dev);
-                                               break;
-                                       }
-                               }
-                               sprintf(cmd.parm.setup.eazmsn, "%s",
-                                       isdn_map_eaz2msn(lp->msn, cmd.driver));
-                               i = isdn_dc2minor(lp->isdn_device, lp->isdn_channel);
-                               if (i >= 0) {
-                                       strcpy(dev->num[i], cmd.parm.setup.phone);
-                                       dev->usage[i] |= ISDN_USAGE_OUTGOING;
-                                       isdn_info_update();
-                               }
-                               printk(KERN_INFO "%s: dialing %d %s... %s\n", p->dev->name,
-                                      lp->dialretry, cmd.parm.setup.phone,
-                                      (cmd.parm.setup.si1 == 1) ? "DOV" : "");
-                               lp->dtimer = 0;
-#ifdef ISDN_DEBUG_NET_DIAL
-                               printk(KERN_DEBUG "dial: d=%d c=%d\n", lp->isdn_device,
-                                      lp->isdn_channel);
-#endif
-                               isdn_command(&cmd);
-                       }
-                       lp->huptimer = 0;
-                       lp->outgoing = 1;
-                       if (lp->chargeint) {
-                               lp->hupflags |= ISDN_HAVECHARGE;
-                               lp->hupflags &= ~ISDN_WAITCHARGE;
-                       } else {
-                               lp->hupflags |= ISDN_WAITCHARGE;
-                               lp->hupflags &= ~ISDN_HAVECHARGE;
-                       }
-                       anymore = 1;
-                       lp->dialstate =
-                               (lp->cbdelay &&
-                                (lp->flags & ISDN_NET_CBOUT)) ? 12 : 4;
-                       break;
-               case 4:
-                       /* Wait for D-Channel-connect.
-                        * If timeout, switch back to state 3.
-                        * Dialmax-handling moved to state 3.
-                        */
-                       if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
-                               lp->dialstate = 3;
-                       anymore = 1;
-                       break;
-               case 5:
-                       /* Got D-Channel-Connect, send B-Channel-request */
-                       cmd.driver = lp->isdn_device;
-                       cmd.arg = lp->isdn_channel;
-                       cmd.command = ISDN_CMD_ACCEPTB;
-                       anymore = 1;
-                       lp->dtimer = 0;
-                       lp->dialstate++;
-                       isdn_command(&cmd);
-                       break;
-               case 6:
-                       /* Wait for B- or D-Channel-connect. If timeout,
-                        * switch back to state 3.
-                        */
-#ifdef ISDN_DEBUG_NET_DIAL
-                       printk(KERN_DEBUG "dialtimer2: %d\n", lp->dtimer);
-#endif
-                       if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
-                               lp->dialstate = 3;
-                       anymore = 1;
-                       break;
-               case 7:
-                       /* Got incoming Call, setup L2 and L3 protocols,
-                        * then wait for D-Channel-connect
-                        */
-#ifdef ISDN_DEBUG_NET_DIAL
-                       printk(KERN_DEBUG "dialtimer4: %d\n", lp->dtimer);
-#endif
-                       cmd.driver = lp->isdn_device;
-                       cmd.command = ISDN_CMD_SETL2;
-                       cmd.arg = lp->isdn_channel + (lp->l2_proto << 8);
-                       isdn_command(&cmd);
-                       cmd.driver = lp->isdn_device;
-                       cmd.command = ISDN_CMD_SETL3;
-                       cmd.arg = lp->isdn_channel + (lp->l3_proto << 8);
-                       isdn_command(&cmd);
-                       if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT15)
-                               isdn_net_hangup(p->dev);
-                       else {
-                               anymore = 1;
-                               lp->dialstate++;
-                       }
-                       break;
-               case 9:
-                       /* Got incoming D-Channel-Connect, send B-Channel-request */
-                       cmd.driver = lp->isdn_device;
-                       cmd.arg = lp->isdn_channel;
-                       cmd.command = ISDN_CMD_ACCEPTB;
-                       isdn_command(&cmd);
-                       anymore = 1;
-                       lp->dtimer = 0;
-                       lp->dialstate++;
-                       break;
-               case 8:
-               case 10:
-                       /*  Wait for B- or D-channel-connect */
-#ifdef ISDN_DEBUG_NET_DIAL
-                       printk(KERN_DEBUG "dialtimer4: %d\n", lp->dtimer);
-#endif
-                       if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
-                               isdn_net_hangup(p->dev);
-                       else
-                               anymore = 1;
-                       break;
-               case 11:
-                       /* Callback Delay */
-                       if (lp->dtimer++ > lp->cbdelay)
-                               lp->dialstate = 1;
-                       anymore = 1;
-                       break;
-               case 12:
-                       /* Remote does callback. Hangup after cbdelay, then wait for incoming
-                        * call (in state 4).
-                        */
-                       if (lp->dtimer++ > lp->cbdelay)
-                       {
-                               printk(KERN_INFO "%s: hangup waiting for callback ...\n", p->dev->name);
-                               lp->dtimer = 0;
-                               lp->dialstate = 4;
-                               cmd.driver = lp->isdn_device;
-                               cmd.command = ISDN_CMD_HANGUP;
-                               cmd.arg = lp->isdn_channel;
-                               isdn_command(&cmd);
-                               isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
-                       }
-                       anymore = 1;
-                       break;
-               default:
-                       printk(KERN_WARNING "isdn_net: Illegal dialstate %d for device %s\n",
-                              lp->dialstate, p->dev->name);
-               }
-               p = (isdn_net_dev *) p->next;
-       }
-       isdn_timer_ctrl(ISDN_TIMER_NETDIAL, anymore);
-}
-
-/*
- * Perform hangup for a net-interface.
- */
-void
-isdn_net_hangup(struct net_device *d)
-{
-       isdn_net_local *lp = netdev_priv(d);
-       isdn_ctrl cmd;
-#ifdef CONFIG_ISDN_X25
-       struct concap_proto *cprot = lp->netdev->cprot;
-       struct concap_proto_ops *pops = cprot ? cprot->pops : NULL;
-#endif
-
-       if (lp->flags & ISDN_NET_CONNECTED) {
-               if (lp->slave != NULL) {
-                       isdn_net_local *slp = ISDN_SLAVE_PRIV(lp);
-                       if (slp->flags & ISDN_NET_CONNECTED) {
-                               printk(KERN_INFO
-                                      "isdn_net: hang up slave %s before %s\n",
-                                      lp->slave->name, d->name);
-                               isdn_net_hangup(lp->slave);
-                       }
-               }
-               printk(KERN_INFO "isdn_net: local hangup %s\n", d->name);
-#ifdef CONFIG_ISDN_PPP
-               if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
-                       isdn_ppp_free(lp);
-#endif
-               isdn_net_lp_disconnected(lp);
-#ifdef CONFIG_ISDN_X25
-               /* try if there are generic encap protocol
-                  receiver routines and signal the closure of
-                  the link */
-               if (pops && pops->disconn_ind)
-                       pops->disconn_ind(cprot);
-#endif /* CONFIG_ISDN_X25 */
-
-               cmd.driver = lp->isdn_device;
-               cmd.command = ISDN_CMD_HANGUP;
-               cmd.arg = lp->isdn_channel;
-               isdn_command(&cmd);
-               printk(KERN_INFO "%s: Chargesum is %d\n", d->name, lp->charge);
-               isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
-       }
-       isdn_net_unbind_channel(lp);
-}
-
-typedef struct {
-       __be16 source;
-       __be16 dest;
-} ip_ports;
-
-static void
-isdn_net_log_skb(struct sk_buff *skb, isdn_net_local *lp)
-{
-       /* hopefully, this was set correctly */
-       const u_char *p = skb_network_header(skb);
-       unsigned short proto = ntohs(skb->protocol);
-       int data_ofs;
-       ip_ports *ipp;
-       char addinfo[100];
-
-       addinfo[0] = '\0';
-       /* This check stolen from 2.1.72 dev_queue_xmit_nit() */
-       if (p < skb->data || skb_network_header(skb) >= skb_tail_pointer(skb)) {
-               /* fall back to old isdn_net_log_packet method() */
-               char *buf = skb->data;
-
-               printk(KERN_DEBUG "isdn_net: protocol %04x is buggy, dev %s\n", skb->protocol, lp->netdev->dev->name);
-               p = buf;
-               proto = ETH_P_IP;
-               switch (lp->p_encap) {
-               case ISDN_NET_ENCAP_IPTYP:
-                       proto = ntohs(*(__be16 *)&buf[0]);
-                       p = &buf[2];
-                       break;
-               case ISDN_NET_ENCAP_ETHER:
-                       proto = ntohs(*(__be16 *)&buf[12]);
-                       p = &buf[14];
-                       break;
-               case ISDN_NET_ENCAP_CISCOHDLC:
-                       proto = ntohs(*(__be16 *)&buf[2]);
-                       p = &buf[4];
-                       break;
-#ifdef CONFIG_ISDN_PPP
-               case ISDN_NET_ENCAP_SYNCPPP:
-                       proto = ntohs(skb->protocol);
-                       p = &buf[IPPP_MAX_HEADER];
-                       break;
-#endif
-               }
-       }
-       data_ofs = ((p[0] & 15) * 4);
-       switch (proto) {
-       case ETH_P_IP:
-               switch (p[9]) {
-               case 1:
-                       strcpy(addinfo, " ICMP");
-                       break;
-               case 2:
-                       strcpy(addinfo, " IGMP");
-                       break;
-               case 4:
-                       strcpy(addinfo, " IPIP");
-                       break;
-               case 6:
-                       ipp = (ip_ports *) (&p[data_ofs]);
-                       sprintf(addinfo, " TCP, port: %d -> %d", ntohs(ipp->source),
-                               ntohs(ipp->dest));
-                       break;
-               case 8:
-                       strcpy(addinfo, " EGP");
-                       break;
-               case 12:
-                       strcpy(addinfo, " PUP");
-                       break;
-               case 17:
-                       ipp = (ip_ports *) (&p[data_ofs]);
-                       sprintf(addinfo, " UDP, port: %d -> %d", ntohs(ipp->source),
-                               ntohs(ipp->dest));
-                       break;
-               case 22:
-                       strcpy(addinfo, " IDP");
-                       break;
-               }
-               printk(KERN_INFO "OPEN: %pI4 -> %pI4%s\n",
-                      p + 12, p + 16, addinfo);
-               break;
-       case ETH_P_ARP:
-               printk(KERN_INFO "OPEN: ARP %pI4 -> *.*.*.* ?%pI4\n",
-                      p + 14, p + 24);
-               break;
-       }
-}
-
-/*
- * this function is used to send supervisory data, i.e. data which was
- * not received from the network layer, but e.g. frames from ipppd, CCP
- * reset frames etc.
- */
-void isdn_net_write_super(isdn_net_local *lp, struct sk_buff *skb)
-{
-       if (in_irq()) {
-               // we can't grab the lock from irq context,
-               // so we just queue the packet
-               skb_queue_tail(&lp->super_tx_queue, skb);
-               schedule_work(&lp->tqueue);
-               return;
-       }
-
-       spin_lock_bh(&lp->xmit_lock);
-       if (!isdn_net_lp_busy(lp)) {
-               isdn_net_writebuf_skb(lp, skb);
-       } else {
-               skb_queue_tail(&lp->super_tx_queue, skb);
-       }
-       spin_unlock_bh(&lp->xmit_lock);
-}
-
-/*
- * called from tq_immediate
- */
-static void isdn_net_softint(struct work_struct *work)
-{
-       isdn_net_local *lp = container_of(work, isdn_net_local, tqueue);
-       struct sk_buff *skb;
-
-       spin_lock_bh(&lp->xmit_lock);
-       while (!isdn_net_lp_busy(lp)) {
-               skb = skb_dequeue(&lp->super_tx_queue);
-               if (!skb)
-                       break;
-               isdn_net_writebuf_skb(lp, skb);
-       }
-       spin_unlock_bh(&lp->xmit_lock);
-}
-
-/*
- * all frames sent from the (net) LL to a HL driver should go via this function
- * it's serialized by the caller holding the lp->xmit_lock spinlock
- */
-void isdn_net_writebuf_skb(isdn_net_local *lp, struct sk_buff *skb)
-{
-       int ret;
-       int len = skb->len;     /* save len */
-
-       /* before obtaining the lock the caller should have checked that
-          the lp isn't busy */
-       if (isdn_net_lp_busy(lp)) {
-               printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__);
-               goto error;
-       }
-
-       if (!(lp->flags & ISDN_NET_CONNECTED)) {
-               printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__);
-               goto error;
-       }
-       ret = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb);
-       if (ret != len) {
-               /* we should never get here */
-               printk(KERN_WARNING "%s: HL driver queue full\n", lp->netdev->dev->name);
-               goto error;
-       }
-
-       lp->transcount += len;
-       isdn_net_inc_frame_cnt(lp);
-       return;
-
-error:
-       dev_kfree_skb(skb);
-       lp->stats.tx_errors++;
-
-}
-
-
-/*
- *  Helper function for isdn_net_start_xmit.
- *  When called, the connection is already established.
- *  Based on cps-calculation, check if device is overloaded.
- *  If so, and if a slave exists, trigger dialing for it.
- *  If any slave is online, deliver packets using a simple round robin
- *  scheme.
- *
- *  Return: 0 on success, !0 on failure.
- */
-
-static int
-isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb)
-{
-       isdn_net_dev *nd;
-       isdn_net_local *slp;
-       isdn_net_local *lp = netdev_priv(ndev);
-       int retv = NETDEV_TX_OK;
-
-       if (((isdn_net_local *) netdev_priv(ndev))->master) {
-               printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__);
-               dev_kfree_skb(skb);
-               return NETDEV_TX_OK;
-       }
-
-       /* For the other encaps the header has already been built */
-#ifdef CONFIG_ISDN_PPP
-       if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
-               return isdn_ppp_xmit(skb, ndev);
-       }
-#endif
-       nd = ((isdn_net_local *) netdev_priv(ndev))->netdev;
-       lp = isdn_net_get_locked_lp(nd);
-       if (!lp) {
-               printk(KERN_WARNING "%s: all channels busy - requeuing!\n", ndev->name);
-               return NETDEV_TX_BUSY;
-       }
-       /* we have our lp locked from now on */
-
-       /* Reset hangup-timeout */
-       lp->huptimer = 0; // FIXME?
-       isdn_net_writebuf_skb(lp, skb);
-       spin_unlock_bh(&lp->xmit_lock);
-
-       /* the following stuff is here for backwards compatibility.
-        * in future, start-up and hangup of slaves (based on current load)
-        * should move to userspace and get based on an overall cps
-        * calculation
-        */
-       if (lp->cps > lp->triggercps) {
-               if (lp->slave) {
-                       if (!lp->sqfull) {
-                               /* First time overload: set timestamp only */
-                               lp->sqfull = 1;
-                               lp->sqfull_stamp = jiffies;
-                       } else {
-                               /* subsequent overload: if slavedelay exceeded, start dialing */
-                               if (time_after(jiffies, lp->sqfull_stamp + lp->slavedelay)) {
-                                       slp = ISDN_SLAVE_PRIV(lp);
-                                       if (!(slp->flags & ISDN_NET_CONNECTED)) {
-                                               isdn_net_force_dial_lp(ISDN_SLAVE_PRIV(lp));
-                                       }
-                               }
-                       }
-               }
-       } else {
-               if (lp->sqfull && time_after(jiffies, lp->sqfull_stamp + lp->slavedelay + (10 * HZ))) {
-                       lp->sqfull = 0;
-               }
-               /* this is a hack to allow auto-hangup for slaves on moderate loads */
-               nd->queue = nd->local;
-       }
-
-       return retv;
-
-}
-
-static void
-isdn_net_adjust_hdr(struct sk_buff *skb, struct net_device *dev)
-{
-       isdn_net_local *lp = netdev_priv(dev);
-       if (!skb)
-               return;
-       if (lp->p_encap == ISDN_NET_ENCAP_ETHER) {
-               const int pullsize = skb_network_offset(skb) - ETH_HLEN;
-               if (pullsize > 0) {
-                       printk(KERN_DEBUG "isdn_net: Pull junk %d\n", pullsize);
-                       skb_pull(skb, pullsize);
-               }
-       }
-}
-
-
-static void isdn_net_tx_timeout(struct net_device *ndev)
-{
-       isdn_net_local *lp = netdev_priv(ndev);
-
-       printk(KERN_WARNING "isdn_tx_timeout dev %s dialstate %d\n", ndev->name, lp->dialstate);
-       if (!lp->dialstate) {
-               lp->stats.tx_errors++;
-               /*
-                * There is a certain probability that this currently
-                * works at all because if we always wake up the interface,
-                * then upper layer will try to send the next packet
-                * immediately. And then, the old clean_up logic in the
-                * driver will hopefully continue to work as it used to do.
-                *
-                * This is rather primitive right know, we better should
-                * clean internal queues here, in particular for multilink and
-                * ppp, and reset HL driver's channel, too.   --HE
-                *
-                * actually, this may not matter at all, because ISDN hardware
-                * should not see transmitter hangs at all IMO
-                * changed KERN_DEBUG to KERN_WARNING to find out if this is
-                * ever called   --KG
-                */
-       }
-       netif_trans_update(ndev);
-       netif_wake_queue(ndev);
-}
-
-/*
- * Try sending a packet.
- * If this interface isn't connected to a ISDN-Channel, find a free channel,
- * and start dialing.
- */
-static netdev_tx_t
-isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
-{
-       isdn_net_local *lp = netdev_priv(ndev);
-#ifdef CONFIG_ISDN_X25
-       struct concap_proto *cprot = lp->netdev->cprot;
-/* At this point hard_start_xmit() passes control to the encapsulation
-   protocol (if present).
-   For X.25 auto-dialing is completly bypassed because:
-   - It does not conform with the semantics of a reliable datalink
-   service as needed by X.25 PLP.
-   - I don't want that the interface starts dialing when the network layer
-   sends a message which requests to disconnect the lapb link (or if it
-   sends any other message not resulting in data transmission).
-   Instead, dialing will be initiated by the encapsulation protocol entity
-   when a dl_establish request is received from the upper layer.
-*/
-       if (cprot && cprot->pops) {
-               int ret = cprot->pops->encap_and_xmit(cprot, skb);
-
-               if (ret)
-                       netif_stop_queue(ndev);
-               return ret;
-       } else
-#endif
-               /* auto-dialing xmit function */
-       {
-#ifdef ISDN_DEBUG_NET_DUMP
-               u_char *buf;
-#endif
-               isdn_net_adjust_hdr(skb, ndev);
-#ifdef ISDN_DEBUG_NET_DUMP
-               buf = skb->data;
-               isdn_dumppkt("S:", buf, skb->len, 40);
-#endif
-
-               if (!(lp->flags & ISDN_NET_CONNECTED)) {
-                       int chi;
-                       /* only do autodial if allowed by config */
-                       if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) {
-                               isdn_net_unreachable(ndev, skb, "dial rejected: interface not in dialmode `auto'");
-                               dev_kfree_skb(skb);
-                               return NETDEV_TX_OK;
-                       }
-                       if (lp->phone[1]) {
-                               ulong flags;
-
-                               if (lp->dialwait_timer <= 0)
-                                       if (lp->dialstarted > 0 && lp->dialtimeout > 0 && time_before(jiffies, lp->dialstarted + lp->dialtimeout + lp->dialwait))
-                                               lp->dialwait_timer = lp->dialstarted + lp->dialtimeout + lp->dialwait;
-
-                               if (lp->dialwait_timer > 0) {
-                                       if (time_before(jiffies, lp->dialwait_timer)) {
-                                               isdn_net_unreachable(ndev, skb, "dial rejected: retry-time not reached");
-                                               dev_kfree_skb(skb);
-                                               return NETDEV_TX_OK;
-                                       } else
-                                               lp->dialwait_timer = 0;
-                               }
-                               /* Grab a free ISDN-Channel */
-                               spin_lock_irqsave(&dev->lock, flags);
-                               if (((chi =
-                                     isdn_get_free_channel(
-                                             ISDN_USAGE_NET,
-                                             lp->l2_proto,
-                                             lp->l3_proto,
-                                             lp->pre_device,
-                                             lp->pre_channel,
-                                             lp->msn)
-                                            ) < 0) &&
-                                   ((chi =
-                                     isdn_get_free_channel(
-                                             ISDN_USAGE_NET,
-                                             lp->l2_proto,
-                                             lp->l3_proto,
-                                             lp->pre_device,
-                                             lp->pre_channel^1,
-                                             lp->msn)
-                                           ) < 0)) {
-                                       spin_unlock_irqrestore(&dev->lock, flags);
-                                       isdn_net_unreachable(ndev, skb,
-                                                            "No channel");
-                                       dev_kfree_skb(skb);
-                                       return NETDEV_TX_OK;
-                               }
-                               /* Log packet, which triggered dialing */
-                               if (dev->net_verbose)
-                                       isdn_net_log_skb(skb, lp);
-                               lp->dialstate = 1;
-                               /* Connect interface with channel */
-                               isdn_net_bind_channel(lp, chi);
-#ifdef CONFIG_ISDN_PPP
-                               if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
-                                       /* no 'first_skb' handling for syncPPP */
-                                       if (isdn_ppp_bind(lp) < 0) {
-                                               dev_kfree_skb(skb);
-                                               isdn_net_unbind_channel(lp);
-                                               spin_unlock_irqrestore(&dev->lock, flags);
-                                               return NETDEV_TX_OK;    /* STN (skb to nirvana) ;) */
-                                       }
-#ifdef CONFIG_IPPP_FILTER
-                                       if (isdn_ppp_autodial_filter(skb, lp)) {
-                                               isdn_ppp_free(lp);
-                                               isdn_net_unbind_channel(lp);
-                                               spin_unlock_irqrestore(&dev->lock, flags);
-                                               isdn_net_unreachable(ndev, skb, "dial rejected: packet filtered");
-                                               dev_kfree_skb(skb);
-                                               return NETDEV_TX_OK;
-                                       }
-#endif
-                                       spin_unlock_irqrestore(&dev->lock, flags);
-                                       isdn_net_dial();        /* Initiate dialing */
-                                       netif_stop_queue(ndev);
-                                       return NETDEV_TX_BUSY;  /* let upper layer requeue skb packet */
-                               }
-#endif
-                               /* Initiate dialing */
-                               spin_unlock_irqrestore(&dev->lock, flags);
-                               isdn_net_dial();
-                               isdn_net_device_stop_queue(lp);
-                               return NETDEV_TX_BUSY;
-                       } else {
-                               isdn_net_unreachable(ndev, skb,
-                                                    "No phone number");
-                               dev_kfree_skb(skb);
-                               return NETDEV_TX_OK;
-                       }
-               } else {
-                       /* Device is connected to an ISDN channel */
-                       netif_trans_update(ndev);
-                       if (!lp->dialstate) {
-                               /* ISDN connection is established, try sending */
-                               int ret;
-                               ret = (isdn_net_xmit(ndev, skb));
-                               if (ret) netif_stop_queue(ndev);
-                               return ret;
-                       } else
-                               netif_stop_queue(ndev);
-               }
-       }
-       return NETDEV_TX_BUSY;
-}
-
-/*
- * Shutdown a net-interface.
- */
-static int
-isdn_net_close(struct net_device *dev)
-{
-       struct net_device *p;
-#ifdef CONFIG_ISDN_X25
-       struct concap_proto *cprot =
-               ((isdn_net_local *)netdev_priv(dev))->netdev->cprot;
-       /* printk(KERN_DEBUG "isdn_net_close %s\n" , dev-> name); */
-#endif
-
-#ifdef CONFIG_ISDN_X25
-       if (cprot && cprot->pops) cprot->pops->close(cprot);
-#endif
-       netif_stop_queue(dev);
-       p = MASTER_TO_SLAVE(dev);
-       if (p) {
-               /* If this interface has slaves, stop them also */
-               while (p) {
-#ifdef CONFIG_ISDN_X25
-                       cprot = ((isdn_net_local *)netdev_priv(p))
-                               ->netdev->cprot;
-                       if (cprot && cprot->pops)
-                               cprot->pops->close(cprot);
-#endif
-                       isdn_net_hangup(p);
-                       p = MASTER_TO_SLAVE(p);
-               }
-       }
-       isdn_net_hangup(dev);
-       isdn_unlock_drivers();
-       return 0;
-}
-
-/*
- * Get statistics
- */
-static struct net_device_stats *
-isdn_net_get_stats(struct net_device *dev)
-{
-       isdn_net_local *lp = netdev_priv(dev);
-       return &lp->stats;
-}
-
-/*      This is simply a copy from std. eth.c EXCEPT we pull ETH_HLEN
- *      instead of dev->hard_header_len off. This is done because the
- *      lowlevel-driver has already pulled off its stuff when we get
- *      here and this routine only gets called with p_encap == ETHER.
- *      Determine the packet's protocol ID. The rule here is that we
- *      assume 802.3 if the type field is short enough to be a length.
- *      This is normal practice and works for any 'now in use' protocol.
- */
-
-static __be16
-isdn_net_type_trans(struct sk_buff *skb, struct net_device *dev)
-{
-       struct ethhdr *eth;
-       unsigned char *rawp;
-
-       skb_reset_mac_header(skb);
-       skb_pull(skb, ETH_HLEN);
-       eth = eth_hdr(skb);
-
-       if (*eth->h_dest & 1) {
-               if (ether_addr_equal(eth->h_dest, dev->broadcast))
-                       skb->pkt_type = PACKET_BROADCAST;
-               else
-                       skb->pkt_type = PACKET_MULTICAST;
-       }
-       /*
-        *      This ALLMULTI check should be redundant by 1.4
-        *      so don't forget to remove it.
-        */
-
-       else if (dev->flags & (IFF_PROMISC /*| IFF_ALLMULTI*/)) {
-               if (!ether_addr_equal(eth->h_dest, dev->dev_addr))
-                       skb->pkt_type = PACKET_OTHERHOST;
-       }
-       if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN)
-               return eth->h_proto;
-
-       rawp = skb->data;
-
-       /*
-        *      This is a magic hack to spot IPX packets. Older Novell breaks
-        *      the protocol design and runs IPX over 802.3 without an 802.2 LLC
-        *      layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
-        *      won't work for fault tolerant netware but does for the rest.
-        */
-       if (*(unsigned short *) rawp == 0xFFFF)
-               return htons(ETH_P_802_3);
-       /*
-        *      Real 802.2 LLC
-        */
-       return htons(ETH_P_802_2);
-}
-
-
-/*
- * CISCO HDLC keepalive specific stuff
- */
-static struct sk_buff*
-isdn_net_ciscohdlck_alloc_skb(isdn_net_local *lp, int len)
-{
-       unsigned short hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen;
-       struct sk_buff *skb;
-
-       skb = alloc_skb(hl + len, GFP_ATOMIC);
-       if (skb)
-               skb_reserve(skb, hl);
-       else
-               printk("isdn out of mem at %s:%d!\n", __FILE__, __LINE__);
-       return skb;
-}
-
-/* cisco hdlck device private ioctls */
-static int
-isdn_ciscohdlck_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-       isdn_net_local *lp = netdev_priv(dev);
-       unsigned long len = 0;
-       unsigned long expires = 0;
-       int tmp = 0;
-       int period = lp->cisco_keepalive_period;
-       s8 debserint = lp->cisco_debserint;
-       int rc = 0;
-
-       if (lp->p_encap != ISDN_NET_ENCAP_CISCOHDLCK)
-               return -EINVAL;
-
-       switch (cmd) {
-               /* get/set keepalive period */
-       case SIOCGKEEPPERIOD:
-               len = (unsigned long)sizeof(lp->cisco_keepalive_period);
-               if (copy_to_user(ifr->ifr_data,
-                                &lp->cisco_keepalive_period, len))
-                       rc = -EFAULT;
-               break;
-       case SIOCSKEEPPERIOD:
-               tmp = lp->cisco_keepalive_period;
-               len = (unsigned long)sizeof(lp->cisco_keepalive_period);
-               if (copy_from_user(&period, ifr->ifr_data, len))
-                       rc = -EFAULT;
-               if ((period > 0) && (period <= 32767))
-                       lp->cisco_keepalive_period = period;
-               else
-                       rc = -EINVAL;
-               if (!rc && (tmp != lp->cisco_keepalive_period)) {
-                       expires = (unsigned long)(jiffies +
-                                                 lp->cisco_keepalive_period * HZ);
-                       mod_timer(&lp->cisco_timer, expires);
-                       printk(KERN_INFO "%s: Keepalive period set "
-                              "to %d seconds.\n",
-                              dev->name, lp->cisco_keepalive_period);
-               }
-               break;
-
-               /* get/set debugging */
-       case SIOCGDEBSERINT:
-               len = (unsigned long)sizeof(lp->cisco_debserint);
-               if (copy_to_user(ifr->ifr_data,
-                                &lp->cisco_debserint, len))
-                       rc = -EFAULT;
-               break;
-       case SIOCSDEBSERINT:
-               len = (unsigned long)sizeof(lp->cisco_debserint);
-               if (copy_from_user(&debserint,
-                                  ifr->ifr_data, len))
-                       rc = -EFAULT;
-               if ((debserint >= 0) && (debserint <= 64))
-                       lp->cisco_debserint = debserint;
-               else
-                       rc = -EINVAL;
-               break;
-
-       default:
-               rc = -EINVAL;
-               break;
-       }
-       return (rc);
-}
-
-
-static int isdn_net_ioctl(struct net_device *dev,
-                         struct ifreq *ifr, int cmd)
-{
-       isdn_net_local *lp = netdev_priv(dev);
-
-       switch (lp->p_encap) {
-#ifdef CONFIG_ISDN_PPP
-       case ISDN_NET_ENCAP_SYNCPPP:
-               return isdn_ppp_dev_ioctl(dev, ifr, cmd);
-#endif
-       case ISDN_NET_ENCAP_CISCOHDLCK:
-               return isdn_ciscohdlck_dev_ioctl(dev, ifr, cmd);
-       default:
-               return -EINVAL;
-       }
-}
-
-/* called via cisco_timer.function */
-static void
-isdn_net_ciscohdlck_slarp_send_keepalive(struct timer_list *t)
-{
-       isdn_net_local *lp = from_timer(lp, t, cisco_timer);
-       struct sk_buff *skb;
-       unsigned char *p;
-       unsigned long last_cisco_myseq = lp->cisco_myseq;
-       int myseq_diff = 0;
-
-       if (!(lp->flags & ISDN_NET_CONNECTED) || lp->dialstate) {
-               printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__);
-               return;
-       }
-       lp->cisco_myseq++;
-
-       myseq_diff = (lp->cisco_myseq - lp->cisco_mineseen);
-       if ((lp->cisco_line_state) && ((myseq_diff >= 3) || (myseq_diff <= -3))) {
-               /* line up -> down */
-               lp->cisco_line_state = 0;
-               printk(KERN_WARNING
-                      "UPDOWN: Line protocol on Interface %s,"
-                      " changed state to down\n", lp->netdev->dev->name);
-               /* should stop routing higher-level data across */
-       } else if ((!lp->cisco_line_state) &&
-                  (myseq_diff >= 0) && (myseq_diff <= 2)) {
-               /* line down -> up */
-               lp->cisco_line_state = 1;
-               printk(KERN_WARNING
-                      "UPDOWN: Line protocol on Interface %s,"
-                      " changed state to up\n", lp->netdev->dev->name);
-               /* restart routing higher-level data across */
-       }
-
-       if (lp->cisco_debserint)
-               printk(KERN_DEBUG "%s: HDLC "
-                      "myseq %lu, mineseen %lu%c, yourseen %lu, %s\n",
-                      lp->netdev->dev->name, last_cisco_myseq, lp->cisco_mineseen,
-                      ((last_cisco_myseq == lp->cisco_mineseen) ? '*' : 040),
-                      lp->cisco_yourseq,
-                      ((lp->cisco_line_state) ? "line up" : "line down"));
-
-       skb = isdn_net_ciscohdlck_alloc_skb(lp, 4 + 14);
-       if (!skb)
-               return;
-
-       p = skb_put(skb, 4 + 14);
-
-       /* cisco header */
-       *(u8 *)(p + 0) = CISCO_ADDR_UNICAST;
-       *(u8 *)(p + 1) = CISCO_CTRL;
-       *(__be16 *)(p + 2) = cpu_to_be16(CISCO_TYPE_SLARP);
-
-       /* slarp keepalive */
-       *(__be32 *)(p +  4) = cpu_to_be32(CISCO_SLARP_KEEPALIVE);
-       *(__be32 *)(p +  8) = cpu_to_be32(lp->cisco_myseq);
-       *(__be32 *)(p + 12) = cpu_to_be32(lp->cisco_yourseq);
-       *(__be16 *)(p + 16) = cpu_to_be16(0xffff); // reliability, always 0xffff
-       p += 18;
-
-       isdn_net_write_super(lp, skb);
-
-       lp->cisco_timer.expires = jiffies + lp->cisco_keepalive_period * HZ;
-
-       add_timer(&lp->cisco_timer);
-}
-
-static void
-isdn_net_ciscohdlck_slarp_send_request(isdn_net_local *lp)
-{
-       struct sk_buff *skb;
-       unsigned char *p;
-
-       skb = isdn_net_ciscohdlck_alloc_skb(lp, 4 + 14);
-       if (!skb)
-               return;
-
-       p = skb_put(skb, 4 + 14);
-
-       /* cisco header */
-       *(u8 *)(p + 0) = CISCO_ADDR_UNICAST;
-       *(u8 *)(p + 1) = CISCO_CTRL;
-       *(__be16 *)(p + 2) = cpu_to_be16(CISCO_TYPE_SLARP);
-
-       /* slarp request */
-       *(__be32 *)(p +  4) = cpu_to_be32(CISCO_SLARP_REQUEST);
-       *(__be32 *)(p +  8) = cpu_to_be32(0); // address
-       *(__be32 *)(p + 12) = cpu_to_be32(0); // netmask
-       *(__be16 *)(p + 16) = cpu_to_be16(0); // unused
-       p += 18;
-
-       isdn_net_write_super(lp, skb);
-}
-
-static void
-isdn_net_ciscohdlck_connected(isdn_net_local *lp)
-{
-       lp->cisco_myseq = 0;
-       lp->cisco_mineseen = 0;
-       lp->cisco_yourseq = 0;
-       lp->cisco_keepalive_period = ISDN_TIMER_KEEPINT;
-       lp->cisco_last_slarp_in = 0;
-       lp->cisco_line_state = 0;
-       lp->cisco_debserint = 0;
-
-       /* send slarp request because interface/seq.no.s reset */
-       isdn_net_ciscohdlck_slarp_send_request(lp);
-
-       timer_setup(&lp->cisco_timer,
-                   isdn_net_ciscohdlck_slarp_send_keepalive, 0);
-       lp->cisco_timer.expires = jiffies + lp->cisco_keepalive_period * HZ;
-       add_timer(&lp->cisco_timer);
-}
-
-static void
-isdn_net_ciscohdlck_disconnected(isdn_net_local *lp)
-{
-       del_timer(&lp->cisco_timer);
-}
-
-static void
-isdn_net_ciscohdlck_slarp_send_reply(isdn_net_local *lp)
-{
-       struct sk_buff *skb;
-       unsigned char *p;
-       struct in_device *in_dev = NULL;
-       __be32 addr = 0;                /* local ipv4 address */
-       __be32 mask = 0;                /* local netmask */
-
-       if ((in_dev = lp->netdev->dev->ip_ptr) != NULL) {
-               /* take primary(first) address of interface */
-               struct in_ifaddr *ifa = in_dev->ifa_list;
-               if (ifa != NULL) {
-                       addr = ifa->ifa_local;
-                       mask = ifa->ifa_mask;
-               }
-       }
-
-       skb = isdn_net_ciscohdlck_alloc_skb(lp, 4 + 14);
-       if (!skb)
-               return;
-
-       p = skb_put(skb, 4 + 14);
-
-       /* cisco header */
-       *(u8 *)(p + 0) = CISCO_ADDR_UNICAST;
-       *(u8 *)(p + 1) = CISCO_CTRL;
-       *(__be16 *)(p + 2) = cpu_to_be16(CISCO_TYPE_SLARP);
-
-       /* slarp reply, send own ip/netmask; if values are nonsense remote
-        * should think we are unable to provide it with an address via SLARP */
-       *(__be32 *)(p +  4) = cpu_to_be32(CISCO_SLARP_REPLY);
-       *(__be32 *)(p +  8) = addr; // address
-       *(__be32 *)(p + 12) = mask; // netmask
-       *(__be16 *)(p + 16) = cpu_to_be16(0); // unused
-       p += 18;
-
-       isdn_net_write_super(lp, skb);
-}
-
-static void
-isdn_net_ciscohdlck_slarp_in(isdn_net_local *lp, struct sk_buff *skb)
-{
-       unsigned char *p;
-       int period;
-       u32 code;
-       u32 my_seq;
-       u32 your_seq;
-       __be32 local;
-       __be32 *addr, *mask;
-
-       if (skb->len < 14)
-               return;
-
-       p = skb->data;
-       code = be32_to_cpup((__be32 *)p);
-       p += 4;
-
-       switch (code) {
-       case CISCO_SLARP_REQUEST:
-               lp->cisco_yourseq = 0;
-               isdn_net_ciscohdlck_slarp_send_reply(lp);
-               break;
-       case CISCO_SLARP_REPLY:
-               addr = (__be32 *)p;
-               mask = (__be32 *)(p + 4);
-               if (*mask != cpu_to_be32(0xfffffffc))
-                       goto slarp_reply_out;
-               if ((*addr & cpu_to_be32(3)) == cpu_to_be32(0) ||
-                   (*addr & cpu_to_be32(3)) == cpu_to_be32(3))
-                       goto slarp_reply_out;
-               local = *addr ^ cpu_to_be32(3);
-               printk(KERN_INFO "%s: got slarp reply: remote ip: %pI4, local ip: %pI4 mask: %pI4\n",
-                      lp->netdev->dev->name, addr, &local, mask);
-               break;
-       slarp_reply_out:
-               printk(KERN_INFO "%s: got invalid slarp reply (%pI4/%pI4) - ignored\n",
-                      lp->netdev->dev->name, addr, mask);
-               break;
-       case CISCO_SLARP_KEEPALIVE:
-               period = (int)((jiffies - lp->cisco_last_slarp_in
-                               + HZ / 2 - 1) / HZ);
-               if (lp->cisco_debserint &&
-                   (period != lp->cisco_keepalive_period) &&
-                   lp->cisco_last_slarp_in) {
-                       printk(KERN_DEBUG "%s: Keepalive period mismatch - "
-                              "is %d but should be %d.\n",
-                              lp->netdev->dev->name, period,
-                              lp->cisco_keepalive_period);
-               }
-               lp->cisco_last_slarp_in = jiffies;
-               my_seq = be32_to_cpup((__be32 *)(p + 0));
-               your_seq = be32_to_cpup((__be32 *)(p + 4));
-               p += 10;
-               lp->cisco_yourseq = my_seq;
-               lp->cisco_mineseen = your_seq;
-               break;
-       }
-}
-
-static void
-isdn_net_ciscohdlck_receive(isdn_net_local *lp, struct sk_buff *skb)
-{
-       unsigned char *p;
-       u8 addr;
-       u8 ctrl;
-       u16 type;
-
-       if (skb->len < 4)
-               goto out_free;
-
-       p = skb->data;
-       addr = *(u8 *)(p + 0);
-       ctrl = *(u8 *)(p + 1);
-       type = be16_to_cpup((__be16 *)(p + 2));
-       p += 4;
-       skb_pull(skb, 4);
-
-       if (addr != CISCO_ADDR_UNICAST && addr != CISCO_ADDR_BROADCAST) {
-               printk(KERN_WARNING "%s: Unknown Cisco addr 0x%02x\n",
-                      lp->netdev->dev->name, addr);
-               goto out_free;
-       }
-       if (ctrl != CISCO_CTRL) {
-               printk(KERN_WARNING "%s: Unknown Cisco ctrl 0x%02x\n",
-                      lp->netdev->dev->name, ctrl);
-               goto out_free;
-       }
-
-       switch (type) {
-       case CISCO_TYPE_SLARP:
-               isdn_net_ciscohdlck_slarp_in(lp, skb);
-               goto out_free;
-       case CISCO_TYPE_CDP:
-               if (lp->cisco_debserint)
-                       printk(KERN_DEBUG "%s: Received CDP packet. use "
-                              "\"no cdp enable\" on cisco.\n",
-                              lp->netdev->dev->name);
-               goto out_free;
-       default:
-               /* no special cisco protocol */
-               skb->protocol = htons(type);
-               netif_rx(skb);
-               return;
-       }
-
-out_free:
-       kfree_skb(skb);
-}
-
-/*
- * Got a packet from ISDN-Channel.
- */
-static void
-isdn_net_receive(struct net_device *ndev, struct sk_buff *skb)
-{
-       isdn_net_local *lp = netdev_priv(ndev);
-       isdn_net_local *olp = lp;       /* original 'lp' */
-#ifdef CONFIG_ISDN_X25
-       struct concap_proto *cprot = lp->netdev->cprot;
-#endif
-       lp->transcount += skb->len;
-
-       lp->stats.rx_packets++;
-       lp->stats.rx_bytes += skb->len;
-       if (lp->master) {
-               /* Bundling: If device is a slave-device, deliver to master, also
-                * handle master's statistics and hangup-timeout
-                */
-               ndev = lp->master;
-               lp = netdev_priv(ndev);
-               lp->stats.rx_packets++;
-               lp->stats.rx_bytes += skb->len;
-       }
-       skb->dev = ndev;
-       skb->pkt_type = PACKET_HOST;
-       skb_reset_mac_header(skb);
-#ifdef ISDN_DEBUG_NET_DUMP
-       isdn_dumppkt("R:", skb->data, skb->len, 40);
-#endif
-       switch (lp->p_encap) {
-       case ISDN_NET_ENCAP_ETHER:
-               /* Ethernet over ISDN */
-               olp->huptimer = 0;
-               lp->huptimer = 0;
-               skb->protocol = isdn_net_type_trans(skb, ndev);
-               break;
-       case ISDN_NET_ENCAP_UIHDLC:
-               /* HDLC with UI-frame (for ispa with -h1 option) */
-               olp->huptimer = 0;
-               lp->huptimer = 0;
-               skb_pull(skb, 2);
-               /* Fall through */
-       case ISDN_NET_ENCAP_RAWIP:
-               /* RAW-IP without MAC-Header */
-               olp->huptimer = 0;
-               lp->huptimer = 0;
-               skb->protocol = htons(ETH_P_IP);
-               break;
-       case ISDN_NET_ENCAP_CISCOHDLCK:
-               isdn_net_ciscohdlck_receive(lp, skb);
-               return;
-       case ISDN_NET_ENCAP_CISCOHDLC:
-               /* CISCO-HDLC IP with type field and  fake I-frame-header */
-               skb_pull(skb, 2);
-               /* Fall through */
-       case ISDN_NET_ENCAP_IPTYP:
-               /* IP with type field */
-               olp->huptimer = 0;
-               lp->huptimer = 0;
-               skb->protocol = *(__be16 *)&(skb->data[0]);
-               skb_pull(skb, 2);
-               if (*(unsigned short *) skb->data == 0xFFFF)
-                       skb->protocol = htons(ETH_P_802_3);
-               break;
-#ifdef CONFIG_ISDN_PPP
-       case ISDN_NET_ENCAP_SYNCPPP:
-               /* huptimer is done in isdn_ppp_push_higher */
-               isdn_ppp_receive(lp->netdev, olp, skb);
-               return;
-#endif
-
-       default:
-#ifdef CONFIG_ISDN_X25
-               /* try if there are generic sync_device receiver routines */
-               if (cprot) if (cprot->pops)
-                                  if (cprot->pops->data_ind) {
-                                          cprot->pops->data_ind(cprot, skb);
-                                          return;
-                                  };
-#endif /* CONFIG_ISDN_X25 */
-               printk(KERN_WARNING "%s: unknown encapsulation, dropping\n",
-                      lp->netdev->dev->name);
-               kfree_skb(skb);
-               return;
-       }
-
-       netif_rx(skb);
-       return;
-}
-
-/*
- * A packet arrived via ISDN. Search interface-chain for a corresponding
- * interface. If found, deliver packet to receiver-function and return 1,
- * else return 0.
- */
-int
-isdn_net_rcv_skb(int idx, struct sk_buff *skb)
-{
-       isdn_net_dev *p = dev->rx_netdev[idx];
-
-       if (p) {
-               isdn_net_local *lp = p->local;
-               if ((lp->flags & ISDN_NET_CONNECTED) &&
-                   (!lp->dialstate)) {
-                       isdn_net_receive(p->dev, skb);
-                       return 1;
-               }
-       }
-       return 0;
-}
-
-/*
- *  build an header
- *  depends on encaps that is being used.
- */
-
-static int isdn_net_header(struct sk_buff *skb, struct net_device *dev,
-                          unsigned short type,
-                          const void *daddr, const void *saddr, unsigned plen)
-{
-       isdn_net_local *lp = netdev_priv(dev);
-       unsigned char *p;
-       int len = 0;
-
-       switch (lp->p_encap) {
-       case ISDN_NET_ENCAP_ETHER:
-               len = eth_header(skb, dev, type, daddr, saddr, plen);
-               break;
-#ifdef CONFIG_ISDN_PPP
-       case ISDN_NET_ENCAP_SYNCPPP:
-               /* stick on a fake header to keep fragmentation code happy. */
-               len = IPPP_MAX_HEADER;
-               skb_push(skb, len);
-               break;
-#endif
-       case ISDN_NET_ENCAP_RAWIP:
-               printk(KERN_WARNING "isdn_net_header called with RAW_IP!\n");
-               len = 0;
-               break;
-       case ISDN_NET_ENCAP_IPTYP:
-               /* ethernet type field */
-               *((__be16 *)skb_push(skb, 2)) = htons(type);
-               len = 2;
-               break;
-       case ISDN_NET_ENCAP_UIHDLC:
-               /* HDLC with UI-Frames (for ispa with -h1 option) */
-               *((__be16 *)skb_push(skb, 2)) = htons(0x0103);
-               len = 2;
-               break;
-       case ISDN_NET_ENCAP_CISCOHDLC:
-       case ISDN_NET_ENCAP_CISCOHDLCK:
-               p = skb_push(skb, 4);
-               *(u8 *)(p + 0) = CISCO_ADDR_UNICAST;
-               *(u8 *)(p + 1) = CISCO_CTRL;
-               *(__be16 *)(p + 2) = cpu_to_be16(type);
-               p += 4;
-               len = 4;
-               break;
-#ifdef CONFIG_ISDN_X25
-       default:
-               /* try if there are generic concap protocol routines */
-               if (lp->netdev->cprot) {
-                       printk(KERN_WARNING "isdn_net_header called with concap_proto!\n");
-                       len = 0;
-                       break;
-               }
-               break;
-#endif /* CONFIG_ISDN_X25 */
-       }
-       return len;
-}
-
-static int isdn_header_cache(const struct neighbour *neigh, struct hh_cache *hh,
-                            __be16 type)
-{
-       const struct net_device *dev = neigh->dev;
-       isdn_net_local *lp = netdev_priv(dev);
-
-       if (lp->p_encap == ISDN_NET_ENCAP_ETHER)
-               return eth_header_cache(neigh, hh, type);
-       return -1;
-}
-
-static void isdn_header_cache_update(struct hh_cache *hh,
-                                    const struct net_device *dev,
-                                    const unsigned char *haddr)
-{
-       isdn_net_local *lp = netdev_priv(dev);
-       if (lp->p_encap == ISDN_NET_ENCAP_ETHER)
-               eth_header_cache_update(hh, dev, haddr);
-}
-
-static const struct header_ops isdn_header_ops = {
-       .create = isdn_net_header,
-       .cache = isdn_header_cache,
-       .cache_update = isdn_header_cache_update,
-};
-
-/*
- * Interface-setup. (just after registering a new interface)
- */
-static int
-isdn_net_init(struct net_device *ndev)
-{
-       ushort max_hlhdr_len = 0;
-       int drvidx;
-
-       /*
-        *  up till binding we ask the protocol layer to reserve as much
-        *  as we might need for HL layer
-        */
-
-       for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++)
-               if (dev->drv[drvidx])
-                       if (max_hlhdr_len < dev->drv[drvidx]->interface->hl_hdrlen)
-                               max_hlhdr_len = dev->drv[drvidx]->interface->hl_hdrlen;
-
-       ndev->hard_header_len = ETH_HLEN + max_hlhdr_len;
-       return 0;
-}
-
-static void
-isdn_net_swapbind(int drvidx)
-{
-       isdn_net_dev *p;
-
-#ifdef ISDN_DEBUG_NET_ICALL
-       printk(KERN_DEBUG "n_fi: swapping ch of %d\n", drvidx);
-#endif
-       p = dev->netdev;
-       while (p) {
-               if (p->local->pre_device == drvidx)
-                       switch (p->local->pre_channel) {
-                       case 0:
-                               p->local->pre_channel = 1;
-                               break;
-                       case 1:
-                               p->local->pre_channel = 0;
-                               break;
-                       }
-               p = (isdn_net_dev *) p->next;
-       }
-}
-
-static void
-isdn_net_swap_usage(int i1, int i2)
-{
-       int u1 = dev->usage[i1] & ISDN_USAGE_EXCLUSIVE;
-       int u2 = dev->usage[i2] & ISDN_USAGE_EXCLUSIVE;
-
-#ifdef ISDN_DEBUG_NET_ICALL
-       printk(KERN_DEBUG "n_fi: usage of %d and %d\n", i1, i2);
-#endif
-       dev->usage[i1] &= ~ISDN_USAGE_EXCLUSIVE;
-       dev->usage[i1] |= u2;
-       dev->usage[i2] &= ~ISDN_USAGE_EXCLUSIVE;
-       dev->usage[i2] |= u1;
-       isdn_info_update();
-}
-
-/*
- * An incoming call-request has arrived.
- * Search the interface-chain for an appropriate interface.
- * If found, connect the interface to the ISDN-channel and initiate
- * D- and B-Channel-setup. If secure-flag is set, accept only
- * configured phone-numbers. If callback-flag is set, initiate
- * callback-dialing.
- *
- * Return-Value: 0 = No appropriate interface for this call.
- *               1 = Call accepted
- *               2 = Reject call, wait cbdelay, then call back
- *               3 = Reject call
- *               4 = Wait cbdelay, then call back
- *               5 = No appropriate interface for this call,
- *                   would eventually match if CID was longer.
- */
-
-int
-isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
-{
-       char *eaz;
-       int si1;
-       int si2;
-       int ematch;
-       int wret;
-       int swapped;
-       int sidx = 0;
-       u_long flags;
-       isdn_net_dev *p;
-       isdn_net_phone *n;
-       char nr[ISDN_MSNLEN];
-       char *my_eaz;
-
-       /* Search name in netdev-chain */
-       if (!setup->phone[0]) {
-               nr[0] = '0';
-               nr[1] = '\0';
-               printk(KERN_INFO "isdn_net: Incoming call without OAD, assuming '0'\n");
-       } else
-               strlcpy(nr, setup->phone, ISDN_MSNLEN);
-       si1 = (int) setup->si1;
-       si2 = (int) setup->si2;
-       if (!setup->eazmsn[0]) {
-               printk(KERN_WARNING "isdn_net: Incoming call without CPN, assuming '0'\n");
-               eaz = "0";
-       } else
-               eaz = setup->eazmsn;
-       if (dev->net_verbose > 1)
-               printk(KERN_INFO "isdn_net: call from %s,%d,%d -> %s\n", nr, si1, si2, eaz);
-       /* Accept DATA and VOICE calls at this stage
-        * local eaz is checked later for allowed call types
-        */
-       if ((si1 != 7) && (si1 != 1)) {
-               if (dev->net_verbose > 1)
-                       printk(KERN_INFO "isdn_net: Service-Indicator not 1 or 7, ignored\n");
-               return 0;
-       }
-       n = (isdn_net_phone *) 0;
-       p = dev->netdev;
-       ematch = wret = swapped = 0;
-#ifdef ISDN_DEBUG_NET_ICALL
-       printk(KERN_DEBUG "n_fi: di=%d ch=%d idx=%d usg=%d\n", di, ch, idx,
-              dev->usage[idx]);
-#endif
-       while (p) {
-               int matchret;
-               isdn_net_local *lp = p->local;
-
-               /* If last check has triggered as binding-swap, revert it */
-               switch (swapped) {
-               case 2:
-                       isdn_net_swap_usage(idx, sidx);
-                       /* fall through */
-               case 1:
-                       isdn_net_swapbind(di);
-                       break;
-               }
-               swapped = 0;
-               /* check acceptable call types for DOV */
-               my_eaz = isdn_map_eaz2msn(lp->msn, di);
-               if (si1 == 1) { /* it's a DOV call, check if we allow it */
-                       if (*my_eaz == 'v' || *my_eaz == 'V' ||
-                           *my_eaz == 'b' || *my_eaz == 'B')
-                               my_eaz++; /* skip to allow a match */
-                       else
-                               my_eaz = NULL; /* force non match */
-               } else { /* it's a DATA call, check if we allow it */
-                       if (*my_eaz == 'b' || *my_eaz == 'B')
-                               my_eaz++; /* skip to allow a match */
-               }
-               if (my_eaz)
-                       matchret = isdn_msncmp(eaz, my_eaz);
-               else
-                       matchret = 1;
-               if (!matchret)
-                       ematch = 1;
-
-               /* Remember if more numbers eventually can match */
-               if (matchret > wret)
-                       wret = matchret;
-#ifdef ISDN_DEBUG_NET_ICALL
-               printk(KERN_DEBUG "n_fi: if='%s', l.msn=%s, l.flags=%d, l.dstate=%d\n",
-                      p->dev->name, lp->msn, lp->flags, lp->dialstate);
-#endif
-               if ((!matchret) &&                                        /* EAZ is matching   */
-                   (((!(lp->flags & ISDN_NET_CONNECTED)) &&              /* but not connected */
-                     (USG_NONE(dev->usage[idx]))) ||                     /* and ch. unused or */
-                    ((((lp->dialstate == 4) || (lp->dialstate == 12)) && /* if dialing        */
-                      (!(lp->flags & ISDN_NET_CALLBACK)))                /* but no callback   */
-                            )))
-               {
-#ifdef ISDN_DEBUG_NET_ICALL
-                       printk(KERN_DEBUG "n_fi: match1, pdev=%d pch=%d\n",
-                              lp->pre_device, lp->pre_channel);
-#endif
-                       if (dev->usage[idx] & ISDN_USAGE_EXCLUSIVE) {
-                               if ((lp->pre_channel != ch) ||
-                                   (lp->pre_device != di)) {
-                                       /* Here we got a problem:
-                                        * If using an ICN-Card, an incoming call is always signaled on
-                                        * on the first channel of the card, if both channels are
-                                        * down. However this channel may be bound exclusive. If the
-                                        * second channel is free, this call should be accepted.
-                                        * The solution is horribly but it runs, so what:
-                                        * We exchange the exclusive bindings of the two channels, the
-                                        * corresponding variables in the interface-structs.
-                                        */
-                                       if (ch == 0) {
-                                               sidx = isdn_dc2minor(di, 1);
-#ifdef ISDN_DEBUG_NET_ICALL
-                                               printk(KERN_DEBUG "n_fi: ch is 0\n");
-#endif
-                                               if (USG_NONE(dev->usage[sidx])) {
-                                                       /* Second Channel is free, now see if it is bound
-                                                        * exclusive too. */
-                                                       if (dev->usage[sidx] & ISDN_USAGE_EXCLUSIVE) {
-#ifdef ISDN_DEBUG_NET_ICALL
-                                                               printk(KERN_DEBUG "n_fi: 2nd channel is down and bound\n");
-#endif
-                                                               /* Yes, swap bindings only, if the original
-                                                                * binding is bound to channel 1 of this driver */
-                                                               if ((lp->pre_device == di) &&
-                                                                   (lp->pre_channel == 1)) {
-                                                                       isdn_net_swapbind(di);
-                                                                       swapped = 1;
-                                                               } else {
-                                                                       /* ... else iterate next device */
-                                                                       p = (isdn_net_dev *) p->next;
-                                                                       continue;
-                                                               }
-                                                       } else {
-#ifdef ISDN_DEBUG_NET_ICALL
-                                                               printk(KERN_DEBUG "n_fi: 2nd channel is down and unbound\n");
-#endif
-                                                               /* No, swap always and swap excl-usage also */
-                                                               isdn_net_swap_usage(idx, sidx);
-                                                               isdn_net_swapbind(di);
-                                                               swapped = 2;
-                                                       }
-                                                       /* Now check for exclusive binding again */
-#ifdef ISDN_DEBUG_NET_ICALL
-                                                       printk(KERN_DEBUG "n_fi: final check\n");
-#endif
-                                                       if ((dev->usage[idx] & ISDN_USAGE_EXCLUSIVE) &&
-                                                           ((lp->pre_channel != ch) ||
-                                                            (lp->pre_device != di))) {
-#ifdef ISDN_DEBUG_NET_ICALL
-                                                               printk(KERN_DEBUG "n_fi: final check failed\n");
-#endif
-                                                               p = (isdn_net_dev *) p->next;
-                                                               continue;
-                                                       }
-                                               }
-                                       } else {
-                                               /* We are already on the second channel, so nothing to do */
-#ifdef ISDN_DEBUG_NET_ICALL
-                                               printk(KERN_DEBUG "n_fi: already on 2nd channel\n");
-#endif
-                                       }
-                               }
-                       }
-#ifdef ISDN_DEBUG_NET_ICALL
-                       printk(KERN_DEBUG "n_fi: match2\n");
-#endif
-                       n = lp->phone[0];
-                       if (lp->flags & ISDN_NET_SECURE) {
-                               while (n) {
-                                       if (!isdn_msncmp(nr, n->num))
-                                               break;
-                                       n = (isdn_net_phone *) n->next;
-                               }
-                       }
-                       if (n || (!(lp->flags & ISDN_NET_SECURE))) {
-#ifdef ISDN_DEBUG_NET_ICALL
-                               printk(KERN_DEBUG "n_fi: match3\n");
-#endif
-                               /* matching interface found */
-
-                               /*
-                                * Is the state STOPPED?
-                                * If so, no dialin is allowed,
-                                * so reject actively.
-                                * */
-                               if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) {
-                                       printk(KERN_INFO "incoming call, interface %s `stopped' -> rejected\n",
-                                              p->dev->name);
-                                       return 3;
-                               }
-                               /*
-                                * Is the interface up?
-                                * If not, reject the call actively.
-                                */
-                               if (!isdn_net_device_started(p)) {
-                                       printk(KERN_INFO "%s: incoming call, interface down -> rejected\n",
-                                              p->dev->name);
-                                       return 3;
-                               }
-                               /* Interface is up, now see if it's a slave. If so, see if
-                                * it's master and parent slave is online. If not, reject the call.
-                                */
-                               if (lp->master) {
-                                       isdn_net_local *mlp = ISDN_MASTER_PRIV(lp);
-                                       printk(KERN_DEBUG "ICALLslv: %s\n", p->dev->name);
-                                       printk(KERN_DEBUG "master=%s\n", lp->master->name);
-                                       if (mlp->flags & ISDN_NET_CONNECTED) {
-                                               printk(KERN_DEBUG "master online\n");
-                                               /* Master is online, find parent-slave (master if first slave) */
-                                               while (mlp->slave) {
-                                                       if (ISDN_SLAVE_PRIV(mlp) == lp)
-                                                               break;
-                                                       mlp = ISDN_SLAVE_PRIV(mlp);
-                                               }
-                                       } else
-                                               printk(KERN_DEBUG "master offline\n");
-                                       /* Found parent, if it's offline iterate next device */
-                                       printk(KERN_DEBUG "mlpf: %d\n", mlp->flags & ISDN_NET_CONNECTED);
-                                       if (!(mlp->flags & ISDN_NET_CONNECTED)) {
-                                               p = (isdn_net_dev *) p->next;
-                                               continue;
-                                       }
-                               }
-                               if (lp->flags & ISDN_NET_CALLBACK) {
-                                       int chi;
-                                       /*
-                                        * Is the state MANUAL?
-                                        * If so, no callback can be made,
-                                        * so reject actively.
-                                        * */
-                                       if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) {
-                                               printk(KERN_INFO "incoming call for callback, interface %s `off' -> rejected\n",
-                                                      p->dev->name);
-                                               return 3;
-                                       }
-                                       printk(KERN_DEBUG "%s: call from %s -> %s, start callback\n",
-                                              p->dev->name, nr, eaz);
-                                       if (lp->phone[1]) {
-                                               /* Grab a free ISDN-Channel */
-                                               spin_lock_irqsave(&dev->lock, flags);
-                                               if ((chi =
-                                                    isdn_get_free_channel(
-                                                            ISDN_USAGE_NET,
-                                                            lp->l2_proto,
-                                                            lp->l3_proto,
-                                                            lp->pre_device,
-                                                            lp->pre_channel,
-                                                            lp->msn)
-                                                           ) < 0) {
-
-                                                       printk(KERN_WARNING "isdn_net_find_icall: No channel for %s\n",
-                                                              p->dev->name);
-                                                       spin_unlock_irqrestore(&dev->lock, flags);
-                                                       return 0;
-                                               }
-                                               /* Setup dialstate. */
-                                               lp->dtimer = 0;
-                                               lp->dialstate = 11;
-                                               /* Connect interface with channel */
-                                               isdn_net_bind_channel(lp, chi);
-#ifdef CONFIG_ISDN_PPP
-                                               if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
-                                                       if (isdn_ppp_bind(lp) < 0) {
-                                                               spin_unlock_irqrestore(&dev->lock, flags);
-                                                               isdn_net_unbind_channel(lp);
-                                                               return 0;
-                                                       }
-#endif
-                                               spin_unlock_irqrestore(&dev->lock, flags);
-                                               /* Initiate dialing by returning 2 or 4 */
-                                               return (lp->flags & ISDN_NET_CBHUP) ? 2 : 4;
-                                       } else
-                                               printk(KERN_WARNING "isdn_net: %s: No phone number\n",
-                                                      p->dev->name);
-                                       return 0;
-                               } else {
-                                       printk(KERN_DEBUG "%s: call from %s -> %s accepted\n",
-                                              p->dev->name, nr, eaz);
-                                       /* if this interface is dialing, it does it probably on a different
-                                          device, so free this device */
-                                       if ((lp->dialstate == 4) || (lp->dialstate == 12)) {
-#ifdef CONFIG_ISDN_PPP
-                                               if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
-                                                       isdn_ppp_free(lp);
-#endif
-                                               isdn_net_lp_disconnected(lp);
-                                               isdn_free_channel(lp->isdn_device, lp->isdn_channel,
-                                                                 ISDN_USAGE_NET);
-                                       }
-                                       spin_lock_irqsave(&dev->lock, flags);
-                                       dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE;
-                                       dev->usage[idx] |= ISDN_USAGE_NET;
-                                       strcpy(dev->num[idx], nr);
-                                       isdn_info_update();
-                                       dev->st_netdev[idx] = lp->netdev;
-                                       lp->isdn_device = di;
-                                       lp->isdn_channel = ch;
-                                       lp->ppp_slot = -1;
-                                       lp->flags |= ISDN_NET_CONNECTED;
-                                       lp->dialstate = 7;
-                                       lp->dtimer = 0;
-                                       lp->outgoing = 0;
-                                       lp->huptimer = 0;
-                                       lp->hupflags |= ISDN_WAITCHARGE;
-                                       lp->hupflags &= ~ISDN_HAVECHARGE;
-#ifdef CONFIG_ISDN_PPP
-                                       if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
-                                               if (isdn_ppp_bind(lp) < 0) {
-                                                       isdn_net_unbind_channel(lp);
-                                                       spin_unlock_irqrestore(&dev->lock, flags);
-                                                       return 0;
-                                               }
-                                       }
-#endif
-                                       spin_unlock_irqrestore(&dev->lock, flags);
-                                       return 1;
-                               }
-                       }
-               }
-               p = (isdn_net_dev *) p->next;
-       }
-       /* If none of configured EAZ/MSN matched and not verbose, be silent */
-       if (!ematch || dev->net_verbose)
-               printk(KERN_INFO "isdn_net: call from %s -> %d %s ignored\n", nr, di, eaz);
-       return (wret == 2) ? 5 : 0;
-}
-
-/*
- * Search list of net-interfaces for an interface with given name.
- */
-isdn_net_dev *
-isdn_net_findif(char *name)
-{
-       isdn_net_dev *p = dev->netdev;
-
-       while (p) {
-               if (!strcmp(p->dev->name, name))
-                       return p;
-               p = (isdn_net_dev *) p->next;
-       }
-       return (isdn_net_dev *) NULL;
-}
-
-/*
- * Force a net-interface to dial out.
- * This is called from the userlevel-routine below or
- * from isdn_net_start_xmit().
- */
-static int
-isdn_net_force_dial_lp(isdn_net_local *lp)
-{
-       if ((!(lp->flags & ISDN_NET_CONNECTED)) && !lp->dialstate) {
-               int chi;
-               if (lp->phone[1]) {
-                       ulong flags;
-
-                       /* Grab a free ISDN-Channel */
-                       spin_lock_irqsave(&dev->lock, flags);
-                       if ((chi = isdn_get_free_channel(
-                                    ISDN_USAGE_NET,
-                                    lp->l2_proto,
-                                    lp->l3_proto,
-                                    lp->pre_device,
-                                    lp->pre_channel,
-                                    lp->msn)) < 0) {
-                               printk(KERN_WARNING "isdn_net_force_dial: No channel for %s\n",
-                                      lp->netdev->dev->name);
-                               spin_unlock_irqrestore(&dev->lock, flags);
-                               return -EAGAIN;
-                       }
-                       lp->dialstate = 1;
-                       /* Connect interface with channel */
-                       isdn_net_bind_channel(lp, chi);
-#ifdef CONFIG_ISDN_PPP
-                       if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
-                               if (isdn_ppp_bind(lp) < 0) {
-                                       isdn_net_unbind_channel(lp);
-                                       spin_unlock_irqrestore(&dev->lock, flags);
-                                       return -EAGAIN;
-                               }
-#endif
-                       /* Initiate dialing */
-                       spin_unlock_irqrestore(&dev->lock, flags);
-                       isdn_net_dial();
-                       return 0;
-               } else
-                       return -EINVAL;
-       } else
-               return -EBUSY;
-}
-
-/*
- * This is called from certain upper protocol layers (multilink ppp
- * and x25iface encapsulation module) that want to initiate dialing
- * themselves.
- */
-int
-isdn_net_dial_req(isdn_net_local *lp)
-{
-       /* is there a better error code? */
-       if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) return -EBUSY;
-
-       return isdn_net_force_dial_lp(lp);
-}
-
-/*
- * Force a net-interface to dial out.
- * This is always called from within userspace (ISDN_IOCTL_NET_DIAL).
- */
-int
-isdn_net_force_dial(char *name)
-{
-       isdn_net_dev *p = isdn_net_findif(name);
-
-       if (!p)
-               return -ENODEV;
-       return (isdn_net_force_dial_lp(p->local));
-}
-
-/* The ISDN-specific entries in the device structure. */
-static const struct net_device_ops isdn_netdev_ops = {
-       .ndo_init             = isdn_net_init,
-       .ndo_open             = isdn_net_open,
-       .ndo_stop             = isdn_net_close,
-       .ndo_do_ioctl         = isdn_net_ioctl,
-
-       .ndo_start_xmit       = isdn_net_start_xmit,
-       .ndo_get_stats        = isdn_net_get_stats,
-       .ndo_tx_timeout       = isdn_net_tx_timeout,
-};
-
-/*
- * Helper for alloc_netdev()
- */
-static void _isdn_setup(struct net_device *dev)
-{
-       isdn_net_local *lp = netdev_priv(dev);
-
-       ether_setup(dev);
-
-       /* Setup the generic properties */
-       dev->flags = IFF_NOARP | IFF_POINTOPOINT;
-
-       /* isdn prepends a header in the tx path, can't share skbs */
-       dev->priv_flags &= ~IFF_TX_SKB_SHARING;
-       dev->header_ops = NULL;
-       dev->netdev_ops = &isdn_netdev_ops;
-
-       /* for clients with MPPP maybe higher values better */
-       dev->tx_queue_len = 30;
-
-       lp->p_encap = ISDN_NET_ENCAP_RAWIP;
-       lp->magic = ISDN_NET_MAGIC;
-       lp->last = lp;
-       lp->next = lp;
-       lp->isdn_device = -1;
-       lp->isdn_channel = -1;
-       lp->pre_device = -1;
-       lp->pre_channel = -1;
-       lp->exclusive = -1;
-       lp->ppp_slot = -1;
-       lp->pppbind = -1;
-       skb_queue_head_init(&lp->super_tx_queue);
-       lp->l2_proto = ISDN_PROTO_L2_X75I;
-       lp->l3_proto = ISDN_PROTO_L3_TRANS;
-       lp->triggercps = 6000;
-       lp->slavedelay = 10 * HZ;
-       lp->hupflags = ISDN_INHUP;      /* Do hangup even on incoming calls */
-       lp->onhtime = 10;       /* Default hangup-time for saving costs */
-       lp->dialmax = 1;
-       /* Hangup before Callback, manual dial */
-       lp->flags = ISDN_NET_CBHUP | ISDN_NET_DM_MANUAL;
-       lp->cbdelay = 25;       /* Wait 5 secs before Callback */
-       lp->dialtimeout = -1;  /* Infinite Dial-Timeout */
-       lp->dialwait = 5 * HZ; /* Wait 5 sec. after failed dial */
-       lp->dialstarted = 0;   /* Jiffies of last dial-start */
-       lp->dialwait_timer = 0;  /* Jiffies of earliest next dial-start */
-}
-
-/*
- * Allocate a new network-interface and initialize its data structures.
- */
-char *
-isdn_net_new(char *name, struct net_device *master)
-{
-       isdn_net_dev *netdev;
-
-       /* Avoid creating an existing interface */
-       if (isdn_net_findif(name)) {
-               printk(KERN_WARNING "isdn_net: interface %s already exists\n", name);
-               return NULL;
-       }
-       if (name == NULL)
-               return NULL;
-       if (!(netdev = kzalloc(sizeof(isdn_net_dev), GFP_KERNEL))) {
-               printk(KERN_WARNING "isdn_net: Could not allocate net-device\n");
-               return NULL;
-       }
-       netdev->dev = alloc_netdev(sizeof(isdn_net_local), name,
-                                  NET_NAME_UNKNOWN, _isdn_setup);
-       if (!netdev->dev) {
-               printk(KERN_WARNING "isdn_net: Could not allocate network device\n");
-               kfree(netdev);
-               return NULL;
-       }
-       netdev->local = netdev_priv(netdev->dev);
-
-       if (master) {
-               /* Device shall be a slave */
-               struct net_device *p = MASTER_TO_SLAVE(master);
-               struct net_device *q = master;
-
-               netdev->local->master = master;
-               /* Put device at end of slave-chain */
-               while (p) {
-                       q = p;
-                       p = MASTER_TO_SLAVE(p);
-               }
-               MASTER_TO_SLAVE(q) = netdev->dev;
-       } else {
-               /* Device shall be a master */
-               /*
-                * Watchdog timer (currently) for master only.
-                */
-               netdev->dev->watchdog_timeo = ISDN_NET_TX_TIMEOUT;
-               if (register_netdev(netdev->dev) != 0) {
-                       printk(KERN_WARNING "isdn_net: Could not register net-device\n");
-                       free_netdev(netdev->dev);
-                       kfree(netdev);
-                       return NULL;
-               }
-       }
-       netdev->queue = netdev->local;
-       spin_lock_init(&netdev->queue_lock);
-
-       netdev->local->netdev = netdev;
-
-       INIT_WORK(&netdev->local->tqueue, isdn_net_softint);
-       spin_lock_init(&netdev->local->xmit_lock);
-
-       /* Put into to netdev-chain */
-       netdev->next = (void *) dev->netdev;
-       dev->netdev = netdev;
-       return netdev->dev->name;
-}
-
-char *
-isdn_net_newslave(char *parm)
-{
-       char *p = strchr(parm, ',');
-       isdn_net_dev *n;
-       char newname[10];
-
-       if (p) {
-               /* Slave-Name MUST not be empty or overflow 'newname' */
-               if (strscpy(newname, p + 1, sizeof(newname)) <= 0)
-                       return NULL;
-               *p = 0;
-               /* Master must already exist */
-               if (!(n = isdn_net_findif(parm)))
-                       return NULL;
-               /* Master must be a real interface, not a slave */
-               if (n->local->master)
-                       return NULL;
-               /* Master must not be started yet */
-               if (isdn_net_device_started(n))
-                       return NULL;
-               return (isdn_net_new(newname, n->dev));
-       }
-       return NULL;
-}
-
-/*
- * Set interface-parameters.
- * Always set all parameters, so the user-level application is responsible
- * for not overwriting existing setups. It has to get the current
- * setup first, if only selected parameters are to be changed.
- */
-int
-isdn_net_setcfg(isdn_net_ioctl_cfg *cfg)
-{
-       isdn_net_dev *p = isdn_net_findif(cfg->name);
-       ulong features;
-       int i;
-       int drvidx;
-       int chidx;
-       char drvid[25];
-
-       if (p) {
-               isdn_net_local *lp = p->local;
-
-               /* See if any registered driver supports the features we want */
-               features = ((1 << cfg->l2_proto) << ISDN_FEATURE_L2_SHIFT) |
-                       ((1 << cfg->l3_proto) << ISDN_FEATURE_L3_SHIFT);
-               for (i = 0; i < ISDN_MAX_DRIVERS; i++)
-                       if (dev->drv[i])
-                               if ((dev->drv[i]->interface->features & features) == features)
-                                       break;
-               if (i == ISDN_MAX_DRIVERS) {
-                       printk(KERN_WARNING "isdn_net: No driver with selected features\n");
-                       return -ENODEV;
-               }
-               if (lp->p_encap != cfg->p_encap) {
-#ifdef CONFIG_ISDN_X25
-                       struct concap_proto *cprot = p->cprot;
-#endif
-                       if (isdn_net_device_started(p)) {
-                               printk(KERN_WARNING "%s: cannot change encap when if is up\n",
-                                      p->dev->name);
-                               return -EBUSY;
-                       }
-#ifdef CONFIG_ISDN_X25
-                       if (cprot && cprot->pops)
-                               cprot->pops->proto_del(cprot);
-                       p->cprot = NULL;
-                       lp->dops = NULL;
-                       /* ... ,  prepare for configuration of new one ... */
-                       switch (cfg->p_encap) {
-                       case ISDN_NET_ENCAP_X25IFACE:
-                               lp->dops = &isdn_concap_reliable_dl_dops;
-                       }
-                       /* ... and allocate new one ... */
-                       p->cprot = isdn_concap_new(cfg->p_encap);
-                       /* p -> cprot == NULL now if p_encap is not supported
-                          by means of the concap_proto mechanism */
-                       /* the protocol is not configured yet; this will
-                          happen later when isdn_net_reset() is called */
-#endif
-               }
-               switch (cfg->p_encap) {
-               case ISDN_NET_ENCAP_SYNCPPP:
-#ifndef CONFIG_ISDN_PPP
-                       printk(KERN_WARNING "%s: SyncPPP support not configured\n",
-                              p->dev->name);
-                       return -EINVAL;
-#else
-                       p->dev->type = ARPHRD_PPP;      /* change ARP type */
-                       p->dev->addr_len = 0;
-#endif
-                       break;
-               case ISDN_NET_ENCAP_X25IFACE:
-#ifndef CONFIG_ISDN_X25
-                       printk(KERN_WARNING "%s: isdn-x25 support not configured\n",
-                              p->dev->name);
-                       return -EINVAL;
-#else
-                       p->dev->type = ARPHRD_X25;      /* change ARP type */
-                       p->dev->addr_len = 0;
-#endif
-                       break;
-               case ISDN_NET_ENCAP_CISCOHDLCK:
-                       break;
-               default:
-                       if (cfg->p_encap >= 0 &&
-                           cfg->p_encap <= ISDN_NET_ENCAP_MAX_ENCAP)
-                               break;
-                       printk(KERN_WARNING
-                              "%s: encapsulation protocol %d not supported\n",
-                              p->dev->name, cfg->p_encap);
-                       return -EINVAL;
-               }
-               if (strlen(cfg->drvid)) {
-                       /* A bind has been requested ... */
-                       char *c,
-                               *e;
-
-                       if (strnlen(cfg->drvid, sizeof(cfg->drvid)) ==
-                           sizeof(cfg->drvid))
-                               return -EINVAL;
-                       drvidx = -1;
-                       chidx = -1;
-                       strcpy(drvid, cfg->drvid);
-                       if ((c = strchr(drvid, ','))) {
-                               /* The channel-number is appended to the driver-Id with a comma */
-                               chidx = (int) simple_strtoul(c + 1, &e, 10);
-                               if (e == c)
-                                       chidx = -1;
-                               *c = '\0';
-                       }
-                       for (i = 0; i < ISDN_MAX_DRIVERS; i++)
-                               /* Lookup driver-Id in array */
-                               if (!(strcmp(dev->drvid[i], drvid))) {
-                                       drvidx = i;
-                                       break;
-                               }
-                       if ((drvidx == -1) || (chidx == -1))
-                               /* Either driver-Id or channel-number invalid */
-                               return -ENODEV;
-               } else {
-                       /* Parameters are valid, so get them */
-                       drvidx = lp->pre_device;
-                       chidx = lp->pre_channel;
-               }
-               if (cfg->exclusive > 0) {
-                       unsigned long flags;
-
-                       /* If binding is exclusive, try to grab the channel */
-                       spin_lock_irqsave(&dev->lock, flags);
-                       if ((i = isdn_get_free_channel(ISDN_USAGE_NET,
-                                                      lp->l2_proto, lp->l3_proto, drvidx,
-                                                      chidx, lp->msn)) < 0) {
-                               /* Grab failed, because desired channel is in use */
-                               lp->exclusive = -1;
-                               spin_unlock_irqrestore(&dev->lock, flags);
-                               return -EBUSY;
-                       }
-                       /* All went ok, so update isdninfo */
-                       dev->usage[i] = ISDN_USAGE_EXCLUSIVE;
-                       isdn_info_update();
-                       spin_unlock_irqrestore(&dev->lock, flags);
-                       lp->exclusive = i;
-               } else {
-                       /* Non-exclusive binding or unbind. */
-                       lp->exclusive = -1;
-                       if ((lp->pre_device != -1) && (cfg->exclusive == -1)) {
-                               isdn_unexclusive_channel(lp->pre_device, lp->pre_channel);
-                               isdn_free_channel(lp->pre_device, lp->pre_channel, ISDN_USAGE_NET);
-                               drvidx = -1;
-                               chidx = -1;
-                       }
-               }
-               strlcpy(lp->msn, cfg->eaz, sizeof(lp->msn));
-               lp->pre_device = drvidx;
-               lp->pre_channel = chidx;
-               lp->onhtime = cfg->onhtime;
-               lp->charge = cfg->charge;
-               lp->l2_proto = cfg->l2_proto;
-               lp->l3_proto = cfg->l3_proto;
-               lp->cbdelay = cfg->cbdelay;
-               lp->dialmax = cfg->dialmax;
-               lp->triggercps = cfg->triggercps;
-               lp->slavedelay = cfg->slavedelay * HZ;
-               lp->pppbind = cfg->pppbind;
-               lp->dialtimeout = cfg->dialtimeout >= 0 ? cfg->dialtimeout * HZ : -1;
-               lp->dialwait = cfg->dialwait * HZ;
-               if (cfg->secure)
-                       lp->flags |= ISDN_NET_SECURE;
-               else
-                       lp->flags &= ~ISDN_NET_SECURE;
-               if (cfg->cbhup)
-                       lp->flags |= ISDN_NET_CBHUP;
-               else
-                       lp->flags &= ~ISDN_NET_CBHUP;
-               switch (cfg->callback) {
-               case 0:
-                       lp->flags &= ~(ISDN_NET_CALLBACK | ISDN_NET_CBOUT);
-                       break;
-               case 1:
-                       lp->flags |= ISDN_NET_CALLBACK;
-                       lp->flags &= ~ISDN_NET_CBOUT;
-                       break;
-               case 2:
-                       lp->flags |= ISDN_NET_CBOUT;
-                       lp->flags &= ~ISDN_NET_CALLBACK;
-                       break;
-               }
-               lp->flags &= ~ISDN_NET_DIALMODE_MASK;   /* first all bits off */
-               if (cfg->dialmode && !(cfg->dialmode & ISDN_NET_DIALMODE_MASK)) {
-                       /* old isdnctrl version, where only 0 or 1 is given */
-                       printk(KERN_WARNING
-                              "Old isdnctrl version detected! Please update.\n");
-                       lp->flags |= ISDN_NET_DM_OFF; /* turn on `off' bit */
-               }
-               else {
-                       lp->flags |= cfg->dialmode;  /* turn on selected bits */
-               }
-               if (cfg->chargehup)
-                       lp->hupflags |= ISDN_CHARGEHUP;
-               else
-                       lp->hupflags &= ~ISDN_CHARGEHUP;
-               if (cfg->ihup)
-                       lp->hupflags |= ISDN_INHUP;
-               else
-                       lp->hupflags &= ~ISDN_INHUP;
-               if (cfg->chargeint > 10) {
-                       lp->hupflags |= ISDN_CHARGEHUP | ISDN_HAVECHARGE | ISDN_MANCHARGE;
-                       lp->chargeint = cfg->chargeint * HZ;
-               }
-               if (cfg->p_encap != lp->p_encap) {
-                       if (cfg->p_encap == ISDN_NET_ENCAP_RAWIP) {
-                               p->dev->header_ops = NULL;
-                               p->dev->flags = IFF_NOARP | IFF_POINTOPOINT;
-                       } else {
-                               p->dev->header_ops = &isdn_header_ops;
-                               if (cfg->p_encap == ISDN_NET_ENCAP_ETHER)
-                                       p->dev->flags = IFF_BROADCAST | IFF_MULTICAST;
-                               else
-                                       p->dev->flags = IFF_NOARP | IFF_POINTOPOINT;
-                       }
-               }
-               lp->p_encap = cfg->p_encap;
-               return 0;
-       }
-       return -ENODEV;
-}
-
-/*
- * Perform get-interface-parameters.ioctl
- */
-int
-isdn_net_getcfg(isdn_net_ioctl_cfg *cfg)
-{
-       isdn_net_dev *p = isdn_net_findif(cfg->name);
-
-       if (p) {
-               isdn_net_local *lp = p->local;
-
-               strcpy(cfg->eaz, lp->msn);
-               cfg->exclusive = lp->exclusive;
-               if (lp->pre_device >= 0) {
-                       sprintf(cfg->drvid, "%s,%d", dev->drvid[lp->pre_device],
-                               lp->pre_channel);
-               } else
-                       cfg->drvid[0] = '\0';
-               cfg->onhtime = lp->onhtime;
-               cfg->charge = lp->charge;
-               cfg->l2_proto = lp->l2_proto;
-               cfg->l3_proto = lp->l3_proto;
-               cfg->p_encap = lp->p_encap;
-               cfg->secure = (lp->flags & ISDN_NET_SECURE) ? 1 : 0;
-               cfg->callback = 0;
-               if (lp->flags & ISDN_NET_CALLBACK)
-                       cfg->callback = 1;
-               if (lp->flags & ISDN_NET_CBOUT)
-                       cfg->callback = 2;
-               cfg->cbhup = (lp->flags & ISDN_NET_CBHUP) ? 1 : 0;
-               cfg->dialmode = lp->flags & ISDN_NET_DIALMODE_MASK;
-               cfg->chargehup = (lp->hupflags & ISDN_CHARGEHUP) ? 1 : 0;
-               cfg->ihup = (lp->hupflags & ISDN_INHUP) ? 1 : 0;
-               cfg->cbdelay = lp->cbdelay;
-               cfg->dialmax = lp->dialmax;
-               cfg->triggercps = lp->triggercps;
-               cfg->slavedelay = lp->slavedelay / HZ;
-               cfg->chargeint = (lp->hupflags & ISDN_CHARGEHUP) ?
-                       (lp->chargeint / HZ) : 0;
-               cfg->pppbind = lp->pppbind;
-               cfg->dialtimeout = lp->dialtimeout >= 0 ? lp->dialtimeout / HZ : -1;
-               cfg->dialwait = lp->dialwait / HZ;
-               if (lp->slave) {
-                       if (strlen(lp->slave->name) >= 10)
-                               strcpy(cfg->slave, "too-long");
-                       else
-                               strcpy(cfg->slave, lp->slave->name);
-               } else
-                       cfg->slave[0] = '\0';
-               if (lp->master) {
-                       if (strlen(lp->master->name) >= 10)
-                               strcpy(cfg->master, "too-long");
-                       else
-                               strcpy(cfg->master, lp->master->name);
-               } else
-                       cfg->master[0] = '\0';
-               return 0;
-       }
-       return -ENODEV;
-}
-
-/*
- * Add a phone-number to an interface.
- */
-int
-isdn_net_addphone(isdn_net_ioctl_phone *phone)
-{
-       isdn_net_dev *p = isdn_net_findif(phone->name);
-       isdn_net_phone *n;
-
-       if (p) {
-               if (!(n = kmalloc(sizeof(isdn_net_phone), GFP_KERNEL)))
-                       return -ENOMEM;
-               strlcpy(n->num, phone->phone, sizeof(n->num));
-               n->next = p->local->phone[phone->outgoing & 1];
-               p->local->phone[phone->outgoing & 1] = n;
-               return 0;
-       }
-       return -ENODEV;
-}
-
-/*
- * Copy a string of all phone-numbers of an interface to user space.
- * This might sleep and must be called with the isdn semaphore down.
- */
-int
-isdn_net_getphones(isdn_net_ioctl_phone *phone, char __user *phones)
-{
-       isdn_net_dev *p = isdn_net_findif(phone->name);
-       int inout = phone->outgoing & 1;
-       int more = 0;
-       int count = 0;
-       isdn_net_phone *n;
-
-       if (!p)
-               return -ENODEV;
-       inout &= 1;
-       for (n = p->local->phone[inout]; n; n = n->next) {
-               if (more) {
-                       put_user(' ', phones++);
-                       count++;
-               }
-               if (copy_to_user(phones, n->num, strlen(n->num) + 1)) {
-                       return -EFAULT;
-               }
-               phones += strlen(n->num);
-               count += strlen(n->num);
-               more = 1;
-       }
-       put_user(0, phones);
-       count++;
-       return count;
-}
-
-/*
- * Copy a string containing the peer's phone number of a connected interface
- * to user space.
- */
-int
-isdn_net_getpeer(isdn_net_ioctl_phone *phone, isdn_net_ioctl_phone __user *peer)
-{
-       isdn_net_dev *p = isdn_net_findif(phone->name);
-       int ch, dv, idx;
-
-       if (!p)
-               return -ENODEV;
-       /*
-        * Theoretical race: while this executes, the remote number might
-        * become invalid (hang up) or change (new connection), resulting
-        * in (partially) wrong number copied to user. This race
-        * currently ignored.
-        */
-       ch = p->local->isdn_channel;
-       dv = p->local->isdn_device;
-       if (ch < 0 && dv < 0)
-               return -ENOTCONN;
-       idx = isdn_dc2minor(dv, ch);
-       if (idx < 0)
-               return -ENODEV;
-       /* for pre-bound channels, we need this extra check */
-       if (strncmp(dev->num[idx], "???", 3) == 0)
-               return -ENOTCONN;
-       strncpy(phone->phone, dev->num[idx], ISDN_MSNLEN);
-       phone->outgoing = USG_OUTGOING(dev->usage[idx]);
-       if (copy_to_user(peer, phone, sizeof(*peer)))
-               return -EFAULT;
-       return 0;
-}
-/*
- * Delete a phone-number from an interface.
- */
-int
-isdn_net_delphone(isdn_net_ioctl_phone *phone)
-{
-       isdn_net_dev *p = isdn_net_findif(phone->name);
-       int inout = phone->outgoing & 1;
-       isdn_net_phone *n;
-       isdn_net_phone *m;
-
-       if (p) {
-               n = p->local->phone[inout];
-               m = NULL;
-               while (n) {
-                       if (!strcmp(n->num, phone->phone)) {
-                               if (p->local->dial == n)
-                                       p->local->dial = n->next;
-                               if (m)
-                                       m->next = n->next;
-                               else
-                                       p->local->phone[inout] = n->next;
-                               kfree(n);
-                               return 0;
-                       }
-                       m = n;
-                       n = (isdn_net_phone *) n->next;
-               }
-               return -EINVAL;
-       }
-       return -ENODEV;
-}
-
-/*
- * Delete all phone-numbers of an interface.
- */
-static int
-isdn_net_rmallphone(isdn_net_dev *p)
-{
-       isdn_net_phone *n;
-       isdn_net_phone *m;
-       int i;
-
-       for (i = 0; i < 2; i++) {
-               n = p->local->phone[i];
-               while (n) {
-                       m = n->next;
-                       kfree(n);
-                       n = m;
-               }
-               p->local->phone[i] = NULL;
-       }
-       p->local->dial = NULL;
-       return 0;
-}
-
-/*
- * Force a hangup of a network-interface.
- */
-int
-isdn_net_force_hangup(char *name)
-{
-       isdn_net_dev *p = isdn_net_findif(name);
-       struct net_device *q;
-
-       if (p) {
-               if (p->local->isdn_device < 0)
-                       return 1;
-               q = p->local->slave;
-               /* If this interface has slaves, do a hangup for them also. */
-               while (q) {
-                       isdn_net_hangup(q);
-                       q = MASTER_TO_SLAVE(q);
-               }
-               isdn_net_hangup(p->dev);
-               return 0;
-       }
-       return -ENODEV;
-}
-
-/*
- * Helper-function for isdn_net_rm: Do the real work.
- */
-static int
-isdn_net_realrm(isdn_net_dev *p, isdn_net_dev *q)
-{
-       u_long flags;
-
-       if (isdn_net_device_started(p)) {
-               return -EBUSY;
-       }
-#ifdef CONFIG_ISDN_X25
-       if (p->cprot && p->cprot->pops)
-               p->cprot->pops->proto_del(p->cprot);
-#endif
-       /* Free all phone-entries */
-       isdn_net_rmallphone(p);
-       /* If interface is bound exclusive, free channel-usage */
-       if (p->local->exclusive != -1)
-               isdn_unexclusive_channel(p->local->pre_device, p->local->pre_channel);
-       if (p->local->master) {
-               /* It's a slave-device, so update master's slave-pointer if necessary */
-               if (((isdn_net_local *) ISDN_MASTER_PRIV(p->local))->slave ==
-                   p->dev)
-                       ((isdn_net_local *)ISDN_MASTER_PRIV(p->local))->slave =
-                               p->local->slave;
-       } else {
-               /* Unregister only if it's a master-device */
-               unregister_netdev(p->dev);
-       }
-       /* Unlink device from chain */
-       spin_lock_irqsave(&dev->lock, flags);
-       if (q)
-               q->next = p->next;
-       else
-               dev->netdev = p->next;
-       if (p->local->slave) {
-               /* If this interface has a slave, remove it also */
-               char *slavename = p->local->slave->name;
-               isdn_net_dev *n = dev->netdev;
-               q = NULL;
-               while (n) {
-                       if (!strcmp(n->dev->name, slavename)) {
-                               spin_unlock_irqrestore(&dev->lock, flags);
-                               isdn_net_realrm(n, q);
-                               spin_lock_irqsave(&dev->lock, flags);
-                               break;
-                       }
-                       q = n;
-                       n = (isdn_net_dev *)n->next;
-               }
-       }
-       spin_unlock_irqrestore(&dev->lock, flags);
-       /* If no more net-devices remain, disable auto-hangup timer */
-       if (dev->netdev == NULL)
-               isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0);
-       free_netdev(p->dev);
-       kfree(p);
-
-       return 0;
-}
-
-/*
- * Remove a single network-interface.
- */
-int
-isdn_net_rm(char *name)
-{
-       u_long flags;
-       isdn_net_dev *p;
-       isdn_net_dev *q;
-
-       /* Search name in netdev-chain */
-       spin_lock_irqsave(&dev->lock, flags);
-       p = dev->netdev;
-       q = NULL;
-       while (p) {
-               if (!strcmp(p->dev->name, name)) {
-                       spin_unlock_irqrestore(&dev->lock, flags);
-                       return (isdn_net_realrm(p, q));
-               }
-               q = p;
-               p = (isdn_net_dev *) p->next;
-       }
-       spin_unlock_irqrestore(&dev->lock, flags);
-       /* If no more net-devices remain, disable auto-hangup timer */
-       if (dev->netdev == NULL)
-               isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0);
-       return -ENODEV;
-}
-
-/*
- * Remove all network-interfaces
- */
-int
-isdn_net_rmall(void)
-{
-       u_long flags;
-       int ret;
-
-       /* Walk through netdev-chain */
-       spin_lock_irqsave(&dev->lock, flags);
-       while (dev->netdev) {
-               if (!dev->netdev->local->master) {
-                       /* Remove master-devices only, slaves get removed with their master */
-                       spin_unlock_irqrestore(&dev->lock, flags);
-                       if ((ret = isdn_net_realrm(dev->netdev, NULL))) {
-                               return ret;
-                       }
-                       spin_lock_irqsave(&dev->lock, flags);
-               }
-       }
-       dev->netdev = NULL;
-       spin_unlock_irqrestore(&dev->lock, flags);
-       return 0;
-}
 
+++ /dev/null
-/* $Id: isdn_net.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
- *
- * header for Linux ISDN subsystem, network related functions (linklevel).
- *
- * Copyright 1994-1999  by Fritz Elfert (fritz@isdn4linux.de)
- * Copyright 1995,96    by Thinking Objects Software GmbH Wuerzburg
- * Copyright 1995,96    by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-/* Definitions for hupflags:                */
-#define ISDN_WAITCHARGE  1      /* did not get a charge info yet            */
-#define ISDN_HAVECHARGE  2      /* We know a charge info                    */
-#define ISDN_CHARGEHUP   4      /* We want to use the charge mechanism      */
-#define ISDN_INHUP       8      /* Even if incoming, close after huptimeout */
-#define ISDN_MANCHARGE  16      /* Charge Interval manually set             */
-
-/*
- * Definitions for Cisco-HDLC header.
- */
-
-#define CISCO_ADDR_UNICAST    0x0f
-#define CISCO_ADDR_BROADCAST  0x8f
-#define CISCO_CTRL            0x00
-#define CISCO_TYPE_CDP        0x2000
-#define CISCO_TYPE_SLARP      0x8035
-#define CISCO_SLARP_REQUEST   0
-#define CISCO_SLARP_REPLY     1
-#define CISCO_SLARP_KEEPALIVE 2
-
-extern char *isdn_net_new(char *, struct net_device *);
-extern char *isdn_net_newslave(char *);
-extern int isdn_net_rm(char *);
-extern int isdn_net_rmall(void);
-extern int isdn_net_stat_callback(int, isdn_ctrl *);
-extern int isdn_net_setcfg(isdn_net_ioctl_cfg *);
-extern int isdn_net_getcfg(isdn_net_ioctl_cfg *);
-extern int isdn_net_addphone(isdn_net_ioctl_phone *);
-extern int isdn_net_getphones(isdn_net_ioctl_phone *, char __user *);
-extern int isdn_net_getpeer(isdn_net_ioctl_phone *, isdn_net_ioctl_phone __user *);
-extern int isdn_net_delphone(isdn_net_ioctl_phone *);
-extern int isdn_net_find_icall(int, int, int, setup_parm *);
-extern void isdn_net_hangup(struct net_device *);
-extern void isdn_net_dial(void);
-extern void isdn_net_autohup(void);
-extern int isdn_net_force_hangup(char *);
-extern int isdn_net_force_dial(char *);
-extern isdn_net_dev *isdn_net_findif(char *);
-extern int isdn_net_rcv_skb(int, struct sk_buff *);
-extern int isdn_net_dial_req(isdn_net_local *);
-extern void isdn_net_writebuf_skb(isdn_net_local *lp, struct sk_buff *skb);
-extern void isdn_net_write_super(isdn_net_local *lp, struct sk_buff *skb);
-
-#define ISDN_NET_MAX_QUEUE_LENGTH 2
-
-#define ISDN_MASTER_PRIV(lp) ((isdn_net_local *) netdev_priv(lp->master))
-#define ISDN_SLAVE_PRIV(lp) ((isdn_net_local *) netdev_priv(lp->slave))
-#define MASTER_TO_SLAVE(master)                                        \
-       (((isdn_net_local *) netdev_priv(master))->slave)
-
-/*
- * is this particular channel busy?
- */
-static __inline__ int isdn_net_lp_busy(isdn_net_local *lp)
-{
-       if (atomic_read(&lp->frame_cnt) < ISDN_NET_MAX_QUEUE_LENGTH)
-               return 0;
-       else
-               return 1;
-}
-
-/*
- * For the given net device, this will get a non-busy channel out of the
- * corresponding bundle. The returned channel is locked.
- */
-static __inline__ isdn_net_local *isdn_net_get_locked_lp(isdn_net_dev *nd)
-{
-       unsigned long flags;
-       isdn_net_local *lp;
-
-       spin_lock_irqsave(&nd->queue_lock, flags);
-       lp = nd->queue;         /* get lp on top of queue */
-       while (isdn_net_lp_busy(nd->queue)) {
-               nd->queue = nd->queue->next;
-               if (nd->queue == lp) { /* not found -- should never happen */
-                       lp = NULL;
-                       goto errout;
-               }
-       }
-       lp = nd->queue;
-       nd->queue = nd->queue->next;
-       spin_unlock_irqrestore(&nd->queue_lock, flags);
-       spin_lock(&lp->xmit_lock);
-       local_bh_disable();
-       return lp;
-errout:
-       spin_unlock_irqrestore(&nd->queue_lock, flags);
-       return lp;
-}
-
-/*
- * add a channel to a bundle
- */
-static __inline__ void isdn_net_add_to_bundle(isdn_net_dev *nd, isdn_net_local *nlp)
-{
-       isdn_net_local *lp;
-       unsigned long flags;
-
-       spin_lock_irqsave(&nd->queue_lock, flags);
-
-       lp = nd->queue;
-//     printk(KERN_DEBUG "%s: lp:%s(%p) nlp:%s(%p) last(%p)\n",
-//             __func__, lp->name, lp, nlp->name, nlp, lp->last);
-       nlp->last = lp->last;
-       lp->last->next = nlp;
-       lp->last = nlp;
-       nlp->next = lp;
-       nd->queue = nlp;
-
-       spin_unlock_irqrestore(&nd->queue_lock, flags);
-}
-/*
- * remove a channel from the bundle it belongs to
- */
-static __inline__ void isdn_net_rm_from_bundle(isdn_net_local *lp)
-{
-       isdn_net_local *master_lp = lp;
-       unsigned long flags;
-
-       if (lp->master)
-               master_lp = ISDN_MASTER_PRIV(lp);
-
-//     printk(KERN_DEBUG "%s: lp:%s(%p) mlp:%s(%p) last(%p) next(%p) mndq(%p)\n",
-//             __func__, lp->name, lp, master_lp->name, master_lp, lp->last, lp->next, master_lp->netdev->queue);
-       spin_lock_irqsave(&master_lp->netdev->queue_lock, flags);
-       lp->last->next = lp->next;
-       lp->next->last = lp->last;
-       if (master_lp->netdev->queue == lp) {
-               master_lp->netdev->queue = lp->next;
-               if (lp->next == lp) { /* last in queue */
-                       master_lp->netdev->queue = master_lp->netdev->local;
-               }
-       }
-       lp->next = lp->last = lp;       /* (re)set own pointers */
-//     printk(KERN_DEBUG "%s: mndq(%p)\n",
-//             __func__, master_lp->netdev->queue);
-       spin_unlock_irqrestore(&master_lp->netdev->queue_lock, flags);
-}
 
+++ /dev/null
-/* $Id: isdn_ppp.c,v 1.1.2.3 2004/02/10 01:07:13 keil Exp $
- *
- * Linux ISDN subsystem, functions for synchronous PPP (linklevel).
- *
- * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#include <linux/isdn.h>
-#include <linux/poll.h>
-#include <linux/ppp-comp.h>
-#include <linux/slab.h>
-#ifdef CONFIG_IPPP_FILTER
-#include <linux/filter.h>
-#endif
-
-#include "isdn_common.h"
-#include "isdn_ppp.h"
-#include "isdn_net.h"
-
-#ifndef PPP_IPX
-#define PPP_IPX 0x002b
-#endif
-
-/* Prototypes */
-static int isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot);
-static int isdn_ppp_closewait(int slot);
-static void isdn_ppp_push_higher(isdn_net_dev *net_dev, isdn_net_local *lp,
-                                struct sk_buff *skb, int proto);
-static int isdn_ppp_if_get_unit(char *namebuf);
-static int isdn_ppp_set_compressor(struct ippp_struct *is, struct isdn_ppp_comp_data *);
-static struct sk_buff *isdn_ppp_decompress(struct sk_buff *,
-                                          struct ippp_struct *, struct ippp_struct *, int *proto);
-static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
-                                struct sk_buff *skb, int proto);
-static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in, int *proto,
-                                        struct ippp_struct *is, struct ippp_struct *master, int type);
-static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
-                             struct sk_buff *skb);
-
-/* New CCP stuff */
-static void isdn_ppp_ccp_kickup(struct ippp_struct *is);
-static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
-                                   unsigned char code, unsigned char id,
-                                   unsigned char *data, int len);
-static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is);
-static void isdn_ppp_ccp_reset_free(struct ippp_struct *is);
-static void isdn_ppp_ccp_reset_free_state(struct ippp_struct *is,
-                                         unsigned char id);
-static void isdn_ppp_ccp_timer_callback(struct timer_list *t);
-static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_struct *is,
-                                                                  unsigned char id);
-static void isdn_ppp_ccp_reset_trans(struct ippp_struct *is,
-                                    struct isdn_ppp_resetparams *rp);
-static void isdn_ppp_ccp_reset_ack_rcvd(struct ippp_struct *is,
-                                       unsigned char id);
-
-
-
-#ifdef CONFIG_ISDN_MPP
-static ippp_bundle *isdn_ppp_bundle_arr = NULL;
-
-static int isdn_ppp_mp_bundle_array_init(void);
-static int isdn_ppp_mp_init(isdn_net_local *lp, ippp_bundle *add_to);
-static void isdn_ppp_mp_receive(isdn_net_dev *net_dev, isdn_net_local *lp,
-                               struct sk_buff *skb);
-static void isdn_ppp_mp_cleanup(isdn_net_local *lp);
-
-static int isdn_ppp_bundle(struct ippp_struct *, int unit);
-#endif /* CONFIG_ISDN_MPP */
-
-char *isdn_ppp_revision = "$Revision: 1.1.2.3 $";
-
-static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
-
-static struct isdn_ppp_compressor *ipc_head = NULL;
-
-/*
- * frame log (debug)
- */
-static void
-isdn_ppp_frame_log(char *info, char *data, int len, int maxlen, int unit, int slot)
-{
-       int cnt,
-               j,
-               i;
-       char buf[80];
-
-       if (len < maxlen)
-               maxlen = len;
-
-       for (i = 0, cnt = 0; cnt < maxlen; i++) {
-               for (j = 0; j < 16 && cnt < maxlen; j++, cnt++)
-                       sprintf(buf + j * 3, "%02x ", (unsigned char)data[cnt]);
-               printk(KERN_DEBUG "[%d/%d].%s[%d]: %s\n", unit, slot, info, i, buf);
-       }
-}
-
-/*
- * unbind isdn_net_local <=> ippp-device
- * note: it can happen, that we hangup/free the master before the slaves
- *       in this case we bind another lp to the master device
- */
-int
-isdn_ppp_free(isdn_net_local *lp)
-{
-       struct ippp_struct *is;
-
-       if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
-               printk(KERN_ERR "%s: ppp_slot(%d) out of range\n",
-                      __func__, lp->ppp_slot);
-               return 0;
-       }
-
-#ifdef CONFIG_ISDN_MPP
-       spin_lock(&lp->netdev->pb->lock);
-#endif
-       isdn_net_rm_from_bundle(lp);
-#ifdef CONFIG_ISDN_MPP
-       if (lp->netdev->pb->ref_ct == 1)        /* last link in queue? */
-               isdn_ppp_mp_cleanup(lp);
-
-       lp->netdev->pb->ref_ct--;
-       spin_unlock(&lp->netdev->pb->lock);
-#endif /* CONFIG_ISDN_MPP */
-       if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
-               printk(KERN_ERR "%s: ppp_slot(%d) now invalid\n",
-                      __func__, lp->ppp_slot);
-               return 0;
-       }
-       is = ippp_table[lp->ppp_slot];
-       if ((is->state & IPPP_CONNECT))
-               isdn_ppp_closewait(lp->ppp_slot);       /* force wakeup on ippp device */
-       else if (is->state & IPPP_ASSIGNED)
-               is->state = IPPP_OPEN;  /* fallback to 'OPEN but not ASSIGNED' state */
-
-       if (is->debug & 0x1)
-               printk(KERN_DEBUG "isdn_ppp_free %d %lx %lx\n", lp->ppp_slot, (long) lp, (long) is->lp);
-
-       is->lp = NULL;          /* link is down .. set lp to NULL */
-       lp->ppp_slot = -1;      /* is this OK ?? */
-
-       return 0;
-}
-
-/*
- * bind isdn_net_local <=> ippp-device
- *
- * This function is allways called with holding dev->lock so
- * no additional lock is needed
- */
-int
-isdn_ppp_bind(isdn_net_local *lp)
-{
-       int i;
-       int unit = 0;
-       struct ippp_struct *is;
-       int retval;
-
-       if (lp->pppbind < 0) {  /* device bounded to ippp device ? */
-               isdn_net_dev *net_dev = dev->netdev;
-               char exclusive[ISDN_MAX_CHANNELS];      /* exclusive flags */
-               memset(exclusive, 0, ISDN_MAX_CHANNELS);
-               while (net_dev) {       /* step through net devices to find exclusive minors */
-                       isdn_net_local *lp = net_dev->local;
-                       if (lp->pppbind >= 0)
-                               exclusive[lp->pppbind] = 1;
-                       net_dev = net_dev->next;
-               }
-               /*
-                * search a free device / slot
-                */
-               for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-                       if (ippp_table[i]->state == IPPP_OPEN && !exclusive[ippp_table[i]->minor]) {    /* OPEN, but not connected! */
-                               break;
-                       }
-               }
-       } else {
-               for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-                       if (ippp_table[i]->minor == lp->pppbind &&
-                           (ippp_table[i]->state & IPPP_OPEN) == IPPP_OPEN)
-                               break;
-               }
-       }
-
-       if (i >= ISDN_MAX_CHANNELS) {
-               printk(KERN_WARNING "isdn_ppp_bind: Can't find a (free) connection to the ipppd daemon.\n");
-               retval = -1;
-               goto out;
-       }
-       /* get unit number from interface name .. ugly! */
-       unit = isdn_ppp_if_get_unit(lp->netdev->dev->name);
-       if (unit < 0) {
-               printk(KERN_ERR "isdn_ppp_bind: illegal interface name %s.\n",
-                      lp->netdev->dev->name);
-               retval = -1;
-               goto out;
-       }
-
-       lp->ppp_slot = i;
-       is = ippp_table[i];
-       is->lp = lp;
-       is->unit = unit;
-       is->state = IPPP_OPEN | IPPP_ASSIGNED;  /* assigned to a netdevice but not connected */
-#ifdef CONFIG_ISDN_MPP
-       retval = isdn_ppp_mp_init(lp, NULL);
-       if (retval < 0)
-               goto out;
-#endif /* CONFIG_ISDN_MPP */
-
-       retval = lp->ppp_slot;
-
-out:
-       return retval;
-}
-
-/*
- * kick the ipppd on the device
- * (wakes up daemon after B-channel connect)
- */
-
-void
-isdn_ppp_wakeup_daemon(isdn_net_local *lp)
-{
-       if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
-               printk(KERN_ERR "%s: ppp_slot(%d) out of range\n",
-                      __func__, lp->ppp_slot);
-               return;
-       }
-       ippp_table[lp->ppp_slot]->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK;
-       wake_up_interruptible(&ippp_table[lp->ppp_slot]->wq);
-}
-
-/*
- * there was a hangup on the netdevice
- * force wakeup of the ippp device
- * go into 'device waits for release' state
- */
-static int
-isdn_ppp_closewait(int slot)
-{
-       struct ippp_struct *is;
-
-       if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
-               printk(KERN_ERR "%s: slot(%d) out of range\n",
-                      __func__, slot);
-               return 0;
-       }
-       is = ippp_table[slot];
-       if (is->state)
-               wake_up_interruptible(&is->wq);
-       is->state = IPPP_CLOSEWAIT;
-       return 1;
-}
-
-/*
- * isdn_ppp_find_slot / isdn_ppp_free_slot
- */
-
-static int
-isdn_ppp_get_slot(void)
-{
-       int i;
-       for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-               if (!ippp_table[i]->state)
-                       return i;
-       }
-       return -1;
-}
-
-/*
- * isdn_ppp_open
- */
-
-int
-isdn_ppp_open(int min, struct file *file)
-{
-       int slot;
-       struct ippp_struct *is;
-
-       if (min < 0 || min >= ISDN_MAX_CHANNELS)
-               return -ENODEV;
-
-       slot = isdn_ppp_get_slot();
-       if (slot < 0) {
-               return -EBUSY;
-       }
-       is = file->private_data = ippp_table[slot];
-
-       printk(KERN_DEBUG "ippp, open, slot: %d, minor: %d, state: %04x\n",
-              slot, min, is->state);
-
-       /* compression stuff */
-       is->link_compressor   = is->compressor = NULL;
-       is->link_decompressor = is->decompressor = NULL;
-       is->link_comp_stat    = is->comp_stat = NULL;
-       is->link_decomp_stat  = is->decomp_stat = NULL;
-       is->compflags = 0;
-
-       is->reset = isdn_ppp_ccp_reset_alloc(is);
-       if (!is->reset)
-               return -ENOMEM;
-
-       is->lp = NULL;
-       is->mp_seqno = 0;       /* MP sequence number */
-       is->pppcfg = 0;         /* ppp configuration */
-       is->mpppcfg = 0;        /* mppp configuration */
-       is->last_link_seqno = -1;       /* MP: maybe set to Bundle-MIN, when joining a bundle ?? */
-       is->unit = -1;          /* set, when we have our interface */
-       is->mru = 1524;         /* MRU, default 1524 */
-       is->maxcid = 16;        /* VJ: maxcid */
-       is->tk = current;
-       init_waitqueue_head(&is->wq);
-       is->first = is->rq + NUM_RCV_BUFFS - 1; /* receive queue */
-       is->last = is->rq;
-       is->minor = min;
-#ifdef CONFIG_ISDN_PPP_VJ
-       /*
-        * VJ header compression init
-        */
-       is->slcomp = slhc_init(16, 16); /* not necessary for 2. link in bundle */
-       if (IS_ERR(is->slcomp)) {
-               isdn_ppp_ccp_reset_free(is);
-               return PTR_ERR(is->slcomp);
-       }
-#endif
-#ifdef CONFIG_IPPP_FILTER
-       is->pass_filter = NULL;
-       is->active_filter = NULL;
-#endif
-       is->state = IPPP_OPEN;
-
-       return 0;
-}
-
-/*
- * release ippp device
- */
-void
-isdn_ppp_release(int min, struct file *file)
-{
-       int i;
-       struct ippp_struct *is;
-
-       if (min < 0 || min >= ISDN_MAX_CHANNELS)
-               return;
-       is = file->private_data;
-
-       if (!is) {
-               printk(KERN_ERR "%s: no file->private_data\n", __func__);
-               return;
-       }
-       if (is->debug & 0x1)
-               printk(KERN_DEBUG "ippp: release, minor: %d %lx\n", min, (long) is->lp);
-
-       if (is->lp) {           /* a lp address says: this link is still up */
-               isdn_net_dev *p = is->lp->netdev;
-
-               if (!p) {
-                       printk(KERN_ERR "%s: no lp->netdev\n", __func__);
-                       return;
-               }
-               is->state &= ~IPPP_CONNECT;     /* -> effect: no call of wakeup */
-               /*
-                * isdn_net_hangup() calls isdn_ppp_free()
-                * isdn_ppp_free() sets is->lp to NULL and lp->ppp_slot to -1
-                * removing the IPPP_CONNECT flag omits calling of isdn_ppp_wakeup_daemon()
-                */
-               isdn_net_hangup(p->dev);
-       }
-       for (i = 0; i < NUM_RCV_BUFFS; i++) {
-               kfree(is->rq[i].buf);
-               is->rq[i].buf = NULL;
-       }
-       is->first = is->rq + NUM_RCV_BUFFS - 1; /* receive queue */
-       is->last = is->rq;
-
-#ifdef CONFIG_ISDN_PPP_VJ
-/* TODO: if this was the previous master: link the slcomp to the new master */
-       slhc_free(is->slcomp);
-       is->slcomp = NULL;
-#endif
-#ifdef CONFIG_IPPP_FILTER
-       if (is->pass_filter) {
-               bpf_prog_destroy(is->pass_filter);
-               is->pass_filter = NULL;
-       }
-
-       if (is->active_filter) {
-               bpf_prog_destroy(is->active_filter);
-               is->active_filter = NULL;
-       }
-#endif
-
-/* TODO: if this was the previous master: link the stuff to the new master */
-       if (is->comp_stat)
-               is->compressor->free(is->comp_stat);
-       if (is->link_comp_stat)
-               is->link_compressor->free(is->link_comp_stat);
-       if (is->link_decomp_stat)
-               is->link_decompressor->free(is->link_decomp_stat);
-       if (is->decomp_stat)
-               is->decompressor->free(is->decomp_stat);
-       is->compressor   = is->link_compressor   = NULL;
-       is->decompressor = is->link_decompressor = NULL;
-       is->comp_stat    = is->link_comp_stat    = NULL;
-       is->decomp_stat  = is->link_decomp_stat  = NULL;
-
-       /* Clean up if necessary */
-       if (is->reset)
-               isdn_ppp_ccp_reset_free(is);
-
-       /* this slot is ready for new connections */
-       is->state = 0;
-}
-
-/*
- * get_arg .. ioctl helper
- */
-static int
-get_arg(void __user *b, void *val, int len)
-{
-       if (len <= 0)
-               len = sizeof(void *);
-       if (copy_from_user(val, b, len))
-               return -EFAULT;
-       return 0;
-}
-
-/*
- * set arg .. ioctl helper
- */
-static int
-set_arg(void __user *b, void *val, int len)
-{
-       if (len <= 0)
-               len = sizeof(void *);
-       if (copy_to_user(b, val, len))
-               return -EFAULT;
-       return 0;
-}
-
-#ifdef CONFIG_IPPP_FILTER
-static int get_filter(void __user *arg, struct sock_filter **p)
-{
-       struct sock_fprog uprog;
-       struct sock_filter *code = NULL;
-       int len;
-
-       if (copy_from_user(&uprog, arg, sizeof(uprog)))
-               return -EFAULT;
-
-       if (!uprog.len) {
-               *p = NULL;
-               return 0;
-       }
-
-       /* uprog.len is unsigned short, so no overflow here */
-       len = uprog.len * sizeof(struct sock_filter);
-       code = memdup_user(uprog.filter, len);
-       if (IS_ERR(code))
-               return PTR_ERR(code);
-
-       *p = code;
-       return uprog.len;
-}
-#endif /* CONFIG_IPPP_FILTER */
-
-/*
- * ippp device ioctl
- */
-int
-isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
-{
-       unsigned long val;
-       int r, i, j;
-       struct ippp_struct *is;
-       isdn_net_local *lp;
-       struct isdn_ppp_comp_data data;
-       void __user *argp = (void __user *)arg;
-
-       is = file->private_data;
-       lp = is->lp;
-
-       if (is->debug & 0x1)
-               printk(KERN_DEBUG "isdn_ppp_ioctl: minor: %d cmd: %x state: %x\n", min, cmd, is->state);
-
-       if (!(is->state & IPPP_OPEN))
-               return -EINVAL;
-
-       switch (cmd) {
-       case PPPIOCBUNDLE:
-#ifdef CONFIG_ISDN_MPP
-               if (!(is->state & IPPP_CONNECT))
-                       return -EINVAL;
-               if ((r = get_arg(argp, &val, sizeof(val))))
-                       return r;
-               printk(KERN_DEBUG "iPPP-bundle: minor: %d, slave unit: %d, master unit: %d\n",
-                      (int) min, (int) is->unit, (int) val);
-               return isdn_ppp_bundle(is, val);
-#else
-               return -1;
-#endif
-               break;
-       case PPPIOCGUNIT:       /* get ppp/isdn unit number */
-               if ((r = set_arg(argp, &is->unit, sizeof(is->unit))))
-                       return r;
-               break;
-       case PPPIOCGIFNAME:
-               if (!lp)
-                       return -EINVAL;
-               if ((r = set_arg(argp, lp->netdev->dev->name,
-                                strlen(lp->netdev->dev->name))))
-                       return r;
-               break;
-       case PPPIOCGMPFLAGS:    /* get configuration flags */
-               if ((r = set_arg(argp, &is->mpppcfg, sizeof(is->mpppcfg))))
-                       return r;
-               break;
-       case PPPIOCSMPFLAGS:    /* set configuration flags */
-               if ((r = get_arg(argp, &val, sizeof(val))))
-                       return r;
-               is->mpppcfg = val;
-               break;
-       case PPPIOCGFLAGS:      /* get configuration flags */
-               if ((r = set_arg(argp, &is->pppcfg, sizeof(is->pppcfg))))
-                       return r;
-               break;
-       case PPPIOCSFLAGS:      /* set configuration flags */
-               if ((r = get_arg(argp, &val, sizeof(val)))) {
-                       return r;
-               }
-               if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP) && (is->state & IPPP_CONNECT)) {
-                       if (lp) {
-                               /* OK .. we are ready to send buffers */
-                               is->pppcfg = val; /* isdn_ppp_xmit test for SC_ENABLE_IP !!! */
-                               netif_wake_queue(lp->netdev->dev);
-                               break;
-                       }
-               }
-               is->pppcfg = val;
-               break;
-       case PPPIOCGIDLE:       /* get idle time information */
-               if (lp) {
-                       struct ppp_idle pidle;
-                       pidle.xmit_idle = pidle.recv_idle = lp->huptimer;
-                       if ((r = set_arg(argp, &pidle, sizeof(struct ppp_idle))))
-                               return r;
-               }
-               break;
-       case PPPIOCSMRU:        /* set receive unit size for PPP */
-               if ((r = get_arg(argp, &val, sizeof(val))))
-                       return r;
-               is->mru = val;
-               break;
-       case PPPIOCSMPMRU:
-               break;
-       case PPPIOCSMPMTU:
-               break;
-       case PPPIOCSMAXCID:     /* set the maximum compression slot id */
-               if ((r = get_arg(argp, &val, sizeof(val))))
-                       return r;
-               val++;
-               if (is->maxcid != val) {
-#ifdef CONFIG_ISDN_PPP_VJ
-                       struct slcompress *sltmp;
-#endif
-                       if (is->debug & 0x1)
-                               printk(KERN_DEBUG "ippp, ioctl: changed MAXCID to %ld\n", val);
-                       is->maxcid = val;
-#ifdef CONFIG_ISDN_PPP_VJ
-                       sltmp = slhc_init(16, val);
-                       if (IS_ERR(sltmp))
-                               return PTR_ERR(sltmp);
-                       if (is->slcomp)
-                               slhc_free(is->slcomp);
-                       is->slcomp = sltmp;
-#endif
-               }
-               break;
-       case PPPIOCGDEBUG:
-               if ((r = set_arg(argp, &is->debug, sizeof(is->debug))))
-                       return r;
-               break;
-       case PPPIOCSDEBUG:
-               if ((r = get_arg(argp, &val, sizeof(val))))
-                       return r;
-               is->debug = val;
-               break;
-       case PPPIOCGCOMPRESSORS:
-       {
-               unsigned long protos[8] = {0,};
-               struct isdn_ppp_compressor *ipc = ipc_head;
-               while (ipc) {
-                       j = ipc->num / (sizeof(long) * 8);
-                       i = ipc->num % (sizeof(long) * 8);
-                       if (j < 8)
-                               protos[j] |= (1UL << i);
-                       ipc = ipc->next;
-               }
-               if ((r = set_arg(argp, protos, 8 * sizeof(long))))
-                       return r;
-       }
-       break;
-       case PPPIOCSCOMPRESSOR:
-               if ((r = get_arg(argp, &data, sizeof(struct isdn_ppp_comp_data))))
-                       return r;
-               return isdn_ppp_set_compressor(is, &data);
-       case PPPIOCGCALLINFO:
-       {
-               struct pppcallinfo pci;
-               memset((char *)&pci, 0, sizeof(struct pppcallinfo));
-               if (lp)
-               {
-                       strncpy(pci.local_num, lp->msn, 63);
-                       if (lp->dial) {
-                               strncpy(pci.remote_num, lp->dial->num, 63);
-                       }
-                       pci.charge_units = lp->charge;
-                       if (lp->outgoing)
-                               pci.calltype = CALLTYPE_OUTGOING;
-                       else
-                               pci.calltype = CALLTYPE_INCOMING;
-                       if (lp->flags & ISDN_NET_CALLBACK)
-                               pci.calltype |= CALLTYPE_CALLBACK;
-               }
-               return set_arg(argp, &pci, sizeof(struct pppcallinfo));
-       }
-#ifdef CONFIG_IPPP_FILTER
-       case PPPIOCSPASS:
-       {
-               struct sock_fprog_kern fprog;
-               struct sock_filter *code;
-               int err, len = get_filter(argp, &code);
-
-               if (len < 0)
-                       return len;
-
-               fprog.len = len;
-               fprog.filter = code;
-
-               if (is->pass_filter) {
-                       bpf_prog_destroy(is->pass_filter);
-                       is->pass_filter = NULL;
-               }
-               if (fprog.filter != NULL)
-                       err = bpf_prog_create(&is->pass_filter, &fprog);
-               else
-                       err = 0;
-               kfree(code);
-
-               return err;
-       }
-       case PPPIOCSACTIVE:
-       {
-               struct sock_fprog_kern fprog;
-               struct sock_filter *code;
-               int err, len = get_filter(argp, &code);
-
-               if (len < 0)
-                       return len;
-
-               fprog.len = len;
-               fprog.filter = code;
-
-               if (is->active_filter) {
-                       bpf_prog_destroy(is->active_filter);
-                       is->active_filter = NULL;
-               }
-               if (fprog.filter != NULL)
-                       err = bpf_prog_create(&is->active_filter, &fprog);
-               else
-                       err = 0;
-               kfree(code);
-
-               return err;
-       }
-#endif /* CONFIG_IPPP_FILTER */
-       default:
-               break;
-       }
-       return 0;
-}
-
-__poll_t
-isdn_ppp_poll(struct file *file, poll_table *wait)
-{
-       __poll_t mask;
-       struct ippp_buf_queue *bf, *bl;
-       u_long flags;
-       struct ippp_struct *is;
-
-       is = file->private_data;
-
-       if (is->debug & 0x2)
-               printk(KERN_DEBUG "isdn_ppp_poll: minor: %d\n",
-                      iminor(file_inode(file)));
-
-       /* just registers wait_queue hook. This doesn't really wait. */
-       poll_wait(file, &is->wq, wait);
-
-       if (!(is->state & IPPP_OPEN)) {
-               if (is->state == IPPP_CLOSEWAIT)
-                       return EPOLLHUP;
-               printk(KERN_DEBUG "isdn_ppp: device not open\n");
-               return EPOLLERR;
-       }
-       /* we're always ready to send .. */
-       mask = EPOLLOUT | EPOLLWRNORM;
-
-       spin_lock_irqsave(&is->buflock, flags);
-       bl = is->last;
-       bf = is->first;
-       /*
-        * if IPPP_NOBLOCK is set we return even if we have nothing to read
-        */
-       if (bf->next != bl || (is->state & IPPP_NOBLOCK)) {
-               is->state &= ~IPPP_NOBLOCK;
-               mask |= EPOLLIN | EPOLLRDNORM;
-       }
-       spin_unlock_irqrestore(&is->buflock, flags);
-       return mask;
-}
-
-/*
- *  fill up isdn_ppp_read() queue ..
- */
-
-static int
-isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot)
-{
-       struct ippp_buf_queue *bf, *bl;
-       u_long flags;
-       u_char *nbuf;
-       struct ippp_struct *is;
-
-       if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
-               printk(KERN_WARNING "ippp: illegal slot(%d).\n", slot);
-               return 0;
-       }
-       is = ippp_table[slot];
-
-       if (!(is->state & IPPP_CONNECT)) {
-               printk(KERN_DEBUG "ippp: device not activated.\n");
-               return 0;
-       }
-       nbuf = kmalloc(len + 4, GFP_ATOMIC);
-       if (!nbuf) {
-               printk(KERN_WARNING "ippp: Can't alloc buf\n");
-               return 0;
-       }
-       nbuf[0] = PPP_ALLSTATIONS;
-       nbuf[1] = PPP_UI;
-       nbuf[2] = proto >> 8;
-       nbuf[3] = proto & 0xff;
-       memcpy(nbuf + 4, buf, len);
-
-       spin_lock_irqsave(&is->buflock, flags);
-       bf = is->first;
-       bl = is->last;
-
-       if (bf == bl) {
-               printk(KERN_WARNING "ippp: Queue is full; discarding first buffer\n");
-               bf = bf->next;
-               kfree(bf->buf);
-               is->first = bf;
-       }
-       bl->buf = (char *) nbuf;
-       bl->len = len + 4;
-
-       is->last = bl->next;
-       spin_unlock_irqrestore(&is->buflock, flags);
-       wake_up_interruptible(&is->wq);
-       return len;
-}
-
-/*
- * read() .. non-blocking: ipppd calls it only after select()
- *           reports, that there is data
- */
-
-int
-isdn_ppp_read(int min, struct file *file, char __user *buf, int count)
-{
-       struct ippp_struct *is;
-       struct ippp_buf_queue *b;
-       u_long flags;
-       u_char *save_buf;
-
-       is = file->private_data;
-
-       if (!(is->state & IPPP_OPEN))
-               return 0;
-
-       spin_lock_irqsave(&is->buflock, flags);
-       b = is->first->next;
-       save_buf = b->buf;
-       if (!save_buf) {
-               spin_unlock_irqrestore(&is->buflock, flags);
-               return -EAGAIN;
-       }
-       if (b->len < count)
-               count = b->len;
-       b->buf = NULL;
-       is->first = b;
-
-       spin_unlock_irqrestore(&is->buflock, flags);
-       if (copy_to_user(buf, save_buf, count))
-               count = -EFAULT;
-       kfree(save_buf);
-
-       return count;
-}
-
-/*
- * ipppd wanna write a packet to the card .. non-blocking
- */
-
-int
-isdn_ppp_write(int min, struct file *file, const char __user *buf, int count)
-{
-       isdn_net_local *lp;
-       struct ippp_struct *is;
-       int proto;
-
-       is = file->private_data;
-
-       if (!(is->state & IPPP_CONNECT))
-               return 0;
-
-       lp = is->lp;
-
-       /* -> push it directly to the lowlevel interface */
-
-       if (!lp)
-               printk(KERN_DEBUG "isdn_ppp_write: lp == NULL\n");
-       else {
-               if (lp->isdn_device < 0 || lp->isdn_channel < 0) {
-                       unsigned char protobuf[4];
-                       /*
-                        * Don't reset huptimer for
-                        * LCP packets. (Echo requests).
-                        */
-                       if (copy_from_user(protobuf, buf, 4))
-                               return -EFAULT;
-
-                       proto = PPP_PROTOCOL(protobuf);
-                       if (proto != PPP_LCP)
-                               lp->huptimer = 0;
-
-                       return 0;
-               }
-
-               if ((dev->drv[lp->isdn_device]->flags & DRV_FLAG_RUNNING) &&
-                   lp->dialstate == 0 &&
-                   (lp->flags & ISDN_NET_CONNECTED)) {
-                       unsigned short hl;
-                       struct sk_buff *skb;
-                       unsigned char *cpy_buf;
-                       /*
-                        * we need to reserve enough space in front of
-                        * sk_buff. old call to dev_alloc_skb only reserved
-                        * 16 bytes, now we are looking what the driver want
-                        */
-                       hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen;
-                       skb = alloc_skb(hl + count, GFP_ATOMIC);
-                       if (!skb) {
-                               printk(KERN_WARNING "isdn_ppp_write: out of memory!\n");
-                               return count;
-                       }
-                       skb_reserve(skb, hl);
-                       cpy_buf = skb_put(skb, count);
-                       if (copy_from_user(cpy_buf, buf, count))
-                       {
-                               kfree_skb(skb);
-                               return -EFAULT;
-                       }
-
-                       /*
-                        * Don't reset huptimer for
-                        * LCP packets. (Echo requests).
-                        */
-                       proto = PPP_PROTOCOL(cpy_buf);
-                       if (proto != PPP_LCP)
-                               lp->huptimer = 0;
-
-                       if (is->debug & 0x40) {
-                               printk(KERN_DEBUG "ppp xmit: len %d\n", (int) skb->len);
-                               isdn_ppp_frame_log("xmit", skb->data, skb->len, 32, is->unit, lp->ppp_slot);
-                       }
-
-                       isdn_ppp_send_ccp(lp->netdev, lp, skb); /* keeps CCP/compression states in sync */
-
-                       isdn_net_write_super(lp, skb);
-               }
-       }
-       return count;
-}
-
-/*
- * init memory, structures etc.
- */
-
-int
-isdn_ppp_init(void)
-{
-       int i,
-               j;
-
-#ifdef CONFIG_ISDN_MPP
-       if (isdn_ppp_mp_bundle_array_init() < 0)
-               return -ENOMEM;
-#endif /* CONFIG_ISDN_MPP */
-
-       for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-               if (!(ippp_table[i] = kzalloc(sizeof(struct ippp_struct), GFP_KERNEL))) {
-                       printk(KERN_WARNING "isdn_ppp_init: Could not alloc ippp_table\n");
-                       for (j = 0; j < i; j++)
-                               kfree(ippp_table[j]);
-                       return -1;
-               }
-               spin_lock_init(&ippp_table[i]->buflock);
-               ippp_table[i]->state = 0;
-               ippp_table[i]->first = ippp_table[i]->rq + NUM_RCV_BUFFS - 1;
-               ippp_table[i]->last = ippp_table[i]->rq;
-
-               for (j = 0; j < NUM_RCV_BUFFS; j++) {
-                       ippp_table[i]->rq[j].buf = NULL;
-                       ippp_table[i]->rq[j].last = ippp_table[i]->rq +
-                               (NUM_RCV_BUFFS + j - 1) % NUM_RCV_BUFFS;
-                       ippp_table[i]->rq[j].next = ippp_table[i]->rq + (j + 1) % NUM_RCV_BUFFS;
-               }
-       }
-       return 0;
-}
-
-void
-isdn_ppp_cleanup(void)
-{
-       int i;
-
-       for (i = 0; i < ISDN_MAX_CHANNELS; i++)
-               kfree(ippp_table[i]);
-
-#ifdef CONFIG_ISDN_MPP
-       kfree(isdn_ppp_bundle_arr);
-#endif /* CONFIG_ISDN_MPP */
-
-}
-
-/*
- * check for address/control field and skip if allowed
- * retval != 0 -> discard packet silently
- */
-static int isdn_ppp_skip_ac(struct ippp_struct *is, struct sk_buff *skb)
-{
-       if (skb->len < 1)
-               return -1;
-
-       if (skb->data[0] == 0xff) {
-               if (skb->len < 2)
-                       return -1;
-
-               if (skb->data[1] != 0x03)
-                       return -1;
-
-               // skip address/control (AC) field
-               skb_pull(skb, 2);
-       } else {
-               if (is->pppcfg & SC_REJ_COMP_AC)
-                       // if AC compression was not negotiated, but used, discard packet
-                       return -1;
-       }
-       return 0;
-}
-
-/*
- * get the PPP protocol header and pull skb
- * retval < 0 -> discard packet silently
- */
-static int isdn_ppp_strip_proto(struct sk_buff *skb)
-{
-       int proto;
-
-       if (skb->len < 1)
-               return -1;
-
-       if (skb->data[0] & 0x1) {
-               // protocol field is compressed
-               proto = skb->data[0];
-               skb_pull(skb, 1);
-       } else {
-               if (skb->len < 2)
-                       return -1;
-               proto = ((int) skb->data[0] << 8) + skb->data[1];
-               skb_pull(skb, 2);
-       }
-       return proto;
-}
-
-
-/*
- * handler for incoming packets on a syncPPP interface
- */
-void isdn_ppp_receive(isdn_net_dev *net_dev, isdn_net_local *lp, struct sk_buff *skb)
-{
-       struct ippp_struct *is;
-       int slot;
-       int proto;
-
-       BUG_ON(net_dev->local->master); // we're called with the master device always
-
-       slot = lp->ppp_slot;
-       if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
-               printk(KERN_ERR "isdn_ppp_receive: lp->ppp_slot(%d)\n",
-                      lp->ppp_slot);
-               kfree_skb(skb);
-               return;
-       }
-       is = ippp_table[slot];
-
-       if (is->debug & 0x4) {
-               printk(KERN_DEBUG "ippp_receive: is:%08lx lp:%08lx slot:%d unit:%d len:%d\n",
-                      (long)is, (long)lp, lp->ppp_slot, is->unit, (int)skb->len);
-               isdn_ppp_frame_log("receive", skb->data, skb->len, 32, is->unit, lp->ppp_slot);
-       }
-
-       if (isdn_ppp_skip_ac(is, skb) < 0) {
-               kfree_skb(skb);
-               return;
-       }
-       proto = isdn_ppp_strip_proto(skb);
-       if (proto < 0) {
-               kfree_skb(skb);
-               return;
-       }
-
-#ifdef CONFIG_ISDN_MPP
-       if (is->compflags & SC_LINK_DECOMP_ON) {
-               skb = isdn_ppp_decompress(skb, is, NULL, &proto);
-               if (!skb) // decompression error
-                       return;
-       }
-
-       if (!(is->mpppcfg & SC_REJ_MP_PROT)) { // we agreed to receive MPPP
-               if (proto == PPP_MP) {
-                       isdn_ppp_mp_receive(net_dev, lp, skb);
-                       return;
-               }
-       }
-#endif
-       isdn_ppp_push_higher(net_dev, lp, skb, proto);
-}
-
-/*
- * we receive a reassembled frame, MPPP has been taken care of before.
- * address/control and protocol have been stripped from the skb
- * note: net_dev has to be master net_dev
- */
-static void
-isdn_ppp_push_higher(isdn_net_dev *net_dev, isdn_net_local *lp, struct sk_buff *skb, int proto)
-{
-       struct net_device *dev = net_dev->dev;
-       struct ippp_struct *is, *mis;
-       isdn_net_local *mlp = NULL;
-       int slot;
-
-       slot = lp->ppp_slot;
-       if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
-               printk(KERN_ERR "isdn_ppp_push_higher: lp->ppp_slot(%d)\n",
-                      lp->ppp_slot);
-               goto drop_packet;
-       }
-       is = ippp_table[slot];
-
-       if (lp->master) { // FIXME?
-               mlp = ISDN_MASTER_PRIV(lp);
-               slot = mlp->ppp_slot;
-               if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
-                       printk(KERN_ERR "isdn_ppp_push_higher: master->ppp_slot(%d)\n",
-                              lp->ppp_slot);
-                       goto drop_packet;
-               }
-       }
-       mis = ippp_table[slot];
-
-       if (is->debug & 0x10) {
-               printk(KERN_DEBUG "push, skb %d %04x\n", (int) skb->len, proto);
-               isdn_ppp_frame_log("rpush", skb->data, skb->len, 32, is->unit, lp->ppp_slot);
-       }
-       if (mis->compflags & SC_DECOMP_ON) {
-               skb = isdn_ppp_decompress(skb, is, mis, &proto);
-               if (!skb) // decompression error
-                       return;
-       }
-       switch (proto) {
-       case PPP_IPX:  /* untested */
-               if (is->debug & 0x20)
-                       printk(KERN_DEBUG "isdn_ppp: IPX\n");
-               skb->protocol = htons(ETH_P_IPX);
-               break;
-       case PPP_IP:
-               if (is->debug & 0x20)
-                       printk(KERN_DEBUG "isdn_ppp: IP\n");
-               skb->protocol = htons(ETH_P_IP);
-               break;
-       case PPP_COMP:
-       case PPP_COMPFRAG:
-               printk(KERN_INFO "isdn_ppp: unexpected compressed frame dropped\n");
-               goto drop_packet;
-#ifdef CONFIG_ISDN_PPP_VJ
-       case PPP_VJC_UNCOMP:
-               if (is->debug & 0x20)
-                       printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n");
-               if (net_dev->local->ppp_slot < 0) {
-                       printk(KERN_ERR "%s: net_dev->local->ppp_slot(%d) out of range\n",
-                              __func__, net_dev->local->ppp_slot);
-                       goto drop_packet;
-               }
-               if (slhc_remember(ippp_table[net_dev->local->ppp_slot]->slcomp, skb->data, skb->len) <= 0) {
-                       printk(KERN_WARNING "isdn_ppp: received illegal VJC_UNCOMP frame!\n");
-                       goto drop_packet;
-               }
-               skb->protocol = htons(ETH_P_IP);
-               break;
-       case PPP_VJC_COMP:
-               if (is->debug & 0x20)
-                       printk(KERN_DEBUG "isdn_ppp: VJC_COMP\n");
-               {
-                       struct sk_buff *skb_old = skb;
-                       int pkt_len;
-                       skb = dev_alloc_skb(skb_old->len + 128);
-
-                       if (!skb) {
-                               printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name);
-                               skb = skb_old;
-                               goto drop_packet;
-                       }
-                       skb_put(skb, skb_old->len + 128);
-                       skb_copy_from_linear_data(skb_old, skb->data,
-                                                 skb_old->len);
-                       if (net_dev->local->ppp_slot < 0) {
-                               printk(KERN_ERR "%s: net_dev->local->ppp_slot(%d) out of range\n",
-                                      __func__, net_dev->local->ppp_slot);
-                               goto drop_packet;
-                       }
-                       pkt_len = slhc_uncompress(ippp_table[net_dev->local->ppp_slot]->slcomp,
-                                                 skb->data, skb_old->len);
-                       kfree_skb(skb_old);
-                       if (pkt_len < 0)
-                               goto drop_packet;
-
-                       skb_trim(skb, pkt_len);
-                       skb->protocol = htons(ETH_P_IP);
-               }
-               break;
-#endif
-       case PPP_CCP:
-       case PPP_CCPFRAG:
-               isdn_ppp_receive_ccp(net_dev, lp, skb, proto);
-               /* Dont pop up ResetReq/Ack stuff to the daemon any
-                  longer - the job is done already */
-               if (skb->data[0] == CCP_RESETREQ ||
-                   skb->data[0] == CCP_RESETACK)
-                       break;
-               /* fall through */
-       default:
-               isdn_ppp_fill_rq(skb->data, skb->len, proto, lp->ppp_slot);     /* push data to pppd device */
-               kfree_skb(skb);
-               return;
-       }
-
-#ifdef CONFIG_IPPP_FILTER
-       /* check if the packet passes the pass and active filters
-        * the filter instructions are constructed assuming
-        * a four-byte PPP header on each packet (which is still present) */
-       skb_push(skb, 4);
-
-       {
-               u_int16_t *p = (u_int16_t *) skb->data;
-
-               *p = 0; /* indicate inbound */
-       }
-
-       if (is->pass_filter
-           && BPF_PROG_RUN(is->pass_filter, skb) == 0) {
-               if (is->debug & 0x2)
-                       printk(KERN_DEBUG "IPPP: inbound frame filtered.\n");
-               kfree_skb(skb);
-               return;
-       }
-       if (!(is->active_filter
-             && BPF_PROG_RUN(is->active_filter, skb) == 0)) {
-               if (is->debug & 0x2)
-                       printk(KERN_DEBUG "IPPP: link-active filter: resetting huptimer.\n");
-               lp->huptimer = 0;
-               if (mlp)
-                       mlp->huptimer = 0;
-       }
-       skb_pull(skb, 4);
-#else /* CONFIG_IPPP_FILTER */
-       lp->huptimer = 0;
-       if (mlp)
-               mlp->huptimer = 0;
-#endif /* CONFIG_IPPP_FILTER */
-       skb->dev = dev;
-       skb_reset_mac_header(skb);
-       netif_rx(skb);
-       /* net_dev->local->stats.rx_packets++; done in isdn_net.c */
-       return;
-
-drop_packet:
-       net_dev->local->stats.rx_dropped++;
-       kfree_skb(skb);
-}
-
-/*
- * isdn_ppp_skb_push ..
- * checks whether we have enough space at the beginning of the skb
- * and allocs a new SKB if necessary
- */
-static unsigned char *isdn_ppp_skb_push(struct sk_buff **skb_p, int len)
-{
-       struct sk_buff *skb = *skb_p;
-
-       if (skb_headroom(skb) < len) {
-               struct sk_buff *nskb = skb_realloc_headroom(skb, len);
-
-               if (!nskb) {
-                       printk(KERN_ERR "isdn_ppp_skb_push: can't realloc headroom!\n");
-                       dev_kfree_skb(skb);
-                       return NULL;
-               }
-               printk(KERN_DEBUG "isdn_ppp_skb_push:under %d %d\n", skb_headroom(skb), len);
-               dev_kfree_skb(skb);
-               *skb_p = nskb;
-               return skb_push(nskb, len);
-       }
-       return skb_push(skb, len);
-}
-
-/*
- * send ppp frame .. we expect a PIDCOMPressable proto --
- *  (here: currently always PPP_IP,PPP_VJC_COMP,PPP_VJC_UNCOMP)
- *
- * VJ compression may change skb pointer!!! .. requeue with old
- * skb isn't allowed!!
- */
-
-int
-isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
-{
-       isdn_net_local *lp, *mlp;
-       isdn_net_dev *nd;
-       unsigned int proto = PPP_IP;     /* 0x21 */
-       struct ippp_struct *ipt, *ipts;
-       int slot, retval = NETDEV_TX_OK;
-
-       mlp = netdev_priv(netdev);
-       nd = mlp->netdev;       /* get master lp */
-
-       slot = mlp->ppp_slot;
-       if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
-               printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n",
-                      mlp->ppp_slot);
-               kfree_skb(skb);
-               goto out;
-       }
-       ipts = ippp_table[slot];
-
-       if (!(ipts->pppcfg & SC_ENABLE_IP)) {   /* PPP connected ? */
-               if (ipts->debug & 0x1)
-                       printk(KERN_INFO "%s: IP frame delayed.\n", netdev->name);
-               retval = NETDEV_TX_BUSY;
-               goto out;
-       }
-
-       switch (ntohs(skb->protocol)) {
-       case ETH_P_IP:
-               proto = PPP_IP;
-               break;
-       case ETH_P_IPX:
-               proto = PPP_IPX;        /* untested */
-               break;
-       default:
-               printk(KERN_ERR "isdn_ppp: skipped unsupported protocol: %#x.\n",
-                      skb->protocol);
-               dev_kfree_skb(skb);
-               goto out;
-       }
-
-       lp = isdn_net_get_locked_lp(nd);
-       if (!lp) {
-               printk(KERN_WARNING "%s: all channels busy - requeuing!\n", netdev->name);
-               retval = NETDEV_TX_BUSY;
-               goto out;
-       }
-       /* we have our lp locked from now on */
-
-       slot = lp->ppp_slot;
-       if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
-               printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n",
-                      lp->ppp_slot);
-               kfree_skb(skb);
-               goto unlock;
-       }
-       ipt = ippp_table[slot];
-
-       /*
-        * after this line .. requeueing in the device queue is no longer allowed!!!
-        */
-
-       /* Pull off the fake header we stuck on earlier to keep
-        * the fragmentation code happy.
-        */
-       skb_pull(skb, IPPP_MAX_HEADER);
-
-#ifdef CONFIG_IPPP_FILTER
-       /* check if we should pass this packet
-        * the filter instructions are constructed assuming
-        * a four-byte PPP header on each packet */
-       *(u8 *)skb_push(skb, 4) = 1; /* indicate outbound */
-
-       {
-               __be16 *p = (__be16 *)skb->data;
-
-               p++;
-               *p = htons(proto);
-       }
-
-       if (ipt->pass_filter
-           && BPF_PROG_RUN(ipt->pass_filter, skb) == 0) {
-               if (ipt->debug & 0x4)
-                       printk(KERN_DEBUG "IPPP: outbound frame filtered.\n");
-               kfree_skb(skb);
-               goto unlock;
-       }
-       if (!(ipt->active_filter
-             && BPF_PROG_RUN(ipt->active_filter, skb) == 0)) {
-               if (ipt->debug & 0x4)
-                       printk(KERN_DEBUG "IPPP: link-active filter: resetting huptimer.\n");
-               lp->huptimer = 0;
-       }
-       skb_pull(skb, 4);
-#else /* CONFIG_IPPP_FILTER */
-       lp->huptimer = 0;
-#endif /* CONFIG_IPPP_FILTER */
-
-       if (ipt->debug & 0x4)
-               printk(KERN_DEBUG "xmit skb, len %d\n", (int) skb->len);
-       if (ipts->debug & 0x40)
-               isdn_ppp_frame_log("xmit0", skb->data, skb->len, 32, ipts->unit, lp->ppp_slot);
-
-#ifdef CONFIG_ISDN_PPP_VJ
-       if (proto == PPP_IP && ipts->pppcfg & SC_COMP_TCP) {    /* ipts here? probably yes, but check this again */
-               struct sk_buff *new_skb;
-               unsigned short hl;
-               /*
-                * we need to reserve enough space in front of
-                * sk_buff. old call to dev_alloc_skb only reserved
-                * 16 bytes, now we are looking what the driver want.
-                */
-               hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen + IPPP_MAX_HEADER;
-               /*
-                * Note: hl might still be insufficient because the method
-                * above does not account for a possibible MPPP slave channel
-                * which had larger HL header space requirements than the
-                * master.
-                */
-               new_skb = alloc_skb(hl + skb->len, GFP_ATOMIC);
-               if (new_skb) {
-                       u_char *buf;
-                       int pktlen;
-
-                       skb_reserve(new_skb, hl);
-                       new_skb->dev = skb->dev;
-                       skb_put(new_skb, skb->len);
-                       buf = skb->data;
-
-                       pktlen = slhc_compress(ipts->slcomp, skb->data, skb->len, new_skb->data,
-                                              &buf, !(ipts->pppcfg & SC_NO_TCP_CCID));
-
-                       if (buf != skb->data) {
-                               if (new_skb->data != buf)
-                                       printk(KERN_ERR "isdn_ppp: FATAL error after slhc_compress!!\n");
-                               dev_kfree_skb(skb);
-                               skb = new_skb;
-                       } else {
-                               dev_kfree_skb(new_skb);
-                       }
-
-                       skb_trim(skb, pktlen);
-                       if (skb->data[0] & SL_TYPE_COMPRESSED_TCP) {    /* cslip? style -> PPP */
-                               proto = PPP_VJC_COMP;
-                               skb->data[0] ^= SL_TYPE_COMPRESSED_TCP;
-                       } else {
-                               if (skb->data[0] >= SL_TYPE_UNCOMPRESSED_TCP)
-                                       proto = PPP_VJC_UNCOMP;
-                               skb->data[0] = (skb->data[0] & 0x0f) | 0x40;
-                       }
-               }
-       }
-#endif
-
-       /*
-        * normal (single link) or bundle compression
-        */
-       if (ipts->compflags & SC_COMP_ON) {
-               /* We send compressed only if both down- und upstream
-                  compression is negotiated, that means, CCP is up */
-               if (ipts->compflags & SC_DECOMP_ON) {
-                       skb = isdn_ppp_compress(skb, &proto, ipt, ipts, 0);
-               } else {
-                       printk(KERN_DEBUG "isdn_ppp: CCP not yet up - sending as-is\n");
-               }
-       }
-
-       if (ipt->debug & 0x24)
-               printk(KERN_DEBUG "xmit2 skb, len %d, proto %04x\n", (int) skb->len, proto);
-
-#ifdef CONFIG_ISDN_MPP
-       if (ipt->mpppcfg & SC_MP_PROT) {
-               /* we get mp_seqno from static isdn_net_local */
-               long mp_seqno = ipts->mp_seqno;
-               ipts->mp_seqno++;
-               if (ipt->mpppcfg & SC_OUT_SHORT_SEQ) {
-                       unsigned char *data = isdn_ppp_skb_push(&skb, 3);
-                       if (!data)
-                               goto unlock;
-                       mp_seqno &= 0xfff;
-                       data[0] = MP_BEGIN_FRAG | MP_END_FRAG | ((mp_seqno >> 8) & 0xf);        /* (B)egin & (E)ndbit .. */
-                       data[1] = mp_seqno & 0xff;
-                       data[2] = proto;        /* PID compression */
-               } else {
-                       unsigned char *data = isdn_ppp_skb_push(&skb, 5);
-                       if (!data)
-                               goto unlock;
-                       data[0] = MP_BEGIN_FRAG | MP_END_FRAG;  /* (B)egin & (E)ndbit .. */
-                       data[1] = (mp_seqno >> 16) & 0xff;      /* sequence number: 24bit */
-                       data[2] = (mp_seqno >> 8) & 0xff;
-                       data[3] = (mp_seqno >> 0) & 0xff;
-                       data[4] = proto;        /* PID compression */
-               }
-               proto = PPP_MP; /* MP Protocol, 0x003d */
-       }
-#endif
-
-       /*
-        * 'link in bundle' compression  ...
-        */
-       if (ipt->compflags & SC_LINK_COMP_ON)
-               skb = isdn_ppp_compress(skb, &proto, ipt, ipts, 1);
-
-       if ((ipt->pppcfg & SC_COMP_PROT) && (proto <= 0xff)) {
-               unsigned char *data = isdn_ppp_skb_push(&skb, 1);
-               if (!data)
-                       goto unlock;
-               data[0] = proto & 0xff;
-       }
-       else {
-               unsigned char *data = isdn_ppp_skb_push(&skb, 2);
-               if (!data)
-                       goto unlock;
-               data[0] = (proto >> 8) & 0xff;
-               data[1] = proto & 0xff;
-       }
-       if (!(ipt->pppcfg & SC_COMP_AC)) {
-               unsigned char *data = isdn_ppp_skb_push(&skb, 2);
-               if (!data)
-                       goto unlock;
-               data[0] = 0xff;    /* All Stations */
-               data[1] = 0x03;    /* Unnumbered information */
-       }
-
-       /* tx-stats are now updated via BSENT-callback */
-
-       if (ipts->debug & 0x40) {
-               printk(KERN_DEBUG "skb xmit: len: %d\n", (int) skb->len);
-               isdn_ppp_frame_log("xmit", skb->data, skb->len, 32, ipt->unit, lp->ppp_slot);
-       }
-
-       isdn_net_writebuf_skb(lp, skb);
-
-unlock:
-       spin_unlock_bh(&lp->xmit_lock);
-out:
-       return retval;
-}
-
-#ifdef CONFIG_IPPP_FILTER
-/*
- * check if this packet may trigger auto-dial.
- */
-
-int isdn_ppp_autodial_filter(struct sk_buff *skb, isdn_net_local *lp)
-{
-       struct ippp_struct *is = ippp_table[lp->ppp_slot];
-       u_int16_t proto;
-       int drop = 0;
-
-       switch (ntohs(skb->protocol)) {
-       case ETH_P_IP:
-               proto = PPP_IP;
-               break;
-       case ETH_P_IPX:
-               proto = PPP_IPX;
-               break;
-       default:
-               printk(KERN_ERR "isdn_ppp_autodial_filter: unsupported protocol 0x%x.\n",
-                      skb->protocol);
-               return 1;
-       }
-
-       /* the filter instructions are constructed assuming
-        * a four-byte PPP header on each packet. we have to
-        * temporarily remove part of the fake header stuck on
-        * earlier.
-        */
-       *(u8 *)skb_pull(skb, IPPP_MAX_HEADER - 4) = 1; /* indicate outbound */
-
-       {
-               __be16 *p = (__be16 *)skb->data;
-
-               p++;
-               *p = htons(proto);
-       }
-
-       drop |= is->pass_filter
-               && BPF_PROG_RUN(is->pass_filter, skb) == 0;
-       drop |= is->active_filter
-               && BPF_PROG_RUN(is->active_filter, skb) == 0;
-
-       skb_push(skb, IPPP_MAX_HEADER - 4);
-       return drop;
-}
-#endif
-#ifdef CONFIG_ISDN_MPP
-
-/* this is _not_ rfc1990 header, but something we convert both short and long
- * headers to for convinience's sake:
- *     byte 0 is flags as in rfc1990
- *     bytes 1...4 is 24-bit seqence number converted to host byte order
- */
-#define MP_HEADER_LEN  5
-
-#define MP_LONGSEQ_MASK                0x00ffffff
-#define MP_SHORTSEQ_MASK       0x00000fff
-#define MP_LONGSEQ_MAX         MP_LONGSEQ_MASK
-#define MP_SHORTSEQ_MAX                MP_SHORTSEQ_MASK
-#define MP_LONGSEQ_MAXBIT      ((MP_LONGSEQ_MASK + 1) >> 1)
-#define MP_SHORTSEQ_MAXBIT     ((MP_SHORTSEQ_MASK + 1) >> 1)
-
-/* sequence-wrap safe comparisons (for long sequence)*/
-#define MP_LT(a, b)    ((a - b) & MP_LONGSEQ_MAXBIT)
-#define MP_LE(a, b)    !((b - a) & MP_LONGSEQ_MAXBIT)
-#define MP_GT(a, b)    ((b - a) & MP_LONGSEQ_MAXBIT)
-#define MP_GE(a, b)    !((a - b) & MP_LONGSEQ_MAXBIT)
-
-#define MP_SEQ(f)      ((*(u32 *)(f->data + 1)))
-#define MP_FLAGS(f)    (f->data[0])
-
-static int isdn_ppp_mp_bundle_array_init(void)
-{
-       int i;
-       int sz = ISDN_MAX_CHANNELS * sizeof(ippp_bundle);
-       if ((isdn_ppp_bundle_arr = kzalloc(sz, GFP_KERNEL)) == NULL)
-               return -ENOMEM;
-       for (i = 0; i < ISDN_MAX_CHANNELS; i++)
-               spin_lock_init(&isdn_ppp_bundle_arr[i].lock);
-       return 0;
-}
-
-static ippp_bundle *isdn_ppp_mp_bundle_alloc(void)
-{
-       int i;
-       for (i = 0; i < ISDN_MAX_CHANNELS; i++)
-               if (isdn_ppp_bundle_arr[i].ref_ct <= 0)
-                       return (isdn_ppp_bundle_arr + i);
-       return NULL;
-}
-
-static int isdn_ppp_mp_init(isdn_net_local *lp, ippp_bundle *add_to)
-{
-       struct ippp_struct *is;
-
-       if (lp->ppp_slot < 0) {
-               printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
-                      __func__, lp->ppp_slot);
-               return (-EINVAL);
-       }
-
-       is = ippp_table[lp->ppp_slot];
-       if (add_to) {
-               if (lp->netdev->pb)
-                       lp->netdev->pb->ref_ct--;
-               lp->netdev->pb = add_to;
-       } else {                /* first link in a bundle */
-               is->mp_seqno = 0;
-               if ((lp->netdev->pb = isdn_ppp_mp_bundle_alloc()) == NULL)
-                       return -ENOMEM;
-               lp->next = lp->last = lp;       /* nobody else in a queue */
-               lp->netdev->pb->frags = NULL;
-               lp->netdev->pb->frames = 0;
-               lp->netdev->pb->seq = UINT_MAX;
-       }
-       lp->netdev->pb->ref_ct++;
-
-       is->last_link_seqno = 0;
-       return 0;
-}
-
-static u32 isdn_ppp_mp_get_seq(int short_seq,
-                              struct sk_buff *skb, u32 last_seq);
-static struct sk_buff *isdn_ppp_mp_discard(ippp_bundle *mp,
-                                          struct sk_buff *from, struct sk_buff *to);
-static void isdn_ppp_mp_reassembly(isdn_net_dev *net_dev, isdn_net_local *lp,
-                                  struct sk_buff *from, struct sk_buff *to);
-static void isdn_ppp_mp_free_skb(ippp_bundle *mp, struct sk_buff *skb);
-static void isdn_ppp_mp_print_recv_pkt(int slot, struct sk_buff *skb);
-
-static void isdn_ppp_mp_receive(isdn_net_dev *net_dev, isdn_net_local *lp,
-                               struct sk_buff *skb)
-{
-       struct ippp_struct *is;
-       isdn_net_local *lpq;
-       ippp_bundle *mp;
-       isdn_mppp_stats *stats;
-       struct sk_buff *newfrag, *frag, *start, *nextf;
-       u32 newseq, minseq, thisseq;
-       unsigned long flags;
-       int slot;
-
-       spin_lock_irqsave(&net_dev->pb->lock, flags);
-       mp = net_dev->pb;
-       stats = &mp->stats;
-       slot = lp->ppp_slot;
-       if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
-               printk(KERN_ERR "%s: lp->ppp_slot(%d)\n",
-                      __func__, lp->ppp_slot);
-               stats->frame_drops++;
-               dev_kfree_skb(skb);
-               spin_unlock_irqrestore(&mp->lock, flags);
-               return;
-       }
-       is = ippp_table[slot];
-       if (++mp->frames > stats->max_queue_len)
-               stats->max_queue_len = mp->frames;
-
-       if (is->debug & 0x8)
-               isdn_ppp_mp_print_recv_pkt(lp->ppp_slot, skb);
-
-       newseq = isdn_ppp_mp_get_seq(is->mpppcfg & SC_IN_SHORT_SEQ,
-                                    skb, is->last_link_seqno);
-
-
-       /* if this packet seq # is less than last already processed one,
-        * toss it right away, but check for sequence start case first
-        */
-       if (mp->seq > MP_LONGSEQ_MAX && (newseq & MP_LONGSEQ_MAXBIT)) {
-               mp->seq = newseq;       /* the first packet: required for
-                                        * rfc1990 non-compliant clients --
-                                        * prevents constant packet toss */
-       } else if (MP_LT(newseq, mp->seq)) {
-               stats->frame_drops++;
-               isdn_ppp_mp_free_skb(mp, skb);
-               spin_unlock_irqrestore(&mp->lock, flags);
-               return;
-       }
-
-       /* find the minimum received sequence number over all links */
-       is->last_link_seqno = minseq = newseq;
-       for (lpq = net_dev->queue;;) {
-               slot = lpq->ppp_slot;
-               if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
-                       printk(KERN_ERR "%s: lpq->ppp_slot(%d)\n",
-                              __func__, lpq->ppp_slot);
-               } else {
-                       u32 lls = ippp_table[slot]->last_link_seqno;
-                       if (MP_LT(lls, minseq))
-                               minseq = lls;
-               }
-               if ((lpq = lpq->next) == net_dev->queue)
-                       break;
-       }
-       if (MP_LT(minseq, mp->seq))
-               minseq = mp->seq;       /* can't go beyond already processed
-                                        * packets */
-       newfrag = skb;
-
-       /* if this new fragment is before the first one, then enqueue it now. */
-       if ((frag = mp->frags) == NULL || MP_LT(newseq, MP_SEQ(frag))) {
-               newfrag->next = frag;
-               mp->frags = frag = newfrag;
-               newfrag = NULL;
-       }
-
-       start = MP_FLAGS(frag) & MP_BEGIN_FRAG &&
-               MP_SEQ(frag) == mp->seq ? frag : NULL;
-
-       /*
-        * main fragment traversing loop
-        *
-        * try to accomplish several tasks:
-        * - insert new fragment into the proper sequence slot (once that's done
-        *   newfrag will be set to NULL)
-        * - reassemble any complete fragment sequence (non-null 'start'
-        *   indicates there is a contiguous sequence present)
-        * - discard any incomplete sequences that are below minseq -- due
-        *   to the fact that sender always increment sequence number, if there
-        *   is an incomplete sequence below minseq, no new fragments would
-        *   come to complete such sequence and it should be discarded
-        *
-        * loop completes when we accomplished the following tasks:
-        * - new fragment is inserted in the proper sequence ('newfrag' is
-        *   set to NULL)
-        * - we hit a gap in the sequence, so no reassembly/processing is
-        *   possible ('start' would be set to NULL)
-        *
-        * algorithm for this code is derived from code in the book
-        * 'PPP Design And Debugging' by James Carlson (Addison-Wesley)
-        */
-       while (start != NULL || newfrag != NULL) {
-
-               thisseq = MP_SEQ(frag);
-               nextf = frag->next;
-
-               /* drop any duplicate fragments */
-               if (newfrag != NULL && thisseq == newseq) {
-                       isdn_ppp_mp_free_skb(mp, newfrag);
-                       newfrag = NULL;
-               }
-
-               /* insert new fragment before next element if possible. */
-               if (newfrag != NULL && (nextf == NULL ||
-                                       MP_LT(newseq, MP_SEQ(nextf)))) {
-                       newfrag->next = nextf;
-                       frag->next = nextf = newfrag;
-                       newfrag = NULL;
-               }
-
-               if (start != NULL) {
-                       /* check for misplaced start */
-                       if (start != frag && (MP_FLAGS(frag) & MP_BEGIN_FRAG)) {
-                               printk(KERN_WARNING"isdn_mppp(seq %d): new "
-                                      "BEGIN flag with no prior END", thisseq);
-                               stats->seqerrs++;
-                               stats->frame_drops++;
-                               start = isdn_ppp_mp_discard(mp, start, frag);
-                               nextf = frag->next;
-                       }
-               } else if (MP_LE(thisseq, minseq)) {
-                       if (MP_FLAGS(frag) & MP_BEGIN_FRAG)
-                               start = frag;
-                       else {
-                               if (MP_FLAGS(frag) & MP_END_FRAG)
-                                       stats->frame_drops++;
-                               if (mp->frags == frag)
-                                       mp->frags = nextf;
-                               isdn_ppp_mp_free_skb(mp, frag);
-                               frag = nextf;
-                               continue;
-                       }
-               }
-
-               /* if start is non-null and we have end fragment, then
-                * we have full reassembly sequence -- reassemble
-                * and process packet now
-                */
-               if (start != NULL && (MP_FLAGS(frag) & MP_END_FRAG)) {
-                       minseq = mp->seq = (thisseq + 1) & MP_LONGSEQ_MASK;
-                       /* Reassemble the packet then dispatch it */
-                       isdn_ppp_mp_reassembly(net_dev, lp, start, nextf);
-
-                       start = NULL;
-                       frag = NULL;
-
-                       mp->frags = nextf;
-               }
-
-               /* check if need to update start pointer: if we just
-                * reassembled the packet and sequence is contiguous
-                * then next fragment should be the start of new reassembly
-                * if sequence is contiguous, but we haven't reassembled yet,
-                * keep going.
-                * if sequence is not contiguous, either clear everything
-                * below low watermark and set start to the next frag or
-                * clear start ptr.
-                */
-               if (nextf != NULL &&
-                   ((thisseq + 1) & MP_LONGSEQ_MASK) == MP_SEQ(nextf)) {
-                       /* if we just reassembled and the next one is here,
-                        * then start another reassembly. */
-
-                       if (frag == NULL) {
-                               if (MP_FLAGS(nextf) & MP_BEGIN_FRAG)
-                                       start = nextf;
-                               else
-                               {
-                                       printk(KERN_WARNING"isdn_mppp(seq %d):"
-                                              " END flag with no following "
-                                              "BEGIN", thisseq);
-                                       stats->seqerrs++;
-                               }
-                       }
-
-               } else {
-                       if (nextf != NULL && frag != NULL &&
-                           MP_LT(thisseq, minseq)) {
-                               /* we've got a break in the sequence
-                                * and we not at the end yet
-                                * and we did not just reassembled
-                                *(if we did, there wouldn't be anything before)
-                                * and we below the low watermark
-                                * discard all the frames below low watermark
-                                * and start over */
-                               stats->frame_drops++;
-                               mp->frags = isdn_ppp_mp_discard(mp, start, nextf);
-                       }
-                       /* break in the sequence, no reassembly */
-                       start = NULL;
-               }
-
-               frag = nextf;
-       }       /* while -- main loop */
-
-       if (mp->frags == NULL)
-               mp->frags = frag;
-
-       /* rather straighforward way to deal with (not very) possible
-        * queue overflow */
-       if (mp->frames > MP_MAX_QUEUE_LEN) {
-               stats->overflows++;
-               while (mp->frames > MP_MAX_QUEUE_LEN) {
-                       frag = mp->frags->next;
-                       isdn_ppp_mp_free_skb(mp, mp->frags);
-                       mp->frags = frag;
-               }
-       }
-       spin_unlock_irqrestore(&mp->lock, flags);
-}
-
-static void isdn_ppp_mp_cleanup(isdn_net_local *lp)
-{
-       struct sk_buff *frag = lp->netdev->pb->frags;
-       struct sk_buff *nextfrag;
-       while (frag) {
-               nextfrag = frag->next;
-               isdn_ppp_mp_free_skb(lp->netdev->pb, frag);
-               frag = nextfrag;
-       }
-       lp->netdev->pb->frags = NULL;
-}
-
-static u32 isdn_ppp_mp_get_seq(int short_seq,
-                              struct sk_buff *skb, u32 last_seq)
-{
-       u32 seq;
-       int flags = skb->data[0] & (MP_BEGIN_FRAG | MP_END_FRAG);
-
-       if (!short_seq)
-       {
-               seq = ntohl(*(__be32 *)skb->data) & MP_LONGSEQ_MASK;
-               skb_push(skb, 1);
-       }
-       else
-       {
-               /* convert 12-bit short seq number to 24-bit long one
-                */
-               seq = ntohs(*(__be16 *)skb->data) & MP_SHORTSEQ_MASK;
-
-               /* check for seqence wrap */
-               if (!(seq &  MP_SHORTSEQ_MAXBIT) &&
-                   (last_seq &  MP_SHORTSEQ_MAXBIT) &&
-                   (unsigned long)last_seq <= MP_LONGSEQ_MAX)
-                       seq |= (last_seq + MP_SHORTSEQ_MAX + 1) &
-                               (~MP_SHORTSEQ_MASK & MP_LONGSEQ_MASK);
-               else
-                       seq |= last_seq & (~MP_SHORTSEQ_MASK & MP_LONGSEQ_MASK);
-
-               skb_push(skb, 3);       /* put converted seqence back in skb */
-       }
-       *(u32 *)(skb->data + 1) = seq;  /* put seqence back in _host_ byte
-                                        * order */
-       skb->data[0] = flags;           /* restore flags */
-       return seq;
-}
-
-static struct sk_buff *isdn_ppp_mp_discard(ippp_bundle *mp,
-                                          struct sk_buff *from,
-                                          struct sk_buff *to)
-{
-       if (from)
-               while (from != to) {
-                       struct sk_buff *next = from->next;
-                       isdn_ppp_mp_free_skb(mp, from);
-                       from = next;
-               }
-       return from;
-}
-
-static void isdn_ppp_mp_reassembly(isdn_net_dev *net_dev, isdn_net_local *lp,
-                                  struct sk_buff *from, struct sk_buff *to)
-{
-       ippp_bundle *mp = net_dev->pb;
-       int proto;
-       struct sk_buff *skb;
-       unsigned int tot_len;
-
-       if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
-               printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
-                      __func__, lp->ppp_slot);
-               return;
-       }
-       if (MP_FLAGS(from) == (MP_BEGIN_FRAG | MP_END_FRAG)) {
-               if (ippp_table[lp->ppp_slot]->debug & 0x40)
-                       printk(KERN_DEBUG "isdn_mppp: reassembly: frame %d, "
-                              "len %d\n", MP_SEQ(from), from->len);
-               skb = from;
-               skb_pull(skb, MP_HEADER_LEN);
-               mp->frames--;
-       } else {
-               struct sk_buff *frag;
-               int n;
-
-               for (tot_len = n = 0, frag = from; frag != to; frag = frag->next, n++)
-                       tot_len += frag->len - MP_HEADER_LEN;
-
-               if (ippp_table[lp->ppp_slot]->debug & 0x40)
-                       printk(KERN_DEBUG"isdn_mppp: reassembling frames %d "
-                              "to %d, len %d\n", MP_SEQ(from),
-                              (MP_SEQ(from) + n - 1) & MP_LONGSEQ_MASK, tot_len);
-               if ((skb = dev_alloc_skb(tot_len)) == NULL) {
-                       printk(KERN_ERR "isdn_mppp: cannot allocate sk buff "
-                              "of size %d\n", tot_len);
-                       isdn_ppp_mp_discard(mp, from, to);
-                       return;
-               }
-
-               while (from != to) {
-                       unsigned int len = from->len - MP_HEADER_LEN;
-
-                       skb_copy_from_linear_data_offset(from, MP_HEADER_LEN,
-                                                        skb_put(skb, len),
-                                                        len);
-                       frag = from->next;
-                       isdn_ppp_mp_free_skb(mp, from);
-                       from = frag;
-               }
-       }
-       proto = isdn_ppp_strip_proto(skb);
-       isdn_ppp_push_higher(net_dev, lp, skb, proto);
-}
-
-static void isdn_ppp_mp_free_skb(ippp_bundle *mp, struct sk_buff *skb)
-{
-       dev_kfree_skb(skb);
-       mp->frames--;
-}
-
-static void isdn_ppp_mp_print_recv_pkt(int slot, struct sk_buff *skb)
-{
-       printk(KERN_DEBUG "mp_recv: %d/%d -> %02x %02x %02x %02x %02x %02x\n",
-              slot, (int) skb->len,
-              (int) skb->data[0], (int) skb->data[1], (int) skb->data[2],
-              (int) skb->data[3], (int) skb->data[4], (int) skb->data[5]);
-}
-
-static int
-isdn_ppp_bundle(struct ippp_struct *is, int unit)
-{
-       char ifn[IFNAMSIZ + 1];
-       isdn_net_dev *p;
-       isdn_net_local *lp, *nlp;
-       int rc;
-       unsigned long flags;
-
-       sprintf(ifn, "ippp%d", unit);
-       p = isdn_net_findif(ifn);
-       if (!p) {
-               printk(KERN_ERR "ippp_bundle: cannot find %s\n", ifn);
-               return -EINVAL;
-       }
-
-       spin_lock_irqsave(&p->pb->lock, flags);
-
-       nlp = is->lp;
-       lp = p->queue;
-       if (nlp->ppp_slot < 0 || nlp->ppp_slot >= ISDN_MAX_CHANNELS ||
-           lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
-               printk(KERN_ERR "ippp_bundle: binding to invalid slot %d\n",
-                      nlp->ppp_slot < 0 || nlp->ppp_slot >= ISDN_MAX_CHANNELS ?
-                      nlp->ppp_slot : lp->ppp_slot);
-               rc = -EINVAL;
-               goto out;
-       }
-
-       isdn_net_add_to_bundle(p, nlp);
-
-       ippp_table[nlp->ppp_slot]->unit = ippp_table[lp->ppp_slot]->unit;
-
-       /* maybe also SC_CCP stuff */
-       ippp_table[nlp->ppp_slot]->pppcfg |= ippp_table[lp->ppp_slot]->pppcfg &
-               (SC_ENABLE_IP | SC_NO_TCP_CCID | SC_REJ_COMP_TCP);
-       ippp_table[nlp->ppp_slot]->mpppcfg |= ippp_table[lp->ppp_slot]->mpppcfg &
-               (SC_MP_PROT | SC_REJ_MP_PROT | SC_OUT_SHORT_SEQ | SC_IN_SHORT_SEQ);
-       rc = isdn_ppp_mp_init(nlp, p->pb);
-out:
-       spin_unlock_irqrestore(&p->pb->lock, flags);
-       return rc;
-}
-
-#endif /* CONFIG_ISDN_MPP */
-
-/*
- * network device ioctl handlers
- */
-
-static int
-isdn_ppp_dev_ioctl_stats(int slot, struct ifreq *ifr, struct net_device *dev)
-{
-       struct ppp_stats __user *res = ifr->ifr_data;
-       struct ppp_stats t;
-       isdn_net_local *lp = netdev_priv(dev);
-
-       /* build a temporary stat struct and copy it to user space */
-
-       memset(&t, 0, sizeof(struct ppp_stats));
-       if (dev->flags & IFF_UP) {
-               t.p.ppp_ipackets = lp->stats.rx_packets;
-               t.p.ppp_ibytes = lp->stats.rx_bytes;
-               t.p.ppp_ierrors = lp->stats.rx_errors;
-               t.p.ppp_opackets = lp->stats.tx_packets;
-               t.p.ppp_obytes = lp->stats.tx_bytes;
-               t.p.ppp_oerrors = lp->stats.tx_errors;
-#ifdef CONFIG_ISDN_PPP_VJ
-               if (slot >= 0 && ippp_table[slot]->slcomp) {
-                       struct slcompress *slcomp = ippp_table[slot]->slcomp;
-                       t.vj.vjs_packets = slcomp->sls_o_compressed + slcomp->sls_o_uncompressed;
-                       t.vj.vjs_compressed = slcomp->sls_o_compressed;
-                       t.vj.vjs_searches = slcomp->sls_o_searches;
-                       t.vj.vjs_misses = slcomp->sls_o_misses;
-                       t.vj.vjs_errorin = slcomp->sls_i_error;
-                       t.vj.vjs_tossed = slcomp->sls_i_tossed;
-                       t.vj.vjs_uncompressedin = slcomp->sls_i_uncompressed;
-                       t.vj.vjs_compressedin = slcomp->sls_i_compressed;
-               }
-#endif
-       }
-       if (copy_to_user(res, &t, sizeof(struct ppp_stats)))
-               return -EFAULT;
-       return 0;
-}
-
-int
-isdn_ppp_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-       int error = 0;
-       int len;
-       isdn_net_local *lp = netdev_priv(dev);
-
-
-       if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP)
-               return -EINVAL;
-
-       switch (cmd) {
-#define PPP_VERSION "2.3.7"
-       case SIOCGPPPVER:
-               len = strlen(PPP_VERSION) + 1;
-               if (copy_to_user(ifr->ifr_data, PPP_VERSION, len))
-                       error = -EFAULT;
-               break;
-
-       case SIOCGPPPSTATS:
-               error = isdn_ppp_dev_ioctl_stats(lp->ppp_slot, ifr, dev);
-               break;
-       default:
-               error = -EINVAL;
-               break;
-       }
-       return error;
-}
-
-static int
-isdn_ppp_if_get_unit(char *name)
-{
-       int len,
-               i,
-               unit = 0,
-               deci;
-
-       len = strlen(name);
-
-       if (strncmp("ippp", name, 4) || len > 8)
-               return -1;
-
-       for (i = 0, deci = 1; i < len; i++, deci *= 10) {
-               char a = name[len - i - 1];
-               if (a >= '0' && a <= '9')
-                       unit += (a - '0') * deci;
-               else
-                       break;
-       }
-       if (!i || len - i != 4)
-               unit = -1;
-
-       return unit;
-}
-
-
-int
-isdn_ppp_dial_slave(char *name)
-{
-#ifdef CONFIG_ISDN_MPP
-       isdn_net_dev *ndev;
-       isdn_net_local *lp;
-       struct net_device *sdev;
-
-       if (!(ndev = isdn_net_findif(name)))
-               return 1;
-       lp = ndev->local;
-       if (!(lp->flags & ISDN_NET_CONNECTED))
-               return 5;
-
-       sdev = lp->slave;
-       while (sdev) {
-               isdn_net_local *mlp = netdev_priv(sdev);
-               if (!(mlp->flags & ISDN_NET_CONNECTED))
-                       break;
-               sdev = mlp->slave;
-       }
-       if (!sdev)
-               return 2;
-
-       isdn_net_dial_req(netdev_priv(sdev));
-       return 0;
-#else
-       return -1;
-#endif
-}
-
-int
-isdn_ppp_hangup_slave(char *name)
-{
-#ifdef CONFIG_ISDN_MPP
-       isdn_net_dev *ndev;
-       isdn_net_local *lp;
-       struct net_device *sdev;
-
-       if (!(ndev = isdn_net_findif(name)))
-               return 1;
-       lp = ndev->local;
-       if (!(lp->flags & ISDN_NET_CONNECTED))
-               return 5;
-
-       sdev = lp->slave;
-       while (sdev) {
-               isdn_net_local *mlp = netdev_priv(sdev);
-
-               if (mlp->slave) { /* find last connected link in chain */
-                       isdn_net_local *nlp = ISDN_SLAVE_PRIV(mlp);
-
-                       if (!(nlp->flags & ISDN_NET_CONNECTED))
-                               break;
-               } else if (mlp->flags & ISDN_NET_CONNECTED)
-                       break;
-
-               sdev = mlp->slave;
-       }
-       if (!sdev)
-               return 2;
-
-       isdn_net_hangup(sdev);
-       return 0;
-#else
-       return -1;
-#endif
-}
-
-/*
- * PPP compression stuff
- */
-
-
-/* Push an empty CCP Data Frame up to the daemon to wake it up and let it
-   generate a CCP Reset-Request or tear down CCP altogether */
-
-static void isdn_ppp_ccp_kickup(struct ippp_struct *is)
-{
-       isdn_ppp_fill_rq(NULL, 0, PPP_COMP, is->lp->ppp_slot);
-}
-
-/* In-kernel handling of CCP Reset-Request and Reset-Ack is necessary,
-   but absolutely nontrivial. The most abstruse problem we are facing is
-   that the generation, reception and all the handling of timeouts and
-   resends including proper request id management should be entirely left
-   to the (de)compressor, but indeed is not covered by the current API to
-   the (de)compressor. The API is a prototype version from PPP where only
-   some (de)compressors have yet been implemented and all of them are
-   rather simple in their reset handling. Especially, their is only one
-   outstanding ResetAck at a time with all of them and ResetReq/-Acks do
-   not have parameters. For this very special case it was sufficient to
-   just return an error code from the decompressor and have a single
-   reset() entry to communicate all the necessary information between
-   the framework and the (de)compressor. Bad enough, LZS is different
-   (and any other compressor may be different, too). It has multiple
-   histories (eventually) and needs to Reset each of them independently
-   and thus uses multiple outstanding Acks and history numbers as an
-   additional parameter to Reqs/Acks.
-   All that makes it harder to port the reset state engine into the
-   kernel because it is not just the same simple one as in (i)pppd but
-   it must be able to pass additional parameters and have multiple out-
-   standing Acks. We are trying to achieve the impossible by handling
-   reset transactions independent by their id. The id MUST change when
-   the data portion changes, thus any (de)compressor who uses more than
-   one resettable state must provide and recognize individual ids for
-   each individual reset transaction. The framework itself does _only_
-   differentiate them by id, because it has no other semantics like the
-   (de)compressor might.
-   This looks like a major redesign of the interface would be nice,
-   but I don't have an idea how to do it better. */
-
-/* Send a CCP Reset-Request or Reset-Ack directly from the kernel. This is
-   getting that lengthy because there is no simple "send-this-frame-out"
-   function above but every wrapper does a bit different. Hope I guess
-   correct in this hack... */
-
-static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
-                                   unsigned char code, unsigned char id,
-                                   unsigned char *data, int len)
-{
-       struct sk_buff *skb;
-       unsigned char *p;
-       int hl;
-       int cnt = 0;
-       isdn_net_local *lp = is->lp;
-
-       /* Alloc large enough skb */
-       hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen;
-       skb = alloc_skb(len + hl + 16, GFP_ATOMIC);
-       if (!skb) {
-               printk(KERN_WARNING
-                      "ippp: CCP cannot send reset - out of memory\n");
-               return;
-       }
-       skb_reserve(skb, hl);
-
-       /* We may need to stuff an address and control field first */
-       if (!(is->pppcfg & SC_COMP_AC)) {
-               p = skb_put(skb, 2);
-               *p++ = 0xff;
-               *p++ = 0x03;
-       }
-
-       /* Stuff proto, code, id and length */
-       p = skb_put(skb, 6);
-       *p++ = (proto >> 8);
-       *p++ = (proto & 0xff);
-       *p++ = code;
-       *p++ = id;
-       cnt = 4 + len;
-       *p++ = (cnt >> 8);
-       *p++ = (cnt & 0xff);
-
-       /* Now stuff remaining bytes */
-       if (len) {
-               skb_put_data(skb, data, len);
-       }
-
-       /* skb is now ready for xmit */
-       printk(KERN_DEBUG "Sending CCP Frame:\n");
-       isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, is->unit, lp->ppp_slot);
-
-       isdn_net_write_super(lp, skb);
-}
-
-/* Allocate the reset state vector */
-static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is)
-{
-       struct ippp_ccp_reset *r;
-       r = kzalloc(sizeof(struct ippp_ccp_reset), GFP_KERNEL);
-       if (!r) {
-               printk(KERN_ERR "ippp_ccp: failed to allocate reset data"
-                      " structure - no mem\n");
-               return NULL;
-       }
-       printk(KERN_DEBUG "ippp_ccp: allocated reset data structure %p\n", r);
-       is->reset = r;
-       return r;
-}
-
-/* Destroy the reset state vector. Kill all pending timers first. */
-static void isdn_ppp_ccp_reset_free(struct ippp_struct *is)
-{
-       unsigned int id;
-
-       printk(KERN_DEBUG "ippp_ccp: freeing reset data structure %p\n",
-              is->reset);
-       for (id = 0; id < 256; id++) {
-               if (is->reset->rs[id]) {
-                       isdn_ppp_ccp_reset_free_state(is, (unsigned char)id);
-               }
-       }
-       kfree(is->reset);
-       is->reset = NULL;
-}
-
-/* Free a given state and clear everything up for later reallocation */
-static void isdn_ppp_ccp_reset_free_state(struct ippp_struct *is,
-                                         unsigned char id)
-{
-       struct ippp_ccp_reset_state *rs;
-
-       if (is->reset->rs[id]) {
-               printk(KERN_DEBUG "ippp_ccp: freeing state for id %d\n", id);
-               rs = is->reset->rs[id];
-               /* Make sure the kernel will not call back later */
-               if (rs->ta)
-                       del_timer(&rs->timer);
-               is->reset->rs[id] = NULL;
-               kfree(rs);
-       } else {
-               printk(KERN_WARNING "ippp_ccp: id %d is not allocated\n", id);
-       }
-}
-
-/* The timer callback function which is called when a ResetReq has timed out,
-   aka has never been answered by a ResetAck */
-static void isdn_ppp_ccp_timer_callback(struct timer_list *t)
-{
-       struct ippp_ccp_reset_state *rs =
-               from_timer(rs, t, timer);
-
-       if (!rs) {
-               printk(KERN_ERR "ippp_ccp: timer cb with zero closure.\n");
-               return;
-       }
-       if (rs->ta && rs->state == CCPResetSentReq) {
-               /* We are correct here */
-               if (!rs->expra) {
-                       /* Hmm, there is no Ack really expected. We can clean
-                          up the state now, it will be reallocated if the
-                          decompressor insists on another reset */
-                       rs->ta = 0;
-                       isdn_ppp_ccp_reset_free_state(rs->is, rs->id);
-                       return;
-               }
-               printk(KERN_DEBUG "ippp_ccp: CCP Reset timed out for id %d\n",
-                      rs->id);
-               /* Push it again */
-               isdn_ppp_ccp_xmit_reset(rs->is, PPP_CCP, CCP_RESETREQ, rs->id,
-                                       rs->data, rs->dlen);
-               /* Restart timer */
-               rs->timer.expires = jiffies + HZ * 5;
-               add_timer(&rs->timer);
-       } else {
-               printk(KERN_WARNING "ippp_ccp: timer cb in wrong state %d\n",
-                      rs->state);
-       }
-}
-
-/* Allocate a new reset transaction state */
-static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_struct *is,
-                                                                  unsigned char id)
-{
-       struct ippp_ccp_reset_state *rs;
-       if (is->reset->rs[id]) {
-               printk(KERN_WARNING "ippp_ccp: old state exists for id %d\n",
-                      id);
-               return NULL;
-       } else {
-               rs = kzalloc(sizeof(struct ippp_ccp_reset_state), GFP_ATOMIC);
-               if (!rs)
-                       return NULL;
-               rs->state = CCPResetIdle;
-               rs->is = is;
-               rs->id = id;
-               timer_setup(&rs->timer, isdn_ppp_ccp_timer_callback, 0);
-               is->reset->rs[id] = rs;
-       }
-       return rs;
-}
-
-
-/* A decompressor wants a reset with a set of parameters - do what is
-   necessary to fulfill it */
-static void isdn_ppp_ccp_reset_trans(struct ippp_struct *is,
-                                    struct isdn_ppp_resetparams *rp)
-{
-       struct ippp_ccp_reset_state *rs;
-
-       if (rp->valid) {
-               /* The decompressor defines parameters by itself */
-               if (rp->rsend) {
-                       /* And he wants us to send a request */
-                       if (!(rp->idval)) {
-                               printk(KERN_ERR "ippp_ccp: decompressor must"
-                                      " specify reset id\n");
-                               return;
-                       }
-                       if (is->reset->rs[rp->id]) {
-                               /* There is already a transaction in existence
-                                  for this id. May be still waiting for a
-                                  Ack or may be wrong. */
-                               rs = is->reset->rs[rp->id];
-                               if (rs->state == CCPResetSentReq && rs->ta) {
-                                       printk(KERN_DEBUG "ippp_ccp: reset"
-                                              " trans still in progress"
-                                              " for id %d\n", rp->id);
-                               } else {
-                                       printk(KERN_WARNING "ippp_ccp: reset"
-                                              " trans in wrong state %d for"
-                                              " id %d\n", rs->state, rp->id);
-                               }
-                       } else {
-                               /* Ok, this is a new transaction */
-                               printk(KERN_DEBUG "ippp_ccp: new trans for id"
-                                      " %d to be started\n", rp->id);
-                               rs = isdn_ppp_ccp_reset_alloc_state(is, rp->id);
-                               if (!rs) {
-                                       printk(KERN_ERR "ippp_ccp: out of mem"
-                                              " allocing ccp trans\n");
-                                       return;
-                               }
-                               rs->state = CCPResetSentReq;
-                               rs->expra = rp->expra;
-                               if (rp->dtval) {
-                                       rs->dlen = rp->dlen;
-                                       memcpy(rs->data, rp->data, rp->dlen);
-                               }
-                               /* HACK TODO - add link comp here */
-                               isdn_ppp_ccp_xmit_reset(is, PPP_CCP,
-                                                       CCP_RESETREQ, rs->id,
-                                                       rs->data, rs->dlen);
-                               /* Start the timer */
-                               rs->timer.expires = jiffies + 5 * HZ;
-                               add_timer(&rs->timer);
-                               rs->ta = 1;
-                       }
-               } else {
-                       printk(KERN_DEBUG "ippp_ccp: no reset sent\n");
-               }
-       } else {
-               /* The reset params are invalid. The decompressor does not
-                  care about them, so we just send the minimal requests
-                  and increase ids only when an Ack is received for a
-                  given id */
-               if (is->reset->rs[is->reset->lastid]) {
-                       /* There is already a transaction in existence
-                          for this id. May be still waiting for a
-                          Ack or may be wrong. */
-                       rs = is->reset->rs[is->reset->lastid];
-                       if (rs->state == CCPResetSentReq && rs->ta) {
-                               printk(KERN_DEBUG "ippp_ccp: reset"
-                                      " trans still in progress"
-                                      " for id %d\n", rp->id);
-                       } else {
-                               printk(KERN_WARNING "ippp_ccp: reset"
-                                      " trans in wrong state %d for"
-                                      " id %d\n", rs->state, rp->id);
-                       }
-               } else {
-                       printk(KERN_DEBUG "ippp_ccp: new trans for id"
-                              " %d to be started\n", is->reset->lastid);
-                       rs = isdn_ppp_ccp_reset_alloc_state(is,
-                                                           is->reset->lastid);
-                       if (!rs) {
-                               printk(KERN_ERR "ippp_ccp: out of mem"
-                                      " allocing ccp trans\n");
-                               return;
-                       }
-                       rs->state = CCPResetSentReq;
-                       /* We always expect an Ack if the decompressor doesn't
-                          know better */
-                       rs->expra = 1;
-                       rs->dlen = 0;
-                       /* HACK TODO - add link comp here */
-                       isdn_ppp_ccp_xmit_reset(is, PPP_CCP, CCP_RESETREQ,
-                                               rs->id, NULL, 0);
-                       /* Start the timer */
-                       rs->timer.expires = jiffies + 5 * HZ;
-                       add_timer(&rs->timer);
-                       rs->ta = 1;
-               }
-       }
-}
-
-/* An Ack was received for this id. This means we stop the timer and clean
-   up the state prior to calling the decompressors reset routine. */
-static void isdn_ppp_ccp_reset_ack_rcvd(struct ippp_struct *is,
-                                       unsigned char id)
-{
-       struct ippp_ccp_reset_state *rs = is->reset->rs[id];
-
-       if (rs) {
-               if (rs->ta && rs->state == CCPResetSentReq) {
-                       /* Great, we are correct */
-                       if (!rs->expra)
-                               printk(KERN_DEBUG "ippp_ccp: ResetAck received"
-                                      " for id %d but not expected\n", id);
-               } else {
-                       printk(KERN_INFO "ippp_ccp: ResetAck received out of"
-                              "sync for id %d\n", id);
-               }
-               if (rs->ta) {
-                       rs->ta = 0;
-                       del_timer(&rs->timer);
-               }
-               isdn_ppp_ccp_reset_free_state(is, id);
-       } else {
-               printk(KERN_INFO "ippp_ccp: ResetAck received for unknown id"
-                      " %d\n", id);
-       }
-       /* Make sure the simple reset stuff uses a new id next time */
-       is->reset->lastid++;
-}
-
-/*
- * decompress packet
- *
- * if master = 0, we're trying to uncompress an per-link compressed packet,
- * as opposed to an compressed reconstructed-from-MPPP packet.
- * proto is updated to protocol field of uncompressed packet.
- *
- * retval: decompressed packet,
- *         same packet if uncompressed,
- *        NULL if decompression error
- */
-
-static struct sk_buff *isdn_ppp_decompress(struct sk_buff *skb, struct ippp_struct *is, struct ippp_struct *master,
-                                          int *proto)
-{
-       void *stat = NULL;
-       struct isdn_ppp_compressor *ipc = NULL;
-       struct sk_buff *skb_out;
-       int len;
-       struct ippp_struct *ri;
-       struct isdn_ppp_resetparams rsparm;
-       unsigned char rsdata[IPPP_RESET_MAXDATABYTES];
-
-       if (!master) {
-               // per-link decompression
-               stat = is->link_decomp_stat;
-               ipc = is->link_decompressor;
-               ri = is;
-       } else {
-               stat = master->decomp_stat;
-               ipc = master->decompressor;
-               ri = master;
-       }
-
-       if (!ipc) {
-               // no decompressor -> we can't decompress.
-               printk(KERN_DEBUG "ippp: no decompressor defined!\n");
-               return skb;
-       }
-       BUG_ON(!stat); // if we have a compressor, stat has been set as well
-
-       if ((master && *proto == PPP_COMP) || (!master && *proto == PPP_COMPFRAG)) {
-               // compressed packets are compressed by their protocol type
-
-               // Set up reset params for the decompressor
-               memset(&rsparm, 0, sizeof(rsparm));
-               rsparm.data = rsdata;
-               rsparm.maxdlen = IPPP_RESET_MAXDATABYTES;
-
-               skb_out = dev_alloc_skb(is->mru + PPP_HDRLEN);
-               if (!skb_out) {
-                       kfree_skb(skb);
-                       printk(KERN_ERR "ippp: decomp memory allocation failure\n");
-                       return NULL;
-               }
-               len = ipc->decompress(stat, skb, skb_out, &rsparm);
-               kfree_skb(skb);
-               if (len <= 0) {
-                       switch (len) {
-                       case DECOMP_ERROR:
-                               printk(KERN_INFO "ippp: decomp wants reset %s params\n",
-                                      rsparm.valid ? "with" : "without");
-
-                               isdn_ppp_ccp_reset_trans(ri, &rsparm);
-                               break;
-                       case DECOMP_FATALERROR:
-                               ri->pppcfg |= SC_DC_FERROR;
-                               /* Kick ipppd to recognize the error */
-                               isdn_ppp_ccp_kickup(ri);
-                               break;
-                       }
-                       kfree_skb(skb_out);
-                       return NULL;
-               }
-               *proto = isdn_ppp_strip_proto(skb_out);
-               if (*proto < 0) {
-                       kfree_skb(skb_out);
-                       return NULL;
-               }
-               return skb_out;
-       } else {
-               // uncompressed packets are fed through the decompressor to
-               // update the decompressor state
-               ipc->incomp(stat, skb, *proto);
-               return skb;
-       }
-}
-
-/*
- * compress a frame
- *   type=0: normal/bundle compression
- *       =1: link compression
- * returns original skb if we haven't compressed the frame
- * and a new skb pointer if we've done it
- */
-static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in, int *proto,
-                                        struct ippp_struct *is, struct ippp_struct *master, int type)
-{
-       int ret;
-       int new_proto;
-       struct isdn_ppp_compressor *compressor;
-       void *stat;
-       struct sk_buff *skb_out;
-
-       /* we do not compress control protocols */
-       if (*proto < 0 || *proto > 0x3fff) {
-               return skb_in;
-       }
-
-       if (type) { /* type=1 => Link compression */
-               return skb_in;
-       }
-       else {
-               if (!master) {
-                       compressor = is->compressor;
-                       stat = is->comp_stat;
-               }
-               else {
-                       compressor = master->compressor;
-                       stat = master->comp_stat;
-               }
-               new_proto = PPP_COMP;
-       }
-
-       if (!compressor) {
-               printk(KERN_ERR "isdn_ppp: No compressor set!\n");
-               return skb_in;
-       }
-       if (!stat) {
-               printk(KERN_ERR "isdn_ppp: Compressor not initialized?\n");
-               return skb_in;
-       }
-
-       /* Allow for at least 150 % expansion (for now) */
-       skb_out = alloc_skb(skb_in->len + skb_in->len / 2 + 32 +
-                           skb_headroom(skb_in), GFP_ATOMIC);
-       if (!skb_out)
-               return skb_in;
-       skb_reserve(skb_out, skb_headroom(skb_in));
-
-       ret = (compressor->compress)(stat, skb_in, skb_out, *proto);
-       if (!ret) {
-               dev_kfree_skb(skb_out);
-               return skb_in;
-       }
-
-       dev_kfree_skb(skb_in);
-       *proto = new_proto;
-       return skb_out;
-}
-
-/*
- * we received a CCP frame ..
- * not a clean solution, but we MUST handle a few cases in the kernel
- */
-static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
-                                struct sk_buff *skb, int proto)
-{
-       struct ippp_struct *is;
-       struct ippp_struct *mis;
-       int len;
-       struct isdn_ppp_resetparams rsparm;
-       unsigned char rsdata[IPPP_RESET_MAXDATABYTES];
-
-       printk(KERN_DEBUG "Received CCP frame from peer slot(%d)\n",
-              lp->ppp_slot);
-       if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
-               printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
-                      __func__, lp->ppp_slot);
-               return;
-       }
-       is = ippp_table[lp->ppp_slot];
-       isdn_ppp_frame_log("ccp-rcv", skb->data, skb->len, 32, is->unit, lp->ppp_slot);
-
-       if (lp->master) {
-               int slot = ISDN_MASTER_PRIV(lp)->ppp_slot;
-               if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
-                       printk(KERN_ERR "%s: slot(%d) out of range\n",
-                              __func__, slot);
-                       return;
-               }
-               mis = ippp_table[slot];
-       } else
-               mis = is;
-
-       switch (skb->data[0]) {
-       case CCP_CONFREQ:
-               if (is->debug & 0x10)
-                       printk(KERN_DEBUG "Disable compression here!\n");
-               if (proto == PPP_CCP)
-                       mis->compflags &= ~SC_COMP_ON;
-               else
-                       is->compflags &= ~SC_LINK_COMP_ON;
-               break;
-       case CCP_TERMREQ:
-       case CCP_TERMACK:
-               if (is->debug & 0x10)
-                       printk(KERN_DEBUG "Disable (de)compression here!\n");
-               if (proto == PPP_CCP)
-                       mis->compflags &= ~(SC_DECOMP_ON | SC_COMP_ON);
-               else
-                       is->compflags &= ~(SC_LINK_DECOMP_ON | SC_LINK_COMP_ON);
-               break;
-       case CCP_CONFACK:
-               /* if we RECEIVE an ackowledge we enable the decompressor */
-               if (is->debug & 0x10)
-                       printk(KERN_DEBUG "Enable decompression here!\n");
-               if (proto == PPP_CCP) {
-                       if (!mis->decompressor)
-                               break;
-                       mis->compflags |= SC_DECOMP_ON;
-               } else {
-                       if (!is->decompressor)
-                               break;
-                       is->compflags |= SC_LINK_DECOMP_ON;
-               }
-               break;
-
-       case CCP_RESETACK:
-               printk(KERN_DEBUG "Received ResetAck from peer\n");
-               len = (skb->data[2] << 8) | skb->data[3];
-               len -= 4;
-
-               if (proto == PPP_CCP) {
-                       /* If a reset Ack was outstanding for this id, then
-                          clean up the state engine */
-                       isdn_ppp_ccp_reset_ack_rcvd(mis, skb->data[1]);
-                       if (mis->decompressor && mis->decomp_stat)
-                               mis->decompressor->
-                                       reset(mis->decomp_stat,
-                                             skb->data[0],
-                                             skb->data[1],
-                                             len ? &skb->data[4] : NULL,
-                                             len, NULL);
-                       /* TODO: This is not easy to decide here */
-                       mis->compflags &= ~SC_DECOMP_DISCARD;
-               }
-               else {
-                       isdn_ppp_ccp_reset_ack_rcvd(is, skb->data[1]);
-                       if (is->link_decompressor && is->link_decomp_stat)
-                               is->link_decompressor->
-                                       reset(is->link_decomp_stat,
-                                             skb->data[0],
-                                             skb->data[1],
-                                             len ? &skb->data[4] : NULL,
-                                             len, NULL);
-                       /* TODO: neither here */
-                       is->compflags &= ~SC_LINK_DECOMP_DISCARD;
-               }
-               break;
-
-       case CCP_RESETREQ:
-               printk(KERN_DEBUG "Received ResetReq from peer\n");
-               /* Receiving a ResetReq means we must reset our compressor */
-               /* Set up reset params for the reset entry */
-               memset(&rsparm, 0, sizeof(rsparm));
-               rsparm.data = rsdata;
-               rsparm.maxdlen = IPPP_RESET_MAXDATABYTES;
-               /* Isolate data length */
-               len = (skb->data[2] << 8) | skb->data[3];
-               len -= 4;
-               if (proto == PPP_CCP) {
-                       if (mis->compressor && mis->comp_stat)
-                               mis->compressor->
-                                       reset(mis->comp_stat,
-                                             skb->data[0],
-                                             skb->data[1],
-                                             len ? &skb->data[4] : NULL,
-                                             len, &rsparm);
-               }
-               else {
-                       if (is->link_compressor && is->link_comp_stat)
-                               is->link_compressor->
-                                       reset(is->link_comp_stat,
-                                             skb->data[0],
-                                             skb->data[1],
-                                             len ? &skb->data[4] : NULL,
-                                             len, &rsparm);
-               }
-               /* Ack the Req as specified by rsparm */
-               if (rsparm.valid) {
-                       /* Compressor reset handler decided how to answer */
-                       if (rsparm.rsend) {
-                               /* We should send a Frame */
-                               isdn_ppp_ccp_xmit_reset(is, proto, CCP_RESETACK,
-                                                       rsparm.idval ? rsparm.id
-                                                       : skb->data[1],
-                                                       rsparm.dtval ?
-                                                       rsparm.data : NULL,
-                                                       rsparm.dtval ?
-                                                       rsparm.dlen : 0);
-                       } else {
-                               printk(KERN_DEBUG "ResetAck suppressed\n");
-                       }
-               } else {
-                       /* We answer with a straight reflected Ack */
-                       isdn_ppp_ccp_xmit_reset(is, proto, CCP_RESETACK,
-                                               skb->data[1],
-                                               len ? &skb->data[4] : NULL,
-                                               len);
-               }
-               break;
-       }
-}
-
-
-/*
- * Daemon sends a CCP frame ...
- */
-
-/* TODO: Clean this up with new Reset semantics */
-
-/* I believe the CCP handling as-is is done wrong. Compressed frames
- * should only be sent/received after CCP reaches UP state, which means
- * both sides have sent CONF_ACK. Currently, we handle both directions
- * independently, which means we may accept compressed frames too early
- * (supposedly not a problem), but may also mean we send compressed frames
- * too early, which may turn out to be a problem.
- * This part of state machine should actually be handled by (i)pppd, but
- * that's too big of a change now. --kai
- */
-
-/* Actually, we might turn this into an advantage: deal with the RFC in
- * the old tradition of beeing generous on what we accept, but beeing
- * strict on what we send. Thus we should just
- * - accept compressed frames as soon as decompression is negotiated
- * - send compressed frames only when decomp *and* comp are negotiated
- * - drop rx compressed frames if we cannot decomp (instead of pushing them
- *   up to ipppd)
- * and I tried to modify this file according to that. --abp
- */
-
-static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, struct sk_buff *skb)
-{
-       struct ippp_struct *mis, *is;
-       int proto, slot = lp->ppp_slot;
-       unsigned char *data;
-
-       if (!skb || skb->len < 3)
-               return;
-       if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
-               printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
-                      __func__, slot);
-               return;
-       }
-       is = ippp_table[slot];
-       /* Daemon may send with or without address and control field comp */
-       data = skb->data;
-       if (!(is->pppcfg & SC_COMP_AC) && data[0] == 0xff && data[1] == 0x03) {
-               data += 2;
-               if (skb->len < 5)
-                       return;
-       }
-
-       proto = ((int)data[0]<<8) + data[1];
-       if (proto != PPP_CCP && proto != PPP_CCPFRAG)
-               return;
-
-       printk(KERN_DEBUG "Received CCP frame from daemon:\n");
-       isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, is->unit, lp->ppp_slot);
-
-       if (lp->master) {
-               slot = ISDN_MASTER_PRIV(lp)->ppp_slot;
-               if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
-                       printk(KERN_ERR "%s: slot(%d) out of range\n",
-                              __func__, slot);
-                       return;
-               }
-               mis = ippp_table[slot];
-       } else
-               mis = is;
-       if (mis != is)
-               printk(KERN_DEBUG "isdn_ppp: Ouch! Master CCP sends on slave slot!\n");
-
-       switch (data[2]) {
-       case CCP_CONFREQ:
-               if (is->debug & 0x10)
-                       printk(KERN_DEBUG "Disable decompression here!\n");
-               if (proto == PPP_CCP)
-                       is->compflags &= ~SC_DECOMP_ON;
-               else
-                       is->compflags &= ~SC_LINK_DECOMP_ON;
-               break;
-       case CCP_TERMREQ:
-       case CCP_TERMACK:
-               if (is->debug & 0x10)
-                       printk(KERN_DEBUG "Disable (de)compression here!\n");
-               if (proto == PPP_CCP)
-                       is->compflags &= ~(SC_DECOMP_ON | SC_COMP_ON);
-               else
-                       is->compflags &= ~(SC_LINK_DECOMP_ON | SC_LINK_COMP_ON);
-               break;
-       case CCP_CONFACK:
-               /* if we SEND an ackowledge we can/must enable the compressor */
-               if (is->debug & 0x10)
-                       printk(KERN_DEBUG "Enable compression here!\n");
-               if (proto == PPP_CCP) {
-                       if (!is->compressor)
-                               break;
-                       is->compflags |= SC_COMP_ON;
-               } else {
-                       if (!is->compressor)
-                               break;
-                       is->compflags |= SC_LINK_COMP_ON;
-               }
-               break;
-       case CCP_RESETACK:
-               /* If we send a ACK we should reset our compressor */
-               if (is->debug & 0x10)
-                       printk(KERN_DEBUG "Reset decompression state here!\n");
-               printk(KERN_DEBUG "ResetAck from daemon passed by\n");
-               if (proto == PPP_CCP) {
-                       /* link to master? */
-                       if (is->compressor && is->comp_stat)
-                               is->compressor->reset(is->comp_stat, 0, 0,
-                                                     NULL, 0, NULL);
-                       is->compflags &= ~SC_COMP_DISCARD;
-               }
-               else {
-                       if (is->link_compressor && is->link_comp_stat)
-                               is->link_compressor->reset(is->link_comp_stat,
-                                                          0, 0, NULL, 0, NULL);
-                       is->compflags &= ~SC_LINK_COMP_DISCARD;
-               }
-               break;
-       case CCP_RESETREQ:
-               /* Just let it pass by */
-               printk(KERN_DEBUG "ResetReq from daemon passed by\n");
-               break;
-       }
-}
-
-int isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc)
-{
-       ipc->next = ipc_head;
-       ipc->prev = NULL;
-       if (ipc_head) {
-               ipc_head->prev = ipc;
-       }
-       ipc_head = ipc;
-       return 0;
-}
-
-int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *ipc)
-{
-       if (ipc->prev)
-               ipc->prev->next = ipc->next;
-       else
-               ipc_head = ipc->next;
-       if (ipc->next)
-               ipc->next->prev = ipc->prev;
-       ipc->prev = ipc->next = NULL;
-       return 0;
-}
-
-static int isdn_ppp_set_compressor(struct ippp_struct *is, struct isdn_ppp_comp_data *data)
-{
-       struct isdn_ppp_compressor *ipc = ipc_head;
-       int ret;
-       void *stat;
-       int num = data->num;
-
-       if (is->debug & 0x10)
-               printk(KERN_DEBUG "[%d] Set %s type %d\n", is->unit,
-                      (data->flags & IPPP_COMP_FLAG_XMIT) ? "compressor" : "decompressor", num);
-
-       /* If is has no valid reset state vector, we cannot allocate a
-          decompressor. The decompressor would cause reset transactions
-          sooner or later, and they need that vector. */
-
-       if (!(data->flags & IPPP_COMP_FLAG_XMIT) && !is->reset) {
-               printk(KERN_ERR "ippp_ccp: no reset data structure - can't"
-                      " allow decompression.\n");
-               return -ENOMEM;
-       }
-
-       while (ipc) {
-               if (ipc->num == num) {
-                       stat = ipc->alloc(data);
-                       if (stat) {
-                               ret = ipc->init(stat, data, is->unit, 0);
-                               if (!ret) {
-                                       printk(KERN_ERR "Can't init (de)compression!\n");
-                                       ipc->free(stat);
-                                       stat = NULL;
-                                       break;
-                               }
-                       }
-                       else {
-                               printk(KERN_ERR "Can't alloc (de)compression!\n");
-                               break;
-                       }
-
-                       if (data->flags & IPPP_COMP_FLAG_XMIT) {
-                               if (data->flags & IPPP_COMP_FLAG_LINK) {
-                                       if (is->link_comp_stat)
-                                               is->link_compressor->free(is->link_comp_stat);
-                                       is->link_comp_stat = stat;
-                                       is->link_compressor = ipc;
-                               }
-                               else {
-                                       if (is->comp_stat)
-                                               is->compressor->free(is->comp_stat);
-                                       is->comp_stat = stat;
-                                       is->compressor = ipc;
-                               }
-                       }
-                       else {
-                               if (data->flags & IPPP_COMP_FLAG_LINK) {
-                                       if (is->link_decomp_stat)
-                                               is->link_decompressor->free(is->link_decomp_stat);
-                                       is->link_decomp_stat = stat;
-                                       is->link_decompressor = ipc;
-                               }
-                               else {
-                                       if (is->decomp_stat)
-                                               is->decompressor->free(is->decomp_stat);
-                                       is->decomp_stat = stat;
-                                       is->decompressor = ipc;
-                               }
-                       }
-                       return 0;
-               }
-               ipc = ipc->next;
-       }
-       return -EINVAL;
-}
 
+++ /dev/null
-/* $Id: isdn_ppp.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
- *
- * header for Linux ISDN subsystem, functions for synchronous PPP (linklevel).
- *
- * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#include <linux/ppp_defs.h>     /* for PPP_PROTOCOL */
-#include <linux/isdn_ppp.h>    /* for isdn_ppp info */
-
-extern int isdn_ppp_read(int, struct file *, char __user *, int);
-extern int isdn_ppp_write(int, struct file *, const char __user *, int);
-extern int isdn_ppp_open(int, struct file *);
-extern int isdn_ppp_init(void);
-extern void isdn_ppp_cleanup(void);
-extern int isdn_ppp_free(isdn_net_local *);
-extern int isdn_ppp_bind(isdn_net_local *);
-extern int isdn_ppp_autodial_filter(struct sk_buff *, isdn_net_local *);
-extern int isdn_ppp_xmit(struct sk_buff *, struct net_device *);
-extern void isdn_ppp_receive(isdn_net_dev *, isdn_net_local *, struct sk_buff *);
-extern int isdn_ppp_dev_ioctl(struct net_device *, struct ifreq *, int);
-extern __poll_t isdn_ppp_poll(struct file *, struct poll_table_struct *);
-extern int isdn_ppp_ioctl(int, struct file *, unsigned int, unsigned long);
-extern void isdn_ppp_release(int, struct file *);
-extern int isdn_ppp_dial_slave(char *);
-extern void isdn_ppp_wakeup_daemon(isdn_net_local *);
-
-extern int isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc);
-extern int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *ipc);
-
-#define IPPP_OPEN      0x01
-#define IPPP_CONNECT   0x02
-#define IPPP_CLOSEWAIT 0x04
-#define IPPP_NOBLOCK   0x08
-#define IPPP_ASSIGNED  0x10
-
-#define IPPP_MAX_HEADER 10
 
+++ /dev/null
-/*
- * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel).
- *
- * Copyright 1994-1999  by Fritz Elfert (fritz@isdn4linux.de)
- * Copyright 1995,96    by Thinking Objects Software GmbH Wuerzburg
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-#undef ISDN_TTY_STAT_DEBUG
-
-#include <linux/isdn.h>
-#include <linux/serial.h> /* ASYNC_* flags */
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/mutex.h>
-#include <linux/sched/signal.h>
-#include "isdn_common.h"
-#include "isdn_tty.h"
-#ifdef CONFIG_ISDN_AUDIO
-#include "isdn_audio.h"
-#define VBUF 0x3e0
-#define VBUFX (VBUF/16)
-#endif
-
-#define FIX_FILE_TRANSFER
-#define        DUMMY_HAYES_AT
-
-/* Prototypes */
-
-static DEFINE_MUTEX(modem_info_mutex);
-static int isdn_tty_edit_at(const char *, int, modem_info *);
-static void isdn_tty_check_esc(const u_char *, u_char, int, int *, u_long *);
-static void isdn_tty_modem_reset_regs(modem_info *, int);
-static void isdn_tty_cmd_ATA(modem_info *);
-static void isdn_tty_flush_buffer(struct tty_struct *);
-static void isdn_tty_modem_result(int, modem_info *);
-#ifdef CONFIG_ISDN_AUDIO
-static int isdn_tty_countDLE(unsigned char *, int);
-#endif
-
-/* Leave this unchanged unless you know what you do! */
-#define MODEM_PARANOIA_CHECK
-#define MODEM_DO_RESTART
-
-static int bit2si[8] =
-{1, 5, 7, 7, 7, 7, 7, 7};
-static int si2bit[8] =
-{4, 1, 4, 4, 4, 4, 4, 4};
-
-/* isdn_tty_try_read() is called from within isdn_tty_rcv_skb()
- * to stuff incoming data directly into a tty's flip-buffer. This
- * is done to speed up tty-receiving if the receive-queue is empty.
- * This routine MUST be called with interrupts off.
- * Return:
- *  1 = Success
- *  0 = Failure, data has to be buffered and later processed by
- *      isdn_tty_readmodem().
- */
-static int
-isdn_tty_try_read(modem_info *info, struct sk_buff *skb)
-{
-       struct tty_port *port = &info->port;
-       int c;
-       int len;
-       char last;
-
-       if (!info->online)
-               return 0;
-
-       if (!(info->mcr & UART_MCR_RTS))
-               return 0;
-
-       len = skb->len
-#ifdef CONFIG_ISDN_AUDIO
-               + ISDN_AUDIO_SKB_DLECOUNT(skb)
-#endif
-               ;
-
-       c = tty_buffer_request_room(port, len);
-       if (c < len)
-               return 0;
-
-#ifdef CONFIG_ISDN_AUDIO
-       if (ISDN_AUDIO_SKB_DLECOUNT(skb)) {
-               int l = skb->len;
-               unsigned char *dp = skb->data;
-               while (--l) {
-                       if (*dp == DLE)
-                               tty_insert_flip_char(port, DLE, 0);
-                       tty_insert_flip_char(port, *dp++, 0);
-               }
-               if (*dp == DLE)
-                       tty_insert_flip_char(port, DLE, 0);
-               last = *dp;
-       } else {
-#endif
-               if (len > 1)
-                       tty_insert_flip_string(port, skb->data, len - 1);
-               last = skb->data[len - 1];
-#ifdef CONFIG_ISDN_AUDIO
-       }
-#endif
-       if (info->emu.mdmreg[REG_CPPP] & BIT_CPPP)
-               tty_insert_flip_char(port, last, 0xFF);
-       else
-               tty_insert_flip_char(port, last, TTY_NORMAL);
-       tty_flip_buffer_push(port);
-       kfree_skb(skb);
-
-       return 1;
-}
-
-/* isdn_tty_readmodem() is called periodically from within timer-interrupt.
- * It tries getting received data from the receive queue an stuff it into
- * the tty's flip-buffer.
- */
-void
-isdn_tty_readmodem(void)
-{
-       int resched = 0;
-       int midx;
-       int i;
-       int r;
-       modem_info *info;
-
-       for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-               midx = dev->m_idx[i];
-               if (midx < 0)
-                       continue;
-
-               info = &dev->mdm.info[midx];
-               if (!info->online)
-                       continue;
-
-               r = 0;
-#ifdef CONFIG_ISDN_AUDIO
-               isdn_audio_eval_dtmf(info);
-               if ((info->vonline & 1) && (info->emu.vpar[1]))
-                       isdn_audio_eval_silence(info);
-#endif
-               if (info->mcr & UART_MCR_RTS) {
-                       /* CISCO AsyncPPP Hack */
-                       if (!(info->emu.mdmreg[REG_CPPP] & BIT_CPPP))
-                               r = isdn_readbchan_tty(info->isdn_driver,
-                                               info->isdn_channel,
-                                               &info->port, 0);
-                       else
-                               r = isdn_readbchan_tty(info->isdn_driver,
-                                               info->isdn_channel,
-                                               &info->port, 1);
-                       if (r)
-                               tty_flip_buffer_push(&info->port);
-               } else
-                       r = 1;
-
-               if (r) {
-                       info->rcvsched = 0;
-                       resched = 1;
-               } else
-                       info->rcvsched = 1;
-       }
-       if (!resched)
-               isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 0);
-}
-
-int
-isdn_tty_rcv_skb(int i, int di, int channel, struct sk_buff *skb)
-{
-       ulong flags;
-       int midx;
-#ifdef CONFIG_ISDN_AUDIO
-       int ifmt;
-#endif
-       modem_info *info;
-
-       if ((midx = dev->m_idx[i]) < 0) {
-               /* if midx is invalid, packet is not for tty */
-               return 0;
-       }
-       info = &dev->mdm.info[midx];
-#ifdef CONFIG_ISDN_AUDIO
-       ifmt = 1;
-
-       if ((info->vonline) && (!info->emu.vpar[4]))
-               isdn_audio_calc_dtmf(info, skb->data, skb->len, ifmt);
-       if ((info->vonline & 1) && (info->emu.vpar[1]))
-               isdn_audio_calc_silence(info, skb->data, skb->len, ifmt);
-#endif
-       if ((info->online < 2)
-#ifdef CONFIG_ISDN_AUDIO
-           && (!(info->vonline & 1))
-#endif
-               ) {
-               /* If Modem not listening, drop data */
-               kfree_skb(skb);
-               return 1;
-       }
-       if (info->emu.mdmreg[REG_T70] & BIT_T70) {
-               if (info->emu.mdmreg[REG_T70] & BIT_T70_EXT) {
-                       /* T.70 decoding: throw away the T.70 header (2 or 4 bytes)   */
-                       if (skb->data[0] == 3) /* pure data packet -> 4 byte headers  */
-                               skb_pull(skb, 4);
-                       else
-                               if (skb->data[0] == 1) /* keepalive packet -> 2 byte hdr  */
-                                       skb_pull(skb, 2);
-               } else
-                       /* T.70 decoding: Simply throw away the T.70 header (4 bytes) */
-                       if ((skb->data[0] == 1) && ((skb->data[1] == 0) || (skb->data[1] == 1)))
-                               skb_pull(skb, 4);
-       }
-#ifdef CONFIG_ISDN_AUDIO
-       ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
-       ISDN_AUDIO_SKB_LOCK(skb) = 0;
-       if (info->vonline & 1) {
-               /* voice conversion/compression */
-               switch (info->emu.vpar[3]) {
-               case 2:
-               case 3:
-               case 4:
-                       /* adpcm
-                        * Since compressed data takes less
-                        * space, we can overwrite the buffer.
-                        */
-                       skb_trim(skb, isdn_audio_xlaw2adpcm(info->adpcmr,
-                                                           ifmt,
-                                                           skb->data,
-                                                           skb->data,
-                                                           skb->len));
-                       break;
-               case 5:
-                       /* a-law */
-                       if (!ifmt)
-                               isdn_audio_ulaw2alaw(skb->data, skb->len);
-                       break;
-               case 6:
-                       /* u-law */
-                       if (ifmt)
-                               isdn_audio_alaw2ulaw(skb->data, skb->len);
-                       break;
-               }
-               ISDN_AUDIO_SKB_DLECOUNT(skb) =
-                       isdn_tty_countDLE(skb->data, skb->len);
-       }
-#ifdef CONFIG_ISDN_TTY_FAX
-       else {
-               if (info->faxonline & 2) {
-                       isdn_tty_fax_bitorder(info, skb);
-                       ISDN_AUDIO_SKB_DLECOUNT(skb) =
-                               isdn_tty_countDLE(skb->data, skb->len);
-               }
-       }
-#endif
-#endif
-       /* Try to deliver directly via tty-buf if queue is empty */
-       spin_lock_irqsave(&info->readlock, flags);
-       if (skb_queue_empty(&dev->drv[di]->rpqueue[channel]))
-               if (isdn_tty_try_read(info, skb)) {
-                       spin_unlock_irqrestore(&info->readlock, flags);
-                       return 1;
-               }
-       /* Direct deliver failed or queue wasn't empty.
-        * Queue up for later dequeueing via timer-irq.
-        */
-       __skb_queue_tail(&dev->drv[di]->rpqueue[channel], skb);
-       dev->drv[di]->rcvcount[channel] +=
-               (skb->len
-#ifdef CONFIG_ISDN_AUDIO
-                + ISDN_AUDIO_SKB_DLECOUNT(skb)
-#endif
-                       );
-       spin_unlock_irqrestore(&info->readlock, flags);
-       /* Schedule dequeuing */
-       if ((dev->modempoll) && (info->rcvsched))
-               isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
-       return 1;
-}
-
-static void
-isdn_tty_cleanup_xmit(modem_info *info)
-{
-       skb_queue_purge(&info->xmit_queue);
-#ifdef CONFIG_ISDN_AUDIO
-       skb_queue_purge(&info->dtmf_queue);
-#endif
-}
-
-static void
-isdn_tty_tint(modem_info *info)
-{
-       struct sk_buff *skb = skb_dequeue(&info->xmit_queue);
-       int len, slen;
-
-       if (!skb)
-               return;
-       len = skb->len;
-       if ((slen = isdn_writebuf_skb_stub(info->isdn_driver,
-                                          info->isdn_channel, 1, skb)) == len) {
-               struct tty_struct *tty = info->port.tty;
-               info->send_outstanding++;
-               info->msr &= ~UART_MSR_CTS;
-               info->lsr &= ~UART_LSR_TEMT;
-               tty_wakeup(tty);
-               return;
-       }
-       if (slen < 0) {
-               /* Error: no channel, already shutdown, or wrong parameter */
-               dev_kfree_skb(skb);
-               return;
-       }
-       skb_queue_head(&info->xmit_queue, skb);
-}
-
-#ifdef CONFIG_ISDN_AUDIO
-static int
-isdn_tty_countDLE(unsigned char *buf, int len)
-{
-       int count = 0;
-
-       while (len--)
-               if (*buf++ == DLE)
-                       count++;
-       return count;
-}
-
-/* This routine is called from within isdn_tty_write() to perform
- * DLE-decoding when sending audio-data.
- */
-static int
-isdn_tty_handleDLEdown(modem_info *info, atemu *m, int len)
-{
-       unsigned char *p = &info->port.xmit_buf[info->xmit_count];
-       int count = 0;
-
-       while (len > 0) {
-               if (m->lastDLE) {
-                       m->lastDLE = 0;
-                       switch (*p) {
-                       case DLE:
-                               /* Escape code */
-                               if (len > 1)
-                                       memmove(p, p + 1, len - 1);
-                               p--;
-                               count++;
-                               break;
-                       case ETX:
-                               /* End of data */
-                               info->vonline |= 4;
-                               return count;
-                       case DC4:
-                               /* Abort RX */
-                               info->vonline &= ~1;
-#ifdef ISDN_DEBUG_MODEM_VOICE
-                               printk(KERN_DEBUG
-                                      "DLEdown: got DLE-DC4, send DLE-ETX on ttyI%d\n",
-                                      info->line);
-#endif
-                               isdn_tty_at_cout("\020\003", info);
-                               if (!info->vonline) {
-#ifdef ISDN_DEBUG_MODEM_VOICE
-                                       printk(KERN_DEBUG
-                                              "DLEdown: send VCON on ttyI%d\n",
-                                              info->line);
-#endif
-                                       isdn_tty_at_cout("\r\nVCON\r\n", info);
-                               }
-                               /* Fall through */
-                       case 'q':
-                       case 's':
-                               /* Silence */
-                               if (len > 1)
-                                       memmove(p, p + 1, len - 1);
-                               p--;
-                               break;
-                       }
-               } else {
-                       if (*p == DLE)
-                               m->lastDLE = 1;
-                       else
-                               count++;
-               }
-               p++;
-               len--;
-       }
-       if (len < 0) {
-               printk(KERN_WARNING "isdn_tty: len<0 in DLEdown\n");
-               return 0;
-       }
-       return count;
-}
-
-/* This routine is called from within isdn_tty_write() when receiving
- * audio-data. It interrupts receiving, if an character other than
- * ^S or ^Q is sent.
- */
-static int
-isdn_tty_end_vrx(const char *buf, int c)
-{
-       char ch;
-
-       while (c--) {
-               ch = *buf;
-               if ((ch != 0x11) && (ch != 0x13))
-                       return 1;
-               buf++;
-       }
-       return 0;
-}
-
-static int voice_cf[7] =
-{0, 0, 4, 3, 2, 0, 0};
-
-#endif                          /* CONFIG_ISDN_AUDIO */
-
-/* isdn_tty_senddown() is called either directly from within isdn_tty_write()
- * or via timer-interrupt from within isdn_tty_modem_xmit(). It pulls
- * outgoing data from the tty's xmit-buffer, handles voice-decompression or
- * T.70 if necessary, and finally queues it up for sending via isdn_tty_tint.
- */
-static void
-isdn_tty_senddown(modem_info *info)
-{
-       int buflen;
-       int skb_res;
-#ifdef CONFIG_ISDN_AUDIO
-       int audio_len;
-#endif
-       struct sk_buff *skb;
-
-#ifdef CONFIG_ISDN_AUDIO
-       if (info->vonline & 4) {
-               info->vonline &= ~6;
-               if (!info->vonline) {
-#ifdef ISDN_DEBUG_MODEM_VOICE
-                       printk(KERN_DEBUG
-                              "senddown: send VCON on ttyI%d\n",
-                              info->line);
-#endif
-                       isdn_tty_at_cout("\r\nVCON\r\n", info);
-               }
-       }
-#endif
-       if (!(buflen = info->xmit_count))
-               return;
-       if ((info->emu.mdmreg[REG_CTS] & BIT_CTS) != 0)
-               info->msr &= ~UART_MSR_CTS;
-       info->lsr &= ~UART_LSR_TEMT;
-       /* info->xmit_count is modified here and in isdn_tty_write().
-        * So we return here if isdn_tty_write() is in the
-        * critical section.
-        */
-       atomic_inc(&info->xmit_lock);
-       if (!(atomic_dec_and_test(&info->xmit_lock)))
-               return;
-       if (info->isdn_driver < 0) {
-               info->xmit_count = 0;
-               return;
-       }
-       skb_res = dev->drv[info->isdn_driver]->interface->hl_hdrlen + 4;
-#ifdef CONFIG_ISDN_AUDIO
-       if (info->vonline & 2)
-               audio_len = buflen * voice_cf[info->emu.vpar[3]];
-       else
-               audio_len = 0;
-       skb = dev_alloc_skb(skb_res + buflen + audio_len);
-#else
-       skb = dev_alloc_skb(skb_res + buflen);
-#endif
-       if (!skb) {
-               printk(KERN_WARNING
-                      "isdn_tty: Out of memory in ttyI%d senddown\n",
-                      info->line);
-               return;
-       }
-       skb_reserve(skb, skb_res);
-       skb_put_data(skb, info->port.xmit_buf, buflen);
-       info->xmit_count = 0;
-#ifdef CONFIG_ISDN_AUDIO
-       if (info->vonline & 2) {
-               /* For now, ifmt is fixed to 1 (alaw), since this
-                * is used with ISDN everywhere in the world, except
-                * US, Canada and Japan.
-                * Later, when US-ISDN protocols are implemented,
-                * this setting will depend on the D-channel protocol.
-                */
-               int ifmt = 1;
-
-               /* voice conversion/decompression */
-               switch (info->emu.vpar[3]) {
-               case 2:
-               case 3:
-               case 4:
-                       /* adpcm, compatible to ZyXel 1496 modem
-                        * with ROM revision 6.01
-                        */
-                       audio_len = isdn_audio_adpcm2xlaw(info->adpcms,
-                                                         ifmt,
-                                                         skb->data,
-                                                         skb_put(skb, audio_len),
-                                                         buflen);
-                       skb_pull(skb, buflen);
-                       skb_trim(skb, audio_len);
-                       break;
-               case 5:
-                       /* a-law */
-                       if (!ifmt)
-                               isdn_audio_alaw2ulaw(skb->data,
-                                                    buflen);
-                       break;
-               case 6:
-                       /* u-law */
-                       if (ifmt)
-                               isdn_audio_ulaw2alaw(skb->data,
-                                                    buflen);
-                       break;
-               }
-       }
-#endif                          /* CONFIG_ISDN_AUDIO */
-       if (info->emu.mdmreg[REG_T70] & BIT_T70) {
-               /* Add T.70 simplified header */
-               if (info->emu.mdmreg[REG_T70] & BIT_T70_EXT)
-                       memcpy(skb_push(skb, 2), "\1\0", 2);
-               else
-                       memcpy(skb_push(skb, 4), "\1\0\1\0", 4);
-       }
-       skb_queue_tail(&info->xmit_queue, skb);
-}
-
-/************************************************************
- *
- * Modem-functions
- *
- * mostly "stolen" from original Linux-serial.c and friends.
- *
- ************************************************************/
-
-/* The next routine is called once from within timer-interrupt
- * triggered within isdn_tty_modem_ncarrier(). It calls
- * isdn_tty_modem_result() to stuff a "NO CARRIER" Message
- * into the tty's buffer.
- */
-static void
-isdn_tty_modem_do_ncarrier(struct timer_list *t)
-{
-       modem_info *info = from_timer(info, t, nc_timer);
-       isdn_tty_modem_result(RESULT_NO_CARRIER, info);
-}
-
-/* Next routine is called, whenever the DTR-signal is raised.
- * It checks the ncarrier-flag, and triggers the above routine
- * when necessary. The ncarrier-flag is set, whenever DTR goes
- * low.
- */
-static void
-isdn_tty_modem_ncarrier(modem_info *info)
-{
-       if (info->ncarrier) {
-               info->nc_timer.expires = jiffies + HZ;
-               add_timer(&info->nc_timer);
-       }
-}
-
-/*
- * return the usage calculated by si and layer 2 protocol
- */
-static int
-isdn_calc_usage(int si, int l2)
-{
-       int usg = ISDN_USAGE_MODEM;
-
-#ifdef CONFIG_ISDN_AUDIO
-       if (si == 1) {
-               switch (l2) {
-               case ISDN_PROTO_L2_MODEM:
-                       usg = ISDN_USAGE_MODEM;
-                       break;
-#ifdef CONFIG_ISDN_TTY_FAX
-               case ISDN_PROTO_L2_FAX:
-                       usg = ISDN_USAGE_FAX;
-                       break;
-#endif
-               case ISDN_PROTO_L2_TRANS:
-               default:
-                       usg = ISDN_USAGE_VOICE;
-                       break;
-               }
-       }
-#endif
-       return (usg);
-}
-
-/* isdn_tty_dial() performs dialing of a tty an the necessary
- * setup of the lower levels before that.
- */
-static void
-isdn_tty_dial(char *n, modem_info *info, atemu *m)
-{
-       int usg = ISDN_USAGE_MODEM;
-       int si = 7;
-       int l2 = m->mdmreg[REG_L2PROT];
-       u_long flags;
-       isdn_ctrl cmd;
-       int i;
-       int j;
-
-       for (j = 7; j >= 0; j--)
-               if (m->mdmreg[REG_SI1] & (1 << j)) {
-                       si = bit2si[j];
-                       break;
-               }
-       usg = isdn_calc_usage(si, l2);
-#ifdef CONFIG_ISDN_AUDIO
-       if ((si == 1) &&
-           (l2 != ISDN_PROTO_L2_MODEM)
-#ifdef CONFIG_ISDN_TTY_FAX
-           && (l2 != ISDN_PROTO_L2_FAX)
-#endif
-               ) {
-               l2 = ISDN_PROTO_L2_TRANS;
-               usg = ISDN_USAGE_VOICE;
-       }
-#endif
-       m->mdmreg[REG_SI1I] = si2bit[si];
-       spin_lock_irqsave(&dev->lock, flags);
-       i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);
-       if (i < 0) {
-               spin_unlock_irqrestore(&dev->lock, flags);
-               isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
-       } else {
-               info->isdn_driver = dev->drvmap[i];
-               info->isdn_channel = dev->chanmap[i];
-               info->drv_index = i;
-               dev->m_idx[i] = info->line;
-               dev->usage[i] |= ISDN_USAGE_OUTGOING;
-               info->last_dir = 1;
-               strcpy(info->last_num, n);
-               isdn_info_update();
-               spin_unlock_irqrestore(&dev->lock, flags);
-               cmd.driver = info->isdn_driver;
-               cmd.arg = info->isdn_channel;
-               cmd.command = ISDN_CMD_CLREAZ;
-               isdn_command(&cmd);
-               strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));
-               cmd.driver = info->isdn_driver;
-               cmd.command = ISDN_CMD_SETEAZ;
-               isdn_command(&cmd);
-               cmd.driver = info->isdn_driver;
-               cmd.command = ISDN_CMD_SETL2;
-               info->last_l2 = l2;
-               cmd.arg = info->isdn_channel + (l2 << 8);
-               isdn_command(&cmd);
-               cmd.driver = info->isdn_driver;
-               cmd.command = ISDN_CMD_SETL3;
-               cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
-#ifdef CONFIG_ISDN_TTY_FAX
-               if (l2 == ISDN_PROTO_L2_FAX) {
-                       cmd.parm.fax = info->fax;
-                       info->fax->direction = ISDN_TTY_FAX_CONN_OUT;
-               }
-#endif
-               isdn_command(&cmd);
-               cmd.driver = info->isdn_driver;
-               cmd.arg = info->isdn_channel;
-               sprintf(cmd.parm.setup.phone, "%s", n);
-               sprintf(cmd.parm.setup.eazmsn, "%s",
-                       isdn_map_eaz2msn(m->msn, info->isdn_driver));
-               cmd.parm.setup.si1 = si;
-               cmd.parm.setup.si2 = m->mdmreg[REG_SI2];
-               cmd.command = ISDN_CMD_DIAL;
-               info->dialing = 1;
-               info->emu.carrierwait = 0;
-               strcpy(dev->num[i], n);
-               isdn_info_update();
-               isdn_command(&cmd);
-               isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1);
-       }
-}
-
-/* isdn_tty_hangup() disassociates a tty from the real
- * ISDN-line (hangup). The usage-status is cleared
- * and some cleanup is done also.
- */
-void
-isdn_tty_modem_hup(modem_info *info, int local)
-{
-       isdn_ctrl cmd;
-       int di, ch;
-
-       if (!info)
-               return;
-
-       di = info->isdn_driver;
-       ch = info->isdn_channel;
-       if (di < 0 || ch < 0)
-               return;
-
-       info->isdn_driver = -1;
-       info->isdn_channel = -1;
-
-#ifdef ISDN_DEBUG_MODEM_HUP
-       printk(KERN_DEBUG "Mhup ttyI%d\n", info->line);
-#endif
-       info->rcvsched = 0;
-       isdn_tty_flush_buffer(info->port.tty);
-       if (info->online) {
-               info->last_lhup = local;
-               info->online = 0;
-               isdn_tty_modem_result(RESULT_NO_CARRIER, info);
-       }
-#ifdef CONFIG_ISDN_AUDIO
-       info->vonline = 0;
-#ifdef CONFIG_ISDN_TTY_FAX
-       info->faxonline = 0;
-       info->fax->phase = ISDN_FAX_PHASE_IDLE;
-#endif
-       info->emu.vpar[4] = 0;
-       info->emu.vpar[5] = 8;
-       kfree(info->dtmf_state);
-       info->dtmf_state = NULL;
-       kfree(info->silence_state);
-       info->silence_state = NULL;
-       kfree(info->adpcms);
-       info->adpcms = NULL;
-       kfree(info->adpcmr);
-       info->adpcmr = NULL;
-#endif
-       if ((info->msr & UART_MSR_RI) &&
-           (info->emu.mdmreg[REG_RUNG] & BIT_RUNG))
-               isdn_tty_modem_result(RESULT_RUNG, info);
-       info->msr &= ~(UART_MSR_DCD | UART_MSR_RI);
-       info->lsr |= UART_LSR_TEMT;
-
-       if (local) {
-               cmd.driver = di;
-               cmd.command = ISDN_CMD_HANGUP;
-               cmd.arg = ch;
-               isdn_command(&cmd);
-       }
-
-       isdn_all_eaz(di, ch);
-       info->emu.mdmreg[REG_RINGCNT] = 0;
-       isdn_free_channel(di, ch, 0);
-
-       if (info->drv_index >= 0) {
-               dev->m_idx[info->drv_index] = -1;
-               info->drv_index = -1;
-       }
-}
-
-/*
- * Begin of a CAPI like interface, currently used only for
- * supplementary service (CAPI 2.0 part III)
- */
-#include <linux/isdn/capicmd.h>
-#include <linux/module.h>
-
-int
-isdn_tty_capi_facility(capi_msg *cm) {
-       return (-1); /* dummy */
-}
-
-/* isdn_tty_suspend() tries to suspend the current tty connection
- */
-static void
-isdn_tty_suspend(char *id, modem_info *info, atemu *m)
-{
-       isdn_ctrl cmd;
-
-       int l;
-
-       if (!info)
-               return;
-
-#ifdef ISDN_DEBUG_MODEM_SERVICES
-       printk(KERN_DEBUG "Msusp ttyI%d\n", info->line);
-#endif
-       l = strlen(id);
-       if ((info->isdn_driver >= 0)) {
-               cmd.parm.cmsg.Length = l + 18;
-               cmd.parm.cmsg.Command = CAPI_FACILITY;
-               cmd.parm.cmsg.Subcommand = CAPI_REQ;
-               cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1;
-               cmd.parm.cmsg.para[0] = 3; /* 16 bit 0x0003 suplementary service */
-               cmd.parm.cmsg.para[1] = 0;
-               cmd.parm.cmsg.para[2] = l + 3;
-               cmd.parm.cmsg.para[3] = 4; /* 16 bit 0x0004 Suspend */
-               cmd.parm.cmsg.para[4] = 0;
-               cmd.parm.cmsg.para[5] = l;
-               memcpy(&cmd.parm.cmsg.para[6], id, l);
-               cmd.command = CAPI_PUT_MESSAGE;
-               cmd.driver = info->isdn_driver;
-               cmd.arg = info->isdn_channel;
-               isdn_command(&cmd);
-       }
-}
-
-/* isdn_tty_resume() tries to resume a suspended call
- * setup of the lower levels before that. unfortunately here is no
- * checking for compatibility of used protocols implemented by Q931
- * It does the same things like isdn_tty_dial, the last command
- * is different, may be we can merge it.
- */
-
-static void
-isdn_tty_resume(char *id, modem_info *info, atemu *m)
-{
-       int usg = ISDN_USAGE_MODEM;
-       int si = 7;
-       int l2 = m->mdmreg[REG_L2PROT];
-       isdn_ctrl cmd;
-       ulong flags;
-       int i;
-       int j;
-       int l;
-
-       l = strlen(id);
-       for (j = 7; j >= 0; j--)
-               if (m->mdmreg[REG_SI1] & (1 << j)) {
-                       si = bit2si[j];
-                       break;
-               }
-       usg = isdn_calc_usage(si, l2);
-#ifdef CONFIG_ISDN_AUDIO
-       if ((si == 1) &&
-           (l2 != ISDN_PROTO_L2_MODEM)
-#ifdef CONFIG_ISDN_TTY_FAX
-           && (l2 != ISDN_PROTO_L2_FAX)
-#endif
-               ) {
-               l2 = ISDN_PROTO_L2_TRANS;
-               usg = ISDN_USAGE_VOICE;
-       }
-#endif
-       m->mdmreg[REG_SI1I] = si2bit[si];
-       spin_lock_irqsave(&dev->lock, flags);
-       i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);
-       if (i < 0) {
-               spin_unlock_irqrestore(&dev->lock, flags);
-               isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
-       } else {
-               info->isdn_driver = dev->drvmap[i];
-               info->isdn_channel = dev->chanmap[i];
-               info->drv_index = i;
-               dev->m_idx[i] = info->line;
-               dev->usage[i] |= ISDN_USAGE_OUTGOING;
-               info->last_dir = 1;
-//             strcpy(info->last_num, n);
-               isdn_info_update();
-               spin_unlock_irqrestore(&dev->lock, flags);
-               cmd.driver = info->isdn_driver;
-               cmd.arg = info->isdn_channel;
-               cmd.command = ISDN_CMD_CLREAZ;
-               isdn_command(&cmd);
-               strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));
-               cmd.driver = info->isdn_driver;
-               cmd.command = ISDN_CMD_SETEAZ;
-               isdn_command(&cmd);
-               cmd.driver = info->isdn_driver;
-               cmd.command = ISDN_CMD_SETL2;
-               info->last_l2 = l2;
-               cmd.arg = info->isdn_channel + (l2 << 8);
-               isdn_command(&cmd);
-               cmd.driver = info->isdn_driver;
-               cmd.command = ISDN_CMD_SETL3;
-               cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
-               isdn_command(&cmd);
-               cmd.driver = info->isdn_driver;
-               cmd.arg = info->isdn_channel;
-               cmd.parm.cmsg.Length = l + 18;
-               cmd.parm.cmsg.Command = CAPI_FACILITY;
-               cmd.parm.cmsg.Subcommand = CAPI_REQ;
-               cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1;
-               cmd.parm.cmsg.para[0] = 3; /* 16 bit 0x0003 suplementary service */
-               cmd.parm.cmsg.para[1] = 0;
-               cmd.parm.cmsg.para[2] = l + 3;
-               cmd.parm.cmsg.para[3] = 5; /* 16 bit 0x0005 Resume */
-               cmd.parm.cmsg.para[4] = 0;
-               cmd.parm.cmsg.para[5] = l;
-               memcpy(&cmd.parm.cmsg.para[6], id, l);
-               cmd.command = CAPI_PUT_MESSAGE;
-               info->dialing = 1;
-//             strcpy(dev->num[i], n);
-               isdn_info_update();
-               isdn_command(&cmd);
-               isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1);
-       }
-}
-
-/* isdn_tty_send_msg() sends a message to a HL driver
- * This is used for hybrid modem cards to send AT commands to it
- */
-
-static void
-isdn_tty_send_msg(modem_info *info, atemu *m, char *msg)
-{
-       int usg = ISDN_USAGE_MODEM;
-       int si = 7;
-       int l2 = m->mdmreg[REG_L2PROT];
-       isdn_ctrl cmd;
-       ulong flags;
-       int i;
-       int j;
-       int l;
-
-       l = min(strlen(msg), sizeof(cmd.parm) - sizeof(cmd.parm.cmsg)
-               + sizeof(cmd.parm.cmsg.para) - 2);
-
-       if (!l) {
-               isdn_tty_modem_result(RESULT_ERROR, info);
-               return;
-       }
-       for (j = 7; j >= 0; j--)
-               if (m->mdmreg[REG_SI1] & (1 << j)) {
-                       si = bit2si[j];
-                       break;
-               }
-       usg = isdn_calc_usage(si, l2);
-#ifdef CONFIG_ISDN_AUDIO
-       if ((si == 1) &&
-           (l2 != ISDN_PROTO_L2_MODEM)
-#ifdef CONFIG_ISDN_TTY_FAX
-           && (l2 != ISDN_PROTO_L2_FAX)
-#endif
-               ) {
-               l2 = ISDN_PROTO_L2_TRANS;
-               usg = ISDN_USAGE_VOICE;
-       }
-#endif
-       m->mdmreg[REG_SI1I] = si2bit[si];
-       spin_lock_irqsave(&dev->lock, flags);
-       i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);
-       if (i < 0) {
-               spin_unlock_irqrestore(&dev->lock, flags);
-               isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
-       } else {
-               info->isdn_driver = dev->drvmap[i];
-               info->isdn_channel = dev->chanmap[i];
-               info->drv_index = i;
-               dev->m_idx[i] = info->line;
-               dev->usage[i] |= ISDN_USAGE_OUTGOING;
-               info->last_dir = 1;
-               isdn_info_update();
-               spin_unlock_irqrestore(&dev->lock, flags);
-               cmd.driver = info->isdn_driver;
-               cmd.arg = info->isdn_channel;
-               cmd.command = ISDN_CMD_CLREAZ;
-               isdn_command(&cmd);
-               strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));
-               cmd.driver = info->isdn_driver;
-               cmd.command = ISDN_CMD_SETEAZ;
-               isdn_command(&cmd);
-               cmd.driver = info->isdn_driver;
-               cmd.command = ISDN_CMD_SETL2;
-               info->last_l2 = l2;
-               cmd.arg = info->isdn_channel + (l2 << 8);
-               isdn_command(&cmd);
-               cmd.driver = info->isdn_driver;
-               cmd.command = ISDN_CMD_SETL3;
-               cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
-               isdn_command(&cmd);
-               cmd.driver = info->isdn_driver;
-               cmd.arg = info->isdn_channel;
-               cmd.parm.cmsg.Length = l + 14;
-               cmd.parm.cmsg.Command = CAPI_MANUFACTURER;
-               cmd.parm.cmsg.Subcommand = CAPI_REQ;
-               cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1;
-               cmd.parm.cmsg.para[0] = l + 1;
-               strncpy(&cmd.parm.cmsg.para[1], msg, l);
-               cmd.parm.cmsg.para[l + 1] = 0xd;
-               cmd.command = CAPI_PUT_MESSAGE;
-/*             info->dialing = 1;
-               strcpy(dev->num[i], n);
-               isdn_info_update();
-*/
-               isdn_command(&cmd);
-       }
-}
-
-static inline int
-isdn_tty_paranoia_check(modem_info *info, char *name, const char *routine)
-{
-#ifdef MODEM_PARANOIA_CHECK
-       if (!info) {
-               printk(KERN_WARNING "isdn_tty: null info_struct for %s in %s\n",
-                      name, routine);
-               return 1;
-       }
-       if (info->magic != ISDN_ASYNC_MAGIC) {
-               printk(KERN_WARNING "isdn_tty: bad magic for modem struct %s in %s\n",
-                      name, routine);
-               return 1;
-       }
-#endif
-       return 0;
-}
-
-/*
- * This routine is called to set the UART divisor registers to match
- * the specified baud rate for a serial port.
- */
-static void
-isdn_tty_change_speed(modem_info *info)
-{
-       struct tty_port *port = &info->port;
-       uint cflag,
-               cval,
-               quot;
-       int i;
-
-       if (!port->tty)
-               return;
-       cflag = port->tty->termios.c_cflag;
-
-       quot = i = cflag & CBAUD;
-       if (i & CBAUDEX) {
-               i &= ~CBAUDEX;
-               if (i < 1 || i > 2)
-                       port->tty->termios.c_cflag &= ~CBAUDEX;
-               else
-                       i += 15;
-       }
-       if (quot) {
-               info->mcr |= UART_MCR_DTR;
-               isdn_tty_modem_ncarrier(info);
-       } else {
-               info->mcr &= ~UART_MCR_DTR;
-               if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {
-#ifdef ISDN_DEBUG_MODEM_HUP
-                       printk(KERN_DEBUG "Mhup in changespeed\n");
-#endif
-                       if (info->online)
-                               info->ncarrier = 1;
-                       isdn_tty_modem_reset_regs(info, 0);
-                       isdn_tty_modem_hup(info, 1);
-               }
-               return;
-       }
-       /* byte size and parity */
-       cval = cflag & (CSIZE | CSTOPB);
-       cval >>= 4;
-       if (cflag & PARENB)
-               cval |= UART_LCR_PARITY;
-       if (!(cflag & PARODD))
-               cval |= UART_LCR_EPAR;
-
-       tty_port_set_check_carrier(port, ~cflag & CLOCAL);
-}
-
-static int
-isdn_tty_startup(modem_info *info)
-{
-       if (tty_port_initialized(&info->port))
-               return 0;
-       isdn_lock_drivers();
-#ifdef ISDN_DEBUG_MODEM_OPEN
-       printk(KERN_DEBUG "starting up ttyi%d ...\n", info->line);
-#endif
-       /*
-        * Now, initialize the UART
-        */
-       info->mcr = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
-       if (info->port.tty)
-               clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
-       /*
-        * and set the speed of the serial port
-        */
-       isdn_tty_change_speed(info);
-
-       tty_port_set_initialized(&info->port, 1);
-       info->msr |= (UART_MSR_DSR | UART_MSR_CTS);
-       info->send_outstanding = 0;
-       return 0;
-}
-
-/*
- * This routine will shutdown a serial port; interrupts are disabled, and
- * DTR is dropped if the hangup on close termio flag is on.
- */
-static void
-isdn_tty_shutdown(modem_info *info)
-{
-       if (!tty_port_initialized(&info->port))
-               return;
-#ifdef ISDN_DEBUG_MODEM_OPEN
-       printk(KERN_DEBUG "Shutting down isdnmodem port %d ....\n", info->line);
-#endif
-       isdn_unlock_drivers();
-       info->msr &= ~UART_MSR_RI;
-       if (!info->port.tty || (info->port.tty->termios.c_cflag & HUPCL)) {
-               info->mcr &= ~(UART_MCR_DTR | UART_MCR_RTS);
-               if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {
-                       isdn_tty_modem_reset_regs(info, 0);
-#ifdef ISDN_DEBUG_MODEM_HUP
-                       printk(KERN_DEBUG "Mhup in isdn_tty_shutdown\n");
-#endif
-                       isdn_tty_modem_hup(info, 1);
-               }
-       }
-       if (info->port.tty)
-               set_bit(TTY_IO_ERROR, &info->port.tty->flags);
-
-       tty_port_set_initialized(&info->port, 0);
-}
-
-/* isdn_tty_write() is the main send-routine. It is called from the upper
- * levels within the kernel to perform sending data. Depending on the
- * online-flag it either directs output to the at-command-interpreter or
- * to the lower level. Additional tasks done here:
- *  - If online, check for escape-sequence (+++)
- *  - If sending audio-data, call isdn_tty_DLEdown() to parse DLE-codes.
- *  - If receiving audio-data, call isdn_tty_end_vrx() to abort if needed.
- *  - If dialing, abort dial.
- */
-static int
-isdn_tty_write(struct tty_struct *tty, const u_char *buf, int count)
-{
-       int c;
-       int total = 0;
-       modem_info *info = (modem_info *) tty->driver_data;
-       atemu *m = &info->emu;
-
-       if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_write"))
-               return 0;
-       /* See isdn_tty_senddown() */
-       atomic_inc(&info->xmit_lock);
-       while (1) {
-               c = count;
-               if (c > info->xmit_size - info->xmit_count)
-                       c = info->xmit_size - info->xmit_count;
-               if (info->isdn_driver >= 0 && c > dev->drv[info->isdn_driver]->maxbufsize)
-                       c = dev->drv[info->isdn_driver]->maxbufsize;
-               if (c <= 0)
-                       break;
-               if ((info->online > 1)
-#ifdef CONFIG_ISDN_AUDIO
-                   || (info->vonline & 3)
-#endif
-                       ) {
-#ifdef CONFIG_ISDN_AUDIO
-                       if (!info->vonline)
-#endif
-                               isdn_tty_check_esc(buf, m->mdmreg[REG_ESC], c,
-                                                  &(m->pluscount),
-                                                  &(m->lastplus));
-                       memcpy(&info->port.xmit_buf[info->xmit_count], buf, c);
-#ifdef CONFIG_ISDN_AUDIO
-                       if (info->vonline) {
-                               int cc = isdn_tty_handleDLEdown(info, m, c);
-                               if (info->vonline & 2) {
-                                       if (!cc) {
-                                               /* If DLE decoding results in zero-transmit, but
-                                                * c originally was non-zero, do a wakeup.
-                                                */
-                                               tty_wakeup(tty);
-                                               info->msr |= UART_MSR_CTS;
-                                               info->lsr |= UART_LSR_TEMT;
-                                       }
-                                       info->xmit_count += cc;
-                               }
-                               if ((info->vonline & 3) == 1) {
-                                       /* Do NOT handle Ctrl-Q or Ctrl-S
-                                        * when in full-duplex audio mode.
-                                        */
-                                       if (isdn_tty_end_vrx(buf, c)) {
-                                               info->vonline &= ~1;
-#ifdef ISDN_DEBUG_MODEM_VOICE
-                                               printk(KERN_DEBUG
-                                                      "got !^Q/^S, send DLE-ETX,VCON on ttyI%d\n",
-                                                      info->line);
-#endif
-                                               isdn_tty_at_cout("\020\003\r\nVCON\r\n", info);
-                                       }
-                               }
-                       } else
-                               if (TTY_IS_FCLASS1(info)) {
-                                       int cc = isdn_tty_handleDLEdown(info, m, c);
-
-                                       if (info->vonline & 4) { /* ETX seen */
-                                               isdn_ctrl c;
-
-                                               c.command = ISDN_CMD_FAXCMD;
-                                               c.driver = info->isdn_driver;
-                                               c.arg = info->isdn_channel;
-                                               c.parm.aux.cmd = ISDN_FAX_CLASS1_CTRL;
-                                               c.parm.aux.subcmd = ETX;
-                                               isdn_command(&c);
-                                       }
-                                       info->vonline = 0;
-#ifdef ISDN_DEBUG_MODEM_VOICE
-                                       printk(KERN_DEBUG "fax dle cc/c %d/%d\n", cc, c);
-#endif
-                                       info->xmit_count += cc;
-                               } else
-#endif
-                                       info->xmit_count += c;
-               } else {
-                       info->msr |= UART_MSR_CTS;
-                       info->lsr |= UART_LSR_TEMT;
-                       if (info->dialing) {
-                               info->dialing = 0;
-#ifdef ISDN_DEBUG_MODEM_HUP
-                               printk(KERN_DEBUG "Mhup in isdn_tty_write\n");
-#endif
-                               isdn_tty_modem_result(RESULT_NO_CARRIER, info);
-                               isdn_tty_modem_hup(info, 1);
-                       } else
-                               c = isdn_tty_edit_at(buf, c, info);
-               }
-               buf += c;
-               count -= c;
-               total += c;
-       }
-       atomic_dec(&info->xmit_lock);
-       if ((info->xmit_count) || !skb_queue_empty(&info->xmit_queue)) {
-               if (m->mdmreg[REG_DXMT] & BIT_DXMT) {
-                       isdn_tty_senddown(info);
-                       isdn_tty_tint(info);
-               }
-               isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1);
-       }
-       return total;
-}
-
-static int
-isdn_tty_write_room(struct tty_struct *tty)
-{
-       modem_info *info = (modem_info *) tty->driver_data;
-       int ret;
-
-       if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_write_room"))
-               return 0;
-       if (!info->online)
-               return info->xmit_size;
-       ret = info->xmit_size - info->xmit_count;
-       return (ret < 0) ? 0 : ret;
-}
-
-static int
-isdn_tty_chars_in_buffer(struct tty_struct *tty)
-{
-       modem_info *info = (modem_info *) tty->driver_data;
-
-       if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_chars_in_buffer"))
-               return 0;
-       if (!info->online)
-               return 0;
-       return (info->xmit_count);
-}
-
-static void
-isdn_tty_flush_buffer(struct tty_struct *tty)
-{
-       modem_info *info;
-
-       if (!tty) {
-               return;
-       }
-       info = (modem_info *) tty->driver_data;
-       if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_flush_buffer")) {
-               return;
-       }
-       isdn_tty_cleanup_xmit(info);
-       info->xmit_count = 0;
-       tty_wakeup(tty);
-}
-
-static void
-isdn_tty_flush_chars(struct tty_struct *tty)
-{
-       modem_info *info = (modem_info *) tty->driver_data;
-
-       if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_flush_chars"))
-               return;
-       if ((info->xmit_count) || !skb_queue_empty(&info->xmit_queue))
-               isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1);
-}
-
-/*
- * ------------------------------------------------------------
- * isdn_tty_throttle()
- *
- * This routine is called by the upper-layer tty layer to signal that
- * incoming characters should be throttled.
- * ------------------------------------------------------------
- */
-static void
-isdn_tty_throttle(struct tty_struct *tty)
-{
-       modem_info *info = (modem_info *) tty->driver_data;
-
-       if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_throttle"))
-               return;
-       if (I_IXOFF(tty))
-               info->x_char = STOP_CHAR(tty);
-       info->mcr &= ~UART_MCR_RTS;
-}
-
-static void
-isdn_tty_unthrottle(struct tty_struct *tty)
-{
-       modem_info *info = (modem_info *) tty->driver_data;
-
-       if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_unthrottle"))
-               return;
-       if (I_IXOFF(tty)) {
-               if (info->x_char)
-                       info->x_char = 0;
-               else
-                       info->x_char = START_CHAR(tty);
-       }
-       info->mcr |= UART_MCR_RTS;
-}
-
-/*
- * ------------------------------------------------------------
- * isdn_tty_ioctl() and friends
- * ------------------------------------------------------------
- */
-
-/*
- * isdn_tty_get_lsr_info - get line status register info
- *
- * Purpose: Let user call ioctl() to get info when the UART physically
- *          is emptied.  On bus types like RS485, the transmitter must
- *          release the bus after transmitting. This must be done when
- *          the transmit shift register is empty, not be done when the
- *          transmit holding register is empty.  This functionality
- *          allows RS485 driver to be written in user space.
- */
-static int
-isdn_tty_get_lsr_info(modem_info *info, uint __user *value)
-{
-       u_char status;
-       uint result;
-
-       status = info->lsr;
-       result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
-       return put_user(result, value);
-}
-
-
-static int
-isdn_tty_tiocmget(struct tty_struct *tty)
-{
-       modem_info *info = (modem_info *) tty->driver_data;
-       u_char control, status;
-
-       if (isdn_tty_paranoia_check(info, tty->name, __func__))
-               return -ENODEV;
-       if (tty_io_error(tty))
-               return -EIO;
-
-       mutex_lock(&modem_info_mutex);
-#ifdef ISDN_DEBUG_MODEM_IOCTL
-       printk(KERN_DEBUG "ttyI%d ioctl TIOCMGET\n", info->line);
-#endif
-
-       control = info->mcr;
-       status = info->msr;
-       mutex_unlock(&modem_info_mutex);
-       return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
-               | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
-               | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0)
-               | ((status & UART_MSR_RI) ? TIOCM_RNG : 0)
-               | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)
-               | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
-}
-
-static int
-isdn_tty_tiocmset(struct tty_struct *tty,
-                 unsigned int set, unsigned int clear)
-{
-       modem_info *info = (modem_info *) tty->driver_data;
-
-       if (isdn_tty_paranoia_check(info, tty->name, __func__))
-               return -ENODEV;
-       if (tty_io_error(tty))
-               return -EIO;
-
-#ifdef ISDN_DEBUG_MODEM_IOCTL
-       printk(KERN_DEBUG "ttyI%d ioctl TIOCMxxx: %x %x\n", info->line, set, clear);
-#endif
-
-       mutex_lock(&modem_info_mutex);
-       if (set & TIOCM_RTS)
-               info->mcr |= UART_MCR_RTS;
-       if (set & TIOCM_DTR) {
-               info->mcr |= UART_MCR_DTR;
-               isdn_tty_modem_ncarrier(info);
-       }
-
-       if (clear & TIOCM_RTS)
-               info->mcr &= ~UART_MCR_RTS;
-       if (clear & TIOCM_DTR) {
-               info->mcr &= ~UART_MCR_DTR;
-               if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {
-                       isdn_tty_modem_reset_regs(info, 0);
-#ifdef ISDN_DEBUG_MODEM_HUP
-                       printk(KERN_DEBUG "Mhup in TIOCMSET\n");
-#endif
-                       if (info->online)
-                               info->ncarrier = 1;
-                       isdn_tty_modem_hup(info, 1);
-               }
-       }
-       mutex_unlock(&modem_info_mutex);
-       return 0;
-}
-
-static int
-isdn_tty_ioctl(struct tty_struct *tty, uint cmd, ulong arg)
-{
-       modem_info *info = (modem_info *) tty->driver_data;
-
-       if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_ioctl"))
-               return -ENODEV;
-       if (tty_io_error(tty))
-               return -EIO;
-       switch (cmd) {
-       case TIOCSERGETLSR:     /* Get line status register */
-#ifdef ISDN_DEBUG_MODEM_IOCTL
-               printk(KERN_DEBUG "ttyI%d ioctl TIOCSERGETLSR\n", info->line);
-#endif
-               return isdn_tty_get_lsr_info(info, (uint __user *) arg);
-       default:
-#ifdef ISDN_DEBUG_MODEM_IOCTL
-               printk(KERN_DEBUG "UNKNOWN ioctl 0x%08x on ttyi%d\n", cmd, info->line);
-#endif
-               return -ENOIOCTLCMD;
-       }
-       return 0;
-}
-
-static void
-isdn_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
-       modem_info *info = (modem_info *) tty->driver_data;
-
-       mutex_lock(&modem_info_mutex);
-       if (!old_termios)
-               isdn_tty_change_speed(info);
-       else {
-               if (tty->termios.c_cflag == old_termios->c_cflag &&
-                   tty->termios.c_ispeed == old_termios->c_ispeed &&
-                   tty->termios.c_ospeed == old_termios->c_ospeed) {
-                       mutex_unlock(&modem_info_mutex);
-                       return;
-               }
-               isdn_tty_change_speed(info);
-       }
-       mutex_unlock(&modem_info_mutex);
-}
-
-/*
- * ------------------------------------------------------------
- * isdn_tty_open() and friends
- * ------------------------------------------------------------
- */
-
-static int isdn_tty_install(struct tty_driver *driver, struct tty_struct *tty)
-{
-       modem_info *info = &dev->mdm.info[tty->index];
-
-       if (isdn_tty_paranoia_check(info, tty->name, __func__))
-               return -ENODEV;
-
-       tty->driver_data = info;
-
-       return tty_port_install(&info->port, driver, tty);
-}
-
-/*
- * This routine is called whenever a serial port is opened.  It
- * enables interrupts for a serial port, linking in its async structure into
- * the IRQ chain.   It also performs the serial-specific
- * initialization for the tty structure.
- */
-static int
-isdn_tty_open(struct tty_struct *tty, struct file *filp)
-{
-       modem_info *info = tty->driver_data;
-       struct tty_port *port = &info->port;
-       int retval;
-
-#ifdef ISDN_DEBUG_MODEM_OPEN
-       printk(KERN_DEBUG "isdn_tty_open %s, count = %d\n", tty->name,
-              port->count);
-#endif
-       port->count++;
-       port->tty = tty;
-       /*
-        * Start up serial port
-        */
-       retval = isdn_tty_startup(info);
-       if (retval) {
-#ifdef ISDN_DEBUG_MODEM_OPEN
-               printk(KERN_DEBUG "isdn_tty_open return after startup\n");
-#endif
-               return retval;
-       }
-       retval = tty_port_block_til_ready(port, tty, filp);
-       if (retval) {
-#ifdef ISDN_DEBUG_MODEM_OPEN
-               printk(KERN_DEBUG "isdn_tty_open return after isdn_tty_block_til_ready \n");
-#endif
-               return retval;
-       }
-#ifdef ISDN_DEBUG_MODEM_OPEN
-       printk(KERN_DEBUG "isdn_tty_open ttyi%d successful...\n", info->line);
-#endif
-       dev->modempoll++;
-#ifdef ISDN_DEBUG_MODEM_OPEN
-       printk(KERN_DEBUG "isdn_tty_open normal exit\n");
-#endif
-       return 0;
-}
-
-static void
-isdn_tty_close(struct tty_struct *tty, struct file *filp)
-{
-       modem_info *info = (modem_info *) tty->driver_data;
-       struct tty_port *port = &info->port;
-       ulong timeout;
-
-       if (!info || isdn_tty_paranoia_check(info, tty->name, "isdn_tty_close"))
-               return;
-       if (tty_hung_up_p(filp)) {
-#ifdef ISDN_DEBUG_MODEM_OPEN
-               printk(KERN_DEBUG "isdn_tty_close return after tty_hung_up_p\n");
-#endif
-               return;
-       }
-       if ((tty->count == 1) && (port->count != 1)) {
-               /*
-                * Uh, oh.  tty->count is 1, which means that the tty
-                * structure will be freed.  Info->count should always
-                * be one in these conditions.  If it's greater than
-                * one, we've got real problems, since it means the
-                * serial port won't be shutdown.
-                */
-               printk(KERN_ERR "isdn_tty_close: bad port count; tty->count is 1, "
-                      "info->count is %d\n", port->count);
-               port->count = 1;
-       }
-       if (--port->count < 0) {
-               printk(KERN_ERR "isdn_tty_close: bad port count for ttyi%d: %d\n",
-                      info->line, port->count);
-               port->count = 0;
-       }
-       if (port->count) {
-#ifdef ISDN_DEBUG_MODEM_OPEN
-               printk(KERN_DEBUG "isdn_tty_close after info->count != 0\n");
-#endif
-               return;
-       }
-       info->closing = 1;
-
-       tty->closing = 1;
-       /*
-        * At this point we stop accepting input.  To do this, we
-        * disable the receive line status interrupts, and tell the
-        * interrupt driver to stop checking the data ready bit in the
-        * line status register.
-        */
-       if (tty_port_initialized(port)) {
-               tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */
-               /*
-                * Before we drop DTR, make sure the UART transmitter
-                * has completely drained; this is especially
-                * important if there is a transmit FIFO!
-                */
-               timeout = jiffies + HZ;
-               while (!(info->lsr & UART_LSR_TEMT)) {
-                       schedule_timeout_interruptible(20);
-                       if (time_after(jiffies, timeout))
-                               break;
-               }
-       }
-       dev->modempoll--;
-       isdn_tty_shutdown(info);
-       isdn_tty_flush_buffer(tty);
-       tty_ldisc_flush(tty);
-       port->tty = NULL;
-       info->ncarrier = 0;
-
-       tty_port_close_end(port, tty);
-       info->closing = 0;
-#ifdef ISDN_DEBUG_MODEM_OPEN
-       printk(KERN_DEBUG "isdn_tty_close normal exit\n");
-#endif
-}
-
-/*
- * isdn_tty_hangup() --- called by tty_hangup() when a hangup is signaled.
- */
-static void
-isdn_tty_hangup(struct tty_struct *tty)
-{
-       modem_info *info = (modem_info *) tty->driver_data;
-       struct tty_port *port = &info->port;
-
-       if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_hangup"))
-               return;
-       isdn_tty_shutdown(info);
-       port->count = 0;
-       tty_port_set_active(port, 0);
-       port->tty = NULL;
-       wake_up_interruptible(&port->open_wait);
-}
-
-/* This routine initializes all emulator-data.
- */
-static void
-isdn_tty_reset_profile(atemu *m)
-{
-       m->profile[0] = 0;
-       m->profile[1] = 0;
-       m->profile[2] = 43;
-       m->profile[3] = 13;
-       m->profile[4] = 10;
-       m->profile[5] = 8;
-       m->profile[6] = 3;
-       m->profile[7] = 60;
-       m->profile[8] = 2;
-       m->profile[9] = 6;
-       m->profile[10] = 7;
-       m->profile[11] = 70;
-       m->profile[12] = 0x45;
-       m->profile[13] = 4;
-       m->profile[14] = ISDN_PROTO_L2_X75I;
-       m->profile[15] = ISDN_PROTO_L3_TRANS;
-       m->profile[16] = ISDN_SERIAL_XMIT_SIZE / 16;
-       m->profile[17] = ISDN_MODEM_WINSIZE;
-       m->profile[18] = 4;
-       m->profile[19] = 0;
-       m->profile[20] = 0;
-       m->profile[23] = 0;
-       m->pmsn[0] = '\0';
-       m->plmsn[0] = '\0';
-}
-
-#ifdef CONFIG_ISDN_AUDIO
-static void
-isdn_tty_modem_reset_vpar(atemu *m)
-{
-       m->vpar[0] = 2;         /* Voice-device            (2 = phone line) */
-       m->vpar[1] = 0;         /* Silence detection level (0 = none      ) */
-       m->vpar[2] = 70;        /* Silence interval        (7 sec.        ) */
-       m->vpar[3] = 2;         /* Compression type        (1 = ADPCM-2   ) */
-       m->vpar[4] = 0;         /* DTMF detection level    (0 = softcode  ) */
-       m->vpar[5] = 8;         /* DTMF interval           (8 * 5 ms.     ) */
-}
-#endif
-
-#ifdef CONFIG_ISDN_TTY_FAX
-static void
-isdn_tty_modem_reset_faxpar(modem_info *info)
-{
-       T30_s *f = info->fax;
-
-       f->code = 0;
-       f->phase = ISDN_FAX_PHASE_IDLE;
-       f->direction = 0;
-       f->resolution = 1;      /* fine */
-       f->rate = 5;            /* 14400 bit/s */
-       f->width = 0;
-       f->length = 0;
-       f->compression = 0;
-       f->ecm = 0;
-       f->binary = 0;
-       f->scantime = 0;
-       memset(&f->id[0], 32, FAXIDLEN - 1);
-       f->id[FAXIDLEN - 1] = 0;
-       f->badlin = 0;
-       f->badmul = 0;
-       f->bor = 0;
-       f->nbc = 0;
-       f->cq = 0;
-       f->cr = 0;
-       f->ctcrty = 0;
-       f->minsp = 0;
-       f->phcto = 30;
-       f->rel = 0;
-       memset(&f->pollid[0], 32, FAXIDLEN - 1);
-       f->pollid[FAXIDLEN - 1] = 0;
-}
-#endif
-
-static void
-isdn_tty_modem_reset_regs(modem_info *info, int force)
-{
-       atemu *m = &info->emu;
-       if ((m->mdmreg[REG_DTRR] & BIT_DTRR) || force) {
-               memcpy(m->mdmreg, m->profile, ISDN_MODEM_NUMREG);
-               memcpy(m->msn, m->pmsn, ISDN_MSNLEN);
-               memcpy(m->lmsn, m->plmsn, ISDN_LMSNLEN);
-               info->xmit_size = m->mdmreg[REG_PSIZE] * 16;
-       }
-#ifdef CONFIG_ISDN_AUDIO
-       isdn_tty_modem_reset_vpar(m);
-#endif
-#ifdef CONFIG_ISDN_TTY_FAX
-       isdn_tty_modem_reset_faxpar(info);
-#endif
-       m->mdmcmdl = 0;
-}
-
-static void
-modem_write_profile(atemu *m)
-{
-       memcpy(m->profile, m->mdmreg, ISDN_MODEM_NUMREG);
-       memcpy(m->pmsn, m->msn, ISDN_MSNLEN);
-       memcpy(m->plmsn, m->lmsn, ISDN_LMSNLEN);
-       if (dev->profd)
-               send_sig(SIGIO, dev->profd, 1);
-}
-
-static const struct tty_operations modem_ops = {
-       .install = isdn_tty_install,
-       .open = isdn_tty_open,
-       .close = isdn_tty_close,
-       .write = isdn_tty_write,
-       .flush_chars = isdn_tty_flush_chars,
-       .write_room = isdn_tty_write_room,
-       .chars_in_buffer = isdn_tty_chars_in_buffer,
-       .flush_buffer = isdn_tty_flush_buffer,
-       .ioctl = isdn_tty_ioctl,
-       .throttle = isdn_tty_throttle,
-       .unthrottle = isdn_tty_unthrottle,
-       .set_termios = isdn_tty_set_termios,
-       .hangup = isdn_tty_hangup,
-       .tiocmget = isdn_tty_tiocmget,
-       .tiocmset = isdn_tty_tiocmset,
-};
-
-static int isdn_tty_carrier_raised(struct tty_port *port)
-{
-       modem_info *info = container_of(port, modem_info, port);
-       return info->msr & UART_MSR_DCD;
-}
-
-static const struct tty_port_operations isdn_tty_port_ops = {
-       .carrier_raised = isdn_tty_carrier_raised,
-};
-
-int
-isdn_tty_modem_init(void)
-{
-       isdn_modem_t    *m;
-       int             i, retval;
-       modem_info      *info;
-
-       m = &dev->mdm;
-       m->tty_modem = alloc_tty_driver(ISDN_MAX_CHANNELS);
-       if (!m->tty_modem)
-               return -ENOMEM;
-       m->tty_modem->name = "ttyI";
-       m->tty_modem->major = ISDN_TTY_MAJOR;
-       m->tty_modem->minor_start = 0;
-       m->tty_modem->type = TTY_DRIVER_TYPE_SERIAL;
-       m->tty_modem->subtype = SERIAL_TYPE_NORMAL;
-       m->tty_modem->init_termios = tty_std_termios;
-       m->tty_modem->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-       m->tty_modem->flags = TTY_DRIVER_REAL_RAW;
-       m->tty_modem->driver_name = "isdn_tty";
-       tty_set_operations(m->tty_modem, &modem_ops);
-       retval = tty_register_driver(m->tty_modem);
-       if (retval) {
-               printk(KERN_WARNING "isdn_tty: Couldn't register modem-device\n");
-               goto err;
-       }
-       for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-               info = &m->info[i];
-#ifdef CONFIG_ISDN_TTY_FAX
-               if (!(info->fax = kmalloc(sizeof(T30_s), GFP_KERNEL))) {
-                       printk(KERN_ERR "Could not allocate fax t30-buffer\n");
-                       retval = -ENOMEM;
-                       goto err_unregister;
-               }
-#endif
-               tty_port_init(&info->port);
-               info->port.ops = &isdn_tty_port_ops;
-               spin_lock_init(&info->readlock);
-               sprintf(info->last_cause, "0000");
-               sprintf(info->last_num, "none");
-               info->last_dir = 0;
-               info->last_lhup = 1;
-               info->last_l2 = -1;
-               info->last_si = 0;
-               isdn_tty_reset_profile(&info->emu);
-               isdn_tty_modem_reset_regs(info, 1);
-               info->magic = ISDN_ASYNC_MAGIC;
-               info->line = i;
-               info->x_char = 0;
-               info->isdn_driver = -1;
-               info->isdn_channel = -1;
-               info->drv_index = -1;
-               info->xmit_size = ISDN_SERIAL_XMIT_SIZE;
-               timer_setup(&info->nc_timer, isdn_tty_modem_do_ncarrier, 0);
-               skb_queue_head_init(&info->xmit_queue);
-#ifdef CONFIG_ISDN_AUDIO
-               skb_queue_head_init(&info->dtmf_queue);
-#endif
-               info->port.xmit_buf = kmalloc(ISDN_SERIAL_XMIT_MAX + 5,
-                               GFP_KERNEL);
-               if (!info->port.xmit_buf) {
-                       printk(KERN_ERR "Could not allocate modem xmit-buffer\n");
-                       retval = -ENOMEM;
-                       goto err_unregister;
-               }
-               /* Make room for T.70 header */
-               info->port.xmit_buf += 4;
-       }
-       return 0;
-err_unregister:
-       for (i--; i >= 0; i--) {
-               info = &m->info[i];
-#ifdef CONFIG_ISDN_TTY_FAX
-               kfree(info->fax);
-#endif
-               kfree(info->port.xmit_buf - 4);
-               info->port.xmit_buf = NULL;
-               tty_port_destroy(&info->port);
-       }
-       tty_unregister_driver(m->tty_modem);
-err:
-       put_tty_driver(m->tty_modem);
-       m->tty_modem = NULL;
-       return retval;
-}
-
-void
-isdn_tty_exit(void)
-{
-       modem_info *info;
-       int i;
-
-       for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-               info = &dev->mdm.info[i];
-               isdn_tty_cleanup_xmit(info);
-#ifdef CONFIG_ISDN_TTY_FAX
-               kfree(info->fax);
-#endif
-               kfree(info->port.xmit_buf - 4);
-               info->port.xmit_buf = NULL;
-               tty_port_destroy(&info->port);
-       }
-       tty_unregister_driver(dev->mdm.tty_modem);
-       put_tty_driver(dev->mdm.tty_modem);
-       dev->mdm.tty_modem = NULL;
-}
-
-
-/*
- * isdn_tty_match_icall(char *MSN, atemu *tty_emulator, int dev_idx)
- *      match the MSN against the MSNs (glob patterns) defined for tty_emulator,
- *      and return 0 for match, 1 for no match, 2 if MSN could match if longer.
- */
-
-static int
-isdn_tty_match_icall(char *cid, atemu *emu, int di)
-{
-#ifdef ISDN_DEBUG_MODEM_ICALL
-       printk(KERN_DEBUG "m_fi: msn=%s lmsn=%s mmsn=%s mreg[SI1]=%d mreg[SI2]=%d\n",
-              emu->msn, emu->lmsn, isdn_map_eaz2msn(emu->msn, di),
-              emu->mdmreg[REG_SI1], emu->mdmreg[REG_SI2]);
-#endif
-       if (strlen(emu->lmsn)) {
-               char *p = emu->lmsn;
-               char *q;
-               int  tmp;
-               int  ret = 0;
-
-               while (1) {
-                       if ((q = strchr(p, ';')))
-                               *q = '\0';
-                       if ((tmp = isdn_msncmp(cid, isdn_map_eaz2msn(p, di))) > ret)
-                               ret = tmp;
-#ifdef ISDN_DEBUG_MODEM_ICALL
-                       printk(KERN_DEBUG "m_fi: lmsnX=%s mmsn=%s -> tmp=%d\n",
-                              p, isdn_map_eaz2msn(emu->msn, di), tmp);
-#endif
-                       if (q) {
-                               *q = ';';
-                               p = q;
-                               p++;
-                       }
-                       if (!tmp)
-                               return 0;
-                       if (!q)
-                               break;
-               }
-               return ret;
-       } else {
-               int tmp;
-               tmp = isdn_msncmp(cid, isdn_map_eaz2msn(emu->msn, di));
-#ifdef ISDN_DEBUG_MODEM_ICALL
-               printk(KERN_DEBUG "m_fi: mmsn=%s -> tmp=%d\n",
-                      isdn_map_eaz2msn(emu->msn, di), tmp);
-#endif
-               return tmp;
-       }
-}
-
-/*
- * An incoming call-request has arrived.
- * Search the tty-devices for an appropriate device and bind
- * it to the ISDN-Channel.
- * Return:
- *
- *  0 = No matching device found.
- *  1 = A matching device found.
- *  3 = No match found, but eventually would match, if
- *      CID is longer.
- */
-int
-isdn_tty_find_icall(int di, int ch, setup_parm *setup)
-{
-       char *eaz;
-       int i;
-       int wret;
-       int idx;
-       int si1;
-       int si2;
-       char *nr;
-       ulong flags;
-
-       if (!setup->phone[0]) {
-               nr = "0";
-               printk(KERN_INFO "isdn_tty: Incoming call without OAD, assuming '0'\n");
-       } else
-               nr = setup->phone;
-       si1 = (int) setup->si1;
-       si2 = (int) setup->si2;
-       if (!setup->eazmsn[0]) {
-               printk(KERN_WARNING "isdn_tty: Incoming call without CPN, assuming '0'\n");
-               eaz = "0";
-       } else
-               eaz = setup->eazmsn;
-#ifdef ISDN_DEBUG_MODEM_ICALL
-       printk(KERN_DEBUG "m_fi: eaz=%s si1=%d si2=%d\n", eaz, si1, si2);
-#endif
-       wret = 0;
-       spin_lock_irqsave(&dev->lock, flags);
-       for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-               modem_info *info = &dev->mdm.info[i];
-
-               if (info->port.count == 0)
-                       continue;
-               if ((info->emu.mdmreg[REG_SI1] & si2bit[si1]) &&  /* SI1 is matching */
-                   (info->emu.mdmreg[REG_SI2] == si2)) {         /* SI2 is matching */
-                       idx = isdn_dc2minor(di, ch);
-#ifdef ISDN_DEBUG_MODEM_ICALL
-                       printk(KERN_DEBUG "m_fi: match1 wret=%d\n", wret);
-                       printk(KERN_DEBUG "m_fi: idx=%d flags=%08lx drv=%d ch=%d usg=%d\n", idx,
-                              info->port.flags, info->isdn_driver,
-                              info->isdn_channel, dev->usage[idx]);
-#endif
-                       if (
-#ifndef FIX_FILE_TRANSFER
-                           tty_port_active(&info->port) &&
-#endif
-                               (info->isdn_driver == -1) &&
-                               (info->isdn_channel == -1) &&
-                               (USG_NONE(dev->usage[idx]))) {
-                               int matchret;
-
-                               if ((matchret = isdn_tty_match_icall(eaz, &info->emu, di)) > wret)
-                                       wret = matchret;
-                               if (!matchret) {                  /* EAZ is matching */
-                                       info->isdn_driver = di;
-                                       info->isdn_channel = ch;
-                                       info->drv_index = idx;
-                                       dev->m_idx[idx] = info->line;
-                                       dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE;
-                                       dev->usage[idx] |= isdn_calc_usage(si1, info->emu.mdmreg[REG_L2PROT]);
-                                       strcpy(dev->num[idx], nr);
-                                       strcpy(info->emu.cpn, eaz);
-                                       info->emu.mdmreg[REG_SI1I] = si2bit[si1];
-                                       info->emu.mdmreg[REG_PLAN] = setup->plan;
-                                       info->emu.mdmreg[REG_SCREEN] = setup->screen;
-                                       isdn_info_update();
-                                       spin_unlock_irqrestore(&dev->lock, flags);
-                                       printk(KERN_INFO "isdn_tty: call from %s, -> RING on ttyI%d\n", nr,
-                                              info->line);
-                                       info->msr |= UART_MSR_RI;
-                                       isdn_tty_modem_result(RESULT_RING, info);
-                                       isdn_timer_ctrl(ISDN_TIMER_MODEMRING, 1);
-                                       return 1;
-                               }
-                       }
-               }
-       }
-       spin_unlock_irqrestore(&dev->lock, flags);
-       printk(KERN_INFO "isdn_tty: call from %s -> %s %s\n", nr, eaz,
-              ((dev->drv[di]->flags & DRV_FLAG_REJBUS) && (wret != 2)) ? "rejected" : "ignored");
-       return (wret == 2) ? 3 : 0;
-}
-
-int
-isdn_tty_stat_callback(int i, isdn_ctrl *c)
-{
-       int mi;
-       modem_info *info;
-       char *e;
-
-       if (i < 0)
-               return 0;
-       if ((mi = dev->m_idx[i]) >= 0) {
-               info = &dev->mdm.info[mi];
-               switch (c->command) {
-               case ISDN_STAT_CINF:
-                       printk(KERN_DEBUG "CHARGEINFO on ttyI%d: %ld %s\n", info->line, c->arg, c->parm.num);
-                       info->emu.charge = (unsigned) simple_strtoul(c->parm.num, &e, 10);
-                       if (e == (char *)c->parm.num)
-                               info->emu.charge = 0;
-
-                       break;
-               case ISDN_STAT_BSENT:
-#ifdef ISDN_TTY_STAT_DEBUG
-                       printk(KERN_DEBUG "tty_STAT_BSENT ttyI%d\n", info->line);
-#endif
-                       if ((info->isdn_driver == c->driver) &&
-                           (info->isdn_channel == c->arg)) {
-                               info->msr |= UART_MSR_CTS;
-                               if (info->send_outstanding)
-                                       if (!(--info->send_outstanding))
-                                               info->lsr |= UART_LSR_TEMT;
-                               isdn_tty_tint(info);
-                               return 1;
-                       }
-                       break;
-               case ISDN_STAT_CAUSE:
-#ifdef ISDN_TTY_STAT_DEBUG
-                       printk(KERN_DEBUG "tty_STAT_CAUSE ttyI%d\n", info->line);
-#endif
-                       /* Signal cause to tty-device */
-                       strncpy(info->last_cause, c->parm.num, 5);
-                       return 1;
-               case ISDN_STAT_DISPLAY:
-#ifdef ISDN_TTY_STAT_DEBUG
-                       printk(KERN_DEBUG "tty_STAT_DISPLAY ttyI%d\n", info->line);
-#endif
-                       /* Signal display to tty-device */
-                       if ((info->emu.mdmreg[REG_DISPLAY] & BIT_DISPLAY) &&
-                           !(info->emu.mdmreg[REG_RESPNUM] & BIT_RESPNUM)) {
-                               isdn_tty_at_cout("\r\n", info);
-                               isdn_tty_at_cout("DISPLAY: ", info);
-                               isdn_tty_at_cout(c->parm.display, info);
-                               isdn_tty_at_cout("\r\n", info);
-                       }
-                       return 1;
-               case ISDN_STAT_DCONN:
-#ifdef ISDN_TTY_STAT_DEBUG
-                       printk(KERN_DEBUG "tty_STAT_DCONN ttyI%d\n", info->line);
-#endif
-                       if (tty_port_active(&info->port)) {
-                               if (info->dialing == 1) {
-                                       info->dialing = 2;
-                                       return 1;
-                               }
-                       }
-                       break;
-               case ISDN_STAT_DHUP:
-#ifdef ISDN_TTY_STAT_DEBUG
-                       printk(KERN_DEBUG "tty_STAT_DHUP ttyI%d\n", info->line);
-#endif
-                       if (tty_port_active(&info->port)) {
-                               if (info->dialing == 1)
-                                       isdn_tty_modem_result(RESULT_BUSY, info);
-                               if (info->dialing > 1)
-                                       isdn_tty_modem_result(RESULT_NO_CARRIER, info);
-                               info->dialing = 0;
-#ifdef ISDN_DEBUG_MODEM_HUP
-                               printk(KERN_DEBUG "Mhup in ISDN_STAT_DHUP\n");
-#endif
-                               isdn_tty_modem_hup(info, 0);
-                               return 1;
-                       }
-                       break;
-               case ISDN_STAT_BCONN:
-#ifdef ISDN_TTY_STAT_DEBUG
-                       printk(KERN_DEBUG "tty_STAT_BCONN ttyI%d\n", info->line);
-#endif
-                       /* Wake up any processes waiting
-                        * for incoming call of this device when
-                        * DCD follow the state of incoming carrier
-                        */
-                       if (info->port.blocked_open &&
-                           (info->emu.mdmreg[REG_DCD] & BIT_DCD)) {
-                               wake_up_interruptible(&info->port.open_wait);
-                       }
-
-                       /* Schedule CONNECT-Message to any tty
-                        * waiting for it and
-                        * set DCD-bit of its modem-status.
-                        */
-                       if (tty_port_active(&info->port) ||
-                           (info->port.blocked_open &&
-                            (info->emu.mdmreg[REG_DCD] & BIT_DCD))) {
-                               info->msr |= UART_MSR_DCD;
-                               info->emu.charge = 0;
-                               if (info->dialing & 0xf)
-                                       info->last_dir = 1;
-                               else
-                                       info->last_dir = 0;
-                               info->dialing = 0;
-                               info->rcvsched = 1;
-                               if (USG_MODEM(dev->usage[i])) {
-                                       if (info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM) {
-                                               strcpy(info->emu.connmsg, c->parm.num);
-                                               isdn_tty_modem_result(RESULT_CONNECT, info);
-                                       } else
-                                               isdn_tty_modem_result(RESULT_CONNECT64000, info);
-                               }
-                               if (USG_VOICE(dev->usage[i]))
-                                       isdn_tty_modem_result(RESULT_VCON, info);
-                               return 1;
-                       }
-                       break;
-               case ISDN_STAT_BHUP:
-#ifdef ISDN_TTY_STAT_DEBUG
-                       printk(KERN_DEBUG "tty_STAT_BHUP ttyI%d\n", info->line);
-#endif
-                       if (tty_port_active(&info->port)) {
-#ifdef ISDN_DEBUG_MODEM_HUP
-                               printk(KERN_DEBUG "Mhup in ISDN_STAT_BHUP\n");
-#endif
-                               isdn_tty_modem_hup(info, 0);
-                               return 1;
-                       }
-                       break;
-               case ISDN_STAT_NODCH:
-#ifdef ISDN_TTY_STAT_DEBUG
-                       printk(KERN_DEBUG "tty_STAT_NODCH ttyI%d\n", info->line);
-#endif
-                       if (tty_port_active(&info->port)) {
-                               if (info->dialing) {
-                                       info->dialing = 0;
-                                       info->last_l2 = -1;
-                                       info->last_si = 0;
-                                       sprintf(info->last_cause, "0000");
-                                       isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
-                               }
-                               isdn_tty_modem_hup(info, 0);
-                               return 1;
-                       }
-                       break;
-               case ISDN_STAT_UNLOAD:
-#ifdef ISDN_TTY_STAT_DEBUG
-                       printk(KERN_DEBUG "tty_STAT_UNLOAD ttyI%d\n", info->line);
-#endif
-                       for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-                               info = &dev->mdm.info[i];
-                               if (info->isdn_driver == c->driver) {
-                                       if (info->online)
-                                               isdn_tty_modem_hup(info, 1);
-                               }
-                       }
-                       return 1;
-#ifdef CONFIG_ISDN_TTY_FAX
-               case ISDN_STAT_FAXIND:
-                       if (tty_port_active(&info->port)) {
-                               isdn_tty_fax_command(info, c);
-                       }
-                       break;
-#endif
-#ifdef CONFIG_ISDN_AUDIO
-               case ISDN_STAT_AUDIO:
-                       if (tty_port_active(&info->port)) {
-                               switch (c->parm.num[0]) {
-                               case ISDN_AUDIO_DTMF:
-                                       if (info->vonline) {
-                                               isdn_audio_put_dle_code(info,
-                                                                       c->parm.num[1]);
-                                       }
-                                       break;
-                               }
-                       }
-                       break;
-#endif
-               }
-       }
-       return 0;
-}
-
-/*********************************************************************
- Modem-Emulator-Routines
-*********************************************************************/
-
-#define cmdchar(c) ((c >= ' ') && (c <= 0x7f))
-
-/*
- * Put a message from the AT-emulator into receive-buffer of tty,
- * convert CR, LF, and BS to values in modem-registers 3, 4 and 5.
- */
-void
-isdn_tty_at_cout(char *msg, modem_info *info)
-{
-       struct tty_port *port = &info->port;
-       atemu *m = &info->emu;
-       char *p;
-       char c;
-       u_long flags;
-       struct sk_buff *skb = NULL;
-       char *sp = NULL;
-       int l;
-
-       if (!msg) {
-               printk(KERN_WARNING "isdn_tty: Null-Message in isdn_tty_at_cout\n");
-               return;
-       }
-
-       l = strlen(msg);
-
-       spin_lock_irqsave(&info->readlock, flags);
-       if (info->closing) {
-               spin_unlock_irqrestore(&info->readlock, flags);
-               return;
-       }
-
-       /* use queue instead of direct, if online and */
-       /* data is in queue or buffer is full */
-       if (info->online && ((tty_buffer_request_room(port, l) < l) ||
-                            !skb_queue_empty(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel]))) {
-               skb = alloc_skb(l, GFP_ATOMIC);
-               if (!skb) {
-                       spin_unlock_irqrestore(&info->readlock, flags);
-                       return;
-               }
-               sp = skb_put(skb, l);
-#ifdef CONFIG_ISDN_AUDIO
-               ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
-               ISDN_AUDIO_SKB_LOCK(skb) = 0;
-#endif
-       }
-
-       for (p = msg; *p; p++) {
-               switch (*p) {
-               case '\r':
-                       c = m->mdmreg[REG_CR];
-                       break;
-               case '\n':
-                       c = m->mdmreg[REG_LF];
-                       break;
-               case '\b':
-                       c = m->mdmreg[REG_BS];
-                       break;
-               default:
-                       c = *p;
-               }
-               if (skb) {
-                       *sp++ = c;
-               } else {
-                       if (tty_insert_flip_char(port, c, TTY_NORMAL) == 0)
-                               break;
-               }
-       }
-       if (skb) {
-               __skb_queue_tail(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel], skb);
-               dev->drv[info->isdn_driver]->rcvcount[info->isdn_channel] += skb->len;
-               spin_unlock_irqrestore(&info->readlock, flags);
-               /* Schedule dequeuing */
-               if (dev->modempoll && info->rcvsched)
-                       isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
-
-       } else {
-               spin_unlock_irqrestore(&info->readlock, flags);
-               tty_flip_buffer_push(port);
-       }
-}
-
-/*
- * Perform ATH Hangup
- */
-static void
-isdn_tty_on_hook(modem_info *info)
-{
-       if (info->isdn_channel >= 0) {
-#ifdef ISDN_DEBUG_MODEM_HUP
-               printk(KERN_DEBUG "Mhup in isdn_tty_on_hook\n");
-#endif
-               isdn_tty_modem_hup(info, 1);
-       }
-}
-
-static void
-isdn_tty_off_hook(void)
-{
-       printk(KERN_DEBUG "isdn_tty_off_hook\n");
-}
-
-#define PLUSWAIT1 (HZ / 2)      /* 0.5 sec. */
-#define PLUSWAIT2 (HZ * 3 / 2)  /* 1.5 sec */
-
-/*
- * Check Buffer for Modem-escape-sequence, activate timer-callback to
- * isdn_tty_modem_escape() if sequence found.
- *
- * Parameters:
- *   p          pointer to databuffer
- *   plus       escape-character
- *   count      length of buffer
- *   pluscount  count of valid escape-characters so far
- *   lastplus   timestamp of last character
- */
-static void
-isdn_tty_check_esc(const u_char *p, u_char plus, int count, int *pluscount,
-                  u_long *lastplus)
-{
-       if (plus > 127)
-               return;
-       if (count > 3) {
-               p += count - 3;
-               count = 3;
-               *pluscount = 0;
-       }
-       while (count > 0) {
-               if (*(p++) == plus) {
-                       if ((*pluscount)++) {
-                               /* Time since last '+' > 0.5 sec. ? */
-                               if (time_after(jiffies, *lastplus + PLUSWAIT1))
-                                       *pluscount = 1;
-                       } else {
-                               /* Time since last non-'+' < 1.5 sec. ? */
-                               if (time_before(jiffies, *lastplus + PLUSWAIT2))
-                                       *pluscount = 0;
-                       }
-                       if ((*pluscount == 3) && (count == 1))
-                               isdn_timer_ctrl(ISDN_TIMER_MODEMPLUS, 1);
-                       if (*pluscount > 3)
-                               *pluscount = 1;
-               } else
-                       *pluscount = 0;
-               *lastplus = jiffies;
-               count--;
-       }
-}
-
-/*
- * Return result of AT-emulator to tty-receive-buffer, depending on
- * modem-register 12, bit 0 and 1.
- * For CONNECT-messages also switch to online-mode.
- * For RING-message handle auto-ATA if register 0 != 0
- */
-
-static void
-isdn_tty_modem_result(int code, modem_info *info)
-{
-       atemu *m = &info->emu;
-       static char *msg[] =
-               {"OK", "CONNECT", "RING", "NO CARRIER", "ERROR",
-                "CONNECT 64000", "NO DIALTONE", "BUSY", "NO ANSWER",
-                "RINGING", "NO MSN/EAZ", "VCON", "RUNG"};
-       char s[ISDN_MSNLEN + 10];
-
-       switch (code) {
-       case RESULT_RING:
-               m->mdmreg[REG_RINGCNT]++;
-               if (m->mdmreg[REG_RINGCNT] == m->mdmreg[REG_RINGATA])
-                       /* Automatically accept incoming call */
-                       isdn_tty_cmd_ATA(info);
-               break;
-       case RESULT_NO_CARRIER:
-#ifdef ISDN_DEBUG_MODEM_HUP
-               printk(KERN_DEBUG "modem_result: NO CARRIER %d %d\n",
-                      info->closing, !info->port.tty);
-#endif
-               m->mdmreg[REG_RINGCNT] = 0;
-               del_timer(&info->nc_timer);
-               info->ncarrier = 0;
-               if (info->closing || !info->port.tty)
-                       return;
-
-#ifdef CONFIG_ISDN_AUDIO
-               if (info->vonline & 1) {
-#ifdef ISDN_DEBUG_MODEM_VOICE
-                       printk(KERN_DEBUG "res3: send DLE-ETX on ttyI%d\n",
-                              info->line);
-#endif
-                       /* voice-recording, add DLE-ETX */
-                       isdn_tty_at_cout("\020\003", info);
-               }
-               if (info->vonline & 2) {
-#ifdef ISDN_DEBUG_MODEM_VOICE
-                       printk(KERN_DEBUG "res3: send DLE-DC4 on ttyI%d\n",
-                              info->line);
-#endif
-                       /* voice-playing, add DLE-DC4 */
-                       isdn_tty_at_cout("\020\024", info);
-               }
-#endif
-               break;
-       case RESULT_CONNECT:
-       case RESULT_CONNECT64000:
-               sprintf(info->last_cause, "0000");
-               if (!info->online)
-                       info->online = 2;
-               break;
-       case RESULT_VCON:
-#ifdef ISDN_DEBUG_MODEM_VOICE
-               printk(KERN_DEBUG "res3: send VCON on ttyI%d\n",
-                      info->line);
-#endif
-               sprintf(info->last_cause, "0000");
-               if (!info->online)
-                       info->online = 1;
-               break;
-       } /* switch (code) */
-
-       if (m->mdmreg[REG_RESP] & BIT_RESP) {
-               /* Show results */
-               if (m->mdmreg[REG_RESPNUM] & BIT_RESPNUM) {
-                       /* Show numeric results only */
-                       sprintf(s, "\r\n%d\r\n", code);
-                       isdn_tty_at_cout(s, info);
-               } else {
-                       if (code == RESULT_RING) {
-                               /* return if "show RUNG" and ringcounter>1 */
-                               if ((m->mdmreg[REG_RUNG] & BIT_RUNG) &&
-                                   (m->mdmreg[REG_RINGCNT] > 1))
-                                       return;
-                               /* print CID, _before_ _every_ ring */
-                               if (!(m->mdmreg[REG_CIDONCE] & BIT_CIDONCE)) {
-                                       isdn_tty_at_cout("\r\nCALLER NUMBER: ", info);
-                                       isdn_tty_at_cout(dev->num[info->drv_index], info);
-                                       if (m->mdmreg[REG_CDN] & BIT_CDN) {
-                                               isdn_tty_at_cout("\r\nCALLED NUMBER: ", info);
-                                               isdn_tty_at_cout(info->emu.cpn, info);
-                                       }
-                               }
-                       }
-                       isdn_tty_at_cout("\r\n", info);
-                       isdn_tty_at_cout(msg[code], info);
-                       switch (code) {
-                       case RESULT_CONNECT:
-                               switch (m->mdmreg[REG_L2PROT]) {
-                               case ISDN_PROTO_L2_MODEM:
-                                       isdn_tty_at_cout(" ", info);
-                                       isdn_tty_at_cout(m->connmsg, info);
-                                       break;
-                               }
-                               break;
-                       case RESULT_RING:
-                               /* Append CPN, if enabled */
-                               if ((m->mdmreg[REG_CPN] & BIT_CPN)) {
-                                       sprintf(s, "/%s", m->cpn);
-                                       isdn_tty_at_cout(s, info);
-                               }
-                               /* Print CID only once, _after_ 1st RING */
-                               if ((m->mdmreg[REG_CIDONCE] & BIT_CIDONCE) &&
-                                   (m->mdmreg[REG_RINGCNT] == 1)) {
-                                       isdn_tty_at_cout("\r\n", info);
-                                       isdn_tty_at_cout("CALLER NUMBER: ", info);
-                                       isdn_tty_at_cout(dev->num[info->drv_index], info);
-                                       if (m->mdmreg[REG_CDN] & BIT_CDN) {
-                                               isdn_tty_at_cout("\r\nCALLED NUMBER: ", info);
-                                               isdn_tty_at_cout(info->emu.cpn, info);
-                                       }
-                               }
-                               break;
-                       case RESULT_NO_CARRIER:
-                       case RESULT_NO_DIALTONE:
-                       case RESULT_BUSY:
-                       case RESULT_NO_ANSWER:
-                               m->mdmreg[REG_RINGCNT] = 0;
-                               /* Append Cause-Message if enabled */
-                               if (m->mdmreg[REG_RESPXT] & BIT_RESPXT) {
-                                       sprintf(s, "/%s", info->last_cause);
-                                       isdn_tty_at_cout(s, info);
-                               }
-                               break;
-                       case RESULT_CONNECT64000:
-                               /* Append Protocol to CONNECT message */
-                               switch (m->mdmreg[REG_L2PROT]) {
-                               case ISDN_PROTO_L2_X75I:
-                               case ISDN_PROTO_L2_X75UI:
-                               case ISDN_PROTO_L2_X75BUI:
-                                       isdn_tty_at_cout("/X.75", info);
-                                       break;
-                               case ISDN_PROTO_L2_HDLC:
-                                       isdn_tty_at_cout("/HDLC", info);
-                                       break;
-                               case ISDN_PROTO_L2_V11096:
-                                       isdn_tty_at_cout("/V110/9600", info);
-                                       break;
-                               case ISDN_PROTO_L2_V11019:
-                                       isdn_tty_at_cout("/V110/19200", info);
-                                       break;
-                               case ISDN_PROTO_L2_V11038:
-                                       isdn_tty_at_cout("/V110/38400", info);
-                                       break;
-                               }
-                               if (m->mdmreg[REG_T70] & BIT_T70) {
-                                       isdn_tty_at_cout("/T.70", info);
-                                       if (m->mdmreg[REG_T70] & BIT_T70_EXT)
-                                               isdn_tty_at_cout("+", info);
-                               }
-                               break;
-                       }
-                       isdn_tty_at_cout("\r\n", info);
-               }
-       }
-       if (code == RESULT_NO_CARRIER) {
-               if (info->closing || (!info->port.tty))
-                       return;
-
-               if (tty_port_check_carrier(&info->port))
-                       tty_hangup(info->port.tty);
-       }
-}
-
-
-/*
- * Display a modem-register-value.
- */
-static void
-isdn_tty_show_profile(int ridx, modem_info *info)
-{
-       char v[6];
-
-       sprintf(v, "\r\n%d", info->emu.mdmreg[ridx]);
-       isdn_tty_at_cout(v, info);
-}
-
-/*
- * Get MSN-string from char-pointer, set pointer to end of number
- */
-static void
-isdn_tty_get_msnstr(char *n, char **p)
-{
-       int limit = ISDN_MSNLEN - 1;
-
-       while (((*p[0] >= '0' && *p[0] <= '9') ||
-               /* Why a comma ??? */
-               (*p[0] == ',') || (*p[0] == ':')) &&
-              (limit--))
-               *n++ = *p[0]++;
-       *n = '\0';
-}
-
-/*
- * Get phone-number from modem-commandbuffer
- */
-static void
-isdn_tty_getdial(char *p, char *q, int cnt)
-{
-       int first = 1;
-       int limit = ISDN_MSNLEN - 1;    /* MUST match the size of interface var to avoid
-                                          buffer overflow */
-
-       while (strchr(" 0123456789,#.*WPTSR-", *p) && *p && --cnt > 0) {
-               if ((*p >= '0' && *p <= '9') || ((*p == 'S') && first) ||
-                   ((*p == 'R') && first) ||
-                   (*p == '*') || (*p == '#')) {
-                       *q++ = *p;
-                       limit--;
-               }
-               if (!limit)
-                       break;
-               p++;
-               first = 0;
-       }
-       *q = 0;
-}
-
-#define PARSE_ERROR { isdn_tty_modem_result(RESULT_ERROR, info); return; }
-#define PARSE_ERROR1 { isdn_tty_modem_result(RESULT_ERROR, info); return 1; }
-
-static void
-isdn_tty_report(modem_info *info)
-{
-       atemu *m = &info->emu;
-       char s[80];
-
-       isdn_tty_at_cout("\r\nStatistics of last connection:\r\n\r\n", info);
-       sprintf(s, "    Remote Number:    %s\r\n", info->last_num);
-       isdn_tty_at_cout(s, info);
-       sprintf(s, "    Direction:        %s\r\n", info->last_dir ? "outgoing" : "incoming");
-       isdn_tty_at_cout(s, info);
-       isdn_tty_at_cout("    Layer-2 Protocol: ", info);
-       switch (info->last_l2) {
-       case ISDN_PROTO_L2_X75I:
-               isdn_tty_at_cout("X.75i", info);
-               break;
-       case ISDN_PROTO_L2_X75UI:
-               isdn_tty_at_cout("X.75ui", info);
-               break;
-       case ISDN_PROTO_L2_X75BUI:
-               isdn_tty_at_cout("X.75bui", info);
-               break;
-       case ISDN_PROTO_L2_HDLC:
-               isdn_tty_at_cout("HDLC", info);
-               break;
-       case ISDN_PROTO_L2_V11096:
-               isdn_tty_at_cout("V.110 9600 Baud", info);
-               break;
-       case ISDN_PROTO_L2_V11019:
-               isdn_tty_at_cout("V.110 19200 Baud", info);
-               break;
-       case ISDN_PROTO_L2_V11038:
-               isdn_tty_at_cout("V.110 38400 Baud", info);
-               break;
-       case ISDN_PROTO_L2_TRANS:
-               isdn_tty_at_cout("transparent", info);
-               break;
-       case ISDN_PROTO_L2_MODEM:
-               isdn_tty_at_cout("modem", info);
-               break;
-       case ISDN_PROTO_L2_FAX:
-               isdn_tty_at_cout("fax", info);
-               break;
-       default:
-               isdn_tty_at_cout("unknown", info);
-               break;
-       }
-       if (m->mdmreg[REG_T70] & BIT_T70) {
-               isdn_tty_at_cout("/T.70", info);
-               if (m->mdmreg[REG_T70] & BIT_T70_EXT)
-                       isdn_tty_at_cout("+", info);
-       }
-       isdn_tty_at_cout("\r\n", info);
-       isdn_tty_at_cout("    Service:          ", info);
-       switch (info->last_si) {
-       case 1:
-               isdn_tty_at_cout("audio\r\n", info);
-               break;
-       case 5:
-               isdn_tty_at_cout("btx\r\n", info);
-               break;
-       case 7:
-               isdn_tty_at_cout("data\r\n", info);
-               break;
-       default:
-               sprintf(s, "%d\r\n", info->last_si);
-               isdn_tty_at_cout(s, info);
-               break;
-       }
-       sprintf(s, "    Hangup location:  %s\r\n", info->last_lhup ? "local" : "remote");
-       isdn_tty_at_cout(s, info);
-       sprintf(s, "    Last cause:       %s\r\n", info->last_cause);
-       isdn_tty_at_cout(s, info);
-}
-
-/*
- * Parse AT&.. commands.
- */
-static int
-isdn_tty_cmd_ATand(char **p, modem_info *info)
-{
-       atemu *m = &info->emu;
-       int i;
-       char rb[100];
-
-#define MAXRB (sizeof(rb) - 1)
-
-       switch (*p[0]) {
-       case 'B':
-               /* &B - Set Buffersize */
-               p[0]++;
-               i = isdn_getnum(p);
-               if ((i < 0) || (i > ISDN_SERIAL_XMIT_MAX))
-                       PARSE_ERROR1;
-#ifdef CONFIG_ISDN_AUDIO
-               if ((m->mdmreg[REG_SI1] & 1) && (i > VBUF))
-                       PARSE_ERROR1;
-#endif
-               m->mdmreg[REG_PSIZE] = i / 16;
-               info->xmit_size = m->mdmreg[REG_PSIZE] * 16;
-               switch (m->mdmreg[REG_L2PROT]) {
-               case ISDN_PROTO_L2_V11096:
-               case ISDN_PROTO_L2_V11019:
-               case ISDN_PROTO_L2_V11038:
-                       info->xmit_size /= 10;
-               }
-               break;
-       case 'C':
-               /* &C - DCD Status */
-               p[0]++;
-               switch (isdn_getnum(p)) {
-               case 0:
-                       m->mdmreg[REG_DCD] &= ~BIT_DCD;
-                       break;
-               case 1:
-                       m->mdmreg[REG_DCD] |= BIT_DCD;
-                       break;
-               default:
-                       PARSE_ERROR1
-                               }
-               break;
-       case 'D':
-               /* &D - Set DTR-Low-behavior */
-               p[0]++;
-               switch (isdn_getnum(p)) {
-               case 0:
-                       m->mdmreg[REG_DTRHUP] &= ~BIT_DTRHUP;
-                       m->mdmreg[REG_DTRR] &= ~BIT_DTRR;
-                       break;
-               case 2:
-                       m->mdmreg[REG_DTRHUP] |= BIT_DTRHUP;
-                       m->mdmreg[REG_DTRR] &= ~BIT_DTRR;
-                       break;
-               case 3:
-                       m->mdmreg[REG_DTRHUP] |= BIT_DTRHUP;
-                       m->mdmreg[REG_DTRR] |= BIT_DTRR;
-                       break;
-               default:
-                       PARSE_ERROR1
-                               }
-               break;
-       case 'E':
-               /* &E -Set EAZ/MSN */
-               p[0]++;
-               isdn_tty_get_msnstr(m->msn, p);
-               break;
-       case 'F':
-               /* &F -Set Factory-Defaults */
-               p[0]++;
-               if (info->msr & UART_MSR_DCD)
-                       PARSE_ERROR1;
-               isdn_tty_reset_profile(m);
-               isdn_tty_modem_reset_regs(info, 1);
-               break;
-#ifdef DUMMY_HAYES_AT
-       case 'K':
-               /* only for be compilant with common scripts */
-               /* &K Flowcontrol - no function */
-               p[0]++;
-               isdn_getnum(p);
-               break;
-#endif
-       case 'L':
-               /* &L -Set Numbers to listen on */
-               p[0]++;
-               i = 0;
-               while (*p[0] && (strchr("0123456789,-*[]?;", *p[0])) &&
-                      (i < ISDN_LMSNLEN - 1))
-                       m->lmsn[i++] = *p[0]++;
-               m->lmsn[i] = '\0';
-               break;
-       case 'R':
-               /* &R - Set V.110 bitrate adaption */
-               p[0]++;
-               i = isdn_getnum(p);
-               switch (i) {
-               case 0:
-                       /* Switch off V.110, back to X.75 */
-                       m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I;
-                       m->mdmreg[REG_SI2] = 0;
-                       info->xmit_size = m->mdmreg[REG_PSIZE] * 16;
-                       break;
-               case 9600:
-                       m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_V11096;
-                       m->mdmreg[REG_SI2] = 197;
-                       info->xmit_size = m->mdmreg[REG_PSIZE] * 16 / 10;
-                       break;
-               case 19200:
-                       m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_V11019;
-                       m->mdmreg[REG_SI2] = 199;
-                       info->xmit_size = m->mdmreg[REG_PSIZE] * 16 / 10;
-                       break;
-               case 38400:
-                       m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_V11038;
-                       m->mdmreg[REG_SI2] = 198; /* no existing standard for this */
-                       info->xmit_size = m->mdmreg[REG_PSIZE] * 16 / 10;
-                       break;
-               default:
-                       PARSE_ERROR1;
-               }
-               /* Switch off T.70 */
-               m->mdmreg[REG_T70] &= ~(BIT_T70 | BIT_T70_EXT);
-               /* Set Service 7 */
-               m->mdmreg[REG_SI1] |= 4;
-               break;
-       case 'S':
-               /* &S - Set Windowsize */
-               p[0]++;
-               i = isdn_getnum(p);
-               if ((i > 0) && (i < 9))
-                       m->mdmreg[REG_WSIZE] = i;
-               else
-                       PARSE_ERROR1;
-               break;
-       case 'V':
-               /* &V - Show registers */
-               p[0]++;
-               isdn_tty_at_cout("\r\n", info);
-               for (i = 0; i < ISDN_MODEM_NUMREG; i++) {
-                       sprintf(rb, "S%02d=%03d%s", i,
-                               m->mdmreg[i], ((i + 1) % 10) ? " " : "\r\n");
-                       isdn_tty_at_cout(rb, info);
-               }
-               sprintf(rb, "\r\nEAZ/MSN: %.50s\r\n",
-                       strlen(m->msn) ? m->msn : "None");
-               isdn_tty_at_cout(rb, info);
-               if (strlen(m->lmsn)) {
-                       isdn_tty_at_cout("\r\nListen: ", info);
-                       isdn_tty_at_cout(m->lmsn, info);
-                       isdn_tty_at_cout("\r\n", info);
-               }
-               break;
-       case 'W':
-               /* &W - Write Profile */
-               p[0]++;
-               switch (*p[0]) {
-               case '0':
-                       p[0]++;
-                       modem_write_profile(m);
-                       break;
-               default:
-                       PARSE_ERROR1;
-               }
-               break;
-       case 'X':
-               /* &X - Switch to BTX-Mode and T.70 */
-               p[0]++;
-               switch (isdn_getnum(p)) {
-               case 0:
-                       m->mdmreg[REG_T70] &= ~(BIT_T70 | BIT_T70_EXT);
-                       info->xmit_size = m->mdmreg[REG_PSIZE] * 16;
-                       break;
-               case 1:
-                       m->mdmreg[REG_T70] |= BIT_T70;
-                       m->mdmreg[REG_T70] &= ~BIT_T70_EXT;
-                       m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I;
-                       info->xmit_size = 112;
-                       m->mdmreg[REG_SI1] = 4;
-                       m->mdmreg[REG_SI2] = 0;
-                       break;
-               case 2:
-                       m->mdmreg[REG_T70] |= (BIT_T70 | BIT_T70_EXT);
-                       m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I;
-                       info->xmit_size = 112;
-                       m->mdmreg[REG_SI1] = 4;
-                       m->mdmreg[REG_SI2] = 0;
-                       break;
-               default:
-                       PARSE_ERROR1;
-               }
-               break;
-       default:
-               PARSE_ERROR1;
-       }
-       return 0;
-}
-
-static int
-isdn_tty_check_ats(int mreg, int mval, modem_info *info, atemu *m)
-{
-       /* Some plausibility checks */
-       switch (mreg) {
-       case REG_L2PROT:
-               if (mval > ISDN_PROTO_L2_MAX)
-                       return 1;
-               break;
-       case REG_PSIZE:
-               if ((mval * 16) > ISDN_SERIAL_XMIT_MAX)
-                       return 1;
-#ifdef CONFIG_ISDN_AUDIO
-               if ((m->mdmreg[REG_SI1] & 1) && (mval > VBUFX))
-                       return 1;
-#endif
-               info->xmit_size = mval * 16;
-               switch (m->mdmreg[REG_L2PROT]) {
-               case ISDN_PROTO_L2_V11096:
-               case ISDN_PROTO_L2_V11019:
-               case ISDN_PROTO_L2_V11038:
-                       info->xmit_size /= 10;
-               }
-               break;
-       case REG_SI1I:
-       case REG_PLAN:
-       case REG_SCREEN:
-               /* readonly registers */
-               return 1;
-       }
-       return 0;
-}
-
-/*
- * Perform ATS command
- */
-static int
-isdn_tty_cmd_ATS(char **p, modem_info *info)
-{
-       atemu *m = &info->emu;
-       int bitpos;
-       int mreg;
-       int mval;
-       int bval;
-
-       mreg = isdn_getnum(p);
-       if (mreg < 0 || mreg >= ISDN_MODEM_NUMREG)
-               PARSE_ERROR1;
-       switch (*p[0]) {
-       case '=':
-               p[0]++;
-               mval = isdn_getnum(p);
-               if (mval < 0 || mval > 255)
-                       PARSE_ERROR1;
-               if (isdn_tty_check_ats(mreg, mval, info, m))
-                       PARSE_ERROR1;
-               m->mdmreg[mreg] = mval;
-               break;
-       case '.':
-               /* Set/Clear a single bit */
-               p[0]++;
-               bitpos = isdn_getnum(p);
-               if ((bitpos < 0) || (bitpos > 7))
-                       PARSE_ERROR1;
-               switch (*p[0]) {
-               case '=':
-                       p[0]++;
-                       bval = isdn_getnum(p);
-                       if (bval < 0 || bval > 1)
-                               PARSE_ERROR1;
-                       if (bval)
-                               mval = m->mdmreg[mreg] | (1 << bitpos);
-                       else
-                               mval = m->mdmreg[mreg] & ~(1 << bitpos);
-                       if (isdn_tty_check_ats(mreg, mval, info, m))
-                               PARSE_ERROR1;
-                       m->mdmreg[mreg] = mval;
-                       break;
-               case '?':
-                       p[0]++;
-                       isdn_tty_at_cout("\r\n", info);
-                       isdn_tty_at_cout((m->mdmreg[mreg] & (1 << bitpos)) ? "1" : "0",
-                                        info);
-                       break;
-               default:
-                       PARSE_ERROR1;
-               }
-               break;
-       case '?':
-               p[0]++;
-               isdn_tty_show_profile(mreg, info);
-               break;
-       default:
-               PARSE_ERROR1;
-               break;
-       }
-       return 0;
-}
-
-/*
- * Perform ATA command
- */
-static void
-isdn_tty_cmd_ATA(modem_info *info)
-{
-       atemu *m = &info->emu;
-       isdn_ctrl cmd;
-       int l2;
-
-       if (info->msr & UART_MSR_RI) {
-               /* Accept incoming call */
-               info->last_dir = 0;
-               strcpy(info->last_num, dev->num[info->drv_index]);
-               m->mdmreg[REG_RINGCNT] = 0;
-               info->msr &= ~UART_MSR_RI;
-               l2 = m->mdmreg[REG_L2PROT];
-#ifdef CONFIG_ISDN_AUDIO
-               /* If more than one bit set in reg18, autoselect Layer2 */
-               if ((m->mdmreg[REG_SI1] & m->mdmreg[REG_SI1I]) != m->mdmreg[REG_SI1]) {
-                       if (m->mdmreg[REG_SI1I] == 1) {
-                               if ((l2 != ISDN_PROTO_L2_MODEM) && (l2 != ISDN_PROTO_L2_FAX))
-                                       l2 = ISDN_PROTO_L2_TRANS;
-                       } else
-                               l2 = ISDN_PROTO_L2_X75I;
-               }
-#endif
-               cmd.driver = info->isdn_driver;
-               cmd.command = ISDN_CMD_SETL2;
-               cmd.arg = info->isdn_channel + (l2 << 8);
-               info->last_l2 = l2;
-               isdn_command(&cmd);
-               cmd.driver = info->isdn_driver;
-               cmd.command = ISDN_CMD_SETL3;
-               cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
-#ifdef CONFIG_ISDN_TTY_FAX
-               if (l2 == ISDN_PROTO_L2_FAX) {
-                       cmd.parm.fax = info->fax;
-                       info->fax->direction = ISDN_TTY_FAX_CONN_IN;
-               }
-#endif
-               isdn_command(&cmd);
-               cmd.driver = info->isdn_driver;
-               cmd.arg = info->isdn_channel;
-               cmd.command = ISDN_CMD_ACCEPTD;
-               info->dialing = 16;
-               info->emu.carrierwait = 0;
-               isdn_command(&cmd);
-               isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1);
-       } else
-               isdn_tty_modem_result(RESULT_NO_ANSWER, info);
-}
-
-#ifdef CONFIG_ISDN_AUDIO
-/*
- * Parse AT+F.. commands
- */
-static int
-isdn_tty_cmd_PLUSF(char **p, modem_info *info)
-{
-       atemu *m = &info->emu;
-       char rs[20];
-
-       if (!strncmp(p[0], "CLASS", 5)) {
-               p[0] += 5;
-               switch (*p[0]) {
-               case '?':
-                       p[0]++;
-                       sprintf(rs, "\r\n%d",
-                               (m->mdmreg[REG_SI1] & 1) ? 8 : 0);
-#ifdef CONFIG_ISDN_TTY_FAX
-                       if (TTY_IS_FCLASS2(info))
-                               sprintf(rs, "\r\n2");
-                       else if (TTY_IS_FCLASS1(info))
-                               sprintf(rs, "\r\n1");
-#endif
-                       isdn_tty_at_cout(rs, info);
-                       break;
-               case '=':
-                       p[0]++;
-                       switch (*p[0]) {
-                       case '0':
-                               p[0]++;
-                               m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I;
-                               m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_TRANS;
-                               m->mdmreg[REG_SI1] = 4;
-                               info->xmit_size =
-                                       m->mdmreg[REG_PSIZE] * 16;
-                               break;
-#ifdef CONFIG_ISDN_TTY_FAX
-                       case '1':
-                               p[0]++;
-                               if (!(dev->global_features &
-                                     ISDN_FEATURE_L3_FCLASS1))
-                                       PARSE_ERROR1;
-                               m->mdmreg[REG_SI1] = 1;
-                               m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_FAX;
-                               m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_FCLASS1;
-                               info->xmit_size =
-                                       m->mdmreg[REG_PSIZE] * 16;
-                               break;
-                       case '2':
-                               p[0]++;
-                               if (!(dev->global_features &
-                                     ISDN_FEATURE_L3_FCLASS2))
-                                       PARSE_ERROR1;
-                               m->mdmreg[REG_SI1] = 1;
-                               m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_FAX;
-                               m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_FCLASS2;
-                               info->xmit_size =
-                                       m->mdmreg[REG_PSIZE] * 16;
-                               break;
-#endif
-                       case '8':
-                               p[0]++;
-                               /* L2 will change on dialout with si=1 */
-                               m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I;
-                               m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_TRANS;
-                               m->mdmreg[REG_SI1] = 5;
-                               info->xmit_size = VBUF;
-                               break;
-                       case '?':
-                               p[0]++;
-                               strcpy(rs, "\r\n0,");
-#ifdef CONFIG_ISDN_TTY_FAX
-                               if (dev->global_features &
-                                   ISDN_FEATURE_L3_FCLASS1)
-                                       strcat(rs, "1,");
-                               if (dev->global_features &
-                                   ISDN_FEATURE_L3_FCLASS2)
-                                       strcat(rs, "2,");
-#endif
-                               strcat(rs, "8");
-                               isdn_tty_at_cout(rs, info);
-                               break;
-                       default:
-                               PARSE_ERROR1;
-                       }
-                       break;
-               default:
-                       PARSE_ERROR1;
-               }
-               return 0;
-       }
-#ifdef CONFIG_ISDN_TTY_FAX
-       return (isdn_tty_cmd_PLUSF_FAX(p, info));
-#else
-       PARSE_ERROR1;
-#endif
-}
-
-/*
- * Parse AT+V.. commands
- */
-static int
-isdn_tty_cmd_PLUSV(char **p, modem_info *info)
-{
-       atemu *m = &info->emu;
-       isdn_ctrl cmd;
-       static char *vcmd[] =
-               {"NH", "IP", "LS", "RX", "SD", "SM", "TX", "DD", NULL};
-       int i;
-       int par1;
-       int par2;
-       char rs[20];
-
-       i = 0;
-       while (vcmd[i]) {
-               if (!strncmp(vcmd[i], p[0], 2)) {
-                       p[0] += 2;
-                       break;
-               }
-               i++;
-       }
-       switch (i) {
-       case 0:
-               /* AT+VNH - Auto hangup feature */
-               switch (*p[0]) {
-               case '?':
-                       p[0]++;
-                       isdn_tty_at_cout("\r\n1", info);
-                       break;
-               case '=':
-                       p[0]++;
-                       switch (*p[0]) {
-                       case '1':
-                               p[0]++;
-                               break;
-                       case '?':
-                               p[0]++;
-                               isdn_tty_at_cout("\r\n1", info);
-                               break;
-                       default:
-                               PARSE_ERROR1;
-                       }
-                       break;
-               default:
-                       PARSE_ERROR1;
-               }
-               break;
-       case 1:
-               /* AT+VIP - Reset all voice parameters */
-               isdn_tty_modem_reset_vpar(m);
-               break;
-       case 2:
-               /* AT+VLS - Select device, accept incoming call */
-               switch (*p[0]) {
-               case '?':
-                       p[0]++;
-                       sprintf(rs, "\r\n%d", m->vpar[0]);
-                       isdn_tty_at_cout(rs, info);
-                       break;
-               case '=':
-                       p[0]++;
-                       switch (*p[0]) {
-                       case '0':
-                               p[0]++;
-                               m->vpar[0] = 0;
-                               break;
-                       case '2':
-                               p[0]++;
-                               m->vpar[0] = 2;
-                               break;
-                       case '?':
-                               p[0]++;
-                               isdn_tty_at_cout("\r\n0,2", info);
-                               break;
-                       default:
-                               PARSE_ERROR1;
-                       }
-                       break;
-               default:
-                       PARSE_ERROR1;
-               }
-               break;
-       case 3:
-               /* AT+VRX - Start recording */
-               if (!m->vpar[0])
-                       PARSE_ERROR1;
-               if (info->online != 1) {
-                       isdn_tty_modem_result(RESULT_NO_ANSWER, info);
-                       return 1;
-               }
-               info->dtmf_state = isdn_audio_dtmf_init(info->dtmf_state);
-               if (!info->dtmf_state) {
-                       printk(KERN_WARNING "isdn_tty: Couldn't malloc dtmf state\n");
-                       PARSE_ERROR1;
-               }
-               info->silence_state = isdn_audio_silence_init(info->silence_state);
-               if (!info->silence_state) {
-                       printk(KERN_WARNING "isdn_tty: Couldn't malloc silence state\n");
-                       PARSE_ERROR1;
-               }
-               if (m->vpar[3] < 5) {
-                       info->adpcmr = isdn_audio_adpcm_init(info->adpcmr, m->vpar[3]);
-                       if (!info->adpcmr) {
-                               printk(KERN_WARNING "isdn_tty: Couldn't malloc adpcm state\n");
-                               PARSE_ERROR1;
-                       }
-               }
-#ifdef ISDN_DEBUG_AT
-               printk(KERN_DEBUG "AT: +VRX\n");
-#endif
-               info->vonline |= 1;
-               isdn_tty_modem_result(RESULT_CONNECT, info);
-               return 0;
-               break;
-       case 4:
-               /* AT+VSD - Silence detection */
-               switch (*p[0]) {
-               case '?':
-                       p[0]++;
-                       sprintf(rs, "\r\n<%d>,<%d>",
-                               m->vpar[1],
-                               m->vpar[2]);
-                       isdn_tty_at_cout(rs, info);
-                       break;
-               case '=':
-                       p[0]++;
-                       if ((*p[0] >= '0') && (*p[0] <= '9')) {
-                               par1 = isdn_getnum(p);
-                               if ((par1 < 0) || (par1 > 31))
-                                       PARSE_ERROR1;
-                               if (*p[0] != ',')
-                                       PARSE_ERROR1;
-                               p[0]++;
-                               par2 = isdn_getnum(p);
-                               if ((par2 < 0) || (par2 > 255))
-                                       PARSE_ERROR1;
-                               m->vpar[1] = par1;
-                               m->vpar[2] = par2;
-                               break;
-                       } else
-                               if (*p[0] == '?') {
-                                       p[0]++;
-                                       isdn_tty_at_cout("\r\n<0-31>,<0-255>",
-                                                        info);
-                                       break;
-                               } else
-                                       PARSE_ERROR1;
-                       break;
-               default:
-                       PARSE_ERROR1;
-               }
-               break;
-       case 5:
-               /* AT+VSM - Select compression */
-               switch (*p[0]) {
-               case '?':
-                       p[0]++;
-                       sprintf(rs, "\r\n<%d>,<%d><8000>",
-                               m->vpar[3],
-                               m->vpar[1]);
-                       isdn_tty_at_cout(rs, info);
-                       break;
-               case '=':
-                       p[0]++;
-                       switch (*p[0]) {
-                       case '2':
-                       case '3':
-                       case '4':
-                       case '5':
-                       case '6':
-                               par1 = isdn_getnum(p);
-                               if ((par1 < 2) || (par1 > 6))
-                                       PARSE_ERROR1;
-                               m->vpar[3] = par1;
-                               break;
-                       case '?':
-                               p[0]++;
-                               isdn_tty_at_cout("\r\n2;ADPCM;2;0;(8000)\r\n",
-                                                info);
-                               isdn_tty_at_cout("3;ADPCM;3;0;(8000)\r\n",
-                                                info);
-                               isdn_tty_at_cout("4;ADPCM;4;0;(8000)\r\n",
-                                                info);
-                               isdn_tty_at_cout("5;ALAW;8;0;(8000)\r\n",
-                                                info);
-                               isdn_tty_at_cout("6;ULAW;8;0;(8000)\r\n",
-                                                info);
-                               break;
-                       default:
-                               PARSE_ERROR1;
-                       }
-                       break;
-               default:
-                       PARSE_ERROR1;
-               }
-               break;
-       case 6:
-               /* AT+VTX - Start sending */
-               if (!m->vpar[0])
-                       PARSE_ERROR1;
-               if (info->online != 1) {
-                       isdn_tty_modem_result(RESULT_NO_ANSWER, info);
-                       return 1;
-               }
-               info->dtmf_state = isdn_audio_dtmf_init(info->dtmf_state);
-               if (!info->dtmf_state) {
-                       printk(KERN_WARNING "isdn_tty: Couldn't malloc dtmf state\n");
-                       PARSE_ERROR1;
-               }
-               if (m->vpar[3] < 5) {
-                       info->adpcms = isdn_audio_adpcm_init(info->adpcms, m->vpar[3]);
-                       if (!info->adpcms) {
-                               printk(KERN_WARNING "isdn_tty: Couldn't malloc adpcm state\n");
-                               PARSE_ERROR1;
-                       }
-               }
-#ifdef ISDN_DEBUG_AT
-               printk(KERN_DEBUG "AT: +VTX\n");
-#endif
-               m->lastDLE = 0;
-               info->vonline |= 2;
-               isdn_tty_modem_result(RESULT_CONNECT, info);
-               return 0;
-               break;
-       case 7:
-               /* AT+VDD - DTMF detection */
-               switch (*p[0]) {
-               case '?':
-                       p[0]++;
-                       sprintf(rs, "\r\n<%d>,<%d>",
-                               m->vpar[4],
-                               m->vpar[5]);
-                       isdn_tty_at_cout(rs, info);
-                       break;
-               case '=':
-                       p[0]++;
-                       if ((*p[0] >= '0') && (*p[0] <= '9')) {
-                               if (info->online != 1)
-                                       PARSE_ERROR1;
-                               par1 = isdn_getnum(p);
-                               if ((par1 < 0) || (par1 > 15))
-                                       PARSE_ERROR1;
-                               if (*p[0] != ',')
-                                       PARSE_ERROR1;
-                               p[0]++;
-                               par2 = isdn_getnum(p);
-                               if ((par2 < 0) || (par2 > 255))
-                                       PARSE_ERROR1;
-                               m->vpar[4] = par1;
-                               m->vpar[5] = par2;
-                               cmd.driver = info->isdn_driver;
-                               cmd.command = ISDN_CMD_AUDIO;
-                               cmd.arg = info->isdn_channel + (ISDN_AUDIO_SETDD << 8);
-                               cmd.parm.num[0] = par1;
-                               cmd.parm.num[1] = par2;
-                               isdn_command(&cmd);
-                               break;
-                       } else
-                               if (*p[0] == '?') {
-                                       p[0]++;
-                                       isdn_tty_at_cout("\r\n<0-15>,<0-255>",
-                                                        info);
-                                       break;
-                               } else
-                                       PARSE_ERROR1;
-                       break;
-               default:
-                       PARSE_ERROR1;
-               }
-               break;
-       default:
-               PARSE_ERROR1;
-       }
-       return 0;
-}
-#endif                          /* CONFIG_ISDN_AUDIO */
-
-/*
- * Parse and perform an AT-command-line.
- */
-static void
-isdn_tty_parse_at(modem_info *info)
-{
-       atemu *m = &info->emu;
-       char *p;
-       char ds[ISDN_MSNLEN];
-
-#ifdef ISDN_DEBUG_AT
-       printk(KERN_DEBUG "AT: '%s'\n", m->mdmcmd);
-#endif
-       for (p = &m->mdmcmd[2]; *p;) {
-               switch (*p) {
-               case ' ':
-                       p++;
-                       break;
-               case 'A':
-                       /* A - Accept incoming call */
-                       p++;
-                       isdn_tty_cmd_ATA(info);
-                       return;
-               case 'D':
-                       /* D - Dial */
-                       if (info->msr & UART_MSR_DCD)
-                               PARSE_ERROR;
-                       if (info->msr & UART_MSR_RI) {
-                               isdn_tty_modem_result(RESULT_NO_CARRIER, info);
-                               return;
-                       }
-                       isdn_tty_getdial(++p, ds, sizeof ds);
-                       p += strlen(p);
-                       if (!strlen(m->msn))
-                               isdn_tty_modem_result(RESULT_NO_MSN_EAZ, info);
-                       else if (strlen(ds))
-                               isdn_tty_dial(ds, info, m);
-                       else
-                               PARSE_ERROR;
-                       return;
-               case 'E':
-                       /* E - Turn Echo on/off */
-                       p++;
-                       switch (isdn_getnum(&p)) {
-                       case 0:
-                               m->mdmreg[REG_ECHO] &= ~BIT_ECHO;
-                               break;
-                       case 1:
-                               m->mdmreg[REG_ECHO] |= BIT_ECHO;
-                               break;
-                       default:
-                               PARSE_ERROR;
-                       }
-                       break;
-               case 'H':
-                       /* H - On/Off-hook */
-                       p++;
-                       switch (*p) {
-                       case '0':
-                               p++;
-                               isdn_tty_on_hook(info);
-                               break;
-                       case '1':
-                               p++;
-                               isdn_tty_off_hook();
-                               break;
-                       default:
-                               isdn_tty_on_hook(info);
-                               break;
-                       }
-                       break;
-               case 'I':
-                       /* I - Information */
-                       p++;
-                       isdn_tty_at_cout("\r\nLinux ISDN", info);
-                       switch (*p) {
-                       case '0':
-                       case '1':
-                               p++;
-                               break;
-                       case '2':
-                               p++;
-                               isdn_tty_report(info);
-                               break;
-                       case '3':
-                               p++;
-                               snprintf(ds, sizeof(ds), "\r\n%d", info->emu.charge);
-                               isdn_tty_at_cout(ds, info);
-                               break;
-                       default:;
-                       }
-                       break;
-#ifdef DUMMY_HAYES_AT
-               case 'L':
-               case 'M':
-                       /* only for be compilant with common scripts */
-                       /* no function */
-                       p++;
-                       isdn_getnum(&p);
-                       break;
-#endif
-               case 'O':
-                       /* O - Go online */
-                       p++;
-                       if (info->msr & UART_MSR_DCD)
-                               /* if B-Channel is up */
-                               isdn_tty_modem_result((m->mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM) ? RESULT_CONNECT : RESULT_CONNECT64000, info);
-                       else
-                               isdn_tty_modem_result(RESULT_NO_CARRIER, info);
-                       return;
-               case 'Q':
-                       /* Q - Turn Emulator messages on/off */
-                       p++;
-                       switch (isdn_getnum(&p)) {
-                       case 0:
-                               m->mdmreg[REG_RESP] |= BIT_RESP;
-                               break;
-                       case 1:
-                               m->mdmreg[REG_RESP] &= ~BIT_RESP;
-                               break;
-                       default:
-                               PARSE_ERROR;
-                       }
-                       break;
-               case 'S':
-                       /* S - Set/Get Register */
-                       p++;
-                       if (isdn_tty_cmd_ATS(&p, info))
-                               return;
-                       break;
-               case 'V':
-                       /* V - Numeric or ASCII Emulator-messages */
-                       p++;
-                       switch (isdn_getnum(&p)) {
-                       case 0:
-                               m->mdmreg[REG_RESP] |= BIT_RESPNUM;
-                               break;
-                       case 1:
-                               m->mdmreg[REG_RESP] &= ~BIT_RESPNUM;
-                               break;
-                       default:
-                               PARSE_ERROR;
-                       }
-                       break;
-               case 'Z':
-                       /* Z - Load Registers from Profile */
-                       p++;
-                       if (info->msr & UART_MSR_DCD) {
-                               info->online = 0;
-                               isdn_tty_on_hook(info);
-                       }
-                       isdn_tty_modem_reset_regs(info, 1);
-                       break;
-               case '+':
-                       p++;
-                       switch (*p) {
-#ifdef CONFIG_ISDN_AUDIO
-                       case 'F':
-                               p++;
-                               if (isdn_tty_cmd_PLUSF(&p, info))
-                                       return;
-                               break;
-                       case 'V':
-                               if ((!(m->mdmreg[REG_SI1] & 1)) ||
-                                   (m->mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM))
-                                       PARSE_ERROR;
-                               p++;
-                               if (isdn_tty_cmd_PLUSV(&p, info))
-                                       return;
-                               break;
-#endif                          /* CONFIG_ISDN_AUDIO */
-                       case 'S':       /* SUSPEND */
-                               p++;
-                               isdn_tty_get_msnstr(ds, &p);
-                               isdn_tty_suspend(ds, info, m);
-                               break;
-                       case 'R':       /* RESUME */
-                               p++;
-                               isdn_tty_get_msnstr(ds, &p);
-                               isdn_tty_resume(ds, info, m);
-                               break;
-                       case 'M':       /* MESSAGE */
-                               p++;
-                               isdn_tty_send_msg(info, m, p);
-                               break;
-                       default:
-                               PARSE_ERROR;
-                       }
-                       break;
-               case '&':
-                       p++;
-                       if (isdn_tty_cmd_ATand(&p, info))
-                               return;
-                       break;
-               default:
-                       PARSE_ERROR;
-               }
-       }
-#ifdef CONFIG_ISDN_AUDIO
-       if (!info->vonline)
-#endif
-               isdn_tty_modem_result(RESULT_OK, info);
-}
-
-/* Need own toupper() because standard-toupper is not available
- * within modules.
- */
-#define my_toupper(c) (((c >= 'a') && (c <= 'z')) ? (c & 0xdf) : c)
-
-/*
- * Perform line-editing of AT-commands
- *
- * Parameters:
- *   p        inputbuffer
- *   count    length of buffer
- *   channel  index to line (minor-device)
- */
-static int
-isdn_tty_edit_at(const char *p, int count, modem_info *info)
-{
-       atemu *m = &info->emu;
-       int total = 0;
-       u_char c;
-       char eb[2];
-       int cnt;
-
-       for (cnt = count; cnt > 0; p++, cnt--) {
-               c = *p;
-               total++;
-               if (c == m->mdmreg[REG_CR] || c == m->mdmreg[REG_LF]) {
-                       /* Separator (CR or LF) */
-                       m->mdmcmd[m->mdmcmdl] = 0;
-                       if (m->mdmreg[REG_ECHO] & BIT_ECHO) {
-                               eb[0] = c;
-                               eb[1] = 0;
-                               isdn_tty_at_cout(eb, info);
-                       }
-                       if ((m->mdmcmdl >= 2) && (!(strncmp(m->mdmcmd, "AT", 2))))
-                               isdn_tty_parse_at(info);
-                       m->mdmcmdl = 0;
-                       continue;
-               }
-               if (c == m->mdmreg[REG_BS] && m->mdmreg[REG_BS] < 128) {
-                       /* Backspace-Function */
-                       if ((m->mdmcmdl > 2) || (!m->mdmcmdl)) {
-                               if (m->mdmcmdl)
-                                       m->mdmcmdl--;
-                               if (m->mdmreg[REG_ECHO] & BIT_ECHO)
-                                       isdn_tty_at_cout("\b", info);
-                       }
-                       continue;
-               }
-               if (cmdchar(c)) {
-                       if (m->mdmreg[REG_ECHO] & BIT_ECHO) {
-                               eb[0] = c;
-                               eb[1] = 0;
-                               isdn_tty_at_cout(eb, info);
-                       }
-                       if (m->mdmcmdl < 255) {
-                               c = my_toupper(c);
-                               switch (m->mdmcmdl) {
-                               case 1:
-                                       if (c == 'T') {
-                                               m->mdmcmd[m->mdmcmdl] = c;
-                                               m->mdmcmd[++m->mdmcmdl] = 0;
-                                               break;
-                                       } else
-                                               m->mdmcmdl = 0;
-                                       /* Fall through - check for 'A' */
-                               case 0:
-                                       if (c == 'A') {
-                                               m->mdmcmd[m->mdmcmdl] = c;
-                                               m->mdmcmd[++m->mdmcmdl] = 0;
-                                       }
-                                       break;
-                               default:
-                                       m->mdmcmd[m->mdmcmdl] = c;
-                                       m->mdmcmd[++m->mdmcmdl] = 0;
-                               }
-                       }
-               }
-       }
-       return total;
-}
-
-/*
- * Switch all modem-channels who are online and got a valid
- * escape-sequence 1.5 seconds ago, to command-mode.
- * This function is called every second via timer-interrupt from within
- * timer-dispatcher isdn_timer_function()
- */
-void
-isdn_tty_modem_escape(void)
-{
-       int ton = 0;
-       int i;
-       int midx;
-
-       for (i = 0; i < ISDN_MAX_CHANNELS; i++)
-               if (USG_MODEM(dev->usage[i]) && (midx = dev->m_idx[i]) >= 0) {
-                       modem_info *info = &dev->mdm.info[midx];
-                       if (info->online) {
-                               ton = 1;
-                               if ((info->emu.pluscount == 3) &&
-                                   time_after(jiffies,
-                                           info->emu.lastplus + PLUSWAIT2)) {
-                                       info->emu.pluscount = 0;
-                                       info->online = 0;
-                                       isdn_tty_modem_result(RESULT_OK, info);
-                               }
-                       }
-               }
-       isdn_timer_ctrl(ISDN_TIMER_MODEMPLUS, ton);
-}
-
-/*
- * Put a RING-message to all modem-channels who have the RI-bit set.
- * This function is called every second via timer-interrupt from within
- * timer-dispatcher isdn_timer_function()
- */
-void
-isdn_tty_modem_ring(void)
-{
-       int ton = 0;
-       int i;
-
-       for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-               modem_info *info = &dev->mdm.info[i];
-               if (info->msr & UART_MSR_RI) {
-                       ton = 1;
-                       isdn_tty_modem_result(RESULT_RING, info);
-               }
-       }
-       isdn_timer_ctrl(ISDN_TIMER_MODEMRING, ton);
-}
-
-/*
- * For all online tty's, try sending data to
- * the lower levels.
- */
-void
-isdn_tty_modem_xmit(void)
-{
-       int ton = 1;
-       int i;
-
-       for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-               modem_info *info = &dev->mdm.info[i];
-               if (info->online) {
-                       ton = 1;
-                       isdn_tty_senddown(info);
-                       isdn_tty_tint(info);
-               }
-       }
-       isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, ton);
-}
-
-/*
- * Check all channels if we have a 'no carrier' timeout.
- * Timeout value is set by Register S7.
- */
-void
-isdn_tty_carrier_timeout(void)
-{
-       int ton = 0;
-       int i;
-
-       for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-               modem_info *info = &dev->mdm.info[i];
-               if (!info->dialing)
-                       continue;
-               if (info->emu.carrierwait++ > info->emu.mdmreg[REG_WAITC]) {
-                       info->dialing = 0;
-                       isdn_tty_modem_result(RESULT_NO_CARRIER, info);
-                       isdn_tty_modem_hup(info, 1);
-               } else
-                       ton = 1;
-       }
-       isdn_timer_ctrl(ISDN_TIMER_CARRIER, ton);
-}
 
+++ /dev/null
-/* $Id: isdn_tty.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
- *
- * header for Linux ISDN subsystem, tty related functions (linklevel).
- *
- * Copyright 1994-1999  by Fritz Elfert (fritz@isdn4linux.de)
- * Copyright 1995,96    by Thinking Objects Software GmbH Wuerzburg
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-
-#define DLE 0x10
-#define ETX 0x03
-#define DC4 0x14
-
-
-/*
- * Definition of some special Registers of AT-Emulator
- */
-#define REG_RINGATA   0
-#define REG_RINGCNT   1  /* ring counter register */
-#define REG_ESC       2
-#define REG_CR        3
-#define REG_LF        4
-#define REG_BS        5
-
-#define REG_WAITC     7
-
-#define REG_RESP     12  /* show response messages register */
-#define BIT_RESP      1  /* show response messages bit      */
-#define REG_RESPNUM  12  /* show numeric responses register */
-#define BIT_RESPNUM   2  /* show numeric responses bit      */
-#define REG_ECHO     12
-#define BIT_ECHO      4
-#define REG_DCD      12
-#define BIT_DCD       8
-#define REG_CTS      12
-#define BIT_CTS      16
-#define REG_DTRR     12
-#define BIT_DTRR     32
-#define REG_DSR      12
-#define BIT_DSR      64
-#define REG_CPPP     12
-#define BIT_CPPP    128
-
-#define REG_DXMT     13
-#define BIT_DXMT      1
-#define REG_T70      13
-#define BIT_T70       2
-#define BIT_T70_EXT  32
-#define REG_DTRHUP   13
-#define BIT_DTRHUP    4
-#define REG_RESPXT   13
-#define BIT_RESPXT    8
-#define REG_CIDONCE  13
-#define BIT_CIDONCE  16
-#define REG_RUNG     13  /* show RUNG message register      */
-#define BIT_RUNG     64  /* show RUNG message bit           */
-#define REG_DISPLAY  13
-#define BIT_DISPLAY 128
-
-#define REG_L2PROT   14
-#define REG_L3PROT   15
-#define REG_PSIZE    16
-#define REG_WSIZE    17
-#define REG_SI1      18
-#define REG_SI2      19
-#define REG_SI1I     20
-#define REG_PLAN     21
-#define REG_SCREEN   22
-
-#define REG_CPN      23
-#define BIT_CPN       1
-#define REG_CPNFCON  23
-#define BIT_CPNFCON   2
-#define REG_CDN      23
-#define BIT_CDN       4
-
-/* defines for result codes */
-#define RESULT_OK              0
-#define RESULT_CONNECT         1
-#define RESULT_RING            2
-#define RESULT_NO_CARRIER      3
-#define RESULT_ERROR           4
-#define RESULT_CONNECT64000    5
-#define RESULT_NO_DIALTONE     6
-#define RESULT_BUSY            7
-#define RESULT_NO_ANSWER       8
-#define RESULT_RINGING         9
-#define RESULT_NO_MSN_EAZ      10
-#define RESULT_VCON            11
-#define RESULT_RUNG            12
-
-#define TTY_IS_FCLASS1(info)                                           \
-       ((info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_FAX) &&         \
-        (info->emu.mdmreg[REG_L3PROT] == ISDN_PROTO_L3_FCLASS1))
-#define TTY_IS_FCLASS2(info)                                           \
-       ((info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_FAX) &&         \
-        (info->emu.mdmreg[REG_L3PROT] == ISDN_PROTO_L3_FCLASS2))
-
-extern void isdn_tty_modem_escape(void);
-extern void isdn_tty_modem_ring(void);
-extern void isdn_tty_carrier_timeout(void);
-extern void isdn_tty_modem_xmit(void);
-extern int  isdn_tty_modem_init(void);
-extern void isdn_tty_exit(void);
-extern void isdn_tty_readmodem(void);
-extern int  isdn_tty_find_icall(int, int, setup_parm *);
-extern int  isdn_tty_stat_callback(int, isdn_ctrl *);
-extern int  isdn_tty_rcv_skb(int, int, int, struct sk_buff *);
-extern int  isdn_tty_capi_facility(capi_msg *cm);
-extern void isdn_tty_at_cout(char *, modem_info *);
-extern void isdn_tty_modem_hup(modem_info *, int);
-#ifdef CONFIG_ISDN_TTY_FAX
-extern int  isdn_tty_cmd_PLUSF_FAX(char **, modem_info *);
-extern int  isdn_tty_fax_command(modem_info *, isdn_ctrl *);
-extern void isdn_tty_fax_bitorder(modem_info *, struct sk_buff *);
-#endif
 
+++ /dev/null
-/* $Id: isdn_ttyfax.c,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
- *
- * Linux ISDN subsystem, tty_fax AT-command emulator (linklevel).
- *
- * Copyright 1999    by Armin Schindler (mac@melware.de)
- * Copyright 1999    by Ralf Spachmann (mel@melware.de)
- * Copyright 1999    by Cytronics & Melware
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#undef ISDN_TTY_FAX_STAT_DEBUG
-#undef ISDN_TTY_FAX_CMD_DEBUG
-
-#include <linux/isdn.h>
-#include "isdn_common.h"
-#include "isdn_tty.h"
-#include "isdn_ttyfax.h"
-
-
-static char *isdn_tty_fax_revision = "$Revision: 1.1.2.2 $";
-
-#define PARSE_ERROR1 { isdn_tty_fax_modem_result(1, info); return 1; }
-
-static char *
-isdn_getrev(const char *revision)
-{
-       char *rev;
-       char *p;
-
-       if ((p = strchr(revision, ':'))) {
-               rev = p + 2;
-               p = strchr(rev, '$');
-               *--p = 0;
-       } else
-               rev = "???";
-       return rev;
-}
-
-/*
- * Fax Class 2 Modem results
- *
- */
-
-static void
-isdn_tty_fax_modem_result(int code, modem_info *info)
-{
-       atemu *m = &info->emu;
-       T30_s *f = info->fax;
-       char rs[50];
-       char rss[50];
-       char *rp;
-       int i;
-       static char *msg[] =
-               {"OK", "ERROR", "+FCON", "+FCSI:", "+FDIS:",
-                "+FHNG:", "+FDCS:", "CONNECT", "+FTSI:",
-                "+FCFR", "+FPTS:", "+FET:"};
-
-
-       isdn_tty_at_cout("\r\n", info);
-       isdn_tty_at_cout(msg[code], info);
-
-#ifdef ISDN_TTY_FAX_CMD_DEBUG
-       printk(KERN_DEBUG "isdn_tty: Fax send %s on ttyI%d\n",
-              msg[code], info->line);
-#endif
-       switch (code) {
-       case 0: /* OK */
-               break;
-       case 1: /* ERROR */
-               break;
-       case 2: /* +FCON */
-               /* Append CPN, if enabled */
-               if ((m->mdmreg[REG_CPNFCON] & BIT_CPNFCON) &&
-                   (!(dev->usage[info->isdn_channel] & ISDN_USAGE_OUTGOING))) {
-                       sprintf(rs, "/%s", m->cpn);
-                       isdn_tty_at_cout(rs, info);
-               }
-               info->online = 1;
-               f->fet = 0;
-               if (f->phase == ISDN_FAX_PHASE_A)
-                       f->phase = ISDN_FAX_PHASE_B;
-               break;
-       case 3: /* +FCSI */
-       case 8: /* +FTSI */
-               sprintf(rs, "\"%s\"", f->r_id);
-               isdn_tty_at_cout(rs, info);
-               break;
-       case 4: /* +FDIS */
-               rs[0] = 0;
-               rp = &f->r_resolution;
-               for (i = 0; i < 8; i++) {
-                       sprintf(rss, "%c%s", rp[i] + 48,
-                               (i < 7) ? "," : "");
-                       strcat(rs, rss);
-               }
-               isdn_tty_at_cout(rs, info);
-#ifdef ISDN_TTY_FAX_CMD_DEBUG
-               printk(KERN_DEBUG "isdn_tty: Fax DIS=%s on ttyI%d\n",
-                      rs, info->line);
-#endif
-               break;
-       case 5: /* +FHNG */
-               sprintf(rs, "%d", f->code);
-               isdn_tty_at_cout(rs, info);
-               info->faxonline = 0;
-               break;
-       case 6: /* +FDCS */
-               rs[0] = 0;
-               rp = &f->r_resolution;
-               for (i = 0; i < 8; i++) {
-                       sprintf(rss, "%c%s", rp[i] + 48,
-                               (i < 7) ? "," : "");
-                       strcat(rs, rss);
-               }
-               isdn_tty_at_cout(rs, info);
-#ifdef ISDN_TTY_FAX_CMD_DEBUG
-               printk(KERN_DEBUG "isdn_tty: Fax DCS=%s on ttyI%d\n",
-                      rs, info->line);
-#endif
-               break;
-       case 7: /* CONNECT */
-               info->faxonline |= 2;
-               break;
-       case 9: /* FCFR */
-               break;
-       case 10:        /* FPTS */
-               isdn_tty_at_cout("1", info);
-               break;
-       case 11:        /* FET */
-               sprintf(rs, "%d", f->fet);
-               isdn_tty_at_cout(rs, info);
-               break;
-       }
-
-       isdn_tty_at_cout("\r\n", info);
-
-       switch (code) {
-       case 7: /* CONNECT */
-               info->online = 2;
-               if (info->faxonline & 1) {
-                       sprintf(rs, "%c", XON);
-                       isdn_tty_at_cout(rs, info);
-               }
-               break;
-       }
-}
-
-static int
-isdn_tty_fax_command1(modem_info *info, isdn_ctrl *c)
-{
-       static char *msg[] =
-               {"OK", "CONNECT", "NO CARRIER", "ERROR", "FCERROR"};
-
-#ifdef ISDN_TTY_FAX_CMD_DEBUG
-       printk(KERN_DEBUG "isdn_tty: FCLASS1 cmd(%d)\n", c->parm.aux.cmd);
-#endif
-       if (c->parm.aux.cmd < ISDN_FAX_CLASS1_QUERY) {
-               if (info->online)
-                       info->online = 1;
-               isdn_tty_at_cout("\r\n", info);
-               isdn_tty_at_cout(msg[c->parm.aux.cmd], info);
-               isdn_tty_at_cout("\r\n", info);
-       }
-       switch (c->parm.aux.cmd) {
-       case ISDN_FAX_CLASS1_CONNECT:
-               info->online = 2;
-               break;
-       case ISDN_FAX_CLASS1_OK:
-       case ISDN_FAX_CLASS1_FCERROR:
-       case ISDN_FAX_CLASS1_ERROR:
-       case ISDN_FAX_CLASS1_NOCARR:
-               break;
-       case ISDN_FAX_CLASS1_QUERY:
-               isdn_tty_at_cout("\r\n", info);
-               if (!c->parm.aux.para[0]) {
-                       isdn_tty_at_cout(msg[ISDN_FAX_CLASS1_ERROR], info);
-                       isdn_tty_at_cout("\r\n", info);
-               } else {
-                       isdn_tty_at_cout(c->parm.aux.para, info);
-                       isdn_tty_at_cout("\r\nOK\r\n", info);
-               }
-               break;
-       }
-       return (0);
-}
-
-int
-isdn_tty_fax_command(modem_info *info, isdn_ctrl *c)
-{
-       T30_s *f = info->fax;
-       char rs[10];
-
-       if (TTY_IS_FCLASS1(info))
-               return (isdn_tty_fax_command1(info, c));
-
-#ifdef ISDN_TTY_FAX_CMD_DEBUG
-       printk(KERN_DEBUG "isdn_tty: Fax cmd %d on ttyI%d\n",
-              f->r_code, info->line);
-#endif
-       switch (f->r_code) {
-       case ISDN_TTY_FAX_FCON:
-               info->faxonline = 1;
-               isdn_tty_fax_modem_result(2, info);     /* +FCON */
-               return (0);
-       case ISDN_TTY_FAX_FCON_I:
-               info->faxonline = 16;
-               isdn_tty_fax_modem_result(2, info);     /* +FCON */
-               return (0);
-       case ISDN_TTY_FAX_RID:
-               if (info->faxonline & 1)
-                       isdn_tty_fax_modem_result(3, info);     /* +FCSI */
-               if (info->faxonline & 16)
-                       isdn_tty_fax_modem_result(8, info);     /* +FTSI */
-               return (0);
-       case ISDN_TTY_FAX_DIS:
-               isdn_tty_fax_modem_result(4, info);     /* +FDIS */
-               return (0);
-       case ISDN_TTY_FAX_HNG:
-               if (f->phase == ISDN_FAX_PHASE_C) {
-                       if (f->direction == ISDN_TTY_FAX_CONN_IN) {
-                               sprintf(rs, "%c%c", DLE, ETX);
-                               isdn_tty_at_cout(rs, info);
-                       } else {
-                               sprintf(rs, "%c", 0x18);
-                               isdn_tty_at_cout(rs, info);
-                       }
-                       info->faxonline &= ~2;  /* leave data mode */
-                       info->online = 1;
-               }
-               f->phase = ISDN_FAX_PHASE_E;
-               isdn_tty_fax_modem_result(5, info);     /* +FHNG */
-               isdn_tty_fax_modem_result(0, info);     /* OK */
-               return (0);
-       case ISDN_TTY_FAX_DCS:
-               isdn_tty_fax_modem_result(6, info);     /* +FDCS */
-               isdn_tty_fax_modem_result(7, info);     /* CONNECT */
-               f->phase = ISDN_FAX_PHASE_C;
-               return (0);
-       case ISDN_TTY_FAX_TRAIN_OK:
-               isdn_tty_fax_modem_result(6, info);     /* +FDCS */
-               isdn_tty_fax_modem_result(0, info);     /* OK */
-               return (0);
-       case ISDN_TTY_FAX_SENT:
-               isdn_tty_fax_modem_result(0, info);     /* OK */
-               return (0);
-       case ISDN_TTY_FAX_CFR:
-               isdn_tty_fax_modem_result(9, info);     /* +FCFR */
-               return (0);
-       case ISDN_TTY_FAX_ET:
-               sprintf(rs, "%c%c", DLE, ETX);
-               isdn_tty_at_cout(rs, info);
-               isdn_tty_fax_modem_result(10, info);    /* +FPTS */
-               isdn_tty_fax_modem_result(11, info);    /* +FET */
-               isdn_tty_fax_modem_result(0, info);     /* OK */
-               info->faxonline &= ~2;  /* leave data mode */
-               info->online = 1;
-               f->phase = ISDN_FAX_PHASE_D;
-               return (0);
-       case ISDN_TTY_FAX_PTS:
-               isdn_tty_fax_modem_result(10, info);    /* +FPTS */
-               if (f->direction == ISDN_TTY_FAX_CONN_OUT) {
-                       if (f->fet == 1)
-                               f->phase = ISDN_FAX_PHASE_B;
-                       if (f->fet == 0)
-                               isdn_tty_fax_modem_result(0, info);     /* OK */
-               }
-               return (0);
-       case ISDN_TTY_FAX_EOP:
-               info->faxonline &= ~2;  /* leave data mode */
-               info->online = 1;
-               f->phase = ISDN_FAX_PHASE_D;
-               return (0);
-
-       }
-       return (-1);
-}
-
-
-void
-isdn_tty_fax_bitorder(modem_info *info, struct sk_buff *skb)
-{
-       __u8 LeftMask;
-       __u8 RightMask;
-       __u8 fBit;
-       __u8 Data;
-       int i;
-
-       if (!info->fax->bor) {
-               for (i = 0; i < skb->len; i++) {
-                       Data = skb->data[i];
-                       for (
-                               LeftMask = 0x80, RightMask = 0x01;
-                               LeftMask > RightMask;
-                               LeftMask >>= 1, RightMask <<= 1
-                               ) {
-                               fBit = (Data & LeftMask);
-                               if (Data & RightMask)
-                                       Data |= LeftMask;
-                               else
-                                       Data &= ~LeftMask;
-                               if (fBit)
-                                       Data |= RightMask;
-                               else
-                                       Data &= ~RightMask;
-
-                       }
-                       skb->data[i] = Data;
-               }
-       }
-}
-
-/*
- * Parse AT+F.. FAX class 1 commands
- */
-
-static int
-isdn_tty_cmd_FCLASS1(char **p, modem_info *info)
-{
-       static char *cmd[] =
-               {"AE", "TS", "RS", "TM", "RM", "TH", "RH"};
-       isdn_ctrl c;
-       int par, i;
-       u_long flags;
-
-       for (c.parm.aux.cmd = 0; c.parm.aux.cmd < 7; c.parm.aux.cmd++)
-               if (!strncmp(p[0], cmd[c.parm.aux.cmd], 2))
-                       break;
-
-#ifdef ISDN_TTY_FAX_CMD_DEBUG
-       printk(KERN_DEBUG "isdn_tty_cmd_FCLASS1 (%s,%d)\n", p[0], c.parm.aux.cmd);
-#endif
-       if (c.parm.aux.cmd == 7)
-               PARSE_ERROR1;
-
-       p[0] += 2;
-       switch (*p[0]) {
-       case '?':
-               p[0]++;
-               c.parm.aux.subcmd = AT_QUERY;
-               break;
-       case '=':
-               p[0]++;
-               if (*p[0] == '?') {
-                       p[0]++;
-                       c.parm.aux.subcmd = AT_EQ_QUERY;
-               } else {
-                       par = isdn_getnum(p);
-                       if ((par < 0) || (par > 255))
-                               PARSE_ERROR1;
-                       c.parm.aux.subcmd = AT_EQ_VALUE;
-                       c.parm.aux.para[0] = par;
-               }
-               break;
-       case 0:
-               c.parm.aux.subcmd = AT_COMMAND;
-               break;
-       default:
-               PARSE_ERROR1;
-       }
-       c.command = ISDN_CMD_FAXCMD;
-#ifdef ISDN_TTY_FAX_CMD_DEBUG
-       printk(KERN_DEBUG "isdn_tty_cmd_FCLASS1 %d/%d/%d)\n",
-              c.parm.aux.cmd, c.parm.aux.subcmd, c.parm.aux.para[0]);
-#endif
-       if (info->isdn_driver < 0) {
-               if ((c.parm.aux.subcmd == AT_EQ_VALUE) ||
-                   (c.parm.aux.subcmd == AT_COMMAND)) {
-                       PARSE_ERROR1;
-               }
-               spin_lock_irqsave(&dev->lock, flags);
-               /* get a temporary connection to the first free fax driver */
-               i = isdn_get_free_channel(ISDN_USAGE_FAX, ISDN_PROTO_L2_FAX,
-                                         ISDN_PROTO_L3_FCLASS1, -1, -1, "00");
-               if (i < 0) {
-                       spin_unlock_irqrestore(&dev->lock, flags);
-                       PARSE_ERROR1;
-               }
-               info->isdn_driver = dev->drvmap[i];
-               info->isdn_channel = dev->chanmap[i];
-               info->drv_index = i;
-               dev->m_idx[i] = info->line;
-               spin_unlock_irqrestore(&dev->lock, flags);
-               c.driver = info->isdn_driver;
-               c.arg = info->isdn_channel;
-               isdn_command(&c);
-               spin_lock_irqsave(&dev->lock, flags);
-               isdn_free_channel(info->isdn_driver, info->isdn_channel,
-                                 ISDN_USAGE_FAX);
-               info->isdn_driver = -1;
-               info->isdn_channel = -1;
-               if (info->drv_index >= 0) {
-                       dev->m_idx[info->drv_index] = -1;
-                       info->drv_index = -1;
-               }
-               spin_unlock_irqrestore(&dev->lock, flags);
-       } else {
-               c.driver = info->isdn_driver;
-               c.arg = info->isdn_channel;
-               isdn_command(&c);
-       }
-       return 1;
-}
-
-/*
- * Parse AT+F.. FAX class 2 commands
- */
-
-static int
-isdn_tty_cmd_FCLASS2(char **p, modem_info *info)
-{
-       atemu *m = &info->emu;
-       T30_s *f = info->fax;
-       isdn_ctrl cmd;
-       int par;
-       char rs[50];
-       char rss[50];
-       int maxdccval[] =
-               {1, 5, 2, 2, 3, 2, 0, 7};
-
-       /* FAA still unchanged */
-       if (!strncmp(p[0], "AA", 2)) {  /* TODO */
-               p[0] += 2;
-               switch (*p[0]) {
-               case '?':
-                       p[0]++;
-                       sprintf(rs, "\r\n%d", 0);
-                       isdn_tty_at_cout(rs, info);
-                       break;
-               case '=':
-                       p[0]++;
-                       par = isdn_getnum(p);
-                       if ((par < 0) || (par > 255))
-                               PARSE_ERROR1;
-                       break;
-               default:
-                       PARSE_ERROR1;
-               }
-               return 0;
-       }
-       /* BADLIN=value - dummy 0=disable errorchk disabled, 1-255 nr. of lines for making page bad */
-       if (!strncmp(p[0], "BADLIN", 6)) {
-               p[0] += 6;
-               switch (*p[0]) {
-               case '?':
-                       p[0]++;
-                       sprintf(rs, "\r\n%d", f->badlin);
-                       isdn_tty_at_cout(rs, info);
-                       break;
-               case '=':
-                       p[0]++;
-                       if (*p[0] == '?') {
-                               p[0]++;
-                               sprintf(rs, "\r\n0-255");
-                               isdn_tty_at_cout(rs, info);
-                       } else {
-                               par = isdn_getnum(p);
-                               if ((par < 0) || (par > 255))
-                                       PARSE_ERROR1;
-                               f->badlin = par;
-#ifdef ISDN_TTY_FAX_STAT_DEBUG
-                               printk(KERN_DEBUG "isdn_tty: Fax FBADLIN=%d\n", par);
-#endif
-                       }
-                       break;
-               default:
-                       PARSE_ERROR1;
-               }
-               return 0;
-       }
-       /* BADMUL=value - dummy 0=disable errorchk disabled (threshold multiplier) */
-       if (!strncmp(p[0], "BADMUL", 6)) {
-               p[0] += 6;
-               switch (*p[0]) {
-               case '?':
-                       p[0]++;
-                       sprintf(rs, "\r\n%d", f->badmul);
-                       isdn_tty_at_cout(rs, info);
-                       break;
-               case '=':
-                       p[0]++;
-                       if (*p[0] == '?') {
-                               p[0]++;
-                               sprintf(rs, "\r\n0-255");
-                               isdn_tty_at_cout(rs, info);
-                       } else {
-                               par = isdn_getnum(p);
-                               if ((par < 0) || (par > 255))
-                                       PARSE_ERROR1;
-                               f->badmul = par;
-#ifdef ISDN_TTY_FAX_STAT_DEBUG
-                               printk(KERN_DEBUG "isdn_tty: Fax FBADMUL=%d\n", par);
-#endif
-                       }
-                       break;
-               default:
-                       PARSE_ERROR1;
-               }
-               return 0;
-       }
-       /* BOR=n - Phase C bit order, 0=direct, 1=reverse */
-       if (!strncmp(p[0], "BOR", 3)) {
-               p[0] += 3;
-               switch (*p[0]) {
-               case '?':
-                       p[0]++;
-                       sprintf(rs, "\r\n%d", f->bor);
-                       isdn_tty_at_cout(rs, info);
-                       break;
-               case '=':
-                       p[0]++;
-                       if (*p[0] == '?') {
-                               p[0]++;
-                               sprintf(rs, "\r\n0,1");
-                               isdn_tty_at_cout(rs, info);
-                       } else {
-                               par = isdn_getnum(p);
-                               if ((par < 0) || (par > 1))
-                                       PARSE_ERROR1;
-                               f->bor = par;
-#ifdef ISDN_TTY_FAX_STAT_DEBUG
-                               printk(KERN_DEBUG "isdn_tty: Fax FBOR=%d\n", par);
-#endif
-                       }
-                       break;
-               default:
-                       PARSE_ERROR1;
-               }
-               return 0;
-       }
-       /* NBC=n - No Best Capabilities */
-       if (!strncmp(p[0], "NBC", 3)) {
-               p[0] += 3;
-               switch (*p[0]) {
-               case '?':
-                       p[0]++;
-                       sprintf(rs, "\r\n%d", f->nbc);
-                       isdn_tty_at_cout(rs, info);
-                       break;
-               case '=':
-                       p[0]++;
-                       if (*p[0] == '?') {
-                               p[0]++;
-                               sprintf(rs, "\r\n0,1");
-                               isdn_tty_at_cout(rs, info);
-                       } else {
-                               par = isdn_getnum(p);
-                               if ((par < 0) || (par > 1))
-                                       PARSE_ERROR1;
-                               f->nbc = par;
-#ifdef ISDN_TTY_FAX_STAT_DEBUG
-                               printk(KERN_DEBUG "isdn_tty: Fax FNBC=%d\n", par);
-#endif
-                       }
-                       break;
-               default:
-                       PARSE_ERROR1;
-               }
-               return 0;
-       }
-       /* BUF? - Readonly buffersize readout  */
-       if (!strncmp(p[0], "BUF?", 4)) {
-               p[0] += 4;
-#ifdef ISDN_TTY_FAX_STAT_DEBUG
-               printk(KERN_DEBUG "isdn_tty: Fax FBUF? (%d) \n", (16 * m->mdmreg[REG_PSIZE]));
-#endif
-               p[0]++;
-               sprintf(rs, "\r\n %d ", (16 * m->mdmreg[REG_PSIZE]));
-               isdn_tty_at_cout(rs, info);
-               return 0;
-       }
-       /* CIG=string - local fax station id string for polling rx */
-       if (!strncmp(p[0], "CIG", 3)) {
-               int i, r;
-               p[0] += 3;
-               switch (*p[0]) {
-               case '?':
-                       p[0]++;
-                       sprintf(rs, "\r\n\"%s\"", f->pollid);
-                       isdn_tty_at_cout(rs, info);
-                       break;
-               case '=':
-                       p[0]++;
-                       if (*p[0] == '?') {
-                               p[0]++;
-                               sprintf(rs, "\r\n\"STRING\"");
-                               isdn_tty_at_cout(rs, info);
-                       } else {
-                               if (*p[0] == '"')
-                                       p[0]++;
-                               for (i = 0; (*p[0]) && i < (FAXIDLEN - 1) && (*p[0] != '"'); i++) {
-                                       f->pollid[i] = *p[0]++;
-                               }
-                               if (*p[0] == '"')
-                                       p[0]++;
-                               for (r = i; r < FAXIDLEN; r++) {
-                                       f->pollid[r] = 32;
-                               }
-                               f->pollid[FAXIDLEN - 1] = 0;
-#ifdef ISDN_TTY_FAX_STAT_DEBUG
-                               printk(KERN_DEBUG "isdn_tty: Fax local poll ID rx \"%s\"\n", f->pollid);
-#endif
-                       }
-                       break;
-               default:
-                       PARSE_ERROR1;
-               }
-               return 0;
-       }
-       /* CQ=n - copy qlty chk, 0= no chk, 1=only 1D chk, 2=1D+2D chk */
-       if (!strncmp(p[0], "CQ", 2)) {
-               p[0] += 2;
-               switch (*p[0]) {
-               case '?':
-                       p[0]++;
-                       sprintf(rs, "\r\n%d", f->cq);
-                       isdn_tty_at_cout(rs, info);
-                       break;
-               case '=':
-                       p[0]++;
-                       if (*p[0] == '?') {
-                               p[0]++;
-                               sprintf(rs, "\r\n0,1,2");
-                               isdn_tty_at_cout(rs, info);
-                       } else {
-                               par = isdn_getnum(p);
-                               if ((par < 0) || (par > 2))
-                                       PARSE_ERROR1;
-                               f->cq = par;
-#ifdef ISDN_TTY_FAX_STAT_DEBUG
-                               printk(KERN_DEBUG "isdn_tty: Fax FCQ=%d\n", par);
-#endif
-                       }
-                       break;
-               default:
-                       PARSE_ERROR1;
-               }
-               return 0;
-       }
-       /* CR=n - can receive? 0= no data rx or poll remote dev, 1=do receive data or poll remote dev */
-       if (!strncmp(p[0], "CR", 2)) {
-               p[0] += 2;
-               switch (*p[0]) {
-               case '?':
-                       p[0]++;
-                       sprintf(rs, "\r\n%d", f->cr);   /* read actual value from struct and print */
-                       isdn_tty_at_cout(rs, info);
-                       break;
-               case '=':
-                       p[0]++;
-                       if (*p[0] == '?') {
-                               p[0]++;
-                               sprintf(rs, "\r\n0,1");         /* display online help */
-                               isdn_tty_at_cout(rs, info);
-                       } else {
-                               par = isdn_getnum(p);
-                               if ((par < 0) || (par > 1))
-                                       PARSE_ERROR1;
-                               f->cr = par;
-#ifdef ISDN_TTY_FAX_STAT_DEBUG
-                               printk(KERN_DEBUG "isdn_tty: Fax FCR=%d\n", par);
-#endif
-                       }
-                       break;
-               default:
-                       PARSE_ERROR1;
-               }
-               return 0;
-       }
-       /* CTCRTY=value - ECM retry count */
-       if (!strncmp(p[0], "CTCRTY", 6)) {
-               p[0] += 6;
-               switch (*p[0]) {
-               case '?':
-                       p[0]++;
-                       sprintf(rs, "\r\n%d", f->ctcrty);
-                       isdn_tty_at_cout(rs, info);
-                       break;
-               case '=':
-                       p[0]++;
-                       if (*p[0] == '?') {
-                               p[0]++;
-                               sprintf(rs, "\r\n0-255");
-                               isdn_tty_at_cout(rs, info);
-                       } else {
-                               par = isdn_getnum(p);
-                               if ((par < 0) || (par > 255))
-                                       PARSE_ERROR1;
-                               f->ctcrty = par;
-#ifdef ISDN_TTY_FAX_STAT_DEBUG
-                               printk(KERN_DEBUG "isdn_tty: Fax FCTCRTY=%d\n", par);
-#endif
-                       }
-                       break;
-               default:
-                       PARSE_ERROR1;
-               }
-               return 0;
-       }
-       /* DCC=vr,br,wd,ln,df,ec,bf,st - DCE capabilities parms */
-       if (!strncmp(p[0], "DCC", 3)) {
-               char *rp = &f->resolution;
-               int i;
-
-               p[0] += 3;
-               switch (*p[0]) {
-               case '?':
-                       p[0]++;
-                       strcpy(rs, "\r\n");
-                       for (i = 0; i < 8; i++) {
-                               sprintf(rss, "%c%s", rp[i] + 48,
-                                       (i < 7) ? "," : "");
-                               strcat(rs, rss);
-                       }
-                       isdn_tty_at_cout(rs, info);
-                       break;
-               case '=':
-                       p[0]++;
-                       if (*p[0] == '?') {
-                               isdn_tty_at_cout("\r\n(0,1),(0-5),(0-2),(0-2),(0-3),(0-2),(0),(0-7)", info);
-                               p[0]++;
-                       } else {
-                               for (i = 0; (((*p[0] >= '0') && (*p[0] <= '9')) || (*p[0] == ',')) && (i < 8); i++) {
-                                       if (*p[0] != ',') {
-                                               if ((*p[0] - 48) > maxdccval[i]) {
-                                                       PARSE_ERROR1;
-                                               }
-                                               rp[i] = *p[0] - 48;
-                                               p[0]++;
-                                               if (*p[0] == ',')
-                                                       p[0]++;
-                                       } else
-                                               p[0]++;
-                               }
-#ifdef ISDN_TTY_FAX_STAT_DEBUG
-                               printk(KERN_DEBUG "isdn_tty: Fax FDCC capabilities DCE=%d,%d,%d,%d,%d,%d,%d,%d\n",
-                                      rp[0], rp[1], rp[2], rp[3], rp[4], rp[5], rp[6], rp[7]);
-#endif
-                       }
-                       break;
-               default:
-                       PARSE_ERROR1;
-               }
-               return 0;
-       }
-       /* DIS=vr,br,wd,ln,df,ec,bf,st - current session parms */
-       if (!strncmp(p[0], "DIS", 3)) {
-               char *rp = &f->resolution;
-               int i;
-
-               p[0] += 3;
-               switch (*p[0]) {
-               case '?':
-                       p[0]++;
-                       strcpy(rs, "\r\n");
-                       for (i = 0; i < 8; i++) {
-                               sprintf(rss, "%c%s", rp[i] + 48,
-                                       (i < 7) ? "," : "");
-                               strcat(rs, rss);
-                       }
-                       isdn_tty_at_cout(rs, info);
-                       break;
-               case '=':
-                       p[0]++;
-                       if (*p[0] == '?') {
-                               isdn_tty_at_cout("\r\n(0,1),(0-5),(0-2),(0-2),(0-3),(0-2),(0),(0-7)", info);
-                               p[0]++;
-                       } else {
-                               for (i = 0; (((*p[0] >= '0') && (*p[0] <= '9')) || (*p[0] == ',')) && (i < 8); i++) {
-                                       if (*p[0] != ',') {
-                                               if ((*p[0] - 48) > maxdccval[i]) {
-                                                       PARSE_ERROR1;
-                                               }
-                                               rp[i] = *p[0] - 48;
-                                               p[0]++;
-                                               if (*p[0] == ',')
-                                                       p[0]++;
-                                       } else
-                                               p[0]++;
-                               }
-#ifdef ISDN_TTY_FAX_STAT_DEBUG
-                               printk(KERN_DEBUG "isdn_tty: Fax FDIS session parms=%d,%d,%d,%d,%d,%d,%d,%d\n",
-                                      rp[0], rp[1], rp[2], rp[3], rp[4], rp[5], rp[6], rp[7]);
-#endif
-                       }
-                       break;
-               default:
-                       PARSE_ERROR1;
-               }
-               return 0;
-       }
-       /* DR - Receive Phase C data command, initiates document reception */
-       if (!strncmp(p[0], "DR", 2)) {
-               p[0] += 2;
-               if ((info->faxonline & 16) &&   /* incoming connection */
-                   ((f->phase == ISDN_FAX_PHASE_B) || (f->phase == ISDN_FAX_PHASE_D))) {
-#ifdef ISDN_TTY_FAX_STAT_DEBUG
-                       printk(KERN_DEBUG "isdn_tty: Fax FDR\n");
-#endif
-                       f->code = ISDN_TTY_FAX_DR;
-                       cmd.driver = info->isdn_driver;
-                       cmd.arg = info->isdn_channel;
-                       cmd.command = ISDN_CMD_FAXCMD;
-                       isdn_command(&cmd);
-                       if (f->phase == ISDN_FAX_PHASE_B) {
-                               f->phase = ISDN_FAX_PHASE_C;
-                       } else if (f->phase == ISDN_FAX_PHASE_D) {
-                               switch (f->fet) {
-                               case 0: /* next page will be received */
-                                       f->phase = ISDN_FAX_PHASE_C;
-                                       isdn_tty_fax_modem_result(7, info);     /* CONNECT */
-                                       break;
-                               case 1: /* next doc will be received */
-                                       f->phase = ISDN_FAX_PHASE_B;
-                                       break;
-                               case 2: /* fax session is terminating */
-                                       f->phase = ISDN_FAX_PHASE_E;
-                                       break;
-                               default:
-                                       PARSE_ERROR1;
-                               }
-                       }
-               } else {
-                       PARSE_ERROR1;
-               }
-               return 1;
-       }
-       /* DT=df,vr,wd,ln - TX phase C data command (release DCE to proceed with negotiation) */
-       if (!strncmp(p[0], "DT", 2)) {
-               int i, val[] =
-                       {4, 0, 2, 3};
-               char *rp = &f->resolution;
-
-               p[0] += 2;
-               if (!(info->faxonline & 1))     /* not outgoing connection */
-                       PARSE_ERROR1;
-
-               for (i = 0; (((*p[0] >= '0') && (*p[0] <= '9')) || (*p[0] == ',')) && (i < 4); i++) {
-                       if (*p[0] != ',') {
-                               if ((*p[0] - 48) > maxdccval[val[i]]) {
-                                       PARSE_ERROR1;
-                               }
-                               rp[val[i]] = *p[0] - 48;
-                               p[0]++;
-                               if (*p[0] == ',')
-                                       p[0]++;
-                       } else
-                               p[0]++;
-               }
-#ifdef ISDN_TTY_FAX_STAT_DEBUG
-               printk(KERN_DEBUG "isdn_tty: Fax FDT tx data command parms=%d,%d,%d,%d\n",
-                      rp[4], rp[0], rp[2], rp[3]);
-#endif
-               if ((f->phase == ISDN_FAX_PHASE_B) || (f->phase == ISDN_FAX_PHASE_D)) {
-                       f->code = ISDN_TTY_FAX_DT;
-                       cmd.driver = info->isdn_driver;
-                       cmd.arg = info->isdn_channel;
-                       cmd.command = ISDN_CMD_FAXCMD;
-                       isdn_command(&cmd);
-                       if (f->phase == ISDN_FAX_PHASE_D) {
-                               f->phase = ISDN_FAX_PHASE_C;
-                               isdn_tty_fax_modem_result(7, info);     /* CONNECT */
-                       }
-               } else {
-                       PARSE_ERROR1;
-               }
-               return 1;
-       }
-       /* ECM=n - Error mode control 0=disabled, 2=enabled, handled by DCE alone incl. buff of partial pages */
-       if (!strncmp(p[0], "ECM", 3)) {
-               p[0] += 3;
-               switch (*p[0]) {
-               case '?':
-                       p[0]++;
-                       sprintf(rs, "\r\n%d", f->ecm);
-                       isdn_tty_at_cout(rs, info);
-                       break;
-               case '=':
-                       p[0]++;
-                       if (*p[0] == '?') {
-                               p[0]++;
-                               sprintf(rs, "\r\n0,2");
-                               isdn_tty_at_cout(rs, info);
-                       } else {
-                               par = isdn_getnum(p);
-                               if ((par != 0) && (par != 2))
-                                       PARSE_ERROR1;
-                               f->ecm = par;
-#ifdef ISDN_TTY_FAX_STAT_DEBUG
-                               printk(KERN_DEBUG "isdn_tty: Fax FECM=%d\n", par);
-#endif
-                       }
-                       break;
-               default:
-                       PARSE_ERROR1;
-               }
-               return 0;
-       }
-       /* ET=n - End of page or document */
-       if (!strncmp(p[0], "ET=", 3)) {
-               p[0] += 3;
-               if (*p[0] == '?') {
-                       p[0]++;
-                       sprintf(rs, "\r\n0-2");
-                       isdn_tty_at_cout(rs, info);
-               } else {
-                       if ((f->phase != ISDN_FAX_PHASE_D) ||
-                           (!(info->faxonline & 1)))
-                               PARSE_ERROR1;
-                       par = isdn_getnum(p);
-                       if ((par < 0) || (par > 2))
-                               PARSE_ERROR1;
-                       f->fet = par;
-                       f->code = ISDN_TTY_FAX_ET;
-                       cmd.driver = info->isdn_driver;
-                       cmd.arg = info->isdn_channel;
-                       cmd.command = ISDN_CMD_FAXCMD;
-                       isdn_command(&cmd);
-#ifdef ISDN_TTY_FAX_STAT_DEBUG
-                       printk(KERN_DEBUG "isdn_tty: Fax FET=%d\n", par);
-#endif
-                       return 1;
-               }
-               return 0;
-       }
-       /* K - terminate */
-       if (!strncmp(p[0], "K", 1)) {
-               p[0] += 1;
-               if ((f->phase == ISDN_FAX_PHASE_IDLE) || (f->phase == ISDN_FAX_PHASE_E))
-                       PARSE_ERROR1;
-               isdn_tty_modem_hup(info, 1);
-               return 1;
-       }
-       /* LID=string - local fax ID */
-       if (!strncmp(p[0], "LID", 3)) {
-               int i, r;
-               p[0] += 3;
-               switch (*p[0]) {
-               case '?':
-                       p[0]++;
-                       sprintf(rs, "\r\n\"%s\"", f->id);
-                       isdn_tty_at_cout(rs, info);
-                       break;
-               case '=':
-                       p[0]++;
-                       if (*p[0] == '?') {
-                               p[0]++;
-                               sprintf(rs, "\r\n\"STRING\"");
-                               isdn_tty_at_cout(rs, info);
-                       } else {
-                               if (*p[0] == '"')
-                                       p[0]++;
-                               for (i = 0; (*p[0]) && i < (FAXIDLEN - 1) && (*p[0] != '"'); i++) {
-                                       f->id[i] = *p[0]++;
-                               }
-                               if (*p[0] == '"')
-                                       p[0]++;
-                               for (r = i; r < FAXIDLEN; r++) {
-                                       f->id[r] = 32;
-                               }
-                               f->id[FAXIDLEN - 1] = 0;
-#ifdef ISDN_TTY_FAX_STAT_DEBUG
-                               printk(KERN_DEBUG "isdn_tty: Fax local ID \"%s\"\n", f->id);
-#endif
-                       }
-                       break;
-               default:
-                       PARSE_ERROR1;
-               }
-               return 0;
-       }
-
-       /* MDL? - DCE Model       */
-       if (!strncmp(p[0], "MDL?", 4)) {
-               p[0] += 4;
-#ifdef ISDN_TTY_FAX_STAT_DEBUG
-               printk(KERN_DEBUG "isdn_tty: FMDL?\n");
-#endif
-               isdn_tty_at_cout("\r\nisdn4linux", info);
-               return 0;
-       }
-       /* MFR? - DCE Manufacturer */
-       if (!strncmp(p[0], "MFR?", 4)) {
-               p[0] += 4;
-#ifdef ISDN_TTY_FAX_STAT_DEBUG
-               printk(KERN_DEBUG "isdn_tty: FMFR?\n");
-#endif
-               isdn_tty_at_cout("\r\nisdn4linux", info);
-               return 0;
-       }
-       /* MINSP=n - Minimum Speed for Phase C */
-       if (!strncmp(p[0], "MINSP", 5)) {
-               p[0] += 5;
-               switch (*p[0]) {
-               case '?':
-                       p[0]++;
-                       sprintf(rs, "\r\n%d", f->minsp);
-                       isdn_tty_at_cout(rs, info);
-                       break;
-               case '=':
-                       p[0]++;
-                       if (*p[0] == '?') {
-                               p[0]++;
-                               sprintf(rs, "\r\n0-5");
-                               isdn_tty_at_cout(rs, info);
-                       } else {
-                               par = isdn_getnum(p);
-                               if ((par < 0) || (par > 5))
-                                       PARSE_ERROR1;
-                               f->minsp = par;
-#ifdef ISDN_TTY_FAX_STAT_DEBUG
-                               printk(KERN_DEBUG "isdn_tty: Fax FMINSP=%d\n", par);
-#endif
-                       }
-                       break;
-               default:
-                       PARSE_ERROR1;
-               }
-               return 0;
-       }
-       /* PHCTO=value - DTE phase C timeout */
-       if (!strncmp(p[0], "PHCTO", 5)) {
-               p[0] += 5;
-               switch (*p[0]) {
-               case '?':
-                       p[0]++;
-                       sprintf(rs, "\r\n%d", f->phcto);
-                       isdn_tty_at_cout(rs, info);
-                       break;
-               case '=':
-                       p[0]++;
-                       if (*p[0] == '?') {
-                               p[0]++;
-                               sprintf(rs, "\r\n0-255");
-                               isdn_tty_at_cout(rs, info);
-                       } else {
-                               par = isdn_getnum(p);
-                               if ((par < 0) || (par > 255))
-                                       PARSE_ERROR1;
-                               f->phcto = par;
-#ifdef ISDN_TTY_FAX_STAT_DEBUG
-                               printk(KERN_DEBUG "isdn_tty: Fax FPHCTO=%d\n", par);
-#endif
-                       }
-                       break;
-               default:
-                       PARSE_ERROR1;
-               }
-               return 0;
-       }
-
-       /* REL=n - Phase C received EOL alignment */
-       if (!strncmp(p[0], "REL", 3)) {
-               p[0] += 3;
-               switch (*p[0]) {
-               case '?':
-                       p[0]++;
-                       sprintf(rs, "\r\n%d", f->rel);
-                       isdn_tty_at_cout(rs, info);
-                       break;
-               case '=':
-                       p[0]++;
-                       if (*p[0] == '?') {
-                               p[0]++;
-                               sprintf(rs, "\r\n0,1");
-                               isdn_tty_at_cout(rs, info);
-                       } else {
-                               par = isdn_getnum(p);
-                               if ((par < 0) || (par > 1))
-                                       PARSE_ERROR1;
-                               f->rel = par;
-#ifdef ISDN_TTY_FAX_STAT_DEBUG
-                               printk(KERN_DEBUG "isdn_tty: Fax FREL=%d\n", par);
-#endif
-                       }
-                       break;
-               default:
-                       PARSE_ERROR1;
-               }
-               return 0;
-       }
-       /* REV? - DCE Revision */
-       if (!strncmp(p[0], "REV?", 4)) {
-               p[0] += 4;
-#ifdef ISDN_TTY_FAX_STAT_DEBUG
-               printk(KERN_DEBUG "isdn_tty: FREV?\n");
-#endif
-               strcpy(rss, isdn_tty_fax_revision);
-               sprintf(rs, "\r\nRev: %s", isdn_getrev(rss));
-               isdn_tty_at_cout(rs, info);
-               return 0;
-       }
-
-       /* Phase C Transmit Data Block Size */
-       if (!strncmp(p[0], "TBC=", 4)) {        /* dummy, not used */
-               p[0] += 4;
-#ifdef ISDN_TTY_FAX_STAT_DEBUG
-               printk(KERN_DEBUG "isdn_tty: Fax FTBC=%c\n", *p[0]);
-#endif
-               switch (*p[0]) {
-               case '0':
-                       p[0]++;
-                       break;
-               default:
-                       PARSE_ERROR1;
-               }
-               return 0;
-       }
-       printk(KERN_DEBUG "isdn_tty: unknown token=>AT+F%s<\n", p[0]);
-       PARSE_ERROR1;
-}
-
-int
-isdn_tty_cmd_PLUSF_FAX(char **p, modem_info *info)
-{
-       if (TTY_IS_FCLASS2(info))
-               return (isdn_tty_cmd_FCLASS2(p, info));
-       else if (TTY_IS_FCLASS1(info))
-               return (isdn_tty_cmd_FCLASS1(p, info));
-       PARSE_ERROR1;
-}
 
+++ /dev/null
-/* $Id: isdn_ttyfax.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
- *
- * header for Linux ISDN subsystem, tty_fax related functions (linklevel).
- *
- * Copyright 1999   by Armin Schindler (mac@melware.de)
- * Copyright 1999   by Ralf Spachmann (mel@melware.de)
- * Copyright 1999   by Cytronics & Melware
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-
-#define XON    0x11
-#define XOFF   0x13
-#define DC2    0x12
 
+++ /dev/null
-/* $Id: isdn_v110.c,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
- *
- * Linux ISDN subsystem, V.110 related functions (linklevel).
- *
- * Copyright by Thomas Pfeiffer (pfeiffer@pds.de)
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-
-#include <linux/isdn.h>
-#include "isdn_v110.h"
-
-#undef ISDN_V110_DEBUG
-
-char *isdn_v110_revision = "$Revision: 1.1.2.2 $";
-
-#define V110_38400 255
-#define V110_19200  15
-#define V110_9600    3
-
-/*
- * The following data are precoded matrices, online and offline matrix
- * for 9600, 19200 und 38400, respectively
- */
-static unsigned char V110_OnMatrix_9600[] =
-{0xfc, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff,
- 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd,
- 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff,
- 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd};
-
-static unsigned char V110_OffMatrix_9600[] =
-{0xfc, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-
-static unsigned char V110_OnMatrix_19200[] =
-{0xf0, 0xf0, 0xff, 0xf7, 0xff, 0xf7, 0xff, 0xf7, 0xff, 0xf7,
- 0xfd, 0xff, 0xff, 0xf7, 0xff, 0xf7, 0xff, 0xf7, 0xff, 0xf7};
-
-static unsigned char V110_OffMatrix_19200[] =
-{0xf0, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-
-static unsigned char V110_OnMatrix_38400[] =
-{0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0xfd, 0x7f, 0x7f, 0x7f, 0x7f};
-
-static unsigned char V110_OffMatrix_38400[] =
-{0x00, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff};
-
-/*
- * FlipBits reorders sequences of keylen bits in one byte.
- * E.g. source order 7654321 will be converted to 45670123 when keylen = 4,
- * and to 67452301 when keylen = 2. This is necessary because ordering on
- * the isdn line is the other way.
- */
-static inline unsigned char
-FlipBits(unsigned char c, int keylen)
-{
-       unsigned char b = c;
-       unsigned char bit = 128;
-       int i;
-       int j;
-       int hunks = (8 / keylen);
-
-       c = 0;
-       for (i = 0; i < hunks; i++) {
-               for (j = 0; j < keylen; j++) {
-                       if (b & (bit >> j))
-                               c |= bit >> (keylen - j - 1);
-               }
-               bit >>= keylen;
-       }
-       return c;
-}
-
-
-/* isdn_v110_open allocates and initializes private V.110 data
- * structures and returns a pointer to these.
- */
-static isdn_v110_stream *
-isdn_v110_open(unsigned char key, int hdrlen, int maxsize)
-{
-       int i;
-       isdn_v110_stream *v;
-
-       if ((v = kzalloc(sizeof(isdn_v110_stream), GFP_ATOMIC)) == NULL)
-               return NULL;
-       v->key = key;
-       v->nbits = 0;
-       for (i = 0; key & (1 << i); i++)
-               v->nbits++;
-
-       v->nbytes = 8 / v->nbits;
-       v->decodelen = 0;
-
-       switch (key) {
-       case V110_38400:
-               v->OnlineFrame = V110_OnMatrix_38400;
-               v->OfflineFrame = V110_OffMatrix_38400;
-               break;
-       case V110_19200:
-               v->OnlineFrame = V110_OnMatrix_19200;
-               v->OfflineFrame = V110_OffMatrix_19200;
-               break;
-       default:
-               v->OnlineFrame = V110_OnMatrix_9600;
-               v->OfflineFrame = V110_OffMatrix_9600;
-               break;
-       }
-       v->framelen = v->nbytes * 10;
-       v->SyncInit = 5;
-       v->introducer = 0;
-       v->dbit = 1;
-       v->b = 0;
-       v->skbres = hdrlen;
-       v->maxsize = maxsize - hdrlen;
-       if ((v->encodebuf = kmalloc(maxsize, GFP_ATOMIC)) == NULL) {
-               kfree(v);
-               return NULL;
-       }
-       return v;
-}
-
-/* isdn_v110_close frees private V.110 data structures */
-void
-isdn_v110_close(isdn_v110_stream *v)
-{
-       if (v == NULL)
-               return;
-#ifdef ISDN_V110_DEBUG
-       printk(KERN_DEBUG "v110 close\n");
-#endif
-       kfree(v->encodebuf);
-       kfree(v);
-}
-
-
-/*
- * ValidHeaderBytes return the number of valid bytes in v->decodebuf
- */
-static int
-ValidHeaderBytes(isdn_v110_stream *v)
-{
-       int i;
-       for (i = 0; (i < v->decodelen) && (i < v->nbytes); i++)
-               if ((v->decodebuf[i] & v->key) != 0)
-                       break;
-       return i;
-}
-
-/*
- * SyncHeader moves the decodebuf ptr to the next valid header
- */
-static void
-SyncHeader(isdn_v110_stream *v)
-{
-       unsigned char *rbuf = v->decodebuf;
-       int len = v->decodelen;
-
-       if (len == 0)
-               return;
-       for (rbuf++, len--; len > 0; len--, rbuf++)     /* such den SyncHeader in buf ! */
-               if ((*rbuf & v->key) == 0)      /* erstes byte gefunden ?       */
-                       break;  /* jupp!                        */
-       if (len)
-               memcpy(v->decodebuf, rbuf, len);
-
-       v->decodelen = len;
-#ifdef ISDN_V110_DEBUG
-       printk(KERN_DEBUG "isdn_v110: Header resync\n");
-#endif
-}
-
-/* DecodeMatrix takes n (n>=1) matrices (v110 frames, 10 bytes) where
-   len is the number of matrix-lines. len must be a multiple of 10, i.e.
-   only complete matices must be given.
-   From these, netto data is extracted and returned in buf. The return-value
-   is the bytecount of the decoded data.
-*/
-static int
-DecodeMatrix(isdn_v110_stream *v, unsigned char *m, int len, unsigned char *buf)
-{
-       int line = 0;
-       int buflen = 0;
-       int mbit = 64;
-       int introducer = v->introducer;
-       int dbit = v->dbit;
-       unsigned char b = v->b;
-
-       while (line < len) {    /* Are we done with all lines of the matrix? */
-               if ((line % 10) == 0) { /* the 0. line of the matrix is always 0 ! */
-                       if (m[line] != 0x00) {  /* not 0 ? -> error! */
-#ifdef ISDN_V110_DEBUG
-                               printk(KERN_DEBUG "isdn_v110: DecodeMatrix, V110 Bad Header\n");
-                               /* returning now is not the right thing, though :-( */
-#endif
-                       }
-                       line++; /* next line of matrix */
-                       continue;
-               } else if ((line % 10) == 5) {  /* in line 5 there's only e-bits ! */
-                       if ((m[line] & 0x70) != 0x30) { /* 011 has to be at the beginning! */
-#ifdef ISDN_V110_DEBUG
-                               printk(KERN_DEBUG "isdn_v110: DecodeMatrix, V110 Bad 5th line\n");
-                               /* returning now is not the right thing, though :-( */
-#endif
-                       }
-                       line++; /* next line */
-                       continue;
-               } else if (!introducer) {       /* every byte starts with 10 (stopbit, startbit) */
-                       introducer = (m[line] & mbit) ? 0 : 1;  /* current bit of the matrix */
-               next_byte:
-                       if (mbit > 2) { /* was it the last bit in this line ? */
-                               mbit >>= 1;     /* no -> take next */
-                               continue;
-                       }       /* otherwise start with leftmost bit in the next line */
-                       mbit = 64;
-                       line++;
-                       continue;
-               } else {        /* otherwise we need to set a data bit */
-                       if (m[line] & mbit)     /* was that bit set in the matrix ? */
-                               b |= dbit;      /* yes -> set it in the data byte */
-                       else
-                               b &= dbit - 1;  /* no -> clear it in the data byte */
-                       if (dbit < 128) /* is that data byte done ? */
-                               dbit <<= 1;     /* no, got the next bit */
-                       else {  /* data byte is done */
-                               buf[buflen++] = b;      /* copy byte into the output buffer */
-                               introducer = b = 0;     /* init of the intro sequence and of the data byte */
-                               dbit = 1;       /* next we look for the 0th bit */
-                       }
-                       goto next_byte; /* look for next bit in the matrix */
-               }
-       }
-       v->introducer = introducer;
-       v->dbit = dbit;
-       v->b = b;
-       return buflen;          /* return number of bytes in the output buffer */
-}
-
-/*
- * DecodeStream receives V.110 coded data from the input stream. It recovers the
- * original frames.
- * The input stream doesn't need to be framed
- */
-struct sk_buff *
-isdn_v110_decode(isdn_v110_stream *v, struct sk_buff *skb)
-{
-       int i;
-       int j;
-       int len;
-       unsigned char *v110_buf;
-       unsigned char *rbuf;
-
-       if (!skb) {
-               printk(KERN_WARNING "isdn_v110_decode called with NULL skb!\n");
-               return NULL;
-       }
-       rbuf = skb->data;
-       len = skb->len;
-       if (v == NULL) {
-               /* invalid handle, no chance to proceed */
-               printk(KERN_WARNING "isdn_v110_decode called with NULL stream!\n");
-               dev_kfree_skb(skb);
-               return NULL;
-       }
-       if (v->decodelen == 0)  /* cache empty?               */
-               for (; len > 0; len--, rbuf++)  /* scan for SyncHeader in buf */
-                       if ((*rbuf & v->key) == 0)
-                               break;  /* found first byte           */
-       if (len == 0) {
-               dev_kfree_skb(skb);
-               return NULL;
-       }
-       /* copy new data to decode-buffer */
-       memcpy(&(v->decodebuf[v->decodelen]), rbuf, len);
-       v->decodelen += len;
-ReSync:
-       if (v->decodelen < v->nbytes) { /* got a new header ? */
-               dev_kfree_skb(skb);
-               return NULL;    /* no, try later      */
-       }
-       if (ValidHeaderBytes(v) != v->nbytes) { /* is that a valid header? */
-               SyncHeader(v);  /* no -> look for header */
-               goto ReSync;
-       }
-       len = (v->decodelen - (v->decodelen % (10 * v->nbytes))) / v->nbytes;
-       if ((v110_buf = kmalloc(len, GFP_ATOMIC)) == NULL) {
-               printk(KERN_WARNING "isdn_v110_decode: Couldn't allocate v110_buf\n");
-               dev_kfree_skb(skb);
-               return NULL;
-       }
-       for (i = 0; i < len; i++) {
-               v110_buf[i] = 0;
-               for (j = 0; j < v->nbytes; j++)
-                       v110_buf[i] |= (v->decodebuf[(i * v->nbytes) + j] & v->key) << (8 - ((j + 1) * v->nbits));
-               v110_buf[i] = FlipBits(v110_buf[i], v->nbits);
-       }
-       v->decodelen = (v->decodelen % (10 * v->nbytes));
-       memcpy(v->decodebuf, &(v->decodebuf[len * v->nbytes]), v->decodelen);
-
-       skb_trim(skb, DecodeMatrix(v, v110_buf, len, skb->data));
-       kfree(v110_buf);
-       if (skb->len)
-               return skb;
-       else {
-               kfree_skb(skb);
-               return NULL;
-       }
-}
-
-/* EncodeMatrix takes input data in buf, len is the bytecount.
-   Data is encoded into v110 frames in m. Return value is the number of
-   matrix-lines generated.
-*/
-static int
-EncodeMatrix(unsigned char *buf, int len, unsigned char *m, int mlen)
-{
-       int line = 0;
-       int i = 0;
-       int mbit = 128;
-       int dbit = 1;
-       int introducer = 3;
-       int ibit[] = {0, 1, 1};
-
-       while ((i < len) && (line < mlen)) {    /* while we still have input data */
-               switch (line % 10) {    /* in which line of the matrix are we? */
-               case 0:
-                       m[line++] = 0x00;       /* line 0 is always 0 */
-                       mbit = 128;     /* go on with the 7th bit */
-                       break;
-               case 5:
-                       m[line++] = 0xbf;       /* line 5 is always 10111111 */
-                       mbit = 128;     /* go on with the 7th bit */
-                       break;
-               }
-               if (line >= mlen) {
-                       printk(KERN_WARNING "isdn_v110 (EncodeMatrix): buffer full!\n");
-                       return line;
-               }
-       next_bit:
-               switch (mbit) { /* leftmost or rightmost bit ? */
-               case 1:
-                       line++; /* rightmost -> go to next line */
-                       if (line >= mlen) {
-                               printk(KERN_WARNING "isdn_v110 (EncodeMatrix): buffer full!\n");
-                               return line;
-                       }
-                       /* fall through */
-               case 128:
-                       m[line] = 128;  /* leftmost -> set byte to 1000000 */
-                       mbit = 64;      /* current bit in the matrix line */
-                       continue;
-               }
-               if (introducer) {       /* set 110 sequence ? */
-                       introducer--;   /* set on digit less */
-                       m[line] |= ibit[introducer] ? mbit : 0; /* set corresponding bit */
-                       mbit >>= 1;     /* bit of matrix line  >> 1 */
-                       goto next_bit;  /* and go on there */
-               }               /* else push data bits into the matrix! */
-               m[line] |= (buf[i] & dbit) ? mbit : 0;  /* set data bit in matrix */
-               if (dbit == 128) {      /* was it the last one? */
-                       dbit = 1;       /* then go on with first bit of  */
-                       i++;            /* next byte in input buffer */
-                       if (i < len)    /* input buffer done ? */
-                               introducer = 3; /* no, write introducer 110 */
-                       else {  /* input buffer done ! */
-                               m[line] |= (mbit - 1) & 0xfe;   /* set remaining bits in line to 1 */
-                               break;
-                       }
-               } else          /* not the last data bit */
-                       dbit <<= 1;     /* then go to next data bit */
-               mbit >>= 1;     /* go to next bit of matrix */
-               goto next_bit;
-
-       }
-       /* if necessary, generate remaining lines of the matrix... */
-       if ((line) && ((line + 10) < mlen))
-               switch (++line % 10) {
-               case 1:
-                       m[line++] = 0xfe;
-                       /* fall through */
-               case 2:
-                       m[line++] = 0xfe;
-                       /* fall through */
-               case 3:
-                       m[line++] = 0xfe;
-                       /* fall through */
-               case 4:
-                       m[line++] = 0xfe;
-                       /* fall through */
-               case 5:
-                       m[line++] = 0xbf;
-                       /* fall through */
-               case 6:
-                       m[line++] = 0xfe;
-                       /* fall through */
-               case 7:
-                       m[line++] = 0xfe;
-                       /* fall through */
-               case 8:
-                       m[line++] = 0xfe;
-                       /* fall through */
-               case 9:
-                       m[line++] = 0xfe;
-               }
-       return line;            /* that's how many lines we have */
-}
-
-/*
- * Build a sync frame.
- */
-static struct sk_buff *
-isdn_v110_sync(isdn_v110_stream *v)
-{
-       struct sk_buff *skb;
-
-       if (v == NULL) {
-               /* invalid handle, no chance to proceed */
-               printk(KERN_WARNING "isdn_v110_sync called with NULL stream!\n");
-               return NULL;
-       }
-       if ((skb = dev_alloc_skb(v->framelen + v->skbres))) {
-               skb_reserve(skb, v->skbres);
-               skb_put_data(skb, v->OfflineFrame, v->framelen);
-       }
-       return skb;
-}
-
-/*
- * Build an idle frame.
- */
-static struct sk_buff *
-isdn_v110_idle(isdn_v110_stream *v)
-{
-       struct sk_buff *skb;
-
-       if (v == NULL) {
-               /* invalid handle, no chance to proceed */
-               printk(KERN_WARNING "isdn_v110_sync called with NULL stream!\n");
-               return NULL;
-       }
-       if ((skb = dev_alloc_skb(v->framelen + v->skbres))) {
-               skb_reserve(skb, v->skbres);
-               skb_put_data(skb, v->OnlineFrame, v->framelen);
-       }
-       return skb;
-}
-
-struct sk_buff *
-isdn_v110_encode(isdn_v110_stream *v, struct sk_buff *skb)
-{
-       int i;
-       int j;
-       int rlen;
-       int mlen;
-       int olen;
-       int size;
-       int sval1;
-       int sval2;
-       int nframes;
-       unsigned char *v110buf;
-       unsigned char *rbuf;
-       struct sk_buff *nskb;
-
-       if (v == NULL) {
-               /* invalid handle, no chance to proceed */
-               printk(KERN_WARNING "isdn_v110_encode called with NULL stream!\n");
-               return NULL;
-       }
-       if (!skb) {
-               /* invalid skb, no chance to proceed */
-               printk(KERN_WARNING "isdn_v110_encode called with NULL skb!\n");
-               return NULL;
-       }
-       rlen = skb->len;
-       nframes = (rlen + 3) / 4;
-       v110buf = v->encodebuf;
-       if ((nframes * 40) > v->maxsize) {
-               size = v->maxsize;
-               rlen = v->maxsize / 40;
-       } else
-               size = nframes * 40;
-       if (!(nskb = dev_alloc_skb(size + v->skbres + sizeof(int)))) {
-               printk(KERN_WARNING "isdn_v110_encode: Couldn't alloc skb\n");
-               return NULL;
-       }
-       skb_reserve(nskb, v->skbres + sizeof(int));
-       if (skb->len == 0) {
-               skb_put_data(nskb, v->OnlineFrame, v->framelen);
-               *((int *)skb_push(nskb, sizeof(int))) = 0;
-               return nskb;
-       }
-       mlen = EncodeMatrix(skb->data, rlen, v110buf, size);
-       /* now distribute 2 or 4 bits each to the output stream! */
-       rbuf = skb_put(nskb, size);
-       olen = 0;
-       sval1 = 8 - v->nbits;
-       sval2 = v->key << sval1;
-       for (i = 0; i < mlen; i++) {
-               v110buf[i] = FlipBits(v110buf[i], v->nbits);
-               for (j = 0; j < v->nbytes; j++) {
-                       if (size--)
-                               *rbuf++ = ~v->key | (((v110buf[i] << (j * v->nbits)) & sval2) >> sval1);
-                       else {
-                               printk(KERN_WARNING "isdn_v110_encode: buffers full!\n");
-                               goto buffer_full;
-                       }
-                       olen++;
-               }
-       }
-buffer_full:
-       skb_trim(nskb, olen);
-       *((int *)skb_push(nskb, sizeof(int))) = rlen;
-       return nskb;
-}
-
-int
-isdn_v110_stat_callback(int idx, isdn_ctrl *c)
-{
-       isdn_v110_stream *v = NULL;
-       int i;
-       int ret = 0;
-
-       if (idx < 0)
-               return 0;
-       switch (c->command) {
-       case ISDN_STAT_BSENT:
-               /* Keep the send-queue of the driver filled
-                * with frames:
-                * If number of outstanding frames < 3,
-                * send down an Idle-Frame (or an Sync-Frame, if
-                * v->SyncInit != 0).
-                */
-               if (!(v = dev->v110[idx]))
-                       return 0;
-               atomic_inc(&dev->v110use[idx]);
-               for (i = 0; i * v->framelen < c->parm.length; i++) {
-                       if (v->skbidle > 0) {
-                               v->skbidle--;
-                               ret = 1;
-                       } else {
-                               if (v->skbuser > 0)
-                                       v->skbuser--;
-                               ret = 0;
-                       }
-               }
-               for (i = v->skbuser + v->skbidle; i < 2; i++) {
-                       struct sk_buff *skb;
-                       if (v->SyncInit > 0)
-                               skb = isdn_v110_sync(v);
-                       else
-                               skb = isdn_v110_idle(v);
-                       if (skb) {
-                               if (dev->drv[c->driver]->interface->writebuf_skb(c->driver, c->arg, 1, skb) <= 0) {
-                                       dev_kfree_skb(skb);
-                                       break;
-                               } else {
-                                       if (v->SyncInit)
-                                               v->SyncInit--;
-                                       v->skbidle++;
-                               }
-                       } else
-                               break;
-               }
-               atomic_dec(&dev->v110use[idx]);
-               return ret;
-       case ISDN_STAT_DHUP:
-       case ISDN_STAT_BHUP:
-               while (1) {
-                       atomic_inc(&dev->v110use[idx]);
-                       if (atomic_dec_and_test(&dev->v110use[idx])) {
-                               isdn_v110_close(dev->v110[idx]);
-                               dev->v110[idx] = NULL;
-                               break;
-                       }
-                       mdelay(1);
-               }
-               break;
-       case ISDN_STAT_BCONN:
-               if (dev->v110emu[idx] && (dev->v110[idx] == NULL)) {
-                       int hdrlen = dev->drv[c->driver]->interface->hl_hdrlen;
-                       int maxsize = dev->drv[c->driver]->interface->maxbufsize;
-                       atomic_inc(&dev->v110use[idx]);
-                       switch (dev->v110emu[idx]) {
-                       case ISDN_PROTO_L2_V11096:
-                               dev->v110[idx] = isdn_v110_open(V110_9600, hdrlen, maxsize);
-                               break;
-                       case ISDN_PROTO_L2_V11019:
-                               dev->v110[idx] = isdn_v110_open(V110_19200, hdrlen, maxsize);
-                               break;
-                       case ISDN_PROTO_L2_V11038:
-                               dev->v110[idx] = isdn_v110_open(V110_38400, hdrlen, maxsize);
-                               break;
-                       default:;
-                       }
-                       if ((v = dev->v110[idx])) {
-                               while (v->SyncInit) {
-                                       struct sk_buff *skb = isdn_v110_sync(v);
-                                       if (dev->drv[c->driver]->interface->writebuf_skb(c->driver, c->arg, 1, skb) <= 0) {
-                                               dev_kfree_skb(skb);
-                                               /* Unable to send, try later */
-                                               break;
-                                       }
-                                       v->SyncInit--;
-                                       v->skbidle++;
-                               }
-                       } else
-                               printk(KERN_WARNING "isdn_v110: Couldn't open stream for chan %d\n", idx);
-                       atomic_dec(&dev->v110use[idx]);
-               }
-               break;
-       default:
-               return 0;
-       }
-       return 0;
-}
 
+++ /dev/null
-/* $Id: isdn_v110.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
- *
- * Linux ISDN subsystem, V.110 related functions (linklevel).
- *
- * Copyright by Thomas Pfeiffer (pfeiffer@pds.de)
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#ifndef _isdn_v110_h_
-#define _isdn_v110_h_
-
-/*
- * isdn_v110_encode will take raw data and encode it using V.110
- */
-extern struct sk_buff *isdn_v110_encode(isdn_v110_stream *, struct sk_buff *);
-
-/*
- * isdn_v110_decode receives V.110 coded data from the stream and rebuilds
- * frames from them. The source stream doesn't need to be framed.
- */
-extern struct sk_buff *isdn_v110_decode(isdn_v110_stream *, struct sk_buff *);
-
-extern int isdn_v110_stat_callback(int, isdn_ctrl *);
-extern void isdn_v110_close(isdn_v110_stream *v);
-
-#endif
 
+++ /dev/null
-/* $Id: isdn_x25iface.c,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
- *
- * Linux ISDN subsystem, X.25 related functions
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- * stuff needed to support the Linux X.25 PLP code on top of devices that
- * can provide a lab_b service using the concap_proto mechanism.
- * This module supports a network interface which provides lapb_sematics
- * -- as defined in Documentation/networking/x25-iface.txt -- to
- * the upper layer and assumes that the lower layer provides a reliable
- * data link service by means of the concap_device_ops callbacks.
- *
- * Only protocol specific stuff goes here. Device specific stuff
- * goes to another -- device related -- concap_proto support source file.
- *
- */
-
-/* #include <linux/isdn.h> */
-#include <linux/netdevice.h>
-#include <linux/concap.h>
-#include <linux/slab.h>
-#include <linux/wanrouter.h>
-#include <net/x25device.h>
-#include "isdn_x25iface.h"
-
-/* for debugging messages not to cause an oops when device pointer is NULL*/
-#define MY_DEVNAME(dev)  ((dev) ? (dev)->name : "DEVICE UNSPECIFIED")
-
-
-typedef struct isdn_x25iface_proto_data {
-       int magic;
-       enum wan_states state;
-       /* Private stuff, not to be accessed via proto_data. We provide the
-          other storage for the concap_proto instance here as well,
-          enabling us to allocate both with just one kmalloc(): */
-       struct concap_proto priv;
-} ix25_pdata_t;
-
-
-
-/* is now in header file (extern): struct concap_proto * isdn_x25iface_proto_new(void); */
-static void isdn_x25iface_proto_del(struct concap_proto *);
-static int isdn_x25iface_proto_close(struct concap_proto *);
-static int isdn_x25iface_proto_restart(struct concap_proto *,
-                                      struct net_device *,
-                                      struct concap_device_ops *);
-static int isdn_x25iface_xmit(struct concap_proto *, struct sk_buff *);
-static int isdn_x25iface_receive(struct concap_proto *, struct sk_buff *);
-static int isdn_x25iface_connect_ind(struct concap_proto *);
-static int isdn_x25iface_disconn_ind(struct concap_proto *);
-
-
-static struct concap_proto_ops ix25_pops = {
-       .proto_new = &isdn_x25iface_proto_new,
-       .proto_del = &isdn_x25iface_proto_del,
-       .restart = &isdn_x25iface_proto_restart,
-       .close = &isdn_x25iface_proto_close,
-       .encap_and_xmit = &isdn_x25iface_xmit,
-       .data_ind = &isdn_x25iface_receive,
-       .connect_ind = &isdn_x25iface_connect_ind,
-       .disconn_ind = &isdn_x25iface_disconn_ind
-};
-
-/* error message helper function */
-static void illegal_state_warn(unsigned state, unsigned char firstbyte)
-{
-       printk(KERN_WARNING "isdn_x25iface: firstbyte %x illegal in"
-              "current state %d\n", firstbyte, state);
-}
-
-/* check protocol data field for consistency */
-static int pdata_is_bad(ix25_pdata_t *pda) {
-
-       if (pda  &&  pda->magic == ISDN_X25IFACE_MAGIC) return 0;
-       printk(KERN_WARNING
-              "isdn_x25iface_xxx: illegal pointer to proto data\n");
-       return 1;
-}
-
-/* create a new x25 interface protocol instance
- */
-struct concap_proto *isdn_x25iface_proto_new(void)
-{
-       ix25_pdata_t *tmp = kmalloc(sizeof(ix25_pdata_t), GFP_KERNEL);
-       IX25DEBUG("isdn_x25iface_proto_new\n");
-       if (tmp) {
-               tmp->magic = ISDN_X25IFACE_MAGIC;
-               tmp->state = WAN_UNCONFIGURED;
-               /* private data space used to hold the concap_proto data.
-                  Only to be accessed via the returned pointer */
-               spin_lock_init(&tmp->priv.lock);
-               tmp->priv.dops       = NULL;
-               tmp->priv.net_dev    = NULL;
-               tmp->priv.pops       = &ix25_pops;
-               tmp->priv.flags      = 0;
-               tmp->priv.proto_data = tmp;
-               return (&(tmp->priv));
-       }
-       return NULL;
-};
-
-/* close the x25iface encapsulation protocol
- */
-static int isdn_x25iface_proto_close(struct concap_proto *cprot) {
-
-       ix25_pdata_t *tmp;
-       int ret = 0;
-       ulong flags;
-
-       if (!cprot) {
-               printk(KERN_ERR "isdn_x25iface_proto_close: "
-                      "invalid concap_proto pointer\n");
-               return -1;
-       }
-       IX25DEBUG("isdn_x25iface_proto_close %s \n", MY_DEVNAME(cprot->net_dev));
-       spin_lock_irqsave(&cprot->lock, flags);
-       cprot->dops    = NULL;
-       cprot->net_dev = NULL;
-       tmp = cprot->proto_data;
-       if (pdata_is_bad(tmp)) {
-               ret = -1;
-       } else {
-               tmp->state = WAN_UNCONFIGURED;
-       }
-       spin_unlock_irqrestore(&cprot->lock, flags);
-       return ret;
-}
-
-/* Delete the x25iface encapsulation protocol instance
- */
-static void isdn_x25iface_proto_del(struct concap_proto *cprot) {
-
-       ix25_pdata_t *tmp;
-
-       IX25DEBUG("isdn_x25iface_proto_del \n");
-       if (!cprot) {
-               printk(KERN_ERR "isdn_x25iface_proto_del: "
-                      "concap_proto pointer is NULL\n");
-               return;
-       }
-       tmp = cprot->proto_data;
-       if (tmp == NULL) {
-               printk(KERN_ERR "isdn_x25iface_proto_del: inconsistent "
-                      "proto_data pointer (maybe already deleted?)\n");
-               return;
-       }
-       /* close if the protocol is still open */
-       if (cprot->dops) isdn_x25iface_proto_close(cprot);
-       /* freeing the storage should be sufficient now. But some additional
-          settings might help to catch wild pointer bugs */
-       tmp->magic = 0;
-       cprot->proto_data = NULL;
-
-       kfree(tmp);
-       return;
-}
-
-/* (re-)initialize the data structures for x25iface encapsulation
- */
-static int isdn_x25iface_proto_restart(struct concap_proto *cprot,
-                                      struct net_device *ndev,
-                                      struct concap_device_ops *dops)
-{
-       ix25_pdata_t *pda = cprot->proto_data;
-       ulong flags;
-
-       IX25DEBUG("isdn_x25iface_proto_restart %s \n", MY_DEVNAME(ndev));
-
-       if (pdata_is_bad(pda)) return -1;
-
-       if (!(dops && dops->data_req && dops->connect_req
-             && dops->disconn_req)) {
-               printk(KERN_WARNING "isdn_x25iface_restart: required dops"
-                      " missing\n");
-               isdn_x25iface_proto_close(cprot);
-               return -1;
-       }
-       spin_lock_irqsave(&cprot->lock, flags);
-       cprot->net_dev = ndev;
-       cprot->pops = &ix25_pops;
-       cprot->dops = dops;
-       pda->state = WAN_DISCONNECTED;
-       spin_unlock_irqrestore(&cprot->lock, flags);
-       return 0;
-}
-
-/* deliver a dl_data frame received from i4l HL driver to the network layer
- */
-static int isdn_x25iface_receive(struct concap_proto *cprot, struct sk_buff *skb)
-{
-       IX25DEBUG("isdn_x25iface_receive %s \n", MY_DEVNAME(cprot->net_dev));
-       if (((ix25_pdata_t *)(cprot->proto_data))
-           ->state == WAN_CONNECTED) {
-               if (skb_push(skb, 1)) {
-                       skb->data[0] = X25_IFACE_DATA;
-                       skb->protocol = x25_type_trans(skb, cprot->net_dev);
-                       netif_rx(skb);
-                       return 0;
-               }
-       }
-       printk(KERN_WARNING "isdn_x25iface_receive %s: not connected, skb dropped\n", MY_DEVNAME(cprot->net_dev));
-       dev_kfree_skb(skb);
-       return -1;
-}
-
-/* a connection set up is indicated by lower layer
- */
-static int isdn_x25iface_connect_ind(struct concap_proto *cprot)
-{
-       struct sk_buff *skb;
-       enum wan_states *state_p
-               = &(((ix25_pdata_t *)(cprot->proto_data))->state);
-       IX25DEBUG("isdn_x25iface_connect_ind %s \n"
-                 , MY_DEVNAME(cprot->net_dev));
-       if (*state_p == WAN_UNCONFIGURED) {
-               printk(KERN_WARNING
-                      "isdn_x25iface_connect_ind while unconfigured %s\n"
-                      , MY_DEVNAME(cprot->net_dev));
-               return -1;
-       }
-       *state_p = WAN_CONNECTED;
-
-       skb = dev_alloc_skb(1);
-       if (skb) {
-               skb_put_u8(skb, X25_IFACE_CONNECT);
-               skb->protocol = x25_type_trans(skb, cprot->net_dev);
-               netif_rx(skb);
-               return 0;
-       } else {
-               printk(KERN_WARNING "isdn_x25iface_connect_ind: "
-                      " out of memory -- disconnecting\n");
-               cprot->dops->disconn_req(cprot);
-               return -1;
-       }
-}
-
-/* a disconnect is indicated by lower layer
- */
-static int isdn_x25iface_disconn_ind(struct concap_proto *cprot)
-{
-       struct sk_buff *skb;
-       enum wan_states *state_p
-               = &(((ix25_pdata_t *)(cprot->proto_data))->state);
-       IX25DEBUG("isdn_x25iface_disconn_ind %s \n", MY_DEVNAME(cprot->net_dev));
-       if (*state_p == WAN_UNCONFIGURED) {
-               printk(KERN_WARNING
-                      "isdn_x25iface_disconn_ind while unconfigured\n");
-               return -1;
-       }
-       if (!cprot->net_dev) return -1;
-       *state_p = WAN_DISCONNECTED;
-       skb = dev_alloc_skb(1);
-       if (skb) {
-               skb_put_u8(skb, X25_IFACE_DISCONNECT);
-               skb->protocol = x25_type_trans(skb, cprot->net_dev);
-               netif_rx(skb);
-               return 0;
-       } else {
-               printk(KERN_WARNING "isdn_x25iface_disconn_ind:"
-                      " out of memory\n");
-               return -1;
-       }
-}
-
-/* process a frame handed over to us from linux network layer. First byte
-   semantics as defined in Documentation/networking/x25-iface.txt
-*/
-static int isdn_x25iface_xmit(struct concap_proto *cprot, struct sk_buff *skb)
-{
-       unsigned char firstbyte = skb->data[0];
-       enum wan_states *state = &((ix25_pdata_t *)cprot->proto_data)->state;
-       int ret = 0;
-       IX25DEBUG("isdn_x25iface_xmit: %s first=%x state=%d\n",
-                 MY_DEVNAME(cprot->net_dev), firstbyte, *state);
-       switch (firstbyte) {
-       case X25_IFACE_DATA:
-               if (*state == WAN_CONNECTED) {
-                       skb_pull(skb, 1);
-                       netif_trans_update(cprot->net_dev);
-                       ret = (cprot->dops->data_req(cprot, skb));
-                       /* prepare for future retransmissions */
-                       if (ret) skb_push(skb, 1);
-                       return ret;
-               }
-               illegal_state_warn(*state, firstbyte);
-               break;
-       case X25_IFACE_CONNECT:
-               if (*state == WAN_DISCONNECTED) {
-                       *state = WAN_CONNECTING;
-                       ret = cprot->dops->connect_req(cprot);
-                       if (ret) {
-                               /* reset state and notify upper layer about
-                                * immidiatly failed attempts */
-                               isdn_x25iface_disconn_ind(cprot);
-                       }
-               } else {
-                       illegal_state_warn(*state, firstbyte);
-               }
-               break;
-       case X25_IFACE_DISCONNECT:
-               switch (*state) {
-               case WAN_DISCONNECTED:
-                       /* Should not happen. However, give upper layer a
-                          chance to recover from inconstistency  but don't
-                          trust the lower layer sending the disconn_confirm
-                          when already disconnected */
-                       printk(KERN_WARNING "isdn_x25iface_xmit: disconnect "
-                              " requested while disconnected\n");
-                       isdn_x25iface_disconn_ind(cprot);
-                       break; /* prevent infinite loops */
-               case WAN_CONNECTING:
-               case WAN_CONNECTED:
-                       *state = WAN_DISCONNECTED;
-                       cprot->dops->disconn_req(cprot);
-                       break;
-               default:
-                       illegal_state_warn(*state, firstbyte);
-               }
-               break;
-       case X25_IFACE_PARAMS:
-               printk(KERN_WARNING "isdn_x25iface_xmit: setting of lapb"
-                      " options not yet supported\n");
-               break;
-       default:
-               printk(KERN_WARNING "isdn_x25iface_xmit: frame with illegal"
-                      " first byte %x ignored:\n", firstbyte);
-       }
-       dev_kfree_skb(skb);
-       return 0;
-}
 
+++ /dev/null
-/* $Id: isdn_x25iface.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
- *
- * header for Linux ISDN subsystem, x.25 related functions
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#ifndef _LINUX_ISDN_X25IFACE_H
-#define _LINUX_ISDN_X25IFACE_H
-
-#define ISDN_X25IFACE_MAGIC 0x1e75a2b9
-/* #define DEBUG_ISDN_X25 if you want isdn_x25 debugging messages */
-#ifdef DEBUG_ISDN_X25
-#   define IX25DEBUG(fmt, args...) printk(KERN_DEBUG fmt, ##args)
-#else
-#   define IX25DEBUG(fmt, args...)
-#endif
-
-#include <linux/skbuff.h>
-#include <linux/isdn.h>
-#include <linux/concap.h>
-
-extern struct concap_proto_ops *isdn_x25iface_concap_proto_ops_pt;
-extern struct concap_proto *isdn_x25iface_proto_new(void);
-
-
-
-#endif
 
+++ /dev/null
-# SPDX-License-Identifier: GPL-2.0-only
-# Makefile for the isdnloop ISDN device driver
-
-# Each configuration option enables a list of files.
-
-obj-$(CONFIG_ISDN_DRV_LOOP)    += isdnloop.o
 
+++ /dev/null
-/* $Id: isdnloop.c,v 1.11.6.7 2001/11/11 19:54:31 kai Exp $
- *
- * ISDN low-level module implementing a dummy loop driver.
- *
- * Copyright 1997 by Fritz Elfert (fritz@isdn4linux.de)
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include "isdnloop.h"
-
-static char *isdnloop_id = "loop0";
-
-MODULE_DESCRIPTION("ISDN4Linux: Pseudo Driver that simulates an ISDN card");
-MODULE_AUTHOR("Fritz Elfert");
-MODULE_LICENSE("GPL");
-module_param(isdnloop_id, charp, 0);
-MODULE_PARM_DESC(isdnloop_id, "ID-String of first card");
-
-static int isdnloop_addcard(char *);
-
-/*
- * Free queue completely.
- *
- * Parameter:
- *   card    = pointer to card struct
- *   channel = channel number
- */
-static void
-isdnloop_free_queue(isdnloop_card *card, int channel)
-{
-       struct sk_buff_head *queue = &card->bqueue[channel];
-
-       skb_queue_purge(queue);
-       card->sndcount[channel] = 0;
-}
-
-/*
- * Send B-Channel data to another virtual card.
- * This routine is called via timer-callback from isdnloop_pollbchan().
- *
- * Parameter:
- *   card = pointer to card struct.
- *   ch   = channel number (0-based)
- */
-static void
-isdnloop_bchan_send(isdnloop_card *card, int ch)
-{
-       isdnloop_card *rcard = card->rcard[ch];
-       int rch = card->rch[ch], len, ack;
-       struct sk_buff *skb;
-       isdn_ctrl cmd;
-
-       while (card->sndcount[ch]) {
-               skb = skb_dequeue(&card->bqueue[ch]);
-               if (skb) {
-                       len = skb->len;
-                       card->sndcount[ch] -= len;
-                       ack = *(skb->head); /* used as scratch area */
-                       cmd.driver = card->myid;
-                       cmd.arg = ch;
-                       if (rcard) {
-                               rcard->interface.rcvcallb_skb(rcard->myid, rch, skb);
-                       } else {
-                               printk(KERN_WARNING "isdnloop: no rcard, skb dropped\n");
-                               dev_kfree_skb(skb);
-
-                       }
-                       cmd.command = ISDN_STAT_BSENT;
-                       cmd.parm.length = len;
-                       card->interface.statcallb(&cmd);
-               } else
-                       card->sndcount[ch] = 0;
-       }
-}
-
-/*
- * Send/Receive Data to/from the B-Channel.
- * This routine is called via timer-callback.
- * It schedules itself while any B-Channel is open.
- *
- * Parameter:
- *   data = pointer to card struct, set by kernel timer.data
- */
-static void
-isdnloop_pollbchan(struct timer_list *t)
-{
-       isdnloop_card *card = from_timer(card, t, rb_timer);
-       unsigned long flags;
-
-       if (card->flags & ISDNLOOP_FLAGS_B1ACTIVE)
-               isdnloop_bchan_send(card, 0);
-       if (card->flags & ISDNLOOP_FLAGS_B2ACTIVE)
-               isdnloop_bchan_send(card, 1);
-       if (card->flags & (ISDNLOOP_FLAGS_B1ACTIVE | ISDNLOOP_FLAGS_B2ACTIVE)) {
-               /* schedule b-channel polling again */
-               spin_lock_irqsave(&card->isdnloop_lock, flags);
-               card->rb_timer.expires = jiffies + ISDNLOOP_TIMER_BCREAD;
-               add_timer(&card->rb_timer);
-               card->flags |= ISDNLOOP_FLAGS_RBTIMER;
-               spin_unlock_irqrestore(&card->isdnloop_lock, flags);
-       } else
-               card->flags &= ~ISDNLOOP_FLAGS_RBTIMER;
-}
-
-/*
- * Parse ICN-type setup string and fill fields of setup-struct
- * with parsed data.
- *
- * Parameter:
- *   setup = setup string, format: [caller-id],si1,si2,[called-id]
- *   cmd   = pointer to struct to be filled.
- */
-static void
-isdnloop_parse_setup(char *setup, isdn_ctrl *cmd)
-{
-       char *t = setup;
-       char *s = strchr(t, ',');
-
-       *s++ = '\0';
-       strlcpy(cmd->parm.setup.phone, t, sizeof(cmd->parm.setup.phone));
-       s = strchr(t = s, ',');
-       *s++ = '\0';
-       if (!strlen(t))
-               cmd->parm.setup.si1 = 0;
-       else
-               cmd->parm.setup.si1 = simple_strtoul(t, NULL, 10);
-       s = strchr(t = s, ',');
-       *s++ = '\0';
-       if (!strlen(t))
-               cmd->parm.setup.si2 = 0;
-       else
-               cmd->parm.setup.si2 =
-                       simple_strtoul(t, NULL, 10);
-       strlcpy(cmd->parm.setup.eazmsn, s, sizeof(cmd->parm.setup.eazmsn));
-       cmd->parm.setup.plan = 0;
-       cmd->parm.setup.screen = 0;
-}
-
-typedef struct isdnloop_stat {
-       char *statstr;
-       int command;
-       int action;
-} isdnloop_stat;
-/* *INDENT-OFF* */
-static isdnloop_stat isdnloop_stat_table[] = {
-       {"BCON_",          ISDN_STAT_BCONN, 1}, /* B-Channel connected        */
-       {"BDIS_",          ISDN_STAT_BHUP,  2}, /* B-Channel disconnected     */
-       {"DCON_",          ISDN_STAT_DCONN, 0}, /* D-Channel connected        */
-       {"DDIS_",          ISDN_STAT_DHUP,  0}, /* D-Channel disconnected     */
-       {"DCAL_I",         ISDN_STAT_ICALL, 3}, /* Incoming call dialup-line  */
-       {"DSCA_I",         ISDN_STAT_ICALL, 3}, /* Incoming call 1TR6-SPV     */
-       {"FCALL",          ISDN_STAT_ICALL, 4}, /* Leased line connection up  */
-       {"CIF",            ISDN_STAT_CINF,  5}, /* Charge-info, 1TR6-type     */
-       {"AOC",            ISDN_STAT_CINF,  6}, /* Charge-info, DSS1-type     */
-       {"CAU",            ISDN_STAT_CAUSE, 7}, /* Cause code                 */
-       {"TEI OK",         ISDN_STAT_RUN,   0}, /* Card connected to wallplug */
-       {"E_L1: ACT FAIL", ISDN_STAT_BHUP,  8}, /* Layer-1 activation failed  */
-       {"E_L2: DATA LIN", ISDN_STAT_BHUP,  8}, /* Layer-2 data link lost     */
-       {"E_L1: ACTIVATION FAILED",
-        ISDN_STAT_BHUP,  8},         /* Layer-1 activation failed  */
-       {NULL, 0, -1}
-};
-/* *INDENT-ON* */
-
-
-/*
- * Parse Status message-strings from virtual card.
- * Depending on status, call statcallb for sending messages to upper
- * levels. Also set/reset B-Channel active-flags.
- *
- * Parameter:
- *   status  = status string to parse.
- *   channel = channel where message comes from.
- *   card    = card where message comes from.
- */
-static void
-isdnloop_parse_status(u_char *status, int channel, isdnloop_card *card)
-{
-       isdnloop_stat *s = isdnloop_stat_table;
-       int action = -1;
-       isdn_ctrl cmd;
-
-       while (s->statstr) {
-               if (!strncmp(status, s->statstr, strlen(s->statstr))) {
-                       cmd.command = s->command;
-                       action = s->action;
-                       break;
-               }
-               s++;
-       }
-       if (action == -1)
-               return;
-       cmd.driver = card->myid;
-       cmd.arg = channel;
-       switch (action) {
-       case 1:
-               /* BCON_x */
-               card->flags |= (channel) ?
-                       ISDNLOOP_FLAGS_B2ACTIVE : ISDNLOOP_FLAGS_B1ACTIVE;
-               break;
-       case 2:
-               /* BDIS_x */
-               card->flags &= ~((channel) ?
-                                ISDNLOOP_FLAGS_B2ACTIVE : ISDNLOOP_FLAGS_B1ACTIVE);
-               isdnloop_free_queue(card, channel);
-               break;
-       case 3:
-               /* DCAL_I and DSCA_I */
-               isdnloop_parse_setup(status + 6, &cmd);
-               break;
-       case 4:
-               /* FCALL */
-               sprintf(cmd.parm.setup.phone, "LEASED%d", card->myid);
-               sprintf(cmd.parm.setup.eazmsn, "%d", channel + 1);
-               cmd.parm.setup.si1 = 7;
-               cmd.parm.setup.si2 = 0;
-               cmd.parm.setup.plan = 0;
-               cmd.parm.setup.screen = 0;
-               break;
-       case 5:
-               /* CIF */
-               strlcpy(cmd.parm.num, status + 3, sizeof(cmd.parm.num));
-               break;
-       case 6:
-               /* AOC */
-               snprintf(cmd.parm.num, sizeof(cmd.parm.num), "%d",
-                        (int) simple_strtoul(status + 7, NULL, 16));
-               break;
-       case 7:
-               /* CAU */
-               status += 3;
-               if (strlen(status) == 4)
-                       snprintf(cmd.parm.num, sizeof(cmd.parm.num), "%s%c%c",
-                                status + 2, *status, *(status + 1));
-               else
-                       strlcpy(cmd.parm.num, status + 1, sizeof(cmd.parm.num));
-               break;
-       case 8:
-               /* Misc Errors on L1 and L2 */
-               card->flags &= ~ISDNLOOP_FLAGS_B1ACTIVE;
-               isdnloop_free_queue(card, 0);
-               cmd.arg = 0;
-               cmd.driver = card->myid;
-               card->interface.statcallb(&cmd);
-               cmd.command = ISDN_STAT_DHUP;
-               cmd.arg = 0;
-               cmd.driver = card->myid;
-               card->interface.statcallb(&cmd);
-               cmd.command = ISDN_STAT_BHUP;
-               card->flags &= ~ISDNLOOP_FLAGS_B2ACTIVE;
-               isdnloop_free_queue(card, 1);
-               cmd.arg = 1;
-               cmd.driver = card->myid;
-               card->interface.statcallb(&cmd);
-               cmd.command = ISDN_STAT_DHUP;
-               cmd.arg = 1;
-               cmd.driver = card->myid;
-               break;
-       }
-       card->interface.statcallb(&cmd);
-}
-
-/*
- * Store a cwcharacter into ringbuffer for reading from /dev/isdnctrl
- *
- * Parameter:
- *   card = pointer to card struct.
- *   c    = char to store.
- */
-static void
-isdnloop_putmsg(isdnloop_card *card, unsigned char c)
-{
-       ulong flags;
-
-       spin_lock_irqsave(&card->isdnloop_lock, flags);
-       *card->msg_buf_write++ = (c == 0xff) ? '\n' : c;
-       if (card->msg_buf_write == card->msg_buf_read) {
-               if (++card->msg_buf_read > card->msg_buf_end)
-                       card->msg_buf_read = card->msg_buf;
-       }
-       if (card->msg_buf_write > card->msg_buf_end)
-               card->msg_buf_write = card->msg_buf;
-       spin_unlock_irqrestore(&card->isdnloop_lock, flags);
-}
-
-/*
- * Poll a virtual cards message queue.
- * If there are new status-replies from the card, copy them to
- * ringbuffer for reading on /dev/isdnctrl and call
- * isdnloop_parse_status() for processing them. Watch for special
- * Firmware bootmessage and parse it, to get the D-Channel protocol.
- * If there are B-Channels open, initiate a timer-callback to
- * isdnloop_pollbchan().
- * This routine is called periodically via timer interrupt.
- *
- * Parameter:
- *   data = pointer to card struct
- */
-static void
-isdnloop_polldchan(struct timer_list *t)
-{
-       isdnloop_card *card = from_timer(card, t, st_timer);
-       struct sk_buff *skb;
-       int avail;
-       int left;
-       u_char c;
-       int ch;
-       unsigned long flags;
-       u_char *p;
-       isdn_ctrl cmd;
-
-       skb = skb_dequeue(&card->dqueue);
-       if (skb)
-               avail = skb->len;
-       else
-               avail = 0;
-       for (left = avail; left > 0; left--) {
-               c = *skb->data;
-               skb_pull(skb, 1);
-               isdnloop_putmsg(card, c);
-               card->imsg[card->iptr] = c;
-               if (card->iptr < 59)
-                       card->iptr++;
-               if (!skb->len) {
-                       avail++;
-                       isdnloop_putmsg(card, '\n');
-                       card->imsg[card->iptr] = 0;
-                       card->iptr = 0;
-                       if (card->imsg[0] == '0' && card->imsg[1] >= '0' &&
-                           card->imsg[1] <= '2' && card->imsg[2] == ';') {
-                               ch = (card->imsg[1] - '0') - 1;
-                               p = &card->imsg[3];
-                               isdnloop_parse_status(p, ch, card);
-                       } else {
-                               p = card->imsg;
-                               if (!strncmp(p, "DRV1.", 5)) {
-                                       printk(KERN_INFO "isdnloop: (%s) %s\n", CID, p);
-                                       if (!strncmp(p + 7, "TC", 2)) {
-                                               card->ptype = ISDN_PTYPE_1TR6;
-                                               card->interface.features |= ISDN_FEATURE_P_1TR6;
-                                               printk(KERN_INFO
-                                                      "isdnloop: (%s) 1TR6-Protocol loaded and running\n", CID);
-                                       }
-                                       if (!strncmp(p + 7, "EC", 2)) {
-                                               card->ptype = ISDN_PTYPE_EURO;
-                                               card->interface.features |= ISDN_FEATURE_P_EURO;
-                                               printk(KERN_INFO
-                                                      "isdnloop: (%s) Euro-Protocol loaded and running\n", CID);
-                                       }
-                                       continue;
-
-                               }
-                       }
-               }
-       }
-       if (avail) {
-               cmd.command = ISDN_STAT_STAVAIL;
-               cmd.driver = card->myid;
-               cmd.arg = avail;
-               card->interface.statcallb(&cmd);
-       }
-       if (card->flags & (ISDNLOOP_FLAGS_B1ACTIVE | ISDNLOOP_FLAGS_B2ACTIVE))
-               if (!(card->flags & ISDNLOOP_FLAGS_RBTIMER)) {
-                       /* schedule b-channel polling */
-                       card->flags |= ISDNLOOP_FLAGS_RBTIMER;
-                       spin_lock_irqsave(&card->isdnloop_lock, flags);
-                       del_timer(&card->rb_timer);
-                       card->rb_timer.expires = jiffies + ISDNLOOP_TIMER_BCREAD;
-                       add_timer(&card->rb_timer);
-                       spin_unlock_irqrestore(&card->isdnloop_lock, flags);
-               }
-       /* schedule again */
-       spin_lock_irqsave(&card->isdnloop_lock, flags);
-       card->st_timer.expires = jiffies + ISDNLOOP_TIMER_DCREAD;
-       add_timer(&card->st_timer);
-       spin_unlock_irqrestore(&card->isdnloop_lock, flags);
-}
-
-/*
- * Append a packet to the transmit buffer-queue.
- *
- * Parameter:
- *   channel = Number of B-channel
- *   skb     = packet to send.
- *   card    = pointer to card-struct
- * Return:
- *   Number of bytes transferred, -E??? on error
- */
-static int
-isdnloop_sendbuf(int channel, struct sk_buff *skb, isdnloop_card *card)
-{
-       int len = skb->len;
-       unsigned long flags;
-       struct sk_buff *nskb;
-
-       if (len > 4000) {
-               printk(KERN_WARNING
-                      "isdnloop: Send packet too large\n");
-               return -EINVAL;
-       }
-       if (len) {
-               if (!(card->flags & (channel ? ISDNLOOP_FLAGS_B2ACTIVE : ISDNLOOP_FLAGS_B1ACTIVE)))
-                       return 0;
-               if (card->sndcount[channel] > ISDNLOOP_MAX_SQUEUE)
-                       return 0;
-               spin_lock_irqsave(&card->isdnloop_lock, flags);
-               nskb = dev_alloc_skb(skb->len);
-               if (nskb) {
-                       skb_copy_from_linear_data(skb,
-                                                 skb_put(nskb, len), len);
-                       skb_queue_tail(&card->bqueue[channel], nskb);
-                       dev_kfree_skb(skb);
-               } else
-                       len = 0;
-               card->sndcount[channel] += len;
-               spin_unlock_irqrestore(&card->isdnloop_lock, flags);
-       }
-       return len;
-}
-
-/*
- * Read the messages from the card's ringbuffer
- *
- * Parameter:
- *   buf  = pointer to buffer.
- *   len  = number of bytes to read.
- *   user = flag, 1: called from userlevel 0: called from kernel.
- *   card = pointer to card struct.
- * Return:
- *   number of bytes actually transferred.
- */
-static int
-isdnloop_readstatus(u_char __user *buf, int len, isdnloop_card *card)
-{
-       int count;
-       u_char __user *p;
-
-       for (p = buf, count = 0; count < len; p++, count++) {
-               if (card->msg_buf_read == card->msg_buf_write)
-                       return count;
-               if (put_user(*card->msg_buf_read++, p))
-                       return -EFAULT;
-               if (card->msg_buf_read > card->msg_buf_end)
-                       card->msg_buf_read = card->msg_buf;
-       }
-       return count;
-}
-
-/*
- * Simulate a card's response by appending it to the cards
- * message queue.
- *
- * Parameter:
- *   card = pointer to card struct.
- *   s    = pointer to message-string.
- *   ch   = channel: 0 = generic messages, 1 and 2 = D-channel messages.
- * Return:
- *   0 on success, 1 on memory squeeze.
- */
-static int
-isdnloop_fake(isdnloop_card *card, char *s, int ch)
-{
-       struct sk_buff *skb;
-       int len = strlen(s) + ((ch >= 0) ? 3 : 0);
-       skb = dev_alloc_skb(len);
-       if (!skb) {
-               printk(KERN_WARNING "isdnloop: Out of memory in isdnloop_fake\n");
-               return 1;
-       }
-       if (ch >= 0)
-               sprintf(skb_put(skb, 3), "%02d;", ch);
-       skb_put_data(skb, s, strlen(s));
-       skb_queue_tail(&card->dqueue, skb);
-       return 0;
-}
-/* *INDENT-OFF* */
-static isdnloop_stat isdnloop_cmd_table[] = {
-       {"BCON_R",         0,  1},      /* B-Channel connect        */
-       {"BCON_I",         0, 17},      /* B-Channel connect ind    */
-       {"BDIS_R",         0,  2},      /* B-Channel disconnect     */
-       {"DDIS_R",         0,  3},      /* D-Channel disconnect     */
-       {"DCON_R",         0, 16},      /* D-Channel connect        */
-       {"DSCA_R",         0,  4},      /* Dial 1TR6-SPV     */
-       {"DCAL_R",         0,  5},      /* Dial */
-       {"EAZC",           0,  6},      /* Clear EAZ listener */
-       {"EAZ",            0,  7},      /* Set EAZ listener */
-       {"SEEAZ",          0,  8},      /* Get EAZ listener */
-       {"MSN",            0,  9},      /* Set/Clear MSN listener */
-       {"MSALL",          0, 10},      /* Set multi MSN listeners */
-       {"SETSIL",         0, 11},      /* Set SI list     */
-       {"SEESIL",         0, 12},      /* Get SI list     */
-       {"SILC",           0, 13},      /* Clear SI list     */
-       {"LOCK",           0, -1},      /* LOCK channel     */
-       {"UNLOCK",         0, -1},      /* UNLOCK channel     */
-       {"FV2ON",          1, 14},      /* Leased mode on               */
-       {"FV2OFF",         1, 15},      /* Leased mode off              */
-       {NULL, 0, -1}
-};
-/* *INDENT-ON* */
-
-
-/*
- * Simulate an error-response from a card.
- *
- * Parameter:
- *   card = pointer to card struct.
- */
-static void
-isdnloop_fake_err(isdnloop_card *card)
-{
-       char buf[64];
-
-       snprintf(buf, sizeof(buf), "E%s", card->omsg);
-       isdnloop_fake(card, buf, -1);
-       isdnloop_fake(card, "NAK", -1);
-}
-
-static u_char ctable_eu[] = {0x00, 0x11, 0x01, 0x12};
-static u_char ctable_1t[] = {0x00, 0x3b, 0x01, 0x3a};
-
-/*
- * Assemble a simplified cause message depending on the
- * D-channel protocol used.
- *
- * Parameter:
- *   card = pointer to card struct.
- *   loc  = location: 0 = local, 1 = remote.
- *   cau  = cause: 1 = busy, 2 = nonexistent callerid, 3 = no user responding.
- * Return:
- *   Pointer to buffer containing the assembled message.
- */
-static char *
-isdnloop_unicause(isdnloop_card *card, int loc, int cau)
-{
-       static char buf[6];
-
-       switch (card->ptype) {
-       case ISDN_PTYPE_EURO:
-               sprintf(buf, "E%02X%02X", (loc) ? 4 : 2, ctable_eu[cau]);
-               break;
-       case ISDN_PTYPE_1TR6:
-               sprintf(buf, "%02X44", ctable_1t[cau]);
-               break;
-       default:
-               return "0000";
-       }
-       return buf;
-}
-
-/*
- * Release a virtual connection. Called from timer interrupt, when
- * called party did not respond.
- *
- * Parameter:
- *   card = pointer to card struct.
- *   ch   = channel (0-based)
- */
-static void
-isdnloop_atimeout(isdnloop_card *card, int ch)
-{
-       unsigned long flags;
-       char buf[60];
-
-       spin_lock_irqsave(&card->isdnloop_lock, flags);
-       if (card->rcard[ch]) {
-               isdnloop_fake(card->rcard[ch], "DDIS_I", card->rch[ch] + 1);
-               card->rcard[ch]->rcard[card->rch[ch]] = NULL;
-               card->rcard[ch] = NULL;
-       }
-       isdnloop_fake(card, "DDIS_I", ch + 1);
-       /* No user responding */
-       sprintf(buf, "CAU%s", isdnloop_unicause(card, 1, 3));
-       isdnloop_fake(card, buf, ch + 1);
-       spin_unlock_irqrestore(&card->isdnloop_lock, flags);
-}
-
-/*
- * Wrapper for isdnloop_atimeout().
- */
-static void
-isdnloop_atimeout0(struct timer_list *t)
-{
-       isdnloop_card *card = from_timer(card, t, c_timer[0]);
-
-       isdnloop_atimeout(card, 0);
-}
-
-/*
- * Wrapper for isdnloop_atimeout().
- */
-static void
-isdnloop_atimeout1(struct timer_list *t)
-{
-       isdnloop_card *card = from_timer(card, t, c_timer[1]);
-
-       isdnloop_atimeout(card, 1);
-}
-
-/*
- * Install a watchdog for a user, not responding.
- *
- * Parameter:
- *   card = pointer to card struct.
- *   ch   = channel to watch for.
- */
-static void
-isdnloop_start_ctimer(isdnloop_card *card, int ch)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&card->isdnloop_lock, flags);
-       timer_setup(&card->c_timer[ch], ch ? isdnloop_atimeout1
-                                          : isdnloop_atimeout0, 0);
-       card->c_timer[ch].expires = jiffies + ISDNLOOP_TIMER_ALERTWAIT;
-       add_timer(&card->c_timer[ch]);
-       spin_unlock_irqrestore(&card->isdnloop_lock, flags);
-}
-
-/*
- * Kill a pending channel watchdog.
- *
- * Parameter:
- *   card = pointer to card struct.
- *   ch   = channel (0-based).
- */
-static void
-isdnloop_kill_ctimer(isdnloop_card *card, int ch)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&card->isdnloop_lock, flags);
-       del_timer(&card->c_timer[ch]);
-       spin_unlock_irqrestore(&card->isdnloop_lock, flags);
-}
-
-static u_char si2bit[] = {0, 1, 0, 0, 0, 2, 0, 4, 0, 0};
-static u_char bit2si[] = {1, 5, 7};
-
-/*
- * Try finding a listener for an outgoing call.
- *
- * Parameter:
- *   card = pointer to calling card.
- *   p    = pointer to ICN-type setup-string.
- *   lch  = channel of calling card.
- *   cmd  = pointer to struct to be filled when parsing setup.
- * Return:
- *   0 = found match, alerting should happen.
- *   1 = found matching number but it is busy.
- *   2 = no matching listener.
- *   3 = found matching number but SI does not match.
- */
-static int
-isdnloop_try_call(isdnloop_card *card, char *p, int lch, isdn_ctrl *cmd)
-{
-       isdnloop_card *cc = cards;
-       unsigned long flags;
-       int ch;
-       int num_match;
-       int i;
-       char *e;
-       char nbuf[32];
-
-       isdnloop_parse_setup(p, cmd);
-       while (cc) {
-               for (ch = 0; ch < 2; ch++) {
-                       /* Exclude ourself */
-                       if ((cc == card) && (ch == lch))
-                               continue;
-                       num_match = 0;
-                       switch (cc->ptype) {
-                       case ISDN_PTYPE_EURO:
-                               for (i = 0; i < 3; i++)
-                                       if (!(strcmp(cc->s0num[i], cmd->parm.setup.phone)))
-                                               num_match = 1;
-                               break;
-                       case ISDN_PTYPE_1TR6:
-                               e = cc->eazlist[ch];
-                               while (*e) {
-                                       sprintf(nbuf, "%s%c", cc->s0num[0], *e);
-                                       if (!(strcmp(nbuf, cmd->parm.setup.phone)))
-                                               num_match = 1;
-                                       e++;
-                               }
-                       }
-                       if (num_match) {
-                               spin_lock_irqsave(&card->isdnloop_lock, flags);
-                               /* channel idle? */
-                               if (!(cc->rcard[ch])) {
-                                       /* Check SI */
-                                       if (!(si2bit[cmd->parm.setup.si1] & cc->sil[ch])) {
-                                               spin_unlock_irqrestore(&card->isdnloop_lock, flags);
-                                               return 3;
-                                       }
-                                       /* ch is idle, si and number matches */
-                                       cc->rcard[ch] = card;
-                                       cc->rch[ch] = lch;
-                                       card->rcard[lch] = cc;
-                                       card->rch[lch] = ch;
-                                       spin_unlock_irqrestore(&card->isdnloop_lock, flags);
-                                       return 0;
-                               } else {
-                                       spin_unlock_irqrestore(&card->isdnloop_lock, flags);
-                                       /* num matches, but busy */
-                                       if (ch == 1)
-                                               return 1;
-                               }
-                       }
-               }
-               cc = cc->next;
-       }
-       return 2;
-}
-
-/*
- * Depending on D-channel protocol and caller/called, modify
- * phone number.
- *
- * Parameter:
- *   card   = pointer to card struct.
- *   phone  = pointer phone number.
- *   caller = flag: 1 = caller, 0 = called.
- * Return:
- *   pointer to new phone number.
- */
-static char *
-isdnloop_vstphone(isdnloop_card *card, char *phone, int caller)
-{
-       int i;
-       static char nphone[30];
-
-       if (!card) {
-               printk("BUG!!!\n");
-               return "";
-       }
-       switch (card->ptype) {
-       case ISDN_PTYPE_EURO:
-               if (caller) {
-                       for (i = 0; i < 2; i++)
-                               if (!(strcmp(card->s0num[i], phone)))
-                                       return phone;
-                       return card->s0num[0];
-               }
-               return phone;
-               break;
-       case ISDN_PTYPE_1TR6:
-               if (caller) {
-                       sprintf(nphone, "%s%c", card->s0num[0], phone[0]);
-                       return nphone;
-               } else
-                       return &phone[strlen(phone) - 1];
-               break;
-       }
-       return "";
-}
-
-/*
- * Parse an ICN-type command string sent to the 'card'.
- * Perform misc. actions depending on the command.
- *
- * Parameter:
- *   card = pointer to card struct.
- */
-static void
-isdnloop_parse_cmd(isdnloop_card *card)
-{
-       char *p = card->omsg;
-       isdn_ctrl cmd;
-       char buf[60];
-       isdnloop_stat *s = isdnloop_cmd_table;
-       int action = -1;
-       int i;
-       int ch;
-
-       if ((card->omsg[0] != '0') && (card->omsg[2] != ';')) {
-               isdnloop_fake_err(card);
-               return;
-       }
-       ch = card->omsg[1] - '0';
-       if ((ch < 0) || (ch > 2)) {
-               isdnloop_fake_err(card);
-               return;
-       }
-       p += 3;
-       while (s->statstr) {
-               if (!strncmp(p, s->statstr, strlen(s->statstr))) {
-                       action = s->action;
-                       if (s->command && (ch != 0)) {
-                               isdnloop_fake_err(card);
-                               return;
-                       }
-                       break;
-               }
-               s++;
-       }
-       if (action == -1)
-               return;
-       switch (action) {
-       case 1:
-               /* 0x;BCON_R */
-               if (card->rcard[ch - 1]) {
-                       isdnloop_fake(card->rcard[ch - 1], "BCON_I",
-                                     card->rch[ch - 1] + 1);
-                       isdnloop_fake(card, "BCON_C", ch);
-               }
-               break;
-       case 17:
-               /* 0x;BCON_I */
-               if (card->rcard[ch - 1]) {
-                       isdnloop_fake(card->rcard[ch - 1], "BCON_C",
-                                     card->rch[ch - 1] + 1);
-               }
-               break;
-       case 2:
-               /* 0x;BDIS_R */
-               isdnloop_fake(card, "BDIS_C", ch);
-               if (card->rcard[ch - 1]) {
-                       isdnloop_fake(card->rcard[ch - 1], "BDIS_I",
-                                     card->rch[ch - 1] + 1);
-               }
-               break;
-       case 16:
-               /* 0x;DCON_R */
-               isdnloop_kill_ctimer(card, ch - 1);
-               if (card->rcard[ch - 1]) {
-                       isdnloop_kill_ctimer(card->rcard[ch - 1], card->rch[ch - 1]);
-                       isdnloop_fake(card->rcard[ch - 1], "DCON_C",
-                                     card->rch[ch - 1] + 1);
-                       isdnloop_fake(card, "DCON_C", ch);
-               }
-               break;
-       case 3:
-               /* 0x;DDIS_R */
-               isdnloop_kill_ctimer(card, ch - 1);
-               if (card->rcard[ch - 1]) {
-                       isdnloop_kill_ctimer(card->rcard[ch - 1], card->rch[ch - 1]);
-                       isdnloop_fake(card->rcard[ch - 1], "DDIS_I",
-                                     card->rch[ch - 1] + 1);
-                       card->rcard[ch - 1] = NULL;
-               }
-               isdnloop_fake(card, "DDIS_C", ch);
-               break;
-       case 4:
-               /* 0x;DSCA_Rdd,yy,zz,oo */
-               if (card->ptype != ISDN_PTYPE_1TR6) {
-                       isdnloop_fake_err(card);
-                       return;
-               }
-               /* Fall through */
-       case 5:
-               /* 0x;DCAL_Rdd,yy,zz,oo */
-               p += 6;
-               switch (isdnloop_try_call(card, p, ch - 1, &cmd)) {
-               case 0:
-                       /* Alerting */
-                       sprintf(buf, "D%s_I%s,%02d,%02d,%s",
-                               (action == 4) ? "SCA" : "CAL",
-                               isdnloop_vstphone(card, cmd.parm.setup.eazmsn, 1),
-                               cmd.parm.setup.si1,
-                               cmd.parm.setup.si2,
-                               isdnloop_vstphone(card->rcard[ch - 1],
-                                                 cmd.parm.setup.phone, 0));
-                       isdnloop_fake(card->rcard[ch - 1], buf, card->rch[ch - 1] + 1);
-                       /* Fall through */
-               case 3:
-                       /* si1 does not match, don't alert but start timer */
-                       isdnloop_start_ctimer(card, ch - 1);
-                       break;
-               case 1:
-                       /* Remote busy */
-                       isdnloop_fake(card, "DDIS_I", ch);
-                       sprintf(buf, "CAU%s", isdnloop_unicause(card, 1, 1));
-                       isdnloop_fake(card, buf, ch);
-                       break;
-               case 2:
-                       /* No such user */
-                       isdnloop_fake(card, "DDIS_I", ch);
-                       sprintf(buf, "CAU%s", isdnloop_unicause(card, 1, 2));
-                       isdnloop_fake(card, buf, ch);
-                       break;
-               }
-               break;
-       case 6:
-               /* 0x;EAZC */
-               card->eazlist[ch - 1][0] = '\0';
-               break;
-       case 7:
-               /* 0x;EAZ */
-               p += 3;
-               if (strlen(p) >= sizeof(card->eazlist[0]))
-                       break;
-               strcpy(card->eazlist[ch - 1], p);
-               break;
-       case 8:
-               /* 0x;SEEAZ */
-               sprintf(buf, "EAZ-LIST: %s", card->eazlist[ch - 1]);
-               isdnloop_fake(card, buf, ch + 1);
-               break;
-       case 9:
-               /* 0x;MSN */
-               break;
-       case 10:
-               /* 0x;MSNALL */
-               break;
-       case 11:
-               /* 0x;SETSIL */
-               p += 6;
-               i = 0;
-               while (strchr("0157", *p)) {
-                       if (i)
-                               card->sil[ch - 1] |= si2bit[*p - '0'];
-                       i = (*p++ == '0');
-               }
-               if (*p)
-                       isdnloop_fake_err(card);
-               break;
-       case 12:
-               /* 0x;SEESIL */
-               sprintf(buf, "SIN-LIST: ");
-               p = buf + 10;
-               for (i = 0; i < 3; i++)
-                       if (card->sil[ch - 1] & (1 << i))
-                               p += sprintf(p, "%02d", bit2si[i]);
-               isdnloop_fake(card, buf, ch + 1);
-               break;
-       case 13:
-               /* 0x;SILC */
-               card->sil[ch - 1] = 0;
-               break;
-       case 14:
-               /* 00;FV2ON */
-               break;
-       case 15:
-               /* 00;FV2OFF */
-               break;
-       }
-}
-
-/*
- * Put command-strings into the of the 'card'. In reality, execute them
- * right in place by calling isdnloop_parse_cmd(). Also copy every
- * command to the read message ringbuffer, preceding it with a '>'.
- * These mesagges can be read at /dev/isdnctrl.
- *
- * Parameter:
- *   buf  = pointer to command buffer.
- *   len  = length of buffer data.
- *   user = flag: 1 = called form userlevel, 0 called from kernel.
- *   card = pointer to card struct.
- * Return:
- *   number of bytes transferred (currently always equals len).
- */
-static int
-isdnloop_writecmd(const u_char *buf, int len, int user, isdnloop_card *card)
-{
-       int xcount = 0;
-       int ocount = 1;
-       isdn_ctrl cmd;
-
-       while (len) {
-               int count = len;
-               u_char *p;
-               u_char msg[0x100];
-
-               if (count > 255)
-                       count = 255;
-               if (user) {
-                       if (copy_from_user(msg, buf, count))
-                               return -EFAULT;
-               } else
-                       memcpy(msg, buf, count);
-               isdnloop_putmsg(card, '>');
-               for (p = msg; count > 0; count--, p++) {
-                       len--;
-                       xcount++;
-                       isdnloop_putmsg(card, *p);
-                       card->omsg[card->optr] = *p;
-                       if (*p == '\n') {
-                               card->omsg[card->optr] = '\0';
-                               card->optr = 0;
-                               isdnloop_parse_cmd(card);
-                               if (len) {
-                                       isdnloop_putmsg(card, '>');
-                                       ocount++;
-                               }
-                       } else {
-                               if (card->optr < 59)
-                                       card->optr++;
-                       }
-                       ocount++;
-               }
-       }
-       cmd.command = ISDN_STAT_STAVAIL;
-       cmd.driver = card->myid;
-       cmd.arg = ocount;
-       card->interface.statcallb(&cmd);
-       return xcount;
-}
-
-/*
- * Delete card's pending timers, send STOP to linklevel
- */
-static void
-isdnloop_stopcard(isdnloop_card *card)
-{
-       unsigned long flags;
-       isdn_ctrl cmd;
-
-       spin_lock_irqsave(&card->isdnloop_lock, flags);
-       if (card->flags & ISDNLOOP_FLAGS_RUNNING) {
-               card->flags &= ~ISDNLOOP_FLAGS_RUNNING;
-               del_timer(&card->st_timer);
-               del_timer(&card->rb_timer);
-               del_timer(&card->c_timer[0]);
-               del_timer(&card->c_timer[1]);
-               cmd.command = ISDN_STAT_STOP;
-               cmd.driver = card->myid;
-               card->interface.statcallb(&cmd);
-       }
-       spin_unlock_irqrestore(&card->isdnloop_lock, flags);
-}
-
-/*
- * Stop all cards before unload.
- */
-static void
-isdnloop_stopallcards(void)
-{
-       isdnloop_card *p = cards;
-
-       while (p) {
-               isdnloop_stopcard(p);
-               p = p->next;
-       }
-}
-
-/*
- * Start a 'card'. Simulate card's boot message and set the phone
- * number(s) of the virtual 'S0-Interface'. Install D-channel
- * poll timer.
- *
- * Parameter:
- *   card  = pointer to card struct.
- *   sdefp = pointer to struct holding ioctl parameters.
- * Return:
- *   0 on success, -E??? otherwise.
- */
-static int
-isdnloop_start(isdnloop_card *card, isdnloop_sdef *sdefp)
-{
-       unsigned long flags;
-       isdnloop_sdef sdef;
-       int i;
-
-       if (card->flags & ISDNLOOP_FLAGS_RUNNING)
-               return -EBUSY;
-       if (copy_from_user((char *) &sdef, (char *) sdefp, sizeof(sdef)))
-               return -EFAULT;
-
-       for (i = 0; i < 3; i++) {
-               if (!memchr(sdef.num[i], 0, sizeof(sdef.num[i])))
-                       return -EINVAL;
-       }
-
-       spin_lock_irqsave(&card->isdnloop_lock, flags);
-       switch (sdef.ptype) {
-       case ISDN_PTYPE_EURO:
-               if (isdnloop_fake(card, "DRV1.23EC-Q.931-CAPI-CNS-BASIS-20.02.96",
-                                 -1)) {
-                       spin_unlock_irqrestore(&card->isdnloop_lock, flags);
-                       return -ENOMEM;
-               }
-               card->sil[0] = card->sil[1] = 4;
-               if (isdnloop_fake(card, "TEI OK", 0)) {
-                       spin_unlock_irqrestore(&card->isdnloop_lock, flags);
-                       return -ENOMEM;
-               }
-               for (i = 0; i < 3; i++) {
-                       strlcpy(card->s0num[i], sdef.num[i],
-                               sizeof(card->s0num[0]));
-               }
-               break;
-       case ISDN_PTYPE_1TR6:
-               if (isdnloop_fake(card, "DRV1.04TC-1TR6-CAPI-CNS-BASIS-29.11.95",
-                                 -1)) {
-                       spin_unlock_irqrestore(&card->isdnloop_lock, flags);
-                       return -ENOMEM;
-               }
-               card->sil[0] = card->sil[1] = 4;
-               if (isdnloop_fake(card, "TEI OK", 0)) {
-                       spin_unlock_irqrestore(&card->isdnloop_lock, flags);
-                       return -ENOMEM;
-               }
-               strlcpy(card->s0num[0], sdef.num[0], sizeof(card->s0num[0]));
-               card->s0num[1][0] = '\0';
-               card->s0num[2][0] = '\0';
-               break;
-       default:
-               spin_unlock_irqrestore(&card->isdnloop_lock, flags);
-               printk(KERN_WARNING "isdnloop: Illegal D-channel protocol %d\n",
-                      sdef.ptype);
-               return -EINVAL;
-       }
-       timer_setup(&card->rb_timer, isdnloop_pollbchan, 0);
-       timer_setup(&card->st_timer, isdnloop_polldchan, 0);
-       card->st_timer.expires = jiffies + ISDNLOOP_TIMER_DCREAD;
-       add_timer(&card->st_timer);
-       card->flags |= ISDNLOOP_FLAGS_RUNNING;
-       spin_unlock_irqrestore(&card->isdnloop_lock, flags);
-       return 0;
-}
-
-/*
- * Main handler for commands sent by linklevel.
- */
-static int
-isdnloop_command(isdn_ctrl *c, isdnloop_card *card)
-{
-       ulong a;
-       int i;
-       char cbuf[80];
-       isdn_ctrl cmd;
-       isdnloop_cdef cdef;
-
-       switch (c->command) {
-       case ISDN_CMD_IOCTL:
-               memcpy(&a, c->parm.num, sizeof(ulong));
-               switch (c->arg) {
-               case ISDNLOOP_IOCTL_DEBUGVAR:
-                       return (ulong) card;
-               case ISDNLOOP_IOCTL_STARTUP:
-                       return isdnloop_start(card, (isdnloop_sdef *) a);
-                       break;
-               case ISDNLOOP_IOCTL_ADDCARD:
-                       if (copy_from_user((char *)&cdef,
-                                          (char *)a,
-                                          sizeof(cdef)))
-                               return -EFAULT;
-                       return isdnloop_addcard(cdef.id1);
-                       break;
-               case ISDNLOOP_IOCTL_LEASEDCFG:
-                       if (a) {
-                               if (!card->leased) {
-                                       card->leased = 1;
-                                       while (card->ptype == ISDN_PTYPE_UNKNOWN)
-                                               schedule_timeout_interruptible(10);
-                                       schedule_timeout_interruptible(10);
-                                       sprintf(cbuf, "00;FV2ON\n01;EAZ1\n02;EAZ2\n");
-                                       i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
-                                       printk(KERN_INFO
-                                              "isdnloop: (%s) Leased-line mode enabled\n",
-                                              CID);
-                                       cmd.command = ISDN_STAT_RUN;
-                                       cmd.driver = card->myid;
-                                       cmd.arg = 0;
-                                       card->interface.statcallb(&cmd);
-                               }
-                       } else {
-                               if (card->leased) {
-                                       card->leased = 0;
-                                       sprintf(cbuf, "00;FV2OFF\n");
-                                       i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
-                                       printk(KERN_INFO
-                                              "isdnloop: (%s) Leased-line mode disabled\n",
-                                              CID);
-                                       cmd.command = ISDN_STAT_RUN;
-                                       cmd.driver = card->myid;
-                                       cmd.arg = 0;
-                                       card->interface.statcallb(&cmd);
-                               }
-                       }
-                       return 0;
-               default:
-                       return -EINVAL;
-               }
-               break;
-       case ISDN_CMD_DIAL:
-               if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
-                       return -ENODEV;
-               if (card->leased)
-                       break;
-               if ((c->arg & 255) < ISDNLOOP_BCH) {
-                       char *p;
-                       char dcode[4];
-
-                       a = c->arg;
-                       p = c->parm.setup.phone;
-                       if (*p == 's' || *p == 'S') {
-                               /* Dial for SPV */
-                               p++;
-                               strcpy(dcode, "SCA");
-                       } else
-                               /* Normal Dial */
-                               strcpy(dcode, "CAL");
-                       snprintf(cbuf, sizeof(cbuf),
-                                "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1),
-                                dcode, p, c->parm.setup.si1,
-                                c->parm.setup.si2, c->parm.setup.eazmsn);
-                       i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
-               }
-               break;
-       case ISDN_CMD_ACCEPTD:
-               if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
-                       return -ENODEV;
-               if (c->arg < ISDNLOOP_BCH) {
-                       a = c->arg + 1;
-                       cbuf[0] = 0;
-                       switch (card->l2_proto[a - 1]) {
-                       case ISDN_PROTO_L2_X75I:
-                               sprintf(cbuf, "%02d;BX75\n", (int) a);
-                               break;
-#ifdef CONFIG_ISDN_X25
-                       case ISDN_PROTO_L2_X25DTE:
-                               sprintf(cbuf, "%02d;BX2T\n", (int) a);
-                               break;
-                       case ISDN_PROTO_L2_X25DCE:
-                               sprintf(cbuf, "%02d;BX2C\n", (int) a);
-                               break;
-#endif
-                       case ISDN_PROTO_L2_HDLC:
-                               sprintf(cbuf, "%02d;BTRA\n", (int) a);
-                               break;
-                       }
-                       if (strlen(cbuf))
-                               i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
-                       sprintf(cbuf, "%02d;DCON_R\n", (int) a);
-                       i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
-               }
-               break;
-       case ISDN_CMD_ACCEPTB:
-               if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
-                       return -ENODEV;
-               if (c->arg < ISDNLOOP_BCH) {
-                       a = c->arg + 1;
-                       switch (card->l2_proto[a - 1]) {
-                       case ISDN_PROTO_L2_X75I:
-                               sprintf(cbuf, "%02d;BCON_R,BX75\n", (int) a);
-                               break;
-#ifdef CONFIG_ISDN_X25
-                       case ISDN_PROTO_L2_X25DTE:
-                               sprintf(cbuf, "%02d;BCON_R,BX2T\n", (int) a);
-                               break;
-                       case ISDN_PROTO_L2_X25DCE:
-                               sprintf(cbuf, "%02d;BCON_R,BX2C\n", (int) a);
-                               break;
-#endif
-                       case ISDN_PROTO_L2_HDLC:
-                               sprintf(cbuf, "%02d;BCON_R,BTRA\n", (int) a);
-                               break;
-                       default:
-                               sprintf(cbuf, "%02d;BCON_R\n", (int) a);
-                       }
-                       printk(KERN_DEBUG "isdnloop writecmd '%s'\n", cbuf);
-                       i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
-                       break;
-               case ISDN_CMD_HANGUP:
-                       if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
-                               return -ENODEV;
-                       if (c->arg < ISDNLOOP_BCH) {
-                               a = c->arg + 1;
-                               sprintf(cbuf, "%02d;BDIS_R\n%02d;DDIS_R\n", (int) a, (int) a);
-                               i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
-                       }
-                       break;
-               case ISDN_CMD_SETEAZ:
-                       if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
-                               return -ENODEV;
-                       if (card->leased)
-                               break;
-                       if (c->arg < ISDNLOOP_BCH) {
-                               a = c->arg + 1;
-                               if (card->ptype == ISDN_PTYPE_EURO) {
-                                       sprintf(cbuf, "%02d;MS%s%s\n", (int) a,
-                                               c->parm.num[0] ? "N" : "ALL", c->parm.num);
-                               } else
-                                       sprintf(cbuf, "%02d;EAZ%s\n", (int) a,
-                                               c->parm.num[0] ? c->parm.num : (u_char *) "0123456789");
-                               i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
-                       }
-                       break;
-               case ISDN_CMD_CLREAZ:
-                       if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
-                               return -ENODEV;
-                       if (card->leased)
-                               break;
-                       if (c->arg < ISDNLOOP_BCH) {
-                               a = c->arg + 1;
-                               if (card->ptype == ISDN_PTYPE_EURO)
-                                       sprintf(cbuf, "%02d;MSNC\n", (int) a);
-                               else
-                                       sprintf(cbuf, "%02d;EAZC\n", (int) a);
-                               i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
-                       }
-                       break;
-               case ISDN_CMD_SETL2:
-                       if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
-                               return -ENODEV;
-                       if ((c->arg & 255) < ISDNLOOP_BCH) {
-                               a = c->arg;
-                               switch (a >> 8) {
-                               case ISDN_PROTO_L2_X75I:
-                                       sprintf(cbuf, "%02d;BX75\n", (int) (a & 255) + 1);
-                                       break;
-#ifdef CONFIG_ISDN_X25
-                               case ISDN_PROTO_L2_X25DTE:
-                                       sprintf(cbuf, "%02d;BX2T\n", (int) (a & 255) + 1);
-                                       break;
-                               case ISDN_PROTO_L2_X25DCE:
-                                       sprintf(cbuf, "%02d;BX2C\n", (int) (a & 255) + 1);
-                                       break;
-#endif
-                               case ISDN_PROTO_L2_HDLC:
-                                       sprintf(cbuf, "%02d;BTRA\n", (int) (a & 255) + 1);
-                                       break;
-                               case ISDN_PROTO_L2_TRANS:
-                                       sprintf(cbuf, "%02d;BTRA\n", (int) (a & 255) + 1);
-                                       break;
-                               default:
-                                       return -EINVAL;
-                               }
-                               i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
-                               card->l2_proto[a & 255] = (a >> 8);
-                       }
-                       break;
-               case ISDN_CMD_SETL3:
-                       if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
-                               return -ENODEV;
-                       return 0;
-               default:
-                       return -EINVAL;
-               }
-       }
-       return 0;
-}
-
-/*
- * Find card with given driverId
- */
-static inline isdnloop_card *
-isdnloop_findcard(int driverid)
-{
-       isdnloop_card *p = cards;
-
-       while (p) {
-               if (p->myid == driverid)
-                       return p;
-               p = p->next;
-       }
-       return (isdnloop_card *) 0;
-}
-
-/*
- * Wrapper functions for interface to linklevel
- */
-static int
-if_command(isdn_ctrl *c)
-{
-       isdnloop_card *card = isdnloop_findcard(c->driver);
-
-       if (card)
-               return isdnloop_command(c, card);
-       printk(KERN_ERR
-              "isdnloop: if_command called with invalid driverId!\n");
-       return -ENODEV;
-}
-
-static int
-if_writecmd(const u_char __user *buf, int len, int id, int channel)
-{
-       isdnloop_card *card = isdnloop_findcard(id);
-
-       if (card) {
-               if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
-                       return -ENODEV;
-               return isdnloop_writecmd(buf, len, 1, card);
-       }
-       printk(KERN_ERR
-              "isdnloop: if_writecmd called with invalid driverId!\n");
-       return -ENODEV;
-}
-
-static int
-if_readstatus(u_char __user *buf, int len, int id, int channel)
-{
-       isdnloop_card *card = isdnloop_findcard(id);
-
-       if (card) {
-               if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
-                       return -ENODEV;
-               return isdnloop_readstatus(buf, len, card);
-       }
-       printk(KERN_ERR
-              "isdnloop: if_readstatus called with invalid driverId!\n");
-       return -ENODEV;
-}
-
-static int
-if_sendbuf(int id, int channel, int ack, struct sk_buff *skb)
-{
-       isdnloop_card *card = isdnloop_findcard(id);
-
-       if (card) {
-               if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
-                       return -ENODEV;
-               /* ack request stored in skb scratch area */
-               *(skb->head) = ack;
-               return isdnloop_sendbuf(channel, skb, card);
-       }
-       printk(KERN_ERR
-              "isdnloop: if_sendbuf called with invalid driverId!\n");
-       return -ENODEV;
-}
-
-/*
- * Allocate a new card-struct, initialize it
- * link it into cards-list and register it at linklevel.
- */
-static isdnloop_card *
-isdnloop_initcard(char *id)
-{
-       isdnloop_card *card;
-       int i;
-       card = kzalloc(sizeof(isdnloop_card), GFP_KERNEL);
-       if (!card) {
-               printk(KERN_WARNING
-                      "isdnloop: (%s) Could not allocate card-struct.\n", id);
-               return (isdnloop_card *) 0;
-       }
-       card->interface.owner = THIS_MODULE;
-       card->interface.channels = ISDNLOOP_BCH;
-       card->interface.hl_hdrlen  = 1; /* scratch area for storing ack flag*/
-       card->interface.maxbufsize = 4000;
-       card->interface.command = if_command;
-       card->interface.writebuf_skb = if_sendbuf;
-       card->interface.writecmd = if_writecmd;
-       card->interface.readstat = if_readstatus;
-       card->interface.features = ISDN_FEATURE_L2_X75I |
-#ifdef CONFIG_ISDN_X25
-               ISDN_FEATURE_L2_X25DTE |
-               ISDN_FEATURE_L2_X25DCE |
-#endif
-               ISDN_FEATURE_L2_HDLC |
-               ISDN_FEATURE_L3_TRANS |
-               ISDN_FEATURE_P_UNKNOWN;
-       card->ptype = ISDN_PTYPE_UNKNOWN;
-       strlcpy(card->interface.id, id, sizeof(card->interface.id));
-       card->msg_buf_write = card->msg_buf;
-       card->msg_buf_read = card->msg_buf;
-       card->msg_buf_end = &card->msg_buf[sizeof(card->msg_buf) - 1];
-       for (i = 0; i < ISDNLOOP_BCH; i++) {
-               card->l2_proto[i] = ISDN_PROTO_L2_X75I;
-               skb_queue_head_init(&card->bqueue[i]);
-       }
-       skb_queue_head_init(&card->dqueue);
-       spin_lock_init(&card->isdnloop_lock);
-       card->next = cards;
-       cards = card;
-       if (!register_isdn(&card->interface)) {
-               cards = cards->next;
-               printk(KERN_WARNING
-                      "isdnloop: Unable to register %s\n", id);
-               kfree(card);
-               return (isdnloop_card *) 0;
-       }
-       card->myid = card->interface.channels;
-       return card;
-}
-
-static int
-isdnloop_addcard(char *id1)
-{
-       isdnloop_card *card;
-       card = isdnloop_initcard(id1);
-       if (!card) {
-               return -EIO;
-       }
-       printk(KERN_INFO
-              "isdnloop: (%s) virtual card added\n",
-              card->interface.id);
-       return 0;
-}
-
-static int __init
-isdnloop_init(void)
-{
-       if (isdnloop_id)
-               return isdnloop_addcard(isdnloop_id);
-
-       return 0;
-}
-
-static void __exit
-isdnloop_exit(void)
-{
-       isdn_ctrl cmd;
-       isdnloop_card *card = cards;
-       isdnloop_card *last;
-       int i;
-
-       isdnloop_stopallcards();
-       while (card) {
-               cmd.command = ISDN_STAT_UNLOAD;
-               cmd.driver = card->myid;
-               card->interface.statcallb(&cmd);
-               for (i = 0; i < ISDNLOOP_BCH; i++)
-                       isdnloop_free_queue(card, i);
-               card = card->next;
-       }
-       card = cards;
-       while (card) {
-               last = card;
-               skb_queue_purge(&card->dqueue);
-               card = card->next;
-               kfree(last);
-       }
-       printk(KERN_NOTICE "isdnloop-ISDN-driver unloaded\n");
-}
-
-module_init(isdnloop_init);
-module_exit(isdnloop_exit);
 
+++ /dev/null
-/* $Id: isdnloop.h,v 1.5.6.3 2001/09/23 22:24:56 kai Exp $
- *
- * Loopback lowlevel module for testing of linklevel.
- *
- * Copyright 1997 by Fritz Elfert (fritz@isdn4linux.de)
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#ifndef isdnloop_h
-#define isdnloop_h
-
-#define ISDNLOOP_IOCTL_DEBUGVAR  0
-#define ISDNLOOP_IOCTL_ADDCARD   1
-#define ISDNLOOP_IOCTL_LEASEDCFG 2
-#define ISDNLOOP_IOCTL_STARTUP   3
-
-/* Struct for adding new cards */
-typedef struct isdnloop_cdef {
-       char id1[10];
-} isdnloop_cdef;
-
-/* Struct for configuring cards */
-typedef struct isdnloop_sdef {
-       int ptype;
-       char num[3][20];
-} isdnloop_sdef;
-
-#if defined(__KERNEL__) || defined(__DEBUGVAR__)
-
-#ifdef __KERNEL__
-/* Kernel includes */
-
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/major.h>
-#include <asm/io.h>
-#include <linux/kernel.h>
-#include <linux/signal.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/mman.h>
-#include <linux/ioport.h>
-#include <linux/timer.h>
-#include <linux/wait.h>
-#include <linux/isdnif.h>
-
-#endif                          /* __KERNEL__ */
-
-#define ISDNLOOP_FLAGS_B1ACTIVE 1      /* B-Channel-1 is open           */
-#define ISDNLOOP_FLAGS_B2ACTIVE 2      /* B-Channel-2 is open           */
-#define ISDNLOOP_FLAGS_RUNNING  4      /* Cards driver activated        */
-#define ISDNLOOP_FLAGS_RBTIMER  8      /* scheduling of B-Channel-poll  */
-#define ISDNLOOP_TIMER_BCREAD 1 /* B-Channel poll-cycle          */
-#define ISDNLOOP_TIMER_DCREAD (HZ/2)   /* D-Channel poll-cycle          */
-#define ISDNLOOP_TIMER_ALERTWAIT (10 * HZ)     /* Alert timeout                 */
-#define ISDNLOOP_MAX_SQUEUE 65536      /* Max. outstanding send-data    */
-#define ISDNLOOP_BCH 2          /* channels per card             */
-
-/*
- * Per card driver data
- */
-typedef struct isdnloop_card {
-       struct isdnloop_card *next;     /* Pointer to next device struct    */
-       struct isdnloop_card
-       *rcard[ISDNLOOP_BCH];   /* Pointer to 'remote' card         */
-       int rch[ISDNLOOP_BCH];  /* 'remote' channel                 */
-       int myid;               /* Driver-Nr. assigned by linklevel */
-       int leased;             /* Flag: This Adapter is connected  */
-       /*       to a leased line           */
-       int sil[ISDNLOOP_BCH];  /* SI's to listen for               */
-       char eazlist[ISDNLOOP_BCH][11];
-       /* EAZ's to listen for              */
-       char s0num[3][20];      /* 1TR6 base-number or MSN's        */
-       unsigned short flags;   /* Statusflags                      */
-       int ptype;              /* Protocol type (1TR6 or Euro)     */
-       struct timer_list st_timer;     /* Timer for Status-Polls           */
-       struct timer_list rb_timer;     /* Timer for B-Channel-Polls        */
-       struct timer_list
-       c_timer[ISDNLOOP_BCH]; /* Timer for Alerting               */
-       int l2_proto[ISDNLOOP_BCH];     /* Current layer-2-protocol         */
-       isdn_if interface;      /* Interface to upper layer         */
-       int iptr;               /* Index to imsg-buffer             */
-       char imsg[60];          /* Internal buf for status-parsing  */
-       int optr;               /* Index to omsg-buffer             */
-       char omsg[60];          /* Internal buf for cmd-parsing     */
-       char msg_buf[2048];     /* Buffer for status-messages       */
-       char *msg_buf_write;    /* Writepointer for statusbuffer    */
-       char *msg_buf_read;     /* Readpointer for statusbuffer     */
-       char *msg_buf_end;      /* Pointer to end of statusbuffer   */
-       int sndcount[ISDNLOOP_BCH];     /* Byte-counters for B-Ch.-send     */
-       struct sk_buff_head
-       bqueue[ISDNLOOP_BCH];  /* B-Channel queues                 */
-       struct sk_buff_head dqueue;     /* D-Channel queue                  */
-       spinlock_t isdnloop_lock;
-} isdnloop_card;
-
-/*
- * Main driver data
- */
-#ifdef __KERNEL__
-static isdnloop_card *cards = (isdnloop_card *) 0;
-#endif                          /* __KERNEL__ */
-
-/* Utility-Macros */
-
-#define CID (card->interface.id)
-
-#endif                          /* defined(__KERNEL__) || defined(__DEBUGVAR__) */
-#endif                          /* isdnloop_h */
 
+++ /dev/null
-/* $Id: concap.h,v 1.3.2.2 2004/01/12 23:08:35 keil Exp $
- *
- * Copyright 1997 by Henner Eisen <eis@baty.hanse.de>
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- */
-
-#ifndef _LINUX_CONCAP_H
-#define _LINUX_CONCAP_H
-
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-
-/* Stuff to support encapsulation protocols genericly. The encapsulation
-   protocol is processed at the uppermost layer of the network interface.
-
-   Based on a ideas developed in a 'synchronous device' thread in the
-   linux-x25 mailing list contributed by Alan Cox, Thomasz Motylewski
-   and Jonathan Naylor.
-
-   For more documetation on this refer to Documentation/isdn/README.concap
-*/
-
-struct concap_proto_ops;
-struct concap_device_ops;
-
-/* this manages all data needed by the encapsulation protocol
- */
-struct concap_proto{
-       struct net_device *net_dev;     /* net device using our service  */
-       struct concap_device_ops *dops; /* callbacks provided by device */
-       struct concap_proto_ops  *pops; /* callbacks provided by us */
-       spinlock_t lock;
-       int flags;
-       void *proto_data;               /* protocol specific private data, to
-                                          be accessed via *pops methods only*/
-       /*
-         :
-         whatever 
-         :
-         */
-};
-
-/* Operations to be supported by the net device. Called by the encapsulation
- * protocol entity. No receive method is offered because the encapsulation
- * protocol directly calls netif_rx().
- */
-struct concap_device_ops{
-
-       /* to request data is submitted by device*/ 
-       int (*data_req)(struct concap_proto *, struct sk_buff *);
-
-       /* Control methods must be set to NULL by devices which do not
-          support connection control.*/
-       /* to request a connection is set up */ 
-       int (*connect_req)(struct concap_proto *);
-
-       /* to request a connection is released */
-       int (*disconn_req)(struct concap_proto *);      
-};
-
-/* Operations to be supported by the encapsulation protocol. Called by
- * device driver.
- */
-struct concap_proto_ops{
-
-       /* create a new encapsulation protocol instance of same type */
-       struct concap_proto *  (*proto_new) (void);
-
-       /* delete encapsulation protocol instance and free all its resources.
-          cprot may no loger be referenced after calling this */
-       void (*proto_del)(struct concap_proto *cprot);
-
-       /* initialize the protocol's data. To be called at interface startup
-          or when the device driver resets the interface. All services of the
-          encapsulation protocol may be used after this*/
-       int (*restart)(struct concap_proto *cprot, 
-                      struct net_device *ndev,
-                      struct concap_device_ops *dops);
-
-       /* inactivate an encapsulation protocol instance. The encapsulation
-          protocol may not call any *dops methods after this. */
-       int (*close)(struct concap_proto *cprot);
-
-       /* process a frame handed down to us by upper layer */
-       int (*encap_and_xmit)(struct concap_proto *cprot, struct sk_buff *skb);
-
-       /* to be called for each data entity received from lower layer*/ 
-       int (*data_ind)(struct concap_proto *cprot, struct sk_buff *skb);
-
-       /* to be called when a connection was set up/down.
-          Protocols that don't process these primitives might fill in
-          dummy methods here */
-       int (*connect_ind)(struct concap_proto *cprot);
-       int (*disconn_ind)(struct concap_proto *cprot);
-  /*
-    Some network device support functions, like net_header(), rebuild_header(),
-    and others, that depend solely on the encapsulation protocol, might
-    be provided here, too. The net device would just fill them in its
-    corresponding fields when it is opened.
-    */
-};
-
-/* dummy restart/close/connect/reset/disconn methods
- */
-extern int concap_nop(struct concap_proto *cprot); 
-
-/* dummy submit method
- */
-extern int concap_drop_skb(struct concap_proto *cprot, struct sk_buff *skb);
-#endif
 
+++ /dev/null
-/* $Id: isdn.h,v 1.125.2.3 2004/02/10 01:07:14 keil Exp $
- *
- * Main header for the Linux ISDN subsystem (linklevel).
- *
- * Copyright 1994,95,96 by Fritz Elfert (fritz@isdn4linux.de)
- * Copyright 1995,96    by Thinking Objects Software GmbH Wuerzburg
- * Copyright 1995,96    by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
- * 
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-#ifndef __ISDN_H__
-#define __ISDN_H__
-
-
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/major.h>
-#include <asm/io.h>
-#include <linux/kernel.h>
-#include <linux/signal.h>
-#include <linux/slab.h>
-#include <linux/timer.h>
-#include <linux/wait.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial_reg.h>
-#include <linux/fcntl.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/ip.h>
-#include <linux/in.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/tcp.h>
-#include <linux/mutex.h>
-#include <uapi/linux/isdn.h>
-
-#define ISDN_TTY_MAJOR    43
-#define ISDN_TTYAUX_MAJOR 44
-#define ISDN_MAJOR        45
-
-/* The minor-devicenumbers for Channel 0 and 1 are used as arguments for
- * physical Channel-Mapping, so they MUST NOT be changed without changing
- * the correspondent code in isdn.c
- */
-
-#define ISDN_MINOR_B        0
-#define ISDN_MINOR_BMAX     (ISDN_MAX_CHANNELS-1)
-#define ISDN_MINOR_CTRL     64
-#define ISDN_MINOR_CTRLMAX  (64 + (ISDN_MAX_CHANNELS-1))
-#define ISDN_MINOR_PPP      128
-#define ISDN_MINOR_PPPMAX   (128 + (ISDN_MAX_CHANNELS-1))
-#define ISDN_MINOR_STATUS   255
-
-#ifdef CONFIG_ISDN_PPP
-
-#ifdef CONFIG_ISDN_PPP_VJ
-#  include <net/slhc_vj.h>
-#endif
-
-#include <linux/ppp_defs.h>
-#include <linux/ppp-ioctl.h>
-
-#include <linux/isdn_ppp.h>
-#endif
-
-#ifdef CONFIG_ISDN_X25
-#  include <linux/concap.h>
-#endif
-
-#include <linux/isdnif.h>
-
-#define ISDN_DRVIOCTL_MASK       0x7f  /* Mask for Device-ioctl */
-
-/* Until now unused */
-#define ISDN_SERVICE_VOICE 1
-#define ISDN_SERVICE_AB    1<<1 
-#define ISDN_SERVICE_X21   1<<2
-#define ISDN_SERVICE_G4    1<<3
-#define ISDN_SERVICE_BTX   1<<4
-#define ISDN_SERVICE_DFUE  1<<5
-#define ISDN_SERVICE_X25   1<<6
-#define ISDN_SERVICE_TTX   1<<7
-#define ISDN_SERVICE_MIXED 1<<8
-#define ISDN_SERVICE_FW    1<<9
-#define ISDN_SERVICE_GTEL  1<<10
-#define ISDN_SERVICE_BTXN  1<<11
-#define ISDN_SERVICE_BTEL  1<<12
-
-/* Macros checking plain usage */
-#define USG_NONE(x)         ((x & ISDN_USAGE_MASK)==ISDN_USAGE_NONE)
-#define USG_RAW(x)          ((x & ISDN_USAGE_MASK)==ISDN_USAGE_RAW)
-#define USG_MODEM(x)        ((x & ISDN_USAGE_MASK)==ISDN_USAGE_MODEM)
-#define USG_VOICE(x)        ((x & ISDN_USAGE_MASK)==ISDN_USAGE_VOICE)
-#define USG_NET(x)          ((x & ISDN_USAGE_MASK)==ISDN_USAGE_NET)
-#define USG_FAX(x)          ((x & ISDN_USAGE_MASK)==ISDN_USAGE_FAX)
-#define USG_OUTGOING(x)     ((x & ISDN_USAGE_OUTGOING)==ISDN_USAGE_OUTGOING)
-#define USG_MODEMORVOICE(x) (((x & ISDN_USAGE_MASK)==ISDN_USAGE_MODEM) || \
-                             ((x & ISDN_USAGE_MASK)==ISDN_USAGE_VOICE)     )
-
-/* Timer-delays and scheduling-flags */
-#define ISDN_TIMER_RES         4                         /* Main Timer-Resolution   */
-#define ISDN_TIMER_02SEC       (HZ/ISDN_TIMER_RES/5)     /* Slow-Timer1 .2 sec      */
-#define ISDN_TIMER_1SEC        (HZ/ISDN_TIMER_RES)       /* Slow-Timer2 1 sec       */
-#define ISDN_TIMER_RINGING     5 /* tty RINGs = ISDN_TIMER_1SEC * this factor       */
-#define ISDN_TIMER_KEEPINT    10 /* Cisco-Keepalive = ISDN_TIMER_1SEC * this factor */
-#define ISDN_TIMER_MODEMREAD   1
-#define ISDN_TIMER_MODEMPLUS   2
-#define ISDN_TIMER_MODEMRING   4
-#define ISDN_TIMER_MODEMXMIT   8
-#define ISDN_TIMER_NETDIAL    16 
-#define ISDN_TIMER_NETHANGUP  32
-#define ISDN_TIMER_CARRIER   256 /* Wait for Carrier */
-#define ISDN_TIMER_FAST      (ISDN_TIMER_MODEMREAD | ISDN_TIMER_MODEMPLUS | \
-                              ISDN_TIMER_MODEMXMIT)
-#define ISDN_TIMER_SLOW      (ISDN_TIMER_MODEMRING | ISDN_TIMER_NETHANGUP | \
-                              ISDN_TIMER_NETDIAL | ISDN_TIMER_CARRIER)
-
-/* Timeout-Values for isdn_net_dial() */
-#define ISDN_TIMER_DTIMEOUT10 (10*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1)))
-#define ISDN_TIMER_DTIMEOUT15 (15*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1)))
-#define ISDN_TIMER_DTIMEOUT60 (60*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1)))
-
-/* GLOBAL_FLAGS */
-#define ISDN_GLOBAL_STOPPED 1
-
-/*=================== Start of ip-over-ISDN stuff =========================*/
-
-/* Feature- and status-flags for a net-interface */
-#define ISDN_NET_CONNECTED  0x01       /* Bound to ISDN-Channel             */
-#define ISDN_NET_SECURE     0x02       /* Accept calls from phonelist only  */
-#define ISDN_NET_CALLBACK   0x04       /* activate callback                 */
-#define ISDN_NET_CBHUP      0x08       /* hangup before callback            */
-#define ISDN_NET_CBOUT      0x10       /* remote machine does callback      */
-
-#define ISDN_NET_MAGIC      0x49344C02 /* for paranoia-checking             */
-
-/* Phone-list-element */
-typedef struct {
-  void *next;
-  char num[ISDN_MSNLEN];
-} isdn_net_phone;
-
-/*
-   Principles when extending structures for generic encapsulation protocol
-   ("concap") support:
-   - Stuff which is hardware specific (here i4l-specific) goes in 
-     the netdev -> local structure (here: isdn_net_local)
-   - Stuff which is encapsulation protocol specific goes in the structure
-     which holds the linux device structure (here: isdn_net_device)
-*/
-
-/* Local interface-data */
-typedef struct isdn_net_local_s {
-  ulong                  magic;
-  struct net_device_stats stats;       /* Ethernet Statistics              */
-  int                    isdn_device;  /* Index to isdn-device             */
-  int                    isdn_channel; /* Index to isdn-channel            */
-  int                   ppp_slot;     /* PPPD device slot number          */
-  int                    pre_device;   /* Preselected isdn-device          */
-  int                    pre_channel;  /* Preselected isdn-channel         */
-  int                    exclusive;    /* If non-zero idx to reserved chan.*/
-  int                    flags;        /* Connection-flags                 */
-  int                    dialretry;    /* Counter for Dialout-retries      */
-  int                    dialmax;      /* Max. Number of Dial-retries      */
-  int                    cbdelay;      /* Delay before Callback starts     */
-  int                    dtimer;       /* Timeout-counter for dialing      */
-  char                   msn[ISDN_MSNLEN]; /* MSNs/EAZs for this interface */
-  u_char                 cbhup;        /* Flag: Reject Call before Callback*/
-  u_char                 dialstate;    /* State for dialing                */
-  u_char                 p_encap;      /* Packet encapsulation             */
-                                       /*   0 = Ethernet over ISDN         */
-                                      /*   1 = RAW-IP                     */
-                                       /*   2 = IP with type field         */
-  u_char                 l2_proto;     /* Layer-2-protocol                 */
-                                      /* See ISDN_PROTO_L2..-constants in */
-                                       /* isdnif.h                         */
-                                       /*   0 = X75/LAPB with I-Frames     */
-                                      /*   1 = X75/LAPB with UI-Frames    */
-                                      /*   2 = X75/LAPB with BUI-Frames   */
-                                      /*   3 = HDLC                       */
-  u_char                 l3_proto;     /* Layer-3-protocol                 */
-                                      /* See ISDN_PROTO_L3..-constants in */
-                                       /* isdnif.h                         */
-                                       /*   0 = Transparent                */
-  int                    huptimer;     /* Timeout-counter for auto-hangup  */
-  int                    charge;       /* Counter for charging units       */
-  ulong                  chargetime;   /* Timer for Charging info          */
-  int                    hupflags;     /* Flags for charge-unit-hangup:    */
-                                      /* bit0: chargeint is invalid       */
-                                      /* bit1: Getting charge-interval    */
-                                       /* bit2: Do charge-unit-hangup      */
-                                       /* bit3: Do hangup even on incoming */
-  int                    outgoing;     /* Flag: outgoing call              */
-  int                    onhtime;      /* Time to keep link up             */
-  int                    chargeint;    /* Interval between charge-infos    */
-  int                    onum;         /* Flag: at least 1 outgoing number */
-  int                    cps;          /* current speed of this interface  */
-  int                    transcount;   /* byte-counter for cps-calculation */
-  int                    sqfull;       /* Flag: netdev-queue overloaded    */
-  ulong                  sqfull_stamp; /* Start-Time of overload           */
-  ulong                  slavedelay;   /* Dynamic bundling delaytime       */
-  int                    triggercps;   /* BogoCPS needed for trigger slave */
-  isdn_net_phone         *phone[2];    /* List of remote-phonenumbers      */
-                                      /* phone[0] = Incoming Numbers      */
-                                      /* phone[1] = Outgoing Numbers      */
-  isdn_net_phone         *dial;        /* Pointer to dialed number         */
-  struct net_device      *master;      /* Ptr to Master device for slaves  */
-  struct net_device      *slave;       /* Ptr to Slave device for masters  */
-  struct isdn_net_local_s *next;       /* Ptr to next link in bundle       */
-  struct isdn_net_local_s *last;       /* Ptr to last link in bundle       */
-  struct isdn_net_dev_s  *netdev;      /* Ptr to netdev                    */
-  struct sk_buff_head    super_tx_queue; /* List of supervisory frames to  */
-                                      /* be transmitted asap              */
-  atomic_t frame_cnt;                  /* number of frames currently       */
-                                      /* queued in HL driver              */    
-                                       /* Ptr to orig. hard_header_cache   */
-  spinlock_t             xmit_lock;    /* used to protect the xmit path of */
-                                       /* a particular channel (including  */
-                                       /* the frame_cnt                    */
-
-  int  pppbind;                        /* ippp device for bindings         */
-  int                                  dialtimeout;    /* How long shall we try on dialing? (jiffies) */
-  int                                  dialwait;               /* How long shall we wait after failed attempt? (jiffies) */
-  ulong                                        dialstarted;    /* jiffies of first dialing-attempt */
-  ulong                                        dialwait_timer; /* jiffies of earliest next dialing-attempt */
-  int                                  huptimeout;             /* How long will the connection be up? (seconds) */
-#ifdef CONFIG_ISDN_X25
-  struct concap_device_ops *dops;      /* callbacks used by encapsulator   */
-#endif
-  /* use an own struct for that in later versions */
-  ulong cisco_myseq;                   /* Local keepalive seq. for Cisco   */
-  ulong cisco_mineseen;                /* returned keepalive seq. from remote */
-  ulong cisco_yourseq;                 /* Remote keepalive seq. for Cisco  */
-  int cisco_keepalive_period;          /* keepalive period */
-  ulong cisco_last_slarp_in;           /* jiffie of last keepalive packet we received */
-  char cisco_line_state;               /* state of line according to keepalive packets */
-  char cisco_debserint;                        /* debugging flag of cisco hdlc with slarp */
-  struct timer_list cisco_timer;
-  struct work_struct tqueue;
-} isdn_net_local;
-
-/* the interface itself */
-typedef struct isdn_net_dev_s {
-  isdn_net_local *local;
-  isdn_net_local *queue;               /* circular list of all bundled
-                                         channels, which are currently
-                                         online                           */
-  spinlock_t queue_lock;               /* lock to protect queue            */
-  void *next;                          /* Pointer to next isdn-interface   */
-  struct net_device *dev;              /* interface to upper levels        */
-#ifdef CONFIG_ISDN_PPP
-  ippp_bundle * pb;            /* pointer to the common bundle structure
-                                * with the per-bundle data */
-#endif
-#ifdef CONFIG_ISDN_X25
-  struct concap_proto  *cprot; /* connection oriented encapsulation protocol */
-#endif
-
-} isdn_net_dev;
-
-/*===================== End of ip-over-ISDN stuff ===========================*/
-
-/*======================= Start of ISDN-tty stuff ===========================*/
-
-#define ISDN_ASYNC_MAGIC          0x49344C01 /* for paranoia-checking        */
-#define ISDN_SERIAL_XMIT_SIZE           1024 /* Default bufsize for write    */
-#define ISDN_SERIAL_XMIT_MAX            4000 /* Maximum bufsize for write    */
-
-#ifdef CONFIG_ISDN_AUDIO
-/* For using sk_buffs with audio we need some private variables
- * within each sk_buff. For this purpose, we declare a struct here,
- * and put it always at the private skb->cb data array. A few macros help
- * accessing the variables.
- */
-typedef struct _isdn_audio_data {
-  unsigned short dle_count;
-  unsigned char  lock;
-} isdn_audio_data_t;
-
-#define ISDN_AUDIO_SKB_DLECOUNT(skb)   (((isdn_audio_data_t *)&skb->cb[0])->dle_count)
-#define ISDN_AUDIO_SKB_LOCK(skb)       (((isdn_audio_data_t *)&skb->cb[0])->lock)
-#endif
-
-/* Private data of AT-command-interpreter */
-typedef struct atemu {
-       u_char       profile[ISDN_MODEM_NUMREG]; /* Modem-Regs. Profile 0              */
-       u_char       mdmreg[ISDN_MODEM_NUMREG];  /* Modem-Registers                    */
-       char         pmsn[ISDN_MSNLEN];          /* EAZ/MSNs Profile 0                 */
-       char         msn[ISDN_MSNLEN];           /* EAZ/MSN                            */
-       char         plmsn[ISDN_LMSNLEN];        /* Listening MSNs Profile 0           */
-       char         lmsn[ISDN_LMSNLEN];         /* Listening MSNs                     */
-       char         cpn[ISDN_MSNLEN];           /* CalledPartyNumber on incoming call */
-       char         connmsg[ISDN_CMSGLEN];      /* CONNECT-Msg from HL-Driver         */
-#ifdef CONFIG_ISDN_AUDIO
-       u_char       vpar[10];                   /* Voice-parameters                   */
-       int          lastDLE;                    /* Flag for voice-coding: DLE seen    */
-#endif
-       int          mdmcmdl;                    /* Length of Modem-Commandbuffer      */
-       int          pluscount;                  /* Counter for +++ sequence           */
-       u_long       lastplus;                   /* Timestamp of last +                */
-       int          carrierwait;                /* Seconds of carrier waiting         */
-       char         mdmcmd[255];                /* Modem-Commandbuffer                */
-       unsigned int charge;                     /* Charge units of current connection */
-} atemu;
-
-/* Private data (similar to async_struct in <linux/serial.h>) */
-typedef struct modem_info {
-  int                  magic;
-  struct tty_port      port;
-  int                  x_char;          /* xon/xoff character             */
-  int                  mcr;             /* Modem control register         */
-  int                   msr;             /* Modem status register          */
-  int                   lsr;             /* Line status register           */
-  int                  line;
-  int                   online;          /* 1 = B-Channel is up, drop data */
-                                        /* 2 = B-Channel is up, deliver d.*/
-  int                   dialing;         /* Dial in progress or ATA        */
-  int                   closing;
-  int                   rcvsched;        /* Receive needs schedule         */
-  int                   isdn_driver;    /* Index to isdn-driver           */
-  int                   isdn_channel;    /* Index to isdn-channel          */
-  int                   drv_index;       /* Index to dev->usage            */
-  int                   ncarrier;        /* Flag: schedule NO CARRIER      */
-  unsigned char         last_cause[8];   /* Last cause message             */
-  unsigned char         last_num[ISDN_MSNLEN];
-                                        /* Last phone-number              */
-  unsigned char         last_l2;         /* Last layer-2 protocol          */
-  unsigned char         last_si;         /* Last service                   */
-  unsigned char         last_lhup;       /* Last hangup local?             */
-  unsigned char         last_dir;        /* Last direction (in or out)     */
-  struct timer_list     nc_timer;        /* Timer for delayed NO CARRIER   */
-  int                   send_outstanding;/* # of outstanding send-requests */
-  int                   xmit_size;       /* max. # of chars in xmit_buf    */
-  int                   xmit_count;      /* # of chars in xmit_buf         */
-  struct sk_buff_head   xmit_queue;      /* transmit queue                 */
-  atomic_t              xmit_lock;       /* Semaphore for isdn_tty_write   */
-#ifdef CONFIG_ISDN_AUDIO
-  int                   vonline;         /* Voice-channel status           */
-                                        /* Bit 0 = recording              */
-                                        /* Bit 1 = playback               */
-                                        /* Bit 2 = playback, DLE-ETX seen */
-  struct sk_buff_head   dtmf_queue;      /* queue for dtmf results         */
-  void                  *adpcms;         /* state for adpcm decompression  */
-  void                  *adpcmr;         /* state for adpcm compression    */
-  void                  *dtmf_state;     /* state for dtmf decoder         */
-  void                  *silence_state;  /* state for silence detection    */
-#endif
-#ifdef CONFIG_ISDN_TTY_FAX
-  struct T30_s         *fax;            /* T30 Fax Group 3 data/interface */
-  int                  faxonline;       /* Fax-channel status             */
-#endif
-  atemu                 emu;             /* AT-emulator data               */
-  spinlock_t           readlock;
-} modem_info;
-
-#define ISDN_MODEM_WINSIZE 8
-
-/* Description of one ISDN-tty */
-typedef struct _isdn_modem {
-  int                refcount;                         /* Number of opens        */
-  struct tty_driver  *tty_modem;                       /* tty-device             */
-  struct tty_struct  *modem_table[ISDN_MAX_CHANNELS];  /* ?? copied from Orig    */
-  struct ktermios     *modem_termios[ISDN_MAX_CHANNELS];
-  struct ktermios     *modem_termios_locked[ISDN_MAX_CHANNELS];
-  modem_info         info[ISDN_MAX_CHANNELS];     /* Private data           */
-} isdn_modem_t;
-
-/*======================= End of ISDN-tty stuff ============================*/
-
-/*======================== Start of V.110 stuff ============================*/
-#define V110_BUFSIZE 1024
-
-typedef struct {
-       int nbytes;                    /* 1 Matrixbyte -> nbytes in stream     */
-       int nbits;                     /* Number of used bits in streambyte    */
-       unsigned char key;             /* Bitmask in stream eg. 11 (nbits=2)   */
-       int decodelen;                 /* Amount of data in decodebuf          */
-       int SyncInit;                  /* Number of sync frames to send        */
-       unsigned char *OnlineFrame;    /* Precalculated V110 idle frame        */
-       unsigned char *OfflineFrame;   /* Precalculated V110 sync Frame        */
-       int framelen;                  /* Length of frames                     */
-       int skbuser;                   /* Number of unacked userdata skbs      */
-       int skbidle;                   /* Number of unacked idle/sync skbs     */
-       int introducer;                /* Local vars for decoder               */
-       int dbit;
-       unsigned char b;
-       int skbres;                    /* space to reserve in outgoing skb     */
-       int maxsize;                   /* maxbufsize of lowlevel driver        */
-       unsigned char *encodebuf;      /* temporary buffer for encoding        */
-       unsigned char decodebuf[V110_BUFSIZE]; /* incomplete V110 matrices     */
-} isdn_v110_stream;
-
-/*========================= End of V.110 stuff =============================*/
-
-/*======================= Start of general stuff ===========================*/
-
-typedef struct {
-       char *next;
-       char *private;
-} infostruct;
-
-#define DRV_FLAG_RUNNING 1
-#define DRV_FLAG_REJBUS  2
-#define DRV_FLAG_LOADED  4
-
-/* Description of hardware-level-driver */
-typedef struct _isdn_driver {
-       ulong               online;           /* Channel-Online flags             */
-       ulong               flags;            /* Misc driver Flags                */
-       int                 locks;            /* Number of locks for this driver  */
-       int                 channels;         /* Number of channels               */
-       wait_queue_head_t   st_waitq;         /* Wait-Queue for status-read's     */
-       int                 maxbufsize;       /* Maximum Buffersize supported     */
-       unsigned long       pktcount;         /* Until now: unused                */
-       int                 stavail;          /* Chars avail on Status-device     */
-       isdn_if            *interface;        /* Interface to driver              */
-       int                *rcverr;           /* Error-counters for B-Ch.-receive */
-       int                *rcvcount;         /* Byte-counters for B-Ch.-receive  */
-#ifdef CONFIG_ISDN_AUDIO
-       unsigned long      DLEflag;           /* Flags: Insert DLE at next read   */
-#endif
-       struct sk_buff_head *rpqueue;         /* Pointers to start of Rcv-Queue   */
-       wait_queue_head_t  *rcv_waitq;       /* Wait-Queues for B-Channel-Reads  */
-       wait_queue_head_t  *snd_waitq;       /* Wait-Queue for B-Channel-Send's  */
-       char               msn2eaz[10][ISDN_MSNLEN];  /* Mapping-Table MSN->EAZ   */
-} isdn_driver_t;
-
-/* Main driver-data */
-typedef struct isdn_devt {
-       struct module     *owner;
-       spinlock_t        lock;
-       unsigned short    flags;                      /* Bitmapped Flags:           */
-       int               drivers;                    /* Current number of drivers  */
-       int               channels;                   /* Current number of channels */
-       int               net_verbose;                /* Verbose-Flag               */
-       int               modempoll;                  /* Flag: tty-read active      */
-       spinlock_t        timerlock;
-       int               tflags;                     /* Timer-Flags:               */
-       /*  see ISDN_TIMER_..defines  */
-       int               global_flags;
-       infostruct        *infochain;                 /* List of open info-devs.    */
-       wait_queue_head_t info_waitq;                 /* Wait-Queue for isdninfo    */
-       struct timer_list timer;                      /* Misc.-function Timer       */
-       int               chanmap[ISDN_MAX_CHANNELS]; /* Map minor->device-channel  */
-       int               drvmap[ISDN_MAX_CHANNELS];  /* Map minor->driver-index    */
-       int               usage[ISDN_MAX_CHANNELS];   /* Used by tty/ip/voice       */
-       char              num[ISDN_MAX_CHANNELS][ISDN_MSNLEN];
-       /* Remote number of active ch.*/
-       int               m_idx[ISDN_MAX_CHANNELS];   /* Index for mdm....          */
-       isdn_driver_t     *drv[ISDN_MAX_DRIVERS];     /* Array of drivers           */
-       isdn_net_dev      *netdev;                    /* Linked list of net-if's    */
-       char              drvid[ISDN_MAX_DRIVERS][20];/* Driver-ID                 */
-       struct task_struct *profd;                    /* For iprofd                 */
-       isdn_modem_t      mdm;                        /* tty-driver-data            */
-       isdn_net_dev      *rx_netdev[ISDN_MAX_CHANNELS]; /* rx netdev-pointers     */
-       isdn_net_dev      *st_netdev[ISDN_MAX_CHANNELS]; /* stat netdev-pointers   */
-       ulong             ibytes[ISDN_MAX_CHANNELS];  /* Statistics incoming bytes  */
-       ulong             obytes[ISDN_MAX_CHANNELS];  /* Statistics outgoing bytes  */
-       int               v110emu[ISDN_MAX_CHANNELS]; /* V.110 emulator-mode 0=none */
-       atomic_t          v110use[ISDN_MAX_CHANNELS]; /* Usage-Semaphore for stream */
-       isdn_v110_stream  *v110[ISDN_MAX_CHANNELS];   /* V.110 private data         */
-       struct mutex      mtx;                        /* serialize list access*/
-       unsigned long     global_features;
-} isdn_dev;
-
-extern isdn_dev *dev;
-
-
-#endif /* __ISDN_H__ */
 
+++ /dev/null
-/* $Id: isdn_divertif.h,v 1.4.6.1 2001/09/23 22:25:05 kai Exp $
- *
- * Header for the diversion supplementary interface for i4l.
- *
- * Author    Werner Cornelius (werner@titro.de)
- * Copyright by Werner Cornelius (werner@titro.de)
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-#ifndef _LINUX_ISDN_DIVERTIF_H
-#define _LINUX_ISDN_DIVERTIF_H
-
-#include <linux/isdnif.h>
-#include <linux/types.h>
-#include <uapi/linux/isdn_divertif.h>
-
-/***************************************************************/
-/* structure exchanging data between isdn hl and divert module */
-/***************************************************************/ 
-typedef struct
-  { ulong if_magic; /* magic info and version */
-    int cmd; /* command */
-    int (*stat_callback)(isdn_ctrl *); /* supplied by divert module when calling */
-    int (*ll_cmd)(isdn_ctrl *); /* supplied by hl on return */
-    char * (*drv_to_name)(int); /* map a driver id to name, supplied by hl */
-    int (*name_to_drv)(char *); /* map a driver id to name, supplied by hl */
-  } isdn_divert_if;
-
-/*********************/
-/* function register */
-/*********************/
-extern int DIVERT_REG_NAME(isdn_divert_if *);
-#endif /* _LINUX_ISDN_DIVERTIF_H */
 
+++ /dev/null
-/* Linux ISDN subsystem, sync PPP, interface to ipppd
- *
- * Copyright 1994-1999  by Fritz Elfert (fritz@isdn4linux.de)
- * Copyright 1995,96    Thinking Objects Software GmbH Wuerzburg
- * Copyright 1995,96    by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
- * Copyright 2000-2002  by Kai Germaschewski (kai@germaschewski.name)
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-#ifndef _LINUX_ISDN_PPP_H
-#define _LINUX_ISDN_PPP_H
-
-
-
-
-#ifdef CONFIG_IPPP_FILTER
-#include <linux/filter.h>
-#endif
-#include <uapi/linux/isdn_ppp.h>
-
-#define DECOMP_ERR_NOMEM       (-10)
-
-#define MP_END_FRAG    0x40
-#define MP_BEGIN_FRAG  0x80
-
-#define MP_MAX_QUEUE_LEN       16
-
-/*
- * We need a way for the decompressor to influence the generation of CCP
- * Reset-Requests in a variety of ways. The decompressor is already returning
- * a lot of information (generated skb length, error conditions) so we use
- * another parameter. This parameter is a pointer to a structure which is
- * to be marked valid by the decompressor and only in this case is ever used.
- * Furthermore, the only case where this data is used is when the decom-
- * pressor returns DECOMP_ERROR.
- *
- * We use this same struct for the reset entry of the compressor to commu-
- * nicate to its caller how to deal with sending of a Reset Ack. In this
- * case, expra is not used, but other options still apply (suppressing
- * sending with rsend, appending arbitrary data, etc).
- */
-
-#define IPPP_RESET_MAXDATABYTES        32
-
-struct isdn_ppp_resetparams {
-  unsigned char valid:1;       /* rw Is this structure filled at all ? */
-  unsigned char rsend:1;       /* rw Should we send one at all ? */
-  unsigned char idval:1;       /* rw Is the id field valid ? */
-  unsigned char dtval:1;       /* rw Is the data field valid ? */
-  unsigned char expra:1;       /* rw Is an Ack expected for this Req ? */
-  unsigned char id;            /* wo Send CCP ResetReq with this id */
-  unsigned short maxdlen;      /* ro Max bytes to be stored in data field */
-  unsigned short dlen;         /* rw Bytes stored in data field */
-  unsigned char *data;         /* wo Data for ResetReq info field */
-};
-
-/*
- * this is an 'old friend' from ppp-comp.h under a new name 
- * check the original include for more information
- */
-struct isdn_ppp_compressor {
-  struct isdn_ppp_compressor *next, *prev;
-  struct module *owner;
-  int num; /* CCP compression protocol number */
-  
-  void *(*alloc) (struct isdn_ppp_comp_data *);
-  void (*free) (void *state);
-  int  (*init) (void *state, struct isdn_ppp_comp_data *,
-               int unit,int debug);
-  
-  /* The reset entry needs to get more exact information about the
-     ResetReq or ResetAck it was called with. The parameters are
-     obvious. If reset is called without a Req or Ack frame which
-     could be handed into it, code MUST be set to 0. Using rsparm,
-     the reset entry can control if and how a ResetAck is returned. */
-  
-  void (*reset) (void *state, unsigned char code, unsigned char id,
-                unsigned char *data, unsigned len,
-                struct isdn_ppp_resetparams *rsparm);
-  
-  int  (*compress) (void *state, struct sk_buff *in,
-                   struct sk_buff *skb_out, int proto);
-  
-       int  (*decompress) (void *state,struct sk_buff *in,
-                           struct sk_buff *skb_out,
-                           struct isdn_ppp_resetparams *rsparm);
-  
-  void (*incomp) (void *state, struct sk_buff *in,int proto);
-  void (*stat) (void *state, struct compstat *stats);
-};
-
-extern int isdn_ppp_register_compressor(struct isdn_ppp_compressor *);
-extern int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *);
-extern int isdn_ppp_dial_slave(char *);
-extern int isdn_ppp_hangup_slave(char *);
-
-typedef struct {
-  unsigned long seqerrs;
-  unsigned long frame_drops;
-  unsigned long overflows;
-  unsigned long max_queue_len;
-} isdn_mppp_stats;
-
-typedef struct {
-  int mp_mrru;                        /* unused                             */
-  struct sk_buff * frags;      /* fragments sl list -- use skb->next */
-  long frames;                 /* number of frames in the frame list */
-  unsigned int seq;            /* last processed packet seq #: any packets
-                                * with smaller seq # will be dropped
-                                * unconditionally */
-  spinlock_t lock;
-  int ref_ct;                           
-  /* statistics */
-  isdn_mppp_stats stats;
-} ippp_bundle;
-
-#define NUM_RCV_BUFFS     64
-
-struct ippp_buf_queue {
-  struct ippp_buf_queue *next;
-  struct ippp_buf_queue *last;
-  char *buf;                 /* NULL here indicates end of queue */
-  int len;
-};
-
-/* The data structure for one CCP reset transaction */
-enum ippp_ccp_reset_states {
-  CCPResetIdle,
-  CCPResetSentReq,
-  CCPResetRcvdReq,
-  CCPResetSentAck,
-  CCPResetRcvdAck
-};
-
-struct ippp_ccp_reset_state {
-  enum ippp_ccp_reset_states state;    /* State of this transaction */
-  struct ippp_struct *is;              /* Backlink to device stuff */
-  unsigned char id;                    /* Backlink id index */
-  unsigned char ta:1;                  /* The timer is active (flag) */
-  unsigned char expra:1;               /* We expect a ResetAck at all */
-  int dlen;                            /* Databytes stored in data */
-  struct timer_list timer;             /* For timeouts/retries */
-  /* This is a hack but seems sufficient for the moment. We do not want
-     to have this be yet another allocation for some bytes, it is more
-     memory management overhead than the whole mess is worth. */
-  unsigned char data[IPPP_RESET_MAXDATABYTES];
-};
-
-/* The data structure keeping track of the currently outstanding CCP Reset
-   transactions. */
-struct ippp_ccp_reset {
-  struct ippp_ccp_reset_state *rs[256];        /* One per possible id */
-  unsigned char lastid;                        /* Last id allocated by the engine */
-};
-
-struct ippp_struct {
-  struct ippp_struct *next_link;
-  int state;
-  spinlock_t buflock;
-  struct ippp_buf_queue rq[NUM_RCV_BUFFS]; /* packet queue for isdn_ppp_read() */
-  struct ippp_buf_queue *first;  /* pointer to (current) first packet */
-  struct ippp_buf_queue *last;   /* pointer to (current) last used packet in queue */
-  wait_queue_head_t wq;
-  struct task_struct *tk;
-  unsigned int mpppcfg;
-  unsigned int pppcfg;
-  unsigned int mru;
-  unsigned int mpmru;
-  unsigned int mpmtu;
-  unsigned int maxcid;
-  struct isdn_net_local_s *lp;
-  int unit;
-  int minor;
-  unsigned int last_link_seqno;
-  long mp_seqno;
-#ifdef CONFIG_ISDN_PPP_VJ
-  unsigned char *cbuf;
-  struct slcompress *slcomp;
-#endif
-#ifdef CONFIG_IPPP_FILTER
-  struct bpf_prog *pass_filter;   /* filter for packets to pass */
-  struct bpf_prog *active_filter; /* filter for pkts to reset idle */
-#endif
-  unsigned long debug;
-  struct isdn_ppp_compressor *compressor,*decompressor;
-  struct isdn_ppp_compressor *link_compressor,*link_decompressor;
-  void *decomp_stat,*comp_stat,*link_decomp_stat,*link_comp_stat;
-  struct ippp_ccp_reset *reset;        /* Allocated on demand, may never be needed */
-  unsigned long compflags;
-};
-
-#endif /* _LINUX_ISDN_PPP_H */
 
+++ /dev/null
-/* $Id: isdnif.h,v 1.43.2.2 2004/01/12 23:08:35 keil Exp $
- *
- * Linux ISDN subsystem
- * Definition of the interface between the subsystem and its low-level drivers.
- *
- * Copyright 1994,95,96 by Fritz Elfert (fritz@isdn4linux.de)
- * Copyright 1995,96    Thinking Objects Software GmbH Wuerzburg
- * 
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-#ifndef __ISDNIF_H__
-#define __ISDNIF_H__
-
-
-#include <linux/skbuff.h>
-#include <uapi/linux/isdnif.h>
-
-/***************************************************************************/
-/* Extensions made by Werner Cornelius (werner@ikt.de)                     */
-/*                                                                         */ 
-/* The proceed command holds a incoming call in a state to leave processes */
-/* enough time to check whether ist should be accepted.                    */
-/* The PROT_IO Command extends the interface to make protocol dependent    */
-/* features available (call diversion, call waiting...).                   */
-/*                                                                         */ 
-/* The PROT_IO Command is executed with the desired driver id and the arg  */
-/* parameter coded as follows:                                             */
-/* The lower 8 bits of arg contain the desired protocol from ISDN_PTYPE    */
-/* definitions. The upper 24 bits represent the protocol specific cmd/stat.*/
-/* Any additional data is protocol and command specific.                   */
-/* This mechanism also applies to the statcallb callback STAT_PROT.        */    
-/*                                                                         */
-/* This suggested extension permits an easy expansion of protocol specific */
-/* handling. Extensions may be added at any time without changing the HL   */
-/* driver code and not getting conflicts without certifications.           */
-/* The well known CAPI 2.0 interface handles such extensions in a similar  */
-/* way. Perhaps a protocol specific module may be added and separately     */
-/* loaded and linked to the basic isdn module for handling.                */                    
-/***************************************************************************/
-
-/*****************/
-/* DSS1 commands */ 
-/*****************/
-#define DSS1_CMD_INVOKE       ((0x00 << 8) | ISDN_PTYPE_EURO)   /* invoke a supplementary service */
-#define DSS1_CMD_INVOKE_ABORT ((0x01 << 8) | ISDN_PTYPE_EURO)   /* abort a invoke cmd */
-
-/*******************************/
-/* DSS1 Status callback values */
-/*******************************/
-#define DSS1_STAT_INVOKE_RES  ((0x80 << 8) | ISDN_PTYPE_EURO)   /* Result for invocation */
-#define DSS1_STAT_INVOKE_ERR  ((0x81 << 8) | ISDN_PTYPE_EURO)   /* Error Return for invocation */
-#define DSS1_STAT_INVOKE_BRD  ((0x82 << 8) | ISDN_PTYPE_EURO)   /* Deliver invoke broadcast info */
-
-
-/*********************************************************************/
-/* structures for DSS1 commands and callback                         */
-/*                                                                   */
-/* An action is invoked by sending a DSS1_CMD_INVOKE. The ll_id, proc*/
-/* timeout, datalen and data fields must be set before calling.      */
-/*                                                                   */
-/* The return value is a positive hl_id value also delivered in the  */
-/* hl_id field. A value of zero signals no more left hl_id capacitys.*/
-/* A negative return value signals errors in LL. So if the return    */
-/* value is <= 0 no action in LL will be taken -> request ignored    */
-/*                                                                   */
-/* The timeout field must be filled with a positive value specifying */
-/* the amount of time the INVOKED process waits for a reaction from  */
-/* the network.                                                      */
-/* If a response (either error or result) is received during this    */
-/* intervall, a reporting callback is initiated and the process will */
-/* be deleted, the hl identifier will be freed.                      */
-/* If no response is received during the specified intervall, a error*/
-/* callback is initiated with timeout set to -1 and a datalen set    */
-/* to 0.                                                             */
-/* If timeout is set to a value <= 0 during INVOCATION the process is*/
-/* immediately deleted after sending the data. No callback occurs !  */
-/*                                                                   */
-/* A currently waiting process may be aborted with INVOKE_ABORT. No  */
-/* callback will occur when a process has been aborted.              */
-/*                                                                   */
-/* Broadcast invoke frames from the network are reported via the     */
-/* STAT_INVOKE_BRD callback. The ll_id is set to 0, the other fields */
-/* are supplied by the network and not by the HL.                    */   
-/*********************************************************************/
-
-/*****************/
-/* NI1 commands */ 
-/*****************/
-#define NI1_CMD_INVOKE       ((0x00 << 8) | ISDN_PTYPE_NI1)   /* invoke a supplementary service */
-#define NI1_CMD_INVOKE_ABORT ((0x01 << 8) | ISDN_PTYPE_NI1)   /* abort a invoke cmd */
-
-/*******************************/
-/* NI1 Status callback values */
-/*******************************/
-#define NI1_STAT_INVOKE_RES  ((0x80 << 8) | ISDN_PTYPE_NI1)   /* Result for invocation */
-#define NI1_STAT_INVOKE_ERR  ((0x81 << 8) | ISDN_PTYPE_NI1)   /* Error Return for invocation */
-#define NI1_STAT_INVOKE_BRD  ((0x82 << 8) | ISDN_PTYPE_NI1)   /* Deliver invoke broadcast info */
-
-typedef struct
-  { ulong ll_id; /* ID supplied by LL when executing    */
-                /* a command and returned by HL for    */
-                 /* INVOKE_RES and INVOKE_ERR           */
-    int hl_id;   /* ID supplied by HL when called       */
-                 /* for executing a cmd and delivered   */
-                 /* for results and errors              */
-                 /* must be supplied by LL when aborting*/  
-    int proc;    /* invoke procedure used by CMD_INVOKE */
-                 /* returned by callback and broadcast  */ 
-    int timeout; /* timeout for INVOKE CMD in ms        */
-                 /* -1  in stat callback when timed out */
-                 /* error value when error callback     */
-    int datalen; /* length of cmd or stat data          */
-    u_char *data;/* pointer to data delivered or send   */
-  } isdn_cmd_stat;
-
-/*
- * Commands from linklevel to lowlevel
- *
- */
-#define ISDN_CMD_IOCTL    0       /* Perform ioctl                         */
-#define ISDN_CMD_DIAL     1       /* Dial out                              */
-#define ISDN_CMD_ACCEPTD  2       /* Accept an incoming call on D-Chan.    */
-#define ISDN_CMD_ACCEPTB  3       /* Request B-Channel connect.            */
-#define ISDN_CMD_HANGUP   4       /* Hangup                                */
-#define ISDN_CMD_CLREAZ   5       /* Clear EAZ(s) of channel               */
-#define ISDN_CMD_SETEAZ   6       /* Set EAZ(s) of channel                 */
-#define ISDN_CMD_GETEAZ   7       /* Get EAZ(s) of channel                 */
-#define ISDN_CMD_SETSIL   8       /* Set Service-Indicator-List of channel */
-#define ISDN_CMD_GETSIL   9       /* Get Service-Indicator-List of channel */
-#define ISDN_CMD_SETL2   10       /* Set B-Chan. Layer2-Parameter          */
-#define ISDN_CMD_GETL2   11       /* Get B-Chan. Layer2-Parameter          */
-#define ISDN_CMD_SETL3   12       /* Set B-Chan. Layer3-Parameter          */
-#define ISDN_CMD_GETL3   13       /* Get B-Chan. Layer3-Parameter          */
-// #define ISDN_CMD_LOCK    14       /* Signal usage by upper levels          */
-// #define ISDN_CMD_UNLOCK  15       /* Release usage-lock                    */
-#define ISDN_CMD_SUSPEND 16       /* Suspend connection                    */
-#define ISDN_CMD_RESUME  17       /* Resume connection                     */
-#define ISDN_CMD_PROCEED 18       /* Proceed with call establishment       */
-#define ISDN_CMD_ALERT   19       /* Alert after Proceeding                */
-#define ISDN_CMD_REDIR   20       /* Redir a incoming call                 */
-#define ISDN_CMD_PROT_IO 21       /* Protocol specific commands            */
-#define CAPI_PUT_MESSAGE 22       /* CAPI message send down or up          */
-#define ISDN_CMD_FAXCMD  23       /* FAX commands to HL-driver             */
-#define ISDN_CMD_AUDIO   24       /* DSP, DTMF, ... settings               */
-
-/*
- * Status-Values delivered from lowlevel to linklevel via
- * statcallb().
- *
- */
-#define ISDN_STAT_STAVAIL 256    /* Raw status-data available             */
-#define ISDN_STAT_ICALL   257    /* Incoming call detected                */
-#define ISDN_STAT_RUN     258    /* Signal protocol-code is running       */
-#define ISDN_STAT_STOP    259    /* Signal halt of protocol-code          */
-#define ISDN_STAT_DCONN   260    /* Signal D-Channel connect              */
-#define ISDN_STAT_BCONN   261    /* Signal B-Channel connect              */
-#define ISDN_STAT_DHUP    262    /* Signal D-Channel disconnect           */
-#define ISDN_STAT_BHUP    263    /* Signal B-Channel disconnect           */
-#define ISDN_STAT_CINF    264    /* Charge-Info                           */
-#define ISDN_STAT_LOAD    265    /* Signal new lowlevel-driver is loaded  */
-#define ISDN_STAT_UNLOAD  266    /* Signal unload of lowlevel-driver      */
-#define ISDN_STAT_BSENT   267    /* Signal packet sent                    */
-#define ISDN_STAT_NODCH   268    /* Signal no D-Channel                   */
-#define ISDN_STAT_ADDCH   269    /* Add more Channels                     */
-#define ISDN_STAT_CAUSE   270    /* Cause-Message                         */
-#define ISDN_STAT_ICALLW  271    /* Incoming call without B-chan waiting  */
-#define ISDN_STAT_REDIR   272    /* Redir result                          */
-#define ISDN_STAT_PROT    273    /* protocol IO specific callback         */
-#define ISDN_STAT_DISPLAY 274    /* deliver a received display message    */
-#define ISDN_STAT_L1ERR   275    /* Signal Layer-1 Error                  */
-#define ISDN_STAT_FAXIND  276    /* FAX indications from HL-driver        */
-#define ISDN_STAT_AUDIO   277    /* DTMF, DSP indications                 */
-#define ISDN_STAT_DISCH   278    /* Disable/Enable channel usage          */
-
-/*
- * Audio commands
- */
-#define ISDN_AUDIO_SETDD       0       /* Set DTMF detection           */
-#define ISDN_AUDIO_DTMF                1       /* Rx/Tx DTMF                   */
-
-/*
- * Values for errcode field
- */
-#define ISDN_STAT_L1ERR_SEND 1
-#define ISDN_STAT_L1ERR_RECV 2
-
-/*
- * Values for feature-field of interface-struct.
- */
-/* Layer 2 */
-#define ISDN_FEATURE_L2_X75I    (0x0001 << ISDN_PROTO_L2_X75I)
-#define ISDN_FEATURE_L2_X75UI   (0x0001 << ISDN_PROTO_L2_X75UI)
-#define ISDN_FEATURE_L2_X75BUI  (0x0001 << ISDN_PROTO_L2_X75BUI)
-#define ISDN_FEATURE_L2_HDLC    (0x0001 << ISDN_PROTO_L2_HDLC)
-#define ISDN_FEATURE_L2_TRANS   (0x0001 << ISDN_PROTO_L2_TRANS)
-#define ISDN_FEATURE_L2_X25DTE  (0x0001 << ISDN_PROTO_L2_X25DTE)
-#define ISDN_FEATURE_L2_X25DCE  (0x0001 << ISDN_PROTO_L2_X25DCE)
-#define ISDN_FEATURE_L2_V11096  (0x0001 << ISDN_PROTO_L2_V11096)
-#define ISDN_FEATURE_L2_V11019  (0x0001 << ISDN_PROTO_L2_V11019)
-#define ISDN_FEATURE_L2_V11038  (0x0001 << ISDN_PROTO_L2_V11038)
-#define ISDN_FEATURE_L2_MODEM   (0x0001 << ISDN_PROTO_L2_MODEM)
-#define ISDN_FEATURE_L2_FAX    (0x0001 << ISDN_PROTO_L2_FAX)
-#define ISDN_FEATURE_L2_HDLC_56K (0x0001 << ISDN_PROTO_L2_HDLC_56K)
-
-#define ISDN_FEATURE_L2_MASK    (0x0FFFF) /* Max. 16 protocols */
-#define ISDN_FEATURE_L2_SHIFT   (0)
-
-/* Layer 3 */
-#define ISDN_FEATURE_L3_TRANS   (0x10000 << ISDN_PROTO_L3_TRANS)
-#define ISDN_FEATURE_L3_TRANSDSP (0x10000 << ISDN_PROTO_L3_TRANSDSP)
-#define ISDN_FEATURE_L3_FCLASS2        (0x10000 << ISDN_PROTO_L3_FCLASS2)
-#define ISDN_FEATURE_L3_FCLASS1        (0x10000 << ISDN_PROTO_L3_FCLASS1)
-
-#define ISDN_FEATURE_L3_MASK    (0x0FF0000) /* Max. 8 Protocols */
-#define ISDN_FEATURE_L3_SHIFT   (16)
-
-/* Signaling */
-#define ISDN_FEATURE_P_UNKNOWN  (0x1000000 << ISDN_PTYPE_UNKNOWN)
-#define ISDN_FEATURE_P_1TR6     (0x1000000 << ISDN_PTYPE_1TR6)
-#define ISDN_FEATURE_P_EURO     (0x1000000 << ISDN_PTYPE_EURO)
-#define ISDN_FEATURE_P_NI1      (0x1000000 << ISDN_PTYPE_NI1)
-
-#define ISDN_FEATURE_P_MASK     (0x0FF000000) /* Max. 8 Protocols */
-#define ISDN_FEATURE_P_SHIFT    (24)
-
-typedef struct setup_parm {
-    unsigned char phone[32];   /* Remote Phone-Number */
-    unsigned char eazmsn[32];  /* Local EAZ or MSN    */
-    unsigned char si1;      /* Service Indicator 1 */
-    unsigned char si2;      /* Service Indicator 2 */
-    unsigned char plan;     /* Numbering plan      */
-    unsigned char screen;   /* Screening info      */
-} setup_parm;
-
-
-#ifdef CONFIG_ISDN_TTY_FAX
-/* T.30 Fax G3 */
-
-#define FAXIDLEN 21
-
-typedef struct T30_s {
-       /* session parameters */
-       __u8 resolution;
-       __u8 rate;
-       __u8 width;
-       __u8 length;
-       __u8 compression;
-       __u8 ecm;
-       __u8 binary;
-       __u8 scantime;
-       __u8 id[FAXIDLEN];
-       /* additional parameters */
-       __u8 phase;
-       __u8 direction;
-       __u8 code;
-       __u8 badlin;
-       __u8 badmul;
-       __u8 bor;
-       __u8 fet;
-       __u8 pollid[FAXIDLEN];
-       __u8 cq;
-       __u8 cr;
-       __u8 ctcrty;
-       __u8 minsp;
-       __u8 phcto;
-       __u8 rel;
-       __u8 nbc;
-       /* remote station parameters */
-       __u8 r_resolution;
-       __u8 r_rate;
-       __u8 r_width;
-       __u8 r_length;
-       __u8 r_compression;
-       __u8 r_ecm;
-       __u8 r_binary;
-       __u8 r_scantime;
-       __u8 r_id[FAXIDLEN];
-       __u8 r_code;
-} __packed T30_s;
-
-#define ISDN_TTY_FAX_CONN_IN   0
-#define ISDN_TTY_FAX_CONN_OUT  1
-
-#define ISDN_TTY_FAX_FCON      0
-#define ISDN_TTY_FAX_DIS       1
-#define ISDN_TTY_FAX_FTT       2
-#define ISDN_TTY_FAX_MCF       3
-#define ISDN_TTY_FAX_DCS       4
-#define ISDN_TTY_FAX_TRAIN_OK  5
-#define ISDN_TTY_FAX_EOP       6
-#define ISDN_TTY_FAX_EOM       7
-#define ISDN_TTY_FAX_MPS       8
-#define ISDN_TTY_FAX_DTC       9
-#define ISDN_TTY_FAX_RID       10
-#define ISDN_TTY_FAX_HNG       11
-#define ISDN_TTY_FAX_DT        12
-#define ISDN_TTY_FAX_FCON_I    13
-#define ISDN_TTY_FAX_DR        14
-#define ISDN_TTY_FAX_ET        15
-#define ISDN_TTY_FAX_CFR       16
-#define ISDN_TTY_FAX_PTS       17
-#define ISDN_TTY_FAX_SENT      18
-
-#define ISDN_FAX_PHASE_IDLE    0
-#define ISDN_FAX_PHASE_A       1
-#define ISDN_FAX_PHASE_B       2
-#define ISDN_FAX_PHASE_C       3
-#define ISDN_FAX_PHASE_D       4
-#define ISDN_FAX_PHASE_E       5
-
-#endif /* TTY_FAX */
-
-#define ISDN_FAX_CLASS1_FAE    0
-#define ISDN_FAX_CLASS1_FTS    1
-#define ISDN_FAX_CLASS1_FRS    2
-#define ISDN_FAX_CLASS1_FTM    3
-#define ISDN_FAX_CLASS1_FRM    4
-#define ISDN_FAX_CLASS1_FTH    5
-#define ISDN_FAX_CLASS1_FRH    6
-#define ISDN_FAX_CLASS1_CTRL   7
-
-#define ISDN_FAX_CLASS1_OK     0
-#define ISDN_FAX_CLASS1_CONNECT        1
-#define ISDN_FAX_CLASS1_NOCARR 2
-#define ISDN_FAX_CLASS1_ERROR  3
-#define ISDN_FAX_CLASS1_FCERROR        4
-#define ISDN_FAX_CLASS1_QUERY  5
-
-typedef struct {
-       __u8    cmd;
-       __u8    subcmd;
-       __u8    para[50];
-} aux_s;
-
-#define AT_COMMAND     0
-#define AT_EQ_VALUE    1
-#define AT_QUERY       2
-#define AT_EQ_QUERY    3
-
-/* CAPI structs */
-
-/* this is compatible to the old union size */
-#define MAX_CAPI_PARA_LEN 50
-
-typedef struct {
-       /* Header */
-       __u16 Length;
-       __u16 ApplId;
-       __u8 Command;
-       __u8 Subcommand;
-       __u16 Messagenumber;
-
-       /* Parameter */
-       union {
-               __u32 Controller;
-               __u32 PLCI;
-               __u32 NCCI;
-       } adr;
-       __u8 para[MAX_CAPI_PARA_LEN];
-} capi_msg;
-
-/*
- * Structure for exchanging above infos
- *
- */
-typedef struct {
-       int   driver;           /* Lowlevel-Driver-ID            */
-       int   command;          /* Command or Status (see above) */
-       ulong arg;              /* Additional Data               */
-       union {
-               ulong errcode;  /* Type of error with STAT_L1ERR        */
-               int length;     /* Amount of bytes sent with STAT_BSENT */
-               u_char num[50]; /* Additional Data                      */
-               setup_parm setup;/* For SETUP msg                       */
-               capi_msg cmsg;  /* For CAPI like messages               */
-               char display[85];/* display message data                */ 
-               isdn_cmd_stat isdn_io; /* ISDN IO-parameter/result      */
-               aux_s aux;      /* for modem commands/indications       */
-#ifdef CONFIG_ISDN_TTY_FAX
-               T30_s   *fax;   /* Pointer to ttys fax struct           */
-#endif
-               ulong userdata; /* User Data */
-       } parm;
-} isdn_ctrl;
-
-#define dss1_io    isdn_io
-#define ni1_io     isdn_io
-
-/*
- * The interface-struct itself (initialized at load-time of lowlevel-driver)
- *
- * See Documentation/isdn/INTERFACE for a description, how the communication
- * between the ISDN subsystem and its drivers is done.
- *
- */
-typedef struct {
-  struct module *owner;
-
-  /* Number of channels supported by this driver
-   */
-  int channels;
-
-  /* 
-   * Maximum Size of transmit/receive-buffer this driver supports.
-   */
-  int maxbufsize;
-
-  /* Feature-Flags for this driver.
-   * See defines ISDN_FEATURE_... for Values
-   */
-  unsigned long features;
-
-  /*
-   * Needed for calculating
-   * dev->hard_header_len = linklayer header + hl_hdrlen;
-   * Drivers, not supporting sk_buff's should set this to 0.
-   */
-  unsigned short hl_hdrlen;
-
-  /*
-   * Receive-Callback using sk_buff's
-   * Parameters:
-   *             int                    Driver-ID
-   *             int                    local channel-number (0 ...)
-   *             struct sk_buff *skb    received Data
-   */
-  void (*rcvcallb_skb)(int, int, struct sk_buff *);
-
-  /* Status-Callback
-   * Parameters:
-   *             isdn_ctrl*
-   *                   driver  = Driver ID.
-   *                   command = One of above ISDN_STAT_... constants.
-   *                   arg     = depending on status-type.
-   *                   num     = depending on status-type.
-   */
-  int (*statcallb)(isdn_ctrl*);
-
-  /* Send command
-   * Parameters:
-   *             isdn_ctrl*
-   *                   driver  = Driver ID.
-   *                   command = One of above ISDN_CMD_... constants.
-   *                   arg     = depending on command.
-   *                   num     = depending on command.
-   */
-  int (*command)(isdn_ctrl*);
-
-  /*
-   * Send data using sk_buff's
-   * Parameters:
-   *             int                    driverId
-   *             int                    local channel-number (0...)
-   *             int                    Flag: Need ACK for this packet.
-   *             struct sk_buff *skb    Data to send
-   */
-  int (*writebuf_skb) (int, int, int, struct sk_buff *);
-
-  /* Send raw D-Channel-Commands
-   * Parameters:
-   *             u_char pointer data
-   *             int    length of data
-   *             int    driverId
-   *             int    local channel-number (0 ...)
-   */
-  int (*writecmd)(const u_char __user *, int, int, int);
-
-  /* Read raw Status replies
-   *             u_char pointer data (volatile)
-   *             int    length of buffer
-   *             int    driverId
-   *             int    local channel-number (0 ...)
-   */
-  int (*readstat)(u_char __user *, int, int, int);
-
-  char id[20];
-} isdn_if;
-
-/*
- * Function which must be called by lowlevel-driver at loadtime with
- * the following fields of above struct set:
- *
- * channels     Number of channels that will be supported.
- * hl_hdrlen    Space to preserve in sk_buff's when sending. Drivers, not
- *              supporting sk_buff's should set this to 0.
- * command      Address of Command-Handler.
- * features     Bitwise coded Features of this driver. (use ISDN_FEATURE_...)
- * writebuf_skb Address of Skbuff-Send-Handler.
- * writecmd        "    "  D-Channel  " which accepts raw D-Ch-Commands.
- * readstat        "    "  D-Channel  " which delivers raw Status-Data.
- *
- * The linklevel-driver fills the following fields:
- *
- * channels      Driver-ID assigned to this driver. (Must be used on all
- *               subsequent callbacks.
- * rcvcallb_skb  Address of handler for received Skbuff's.
- * statcallb        "    "     "    for status-changes.
- *
- */
-extern int register_isdn(isdn_if*);
-#include <linux/uaccess.h>
-
-#endif /* __ISDNIF_H__ */
 
+++ /dev/null
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * wanrouter.h Legacy declarations kept around until X25 is removed
- */
-
-#ifndef        _ROUTER_H
-#define        _ROUTER_H
-
-#include <uapi/linux/wanrouter.h>
-
-#endif /* _ROUTER_H */
 
+++ /dev/null
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/* $Id: isdn.h,v 1.125.2.3 2004/02/10 01:07:14 keil Exp $
- *
- * Main header for the Linux ISDN subsystem (linklevel).
- *
- * Copyright 1994,95,96 by Fritz Elfert (fritz@isdn4linux.de)
- * Copyright 1995,96    by Thinking Objects Software GmbH Wuerzburg
- * Copyright 1995,96    by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
- * 
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#ifndef _UAPI__ISDN_H__
-#define _UAPI__ISDN_H__
-
-#include <linux/ioctl.h>
-#include <linux/tty.h>
-
-#define ISDN_MAX_DRIVERS    32
-#define ISDN_MAX_CHANNELS   64
-
-/* New ioctl-codes */
-#define IIOCNETAIF  _IO('I',1)
-#define IIOCNETDIF  _IO('I',2)
-#define IIOCNETSCF  _IO('I',3)
-#define IIOCNETGCF  _IO('I',4)
-#define IIOCNETANM  _IO('I',5)
-#define IIOCNETDNM  _IO('I',6)
-#define IIOCNETGNM  _IO('I',7)
-#define IIOCGETSET  _IO('I',8) /* no longer supported */
-#define IIOCSETSET  _IO('I',9) /* no longer supported */
-#define IIOCSETVER  _IO('I',10)
-#define IIOCNETHUP  _IO('I',11)
-#define IIOCSETGST  _IO('I',12)
-#define IIOCSETBRJ  _IO('I',13)
-#define IIOCSIGPRF  _IO('I',14)
-#define IIOCGETPRF  _IO('I',15)
-#define IIOCSETPRF  _IO('I',16)
-#define IIOCGETMAP  _IO('I',17)
-#define IIOCSETMAP  _IO('I',18)
-#define IIOCNETASL  _IO('I',19)
-#define IIOCNETDIL  _IO('I',20)
-#define IIOCGETCPS  _IO('I',21)
-#define IIOCGETDVR  _IO('I',22)
-#define IIOCNETLCR  _IO('I',23) /* dwabc ioctl for LCR from isdnlog */
-#define IIOCNETDWRSET  _IO('I',24) /* dwabc ioctl to reset abc-values to default on a net-interface */
-
-#define IIOCNETALN  _IO('I',32)
-#define IIOCNETDLN  _IO('I',33)
-
-#define IIOCNETGPN  _IO('I',34)
-
-#define IIOCDBGVAR  _IO('I',127)
-
-#define IIOCDRVCTL  _IO('I',128)
-
-/* cisco hdlck device private ioctls */
-#define SIOCGKEEPPERIOD        (SIOCDEVPRIVATE + 0)
-#define SIOCSKEEPPERIOD        (SIOCDEVPRIVATE + 1)
-#define SIOCGDEBSERINT (SIOCDEVPRIVATE + 2)
-#define SIOCSDEBSERINT (SIOCDEVPRIVATE + 3)
-
-/* Packet encapsulations for net-interfaces */
-#define ISDN_NET_ENCAP_ETHER      0
-#define ISDN_NET_ENCAP_RAWIP      1
-#define ISDN_NET_ENCAP_IPTYP      2
-#define ISDN_NET_ENCAP_CISCOHDLC  3 /* Without SLARP and keepalive */
-#define ISDN_NET_ENCAP_SYNCPPP    4
-#define ISDN_NET_ENCAP_UIHDLC     5
-#define ISDN_NET_ENCAP_CISCOHDLCK 6 /* With SLARP and keepalive    */
-#define ISDN_NET_ENCAP_X25IFACE   7 /* Documentation/networking/x25-iface.txt */
-#define ISDN_NET_ENCAP_MAX_ENCAP  ISDN_NET_ENCAP_X25IFACE
-
-/* Facility which currently uses an ISDN-channel */
-#define ISDN_USAGE_NONE       0
-#define ISDN_USAGE_RAW        1
-#define ISDN_USAGE_MODEM      2
-#define ISDN_USAGE_NET        3
-#define ISDN_USAGE_VOICE      4
-#define ISDN_USAGE_FAX        5
-#define ISDN_USAGE_MASK       7 /* Mask to get plain usage */
-#define ISDN_USAGE_DISABLED  32 /* This bit is set, if channel is disabled */
-#define ISDN_USAGE_EXCLUSIVE 64 /* This bit is set, if channel is exclusive */
-#define ISDN_USAGE_OUTGOING 128 /* This bit is set, if channel is outgoing  */
-
-#define ISDN_MODEM_NUMREG    24        /* Number of Modem-Registers        */
-#define ISDN_LMSNLEN         255 /* Length of tty's Listen-MSN string */
-#define ISDN_CMSGLEN        50  /* Length of CONNECT-Message to add for Modem */
-
-#define ISDN_MSNLEN          32
-#define NET_DV 0x06  /* Data version for isdn_net_ioctl_cfg   */
-#define TTY_DV 0x06  /* Data version for iprofd etc.          */
-
-#define INF_DV 0x01  /* Data version for /dev/isdninfo        */
-
-typedef struct {
-  char drvid[25];
-  unsigned long arg;
-} isdn_ioctl_struct;
-
-typedef struct {
-  char name[10];
-  char phone[ISDN_MSNLEN];
-  int  outgoing;
-} isdn_net_ioctl_phone;
-
-typedef struct {
-  char name[10];     /* Name of interface                     */
-  char master[10];   /* Name of Master for Bundling           */
-  char slave[10];    /* Name of Slave for Bundling            */
-  char eaz[256];     /* EAZ/MSN                               */
-  char drvid[25];    /* DriverId for Bindings                 */
-  int  onhtime;      /* Hangup-Timeout                        */
-  int  charge;       /* Charge-Units                          */
-  int  l2_proto;     /* Layer-2 protocol                      */
-  int  l3_proto;     /* Layer-3 protocol                      */
-  int  p_encap;      /* Encapsulation                         */
-  int  exclusive;    /* Channel, if bound exclusive           */
-  int  dialmax;      /* Dial Retry-Counter                    */
-  int  slavedelay;   /* Delay until slave starts up           */
-  int  cbdelay;      /* Delay before Callback                 */
-  int  chargehup;    /* Flag: Charge-Hangup                   */
-  int  ihup;         /* Flag: Hangup-Timeout on incoming line */
-  int  secure;       /* Flag: Secure                          */
-  int  callback;     /* Flag: Callback                        */
-  int  cbhup;        /* Flag: Reject Call before Callback     */
-  int  pppbind;      /* ippp device for bindings              */
-  int  chargeint;    /* Use fixed charge interval length      */
-  int  triggercps;   /* BogoCPS needed for triggering slave   */
-  int  dialtimeout;  /* Dial-Timeout                          */
-  int  dialwait;     /* Time to wait after failed dial        */
-  int  dialmode;     /* Flag: off / on / auto                 */
-} isdn_net_ioctl_cfg;
-
-#define ISDN_NET_DIALMODE_MASK  0xC0    /* bits for status                */
-#define ISDN_NET_DM_OFF                0x00    /* this interface is stopped      */
-#define ISDN_NET_DM_MANUAL     0x40    /* this interface is on (manual)  */
-#define ISDN_NET_DM_AUTO       0x80    /* this interface is autodial     */
-#define ISDN_NET_DIALMODE(x) ((&(x))->flags & ISDN_NET_DIALMODE_MASK)
-
-
-#endif /* _UAPI__ISDN_H__ */
 
+++ /dev/null
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/* $Id: isdn_divertif.h,v 1.4.6.1 2001/09/23 22:25:05 kai Exp $
- *
- * Header for the diversion supplementary interface for i4l.
- *
- * Author    Werner Cornelius (werner@titro.de)
- * Copyright by Werner Cornelius (werner@titro.de)
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#ifndef _UAPI_LINUX_ISDN_DIVERTIF_H
-#define _UAPI_LINUX_ISDN_DIVERTIF_H
-
-/***********************************************************/
-/* magic value is also used to control version information */
-/***********************************************************/
-#define DIVERT_IF_MAGIC 0x25873401
-#define DIVERT_CMD_REG  0x00  /* register command */
-#define DIVERT_CMD_REL  0x01  /* release command */
-#define DIVERT_NO_ERR   0x00  /* return value no error */
-#define DIVERT_CMD_ERR  0x01  /* invalid cmd */
-#define DIVERT_VER_ERR  0x02  /* magic/version invalid */
-#define DIVERT_REG_ERR  0x03  /* module already registered */
-#define DIVERT_REL_ERR  0x04  /* module not registered */
-#define DIVERT_REG_NAME isdn_register_divert
-
-
-#endif /* _UAPI_LINUX_ISDN_DIVERTIF_H */
 
+++ /dev/null
-/* SPDX-License-Identifier: GPL-1.0+ WITH Linux-syscall-note */
-/* Linux ISDN subsystem, sync PPP, interface to ipppd
- *
- * Copyright 1994-1999  by Fritz Elfert (fritz@isdn4linux.de)
- * Copyright 1995,96    Thinking Objects Software GmbH Wuerzburg
- * Copyright 1995,96    by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
- * Copyright 2000-2002  by Kai Germaschewski (kai@germaschewski.name)
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#ifndef _UAPI_LINUX_ISDN_PPP_H
-#define _UAPI_LINUX_ISDN_PPP_H
-
-#define CALLTYPE_INCOMING 0x1
-#define CALLTYPE_OUTGOING 0x2
-#define CALLTYPE_CALLBACK 0x4
-
-#define IPPP_VERSION    "2.2.0"
-
-struct pppcallinfo
-{
-  int calltype;
-  unsigned char local_num[64];
-  unsigned char remote_num[64];
-  int charge_units;
-};
-
-#define PPPIOCGCALLINFO _IOWR('t',128,struct pppcallinfo)
-#define PPPIOCBUNDLE   _IOW('t',129,int)
-#define PPPIOCGMPFLAGS _IOR('t',130,int)
-#define PPPIOCSMPFLAGS _IOW('t',131,int)
-#define PPPIOCSMPMTU   _IOW('t',132,int)
-#define PPPIOCSMPMRU   _IOW('t',133,int)
-#define PPPIOCGCOMPRESSORS _IOR('t',134,unsigned long [8])
-#define PPPIOCSCOMPRESSOR _IOW('t',135,int)
-#define PPPIOCGIFNAME      _IOR('t',136, char [IFNAMSIZ] )
-
-
-#define SC_MP_PROT       0x00000200
-#define SC_REJ_MP_PROT   0x00000400
-#define SC_OUT_SHORT_SEQ 0x00000800
-#define SC_IN_SHORT_SEQ  0x00004000
-
-#define SC_DECOMP_ON           0x01
-#define SC_COMP_ON             0x02
-#define SC_DECOMP_DISCARD      0x04
-#define SC_COMP_DISCARD                0x08
-#define SC_LINK_DECOMP_ON      0x10
-#define SC_LINK_COMP_ON                0x20
-#define SC_LINK_DECOMP_DISCARD 0x40
-#define SC_LINK_COMP_DISCARD   0x80
-
-#define ISDN_PPP_COMP_MAX_OPTIONS 16
-
-#define IPPP_COMP_FLAG_XMIT 0x1
-#define IPPP_COMP_FLAG_LINK 0x2
-
-struct isdn_ppp_comp_data {
-  int num;
-  unsigned char options[ISDN_PPP_COMP_MAX_OPTIONS];
-  int optlen;
-  int flags;
-};
-
-#endif /* _UAPI_LINUX_ISDN_PPP_H */
 
+++ /dev/null
-/* SPDX-License-Identifier: GPL-1.0+ WITH Linux-syscall-note */
-/* $Id: isdnif.h,v 1.43.2.2 2004/01/12 23:08:35 keil Exp $
- *
- * Linux ISDN subsystem
- * Definition of the interface between the subsystem and its low-level drivers.
- *
- * Copyright 1994,95,96 by Fritz Elfert (fritz@isdn4linux.de)
- * Copyright 1995,96    Thinking Objects Software GmbH Wuerzburg
- * 
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#ifndef _UAPI__ISDNIF_H__
-#define _UAPI__ISDNIF_H__
-
-
-/*
- * Values for general protocol-selection
- */
-#define ISDN_PTYPE_UNKNOWN   0   /* Protocol undefined   */
-#define ISDN_PTYPE_1TR6      1   /* german 1TR6-protocol */
-#define ISDN_PTYPE_EURO      2   /* EDSS1-protocol       */
-#define ISDN_PTYPE_LEASED    3   /* for leased lines     */
-#define ISDN_PTYPE_NI1       4   /* US NI-1 protocol     */
-#define ISDN_PTYPE_MAX       7   /* Max. 8 Protocols     */
-
-/*
- * Values for Layer-2-protocol-selection
- */
-#define ISDN_PROTO_L2_X75I   0   /* X75/LAPB with I-Frames            */
-#define ISDN_PROTO_L2_X75UI  1   /* X75/LAPB with UI-Frames           */
-#define ISDN_PROTO_L2_X75BUI 2   /* X75/LAPB with UI-Frames           */
-#define ISDN_PROTO_L2_HDLC   3   /* HDLC                              */
-#define ISDN_PROTO_L2_TRANS  4   /* Transparent (Voice)               */
-#define ISDN_PROTO_L2_X25DTE 5   /* X25/LAPB DTE mode                 */
-#define ISDN_PROTO_L2_X25DCE 6   /* X25/LAPB DCE mode                 */
-#define ISDN_PROTO_L2_V11096 7   /* V.110 bitrate adaption 9600 Baud  */
-#define ISDN_PROTO_L2_V11019 8   /* V.110 bitrate adaption 19200 Baud */
-#define ISDN_PROTO_L2_V11038 9   /* V.110 bitrate adaption 38400 Baud */
-#define ISDN_PROTO_L2_MODEM  10  /* Analog Modem on Board */
-#define ISDN_PROTO_L2_FAX    11  /* Fax Group 2/3         */
-#define ISDN_PROTO_L2_HDLC_56K 12   /* HDLC 56k                          */
-#define ISDN_PROTO_L2_MAX    15  /* Max. 16 Protocols                 */
-
-/*
- * Values for Layer-3-protocol-selection
- */
-#define ISDN_PROTO_L3_TRANS    0       /* Transparent */
-#define ISDN_PROTO_L3_TRANSDSP 1       /* Transparent with DSP */
-#define ISDN_PROTO_L3_FCLASS2  2       /* Fax Group 2/3 CLASS 2 */
-#define ISDN_PROTO_L3_FCLASS1  3       /* Fax Group 2/3 CLASS 1 */
-#define ISDN_PROTO_L3_MAX      7       /* Max. 8 Protocols */
-
-
-#endif /* _UAPI__ISDNIF_H__ */
 
+++ /dev/null
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/*
- * wanrouter.h Legacy declarations kept around until X25 is removed
- */
-
-#ifndef _UAPI_ROUTER_H
-#define _UAPI_ROUTER_H
-
-/* 'state' defines */
-enum wan_states
-{
-       WAN_UNCONFIGURED,       /* link/channel is not configured */
-       WAN_DISCONNECTED,       /* link/channel is disconnected */
-       WAN_CONNECTING,         /* connection is in progress */
-       WAN_CONNECTED           /* link/channel is operational */
-};
-
-#endif /* _UAPI_ROUTER_H */