1: /*
   2:  * Copyright (c) 1982, 1986 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  *
   6:  *	@(#)uipc_mbuf.c	2.0 (2.11BSD) 12/24/92
   7:  */
   8: 
   9: #include "param.h"
  10: #ifdef INET
  11: #include "user.h"
  12: #include "mbuf.h"
  13: #include "kernel.h"
  14: #include "domain.h"
  15: #include "protosw.h"
  16: 
  17: struct mbuf *mbuf, *mbutl, xmbuf[NMBUFS + 1];
  18: struct mbuf xmbutl[(NMBCLUSTERS*CLBYTES/sizeof (struct mbuf))+7];
  19: memaddr miobase;            /* click address of dma region */
  20:                     /* this is altered during allocation */
  21: memaddr miostart;           /* click address of dma region */
  22:                     /* this stays unchanged */
  23: ubadr_t mioumr;             /* base UNIBUS virtual address */
  24:                     /* miostart and mioumr stay 0 for */
  25:                     /* non-UNIBUS machines */
  26: u_short miosize = 16384;        /* two umr's worth */
  27: 
  28: mbinit()
  29: {
  30:     register int s;
  31: 
  32:     s = splimp();
  33:     nmbclusters = NMBCLUSTERS;
  34:     /*
  35: 	 * if the following two lines look strange, it's because they are.
  36: 	 * mbufs are aligned on a MSIZE byte boundary and clusters are
  37: 	 * aligned on CLBYTES byte boundary.  extra room has been allocated
  38: 	 * in the arrays to allow for the array origin not being aligned,
  39: 	 * in which case we move part way thru and start there.
  40: 	 */
  41:     mbutl = (struct mbuf *)(((int)xmbutl | CLBYTES-1) + 1);
  42:     mbuf = (struct mbuf *)(((int)xmbuf | MSIZE-1) + 1);
  43:     mbinit2(mbuf, MPG_MBUFS, NMBUFS);
  44:     mbinit2(mbutl, MPG_CLUSTERS, NMBCLUSTERS);
  45:     splx(s);
  46:     return;
  47: }
  48: 
  49: mbinit2(mem, how, num)
  50:     char *mem;
  51:     int how;
  52:     register int num;
  53: {
  54:     register struct mbuf *m;
  55:     register int i;
  56: 
  57:     m = (struct mbuf *)mem;
  58:     switch (how) {
  59:     case MPG_CLUSTERS:
  60:         for (i = 0; i < num; i++) {
  61:             m->m_off = 0;
  62:             m->m_next = mclfree;
  63:             mclfree = m;
  64:             m += NMBPCL;
  65:             mbstat.m_clfree++;
  66:         }
  67:         mbstat.m_clusters = num;
  68:         break;
  69:     case MPG_MBUFS:
  70:         for (i = num; i > 0; i--) {
  71:             m->m_off = 0;
  72:             m->m_type = MT_DATA;
  73:             mbstat.m_mtypes[MT_DATA]++;
  74:             (void) m_free(m);
  75:             m++;
  76:         }
  77:         mbstat.m_mbufs = NMBUFS;
  78:         break;
  79:     }
  80: }
  81: 
  82: /*
  83:  * Allocate a contiguous buffer for DMA IO.  Called from if_ubainit().
  84:  * TODO: fix net device drivers to handle scatter/gather to mbufs
  85:  * on their own; thus avoiding the copy to/from this area.
  86:  */
  87: u_int
  88: m_ioget(size)
  89:     u_int size;     /* Number of bytes to allocate */
  90: {
  91:     memaddr base;
  92:     u_int csize;
  93: 
  94:     csize = btoc(size);     /* size in clicks */
  95:     size = ctob(csize);     /* round up byte size */
  96: 
  97:     if (size > miosize)
  98:         return(0);
  99:     miosize -= size;
 100:     base = miobase;
 101:     miobase += csize;
 102:     return (base);
 103: }
 104: 
 105: /*
 106:  * Must be called at splimp.
 107:  */
 108: m_expand(canwait)
 109:     int canwait;
 110: {
 111:     register struct domain *dp;
 112:     register struct protosw *pr;
 113:     register int tries;
 114: 
 115:     for (tries = 0;; ) {
 116: #ifdef  pdp11
 117:         if (mfree)
 118:             return (1);
 119: #else
 120:         if (m_clalloc(1, MPG_MBUFS, canwait))
 121:             return (1);
 122: #endif
 123:         if (canwait == M_DONTWAIT || tries++)
 124:             return (0);
 125: 
 126:         /* ask protocols to free space */
 127:         for (dp = domains; dp; dp = dp->dom_next)
 128:             for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW;
 129:                 pr++)
 130:                 if (pr->pr_drain)
 131:                     (*pr->pr_drain)();
 132:         mbstat.m_drain++;
 133:     }
 134: }
 135: 
 136: /* NEED SOME WAY TO RELEASE SPACE */
 137: 
 138: /*
 139:  * Space allocation routines.
 140:  * These are also available as macros
 141:  * for critical paths.
 142:  */
 143: struct mbuf *
 144: m_get(canwait, type)
 145:     int canwait, type;
 146: {
 147:     register struct mbuf *m;
 148: 
 149:     MGET(m, canwait, type);
 150:     return (m);
 151: }
 152: 
 153: struct mbuf *
 154: m_getclr(canwait, type)
 155:     int canwait, type;
 156: {
 157:     register struct mbuf *m;
 158: 
 159:     MGET(m, canwait, type);
 160:     if (m == 0)
 161:         return (0);
 162:     bzero(mtod(m, caddr_t), MLEN);
 163:     return (m);
 164: }
 165: 
 166: struct mbuf *
 167: m_free(m)
 168:     struct mbuf *m;
 169: {
 170:     register struct mbuf *n;
 171: 
 172:     MFREE(m, n);
 173:     return (n);
 174: }
 175: 
 176: /*
 177:  * Get more mbufs; called from MGET macro if mfree list is empty.
 178:  * Must be called at splimp.
 179:  */
 180: /*ARGSUSED*/
 181: struct mbuf *
 182: m_more(canwait, type)
 183:     int canwait, type;
 184: {
 185:     register struct mbuf *m;
 186: 
 187:     while (m_expand(canwait) == 0) {
 188:         if (canwait == M_WAIT) {
 189:             mbstat.m_wait++;
 190:             m_want++;
 191:             SLEEP((caddr_t)&mfree, PZERO - 1);
 192:         } else {
 193:             mbstat.m_drops++;
 194:             return (NULL);
 195:         }
 196:     }
 197: #define m_more(x,y) (panic("m_more"), (struct mbuf *)0)
 198:     MGET(m, canwait, type);
 199: #undef m_more
 200:     return (m);
 201: }
 202: 
 203: m_freem(m)
 204:     register struct mbuf *m;
 205: {
 206:     register struct mbuf *n;
 207:     register int s;
 208: 
 209:     if (m == NULL)
 210:         return;
 211:     s = splimp();
 212:     do {
 213:         MFREE(m, n);
 214:     } while (m = n);
 215:     splx(s);
 216: }
 217: 
 218: /*
 219:  * Mbuffer utility routines.
 220:  */
 221: 
 222: /*
 223:  * Make a copy of an mbuf chain starting "off" bytes from the beginning,
 224:  * continuing for "len" bytes.  If len is M_COPYALL, copy to end of mbuf.
 225:  * Should get M_WAIT/M_DONTWAIT from caller.
 226:  */
 227: struct mbuf *
 228: m_copy(m, off, len)
 229:     register struct mbuf *m;
 230:     int off;
 231:     register int len;
 232: {
 233:     register struct mbuf *n, **np;
 234:     struct mbuf *top, *p;
 235: 
 236:     if (len == 0)
 237:         return (0);
 238:     if (off < 0 || len < 0)
 239:         panic("m_copy");
 240:     while (off > 0) {
 241:         if (m == 0)
 242:             panic("m_copy");
 243:         if (off < m->m_len)
 244:             break;
 245:         off -= m->m_len;
 246:         m = m->m_next;
 247:     }
 248:     np = &top;
 249:     top = 0;
 250:     while (len > 0) {
 251:         if (m == 0) {
 252:             if (len != M_COPYALL)
 253:                 panic("m_copy");
 254:             break;
 255:         }
 256:         MGET(n, M_DONTWAIT, m->m_type);
 257:         *np = n;
 258:         if (n == 0)
 259:             goto nospace;
 260:         n->m_len = MIN(len, m->m_len - off);
 261:         if (m->m_off > MMAXOFF) {
 262:             p = mtod(m, struct mbuf *);
 263:             n->m_off = ((int)p - (int)n) + off;
 264:             mclrefcnt[mtocl(p)]++;
 265:         } else
 266:             bcopy(mtod(m, caddr_t)+off, mtod(n, caddr_t),
 267:                 (unsigned)n->m_len);
 268:         if (len != M_COPYALL)
 269:             len -= n->m_len;
 270:         off = 0;
 271:         m = m->m_next;
 272:         np = &n->m_next;
 273:     }
 274:     return (top);
 275: nospace:
 276:     m_freem(top);
 277:     return (0);
 278: }
 279: 
 280: m_cat(m, n)
 281:     register struct mbuf *m, *n;
 282: {
 283:     while (m->m_next)
 284:         m = m->m_next;
 285:     while (n) {
 286:         if (m->m_off >= MMAXOFF ||
 287:             m->m_off + m->m_len + n->m_len > MMAXOFF) {
 288:             /* just join the two chains */
 289:             m->m_next = n;
 290:             return;
 291:         }
 292:         /* splat the data from one into the other */
 293:         bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
 294:             (u_int)n->m_len);
 295:         m->m_len += n->m_len;
 296:         n = m_free(n);
 297:     }
 298: }
 299: 
 300: m_adj(mp, len)
 301:     struct mbuf *mp;
 302:     register int len;
 303: {
 304:     register struct mbuf *m;
 305:     register count;
 306: 
 307:     if ((m = mp) == NULL)
 308:         return;
 309:     if (len >= 0) {
 310:         while (m != NULL && len > 0) {
 311:             if (m->m_len <= len) {
 312:                 len -= m->m_len;
 313:                 m->m_len = 0;
 314:                 m = m->m_next;
 315:             } else {
 316:                 m->m_len -= len;
 317:                 m->m_off += len;
 318:                 break;
 319:             }
 320:         }
 321:     } else {
 322:         /*
 323: 		 * Trim from tail.  Scan the mbuf chain,
 324: 		 * calculating its length and finding the last mbuf.
 325: 		 * If the adjustment only affects this mbuf, then just
 326: 		 * adjust and return.  Otherwise, rescan and truncate
 327: 		 * after the remaining size.
 328: 		 */
 329:         len = -len;
 330:         count = 0;
 331:         for (;;) {
 332:             count += m->m_len;
 333:             if (m->m_next == (struct mbuf *)0)
 334:                 break;
 335:             m = m->m_next;
 336:         }
 337:         if (m->m_len >= len) {
 338:             m->m_len -= len;
 339:             return;
 340:         }
 341:         count -= len;
 342:         /*
 343: 		 * Correct length for chain is "count".
 344: 		 * Find the mbuf with last data, adjust its length,
 345: 		 * and toss data from remaining mbufs on chain.
 346: 		 */
 347:         for (m = mp; m; m = m->m_next) {
 348:             if (m->m_len >= count) {
 349:                 m->m_len = count;
 350:                 break;
 351:             }
 352:             count -= m->m_len;
 353:         }
 354:         while (m = m->m_next)
 355:             m->m_len = 0;
 356:     }
 357: }
 358: 
 359: /*
 360:  * Rearange an mbuf chain so that len bytes are contiguous
 361:  * and in the data area of an mbuf (so that mtod and dtom
 362:  * will work for a structure of size len).  Returns the resulting
 363:  * mbuf chain on success, frees it and returns null on failure.
 364:  * If there is room, it will add up to MPULL_EXTRA bytes to the
 365:  * contiguous region in an attempt to avoid being called next time.
 366:  */
 367: struct mbuf *
 368: m_pullup(n, len)
 369:     register struct mbuf *n;
 370:     int len;
 371: {
 372:     register struct mbuf *m;
 373:     register int count;
 374:     int space;
 375: 
 376:     if (n->m_off + len <= MMAXOFF && n->m_next) {
 377:         m = n;
 378:         n = n->m_next;
 379:         len -= m->m_len;
 380:     } else {
 381:         if (len > MLEN)
 382:             goto bad;
 383:         MGET(m, M_DONTWAIT, n->m_type);
 384:         if (m == 0)
 385:             goto bad;
 386:         m->m_len = 0;
 387:     }
 388:     space = MMAXOFF - m->m_off;
 389:     do {
 390:         count = MIN(MIN(space - m->m_len, len + MPULL_EXTRA), n->m_len);
 391:         bcopy(mtod(n, caddr_t), mtod(m, caddr_t)+m->m_len,
 392:           (unsigned)count);
 393:         len -= count;
 394:         m->m_len += count;
 395:         n->m_len -= count;
 396:         if (n->m_len)
 397:             n->m_off += count;
 398:         else
 399:             n = m_free(n);
 400:     } while (len > 0 && n);
 401:     if (len > 0) {
 402:         (void) m_free(m);
 403:         goto bad;
 404:     }
 405:     m->m_next = n;
 406:     return (m);
 407: bad:
 408:     m_freem(n);
 409:     return (0);
 410: }
 411: #endif

Defined functions

m_expand defined in line 108; used 1 times
m_freem defined in line 203; used 140 times
m_more defined in line 181; used 2 times
mbinit defined in line 28; used 1 times
mbinit2 defined in line 49; used 2 times

Defined variables

mbuf defined in line 17; used 2 times
mbutl defined in line 17; used 6 times
miobase defined in line 19; used 2 times
miosize defined in line 26; used 2 times
miostart defined in line 21; never used
mioumr defined in line 23; never used
xmbuf defined in line 17; used 1 times
  • in line 42
xmbutl defined in line 18; used 1 times
  • in line 41

Defined macros

m_more defined in line 197; used 1 times
Last modified: 1992-12-25
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4337
Valid CSS Valid XHTML 1.0 Strict