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_i4bdrv.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_i4bdrv.c - i4b userland interface driver
   28  *      --------------------------------------------
   29  *
   30  *      $Id: i4b_i4bdrv.c,v 1.34 2008/03/01 18:59:45 veego Exp $
   31  *
   32  * $FreeBSD$
   33  *
   34  *      last edit-date: [Fri Jan  5 11:33:47 2001]
   35  *
   36  *---------------------------------------------------------------------------*/
   37 
   38 #include <sys/cdefs.h>
   39 __KERNEL_RCSID(0, "$NetBSD: i4b_i4bdrv.c,v 1.34 2008/03/01 18:59:45 veego Exp $");
   40 
   41 #include "isdn.h"
   42 
   43 #if NISDN > 0
   44 
   45 #include <sys/param.h>
   46 
   47 #if defined(__FreeBSD__)
   48 #include <sys/ioccom.h>
   49 #include <sys/malloc.h>
   50 #include <sys/uio.h>
   51 #else
   52 #include <sys/ioctl.h>
   53 #endif
   54 
   55 #include <sys/kernel.h>
   56 #include <sys/systm.h>
   57 #include <sys/conf.h>
   58 #include <sys/mbuf.h>
   59 #include <sys/proc.h>
   60 #include <sys/fcntl.h>
   61 #include <sys/socket.h>
   62 #include <sys/select.h>
   63 #include <net/if.h>
   64 
   65 #ifdef __FreeBSD__
   66 
   67 #if defined(__FreeBSD__) && __FreeBSD__ == 3
   68 #include "opt_devfs.h"
   69 #endif
   70 
   71 #ifdef DEVFS
   72 #include <sys/devfsext.h>
   73 #endif
   74 
   75 #endif /* __FreeBSD__*/
   76 
   77 #ifdef __FreeBSD__
   78 #include <machine/i4b_debug.h>
   79 #include <machine/i4b_ioctl.h>
   80 #include <machine/i4b_cause.h>
   81 #else
   82 #include <netisdn/i4b_debug.h>
   83 #include <netisdn/i4b_ioctl.h>
   84 #include <netisdn/i4b_cause.h>
   85 #endif
   86 
   87 #include <netisdn/i4b_l3l4.h>
   88 #include <netisdn/i4b_mbuf.h>
   89 #include <netisdn/i4b_global.h>
   90 
   91 #include <netisdn/i4b_l4.h>
   92 
   93 #ifdef OS_USES_POLL
   94 #include <sys/poll.h>
   95 #endif
   96 
   97 struct selinfo select_rd_info;
   98 
   99 static struct ifqueue i4b_rdqueue;
  100 static int openflag = 0;
  101 static int selflag = 0;
  102 static int readflag = 0;
  103 
  104 #if defined(__FreeBSD__) && __FreeBSD__ == 3
  105 #ifdef DEVFS
  106 static void *devfs_token;
  107 #endif
  108 #endif
  109 
  110 #ifndef __FreeBSD__
  111 
  112 #define PDEVSTATIC      /* - not static - */
  113 PDEVSTATIC void isdnattach __P((void));
  114 PDEVSTATIC int isdnopen __P((dev_t dev, int flag, int fmt, struct lwp *l));
  115 PDEVSTATIC int isdnclose __P((dev_t dev, int flag, int fmt, struct lwp *l));
  116 PDEVSTATIC int isdnread __P((dev_t dev, struct uio *uio, int ioflag));
  117 PDEVSTATIC int isdnioctl __P((dev_t dev, u_long cmd, void *data, int flag, struct lwp *l));
  118 
  119 #ifdef OS_USES_POLL
  120 PDEVSTATIC int isdnpoll __P((dev_t dev, int events, struct lwp *l));
  121 PDEVSTATIC int isdnkqfilter __P((dev_t dev, struct knote *kn));
  122 #else
  123 PDEVSTATIC int isdnselect __P((dev_t dev, int rw, struct lwp *l));
  124 #endif
  125 
  126 #endif /* #ifndef __FreeBSD__ */
  127 
  128 #if BSD > 199306 && defined(__FreeBSD__)
  129 
  130 #define PDEVSTATIC      static
  131 
  132 PDEVSTATIC      d_open_t        i4bopen;
  133 PDEVSTATIC      d_close_t       i4bclose;
  134 PDEVSTATIC      d_read_t        i4bread;
  135 PDEVSTATIC      d_ioctl_t       i4bioctl;
  136 
  137 #ifdef OS_USES_POLL
  138 PDEVSTATIC      d_poll_t        i4bpoll;
  139 #define POLLFIELD               i4bpoll
  140 #else
  141 PDEVSTATIC      d_select_t      i4bselect;
  142 #define POLLFIELD               i4bselect
  143 #endif
  144 
  145 #define CDEV_MAJOR 60
  146 
  147 #if defined(__FreeBSD__) && __FreeBSD__ >= 4
  148 static struct cdevsw i4b_cdevsw = {
  149         /* open */      i4bopen,
  150         /* close */     i4bclose,
  151         /* read */      i4bread,
  152         /* write */     nowrite,
  153         /* ioctl */     i4bioctl,
  154         /* poll */      POLLFIELD,
  155         /* mmap */      nommap,
  156         /* strategy */  nostrategy,
  157         /* name */      "i4b",
  158         /* maj */       CDEV_MAJOR,
  159         /* dump */      nodump,
  160         /* psize */     nopsize,
  161         /* flags */     0,
  162         /* bmaj */      -1
  163 };
  164 #else
  165 static struct cdevsw i4b_cdevsw = {
  166         i4bopen,        i4bclose,       i4bread,        nowrite,
  167         i4bioctl,       nostop,         nullreset,      nodevtotty,
  168         POLLFIELD,      nommap,         NULL,           "i4b", NULL,    -1
  169 };
  170 #endif
  171 
  172 PDEVSTATIC void i4battach(void *);
  173 PSEUDO_SET(i4battach, i4b_i4bdrv);
  174 
  175 static void
  176 i4b_drvinit(void *unused)
  177 {
  178 #if defined(__FreeBSD__) && __FreeBSD__ >= 4
  179         cdevsw_add(&i4b_cdevsw);
  180 #else
  181         static int i4b_devsw_installed = 0;
  182         dev_t dev;
  183 
  184         if( ! i4b_devsw_installed )
  185         {
  186                 dev = makedev(CDEV_MAJOR,0);
  187                 cdevsw_add(&dev,&i4b_cdevsw,NULL);
  188                 i4b_devsw_installed = 1;
  189         }
  190 #endif
  191 }
  192 
  193 SYSINIT(i4bdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,i4b_drvinit,NULL)
  194 
  195 #endif /* BSD > 199306 && defined(__FreeBSD__) */
  196 
  197 #ifdef __NetBSD__
  198 const struct cdevsw isdn_cdevsw = {
  199         isdnopen, isdnclose, isdnread, nowrite, isdnioctl,
  200         nostop, notty, isdnpoll, nommap, isdnkqfilter, D_OTHER
  201 };
  202 #endif /* __NetBSD__ */
  203 
  204 #ifdef __bsdi__
  205 #include <sys/device.h>
  206 int i4bmatch(struct device *parent, struct cfdata *cf, void *aux);
  207 void dummy_i4battach(struct device*, struct device *, void *);
  208 
  209 #define CDEV_MAJOR 65
  210 
  211 static struct cfdriver i4bcd =
  212         { NULL, "i4b", i4bmatch, dummy_i4battach, DV_DULL,
  213           sizeof(struct cfdriver) };
  214 struct devsw i4bsw =
  215         { &i4bcd,
  216           i4bopen,      i4bclose,       i4bread,        nowrite,
  217           i4bioctl,     i4bselect,      nommap,         nostrat,
  218           nodump,       nopsize,        0,              nostop
  219 };
  220 
  221 int
  222 i4bmatch(struct device *parent, struct cfdata *cf, void *aux)
  223 {
  224         printf("i4bmatch: aux=0x%x\n", aux);
  225         return 1;
  226 }
  227 void
  228 dummy_i4battach(struct device *parent, struct device *self, void *aux)
  229 {
  230         printf("dummy_i4battach: aux=0x%x\n", aux);
  231 }
  232 #endif /* __bsdi__ */
  233 
  234 /*---------------------------------------------------------------------------*
  235  *      interface attach routine
  236  *---------------------------------------------------------------------------*/
  237 PDEVSTATIC void
  238 #ifdef __FreeBSD__
  239 isdnattach(void *dummy)
  240 #else
  241 isdnattach()
  242 #endif
  243 {
  244         i4b_rdqueue.ifq_maxlen = IFQ_MAXLEN;
  245         selinit(&select_rd_info);
  246 
  247 #if defined(__FreeBSD__)
  248 #if __FreeBSD__ == 3
  249 
  250 #ifdef DEVFS
  251         devfs_token = devfs_add_devswf(&i4b_cdevsw, 0, DV_CHR,
  252                                        UID_ROOT, GID_WHEEL, 0600,
  253                                        "i4b");
  254 #endif
  255 
  256 #else
  257         make_dev(&i4b_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "i4b");
  258 #endif
  259 #endif
  260 }
  261 
  262 /*---------------------------------------------------------------------------*
  263  *      i4bopen - device driver open routine
  264  *---------------------------------------------------------------------------*/
  265 PDEVSTATIC int
  266 isdnopen(dev_t dev, int flag, int fmt, struct lwp *l)
  267 {
  268         int x;
  269 
  270         if(minor(dev))
  271                 return(ENXIO);
  272 
  273         if(openflag)
  274                 return(EBUSY);
  275 
  276         x = splnet();
  277         openflag = 1;
  278         i4b_l4_daemon_attached();
  279         splx(x);
  280 
  281         return(0);
  282 }
  283 
  284 /*---------------------------------------------------------------------------*
  285  *      i4bclose - device driver close routine
  286  *---------------------------------------------------------------------------*/
  287 PDEVSTATIC int
  288 isdnclose(dev_t dev, int flag, int fmt,
  289         struct lwp *l)
  290 {
  291         int x = splnet();
  292         openflag = 0;
  293         i4b_l4_daemon_detached();
  294         i4b_Dcleanifq(&i4b_rdqueue);
  295         splx(x);
  296         return(0);
  297 }
  298 
  299 /*---------------------------------------------------------------------------*
  300  *      i4bread - device driver read routine
  301  *---------------------------------------------------------------------------*/
  302 PDEVSTATIC int
  303 isdnread(dev_t dev, struct uio *uio, int ioflag)
  304 {
  305         struct mbuf *m;
  306         int x;
  307         int error = 0;
  308 
  309         if(minor(dev))
  310                 return(ENODEV);
  311 
  312         x = splnet();
  313         while(IF_QEMPTY(&i4b_rdqueue))
  314         {
  315                 readflag = 1;
  316                 error = tsleep((void *) &i4b_rdqueue, (PZERO + 1) | PCATCH, "bird", 0);
  317                 if (error != 0) {
  318                         splx(x);
  319                         return error;
  320                 }
  321         }
  322 
  323         IF_DEQUEUE(&i4b_rdqueue, m);
  324 
  325         splx(x);
  326 
  327         if(m && m->m_len)
  328                 error = uiomove(m->m_data, m->m_len, uio);
  329         else
  330                 error = EIO;
  331 
  332         if(m)
  333                 i4b_Dfreembuf(m);
  334 
  335         return(error);
  336 }
  337 
  338 /*---------------------------------------------------------------------------*
  339  *      i4bioctl - device driver ioctl routine
  340  *---------------------------------------------------------------------------*/
  341 PDEVSTATIC int
  342 isdnioctl(dev_t dev, u_long cmd, void *data, int flag,
  343         struct lwp *l)
  344 {
  345         struct isdn_l3_driver *d;
  346         call_desc_t *cd;
  347         int error = 0;
  348 
  349         if(minor(dev))
  350                 return(ENODEV);
  351 
  352         switch(cmd)
  353         {
  354                 /* cdid request, reserve cd and return cdid */
  355 
  356                 case I4B_CDID_REQ:
  357                 {
  358                         msg_cdid_req_t *mir;
  359                         mir = (msg_cdid_req_t *)data;
  360                         cd = reserve_cd();
  361                         mir->cdid = cd->cdid;
  362                         break;
  363                 }
  364 
  365                 /* connect request, dial out to remote */
  366 
  367                 case I4B_CONNECT_REQ:
  368                 {
  369                         msg_connect_req_t *mcr;
  370                         mcr = (msg_connect_req_t *)data;        /* setup ptr */
  371 
  372                         if((cd = cd_by_cdid(mcr->cdid)) == NULL)/* get cd */
  373                         {
  374                                 NDBGL4(L4_ERR, "I4B_CONNECT_REQ ioctl, cdid not found!");
  375                                 error = EINVAL;
  376                                 break;
  377                         }
  378                         cd->isdnif = -1;
  379                         cd->l3drv = NULL;
  380 
  381                         d = isdn_find_l3_by_isdnif(mcr->controller);
  382                         if (d == NULL) {
  383                                 error = EINVAL;
  384                                 break;
  385                         }
  386 
  387                         /* prevent dialling on leased lines */
  388                         if(d->protocol == PROTOCOL_D64S)
  389                         {
  390                                 SET_CAUSE_TYPE(cd->cause_in, CAUSET_I4B);
  391                                 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_LLDIAL);
  392                                 i4b_l4_disconnect_ind(cd);
  393                                 freecd_by_cd(cd);
  394                                 break;
  395                         }
  396 
  397                         cd->isdnif = mcr->controller;   /* fill cd */
  398                         cd->l3drv = d;
  399                         cd->bprot = mcr->bprot;
  400                         cd->bchan_driver_index = mcr->driver;
  401                         cd->bchan_driver_unit = mcr->driver_unit;
  402                         cd->cr = get_rand_cr(cd->isdnif);
  403 
  404                         cd->shorthold_data.shorthold_algorithm = mcr->shorthold_data.shorthold_algorithm;
  405                         cd->shorthold_data.unitlen_time  = mcr->shorthold_data.unitlen_time;
  406                         cd->shorthold_data.idle_time     = mcr->shorthold_data.idle_time;
  407                         cd->shorthold_data.earlyhup_time = mcr->shorthold_data.earlyhup_time;
  408 
  409                         cd->last_aocd_time = 0;
  410                         if(mcr->unitlen_method == ULEN_METHOD_DYNAMIC)
  411                                 cd->aocd_flag = 1;
  412                         else
  413                                 cd->aocd_flag = 0;
  414 
  415                         cd->cunits = 0;
  416 
  417                         cd->max_idle_time = 0;  /* this is outgoing */
  418 
  419                         cd->dir = DIR_OUTGOING;
  420 
  421                         NDBGL4(L4_TIMO, "I4B_CONNECT_REQ times, algorithm=%ld unitlen=%ld idle=%ld earlyhup=%ld",
  422                                         (long)cd->shorthold_data.shorthold_algorithm, (long)cd->shorthold_data.unitlen_time,
  423                                         (long)cd->shorthold_data.idle_time, (long)cd->shorthold_data.earlyhup_time);
  424 
  425                         strlcpy(cd->dst_telno, mcr->dst_telno,
  426                             sizeof(cd->dst_telno));
  427                         strlcpy(cd->src_telno, mcr->src_telno,
  428                             sizeof(cd->src_telno));
  429                         cd->display[0] = '\0';
  430 
  431                         SET_CAUSE_TYPE(cd->cause_in, CAUSET_I4B);
  432                         SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NORMAL);
  433 
  434                         /*
  435                          * If we want a specific channel, check if that
  436                          * one is available.
  437                          */
  438                         if ((mcr->channel >= 0) && (mcr->channel < d->nbch)) {
  439                                 if(d->bch_state[mcr->channel] != BCH_ST_FREE)
  440                                         SET_CAUSE_VAL(cd->cause_in,
  441                                             CAUSE_I4B_NOCHAN);
  442 
  443                         /*
  444                          * If any channel will do, see if any are free.
  445                          */
  446                         } else if (mcr->channel == CHAN_ANY) {
  447                                 int i;
  448 
  449                                 for (i = 0; i < d->nbch; i++)
  450                                         if (d->bch_state[i] == BCH_ST_FREE)
  451                                                 break;
  452 
  453                                 if (i == d->nbch)
  454                                         SET_CAUSE_VAL(cd->cause_in,
  455                                             CAUSE_I4B_NOCHAN);
  456 
  457                         } else {
  458                                 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
  459                         }
  460 
  461                         cd->channelid = mcr->channel;
  462 
  463                         cd->isdntxdelay = mcr->txdelay;
  464 
  465                         if((GET_CAUSE_VAL(cd->cause_in)) != CAUSE_I4B_NORMAL)
  466                         {
  467                                 i4b_l4_disconnect_ind(cd);
  468                                 freecd_by_cd(cd);
  469                         }
  470                         else
  471                         {
  472                                 d->l3driver->N_CONNECT_REQUEST(cd);
  473                         }
  474                         break;
  475                 }
  476 
  477                 /* connect response, accept/reject/ignore incoming call */
  478 
  479                 case I4B_CONNECT_RESP:
  480                 {
  481                         msg_connect_resp_t *mcrsp;
  482 
  483                         mcrsp = (msg_connect_resp_t *)data;
  484 
  485                         if((cd = cd_by_cdid(mcrsp->cdid)) == NULL)/* get cd */
  486                         {
  487                                 NDBGL4(L4_ERR, "I4B_CONNECT_RESP ioctl, cdid not found!");
  488                                 error = EINVAL;
  489                                 break;
  490                         }
  491 
  492                         T400_stop(cd);
  493 
  494                         cd->bchan_driver_index = mcrsp->driver;
  495                         cd->bchan_driver_unit = mcrsp->driver_unit;
  496                         cd->max_idle_time = mcrsp->max_idle_time;
  497 
  498                         cd->shorthold_data.shorthold_algorithm = SHA_FIXU;
  499                         cd->shorthold_data.unitlen_time = 0;    /* this is incoming */
  500                         cd->shorthold_data.idle_time = 0;
  501                         cd->shorthold_data.earlyhup_time = 0;
  502 
  503                         cd->isdntxdelay = mcrsp->txdelay;
  504 
  505                         NDBGL4(L4_TIMO, "I4B_CONNECT_RESP max_idle_time set to %ld seconds", (long)cd->max_idle_time);
  506 
  507                         d = isdn_find_l3_by_isdnif(cd->isdnif);
  508                         if (d == NULL) {
  509                                 error = EINVAL;
  510                                 break;
  511                         }
  512                         d->l3driver->N_CONNECT_RESPONSE(cd, mcrsp->response, mcrsp->cause);
  513                         break;
  514                 }
  515 
  516                 /* disconnect request, actively terminate connection */
  517 
  518                 case I4B_DISCONNECT_REQ:
  519                 {
  520                         msg_discon_req_t *mdr;
  521 
  522                         mdr = (msg_discon_req_t *)data;
  523 
  524                         if((cd = cd_by_cdid(mdr->cdid)) == NULL)/* get cd */
  525                         {
  526                                 NDBGL4(L4_ERR, "I4B_DISCONNECT_REQ ioctl, cdid %d not found!", mdr->cdid);
  527                                 error = EINVAL;
  528                                 break;
  529                         }
  530 
  531                         /* preset causes with our cause */
  532                         cd->cause_in = cd->cause_out = mdr->cause;
  533 
  534                         d = isdn_find_l3_by_isdnif(cd->isdnif);
  535                         if (d == NULL) {
  536                                 error = EINVAL;
  537                                 break;
  538                         }
  539 
  540                         d->l3driver->N_DISCONNECT_REQUEST(cd, mdr->cause);
  541                         break;
  542                 }
  543 
  544                 /* controller info request */
  545 
  546                 case I4B_CTRL_INFO_REQ:
  547                 {
  548                         msg_ctrl_info_req_t *mcir;
  549                         int isdnif;
  550 
  551                         mcir = (msg_ctrl_info_req_t *)data;
  552                         isdnif = mcir->controller;
  553                         memset(mcir, 0, sizeof(msg_ctrl_info_req_t));
  554                         mcir->controller = isdnif;
  555                         mcir->ncontroller
  556                             = isdn_count_isdnif(&mcir->max_isdnif);
  557                         d = isdn_find_l3_by_isdnif(isdnif);
  558                         if (d != NULL) {
  559                                 mcir->tei = d->tei;
  560                                 mcir->nbch = d->nbch;
  561                                 strncpy(mcir->devname, d->devname, sizeof(mcir->devname)-1);
  562                                 strncpy(mcir->cardname, d->card_name, sizeof(mcir->cardname)-1);
  563                         } else {
  564                                 error = ENODEV;
  565                         }
  566                         break;
  567                 }
  568 
  569                 /* dial response */
  570 
  571                 case I4B_DIALOUT_RESP:
  572                 {
  573                         const struct isdn_l4_driver_functions *drv;
  574                         msg_dialout_resp_t *mdrsp;
  575                         void *l4_softc;
  576 
  577                         mdrsp = (msg_dialout_resp_t *)data;
  578                         drv = isdn_l4_get_driver(mdrsp->driver, mdrsp->driver_unit);
  579 
  580                         if(drv != NULL) {
  581                                 l4_softc = (*drv->get_softc)(mdrsp->driver_unit);
  582                                 (*drv->dial_response)(l4_softc, mdrsp->stat, mdrsp->cause);
  583                         }
  584                         break;
  585                 }
  586 
  587                 /* update timeout value */
  588 
  589                 case I4B_TIMEOUT_UPD:
  590                 {
  591                         msg_timeout_upd_t *mtu;
  592                         int x;
  593 
  594                         mtu = (msg_timeout_upd_t *)data;
  595 
  596                         NDBGL4(L4_TIMO, "I4B_TIMEOUT_UPD ioctl, alg %d, unit %d, idle %d, early %d!",
  597                                         mtu->shorthold_data.shorthold_algorithm, mtu->shorthold_data.unitlen_time,
  598                                         mtu->shorthold_data.idle_time, mtu->shorthold_data.earlyhup_time);
  599 
  600                         if((cd = cd_by_cdid(mtu->cdid)) == NULL)/* get cd */
  601                         {
  602                                 NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, cdid not found!");
  603                                 error = EINVAL;
  604                                 break;
  605                         }
  606 
  607                         switch( mtu->shorthold_data.shorthold_algorithm )
  608                         {
  609                                 case SHA_FIXU:
  610                                         /*
  611                                          * For this algorithm unitlen_time,
  612                                          * idle_time and earlyhup_time are used.
  613                                          */
  614 
  615                                         if(!(mtu->shorthold_data.unitlen_time >= 0 &&
  616                                              mtu->shorthold_data.idle_time >= 0    &&
  617                                              mtu->shorthold_data.earlyhup_time >= 0))
  618                                         {
  619                                                 NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, invalid args for fix unit algorithm!");
  620                                                 error = EINVAL;
  621                                         }
  622                                         break;
  623 
  624                                 case SHA_VARU:
  625                                         /*
  626                                          * For this algorithm unitlen_time and
  627                                          * idle_time are used. both must be
  628                                          * positive integers. earlyhup_time is
  629                                          * not used and must be 0.
  630                                          */
  631 
  632                                         if(!(mtu->shorthold_data.unitlen_time > 0 &&
  633                                              mtu->shorthold_data.idle_time >= 0   &&
  634                                              mtu->shorthold_data.earlyhup_time == 0))
  635                                         {
  636                                                 NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, invalid args for var unit algorithm!");
  637                                                 error = EINVAL;
  638                                         }
  639                                         break;
  640 
  641                                 default:
  642                                         NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, invalid algorithm!");
  643                                         error = EINVAL;
  644                                         break;
  645                         }
  646 
  647                         /*
  648                          * any error set above requires us to break
  649                          * out of the outer switch
  650                          */
  651                         if(error != 0)
  652                                 break;
  653 
  654                         x = splnet();
  655                         cd->shorthold_data.shorthold_algorithm = mtu->shorthold_data.shorthold_algorithm;
  656                         cd->shorthold_data.unitlen_time = mtu->shorthold_data.unitlen_time;
  657                         cd->shorthold_data.idle_time = mtu->shorthold_data.idle_time;
  658                         cd->shorthold_data.earlyhup_time = mtu->shorthold_data.earlyhup_time;
  659                         splx(x);
  660                         break;
  661                 }
  662 
  663                 /* soft enable/disable interface */
  664 
  665                 case I4B_UPDOWN_IND:
  666                 {
  667                         msg_updown_ind_t *mui;
  668                         const struct isdn_l4_driver_functions *drv;
  669                         void *l4_softc;
  670 
  671                         mui = (msg_updown_ind_t *)data;
  672                         drv = isdn_l4_get_driver(mui->driver, mui->driver_unit);
  673 
  674                         if (drv)
  675                         {
  676                                 l4_softc = drv->get_softc(mui->driver_unit);
  677                                 (*drv->updown_ind)(l4_softc, mui->updown);
  678                         }
  679                         break;
  680                 }
  681 
  682                 /* send ALERT request */
  683 
  684                 case I4B_ALERT_REQ:
  685                 {
  686                         msg_alert_req_t *mar;
  687 
  688                         mar = (msg_alert_req_t *)data;
  689 
  690                         if((cd = cd_by_cdid(mar->cdid)) == NULL)
  691                         {
  692                                 NDBGL4(L4_ERR, "I4B_ALERT_REQ ioctl, cdid not found!");
  693                                 error = EINVAL;
  694                                 break;
  695                         }
  696 
  697                         T400_stop(cd);
  698 
  699                         d = cd->l3drv;
  700                         if (d == NULL) {
  701                                 error = EINVAL;
  702                                 break;
  703                         }
  704                         d->l3driver->N_ALERT_REQUEST(cd);
  705 
  706                         break;
  707                 }
  708 
  709                 /* version/release number request */
  710 
  711                 case I4B_VR_REQ:
  712                 {
  713                         msg_vr_req_t *mvr;
  714 
  715                         mvr = (msg_vr_req_t *)data;
  716 
  717                         mvr->version = VERSION;
  718                         mvr->release = REL;
  719                         mvr->step = STEP;
  720                         break;
  721                 }
  722 
  723                 /* set D-channel protocol for a controller */
  724 
  725                 case I4B_PROT_IND:
  726                 {
  727                         msg_prot_ind_t *mpi;
  728 
  729                         mpi = (msg_prot_ind_t *)data;
  730 
  731                         d = isdn_find_l3_by_isdnif(mpi->controller);
  732                         if (d == NULL) {
  733                                 error = EINVAL;
  734                                 break;
  735                         }
  736                         d->protocol = mpi->protocol;
  737 
  738                         break;
  739                 }
  740 
  741                 case I4B_L4DRIVER_LOOKUP:
  742                 {
  743                         msg_l4driver_lookup_t *lookup = (msg_l4driver_lookup_t*)data;
  744                         lookup->name[L4DRIVER_NAME_SIZ-1] = 0;
  745                         lookup->driver_id = isdn_l4_find_driverid(lookup->name);
  746                         if (lookup->driver_id < 0)
  747                                 error = ENXIO;
  748                         break;
  749                 }
  750 
  751                 /* Download request */
  752                 case I4B_CTRL_DOWNLOAD:
  753                 {
  754                         struct isdn_dr_prot *prots = NULL, *prots2 = NULL;
  755                         struct isdn_download_request *r =
  756                                 (struct isdn_download_request*)data;
  757                         int i;
  758 
  759                         d = isdn_find_l3_by_isdnif(r->controller);
  760                         if (d == NULL)
  761                         {
  762                                 error = ENODEV;
  763                                 goto download_done;
  764                         }
  765 
  766                         if(d->l3driver->N_DOWNLOAD == NULL)
  767                         {
  768                                 error = ENODEV;
  769                                 goto download_done;
  770                         }
  771 
  772                         prots = malloc(r->numprotos * sizeof(struct isdn_dr_prot),
  773                                         M_DEVBUF, M_WAITOK);
  774 
  775                         prots2 = malloc(r->numprotos * sizeof(struct isdn_dr_prot),
  776                                         M_DEVBUF, M_WAITOK);
  777 
  778                         if(!prots || !prots2)
  779                         {
  780                                 error = ENOMEM;
  781                                 goto download_done;
  782                         }
  783 
  784                         copyin(r->protocols, prots, r->numprotos * sizeof(struct isdn_dr_prot));
  785 
  786                         for(i = 0; i < r->numprotos; i++)
  787                         {
  788                                 prots2[i].microcode = malloc(prots[i].bytecount, M_DEVBUF, M_WAITOK);
  789                                 copyin(prots[i].microcode, prots2[i].microcode, prots[i].bytecount);
  790                                 prots2[i].bytecount = prots[i].bytecount;
  791                         }
  792 
  793                         error = d->l3driver->N_DOWNLOAD(
  794                                                 d->l1_token,
  795                                                 r->numprotos, prots2);
  796 
  797 download_done:
  798                         if(prots2)
  799                         {
  800                                 for(i = 0; i < r->numprotos; i++)
  801                                 {
  802                                         if(prots2[i].microcode)
  803                                         {
  804                                                 free(prots2[i].microcode, M_DEVBUF);
  805                                         }
  806                                 }
  807                                 free(prots2, M_DEVBUF);
  808                         }
  809 
  810                         if(prots)
  811                         {
  812                                 free(prots, M_DEVBUF);
  813                         }
  814                         break;
  815                 }
  816 
  817                 /* Diagnostic request */
  818 
  819                 case I4B_ACTIVE_DIAGNOSTIC:
  820                 {
  821                         struct isdn_diagnostic_request req, *r =
  822                                 (struct isdn_diagnostic_request*)data;
  823 
  824                         req.in_param = req.out_param = NULL;
  825                         d = isdn_find_l3_by_isdnif(r->controller);
  826                         if (d == NULL)
  827                         {
  828                                 error = ENODEV;
  829                                 goto diag_done;
  830                         }
  831 
  832                         if (d->l3driver->N_DIAGNOSTICS == NULL)
  833                         {
  834                                 error = ENODEV;
  835                                 goto diag_done;
  836                         }
  837 
  838                         memcpy(&req, r, sizeof(req));
  839 
  840                         if(req.in_param_len)
  841                         {
  842                                 /* XXX arbitrary limit */
  843                                 if (req.in_param_len > I4B_ACTIVE_DIAGNOSTIC_MAXPARAMLEN) {
  844                                         error = EINVAL;
  845                                         goto diag_done;
  846                                 }
  847 
  848                                 req.in_param = malloc(r->in_param_len, M_DEVBUF, M_WAITOK);
  849 
  850                                 if(!req.in_param)
  851                                 {
  852                                         error = ENOMEM;
  853                                         goto diag_done;
  854                                 }
  855                                 error = copyin(r->in_param, req.in_param, req.in_param_len);
  856                                 if (error)
  857                                         goto diag_done;
  858                         }
  859 
  860                         if(req.out_param_len)
  861                         {
  862                                 req.out_param = malloc(r->out_param_len, M_DEVBUF, M_WAITOK);
  863 
  864                                 if(!req.out_param)
  865                                 {
  866                                         error = ENOMEM;
  867                                         goto diag_done;
  868                                 }
  869                         }
  870 
  871                         error = d->l3driver->N_DIAGNOSTICS(d->l1_token, &req);
  872 
  873                         if(!error && req.out_param_len)
  874                                 error = copyout(req.out_param, r->out_param, req.out_param_len);
  875 
  876 diag_done:
  877                         if(req.in_param)
  878                                 free(req.in_param, M_DEVBUF);
  879 
  880                         if(req.out_param)
  881                                 free(req.out_param, M_DEVBUF);
  882 
  883                         break;
  884                 }
  885 
  886                 /* default */
  887 
  888                 default:
  889                         error = ENOTTY;
  890                         break;
  891         }
  892 
  893         return(error);
  894 }
  895 
  896 #ifdef OS_USES_SELECT
  897 
  898 /*---------------------------------------------------------------------------*
  899  *      i4bselect - device driver select routine
  900  *---------------------------------------------------------------------------*/
  901 PDEVSTATIC int
  902 i4bselect(dev_t dev, int rw, struct lwp *l)
  903 {
  904         int x;
  905 
  906         if(minor(dev))
  907                 return(ENODEV);
  908 
  909         switch(rw)
  910         {
  911                 case FREAD:
  912                         if(!IF_QEMPTY(&i4b_rdqueue))
  913                                 return(1);
  914                         x = splnet();
  915                         selrecord(l, &select_rd_info);
  916                         selflag = 1;
  917                         splx(x);
  918                         return(0);
  919                         break;
  920 
  921                 case FWRITE:
  922                         return(1);
  923                         break;
  924         }
  925         return(0);
  926 }
  927 
  928 #else /* OS_USES_SELECT */
  929 
  930 /*---------------------------------------------------------------------------*
  931  *      i4bpoll - device driver poll routine
  932  *---------------------------------------------------------------------------*/
  933 PDEVSTATIC int
  934 isdnpoll(dev_t dev, int events, struct lwp *l)
  935 {
  936         int x;
  937 
  938         if(minor(dev))
  939                 return(ENODEV);
  940 
  941         if((events & POLLIN) || (events & POLLRDNORM))
  942         {
  943                 if(!IF_QEMPTY(&i4b_rdqueue))
  944                         return(1);
  945 
  946                 x = splnet();
  947                 selrecord(l, &select_rd_info);
  948                 selflag = 1;
  949                 splx(x);
  950                 return(0);
  951         }
  952         else if((events & POLLOUT) || (events & POLLWRNORM))
  953         {
  954                 return(1);
  955         }
  956 
  957         return(0);
  958 }
  959 
  960 static void
  961 filt_i4brdetach(struct knote *kn)
  962 {
  963         int s;
  964 
  965         s = splnet();
  966         SLIST_REMOVE(&select_rd_info.sel_klist, kn, knote, kn_selnext);
  967         splx(s);
  968 }
  969 
  970 static int
  971 filt_i4bread(struct knote *kn, long hint)
  972 {
  973         struct mbuf *m;
  974 
  975         if (IF_QEMPTY(&i4b_rdqueue))
  976                 return (0);
  977 
  978         IF_POLL(&i4b_rdqueue, m);
  979 
  980         kn->kn_data = m->m_len;
  981         return (1);
  982 }
  983 
  984 static const struct filterops i4bread_filtops =
  985         { 1, NULL, filt_i4brdetach, filt_i4bread };
  986 
  987 static const struct filterops i4b_seltrue_filtops =
  988         { 1, NULL, filt_i4brdetach, filt_seltrue };
  989 
  990 int
  991 isdnkqfilter(dev_t dev, struct knote *kn)
  992 {
  993         struct klist *klist;
  994         int s;
  995 
  996         switch (kn->kn_filter) {
  997         case EVFILT_READ:
  998                 klist = &select_rd_info.sel_klist;
  999                 kn->kn_fop = &i4bread_filtops;
 1000                 break;
 1001 
 1002         case EVFILT_WRITE:
 1003                 klist = &select_rd_info.sel_klist;
 1004                 kn->kn_fop = &i4b_seltrue_filtops;
 1005                 break;
 1006 
 1007         default:
 1008                 return (EINVAL);
 1009         }
 1010 
 1011         kn->kn_hook = NULL;
 1012 
 1013         s = splnet();
 1014         SLIST_INSERT_HEAD(klist, kn, kn_selnext);
 1015         splx(s);
 1016 
 1017         return (0);
 1018 }
 1019 
 1020 #endif /* OS_USES_SELECT */
 1021 
 1022 /*---------------------------------------------------------------------------*
 1023  *      i4bputqueue - put message into queue to userland
 1024  *---------------------------------------------------------------------------*/
 1025 void
 1026 i4bputqueue(struct mbuf *m)
 1027 {
 1028         int x;
 1029 
 1030         if(!openflag)
 1031         {
 1032                 i4b_Dfreembuf(m);
 1033                 return;
 1034         }
 1035 
 1036         x = splnet();
 1037 
 1038         if(IF_QFULL(&i4b_rdqueue))
 1039         {
 1040                 struct mbuf *m1;
 1041                 IF_DEQUEUE(&i4b_rdqueue, m1);
 1042                 i4b_Dfreembuf(m1);
 1043                 NDBGL4(L4_ERR, "ERROR, queue full, removing entry!");
 1044         }
 1045 
 1046         IF_ENQUEUE(&i4b_rdqueue, m);
 1047 
 1048         splx(x);
 1049 
 1050         if(readflag)
 1051         {
 1052                 readflag = 0;
 1053                 wakeup((void *) &i4b_rdqueue);
 1054         }
 1055 
 1056         if(selflag)
 1057         {
 1058                 selflag = 0;
 1059                 selnotify(&select_rd_info, 0, 0);
 1060         }
 1061 }
 1062 
 1063 /*---------------------------------------------------------------------------*
 1064  *      i4bputqueue_hipri - put message into front of queue to userland
 1065  *---------------------------------------------------------------------------*/
 1066 void
 1067 i4bputqueue_hipri(struct mbuf *m)
 1068 {
 1069         int x;
 1070 
 1071         if(!openflag)
 1072         {
 1073                 i4b_Dfreembuf(m);
 1074                 return;
 1075         }
 1076 
 1077         x = splnet();
 1078 
 1079         if(IF_QFULL(&i4b_rdqueue))
 1080         {
 1081                 struct mbuf *m1;
 1082                 IF_DEQUEUE(&i4b_rdqueue, m1);
 1083                 i4b_Dfreembuf(m1);
 1084                 NDBGL4(L4_ERR, "ERROR, queue full, removing entry!");
 1085         }
 1086 
 1087         IF_PREPEND(&i4b_rdqueue, m);
 1088 
 1089         splx(x);
 1090 
 1091         if(readflag)
 1092         {
 1093                 readflag = 0;
 1094                 wakeup((void *) &i4b_rdqueue);
 1095         }
 1096 
 1097         if(selflag)
 1098         {
 1099                 selflag = 0;
 1100                 selnotify(&select_rd_info, 0, 0);
 1101         }
 1102 }
 1103 
 1104 void
 1105 isdn_isdnif_ready(int isdnif)
 1106 {
 1107         struct isdn_l3_driver *d = isdn_find_l3_by_isdnif(isdnif);
 1108 
 1109         if (d == NULL)
 1110                 return;
 1111 
 1112         printf("ISDN %d at %s, %d B channels\n", isdnif, d->devname, d->nbch);
 1113         if (!openflag) return;
 1114 
 1115         d->l3driver->N_MGMT_COMMAND(d, CMR_DOPEN, 0);
 1116         i4b_l4_contr_ev_ind(isdnif, 1);
 1117 }
 1118 
 1119 #endif /* NISDN > 0 */

Cache object: ce6d602889adfc0cdbe12ec9c68cbc1d


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