/*	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 ; i<NMBUFS ; i++) {		m->m_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("<mget from %x>",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;	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("<MGET from %x>",cp->raddr);}prmfree(){	int i;	register struct call * cp = &i;	if (dof_pr) printf("[MFREE from %x]",cp->raddr);}#endif