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

VxWorks

开发平台:

C/C++

  1. /* uipc_mbuf.c - mbuf routines */
  2. /* Copyright 1984 - 2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5.  * Copyright (c) 1982, 1986, 1988, 1991, 1993, 1995
  6.  * The Regents of the University of California.  All rights reserved.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  * This product includes software developed by the University of
  19.  * California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  *
  36.  * @(#)uipc_mbuf.c 8.4 (Berkeley) 2/14/95
  37.  */
  38. /*
  39. modification history
  40. --------------------
  41. 01p,12oct01,rae  merge from truestack ver 01t, base 01n
  42. 01o,07feb01,spm  removed unused garbage collection code
  43. 01n,25aug98,n_s  made _bufCollect only call pr_drain 1 time. spr #22104
  44. 01m,11dec97,vin  made m_free and m_freem as macros calling netMblkClFree
  45.  and netMblkClChainFree functions.
  46. 01l,08dec97,vin  removed m_copym merged with netMblkChainDup SPR 9966.
  47.  moved old m_copym code to #if 0 section.
  48. 01k,01dec97,vin  added system pool configuration logic.
  49.  Ifdefed m_copyback and m_copydata in uipc_mbuf.c these
  50.                  need some rework so that they can be tied up efficiently
  51.                  with the new buffering scheme.
  52. 01j,08oct97,vin  fixed clBlkFree.
  53. 01i,05oct97,vin  bug fix in m_copym
  54. 01h,19sep97,vin  added clBlk specific code, changed pointers to refcounts
  55.  of clusters to refcounts since refcount has been moved to
  56.                  clBlk
  57. 01g,11aug97,vin  interfaced with netBufLib.c, moved all windRiver specific
  58.  buffering code to netBufLib.c
  59. 01f,02jul97,vin  SPR 8878.
  60. 01e,15may97,vin  reworked m_devget(), added support for width of copying.
  61. 01d,31jan97,vin  removed local variable clLog2Def, cleanup
  62. 01c,03dec96,vin  changed interface to m_getclr() added additional parameters.
  63. 01b,13nov96,vin  removed BSD4.4 mbufs, modified m_devget, deleted m_get,
  64.  m_gethdr, m_split, wrote new cluster and mBlk functions.
  65.  moved m_copyback from rtsock.c.
  66. 01a,03mar96,vin  created from BSD4.4 stuff,integrated with 02v of uipc_mbuf.c
  67. */
  68. #include "vxWorks.h"
  69. #include "intLib.h"
  70. #include "net/mbuf.h"
  71. #include "net/systm.h"
  72. #include "net/domain.h"
  73. #include "net/protosw.h"
  74. #include "memPartLib.h"
  75. #ifdef WV_INSTRUMENTATION
  76. #ifdef INCLUDE_WVNET
  77. #include "wvNetLib.h"
  78. #endif /* INCLUDE_WVNET */
  79. #endif
  80. /* Virtual Stack support. */
  81. #ifdef VIRTUAL_STACK
  82. #include "netinet/vsLib.h"
  83. #endif
  84. /* externs */
  85. #ifndef VIRTUAL_STACK
  86. IMPORT struct domain *domains;
  87. #endif
  88. IMPORT VOIDFUNCPTR _pNetBufCollect;
  89. IMPORT STATUS netPoolKheapInit   (NET_POOL_ID pNetPool,
  90.                                   M_CL_CONFIG *pMclBlkConfig,
  91.   CL_DESC *pClDescTbl, int clDescTblNumEnt,
  92.   POOL_FUNC *pFuncTbl);
  93. /* globals */
  94. /* locals */
  95. LOCAL int  MPFail;   /* XXX temp variable pullup fails */
  96. #ifndef VIRTUAL_STACK
  97. LOCAL NET_POOL _netDpool;  /* system network data pool */
  98. LOCAL NET_POOL _netSysPool; /* system network structure pool */
  99. NET_POOL_ID _pNetDpool   = &_netDpool; 
  100. NET_POOL_ID _pNetSysPool = &_netSysPool; 
  101. #endif
  102. #ifdef WV_INSTRUMENTATION
  103. #ifdef INCLUDE_WVNET
  104.     /* Set common fields of event identifiers for this module. */
  105. LOCAL UCHAR wvNetModuleId = WV_NET_UIMBUF_MODULE; /* Value for uipc_mbuf.c */
  106. LOCAL UCHAR wvNetLocalFilter = WV_NET_NONE;     /* Available event filter */
  107. LOCAL ULONG wvNetEventId;       /* Event identifier: see wvNetLib.h */
  108. #endif    /* INCLUDE_WVNET */
  109. #endif
  110. /* forward declarations */
  111. LOCAL void _bufCollect (M_STAT * pPoolStat);
  112. LOCAL STATUS  _netStackPoolInit (NET_POOL_ID pNetPool,
  113.                                    M_CL_CONFIG * pMclConfig,
  114.                                    CL_DESC * pClDescTbl,
  115.                                    int clTblNumEnt);
  116. /*******************************************************************************
  117. *
  118. * _netStackPoolInit - initialize the net pool
  119. *
  120. * This routines initializes the netpool.
  121. *
  122. * NOMANUAL
  123. *
  124. * RETURNS: OK/ERROR
  125. */
  126. LOCAL STATUS _netStackPoolInit
  127.     (
  128.     NET_POOL_ID pNetPool, /* pointer to a net pool */
  129.     M_CL_CONFIG *  pMclConfig, /* ptr to mblk/clBlk config tbl */
  130.     CL_DESC *  pClDescTbl, /* ptr to first entry in clDesc tbl */
  131.     int  clTblNumEnt /* number of entries */
  132.     )
  133.     {
  134.     int  ix; /* index variable */
  135.     CL_DESC *  pClDesc; /* pointer to the cluster descriptor */
  136.     if (pMclConfig->memArea == NULL) /* do a default allocation */
  137.         {
  138.         /* memory size adjusted to hold the netPool pointer at the head */
  139.         pMclConfig->memSize = (pMclConfig->mBlkNum *
  140.                                 (MSIZE + sizeof (long))) +
  141.                     (pMclConfig->clBlkNum * CL_BLK_SZ); 
  142. /* the config table MUST be allocated in kernel heap */
  143.         if ((pMclConfig->memArea = (char *) KHEAP_ALLOC(pMclConfig->memSize))
  144.             == NULL)
  145.             {
  146. #ifdef WV_INSTRUMENTATION
  147. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  148.             WV_NET_MARKER_2 (NET_AUX_EVENT, WV_NET_EMERGENCY, 33, 1,
  149.                              WV_NETEVENT_POOLINIT_PANIC,
  150.                              pNetPool, pMclConfig->memSize)
  151. #endif  /* INCLUDE_WVNET */
  152. #endif
  153.             panic ("no memory: mBlks/clBlks");
  154.             return (ERROR); 
  155.             }
  156.         }
  157.     for (pClDesc = pClDescTbl, ix = 0; ix < clTblNumEnt; ix++, pClDesc++)
  158.         {
  159.         /* memory size adjusted for refcount, pool ptr and 4 byte alignmnt */
  160.         
  161.         if (pClDesc->memArea == NULL) /* do a default allocation */
  162.             {
  163.             pClDesc->memSize = (pClDesc->clNum *
  164.                                 (pClDesc->clSize + sizeof (long)));
  165.     /* the cluster desc MUST be allocated in kernel heap */
  166.             if ((pClDesc->memArea = (char *) KHEAP_ALLOC(pClDesc->memSize)) == NULL)
  167.                 {
  168.                 panic ("no memory: clusters");
  169.                 return (ERROR);
  170.                 }
  171.             }
  172.         }
  173.     return (netPoolKheapInit (pNetPool, pMclConfig, pClDescTbl, clTblNumEnt, NULL));
  174.     }
  175. /*******************************************************************************
  176. *
  177. * mbinit - initialize mbuf package
  178. *
  179. * Initialize a number of mbufs and clusters to start the ball rolling.
  180. * This is accomplished by calling routines _mBlkAlloc() and _clAlloc()
  181. *
  182. * NOMANUAL
  183. */
  184. void mbinit (void)
  185.     {
  186.     netBufLibInit (); /* initialize the buffering library */
  187.     _pNetBufCollect = _bufCollect;  /* intialize buffer collect routine */
  188. #ifdef VIRTUAL_STACK
  189.     /*
  190.      * Set the pointers appropriately.  This is because in C we can't
  191.      * do this in the global structure itself.
  192.      */
  193.     
  194.     _pNetDpool   = &_netDpool; 
  195.     _pNetSysPool = &_netSysPool; 
  196. #endif /* VIRTUAL_STACK */
  197.     if (_netStackPoolInit (_pNetDpool, &mClBlkConfig, &clDescTbl [0],
  198.                            clDescTblNumEnt) != OK)
  199.         goto mbInitError;
  200.     if (_netStackPoolInit (_pNetSysPool, &sysMclBlkConfig, &sysClDescTbl [0],
  201.                            sysClDescTblNumEnt) != OK)
  202.         goto mbInitError;
  203.     return;
  204.     
  205.     mbInitError:
  206.      {
  207. #ifdef WV_INSTRUMENTATION
  208. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  209.         WV_NET_MARKER_0 (NET_AUX_EVENT, WV_NET_EMERGENCY, 34, 2,
  210.                          WV_NETEVENT_MEMINIT_PANIC)
  211. #endif  /* INCLUDE_WVNET */
  212. #endif
  213.         panic ("mbinit");
  214.         return;
  215.         }
  216.     }
  217. /*******************************************************************************
  218. *
  219. * _bufCollect - drain protocols and collect required buffers
  220. *
  221. * Must be called at splimp.
  222. * NOMANUAL
  223. *
  224. */
  225. LOCAL void _bufCollect
  226.     (
  227.     M_STAT * pPoolStat /* pointer to the pools stats struct */
  228.     )
  229.     {
  230.     FAST struct domain *dp;
  231.     FAST struct protosw *pr;
  232.     int   level;  /* level of interrupt */
  233.     /* ask protocols to free space */
  234.     for (dp = domains; dp; dp = dp->dom_next)
  235. for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
  236.     if (pr->pr_drain)
  237. (*pr->pr_drain)();
  238.     level = intLock (); 
  239.     pPoolStat->mDrain++; /* no. of times protocols drained */
  240.     intUnlock (level); 
  241.     }
  242. /*******************************************************************************
  243. *
  244. * mBufClGet - get a new mBlk with a cluster 
  245. *
  246. * This routine allocates an mBlk and points it to a cluster allocated
  247. * Different clusters are allocated depending upon the cluster size requested.
  248. * INTERNAL
  249. * NOMANUAL
  250. * RETURNS: NULL/mBlk
  251. */
  252. struct mbuf * mBufClGet
  253.     (
  254.     int canWait, /* M_DONTWAIT/M_WAIT */
  255.     UCHAR type, /* type of data */
  256.     int bufSize, /* size of the buffer to get */
  257.     BOOL bestFit /* TRUE/FALSE */
  258.     )
  259.     {
  260.     FAST struct mbuf * pMblk;  /* pointer to mbuf */
  261.     pMblk = mBlkGet (_pNetDpool, canWait, type);  /* get an mBlk */
  262.     /* allocate a cluster and point the mbuf to it */
  263.     if (pMblk && (mClGet (_pNetDpool, pMblk, bufSize, canWait, bestFit) != OK))
  264. {
  265. (void)m_free (pMblk); 
  266. pMblk = NULL; 
  267. }
  268.     return (pMblk);
  269.     }
  270. /*******************************************************************************
  271. *
  272. * mHdrClGet - get a new mBlkHdr with a cluster 
  273. *
  274. * This routine allocates an mBlkHdr and points it to a cluster allocated
  275. * Different clusters are allocated depending upon the cluster size requested.
  276. *
  277. * INTERNAL
  278. *  
  279. * NOMANUAL
  280. * RETURNS: NULL/mBlkHdr
  281. */
  282. struct mbuf * mHdrClGet
  283.     (
  284.     int canWait, /* M_DONTWAIT/M_WAIT */
  285.     UCHAR type, /* type of data */
  286.     int bufSize, /* size of the buffer to get */
  287.     BOOL bestFit /* TRUE/FALSE */
  288.     )
  289.     {
  290.     FAST struct mbuf * pMblk = NULL;  /* pointer to mbuf */
  291.     /* get an mBlk/cluster pair */
  292.     
  293.     pMblk = mBlkGet (_pNetDpool, canWait, type);  /* get an mBlk */
  294.     if (pMblk == NULL)
  295.         return (NULL);
  296.     
  297.     pMblk->m_flags |= M_PKTHDR; 
  298.     /* allocate a cluster and point the mbuf to it */
  299.     if (mClGet (_pNetDpool, pMblk, bufSize, canWait, bestFit) != OK)
  300. {
  301. (void)m_free (pMblk); 
  302. pMblk = NULL; 
  303. }
  304.     return (pMblk);
  305.     }
  306. /*******************************************************************************
  307. *
  308. * m_getclr - get a clean mBlk, cluster pair
  309. *
  310. * This routine allocates an mBlk, points it to a cluster,
  311. * and zero's the cluster allocated.
  312. *
  313. * INTERNAL
  314. *  
  315. * NOMANUAL
  316. * RETURNS: NULL/mBlk
  317. */
  318. struct mbuf * m_getclr
  319.     (
  320.     int  canwait, /* M_WAIT/M_DONTWAIT */
  321.     UCHAR type, /* type of mbuf to allocate */
  322.     int bufSize, /* size of the buffer to get */
  323.     BOOL bestFit /* TRUE/FALSE */
  324.     )
  325.     {
  326.     FAST struct mbuf * pMblk = NULL;  /* pointer to mbuf */
  327.     /* allocate mBlk/cluster pair */
  328.     
  329.     if ((pMblk = mBufClGet (canwait, type, bufSize, bestFit)) != NULL)
  330. bzero(mtod(pMblk, caddr_t), pMblk->m_extSize); 
  331.     return (pMblk);
  332.     }
  333. #if 0 /* XXX */
  334. #endif /* XXX */
  335. /*
  336.  * Mbuffer utility routines.
  337.  */
  338. /*******************************************************************************
  339. *
  340. * m_prepend - prepend an mbuf to a chain.
  341. *
  342. * Lesser-used path for M_PREPEND:
  343. * allocate new mbuf to prepend to chain,
  344. * copy junk along.
  345. */
  346. struct mbuf * m_prepend(m, len, how)
  347.     register struct mbuf *m;
  348.     int len;
  349.     int how;
  350.     {
  351.     struct mbuf *mn;
  352.     if ((mn = mBufClGet (how, m->m_type, len, TRUE)) == NULL)
  353. {
  354. m_freem(m);
  355. return ((struct mbuf *)NULL);
  356. }
  357.     if (m->m_flags & M_PKTHDR)
  358. {
  359. mn->m_pkthdr = m->m_pkthdr;
  360. mn->m_flags = m->m_flags;
  361. m->m_flags &= ~M_PKTHDR;
  362. }
  363.     mn->m_next = m;
  364.     m = mn;
  365.     if (len < m->m_extSize)
  366. MH_ALIGN(m, len);
  367.     m->m_len = len;
  368.     return (m);
  369.     }
  370. /*******************************************************************************
  371. *
  372. * m_cat - concatenate mbuf chain n to m.
  373. *
  374. * Concatenate mbuf chain n to m.
  375. * Both chains must be of the same type (e.g. MT_DATA).
  376. * Any m_pkthdr is not updated.
  377. */
  378. void m_cat(m, n)
  379.     register struct mbuf * m;
  380.     register struct mbuf * n;
  381.     {
  382.     while (m->m_next)
  383. m = m->m_next;
  384.     if (n != NULL) /* clusters are used by default */
  385. m->m_next = n; 
  386.     }
  387. /*******************************************************************************
  388. *
  389. * m_adj - adjust the data in the mbuf
  390. *
  391. */
  392. void m_adj(mp, req_len)
  393.     struct mbuf * mp;
  394.     int req_len;
  395.     {
  396.     register int len = req_len;
  397.     register struct mbuf *m;
  398.     register int count;
  399.     if ((m = mp) == NULL)
  400. return;
  401.     if (len >= 0)
  402. {
  403. /*
  404.  * Trim from head.
  405.  */
  406. while (m != NULL && len > 0)
  407.     {
  408.     if (m->m_len <= len)
  409. {
  410. len -= m->m_len;
  411. m->m_len = 0;
  412. m = m->m_next;
  413. }
  414.     else
  415. {
  416. m->m_len -= len;
  417. m->m_data += len;
  418. len = 0;
  419. }
  420.     }
  421. m = mp;
  422. if (mp->m_flags & M_PKTHDR)
  423.     m->m_pkthdr.len -= (req_len - len);
  424.     else
  425. {
  426. /*
  427.  * Trim from tail.  Scan the mbuf chain,
  428.  * calculating its length and finding the last mbuf.
  429.  * If the adjustment only affects this mbuf, then just
  430.  * adjust and return.  Otherwise, rescan and truncate
  431.  * after the remaining size.
  432.  */
  433. len = -len;
  434. count = 0;
  435. for (;;)
  436.     {
  437.     count += m->m_len;
  438.     if (m->m_next == (struct mbuf *)0)
  439. break;
  440.     m = m->m_next;
  441.     }
  442. if (m->m_len >= len)
  443.     {
  444.     m->m_len -= len;
  445.     if (mp->m_flags & M_PKTHDR)
  446. mp->m_pkthdr.len -= len;
  447.     return;
  448.     }
  449. count -= len;
  450. if (count < 0)
  451.     count = 0;
  452. /*
  453.  * Correct length for chain is "count".
  454.  * Find the mbuf with last data, adjust its length,
  455.  * and toss data from remaining mbufs on chain.
  456.  */
  457. m = mp;
  458. if (m->m_flags & M_PKTHDR)
  459.     m->m_pkthdr.len = count;
  460. for (; m; m = m->m_next) 
  461.     {
  462.     if (m->m_len >= count) 
  463. {
  464. m->m_len = count;
  465. break;
  466. }
  467.     count -= m->m_len;
  468.     }
  469. while ((m = m->m_next))
  470.     m->m_len = 0;
  471. }
  472.     }
  473. /*******************************************************************************
  474. *
  475. * m_pullup - ensure contiguous data area at the beginnig of an mbuf chain
  476. *
  477. * Rearange an mbuf chain so that len bytes are contiguous
  478. * and in the data area of an mbuf (so that mtod and dtom
  479. * will work for a structure of size len).  Returns the resulting
  480. * mbuf chain on success, frees it and returns null on failure.
  481. */
  482. struct mbuf *
  483. m_pullup(n, len)
  484.     register struct mbuf *n;
  485.     int len;
  486.     {
  487.     register struct mbuf *m;
  488.     register int count;
  489.     int space;
  490.     if (((n->m_data + len) < (n->m_extBuf + n->m_extSize)) && n->m_next)
  491. {
  492. if (n->m_len >= len)
  493.     return (n); 
  494. m = n;
  495. n = n->m_next;
  496. len -= m->m_len;
  497. }
  498.     else 
  499. {
  500. m = mBufClGet(M_DONTWAIT, n->m_type, len, TRUE);
  501. if (m == 0)
  502.     goto bad;
  503. m->m_len = 0;
  504. if (n->m_flags & M_PKTHDR)
  505.     {
  506.     m->m_pkthdr = n->m_pkthdr;
  507.     m->m_flags = n->m_flags; 
  508.     n->m_flags &= ~M_PKTHDR;
  509.     }
  510. }
  511.     space = (m->m_extBuf + m->m_extSize) - (m->m_data + m->m_len);
  512.     do 
  513. {
  514. count = min(min(max(len, max_protohdr), space), n->m_len);
  515. bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
  516.       (unsigned)count);
  517. len -= count;
  518. m->m_len += count;
  519. n->m_len -= count;
  520. space -= count;
  521. if (n->m_len)
  522.     n->m_data += count;
  523. else
  524.     n = m_free(n);
  525. } while (len > 0 && n);
  526.     if (len > 0)
  527. {
  528. (void) m_free(m);
  529. goto bad;
  530. }
  531.     m->m_next = n;
  532.     return (m);
  533.     bad:
  534.     m_freem(n);
  535.     MPFail++;
  536.     return (0);
  537.     }
  538. /*******************************************************************************
  539. *
  540. * m_devget - Routine to copy from device local memory into mbufs.
  541. *
  542. * Routine to copy from device local memory into mbufs.
  543. * This routine copies the device local memory into mbufs according to the
  544. * specified width. The interface pointer is initialized as a part of the
  545. * packet header in the mbuf chain. The first mbuf in the chain is always
  546. * a packet header and contains the interface pointer. This field is used
  547. * when it is necessary to retrieve the interface pointer from the mbuf chain.
  548. * If a copy function pointer is given, this function uses that function
  549. * pointer. This is given to enable the hardware specific copy routines to be
  550. * used instead of system routines.
  551. *
  552. */
  553. struct mbuf * m_devget(buf, totlen, width, ifp, copy)
  554.     char * buf;
  555.     int totlen;
  556.     int width;
  557.     struct ifnet *ifp;
  558.     void (*copy)();
  559.     {
  560.     register struct mbuf *m;
  561.     struct mbuf *top = NULL, **mp = &top;
  562.     register int len;
  563.     register char *cp;
  564.     cp = buf;
  565.     while (totlen > 0)
  566. {
  567.         m = mBufClGet (M_DONTWAIT, MT_DATA, totlen, FALSE);
  568.         if (m == NULL)
  569.             {
  570.             if (top != NULL)
  571.                 m_freem (top);
  572.             return (NULL);
  573.             }
  574.         
  575. if (top == NULL)
  576.     {
  577.             m->m_flags  |= M_PKTHDR; 
  578.     m->m_pkthdr.rcvif  = ifp;
  579.     m->m_pkthdr.len  = totlen;
  580.     len = min(totlen, m->m_extSize);  /* length to copy */
  581.     if (m->m_extSize > max_hdr) 
  582. {
  583. /* avoid costly m_prepends done in the context of tNetTask,
  584.  * especially effective while forwarding packets.
  585.  */
  586. len = min (len, (m->m_extSize - max_linkhdr)); 
  587. m->m_data += max_linkhdr;
  588. }
  589.     }
  590. else
  591.             {
  592.     len = min(totlen, m->m_extSize);  /* length to copy */
  593.             }
  594. m->m_len = len;  /* initialize the length of mbuf */
  595.         
  596. if (copy)
  597.     (*copy)(cp, mtod(m, caddr_t), (unsigned)len);
  598. else
  599.             {
  600.             switch (width)
  601.                 {
  602.                 case NONE:
  603.                     bcopy(cp, mtod(m, caddr_t), (unsigned)len);
  604.                     break;
  605.                 case 1:
  606.                     bcopyBytes (cp, mtod(m, caddr_t), len);
  607.                     break;
  608.                 case 2:
  609.                     bcopyWords (cp, mtod(m, caddr_t), (len + 1) >> 1);
  610.                     break;
  611.                 case 4:
  612.                     bcopyLongs (cp, mtod(m, caddr_t), (len + 3) >> 2);
  613.                     break;
  614.                         
  615.                 default:
  616. #ifdef WV_INSTRUMENTATION
  617. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  618.                     WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_EMERGENCY, 35, 3,
  619.                              WV_NETEVENT_DEVMEM_PANIC, width)
  620. #endif  /* INCLUDE_WVNET */
  621. #endif
  622.                     panic ("m_devget -- invalid mem copy width");
  623.                     break;
  624.                 }
  625.             }
  626. cp += len; /* advance the pointer */
  627. *mp = m;
  628. mp = &m->m_next; /* advance the mbuf */
  629. totlen -= len; /* decrment the total length */
  630. }
  631.     return (top); /* return the filled mbuf chain */
  632.     }
  633. #if 0 /* XXX */
  634. /* both m_copyback and m_copydata have to be reworked, these functions
  635.  * are only used in rt_sock.c. They have been moved to rt_sock.c.
  636.  * They have to be reworked and integrated into netBufLib.c
  637.  */
  638. /*
  639.  * Copy data from a buffer back into the indicated mbuf chain,
  640.  * starting "off" bytes from the beginning, extending the mbuf
  641.  * chain if necessary.
  642.  */
  643. void
  644. m_copyback(m0, off, len, cp)
  645. struct mbuf *m0;
  646. register int off;
  647. register int len;
  648. caddr_t cp;
  649. {
  650. register int mlen;
  651. register struct mbuf *m = m0, *n;
  652. int totlen = 0;
  653. if (m0 == 0)
  654. return;
  655. while (off > (mlen = m->m_len)) {
  656. off -= mlen;
  657. totlen += mlen;
  658. if (m->m_next == 0) {
  659. n = m_getclr(M_DONTWAIT, m->m_type, CL_SIZE_128, TRUE);
  660. if (n == 0)
  661. goto out;
  662. n->m_len = min(n->m_extSize, len + off);
  663. m->m_next = n;
  664. }
  665. m = m->m_next;
  666. }
  667. while (len > 0) {
  668. mlen = min (m->m_len - off, len);
  669. bcopy(cp, off + mtod(m, caddr_t), (unsigned)mlen);
  670. cp += mlen;
  671. len -= mlen;
  672. mlen += off;
  673. off = 0;
  674. totlen += mlen;
  675. if (len == 0)
  676. break;
  677. if (m->m_next == 0) {
  678. n = mBufClGet(M_DONTWAIT, m->m_type, CL_SIZE_128, TRUE);
  679. if (n == 0)
  680. break;
  681. n->m_len = min(n->m_extSize, len);
  682. m->m_next = n;
  683. }
  684. m = m->m_next;
  685. }
  686. out: if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen))
  687. m->m_pkthdr.len = totlen;
  688. }
  689. /*******************************************************************************
  690. *
  691. * m_copydata - copy data from an mbuf chain into a buff
  692. * Copy data from an mbuf chain starting "off" bytes from the beginning,
  693. * continuing for "len" bytes, into the indicated buffer.
  694. */
  695. void m_copydata(m, off, len, cp)
  696.     register struct mbuf *m;
  697.     register int off;
  698.     register int len;
  699.     caddr_t cp;
  700.     {
  701.     register unsigned count;
  702.     if (off < 0 || len < 0)
  703. panic("m_copydata");
  704.     while (off > 0)
  705. {
  706. if (m == 0)
  707.     panic("m_copydata");
  708. if (off < m->m_len)
  709.     break;
  710. off -= m->m_len;
  711. m = m->m_next;
  712. }
  713.     while (len > 0)
  714. {
  715. if (m == 0)
  716.     panic("m_copydata");
  717. count = min(m->m_len - off, len);
  718. bcopy(mtod(m, caddr_t) + off, cp, count);
  719. len -= count;
  720. cp += count;
  721. off = 0;
  722. m = m->m_next;
  723. }
  724.     }
  725. /* XXX merged with netMblkChainDup in netBufLib.c */
  726. LOCAL int  MCFail;   /* XXX temp variable pullup fails */
  727. /*******************************************************************************
  728. *
  729. * m_copym - make a copy of an mbuf chain.
  730. *
  731. * Make a copy of an mbuf chain starting "off0" bytes from the beginning,
  732. * continuing for "len" bytes.  If len is M_COPYALL, copy to end of mbuf.
  733. * The wait parameter is a choice of M_WAIT/M_DONTWAIT from caller.
  734. */
  735. struct mbuf * m_copym(m, off0, len, wait)
  736.     register struct mbuf *m;
  737.     int off0, wait;
  738.     register int len;
  739.     {
  740.     register struct mbuf *n, **np;
  741.     register int off = off0;
  742.     struct mbuf *top;
  743.     int copyhdr = 0;
  744.     if (off < 0 || len < 0)
  745.         {
  746. #ifdef WV_INSTRUMENTATION
  747. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  748.         WV_NET_MARKER_3 (NET_AUX_EVENT, WV_NET_EMERGENCY, 36, 4,
  749.                          WV_NETEVENT_MEMCOPY_PANIC, off, len, m)
  750. #endif  /* INCLUDE_WVNET */
  751. #endif
  752.         panic("m_copym");
  753.         }
  754.     if (off == 0 && m->m_flags & M_PKTHDR)
  755. copyhdr = 1;
  756.     while (off > 0)
  757. {
  758. if (m == 0)
  759.             {
  760. #ifdef WV_INSTRUMENTATION
  761. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  762.             WV_NET_MARKER_3 (NET_AUX_EVENT, WV_NET_EMERGENCY, 36, 4,
  763.                              WV_NETEVENT_MEMCOPY_PANIC, off, len, m)
  764. #endif  /* INCLUDE_WVNET */
  765. #endif
  766.     panic("m_copym");
  767.             }
  768. if (off < m->m_len)
  769.     break;
  770. off -= m->m_len;
  771. m = m->m_next;
  772. }
  773.     np = &top;
  774.     top = 0;
  775.     while (len > 0)
  776. {
  777. if (m == 0)
  778.     {
  779.     if (len != M_COPYALL)
  780.                 {
  781. #ifdef WV_INSTRUMENTATION
  782. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  783.                 WV_NET_MARKER_3 (NET_AUX_EVENT, WV_NET_EMERGENCY, 36, 4,
  784.                                  WV_NETEVENT_MEMCOPY_PANIC, off, len, m)
  785. #endif  /* INCLUDE_WVNET */
  786. #endif
  787.                 panic("m_copym");
  788.                 }
  789.     break;
  790.     }
  791. n = mBlkGet(_pNetDpool, wait, m->m_type);
  792. if ((*np = n) == NULL)
  793.     goto nospace;
  794. if (copyhdr)
  795.     {
  796.             n->m_pkthdr = m->m_pkthdr;
  797.     if (len == M_COPYALL)
  798. n->m_pkthdr.len -= off0;
  799.     else
  800. n->m_pkthdr.len = len;
  801.     copyhdr = 0;
  802.     }
  803. n->m_flags = m->m_flags; 
  804. n->m_len = min(len, m->m_len - off);
  805. n->m_data = m->m_data + off;
  806. n->m_ext = m->m_ext;
  807. ++(n->m_extRefCnt);
  808. if (len != M_COPYALL)
  809.     len -= n->m_len;
  810. off = 0;
  811. m = m->m_next;
  812. np = &n->m_next;
  813. }
  814.     if (top == 0)
  815. MCFail++;
  816.     return (top);
  817.     nospace:
  818.     m_freem(top);
  819.     MCFail++;
  820.     return (0);
  821.     }
  822. /*
  823.  * XXX merged with netMblkClFree & netMblkClChainFree in netBufLib.c
  824.  * turned m_free and m_freem as macros in mbuf.h
  825.  */
  826. /*******************************************************************************
  827. *
  828. * m_free - free the mBlk and cluster pair
  829. *
  830. * This function frees the mBlk and also the cluster if the mBlk points to it.
  831. * This function returns a pointer to the next mBlk connected to the one that
  832. * is freed.
  833. *
  834. * NOMANUAL
  835. * RETURNS mBLK/NULL
  836. */
  837. struct mbuf * m_free
  838.     (
  839.     FAST struct mbuf *  pMblk /* pointer to the mBlk to free */
  840.     )
  841.     {
  842.     FAST struct mbuf * pMblkNext; /* pointer to the next mBlk */
  843.     NET_POOL_ID pNetPool; /* pointer to net pool */
  844.     
  845.     if (pMblk->m_type == MT_FREE)
  846.         {
  847. #ifdef WV_INSTRUMENTATION
  848. #ifdef INCLUDE_WVNET    /* WV_NET_EMERGENCY event */
  849.         WV_NET_MARKER_1 (NET_AUX_EVENT, WV_NET_EMERGENCY, 37, 5,
  850.                          WV_NETEVENT_MEMFREE_PANIC, pMblk)
  851. #endif  /* INCLUDE_WVNET */
  852. #endif
  853.         panic("m_free");
  854.         }
  855.     pNetPool  = MBLK_TO_NET_POOL(pMblk); 
  856.     pMblkNext  = pMblk->m_next;
  857.     /* free the cluster first if it is attached to the mBlk */
  858.     
  859.     if (M_HASCL(pMblk))
  860.         clBlkFree (pMblk->pClBlk->pNetPool, pMblk->pClBlk);
  861.     mBlkFree (pNetPool, pMblk);  /* free the mBlk */
  862.     return (pMblkNext);
  863.     }
  864. /*******************************************************************************
  865. *
  866. * m_freem - free a list of mbufs linked via m_next
  867. *
  868. * N.B.: If MFREE macro changes in mbuf.h m_freem should also change
  869. *  accordingly.
  870. */
  871. void m_freem(m)
  872.     FAST struct mbuf *m;
  873.     {
  874.     FAST struct mbuf *n;
  875.     if (m == NULL)
  876. return;
  877.     do
  878. {
  879. n = m_free (m); 
  880. }
  881.     while ((m = n));
  882.     }
  883. #endif /* XXX have to be reworked */