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/i4b/layer4/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, 2002 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  *
   28  *      i4b_i4bdrv.c - i4b userland interface driver
   29  *      --------------------------------------------
   30  *      last edit-date: [Sun Aug 11 12:42:46 2002]
   31  *
   32  *---------------------------------------------------------------------------*/
   33 
   34 #include <sys/cdefs.h>
   35 __FBSDID("$FreeBSD: releng/5.4/sys/i4b/layer4/i4b_i4bdrv.c 141090 2005-01-31 23:27:04Z imp $");
   36 
   37 #include "i4bipr.h"
   38 #include "i4btel.h"
   39 #include "i4bing.h"
   40 #include "i4bisppp.h"
   41 
   42 #include <sys/param.h>
   43 #include <sys/ioccom.h>
   44 #include <sys/malloc.h>
   45 #include <sys/uio.h>
   46 #include <sys/kernel.h>
   47 #include <sys/systm.h>
   48 #include <sys/conf.h>
   49 #include <sys/mbuf.h>
   50 #include <sys/socket.h>
   51 #include <sys/selinfo.h>
   52 #include <net/if.h>
   53 
   54 #include <machine/i4b_debug.h>
   55 #include <machine/i4b_ioctl.h>
   56 #include <machine/i4b_cause.h>
   57 
   58 #include <i4b/include/i4b_l3l4.h>
   59 #include <i4b/include/i4b_mbuf.h>
   60 #include <i4b/include/i4b_global.h>
   61 
   62 #include <i4b/layer4/i4b_l4.h>
   63 
   64 #include <sys/poll.h>
   65 
   66 struct selinfo select_rd_info;
   67 
   68 static struct ifqueue i4b_rdqueue;
   69 static int openflag = 0;
   70 static int selflag = 0;
   71 static int readflag = 0;
   72 
   73 static  d_open_t        i4bopen;
   74 static  d_close_t       i4bclose;
   75 static  d_read_t        i4bread;
   76 static  d_ioctl_t       i4bioctl;
   77 static  d_poll_t        i4bpoll;
   78 
   79 
   80 static struct cdevsw i4b_cdevsw = {
   81         .d_version =    D_VERSION,
   82         .d_flags =      D_NEEDGIANT,
   83         .d_open =       i4bopen,
   84         .d_close =      i4bclose,
   85         .d_read =       i4bread,
   86         .d_ioctl =      i4bioctl,
   87         .d_poll =       i4bpoll,
   88         .d_name =       "i4b",
   89 };
   90 
   91 static void i4battach(void *);
   92 PSEUDO_SET(i4battach, i4b_i4bdrv);
   93 
   94 /*---------------------------------------------------------------------------*
   95  *      interface attach routine
   96  *---------------------------------------------------------------------------*/
   97 static void
   98 i4battach(void *dummy)
   99 {
  100         printf("i4b: ISDN call control device attached\n");
  101 
  102         i4b_rdqueue.ifq_maxlen = IFQ_MAXLEN;
  103 
  104         if(!mtx_initialized(&i4b_rdqueue.ifq_mtx))
  105                 mtx_init(&i4b_rdqueue.ifq_mtx, "i4b_rdqueue", NULL, MTX_DEF);
  106 
  107         make_dev(&i4b_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "i4b");
  108 }
  109 
  110 /*---------------------------------------------------------------------------*
  111  *      i4bopen - device driver open routine
  112  *---------------------------------------------------------------------------*/
  113 static int
  114 i4bopen(struct cdev *dev, int flag, int fmt, struct thread *td)
  115 {
  116         int x;
  117         
  118         if(minor(dev))
  119                 return(ENXIO);
  120 
  121         if(openflag)
  122                 return(EBUSY);
  123         
  124         x = splimp();
  125         openflag = 1;
  126         i4b_l4_daemon_attached();
  127         splx(x);
  128         
  129         return(0);
  130 }
  131 
  132 /*---------------------------------------------------------------------------*
  133  *      i4bclose - device driver close routine
  134  *---------------------------------------------------------------------------*/
  135 static int
  136 i4bclose(struct cdev *dev, int flag, int fmt, struct thread *td)
  137 {
  138         int x = splimp();       
  139         openflag = 0;
  140         i4b_l4_daemon_detached();
  141         i4b_Dcleanifq(&i4b_rdqueue);
  142         splx(x);
  143         return(0);
  144 }
  145 
  146 /*---------------------------------------------------------------------------*
  147  *      i4bread - device driver read routine
  148  *---------------------------------------------------------------------------*/
  149 static int
  150 i4bread(struct cdev *dev, struct uio *uio, int ioflag)
  151 {
  152         struct mbuf *m;
  153         int x;
  154         int error = 0;
  155 
  156         if(minor(dev))
  157                 return(ENODEV);
  158 
  159         x = splimp();
  160         IF_LOCK(&i4b_rdqueue);
  161         while(IF_QEMPTY(&i4b_rdqueue))
  162         {
  163                 readflag = 1;
  164 
  165                 error = msleep( &i4b_rdqueue, &i4b_rdqueue.ifq_mtx,
  166                         (PZERO + 1) | PCATCH, "bird", 0);
  167 
  168                 if (error != 0) {
  169                         IF_UNLOCK(&i4b_rdqueue);
  170                         splx(x);
  171                         return error;
  172                 }
  173         }
  174 
  175         _IF_DEQUEUE(&i4b_rdqueue, m);
  176         IF_UNLOCK(&i4b_rdqueue);
  177 
  178         splx(x);
  179                 
  180         if(m && m->m_len)
  181                 error = uiomove(m->m_data, m->m_len, uio);
  182         else
  183                 error = EIO;
  184                 
  185         if(m)
  186                 i4b_Dfreembuf(m);
  187 
  188         return(error);
  189 }
  190 
  191 /*---------------------------------------------------------------------------*
  192  *      i4bioctl - device driver ioctl routine
  193  *---------------------------------------------------------------------------*/
  194 static int
  195 i4bioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
  196 {
  197         call_desc_t *cd;
  198         int error = 0;
  199         
  200         if(minor(dev))
  201                 return(ENODEV);
  202 
  203         switch(cmd)
  204         {
  205                 /* cdid request, reserve cd and return cdid */
  206 
  207                 case I4B_CDID_REQ:
  208                 {
  209                         msg_cdid_req_t *mir;
  210                         mir = (msg_cdid_req_t *)data;
  211                         cd = reserve_cd();
  212                         mir->cdid = cd->cdid;
  213                         break;
  214                 }
  215                 
  216                 /* connect request, dial out to remote */
  217                 
  218                 case I4B_CONNECT_REQ:
  219                 {
  220                         msg_connect_req_t *mcr;
  221                         mcr = (msg_connect_req_t *)data;        /* setup ptr */
  222 
  223                         if((cd = cd_by_cdid(mcr->cdid)) == NULL)/* get cd */
  224                         {
  225                                 NDBGL4(L4_ERR, "I4B_CONNECT_REQ ioctl, cdid not found!"); 
  226                                 error = EINVAL;
  227                                 break;
  228                         }
  229 
  230                         /* prevent dialling on leased lines */
  231                         if(ctrl_desc[mcr->controller].protocol == PROTOCOL_D64S)
  232                         {
  233                                 SET_CAUSE_TYPE(cd->cause_in, CAUSET_I4B);
  234                                 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_LLDIAL);
  235                                 i4b_l4_disconnect_ind(cd);
  236                                 freecd_by_cd(cd);
  237                                 break;
  238                         }
  239 
  240                         cd->controller = mcr->controller;       /* fill cd */
  241                         cd->bprot = mcr->bprot;
  242                         cd->bcap = mcr->bcap;                   
  243                         cd->driver = mcr->driver;
  244                         cd->driver_unit = mcr->driver_unit;
  245                         cd->cr = get_rand_cr(ctrl_desc[cd->controller].unit);
  246 
  247                         cd->shorthold_data.shorthold_algorithm = mcr->shorthold_data.shorthold_algorithm;
  248                         cd->shorthold_data.unitlen_time  = mcr->shorthold_data.unitlen_time;
  249                         cd->shorthold_data.idle_time     = mcr->shorthold_data.idle_time;
  250                         cd->shorthold_data.earlyhup_time = mcr->shorthold_data.earlyhup_time;
  251 
  252                         cd->last_aocd_time = 0;
  253                         if(mcr->unitlen_method == ULEN_METHOD_DYNAMIC)
  254                                 cd->aocd_flag = 1;
  255                         else
  256                                 cd->aocd_flag = 0;
  257                                 
  258                         cd->cunits = 0;
  259 
  260                         cd->max_idle_time = 0;  /* this is outgoing */
  261 
  262                         cd->dir = DIR_OUTGOING;
  263                         
  264                         NDBGL4(L4_TIMO, "I4B_CONNECT_REQ times, algorithm=%ld unitlen=%ld idle=%ld earlyhup=%ld",
  265                                         (long)cd->shorthold_data.shorthold_algorithm, (long)cd->shorthold_data.unitlen_time,
  266                                         (long)cd->shorthold_data.idle_time, (long)cd->shorthold_data.earlyhup_time);
  267 
  268                         strcpy(cd->dst_telno, mcr->dst_telno);
  269                         strcpy(cd->src_telno, mcr->src_telno);
  270 
  271                         strcpy(cd->dst_subaddr, mcr->dst_subaddr);
  272                         strcpy(cd->src_subaddr, mcr->src_subaddr);
  273 
  274                         if(mcr->keypad[0] != '\0')
  275                                 strcpy(cd->keypad, mcr->keypad);
  276                         else
  277                                 cd->keypad[0] = '\0';
  278                                 
  279                         cd->display[0] = '\0';
  280 
  281                         SET_CAUSE_TYPE(cd->cause_in, CAUSET_I4B);
  282                         SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NORMAL);
  283                         
  284                         switch(mcr->channel)
  285                         {
  286                                 case CHAN_B1:
  287                                 case CHAN_B2:
  288                                         if(ctrl_desc[mcr->controller].bch_state[mcr->channel] != BCH_ST_FREE)
  289                                                 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
  290                                         break;
  291 
  292                                 case CHAN_ANY:
  293                                 {
  294                                     int i;
  295                                     for (i = 0;
  296                                          i < ctrl_desc[mcr->controller].nbch &&
  297                                          ctrl_desc[mcr->controller].bch_state[i] != BCH_ST_FREE;
  298                                          i++);
  299                                     if (i == ctrl_desc[mcr->controller].nbch)
  300                                                 SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
  301                                     /* else mcr->channel = i; XXX */
  302                                 }
  303                                         break;
  304 
  305                                 default:
  306                                         SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
  307                                         break;
  308                         }
  309 
  310                         cd->channelid = mcr->channel;
  311 
  312                         cd->isdntxdelay = mcr->txdelay;
  313                         
  314                         /* check whether we have a pointer. Seems like */
  315                         /* this should be adequate. GJ 19.09.97 */
  316                         if(ctrl_desc[cd->controller].N_CONNECT_REQUEST == NULL)
  317 /*XXX*/                         SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN);
  318 
  319                         if((GET_CAUSE_VAL(cd->cause_in)) != CAUSE_I4B_NORMAL)
  320                         {
  321                                 i4b_l4_disconnect_ind(cd);
  322                                 freecd_by_cd(cd);
  323                         }
  324                         else
  325                         {
  326                                 (*ctrl_desc[cd->controller].N_CONNECT_REQUEST)(mcr->cdid);
  327                         }
  328                         break;
  329                 }
  330                 
  331                 /* connect response, accept/reject/ignore incoming call */
  332                 
  333                 case I4B_CONNECT_RESP:
  334                 {
  335                         msg_connect_resp_t *mcrsp;
  336                         
  337                         mcrsp = (msg_connect_resp_t *)data;
  338 
  339                         if((cd = cd_by_cdid(mcrsp->cdid)) == NULL)/* get cd */
  340                         {
  341                                 NDBGL4(L4_ERR, "I4B_CONNECT_RESP ioctl, cdid not found!"); 
  342                                 error = EINVAL;
  343                                 break;
  344                         }
  345 
  346                         T400_stop(cd);
  347 
  348                         cd->driver = mcrsp->driver;
  349                         cd->driver_unit = mcrsp->driver_unit;
  350                         cd->max_idle_time = mcrsp->max_idle_time;
  351 
  352                         cd->shorthold_data.shorthold_algorithm = SHA_FIXU;
  353                         cd->shorthold_data.unitlen_time = 0;    /* this is incoming */
  354                         cd->shorthold_data.idle_time = 0;
  355                         cd->shorthold_data.earlyhup_time = 0;
  356 
  357                         cd->isdntxdelay = mcrsp->txdelay;                       
  358                         
  359                         NDBGL4(L4_TIMO, "I4B_CONNECT_RESP max_idle_time set to %ld seconds", (long)cd->max_idle_time);
  360 
  361                         (*ctrl_desc[cd->controller].N_CONNECT_RESPONSE)(mcrsp->cdid, mcrsp->response, mcrsp->cause);
  362                         break;
  363                 }
  364                 
  365                 /* disconnect request, actively terminate connection */
  366                 
  367                 case I4B_DISCONNECT_REQ:
  368                 {
  369                         msg_discon_req_t *mdr;
  370                         
  371                         mdr = (msg_discon_req_t *)data;
  372 
  373                         if((cd = cd_by_cdid(mdr->cdid)) == NULL)/* get cd */
  374                         {
  375                                 NDBGL4(L4_ERR, "I4B_DISCONNECT_REQ ioctl, cdid not found!"); 
  376                                 error = EINVAL;
  377                                 break;
  378                         }
  379 
  380                         /* preset causes with our cause */
  381                         cd->cause_in = cd->cause_out = mdr->cause;
  382                         
  383                         (*ctrl_desc[cd->controller].N_DISCONNECT_REQUEST)(mdr->cdid, mdr->cause);
  384                         break;
  385                 }
  386                 
  387                 /* controller info request */
  388 
  389                 case I4B_CTRL_INFO_REQ:
  390                 {
  391                         msg_ctrl_info_req_t *mcir;
  392                         
  393                         mcir = (msg_ctrl_info_req_t *)data;
  394                         mcir->ncontroller = nctrl;
  395 
  396                         if(mcir->controller > nctrl)
  397                         {
  398                                 mcir->ctrl_type = -1;
  399                                 mcir->card_type = -1;
  400                         }
  401                         else
  402                         {
  403                                 mcir->ctrl_type = 
  404                                         ctrl_desc[mcir->controller].ctrl_type;
  405                                 mcir->card_type = 
  406                                         ctrl_desc[mcir->controller].card_type;
  407                                 mcir->nbch =
  408                                         ctrl_desc[mcir->controller].nbch;
  409 
  410                                 if(ctrl_desc[mcir->controller].ctrl_type == CTRL_PASSIVE)
  411                                         mcir->tei = ctrl_desc[mcir->controller].tei;
  412                                 else
  413                                         mcir->tei = -1;
  414                         }
  415                         break;
  416                 }
  417                 
  418                 /* dial response */
  419                 
  420                 case I4B_DIALOUT_RESP:
  421                 {
  422                         drvr_link_t *dlt = NULL;
  423                         msg_dialout_resp_t *mdrsp;
  424                         
  425                         mdrsp = (msg_dialout_resp_t *)data;
  426 
  427                         switch(mdrsp->driver)
  428                         {
  429 #if NI4BIPR > 0
  430                                 case BDRV_IPR:
  431                                         dlt = ipr_ret_linktab(mdrsp->driver_unit);
  432                                         break;
  433 #endif                                  
  434 
  435 #if NI4BISPPP > 0
  436                                 case BDRV_ISPPP:
  437                                         dlt = i4bisppp_ret_linktab(mdrsp->driver_unit);
  438                                         break;
  439 #endif
  440 
  441 #if NI4BTEL > 0
  442                                 case BDRV_TEL:
  443                                         dlt = tel_ret_linktab(mdrsp->driver_unit);
  444                                         break;
  445 #endif
  446 
  447 #if NIBC > 0
  448                                 case BDRV_IBC:
  449                                         dlt = ibc_ret_linktab(mdrsp->driver_unit);
  450                                         break;
  451 #endif
  452 
  453 #if NI4BING > 0
  454                                 case BDRV_ING:
  455                                         dlt = ing_ret_linktab(mdrsp->driver_unit);
  456                                         break;
  457 #endif                                  
  458                         }
  459 
  460                         if(dlt != NULL)         
  461                                 (*dlt->dial_response)(mdrsp->driver_unit, mdrsp->stat, mdrsp->cause);
  462                         break;
  463                 }
  464                 
  465                 /* update timeout value */
  466                 
  467                 case I4B_TIMEOUT_UPD:
  468                 {
  469                         msg_timeout_upd_t *mtu;
  470                         int x;
  471                         
  472                         mtu = (msg_timeout_upd_t *)data;
  473 
  474                         NDBGL4(L4_TIMO, "I4B_TIMEOUT_UPD ioctl, alg %d, unit %d, idle %d, early %d!",
  475                                         mtu->shorthold_data.shorthold_algorithm, mtu->shorthold_data.unitlen_time,
  476                                         mtu->shorthold_data.idle_time, mtu->shorthold_data.earlyhup_time); 
  477 
  478                         if((cd = cd_by_cdid(mtu->cdid)) == NULL)/* get cd */
  479                         {
  480                                 NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, cdid not found!"); 
  481                                 error = EINVAL;
  482                                 break;
  483                         }
  484 
  485                         switch( mtu->shorthold_data.shorthold_algorithm )
  486                         {
  487                                 case SHA_FIXU:
  488                                         /*
  489                                          * For this algorithm unitlen_time,
  490                                          * idle_time and earlyhup_time are used.
  491                                          */
  492 
  493                                         if(!(mtu->shorthold_data.unitlen_time >= 0 &&
  494                                              mtu->shorthold_data.idle_time >= 0    &&
  495                                              mtu->shorthold_data.earlyhup_time >= 0))
  496                                         {
  497                                                 NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, invalid args for fix unit algorithm!"); 
  498                                                 error = EINVAL;
  499                                         }
  500                                         break;
  501         
  502                                 case SHA_VARU:
  503                                         /*
  504                                          * For this algorithm unitlen_time and
  505                                          * idle_time are used. both must be
  506                                          * positive integers. earlyhup_time is
  507                                          * not used and must be 0.
  508                                          */
  509 
  510                                         if(!(mtu->shorthold_data.unitlen_time > 0 &&
  511                                              mtu->shorthold_data.idle_time >= 0   &&
  512                                              mtu->shorthold_data.earlyhup_time == 0))
  513                                         {
  514                                                 NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, invalid args for var unit algorithm!"); 
  515                                                 error = EINVAL;
  516                                         }
  517                                         break;
  518         
  519                                 default:
  520                                         NDBGL4(L4_ERR, "I4B_TIMEOUT_UPD ioctl, invalid algorithm!"); 
  521                                         error = EINVAL;
  522                                         break;
  523                         }
  524 
  525                         /*
  526                          * any error set above requires us to break
  527                          * out of the outer switch
  528                          */
  529                         if(error != 0)
  530                                 break;
  531 
  532                         x = SPLI4B();
  533                         cd->shorthold_data.shorthold_algorithm = mtu->shorthold_data.shorthold_algorithm;
  534                         cd->shorthold_data.unitlen_time = mtu->shorthold_data.unitlen_time;
  535                         cd->shorthold_data.idle_time = mtu->shorthold_data.idle_time;
  536                         cd->shorthold_data.earlyhup_time = mtu->shorthold_data.earlyhup_time;
  537                         splx(x);
  538                         break;
  539                 }
  540                         
  541                 /* soft enable/disable interface */
  542                 
  543                 case I4B_UPDOWN_IND:
  544                 {
  545                         msg_updown_ind_t *mui;
  546                         
  547                         mui = (msg_updown_ind_t *)data;
  548 
  549 #if NI4BIPR > 0
  550                         if(mui->driver == BDRV_IPR)
  551                         {
  552                                 drvr_link_t *dlt;
  553                                 dlt = ipr_ret_linktab(mui->driver_unit);
  554                                 (*dlt->updown_ind)(mui->driver_unit, mui->updown);
  555                         }
  556 #endif
  557                         break;
  558                 }
  559                 
  560                 /* send ALERT request */
  561                 
  562                 case I4B_ALERT_REQ:
  563                 {
  564                         msg_alert_req_t *mar;
  565                         
  566                         mar = (msg_alert_req_t *)data;
  567 
  568                         if((cd = cd_by_cdid(mar->cdid)) == NULL)
  569                         {
  570                                 NDBGL4(L4_ERR, "I4B_ALERT_REQ ioctl, cdid not found!"); 
  571                                 error = EINVAL;
  572                                 break;
  573                         }
  574 
  575                         T400_stop(cd);
  576                         
  577                         (*ctrl_desc[cd->controller].N_ALERT_REQUEST)(mar->cdid);
  578 
  579                         break;
  580                 }
  581 
  582                 /* version/release number request */
  583                 
  584                 case I4B_VR_REQ:
  585                 {
  586                         msg_vr_req_t *mvr;
  587 
  588                         mvr = (msg_vr_req_t *)data;
  589 
  590                         mvr->version = VERSION;
  591                         mvr->release = REL;
  592                         mvr->step = STEP;                       
  593                         break;
  594                 }
  595 
  596                 /* set D-channel protocol for a controller */
  597                 
  598                 case I4B_PROT_IND:
  599                 {
  600                         msg_prot_ind_t *mpi;
  601                         
  602                         mpi = (msg_prot_ind_t *)data;
  603 
  604                         ctrl_desc[mpi->controller].protocol = mpi->protocol;
  605                         
  606                         break;
  607                 }
  608                 
  609                 /* Download request */
  610 
  611                 case I4B_CTRL_DOWNLOAD:
  612                 {
  613                         struct isdn_dr_prot *prots = NULL, *prots2 = NULL;
  614                         struct isdn_download_request *r =
  615                                 (struct isdn_download_request*)data;
  616                         int i;
  617 
  618                         if (r->controller < 0 || r->controller >= nctrl)
  619                         {
  620                                 error = ENODEV;
  621                                 goto download_done;
  622                         }
  623 
  624                         if(!ctrl_desc[r->controller].N_DOWNLOAD)
  625                         {
  626                                 error = ENODEV;
  627                                 goto download_done;
  628                         }
  629 
  630                         prots = malloc(r->numprotos * sizeof(struct isdn_dr_prot),
  631                                         M_DEVBUF, M_WAITOK);
  632 
  633                         prots2 = malloc(r->numprotos * sizeof(struct isdn_dr_prot),
  634                                         M_DEVBUF, M_WAITOK);
  635 
  636                         if(!prots || !prots2)
  637                         {
  638                                 error = ENOMEM;
  639                                 goto download_done;
  640                         }
  641 
  642                         copyin(r->protocols, prots, r->numprotos * sizeof(struct isdn_dr_prot));
  643 
  644                         for(i = 0; i < r->numprotos; i++)
  645                         {
  646                                 prots2[i].microcode = malloc(prots[i].bytecount, M_DEVBUF, M_WAITOK);
  647                                 copyin(prots[i].microcode, prots2[i].microcode, prots[i].bytecount);
  648                                 prots2[i].bytecount = prots[i].bytecount; 
  649                         }
  650 
  651                         error = ctrl_desc[r->controller].N_DOWNLOAD(
  652                                                 ctrl_desc[r->controller].unit,
  653                                                 r->numprotos, prots2);
  654 
  655 download_done:
  656                         if(prots2)
  657                         {
  658                                 for(i = 0; i < r->numprotos; i++)
  659                                 {
  660                                         if(prots2[i].microcode)
  661                                         {
  662                                                 free(prots2[i].microcode, M_DEVBUF);
  663                                         }
  664                                 }
  665                                 free(prots2, M_DEVBUF);
  666                         }
  667 
  668                         if(prots)
  669                         {
  670                                 free(prots, M_DEVBUF);
  671                         }
  672                         break;
  673                 }
  674 
  675                 /* Diagnostic request */
  676 
  677                 case I4B_ACTIVE_DIAGNOSTIC:
  678                 {
  679                         struct isdn_diagnostic_request req, *r =
  680                                 (struct isdn_diagnostic_request*)data;
  681 
  682                         req.in_param = req.out_param = NULL;
  683                         if (r->controller < 0 || r->controller >= nctrl)
  684                         {
  685                                 error = ENODEV;
  686                                 goto diag_done;
  687                         }
  688 
  689                         if(!ctrl_desc[r->controller].N_DIAGNOSTICS)
  690                         {
  691                                 error = ENODEV;
  692                                 goto diag_done;
  693                         }
  694 
  695                         memcpy(&req, r, sizeof(req));
  696 
  697                         if(req.in_param_len)
  698                         {
  699                                 /* XXX arbitrary limit */
  700                                 if (req.in_param_len >
  701                                     I4B_ACTIVE_DIAGNOSTIC_MAXPARAMLEN) {
  702                                         error = EINVAL;
  703                                         goto diag_done;
  704                                 }       
  705 
  706                                 req.in_param = malloc(r->in_param_len, M_DEVBUF, M_WAITOK);
  707 
  708                                 if(!req.in_param)
  709                                 {
  710                                         error = ENOMEM;
  711                                         goto diag_done;
  712                                 }
  713                                 error = copyin(r->in_param, req.in_param, req.in_param_len);
  714                                 if (error)
  715                                         goto diag_done;
  716                         }
  717 
  718                         if(req.out_param_len)
  719                         {
  720                                 req.out_param = malloc(r->out_param_len, M_DEVBUF, M_WAITOK);
  721 
  722                                 if(!req.out_param)
  723                                 {
  724                                         error = ENOMEM;
  725                                         goto diag_done;
  726                                 }
  727                         }
  728                         
  729                         error = ctrl_desc[r->controller].N_DIAGNOSTICS(r->controller, &req);
  730 
  731                         if(!error && req.out_param_len)
  732                                 error = copyout(req.out_param, r->out_param, req.out_param_len);
  733 
  734 diag_done:
  735                         if(req.in_param)
  736                                 free(req.in_param, M_DEVBUF);
  737                                 
  738                         if(req.out_param)
  739                                 free(req.out_param, M_DEVBUF);
  740 
  741                         break;
  742                 }
  743 
  744                 /* default */
  745                 
  746                 default:
  747                         error = ENOTTY;
  748                         break;
  749         }
  750         
  751         return(error);
  752 }
  753 
  754 /*---------------------------------------------------------------------------*
  755  *      i4bpoll - device driver poll routine
  756  *---------------------------------------------------------------------------*/
  757 static int
  758 i4bpoll(struct cdev *dev, int events, struct thread *td)
  759 {
  760         int x;
  761         
  762         if(minor(dev))
  763                 return(ENODEV);
  764 
  765         if((events & POLLIN) || (events & POLLRDNORM))
  766         {
  767                 if(!IF_QEMPTY(&i4b_rdqueue))
  768                         return(1);
  769 
  770                 x = splimp();
  771                 selrecord(td, &select_rd_info);
  772                 selflag = 1;
  773                 splx(x);
  774                 return(0);
  775         }
  776         else if((events & POLLOUT) || (events & POLLWRNORM))
  777         {
  778                 return(1);
  779         }
  780 
  781         return(0);
  782 }
  783 
  784 /*---------------------------------------------------------------------------*
  785  *      i4bputqueue - put message into queue to userland
  786  *---------------------------------------------------------------------------*/
  787 void
  788 i4bputqueue(struct mbuf *m)
  789 {
  790         int x;
  791         
  792         if(!openflag)
  793         {
  794                 i4b_Dfreembuf(m);
  795                 return;
  796         }
  797 
  798         x = splimp();
  799         
  800         IF_LOCK(&i4b_rdqueue);
  801         if(_IF_QFULL(&i4b_rdqueue))
  802         {
  803                 struct mbuf *m1;
  804                 _IF_DEQUEUE(&i4b_rdqueue, m1);
  805                 i4b_Dfreembuf(m1);
  806                 NDBGL4(L4_ERR, "ERROR, queue full, removing entry!");
  807         }
  808 
  809         _IF_ENQUEUE(&i4b_rdqueue, m);
  810         IF_UNLOCK(&i4b_rdqueue);
  811 
  812         splx(x);        
  813 
  814         if(readflag)
  815         {
  816                 readflag = 0;
  817                 wakeup( &i4b_rdqueue);
  818         }
  819 
  820         if(selflag)
  821         {
  822                 selflag = 0;
  823                 selwakeuppri(&select_rd_info, I4BPRI);
  824         }
  825 }
  826 
  827 /*---------------------------------------------------------------------------*
  828  *      i4bputqueue_hipri - put message into front of queue to userland
  829  *---------------------------------------------------------------------------*/
  830 void
  831 i4bputqueue_hipri(struct mbuf *m)
  832 {
  833         int x;
  834         
  835         if(!openflag)
  836         {
  837                 i4b_Dfreembuf(m);
  838                 return;
  839         }
  840 
  841         x = splimp();
  842         
  843         IF_LOCK(&i4b_rdqueue);
  844         if(_IF_QFULL(&i4b_rdqueue))
  845         {
  846                 struct mbuf *m1;
  847                 _IF_DEQUEUE(&i4b_rdqueue, m1);
  848                 i4b_Dfreembuf(m1);
  849                 NDBGL4(L4_ERR, "ERROR, queue full, removing entry!");
  850         }
  851 
  852         _IF_PREPEND(&i4b_rdqueue, m);
  853         IF_UNLOCK(&i4b_rdqueue);
  854 
  855         splx(x);        
  856 
  857         if(readflag)
  858         {
  859                 readflag = 0;
  860                 wakeup( &i4b_rdqueue);
  861         }
  862 
  863         if(selflag)
  864         {
  865                 selflag = 0;
  866                 selwakeuppri(&select_rd_info, I4BPRI);
  867         }
  868 }

Cache object: 2145a792b0d05578196b00c27079447d


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