code:
/*-
 * Copyright (c) 1989, 1991, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	@(#)mount.h	8.21 (Berkeley) 5/20/95
 * $FreeBSD: release/9.0.0/sys/sys/mount.h 224294 2011-07-24 18:27:09Z mckusick $
 */

#ifndef _SYS_MOUNT_H_
#define _SYS_MOUNT_H_

#include <sys/ucred.h>
#include <sys/queue.h>
#ifdef _KERNEL
#include <sys/lock.h>
#include <sys/lockmgr.h>
#include <sys/_mutex.h>
#endif

/*
 * NOTE: When changing statfs structure, mount structure, MNT_* flags or
 * MNTK_* flags also update DDB show mount command in vfs_subr.c.
 */

typedef struct fsid { int32_t val[2]; } fsid_t;	/* filesystem id type */

/*
 * File identifier.
 * These are unique per filesystem on a single machine.
 */
#define	MAXFIDSZ	16

struct fid {
	u_short		fid_len;		/* length of data in bytes */
	u_short		fid_data0;		/* force longword alignment */
	char		fid_data[MAXFIDSZ];	/* data (variable length) */
};

/*
 * filesystem statistics
 */
#define	MFSNAMELEN	16		/* length of type name including null */
#define	MNAMELEN	88		/* size of on/from name bufs */
#define	STATFS_VERSION	0x20030518	/* current version number */
struct statfs {
	uint32_t f_version;		/* structure version number */
	uint32_t f_type;		/* type of filesystem */
	uint64_t f_flags;		/* copy of mount exported flags */
	uint64_t f_bsize;		/* filesystem fragment size */
	uint64_t f_iosize;		/* optimal transfer block size */
	uint64_t f_blocks;		/* total data blocks in filesystem */
	uint64_t f_bfree;		/* free blocks in filesystem */
	int64_t	 f_bavail;		/* free blocks avail to non-superuser */
	uint64_t f_files;		/* total file nodes in filesystem */
	int64_t	 f_ffree;		/* free nodes avail to non-superuser */
	uint64_t f_syncwrites;		/* count of sync writes since mount */
	uint64_t f_asyncwrites;		/* count of async writes since mount */
	uint64_t f_syncreads;		/* count of sync reads since mount */
	uint64_t f_asyncreads;		/* count of async reads since mount */
	uint64_t f_spare[10];		/* unused spare */
	uint32_t f_namemax;		/* maximum filename length */
	uid_t	  f_owner;		/* user that mounted the filesystem */
	fsid_t	  f_fsid;		/* filesystem id */
	char	  f_charspare[80];	    /* spare string space */
	char	  f_fstypename[MFSNAMELEN]; /* filesystem type name */
	char	  f_mntfromname[MNAMELEN];  /* mounted filesystem */
	char	  f_mntonname[MNAMELEN];    /* directory on which mounted */
};

#ifdef _KERNEL
#define	OMFSNAMELEN	16	/* length of fs type name, including null */
#define	OMNAMELEN	(88 - 2 * sizeof(long))	/* size of on/from name bufs */

/* XXX getfsstat.2 is out of date with write and read counter changes here. */
/* XXX statfs.2 is out of date with read counter changes here. */
struct ostatfs {
	long	f_spare2;		/* placeholder */
	long	f_bsize;		/* fundamental filesystem block size */
	long	f_iosize;		/* optimal transfer block size */
	long	f_blocks;		/* total data blocks in filesystem */
	long	f_bfree;		/* free blocks in fs */
	long	f_bavail;		/* free blocks avail to non-superuser */
	long	f_files;		/* total file nodes in filesystem */
	long	f_ffree;		/* free file nodes in fs */
	fsid_t	f_fsid;			/* filesystem id */
	uid_t	f_owner;		/* user that mounted the filesystem */
	int	f_type;			/* type of filesystem */
	int	f_flags;		/* copy of mount exported flags */
	long	f_syncwrites;		/* count of sync writes since mount */
	long	f_asyncwrites;		/* count of async writes since mount */
	char	f_fstypename[OMFSNAMELEN]; /* fs type name */
	char	f_mntonname[OMNAMELEN];	/* directory on which mounted */
	long	f_syncreads;		/* count of sync reads since mount */
	long	f_asyncreads;		/* count of async reads since mount */
	short	f_spares1;		/* unused spare */
	char	f_mntfromname[OMNAMELEN];/* mounted filesystem */
	short	f_spares2;		/* unused spare */
	/*
	 * XXX on machines where longs are aligned to 8-byte boundaries, there
	 * is an unnamed int32_t here.  This spare was after the apparent end
	 * of the struct until we bit off the read counters from f_mntonname.
	 */
	long	f_spare[2];		/* unused spare */
};

TAILQ_HEAD(vnodelst, vnode);

/* Mount options list */
TAILQ_HEAD(vfsoptlist, vfsopt);
struct vfsopt {
	TAILQ_ENTRY(vfsopt) link;
	char	*name;
	void	*value;
	int	len;
	int	pos;
	int	seen;
};

/*
 * Structure per mounted filesystem.  Each mounted filesystem has an
 * array of operations and an instance record.  The filesystems are
 * put on a doubly linked list.
 *
 * Lock reference:
 *	m - mountlist_mtx
 *	i - interlock
 *
 * Unmarked fields are considered stable as long as a ref is held.
 *
 */
struct mount {
	struct mtx	mnt_mtx;		/* mount structure interlock */
	int		mnt_gen;		/* struct mount generation */
#define	mnt_startzero	mnt_list
	TAILQ_ENTRY(mount) mnt_list;		/* (m) mount list */
	struct vfsops	*mnt_op;		/* operations on fs */
	struct vfsconf	*mnt_vfc;		/* configuration info */
	struct vnode	*mnt_vnodecovered;	/* vnode we mounted on */
	struct vnode	*mnt_syncer;		/* syncer vnode */
	int		mnt_ref;		/* (i) Reference count */
	struct vnodelst	mnt_nvnodelist;		/* (i) list of vnodes */
	int		mnt_nvnodelistsize;	/* (i) # of vnodes */
	int		mnt_writeopcount;	/* (i) write syscalls pending */
	int		mnt_kern_flag;		/* (i) kernel only flags */
	uint64_t	mnt_flag;		/* (i) flags shared with user */
	u_int		mnt_noasync;		/* (i) # noasync overrides */
	struct vfsoptlist *mnt_opt;		/* current mount options */
	struct vfsoptlist *mnt_optnew;		/* new options passed to fs */
	int		mnt_maxsymlinklen;	/* max size of short symlink */
	struct statfs	mnt_stat;		/* cache of filesystem stats */
	struct ucred	*mnt_cred;		/* credentials of mounter */
	void *		mnt_data;		/* private data */
	time_t		mnt_time;		/* last time written*/
	int		mnt_iosize_max;		/* max size for clusters, etc */
	struct netexport *mnt_export;		/* export list */
	struct label	*mnt_label;		/* MAC label for the fs */
	u_int		mnt_hashseed;		/* Random seed for vfs_hash */
	int		mnt_lockref;		/* (i) Lock reference count */
	int		mnt_secondary_writes;   /* (i) # of secondary writes */
	int		mnt_secondary_accwrites;/* (i) secondary wr. starts */
	struct thread	*mnt_susp_owner;	/* (i) thread owning suspension */
#define	mnt_endzero	mnt_gjprovider
	char		*mnt_gjprovider;	/* gjournal provider name */
	struct lock	mnt_explock;		/* vfs_export walkers lock */
};

struct vnode *__mnt_vnode_next(struct vnode **mvp, struct mount *mp);
struct vnode *__mnt_vnode_first(struct vnode **mvp, struct mount *mp);
void          __mnt_vnode_markerfree(struct vnode **mvp, struct mount *mp);

#define MNT_VNODE_FOREACH(vp, mp, mvp) \
	for (vp = __mnt_vnode_first(&(mvp), (mp)); \
		(vp) != NULL; vp = __mnt_vnode_next(&(mvp), (mp)))

#define MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp)			\
	__mnt_vnode_markerfree(&(mvp), (mp))

#define MNT_VNODE_FOREACH_ABORT(mp, mvp)				\
        do {								\
	  MNT_ILOCK(mp);						\
          MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp);			\
	  MNT_IUNLOCK(mp);						\
	} while (0)

#define	MNT_ILOCK(mp)	mtx_lock(&(mp)->mnt_mtx)
#define	MNT_ITRYLOCK(mp) mtx_trylock(&(mp)->mnt_mtx)
#define	MNT_IUNLOCK(mp)	mtx_unlock(&(mp)->mnt_mtx)
#define	MNT_MTX(mp)	(&(mp)->mnt_mtx)
#define	MNT_REF(mp)	(mp)->mnt_ref++
#define	MNT_REL(mp)	do {						\
	KASSERT((mp)->mnt_ref > 0, ("negative mnt_ref"));			\
	(mp)->mnt_ref--;						\
	if ((mp)->mnt_ref == 0)						\
		wakeup((mp));						\
} while (0)

#endif /* _KERNEL */

/*
 * User specifiable flags, stored in mnt_flag.
 */
#define	MNT_RDONLY	0x0000000000000001ULL /* read only filesystem */
#define	MNT_SYNCHRONOUS	0x0000000000000002ULL /* fs written synchronously */
#define	MNT_NOEXEC	0x0000000000000004ULL /* can't exec from filesystem */
#define	MNT_NOSUID	0x0000000000000008ULL /* don't honor setuid fs bits */
#define	MNT_NFS4ACLS	0x0000000000000010ULL /* enable NFS version 4 ACLs */
#define	MNT_UNION	0x0000000000000020ULL /* union with underlying fs */
#define	MNT_ASYNC	0x0000000000000040ULL /* fs written asynchronously */
#define	MNT_SUIDDIR	0x0000000000100000ULL /* special SUID dir handling */
#define	MNT_SOFTDEP	0x0000000000200000ULL /* using soft updates */
#define	MNT_NOSYMFOLLOW	0x0000000000400000ULL /* do not follow symlinks */
#define	MNT_GJOURNAL	0x0000000002000000ULL /* GEOM journal support enabled */
#define	MNT_MULTILABEL	0x0000000004000000ULL /* MAC support for objects */
#define	MNT_ACLS	0x0000000008000000ULL /* ACL support enabled */
#define	MNT_NOATIME	0x0000000010000000ULL /* dont update file access time */
#define	MNT_NOCLUSTERR	0x0000000040000000ULL /* disable cluster read */
#define	MNT_NOCLUSTERW	0x0000000080000000ULL /* disable cluster write */
#define	MNT_SUJ		0x0000000100000000ULL /* using journaled soft updates */

/*
 * NFS export related mount flags.
 */
#define	MNT_EXRDONLY	0x0000000000000080ULL	/* exported read only */
#define	MNT_EXPORTED	0x0000000000000100ULL	/* filesystem is exported */
#define	MNT_DEFEXPORTED	0x0000000000000200ULL	/* exported to the world */
#define	MNT_EXPORTANON	0x0000000000000400ULL	/* anon uid mapping for all */
#define	MNT_EXKERB	0x0000000000000800ULL	/* exported with Kerberos */
#define	MNT_EXPUBLIC	0x0000000020000000ULL	/* public export (WebNFS) */

/*
 * Flags set by internal operations,
 * but visible to the user.
 * XXX some of these are not quite right.. (I've never seen the root flag set)
 */
#define	MNT_LOCAL	0x0000000000001000ULL /* filesystem is stored locally */
#define	MNT_QUOTA	0x0000000000002000ULL /* quotas are enabled on fs */
#define	MNT_ROOTFS	0x0000000000004000ULL /* identifies the root fs */
#define	MNT_USER	0x0000000000008000ULL /* mounted by a user */
#define	MNT_IGNORE	0x0000000000800000ULL /* do not show entry in df */

/*
 * Mask of flags that are visible to statfs().
 * XXX I think that this could now become (~(MNT_CMDFLAGS))
 * but the 'mount' program may need changing to handle this.
 */
#define	MNT_VISFLAGMASK	(MNT_RDONLY	| MNT_SYNCHRONOUS | MNT_NOEXEC	| \
			MNT_NOSUID	| MNT_UNION	| MNT_SUJ	| \
			MNT_ASYNC	| MNT_EXRDONLY	| MNT_EXPORTED	| \
			MNT_DEFEXPORTED	| MNT_EXPORTANON| MNT_EXKERB	| \
			MNT_LOCAL	| MNT_USER	| MNT_QUOTA	| \
			MNT_ROOTFS	| MNT_NOATIME	| MNT_NOCLUSTERR| \
			MNT_NOCLUSTERW	| MNT_SUIDDIR	| MNT_SOFTDEP	| \
			MNT_IGNORE	| MNT_EXPUBLIC	| MNT_NOSYMFOLLOW | \
			MNT_GJOURNAL	| MNT_MULTILABEL | MNT_ACLS	| \
			MNT_NFS4ACLS)

/* Mask of flags that can be updated. */
#define	MNT_UPDATEMASK (MNT_NOSUID	| MNT_NOEXEC	| \
			MNT_SYNCHRONOUS	| MNT_UNION	| MNT_ASYNC	| \
			MNT_NOATIME | \
			MNT_NOSYMFOLLOW	| MNT_IGNORE	| \
			MNT_NOCLUSTERR	| MNT_NOCLUSTERW | MNT_SUIDDIR	| \
			MNT_ACLS	| MNT_USER | MNT_NFS4ACLS)

/*
 * External filesystem command modifier flags.
 * Unmount can use the MNT_FORCE flag.
 * XXX: These are not STATES and really should be somewhere else.
 * XXX: MNT_BYFSID collides with MNT_ACLS, but because MNT_ACLS is only used for
 *      mount(2) and MNT_BYFSID is only used for unmount(2) it's harmless.
 */
