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

Cache object: e6d6ae7b5541cf1833b6891537676fb8


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