/*
 * copyright (c) 2004
 * the regents of the university of michigan
 * all rights reserved
 * 
 * permission is granted to use, copy, create derivative works and redistribute
 * this software and such derivative works for any purpose, so long as the name
 * of the university of michigan is not used in any advertising or publicity
 * pertaining to the use or distribution of this software without specific,
 * written prior authorization.  if the above copyright notice or any other
 * identification of the university of michigan is included in any copy of any
 * portion of this software, then the disclaimer below must also be included.
 * 
 * this software is provided as is, without representation from the university
 * of michigan as to its fitness for any purpose, and without warranty by the
 * university of michigan of any kind, either express or implied, including
 * without limitation the implied warranties of merchantability and fitness for
 * a particular purpose. the regents of the university of michigan shall not be
 * liable for any damages, including special, indirect, incidental, or
 * consequential damages, with respect to any claim arising out of or in
 * connection with the use of the software, even if it has been or is hereafter
 * advised of the possibility of such damages.
 */

#ifndef _NFS4CLIENT_NFS4_GLUE_H
#define _NFS4CLIENT_NFS4_GLUE_H

#ifdef __FreeBSD__
typedef struct thread cthread_t;
#define curcthread curthread
#define cthread_ucred(ctd) (ctd)->td_ucred
#define cthread__ap(ap) ((ap)->a_td)
#define cthread__cnp(cnp) ((cnp)->cn_thread)
#define cthread_proc(ctd) (ctd)->td_proc

#define uio__td(uiop) ((uiop)->uio_td)

#define czone_nfsmnt nfsxmount_zone
#define czone_nfsnode nfsxnode_zone

#define czone_alloc(p, cast, siz, typ, fl) (p) = uma_zalloc((typ), (fl))
#define czone_free(p, siz, typ) uma_zfree((typ), (p))
#define czone_create(z, s, siz, p0, p1, p2, p3, fl, n) \
	(z) = uma_zcreate(s, siz, p0, p1, p2, p3, fl, n)
#define czone_decl(d) d

typedef struct mtx cmtx_t;
#define cmtx_init(l,s) mtx_init(l, s, NULL, MTX_DEF)
#define cmtx_lock(l) mtx_lock(l)
#define cmtx_unlock(l) mtx_unlock(l)
#define cmtx_destroy(l) mtx_destroy(l)

/* hmmm these are mysteriously missing */
#define SET(t, f)	((t) |= (f))
#define CLR(t, f)	((t) &= ~(f))
#define ISSET(t, f)	((t) & (f))

#else

#define umajor(x) major(x)
#define uminor(x) minor(x)
#define makeudev(x, y) makedev(x, y)

#define MNT_ILOCK(x)
#define MNT_IUNLOCK(x)

#define VI_LOCK(x)
#define VI_UNLOCK(x)

#define ifatoia(ifa) ((struct in_ifaddr *)(ifa))

char *strsep(char **, const char *);

typedef struct proc cthread_t;
#define cthread_proc(ctd) (ctd)
#define cthread_ucred(ctd) ((ctd)->p_ucred)
#define cthread__ap(ap) ((ap)->a_p)
#define cthread__cnp(cnp) ((cnp)->cn_proc)

#define uio__td(uiop) ((uiop)->uio_procp)

#ifdef __OpenBSD__
#define curcthread curproc
#else  /* Darwin */
#define curcthread current_proc()
#endif /* __OpenBSD__ */

typedef struct slock cmtx_t;
#define cmtx_init(l,n) simple_lock_init(l)
#define cmtx_lock(l) simple_lock(l)
#define cmtx_unlock(l) simple_unlock(l)
#define cmtx_destroy(l) /* XXX no way to destroy a simple lock! */

#define czone_nfsmnt M_NFSMNT
#define czone_nfsnode M_NFSNODE

#define czone_create
#define czone_alloc(p, cast, siz, typ, fl) \
	MALLOC_ZONE(p, cast, siz, typ, fl)

#define czone_free(p, siz, typ) FREE_ZONE(p, siz, typ)
#define czone_decl

#endif /* __FreeBSD__ */

#ifdef __APPLE__
typedef struct lock__bsd__ clk_t;
#else
typedef struct lock clk_t;
#endif /* __APPLE__ */


#ifdef __APPLE__
typedef u_quad_t uoff_t;
#endif


/* start RPC glue */

/* --------- APPLE -------- */
#if defined(__APPLE__)


#define M_TRYWAIT M_WAIT

#define SOCREATE(fam, so, type, proto, td) socreate(fam, so, type, proto)