#define	MNT_UPDATE	0x0000000000010000ULL /* not real mount, just update */
#define	MNT_DELEXPORT	0x0000000000020000ULL /* delete export host lists */
#define	MNT_RELOAD	0x0000000000040000ULL /* reload filesystem data */
#define	MNT_FORCE	0x0000000000080000ULL /* force unmount or readonly */
#define	MNT_SNAPSHOT	0x0000000001000000ULL /* snapshot the filesystem */
#define	MNT_BYFSID	0x0000000008000000ULL /* specify filesystem by ID. */
#define MNT_CMDFLAGS   (MNT_UPDATE	| MNT_DELEXPORT	| MNT_RELOAD	| \
			MNT_FORCE	| MNT_SNAPSHOT	| MNT_BYFSID)
/*
 * Internal filesystem control flags stored in mnt_kern_flag.
 *
 * MNTK_UNMOUNT locks the mount entry so that name lookup cannot proceed
 * past the mount point.  This keeps the subtree stable during mounts
 * and unmounts.
 *
 * MNTK_UNMOUNTF permits filesystems to detect a forced unmount while
 * dounmount() is still waiting to lock the mountpoint. This allows
 * the filesystem to cancel operations that might otherwise deadlock
 * with the unmount attempt (used by NFS).
 *
 * MNTK_NOINSMNTQ is strict subset of MNTK_UNMOUNT. They are separated
 * to allow for failed unmount attempt to restore the syncer vnode for
 * the mount.
 */
#define MNTK_UNMOUNTF	0x00000001	/* forced unmount in progress */
#define MNTK_ASYNC	0x00000002	/* filtered async flag */
#define MNTK_SOFTDEP	0x00000004	/* async disabled by softdep */
#define MNTK_NOINSMNTQ	0x00000008	/* insmntque is not allowed */
#define	MNTK_DRAINING	0x00000010	/* lock draining is happening */
#define	MNTK_REFEXPIRE	0x00000020	/* refcount expiring is happening */
#define MNTK_EXTENDED_SHARED	0x00000040 /* Allow shared locking for more ops */
#define	MNTK_SHARED_WRITES	0x00000080 /* Allow shared locking for writes */
#define MNTK_UNMOUNT	0x01000000	/* unmount in progress */
#define	MNTK_MWAIT	0x02000000	/* waiting for unmount to finish */
#define	MNTK_SUSPEND	0x08000000	/* request write suspension */
#define	MNTK_SUSPEND2	0x04000000	/* block secondary writes */
#define	MNTK_SUSPENDED	0x10000000	/* write operations are suspended */
#define	MNTK_MPSAFE	0x20000000	/* Filesystem is MPSAFE. */
#define MNTK_LOOKUP_SHARED	0x40000000 /* FS supports shared lock lookups */
#define	MNTK_NOKNOTE	0x80000000	/* Don't send KNOTEs from VOP hooks */

#define	MNT_SHARED_WRITES(mp) (((mp) != NULL) && 	\
				((mp)->mnt_kern_flag & MNTK_SHARED_WRITES))

/*
 * Sysctl CTL_VFS definitions.
 *
 * Second level identifier specifies which filesystem. Second level
 * identifier VFS_VFSCONF returns information about all filesystems.
 * Second level identifier VFS_GENERIC is non-terminal.
 */
#define	VFS_VFSCONF		0	/* get configured filesystems */
#define	VFS_GENERIC		0	/* generic filesystem information */
/*
 * Third level identifiers for VFS_GENERIC are given below; third
 * level identifiers for specific filesystems are given in their
 * mount specific header files.
 */
#define VFS_MAXTYPENUM	1	/* int: highest defined filesystem type */
#define VFS_CONF	2	/* struct: vfsconf for filesystem given
				   as next argument */

/*
 * Flags for various system call interfaces.
 *
 * waitfor flags to vfs_sync() and getfsstat()
 */
#define MNT_WAIT	1	/* synchronously wait for I/O to complete */
#define MNT_NOWAIT	2	/* start all I/O, but do not wait for it */
#define MNT_LAZY	3	/* push data not written by filesystem syncer */
#define MNT_SUSPEND	4	/* Suspend file system after sync */

/*
 * Generic file handle
 */
struct fhandle {
	fsid_t	fh_fsid;	/* Filesystem id of mount point */
	struct	fid fh_fid;	/* Filesys specific id */
};
typedef struct fhandle	fhandle_t;

/*
 * Old export arguments without security flavor list
 */
struct oexport_args {
	int	ex_flags;		/* export related flags */
	uid_t	ex_root;		/* mapping for root uid */
	struct	xucred ex_anon;		/* mapping for anonymous user */
	struct	sockaddr *ex_addr;	/* net address to which exported */
	u_char	ex_addrlen;		/* and the net address length */
	struct	sockaddr *ex_mask;	/* mask of valid bits in saddr */
	u_char	ex_masklen;		/* and the smask length */
	char	*ex_indexfile;		/* index file for WebNFS URLs */
};

/*
 * Export arguments for local filesystem mount calls.
 */
#define	MAXSECFLAVORS	5
struct export_args {
	int	ex_flags;		/* export related flags */
	uid_t	ex_root;		/* mapping for root uid */
	struct	xucred ex_anon;		/* mapping for anonymous user */
	struct	sockaddr *ex_addr;	/* net address to which exported */
	u_char	ex_addrlen;		/* and the net address length */
	struct	sockaddr *ex_mask;	/* mask of valid bits in saddr */
	u_char	ex_masklen;		/* and the smask length */
	char	*ex_indexfile;		/* index file for WebNFS URLs */
	int	ex_numsecflavors;	/* security flavor count */
	int	ex_secflavors[MAXSECFLAVORS]; /* list of security flavors */
};

/*
 * Structure holding information for a publicly exported filesystem
 * (WebNFS). Currently the specs allow just for one such filesystem.
 */
struct nfs_public {
	int		np_valid;	/* Do we hold valid information */
	fhandle_t	np_handle;	/* Filehandle for pub fs (internal) */
	struct mount	*np_mount;	/* Mountpoint of exported fs */
	char		*np_index;	/* Index file */
};

/*
 * Filesystem configuration information. One of these exists for each
 * type of filesystem supported by the kernel. These are searched at
 * mount time to identify the requested filesystem.
 *
 * XXX: Never change the first two arguments!
 */
struct vfsconf {
	u_int	vfc_version;		/* ABI version number */
	char	vfc_name[MFSNAMELEN];	/* filesystem type name */
	struct	vfsops *vfc_vfsops;	/* filesystem operations vector */
	int	vfc_typenum;		/* historic filesystem type number */
	int	vfc_refcount;		/* number mounted of this type */
	int	vfc_flags;		/* permanent flags */
	struct	vfsoptdecl *vfc_opts;	/* mount options */
	TAILQ_ENTRY(vfsconf) vfc_list;	/* list of vfscons */
};

/* Userland version of the struct vfsconf. */
struct xvfsconf {
	struct	vfsops *vfc_vfsops;	/* filesystem operations vector */
	char	vfc_name[MFSNAMELEN];	/* filesystem type name */
	int	vfc_typenum;		/* historic filesystem type number */
	int	vfc_refcount;		/* number mounted of this type */
	int	vfc_flags;		/* permanent flags */
	struct	vfsconf *vfc_next;	/* next in list */
};

#ifndef BURN_BRIDGES
struct ovfsconf {
	void	*vfc_vfsops;
	char	vfc_name[32];
	int	vfc_index;
	int	vfc_refcount;
	int	vfc_flags;
};
#endif

/*
 * NB: these flags refer to IMPLEMENTATION properties, not properties of
 * any actual mounts; i.e., it does not make sense to change the flags.
 */
#define	VFCF_STATIC	0x00010000	/* statically compiled into kernel */
#define	VFCF_NETWORK	0x00020000	/* may get data over the network */
#define	VFCF_READONLY	0x00040000	/* writes are not implemented */
#define	VFCF_SYNTHETIC	0x00080000	/* data does not represent real files */
#define	VFCF_LOOPBACK	0x00100000	/* aliases some other mounted FS */
#define	VFCF_UNICODE	0x00200000	/* stores file names as Unicode */
#define	VFCF_JAIL	0x00400000	/* can be mounted from within a jail */
#define	VFCF_DELEGADMIN	0x00800000	/* supports delegated administration */

typedef uint32_t fsctlop_t;

struct vfsidctl {
	int		vc_vers;	/* should be VFSIDCTL_VERS1 (below) */
	fsid_t		vc_fsid;	/* fsid to operate on */
	char		vc_fstypename[MFSNAMELEN];
					/* type of fs 'nfs' or '*' */
	fsctlop_t	vc_op;		/* operation VFS_CTL_* (below) */
	void		*vc_ptr;	/* pointer to data structure */
	size_t		vc_len;		/* sizeof said structure */
	u_int32_t	vc_spare[12];	/* spare (must be zero) */
};

/* vfsidctl API version. */
#define VFS_CTL_VERS1	0x01

/*
 * New style VFS sysctls, do not reuse/conflict with the namespace for
 * private sysctls.
 * All "global" sysctl ops have the 33rd bit set:
 * 0x...1....
 * Private sysctl ops should have the 33rd bit unset.
 */
#define VFS_CTL_QUERY	0x00010001	/* anything wrong? (vfsquery) */
#define VFS_CTL_TIMEO	0x00010002	/* set timeout for vfs notification */
#define VFS_CTL_NOLOCKS	0x00010003	/* disable file locking */

struct vfsquery {
	u_int32_t	vq_flags;
	u_int32_t	vq_spare[31];
};

/* vfsquery flags */
#define VQ_NOTRESP	0x0001	/* server down */
#define VQ_NEEDAUTH	0x0002	/* server bad auth */
#define VQ_LOWDISK	0x0004	/* we're low on space */
#define VQ_MOUNT	0x0008	/* new filesystem arrived */
#define VQ_UNMOUNT	0x0010	/* filesystem has left */
#define VQ_DEAD		0x0020	/* filesystem is dead, needs force unmount */
#define VQ_ASSIST	0x0040	/* filesystem needs assistance from external
				   program */
#define VQ_NOTRESPLOCK	0x0080	/* server lockd down */
#define VQ_FLAG0100	0x0100	/* placeholder */
#define VQ_FLAG0200	0x0200	/* placeholder */
#define VQ_FLAG0400	0x0400	/* placeholder */
#define VQ_FLAG0800	0x0800	/* placeholder */
#define VQ_FLAG1000	0x1000	/* placeholder */
#define VQ_FLAG2000	0x2000	/* placeholder */
#define VQ_FLAG4000	0x4000	/* placeholder */
#define VQ_FLAG8000	0x8000	/* placeholder */

#ifdef _KERNEL
/* Point a sysctl request at a vfsidctl's data. */
#define VCTLTOREQ(vc, req)						\
	do {								\
		(req)->newptr = (vc)->vc_ptr;				\
		(req)->newlen = (vc)->vc_len;				\
		(req)->newidx = 0;					\
	} while (0)
#endif

struct iovec;
struct uio;

#ifdef _KERNEL

/*
 * vfs_busy specific flags and mask.
 */
#define	MBF_NOWAIT	0x01
#define	MBF_MNTLSTLOCK	0x02
#define	MBF_MASK	(MBF_NOWAIT | MBF_MNTLSTLOCK)

#ifdef MALLOC_DECLARE
MALLOC_DECLARE(M_MOUNT);
#endif
extern int maxvfsconf;		/* highest defined filesystem type */
extern int nfs_mount_type;	/* vfc_typenum for nfs, or -1 */

TAILQ_HEAD(vfsconfhead, vfsconf);
extern struct vfsconfhead vfsconf;

/*
 * Operations supported on mounted filesystem.
 */
struct mount_args;
struct nameidata;
struct sysctl_req;
struct mntarg;

typedef int vfs_cmount_t(struct mntarg *ma, void *data, int flags);
typedef int vfs_unmount_t(struct mount *mp, int mntflags);
typedef int vfs_root_t(struct mount *mp, int flags, struct vnode **vpp);
typedef	int vfs_quotactl_t(struct mount *mp, int cmds, uid_t uid, void *arg);
typedef	int vfs_statfs_t(struct mount *mp, struct statfs *sbp);
typedef	int vfs_sync_t(struct mount *mp, int waitfor);
typedef	int vfs_vget_t(struct mount *mp, ino_t ino, int flags,
		    struct vnode **vpp);
typedef	int vfs_fhtovp_t(struct mount *mp, struct fid *fhp,
		    int flags, struct vnode **vpp);
typedef	int vfs_checkexp_t(struct mount *mp, struct sockaddr *nam,
		    int *extflagsp, struct ucred **credanonp,
		    int *numsecflavors, int **secflavors);
typedef	int vfs_init_t(struct vfsconf *);
typedef	int vfs_uninit_t(struct vfsconf *);
typedef	int vfs_extattrctl_t(struct mount *mp, int cmd,
		    struct vnode *filename_vp, int attrnamespace,
		    const char *attrname);
typedef	int vfs_mount_t(struct mount *mp);
typedef int vfs_sysctl_t(struct mount *mp, fsctlop_t op,
		    struct sysctl_req *req);
typedef void vfs_susp_clean_t(struct mount *mp);

struct vfsops {
	vfs_mount_t		*vfs_mount;
	vfs_cmount_t		*vfs_cmount;
	vfs_unmount_t		*vfs_unmount;
	vfs_root_t		*vfs_root;
	vfs_quotactl_t		*vfs_quotactl;
	vfs_statfs_t		*vfs_statfs;
	vfs_sync_t		*vfs_sync;
	vfs_vget_t		*vfs_vget;
	vfs_fhtovp_t		*vfs_fhtovp;
	vfs_checkexp_t		*vfs_checkexp;
	vfs_init_t		*vfs_init;
	vfs_uninit_t		*vfs_uninit;
	vfs_extattrctl_t	*vfs_extattrctl;
	vfs_sysctl_t		*vfs_sysctl;
	vfs_susp_clean_t	*vfs_susp_clean;
};

vfs_statfs_t	__vfs_statfs;

#define	VFS_MOUNT(MP)		(*(MP)->mnt_op->vfs_mount)(MP)
#define	VFS_UNMOUNT(MP, FORCE)	(*(MP)->mnt_op->vfs_unmount)(MP, FORCE)
#define	VFS_ROOT(MP, FLAGS, VPP)					\
	(*(MP)->mnt_op->vfs_root)(MP, FLAGS, VPP)
