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

Cache object: b7407973951a8e6cbfd750c7fa7b0ed4


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