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

Cache object: 0291c703798ad413349d84b3e8450b48


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