#define	VFS_QUOTACTL(MP, C, U, A)					\
	(*(MP)->mnt_op->vfs_quotactl)(MP, C, U, A)
#define	VFS_STATFS(MP, SBP)	__vfs_statfs((MP), (SBP))
#define	VFS_SYNC(MP, WAIT)	(*(MP)->mnt_op->vfs_sync)(MP, WAIT)
#define VFS_VGET(MP, INO, FLAGS, VPP) \
	(*(MP)->mnt_op->vfs_vget)(MP, INO, FLAGS, VPP)
#define VFS_FHTOVP(MP, FIDP, FLAGS, VPP) \
	(*(MP)->mnt_op->vfs_fhtovp)(MP, FIDP, FLAGS, VPP)
#define VFS_CHECKEXP(MP, NAM, EXFLG, CRED, NUMSEC, SEC)	\
	(*(MP)->mnt_op->vfs_checkexp)(MP, NAM, EXFLG, CRED, NUMSEC, SEC)
#define	VFS_EXTATTRCTL(MP, C, FN, NS, N)				\
	(*(MP)->mnt_op->vfs_extattrctl)(MP, C, FN, NS, N)
#define VFS_SYSCTL(MP, OP, REQ) \
	(*(MP)->mnt_op->vfs_sysctl)(MP, OP, REQ)
#define	VFS_SUSP_CLEAN(MP) \
	({if (*(MP)->mnt_op->vfs_susp_clean != NULL)		\
	       (*(MP)->mnt_op->vfs_susp_clean)(MP); })

#define	VFS_NEEDSGIANT_(MP)						\
    ((MP) != NULL && ((MP)->mnt_kern_flag & MNTK_MPSAFE) == 0)

#define	VFS_NEEDSGIANT(MP) __extension__				\
({									\
	struct mount *_mp;						\
	_mp = (MP);							\
	VFS_NEEDSGIANT_(_mp);						\
})

#define	VFS_LOCK_GIANT(MP) __extension__				\
({									\
	int _locked;							\
	struct mount *_mp;						\
	_mp = (MP);							\
	if (VFS_NEEDSGIANT_(_mp)) {					\
		mtx_lock(&Giant);					\
		_locked = 1;						\
	} else								\
		_locked = 0;						\
	_locked;							\
})
#define	VFS_UNLOCK_GIANT(locked) do					\
{									\
	if ((locked))							\
		mtx_unlock(&Giant);					\
} while (0)
#define	VFS_ASSERT_GIANT(MP) do						\
{									\
	struct mount *_mp;						\
	_mp = (MP);							\
	if (VFS_NEEDSGIANT_(_mp))					\
		mtx_assert(&Giant, MA_OWNED);				\
} while (0)

#define VFS_KNOTE_LOCKED(vp, hint) do					\
{									\
	if (((vp)->v_vflag & VV_NOKNOTE) == 0)				\
		VN_KNOTE((vp), (hint), KNF_LISTLOCKED);			\
} while (0)

#define VFS_KNOTE_UNLOCKED(vp, hint) do					\
{									\
	if (((vp)->v_vflag & VV_NOKNOTE) == 0)				\
		VN_KNOTE((vp), (hint), 0);				\
} while (0)

#include <sys/module.h>

/*
 * Version numbers.
 */
#define VFS_VERSION_00	0x19660120
#define VFS_VERSION	VFS_VERSION_00

