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_device.c

Version: -  FREEBSD  -  FREEBSD11  -  FREEBSD10  -  FREEBSD9  -  FREEBSD92  -  FREEBSD91  -  FREEBSD90  -  FREEBSD8  -  FREEBSD82  -  FREEBSD81  -  FREEBSD80  -  FREEBSD7  -  FREEBSD74  -  FREEBSD73  -  FREEBSD72  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * ===================================
    3  * HARP  |  Host ATM Research Platform
    4  * ===================================
    5  *
    6  *
    7  * This Host ATM Research Platform ("HARP") file (the "Software") is
    8  * made available by Network Computing Services, Inc. ("NetworkCS")
    9  * "AS IS".  NetworkCS does not provide maintenance, improvements or
   10  * support of any kind.
   11  *
   12  * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
   13  * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
   14  * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
   15  * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
   16  * In no event shall NetworkCS be responsible for any damages, including
   17  * but not limited to consequential damages, arising from or relating to
   18  * any use of the Software or related support.
   19  *
   20  * Copyright 1994-1998 Network Computing Services, Inc.
   21  *
   22  * Copies of this Software may be made, however, the above copyright
   23  * notice must be reproduced on all copies.
   24  */
   25 
   26 /*
   27  * Core ATM Services
   28  * -----------------
   29  *
   30  * ATM device support functions
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __FBSDID("$FreeBSD: src/sys/netatm/atm_device.c,v 1.25.4.1 2005/01/31 23:26:25 imp Exp $");
   35 
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/errno.h>
   39 #include <sys/malloc.h>
   40 #include <sys/time.h>
   41 #include <sys/socket.h>
   42 #include <sys/socketvar.h>
   43 #include <sys/syslog.h>
   44 #include <net/if.h>
   45 #include <net/bpf.h>
   46 #include <netatm/port.h>
   47 #include <netatm/queue.h>
   48 #include <netatm/atm.h>
   49 #include <netatm/atm_sys.h>
   50 #include <netatm/atm_sap.h>
   51 #include <netatm/atm_cm.h>
   52 #include <netatm/atm_if.h>
   53 #include <netatm/atm_vc.h>
   54 #include <netatm/atm_stack.h>
   55 #include <netatm/atm_pcb.h>
   56 #include <netatm/atm_var.h>
   57 
   58 /*
   59  * Private structures for managing allocated kernel memory resources
   60  *
   61  * For each allocation of kernel memory, one Mem_ent will be used.  
   62  * The Mem_ent structures will be allocated in blocks inside of a 
   63  * Mem_blk structure.
   64  */
   65 #define MEM_NMEMENT     10              /* How many Mem_ent's in a Mem_blk */
   66 
   67 struct mem_ent {
   68         void            *me_kaddr;      /* Allocated memory address */
   69         u_int           me_ksize;       /* Allocated memory length */
   70         void            *me_uaddr;      /* Memory address returned to caller */
   71         u_int           me_flags;       /* Flags (see below) */
   72 };
   73 typedef struct mem_ent  Mem_ent;
   74 
   75 /*
   76  * Memory entry flags
   77  */
   78 #define MEF_NONCACHE    1               /* Memory is noncacheable */
   79 
   80 
   81 struct mem_blk {
   82         struct mem_blk  *mb_next;       /* Next block in chain */
   83         Mem_ent         mb_mement[MEM_NMEMENT]; /* Allocated memory entries */
   84 };
   85 typedef struct mem_blk  Mem_blk;
   86 
   87 static Mem_blk          *atm_mem_head = NULL;
   88 
   89 static struct t_atm_cause       atm_dev_cause = {
   90         T_ATM_ITU_CODING,
   91         T_ATM_LOC_USER,
   92         T_ATM_CAUSE_VPCI_VCI_ASSIGNMENT_FAILURE,
   93         {0, 0, 0, 0}
   94 };
   95 
   96 extern struct ifqueue atm_intrq;
   97 
   98 /*
   99  * ATM Device Stack Instantiation
  100  *
  101  * Called at splnet.
  102  *
  103  * Arguments
  104  *      ssp             pointer to array of stack definition pointers
  105  *                      for connection
  106  *                      ssp[0] points to upper layer's stack definition
  107  *                      ssp[1] points to this layer's stack definition
  108  *                      ssp[2] points to lower layer's stack definition
  109  *      cvcp            pointer to connection vcc for this stack
  110  *
  111  * Returns
  112  *      0               instantiation successful
  113  *      err             instantiation failed - reason indicated
  114  *
  115  */
  116 int
  117 atm_dev_inst(ssp, cvcp)
  118         struct stack_defn       **ssp;
  119         Atm_connvc              *cvcp;
  120 {
  121         Cmn_unit        *cup = (Cmn_unit *)cvcp->cvc_attr.nif->nif_pif;
  122         Cmn_vcc         *cvp;
  123         int             err;
  124 
  125         /*
  126          * Check to see if device has been initialized
  127          */
  128         if ((cup->cu_flags & CUF_INITED) == 0)
  129                 return ( EIO );
  130 
  131         /*
  132          * Validate lower SAP
  133          */
  134         /*
  135          * Device driver is the lowest layer - no need to validate
  136          */
  137 
  138         /*
  139          * Validate PVC vpi.vci
  140          */
  141         if (cvcp->cvc_attr.called.addr.address_format == T_ATM_PVC_ADDR) {
  142                 /*
  143                  * Look through existing circuits - return error if found
  144                  */
  145                 Atm_addr_pvc    *pp;
  146 
  147                 pp = (Atm_addr_pvc *)cvcp->cvc_attr.called.addr.address;
  148                 if (atm_dev_vcc_find(cup, ATM_PVC_GET_VPI(pp),
  149                                 ATM_PVC_GET_VCI(pp), 0))
  150                         return ( EADDRINUSE );
  151         }
  152 
  153         /*
  154          * Validate our SAP type
  155          */
  156         switch ((*(ssp+1))->sd_sap) {
  157         case SAP_CPCS_AAL3_4:
  158         case SAP_CPCS_AAL5:
  159         case SAP_ATM:
  160                 break;
  161         default:
  162                 return (EINVAL);
  163         }
  164 
  165         /*
  166          * Allocate a VCC control block
  167          * This can happen from a callout so don't wait here.
  168          */
  169         cvp = uma_zalloc(cup->cu_vcc_zone, M_NOWAIT);
  170         if (cvp == NULL)
  171                 return (ENOMEM);
  172         
  173         cvp->cv_state = CVS_INST;
  174         cvp->cv_toku = (*ssp)->sd_toku;
  175         cvp->cv_upper = (*ssp)->sd_upper;
  176         cvp->cv_connvc = cvcp;
  177 
  178         /*
  179          * Let device have a look at the connection request
  180          */
  181         err = (*cup->cu_instvcc)(cup, cvp);
  182         if (err) {
  183                 uma_zfree(cup->cu_vcc_zone, cvp);
  184                 return (err);
  185         }
  186 
  187         /*
  188          * Looks good so far, so link in device VCC
  189          */
  190         LINK2TAIL ( cvp, Cmn_vcc, cup->cu_vcc, cv_next );
  191 
  192         /*
  193          * Save my token
  194          */
  195         (*++ssp)->sd_toku = cvp;
  196 
  197         /*
  198          * Pass instantiation down the stack
  199          */
  200         /*
  201          * No need - we're the lowest point.
  202          */
  203         /* err = (*(ssp + 1))->sd_inst(ssp, cvcp); */
  204 
  205         /*
  206          * Save the lower layer's interface info
  207          */
  208         /*
  209          * No need - we're the lowest point
  210          */
  211         /* cvp->cv_lower = (*++ssp)->sd_lower; */
  212         /* cvp->cv_tok1 = (*ssp)->sd_toku; */
  213 
  214         return (0);
  215 }
  216 
  217 
  218 /*
  219  * ATM Device Stack Command Handler
  220  *
  221  * Arguments
  222  *      cmd             stack command code
  223  *      tok             session token (Cmn_vcc)
  224  *      arg1            command specific argument
  225  *      arg2            command specific argument
  226  *
  227  * Returns
  228  *      none
  229  *
  230  */
  231 /*ARGSUSED*/
  232 void
  233 atm_dev_lower(cmd, tok, arg1, arg2)
  234         int     cmd;
  235         void    *tok;
  236         intptr_t        arg1;
  237         intptr_t        arg2;
  238 {
  239         Cmn_vcc         *cvp = (Cmn_vcc *)tok;
  240         Atm_connvc      *cvcp = cvp->cv_connvc;
  241         Cmn_unit        *cup = (Cmn_unit *)cvcp->cvc_attr.nif->nif_pif;
  242         struct vccb     *vcp;
  243         u_int           state;
  244         int             s;
  245 
  246         switch ( cmd ) {
  247 
  248         case CPCS_INIT:
  249                 /*
  250                  * Sanity check
  251                  */
  252                 if ( cvp->cv_state != CVS_INST ) {
  253                         log ( LOG_ERR,
  254                                 "atm_dev_lower: INIT: tok=%p, state=%d\n",
  255                                 tok, cvp->cv_state );
  256                         break;
  257                 }
  258 
  259                 vcp = cvp->cv_connvc->cvc_vcc;
  260 
  261                 /*
  262                  * Validate SVC vpi.vci
  263                  */
  264                 if ( vcp->vc_type & VCC_SVC ) {
  265 
  266                         if (atm_dev_vcc_find(cup, vcp->vc_vpi, vcp->vc_vci,
  267                                         vcp->vc_type & (VCC_IN | VCC_OUT))
  268                                                 != cvp){
  269                                 log ( LOG_ERR,
  270                                   "atm_dev_lower: dup SVC (%d,%d) tok=%p\n",
  271                                         vcp->vc_vpi, vcp->vc_vci, tok );
  272                                 atm_cm_abort(cvp->cv_connvc, &atm_dev_cause);
  273                                 break;
  274                         }
  275                 }
  276 
  277                 /*
  278                  * Tell the device to open the VCC
  279                  */
  280                 cvp->cv_state = CVS_INITED;
  281                 s = splimp();
  282                 if ((*cup->cu_openvcc)(cup, cvp)) {
  283                         atm_cm_abort(cvp->cv_connvc, &atm_dev_cause);
  284                         (void) splx(s);
  285                         break;
  286                 }
  287                 (void) splx(s);
  288                 break;
  289 
  290         case CPCS_TERM: {
  291                 KBuffer         *m, *prev, *next;
  292                 int             *ip;
  293 
  294                 s = splimp();
  295 
  296                 /*
  297                  * Disconnect the VCC - ignore return code
  298                  */
  299                 if ((cvp->cv_state == CVS_INITED) || 
  300                     (cvp->cv_state == CVS_ACTIVE)) {
  301                         (void) (*cup->cu_closevcc)(cup, cvp);
  302                 }
  303                 cvp->cv_state = CVS_TERM;
  304 
  305                 /*
  306                  * Remove from interface list
  307                  */
  308                 UNLINK ( cvp, Cmn_vcc, cup->cu_vcc, cv_next );
  309 
  310                 /*
  311                  * Free any buffers from this VCC on the ATM interrupt queue
  312                  */
  313                 prev = NULL;
  314                 IF_LOCK(&atm_intrq);
  315                 for (m = atm_intrq.ifq_head; m; m = next) {
  316                         next = KB_QNEXT(m);
  317 
  318                         /*
  319                          * See if this entry is for the terminating VCC
  320                          */
  321                         KB_DATASTART(m, ip, int *);
  322                         ip++;
  323                         if (*ip == (intptr_t)cvp) {
  324                                 /*
  325                                  * Yep, so dequeue the entry
  326                                  */
  327                                 if (prev == NULL)
  328                                         atm_intrq.ifq_head = next;
  329                                 else
  330                                         KB_QNEXT(prev) = next;
  331 
  332                                 if (next == NULL)
  333                                         atm_intrq.ifq_tail = prev;
  334 
  335                                 atm_intrq.ifq_len--;
  336 
  337                                 /*
  338                                  * Free the unwanted buffers
  339                                  */
  340                                 KB_FREEALL(m);
  341                         } else {
  342                                 prev = m;
  343                         }
  344                 }
  345                 IF_UNLOCK(&atm_intrq);
  346                 (void) splx(s);
  347 
  348                 /*
  349                  * Free VCC resources
  350                  */
  351                 uma_zfree(cup->cu_vcc_zone, cvp);
  352                 break;
  353                 }
  354 
  355         case CPCS_UNITDATA_INV:
  356 
  357                 /*
  358                  * Sanity check
  359                  *
  360                  * Use temp state variable since we dont want to lock out
  361                  * interrupts, but initial VC activation interrupt may
  362                  * happen here, changing state somewhere in the middle.
  363                  */
  364                 state = cvp->cv_state;
  365                 if ((state != CVS_ACTIVE) && 
  366                     (state != CVS_INITED)) {
  367                         log ( LOG_ERR,
  368                             "atm_dev_lower: UNITDATA: tok=%p, state=%d\n",
  369                                 tok, state );
  370                         KB_FREEALL((KBuffer *)arg1);
  371                         break;
  372                 }
  373 
  374                 /*
  375                  * Send the packet to the interface's bpf if this vc has one.
  376                  */
  377                 if (cvcp->cvc_vcc != NULL && cvcp->cvc_vcc->vc_nif != NULL) {
  378                         struct ifnet *ifp =
  379                             (struct ifnet *)cvcp->cvc_vcc->vc_nif;
  380 
  381                         BPF_MTAP(ifp, (KBuffer *)arg1);
  382                 }
  383 
  384                 /*
  385                  * Hand the data off to the device
  386                  */
  387                 (*cup->cu_output)(cup, cvp, (KBuffer *)arg1);
  388 
  389                 break;
  390 
  391         case CPCS_UABORT_INV:
  392                 log ( LOG_ERR,
  393                     "atm_dev_lower: unimplemented stack cmd 0x%x, tok=%p\n",
  394                         cmd, tok );
  395                 break;
  396 
  397         default:
  398                 log ( LOG_ERR,
  399                         "atm_dev_lower: unknown stack cmd 0x%x, tok=%p\n",
  400                         cmd, tok );
  401 
  402         }
  403 
  404         return;
  405 }
  406 
  407 
  408 
  409 /*
  410  * Allocate kernel memory block
  411  * 
  412  * This function will allocate a kernel memory block of the type specified
  413  * in the flags parameter.  The returned address will point to a memory
  414  * block of the requested size and alignment.  The memory block will also 
  415  * be zeroed.  The alloc/free functions will manage/mask both the OS-specific 
  416  * kernel memory management requirements and the bookkeeping required to
  417  * deal with data alignment issues. 
  418  *
  419  * This function should not be called from interrupt level.
  420  *
  421  * Arguments:
  422  *      size    size of memory block to allocate
  423  *      align   data alignment requirement 
  424  *      flags   allocation flags (ATM_DEV_*)
  425  *
  426  * Returns:
  427  *      uaddr   pointer to aligned memory block
  428  *      NULL    unable to allocate memory
  429  *
  430  */
  431 void *         
  432 atm_dev_alloc(size, align, flags)
  433         u_int           size;
  434         u_int           align;
  435         u_int           flags;
  436 {
  437         Mem_blk         *mbp;
  438         Mem_ent         *mep;
  439         u_int           kalign, ksize;
  440         int             s, i;
  441 
  442         s = splimp();
  443 
  444         /*
  445          * Find a free Mem_ent
  446          */
  447         mep = NULL;
  448         for (mbp = atm_mem_head; mbp && mep == NULL; mbp = mbp->mb_next) {
  449                 for (i = 0; i < MEM_NMEMENT; i++) {
  450                         if (mbp->mb_mement[i].me_uaddr == NULL) {
  451                                 mep = &mbp->mb_mement[i];
  452                                 break;
  453                         }
  454                 }
  455         }
  456 
  457         /*
  458          * If there are no free Mem_ent's, then allocate a new Mem_blk
  459          * and link it into the chain
  460          */
  461         if (mep == NULL) {
  462                 mbp = malloc(sizeof(Mem_blk), M_DEVBUF, M_NOWAIT|M_ZERO);
  463                 if (mbp == NULL) {
  464                         log(LOG_ERR, "atm_dev_alloc: Mem_blk failure\n");
  465                         (void) splx(s);
  466                         return (NULL);
  467                 }
  468                 mbp->mb_next = atm_mem_head;
  469                 atm_mem_head = mbp;
  470                 mep = mbp->mb_mement;
  471         }
  472 
  473         /*
  474          * Now we need to get the kernel's allocation alignment minimum
  475          *
  476          * This is obviously very OS-specific stuff
  477          */
  478         kalign = MINALLOCSIZE;
  479 
  480         /*
  481          * Figure out how much memory we must allocate to satify the
  482          * user's size and alignment needs
  483          */
  484         if (align <= kalign)
  485                 ksize = size;
  486         else
  487                 ksize = size + align - kalign;
  488 
  489         /*
  490          * Finally, go get the memory
  491          */
  492         if (flags & ATM_DEV_NONCACHE) {
  493                 mep->me_kaddr = malloc(ksize, M_DEVBUF, M_NOWAIT);
  494         } else {
  495                 mep->me_kaddr = malloc(ksize, M_DEVBUF, M_NOWAIT);
  496         }
  497 
  498         if (mep->me_kaddr == NULL) {
  499                 log(LOG_ERR, "atm_dev_alloc: %skernel memory unavailable\n",
  500                         (flags & ATM_DEV_NONCACHE) ? "non-cacheable " : "");
  501                 (void) splx(s);
  502                 return (NULL);
  503         }
  504 
  505         /*
  506          * Calculate correct alignment address to pass back to user
  507          */
  508         mep->me_uaddr = (void *) roundup((uintptr_t)mep->me_kaddr, align);
  509         mep->me_ksize = ksize;
  510         mep->me_flags = flags;
  511 
  512         /*
  513          * Clear memory for user
  514          */
  515         bzero(mep->me_uaddr, size);
  516 
  517         ATM_DEBUG4("atm_dev_alloc: size=%d, align=%d, flags=%d, uaddr=%p\n", 
  518                 size, align, flags, mep->me_uaddr);
  519 
  520         (void) splx(s);
  521 
  522         return (mep->me_uaddr);
  523 }
  524 
  525 
  526 /*
  527  * Free kernel memory block
  528  * 
  529  * This function will free a kernel memory block previously allocated by
  530  * the atm_dev_alloc function.  
  531  *
  532  * This function should not be called from interrupt level.
  533  *
  534  * Arguments:
  535  *      uaddr   pointer to allocated aligned memory block
  536  *
  537  * Returns:
  538  *      none
  539  *
  540  */
  541 void
  542 atm_dev_free(uaddr)
  543         volatile void           *uaddr;
  544 {
  545         Mem_blk         *mbp;
  546         Mem_ent         *mep;
  547         int             s, i;
  548 
  549         ATM_DEBUG1("atm_dev_free: uaddr=%p\n", uaddr);
  550 
  551         s = splimp();
  552 
  553         /*
  554          * Protect ourselves...
  555          */
  556         if (uaddr == NULL)
  557                 panic("atm_dev_free: trying to free null address");
  558 
  559         /*
  560          * Find our associated entry
  561          */
  562         mep = NULL;
  563         for (mbp = atm_mem_head; mbp && mep == NULL; mbp = mbp->mb_next) {
  564                 for (i = 0; i < MEM_NMEMENT; i++) {
  565                         if (mbp->mb_mement[i].me_uaddr == uaddr) {
  566                                 mep = &mbp->mb_mement[i];
  567                                 break;
  568                         }
  569                 }
  570         }
  571 
  572         /*
  573          * If we didn't find our entry, then unceremoniously let the caller
  574          * know they screwed up (it certainly couldn't be a bug here...)
  575          */
  576         if (mep == NULL)
  577                 panic("atm_dev_free: trying to free unknown address");
  578         
  579         /*
  580          * Give the memory space back to the kernel
  581          */
  582         if (mep->me_flags & ATM_DEV_NONCACHE) {
  583                 free(mep->me_kaddr, M_DEVBUF);
  584         } else {
  585                 free(mep->me_kaddr, M_DEVBUF);
  586         }
  587 
  588         /*
  589          * Free our entry
  590          */
  591         mep->me_uaddr = NULL;
  592 
  593         (void) splx(s);
  594 
  595         return;
  596 }
  597 
  598 /*
  599  * Compress buffer chain
  600  * 
  601  * This function will compress a supplied buffer chain into a minimum number
  602  * of kernel buffers.  Typically, this function will be used because the
  603  * number of buffers in an output buffer chain is too large for a device's
  604  * DMA capabilities.  This should only be called as a last resort, since
  605  * all the data copying will surely kill any hopes of decent performance.
  606  *
  607  * Arguments:
  608  *      m       pointer to source buffer chain
  609  *
  610  * Returns:
  611  *      n       pointer to compressed buffer chain
  612  *
  613  */
  614 KBuffer *         
  615 atm_dev_compress(m)
  616         KBuffer         *m;
  617 {
  618         KBuffer         *n, *n0, **np;
  619         int             len, space;
  620         caddr_t         src, dst;
  621 
  622         n = n0 = NULL;
  623         np = &n0;
  624         dst = NULL;
  625         space = 0;
  626 
  627         /*
  628          * Copy each source buffer into compressed chain
  629          */
  630         while (m) {
  631 
  632                 if (space == 0) {
  633 
  634                         /*
  635                          * Allocate another buffer for compressed chain
  636                          */
  637                         KB_ALLOCEXT(n, ATM_DEV_CMPR_LG, KB_F_NOWAIT, KB_T_DATA);
  638                         if (n) {
  639                                 space = ATM_DEV_CMPR_LG;
  640                         } else {
  641                                 KB_ALLOC(n, ATM_DEV_CMPR_SM, KB_F_NOWAIT, 
  642                                         KB_T_DATA);
  643                                 if (n) {
  644                                         space = ATM_DEV_CMPR_SM;
  645                                 } else {
  646                                         /*
  647                                          * Unable to get any new buffers, so
  648                                          * just return the partially compressed
  649                                          * chain and hope...
  650                                          */
  651                                         *np = m;
  652                                         break;
  653                                 }
  654                         }
  655 
  656                         KB_HEADSET(n, 0);
  657                         KB_LEN(n) = 0;
  658                         KB_BFRSTART(n, dst, caddr_t);
  659 
  660                         *np = n;
  661                         np = &KB_NEXT(n);
  662                 }
  663 
  664                 /*
  665                  * Copy what we can from source buffer
  666                  */
  667                 len = MIN(space, KB_LEN(m));
  668                 KB_DATASTART(m, src, caddr_t);
  669                 bcopy(src, dst, len);
  670 
  671                 /*
  672                  * Adjust for copied data
  673                  */
  674                 dst += len;
  675                 space -= len;
  676 
  677                 KB_HEADADJ(m, -len);
  678                 KB_TAILADJ(n, len);
  679 
  680                 /*
  681                  * If we've exhausted our current source buffer, free it
  682                  * and move to the next one
  683                  */
  684                 if (KB_LEN(m) == 0) {
  685                         KB_FREEONE(m, m);
  686                 }
  687         }
  688 
  689         return (n0);
  690 }
  691 
  692 
  693 /*
  694  * Locate VCC entry
  695  * 
  696  * This function will return the VCC entry for a specified interface and
  697  * VPI/VCI value.
  698  *
  699  * Arguments:
  700  *      cup     pointer to interface unit structure
  701  *      vpi     VPI value
  702  *      vci     VCI value
  703  *      type    VCC type
  704  *
  705  * Returns:
  706  *      vcp     pointer to located VCC entry matching
  707  *      NULL    no VCC found
  708  *
  709  */
  710 Cmn_vcc *
  711 atm_dev_vcc_find(cup, vpi, vci, type)
  712         Cmn_unit        *cup;
  713         u_int           vpi;
  714         u_int           vci;
  715         u_int           type;
  716 {
  717         Cmn_vcc         *cvp;
  718         int             s = splnet();
  719 
  720         /*
  721          * Go find VCC
  722          *
  723          * (Probably should stick in a hash table some time)
  724          */
  725         for (cvp = cup->cu_vcc; cvp; cvp = cvp->cv_next) {
  726                 struct vccb     *vcp;
  727 
  728                 vcp = cvp->cv_connvc->cvc_vcc;
  729                 if ((vcp->vc_vci == vci) && (vcp->vc_vpi == vpi) && 
  730                     ((vcp->vc_type & type) == type))
  731                         break;
  732         }
  733 
  734         (void) splx(s);
  735         return (cvp);
  736 }
  737 
  738 
  739 #ifdef notdef
  740 /*
  741  * Module unloading notification
  742  * 
  743  * This function must be called just prior to unloading the module from 
  744  * memory.  All allocated memory will be freed here and anything else that
  745  * needs cleaning up.
  746  *
  747  * Arguments:
  748  *      none
  749  *
  750  * Returns:
  751  *      none
  752  *
  753  */
  754 void
  755 atm_unload()
  756 {
  757         Mem_blk         *mbp;
  758         Mem_ent         *mep;
  759         int             s, i;
  760 
  761         s = splimp();
  762 
  763         /*
  764          * Free up all of our memory management storage
  765          */
  766         while (mbp = atm_mem_head) {
  767 
  768                 /*
  769                  * Make sure users have freed up all of their memory
  770                  */
  771                 for (i = 0; i < MEM_NMEMENT; i++) {
  772                         if (mbp->mb_mement[i].me_uaddr != NULL) {
  773                                 panic("atm_unload: unfreed memory");
  774                         }
  775                 }
  776 
  777                 atm_mem_head = mbp->mb_next;
  778 
  779                 /*
  780                  * Hand this block back to the kernel
  781                  */
  782                 free((caddr_t)mbp, M_DEVBUF);
  783         }
  784 
  785         (void) splx(s);
  786 
  787         return;
  788 }
  789 #endif  /* notdef */
  790 
  791 
  792 /*
  793  * Print a PDU
  794  * 
  795  * Arguments:
  796  *      cup     pointer to device unit
  797  *      cvp     pointer to VCC control block
  798  *      m       pointer to pdu buffer chain
  799  *      msg     pointer to message string
  800  *
  801  * Returns:
  802  *      none
  803  *
  804  */
  805 void
  806 atm_dev_pdu_print(const Cmn_unit *cup, const Cmn_vcc *cvp,
  807     const KBuffer *m, const char *msg)
  808 {
  809         char            buf[128];
  810 
  811         snprintf(buf, sizeof(buf), "%s vcc=(%d,%d)", msg, 
  812                 cvp->cv_connvc->cvc_vcc->vc_vpi, 
  813                 cvp->cv_connvc->cvc_vcc->vc_vci);
  814 
  815         atm_pdu_print(m, buf);
  816 }

Cache object: 5d8db5c352e6c1aa32c0272403ea38a0


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