/********************************************************Copyright.IBM*****/
/*                                                                        */
/*                                                                        */
/*      Multi-Protocol Transport Services - mbuf.h                        */
/*                                                                        */
/*      Licensed Materials - Property of IBM (R)                          */
/*      5622-069                                                          */
/*      (C) Copyright IBM Corp. 1993, All right reserved.                 */
/*      US Government Users Restricted Rights - Use, duplication,         */
/*      disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */
/*                                                                        */
/********************************************************Copyright.IBM*****/




/* IBM COPYRIGHT 1989 */
/*
 * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that this notice is preserved and that due credit is given
 * to the University of California at Berkeley. The name of the University
 * may not be used to endorse or promote products derived from this
 * software without specific prior written permission. This software
 * is provided ``as is'' without express or implied warranty.
 *
 *      @(#)mbuf.h      7.8.1.2 (Berkeley) 2/8/88
 */
#define  BYTES_IN_CLUSTER    (512+sizeof(int))   /* int for cluster no.*/
#define  MB_CLBYTES          (BYTES_IN_CLUSTER - sizeof(int))
#define  MB_CLSIZE           1

#define CLBYTES   MB_CLBYTES
#define MCLBYTES         512
#define  SELECTOR_MASK       (0xFFFF0000L | (~(MCLBYTES - 1)))

/*
 * Constants related to memory allocator.
 */
#define MSIZE           128                     /* size of an mbuf        */

#define MMINOFF         12                      /* mbuf header length     */
#define MTAIL           4
#define MMAXOFF         (MSIZE-MTAIL)           /* offset where data ends */
#define MLEN            (MSIZE-MMINOFF-MTAIL)   /* mbuf data length       */
#define NMBCLUSTERS     256
#define NMBPCL          (MB_CLBYTES/MSIZE)      /* # mbufs per cluster    */

/*
 * Macros for type conversion
 */

/* network mbuf to cluster number */
#define mtocl(x) (* ((int *)((((u_long)x) & SELECTOR_MASK)+ MB_CLBYTES) ))

/* address in mbuf to mbuf head */
#define dtom(x)         ((struct mbuf *)((u_long)x & ~(MSIZE-1)))

/* mbuf head, to typed data */
#define mtod(x,t)       ((t)((u_long)(x) + (x)->m_off))

struct mbuf {
        struct  mbuf *m_next;           /* next buffer in chain */
        u_long  m_off;                  /* offset of data */
        short   m_len;                  /* amount of data in this mbuf */
        short   m_type;                 /* mbuf type (0 == free) */
        u_char  m_dat[MLEN];            /* data storage */
        struct  mbuf *m_act;            /* link in higher-level mbuf list */
};

/* mbuf types */
#define MT_FREE         0       /* should be on free list */
#define MT_DATA         1       /* dynamic (data) allocation */
#define MT_HEADER       2       /* packet header */
#define MT_SOCKET       3       /* socket structure */
#define MT_PCB          4       /* protocol control block */
#define MT_RTABLE       5       /* routing tables */
#define MT_HTABLE       6       /* IMP host tables */
#define MT_ATABLE       7       /* address resolution tables */
#define MT_SONAME       8       /* socket name */
#define MT_ZOMBIE       9       /* zombie proc status */
#define MT_SOOPTS       10      /* socket options */
#define MT_FTABLE       11      /* fragment reassembly header */
#define MT_RIGHTS       12      /* access rights */
#define MT_IFADDR       13      /* interface address */

/* flags to m_get */
#define M_DONTWAIT      0
#define M_WAIT          1

/* flags to m_pgalloc */
#define MPG_MBUFS       0               /* put new mbufs on free list */
#define MPG_CLUSTERS    1               /* put new clusters on free list */
#define MPG_SPACE       2               /* don't free; caller wants space */

/* length to m_copy to copy all */
#define M_COPYALL       0x7FFF
/*
 * m_pullup will pull up additional length if convenient;
 * should be enough to hold headers of second-level and higher protocols.
 */
#define MPULL_EXTRA     32

#define MGET(m, i, t) \
        { splimp(); \
          if ((m)=mfree) \
                { if ((m)->m_type != MT_FREE) panic("mget"); (m)->m_type = t; \
                  mbstat.m_mtypes[MT_FREE]--; mbstat.m_mtypes[t]++; \
                  mfree = (m)->m_next; (m)->m_next = (struct mbuf *)0; \
                  (m)->m_off = MMINOFF; } \
          else \
                (m) = m_more(i, t); \
          splx(); }
/*
 * Mbuf page cluster macros.
 * MCLALLOC allocates mbuf page clusters.
 * Note that it works only with a count of 1 at the moment.
 * MCLGET adds such clusters to a normal mbuf.
 * m->m_len is set to MB_CLBYTES upon success.
 * MCLFREE frees clusters allocated by MCLALLOC.
 */
#define MCLALLOC(m, i) \
        { splimp(); \
          if (mclfree == (struct mbuf *)0) \
                (void)m_clalloc((i), MPG_CLUSTERS, M_DONTWAIT); \
          if (((m)=mclfree)!=(struct mbuf *)0) \
             {++mclrefcnt[mtocl(m)];mbstat.m_clfree--;mclfree = (m)->m_next;} \
          splx(); }
#define M_HASCL(m)      ((m)->m_off >= MSIZE)
#define MTOCL(m)        ((struct mbuf *)( (mtod(m,u_long)) & SELECTOR_MASK))

#define MCLGET(m) \
        { struct mbuf *p; \
          MCLALLOC(p, 1); \
          if (p!=(struct mbuf *)0) { \
                (m)->m_off = ((u_long)p) - ((u_long)(m)); \
                (m)->m_len = MCLBYTES; \
          } else \
                (m)->m_len = MLEN; \
        }
#define MCLFREE(m) { \
        if (--mclrefcnt[mtocl(m)] == 0) \
            { (m)->m_next = mclfree;mclfree = (m);mbstat.m_clfree++;} \
        }
#define MFREE(m, n) \
        { splimp(); \
          if ((m)->m_type == MT_FREE) panic("mfree"); \
          mbstat.m_mtypes[(m)->m_type]--; mbstat.m_mtypes[MT_FREE]++; \
          (m)->m_type = MT_FREE; \
          if (M_HASCL(m)) { \
                (n) = MTOCL(m); \
                MCLFREE(n); \
          } \
          (n) = (m)->m_next; (m)->m_next = mfree; \
          (m)->m_off = 0; (m)->m_act = 0; mfree = (m); \
          splx(); \
          if (m_want) { \
                  m_want = 0; \
                  wakeup((caddr_t)&mfree); \
          } \
        }

/*
 * Mbuf statistics.
 */
struct mbstat {
        short   m_mbufs;        /* mbufs obtained from page pool */
        short   m_clusters;     /* clusters obtained from page pool */
        short   m_clfree;       /* free clusters */
        short   m_drops;        /* times failed to find space */
        u_long  m_wait;         /* times waited for space */
        short   m_mtypes[256];  /* type specific mbuf allocations */
};

extern struct  mbstat mbstat;
extern struct  mbuf *mfree, *mclfree;
extern char    mclrefcnt[];
extern int     m_want;

struct  mbuf *m_get(),*m_getclr(),*m_free(),*m_more(),*m_copy(),*m_pullup();
caddr_t m_clalloc();
