netBufLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:72k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* netBufLib.c - network buffer library */
  2. /* Copyright 1984 - 2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01r,07may02,kbw  man page edits
  8. 01q,15oct01,rae  merge from truestack ver 01w, base 01n (SPR #65195 etc.)
  9. 01p,08feb01,kbw  fixing a man page format problem
  10. 01o,07feb01,spm  removed unused garbage collection code; updated documentation
  11. 01n,26aug98,fle  doc : fixed a proc header trouble with netPoolInit
  12. 01m,25aug98,n_s  M_WAIT will only call _pNetBufCollect 1 time. spr #22104
  13. 01l,12dec97,kbw  making minor man page fixes
  14. 01k,11dec97,vin  added netMblkOffsetToBufCopy part of SPR 9563.
  15. 01j,08dec97,vin  added netMblkChainDup() SPR 9966.
  16. 01i,05dec97,vin  changed netMblkClFree to netMblkFree in netTupleGet()
  17. 01h,03dec97,vin  added netTupleGet() SPR 9955, added some unsupported routines 
  18. 01g,13nov97,vin  code clean up.
  19. 01f,25oct97,kbw  making minor man page fixes
  20. 01e,08oct97,vin  corrected clBlkFree()
  21. 01d,06oct97,vin  fixed a man page.
  22. 01c,30sep97,vin  changed MSIZE to M_BLK_SZ.
  23. 01b,19sep97,vin  added cluster Blks, fixed bugs, removed reference count
  24.  pointers.
  25. 01a,08aug97,vin  written.
  26. */
  27. /*
  28. DESCRIPTION
  29. This library contains routines that you can use to organize and maintain
  30. a memory pool that consists of pools of `mBlk' structures, pools of `clBlk'
  31. structures, and pools of clusters.  The `mBlk' and `clBlk' structures
  32. are used to manage the clusters.  The clusters are containers for the data
  33. described by the `mBlk' and `clBlk' structures.
  34. These structures and the various routines of this library constitute a
  35. buffering API that has been designed to meet the needs both of network 
  36. protocols and network device drivers.
  37.  
  38. The `mBlk' structure is the primary vehicle for passing data between
  39. a network driver and a protocol.  However, the `mBlk' structure must
  40. first be properly joined with a `clBlk' structure that was previously
  41. joined with a cluster.  Thus, the actual vehicle for passing data is
  42. not merely an `mBlk' structure but an `mBlk'-`clBlk'-cluster
  43. construct.
  44.  
  45. To use this feature, include the following component:
  46. INCLUDE_NETWRS_NETBUFLIB
  47. INCLUDE FILES: netBufLib.h
  48. INTERNAL
  49.  ------------
  50.         |mBlk       |
  51.         |manages    |
  52. |clusterBlk |
  53.         |           |
  54. |     |
  55.         ------------|    -------------
  56.                  |clBlk      |
  57.          |manages the|
  58.  |cluster.   |
  59.          |clRefCnt=1 |
  60.   ------------|
  61.            
  62.     
  63.        ------------|
  64.       |Cluster     |
  65.        |     |
  66.        |     |
  67.        |     |
  68.        |     |
  69.        |-------------
  70. Two mBlks sharing the same cluster:
  71. -----------------------------------
  72.                                                  
  73.          -----------|                      |-----------|
  74.         | mBlk      |                      | mBlk      |
  75.         |           |                      |           |
  76.         |           |                      |           |
  77.         |           |                      |           |
  78.         |           |                      |           |
  79.         |-----------                      /-----------|
  80.                                          /    
  81.                                         /
  82.                                        /
  83.                         |------------|/
  84.                          | clBlk      |               
  85.                          |            |                
  86.                          |clRefCnt = 2|                
  87.                          |            |                
  88.                          |            |                
  89.                          |------------                
  90.                                                       
  91.                                        |---------------|
  92.                                        | cluster       |
  93.                                        |               |
  94.                                        |               |
  95.                                        |---------------|
  96. */
  97. /* includes */
  98. #include "vxWorks.h"
  99. #include "stdlib.h"
  100. #include "intLib.h"
  101. #include "string.h"
  102. #include "semaphore.h"
  103. #include "memLib.h"
  104. #include "errnoLib.h"
  105. #include "netBufLib.h"
  106. #include "private/semLibP.h"
  107. #include "memPartLib.h"
  108. /* Virtual Stack Support */
  109. #ifdef VIRTUAL_STACK
  110. #include "netinet/vsLib.h"
  111. #endif
  112. /* defines */
  113. #undef NETBUF_DEBUG
  114. #ifdef NETBUF_DEBUG
  115. #include "logLib.h"
  116. #endif /* NETBUF_DEBUG */
  117. #define FROM_KHEAP      1   /* let _poolInit() use KHEAP_ALLOC */
  118. #define FROM_HOMEPDHEAP 0   /* let _poolInit() use calloc() */ 
  119. /* global */
  120. VOIDFUNCPTR  _pNetBufCollect = NULL; /* protocol specific routine */
  121. /* extern */
  122. IMPORT int ffsMsb ();
  123. /* forward declarations */
  124. LOCAL STATUS _poolInit (NET_POOL_ID pNetPool, M_CL_CONFIG *
  125.                                    pMclBlkConfig, CL_DESC * pClDescTbl,
  126.                                    int clDescTblNumEnt, BOOL fromKheap);
  127. LOCAL M_BLK_ID  _mBlkCarve (NET_POOL_ID pNetPool, int num,
  128.                                     char * pool);
  129. LOCAL CL_BLK_ID  _clBlkCarve (int num, char * pool);
  130. LOCAL CL_BUF_ID  _clPoolCarve (CL_POOL_ID pClPool, int num, int clSize,
  131.                                       char * pool);
  132. LOCAL STATUS  _memPoolInit (int num, int unitSize, int headerSize,
  133.                                       char * memArea);
  134. LOCAL void _mBlkFree (NET_POOL_ID pNetPool, M_BLK_ID pMblk);
  135. LOCAL void  _clBlkFree (CL_BLK_ID pClBlk);
  136. LOCAL void  _clFree (NET_POOL_ID pNetPool, char * pClBuf);
  137. LOCAL M_BLK_ID  _mBlkClFree (NET_POOL_ID pNetPool, M_BLK_ID pMblk);
  138. LOCAL M_BLK_ID  _mBlkGet (NET_POOL_ID pNetPool, int canWait,
  139.                                   UCHAR type);
  140. LOCAL CL_BLK_ID _clBlkGet (NET_POOL_ID pNetPool, int canWait);
  141. LOCAL char *   _clusterGet (NET_POOL_ID pNetPool, CL_POOL_ID pClPool);
  142. LOCAL STATUS  _mClGet (NET_POOL_ID pNetPool, M_BLK_ID pMblk,
  143.                                  int bufSize, int canWait, BOOL bestFit);
  144. LOCAL CL_POOL_ID  _clPoolIdGet (NET_POOL_ID pNetPool, int bufSize,
  145.                                       BOOL bestFit);
  146. LOCAL POOL_FUNC dfltFuncTbl = /* default pool function table */
  147.     {
  148.     _poolInit,
  149.     _mBlkFree,
  150.     _clBlkFree,
  151.     _clFree,
  152.     _mBlkClFree,
  153.     _mBlkGet,
  154.     _clBlkGet,
  155.     _clusterGet,
  156.     _mClGet,
  157.     _clPoolIdGet,
  158.     };
  159. /*
  160.  * this is a global pointer to a function table provided as a back door
  161.  * for users who want to use a different allocation scheme for defaults
  162.  * By initializing this _pNetPoolFuncTbl at runtime before initialization of
  163.  * the network stack, one can change the default function table.  The system
  164.  * pools use the default function table.
  165.  */
  166.    
  167. POOL_FUNC *  _pNetPoolFuncTbl = &dfltFuncTbl;
  168. /*******************************************************************************
  169. *  
  170. * _poolInit - initialize the net pool
  171. *
  172. * This function initializes a net pool
  173. *
  174. * RETURNS: OK or ERROR.
  175. *
  176. * NOMANUAL
  177. */
  178. LOCAL STATUS _poolInit
  179.     (
  180.     NET_POOL_ID pNetPool, /* pointer to a net pool */
  181.     M_CL_CONFIG * pMclBlkConfig, /* pointer to mBlk,clBlk config */
  182.     CL_DESC * pClDescTbl, /* pointer to cluster desc table */
  183.     int clDescTblNumEnt, /* number of cluster desc entries */
  184.     BOOL                fromKheap       /* 1:KHEAP_ALLOC  0:malloc/calloc */
  185.     )
  186.     {
  187.     int  ix; /* index variable */
  188.     int  iy;  /* index variable */
  189.     int  log2Size; /* cluster size to the base 2 */
  190.     CL_DESC *  pClDesc; /* pointer to the cluster descriptor */
  191.     CL_POOL *  pClPool;  /* pointer to the cluster pool */
  192.     char *  memArea;
  193.     bzero ((char *) pNetPool->clTbl, sizeof (pNetPool->clTbl));
  194.     if (fromKheap)
  195. {
  196. if ((pNetPool->pPoolStat = (M_STAT *) KHEAP_ALLOC(sizeof (M_STAT))) == NULL)
  197.     return (ERROR);
  198. bzero ((char *)pNetPool->pPoolStat, sizeof (M_STAT));
  199. }
  200.     else {
  201. if ((pNetPool->pPoolStat = (M_STAT *) calloc (1, sizeof (M_STAT))) == NULL)
  202.     return (ERROR);
  203.         }
  204.     pNetPool->pmBlkHead = NULL;
  205.     if (pMclBlkConfig != NULL) /* if mbuf config is specified */
  206.         {
  207.         if (pMclBlkConfig->memSize <
  208.             ((pMclBlkConfig->mBlkNum *  (M_BLK_SZ + sizeof(long))) +
  209.              (pMclBlkConfig->clBlkNum * CL_BLK_SZ)))
  210.             {
  211.             errno = S_netBufLib_MEMSIZE_INVALID;
  212.             goto poolInitError;
  213.             }
  214.         /* initialize the memory pool */
  215.         if (_memPoolInit (pMclBlkConfig->mBlkNum, M_BLK_SZ, sizeof(void *),
  216.                           pMclBlkConfig->memArea
  217.                           ) != OK)
  218.             {
  219.             goto poolInitError;
  220.             }
  221.         /* carve up the mBlk pool */
  222.         pNetPool->pmBlkHead = _mBlkCarve (
  223.           pNetPool,
  224.                                          pMclBlkConfig->mBlkNum,
  225.                                          pMclBlkConfig->memArea
  226.                                          );
  227.         /* increment free mBlks  and number of mBlks */
  228.         pNetPool->mBlkCnt       = pMclBlkConfig->mBlkNum;
  229.         pNetPool->mBlkFree       = pMclBlkConfig->mBlkNum;
  230.         pNetPool->pPoolStat->mTypes [MT_FREE] = pMclBlkConfig->mBlkNum;
  231.         pNetPool->pPoolStat->mNum        = pMclBlkConfig->mBlkNum;
  232.         memArea = (char * )((int)pMclBlkConfig->memArea +
  233.                             (pMclBlkConfig->mBlkNum * (M_BLK_SZ +
  234.                                                        sizeof(long))));
  235.         if (pMclBlkConfig->clBlkNum > 0)
  236.             {
  237.             /* initialize the memory pool */
  238.             if (_memPoolInit (pMclBlkConfig->clBlkNum, CL_BLK_SZ, 0, memArea)
  239.                 != OK)
  240.                 goto poolInitError;
  241.             pNetPool->pClBlkHead = _clBlkCarve (
  242.                                                pMclBlkConfig->clBlkNum,
  243.                                                memArea
  244.                                                );
  245.             if (pNetPool->pClBlkHead == NULL)
  246.                 goto poolInitError;
  247.             }
  248.         }
  249.     /* initialize clusters */
  250.     pNetPool->clMask   = 0;
  251.     pNetPool->clLg2Max = 0;
  252.     pNetPool->clLg2Min = 0;
  253.     for (pClDesc = pClDescTbl, ix = 0 ; (pClDesc != NULL) &&
  254.              (pClDesc->clNum > 0) && (ix < clDescTblNumEnt); ix++, pClDesc++)
  255. {
  256. /* range check cluster type */
  257. if ((pClDesc->clSize < CL_SIZE_MIN) || (pClDesc->clSize > CL_SIZE_MAX))
  258.             {
  259. #ifdef NETBUF_DEBUG
  260.     logMsg ("poolInit -- Invalid cluster typen", 0, 0, 0, 0, 0, 0);
  261. #endif /* NETBUF_DEBUG */
  262.             errno = S_netBufLib_CLSIZE_INVALID;
  263.             goto poolInitError;
  264.             }
  265. log2Size   = SIZE_TO_LOG2(pClDesc->clSize);
  266. pNetPool->clMask |= CL_LOG2_TO_CL_SIZE(log2Size); /* set the mask */
  267. if ((pNetPool->clLg2Max == 0) && (pNetPool->clLg2Min == 0))
  268.     {
  269.     pNetPool->clLg2Min  = log2Size;
  270.     pNetPool->clLg2Max  = log2Size;
  271.     }
  272. pNetPool->clLg2Max  = max(log2Size, pNetPool->clLg2Max);
  273. pNetPool->clLg2Min  = min(log2Size, pNetPool->clLg2Min);
  274.         pNetPool->clSizeMax = CL_LOG2_TO_CL_SIZE(pNetPool->clLg2Max);
  275.         pNetPool->clSizeMin = CL_LOG2_TO_CL_SIZE(pNetPool->clLg2Min);
  276. if (fromKheap)
  277.     {
  278.     if ((pClPool = (CL_POOL *) KHEAP_ALLOC(sizeof(CL_POOL))) == NULL)
  279. {
  280. #ifdef NETBUF_DEBUG
  281. logMsg ("poolInit -- cluster pool allocationn", 0, 0, 0, 0, 0, 0);
  282. #endif /* NETBUF_DEBUG */
  283. errno = S_netBufLib_NO_SYSTEM_MEMORY;
  284. goto poolInitError;
  285. }
  286.     bzero ((char *)pClPool, sizeof (CL_POOL));
  287.     }
  288. else {
  289.     if ((pClPool = (CL_POOL *) calloc (1, sizeof(CL_POOL))) == NULL)
  290. {
  291. #ifdef NETBUF_DEBUG
  292. logMsg ("poolInit -- cluster pool allocationn", 0, 0, 0, 0, 0, 0);
  293. #endif /* NETBUF_DEBUG */
  294. errno = S_netBufLib_NO_SYSTEM_MEMORY;
  295. goto poolInitError;
  296. }
  297.     }
  298.         pNetPool->clTbl [CL_LOG2_TO_CL_INDEX(log2Size)] = pClPool;
  299. for (iy = (log2Size - 1);
  300.     ((!(pNetPool->clMask & CL_LOG2_TO_CL_SIZE(iy))) &&
  301.      (CL_LOG2_TO_CL_INDEX(iy) >= CL_INDX_MIN))  ; iy--)
  302.     {
  303.     pNetPool->clTbl [CL_LOG2_TO_CL_INDEX(iy)] = pClPool;
  304.     }
  305. pClPool->clSize   = pClDesc->clSize;
  306.         pClPool->clLg2   = log2Size;
  307.         pClPool->pNetPool = pNetPool; /* initialize the back pointer */
  308.         if (pClDesc->memSize < (pClDesc->clNum * (pClDesc->clSize +
  309.                                                   sizeof(int))))
  310.             {
  311.             errno = S_netBufLib_MEMSIZE_INVALID;
  312.             goto poolInitError;
  313.             }
  314.         if (_memPoolInit (pClDesc->clNum, pClDesc->clSize,
  315.                           sizeof (void *) , pClDesc->memArea) != OK)
  316.             goto poolInitError;
  317.         pClPool->pClHead = _clPoolCarve (pClPool, pClDesc->clNum,
  318.                                          pClDesc->clSize, pClDesc->memArea);
  319.         if (pClPool->pClHead == NULL)
  320.             {
  321.             goto poolInitError;
  322.             }
  323.         pClPool->clNum    = pClDesc->clNum;
  324.         pClPool->clNumFree = pClDesc->clNum;
  325. }
  326.     return (OK);
  327.     poolInitError:
  328.     netPoolDelete (pNetPool);
  329.     return (ERROR);
  330.     }
  331. /*******************************************************************************
  332. *
  333. * _mBlkCarve - carve up the mBlk pool.
  334. *
  335. * This function carves the the mBlks from a pre allocated pool.
  336. *
  337. * RETURNS: M_BLK_ID or NULL.
  338. *
  339. * NOMANUAL
  340. */
  341. LOCAL M_BLK_ID _mBlkCarve
  342.     (
  343.     NET_POOL_ID pNetPool, /* pointer to net pool */
  344.     int  num, /* number of units to allocate */
  345.     char * pool /* pre allocated memory area */
  346.     )
  347.     {
  348.     M_BLK_ID pMblk = NULL;
  349.     int  ix;
  350.     int size; /* size of each unit */
  351.     M_BLK_ID * ppMblk;
  352.     size = M_BLK_SZ + sizeof (void *); /* accomodate for netPoolId */
  353.     ppMblk = &pMblk;
  354.     for (ix = 0; ix < num; ++ix)
  355. {
  356. *ppMblk   = (M_BLK_ID) (pool + sizeof (void *));
  357.         *((NET_POOL_ID *)(pool)) = pNetPool;
  358. (*ppMblk)->mBlkHdr.mType = MT_FREE;
  359.         ppMblk   = &((*ppMblk)->mBlkHdr.mNext);
  360. pool   += size;
  361. }
  362.     return (pMblk);
  363.     }
  364. /*******************************************************************************
  365. *
  366. * _clBlkCarve - carve up the clBlk pool.
  367. *
  368. * This function carves the the clBlks from a pre allocated pool.
  369. *
  370. * RETURNS: CL_BLK_ID or NULL.
  371. *
  372. * NOMANUAL
  373. */
  374. LOCAL CL_BLK_ID _clBlkCarve
  375.     (
  376.     int  num, /* number of units to allocate */
  377.     char * pool /* pre allocated memory area */
  378.     )
  379.     {
  380.     CL_BLK_ID pClBlk = NULL;
  381.     int  ix;
  382.     CL_BLK_ID * ppClBlk;
  383.     ppClBlk = &pClBlk;
  384.     for (ix = 0; ix < num; ++ix)
  385. {
  386. *ppClBlk = (CL_BLK_ID) (pool);
  387.         ppClBlk  = &((*ppClBlk)->clNode.pClBlkNext);
  388. pool   += CL_BLK_SZ;
  389. }
  390.     return (pClBlk);
  391.     }
  392. /*******************************************************************************
  393. *
  394. * _clPoolCarve - carve up the cluster pool
  395. *
  396. * This function carves the clusters from a pre allocated pool.
  397. * Each cluster maintains an 4 byte header info.  This header info contains
  398. * a place to hold the pointer to the cluster pool.
  399. * This header info is prepended to the cluster buffer
  400. * and is hidden from the user.  The header info is used at the time of
  401. * freeing the cluster.  This function returns the pointer the cluster buffer
  402. * chain.
  403. *
  404. * RETURNS: CL_BUF_ID or NULL.
  405. *
  406. * NOMANUAL
  407. */
  408. LOCAL CL_BUF_ID _clPoolCarve
  409.     (
  410.     CL_POOL_ID pClPool, /* pointer to the cluster pool */
  411.     int  num, /* number of units to allocate */
  412.     int clSize, /* cluster size */
  413.     char * pool /* pre allocated memory area */
  414.     )
  415.     {
  416.     CL_BUF_ID pClBuf = NULL;  /* pointer to cluster buffer */
  417.     FAST int  ix; /* counter */
  418.     CL_BUF_ID * ppClBuf; /* ptr to ptr to cluster buffer */
  419.     clSize += sizeof (void *); /* make space for pool pointer */
  420.     ppClBuf = &pClBuf;
  421.     for (ix = 0; ix < num; ++ix)
  422. {
  423. *ppClBuf  = (CL_BUF_ID) (pool + sizeof (void *));
  424.         *((CL_POOL_ID *) (pool)) = pClPool;
  425.         ppClBuf   = &((*ppClBuf)->pClNext);
  426. pool   += clSize;
  427. }
  428.     return (pClBuf);
  429.     }
  430. /*******************************************************************************
  431. *
  432. * _memPoolInit - initialize the memory
  433. *
  434. * This function initialized the memory passed to it.
  435. *
  436. * RETURNS: OK or ERROR.
  437. *
  438. * NOMANUAL
  439. */
  440. LOCAL STATUS _memPoolInit
  441.     (
  442.     int  num, /* number of units to allocate */
  443.     int unitSize, /* size of each unit */
  444.     int headerSize, /* hidden header size */
  445.     char * memArea /* pre allocated memory area */
  446.     )
  447.     {
  448.     if (((int) unitSize & ~(sizeof (void *) - 1)) != unitSize )
  449.         {
  450.         errno = S_netBufLib_MEMSIZE_UNALIGNED;
  451.         return (ERROR); /* unaligned size */
  452.         }
  453.     unitSize += headerSize; /* adjust for NET_POOL_ID */
  454.     if (memArea == NULL)
  455.         {
  456.         errno = S_netBufLib_MEMAREA_INVALID;
  457.         return (ERROR);
  458.         }
  459.     if (((int) memArea & ~(sizeof (void *) - 1)) != (int)memArea )
  460.         {
  461.         errno = S_netBufLib_MEM_UNALIGNED;
  462.         return (ERROR); /* unaligned memory */
  463.         }
  464.     bzero ((char *)memArea, (num * unitSize));
  465.     return (OK);
  466.     }
  467. /*******************************************************************************
  468. *
  469. * _mBlkFree - free the given mBlk
  470. *
  471. * This function frees the given mBlk and returns it to the mBlk pool.
  472. *
  473. * RETURNS: N/A
  474. *
  475. * NOMANUAL
  476. */
  477. LOCAL void _mBlkFree
  478.     (
  479.     NET_POOL_ID pNetPool, /* pointer to the net pool */
  480.     M_BLK_ID   pMblk /* mBlk to free */
  481.     )
  482.     {
  483.     FAST int ms;
  484.     pMblk->mBlkHdr.mNextPkt  = NULL;
  485.     ms = intLock ();
  486.     pNetPool->pPoolStat->mTypes [pMblk->mBlkHdr.mType]--;
  487.     pNetPool->pPoolStat->mTypes [MT_FREE]++;
  488.     pMblk->mBlkHdr.mType  = MT_FREE;
  489.     pMblk->mBlkHdr.mNext  = pNetPool->pmBlkHead;
  490.     pNetPool->pmBlkHead  = pMblk; /* add the mbuf to the free list */
  491.     intUnlock (ms);
  492.     }
  493. /*******************************************************************************
  494. *
  495. * _clBlkFree - free the given cluster Blk
  496. *
  497. * This function frees the given clBlk and returns it to the cluster Blk pool.
  498. *
  499. * RETURNS: N/A
  500. *
  501. * NOMANUAL
  502. */
  503. LOCAL void _clBlkFree
  504.     (
  505.     CL_BLK_ID   pClBlk /* clBlk to free */
  506.     )
  507.     {
  508.     FAST int level;
  509.     CL_POOL_ID pClPool;
  510.     CL_BUF_ID pClBuf;
  511.     NET_POOL_ID pNetPool; /* pointer to the net pool */
  512.     
  513.     pNetPool = pClBlk->pNetPool;
  514.     pClBuf   = (CL_BUF_ID)pClBlk->clNode.pClBuf;
  515.     level = intLock (); /* lock interrupts briefly */
  516.     if (pClBuf == NULL) /* no cluster attached */
  517.         goto returnClBlk;
  518.     else if (--(pClBlk->clRefCnt) == 0)
  519.         {
  520.         if (pClBlk->pClFreeRtn != NULL)
  521.             { /* call the free routine if associated with one */
  522.             intUnlock (level);
  523.     (*pClBlk->pClFreeRtn) (pClBlk->clFreeArg1, pClBlk->clFreeArg2,
  524.                                    pClBlk->clFreeArg3);
  525.             level = intLock ();
  526.             }
  527.         else
  528.             {
  529.             /* return the cluster to its pool */
  530.             pClPool  = CL_BUF_TO_CL_POOL (pClBuf);
  531.             pClBuf->pClNext  = pClPool->pClHead;
  532.             pClPool->pClHead = pClBuf;
  533.             /* update mask */
  534.             pClPool->pNetPool->clMask  |= CL_LOG2_TO_CL_SIZE(pClPool->clLg2);
  535.             pClPool->clNumFree++;
  536.     }
  537.         goto returnClBlk;
  538. }
  539.     else
  540.         goto clBlkFreeEnd;
  541.     returnClBlk:
  542.     /* free the cluster blk and add it to the free list */
  543.     pClBlk->clNode.pClBlkNext  = pNetPool->pClBlkHead;
  544.     pNetPool->pClBlkHead  = pClBlk;
  545.     clBlkFreeEnd:
  546.     intUnlock (level);
  547.     }
  548. /*******************************************************************************
  549. *
  550. * _clFree - free a  cluster of a given size.
  551. *
  552. * This function frees a cluster of given size in a net pool
  553. *
  554. * RETURNS: N/A
  555. *
  556. * NOMANUAL
  557. */
  558. LOCAL void _clFree
  559.     (
  560.     NET_POOL_ID pNetPool, /* pointer to the net pool */
  561.     char *  pClBuf /* pointer to the cluster buffer */
  562.     )
  563.     {
  564.     CL_POOL_ID pClPool;
  565.     FAST int level;
  566.     pClPool = CL_BUF_TO_CL_POOL (pClBuf);
  567.     level = intLock ();
  568.     ((CL_BUF_ID)pClBuf)->pClNext = pClPool->pClHead;
  569.     pClPool->pClHead  = (CL_BUF_ID)pClBuf;
  570.     /* update mask */
  571.     pClPool->pNetPool->clMask  |= CL_LOG2_TO_CL_SIZE(pClPool->clLg2);
  572.     pClPool->clNumFree++;
  573.     intUnlock (level);
  574.     }
  575. /*******************************************************************************
  576. *
  577. * _mBlkClFree - free an mBlk/cluster pair.
  578. *
  579. * This function frees a mBlk/cluster pair.  This function returns a pointer
  580. * to the next mBlk which is connected to the current one.  This routine will
  581. * free the cluster only if it is attached to the mBlk.
  582. *
  583. * RETURNS: M_BLK_ID or NULL.
  584. *
  585. * NOMANUAL
  586. */
  587. LOCAL M_BLK_ID _mBlkClFree
  588.     (
  589.     NET_POOL_ID pNetPool, /* pointer to net pool */
  590.     M_BLK_ID  pMblk /* pointer to the mBlk */
  591.     )
  592.     {
  593.     M_BLK_ID pMblkNext; /* pointer to the next mBlk */
  594.     if (pMblk->mBlkHdr.mType == MT_FREE)
  595.         {
  596. #ifdef NETBUF_DEBUG
  597.         logMsg ("mBlkClFree -- Invalid mBlkn", 0, 0, 0, 0, 0, 0);
  598. #endif /* NETBUF_DEBUG */
  599.         errno = S_netBufLib_MBLK_INVALID;
  600.         return (NULL);
  601.         }
  602.     pMblkNext = pMblk->mBlkHdr.mNext;
  603.     /* free the cluster first if it is attached to the mBlk */
  604.     if (M_HASCL(pMblk))
  605.         netClBlkFree (pMblk->pClBlk->pNetPool, pMblk->pClBlk);
  606.     _mBlkFree (pNetPool, pMblk);  /* free the mBlk */
  607.     return (pMblkNext);
  608.     }
  609. /*******************************************************************************
  610. *
  611. * _mBlkGet - get a free mBlk
  612. *
  613. * This routine returns a free mBlk if one is available. If the <canWait>
  614. * parameter is set to M_WAIT and an mBlk is not immediately available, the
  615. * routine repeats the allocation attempt after calling any installed garbage
  616. * collection routine.
  617. *
  618. * RETURNS: M_BLK_ID or NULL if none available
  619. *
  620. * NOMANUAL
  621. */
  622. LOCAL M_BLK_ID _mBlkGet
  623.     (
  624.     NET_POOL_ID pNetPool, /* pointer to the net pool */
  625.     int canWait, /* M_WAIT/M_DONTWAIT */
  626.     UCHAR type /* mBlk type */
  627.     )
  628.     {
  629.     M_BLK_ID   pMblk = NULL; /* pointer to mbuf */
  630.     int  level; /* level of interrupt */
  631.     reTry:
  632.     level = intLock(); /* lock interrupts very briefly */
  633.     if ((pMblk = pNetPool->pmBlkHead) != NULL)
  634.         {
  635.         pNetPool->pmBlkHead = pMblk->mBlkHdr.mNext;
  636.         pNetPool->pPoolStat->mTypes [MT_FREE]--;
  637.         pNetPool->pPoolStat->mTypes [type]++;
  638.         intUnlock (level);  /* unlock interrupts */
  639.         if (pMblk->mBlkHdr.mType != MT_FREE)
  640.             {
  641. #ifdef NETBUF_DEBUG
  642.             logMsg("mBlkGet free error:n", 0, 0, 0, 0, 0, 0);
  643. #endif /* NETBUF_DEBUG */
  644.             errno = S_netBufLib_MBLK_INVALID;
  645.             return (NULL);
  646.             }
  647.         pMblk->mBlkHdr.mType = type;
  648.         pMblk->mBlkHdr.mNext  = NULL;
  649.         pMblk->mBlkHdr.mNextPkt = NULL;
  650.         pMblk->mBlkHdr.mFlags  = 0;
  651.         }
  652.     else /* if (canWait != M_ISR) */
  653.         {
  654.         if (canWait == M_WAIT)
  655.             {
  656.             if (_pNetBufCollect)
  657.                 {
  658.                 intUnlock (level); /* unlock interrupts */
  659.                 (*_pNetBufCollect) (pNetPool->pPoolStat);
  660. canWait = M_DONTWAIT;
  661.                 goto reTry;
  662.                 }
  663.             }
  664.         pNetPool->pPoolStat->mDrops++;
  665.         intUnlock (level);
  666. errnoSet (S_netBufLib_NO_POOL_MEMORY);
  667.         }
  668.     return (pMblk);
  669.     }
  670. /*******************************************************************************
  671. *
  672. * _clBlkGet - get a free clBlk
  673. *
  674. * This routine returns a free clBlk if one is available. If the <canWait>
  675. * parameter is set to M_WAIT and a clBlk is not immediately available, the
  676. * routine repeats the allocation attempt after calling any installed garbage
  677. * collection routine.
  678. *
  679. * RETURNS: CL_BLK_ID or NULL.
  680. *
  681. * NOMANUAL
  682. */
  683. LOCAL CL_BLK_ID _clBlkGet
  684.     (
  685.     NET_POOL_ID pNetPool, /* pointer to the net pool */
  686.     int canWait /* M_WAIT/M_DONTWAIT */
  687.     )
  688.     {
  689.     CL_BLK_ID   pClBlk = NULL; /* pointer to mbuf */
  690.     int  level; /* level of interrupt */
  691.     reTry:
  692.     level = intLock(); /* lock interrupts very briefly */
  693.     if ((pClBlk = pNetPool->pClBlkHead) != NULL)
  694.         {
  695.         pNetPool->pClBlkHead = pClBlk->clNode.pClBlkNext;
  696.         intUnlock (level);  /* unlock interrupts */
  697.         pClBlk->clNode.pClBuf = NULL;
  698.         pClBlk->pClFreeRtn    = NULL;
  699.         pClBlk->clRefCnt      = 0;
  700.         pClBlk->pNetPool      = pNetPool;  /* netPool originator */
  701.         }
  702.     else /* if (canWait != M_ISR) */
  703.         {
  704.         if (canWait == M_WAIT)
  705.             {
  706.             if (_pNetBufCollect)
  707.                 {
  708.                 intUnlock (level); /* unlock interrupts */
  709.                 (*_pNetBufCollect) (pNetPool->pPoolStat);
  710. canWait = M_DONTWAIT;
  711.                 goto reTry;
  712.                 }
  713.             }
  714.         intUnlock (level);
  715.         errnoSet (S_netBufLib_NO_POOL_MEMORY);
  716. }
  717.     return (pClBlk);
  718.     }
  719. /*******************************************************************************
  720. *
  721. * _clusterGet - get a new cluster of a given cluster pool.
  722. *
  723. * This function returns a cluster given a pool pointer.  The reference count
  724. * for the cluster is incremented.
  725. *
  726. * RETURNS: pointer to a cluster or NULL
  727. *
  728. * NOMANUAL
  729. */
  730. LOCAL char * _clusterGet
  731.     (
  732.     NET_POOL_ID pNetPool, /* pointer to the net pool */
  733.     CL_POOL_ID  pClPool  /* ptr to the cluster pool */
  734.     )
  735.     {
  736.     int level; /* level of interrupt */
  737.     CL_BUF_ID pClBuf; /* ptr to the cluster buffer */
  738.     level = intLock ();  /* lock interrupts briefly */
  739.     if (pClPool->pClHead == NULL) /* return if no buffers */
  740.         {
  741.         intUnlock (level);
  742.         return (NULL);
  743.         }
  744.     pClBuf = pClPool->pClHead; /* update the head */
  745.     if ((pClPool->pClHead = pClBuf->pClNext) == NULL)
  746.         { /* update the pool Mask */
  747.         pNetPool->clMask &= ~(CL_LOG2_TO_CL_SIZE(pClPool->clLg2));
  748.         }
  749.     pClPool->clNumFree--;  /* decrement the free count */
  750.     pClPool->clUsage++; /* increment the usage count */
  751.     intUnlock (level);
  752.     return ((char *)pClBuf);
  753.     }
  754. /*******************************************************************************
  755. *
  756. * mClGet - get a new mBlk/cluster pair.
  757. *
  758. * This function gets a free cluster from the NET_POOL and joins it with
  759. * the mBlk passed to it.  An mBlk must be pre allocated and passed to this
  760. * function.
  761. *
  762. * RETURNS: OK or ERROR.
  763. *
  764. * NOMANUAL
  765. */
  766. LOCAL STATUS _mClGet
  767.     (
  768.     NET_POOL_ID pNetPool, /* pointer to the net pool */
  769.     M_BLK_ID   pMblk,  /* mBlk to embed the cluster in */
  770.     int bufSize, /* size of the buffer to get */
  771.     int canWait, /* wait or dontwait */
  772.     BOOL bestFit /* TRUE/FALSE */
  773.     )
  774.     {
  775.     int log2Size; /* size of cluster to the base 2 */
  776.     CL_POOL_ID  pClPool;  /* pointer to the cluster pool */
  777.     CL_BUF_ID pClBuf = NULL;  /* pointer to the cluster buffer */
  778.     CL_BLK_ID pClBlk = NULL;  /* pointer to the cluster blk */
  779.     FAST int  ms;  /* integer for level */
  780.     /* check pMblk */
  781.     if ((pMblk == NULL) || ((pClBlk = _clBlkGet (pNetPool, canWait)) == NULL))
  782. goto mClGetError;
  783.     /* check the boundary conditions */
  784.     if (bufSize > pNetPool->clSizeMax)
  785. {
  786. if (bestFit)
  787.             {
  788.             errno = S_netBufLib_CLSIZE_INVALID;
  789.     goto mClGetError;
  790.             }
  791. else
  792.     log2Size = pNetPool->clLg2Max;
  793. }
  794.     else if (bufSize < pNetPool->clSizeMin)
  795. log2Size = pNetPool->clLg2Min;
  796.     else
  797. {
  798. log2Size = SIZE_TO_LOG2(bufSize);
  799. if (bufSize > CL_LOG2_TO_CL_SIZE(log2Size))
  800.     log2Size++;
  801. }
  802.     /* get the appropriate pool pointer */
  803.     if ((pClPool = pNetPool->clTbl [CL_LOG2_TO_CL_INDEX (log2Size)]) == NULL)
  804. {
  805. #ifdef NETBUF_DEBUG
  806. logMsg ("mClGet: Invalid cluster typen", 0, 0, 0, 0, 0, 0);
  807. #endif /* NETBUF_DEBUG */
  808.         errno = S_netBufLib_CLSIZE_INVALID;
  809. goto mClGetError;
  810. }
  811.     reTry:
  812.     ms = intLock();  /* lock interrupts briefly */
  813.     if (pClPool->pClHead == NULL)
  814.         {
  815.         /* pool has max clusters, find best fit or close fit */
  816.         if (pNetPool->clMask >= CL_LOG2_TO_CL_SIZE(pClPool->clLg2))
  817.             { /* first fetch a cluster with a closest bigger size */
  818.             bufSize  = CL_LOG2_TO_CL_SIZE(pClPool->clLg2);
  819.             log2Size = pClPool->clLg2;
  820.             while (bufSize <= CL_SIZE_MAX)
  821.                 {
  822.                 if (pNetPool->clMask & bufSize)
  823.                     {
  824.                     pClPool = pNetPool->clTbl [CL_LOG2_TO_CL_INDEX (log2Size)];
  825.                     break;
  826.                     }
  827.                 bufSize <<= 1;
  828.                 log2Size ++;
  829.                 }
  830.             }
  831.         /* if close fit then find closest lower size */
  832.         else if (!bestFit && pNetPool->clMask)
  833.             {
  834.             pClPool = pNetPool->clTbl [CL_SIZE_TO_CL_INDEX(pNetPool->clMask)];
  835.             }
  836.         else if (canWait == M_WAIT) /* want for buffers */
  837.             {
  838.             if (_pNetBufCollect)
  839.                 {
  840.                 intUnlock (ms);
  841.                 (*_pNetBufCollect) (pNetPool->pPoolStat);
  842. canWait = M_DONTWAIT;
  843.                 goto reTry;
  844.                 }
  845.             }
  846.         }
  847.     if ((pClBuf = pClPool->pClHead))
  848. {
  849. /* if this is the last cluster available set the mask */
  850. if ((pClPool->pClHead = pClBuf->pClNext) == NULL)
  851.             {
  852.     pNetPool->clMask &= ~(CL_LOG2_TO_CL_SIZE(pClPool->clLg2));
  853.             }
  854. pClPool->clNumFree--;
  855. pClPool->clUsage++;
  856.         intUnlock (ms);
  857. }
  858.     else
  859. {
  860. pNetPool->pPoolStat->mDrops++; /* no. times failed to find space */
  861.         intUnlock (ms);
  862. errnoSet (S_netBufLib_NO_POOL_MEMORY);
  863. goto mClGetError;
  864. }
  865.     pMblk->mBlkHdr.mData  = (caddr_t) pClBuf;
  866.     pMblk->mBlkHdr.mFlags |= M_EXT;
  867.     pClBlk->clNode.pClBuf = (caddr_t) pClBuf;
  868.     pClBlk->clSize   = pClPool->clSize;
  869.     pClBlk->pClFreeRtn   = NULL;
  870.     pClBlk->clRefCnt   = 1;
  871.     pMblk->pClBlk    = pClBlk;
  872.     return (OK);  /* return OK */
  873.     mClGetError:
  874.     if (pClBlk != NULL)
  875.         _clBlkFree (pClBlk);
  876.     return (ERROR);  /* return ERROR */
  877.     }
  878. /*******************************************************************************
  879. *
  880. * clPoolIdGet - return a pool Id for a given cluster Size
  881. *
  882. * This function returns a poolID for a given cluster Size.
  883. * If this returns NULL then the corresponding pool has not been initialized.
  884. *
  885. * RETURNS: CL_POOL_ID or NULL.
  886. *
  887. * NOMANUAL
  888. */
  889. LOCAL CL_POOL_ID _clPoolIdGet
  890.     (
  891.     NET_POOL_ID pNetPool, /* pointer to the net pool */
  892.     int  bufSize, /* size of the buffer */
  893.     BOOL bestFit /* TRUE/FALSE */
  894.     )
  895.     {
  896.     int log2Size;
  897.     if (bufSize > pNetPool->clSizeMax)
  898. {
  899. log2Size = pNetPool->clLg2Max;
  900. if (bestFit)
  901.     return (NULL);
  902. }
  903.     else if (bufSize < pNetPool->clSizeMin)
  904.         {
  905. log2Size = pNetPool->clLg2Min;
  906.         }
  907.     else
  908. {
  909. log2Size = SIZE_TO_LOG2(bufSize);
  910. if (bufSize > CL_LOG2_TO_CL_SIZE(log2Size))
  911.     log2Size++;
  912. }
  913.     return (pNetPool->clTbl [CL_LOG2_TO_CL_INDEX(log2Size)]);
  914.     }
  915. /*******************************************************************************
  916. *
  917. * netBufLibInit - initialize netBufLib
  918. *
  919. * This routine executes during system startup if INCLUDE_NETWORK is defined
  920. * when the image is built. It links the network buffer library into the image.
  921. *
  922. * RETURNS: OK or ERROR.
  923. *
  924. */
  925. STATUS netBufLibInit (void)
  926.     {
  927.     return (OK);
  928.     }
  929. /*******************************************************************************
  930. *
  931. * netPoolInit - initialize a netBufLib-managed memory pool
  932. *
  933. * Call this routine to set up a netBufLib-managed memory
  934. * pool.  Within this pool, netPoolInit() organizes several sub-pools: one
  935. * for `mBlk' structures, one for `clBlk' structures, and as many cluster
  936. * sub-pools are there are cluster sizes.  As input, this routine expects
  937. * the following parameters:
  938. * .IP <pNetPool> 15
  939. * Expects a NET_POOL_ID that points to a previously allocated NET_POOL
  940. * structure.  You need not initialize any values in this structure.  That
  941. * is handled by netPoolInit().
  942. * .IP <pMclBlkConfig>
  943. * Expects a pointer to a previously allocated and initialized M_CL_CONFIG
  944. * structure.  Within this structure, you must provide four
  945. * values: 'mBlkNum', a count of `mBlk' structures; 'clBlkNum', a count
  946. * of `clBlk' structures; 'memArea', a pointer to an area of memory
  947. * that can contain all the `mBlk' and `clBlk' structures; and 'memSize', 
  948. * the size of that memory area.  For example, you can set up an M_CL_CONFIG 
  949. * structure as follows:
  950. * .CS
  951. *     M_CL_CONFIG mClBlkConfig = /@ mBlk, clBlk configuration table @/
  952. *         {
  953. *         mBlkNum     clBlkNum        memArea         memSize
  954. *         ----------  ----            -------         -------
  955. *         400,        245,            0xfe000000,     21260
  956. *         };
  957. * .CE
  958. * You can 
  959. * calculate the 'memArea' and 'memSize' values.  Such code could first 
  960. * define a table as shown above, but set both 'memArea' and 'memSize' 
  961. * as follows:
  962. * .CS
  963. * mClBlkConfig.memSize = (mClBlkConfig.mBlkNum * (M_BLK_SZ + sizeof(long))) +
  964. *                        (mClBlkConfig.clBlkNum * CL_BLK_SZ);
  965. * .CE
  966. * You can set the memArea value to a pointer to private memory, or you can
  967. * reserve the memory with a call to malloc().  For example:
  968. * .CS
  969. *     mClBlkConfig.memArea = malloc(mClBlkConfig.memSize);
  970. * .CE
  971. *
  972. * The netBufLib.h file defines M_BLK_SZ as:
  973. * .CS
  974. *     sizeof(struct mBlk)
  975. * .CE
  976. * Currently, this evaluates to 32 bytes.  Likewise, this file 
  977. * defines CL_BLK_SZ as:
  978. * .CS 
  979. *     sizeof(struct clBlk)
  980. * .CE
  981. * Currently, this evaluates to 32 bytes. 
  982. *
  983. * When choosing values for 'mBlkNum' and 'clBlkNum', remember that you need 
  984. * as many `clBlk' structures as you have clusters (data buffers).  You also 
  985. * need at least as many `mBlk' structures as you have `clBlk' structures, but 
  986. * you will most likely need more. 
  987. * That is because netBufLib shares buffers by letting multiple `mBlk' 
  988. * structures join to the same `clBlk' and thus to its underlying cluster.  
  989. * The `clBlk' keeps a count of the number of `mBlk' structures that 
  990. * reference it.  
  991. *
  992. * .IP <pClDescTbl>
  993. * Expects a pointer to a table of previously allocated and initialized CL_DESC
  994. * structures.  Each structure in this table describes a single cluster pool.
  995. * You need a dedicated cluster pool for each cluster size you want to support.
  996. * Within each CL_DESC structure, you must provide four values: 'clusterSize',
  997. * the size of a cluster in this cluster pool; 'num', the number of clusters 
  998. * in this cluster pool; 'memArea', a pointer to an area of memory that can 
  999. * contain all the clusters; and 'memSize', the size of that memory area.
  1000. * Thus, if you need to support six different cluster sizes, this parameter
  1001. * must point to a table containing six CL_DESC structures.  For example,
  1002. * consider the following:
  1003. * .CS
  1004. *     CL_DESC clDescTbl [] =   /@ cluster descriptor table @/
  1005. *         {
  1006. *         /@
  1007. *         clusterSize        num     memArea         memSize
  1008. *         ----------         ----    -------         -------
  1009. *         @/
  1010. *         {64,               100,    0x10000,        6800},
  1011. *         {128,              50,     0x20000,        6600},
  1012. *         {256,              50,     0x30000,        13000},
  1013. *         {512,              25,     0x40000,        12900},
  1014. *         {1024,             10,     0x50000,        10280},
  1015. *         {2048,             10,     0x60000,        20520}
  1016. *         };
  1017. * .CE
  1018. * As with the 'memArea' and 'memSize' members in the M_CL_CONFIG structure,
  1019. * you can set these members of the CL_DESC structures by calculation after
  1020. * you create the table.  The formula would be as follows:
  1021. * .CS
  1022. *     clDescTbl[n].memSize = 
  1023. *         (clDescTbl[n].num * (clDescTbl[n].clusterSize + sizeof(long)));
  1024. * .CE
  1025. * The 'memArea' member can point to a private memory area that you know to be 
  1026. * available for storing clusters, or you can use malloc().
  1027. * .CS
  1028. *     clDescTbl[n].memArea =  malloc( clDescTbl[n].memSize ); 
  1029. * .CE
  1030. *
  1031. * Valid cluster sizes range from 64 bytes to 65536 bytes.  If there are 
  1032. * multiple cluster pools, valid sizes are further restricted to powers of
  1033. * two (for example, 64, 128, 256, and so on).  If there is only one cluster 
  1034. * pool (as is often the case for the memory pool specific to a single 
  1035. * device driver), there is no power of two restriction.  Thus, the cluster 
  1036. * can be of any size between 64 bytes and 65536 bytes on 4-byte alignment.  A 
  1037. * typical buffer size for Ethernet devices is 1514 bytes.  However, because
  1038. * a cluster size requires a 4-byte alignment, the cluster size for this 
  1039. * Ethernet buffer would have to be increased to at least 1516 bytes.
  1040. * .IP <clDescTblNumEnt>
  1041. * Expects a count of the elements in the CL_DESC table referenced by 
  1042. * the <pClDescTbl> parameter.  This is a count of the number of cluster
  1043. * pools.  You can get this value using the NELEMENTS macro defined  
  1044. * in vxWorks.h.  For example:
  1045. * .CS
  1046. *     int clDescTblNumEnt = (NELEMENTS(clDescTbl));
  1047. * .CE
  1048. * .IP <pFuncTbl>
  1049. * Expects a NULL or a pointer to a function table.  This table contains 
  1050. * pointers to the functions used to manage the buffers in this memory pool.  
  1051. * Using a NULL for this parameter tells netBufLib to use its default function 
  1052. * table.  If you opt for the default function table, every `mBlk' and 
  1053. * every cluster is prepended by a 4-byte header (which is why the size 
  1054. * calculations above for clusters and `mBlk' structures contained an 
  1055. * extra 'sizeof(long)').  However, users need not concern themselves 
  1056. * with this header when accessing these buffers.  The returned pointers 
  1057. * from functions such as netClusterGet() return pointers to the start of
  1058. * data, which is just after the header.  
  1059. * .LP
  1060. * Assuming you have set up the configuration tables as shown above, a 
  1061. * typical call to netPoolInit() would be as follows:
  1062. * .CS
  1063. *     int clDescTblNumEnt = (NELEMENTS(clDescTbl));
  1064. *     NET_POOL  netPool;
  1065. *     NET_POOL_ID  pNetPool = &netPool;
  1066. *
  1067. *     if (netPoolInit (pNetPool, &mClBlkConfig, &clDescTbl [0], clDescTblNumEnt,
  1068. *         NULL) != OK)
  1069. *         return (ERROR);
  1070. *.CE
  1071. *
  1072. * VXWORKS AE PROTECTION DOMAINS
  1073. * Under VxWorks AE, access to the contents of a memory pool is limited to 
  1074. * the protection domain within which you made the netPoolInit() call that 
  1075. * created the pool.  In addition, all parameters to a netPoolInit() call 
  1076. * must be valid within the protection domain from which you make the call. 
  1077. * This restriction does not apply under non-AE versions of VxWorks.  
  1078. *
  1079. * RETURNS: OK or ERROR.
  1080. *
  1081. * ERRNO:
  1082. *  S_netBufLib_MEMSIZE_INVALID
  1083. *  S_netBufLib_CLSIZE_INVALID
  1084. *  S_netBufLib_NO_SYSTEM_MEMORY
  1085. *  S_netBufLib_MEM_UNALIGNED
  1086. *  S_netBufLib_MEMSIZE_UNALIGNED
  1087. *  S_netBufLib_MEMAREA_INVALID
  1088. *
  1089. * SEE ALSO: netPoolDelete()
  1090. */
  1091. STATUS netPoolInit
  1092.     (
  1093.     NET_POOL_ID pNetPool,  /* pointer to a net pool */
  1094.     M_CL_CONFIG * pMclBlkConfig,  /* pointer to a mBlk configuration */
  1095.     CL_DESC * pClDescTbl,  /* pointer to cluster desc table */
  1096.     int clDescTblNumEnt, /* number of cluster desc entries */
  1097.     POOL_FUNC * pFuncTbl  /* pointer to pool function table */
  1098.     )
  1099.     {
  1100.     if (pNetPool == NULL)
  1101.         return (ERROR);
  1102.     if (pFuncTbl != NULL)
  1103.         pNetPool->pFuncTbl = pFuncTbl;
  1104.     else
  1105.         pNetPool->pFuncTbl = _pNetPoolFuncTbl; /* default func table */
  1106.     return (poolInit (pNetPool, pMclBlkConfig, pClDescTbl,
  1107.         clDescTblNumEnt, FROM_HOMEPDHEAP)); /* allocate from the homePD's heap */
  1108.     }
  1109. /*******************************************************************************
  1110. *
  1111. * netPoolKheapInit - kernel heap version of netPoolInit()
  1112. * This initializes a netBufLib-managed memory pool from Kernel heap.
  1113. * See netPoolInit() for more detail.
  1114. *
  1115. * VXWORKS AE PROTECTION DOMAINS
  1116. * Under VxWorks AE, you can call this function from within the kernel 
  1117. * protection domain only.  In addition, all arguments to this function can  
  1118. * reference only that data which is valid in the kernel protection domain. 
  1119. * This restriction does not apply under non-AE versions of VxWorks.  
  1120. *
  1121. * RETURNS: OK or ERROR.
  1122. *
  1123. * ERRNO:
  1124. *  N/A
  1125. *
  1126. * SEE ALSO: netPoolInit(), netPoolDelete()
  1127. */
  1128. STATUS netPoolKheapInit
  1129.     (
  1130.     NET_POOL_ID pNetPool,  /* pointer to a net pool */
  1131.     M_CL_CONFIG * pMclBlkConfig,  /* pointer to a mBlk configuration */
  1132.     CL_DESC * pClDescTbl,  /* pointer to cluster desc table */
  1133.     int clDescTblNumEnt, /* number of cluster desc entries */
  1134.     POOL_FUNC * pFuncTbl  /* pointer to pool function table */
  1135.     )
  1136.     {
  1137.     if (pNetPool == NULL)
  1138.         return (ERROR);
  1139.     if (pFuncTbl != NULL)
  1140.         pNetPool->pFuncTbl = pFuncTbl;
  1141.     else
  1142.         pNetPool->pFuncTbl = _pNetPoolFuncTbl; /* default func table */
  1143.     return (poolInit (pNetPool, pMclBlkConfig, pClDescTbl,
  1144.         clDescTblNumEnt, FROM_KHEAP)); /* allocate from kernel heap */
  1145.     }
  1146. /*******************************************************************************
  1147. *
  1148. * netPoolDelete - delete a memory pool
  1149. *
  1150. * This routine deletes the specified netBufLib-managed memory pool.
  1151. *
  1152. * VXWORKS AE PROTECTION DOMAINS
  1153. * Under VxWorks AE, you can call this function from within the kernel 
  1154. * protection domain only.  In addition, all arguments to this function can  
  1155. * reference only that data which is valid in the kernel protection domain. 
  1156. * This restriction does not apply under non-AE versions of VxWorks.  
  1157. *
  1158. * RETURNS: OK or ERROR.
  1159. *
  1160. * ERRNO:
  1161. *  S_netBufLib_NETPOOL_INVALID
  1162. */
  1163. STATUS netPoolDelete
  1164.     (
  1165.     NET_POOL_ID pNetPool /* pointer to a net pool */
  1166.     )
  1167.     {
  1168.     int ix; /* index variable */
  1169.     int iy; /* index variable */
  1170.     CL_POOL_ID pClPool; /* pointer to the pool */
  1171.     if (pNetPool->pPoolStat == NULL)
  1172.         {
  1173.         errno = S_netBufLib_NETPOOL_INVALID;
  1174.         return (ERROR); /* pool already deleted */
  1175.         }
  1176.     free (pNetPool->pPoolStat);
  1177.     for (ix = 0; ix < CL_TBL_SIZE; ix++)
  1178.         {
  1179.         pClPool = pNetPool->clTbl [ix];
  1180.         if (pClPool != NULL)
  1181.             {
  1182.             for (iy = ix + 1; iy < CL_TBL_SIZE; iy++)
  1183.                 {
  1184.                 if (pClPool == pNetPool->clTbl [iy])
  1185.                     pNetPool->clTbl [iy] = NULL;
  1186.                 }
  1187.             free (pClPool);
  1188.             }
  1189.         }
  1190.     bzero ((char *)pNetPool, sizeof(NET_POOL)); /* zero the structure */
  1191.     return (OK);
  1192.     }
  1193. /*******************************************************************************
  1194. *
  1195. * netMblkFree - free an `mBlk' back to its memory pool
  1196. *
  1197. * This routine frees the specified `mBlk' back to the specified memory pool.
  1198. *
  1199. * VXWORKS AE PROTECTION DOMAINS
  1200. * Under VxWorks AE, you can call this function from within the kernel 
  1201. * protection domain only.  In addition, all arguments to this function can  
  1202. * reference only that data which is valid in the kernel protection domain. 
  1203. * This restriction does not apply under non-AE versions of VxWorks.  
  1204. *
  1205. * RETURNS: N/A
  1206. */
  1207. void netMblkFree
  1208.     (
  1209.     NET_POOL_ID pNetPool, /* pointer to the net pool */
  1210.     M_BLK_ID   pMblk /* mBlk to free */
  1211.     )
  1212.     {
  1213.     if (pNetPool == NULL || pNetPool->pFuncTbl == NULL ||
  1214.         pNetPool->pFuncTbl->pMblkFreeRtn == NULL)
  1215.         return;
  1216.     (*pNetPool->pFuncTbl->pMblkFreeRtn) (pNetPool, pMblk);
  1217.     }
  1218. /*******************************************************************************
  1219. *
  1220. * netClBlkFree - free a `clBlk'-cluster construct back to the memory pool
  1221. *
  1222. * This routine decrements the reference counter in the specified `clBlk'. 
  1223. * If the reference count falls to zero, this routine frees both the `clBlk'
  1224. * and its associated cluster back to the specified memory pool.
  1225. *
  1226. * VXWORKS AE PROTECTION DOMAINS
  1227. * Under VxWorks AE, you can call this function from within the kernel 
  1228. * protection domain only.  In addition, all arguments to this function can  
  1229. * reference only that data which is valid in the kernel protection domain. 
  1230. * This restriction does not apply under non-AE versions of VxWorks.  
  1231. *
  1232. * RETURNS: N/A
  1233. */
  1234. void netClBlkFree
  1235.     (
  1236.     NET_POOL_ID pNetPool, /* pointer to the net pool */
  1237.     CL_BLK_ID   pClBlk /* pointer to the clBlk to free */
  1238.     )
  1239.     {
  1240.     pNetPool  = pClBlk->pNetPool;
  1241.     
  1242.     if (pNetPool == NULL || pNetPool->pFuncTbl == NULL ||
  1243.         pNetPool->pFuncTbl->pClBlkFreeRtn == NULL)
  1244.         return;
  1245.     (*pNetPool->pFuncTbl->pClBlkFreeRtn) (pClBlk);
  1246.     }
  1247. /*******************************************************************************
  1248. *
  1249. * netClFree - free a cluster back to the memory pool
  1250. *
  1251. * This routine returns the specified cluster buffer back to the specified
  1252. * memory pool.  
  1253. * VXWORKS AE PROTECTION DOMAINS
  1254. * Under VxWorks AE, you can call this function from within the kernel 
  1255. * protection domain only.  In addition, all arguments to this function can  
  1256. * reference only that data which is valid in the kernel protection domain. 
  1257. * This restriction does not apply under non-AE versions of VxWorks.  
  1258. *
  1259. * RETURNS: N/A
  1260. */
  1261. void netClFree
  1262.     (
  1263.     NET_POOL_ID pNetPool, /* pointer to the net pool */
  1264.     UCHAR *  pClBuf /* pointer to the cluster buffer */
  1265.     )
  1266.     {
  1267.     if (pNetPool == NULL || pNetPool->pFuncTbl == NULL ||
  1268.         pNetPool->pFuncTbl->pClFreeRtn == NULL)
  1269.         return;
  1270.     (*pNetPool->pFuncTbl->pClFreeRtn) (pNetPool, pClBuf);
  1271.     }
  1272. /*******************************************************************************
  1273. *
  1274. * netMblkClFree - free an `mBlk'-`clBlk'-cluster construct
  1275. *
  1276. * For the specified `mBlk'-`clBlk'-cluster construct, this routine
  1277. * frees the `mBlk' back to the specified memory pool.  It also decrements 
  1278. * the reference count in the `clBlk' structure.  If the reference count 
  1279. * falls to zero, no other `mBlk' structure reference this `clBlk'.  In that 
  1280. * case, this routine also frees the `clBlk' structure and its associated 
  1281. * cluster back to the specified memory pool.  
  1282. *
  1283. * VXWORKS AE PROTECTION DOMAINS
  1284. * Under VxWorks AE, you can call this function from within the kernel 
  1285. * protection domain only.  In addition, all arguments to this function can  
  1286. * reference only that data which is valid in the kernel protection domain. 
  1287. * Likewise, the returned ID is valid in the kernel protection domain only.
  1288. * This restriction does not apply under non-AE versions of VxWorks.  
  1289. *
  1290. * RETURNS
  1291. * If the specified `mBlk' was part of an `mBlk' chain, this routine returns 
  1292. * a pointer to the next `mBlk'.  Otherwise, it returns a NULL.
  1293. *
  1294. * ERRNO:
  1295. *  S_netBufLib_MBLK_INVALID
  1296. */
  1297. M_BLK_ID netMblkClFree
  1298.     (
  1299.     M_BLK_ID  pMblk /* pointer to the mBlk */
  1300.     )
  1301.     {
  1302.     NET_POOL_ID  pNetPool;
  1303.     if (pMblk == NULL)
  1304.         return (NULL);
  1305.     pNetPool = MBLK_TO_NET_POOL(pMblk);
  1306.     return ((*pNetPool->pFuncTbl->pMblkClFreeRtn) (pNetPool, pMblk));
  1307.     }
  1308. /*******************************************************************************
  1309. *
  1310. * netMblkClChainFree - free a chain of `mBlk'-`clBlk'-cluster constructs
  1311. *
  1312. * For the specified chain of `mBlk'-`clBlk'-cluster constructs, this 
  1313. * routine frees all the `mBlk' structures back to the specified memory pool.  
  1314. * It also decrements the reference count in all the `clBlk' structures.  If 
  1315. * the reference count in a `clBlk' falls to zero, this routine also frees 
  1316. * that `clBlk' and its associated cluster back to the specified memory pool. 
  1317. *
  1318. * VXWORKS AE PROTECTION DOMAINS
  1319. * Under VxWorks AE, you can call this function from within the kernel 
  1320. * protection domain only.  In addition, all arguments to this function can  
  1321. * reference only that data which is valid in the kernel protection domain. 
  1322. * This restriction does not apply under non-AE versions of VxWorks.  
  1323. *
  1324. * RETURNS: N/A
  1325. *
  1326. * ERRNO:
  1327. *  S_netBufLib_MBLK_INVALID
  1328. */
  1329. void netMblkClChainFree
  1330.     (
  1331.     M_BLK_ID  pMblk /* pointer to the mBlk */
  1332.     )
  1333.     {
  1334.     NET_POOL_ID  pNetPool;
  1335.     while (pMblk != NULL)
  1336.         {
  1337.         pNetPool = MBLK_TO_NET_POOL(pMblk);
  1338.         pMblk   = (*pNetPool->pFuncTbl->pMblkClFreeRtn) (pNetPool, pMblk);
  1339.         }
  1340.     }
  1341. /*******************************************************************************
  1342. *
  1343. * netMblkGet - get an `mBlk' from a memory pool
  1344. *
  1345. * This routine allocates an `mBlk' from the specified memory pool, if
  1346. * available.
  1347. *
  1348. * .IP <pNetPool> 9
  1349. * Expects a pointer to the pool from which you want an `mBlk'.
  1350. * .IP <canWait>
  1351. * Expects either M_WAIT or M_DONTWAIT.  If no 'mBlk' is immediately available,
  1352. * the M_WAIT value allows this routine to repeat the allocation attempt after
  1353. * performing garbage collection. It omits these steps when the M_DONTWAIT
  1354. * value is used.
  1355. * .IP <type>
  1356. * Expects the type value that you want to associate with the returned `mBlk'.
  1357. * .LP
  1358. *
  1359. * VXWORKS AE PROTECTION DOMAINS
  1360. * Under VxWorks AE, you can call this function from within the kernel 
  1361. * protection domain only.  In addition, all arguments to this function can  
  1362. * reference only that data which is valid in the kernel protection domain. 
  1363. * Likewise, the returned ID is valid in the kernel protection domain only.
  1364. * This restriction does not apply under non-AE versions of VxWorks.  
  1365. *
  1366. * RETURNS
  1367. * M_BLK_ID or NULL if no `mBlk' is available.
  1368. *
  1369. * ERRNO:
  1370. *  S_netBufLib_MBLK_INVALID
  1371. */
  1372. M_BLK_ID netMblkGet
  1373.     (
  1374.     NET_POOL_ID pNetPool, /* pointer to the net pool */
  1375.     int canWait, /* M_WAIT/M_DONTWAIT */
  1376.     UCHAR type /* mBlk type */
  1377.     )
  1378.     {
  1379.     if (pNetPool == NULL || pNetPool->pFuncTbl == NULL ||
  1380.         pNetPool->pFuncTbl->pMblkGetRtn == NULL)
  1381.         return (NULL);
  1382.     return ((*pNetPool->pFuncTbl->pMblkGetRtn) (pNetPool, canWait, type));
  1383.     }
  1384. /*******************************************************************************
  1385. *
  1386. * netClBlkGet - get a `clBlk'
  1387. *
  1388. * This routine gets a `clBlk' from the specified memory pool.
  1389. * .IP <pNetPool> 9
  1390. * Expects a pointer to the pool from which you want a `clBlk'.
  1391. * .IP <canWait>
  1392. * Expects either M_WAIT or M_DONTWAIT.  If no 'clBlk' is immediately available,
  1393. * the M_WAIT value allows this routine to repeat the allocation attempt after
  1394. * performing garbage collection. It omits these steps when the M_DONTWAIT
  1395. * value is used.
  1396. *
  1397. * VXWORKS AE PROTECTION DOMAINS
  1398. * Under VxWorks AE, you can call this function from within the kernel 
  1399. * protection domain only.  In addition, all arguments to this function can  
  1400. * reference only that data which is valid in the kernel protection domain. 
  1401. * Likewise, the returned ID is valid in the kernel protection domain only.
  1402. * This restriction does not apply under non-AE versions of VxWorks.  
  1403. *
  1404. * RETURNS: CL_BLK_ID or a NULL if no `clBlk' was available.
  1405. */
  1406. CL_BLK_ID netClBlkGet
  1407.     (
  1408.     NET_POOL_ID pNetPool, /* pointer to the net pool */
  1409.     int canWait /* M_WAIT/M_DONTWAIT */
  1410.     )
  1411.     {
  1412.     if (pNetPool == NULL || pNetPool->pFuncTbl == NULL ||
  1413.         pNetPool->pFuncTbl->pClBlkGetRtn == NULL)
  1414.         return (NULL);
  1415.     return ((*pNetPool->pFuncTbl->pClBlkGetRtn) (pNetPool, canWait));
  1416.     }
  1417. /*******************************************************************************
  1418. *
  1419. * netClusterGet - get a cluster from the specified cluster pool
  1420. *
  1421. * This routine gets a cluster from the specified cluster pool <pClPool> 
  1422. * within the specified memory pool <pNetPool>. 
  1423. *
  1424. * VXWORKS AE PROTECTION DOMAINS
  1425. * Under VxWorks AE, you can call this function from within the kernel 
  1426. * protection domain only.  In addition, all arguments to this function can  
  1427. * reference only that data which is valid in the kernel protection domain. 
  1428. * Likewise, the returned ID is valid in the kernel protection domain only.
  1429. * This restriction does not apply under non-AE versions of VxWorks.  
  1430. *
  1431. * RETURNS
  1432. * This routine returns a character pointer to a cluster buffer or NULL
  1433. * if none was available.
  1434. *
  1435. */
  1436. char * netClusterGet
  1437.     (
  1438.     NET_POOL_ID pNetPool, /* pointer to the net pool */
  1439.     CL_POOL_ID  pClPool  /* ptr to the cluster pool */
  1440.     )
  1441.     {
  1442.     if (pNetPool == NULL || pNetPool->pFuncTbl == NULL ||
  1443.         pNetPool->pFuncTbl->pClGetRtn == NULL)
  1444.         return (NULL);
  1445.     return ((*pNetPool->pFuncTbl->pClGetRtn) (pNetPool, pClPool));
  1446.     }
  1447. /*******************************************************************************
  1448. *
  1449. * netMblkClGet - get a `clBlk'-cluster and join it to the specified `mBlk'
  1450. *
  1451. * This routine gets a `clBlk'-cluster pair from the specified memory pool
  1452. * and joins it to the specified `mBlk' structure.  The `mBlk'-`clBlk'-cluster
  1453. * triplet it produces is the basic structure for handling data at all layers
  1454. * of the network stack.
  1455. *
  1456. * .IP <pNetPool> 9
  1457. * Expects a pointer to the memory pool from which you want to get a 
  1458. * free `clBlk'-cluster pair.
  1459. * .IP <pMbkl>
  1460. * Expects a pointer to the `mBlk' structure (previously allocated) to which 
  1461. * you want to join the retrieved `clBlk'-cluster pair.  
  1462. * .IP <bufSize>
  1463. * Expects the size, in bytes, of the cluster in the `clBlk'-cluster pair.  
  1464. * .IP <canWait>
  1465. * Expects either M_WAIT or M_DONTWAIT.  If either item is not immediately
  1466. * available, the M_WAIT value allows this routine to repeat the allocation
  1467. * attempt after performing garbage collection. It omits those steps when the
  1468. * M_DONTWAIT value is used.
  1469. * .IP <bestFit>
  1470. * Expects either TRUE or FALSE.  If <bestFit> is TRUE and a cluster of the 
  1471. * exact size is unavailable, this routine gets a larger cluster (if
  1472. * available).  If <bestFit> is FALSE and an exact size cluster is unavailable, 
  1473. * this routine gets either a smaller or a larger cluster (depending 
  1474. * on what is available).  Otherwise, it returns immediately with an ERROR value.
  1475. * For memory pools containing only one cluster size, <bestFit> should always
  1476. * be set to FALSE.
  1477. *
  1478. * VXWORKS AE PROTECTION DOMAINS
  1479. * Under VxWorks AE, you can call this function from within the kernel 
  1480. * protection domain only.  In addition, all arguments to this function can  
  1481. * reference only that data which is valid in the kernel protection domain. 
  1482. * This restriction does not apply under non-AE versions of VxWorks.  
  1483. *
  1484. * .SH "RETURNS"
  1485. * OK or ERROR.
  1486. *
  1487. * ERRNO:
  1488. *  S_netBufLib_CLSIZE_INVALID
  1489. */
  1490. STATUS netMblkClGet
  1491.     (
  1492.     NET_POOL_ID pNetPool, /* pointer to the net pool */
  1493.     M_BLK_ID   pMblk,  /* mBlk to embed the cluster in */
  1494.     int bufSize, /* size of the buffer to get */
  1495.     int canWait, /* wait or dontwait */
  1496.     BOOL bestFit /* TRUE/FALSE */
  1497.     )
  1498.     {
  1499.     if (pNetPool == NULL || pNetPool->pFuncTbl == NULL ||
  1500.         pNetPool->pFuncTbl->pMblkClGetRtn == NULL)
  1501.         return (ERROR);
  1502.     return ((*pNetPool->pFuncTbl->pMblkClGetRtn) (pNetPool, pMblk, bufSize,
  1503.                                                   canWait, bestFit));
  1504.     }
  1505. /*******************************************************************************
  1506. *
  1507. * netTupleGet - get an `mBlk'-`clBlk'-cluster
  1508. *
  1509. * This routine gets an `mBlk'-`clBlk'-cluster triplet from the specified
  1510. * memory pool.  The resulting structure is the basic method for accessing
  1511. * data at all layers of the network stack.
  1512. *
  1513. * .IP <pNetPool> 9
  1514. * Expects a pointer to the memory pool with which you want to build a
  1515. * `mBlk'-`clBlk'-cluster triplet.
  1516. * .IP <bufSize>
  1517. * Expects the size, in bytes, of the cluster in the `clBlk'-cluster
  1518. * pair.
  1519. * .IP <canWait>
  1520. * Expects either M_WAIT or M_DONTWAIT.  If any item in the triplet is not
  1521. * immediately available, the M_WAIT value allows this routine to repeat the
  1522. * allocation attempt after performing garbage collection. The M_DONTWAIT value
  1523. * prevents those extra steps.
  1524. * .IP <type>
  1525. * Expects the type of data, for example MT_DATA, MT_HEADER. The various
  1526. * values for this type are defined in netBufLib.h.
  1527. * .IP <bestFit>
  1528. * Expects either TRUE or FALSE.  If <bestFit> is TRUE and a cluster of the 
  1529. * exact size is unavailable, this routine gets a larger cluster (if
  1530. * available).  If <bestFit> is FALSE and an exact size cluster is unavailable, 
  1531. * this routine gets either a smaller or a larger cluster (depending 
  1532. * on what is available).  Otherwise, it returns immediately with an ERROR value.
  1533. * For memory pools containing only one cluster size, <bestFit> should always
  1534. * be set to FALSE.
  1535. *
  1536. * VXWORKS AE PROTECTION DOMAINS
  1537. * Under VxWorks AE, you can call this function from within the kernel 
  1538. * protection domain only.  In addition, all arguments to this function can  
  1539. * reference only that data which is valid in the kernel protection domain. 
  1540. * Likewise, the returned ID is valid in the kernel protection domain only.
  1541. * This restriction does not apply under non-AE versions of VxWorks.  
  1542. *
  1543. * RETURNS
  1544. * M_BLK_ID or NULL.
  1545. *
  1546. * ERRNO:
  1547. *  S_netBufLib_MBLK_INVALID
  1548. *  S_netBufLib_CLSIZE_INVALID
  1549. *  S_netBufLib_NETPOOL_INVALID
  1550. */
  1551. M_BLK_ID netTupleGet
  1552.     (
  1553.     NET_POOL_ID pNetPool, /* pointer to the net pool */
  1554.     int bufSize, /* size of the buffer to get */
  1555.     int canWait, /* wait or dontwait */
  1556.     UCHAR type, /* type of data */
  1557.     BOOL bestFit /* TRUE/FALSE */
  1558.     )
  1559.     {
  1560.     M_BLK_ID pMblk = NULL;  /* pointer to mBlk */
  1561.     if (pNetPool != NULL && pNetPool->pFuncTbl != NULL)
  1562.         {
  1563.         pMblk = mBlkGet (pNetPool, canWait, type);  /* get an mBlk */
  1564.         /* allocate a cluster and point the mBlk to it */
  1565.         if (pMblk && (mClGet (pNetPool, pMblk, bufSize, canWait, bestFit)
  1566.                       != OK))
  1567.             {
  1568.             netMblkFree (pNetPool, pMblk); 
  1569.             pMblk = NULL; 
  1570.             }
  1571.         }
  1572.     else
  1573.         errno = S_netBufLib_NETPOOL_INVALID; 
  1574.     return (pMblk); 
  1575.     }
  1576. /*******************************************************************************
  1577. *
  1578. * netClBlkJoin - join a cluster to a `clBlk' structure 
  1579. *
  1580. * This routine joins the previously reserved cluster specified by <pClBuf> 
  1581. * to the previously reserved `clBlk' structure specified by <pClBlk>. 
  1582. * The <size> parameter passes in the size of the cluster referenced 
  1583. * in <pClBuf>.  The arguments <pFreeRtn>, <arg1>, <arg2>, <arg3> set the  
  1584. * values of the 'pCLFreeRtn', 'clFreeArg1', 'clFreeArg2', and 'clFreeArg1', 
  1585. * members of the specified `clBlk' structure.
  1586. *
  1587. * VXWORKS AE PROTECTION DOMAINS
  1588. * Under VxWorks AE, you can call this function from within the kernel 
  1589. * protection domain only.  In addition, all arguments to this function can  
  1590. * reference only that data which is valid in the kernel protection domain. 
  1591. * Likewise, the returned ID is valid in the kernel protection domain only.
  1592. * This restriction does not apply under non-AE versions of VxWorks.  
  1593. *
  1594. * RETURNS: CL_BLK_ID or NULL.
  1595. */
  1596. CL_BLK_ID netClBlkJoin
  1597.     (
  1598.     CL_BLK_ID pClBlk, /* pointer to a cluster Blk */
  1599.     char * pClBuf, /* pointer to a cluster buffer */
  1600.     int size, /* size of the cluster buffer */
  1601.     FUNCPTR pFreeRtn, /* pointer to the free routine */
  1602.     int arg1, /* argument 1 of the free routine */
  1603.     int arg2, /* argument 2 of the free routine */
  1604.     int arg3 /* argument 3 of the free routine */
  1605.     )
  1606.     {
  1607.     if (pClBlk == NULL || pClBuf == NULL)
  1608.         return (NULL);
  1609.     pClBlk->clNode.pClBuf  = pClBuf;
  1610.     pClBlk->clSize  = size;
  1611.     pClBlk->pClFreeRtn  = pFreeRtn;
  1612.     pClBlk->clFreeArg1  = arg1;
  1613.     pClBlk->clFreeArg2  = arg2;
  1614.     pClBlk->clFreeArg3  = arg3;
  1615.     pClBlk->clRefCnt = 1;
  1616.     return (pClBlk);
  1617.     }
  1618. /*******************************************************************************
  1619. *
  1620. * netMblkClJoin - join an `mBlk' to a `clBlk'-cluster construct
  1621. *
  1622. * This routine joins the previously reserved `mBlk' referenced in <pMblk> to
  1623. * the `clBlk'-cluster construct referenced in <pClBlk>. 
  1624. * Internally, this routine sets the M_EXT flag in 'mBlk.mBlkHdr.mFlags'.  It 
  1625. * also and sets the 'mBlk.mBlkHdr.mData' to point to the start of the data 
  1626. * in the cluster.
  1627. *
  1628. * VXWORKS AE PROTECTION DOMAINS
  1629. * Under VxWorks AE, you can call this function from within the kernel 
  1630. * protection domain only.  In addition, all arguments to this function can  
  1631. * reference only that data which is valid in the kernel protection domain. 
  1632. * Likewise, the returned ID is valid in the kernel protection domain only.
  1633. * This restriction does not apply under non-AE versions of VxWorks.  
  1634. *
  1635. * .SH "RETURNS"
  1636. * M_BLK_ID or NULL. 
  1637. *
  1638. */
  1639. M_BLK_ID netMblkClJoin
  1640.     (
  1641.     M_BLK_ID  pMblk, /* pointer to an mBlk */
  1642.     CL_BLK_ID pClBlk /* pointer to a cluster Blk */
  1643.     )
  1644.     {
  1645.     if (pMblk == NULL || pClBlk == NULL)
  1646.         return (NULL);
  1647.     pMblk->mBlkHdr.mData  = pClBlk->clNode.pClBuf;
  1648.     pMblk->mBlkHdr.mFlags  |= M_EXT;
  1649.     pMblk->pClBlk = pClBlk;
  1650.     return (pMblk);
  1651.     }
  1652. /*******************************************************************************
  1653. *
  1654. * netClPoolIdGet - return a CL_POOL_ID for a specified buffer size 
  1655. * This routine returns a CL_POOL_ID for a cluster pool containing clusters 
  1656. * that match the specified <bufSize>.  If bestFit is TRUE, this routine returns 
  1657. * a CL_POOL_ID for a pool that contains clusters greater than or equal 
  1658. * to <bufSize>.  If <bestFit> is FALSE, this routine returns a CL_POOL_ID for a 
  1659. * cluster from whatever cluster pool is available.  If the memory pool 
  1660. * specified by <pNetPool> contains only one cluster pool, <bestFit> should 
  1661. * always be FALSE.
  1662. *
  1663. * VXWORKS AE PROTECTION DOMAINS
  1664. * Under VxWorks AE, you can call this function from within the kernel 
  1665. * protection domain only.  In addition, all arguments to this function can  
  1666. * reference only that data which is valid in the kernel protection domain. 
  1667. * Likewise, the returned ID is valid in the kernel protection domain only.
  1668. * This restriction does not apply under non-AE versions of VxWorks.  
  1669. *
  1670. * RETURNS: CL_POOL_ID or NULL.
  1671. */
  1672. CL_POOL_ID netClPoolIdGet
  1673.     (
  1674.     NET_POOL_ID pNetPool, /* pointer to the net pool */
  1675.     int  bufSize, /* size of the buffer */
  1676.     BOOL bestFit /* TRUE/FALSE */
  1677.     )
  1678.     {
  1679.     if (pNetPool == NULL || pNetPool->pFuncTbl == NULL ||
  1680.         pNetPool->pFuncTbl->pClPoolIdGetRtn == NULL)
  1681.         return (NULL);
  1682.     return ((*pNetPool->pFuncTbl->pClPoolIdGetRtn) (pNetPool, bufSize,
  1683.                                                     bestFit));
  1684.     }
  1685. /*******************************************************************************
  1686. *
  1687. * netMblkToBufCopy - copy data from an `mBlk' to a buffer
  1688. *
  1689. * This routine copies data from the `mBlk' chain referenced in <pMblk> to 
  1690. * the buffer referenced in <pBuf>.  It is assumed that <pBuf> points to 
  1691. * enough memory to contain all the data in the entire `mBlk' chain.
  1692. * The argument <pCopyRtn> expects either a NULL or a function pointer to a 
  1693. * copy routine.  The arguments passed to the copy routine are source 
  1694. * pointer, destination pointer and the length of data to copy.  If <pCopyRtn> 
  1695. * is NULL, netMblkToBufCopy() uses a default routine to extract the data from 
  1696. * the chain.
  1697. * .SH "RETURNS"
  1698. * The length of data copied or zero.
  1699. */
  1700. int netMblkToBufCopy
  1701.     (
  1702.     M_BLK_ID  pMblk, /* pointer to an mBlk */
  1703.     char * pBuf, /* pointer to the buffer to copy */
  1704.     FUNCPTR pCopyRtn /* function pointer for copy routine */
  1705.     )
  1706.     {
  1707.     char * pChar;
  1708.     if (pCopyRtn == NULL)
  1709.         pCopyRtn = (FUNCPTR) bcopy; /* default copy routine */
  1710.     pChar = pBuf;
  1711.     while (pMblk != NULL)
  1712.         {
  1713.         (*pCopyRtn) ((char *)pMblk->mBlkHdr.mData, pBuf, pMblk->mBlkHdr.mLen);
  1714.         pBuf  += pMblk->mBlkHdr.mLen;
  1715.         pMblk  = pMblk->mBlkHdr.mNext;
  1716.         }
  1717.     return ((int) pBuf - (int) pChar); /* return length copied */
  1718.     }
  1719. /*******************************************************************************
  1720. *
  1721. * netMblkDup - duplicate an `mBlk'
  1722. *
  1723. * This routine copies the references from a source `mBlk' in 
  1724. * an `mBlk'-`clBlk'-cluster construct to a stand-alone `mBlk'.
  1725. * This lets the two `mBlk' structures share the same `clBlk'-cluster
  1726. * construct.  This routine also increments the reference count in the 
  1727. * shared `clBlk'.  The <pSrcMblk> expects a pointer to the source `mBlk'.  
  1728. * The <pDescMblk> parameter expects a pointer to the destination `mBlk'. 
  1729. *
  1730. * VXWORKS AE PROTECTION DOMAINS
  1731. * Under VxWorks AE, you can call this function from within the kernel 
  1732. * protection domain only.  In addition, all arguments to this function can  
  1733. * reference only that data which is valid in the kernel protection domain. 
  1734. * Likewise, the returned ID is valid in the kernel protection domain only.
  1735. * This restriction does not apply under non-AE versions of VxWorks.  
  1736. *
  1737. * .SH "RETURNS"
  1738. * A pointer to the destination `mBlk' or NULL if the source `mBlk' 
  1739. * referenced in <pSrcMblk> is not part of a 
  1740. * valid `mBlk'-`clBlk'-cluster construct.
  1741. *
  1742. */
  1743. M_BLK_ID netMblkDup
  1744.     (
  1745.     M_BLK_ID pSrcMblk, /* pointer to source mBlk */
  1746.     M_BLK_ID pDestMblk /* pointer to the destination mBlk */
  1747.     )
  1748.     {
  1749.     int level; /* level of interrupt */
  1750.     if (pSrcMblk == NULL || pDestMblk == NULL)
  1751.         return (NULL);
  1752.     if (M_HASCL (pSrcMblk)) /* only if associated with a cluster */
  1753.         {
  1754.         if (pSrcMblk->mBlkHdr.mFlags & M_PKTHDR)
  1755.             pDestMblk->mBlkPktHdr = pSrcMblk->mBlkPktHdr;
  1756.         pDestMblk->mBlkHdr.mData  = pSrcMblk->mBlkHdr.mData;
  1757.         pDestMblk->mBlkHdr.mLen  = pSrcMblk->mBlkHdr.mLen;
  1758.         pDestMblk->mBlkHdr.mType  = pSrcMblk->mBlkHdr.mType;
  1759.         pDestMblk->mBlkHdr.mFlags  = pSrcMblk->mBlkHdr.mFlags;
  1760.         pDestMblk->pClBlk  = pSrcMblk->pClBlk;
  1761.         level = intLock ();
  1762.         ++(pDestMblk->pClBlk->clRefCnt); /* increment the ref count */
  1763.         intUnlock (level);
  1764.         }
  1765.     else
  1766.         pDestMblk = NULL;
  1767.     return (pDestMblk);
  1768.     }
  1769. /*******************************************************************************
  1770. *
  1771. * netMblkChainDup - duplicate an `mBlk' chain
  1772. *
  1773. * This routine makes a copy of an `mBlk' chain starting at <offset> bytes from
  1774. * the beginning of the chain and continuing for <len> bytes.  If <len> 
  1775. * is M_COPYALL, then this routine will copy the entire `mBlk' chain from 
  1776. * the <offset>.
  1777. * This routine copies the references from a source <pMblk> chain to
  1778. * a newly allocated `mBlk' chain. 
  1779. * This lets the two `mBlk' chains share the same `clBlk'-cluster
  1780. * constructs.  This routine also increments the reference count in the 
  1781. * shared `clBlk'.  The <pMblk> expects a pointer to the source `mBlk'
  1782. * chain.  
  1783. * The <pNetPool> parameter expects a pointer to the netPool from which
  1784. * the new `mBlk' chain is allocated.
  1785. *
  1786. * The <canWait> parameter determines the behavior if any required 'mBlk'
  1787. * is not immediately available. A value of M_WAIT allows this routine to
  1788. * repeat the allocation attempt after performing garbage collection. The
  1789. * M_DONTWAIT value prevents those extra steps.
  1790. *
  1791. * VXWORKS AE PROTECTION DOMAINS
  1792. * Under VxWorks AE, you can call this function from within the kernel 
  1793. * protection domain only.  In addition, all arguments to this function can  
  1794. * reference only that data which is valid in the kernel protection domain. 
  1795. * Likewise, the returned ID is valid in the kernel protection domain only.
  1796. * This restriction does not apply under non-AE versions of VxWorks.  
  1797. *
  1798. * SEE ALSO: netMblkDup()
  1799. *
  1800. * .SH "RETURNS"
  1801. * A pointer to the newly allocated `mBlk' chain or NULL.
  1802. *
  1803. * ERRNO:
  1804. *  S_netBufLib_INVALID_ARGUMENT
  1805. *  S_netBufLib_NO_POOL_MEMORY
  1806. */
  1807. M_BLK_ID netMblkChainDup
  1808.     (
  1809.     NET_POOL_ID pNetPool, /* pointer to the pool */
  1810.     M_BLK_ID pMblk, /* pointer to source mBlk chain*/
  1811.     int  offset, /* offset to duplicate from */
  1812.     int  len, /* length to copy */
  1813.     int canWait /* M_DONTWAIT/M_WAIT */
  1814.     )
  1815.     {
  1816.     M_BLK_ID  pNewMblk = NULL;
  1817.     M_BLK_ID * ppMblk   = NULL;
  1818.     M_BLK_ID  top      = NULL;
  1819.     BOOL copyhdr  = FALSE;
  1820.     int  off      = offset;
  1821.     int level;
  1822.     if (off < 0 || len < 0)
  1823.         {
  1824.         errno = S_netBufLib_INVALID_ARGUMENT;
  1825.         goto netMblkChainDupError;
  1826.         }
  1827.     if (off == 0 && pMblk->mBlkHdr.mFlags & M_PKTHDR)
  1828. copyhdr = TRUE;
  1829.     while (off > 0)
  1830. {
  1831. if (pMblk == 0)
  1832.             {
  1833.             errno = S_netBufLib_INVALID_ARGUMENT;
  1834.             goto netMblkChainDupError;
  1835.             }
  1836. if (off < pMblk->mBlkHdr.mLen)
  1837.     break;
  1838. off   -= pMblk->mBlkHdr.mLen;
  1839. pMblk = pMblk->mBlkHdr.mNext;
  1840. }
  1841.     ppMblk = &top;
  1842.     while (len > 0)
  1843. {
  1844. if (pMblk == 0)
  1845.     {
  1846.     if (len != M_COPYALL)
  1847.                 {
  1848.                 errno = S_netBufLib_INVALID_ARGUMENT;
  1849.                 goto netMblkChainDupError;
  1850.                 }
  1851.     break;
  1852.     }
  1853. pNewMblk = mBlkGet(pNetPool, canWait, pMblk->mBlkHdr.mType);
  1854. if ((*ppMblk = pNewMblk) == NULL)
  1855.             {
  1856.             errno = S_netBufLib_NO_POOL_MEMORY;
  1857.             goto netMblkChainDupError;
  1858.             }
  1859. if (copyhdr)
  1860.     {
  1861.             pNewMblk->mBlkPktHdr = pMblk->mBlkPktHdr;
  1862.     if (len == M_COPYALL)
  1863. pNewMblk->mBlkPktHdr.len -= offset;
  1864.     else
  1865. pNewMblk->mBlkPktHdr.len = len;
  1866.     copyhdr = FALSE;
  1867.     }
  1868. pNewMblk->mBlkHdr.mFlags = pMblk->mBlkHdr.mFlags; 
  1869. pNewMblk->mBlkHdr.mLen = min(len, pMblk->mBlkHdr.mLen - off);
  1870. pNewMblk->mBlkHdr.mData = pMblk->mBlkHdr.mData + off;
  1871. pNewMblk->pClBlk = pMblk->pClBlk;
  1872.         level = intLock ();
  1873.         ++(pNewMblk->pClBlk->clRefCnt); /* increment the ref count */
  1874.         intUnlock (level);
  1875. if (len != M_COPYALL)
  1876.     len -= pNewMblk->mBlkHdr.mLen;
  1877. off = 0;
  1878. pMblk = pMblk->mBlkHdr.mNext;
  1879. ppMblk = &pNewMblk->mBlkHdr.mNext;
  1880. }
  1881.     return (top);
  1882.     netMblkChainDupError:
  1883.      {
  1884.         if (top != NULL)
  1885.             netMblkClChainFree (top);
  1886.         return (NULL);
  1887.         }
  1888.     }
  1889. /*******************************************************************************
  1890. *
  1891. * netMblkOffsetToBufCopy - copy data from an `mBlk' from an offset to a buffer
  1892. *
  1893. * This routine copies data from the `mBlk' chain referenced in <pMblk> to 
  1894. * the buffer referenced in <pBuf>.  It is assumed that <pBuf> points to 
  1895. * enough memory to contain all the data in the entire `mBlk' chain.
  1896. * The argument <pCopyRtn> expects either a NULL or a function pointer to a 
  1897. * copy routine.  The arguments passed to the copy routine are source 
  1898. * pointer, destination pointer and the length of data to copy.  If <pCopyRtn> 
  1899. * is NULL, netMblkToBufCopy() uses a default routine to extract the data from 
  1900. * the chain.  The argument <offset> is a an offset from the first byte of data
  1901. * in the mBlk chain.  The argument <len> is the total of length of data to be
  1902. * copied from the mBlk Chain.  If value of <len> is M_COPYALL then the entire
  1903. * mBlkChain is copied from the offset.  M_COPYALL is defined to be 1000000000
  1904. *
  1905. * NOMANUAL
  1906. *
  1907. * .SH "RETURNS"
  1908. * The length of data copied or zero.
  1909. *
  1910. * ERRNO:
  1911. *  S_netBufLib_INVALID_ARGUMENT
  1912. */
  1913. int netMblkOffsetToBufCopy
  1914.     (
  1915.     M_BLK_ID  pMblk, /* pointer to an mBlk */
  1916.     int offset, /* offset to copy from */
  1917.     char * pBuf, /* pointer to the buffer to copy */
  1918.     int  len, /* length to copy */
  1919.     FUNCPTR pCopyRtn /* function pointer for copy routine */
  1920.     )
  1921.     {
  1922.     ULONG  count;
  1923.     char * pChar;
  1924.     pChar = pBuf;
  1925.     if (pCopyRtn == NULL)
  1926.         pCopyRtn = (FUNCPTR) bcopy; /* default copy routine */
  1927.     if (offset < 0 || len < 0 || pMblk == NULL) 
  1928.         goto netMblkOffsetToBufCopyError;
  1929.     
  1930.     while (offset > 0 && pMblk != NULL)
  1931. {
  1932. if (offset < pMblk->mBlkHdr.mLen)
  1933.     break;
  1934. offset -= pMblk->mBlkHdr.mLen;
  1935. pMblk  = pMblk->mBlkHdr.mNext;
  1936. }
  1937.     while (len > 0 && pMblk != NULL)
  1938. {
  1939.         if (len != M_COPYALL)
  1940.             {
  1941.             count = min(pMblk->mBlkHdr.mLen - offset, len);
  1942.             len   -= count;
  1943.             }
  1944.         else
  1945.             count = pMblk->mBlkHdr.mLen - offset;
  1946.             
  1947.         (*pCopyRtn) ((char *)pMblk->mBlkHdr.mData + offset, pBuf, count);
  1948. pBuf   += count;
  1949. offset = 0;
  1950. pMblk  = pMblk->mBlkHdr.mNext;
  1951. }
  1952.     return ((int) pBuf - (int) pChar); /* return length copied */
  1953.     
  1954.     netMblkOffsetToBufCopyError:
  1955.      {
  1956.         errno = S_netBufLib_INVALID_ARGUMENT;
  1957.         return (0);
  1958.         }
  1959.     }
  1960. #if 0 /* XXX support may be required later */
  1961. /*******************************************************************************
  1962. *
  1963. * netMblkFromBufCopy - copy data to an mBlk chain
  1964. *
  1965. * This routine copies data from a given buffer to an mBlk chain.
  1966. * The argument <pCopyRtn> is a function pointer to a copy routine which
  1967. * if not specified a default copy routine would be used.  The arguments passed
  1968. * to the copy routine are source pointer, destination pointer and the length
  1969. * of data to copy.  The data is copied from an offset indicated the argument
  1970. * <offset>.
  1971. *
  1972. * NOMANUAL
  1973. *
  1974. * RETURNS unsigned char pointer to the buffer or NULL.
  1975. */
  1976. UCHAR * netMblkFromBufCopy
  1977.     (
  1978.     M_BLK_ID  pMblk, /* pointer to an mBlk chain */
  1979.     char * pBuffer, /* pointer to the data buffer */
  1980.     int  offset, /* offset from the beginning of the data */
  1981.     int  len, /* total length to copy */
  1982.     FUNCPTR pCopyRtn /* function pointer for copy routine */
  1983.     )
  1984.     {
  1985.     return (NULL);
  1986.     }
  1987. #endif /* XXX future support */
  1988. /*******************************************************************************
  1989. *
  1990. * netTupleGet2 - makes a mblk chain
  1991. *
  1992. * This routine allocates a mblk chain just like how a network card driver
  1993. * would do it. It also changes mLen to the <len> parameter.
  1994. *
  1995. * RETURNS: a Mblk if successful, else NULL
  1996. *
  1997. * NOMANUAL
  1998. */
  1999. M_BLK_ID netTupleGet2 
  2000.     (
  2001.     NET_POOL_ID poolId, 
  2002.     int len,
  2003.     int bestFit
  2004.     )
  2005.     {
  2006.     M_BLK_ID            pMblk           = NULL;
  2007.     CL_BLK_ID           pClBlk          = NULL;
  2008.     char *              pData;
  2009.     CL_POOL_ID clPoolId;
  2010.     clPoolId = clPoolIdGet (poolId, len, bestFit);
  2011.     if ((pMblk = netMblkGet (poolId,
  2012.                             M_DONTWAIT, MT_DATA)) == NULL)
  2013.         {
  2014.         goto Error;
  2015.         }
  2016.     if ((pClBlk = netClBlkGet (poolId, M_DONTWAIT)) == NULL)
  2017.         {
  2018.         goto Error;
  2019.         }
  2020.     if ((pData = (char *) netClusterGet (poolId, clPoolId)) == NULL)
  2021.         {
  2022.         goto Error;
  2023.         }
  2024.     /* is the RFD to be given back?? */
  2025.     if (netClBlkJoin (pClBlk, pData, len, NULL, 0, 0, 0) == NULL)
  2026.         {
  2027.         goto Error;
  2028.         }
  2029.     if (netMblkClJoin (pMblk, pClBlk) == NULL)
  2030.         {
  2031.         goto Error;
  2032.         }
  2033.     pMblk->mBlkHdr.mLen = len;
  2034.     pMblk->mBlkPktHdr.len = len;
  2035.     return (pMblk);
  2036. Error:
  2037.     return ((M_BLK_ID)0);
  2038.     }