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.30 2006/11/16 01:33:49 christos 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.30 2006/11/16 01:33:49 christos 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, caddr_t 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 
  246 #if defined(__FreeBSD__)
  247 #if __FreeBSD__ == 3
  248 
  249 #ifdef DEVFS
  250         devfs_token = devfs_add_devswf(&i4b_cdevsw, 0, DV_CHR,
  251                                        UID_ROOT, GID_WHEEL, 0600,
  252                                        "i4b");
  253 #endif
  254 
  255 #else
  256         make_dev(&i4b_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "i4b");
  257 #endif
  258 #endif
  259 }
  260 
  261 /*---------------------------------------------------------------------------*
  262  *      i4bopen - device driver open routine
  263  *---------------------------------------------------------------------------*/
  264 PDEVSTATIC int
  265 isdnopen(dev_t dev, int flag, int fmt, struct lwp *l)
  266 {
  267         int x;
  268 
  269         if(minor(dev))
  270                 return(ENXIO);
  271 
  272         if(openflag)
  273                 return(EBUSY);
  274 
  275         x = splnet();
  276         openflag = 1;
  277         i4b_l4_daemon_attached();
  278         splx(x);
  279 
  280         return(0);
  281 }
  282 
  283 /*---------------------------------------------------------------------------*
  284  *      i4bclose - device driver close routine
  285  *---------------------------------------------------------------------------*/
  286 PDEVSTATIC int
  287 isdnclose(dev_t dev, int flag, int fmt,
  288         struct lwp *l)
  289 {
  290         int x = splnet();
  291         openflag = 0;
  292         i4b_l4_daemon_detached();
  293         i4b_Dcleanifq(&i4b_rdqueue);
  294         splx(x);
  295         return(0);
  296 }
  297 
  298 /*---------------------------------------------------------------------------*
  299  *      i4bread - device driver read routine
  300  *---------------------------------------------------------------------------*/
  301 PDEVSTATIC int
  302 isdnread(dev_t dev, struct uio *uio, int ioflag)
  303 {
  304         struct mbuf *m;
  305         int x;
  306         int error = 0;
  307 
  308         if(minor(dev))
  309                 return(ENODEV);
  310 
  311         x = splnet();
  312         while(IF_QEMPTY(&i4b_rdqueue))
  313         {
  314                 readflag = 1;
  315                 error = tsleep((caddr_t) &i4b_rdqueue, (PZERO + 1) | PCATCH, "bird", 0);
  316                 if (error != 0) {
  317                         splx(x);
  318                         return error;
  319                 }
  320         }
  321 
  322         IF_DEQUEUE(&i4b_rdqueue, m);
  323 
  324         splx(x);
  325 
  326         if(m && m->m_len)
  327                 error = uiomove(m->m_data, m->m_len, uio);
  328         else
  329                 error = EIO;
  330 
  331         if(m)
  332                 i4b_Dfreembuf(m);
  333 
  334         return(error);
  335 }
  336 
  337 /*---------------------------------------------------------------------------*
  338  *      i4bioctl - device driver ioctl routine
  339  *---------------------------------------------------------------------------*/
  340 PDEVSTATIC int
  341 isdnioctl(dev_t dev, u_long cmd, caddr_t data, int flag,
  342         struct lwp *l)
  343 {
  344         struct isdn_l3_driver *d;
  345         call_desc_t *cd;
  346         int error = 0;
  347 
  348         if(minor(dev))
  349                 return(ENODEV);
  350 
  351         switch(cmd)
  352         {
  353                 /* cdid request, reserve cd and return cdid */
  354 
  355                 case I4B_CDID_REQ:
  356                 {
  357                         msg_cdid_req_t *mir;
  358                         mir = (msg_cdid_req_t *)data;
  359                         cd = reserve_cd();
  360                         mir->cdid = cd->cdid;
  361                         break;
  362                 }
  363 
  364                 /* connect request, dial out to remote */
  365 
  366                 case I4B_CONNECT_REQ:
  367                 {
  368                         msg_connect_req_t *mcr;
  369                         mcr = (msg_connect_req_t *)data;        /* setup ptr */
  370 
  371                         if((cd = cd_by_cdid(mcr->cdid)) == NULL)/* get cd */
  372                         {
  373                                 NDBGL4(L4_ERR, "I4B_CONNECT_REQ ioctl, cdid not found!");
  374                                 error = EINVAL;
  375                                 break;
  376                         }
  377                         cd->isdnif = -1;
  378                         cd->l3drv = NULL;
  379 
  380                         d = isdn_find_l3_by_isdnif(mcr->controller);
  381                         if (d == NULL) {
  382                                 error = EINVAL;
  383                                 break;
  384                         }
  385 
  386                         /* prevent dialling on leased lines */
  387                         if(d->protocol == PROTOCOL_D64S)
  388                         {
  389                                 SET_CAUSE_TYPE(cd->cause_in, CAUSET_I4B);
  390                                 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_LLDIAL);
  391                                 i4b_l4_disconnect_ind(cd);
  392                                 freecd_by_cd(cd);
  393                                 break;
  394                         }
  395 
  396                         cd->isdnif = mcr->controller;   /* fill cd */
  397                         cd->l3drv = d;
  398                         cd->bprot = mcr->bprot;
  399                         cd->bchan_driver_index = mcr->driver;
  400                         cd->bchan_driver_unit = mcr->driver_unit;
  401                         cd->cr = get_rand_cr(cd->isdnif);
  402 
  403                         cd->shorthold_data.shorthold_algorithm = mcr->shorthold_data.shorthold_algorithm;
  404                         cd->shorthold_data.unitlen_time  = mcr->shorthold_data.unitlen_time;
  405                         cd->shorthold_data.idle_time     = mcr->shorthold_data.idle_time;
  406                         cd->shorthold_data.earlyhup_time = mcr->shorthold_data.earlyhup_time;
  407 
  408                         cd->last_aocd_time = 0;
  409                         if(mcr->unitlen_method == ULEN_METHOD_DYNAMIC)
  410                                 cd->aocd_flag = 1;
  411                         else
  412                                 cd->aocd_flag = 0;
  413 
  414                         cd->cunits = 0;
  415 
  416                         cd->max_idle_time = 0;  /* this is outgoing */
  417 
  418                         cd->dir = DIR_OUTGOING;
  419 
  420                         NDBGL4(L4_TIMO, "I4B_CONNECT_REQ times, algorithm=%ld unitlen=%ld idle=%ld earlyhup=%ld",
  421                                         (long)cd->shorthold_data.shorthold_algorithm, (long)cd->shorthold_data.unitlen_time,
  422                                         (long)cd->shorthold_data.idle_time, (long)cd->shorthold_data.earlyhup_time);
  423 
  424                         strlcpy(cd->dst_telno, mcr->dst_telno,
  425                             sizeof(cd->dst_telno));
  426                         strlcpy(cd->src_telno, mcr->src_telno,
  427                             sizeof(cd->src_telno));
  428                         cd->display[0] = '\0';
  429 
  430                         SET_CAUSE_TYPE(cd->cause_in, CAUSET_I4B);
  431                         SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NORMAL);
  432 
  433                         /*
  434                          * If we want a specific channel, check if that
  435                          * one is available.
  436                          */
  437                         if ((mcr->channel >= 0) && (mcr->channel < d->nbch)) {
  438                                 if(d->bch_state[mcr->channel] != BCH_ST_FREE)
  439                                         SET_CAUSE_VAL(cd->cause_in,
  440                                             CAUSE_I4B_NOCHAN);
  441 
  442                         /*
  443                          * If any channel will do, see if any are free.
  444                          */
  445                         } else if (mcr->channel == CHAN_ANY) {
  446                                 int i;
  447 
  448                                 for (i = 0; i < d->nbch; i++)
  449                                         if (d->bch_state[i] == BCH_ST_FREE)
  450                                                 break;
  451 
  452                                 if (i == d->nbch)
  453                                         SET_CAUSE_VAL(cd->cause_in,
  454                                             CAUSE_I4B_NOCHAN);
  455 
  456                         } else {
  457                                 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
  458                         }
  459 
  460                         cd->channelid = mcr->channel;
  461 
  462                         cd->isdntxdelay = mcr->txdelay;
  463 
  464                         if((GET_CAUSE_VAL(cd->cause_in)) != CAUSE_I4B_NORMAL)
  465                         {
  466                                 i4b_l4_disconnect_ind(cd);
  467                                 freecd_by_cd(cd);
  468                         }
  469                         else
  470                         {
  471                                 d->l3driver->N_CONNECT_REQUEST(cd);
  472                         }
  473                         break;
  474                 }
  475 
  476                 /* connect response, accept/reject/ignore incoming call */
  477 
  478                 case I4B_CONNECT_RESP:
  479                 {
  480                         msg_connect_resp_t *mcrsp;
  481 
  482                         mcrsp = (msg_connect_resp_t *)data;
  483 
  484                         if((cd = cd_by_cdid(mcrsp->cdid)) == NULL)/* get cd */
  485                         {
  486                                 NDBGL4(L4_ERR, "I4B_CONNECT_RESP ioctl, cdid not found!");
  487                                 error = EINVAL;
  488                                 break;
  489                         }
  490 
  491                         T400_stop(cd);
  492 
  493                         cd->bchan_driver_index = mcrsp->driver;
  494                         cd->bchan_driver_unit = mcrsp->driver_unit;
  495                         cd->max_idle_time = mcrsp->max_idle_time;
  496 
  497                         cd->shorthold_data.shorthold_algorithm = SHA_FIXU;
  498                         cd->shorthold_data.unitlen_time = 0;    /* this is incoming */
  499                         cd->shorthold_data.idle_time = 0;
  500                         cd->shorthold_data.earlyhup_time = 0;
  501 
  502                         cd->isdntxdelay = mcrsp->txdelay;
  503 
  504                         NDBGL4(L4_TIMO, "I4B_CONNECT_RESP max_idle_time set to %ld seconds", (long)cd->max_idle_time);
  505 
  506                         d = isdn_find_l3_by_isdnif(cd->isdnif);
  507                         if (d == NULL) {
  508                                 error = EINVAL;
  509                                 break;
  510                         }
  511                         d->l3driver->N_CONNECT_RESPONSE(cd, mcrsp->response, mcrsp->cause);
  512                         break;
  513                 }
  514 
  515                 /* disconnect request, actively terminate connection */
  516 
  517                 case I4B_DISCONNECT_REQ:
  518                 {
  519                         msg_discon_req_t *mdr;
  520 
  521                         mdr = (msg_discon_req_t *)data;
  522 
  523                         if((cd = cd_by_cdid(mdr->cdid)) == NULL)/* get cd */
  524                         {
  525                                 NDBGL4(L4_ERR, "I4B_DISCONNECT_REQ ioctl, cdid %d not found!", mdr->cdid);
  526                                 error = EINVAL;
  527                                 break;
  528                         }
  529 
  530                         /* preset causes with our cause */
  531                         cd->cause_in = cd->cause_out = mdr->cause;
  532 
  533                         d = isdn_find_l3_by_isdnif(cd->isdnif);
  534                         if (d == NULL) {
  535                                 error = EINVAL;
  536                                 break;
  537                         }
  538 
  539                         d->l3driver->N_DISCONNECT_REQUEST(cd, mdr->cause);
  540                         break;
  541                 }
  542 
  543                 /* controller info request */
  544 
  545                 case I4B_CTRL_INFO_REQ:
  546                 {
  547                         msg_ctrl_info_req_t *mcir;
  548                         int isdnif;
  549 
  550                         mcir = (msg_ctrl_info_req_t *)data;
  551                         isdnif = mcir->controller;
  552                         memset(mcir, 0, sizeof(msg_ctrl_info_req_t));
  553                         mcir->controller = isdnif;
  554                         mcir->ncontroller
  555                             = isdn_count_isdnif(&mcir->max_isdnif);
  556                         d = isdn_find_l3_by_isdnif(isdnif);
  557                         if (d != NULL) {
  558                                 mcir->tei = d->tei;
  559                                 mcir->nbch = d->nbch;
  560                                 strncpy(mcir->devname, d->devname, sizeof(mcir->devname)-1);
  561                                 strncpy(mcir->cardname, d->card_name, sizeof(mcir->cardname)-1);
  562                         } else {
  563                                 error = ENODEV;
  564                         }
  565                         break;
  566                 }
  567 
  568                 /* dial response */
  569 
  570                 case I4B_DIALOUT_RESP:
  571                 {
  572                         const struct isdn_l4_driver_functions *drv;
  573                         msg_dialout_resp_t *mdrsp;
  574                         void * l4_softc;
  575 
  576                         mdrsp = (msg_dialout_resp_t *)data;
  577                         drv = isdn_l4_get_driver(mdrsp->driver, mdrsp->driver_unit);
  578 
  579                         if(drv != NULL) {
  580                                 l4_softc = (*drv->get_softc)(mdrsp->driver_unit);
  581                                 (*drv->dial_response)(l4_softc, mdrsp->stat, mdrsp->cause);
  582                         }
  583                         break;
  584                 }
  585 
  586                 /* update timeout value */
  587 
  588                 case I4B_TIMEOUT_UPD:
  589                 {
  590                         msg_timeout_upd_t *mtu;
  591                         int x;
  592 
  593                         mtu = (msg_timeout_upd_t *)data;
  594 
  595                         NDBGL4(L4_TIMO, "I4B_TIMEOUT_UPD ioctl, alg %d, unit %d, idle %d, early %d!",
  596                                         mtu->shorthold_data.shorthold_algorithm, mtu->shorthold_data.unitlen_time,
  597                                         mtu->shorthold_data.idle_time, mtu->shorthold_data.earlyhup_time);
  598 
  599                         if((cd = cd_by_cdid(mtu->cdid)) == NULL)/* get cd */
  600                         {
  601                                 NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, cdid not found!");
  602                                 error = EINVAL;
  603                                 break;
  604                         }
  605 
  606                         switch( mtu->shorthold_data.shorthold_algorithm )
  607                         {
  608                                 case SHA_FIXU:
  609                                         /*
  610                                          * For this algorithm unitlen_time,
  611                                          * idle_time and earlyhup_time are used.
  612                                          */
  613 
  614                                         if(!(mtu->shorthold_data.unitlen_time >= 0 &&
  615                                              mtu->shorthold_data.idle_time >= 0    &&
  616                                              mtu->shorthold_data.earlyhup_time >= 0))
  617                                         {
  618                                                 NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, invalid args for fix unit algorithm!");
  619                                                 error = EINVAL;
  620                                         }
  621                                         break;
  622 
  623                                 case SHA_VARU:
  624                                         /*
  625                                          * For this algorithm unitlen_time and
  626                                          * idle_time are used. both must be
  627                                          * positive integers. earlyhup_time is
  628                                          * not used and must be 0.
  629                                          */
  630 
  631                                         if(!(mtu->shorthold_data.unitlen_time > 0 &&
  632                                              mtu->shorthold_data.idle_time >= 0   &&
  633                                              mtu->shorthold_data.earlyhup_time == 0))
  634                                         {
  635                                                 NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, invalid args for var unit algorithm!");
  636                                                 error = EINVAL;
  637                                         }
  638                                         break;
  639 
  640                                 default:
  641                                         NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, invalid algorithm!");
  642                                         error = EINVAL;
  643                                         break;
  644                         }
  645 
  646                         /*
  647                          * any error set above requires us to break
  648                          * out of the outer switch
  649                          */
  650                         if(error != 0)
  651                                 break;
  652 
  653                         x = splnet();
  654                         cd->shorthold_data.shorthold_algorithm = mtu->shorthold_data.shorthold_algorithm;
  655                         cd->shorthold_data.unitlen_time = mtu->shorthold_data.unitlen_time;
  656                         cd->shorthold_data.idle_time = mtu->shorthold_data.idle_time;
  657                         cd->shorthold_data.earlyhup_time = mtu->shorthold_data.earlyhup_time;
  658                         splx(x);
  659                         break;
  660                 }
  661 
  662                 /* soft enable/disable interface */
  663 
  664                 case I4B_UPDOWN_IND:
  665                 {
  666                         msg_updown_ind_t *mui;
  667                         const struct isdn_l4_driver_functions *drv;
  668                         void * l4_softc;
  669 
  670                         mui = (msg_updown_ind_t *)data;
  671                         drv = isdn_l4_get_driver(mui->driver, mui->driver_unit);
  672 
  673                         if (drv)
  674                         {
  675                                 l4_softc = drv->get_softc(mui->driver_unit);
  676                                 (*drv->updown_ind)(l4_softc, mui->updown);
  677                         }
  678                         break;
  679                 }
  680 
  681                 /* send ALERT request */
  682 
  683                 case I4B_ALERT_REQ:
  684                 {
  685                         msg_alert_req_t *mar;
  686 
  687                         mar = (msg_alert_req_t *)data;
  688 
  689                         if((cd = cd_by_cdid(mar->cdid)) == NULL)
  690                         {
  691                                 NDBGL4(L4_ERR, "I4B_ALERT_REQ ioctl, cdid not found!");
  692                                 error = EINVAL;
  693                                 break;
  694                         }
  695 
  696                         T400_stop(cd);
  697 
  698                         d = cd->l3drv;
  699                         if (d == NULL) {
  700                                 error = EINVAL;
  701                                 break;
  702                         }
  703                         d->l3driver->N_ALERT_REQUEST(cd);
  704 
  705                         break;
  706                 }
  707 
  708                 /* version/release number request */
  709 
  710                 case I4B_VR_REQ:
  711                 {
  712                         msg_vr_req_t *mvr;
  713 
  714                         mvr = (msg_vr_req_t *)data;
  715 
  716                         mvr->version = VERSION;
  717                         mvr->release = REL;
  718                         mvr->step = STEP;
  719                         break;
  720                 }
  721 
  722                 /* set D-channel protocol for a controller */
  723 
  724                 case I4B_PROT_IND:
  725                 {
  726                         msg_prot_ind_t *mpi;
  727 
  728                         mpi = (msg_prot_ind_t *)data;
  729 
  730                         d = isdn_find_l3_by_isdnif(mpi->controller);
  731                         if (d == NULL) {
  732                                 error = EINVAL;
  733                                 break;
  734                         }
  735                         d->protocol = mpi->protocol;
  736 
  737                         break;
  738                 }
  739 
  740                 case I4B_L4DRIVER_LOOKUP:
  741                 {
  742                         msg_l4driver_lookup_t *lookup = (msg_l4driver_lookup_t*)data;
  743                         lookup->name[L4DRIVER_NAME_SIZ-1] = 0;
  744                         lookup->driver_id = isdn_l4_find_driverid(lookup->name);
  745                         if (lookup->driver_id < 0)
  746                                 error = ENXIO;
  747                         break;
  748                 }
  749 
  750                 /* Download request */
  751                 case I4B_CTRL_DOWNLOAD:
  752                 {
  753                         struct isdn_dr_prot *prots = NULL, *prots2 = NULL;
  754                         struct isdn_download_request *r =
  755                                 (struct isdn_download_request*)data;
  756                         int i;
  757 
  758                         d = isdn_find_l3_by_isdnif(r->controller);
  759                         if (d == NULL)
  760                         {
  761                                 error = ENODEV;
  762                                 goto download_done;
  763                         }
  764 
  765                         if(d->l3driver->N_DOWNLOAD == NULL)
  766                         {
  767                                 error = ENODEV;
  768                                 goto download_done;
  769                         }
  770 
  771                         prots = malloc(r->numprotos * sizeof(struct isdn_dr_prot),
  772                                         M_DEVBUF, M_WAITOK);
  773 
  774                         prots2 = malloc(r->numprotos * sizeof(struct isdn_dr_prot),
  775                                         M_DEVBUF, M_WAITOK);
  776 
  777                         if(!prots || !prots2)
  778                         {
  779                                 error = ENOMEM;
  780                                 goto download_done;
  781                         }
  782 
  783                         copyin(r->protocols, prots, r->numprotos * sizeof(struct isdn_dr_prot));
  784 
  785                         for(i = 0; i < r->numprotos; i++)
  786                         {
  787                                 prots2[i].microcode = malloc(prots[i].bytecount, M_DEVBUF, M_WAITOK);
  788                                 copyin(prots[i].microcode, prots2[i].microcode, prots[i].bytecount);
  789                                 prots2[i].bytecount = prots[i].bytecount;
  790                         }
  791 
  792                         error = d->l3driver->N_DOWNLOAD(
  793                                                 d->l1_token,
  794                                                 r->numprotos, prots2);
  795 
  796 download_done:
  797                         if(prots2)
  798                         {
  799                                 for(i = 0; i < r->numprotos; i++)
  800                                 {
  801                                         if(prots2[i].microcode)
  802                                         {
  803                                                 free(prots2[i].microcode, M_DEVBUF);
  804                                         }
  805                                 }
  806                                 free(prots2, M_DEVBUF);
  807                         }
  808 
  809                         if(prots)
  810                         {
  811                                 free(prots, M_DEVBUF);
  812                         }
  813                         break;
  814                 }
  815 
  816                 /* Diagnostic request */
  817 
  818                 case I4B_ACTIVE_DIAGNOSTIC:
  819                 {
  820                         struct isdn_diagnostic_request req, *r =
  821                                 (struct isdn_diagnostic_request*)data;
  822 
  823                         req.in_param = req.out_param = NULL;
  824                         d = isdn_find_l3_by_isdnif(r->controller);
  825                         if (d == NULL)
  826                         {
  827                                 error = ENODEV;
  828                                 goto diag_done;
  829                         }
  830 
  831                         if (d->l3driver->N_DIAGNOSTICS == NULL)
  832                         {
  833                                 error = ENODEV;
  834                                 goto diag_done;
  835                         }
  836 
  837                         memcpy(&req, r, sizeof(req));
  838 
  839                         if(req.in_param_len)
  840                         {
  841                                 /* XXX arbitrary limit */
  842                                 if (req.in_param_len > I4B_ACTIVE_DIAGNOSTIC_MAXPARAMLEN) {
  843                                         error = EINVAL;
  844                                         goto diag_done;
  845                                 }
  846 
  847                                 req.in_param = malloc(r->in_param_len, M_DEVBUF, M_WAITOK);
  848 
  849                                 if(!req.in_param)
  850                                 {
  851                                         error = ENOMEM;
  852                                         goto diag_done;
  853                                 }
  854                                 error = copyin(r->in_param, req.in_param, req.in_param_len);
  855                                 if (error)
  856                                         goto diag_done;
  857                         }
  858 
  859                         if(req.out_param_len)
  860                         {
  861                                 req.out_param = malloc(r->out_param_len, M_DEVBUF, M_WAITOK);
  862 
  863                                 if(!req.out_param)
  864                                 {
  865                                         error = ENOMEM;
  866                                         goto diag_done;
  867                                 }
  868                         }
  869 
  870                         error = d->l3driver->N_DIAGNOSTICS(d->l1_token, &req);
  871 
  872                         if(!error && req.out_param_len)
  873                                 error = copyout(req.out_param, r->out_param, req.out_param_len);
  874 
  875 diag_done:
  876                         if(req.in_param)
  877                                 free(req.in_param, M_DEVBUF);
  878 
  879                         if(req.out_param)
  880                                 free(req.out_param, M_DEVBUF);
  881 
  882                         break;
  883                 }
  884 
  885                 /* default */
  886 
  887                 default:
  888                         error = ENOTTY;
  889                         break;
  890         }
  891 
  892         return(error);
  893 }
  894 
  895 #ifdef OS_USES_SELECT
  896 
  897 /*---------------------------------------------------------------------------*
  898  *      i4bselect - device driver select routine
  899  *---------------------------------------------------------------------------*/
  900 PDEVSTATIC int
  901 i4bselect(dev_t dev, int rw, struct lwp *l)
  902 {
  903         int x;
  904 
  905         if(minor(dev))
  906                 return(ENODEV);
  907 
  908         switch(rw)
  909         {
  910                 case FREAD:
  911                         if(!IF_QEMPTY(&i4b_rdqueue))
  912                                 return(1);
  913                         x = splnet();
  914                         selrecord(l, &select_rd_info);
  915                         selflag = 1;
  916                         splx(x);
  917                         return(0);
  918                         break;
  919 
  920                 case FWRITE:
  921                         return(1);
  922                         break;
  923         }
  924         return(0);
  925 }
  926 
  927 #else /* OS_USES_SELECT */
  928 
  929 /*---------------------------------------------------------------------------*
  930  *      i4bpoll - device driver poll routine
  931  *---------------------------------------------------------------------------*/
  932 PDEVSTATIC int
  933 isdnpoll(dev_t dev, int events, struct lwp *l)
  934 {
  935         int x;
  936 
  937         if(minor(dev))
  938                 return(ENODEV);
  939 
  940         if((events & POLLIN) || (events & POLLRDNORM))
  941         {
  942                 if(!IF_QEMPTY(&i4b_rdqueue))
  943                         return(1);
  944 
  945                 x = splnet();
  946                 selrecord(l, &select_rd_info);
  947                 selflag = 1;
  948                 splx(x);
  949                 return(0);
  950         }
  951         else if((events & POLLOUT) || (events & POLLWRNORM))
  952         {
  953                 return(1);
  954         }
  955 
  956         return(0);
  957 }
  958 
  959 static void
  960 filt_i4brdetach(struct knote *kn)
  961 {
  962         int s;
  963 
  964         s = splnet();
  965         SLIST_REMOVE(&select_rd_info.sel_klist, kn, knote, kn_selnext);
  966         splx(s);
  967 }
  968 
  969 static int
  970 filt_i4bread(struct knote *kn, long hint)
  971 {
  972         struct mbuf *m;
  973 
  974         if (IF_QEMPTY(&i4b_rdqueue))
  975                 return (0);
  976 
  977         IF_POLL(&i4b_rdqueue, m);
  978 
  979         kn->kn_data = m->m_len;
  980         return (1);
  981 }
  982 
  983 static const struct filterops i4bread_filtops =
  984         { 1, NULL, filt_i4brdetach, filt_i4bread };
  985 
  986 static const struct filterops i4b_seltrue_filtops =
  987         { 1, NULL, filt_i4brdetach, filt_seltrue };
  988 
  989 int
  990 isdnkqfilter(dev_t dev, struct knote *kn)
  991 {
  992         struct klist *klist;
  993         int s;
  994 
  995         switch (kn->kn_filter) {
  996         case EVFILT_READ:
  997                 klist = &select_rd_info.sel_klist;
  998                 kn->kn_fop = &i4bread_filtops;
  999                 break;
 1000 
 1001         case EVFILT_WRITE:
 1002                 klist = &select_rd_info.sel_klist;
 1003                 kn->kn_fop = &i4b_seltrue_filtops;
 1004                 break;
 1005 
 1006         default:
 1007                 return (1);
 1008         }
 1009 
 1010         kn->kn_hook = NULL;
 1011 
 1012         s = splnet();
 1013         SLIST_INSERT_HEAD(klist, kn, kn_selnext);
 1014         splx(s);
 1015 
 1016         return (0);
 1017 }
 1018 
 1019 #endif /* OS_USES_SELECT */
 1020 
 1021 /*---------------------------------------------------------------------------*
 1022  *      i4bputqueue - put message into queue to userland
 1023  *---------------------------------------------------------------------------*/
 1024 void
 1025 i4bputqueue(struct mbuf *m)
 1026 {
 1027         int x;
 1028 
 1029         if(!openflag)
 1030         {
 1031                 i4b_Dfreembuf(m);
 1032                 return;
 1033         }
 1034 
 1035         x = splnet();
 1036 
 1037         if(IF_QFULL(&i4b_rdqueue))
 1038         {
 1039                 struct mbuf *m1;
 1040                 IF_DEQUEUE(&i4b_rdqueue, m1);
 1041                 i4b_Dfreembuf(m1);
 1042                 NDBGL4(L4_ERR, "ERROR, queue full, removing entry!");
 1043         }
 1044 
 1045         IF_ENQUEUE(&i4b_rdqueue, m);
 1046 
 1047         splx(x);
 1048 
 1049         if(readflag)
 1050         {
 1051                 readflag = 0;
 1052                 wakeup((caddr_t) &i4b_rdqueue);
 1053         }
 1054 
 1055         if(selflag)
 1056         {
 1057                 selflag = 0;
 1058                 selnotify(&select_rd_info, 0);
 1059         }
 1060 }
 1061 
 1062 /*---------------------------------------------------------------------------*
 1063  *      i4bputqueue_hipri - put message into front of queue to userland
 1064  *---------------------------------------------------------------------------*/
 1065 void
 1066 i4bputqueue_hipri(struct mbuf *m)
 1067 {
 1068         int x;
 1069 
 1070         if(!openflag)
 1071         {
 1072                 i4b_Dfreembuf(m);
 1073                 return;
 1074         }
 1075 
 1076         x = splnet();
 1077 
 1078         if(IF_QFULL(&i4b_rdqueue))
 1079         {
 1080                 struct mbuf *m1;
 1081                 IF_DEQUEUE(&i4b_rdqueue, m1);
 1082                 i4b_Dfreembuf(m1);
 1083                 NDBGL4(L4_ERR, "ERROR, queue full, removing entry!");
 1084         }
 1085 
 1086         IF_PREPEND(&i4b_rdqueue, m);
 1087 
 1088         splx(x);
 1089 
 1090         if(readflag)
 1091         {
 1092                 readflag = 0;
 1093                 wakeup((caddr_t) &i4b_rdqueue);
 1094         }
 1095 
 1096         if(selflag)
 1097         {
 1098                 selflag = 0;
 1099                 selnotify(&select_rd_info, 0);
 1100         }
 1101 }
 1102 
 1103 void
 1104 isdn_isdnif_ready(int isdnif)
 1105 {
 1106         struct isdn_l3_driver *d = isdn_find_l3_by_isdnif(isdnif);
 1107 
 1108         if (d == NULL)
 1109                 return;
 1110 
 1111         printf("ISDN %d at %s, %d B channels\n", isdnif, d->devname, d->nbch);
 1112         if (!openflag) return;
 1113 
 1114         d->l3driver->N_MGMT_COMMAND(d, CMR_DOPEN, 0);
 1115         i4b_l4_contr_ev_ind(isdnif, 1);
 1116 }
 1117 
 1118 #endif /* NISDN > 0 */

Cache object: 98b7fae050b409c5eb3fefc6cae01283


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