#define SOSETOPT(error, so, proto, optname, opttype, opt) do {	\
  struct sockopt sockopt;					\
  opttype optval;						\
								\
  optval = opt;							\
  bzero(&sockopt, sizeof(struct sockopt));			\
  sockopt.sopt_dir = SOPT_SET;					\
  sockopt.sopt_level = proto;					\
  sockopt.sopt_name = optname;					\
  sockopt.sopt_val = &optval;					\
  sockopt.sopt_valsize = sizeof(optval);			\
								\
  error = sosetopt(so, &sockopt);				\
} while(0)

#define SOBIND(error, so, family, addr, port, td) do {	\
  struct sockaddr_in sin;					\
								\
  sin.sin_len = sizeof(struct sockaddr_in);			\
  sin.sin_family = family;					\
  sin.sin_addr.s_addr = addr;					\
  sin.sin_port = htons(port);					\
  error = sobind(so, (struct sockaddr *) &sin);			\
} while(0)  

#include <machine/spl.h>
#define SPLNET() splnet()

#define SOCONNECT(so, saddr, td) soconnect(so, saddr)

#define SOSEND(so, nam, uio, top, control, flags, td) sosend(so, nam, uio, top, control, flags)

#define M_LENGTH(len, mb) do {					\
  struct mbuf * m2;						\
  len = 0;							\
  for (m2 = mb; m2 != NULL; m2 = m2->m_next)			\
    len += m2->m_len;						\
} while(0)

#include <sys/random.h>
#define RANDOM(X) read_random(&(X), sizeof(X))
/* -------- FreeBSD -------- */
#elif defined(__FreeBSD__) 

#define SOCREATE(fam, so, type, proto, td) socreate(fam, so, type, proto, (td)->td_ucred, td)

#define SOSETOPT(error, so, proto, optname, opttype, opt) do {	\
  struct sockopt sockopt;					\
  opttype optval;						\
								\
  optval = opt;							\
  bzero(&sockopt, sizeof(struct sockopt));			\
  sockopt.sopt_dir = SOPT_SET;					\
  sockopt.sopt_level = proto;					\
  sockopt.sopt_name = optname;					\
  sockopt.sopt_val = &optval;					\
  sockopt.sopt_valsize = sizeof(optval);			\
								\
  error = sosetopt(so, &sockopt);				\
} while(0)

#define SOBIND(error, so, family, addr, port, td) do {	\
  struct sockaddr_in sin;					\
								\
  sin.sin_len = sizeof(struct sockaddr_in);			\
  sin.sin_family = family;					\
  sin.sin_addr.s_addr = addr;					\
  sin.sin_port = htons(port);					\
  error = sobind(so, (struct sockaddr *) &sin, td);		\
} while(0)

#define SPLNET() splnet()

#define SOCONNECT(so, saddr, td) soconnect(so, saddr, td)

#define SOSEND(so, nam, uio, top, control, flags, td) sosend(so, nam, uio, top, control, flags, td)

#define M_LENGTH(len, mb) do {					\
  len = m_length(mb, NULL);						\
} while(0)

#define RANDOM(X) (X) = arc4random()


/* --------- OpennBSD ---------- */
#elif defined(__OpenBSD__) 

#define SOCREATE(fam, so, type, proto, td) socreate(fam, so, type, proto)

#define SOSETOPT(error, so, proto, optname, opttype, opt) do {	\
  struct mbuf *mopt;						\
  opttype *optval;						\
								\
  MGET(mopt, M_TRYWAIT, MT_SOOPTS);				\
  mopt->m_len = sizeof(opttype);				\
  optval = mtod(mopt, opttype *); 				\
  *optval = opt;						\
  error = sosetopt(so, proto, optname, mopt);			\
  free_m(mopt);							\
} while(0)

#define SOBIND(error, so, family, addr, port, td) do {	\
  struct mbuf * msock;						\
  struct sockaddr_in * sinp;					\
  								\
  MGET(msock, M_TRYWAIT, MT_SONAME);					\
  sin = mtod(m, struct sockaddr_in *);				\
  sin->sin_len = m->m_len = sizeof(struct sockaddr_in);		\
  sin->sin_family = family;					\
  sin->sin_addr.s_addr = addr;					\
  sin->sin_port = htons(port);					\
  error = sobind(so, msock);					\
  m_freem(m);							\
} while(0)

#define SPLNET() splsoftnet()

#define SOCONNECT(so, saddr, td) soconnect(so, saddr)

#define SOSEND(so, nam, uio, top, control, flags, td) sosend(so, nam, uio, top, control, flags)

#define M_LENGTH(len, mb) do {					\
  struct mbuf * m2;						\
  len = 0;							\
  for (m2 = mb; m2 != NULL; m2 = m2->m_next)			\
    len += m2->m_len;						\
} while(0)

#define RANDOM(X) (X) = arc4random()

#endif
/* end RPC glue */



#endif /* _NFS4CLIENT_NFS4_GLUE_H */