#define VFS_SET(vfsops, fsname, flags) \
	static struct vfsconf fsname ## _vfsconf = {		\
		.vfc_version = VFS_VERSION,			\
		.vfc_name = #fsname,				\
		.vfc_vfsops = &vfsops,				\
		.vfc_typenum = -1,				\
		.vfc_flags = flags,				\
	};							\
	static moduledata_t fsname ## _mod = {			\
		#fsname,					\
		vfs_modevent,					\
		& fsname ## _vfsconf				\
	};							\
	DECLARE_MODULE(fsname, fsname ## _mod, SI_SUB_VFS, SI_ORDER_MIDDLE)

extern	char *mountrootfsname;

/*
 * exported vnode operations
 */

int	dounmount(struct mount *, int, struct thread *);

int	kernel_mount(struct mntarg *ma, int flags);
int	kernel_vmount(int flags, ...);
struct mntarg *mount_arg(struct mntarg *ma, const char *name, const void *val, int len);
struct mntarg *mount_argb(struct mntarg *ma, int flag, const char *name);
struct mntarg *mount_argf(struct mntarg *ma, const char *name, const char *fmt, ...);
struct mntarg *mount_argsu(struct mntarg *ma, const char *name, const void *val, int len);
void	statfs_scale_blocks(struct statfs *sf, long max_size);
struct vfsconf *vfs_byname(const char *);
struct vfsconf *vfs_byname_kld(const char *, struct thread *td, int *);
void	vfs_mount_destroy(struct mount *);
void	vfs_event_signal(fsid_t *, u_int32_t, intptr_t);
void	vfs_freeopts(struct vfsoptlist *opts);
void	vfs_deleteopt(struct vfsoptlist *opts, const char *name);
int	vfs_buildopts(struct uio *auio, struct vfsoptlist **options);
int	vfs_flagopt(struct vfsoptlist *opts, const char *name, uint64_t *w,
	    uint64_t val);
int	vfs_getopt(struct vfsoptlist *, const char *, void **, int *);
int	vfs_getopt_pos(struct vfsoptlist *opts, const char *name);
char	*vfs_getopts(struct vfsoptlist *, const char *, int *error);
int	vfs_copyopt(struct vfsoptlist *, const char *, void *, int);
int	vfs_filteropt(struct vfsoptlist *, const char **legal);
void	vfs_opterror(struct vfsoptlist *opts, const char *fmt, ...);
int	vfs_scanopt(struct vfsoptlist *opts, const char *name, const char *fmt, ...);
int	vfs_setopt(struct vfsoptlist *opts, const char *name, void *value,
	    int len);
int	vfs_setopt_part(struct vfsoptlist *opts, const char *name, void *value,
	    int len);
int	vfs_setopts(struct vfsoptlist *opts, const char *name,
	    const char *value);
int	vfs_setpublicfs			    /* set publicly exported fs */
	    (struct mount *, struct netexport *, struct export_args *);
void	vfs_msync(struct mount *, int);
int	vfs_busy(struct mount *, int);
int	vfs_export			 /* process mount export info */
	    (struct mount *, struct export_args *);
void	vfs_allocate_syncvnode(struct mount *);
void	vfs_deallocate_syncvnode(struct mount *);
int	vfs_donmount(struct thread *td, int fsflags, struct uio *fsoptions);
void	vfs_getnewfsid(struct mount *);
struct cdev *vfs_getrootfsid(struct mount *);
struct	mount *vfs_getvfs(fsid_t *);      /* return vfs given fsid */
struct	mount *vfs_busyfs(fsid_t *);
int	vfs_modevent(module_t, int, void *);
void	vfs_mount_error(struct mount *, const char *, ...);
void	vfs_mountroot(void);			/* mount our root filesystem */
void	vfs_mountedfrom(struct mount *, const char *from);
void	vfs_oexport_conv(const struct oexport_args *oexp,
	    struct export_args *exp);
void	vfs_ref(struct mount *);
void	vfs_rel(struct mount *);
struct mount *vfs_mount_alloc(struct vnode *, struct vfsconf *, const char *,
	    struct ucred *);
int	vfs_suser(struct mount *, struct thread *);
void	vfs_unbusy(struct mount *);
void	vfs_unmountall(void);
extern	TAILQ_HEAD(mntlist, mount) mountlist;	/* mounted filesystem list */
extern	struct mtx mountlist_mtx;
extern	struct nfs_public nfs_pub;

/*
 * Declarations for these vfs default operations are located in
 * kern/vfs_default.c, they should be used instead of making "dummy"
 * functions or casting entries in the VFS op table to "enopnotsupp()".
 */
vfs_root_t		vfs_stdroot;
vfs_quotactl_t		vfs_stdquotactl;
vfs_statfs_t		vfs_stdstatfs;
vfs_sync_t		vfs_stdsync;
vfs_sync_t		vfs_stdnosync;
vfs_vget_t		vfs_stdvget;
vfs_fhtovp_t		vfs_stdfhtovp;
vfs_checkexp_t		vfs_stdcheckexp;
vfs_init_t		vfs_stdinit;
vfs_uninit_t		vfs_stduninit;
vfs_extattrctl_t	vfs_stdextattrctl;
vfs_sysctl_t		vfs_stdsysctl;

#else /* !_KERNEL */

#include <sys/cdefs.h>

struct stat;

__BEGIN_DECLS
int	fhopen(const struct fhandle *, int);
int	fhstat(const struct fhandle *, struct stat *);
int	fhstatfs(const struct fhandle *, struct statfs *);
int	fstatfs(int, struct statfs *);
int	getfh(const char *, fhandle_t *);
int	getfsstat(struct statfs *, long, int);
int	getmntinfo(struct statfs **, int);
int	lgetfh(const char *, fhandle_t *);
int	mount(const char *, const char *, int, void *);
int	nmount(struct iovec *, unsigned int, int);
int	statfs(const char *, struct statfs *);
int	unmount(const char *, int);

/* C library stuff */
int	getvfsbyname(const char *, struct xvfsconf *);
__END_DECLS

#endif /* _KERNEL */

#endif /* !_SYS_MOUNT_H_ */


code:
/*-
 * Copyright (c) 1992, 1993 Erik Forsberg.
 * Copyright (c) 1996, 1997 Kazutaka YOKOTA
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
 * NO EVENT SHALL I BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/sys/mouse.h 165335 2006-12-18 18:48:28Z keramida $
 */

#ifndef _SYS_MOUSE_H_
#define _SYS_MOUSE_H_

#include <sys/types.h>
#include <sys/ioccom.h>

/* ioctls */
#define MOUSE_GETSTATUS		_IOR('M', 0, mousestatus_t)
#define MOUSE_GETHWINFO		_IOR('M', 1, mousehw_t)
#define MOUSE_GETMODE		_IOR('M', 2, mousemode_t)
#define MOUSE_SETMODE		_IOW('M', 3, mousemode_t)
#define MOUSE_GETLEVEL		_IOR('M', 4, int)
#define MOUSE_SETLEVEL		_IOW('M', 5, int)
#define MOUSE_GETVARS		_IOR('M', 6, mousevar_t)
#define MOUSE_SETVARS		_IOW('M', 7, mousevar_t)
#define MOUSE_READSTATE		_IOWR('M', 8, mousedata_t)
#define MOUSE_READDATA		_IOWR('M', 9, mousedata_t)

#ifdef notyet
#define MOUSE_SETRESOLUTION	_IOW('M', 10, int)
#define MOUSE_SETSCALING	_IOW('M', 11, int)
#define MOUSE_SETRATE		_IOW('M', 12, int)
#define MOUSE_GETHWID		_IOR('M', 13, int)
#endif

#define MOUSE_SYN_GETHWINFO	_IOR('M', 100, synapticshw_t)

/* mouse status block */
typedef struct mousestatus {
    int     flags;		/* state change flags */
    int     button;		/* button status */
    int     obutton;		/* previous button status */
    int     dx;			/* x movement */
    int     dy;			/* y movement */
    int     dz;			/* z movement */
} mousestatus_t;

/* button */
#define MOUSE_BUTTON1DOWN	0x0001	/* left */
#define MOUSE_BUTTON2DOWN	0x0002	/* middle */
#define MOUSE_BUTTON3DOWN	0x0004	/* right */
#define MOUSE_BUTTON4DOWN	0x0008
#define MOUSE_BUTTON5DOWN	0x0010
#define MOUSE_BUTTON6DOWN	0x0020
#define MOUSE_BUTTON7DOWN	0x0040
#define MOUSE_BUTTON8DOWN	0x0080
#define MOUSE_MAXBUTTON		31
#define MOUSE_STDBUTTONS	0x0007		/* buttons 1-3 */
#define MOUSE_EXTBUTTONS	0x7ffffff8	/* the others (28 of them!) */
#define MOUSE_BUTTONS		(MOUSE_STDBUTTONS | MOUSE_EXTBUTTONS)

/* flags */
#define MOUSE_STDBUTTONSCHANGED	MOUSE_STDBUTTONS
#define MOUSE_EXTBUTTONSCHANGED	MOUSE_EXTBUTTONS
#define MOUSE_BUTTONSCHANGED	MOUSE_BUTTONS
#define MOUSE_POSCHANGED	0x80000000

typedef struct mousehw {
	int buttons;		/* -1 if unknown */
	int iftype;		/* MOUSE_IF_XXX */
	int type;		/* mouse/track ball/pad... */
	int model;		/* I/F dependent model ID: MOUSE_MODEL_XXX */
	int hwid;		/* I/F dependent hardware ID
				 * for the PS/2 mouse, it will be PSM_XXX_ID
				 */
} mousehw_t;

typedef struct synapticshw {
	int infoMajor;
	int infoMinor;
	int infoRot180;
	int infoPortrait;
	int infoSensor;
	int infoHardware;
	int infoNewAbs;
	int capPen;
	int infoSimplC;
	int infoGeometry;
	int capExtended;
	int capSleep;
	int capFourButtons;
	int capMultiFinger;
	int capPalmDetect;
	int capPassthrough;
} synapticshw_t;

/* iftype */
#define MOUSE_IF_UNKNOWN	(-1)
#define MOUSE_IF_SERIAL		0
#define MOUSE_IF_BUS		1
#define MOUSE_IF_INPORT		2
#define MOUSE_IF_PS2		3
#define MOUSE_IF_SYSMOUSE	4
#define MOUSE_IF_USB		5

/* type */
#define MOUSE_UNKNOWN		(-1)	/* should be treated as a mouse */
#define MOUSE_MOUSE		0
#define MOUSE_TRACKBALL		1
#define MOUSE_STICK		2
#define MOUSE_PAD		3

/* model */
#define MOUSE_MODEL_UNKNOWN		(-1)
#define MOUSE_MODEL_GENERIC		0
#define MOUSE_MODEL_GLIDEPOINT		1
#define MOUSE_MODEL_NETSCROLL		2
#define MOUSE_MODEL_NET			3
#define MOUSE_MODEL_INTELLI		4
#define MOUSE_MODEL_THINK		5
#define MOUSE_MODEL_EASYSCROLL		6
#define MOUSE_MODEL_MOUSEMANPLUS	7
#define MOUSE_MODEL_KIDSPAD		8
#define MOUSE_MODEL_VERSAPAD		9
#define MOUSE_MODEL_EXPLORER		10
#define MOUSE_MODEL_4D			11
#define MOUSE_MODEL_4DPLUS		12
#define MOUSE_MODEL_SYNAPTICS		13

typedef struct mousemode {
	int protocol;		/* MOUSE_PROTO_XXX */
	int rate;		/* report rate (per sec), -1 if unknown */
	int resolution;		/* MOUSE_RES_XXX, -1 if unknown */
	int accelfactor;	/* accelation factor (must be 1 or greater) */
	int level;		/* driver operation level */
	int packetsize;		/* the length of the data packet */
	unsigned char syncmask[2]; /* sync. data bits in the header byte */
} mousemode_t;

/* protocol */
/*
 * Serial protocols:
 *   Microsoft, MouseSystems, Logitech, MM series, MouseMan, Hitachi Tablet,
 *   GlidePoint, IntelliMouse, Thinking Mouse, MouseRemote, Kidspad,
 *   VersaPad
 * Bus mouse protocols:
 *   bus, InPort
 * PS/2 mouse protocol:
 *   PS/2
 */
#define MOUSE_PROTO_UNKNOWN	(-1)
#define MOUSE_PROTO_MS		0	/* Microsoft Serial, 3 bytes */
#define MOUSE_PROTO_MSC		1	/* Mouse Systems, 5 bytes */
#define MOUSE_PROTO_LOGI	2	/* Logitech, 3 bytes */
#define MOUSE_PROTO_MM		3	/* MM series, 3 bytes */
#define MOUSE_PROTO_LOGIMOUSEMAN 4	/* Logitech MouseMan 3/4 bytes */
#define MOUSE_PROTO_BUS		5	/* MS/Logitech bus mouse */
#define MOUSE_PROTO_INPORT	6	/* MS/ATI InPort mouse */
#define MOUSE_PROTO_PS2		7	/* PS/2 mouse, 3 bytes */
#define MOUSE_PROTO_HITTAB	8	/* Hitachi Tablet 3 bytes */
#define MOUSE_PROTO_GLIDEPOINT	9	/* ALPS GlidePoint, 3/4 bytes */
#define MOUSE_PROTO_INTELLI	10	/* MS IntelliMouse, 4 bytes */
#define MOUSE_PROTO_THINK	11	/* Kensington Thinking Mouse, 3/4 bytes */
#define MOUSE_PROTO_SYSMOUSE	12	/* /dev/sysmouse */
#define MOUSE_PROTO_X10MOUSEREM	13	/* X10 MouseRemote, 3 bytes */
#define MOUSE_PROTO_KIDSPAD	14	/* Genius Kidspad */
#define MOUSE_PROTO_VERSAPAD	15	/* Interlink VersaPad, 6 bytes */
#define MOUSE_PROTO_JOGDIAL	16	/* Vaio's JogDial */
#define MOUSE_PROTO_GTCO_DIGIPAD	17

#define MOUSE_RES_UNKNOWN	(-1)
#define MOUSE_RES_DEFAULT	0
#define MOUSE_RES_LOW		(-2)
#define MOUSE_RES_MEDIUMLOW	(-3)
#define MOUSE_RES_MEDIUMHIGH	(-4)
#define MOUSE_RES_HIGH		(-5)

typedef struct mousedata {
	int len;		/* # of data in the buffer */
	int buf[16];		/* data buffer */
} mousedata_t;

#if (defined(MOUSE_GETVARS))

typedef struct mousevar {
	int var[16];
} mousevar_t;

/* magic numbers in var[0] */
#define MOUSE_VARS_PS2_SIG	0x00325350	/* 'PS2' */
#define MOUSE_VARS_BUS_SIG	0x00535542	/* 'BUS' */
#define MOUSE_VARS_INPORT_SIG	0x00504e49	/* 'INP' */

#endif /* MOUSE_GETVARS */

/* Synaptics Touchpad */
#define MOUSE_SYNAPTICS_PACKETSIZE	6	/* '3' works better */

/* Microsoft Serial mouse data packet */
#define MOUSE_MSS_PACKETSIZE	3
#define MOUSE_MSS_SYNCMASK	0x40
#define MOUSE_MSS_SYNC		0x40
#define MOUSE_MSS_BUTTONS	0x30
#define MOUSE_MSS_BUTTON1DOWN	0x20	/* left */
#define MOUSE_MSS_BUTTON2DOWN	0x00	/* no middle button */
#define MOUSE_MSS_BUTTON3DOWN	0x10	/* right */

/* Logitech MouseMan data packet (M+ protocol) */
#define MOUSE_LMAN_BUTTON2DOWN	0x20	/* middle button, the 4th byte */

/* ALPS GlidePoint extension (variant of M+ protocol) */
#define MOUSE_ALPS_BUTTON2DOWN	0x20	/* middle button, the 4th byte */
#define MOUSE_ALPS_TAP		0x10	/* `tapping' action, the 4th byte */

/* Kinsington Thinking Mouse extension (variant of M+ protocol) */
#define MOUSE_THINK_BUTTON2DOWN 0x20	/* lower-left button, the 4th byte */
#define MOUSE_THINK_BUTTON4DOWN 0x10	/* lower-right button, the 4th byte */

/* MS IntelliMouse (variant of MS Serial) */
#define MOUSE_INTELLI_PACKETSIZE 4
#define MOUSE_INTELLI_BUTTON2DOWN 0x10	/* middle button in the 4th byte */

/* Mouse Systems Corp. mouse data packet */
#define MOUSE_MSC_PACKETSIZE	5
#define MOUSE_MSC_SYNCMASK	0xf8
#define MOUSE_MSC_SYNC		0x80
#define MOUSE_MSC_BUTTONS	0x07
#define MOUSE_MSC_BUTTON1UP	0x04	/* left */
#define MOUSE_MSC_BUTTON2UP	0x02	/* middle */
#define MOUSE_MSC_BUTTON3UP	0x01	/* right */
#define MOUSE_MSC_MAXBUTTON	3

/* MM series mouse data packet */
#define MOUSE_MM_PACKETSIZE	3
#define MOUSE_MM_SYNCMASK	0xe0
#define MOUSE_MM_SYNC		0x80
#define MOUSE_MM_BUTTONS	0x07
#define MOUSE_MM_BUTTON1DOWN	0x04	/* left */
#define MOUSE_MM_BUTTON2DOWN	0x02	/* middle */
#define MOUSE_MM_BUTTON3DOWN	0x01	/* right */
#define MOUSE_MM_XPOSITIVE	0x10
#define MOUSE_MM_YPOSITIVE	0x08

/* PS/2 mouse data packet */
#define MOUSE_PS2_PACKETSIZE	3
#define MOUSE_PS2_SYNCMASK	0xc8
#define MOUSE_PS2_SYNC		0x08
#define MOUSE_PS2_BUTTONS	0x07	/* 0x03 for 2 button mouse */
#define MOUSE_PS2_BUTTON1DOWN	0x01	/* left */
#define MOUSE_PS2_BUTTON2DOWN	0x04	/* middle */
#define MOUSE_PS2_BUTTON3DOWN	0x02	/* right */
#define MOUSE_PS2_TAP		MOUSE_PS2_SYNC /* GlidePoint (PS/2) `tapping'
					        * Yes! this is the same bit
						* as SYNC!
					 	*/

#define MOUSE_PS2_XNEG		0x10
#define MOUSE_PS2_YNEG		0x20
#define MOUSE_PS2_XOVERFLOW	0x40
#define MOUSE_PS2_YOVERFLOW	0x80

/* Logitech MouseMan+ (PS/2) data packet (PS/2++ protocol) */
#define MOUSE_PS2PLUS_SYNCMASK	0x48
#define MOUSE_PS2PLUS_SYNC	0x48
#define MOUSE_PS2PLUS_ZNEG	0x08	/* sign bit */
#define MOUSE_PS2PLUS_BUTTON4DOWN 0x10	/* 4th button on MouseMan+ */
#define MOUSE_PS2PLUS_BUTTON5DOWN 0x20

/* IBM ScrollPoint (PS/2) also uses PS/2++ protocol */
#define MOUSE_SPOINT_ZNEG	0x80	/* sign bits */
#define MOUSE_SPOINT_WNEG	0x08

/* MS IntelliMouse (PS/2) data packet */
#define MOUSE_PS2INTELLI_PACKETSIZE 4
/* some compatible mice have additional buttons */
#define MOUSE_PS2INTELLI_BUTTON4DOWN 0x40
#define MOUSE_PS2INTELLI_BUTTON5DOWN 0x80

/* MS IntelliMouse Explorer (PS/2) data packet (variation of IntelliMouse) */
#define MOUSE_EXPLORER_ZNEG	0x08	/* sign bit */
/* IntelliMouse Explorer has additional button data in the fourth byte */
#define MOUSE_EXPLORER_BUTTON4DOWN 0x10
#define MOUSE_EXPLORER_BUTTON5DOWN 0x20

/* Interlink VersaPad (serial I/F) data packet */
#define MOUSE_VERSA_PACKETSIZE	6
#define MOUSE_VERSA_IN_USE	0x04
#define MOUSE_VERSA_SYNCMASK	0xc3
#define MOUSE_VERSA_SYNC	0xc0
#define MOUSE_VERSA_BUTTONS	0x30
#define MOUSE_VERSA_BUTTON1DOWN	0x20	/* left */
#define MOUSE_VERSA_BUTTON2DOWN	0x00	/* middle */
#define MOUSE_VERSA_BUTTON3DOWN	0x10	/* right */
#define MOUSE_VERSA_TAP		0x08

/* Interlink VersaPad (PS/2 I/F) data packet */
#define MOUSE_PS2VERSA_PACKETSIZE	6
#define MOUSE_PS2VERSA_IN_USE		0x10
#define MOUSE_PS2VERSA_SYNCMASK		0xe8
#define MOUSE_PS2VERSA_SYNC		0xc8
#define MOUSE_PS2VERSA_BUTTONS		0x05
#define MOUSE_PS2VERSA_BUTTON1DOWN	0x04	/* left */
#define MOUSE_PS2VERSA_BUTTON2DOWN	0x00	/* middle */
#define MOUSE_PS2VERSA_BUTTON3DOWN	0x01	/* right */
#define MOUSE_PS2VERSA_TAP		0x02

/* A4 Tech 4D Mouse (PS/2) data packet */
#define MOUSE_4D_PACKETSIZE		3
#define MOUSE_4D_WHEELBITS		0xf0

/* A4 Tech 4D+ Mouse (PS/2) data packet */
#define MOUSE_4DPLUS_PACKETSIZE		3
#define MOUSE_4DPLUS_ZNEG		0x04	/* sign bit */
#define MOUSE_4DPLUS_BUTTON4DOWN	0x08

/* sysmouse extended data packet */
/*
 * /dev/sysmouse sends data in two formats, depending on the protocol
 * level.  At the level 0, format is exactly the same as MousSystems'
 * five byte packet.  At the level 1, the first five bytes are the same
 * as at the level 0.  There are additional three bytes which shows
 * `dz' and the states of additional buttons.  `dz' is expressed as the
 * sum of the byte 5 and 6 which contain signed seven bit values.
 * The states of the button 4 though 10 are in the bit 0 though 6 in
 * the byte 7 respectively: 1 indicates the button is up.
 */
#define MOUSE_SYS_PACKETSIZE	8
#define MOUSE_SYS_SYNCMASK	0xf8
#define MOUSE_SYS_SYNC		0x80
#define MOUSE_SYS_BUTTON1UP	0x04	/* left, 1st byte */
#define MOUSE_SYS_BUTTON2UP	0x02	/* middle, 1st byte */
#define MOUSE_SYS_BUTTON3UP	0x01	/* right, 1st byte */
#define MOUSE_SYS_BUTTON4UP	0x0001	/* 7th byte */
#define MOUSE_SYS_BUTTON5UP	0x0002
#define MOUSE_SYS_BUTTON6UP	0x0004
#define MOUSE_SYS_BUTTON7UP	0x0008
#define MOUSE_SYS_BUTTON8UP	0x0010
#define MOUSE_SYS_BUTTON9UP	0x0020
#define MOUSE_SYS_BUTTON10UP	0x0040
#define MOUSE_SYS_MAXBUTTON	10
#define MOUSE_SYS_STDBUTTONS	0x07
#define MOUSE_SYS_EXTBUTTONS	0x7f	/* the others */

/* Mouse remote socket */
#define _PATH_MOUSEREMOTE	"/var/run/MouseRemote"

#endif /* _SYS_MOUSE_H_ */

repo_name: veiledmerc/mira

license: mit


code:
/*-
 * Copyright (c) 2008 Yahoo!, Inc.
 * All rights reserved.
 * Written by: John Baldwin <jhb@FreeBSD.org>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the author nor the names of any co-contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * LSI MPT-Fusion Host Adapter FreeBSD userland interface
 *
 * $FreeBSD: release/9.0.0/sys/sys/mpt_ioctl.h 178814 2008-05-06 20:49:53Z jhb $
 */

#ifndef _MPT_IOCTL_H_
#define	_MPT_IOCTL_H_

#include <dev/mpt/mpilib/mpi_type.h>
#include <dev/mpt/mpilib/mpi.h>
#include <dev/mpt/mpilib/mpi_cnfg.h>

/*
 * For the read header requests, the header should include the page
 * type or extended page type, page number, and page version.  The
 * buffer and length are unused.  The completed header is returned in
 * the 'header' member.
 *
 * For the read page and write page requests, 'buf' should point to a
 * buffer of 'len' bytes which holds the entire page (including the
 * header).
 *
 * All requests specify the page address in 'page_address'.
 */
struct mpt_cfg_page_req {
	CONFIG_PAGE_HEADER header;
	uint32_t page_address;
	void	*buf;
	int	len;
	uint16_t ioc_status;
};

struct mpt_ext_cfg_page_req {
	CONFIG_EXTENDED_PAGE_HEADER header;
	uint32_t page_address;
	void	*buf;
	int	len;
	uint16_t ioc_status;
};

struct mpt_raid_action {
	uint8_t action;
	uint8_t volume_bus;
	uint8_t volume_id;
	uint8_t phys_disk_num;
	uint32_t action_data_word;
	void *buf;
	int len;
	uint32_t volume_status;
	uint32_t action_data[4];
	uint16_t action_status;
	uint16_t ioc_status;
	uint8_t write;
};

#define	MPTIO_READ_CFG_HEADER	_IOWR('M', 100, struct mpt_cfg_page_req)
#define	MPTIO_READ_CFG_PAGE	_IOWR('M', 101, struct mpt_cfg_page_req)
#define	MPTIO_READ_EXT_CFG_HEADER _IOWR('M', 102, struct mpt_ext_cfg_page_req)
#define	MPTIO_READ_EXT_CFG_PAGE	_IOWR('M', 103, struct mpt_ext_cfg_page_req)
#define	MPTIO_WRITE_CFG_PAGE	_IOWR('M', 104, struct mpt_cfg_page_req)
#define	MPTIO_RAID_ACTION	_IOWR('M', 105, struct mpt_raid_action)

#if defined(__amd64__)
struct mpt_cfg_page_req32 {
	CONFIG_PAGE_HEADER header;
	uint32_t page_address;
	uint32_t buf;
	int	len;
	uint16_t ioc_status;
};

struct mpt_ext_cfg_page_req32 {
	CONFIG_EXTENDED_PAGE_HEADER header;
	uint32_t page_address;
	uint32_t buf;
	int	len;
	uint16_t ioc_status;
};

struct mpt_raid_action32 {
	uint8_t action;
	uint8_t volume_bus;
	uint8_t volume_id;
	uint8_t phys_disk_num;
	uint32_t action_data_word;
	uint32_t buf;
	int len;
	uint32_t volume_status;
	uint32_t action_data[4];
	uint16_t action_status;
	uint16_t ioc_status;
	uint8_t write;
};

#define	MPTIO_READ_CFG_HEADER32	_IOWR('M', 100, struct mpt_cfg_page_req32)
#define	MPTIO_READ_CFG_PAGE32	_IOWR('M', 101, struct mpt_cfg_page_req32)
#define	MPTIO_READ_EXT_CFG_HEADER32 _IOWR('M', 102, struct mpt_ext_cfg_page_req32)
#define	MPTIO_READ_EXT_CFG_PAGE32 _IOWR('M', 103, struct mpt_ext_cfg_page_req32)
#define	MPTIO_WRITE_CFG_PAGE32	_IOWR('M', 104, struct mpt_cfg_page_req32)
#define	MPTIO_RAID_ACTION32	_IOWR('M', 105, struct mpt_raid_action32)
#endif

#endif /* !_MPT_IOCTL_H_ */


code:
/*-
 * Copyright (c) 2005 David Xu <davidxu@freebsd.org>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/sys/mqueue.h 152948 2005-11-30 05:12:03Z davidxu $
 */

#ifndef _SYS_MQUEUE_H_
#define _SYS_MQUEUE_H_

struct mq_attr {
	long	mq_flags;	/* Message queue flags. */
	long	mq_maxmsg;	/* Maximum number of messages. */
	long	mq_msgsize;	/* Maximum message size. */
	long	mq_curmsgs;	/* Number of messages currently queued. */
	long    __reserved[4];  /* Ignored for input, zeroed for output */
};

#ifdef _KERNEL
struct thread;
struct file;
extern void	(*mq_fdclose)(struct thread *td, int fd, struct file *fp);
#endif
#endif


code:
/* $FreeBSD: release/9.0.0/sys/sys/msg.h 220388 2011-04-06 16:59:54Z trasz $ */
/*	$NetBSD: msg.h,v 1.4 1994/06/29 06:44:43 cgd Exp $	*/

/*-
 * SVID compatible msg.h file
 *
 * Author:  Daniel Boulet
 *
 * Copyright 1993 Daniel Boulet and RTMX Inc.
 *
 * This system call was implemented by Daniel Boulet under contract from RTMX.
 *
 * Redistribution and use in source forms, with and without modification,
 * are permitted provided that this entire comment appears intact.
 *
 * Redistribution in binary form may occur without any restrictions.
 * Obviously, it would be nice if you gave credit where credit is due
 * but requiring it would be too onerous.
 *
 * This software is provided ``AS IS'' without any warranties of any kind.
 */

#ifndef _SYS_MSG_H_
#define _SYS_MSG_H_

#include <sys/cdefs.h>
#include <sys/_types.h>
#include <sys/ipc.h>

/*
 * The MSG_NOERROR identifier value, the msqid_ds struct and the msg struct
 * are as defined by the SV API Intel 386 Processor Supplement.
 */

#define MSG_NOERROR	010000		/* don't complain about too long msgs */

typedef	unsigned long	msglen_t;
typedef	unsigned long	msgqnum_t;

#ifndef _PID_T_DECLARED
typedef	__pid_t		pid_t;
#define	_PID_T_DECLARED
#endif

#ifndef _SIZE_T_DECLARED
typedef	__size_t	size_t;
#define	_SIZE_T_DECLARED
#endif

#ifndef _SSIZE_T_DECLARED
typedef	__ssize_t	ssize_t;
#define	_SSIZE_T_DECLARED
#endif

#ifndef _TIME_T_DECLARED
typedef	__time_t	time_t;
#define	_TIME_T_DECLARED
#endif

#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
    defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
struct msqid_ds_old {
	struct	ipc_perm_old msg_perm;	/* msg queue permission bits */
	struct	msg *msg_first;	/* first message in the queue */
	struct	msg *msg_last;	/* last message in the queue */
	msglen_t msg_cbytes;	/* number of bytes in use on the queue */
	msgqnum_t msg_qnum;	/* number of msgs in the queue */
	msglen_t msg_qbytes;	/* max # of bytes on the queue */
	pid_t	msg_lspid;	/* pid of last msgsnd() */
	pid_t	msg_lrpid;	/* pid of last msgrcv() */
	time_t	msg_stime;	/* time of last msgsnd() */
	long	msg_pad1;
	time_t	msg_rtime;	/* time of last msgrcv() */
	long	msg_pad2;
	time_t	msg_ctime;	/* time of last msgctl() */
	long	msg_pad3;
	long	msg_pad4[4];
};
#endif

/*
 * XXX there seems to be no prefix reserved for this header, so the name
 * "msg" in "struct msg" and the names of all of the nonstandard members
 * (mainly "msg_pad*) are namespace pollution.
 */

struct msqid_ds {
	struct	ipc_perm msg_perm;	/* msg queue permission bits */
	struct	msg *msg_first;	/* first message in the queue */
	struct	msg *msg_last;	/* last message in the queue */
	msglen_t msg_cbytes;	/* number of bytes in use on the queue */
	msgqnum_t msg_qnum;	/* number of msgs in the queue */
	msglen_t msg_qbytes;	/* max # of bytes on the queue */
	pid_t	msg_lspid;	/* pid of last msgsnd() */
	pid_t	msg_lrpid;	/* pid of last msgrcv() */
	time_t	msg_stime;	/* time of last msgsnd() */
	time_t	msg_rtime;	/* time of last msgrcv() */
	time_t	msg_ctime;	/* time of last msgctl() */
};

#if __BSD_VISIBLE
/*
 * Structure describing a message.  The SVID doesn't suggest any
 * particular name for this structure.  There is a reference in the
 * msgop man page that reads "The structure mymsg is an example of what
 * this user defined buffer might look like, and includes the following
 * members:".  This sentence is followed by two lines equivalent
 * to the mtype and mtext field declarations below.  It isn't clear
 * if "mymsg" refers to the name of the structure type or the name of an
 * instance of the structure...
 */
struct mymsg {
	long	mtype;		/* message type (+ve integer) */
	char	mtext[1];	/* message body */
};
#endif

#ifdef _KERNEL

struct msg {
	struct	msg *msg_next;  /* next msg in the chain */
	long	msg_type; 	/* type of this message */
				/* >0 -> type of this message */
				/* 0 -> free header */
	u_short	msg_ts;		/* size of this message */
	short	msg_spot;	/* location of start of msg in buffer */
	struct	label *label;	/* MAC Framework label */
};

/*
 * Based on the configuration parameters described in an SVR2 (yes, two)
 * config(1m) man page.
 *
 * Each message is broken up and stored in segments that are msgssz bytes
 * long.  For efficiency reasons, this should be a power of two.  Also,
 * it doesn't make sense if it is less than 8 or greater than about 256.
 * Consequently, msginit in kern/sysv_msg.c checks that msgssz is a power of
 * two between 8 and 1024 inclusive (and panic's if it isn't).
 */
struct msginfo {
	int	msgmax,		/* max chars in a message */
		msgmni,		/* max message queue identifiers */
		msgmnb,		/* max chars in a queue */
		msgtql,		/* max messages in system */
		msgssz,		/* size of a message segment (see notes above) */
		msgseg;		/* number of message segments */
};
extern struct msginfo	msginfo;

/*
 * Kernel wrapper for the user-level structure.
 */
struct msqid_kernel {
	/*
	 * Data structure exposed to user space.
	 */
	struct	msqid_ds u;

	/*
	 * Kernel-private components of the message queue.
	 */
	struct	label *label;	/* MAC label */
	struct	ucred *cred;	/* creator's credentials */
};

#else /* !_KERNEL */

__BEGIN_DECLS
int msgctl(int, int, struct msqid_ds *);
int msgget(key_t, int);
/* XXX return value should be ssize_t. */
int msgrcv(int, void *, size_t, long, int);
int msgsnd(int, const void *, size_t, int);
#if __BSD_VISIBLE
int msgsys(int, ...);
#endif
__END_DECLS

#endif /* _KERNEL */

#endif /* !_SYS_MSG_H_ */


code:
/*-
 * Copyright (c) 1981, 1984, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	@(#)msgbuf.h	8.1 (Berkeley) 6/2/93
 * $FreeBSD: release/9.0.0/sys/sys/msgbuf.h 222537 2011-05-31 17:29:58Z ken $
 */

#ifndef _SYS_MSGBUF_H_
#define	_SYS_MSGBUF_H_

#include <sys/lock.h>
#include <sys/mutex.h>

struct msgbuf {
	char	   *msg_ptr;		/* pointer to buffer */
#define	MSG_MAGIC	0x063062
	u_int	   msg_magic;
	u_int	   msg_size;		/* size of buffer area */
	u_int	   msg_wseq;		/* write sequence number */
	u_int	   msg_rseq;		/* read sequence number */
	u_int	   msg_cksum;		/* checksum of contents */
	u_int	   msg_seqmod;		/* range for sequence numbers */
	int	   msg_lastpri;		/* saved priority value */
	int	   msg_needsnl;		/* set when newline needed */
	struct mtx msg_lock;		/* mutex to protect the buffer */
};

/* Normalise a sequence number or a difference between sequence numbers. */
#define	MSGBUF_SEQNORM(mbp, seq)	(((seq) + (mbp)->msg_seqmod) % \
    (mbp)->msg_seqmod)
