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/dev/ic/isic_bchan.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_bchan.c - B channel handling L1 procedures
   28  *      ----------------------------------------------
   29  *
   30  *      $Id: isic_bchan.c,v 1.13 2008/04/08 12:07:26 cegger Exp $
   31  *
   32  *      last edit-date: [Fri Jan  5 11:36:11 2001]
   33  *
   34  *---------------------------------------------------------------------------*/
   35 
   36 #include <sys/cdefs.h>
   37 __KERNEL_RCSID(0, "$NetBSD: isic_bchan.c,v 1.13 2008/04/08 12:07:26 cegger Exp $");
   38 
   39 #include <sys/param.h>
   40 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
   41 #include <sys/ioccom.h>
   42 #else
   43 #include <sys/ioctl.h>
   44 #endif
   45 #include <sys/kernel.h>
   46 #include <sys/systm.h>
   47 #include <sys/mbuf.h>
   48 #include <machine/stdarg.h>
   49 
   50 #ifdef __FreeBSD__
   51 #include <machine/clock.h>
   52 #include <i386/isa/isa_device.h>
   53 #else
   54 #ifndef __bsdi__
   55 #include <sys/bus.h>
   56 #endif
   57 #include <sys/device.h>
   58 #endif
   59 
   60 #include <sys/socket.h>
   61 #include <net/if.h>
   62 
   63 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
   64 #include <sys/callout.h>
   65 #endif
   66 
   67 #include <netisdn/i4b_debug.h>
   68 #include <netisdn/i4b_ioctl.h>
   69 #include <netisdn/i4b_trace.h>
   70 
   71 #include <netisdn/i4b_l2.h>
   72 #include <netisdn/i4b_l1l2.h>
   73 #include <netisdn/i4b_mbuf.h>
   74 #include <netisdn/i4b_global.h>
   75 
   76 #include <dev/ic/isic_l1.h>
   77 #include <dev/ic/isac.h>
   78 #include <dev/ic/hscx.h>
   79 
   80 static void isic_bchannel_start(isdn_layer1token, int h_chan);
   81 static void isic_bchannel_stat(isdn_layer1token, int h_chan, bchan_statistics_t *bsp);
   82 
   83 void isic_set_link(void*, int channel, const struct isdn_l4_driver_functions *l4_driver, void *l4_driver_softc);
   84 isdn_link_t *isic_ret_linktab(void*, int channel);
   85 
   86 /*---------------------------------------------------------------------------*
   87  *      initialize one B channels rx/tx data structures and init/deinit HSCX
   88  *---------------------------------------------------------------------------*/
   89 void
   90 isic_bchannel_setup(isdn_layer1token t, int h_chan, int bprot, int activate)
   91 {
   92         struct isic_softc *sc = (struct isic_softc*)t;
   93         l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
   94 
   95         int s = splnet();
   96 
   97         if(activate == 0)
   98         {
   99                 /* deactivation */
  100                 isic_hscx_init(sc, h_chan, activate);
  101         }
  102 
  103         NDBGL1(L1_BCHAN, "%s, channel=%d, %s",
  104                 device_xname(&sc->sc_dev), h_chan, activate ? "activate" : "deactivate");
  105 
  106         /* general part */
  107 
  108         chan->channel = h_chan;         /* B channel */
  109         chan->bprot = bprot;            /* B channel protocol */
  110         chan->state = HSCX_IDLE;        /* B channel state */
  111 
  112         /* receiver part */
  113 
  114         i4b_Bcleanifq(&chan->rx_queue); /* clean rx queue */
  115 
  116         chan->rx_queue.ifq_maxlen = IFQ_MAXLEN;
  117 
  118         chan->rxcount = 0;              /* reset rx counter */
  119 
  120         i4b_Bfreembuf(chan->in_mbuf);   /* clean rx mbuf */
  121 
  122         chan->in_mbuf = NULL;           /* reset mbuf ptr */
  123         chan->in_cbptr = NULL;          /* reset mbuf curr ptr */
  124         chan->in_len = 0;               /* reset mbuf data len */
  125 
  126         /* transmitter part */
  127 
  128         i4b_Bcleanifq(&chan->tx_queue); /* clean tx queue */
  129 
  130         chan->tx_queue.ifq_maxlen = IFQ_MAXLEN;
  131 
  132         chan->txcount = 0;              /* reset tx counter */
  133 
  134         i4b_Bfreembuf(chan->out_mbuf_head);     /* clean tx mbuf */
  135 
  136         chan->out_mbuf_head = NULL;     /* reset head mbuf ptr */
  137         chan->out_mbuf_cur = NULL;      /* reset current mbuf ptr */
  138         chan->out_mbuf_cur_ptr = NULL;  /* reset current mbuf data ptr */
  139         chan->out_mbuf_cur_len = 0;     /* reset current mbuf data cnt */
  140 
  141         if(activate != 0)
  142         {
  143                 /* activation */
  144                 isic_hscx_init(sc, h_chan, activate);
  145         }
  146 
  147         splx(s);
  148 }
  149 
  150 /*---------------------------------------------------------------------------*
  151  *      start transmission on a b channel
  152  *---------------------------------------------------------------------------*/
  153 static void
  154 isic_bchannel_start(isdn_layer1token t, int h_chan)
  155 {
  156         struct isic_softc *sc = (struct isic_softc*)t;
  157 
  158         register l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
  159         register int next_len;
  160         register int len;
  161 
  162         int s;
  163         int activity = -1;
  164         int cmd = 0;
  165 
  166         s = splnet();                           /* enter critical section */
  167         if(chan->state & HSCX_TX_ACTIVE)        /* already running ? */
  168         {
  169                 splx(s);
  170                 return;                         /* yes, leave */
  171         }
  172 
  173         /* get next mbuf from queue */
  174 
  175         IF_DEQUEUE(&chan->tx_queue, chan->out_mbuf_head);
  176 
  177         if(chan->out_mbuf_head == NULL)         /* queue empty ? */
  178         {
  179                 splx(s);                        /* leave critical section */
  180                 return;                         /* yes, exit */
  181         }
  182 
  183         /* init current mbuf values */
  184 
  185         chan->out_mbuf_cur = chan->out_mbuf_head;
  186         chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
  187         chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
  188 
  189         /* activity indicator for timeout handling */
  190 
  191         if(chan->bprot == BPROT_NONE)
  192         {
  193                 if(!(isdn_bchan_silence(chan->out_mbuf_cur->m_data,
  194                     chan->out_mbuf_cur->m_len)))
  195                         activity = ACT_TX;
  196         }
  197         else
  198         {
  199                 activity = ACT_TX;
  200         }
  201 
  202         chan->state |= HSCX_TX_ACTIVE;  /* we start transmitting */
  203 
  204         if(sc->sc_trace & TRACE_B_TX)   /* if trace, send mbuf to trace dev */
  205         {
  206                 i4b_trace_hdr hdr;
  207                 hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
  208                 hdr.dir = FROM_TE;
  209                 hdr.count = ++sc->sc_trace_bcount;
  210                 isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr,
  211                         chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
  212         }
  213 
  214         len = 0;        /* # of chars put into HSCX tx fifo this time */
  215 
  216         /*
  217          * fill the HSCX tx fifo with data from the current mbuf. if
  218          * current mbuf holds less data than HSCX fifo length, try to
  219          * get the next mbuf from (a possible) mbuf chain. if there is
  220          * not enough data in a single mbuf or in a chain, then this
  221          * is the last mbuf and we tell the HSCX that it has to send
  222          * CRC and closing flag
  223          */
  224 
  225         while((len < sc->sc_bfifolen) && chan->out_mbuf_cur)
  226         {
  227                 /*
  228                  * put as much data into the HSCX fifo as is
  229                  * available from the current mbuf
  230                  */
  231 
  232                 if((len + chan->out_mbuf_cur_len) >= sc->sc_bfifolen)
  233                         next_len = sc->sc_bfifolen - len;
  234                 else
  235                         next_len = chan->out_mbuf_cur_len;
  236 
  237 #ifdef NOTDEF
  238                 printf("b:mh=%x, mc=%x, mcp=%x, mcl=%d l=%d nl=%d # ",
  239                         chan->out_mbuf_head,
  240                         chan->out_mbuf_cur,
  241                         chan->out_mbuf_cur_ptr,
  242                         chan->out_mbuf_cur_len,
  243                         len,
  244                         next_len);
  245 #endif
  246 
  247                 /* wait for tx fifo write enabled */
  248 
  249                 isic_hscx_waitxfw(sc, h_chan);
  250 
  251                 /* write what we have from current mbuf to HSCX fifo */
  252 
  253                 HSCX_WRFIFO(h_chan, chan->out_mbuf_cur_ptr, next_len);
  254 
  255                 len += next_len;                /* update # of bytes written */
  256                 chan->txcount += next_len;      /* statistics */
  257                 chan->out_mbuf_cur_ptr += next_len;     /* data ptr */
  258                 chan->out_mbuf_cur_len -= next_len;     /* data len */
  259 
  260                 /*
  261                  * in case the current mbuf (of a possible chain) data
  262                  * has been put into the fifo, check if there is a next
  263                  * mbuf in the chain. If there is one, get ptr to it
  264                  * and update the data ptr and the length
  265                  */
  266 
  267                 if((chan->out_mbuf_cur_len <= 0)        &&
  268                   ((chan->out_mbuf_cur = chan->out_mbuf_cur->m_next) != NULL))
  269                 {
  270                         chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
  271                         chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
  272 
  273                         if(sc->sc_trace & TRACE_B_TX)
  274                         {
  275                                 i4b_trace_hdr hdr;
  276                                 hdr.type = (h_chan == HSCX_CH_A ?
  277                                         TRC_CH_B1 : TRC_CH_B2);
  278                                 hdr.dir = FROM_TE;
  279                                 hdr.count = ++sc->sc_trace_bcount;
  280                                 isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token,
  281                                         &hdr,
  282                                         chan->out_mbuf_cur->m_len,
  283                                         chan->out_mbuf_cur->m_data);
  284                         }
  285                 }
  286         }
  287 
  288         /*
  289          * if there is either still data in the current mbuf and/or
  290          * there is a successor on the chain available issue just
  291          * a XTF (transmit) command to HSCX. if ther is no more
  292          * data available from the current mbuf (-chain), issue
  293          * an XTF and an XME (message end) command which will then
  294          * send the CRC and the closing HDLC flag sequence
  295          */
  296 
  297         if(chan->out_mbuf_cur && (chan->out_mbuf_cur_len > 0))
  298         {
  299                 /*
  300                  * more data available, send current fifo out.
  301                  * next xfer to HSCX tx fifo is done in the
  302                  * HSCX interrupt routine.
  303                  */
  304 
  305                 cmd |= HSCX_CMDR_XTF;
  306         }
  307         else
  308         {
  309                 /* end of mbuf chain */
  310 
  311                 if(chan->bprot == BPROT_NONE)
  312                         cmd |= HSCX_CMDR_XTF;
  313                 else
  314                         cmd |= HSCX_CMDR_XTF | HSCX_CMDR_XME;
  315 
  316                 i4b_Bfreembuf(chan->out_mbuf_head);     /* free mbuf chain */
  317 
  318                 chan->out_mbuf_head = NULL;
  319                 chan->out_mbuf_cur = NULL;
  320                 chan->out_mbuf_cur_ptr = NULL;
  321                 chan->out_mbuf_cur_len = 0;
  322         }
  323 
  324         /* call timeout handling routine */
  325 
  326         if(activity == ACT_RX || activity == ACT_TX)
  327                 (*chan->l4_driver->bch_activity)(
  328                     chan->l4_driver_softc, activity);
  329 
  330         if(cmd)
  331                 isic_hscx_cmd(sc, h_chan, cmd);
  332 
  333         splx(s);
  334 }
  335 
  336 /*---------------------------------------------------------------------------*
  337  *      fill statistics struct
  338  *---------------------------------------------------------------------------*/
  339 static void
  340 isic_bchannel_stat(isdn_layer1token t, int h_chan, bchan_statistics_t *bsp)
  341 {
  342         struct isic_softc *sc = (struct isic_softc*)t;
  343         l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
  344         int s;
  345 
  346         s = splnet();
  347 
  348         bsp->outbytes = chan->txcount;
  349         bsp->inbytes = chan->rxcount;
  350 
  351         chan->txcount = 0;
  352         chan->rxcount = 0;
  353 
  354         splx(s);
  355 }
  356 
  357 /*---------------------------------------------------------------------------*
  358  *      return the address of isic drivers linktab
  359  *---------------------------------------------------------------------------*/
  360 isdn_link_t *
  361 isic_ret_linktab(void *token, int channel)
  362 {
  363         struct l2_softc *l2sc = token;
  364         struct isic_softc *sc = l2sc->l1_token;
  365         l1_bchan_state_t *chan = &sc->sc_chan[channel];
  366 
  367         return(&chan->isdn_linktab);
  368 }
  369 
  370 /*---------------------------------------------------------------------------*
  371  *      set the driver linktab in the b channel softc
  372  *---------------------------------------------------------------------------*/
  373 void
  374 isic_set_link(void *token, int channel, const struct isdn_l4_driver_functions *l4_driver, void *l4_driver_softc)
  375 {
  376         struct l2_softc *l2sc = token;
  377         struct isic_softc *sc = l2sc->l1_token;
  378         l1_bchan_state_t *chan = &sc->sc_chan[channel];
  379 
  380         chan->l4_driver = l4_driver;
  381         chan->l4_driver_softc = l4_driver_softc;
  382 }
  383 
  384 static const struct isdn_l4_bchannel_functions
  385 isic_l4_bchannel_functions = {
  386         isic_bchannel_setup,
  387         isic_bchannel_start,
  388         isic_bchannel_stat
  389 };
  390 
  391 /*---------------------------------------------------------------------------*
  392  *      initialize our local linktab
  393  *---------------------------------------------------------------------------*/
  394 void
  395 isic_init_linktab(struct isic_softc *sc)
  396 {
  397         l1_bchan_state_t *chan = &sc->sc_chan[HSCX_CH_A];
  398         isdn_link_t *lt = &chan->isdn_linktab;
  399 
  400         /* local setup */
  401         lt->l1token = sc;
  402         lt->channel = HSCX_CH_A;
  403         lt->bchannel_driver = &isic_l4_bchannel_functions;
  404         lt->tx_queue = &chan->tx_queue;
  405 
  406         /* used by non-HDLC data transfers, i.e. telephony drivers */
  407         lt->rx_queue = &chan->rx_queue;
  408 
  409         /* used by HDLC data transfers, i.e. ipr and isp drivers */
  410         lt->rx_mbuf = &chan->in_mbuf;
  411 
  412         chan = &sc->sc_chan[HSCX_CH_B];
  413         lt = &chan->isdn_linktab;
  414 
  415         lt->l1token = sc;
  416         lt->channel = HSCX_CH_B;
  417         lt->bchannel_driver = &isic_l4_bchannel_functions;
  418         lt->tx_queue = &chan->tx_queue;
  419 
  420         /* used by non-HDLC data transfers, i.e. telephony drivers */
  421         lt->rx_queue = &chan->rx_queue;
  422 
  423         /* used by HDLC data transfers, i.e. ipr and isp drivers */
  424         lt->rx_mbuf = &chan->in_mbuf;
  425 }

Cache object: f1f9d63efeb142a21933ae5748bc8cdd


[ 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.