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_capi_l4if.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 /*      $NetBSD: i4b_capi_l4if.c,v 1.9 2006/11/16 01:33:49 christos Exp $       */
    2 
    3 /*
    4  * Copyright (c) 2001-2003 Cubical Solutions Ltd. All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  *
   27  * capi/capi_l4if.c     The CAPI i4b L4/device interface.
   28  *
   29  * $FreeBSD: src/sys/i4b/capi/capi_l4if.c,v 1.4 2002/04/04 21:03:20 jhb Exp $
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __KERNEL_RCSID(0, "$NetBSD: i4b_capi_l4if.c,v 1.9 2006/11/16 01:33:49 christos Exp $");
   34 
   35 #include <sys/param.h>
   36 #include <sys/kernel.h>
   37 #include <sys/systm.h>
   38 #include <sys/mbuf.h>
   39 #include <sys/socket.h>
   40 #include <sys/callout.h>
   41 #include <net/if.h>
   42 
   43 #include <netisdn/i4b_debug.h>
   44 #include <netisdn/i4b_ioctl.h>
   45 #include <netisdn/i4b_cause.h>
   46 #include <netisdn/i4b_l3l4.h>
   47 #include <netisdn/i4b_mbuf.h>
   48 #include <netisdn/i4b_global.h>
   49 #include <netisdn/i4b_l4.h>
   50 #include <netisdn/i4b_capi.h>
   51 #include <netisdn/i4b_capi_msgs.h>
   52 
   53 static void n_connect_request(call_desc_t *);
   54 static void n_connect_response(call_desc_t *, int response, int cause);
   55 static void n_disconnect_request(call_desc_t *, int cause);
   56 static void n_alert_request(call_desc_t *);
   57 static void n_mgmt_command(struct isdn_l3_driver *, int cmd, void *parm);
   58 static int  n_download(void *, int, struct isdn_dr_prot *);
   59 
   60 static int ncapi = 0;
   61 
   62 /*
   63 //  i4b_capi_{ret,set}_linktab
   64 //      i4b driver glue.
   65 //
   66 //  i4b_capi_bch_config
   67 //      Called by i4b driver to flush + {en,dis}able a channel.
   68 //
   69 //  i4b_capi_bch_start_tx
   70 //      Called by i4b driver to transmit a queued mbuf.
   71 //
   72 //  i4b_capi_bch_stat
   73 //      Called by i4b driver to obtain statistics information.
   74 */
   75 
   76 static isdn_link_t *
   77 i4b_capi_ret_linktab(void *token, int channel)
   78 {
   79     capi_softc_t *sc = token;
   80 
   81     return &sc->sc_bchan[channel].capi_isdn_linktab;
   82 }
   83 
   84 static void
   85 i4b_capi_set_link(void *token, int channel,
   86     const struct isdn_l4_driver_functions *l4_driver, void *l4_inst)
   87 {
   88     capi_softc_t *sc = token;
   89 
   90     sc->sc_bchan[channel].l4_driver = l4_driver;
   91     sc->sc_bchan[channel].l4_driver_softc = l4_inst;
   92 }
   93 
   94 static void
   95 i4b_capi_bch_config(void *token, int chan, int bprot, int activate)
   96 {
   97     capi_softc_t *sc = token;
   98 
   99     i4b_Bcleanifq(&sc->sc_bchan[chan].tx_queue);
  100     sc->sc_bchan[chan].tx_queue.ifq_maxlen = IFQ_MAXLEN;
  101     sc->sc_bchan[chan].txcount = 0;
  102 
  103     /* The telephony drivers use rx_queue for receive. */
  104     i4b_Bcleanifq(&sc->sc_bchan[chan].rx_queue);
  105     sc->sc_bchan[chan].rx_queue.ifq_maxlen = IFQ_MAXLEN;
  106     sc->sc_bchan[chan].rxcount = 0;
  107 
  108     /* HDLC frames are put to in_mbuf */
  109     i4b_Bfreembuf(sc->sc_bchan[chan].in_mbuf);
  110     sc->sc_bchan[chan].in_mbuf = NULL;
  111 
  112     /* Because of the difference, we need to remember the protocol. */
  113     sc->sc_bchan[chan].bprot = bprot;
  114     sc->sc_bchan[chan].busy = 0;
  115 }
  116 
  117 static void
  118 i4b_capi_bch_start_tx(void *token, int chan)
  119 {
  120     capi_softc_t *sc = token;
  121     int s;
  122 
  123     s = splnet();
  124 
  125     if (sc->sc_bchan[chan].state != B_CONNECTED) {
  126         splx(s);
  127         printf("capi%d: start_tx on unconnected channel\n", sc->sc_unit);
  128         return;
  129     }
  130 
  131     if (sc->sc_bchan[chan].busy) {
  132         splx(s);
  133         return;
  134     }
  135 
  136     capi_start_tx(sc, chan);
  137 
  138     splx(s);
  139 }
  140 
  141 static void
  142 i4b_capi_bch_stat(void *token, int chan, bchan_statistics_t *bsp)
  143 {
  144     capi_softc_t *sc = token;
  145     int s = splnet();
  146 
  147     bsp->outbytes = sc->sc_bchan[chan].txcount;
  148     bsp->inbytes = sc->sc_bchan[chan].rxcount;
  149 
  150     sc->sc_bchan[chan].txcount = 0;
  151     sc->sc_bchan[chan].rxcount = 0;
  152 
  153     splx(s);
  154 }
  155 
  156 int capi_start_tx(void *token, int chan)
  157 {
  158     capi_softc_t *sc = token;
  159     struct mbuf *m_b3;
  160     int sent = 0;
  161 
  162     IF_DEQUEUE(&sc->sc_bchan[chan].tx_queue, m_b3);
  163     while (m_b3) {
  164         struct mbuf *m = m_b3->m_next;
  165 
  166         sc->sc_bchan[chan].txcount += m_b3->m_len;
  167         capi_data_b3_req(sc, chan, m_b3);
  168         sent++;
  169 
  170         m_b3 = m;
  171     }
  172 
  173     if (sc->sc_bchan[chan].l4_driver) {
  174         capi_bchan_t *bch = &sc->sc_bchan[chan];
  175 
  176         /* Notify i4b driver of activity, and if the queue is drained. */
  177         if (sent)
  178             (*bch->l4_driver->bch_activity)(bch->l4_driver_softc, ACT_TX);
  179 
  180         if (IF_QEMPTY(&bch->tx_queue))
  181             (*bch->l4_driver->bch_tx_queue_empty)(bch->l4_driver_softc);
  182     }
  183 
  184     return sent;
  185 }
  186 
  187 static const struct isdn_l4_bchannel_functions
  188 capi_l4_driver = {
  189     i4b_capi_bch_config,
  190     i4b_capi_bch_start_tx,
  191     i4b_capi_bch_stat
  192 };
  193 
  194 /*
  195 //  n_mgmt_command
  196 //      i4b L4 management command.
  197 */
  198 
  199 static void
  200 n_mgmt_command(struct isdn_l3_driver *l3, int op, void *arg)
  201 {
  202     capi_softc_t *sc = l3->l1_token;
  203 
  204 #if 0
  205     printf("capi%d: mgmt command %d\n", sc->sc_unit, op);
  206 #endif
  207 
  208     switch(op) {
  209     case CMR_DOPEN:
  210         sc->sc_enabled = 1;
  211         break;
  212 
  213     case CMR_DCLOSE:
  214         sc->sc_enabled = 0;
  215         break;
  216 
  217     case CMR_SETTRACE:
  218         break;
  219 
  220     default:
  221         break;
  222     }
  223 }
  224 
  225 /*
  226 //  n_connect_request
  227 //      i4b L4 wants to connect. We assign a B channel to the call,
  228 //      send a CAPI_CONNECT_REQ, and set the channel to B_CONNECT_CONF.
  229 */
  230 
  231 static void
  232 n_connect_request(call_desc_t *cd)
  233 {
  234     capi_softc_t *sc;
  235     int bch, s;
  236 
  237     sc = cd->l3drv->l1_token;
  238     bch = cd->channelid;
  239 
  240     s = splnet();
  241 
  242     if ((bch < 0) || (bch >= sc->sc_nbch))
  243         for (bch = 0; bch < sc->sc_nbch; bch++)
  244             if (sc->sc_bchan[bch].state == B_FREE)
  245                 break;
  246 
  247     if (bch == sc->sc_nbch) {
  248         splx(s);
  249         printf("capi%d: no free B channel\n", sc->sc_unit);
  250         return;
  251     }
  252 
  253     cd->channelid = bch;
  254 
  255     capi_connect_req(sc, cd);
  256     splx(s);
  257 }
  258 
  259 /*
  260 //  n_connect_response
  261 //      i4b L4 answers a call. We send a CONNECT_RESP with the proper
  262 //      Reject code, and set the channel to B_CONNECT_B3_IND or B_FREE,
  263 //      depending whether we answer or not.
  264 */
  265 
  266 static void
  267 n_connect_response(call_desc_t *cd, int response, int cause)
  268 {
  269     capi_softc_t *sc;
  270     int s;
  271 
  272     sc = cd->l3drv->l1_token;
  273 
  274     T400_stop(cd);
  275 
  276     cd->response = response;
  277     cd->cause_out = cause;
  278 
  279     s = splnet();
  280     capi_connect_resp(sc, cd);
  281     splx(s);
  282 }
  283 
  284 /*
  285 //  n_disconnect_request
  286 //      i4b L4 wants to disconnect. We send a DISCONNECT_REQ and
  287 //      set the channel to B_DISCONNECT_CONF.
  288 */
  289 
  290 static void
  291 n_disconnect_request(call_desc_t *cd, int cause)
  292 {
  293     capi_softc_t *sc;
  294     int s;
  295 
  296     sc = cd->l3drv->l1_token;
  297 
  298     cd->cause_out = cause;
  299 
  300     s = splnet();
  301     capi_disconnect_req(sc, cd);
  302     splx(s);
  303 }
  304 
  305 /*
  306 //  n_alert_request
  307 //      i4b L4 wants to alert an incoming call. We send ALERT_REQ.
  308 */
  309 
  310 static void
  311 n_alert_request(call_desc_t *cd)
  312 {
  313     capi_softc_t *sc;
  314     int s;
  315 
  316     sc = cd->l3drv->l1_token;
  317 
  318     s = splnet();
  319     capi_alert_req(sc, cd);
  320     splx(s);
  321 }
  322 
  323 /*
  324 //  n_download
  325 //      L4 -> firmware download
  326 */
  327 
  328 static int
  329 n_download(void *token, int numprotos, struct isdn_dr_prot *protocols)
  330 {
  331     capi_softc_t *sc = token;
  332 
  333     if (sc->load) {
  334         (*sc->load)(sc, protocols[0].bytecount,
  335                                protocols[0].microcode);
  336         return(0);
  337     }
  338 
  339     return(ENXIO);
  340 }
  341 
  342 static const struct isdn_l3_driver_functions
  343 capi_l3_functions = {
  344     i4b_capi_ret_linktab,
  345     i4b_capi_set_link,
  346     n_connect_request,
  347     n_connect_response,
  348     n_disconnect_request,
  349     n_alert_request,
  350     n_download,
  351     NULL,
  352     n_mgmt_command
  353 };
  354 
  355 /*
  356 //  capi_ll_attach
  357 //      Called by a link layer driver at boot time.
  358 */
  359 
  360 int
  361 capi_ll_attach(capi_softc_t *sc, const char *devname, const char *cardname)
  362 {
  363     struct isdn_l3_driver *l3drv;
  364     int i;
  365 
  366     /* Unit state */
  367 
  368     sc->sc_enabled = 0;
  369     sc->sc_state = C_DOWN;
  370     sc->sc_msgid = 0;
  371 
  372     for (i = 0; i < sc->sc_nbch; i++) {
  373         sc->sc_bchan[i].ncci = INVALID;
  374         sc->sc_bchan[i].msgid = 0;
  375         sc->sc_bchan[i].busy = 0;
  376         sc->sc_bchan[i].state = B_FREE;
  377 
  378         memset(&sc->sc_bchan[i].tx_queue, 0, sizeof(struct ifqueue));
  379         memset(&sc->sc_bchan[i].rx_queue, 0, sizeof(struct ifqueue));
  380         sc->sc_bchan[i].tx_queue.ifq_maxlen = IFQ_MAXLEN;
  381         sc->sc_bchan[i].rx_queue.ifq_maxlen = IFQ_MAXLEN;
  382 
  383         sc->sc_bchan[i].txcount = 0;
  384         sc->sc_bchan[i].rxcount = 0;
  385 
  386         sc->sc_bchan[i].cdid = CDID_UNUSED;
  387         sc->sc_bchan[i].bprot = BPROT_NONE;
  388         sc->sc_bchan[i].in_mbuf = NULL;
  389 
  390         sc->sc_bchan[i].capi_isdn_linktab.l1token = sc;
  391         sc->sc_bchan[i].capi_isdn_linktab.channel = i;
  392         sc->sc_bchan[i].capi_isdn_linktab.bchannel_driver = &capi_l4_driver;
  393         sc->sc_bchan[i].capi_isdn_linktab.tx_queue = &sc->sc_bchan[i].tx_queue;
  394         sc->sc_bchan[i].capi_isdn_linktab.rx_queue = &sc->sc_bchan[i].rx_queue;
  395         sc->sc_bchan[i].capi_isdn_linktab.rx_mbuf = &sc->sc_bchan[i].in_mbuf;
  396     }
  397 
  398     l3drv = isdn_attach_isdnif(devname, cardname, sc, &capi_l3_functions,
  399         sc->sc_nbch);
  400 
  401     l3drv->tei = -1;
  402     l3drv->dl_est = DL_DOWN;
  403     l3drv->nbch = sc->sc_nbch;
  404 
  405     sc->sc_unit = ncapi++;
  406     sc->capi_isdnif = l3drv->isdnif;
  407 
  408     isdn_isdnif_ready(l3drv->isdnif);
  409 
  410     printf("capi%d: card type %d attached\n", sc->sc_unit, sc->card_type);
  411 
  412     return(0);
  413 }
  414 
  415 
  416 /*
  417 //  capi_ll_detach
  418 */
  419 
  420 int
  421 capi_ll_detach(capi_softc_t *sc)
  422 {
  423 
  424         (void)sc;
  425         /* TODO */
  426         return(0);
  427 }

Cache object: 99b39244e542522341014b76a71fef7b


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