#define	MSGBUF_SEQ_TO_POS(mbp, seq)	((seq) % (mbp)->msg_size)
/* Subtract sequence numbers.  Note that only positive values result. */
#define	MSGBUF_SEQSUB(mbp, seq1, seq2)	(MSGBUF_SEQNORM((mbp), (seq1) - (seq2)))

#ifdef _KERNEL
extern int	msgbufsize;
extern int	msgbuftrigger;
extern struct	msgbuf *msgbufp;
extern struct	mtx msgbuf_lock;

void	msgbufinit(void *ptr, int size);
void	msgbuf_addchar(struct msgbuf *mbp, int c);
void	msgbuf_addstr(struct msgbuf *mbp, int pri, char *str, int filter_cr);
void	msgbuf_clear(struct msgbuf *mbp);
void	msgbuf_copy(struct msgbuf *src, struct msgbuf *dst);
int	msgbuf_getbytes(struct msgbuf *mbp, char *buf, int buflen);
int	msgbuf_getchar(struct msgbuf *mbp);
int	msgbuf_getcount(struct msgbuf *mbp);
void	msgbuf_init(struct msgbuf *mbp, void *ptr, int size);
int	msgbuf_peekbytes(struct msgbuf *mbp, char *buf, int buflen,
	    u_int *seqp);
void	msgbuf_reinit(struct msgbuf *mbp, void *ptr, int size);

#ifndef MSGBUF_SIZE
#define	MSGBUF_SIZE	(32768 * 2)
#endif
#endif /* KERNEL */

#endif /* !_SYS_MSGBUF_H_ */


code:
/*-
 * Copyright (c) 1982, 1986, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	@(#)mtio.h	8.1 (Berkeley) 6/2/93
 * $FreeBSD: release/9.0.0/sys/sys/mtio.h 139825 2005-01-07 02:29:27Z imp $
 */

#ifndef	_SYS_MTIO_H_
#define	_SYS_MTIO_H_

#ifndef _KERNEL
#include <sys/types.h>
#endif
#include <sys/ioccom.h>

/*
 * Structures and definitions for mag tape io control commands
 */

/* structure for MTIOCTOP - mag tape op command */
struct mtop {
	short	mt_op;		/* operations defined below */
	int32_t	mt_count;	/* how many of them */
};

