/* mbuf.c 1.36 82/06/20 */ #include "sys/param.h" #include "sys/config.h" #include "sys/types.h" #include "sys/mmu.h" #include "sys/sysmacros.h" #include "sys/dir.h" #include "sys/signal.h" #include "sys/errno.h" #include "sys/user.h" #include "sys/proc.h" #include "net/misc.h" #include "net/mbuf.h" #include "sys/map.h" #include "net/in_systm.h" /* XXX */ /* some random constants, ints */ /* THIS SHOULD BE AN EVEN CLICK NUMBER OF BYTES !!! */ /* #define IOSIZE 8192 /* area for DMA buffers */ #define IOSIZE 0 /* no space for DMA buffers for multibus */ /* unsigned int miosize = IOSIZE; */ unsigned int miobase; /* loc of DMA area. */ /* * Initialize the buffer pool. Called from netinit/main. */ mbinit() { register i; register struct mbuf *m; extern struct mbuf * mballoc(); /* allocate mbuf io area. iomalloc is machine-dependent... */ /* miobase = mbioalloc(btoc(miosize)); */ miobase = mbioalloc(); /* link the mbufs */ m = mballoc(); /* printf("mbufs at %x\n", m); */ mbstat.m_mbufs = NMBUFS; for(i=0 ; im_off = 0; m->m_free = 0; bzero((char *)m, MSIZE); (void) m_free(m); m++; } } /* NEED SOME WAY TO RELEASE SPACE */ /* * Space allocation routines. * These are also available as macros * for critical paths. */ /* ARGSUSED */ struct mbuf * m_get(canwait) int canwait; { register struct mbuf *m; #ifdef PRMDEF struct call { long local; long frmptr; long raddr; }; int i; register struct call * cp = &i; extern dog_pr; register olddogpr = dog_pr; if (dog_pr) {printf("",cp->raddr); dog_pr = 0;} #endif MGET(m, canwait); #ifdef PRMDEF if (olddogpr) dog_pr = 1; #endif return (m); } struct mbuf * m_free(m) struct mbuf *m; { register struct mbuf *n; MFREE(m, n); return (n); } m_freem(m) register struct mbuf *m; { register struct mbuf *n; register int s; if (m == NULL) return; s = splimp(); do { MFREE(m, n); } while (m = n); splx(s); } /* * Mbuffer utility routines. */ struct mbuf * m_copy(m, off, len) register struct mbuf *m; int off; register int len; { register struct mbuf *n, **np; struct mbuf *top; if (len == 0) return (0); if (off < 0 || len < 0) panic("m_copy1"); while (off > 0) { if (m == 0) panic("m_copy2"); if (off < m->m_len) break; off -= m->m_len; m = m->m_next; } MAPSAVE(); np = ⊤ top = 0; while (len > 0) { if (m == 0) { if (len != M_COPYALL) panic("m_copy3"); break; } MGET(n, 1); *np = n; if (n == 0) goto nospace; n->m_len = MIN(len, m->m_len - off); { n->m_off = MMINOFF; MBCOPY(m,off,n,0,(unsigned)n->m_len); } if (len != M_COPYALL) len -= n->m_len; off = 0; m = m->m_next; np = &n->m_next; } goto out; nospace: m_freem(top); top = 0; out: MAPREST(); return (top); } m_cat(m, n) register struct mbuf *m, *n; { while (m->m_next) m = m->m_next; while (n) { if (m->m_off >= MMAXOFF || m->m_off + m->m_len + n->m_len > MMAXOFF) { /* just join the two chains */ m->m_next = n; return; } /* splat the data from one into the other */ MBCOPY(n, 0, m, m->m_len, (u_int)n->m_len); m->m_len += n->m_len; n = m_free(n); } } m_adj(mp, len) struct mbuf *mp; register int len; { register struct mbuf *m, *n; if ((m = mp) == NULL) return; if (len >= 0) { while (m != NULL && len > 0) { if (m->m_len <= len) { len -= m->m_len; m->m_len = 0; m = m->m_next; } else { m->m_len -= len; m->m_off += len; break; } } } else { /* a 2 pass algorithm might be better */ len = -len; while (len > 0 && m->m_len != 0) { while (m != NULL && m->m_len != 0) { n = m; m = m->m_next; } if (n->m_len <= len) { len -= n->m_len; n->m_len = 0; m = mp; } else { n->m_len -= len; break; } } } } struct mbuf * m_pullup(m0, len) struct mbuf *m0; int len; { register struct mbuf *m, *n; int count; n = m0; if (len > MLEN) goto bad; MGET(m, 0); if (m == 0) goto bad; m->m_off = MMINOFF; m->m_len = 0; do { count = MIN(MLEN - m->m_len, len); if (count > n->m_len) count = n->m_len; MBCOPY(n, 0, m, m->m_len, (u_int)count); len -= count; m->m_len += count; n->m_off += count; n->m_len -= count; if (n->m_len) break; n = m_free(n); } while (n); if (len) { (void) m_free(m); goto bad; } m->m_next = n; return (m); bad: m_freem(n); return (0); } #ifdef notdef /* * Allocate a contiguous buffer for DMA IO. Called from if_ubainit(). * TODO: fix net device drivers to handle scatter/gather to mbufs * on their own; thus avoiding the copy to/from this area. */ unsigned int m_ioget(size) { unsigned int base; size = ((size + 077) & ~077); /* round up byte size */ if (size > miosize) return(0); miosize -= size; base = miobase; miobase += size; return(base); } #endif #ifdef debug mbprint(m,s) register struct mbuf *m; char *s; { extern enprint; register char *ba; int col,i,bc; if (enprint == 0) return; MAPSAVE(); nprintf("MB %s\n",s); for (;;) { if (m == 0) break; ba = mtod(m, char *); col = 0; bc = m->m_len; nprintf("m%o next%o off%o len%o act%o free%o\n", m, m->m_next, m->m_off, m->m_len, m->m_click, m->m_free); for(; bc ; bc--) { i = *ba++ & 0377; nprintf("%o ",i); if(++col > 31) { col = 0; nprintf("\n "); } } nprintf("\n"); m = m->m_next; } MAPREST(); } #else mbprint(m,s) register struct mbuf *m; char *s; { #ifdef lint mbprint(m, s); #endif } #endif debug #ifdef notdef mcheck(m, msg) struct mbuf *m; char * msg; { extern char mbufbufs[]; extern struct mbuf * mfreep; register x, ret = 0; x = spl7(); if ( ((m < (struct mbuf *)&mbufbufs[0]) && (m != 0)) || (m > (struct mbuf *)&mbufbufs[(NMBUFS+1)*MSIZE]) || ((mfreep < (struct mbuf *)&mbufbufs[0]) && (mfreep != 0)) || (mfreep > (struct mbuf *)&mbufbufs[(NMBUFS+1)*MSIZE]) ) { printf ("mcheck fail; m, mfreep = %x, %x, from %s\n", m,mfreep,msg); ret = 1; } splx(x); return ret; } #endif #ifdef PRMDEF struct call { long local; long frmptr; long raddr; }; int dog_pr; int dof_pr; prmget() { int i; register struct call * cp = &i; if (dog_pr) printf("",cp->raddr); } prmfree() { int i; register struct call * cp = &i; if (dof_pr) printf("[MFREE from %x]",cp->raddr); } #endif