The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netisdn/i4b_ipr.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
    3  *
    4  * Redistribution and use in source and binary forms, with or without
    5  * modification, are permitted provided that the following conditions
    6  * are met:
    7  * 1. Redistributions of source code must retain the above copyright
    8  *    notice, this list of conditions and the following disclaimer.
    9  * 2. Redistributions in binary form must reproduce the above copyright
   10  *    notice, this list of conditions and the following disclaimer in the
   11  *    documentation and/or other materials provided with the distribution.
   12  *
   13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   23  * SUCH DAMAGE.
   24  *
   25  *---------------------------------------------------------------------------
   26  *
   27  *      i4b_ipr.c - isdn4bsd IP over raw HDLC ISDN network driver
   28  *      ---------------------------------------------------------
   29  *
   30  *      $Id: i4b_ipr.c,v 1.17 2005/02/26 22:39:49 perry Exp $
   31  *
   32  * $FreeBSD$
   33  *
   34  *      last edit-date: [Fri Jan  5 11:33:47 2001]
   35  *
   36  *---------------------------------------------------------------------------*
   37  *
   38  *      statistics counter usage (interface lifetime):
   39  *      ----------------------------------------------
   40  *      sc->sc_if.if_ipackets   # of received packets
   41  *      sc->sc_if.if_ierrors    # of error packets not going to upper layers
   42  *      sc->sc_if.if_opackets   # of transmitted packets
   43  *      sc->sc_if.if_oerrors    # of error packets not being transmitted
   44  *      sc->sc_if.if_collisions # of invalid ip packets after VJ decompression
   45  *      sc->sc_if.if_ibytes     # of bytes coming in from the line (before VJ)
   46  *      sc->sc_if.if_obytes     # of bytes going out to the line (after VJ)
   47  *      sc->sc_if.if_imcasts      (currently unused)
   48  *      sc->sc_if.if_omcasts    # of frames sent out of the fastqueue
   49  *      sc->sc_if.if_iqdrops    # of frames dropped on input because queue full
   50  *      sc->sc_if.if_noproto    # of frames dropped on output because !AF_INET
   51  *
   52  *      statistics counter usage (connection lifetime):
   53  *      -----------------------------------------------
   54  *      sc->sc_iinb             # of ISDN incoming bytes from HSCX
   55  *      sc->sc_ioutb            # of ISDN outgoing bytes from HSCX
   56  *      sc->sc_inb              # of incoming bytes after decompression
   57  *      sc->sc_outb             # of outgoing bytes before compression
   58  *
   59  *---------------------------------------------------------------------------*/
   60 
   61 #include <sys/cdefs.h>
   62 __KERNEL_RCSID(0, "$NetBSD: i4b_ipr.c,v 1.17 2005/02/26 22:39:49 perry Exp $");
   63 
   64 #include "irip.h"
   65 #include "opt_irip.h"
   66 
   67 #if NIRIP > 0
   68 
   69 #ifdef __FreeBSD__
   70 #include "opt_i4b.h"
   71 #endif
   72 
   73 #include <sys/param.h>
   74 #include <sys/systm.h>
   75 #include <sys/mbuf.h>
   76 #include <sys/socket.h>
   77 #include <sys/errno.h>
   78 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
   79 #include <sys/ioccom.h>
   80 #include <sys/sockio.h>
   81 #ifdef IPR_VJ
   82 #include <sys/malloc.h>
   83 #endif
   84 #else
   85 #include <sys/ioctl.h>
   86 #endif
   87 
   88 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
   89 #include <sys/callout.h>
   90 #endif
   91 
   92 #include <sys/kernel.h>
   93 #include <sys/protosw.h>
   94 
   95 #include <net/if.h>
   96 #include <net/if_types.h>
   97 #include <net/netisr.h>
   98 #include <net/route.h>
   99 
  100 #include <netinet/in.h>
  101 #include <netinet/in_systm.h>
  102 #include <netinet/in_var.h>
  103 #include <netinet/ip.h>
  104 
  105 #ifdef IRIP_VJ
  106 #include <net/slcompress.h>
  107 #define IPR_COMPRESS IFF_LINK0  /* compress TCP traffic */
  108 #define IPR_AUTOCOMP IFF_LINK1  /* auto-enable TCP compression */
  109 
  110 /*---------------------------------------------------------------------------
  111  * NOTICE: using NO separate buffer relies on the assumption, that the HSCX
  112  * IRQ handler _always_ allocates a single, continuous mbuf cluster large
  113  * enough to hold the maximum MTU size if the ipr interface !
  114  *
  115  * CAUTION: i have re-defined IPR_VJ_USEBUFFER because it makes problems
  116  *          with 2 i4b's back to back running cvs over ssh, cvs simply
  117  *          aborts because it gets bad data. Everything else (telnet/ftp?etc)
  118  *          functions fine.
  119  *---------------------------------------------------------------------------*/
  120 #define IPR_VJ_USEBUFFER        /* define to use an allocated separate buffer*/
  121                                 /* undef to uncompress in the mbuf itself    */
  122 #endif /* IRIP_VJ */
  123 
  124 #if defined(__FreeBSD_version) &&  __FreeBSD_version >= 400008
  125 #include "bpf.h"
  126 #else
  127 #include "bpfilter.h"
  128 #endif
  129 #if NBPFILTER > 0 || NBPF > 0
  130 #include <sys/time.h>
  131 #include <net/bpf.h>
  132 #endif
  133 
  134 #ifdef __FreeBSD__
  135 #include <machine/i4b_ioctl.h>
  136 #include <machine/i4b_debug.h>
  137 #else
  138 #include <netisdn/i4b_debug.h>
  139 #include <netisdn/i4b_ioctl.h>
  140 #endif
  141 
  142 #include <netisdn/i4b_global.h>
  143 #include <netisdn/i4b_mbuf.h>
  144 #include <netisdn/i4b_l3l4.h>
  145 
  146 #include <netisdn/i4b_l4.h>
  147 
  148 #ifndef __FreeBSD__
  149 #include <machine/cpu.h> /* For softnet */
  150 #endif
  151 
  152 #ifdef __FreeBSD__
  153 #define IPR_FMT "irip%d: "
  154 #define IPR_ARG(sc)     ((sc)->sc_if.if_unit)
  155 #define PDEVSTATIC      static
  156 #elif defined(__bsdi__)
  157 #define IPR_FMT "irip%d: "
  158 #define IPR_ARG(sc)     ((sc)->sc_if.if_unit)
  159 #define PDEVSTATIC      /* not static */
  160 #else
  161 #define IPR_FMT "%s: "
  162 #define IPR_ARG(sc)     ((sc)->sc_if.if_xname)
  163 #define PDEVSTATIC      /* not static */
  164 #endif
  165 
  166 #define I4BIPRMTU       1500            /* regular MTU */
  167 #define I4BIPRMAXMTU    2000            /* max MTU */
  168 #define I4BIPRMINMTU    500             /* min MTU */
  169 
  170 #define I4BIPRMAXQLEN   50              /* max queue length */
  171 
  172 #define I4BIPRACCT      1               /* enable accounting messages */
  173 #define I4BIPRACCTINTVL 2               /* accounting msg interval in secs */
  174 #define I4BIPRADJFRXP   1               /* adjust 1st rxd packet */
  175 
  176 
  177 struct ipr_softc {
  178         struct ifnet    sc_if;          /* network-visible interface    */
  179         int             sc_state;       /* state of the interface       */
  180 
  181         call_desc_t     *sc_cdp;        /* ptr to call descriptor       */
  182         isdn_link_t     *sc_ilt;        /* ptr to B channel driver/state */
  183 
  184         int             sc_unit;        /* which instance are we?       */
  185         int             sc_updown;      /* soft state of interface      */
  186         struct ifqueue  sc_fastq;       /* interactive traffic          */
  187         int             sc_dialresp;    /* dialresponse                 */
  188         int             sc_lastdialresp;/* last dialresponse            */
  189 
  190 #if I4BIPRACCT
  191         int             sc_iinb;        /* isdn driver # of inbytes     */
  192         int             sc_ioutb;       /* isdn driver # of outbytes    */
  193         int             sc_inb;         /* # of bytes rx'd              */
  194         int             sc_outb;        /* # of bytes tx'd              */
  195         int             sc_linb;        /* last # of bytes rx'd         */
  196         int             sc_loutb;       /* last # of bytes tx'd         */
  197         int             sc_fn;          /* flag, first null acct        */
  198 #endif
  199 
  200 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
  201         struct callout  sc_callout;
  202 #endif
  203 #if defined(__FreeBSD__)
  204         struct callout_handle   sc_callout;
  205 #endif
  206 
  207 #ifdef I4BIPRADJFRXP
  208         int             sc_first_pkt;   /* flag, first rxd packet       */
  209 #endif
  210 #if IPR_LOG
  211         int             sc_log_first;   /* log first n packets          */
  212 #endif
  213 
  214 #ifdef IRIP_VJ
  215         struct slcompress sc_compr;     /* tcp compression data         */
  216 #ifdef IPR_VJ_USEBUFFER
  217         u_char          *sc_cbuf;       /* tcp decompression buffer     */
  218 #endif
  219 #endif
  220 
  221 } ipr_softc[NIRIP];
  222 
  223 enum ipr_states {
  224         ST_IDLE,                        /* initialized, ready, idle     */
  225         ST_DIALING,                     /* dialling out to remote       */
  226         ST_CONNECTED_W,                 /* connected to remote          */
  227         ST_CONNECTED_A,                 /* connected to remote          */
  228 };
  229 
  230 #if defined(__FreeBSD__) || defined(__bsdi__)
  231 #define THE_UNIT        sc->sc_if.if_unit
  232 #else
  233 #define THE_UNIT        sc->sc_unit
  234 #endif
  235 
  236 #ifdef __FreeBSD__
  237 #if defined(__FreeBSD_version) && __FreeBSD_version >= 300001
  238 #  define IOCTL_CMD_T u_long
  239 #else
  240 #ifdef __NetBSD__
  241 #  define IOCTL_CMD_T u_long
  242 #else
  243 #  define IOCTL_CMD_T int
  244 #endif
  245 #endif
  246 PDEVSTATIC void iripattach(void *);
  247 PSEUDO_SET(iripattach, i4b_ipr);
  248 static int irpioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, caddr_t data);
  249 #else
  250 PDEVSTATIC void iripattach __P((void));
  251 static int iripioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
  252 #endif
  253 
  254 #ifdef __bsdi__
  255 static int iprwatchdog(int unit);
  256 #else
  257 static void iprwatchdog(struct ifnet *ifp);
  258 #endif
  259 static void ipr_tx_queue_empty(void *);
  260 static int iripoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rtp);
  261 static void iripclearqueues(struct ipr_softc *sc);
  262 static void ipr_set_linktab(void *softc, isdn_link_t *ilt);
  263 static void ipr_activity(void *softc, int rxtx);
  264 static void ipr_rx_data_rdy(void *softc);
  265 static void ipr_disconnect(void *softc, void *cdp);
  266 static void ipr_connect(void *softc, void *cdp);
  267 static void ipr_dialresponse(void *softc, int status, cause_t cause);
  268 static void ipr_updown(void *softc, int updown);
  269 static void* ipr_get_softc(int unit);
  270 
  271 static const struct isdn_l4_driver_functions
  272 ipr_l4_functions = {
  273         ipr_rx_data_rdy,
  274         ipr_tx_queue_empty,
  275         ipr_activity,
  276         ipr_connect,
  277         ipr_disconnect,
  278         ipr_dialresponse,
  279         ipr_updown,
  280         ipr_get_softc,
  281         ipr_set_linktab,
  282         NULL
  283 };
  284 
  285 static int irip_driver_id = -1;
  286 
  287 /*===========================================================================*
  288  *                      DEVICE DRIVER ROUTINES
  289  *===========================================================================*/
  290 
  291 /*---------------------------------------------------------------------------*
  292  *      interface attach routine at kernel boot time
  293  *---------------------------------------------------------------------------*/
  294 PDEVSTATIC void
  295 #ifdef __FreeBSD__
  296 iripattach(void *dummy)
  297 #else
  298 iripattach()
  299 #endif
  300 {
  301         struct ipr_softc *sc = ipr_softc;
  302         int i;
  303 
  304         irip_driver_id = isdn_l4_driver_attach("irip", NIRIP, &ipr_l4_functions);
  305 
  306         for(i=0; i < NIRIP; sc++, i++)
  307         {
  308                 NDBGL4(L4_DIALST, "setting dial state to ST_IDLE");
  309 
  310                 sc->sc_state = ST_IDLE;
  311                 sc->sc_unit = i;
  312 
  313 #ifdef __FreeBSD__
  314                 sc->sc_if.if_name = "irip";
  315 #if __FreeBSD__ < 3
  316                 sc->sc_if.if_next = NULL;
  317 #endif
  318                 sc->sc_if.if_unit = i;
  319 #elif defined(__bsdi__)
  320                 sc->sc_if.if_name = "irip";
  321                 sc->sc_if.if_unit = i;
  322 #else
  323                 snprintf(sc->sc_if.if_xname, sizeof(sc->sc_if.if_xname),
  324                     "irip%d", i);
  325                 sc->sc_if.if_softc = sc;
  326 #endif
  327 
  328 #ifdef  IRIP_VJ
  329                 sc->sc_if.if_flags = IFF_POINTOPOINT | IFF_SIMPLEX | IPR_AUTOCOMP;
  330 #else
  331                 sc->sc_if.if_flags = IFF_POINTOPOINT | IFF_SIMPLEX;
  332 #endif
  333 
  334 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
  335                 callout_init(&sc->sc_callout);
  336 #endif
  337 
  338                 sc->sc_if.if_mtu = I4BIPRMTU;
  339                 sc->sc_if.if_type = IFT_ISDNBASIC;
  340                 sc->sc_if.if_ioctl = iripioctl;
  341                 sc->sc_if.if_output = iripoutput;
  342 
  343                 IFQ_SET_MAXLEN(&sc->sc_if.if_snd, I4BIPRMAXQLEN);
  344                 sc->sc_fastq.ifq_maxlen = I4BIPRMAXQLEN;
  345                 IFQ_SET_READY(&sc->sc_if.if_snd);
  346 
  347                 sc->sc_if.if_ipackets = 0;
  348                 sc->sc_if.if_ierrors = 0;
  349                 sc->sc_if.if_opackets = 0;
  350                 sc->sc_if.if_oerrors = 0;
  351                 sc->sc_if.if_collisions = 0;
  352                 sc->sc_if.if_ibytes = 0;
  353                 sc->sc_if.if_obytes = 0;
  354                 sc->sc_if.if_imcasts = 0;
  355                 sc->sc_if.if_omcasts = 0;
  356                 sc->sc_if.if_iqdrops = 0;
  357                 sc->sc_if.if_noproto = 0;
  358 
  359 #if I4BIPRACCT
  360                 sc->sc_if.if_timer = 0;
  361                 sc->sc_if.if_watchdog = iprwatchdog;
  362                 sc->sc_iinb = 0;
  363                 sc->sc_ioutb = 0;
  364                 sc->sc_inb = 0;
  365                 sc->sc_outb = 0;
  366                 sc->sc_linb = 0;
  367                 sc->sc_loutb = 0;
  368                 sc->sc_fn = 1;
  369 #endif
  370 #if IPR_LOG
  371                 sc->sc_log_first = IPR_LOG;
  372 #endif
  373 
  374 #ifdef  IRIP_VJ
  375 #ifdef __FreeBSD__
  376                 sl_compress_init(&sc->sc_compr, -1);
  377 #else
  378                 sl_compress_init(&sc->sc_compr);
  379 #endif
  380 
  381 #ifdef IPR_VJ_USEBUFFER
  382                 if(!((sc->sc_cbuf =
  383                    (u_char *)malloc(I4BIPRMAXMTU+128, M_DEVBUF, M_WAITOK))))
  384                 {
  385                         panic("if_ipr.c, ipr_attach: VJ malloc failed");
  386                 }
  387 #endif
  388 #endif
  389 
  390                 sc->sc_updown = SOFT_ENA;       /* soft enabled */
  391 
  392                 sc->sc_dialresp = DSTAT_NONE;   /* no response */
  393                 sc->sc_lastdialresp = DSTAT_NONE;
  394 
  395 #if defined(__FreeBSD_version) && ((__FreeBSD_version >= 500009) || (410000 <= __FreeBSD_version && __FreeBSD_version < 500000))
  396                 /* do not call bpfattach in ether_ifattach */
  397                 ether_ifattach(&sc->sc_if, 0);
  398 #else
  399                 if_attach(&sc->sc_if);
  400                 if_alloc_sadl(&sc->sc_if);
  401 #endif
  402 
  403 #if NBPFILTER > 0 || NBPF > 0
  404 #ifdef __FreeBSD__
  405                 bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int));
  406 #else
  407                 bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int));
  408 #endif
  409 #endif
  410         }
  411 }
  412 
  413 /*---------------------------------------------------------------------------*
  414  *      output a packet to the ISDN B-channel
  415  *---------------------------------------------------------------------------*/
  416 static int
  417 iripoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
  418          struct rtentry *rtp)
  419 {
  420         struct ipr_softc *sc;
  421         int s, rv;
  422         struct ifqueue *ifq = NULL;
  423         struct ip *ip;
  424         ALTQ_DECL(struct altq_pktattr pktattr;)
  425 
  426         s = splnet();
  427 
  428 #if defined(__FreeBSD__) || defined(__bsdi__)
  429         unit = ifp->if_unit;
  430         sc = &ipr_softc[unit];
  431 #else
  432         sc = ifp->if_softc;
  433 #endif
  434 
  435         /* check for IP */
  436 
  437         if(dst->sa_family != AF_INET)
  438         {
  439                 printf(IPR_FMT "af%d not supported\n", IPR_ARG(sc), dst->sa_family);
  440                 m_freem(m);
  441                 splx(s);
  442                 sc->sc_if.if_noproto++;
  443                 sc->sc_if.if_oerrors++;
  444                 return(EAFNOSUPPORT);
  445         }
  446 
  447         /* check interface state = UP */
  448 
  449         if(!(ifp->if_flags & IFF_UP))
  450         {
  451                 NDBGL4(L4_IPRDBG, "%s: interface is DOWN!", sc->sc_if.if_xname);
  452                 m_freem(m);
  453                 splx(s);
  454                 sc->sc_if.if_oerrors++;
  455                 return(ENETDOWN);
  456         }
  457 
  458         /* dial if necessary */
  459 
  460         if(sc->sc_state == ST_IDLE || sc->sc_state == ST_DIALING)
  461         {
  462 
  463 #ifdef NOTDEF
  464                 switch(sc->sc_dialresp)
  465                 {
  466                         case DSTAT_TFAIL:       /* transient failure */
  467                                 NDBGL4(L4_IPRDBG, "%s: transient dial failure!", sc->sc_if.if_xname);
  468                                 m_freem(m);
  469                                 iripclearqueues(sc);
  470                                 sc->sc_dialresp = DSTAT_NONE;
  471                                 splx(s);
  472                                 sc->sc_if.if_oerrors++;
  473                                 return(ENETUNREACH);
  474                                 break;
  475 
  476                         case DSTAT_PFAIL:       /* permanent failure */
  477                                 NDBGL4(L4_IPRDBG, "%s: permanent dial failure!", sc->sc_if.if_xname);
  478                                 m_freem(m);
  479                                 iripclearqueues(sc);
  480                                 sc->sc_dialresp = DSTAT_NONE;
  481                                 splx(s);
  482                                 sc->sc_if.if_oerrors++;
  483                                 return(EHOSTUNREACH);
  484                                 break;
  485 
  486                         case DSTAT_INONLY:      /* no dialout allowed*/
  487                                 NDBGL4(L4_IPRDBG, "%s: dialout not allowed failure!", sc->sc_if.if_xname);
  488                                 m_freem(m);
  489                                 iripclearqueues(sc);
  490                                 sc->sc_dialresp = DSTAT_NONE;
  491                                 splx(s);
  492                                 sc->sc_if.if_oerrors++;
  493                                 return(EHOSTUNREACH);
  494                                 break;
  495                 }
  496 #endif
  497 
  498                 NDBGL4(L4_IPRDBG, "%s: send dial request message!", sc->sc_if.if_xname);
  499                 NDBGL4(L4_DIALST, "%s: setting dial state to ST_DIALING", sc->sc_if.if_xname);
  500                 i4b_l4_dialout(irip_driver_id, sc->sc_unit);
  501                 sc->sc_state = ST_DIALING;
  502         }
  503 
  504 #if IPR_LOG
  505         if(sc->sc_log_first > 0)
  506         {
  507                 --(sc->sc_log_first);
  508                 i4b_l4_packet_ind(irip_driver_id, sc->sc_unit, 1, m );
  509         }
  510 #endif
  511 
  512         /*
  513          * check, if type of service indicates interactive, i.e. telnet,
  514          * traffic. in case it is interactive, put it into the fast queue,
  515          * else (i.e. ftp traffic) put it into the "normal" queue
  516          */
  517 
  518         IFQ_CLASSIFY(&ifp->if_snd, m, dst->sa_family, &pktattr);
  519 
  520         ip = mtod(m, struct ip *);              /* get ptr to ip header */
  521 
  522         if(ip->ip_tos & IPTOS_LOWDELAY)
  523                 ifq = &sc->sc_fastq;
  524 
  525         /* check for space in choosen send queue */
  526 
  527         if ((ifq != NULL)
  528 #ifdef ALTQ
  529            && ALTQ_IS_ENABLED(&sc->sc_if.if_snd) == 0
  530 #endif
  531         ) {
  532                 if(IF_QFULL(ifq))
  533                 {
  534                         NDBGL4(L4_IPRDBG, "%s: send queue full!", sc->sc_if.if_xname);
  535                         IF_DROP(ifq);
  536                         m_freem(m);
  537                         sc->sc_if.if_oerrors++;
  538                         splx(s);
  539                         return(ENOBUFS);
  540                 }
  541                 IF_ENQUEUE(ifq, m);
  542         } else {
  543                 IFQ_ENQUEUE(&sc->sc_if.if_snd, m, &pktattr, rv);
  544                 if (rv != 0) {
  545                         sc->sc_if.if_oerrors++;
  546                         splx(s);
  547                         return rv;
  548                 }
  549         }
  550 
  551         NDBGL4(L4_IPRDBG, "%s: added packet to send queue!", sc->sc_if.if_xname);
  552 
  553         ipr_tx_queue_empty(sc);
  554 
  555         splx(s);
  556 
  557         return (0);
  558 }
  559 
  560 /*---------------------------------------------------------------------------*
  561  *      process ioctl
  562  *---------------------------------------------------------------------------*/
  563 #ifdef __FreeBSD__
  564 static int
  565 iripioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, caddr_t data)
  566 #else
  567 static int
  568 iripioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
  569 #endif
  570 {
  571 #if defined(__FreeBSD__) || defined(__bsdi__)
  572         struct ipr_softc *sc = &ipr_softc[ifp->if_unit];
  573 #else
  574         struct ipr_softc *sc = ifp->if_softc;
  575 #endif
  576 
  577         struct ifreq *ifr = (struct ifreq *)data;
  578         struct ifaddr *ifa = (struct ifaddr *)data;
  579         int s;
  580         int error = 0;
  581 
  582         s = splnet();
  583 
  584         switch (cmd)
  585         {
  586                 case SIOCAIFADDR:       /* add interface address */
  587                 case SIOCSIFADDR:       /* set interface address */
  588                 case SIOCSIFDSTADDR:    /* set interface destination address */
  589                         if(ifa->ifa_addr->sa_family != AF_INET)
  590                                 error = EAFNOSUPPORT;
  591                         else
  592                                 sc->sc_if.if_flags |= IFF_UP;
  593                         break;
  594 
  595                 case SIOCSIFFLAGS:      /* set interface flags */
  596                         if(!(ifr->ifr_flags & IFF_UP))
  597                         {
  598                                 if(sc->sc_if.if_flags & IFF_RUNNING)
  599                                 {
  600                                         /* disconnect ISDN line */
  601                                         i4b_l4_drvrdisc(sc->sc_cdp->cdid);
  602                                         sc->sc_if.if_flags &= ~IFF_RUNNING;
  603                                 }
  604 
  605                                 sc->sc_state = ST_IDLE;
  606 
  607                                 /* empty queues */
  608 
  609                                 iripclearqueues(sc);
  610                         }
  611 
  612                         if(ifr->ifr_flags & IFF_DEBUG)
  613                         {
  614                                 /* enable debug messages */
  615                         }
  616 
  617                         break;
  618 
  619 #if !defined(__OpenBSD__)
  620                 case SIOCSIFMTU:        /* set interface MTU */
  621                         if(ifr->ifr_mtu > I4BIPRMAXMTU)
  622                                 error = EINVAL;
  623                         else if(ifr->ifr_mtu < I4BIPRMINMTU)
  624                                 error = EINVAL;
  625                         else
  626                                 ifp->if_mtu = ifr->ifr_mtu;
  627                         break;
  628 #endif /* __OPENBSD__ */
  629 
  630 #if 0
  631         /* not needed for FreeBSD, done in sl_compress_init() (-hm) */
  632 
  633                         /* need to add an ioctl:        set VJ max slot ID
  634                          * #define IPRIOCSMAXCID        _IOW('I', XXX, int)
  635                          */
  636 #ifdef IPR_VJ
  637                 case IPRIOCSMAXCID:
  638                         {
  639                         struct proc *p = curproc;       /* XXX */
  640 
  641 #if defined(__FreeBSD_version) && __FreeBSD_version >= 400005
  642                         if((error = suser(p)) != 0)
  643 #else
  644                         if((error = suser(p->p_ucred, &p->p_acflag)) != 0)
  645 #endif
  646                                 break;
  647                         sl_compress_setup(sc->sc_compr, *(int *)data);
  648                         }
  649                         break;
  650 #endif
  651 #endif
  652                 default:
  653                         error = EINVAL;
  654                         break;
  655         }
  656 
  657         splx(s);
  658 
  659         return(error);
  660 }
  661 
  662 /*---------------------------------------------------------------------------*
  663  *      clear the interface's send queues
  664  *---------------------------------------------------------------------------*/
  665 static void
  666 iripclearqueues(struct ipr_softc *sc)
  667 {
  668         int x;
  669         struct mbuf *m;
  670 
  671         for(;;)
  672         {
  673                 x = splnet();
  674                 IF_DEQUEUE(&sc->sc_fastq, m);
  675                 splx(x);
  676 
  677                 if(m)
  678                         m_freem(m);
  679                 else
  680                         break;
  681         }
  682 
  683         for(;;)
  684         {
  685                 x = splnet();
  686                 IFQ_DEQUEUE(&sc->sc_if.if_snd, m);
  687                 splx(x);
  688 
  689                 if(m)
  690                         m_freem(m);
  691                 else
  692                         break;
  693         }
  694 }
  695 
  696 #if I4BIPRACCT
  697 /*---------------------------------------------------------------------------*
  698  *      watchdog routine
  699  *---------------------------------------------------------------------------*/
  700 #ifdef __bsdi__
  701 static int
  702 iprwatchdog(int unit)
  703 {
  704 #else
  705 static void
  706 iprwatchdog(struct ifnet *ifp)
  707 {
  708 #endif
  709 #ifdef __FreeBSD__
  710         int unit = ifp->if_unit;
  711         struct ipr_softc *sc = &ipr_softc[unit];
  712 #elif defined(__bsdi__)
  713         struct ipr_softc *sc = &ipr_softc[unit];
  714         struct ifnet *ifp = &ipr_softc[unit].sc_if;
  715 #else
  716         struct ipr_softc *sc = ifp->if_softc;
  717 #endif
  718         bchan_statistics_t bs;
  719 
  720         /* get # of bytes in and out from the HSCX driver */
  721 
  722         (*sc->sc_ilt->bchannel_driver->bch_stat)
  723                 (sc->sc_ilt->l1token, sc->sc_ilt->channel, &bs);
  724 
  725         sc->sc_ioutb += bs.outbytes;
  726         sc->sc_iinb += bs.inbytes;
  727 
  728         if((sc->sc_iinb != sc->sc_linb) || (sc->sc_ioutb != sc->sc_loutb) || sc->sc_fn)
  729         {
  730                 int ri = (sc->sc_iinb - sc->sc_linb)/I4BIPRACCTINTVL;
  731                 int ro = (sc->sc_ioutb - sc->sc_loutb)/I4BIPRACCTINTVL;
  732 
  733                 if((sc->sc_iinb == sc->sc_linb) && (sc->sc_ioutb == sc->sc_loutb))
  734                         sc->sc_fn = 0;
  735                 else
  736                         sc->sc_fn = 1;
  737 
  738                 sc->sc_linb = sc->sc_iinb;
  739                 sc->sc_loutb = sc->sc_ioutb;
  740 
  741                 if (sc->sc_cdp)
  742                         i4b_l4_accounting(sc->sc_cdp->cdid, ACCT_DURING,
  743                             sc->sc_ioutb, sc->sc_iinb, ro, ri, sc->sc_outb, sc->sc_inb);
  744         }
  745         sc->sc_if.if_timer = I4BIPRACCTINTVL;
  746 #ifdef __bsdi__
  747         return 0;
  748 #endif
  749 }
  750 #endif /* I4BIPRACCT */
  751 
  752 /*===========================================================================*
  753  *                      ISDN INTERFACE ROUTINES
  754  *===========================================================================*/
  755 
  756 /*---------------------------------------------------------------------------*
  757  *      start transmitting after connect
  758  *---------------------------------------------------------------------------*/
  759 static void
  760 i4bipr_connect_startio(struct ipr_softc *sc)
  761 {
  762         int s = splnet();
  763 
  764         if(sc->sc_state == ST_CONNECTED_W)
  765         {
  766                 sc->sc_state = ST_CONNECTED_A;
  767                 ipr_tx_queue_empty(sc);
  768         }
  769 
  770         splx(s);
  771 }
  772 
  773 /*---------------------------------------------------------------------------*
  774  *      this routine is called from L4 handler at connect time
  775  *---------------------------------------------------------------------------*/
  776 static void
  777 ipr_connect(void *softc, void *cdp)
  778 {
  779         struct ipr_softc *sc = softc;
  780         int s;
  781 
  782         sc->sc_cdp = (call_desc_t *)cdp;
  783 
  784         s = splnet();
  785 
  786         NDBGL4(L4_DIALST, "%s: setting dial state to ST_CONNECTED", sc->sc_if.if_xname);
  787 
  788         sc->sc_if.if_flags |= IFF_RUNNING;
  789         sc->sc_state = ST_CONNECTED_W;
  790 
  791         sc->sc_dialresp = DSTAT_NONE;
  792         sc->sc_lastdialresp = DSTAT_NONE;
  793 
  794 #if I4BIPRACCT
  795         sc->sc_iinb = 0;
  796         sc->sc_ioutb = 0;
  797         sc->sc_inb = 0;
  798         sc->sc_outb = 0;
  799         sc->sc_linb = 0;
  800         sc->sc_loutb = 0;
  801         sc->sc_if.if_timer = I4BIPRACCTINTVL;
  802 #endif
  803 
  804 #ifdef I4BIPRADJFRXP
  805         sc->sc_first_pkt = 1;
  806 #endif
  807 
  808         /*
  809          * Sometimes ISDN B-channels are switched thru asymmetic. This
  810          * means that under such circumstances B-channel data (the first
  811          * three packets of a TCP connection in my case) may get lost,
  812          * causing a large delay until the connection is started.
  813          * When the sending of the very first packet of a TCP connection
  814          * is delayed for a to be empirically determined delay (close
  815          * to a second in my case) those packets go thru and the TCP
  816          * connection comes up "almost" immediately (-hm).
  817          */
  818 
  819         if(sc->sc_cdp->isdntxdelay > 0)
  820         {
  821                 int delay;
  822 
  823                 if (hz == 100) {
  824                         delay = sc->sc_cdp->isdntxdelay;        /* avoid any rounding */
  825                 } else {
  826                         delay = sc->sc_cdp->isdntxdelay*hz;
  827                         delay /= 100;
  828                 }
  829 
  830                 START_TIMER(sc->sc_callout, (TIMEOUT_FUNC_T)i4bipr_connect_startio, (void *)sc,  delay);
  831         }
  832         else
  833         {
  834                 sc->sc_state = ST_CONNECTED_A;
  835                 ipr_tx_queue_empty(sc);
  836         }
  837 
  838         splx(s);
  839 
  840         /* we don't need any negotiation - pass event back right now */
  841         i4b_l4_negcomplete(sc->sc_cdp);
  842 }
  843 
  844 /*---------------------------------------------------------------------------*
  845  *      this routine is called from L4 handler at disconnect time
  846  *---------------------------------------------------------------------------*/
  847 static void
  848 ipr_disconnect(void *softc, void *cdp)
  849 {
  850         call_desc_t *cd = (call_desc_t *)cdp;
  851         struct ipr_softc *sc = softc;
  852 
  853         /* new stuff to check that the active channel is being closed */
  854 
  855         if (cd != sc->sc_cdp)
  856         {
  857                 NDBGL4(L4_IPRDBG, "%s: channel %d not active",
  858                                 sc->sc_if.if_xname, cd->channelid);
  859                 return;
  860         }
  861 
  862 #if I4BIPRACCT
  863         sc->sc_if.if_timer = 0;
  864 #endif
  865 #if IPR_LOG
  866         /* show next IPR_LOG packets again */
  867         sc->sc_log_first = IPR_LOG;
  868 #endif
  869 
  870         i4b_l4_accounting(cd->cdid, ACCT_FINAL,
  871                  sc->sc_ioutb, sc->sc_iinb, 0, 0, sc->sc_outb, sc->sc_inb);
  872 
  873         sc->sc_cdp = NULL;
  874 
  875         NDBGL4(L4_DIALST, "setting dial state to ST_IDLE");
  876 
  877         sc->sc_dialresp = DSTAT_NONE;
  878         sc->sc_lastdialresp = DSTAT_NONE;
  879 
  880         sc->sc_if.if_flags &= ~IFF_RUNNING;
  881         sc->sc_state = ST_IDLE;
  882 }
  883 
  884 /*---------------------------------------------------------------------------*
  885  *      this routine is used to give a feedback from userland daemon
  886  *      in case of dial problems
  887  *---------------------------------------------------------------------------*/
  888 static void
  889 ipr_dialresponse(void *softc, int status, cause_t cause)
  890 {
  891         struct ipr_softc *sc = softc;
  892         sc->sc_dialresp = status;
  893 
  894         NDBGL4(L4_IPRDBG, "%s: last=%d, this=%d",
  895                 sc->sc_if.if_xname, sc->sc_lastdialresp, sc->sc_dialresp);
  896 
  897         if(status != DSTAT_NONE)
  898         {
  899                 NDBGL4(L4_IPRDBG, "%s: clearing queues", sc->sc_if.if_xname);
  900                 iripclearqueues(sc);
  901         }
  902 }
  903 
  904 /*---------------------------------------------------------------------------*
  905  *      interface soft up/down
  906  *---------------------------------------------------------------------------*/
  907 static void
  908 ipr_updown(void *softc, int updown)
  909 {
  910         struct ipr_softc *sc = softc;
  911         sc->sc_updown = updown;
  912 }
  913 
  914 /*---------------------------------------------------------------------------*
  915  *      this routine is called from the HSCX interrupt handler
  916  *      when a new frame (mbuf) has been received and was put on
  917  *      the rx queue. It is assumed that this routines runs at
  918  *      appropriate protection level! Keep it short !
  919  *---------------------------------------------------------------------------*/
  920 static void
  921 ipr_rx_data_rdy(void *softc)
  922 {
  923         register struct ipr_softc *sc = softc;
  924         register struct mbuf *m;
  925 #ifdef IRIP_VJ
  926 #ifdef IPR_VJ_USEBUFFER
  927         u_char *cp = sc->sc_cbuf;
  928 #endif
  929         int len, c;
  930 #endif
  931 
  932         if((m = *sc->sc_ilt->rx_mbuf) == NULL)
  933                 return;
  934 
  935         m->m_pkthdr.rcvif = &sc->sc_if;
  936 
  937         m->m_pkthdr.len = m->m_len;
  938 
  939 #ifdef I4BIPRADJFRXP
  940 
  941         /*
  942          * The very first packet after the B channel is switched thru
  943          * has very often several bytes of random data prepended. This
  944          * routine looks where the IP header starts and removes the
  945          * the bad data.
  946          */
  947 
  948         if(sc->sc_first_pkt)
  949         {
  950                 unsigned char *mp = m->m_data;
  951                 int i;
  952 
  953                 sc->sc_first_pkt = 0;
  954 
  955                 for(i = 0; i < m->m_len; i++, mp++)
  956                 {
  957                         if( ((*mp & 0xf0) == 0x40) &&
  958                             ((*mp & 0x0f) >= 0x05) )
  959                         {
  960                                 m->m_data = mp;
  961                                 m->m_pkthdr.len -= i;
  962                                 break;
  963                         }
  964                 }
  965         }
  966 #endif
  967 
  968         sc->sc_if.if_ipackets++;
  969         sc->sc_if.if_ibytes += m->m_pkthdr.len;
  970 
  971 #ifdef  IRIP_VJ
  972         if((c = (*(mtod(m, u_char *)) & 0xf0)) != (IPVERSION << 4))
  973         {
  974                 /* copy data to buffer */
  975 
  976                 len = m->m_len;
  977 
  978 #ifdef IPR_VJ_USEBUFFER
  979 /* XXX */       m_copydata(m, 0, len, cp);
  980 #endif
  981 
  982                 if(c & 0x80)
  983                 {
  984                         c = TYPE_COMPRESSED_TCP;
  985                 }
  986                 else if(c == TYPE_UNCOMPRESSED_TCP)
  987                 {
  988 #ifdef IPR_VJ_USEBUFFER
  989                         *cp &= 0x4f;            /* XXX */
  990 #else
  991                         *(mtod(m, u_char *)) &= 0x4f;
  992 #endif
  993                 }
  994 
  995                 /*
  996                  * We've got something that's not an IP packet.
  997                  * If compression is enabled, try to decompress it.
  998                  * Otherwise, if `auto-enable' compression is on and
  999                  * it's a reasonable packet, decompress it and then
 1000                  * enable compression.  Otherwise, drop it.
 1001                  */
 1002                 if(sc->sc_if.if_flags & IPR_COMPRESS)
 1003                 {
 1004 #ifdef IPR_VJ_USEBUFFER
 1005                         len = sl_uncompress_tcp(&cp,len,(u_int)c,&sc->sc_compr);
 1006 #else
 1007                         len = sl_uncompress_tcp((u_char **)&m->m_data, len,
 1008                                         (u_int)c, &sc->sc_compr);
 1009 #endif
 1010 
 1011                         if(len <= 0)
 1012                         {
 1013 #ifdef DEBUG_IPR_VJ
 1014                                 printf("i4b_ipr, ipr_rx_data_rdy: len <= 0 IPR_COMPRESS!\n");
 1015 #endif
 1016                                 goto error;
 1017                         }
 1018                 }
 1019                 else if((sc->sc_if.if_flags & IPR_AUTOCOMP) &&
 1020                         (c == TYPE_UNCOMPRESSED_TCP) && (len >= 40))
 1021                 {
 1022 #ifdef IPR_VJ_USEBUFFER
 1023                         len = sl_uncompress_tcp(&cp,len,(u_int)c,&sc->sc_compr);
 1024 #else
 1025                         len = sl_uncompress_tcp((u_char **)&m->m_data, len,
 1026                                         (u_int)c, &sc->sc_compr);
 1027 #endif
 1028 
 1029                         if(len <= 0)
 1030                         {
 1031 #ifdef DEBUG_IPR_VJ
 1032                                 printf("i4b_ipr, ipr_rx_data_rdy: len <= 0 IPR_AUTOCOMP!\n");
 1033 #endif
 1034                                 goto error;
 1035                         }
 1036 
 1037                         sc->sc_if.if_flags |= IPR_COMPRESS;
 1038                 }
 1039                 else
 1040                 {
 1041 #ifdef DEBUG_IPR_VJ
 1042                         printf("i4b_ipr, ipr_input: invalid ip packet!\n");
 1043 #endif
 1044 
 1045 error:
 1046                         sc->sc_if.if_ierrors++;
 1047                         sc->sc_if.if_collisions++;
 1048                         m_freem(m);
 1049                         return;
 1050                 }
 1051 #ifdef IPR_VJ_USEBUFFER
 1052 /* XXX */       m_copyback(m, 0, len, cp);
 1053 #else
 1054                 m->m_len = m->m_pkthdr.len = len;
 1055 #endif
 1056         }
 1057 #endif
 1058 
 1059 #if I4BIPRACCT
 1060         /* NB. do the accounting after decompression!           */
 1061         sc->sc_inb += m->m_pkthdr.len;
 1062 #endif
 1063 #if IPR_LOG
 1064         if(sc->sc_log_first > 0)
 1065         {
 1066                 --(sc->sc_log_first);
 1067                 i4b_l4_packet_ind(irip_driver_id, sc->sc_unit, 0, m );
 1068         }
 1069 #endif
 1070 
 1071 #if NBPFILTER > 0 || NBPF > 0
 1072         if(sc->sc_if.if_bpf)
 1073         {
 1074                 /* prepend the address family as a four byte field */
 1075                 struct mbuf mm;
 1076                 u_int af = AF_INET;
 1077                 mm.m_next = m;
 1078                 mm.m_len = 4;
 1079                 mm.m_data = (char *)&af;
 1080 
 1081 #ifdef __FreeBSD__
 1082                 bpf_mtap(&sc->sc_if, &mm);
 1083 #else
 1084                 bpf_mtap(sc->sc_if.if_bpf, &mm);
 1085 #endif
 1086         }
 1087 #endif /* NBPFILTER > 0  || NBPF > 0 */
 1088 
 1089         if(IF_QFULL(&ipintrq))
 1090         {
 1091                 NDBGL4(L4_IPRDBG, "%s: ipintrq full!", sc->sc_if.if_xname);
 1092 
 1093                 IF_DROP(&ipintrq);
 1094                 sc->sc_if.if_ierrors++;
 1095                 sc->sc_if.if_iqdrops++;
 1096                 m_freem(m);
 1097         }
 1098         else
 1099         {
 1100                 IF_ENQUEUE(&ipintrq, m);
 1101                 schednetisr(NETISR_IP);
 1102         }
 1103 }
 1104 
 1105 /*---------------------------------------------------------------------------*
 1106  *      this routine is called from the HSCX interrupt handler
 1107  *      when the last frame has been sent out and there is no
 1108  *      further frame (mbuf) in the tx queue.
 1109  *---------------------------------------------------------------------------*/
 1110 static void
 1111 ipr_tx_queue_empty(void *softc)
 1112 {
 1113         register struct ipr_softc *sc = softc;
 1114         register struct mbuf *m;
 1115 #ifdef  IRIP_VJ
 1116         struct ip *ip;
 1117 #endif
 1118         int x = 0;
 1119 
 1120         if(sc->sc_state != ST_CONNECTED_A)
 1121                 return;
 1122 
 1123         for(;;)
 1124         {
 1125                 IF_DEQUEUE(&sc->sc_fastq, m);
 1126                 if(m)
 1127                 {
 1128                         sc->sc_if.if_omcasts++;
 1129                 }
 1130                 else
 1131                 {
 1132                         IFQ_DEQUEUE(&sc->sc_if.if_snd, m);
 1133                         if(m == NULL)
 1134                                 break;
 1135                 }
 1136 
 1137 #if NBPFILTER > 0 || NBPF > 0
 1138                 if(sc->sc_if.if_bpf)
 1139                 {
 1140                         /* prepend the address family as a four byte field */
 1141 
 1142                         struct mbuf mm;
 1143                         u_int af = AF_INET;
 1144                         mm.m_next = m;
 1145                         mm.m_len = 4;
 1146                         mm.m_data = (char *)&af;
 1147 
 1148 #ifdef __FreeBSD__
 1149                         bpf_mtap(&sc->sc_if, &mm);
 1150 #else
 1151                         bpf_mtap(sc->sc_if.if_bpf, &mm);
 1152 #endif
 1153                 }
 1154 #endif /* NBPFILTER */
 1155 
 1156 #if I4BIPRACCT
 1157                 sc->sc_outb += m->m_pkthdr.len; /* size before compression */
 1158 #endif
 1159 
 1160 #ifdef  IRIP_VJ
 1161                 if((ip = mtod(m, struct ip *))->ip_p == IPPROTO_TCP)
 1162                 {
 1163                         if(sc->sc_if.if_flags & IPR_COMPRESS)
 1164                         {
 1165                                 *mtod(m, u_char *) |= sl_compress_tcp(m, ip,
 1166                                         &sc->sc_compr, 1);
 1167                         }
 1168                 }
 1169 #endif
 1170                 x = 1;
 1171 
 1172                 if(IF_QFULL(sc->sc_ilt->tx_queue))
 1173                 {
 1174                         NDBGL4(L4_IPRDBG, "%s: tx queue full!", sc->sc_if.if_xname);
 1175                         m_freem(m);
 1176                 }
 1177                 else
 1178                 {
 1179                         IF_ENQUEUE(sc->sc_ilt->tx_queue, m);
 1180 
 1181                         sc->sc_if.if_obytes += m->m_pkthdr.len;
 1182 
 1183                         sc->sc_if.if_opackets++;
 1184                 }
 1185         }
 1186 
 1187         if(x)
 1188                 (*sc->sc_ilt->bchannel_driver->bch_tx_start)(sc->sc_ilt->l1token, sc->sc_ilt->channel);
 1189 }
 1190 
 1191 /*---------------------------------------------------------------------------*
 1192  *      this routine is called from the HSCX interrupt handler
 1193  *      each time a packet is received or transmitted. It should
 1194  *      be used to implement an activity timeout mechanism.
 1195  *---------------------------------------------------------------------------*/
 1196 static void
 1197 ipr_activity(void *softc, int rxtx)
 1198 {
 1199         struct ipr_softc *sc = softc;
 1200         sc->sc_cdp->last_active_time = SECOND;
 1201 }
 1202 
 1203 /*---------------------------------------------------------------------------*
 1204  *      return this drivers linktab address
 1205  *---------------------------------------------------------------------------*/
 1206 static void*
 1207 ipr_get_softc(int unit)
 1208 {
 1209         return &ipr_softc[unit];
 1210 }
 1211 
 1212 /*---------------------------------------------------------------------------*
 1213  *      setup the isdn_linktab for this driver
 1214  *---------------------------------------------------------------------------*/
 1215 static void
 1216 ipr_set_linktab(void *softc, isdn_link_t *ilt)
 1217 {
 1218         struct ipr_softc *sc = softc;
 1219         sc->sc_ilt = ilt;
 1220 }
 1221 
 1222 /*===========================================================================*/
 1223 
 1224 #endif /* NIRIP > 0 */

Cache object: 4aa5e3f47c9cadaebff03eacebd32827


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.