/* operations */
#define MTWEOF		0	/* write an end-of-file record */
#define MTFSF		1	/* forward space file */
#define MTBSF		2	/* backward space file */
#define MTFSR		3	/* forward space record */
#define MTBSR		4	/* backward space record */
#define MTREW		5	/* rewind */
#define MTOFFL		6	/* rewind and put the drive offline */
#define MTNOP		7	/* no operation, sets status only */
#define MTCACHE		8	/* enable controller cache */
#define MTNOCACHE	9	/* disable controller cache */

#if defined(__FreeBSD__)
/* Set block size for device. If device is a variable size dev		*/
/* a non zero parameter will change the device to a fixed block size	*/
/* device with block size set to that of the parameter passed in.	*/
/* Resetting the block size to 0 will restore the device to a variable	*/
/* block size device. */

#define MTSETBSIZ	10

/* Set density values for device. Sets the value for the opened mode only. */

#define MTSETDNSTY	11

#define MTERASE		12	/* erase to EOM */
#define MTEOD		13	/* Space to EOM */
#define MTCOMP		14	/* select compression mode 0=off, 1=def */
#define MTRETENS	15	/* re-tension tape */
#define MTWSS		16	/* write setmark(s) */
#define MTFSS		17	/* forward space setmark */
#define MTBSS		18	/* backward space setmark */

#define MT_COMP_ENABLE		0xffffffff
#define MT_COMP_DISABLED	0xfffffffe
#define MT_COMP_UNSUPP		0xfffffffd

/*
 * Values in mt_dsreg that say what the device is doing
 */
#define	MTIO_DSREG_NIL	0	/* Unknown */
#define	MTIO_DSREG_REST	1	/* Doing Nothing */
#define	MTIO_DSREG_RBSY	2	/* Communicating with tape (but no motion) */
#define	MTIO_DSREG_WR	20	/* Writing */
#define	MTIO_DSREG_FMK	21	/* Writing Filemarks */
#define	MTIO_DSREG_ZER	22	/* Erasing */
#define	MTIO_DSREG_RD	30	/* Reading */
#define	MTIO_DSREG_FWD	40	/* Spacing Forward */
#define	MTIO_DSREG_REV	41	/* Spacing Reverse */
#define	MTIO_DSREG_POS	42	/* Hardware Positioning (direction unknown) */
#define	MTIO_DSREG_REW	43	/* Rewinding */
#define	MTIO_DSREG_TEN	44	/* Retensioning */
#define	MTIO_DSREG_UNL	45	/* Unloading */
#define	MTIO_DSREG_LD	46	/* Loading */

#endif	/* __FreeBSD__ */

/* structure for MTIOCGET - mag tape get status command */

struct mtget {
	short	mt_type;	/* type of magtape device */
/* the following two registers are grossly device dependent */
	short	mt_dsreg;	/* ``drive status'' register */
	short	mt_erreg;	/* ``error'' register */
/* end device-dependent registers */
	/*
	 * Note that the residual count, while maintained, may be
	 * be nonsense because the size of the residual may (greatly)
	 * exceed 32 K-bytes. Use the MTIOCERRSTAT ioctl to get a
	 * more accurate count.
	 */
	short	mt_resid;	/* residual count */
#if defined (__FreeBSD__)
	int32_t mt_blksiz;	/* presently operating blocksize */
	int32_t mt_density;	/* presently operating density */
	u_int32_t mt_comp;	/* presently operating compression */
	int32_t mt_blksiz0;	/* blocksize for mode 0 */
	int32_t mt_blksiz1;	/* blocksize for mode 1 */
	int32_t mt_blksiz2;	/* blocksize for mode 2 */
	int32_t mt_blksiz3;	/* blocksize for mode 3 */
	int32_t mt_density0;	/* density for mode 0 */
	int32_t mt_density1;	/* density for mode 1 */
	int32_t mt_density2;	/* density for mode 2 */
	int32_t mt_density3;	/* density for mode 3 */
/* the following are not yet implemented */
	u_int32_t mt_comp0;	/* compression type for mode 0 */
	u_int32_t mt_comp1;	/* compression type for mode 1 */
	u_int32_t mt_comp2;	/* compression type for mode 2 */
	u_int32_t mt_comp3;	/* compression type for mode 3 */
/* end not yet implemented */
#endif
	int32_t	mt_fileno;	/* relative file number of current position */
	int32_t	mt_blkno;	/* relative block number of current position */
};

/* structure for MTIOCERRSTAT - tape get error status command */
/* really only supported for SCSI tapes right now */
struct scsi_tape_errors {
	/*
	 * These are latched from the last command that had a SCSI
	 * Check Condition noted for these operations. The act
	 * of issuing an MTIOCERRSTAT unlatches and clears them.
	 */
	u_int8_t io_sense[32];	/* Last Sense Data For Data I/O */
	int32_t io_resid;	/* residual count from last Data I/O */
	u_int8_t io_cdb[16];	/* Command that Caused the Last Data Sense */
	u_int8_t ctl_sense[32];	/* Last Sense Data For Control I/O */
	int32_t ctl_resid;	/* residual count from last Control I/O */
	u_int8_t ctl_cdb[16];	/* Command that Caused the Last Control Sense */
	/*
	 * These are the read and write cumulative error counters.
	 * (how to reset cumulative error counters is not yet defined).
	 * (not implemented as yet but space is being reserved for them)
	 */
	struct {
		u_int32_t retries;	/* total # retries performed */
		u_int32_t corrected;	/* total # corrections performed */
		u_int32_t processed;	/* total # corrections successful */
		u_int32_t failures;	/* total # corrections/retries failed */
		u_int64_t nbytes;	/* total # bytes processed */
	} wterr, rderr;
};

union mterrstat {
	struct scsi_tape_errors scsi_errstat;
	char _reserved_padding[256];
};

/*
 * Constants for mt_type byte.  These are the same
 * for controllers compatible with the types listed.
 */
#define	MT_ISTS		0x01		/* TS-11 */
#define	MT_ISHT		0x02		/* TM03 Massbus: TE16, TU45, TU77 */
#define	MT_ISTM		0x03		/* TM11/TE10 Unibus */
#define	MT_ISMT		0x04		/* TM78/TU78 Massbus */
#define	MT_ISUT		0x05		/* SI TU-45 emulation on Unibus */
#define	MT_ISCPC	0x06		/* SUN */
#define	MT_ISAR		0x07		/* SUN */
#define	MT_ISTMSCP	0x08		/* DEC TMSCP protocol (TU81, TK50) */
#define MT_ISCY		0x09		/* CCI Cipher */
#define MT_ISCT		0x0a		/* HP 1/4 tape */
#define MT_ISFHP	0x0b		/* HP 7980 1/2 tape */
#define MT_ISEXABYTE	0x0c		/* Exabyte */
#define MT_ISEXA8200	0x0c		/* Exabyte EXB-8200 */
#define MT_ISEXA8500	0x0d		/* Exabyte EXB-8500 */
#define MT_ISVIPER1	0x0e		/* Archive Viper-150 */
#define MT_ISPYTHON	0x0f		/* Archive Python (DAT) */
#define MT_ISHPDAT	0x10		/* HP 35450A DAT drive */
#define MT_ISMFOUR	0x11		/* M4 Data 1/2 9track drive */
#define MT_ISTK50	0x12		/* DEC SCSI TK50 */
#define MT_ISMT02	0x13		/* Emulex MT02 SCSI tape controller */

/* mag tape io control commands */
#define	MTIOCTOP	_IOW('m', 1, struct mtop)	/* do a mag tape op */
#define	MTIOCGET	_IOR('m', 2, struct mtget)	/* get tape status */
/* these two do not appear to be used anywhere */
#define MTIOCIEOT	_IO('m', 3)			/* ignore EOT error */
#define MTIOCEEOT	_IO('m', 4)			/* enable EOT error */
/*
 * When more SCSI-3 SSC (streaming device) devices are out there
 * that support the full 32 byte type 2 structure, we'll have to
 * rethink these ioctls to support all the entities they haul into
 * the picture (64 bit blocks, logical file record numbers, etc..).
 */
#define	MTIOCRDSPOS	_IOR('m', 5, u_int32_t)	/* get logical blk addr */
#define	MTIOCRDHPOS	_IOR('m', 6, u_int32_t)	/* get hardware blk addr */
#define	MTIOCSLOCATE	_IOW('m', 5, u_int32_t)	/* seek to logical blk addr */
#define	MTIOCHLOCATE	_IOW('m', 6, u_int32_t)	/* seek to hardware blk addr */
#define	MTIOCERRSTAT	_IOR('m', 7, union mterrstat)	/* get tape errors */
/*
 * Set EOT model- argument is number of filemarks to end a tape with.
 * Note that not all possible values will be accepted.
 */
#define	MTIOCSETEOTMODEL	_IOW('m', 8, u_int32_t)
/* Get current EOT model */
#define	MTIOCGETEOTMODEL	_IOR('m', 8, u_int32_t)

#ifndef _KERNEL
#define	DEFTAPE	"/dev/nsa0"
#endif

#endif /* !_SYS_MTIO_H_ */


code:
/*-
 * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Berkeley Software Design Inc's name may not be used to endorse or
 *    promote products derived from this software without specific prior
 *    written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN INC BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	from BSDI $Id: mutex.h,v 2.7.2.35 2000/04/27 03:10:26 cp Exp $
 * $FreeBSD: release/9.0.0/sys/sys/mutex.h 218673 2011-02-14 02:37:27Z alc $
 */

#ifndef _SYS_MUTEX_H_
#define _SYS_MUTEX_H_

#include <sys/queue.h>
#include <sys/_lock.h>
#include <sys/_mutex.h>

#ifdef _KERNEL
#include <sys/pcpu.h>
#include <sys/lock_profile.h>
#include <sys/lockstat.h>
#include <machine/atomic.h>
#include <machine/cpufunc.h>

/*
 * Mutex types and options passed to mtx_init().  MTX_QUIET and MTX_DUPOK
 * can also be passed in.
 */
#define	MTX_DEF		0x00000000	/* DEFAULT (sleep) lock */
#define MTX_SPIN	0x00000001	/* Spin lock (disables interrupts) */
#define MTX_RECURSE	0x00000004	/* Option: lock allowed to recurse */
#define	MTX_NOWITNESS	0x00000008	/* Don't do any witness checking. */
#define MTX_NOPROFILE   0x00000020	/* Don't profile this lock */

/*
 * Option flags passed to certain lock/unlock routines, through the use
 * of corresponding mtx_{lock,unlock}_flags() interface macros.
 */
#define	MTX_QUIET	LOP_QUIET	/* Don't log a mutex event */
#define	MTX_DUPOK	LOP_DUPOK	/* Don't log a duplicate acquire */

/*
 * State bits kept in mutex->mtx_lock, for the DEFAULT lock type. None of this,
 * with the exception of MTX_UNOWNED, applies to spin locks.
 */
#define	MTX_RECURSED	0x00000001	/* lock recursed (for MTX_DEF only) */
#define	MTX_CONTESTED	0x00000002	/* lock contested (for MTX_DEF only) */
#define MTX_UNOWNED	0x00000004	/* Cookie for free mutex */
#define	MTX_FLAGMASK	(MTX_RECURSED | MTX_CONTESTED | MTX_UNOWNED)

/*
 * Value stored in mutex->mtx_lock to denote a destroyed mutex.
 */
#define	MTX_DESTROYED	(MTX_CONTESTED | MTX_UNOWNED)

/*
 * Prototypes
 *
 * NOTE: Functions prepended with `_' (underscore) are exported to other parts
 *	 of the kernel via macros, thus allowing us to use the cpp LOCK_FILE
 *	 and LOCK_LINE. These functions should not be called directly by any
 *	 code using the API. Their macros cover their functionality.
 *
 * [See below for descriptions]
 *
 */
void	mtx_init(struct mtx *m, const char *name, const char *type, int opts);
void	mtx_destroy(struct mtx *m);
void	mtx_sysinit(void *arg);
void	mutex_init(void);
void	_mtx_lock_sleep(struct mtx *m, uintptr_t tid, int opts,
	    const char *file, int line);
void	_mtx_unlock_sleep(struct mtx *m, int opts, const char *file, int line);
#ifdef SMP
void	_mtx_lock_spin(struct mtx *m, uintptr_t tid, int opts,
	    const char *file, int line);
#endif
void	_mtx_unlock_spin(struct mtx *m, int opts, const char *file, int line);
int	_mtx_trylock(struct mtx *m, int opts, const char *file, int line);
void	_mtx_lock_flags(struct mtx *m, int opts, const char *file, int line);
void	_mtx_unlock_flags(struct mtx *m, int opts, const char *file, int line);
void	_mtx_lock_spin_flags(struct mtx *m, int opts, const char *file,
	     int line);
void	_mtx_unlock_spin_flags(struct mtx *m, int opts, const char *file,
	     int line);
#if defined(INVARIANTS) || defined(INVARIANT_SUPPORT)
void	_mtx_assert(struct mtx *m, int what, const char *file, int line);
#endif
void	_thread_lock_flags(struct thread *, int, const char *, int);

#define	thread_lock(tdp)						\
    _thread_lock_flags((tdp), 0, __FILE__, __LINE__)
#define	thread_lock_flags(tdp, opt)					\
    _thread_lock_flags((tdp), (opt), __FILE__, __LINE__)
#define	thread_unlock(tdp)						\
       mtx_unlock_spin((tdp)->td_lock)

#define	mtx_recurse	lock_object.lo_data

/* Very simple operations on mtx_lock. */

/* Try to obtain mtx_lock once. */
#define _mtx_obtain_lock(mp, tid)					\
	atomic_cmpset_acq_ptr(&(mp)->mtx_lock, MTX_UNOWNED, (tid))

/* Try to release mtx_lock if it is unrecursed and uncontested. */
#define _mtx_release_lock(mp, tid)					\
	atomic_cmpset_rel_ptr(&(mp)->mtx_lock, (tid), MTX_UNOWNED)

/* Release mtx_lock quickly, assuming we own it. */
#define _mtx_release_lock_quick(mp)					\
	atomic_store_rel_ptr(&(mp)->mtx_lock, MTX_UNOWNED)

