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/netatm/atm_subr.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  *
    3  * ===================================
    4  * HARP  |  Host ATM Research Platform
    5  * ===================================
    6  *
    7  *
    8  * This Host ATM Research Platform ("HARP") file (the "Software") is
    9  * made available by Network Computing Services, Inc. ("NetworkCS")
   10  * "AS IS".  NetworkCS does not provide maintenance, improvements or
   11  * support of any kind.
   12  *
   13  * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
   14  * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
   15  * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
   16  * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
   17  * In no event shall NetworkCS be responsible for any damages, including
   18  * but not limited to consequential damages, arising from or relating to
   19  * any use of the Software or related support.
   20  *
   21  * Copyright 1994-1998 Network Computing Services, Inc.
   22  *
   23  * Copies of this Software may be made, however, the above copyright
   24  * notice must be reproduced on all copies.
   25  *
   26  *      @(#) $FreeBSD: releng/5.0/sys/netatm/atm_subr.c 106651 2002-11-08 18:27:30Z jhb $
   27  *
   28  */
   29 
   30 /*
   31  * Core ATM Services
   32  * -----------------
   33  *
   34  * Miscellaneous ATM subroutines
   35  *
   36  */
   37 
   38 #include <sys/param.h>
   39 #include <sys/systm.h>
   40 #include <sys/errno.h>
   41 #include <sys/malloc.h>
   42 #include <sys/time.h>
   43 #include <sys/kernel.h>
   44 #include <sys/socket.h>
   45 #include <sys/socketvar.h>
   46 #include <net/if.h>
   47 #include <net/netisr.h>
   48 #include <net/intrq.h>
   49 #include <netatm/port.h>
   50 #include <netatm/queue.h>
   51 #include <netatm/atm.h>
   52 #include <netatm/atm_sys.h>
   53 #include <netatm/atm_sap.h>
   54 #include <netatm/atm_cm.h>
   55 #include <netatm/atm_if.h>
   56 #include <netatm/atm_stack.h>
   57 #include <netatm/atm_pcb.h>
   58 #include <netatm/atm_var.h>
   59 #include <vm/uma.h>
   60 
   61 #ifndef lint
   62 __RCSID("@(#) $FreeBSD: releng/5.0/sys/netatm/atm_subr.c 106651 2002-11-08 18:27:30Z jhb $");
   63 #endif
   64 
   65 
   66 /*
   67  * Global variables
   68  */
   69 struct atm_pif          *atm_interface_head = NULL;
   70 struct atm_ncm          *atm_netconv_head = NULL;
   71 Atm_endpoint            *atm_endpoints[ENDPT_MAX+1] = {NULL};
   72 struct stackq_entry     *atm_stackq_head = NULL, *atm_stackq_tail;
   73 struct atm_sock_stat    atm_sock_stat = { { 0 } };
   74 int                     atm_init = 0;
   75 int                     atm_debug = 0;
   76 int                     atm_dev_print = 0;
   77 int                     atm_print_data = 0;
   78 int                     atm_version = ATM_VERSION;
   79 struct timeval          atm_debugtime = {0, 0};
   80 
   81 uma_zone_t atm_attributes_zone;
   82 
   83 /*
   84  * Local functions
   85  */
   86 static KTimeout_ret     atm_timexp(void *);
   87 
   88 /*
   89  * Local variables
   90  */
   91 static struct atm_time  *atm_timeq = NULL;
   92 static uma_zone_t atm_stackq_zone;
   93 
   94 /*
   95  * Initialize ATM kernel
   96  * 
   97  * Performs any initialization required before things really get underway.
   98  * Called from ATM domain initialization or from first registration function 
   99  * which gets called.
  100  *
  101  * Arguments:
  102  *      none
  103  *
  104  * Returns:
  105  *      none
  106  *
  107  */
  108 void
  109 atm_initialize()
  110 {
  111         /*
  112          * Never called from interrupts, so no locking needed
  113          */
  114         if (atm_init)
  115                 return;
  116         atm_init = 1;
  117 
  118         atm_intrq.ifq_maxlen = ATM_INTRQ_MAX;
  119         mtx_init(&atm_intrq.ifq_mtx, "atm_inq", NULL, MTX_DEF);
  120         atmintrq_present = 1;
  121 
  122         atm_attributes_zone = uma_zcreate("atm attributes",
  123             sizeof(Atm_attributes), NULL, NULL, NULL, NULL,
  124             UMA_ALIGN_PTR, 0);
  125         if (atm_attributes_zone == NULL)
  126                 panic("atm_initialize: unable to create attributes zone");
  127         uma_zone_set_max(atm_attributes_zone, 100);
  128 
  129         atm_stackq_zone = uma_zcreate("atm stackq", sizeof(struct stackq_entry),
  130             NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
  131         if (atm_stackq_zone == NULL)
  132                 panic("atm_initialize: unable to create stackq zone");
  133         uma_zone_set_max(atm_stackq_zone, 10);
  134 
  135         register_netisr(NETISR_ATM, atm_intr);
  136 
  137         /*
  138          * Initialize subsystems
  139          */
  140         atm_sock_init();
  141         atm_cm_init();
  142         atm_aal5_init();
  143 
  144         /*
  145          * Prime the timer
  146          */
  147         (void)timeout(atm_timexp, (void *)0, hz/ATM_HZ);
  148 }
  149 
  150 
  151 /*
  152  * Handle timer tick expiration
  153  * 
  154  * Decrement tick count in first block on timer queue.  If there
  155  * are blocks with expired timers, call their timeout function.
  156  * This function is called ATM_HZ times per second.
  157  *
  158  * Arguments:
  159  *      arg     argument passed on timeout() call
  160  *
  161  * Returns:
  162  *      none
  163  *
  164  */
  165 static KTimeout_ret
  166 atm_timexp(arg)
  167         void    *arg;
  168 {
  169         struct atm_time *tip;
  170         int             s = splimp();
  171 
  172 
  173         /*
  174          * Decrement tick count
  175          */
  176         if (((tip = atm_timeq) == NULL) || (--tip->ti_ticks > 0)) {
  177                 goto restart;
  178         }
  179 
  180         /*
  181          * Stack queue should have been drained
  182          */
  183         KASSERT(atm_stackq_head == NULL, ("atm_timexp: stack queue not empty"));
  184 
  185         /*
  186          * Dispatch expired timers
  187          */
  188         while (((tip = atm_timeq) != NULL) && (tip->ti_ticks == 0)) {
  189                 void    (*func)(struct atm_time *);
  190 
  191                 /*
  192                  * Remove expired block from queue
  193                  */
  194                 atm_timeq = tip->ti_next;
  195                 tip->ti_flag &= ~TIF_QUEUED;
  196 
  197                 /*
  198                  * Call timeout handler (with network interrupts locked out)
  199                  */
  200                 func = tip->ti_func;
  201                 (void) splx(s);
  202                 s = splnet();
  203                 (*func)(tip);
  204                 (void) splx(s);
  205                 s = splimp();
  206 
  207                 /*
  208                  * Drain any deferred calls
  209                  */
  210                 STACK_DRAIN();
  211         }
  212 
  213 restart:
  214         /*
  215          * Restart the timer
  216          */
  217         (void) splx(s);
  218         (void) timeout(atm_timexp, (void *)0, hz/ATM_HZ);
  219 
  220         return;
  221 }
  222 
  223 
  224 /*
  225  * Schedule a control block timeout
  226  * 
  227  * Place the supplied timer control block on the timer queue.  The
  228  * function (func) will be called in 't' timer ticks with the
  229  * control block address as its only argument.  There are ATM_HZ
  230  * timer ticks per second.  The ticks value stored in each block is
  231  * a delta of the number of ticks from the previous block in the queue.
  232  * Thus, for each tick interval, only the first block in the queue 
  233  * needs to have its tick value decremented.
  234  *
  235  * Arguments:
  236  *      tip     pointer to timer control block
  237  *      t       number of timer ticks until expiration
  238  *      func    pointer to function to call at expiration 
  239  *
  240  * Returns:
  241  *      none
  242  *
  243  */
  244 void
  245 atm_timeout(tip, t, func)
  246         struct atm_time *tip;
  247         int             t;
  248         void            (*func)(struct atm_time *);
  249 {
  250         struct atm_time *tip1, *tip2;
  251         int             s;
  252 
  253 
  254         /*
  255          * Check for double queueing error
  256          */
  257         if (tip->ti_flag & TIF_QUEUED)
  258                 panic("atm_timeout: double queueing");
  259 
  260         /*
  261          * Make sure we delay at least a little bit
  262          */
  263         if (t <= 0)
  264                 t = 1;
  265 
  266         /*
  267          * Find out where we belong on the queue
  268          */
  269         s = splimp();
  270         for (tip1 = NULL, tip2 = atm_timeq; tip2 && (tip2->ti_ticks <= t); 
  271                                             tip1 = tip2, tip2 = tip1->ti_next) {
  272                 t -= tip2->ti_ticks;
  273         }
  274 
  275         /*
  276          * Place ourselves on queue and update timer deltas
  277          */
  278         if (tip1 == NULL)
  279                 atm_timeq = tip;
  280         else
  281                 tip1->ti_next = tip;
  282         tip->ti_next = tip2;
  283 
  284         if (tip2)
  285                 tip2->ti_ticks -= t;
  286         
  287         /*
  288          * Setup timer block
  289          */
  290         tip->ti_flag |= TIF_QUEUED;
  291         tip->ti_ticks = t;
  292         tip->ti_func = func;
  293 
  294         (void) splx(s);
  295         return;
  296 }
  297 
  298 
  299 /*
  300  * Cancel a timeout
  301  * 
  302  * Remove the supplied timer control block from the timer queue.
  303  *
  304  * Arguments:
  305  *      tip     pointer to timer control block
  306  *
  307  * Returns:
  308  *      0       control block successfully dequeued
  309  *      1       control block not on timer queue
  310  *
  311  */
  312 int
  313 atm_untimeout(tip)
  314         struct atm_time *tip;
  315 {
  316         struct atm_time *tip1, *tip2;
  317         int             s;
  318 
  319         /*
  320          * Is control block queued?
  321          */
  322         if ((tip->ti_flag & TIF_QUEUED) == 0)
  323                 return(1);
  324 
  325         /*
  326          * Find control block on the queue
  327          */
  328         s = splimp();
  329         for (tip1 = NULL, tip2 = atm_timeq; tip2 && (tip2 != tip); 
  330                                             tip1 = tip2, tip2 = tip1->ti_next) {
  331         }
  332 
  333         if (tip2 == NULL) {
  334                 (void) splx(s);
  335                 return (1);
  336         }
  337 
  338         /*
  339          * Remove block from queue and update timer deltas
  340          */
  341         tip2 = tip->ti_next;
  342         if (tip1 == NULL)
  343                 atm_timeq = tip2;
  344         else
  345                 tip1->ti_next = tip2;
  346 
  347         if (tip2)
  348                 tip2->ti_ticks += tip->ti_ticks;
  349         
  350         /*
  351          * Reset timer block
  352          */
  353         tip->ti_flag &= ~TIF_QUEUED;
  354 
  355         (void) splx(s);
  356         return (0);
  357 }
  358 
  359 
  360 /*
  361  * Queue a Stack Call 
  362  * 
  363  * Queues a stack call which must be deferred to the global stack queue.
  364  * The call parameters are stored in entries which are allocated from the
  365  * stack queue storage pool.
  366  *
  367  * Arguments:
  368  *      cmd     stack command
  369  *      func    destination function
  370  *      token   destination layer's token
  371  *      cvp     pointer to  connection vcc
  372  *      arg1    command argument
  373  *      arg2    command argument
  374  *
  375  * Returns:
  376  *      0       call queued
  377  *      errno   call not queued - reason indicated
  378  *
  379  */
  380 int
  381 atm_stack_enq(cmd, func, token, cvp, arg1, arg2)
  382         int             cmd;
  383         void            (*func)(int, void *, intptr_t, intptr_t);
  384         void            *token;
  385         Atm_connvc      *cvp;
  386         intptr_t        arg1;
  387         intptr_t        arg2;
  388 {
  389         struct stackq_entry     *sqp;
  390         int             s = splnet();
  391 
  392         /*
  393          * Get a new queue entry for this call
  394          */
  395         sqp = uma_zalloc(atm_stackq_zone, M_ZERO);
  396         if (sqp == NULL) {
  397                 (void) splx(s);
  398                 return (ENOMEM);
  399         }
  400 
  401         /*
  402          * Fill in new entry
  403          */
  404         sqp->sq_next = NULL;
  405         sqp->sq_cmd = cmd;
  406         sqp->sq_func = func;
  407         sqp->sq_token = token;
  408         sqp->sq_arg1 = arg1;
  409         sqp->sq_arg2 = arg2;
  410         sqp->sq_connvc = cvp;
  411 
  412         /*
  413          * Put new entry at end of queue
  414          */
  415         if (atm_stackq_head == NULL)
  416                 atm_stackq_head = sqp;
  417         else
  418                 atm_stackq_tail->sq_next = sqp;
  419         atm_stackq_tail = sqp;
  420 
  421         (void) splx(s);
  422         return (0);
  423 }
  424 
  425 
  426 /*
  427  * Drain the Stack Queue
  428  * 
  429  * Dequeues and processes entries from the global stack queue.  
  430  *
  431  * Arguments:
  432  *      none
  433  *
  434  * Returns:
  435  *      none
  436  *
  437  */
  438 void
  439 atm_stack_drain()
  440 {
  441         struct stackq_entry     *sqp, *qprev, *qnext;
  442         int             s = splnet();
  443         int             cnt;
  444 
  445         /*
  446          * Loop thru entire queue until queue is empty
  447          *      (but panic rather loop forever)
  448          */
  449         do {
  450                 cnt = 0;
  451                 qprev = NULL;
  452                 for (sqp = atm_stackq_head; sqp; ) {
  453 
  454                         /*
  455                          * Got an eligible entry, do STACK_CALL stuff
  456                          */
  457                         if (sqp->sq_cmd & STKCMD_UP) {
  458                                 if (sqp->sq_connvc->cvc_downcnt) {
  459 
  460                                         /*
  461                                          * Cant process now, skip it
  462                                          */
  463                                         qprev = sqp;
  464                                         sqp = sqp->sq_next;
  465                                         continue;
  466                                 }
  467 
  468                                 /*
  469                                  * OK, dispatch the call
  470                                  */
  471                                 sqp->sq_connvc->cvc_upcnt++;
  472                                 (*sqp->sq_func)(sqp->sq_cmd, 
  473                                                 sqp->sq_token,
  474                                                 sqp->sq_arg1,
  475                                                 sqp->sq_arg2);
  476                                 sqp->sq_connvc->cvc_upcnt--;
  477                         } else {
  478                                 if (sqp->sq_connvc->cvc_upcnt) {
  479 
  480                                         /*
  481                                          * Cant process now, skip it
  482                                          */
  483                                         qprev = sqp;
  484                                         sqp = sqp->sq_next;
  485                                         continue;
  486                                 }
  487 
  488                                 /*
  489                                  * OK, dispatch the call
  490                                  */
  491                                 sqp->sq_connvc->cvc_downcnt++;
  492                                 (*sqp->sq_func)(sqp->sq_cmd, 
  493                                                 sqp->sq_token,
  494                                                 sqp->sq_arg1,
  495                                                 sqp->sq_arg2);
  496                                 sqp->sq_connvc->cvc_downcnt--;
  497                         }
  498 
  499                         /*
  500                          * Dequeue processed entry and free it
  501                          */
  502                         cnt++;
  503                         qnext = sqp->sq_next;
  504                         if (qprev)
  505                                 qprev->sq_next = qnext;
  506                         else
  507                                 atm_stackq_head = qnext;
  508                         if (qnext == NULL)
  509                                 atm_stackq_tail = qprev;
  510                         uma_zfree(atm_stackq_zone, sqp);
  511                         sqp = qnext;
  512                 }
  513         } while (cnt > 0);
  514 
  515         /*
  516          * Make sure entire queue was drained
  517          */
  518         if (atm_stackq_head != NULL)
  519                 panic("atm_stack_drain: Queue not emptied");
  520 
  521         (void) splx(s);
  522 }
  523 
  524 
  525 /*
  526  * Process Interrupt Queue
  527  * 
  528  * Processes entries on the ATM interrupt queue.  This queue is used by
  529  * device interface drivers in order to schedule events from the driver's 
  530  * lower (interrupt) half to the driver's stack services.
  531  *
  532  * The interrupt routines must store the stack processing function to call
  533  * and a token (typically a driver/stack control block) at the front of the
  534  * queued buffer.  We assume that the function pointer and token values are 
  535  * both contained (and properly aligned) in the first buffer of the chain.
  536  *
  537  * Arguments:
  538  *      none
  539  *
  540  * Returns:
  541  *      none
  542  *
  543  */
  544 void
  545 atm_intr()
  546 {
  547         KBuffer         *m;
  548         caddr_t         cp;
  549         atm_intr_func_t func;
  550         void            *token;
  551         int             s;
  552 
  553         for (; ; ) {
  554                 /*
  555                  * Get next buffer from queue
  556                  */
  557                 s = splimp();
  558                 IF_DEQUEUE(&atm_intrq, m);
  559                 (void) splx(s);
  560                 if (m == NULL)
  561                         break;
  562 
  563                 /*
  564                  * Get function to call and token value
  565                  */
  566                 KB_DATASTART(m, cp, caddr_t);
  567                 func = *(atm_intr_func_t *)cp;
  568                 cp += sizeof(func);
  569                 token = *(void **)cp;
  570                 KB_HEADADJ(m, -(sizeof(func) + sizeof(token)));
  571                 if (KB_LEN(m) == 0) {
  572                         KBuffer         *m1;
  573                         KB_UNLINKHEAD(m, m1);
  574                         m = m1;
  575                 }
  576 
  577                 /*
  578                  * Call processing function
  579                  */
  580                 (*func)(token, m);
  581 
  582                 /*
  583                  * Drain any deferred calls
  584                  */
  585                 STACK_DRAIN();
  586         }
  587 }
  588 
  589 
  590 /*
  591  * Print a pdu buffer chain
  592  * 
  593  * Arguments:
  594  *      m       pointer to pdu buffer chain
  595  *      msg     pointer to message header string
  596  *
  597  * Returns:
  598  *      none
  599  *
  600  */
  601 void
  602 atm_pdu_print(m, msg)
  603         KBuffer         *m;
  604         char            *msg;
  605 {
  606         caddr_t         cp;
  607         int             i;
  608         char            c = ' ';
  609 
  610         printf("%s:", msg);
  611         while (m) { 
  612                 KB_DATASTART(m, cp, caddr_t);
  613                 printf("%cbfr=%p data=%p len=%d: ",
  614                         c, m, cp, KB_LEN(m));
  615                 c = '\t';
  616                 if (atm_print_data) {
  617                         for (i = 0; i < KB_LEN(m); i++) {
  618                                 printf("%2x ", (u_char)*cp++);
  619                         }
  620                         printf("<end_bfr>\n");
  621                 } else {
  622                         printf("\n");
  623                 }
  624                 m = KB_NEXT(m);
  625         }
  626 }
  627 

Cache object: 0d9d05cb960a17d593257cafef548175


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