/*
 * Full lock operations that are suitable to be inlined in non-debug
 * kernels.  If the lock cannot be acquired or released trivially then
 * the work is deferred to another function.
 */

/* Lock a normal mutex. */
#define __mtx_lock(mp, tid, opts, file, line) do {			\
	uintptr_t _tid = (uintptr_t)(tid);				\
									\
	if (!_mtx_obtain_lock((mp), _tid))				\
		_mtx_lock_sleep((mp), _tid, (opts), (file), (line));	\
	else								\
              	LOCKSTAT_PROFILE_OBTAIN_LOCK_SUCCESS(LS_MTX_LOCK_ACQUIRE, \
		    mp, 0, 0, (file), (line));				\
} while (0)

/*
 * Lock a spin mutex.  For spinlocks, we handle recursion inline (it
 * turns out that function calls can be significantly expensive on
 * some architectures).  Since spin locks are not _too_ common,
 * inlining this code is not too big a deal.
 */
#ifdef SMP
#define __mtx_lock_spin(mp, tid, opts, file, line) do {			\
	uintptr_t _tid = (uintptr_t)(tid);				\
									\
	spinlock_enter();						\
	if (!_mtx_obtain_lock((mp), _tid)) {				\
		if ((mp)->mtx_lock == _tid)				\
			(mp)->mtx_recurse++;				\
		else							\
			_mtx_lock_spin((mp), _tid, (opts), (file), (line)); \
	} else 								\
              	LOCKSTAT_PROFILE_OBTAIN_LOCK_SUCCESS(LS_MTX_SPIN_LOCK_ACQUIRE, \
		    mp, 0, 0, (file), (line));				\
} while (0)
#else /* SMP */
#define __mtx_lock_spin(mp, tid, opts, file, line) do {			\
	uintptr_t _tid = (uintptr_t)(tid);				\
									\
	spinlock_enter();						\
	if ((mp)->mtx_lock == _tid)					\
		(mp)->mtx_recurse++;					\
	else {								\
		KASSERT((mp)->mtx_lock == MTX_UNOWNED, ("corrupt spinlock")); \
		(mp)->mtx_lock = _tid;					\
	}								\
} while (0)
#endif /* SMP */

/* Unlock a normal mutex. */
#define __mtx_unlock(mp, tid, opts, file, line) do {			\
	uintptr_t _tid = (uintptr_t)(tid);				\
									\
	if (!_mtx_release_lock((mp), _tid))				\
		_mtx_unlock_sleep((mp), (opts), (file), (line));	\
} while (0)

/*
 * Unlock a spin mutex.  For spinlocks, we can handle everything
 * inline, as it's pretty simple and a function call would be too
 * expensive (at least on some architectures).  Since spin locks are
 * not _too_ common, inlining this code is not too big a deal.
 *
 * Since we always perform a spinlock_enter() when attempting to acquire a
 * spin lock, we need to always perform a matching spinlock_exit() when
 * releasing a spin lock.  This includes the recursion cases.
 */
#ifdef SMP
#define __mtx_unlock_spin(mp) do {					\
	if (mtx_recursed((mp)))						\
		(mp)->mtx_recurse--;					\
	else {								\
		LOCKSTAT_PROFILE_RELEASE_LOCK(LS_MTX_SPIN_UNLOCK_RELEASE, \
			mp);						\
		_mtx_release_lock_quick((mp));				\
	}                                                               \
	spinlock_exit();				                \
} while (0)
#else /* SMP */
#define __mtx_unlock_spin(mp) do {					\
	if (mtx_recursed((mp)))						\
		(mp)->mtx_recurse--;					\
	else {								\
		LOCKSTAT_PROFILE_RELEASE_LOCK(LS_MTX_SPIN_UNLOCK_RELEASE, \
			mp);						\
		(mp)->mtx_lock = MTX_UNOWNED;				\
	}                                                               \
	spinlock_exit();						\
} while (0)
#endif /* SMP */

/*
 * Exported lock manipulation interface.
 *
 * mtx_lock(m) locks MTX_DEF mutex `m'
 *
 * mtx_lock_spin(m) locks MTX_SPIN mutex `m'
 *
 * mtx_unlock(m) unlocks MTX_DEF mutex `m'
 *
 * mtx_unlock_spin(m) unlocks MTX_SPIN mutex `m'
 *
 * mtx_lock_spin_flags(m, opts) and mtx_lock_flags(m, opts) locks mutex `m'
 *     and passes option flags `opts' to the "hard" function, if required.
 *     With these routines, it is possible to pass flags such as MTX_QUIET
 *     to the appropriate lock manipulation routines.
 *
 * mtx_trylock(m) attempts to acquire MTX_DEF mutex `m' but doesn't sleep if
 *     it cannot. Rather, it returns 0 on failure and non-zero on success.
 *     It does NOT handle recursion as we assume that if a caller is properly
 *     using this part of the interface, he will know that the lock in question
 *     is _not_ recursed.
 *
 * mtx_trylock_flags(m, opts) is used the same way as mtx_trylock() but accepts
 *     relevant option flags `opts.'
 *
 * mtx_initialized(m) returns non-zero if the lock `m' has been initialized.
 *
 * mtx_owned(m) returns non-zero if the current thread owns the lock `m'
 *
 * mtx_recursed(m) returns non-zero if the lock `m' is presently recursed.
 */
#define mtx_lock(m)		_mtx_lock_flags((m), 0, __FILE__, __LINE__)
#define mtx_lock_spin(m)	mtx_lock_spin_flags((m), 0)
#define mtx_trylock(m)		mtx_trylock_flags((m), 0)
#define mtx_unlock(m)		_mtx_unlock_flags((m), 0, __FILE__, __LINE__)
#define mtx_unlock_spin(m)	mtx_unlock_spin_flags((m), 0)

struct mtx_pool;

struct mtx_pool *mtx_pool_create(const char *mtx_name, int pool_size, int opts);
void mtx_pool_destroy(struct mtx_pool **poolp);
struct mtx *mtx_pool_find(struct mtx_pool *pool, void *ptr);
struct mtx *mtx_pool_alloc(struct mtx_pool *pool);
#define mtx_pool_lock(pool, ptr)					\
	mtx_lock(mtx_pool_find((pool), (ptr)))
#define mtx_pool_lock_spin(pool, ptr)					\
	mtx_lock_spin(mtx_pool_find((pool), (ptr)))
#define mtx_pool_unlock(pool, ptr)					\
	mtx_unlock(mtx_pool_find((pool), (ptr)))
#define mtx_pool_unlock_spin(pool, ptr)					\
	mtx_unlock_spin(mtx_pool_find((pool), (ptr)))

/*
 * mtxpool_lockbuilder is a pool of sleep locks that is not witness
 * checked and should only be used for building higher level locks.
 *
 * mtxpool_sleep is a general purpose pool of sleep mutexes.
 */
extern struct mtx_pool *mtxpool_lockbuilder;
extern struct mtx_pool *mtxpool_sleep;

#ifndef LOCK_DEBUG
#error LOCK_DEBUG not defined, include <sys/lock.h> before <sys/mutex.h>
#endif
#if LOCK_DEBUG > 0 || defined(MUTEX_NOINLINE)
#define	mtx_lock_flags(m, opts)						\
	_mtx_lock_flags((m), (opts), LOCK_FILE, LOCK_LINE)
#define	mtx_unlock_flags(m, opts)					\
	_mtx_unlock_flags((m), (opts), LOCK_FILE, LOCK_LINE)
#define	mtx_lock_spin_flags(m, opts)					\
	_mtx_lock_spin_flags((m), (opts), LOCK_FILE, LOCK_LINE)
#define	mtx_unlock_spin_flags(m, opts)					\
	_mtx_unlock_spin_flags((m), (opts), LOCK_FILE, LOCK_LINE)
#else	/* LOCK_DEBUG == 0 && !MUTEX_NOINLINE */
#define	mtx_lock_flags(m, opts)						\
	__mtx_lock((m), curthread, (opts), LOCK_FILE, LOCK_LINE)
#define	mtx_unlock_flags(m, opts)					\
	__mtx_unlock((m), curthread, (opts), LOCK_FILE, LOCK_LINE)
#define	mtx_lock_spin_flags(m, opts)					\
	__mtx_lock_spin((m), curthread, (opts), LOCK_FILE, LOCK_LINE)
#define	mtx_unlock_spin_flags(m, opts)					\
	__mtx_unlock_spin((m))
#endif	/* LOCK_DEBUG > 0 || MUTEX_NOINLINE */

#define mtx_trylock_flags(m, opts)					\
	_mtx_trylock((m), (opts), LOCK_FILE, LOCK_LINE)

#define	mtx_sleep(chan, mtx, pri, wmesg, timo)				\
	_sleep((chan), &(mtx)->lock_object, (pri), (wmesg), (timo))

#define	mtx_initialized(m)	lock_initalized(&(m)->lock_object)

#define mtx_owned(m)	(((m)->mtx_lock & ~MTX_FLAGMASK) == (uintptr_t)curthread)

#define mtx_recursed(m)	((m)->mtx_recurse != 0)

#define mtx_name(m)	((m)->lock_object.lo_name)

/*
 * Global locks.
 */
extern struct mtx Giant;
extern struct mtx blocked_lock;

/*
 * Giant lock manipulation and clean exit macros.
 * Used to replace return with an exit Giant and return.
 *
 * Note that DROP_GIANT*() needs to be paired with PICKUP_GIANT()
 * The #ifndef is to allow lint-like tools to redefine DROP_GIANT.
 */
#ifndef DROP_GIANT
#define DROP_GIANT()							\
do {									\
	int _giantcnt = 0;						\
	WITNESS_SAVE_DECL(Giant);					\
									\
	if (mtx_owned(&Giant)) {					\
		WITNESS_SAVE(&Giant.lock_object, Giant);		\
		for (_giantcnt = 0; mtx_owned(&Giant); _giantcnt++)	\
			mtx_unlock(&Giant);				\
	}

#define PICKUP_GIANT()							\
	PARTIAL_PICKUP_GIANT();						\
} while (0)

#define PARTIAL_PICKUP_GIANT()						\
	mtx_assert(&Giant, MA_NOTOWNED);				\
	if (_giantcnt > 0) {						\
		while (_giantcnt--)					\
			mtx_lock(&Giant);				\
		WITNESS_RESTORE(&Giant.lock_object, Giant);		\
	}
#endif

#define	UGAR(rval) do {							\
	int _val = (rval);						\
	mtx_unlock(&Giant);						\
	return (_val);							\
} while (0)

struct mtx_args {
	struct mtx	*ma_mtx;
	const char 	*ma_desc;
	int		 ma_opts;
};

#define	MTX_SYSINIT(name, mtx, desc, opts)				\
	static struct mtx_args name##_args = {				\
		(mtx),							\
		(desc),							\
		(opts)							\
	};								\
	SYSINIT(name##_mtx_sysinit, SI_SUB_LOCK, SI_ORDER_MIDDLE,	\
	    mtx_sysinit, &name##_args);					\
	SYSUNINIT(name##_mtx_sysuninit, SI_SUB_LOCK, SI_ORDER_MIDDLE,	\
	    mtx_destroy, (mtx))

/*
 * The INVARIANTS-enabled mtx_assert() functionality.
 *
 * The constants need to be defined for INVARIANT_SUPPORT infrastructure
 * support as _mtx_assert() itself uses them and the latter implies that
 * _mtx_assert() must build.
 */
#if defined(INVARIANTS) || defined(INVARIANT_SUPPORT)
#define MA_OWNED	LA_XLOCKED
#define MA_NOTOWNED	LA_UNLOCKED
#define MA_RECURSED	LA_RECURSED
#define MA_NOTRECURSED	LA_NOTRECURSED
#endif

#ifdef INVARIANTS
#define	mtx_assert(m, what)						\
	_mtx_assert((m), (what), __FILE__, __LINE__)

#define GIANT_REQUIRED	mtx_assert(&Giant, MA_OWNED)

#else	/* INVARIANTS */
#define mtx_assert(m, what)	(void)0
#define GIANT_REQUIRED
#endif	/* INVARIANTS */

/*
 * Common lock type names.
 */
#define	MTX_NETWORK_LOCK	"network driver"

#endif	/* _KERNEL */
#endif	/* _SYS_MUTEX_H_ */


code:
/*-
 * Copyright (c) 1985, 1989, 1991, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	@(#)namei.h	8.5 (Berkeley) 1/9/95
 * $FreeBSD: release/9.0.0/sys/sys/namei.h 224810 2011-08-13 09:21:16Z jonathan $
 */

#ifndef _SYS_NAMEI_H_
#define	_SYS_NAMEI_H_

#include <sys/queue.h>
#include <sys/uio.h>

struct componentname {
	/*
	 * Arguments to lookup.
	 */
	u_long	cn_nameiop;	/* namei operation */
	u_int64_t cn_flags;	/* flags to namei */
	struct	thread *cn_thread;/* thread requesting lookup */
	struct	ucred *cn_cred;	/* credentials */
	int	cn_lkflags;	/* Lock flags LK_EXCLUSIVE or LK_SHARED */
	/*
	 * Shared between lookup and commit routines.
	 */
	char	*cn_pnbuf;	/* pathname buffer */
	char	*cn_nameptr;	/* pointer to looked up name */
	long	cn_namelen;	/* length of looked up component */
	long	cn_consume;	/* chars to consume in lookup() */
};

/*
 * Encapsulation of namei parameters.
 */
struct nameidata {
	/*
	 * Arguments to namei/lookup.
	 */
	const	char *ni_dirp;		/* pathname pointer */
	enum	uio_seg ni_segflg;	/* location of pathname */
	cap_rights_t ni_rightsneeded;	/* rights required to look up vnode */
	/*
	 * Arguments to lookup.
	 */
	struct  vnode *ni_startdir;	/* starting directory */
	struct	vnode *ni_rootdir;	/* logical root directory */
	struct	vnode *ni_topdir;	/* logical top directory */
	int	ni_dirfd;		/* starting directory for *at functions */
	int	ni_strictrelative;	/* relative lookup only; no '..' */
	/*
	 * Results: returned from namei
	 */
	cap_rights_t ni_baserights;	/* rights the *at base has (or -1) */
	/*
	 * Results: returned from/manipulated by lookup
	 */
	struct	vnode *ni_vp;		/* vnode of result */
	struct	vnode *ni_dvp;		/* vnode of intermediate directory */
	/*
	 * Shared between namei and lookup/commit routines.
	 */
	size_t	ni_pathlen;		/* remaining chars in path */
	char	*ni_next;		/* next location in pathname */
	u_int	ni_loopcnt;		/* count of symlinks encountered */
	/*
	 * Lookup parameters: this structure describes the subset of
	 * information from the nameidata structure that is passed
	 * through the VOP interface.
	 */
	struct componentname ni_cnd;
};

#ifdef _KERNEL
/*
 * namei operations
 */
#define	LOOKUP		0	/* perform name lookup only */
#define	CREATE		1	/* setup for file creation */
#define	DELETE		2	/* setup for file deletion */
#define	RENAME		3	/* setup for file renaming */
#define	OPMASK		3	/* mask for operation */
/*
 * namei operational modifier flags, stored in ni_cnd.flags
 */
#define	LOCKLEAF	0x0004	/* lock inode on return */
#define	LOCKPARENT	0x0008	/* want parent vnode returned locked */
#define	WANTPARENT	0x0010	/* want parent vnode returned unlocked */
#define	NOCACHE		0x0020	/* name must not be left in cache */
#define	FOLLOW		0x0040	/* follow symbolic links */
#define	LOCKSHARED	0x0100	/* Shared lock leaf */
#define	NOFOLLOW	0x0000	/* do not follow symbolic links (pseudo) */
#define	MODMASK		0x01fc	/* mask of operational modifiers */
/*
 * Namei parameter descriptors.
 *
 * SAVENAME may be set by either the callers of namei or by VOP_LOOKUP.
 * If the caller of namei sets the flag (for example execve wants to
 * know the name of the program that is being executed), then it must
 * free the buffer. If VOP_LOOKUP sets the flag, then the buffer must
 * be freed by either the commit routine or the VOP_ABORT routine.
 * SAVESTART is set only by the callers of namei. It implies SAVENAME
 * plus the addition of saving the parent directory that contains the
 * name in ni_startdir. It allows repeated calls to lookup for the
 * name being sought. The caller is responsible for releasing the
 * buffer and for vrele'ing ni_startdir.
 */
#define	RDONLY		0x00000200 /* lookup with read-only semantics */
#define	HASBUF		0x00000400 /* has allocated pathname buffer */
#define	SAVENAME	0x00000800 /* save pathname buffer */
#define	SAVESTART	0x00001000 /* save starting directory */
#define	ISDOTDOT	0x00002000 /* current component name is .. */
#define	MAKEENTRY	0x00004000 /* entry is to be added to name cache */
#define	ISLASTCN	0x00008000 /* this is last component of pathname */
#define	ISSYMLINK	0x00010000 /* symlink needs interpretation */
#define	ISWHITEOUT	0x00020000 /* found whiteout */
#define	DOWHITEOUT	0x00040000 /* do whiteouts */
#define	WILLBEDIR	0x00080000 /* new files will be dirs; allow trailing / */
#define	ISUNICODE	0x00100000 /* current component name is unicode*/
#define	ISOPEN		0x00200000 /* caller is opening; return a real vnode. */
#define	NOCROSSMOUNT	0x00400000 /* do not cross mount points */
#define	NOMACCHECK	0x00800000 /* do not perform MAC checks */
#define	MPSAFE		0x01000000 /* namei() must acquire Giant if needed. */
#define	GIANTHELD	0x02000000 /* namei() is holding giant. */
#define	AUDITVNODE1	0x04000000 /* audit the looked up vnode information */
#define	AUDITVNODE2 	0x08000000 /* audit the looked up vnode information */
#define	TRAILINGSLASH	0x10000000 /* path ended in a slash */
#define	PARAMASK	0x1ffffe00 /* mask of parameter descriptors */

#define	NDHASGIANT(NDP)	(((NDP)->ni_cnd.cn_flags & GIANTHELD) != 0)

/*
 * Initialization of a nameidata structure.
 */
#define	NDINIT(ndp, op, flags, segflg, namep, td)			\
	NDINIT_ALL(ndp, op, flags, segflg, namep, AT_FDCWD, NULL, 0, td)
#define	NDINIT_AT(ndp, op, flags, segflg, namep, dirfd, td)		\
	NDINIT_ALL(ndp, op, flags, segflg, namep, dirfd, NULL, 0, td)
#define	NDINIT_ATRIGHTS(ndp, op, flags, segflg, namep, dirfd, rights, td) \
	NDINIT_ALL(ndp, op, flags, segflg, namep, dirfd, NULL, rights, td)
#define	NDINIT_ATVP(ndp, op, flags, segflg, namep, vp, td)		\
	NDINIT_ALL(ndp, op, flags, segflg, namep, AT_FDCWD, vp, 0, td)

static __inline void
NDINIT_ALL(struct nameidata *ndp,
	u_long op, u_long flags,
	enum uio_seg segflg,
	const char *namep,
	int dirfd,
	struct vnode *startdir,
	cap_rights_t rights,
	struct thread *td)
{
	ndp->ni_cnd.cn_nameiop = op;
	ndp->ni_cnd.cn_flags = flags;
	ndp->ni_segflg = segflg;
	ndp->ni_dirp = namep;
	ndp->ni_dirfd = dirfd;
	ndp->ni_startdir = startdir;
	ndp->ni_strictrelative = 0;
	ndp->ni_rightsneeded = rights;
	ndp->ni_baserights = 0;
	ndp->ni_cnd.cn_thread = td;
}

#define NDF_NO_DVP_RELE		0x00000001
#define NDF_NO_DVP_UNLOCK	0x00000002
#define NDF_NO_DVP_PUT		0x00000003
#define NDF_NO_VP_RELE		0x00000004
#define NDF_NO_VP_UNLOCK	0x00000008
#define NDF_NO_VP_PUT		0x0000000c
#define NDF_NO_STARTDIR_RELE	0x00000010
#define NDF_NO_FREE_PNBUF	0x00000020
#define NDF_ONLY_PNBUF		(~NDF_NO_FREE_PNBUF)

void NDFREE(struct nameidata *, const u_int);

int	namei(struct nameidata *ndp);
int	lookup(struct nameidata *ndp);
int	relookup(struct vnode *dvp, struct vnode **vpp,
	    struct componentname *cnp);
#endif

/*
 * Stats on usefulness of namei caches.
 */
struct nchstats {
	long	ncs_goodhits;		/* hits that we can really use */
	long	ncs_neghits;		/* negative hits that we can use */
	long	ncs_badhits;		/* hits we must drop */
	long	ncs_falsehits;		/* hits with id mismatch */
	long	ncs_miss;		/* misses */
	long	ncs_long;		/* long names that ignore cache */
	long	ncs_pass2;		/* names found with passes == 2 */
	long	ncs_2passes;		/* number of times we attempt it */
};

extern struct nchstats nchstats;

#endif /* !_SYS_NAMEI_H_ */


code:
/*-
 * Copyright (c) 1991, 1993
 *	The Regents of the University of California.  All rights reserved.
 * (c) UNIX System Laboratories, Inc.
 * All or some portions of this file are derived from material licensed
 * to the University of California by American Telephone and Telegraph
 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
 * the permission of UNIX System Laboratories, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	@(#)nlist.h	8.2 (Berkeley) 1/21/94
 *
 * $FreeBSD: release/9.0.0/sys/sys/nlist_aout.h 208986 2010-06-10 14:19:51Z bz $
 */

#ifndef _SYS_NLIST_AOUT_H_
#define	_SYS_NLIST_AOUT_H_

/*
 * Symbol table entries in a.out files.
 */

/*
 * Layout of each symbol.  The "#ifdef _AOUT_INCLUDE_" is so that
 * programs including nlist.h can initialize nlist structures
 * statically.
 */
struct nlist {
#ifdef _AOUT_INCLUDE_
	union {
		const char *n_name; /* symbol name (in memory) */
		long n_strx;	/* file string table offset (on disk) */
	} n_un;
#else
	const char *n_name;	/* symbol name (in memory) */
	int : 8 * (sizeof(long) > sizeof(char *) ?
	    sizeof(long) - sizeof(char *) : sizeof(char *) - sizeof(long));
#endif
	unsigned char n_type;	/* type defines */
	char n_other;		/* ".type" and binding information */
	short n_desc;		/* used by stab entries */
	unsigned long n_value;	/* address/value of the symbol */
};

#define	n_hash	n_desc		/* used internally by ld(1); XXX */

/*
 * Defines for n_type.
 */
#define	N_UNDF	0x00		/* undefined */
#define	N_ABS	0x02		/* absolute address */
#define	N_TEXT	0x04		/* text segment */
#define	N_DATA	0x06		/* data segment */
#define	N_BSS	0x08		/* bss segment */
#define	N_INDR	0x0a		/* alias definition */
#define	N_SIZE	0x0c		/* pseudo type, defines a symbol's size */
#define	N_COMM	0x12		/* common reference */
/* GNU extensions */
#define N_SETA	0x14		/* Absolute set element symbol */
#define N_SETT  0x16		/* Text set element symbol */
#define N_SETD  0x18		/* Data set element symbol */
#define N_SETB  0x1a		/* Bss set element symbol */
#define N_SETV  0x1c		/* Pointer to set vector in data area. */
/* end GNU extensions */
#define	N_FN	0x1e		/* file name (N_EXT on) */
#define	N_WARN	0x1e		/* warning message (N_EXT off) */

#define	N_EXT	0x01		/* external (global) bit, OR'ed in */
#define	N_TYPE	0x1e		/* mask for all the type bits */
#define	N_STAB	0xe0		/* mask for debugger symbols -- stab(5) */

/*
 * Defines for n_other.  It contains the ".type" (AUX) field in the least
 * significant 4 bits, and the binding (for weak symbols) in the most
 * significant 4 bits.
 */
#define N_AUX(p)	((p)->n_other & 0xf)
#define N_BIND(p)	(((unsigned int)(p)->n_other >> 4) & 0xf)
#define N_OTHER(r, v)	(((unsigned int)(r) << 4) | ((v) & 0xf))

#define AUX_OBJECT	1	/* data object */
#define AUX_FUNC	2	/* function */

/*#define BIND_LOCAL	0	not used */
/*#define BIND_GLOBAL	1	not used */
#define BIND_WEAK	2	/* weak binding */

#define	N_FORMAT	"%08x"	/* namelist value format; XXX */

#endif /* !_SYS_NLIST_AOUT_H_ */


code:
/*-
 * Copyright (c) 2007 Pawel Jakub Dawidek <pjd@FreeBSD.org>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD: release/9.0.0/sys/sys/osd.h 216615 2010-12-21 13:45:29Z lstewart $
 */

#ifndef _SYS_OSD_H_
#define _SYS_OSD_H_

#include <sys/queue.h>

/*
 * Lock key:
 *   (c) container lock (e.g. jail's pr_mtx) and/or osd_object_lock
 *   (l) osd_list_lock
 */
struct osd {
	u_int		  osd_nslots;	/* (c) */
	void		**osd_slots;	/* (c) */
	LIST_ENTRY(osd)	  osd_next;	/* (l) */
};

#ifdef _KERNEL

#define	OSD_THREAD	0
#define	OSD_JAIL	1
#define	OSD_KHELP	2

#define	OSD_FIRST	OSD_THREAD
#define	OSD_LAST	OSD_KHELP

typedef void (*osd_destructor_t)(void *value);
typedef int (*osd_method_t)(void *obj, void *data);

int osd_register(u_int type, osd_destructor_t destructor,
    osd_method_t *methods);
void osd_deregister(u_int type, u_int slot);

int osd_set(u_int type, struct osd *osd, u_int slot, void *value);
void *osd_get(u_int type, struct osd *osd, u_int slot);
void osd_del(u_int type, struct osd *osd, u_int slot);
int osd_call(u_int type, u_int method, void *obj, void *data);

void osd_exit(u_int type, struct osd *osd);

#define	osd_thread_register(destructor)					\
	osd_register(OSD_THREAD, (destructor), NULL)
#define	osd_thread_deregister(slot)					\
	osd_deregister(OSD_THREAD, (slot))
#define	osd_thread_set(td, slot, value)					\
	osd_set(OSD_THREAD, &(td)->td_osd, (slot), (value))
#define	osd_thread_get(td, slot)					\
	osd_get(OSD_THREAD, &(td)->td_osd, (slot))
#define	osd_thread_del(td, slot)	do {				\
	KASSERT((td) == curthread, ("Not curthread."));			\
	osd_del(OSD_THREAD, &(td)->td_osd, (slot));			\
} while (0)
#define	osd_thread_call(td, method, data)				\
	osd_call(OSD_THREAD, (method), (td), (data))
#define	osd_thread_exit(td)						\
	osd_exit(OSD_THREAD, &(td)->td_osd)

#define	osd_jail_register(destructor, methods)				\
	osd_register(OSD_JAIL, (destructor), (methods))
#define	osd_jail_deregister(slot)					\
	osd_deregister(OSD_JAIL, (slot))
#define	osd_jail_set(pr, slot, value)					\
	osd_set(OSD_JAIL, &(pr)->pr_osd, (slot), (value))
#define	osd_jail_get(pr, slot)						\
	osd_get(OSD_JAIL, &(pr)->pr_osd, (slot))
#define	osd_jail_del(pr, slot)						\
	osd_del(OSD_JAIL, &(pr)->pr_osd, (slot))
#define	osd_jail_call(pr, method, data)					\
	osd_call(OSD_JAIL, (method), (pr), (data))
#define	osd_jail_exit(pr)						\
	osd_exit(OSD_JAIL, &(pr)->pr_osd)

#endif	/* _KERNEL */

#endif	/* !_SYS_OSD_H_ */