code:
/* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
   Free Software Foundation, Inc.

   This file is part of GCC.

   GCC is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   GCC is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with GCC; see the file COPYING.  If not, write to
   the Free Software Foundation, 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.  */

/* As a special exception, if you include this header file into source
   files compiled by GCC, this header file does not by itself cause
   the resulting executable to be covered by the GNU General Public
   License.  This exception does not however invalidate any other
   reasons why the executable file might be covered by the GNU General
   Public License.  */

/* Implemented from the specification included in the Intel C++ Compiler
   User Guide and Reference, version 9.0.  */

#ifndef _XMMINTRIN_H_INCLUDED
#define _XMMINTRIN_H_INCLUDED

#ifndef __SSE__
# error "SSE instruction set not enabled"
#else

/* We need type definitions from the MMX header file.  */
#include <mmintrin.h>

/* Get _mm_malloc () and _mm_free ().  */
#include <mm_malloc.h>

/* The Intel API is flexible enough that we must allow aliasing with other
   vector types, and their scalar components.  */
typedef float __m128 __attribute__ ((__vector_size__ (16), __may_alias__));

/* Internal data types for implementing the intrinsics.  */
typedef float __v4sf __attribute__ ((__vector_size__ (16)));

/* Create a selector for use with the SHUFPS instruction.  */
#define _MM_SHUFFLE(fp3,fp2,fp1,fp0) \
 (((fp3) << 6) | ((fp2) << 4) | ((fp1) << 2) | (fp0))

/* Constants for use with _mm_prefetch.  */
enum _mm_hint
{
  _MM_HINT_T0 = 3,
  _MM_HINT_T1 = 2,
  _MM_HINT_T2 = 1,
  _MM_HINT_NTA = 0
};

/* Bits in the MXCSR.  */
#define _MM_EXCEPT_MASK       0x003f
#define _MM_EXCEPT_INVALID    0x0001
#define _MM_EXCEPT_DENORM     0x0002
#define _MM_EXCEPT_DIV_ZERO   0x0004
#define _MM_EXCEPT_OVERFLOW   0x0008
#define _MM_EXCEPT_UNDERFLOW  0x0010
#define _MM_EXCEPT_INEXACT    0x0020

#define _MM_MASK_MASK         0x1f80
#define _MM_MASK_INVALID      0x0080
#define _MM_MASK_DENORM       0x0100
#define _MM_MASK_DIV_ZERO     0x0200
#define _MM_MASK_OVERFLOW     0x0400
#define _MM_MASK_UNDERFLOW    0x0800
#define _MM_MASK_INEXACT      0x1000

#define _MM_ROUND_MASK        0x6000
#define _MM_ROUND_NEAREST     0x0000
#define _MM_ROUND_DOWN        0x2000
#define _MM_ROUND_UP          0x4000
#define _MM_ROUND_TOWARD_ZERO 0x6000

#define _MM_FLUSH_ZERO_MASK   0x8000
#define _MM_FLUSH_ZERO_ON     0x8000
#define _MM_FLUSH_ZERO_OFF    0x0000

/* Create a vector of zeros.  */
static __inline __m128 __attribute__((__always_inline__))
_mm_setzero_ps (void)
{
  return __extension__ (__m128){ 0.0f, 0.0f, 0.0f, 0.0f };
}

/* Perform the respective operation on the lower SPFP (single-precision
   floating-point) values of A and B; the upper three SPFP values are
   passed through from A.  */

static __inline __m128 __attribute__((__always_inline__))
_mm_add_ss (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_addss ((__v4sf)__A, (__v4sf)__B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_sub_ss (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_subss ((__v4sf)__A, (__v4sf)__B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_mul_ss (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_mulss ((__v4sf)__A, (__v4sf)__B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_div_ss (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_divss ((__v4sf)__A, (__v4sf)__B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_sqrt_ss (__m128 __A)
{
  return (__m128) __builtin_ia32_sqrtss ((__v4sf)__A);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_rcp_ss (__m128 __A)
{
  return (__m128) __builtin_ia32_rcpss ((__v4sf)__A);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_rsqrt_ss (__m128 __A)
{
  return (__m128) __builtin_ia32_rsqrtss ((__v4sf)__A);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_min_ss (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_minss ((__v4sf)__A, (__v4sf)__B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_max_ss (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_maxss ((__v4sf)__A, (__v4sf)__B);
}

/* Perform the respective operation on the four SPFP values in A and B.  */

static __inline __m128 __attribute__((__always_inline__))
_mm_add_ps (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_addps ((__v4sf)__A, (__v4sf)__B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_sub_ps (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_subps ((__v4sf)__A, (__v4sf)__B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_mul_ps (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_mulps ((__v4sf)__A, (__v4sf)__B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_div_ps (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_divps ((__v4sf)__A, (__v4sf)__B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_sqrt_ps (__m128 __A)
{
  return (__m128) __builtin_ia32_sqrtps ((__v4sf)__A);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_rcp_ps (__m128 __A)
{
  return (__m128) __builtin_ia32_rcpps ((__v4sf)__A);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_rsqrt_ps (__m128 __A)
{
  return (__m128) __builtin_ia32_rsqrtps ((__v4sf)__A);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_min_ps (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_minps ((__v4sf)__A, (__v4sf)__B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_max_ps (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_maxps ((__v4sf)__A, (__v4sf)__B);
}

/* Perform logical bit-wise operations on 128-bit values.  */

static __inline __m128 __attribute__((__always_inline__))
_mm_and_ps (__m128 __A, __m128 __B)
{
  return __builtin_ia32_andps (__A, __B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_andnot_ps (__m128 __A, __m128 __B)
{
  return __builtin_ia32_andnps (__A, __B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_or_ps (__m128 __A, __m128 __B)
{
  return __builtin_ia32_orps (__A, __B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_xor_ps (__m128 __A, __m128 __B)
{
  return __builtin_ia32_xorps (__A, __B);
}

/* Perform a comparison on the lower SPFP values of A and B.  If the
   comparison is true, place a mask of all ones in the result, otherwise a
   mask of zeros.  The upper three SPFP values are passed through from A.  */

static __inline __m128 __attribute__((__always_inline__))
_mm_cmpeq_ss (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_cmpeqss ((__v4sf)__A, (__v4sf)__B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_cmplt_ss (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_cmpltss ((__v4sf)__A, (__v4sf)__B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_cmple_ss (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_cmpless ((__v4sf)__A, (__v4sf)__B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_cmpgt_ss (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_movss ((__v4sf) __A,
					(__v4sf)
					__builtin_ia32_cmpltss ((__v4sf) __B,
								(__v4sf)
								__A));
}

static __inline __m128 __attribute__((__always_inline__))
_mm_cmpge_ss (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_movss ((__v4sf) __A,
					(__v4sf)
					__builtin_ia32_cmpless ((__v4sf) __B,
								(__v4sf)
								__A));
}

static __inline __m128 __attribute__((__always_inline__))
_mm_cmpneq_ss (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_cmpneqss ((__v4sf)__A, (__v4sf)__B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_cmpnlt_ss (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_cmpnltss ((__v4sf)__A, (__v4sf)__B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_cmpnle_ss (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_cmpnless ((__v4sf)__A, (__v4sf)__B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_cmpngt_ss (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_movss ((__v4sf) __A,
					(__v4sf)
					__builtin_ia32_cmpnltss ((__v4sf) __B,
								 (__v4sf)
								 __A));
}

static __inline __m128 __attribute__((__always_inline__))
_mm_cmpnge_ss (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_movss ((__v4sf) __A,
					(__v4sf)
					__builtin_ia32_cmpnless ((__v4sf) __B,
								 (__v4sf)
								 __A));
}

static __inline __m128 __attribute__((__always_inline__))
_mm_cmpord_ss (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_cmpordss ((__v4sf)__A, (__v4sf)__B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_cmpunord_ss (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_cmpunordss ((__v4sf)__A, (__v4sf)__B);
}

/* Perform a comparison on the four SPFP values of A and B.  For each
   element, if the comparison is true, place a mask of all ones in the
   result, otherwise a mask of zeros.  */

static __inline __m128 __attribute__((__always_inline__))
_mm_cmpeq_ps (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_cmpeqps ((__v4sf)__A, (__v4sf)__B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_cmplt_ps (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_cmpltps ((__v4sf)__A, (__v4sf)__B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_cmple_ps (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_cmpleps ((__v4sf)__A, (__v4sf)__B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_cmpgt_ps (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_cmpgtps ((__v4sf)__A, (__v4sf)__B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_cmpge_ps (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_cmpgeps ((__v4sf)__A, (__v4sf)__B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_cmpneq_ps (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_cmpneqps ((__v4sf)__A, (__v4sf)__B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_cmpnlt_ps (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_cmpnltps ((__v4sf)__A, (__v4sf)__B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_cmpnle_ps (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_cmpnleps ((__v4sf)__A, (__v4sf)__B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_cmpngt_ps (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_cmpngtps ((__v4sf)__A, (__v4sf)__B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_cmpnge_ps (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_cmpngeps ((__v4sf)__A, (__v4sf)__B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_cmpord_ps (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_cmpordps ((__v4sf)__A, (__v4sf)__B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_cmpunord_ps (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_cmpunordps ((__v4sf)__A, (__v4sf)__B);
}

/* Compare the lower SPFP values of A and B and return 1 if true
   and 0 if false.  */

static __inline int __attribute__((__always_inline__))
_mm_comieq_ss (__m128 __A, __m128 __B)
{
  return __builtin_ia32_comieq ((__v4sf)__A, (__v4sf)__B);
}

static __inline int __attribute__((__always_inline__))
_mm_comilt_ss (__m128 __A, __m128 __B)
{
  return __builtin_ia32_comilt ((__v4sf)__A, (__v4sf)__B);
}

static __inline int __attribute__((__always_inline__))
_mm_comile_ss (__m128 __A, __m128 __B)
{
  return __builtin_ia32_comile ((__v4sf)__A, (__v4sf)__B);
}

static __inline int __attribute__((__always_inline__))
_mm_comigt_ss (__m128 __A, __m128 __B)
{
  return __builtin_ia32_comigt ((__v4sf)__A, (__v4sf)__B);
}

static __inline int __attribute__((__always_inline__))
_mm_comige_ss (__m128 __A, __m128 __B)
{
  return __builtin_ia32_comige ((__v4sf)__A, (__v4sf)__B);
}

static __inline int __attribute__((__always_inline__))
_mm_comineq_ss (__m128 __A, __m128 __B)
{
  return __builtin_ia32_comineq ((__v4sf)__A, (__v4sf)__B);
}

static __inline int __attribute__((__always_inline__))
_mm_ucomieq_ss (__m128 __A, __m128 __B)
{
  return __builtin_ia32_ucomieq ((__v4sf)__A, (__v4sf)__B);
}

static __inline int __attribute__((__always_inline__))
_mm_ucomilt_ss (__m128 __A, __m128 __B)
{
  return __builtin_ia32_ucomilt ((__v4sf)__A, (__v4sf)__B);
}

static __inline int __attribute__((__always_inline__))
_mm_ucomile_ss (__m128 __A, __m128 __B)
{
  return __builtin_ia32_ucomile ((__v4sf)__A, (__v4sf)__B);
}

static __inline int __attribute__((__always_inline__))
_mm_ucomigt_ss (__m128 __A, __m128 __B)
{
  return __builtin_ia32_ucomigt ((__v4sf)__A, (__v4sf)__B);
}

static __inline int __attribute__((__always_inline__))
_mm_ucomige_ss (__m128 __A, __m128 __B)
{
  return __builtin_ia32_ucomige ((__v4sf)__A, (__v4sf)__B);
}

static __inline int __attribute__((__always_inline__))
_mm_ucomineq_ss (__m128 __A, __m128 __B)
{
  return __builtin_ia32_ucomineq ((__v4sf)__A, (__v4sf)__B);
}

/* Convert the lower SPFP value to a 32-bit integer according to the current
   rounding mode.  */
static __inline int __attribute__((__always_inline__))
_mm_cvtss_si32 (__m128 __A)
{
  return __builtin_ia32_cvtss2si ((__v4sf) __A);
}

static __inline int __attribute__((__always_inline__))
_mm_cvt_ss2si (__m128 __A)
{
  return _mm_cvtss_si32 (__A);
}

#ifdef __x86_64__
/* Convert the lower SPFP value to a 32-bit integer according to the
   current rounding mode.  */

/* Intel intrinsic.  */
static __inline long long __attribute__((__always_inline__))
_mm_cvtss_si64 (__m128 __A)
{
  return __builtin_ia32_cvtss2si64 ((__v4sf) __A);
}

/* Microsoft intrinsic.  */
static __inline long long __attribute__((__always_inline__))
_mm_cvtss_si64x (__m128 __A)
{
  return __builtin_ia32_cvtss2si64 ((__v4sf) __A);
}
#endif

/* Convert the two lower SPFP values to 32-bit integers according to the
   current rounding mode.  Return the integers in packed form.  */
static __inline __m64 __attribute__((__always_inline__))
_mm_cvtps_pi32 (__m128 __A)
{
  return (__m64) __builtin_ia32_cvtps2pi ((__v4sf) __A);
}

static __inline __m64 __attribute__((__always_inline__))
_mm_cvt_ps2pi (__m128 __A)
{
  return _mm_cvtps_pi32 (__A);
}

/* Truncate the lower SPFP value to a 32-bit integer.  */
static __inline int __attribute__((__always_inline__))
_mm_cvttss_si32 (__m128 __A)
{
  return __builtin_ia32_cvttss2si ((__v4sf) __A);
}

static __inline int __attribute__((__always_inline__))
_mm_cvtt_ss2si (__m128 __A)
{
  return _mm_cvttss_si32 (__A);
}

#ifdef __x86_64__
/* Truncate the lower SPFP value to a 32-bit integer.  */

/* Intel intrinsic.  */
static __inline long long __attribute__((__always_inline__))
_mm_cvttss_si64 (__m128 __A)
{
  return __builtin_ia32_cvttss2si64 ((__v4sf) __A);
}

/* Microsoft intrinsic.  */
static __inline long long __attribute__((__always_inline__))
_mm_cvttss_si64x (__m128 __A)
{
  return __builtin_ia32_cvttss2si64 ((__v4sf) __A);
}
#endif

/* Truncate the two lower SPFP values to 32-bit integers.  Return the
   integers in packed form.  */
static __inline __m64 __attribute__((__always_inline__))
_mm_cvttps_pi32 (__m128 __A)
{
  return (__m64) __builtin_ia32_cvttps2pi ((__v4sf) __A);
}

static __inline __m64 __attribute__((__always_inline__))
_mm_cvtt_ps2pi (__m128 __A)
{
  return _mm_cvttps_pi32 (__A);
}

/* Convert B to a SPFP value and insert it as element zero in A.  */
static __inline __m128 __attribute__((__always_inline__))
_mm_cvtsi32_ss (__m128 __A, int __B)
{
  return (__m128) __builtin_ia32_cvtsi2ss ((__v4sf) __A, __B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_cvt_si2ss (__m128 __A, int __B)
{
  return _mm_cvtsi32_ss (__A, __B);
}

#ifdef __x86_64__
/* Convert B to a SPFP value and insert it as element zero in A.  */

/* Intel intrinsic.  */
static __inline __m128 __attribute__((__always_inline__))
_mm_cvtsi64_ss (__m128 __A, long long __B)
{
  return (__m128) __builtin_ia32_cvtsi642ss ((__v4sf) __A, __B);
}

/* Microsoft intrinsic.  */
static __inline __m128 __attribute__((__always_inline__))
_mm_cvtsi64x_ss (__m128 __A, long long __B)
{
  return (__m128) __builtin_ia32_cvtsi642ss ((__v4sf) __A, __B);
}
#endif

/* Convert the two 32-bit values in B to SPFP form and insert them
   as the two lower elements in A.  */
static __inline __m128 __attribute__((__always_inline__))
_mm_cvtpi32_ps (__m128 __A, __m64 __B)
{
  return (__m128) __builtin_ia32_cvtpi2ps ((__v4sf) __A, (__v2si)__B);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_cvt_pi2ps (__m128 __A, __m64 __B)
{
  return _mm_cvtpi32_ps (__A, __B);
}

/* Convert the four signed 16-bit values in A to SPFP form.  */
static __inline __m128 __attribute__((__always_inline__))
_mm_cvtpi16_ps (__m64 __A)
{
  __v4hi __sign;
  __v2si __hisi, __losi;
  __v4sf __r;

  /* This comparison against zero gives us a mask that can be used to
     fill in the missing sign bits in the unpack operations below, so
     that we get signed values after unpacking.  */
  __sign = __builtin_ia32_pcmpgtw ((__v4hi)0LL, (__v4hi)__A);

  /* Convert the four words to doublewords.  */
  __hisi = (__v2si) __builtin_ia32_punpckhwd ((__v4hi)__A, __sign);
  __losi = (__v2si) __builtin_ia32_punpcklwd ((__v4hi)__A, __sign);

  /* Convert the doublewords to floating point two at a time.  */
  __r = (__v4sf) _mm_setzero_ps ();
  __r = __builtin_ia32_cvtpi2ps (__r, __hisi);
  __r = __builtin_ia32_movlhps (__r, __r);
  __r = __builtin_ia32_cvtpi2ps (__r, __losi);

  return (__m128) __r;
}

/* Convert the four unsigned 16-bit values in A to SPFP form.  */
static __inline __m128 __attribute__((__always_inline__))
_mm_cvtpu16_ps (__m64 __A)
{
  __v2si __hisi, __losi;
  __v4sf __r;

  /* Convert the four words to doublewords.  */
  __hisi = (__v2si) __builtin_ia32_punpckhwd ((__v4hi)__A, (__v4hi)0LL);
  __losi = (__v2si) __builtin_ia32_punpcklwd ((__v4hi)__A, (__v4hi)0LL);

  /* Convert the doublewords to floating point two at a time.  */
  __r = (__v4sf) _mm_setzero_ps ();
  __r = __builtin_ia32_cvtpi2ps (__r, __hisi);
  __r = __builtin_ia32_movlhps (__r, __r);
  __r = __builtin_ia32_cvtpi2ps (__r, __losi);

  return (__m128) __r;
}

/* Convert the low four signed 8-bit values in A to SPFP form.  */
static __inline __m128 __attribute__((__always_inline__))
_mm_cvtpi8_ps (__m64 __A)
{
  __v8qi __sign;

  /* This comparison against zero gives us a mask that can be used to
     fill in the missing sign bits in the unpack operations below, so
     that we get signed values after unpacking.  */
  __sign = __builtin_ia32_pcmpgtb ((__v8qi)0LL, (__v8qi)__A);

  /* Convert the four low bytes to words.  */
  __A = (__m64) __builtin_ia32_punpcklbw ((__v8qi)__A, __sign);

  return _mm_cvtpi16_ps(__A);
}

/* Convert the low four unsigned 8-bit values in A to SPFP form.  */
static __inline __m128 __attribute__((__always_inline__))
_mm_cvtpu8_ps(__m64 __A)
{
  __A = (__m64) __builtin_ia32_punpcklbw ((__v8qi)__A, (__v8qi)0LL);
  return _mm_cvtpu16_ps(__A);
}

/* Convert the four signed 32-bit values in A and B to SPFP form.  */
static __inline __m128 __attribute__((__always_inline__))
_mm_cvtpi32x2_ps(__m64 __A, __m64 __B)
{
  __v4sf __zero = (__v4sf) _mm_setzero_ps ();
  __v4sf __sfa = __builtin_ia32_cvtpi2ps (__zero, (__v2si)__A);
  __v4sf __sfb = __builtin_ia32_cvtpi2ps (__zero, (__v2si)__B);
  return (__m128) __builtin_ia32_movlhps (__sfa, __sfb);
}

/* Convert the four SPFP values in A to four signed 16-bit integers.  */
static __inline __m64 __attribute__((__always_inline__))
_mm_cvtps_pi16(__m128 __A)
{
  __v4sf __hisf = (__v4sf)__A;
  __v4sf __losf = __builtin_ia32_movhlps (__hisf, __hisf);
  __v2si __hisi = __builtin_ia32_cvtps2pi (__hisf);
  __v2si __losi = __builtin_ia32_cvtps2pi (__losf);
  return (__m64) __builtin_ia32_packssdw (__hisi, __losi);
}

/* Convert the four SPFP values in A to four signed 8-bit integers.  */
static __inline __m64 __attribute__((__always_inline__))
_mm_cvtps_pi8(__m128 __A)
{
  __v4hi __tmp = (__v4hi) _mm_cvtps_pi16 (__A);
  return (__m64) __builtin_ia32_packsswb (__tmp, (__v4hi)0LL);
}

/* Selects four specific SPFP values from A and B based on MASK.  */
#if 0
static __inline __m128 __attribute__((__always_inline__))
_mm_shuffle_ps (__m128 __A, __m128 __B, int __mask)
{
  return (__m128) __builtin_ia32_shufps ((__v4sf)__A, (__v4sf)__B, __mask);
}
#else
#define _mm_shuffle_ps(A, B, MASK) \
 ((__m128) __builtin_ia32_shufps ((__v4sf)(A), (__v4sf)(B), (MASK)))
#endif

/* Selects and interleaves the upper two SPFP values from A and B.  */
static __inline __m128 __attribute__((__always_inline__))
_mm_unpackhi_ps (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_unpckhps ((__v4sf)__A, (__v4sf)__B);
}

/* Selects and interleaves the lower two SPFP values from A and B.  */
static __inline __m128 __attribute__((__always_inline__))
_mm_unpacklo_ps (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_unpcklps ((__v4sf)__A, (__v4sf)__B);
}

/* Sets the upper two SPFP values with 64-bits of data loaded from P;
   the lower two values are passed through from A.  */
static __inline __m128 __attribute__((__always_inline__))
_mm_loadh_pi (__m128 __A, __m64 const *__P)
{
  return (__m128) __builtin_ia32_loadhps ((__v4sf)__A, (__v2si *)__P);
}

/* Stores the upper two SPFP values of A into P.  */
static __inline void __attribute__((__always_inline__))
_mm_storeh_pi (__m64 *__P, __m128 __A)
{
  __builtin_ia32_storehps ((__v2si *)__P, (__v4sf)__A);
}

/* Moves the upper two values of B into the lower two values of A.  */
static __inline __m128 __attribute__((__always_inline__))
_mm_movehl_ps (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_movhlps ((__v4sf)__A, (__v4sf)__B);
}

/* Moves the lower two values of B into the upper two values of A.  */
static __inline __m128 __attribute__((__always_inline__))
_mm_movelh_ps (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_movlhps ((__v4sf)__A, (__v4sf)__B);
}

/* Sets the lower two SPFP values with 64-bits of data loaded from P;
   the upper two values are passed through from A.  */
static __inline __m128 __attribute__((__always_inline__))
_mm_loadl_pi (__m128 __A, __m64 const *__P)
{
  return (__m128) __builtin_ia32_loadlps ((__v4sf)__A, (__v2si *)__P);
}

/* Stores the lower two SPFP values of A into P.  */
static __inline void __attribute__((__always_inline__))
_mm_storel_pi (__m64 *__P, __m128 __A)
{
  __builtin_ia32_storelps ((__v2si *)__P, (__v4sf)__A);
}

/* Creates a 4-bit mask from the most significant bits of the SPFP values.  */
static __inline int __attribute__((__always_inline__))
_mm_movemask_ps (__m128 __A)
{
  return __builtin_ia32_movmskps ((__v4sf)__A);
}

/* Return the contents of the control register.  */
static __inline unsigned int __attribute__((__always_inline__))
_mm_getcsr (void)
{
  return __builtin_ia32_stmxcsr ();
}

/* Read exception bits from the control register.  */
static __inline unsigned int __attribute__((__always_inline__))
_MM_GET_EXCEPTION_STATE (void)
{
  return _mm_getcsr() & _MM_EXCEPT_MASK;
}

static __inline unsigned int __attribute__((__always_inline__))
_MM_GET_EXCEPTION_MASK (void)
{
  return _mm_getcsr() & _MM_MASK_MASK;
}

static __inline unsigned int __attribute__((__always_inline__))
_MM_GET_ROUNDING_MODE (void)
{
  return _mm_getcsr() & _MM_ROUND_MASK;
}

static __inline unsigned int __attribute__((__always_inline__))
_MM_GET_FLUSH_ZERO_MODE (void)
{
  return _mm_getcsr() & _MM_FLUSH_ZERO_MASK;
}

/* Set the control register to I.  */
static __inline void __attribute__((__always_inline__))
_mm_setcsr (unsigned int __I)
{
  __builtin_ia32_ldmxcsr (__I);
}

/* Set exception bits in the control register.  */
static __inline void __attribute__((__always_inline__))
_MM_SET_EXCEPTION_STATE(unsigned int __mask)
{
  _mm_setcsr((_mm_getcsr() & ~_MM_EXCEPT_MASK) | __mask);
}

static __inline void __attribute__((__always_inline__))
_MM_SET_EXCEPTION_MASK (unsigned int __mask)
{
  _mm_setcsr((_mm_getcsr() & ~_MM_MASK_MASK) | __mask);
}

static __inline void __attribute__((__always_inline__))
_MM_SET_ROUNDING_MODE (unsigned int __mode)
{
  _mm_setcsr((_mm_getcsr() & ~_MM_ROUND_MASK) | __mode);
}

static __inline void __attribute__((__always_inline__))
_MM_SET_FLUSH_ZERO_MODE (unsigned int __mode)
{
  _mm_setcsr((_mm_getcsr() & ~_MM_FLUSH_ZERO_MASK) | __mode);
}

/* Create a vector with element 0 as F and the rest zero.  */
static __inline __m128 __attribute__((__always_inline__))
_mm_set_ss (float __F)
{
  return __extension__ (__m128)(__v4sf){ __F, 0, 0, 0 };
}

/* Create a vector with all four elements equal to F.  */
static __inline __m128 __attribute__((__always_inline__))
_mm_set1_ps (float __F)
{
  return __extension__ (__m128)(__v4sf){ __F, __F, __F, __F };
}

static __inline __m128 __attribute__((__always_inline__))
_mm_set_ps1 (float __F)
{
  return _mm_set1_ps (__F);
}

/* Create a vector with element 0 as *P and the rest zero.  */
static __inline __m128 __attribute__((__always_inline__))
_mm_load_ss (float const *__P)
{
  return _mm_set_ss (*__P);
}

/* Create a vector with all four elements equal to *P.  */
static __inline __m128 __attribute__((__always_inline__))
_mm_load1_ps (float const *__P)
{
  return _mm_set1_ps (*__P);
}

static __inline __m128 __attribute__((__always_inline__))
_mm_load_ps1 (float const *__P)
{
  return _mm_load1_ps (__P);
}

/* Load four SPFP values from P.  The address must be 16-byte aligned.  */
static __inline __m128 __attribute__((__always_inline__))
_mm_load_ps (float const *__P)
{
  return (__m128) *(__v4sf *)__P;
}

/* Load four SPFP values from P.  The address need not be 16-byte aligned.  */
static __inline __m128 __attribute__((__always_inline__))
_mm_loadu_ps (float const *__P)
{
  return (__m128) __builtin_ia32_loadups (__P);
}

/* Load four SPFP values in reverse order.  The address must be aligned.  */
static __inline __m128 __attribute__((__always_inline__))
_mm_loadr_ps (float const *__P)
{
  __v4sf __tmp = *(__v4sf *)__P;
  return (__m128) __builtin_ia32_shufps (__tmp, __tmp, _MM_SHUFFLE (0,1,2,3));
}

/* Create the vector [Z Y X W].  */
static __inline __m128 __attribute__((__always_inline__))
_mm_set_ps (const float __Z, const float __Y, const float __X, const float __W)
{
  return __extension__ (__m128)(__v4sf){ __W, __X, __Y, __Z };
}

/* Create the vector [W X Y Z].  */
static __inline __m128 __attribute__((__always_inline__))
_mm_setr_ps (float __Z, float __Y, float __X, float __W)
{
  return __extension__ (__m128)(__v4sf){ __Z, __Y, __X, __W };
}

/* Stores the lower SPFP value.  */
static __inline void __attribute__((__always_inline__))
_mm_store_ss (float *__P, __m128 __A)
{
  *__P = __builtin_ia32_vec_ext_v4sf ((__v4sf)__A, 0);
}

static __inline float __attribute__((__always_inline__))
_mm_cvtss_f32 (__m128 __A)
{
  return __builtin_ia32_vec_ext_v4sf ((__v4sf)__A, 0);
}

/* Store four SPFP values.  The address must be 16-byte aligned.  */
static __inline void __attribute__((__always_inline__))
_mm_store_ps (float *__P, __m128 __A)
{
  *(__v4sf *)__P = (__v4sf)__A;
}

/* Store four SPFP values.  The address need not be 16-byte aligned.  */
static __inline void __attribute__((__always_inline__))
_mm_storeu_ps (float *__P, __m128 __A)
{
  __builtin_ia32_storeups (__P, (__v4sf)__A);
}

/* Store the lower SPFP value across four words.  */
static __inline void __attribute__((__always_inline__))
_mm_store1_ps (float *__P, __m128 __A)
{
  __v4sf __va = (__v4sf)__A;
  __v4sf __tmp = __builtin_ia32_shufps (__va, __va, _MM_SHUFFLE (0,0,0,0));
  _mm_storeu_ps (__P, __tmp);
}

static __inline void __attribute__((__always_inline__))
_mm_store_ps1 (float *__P, __m128 __A)
{
  _mm_store1_ps (__P, __A);
}

/* Store four SPFP values in reverse order.  The address must be aligned.  */
static __inline void __attribute__((__always_inline__))
_mm_storer_ps (float *__P, __m128 __A)
{
  __v4sf __va = (__v4sf)__A;
  __v4sf __tmp = __builtin_ia32_shufps (__va, __va, _MM_SHUFFLE (0,1,2,3));
  _mm_store_ps (__P, __tmp);
}

/* Sets the low SPFP value of A from the low value of B.  */
static __inline __m128 __attribute__((__always_inline__))
_mm_move_ss (__m128 __A, __m128 __B)
{
  return (__m128) __builtin_ia32_movss ((__v4sf)__A, (__v4sf)__B);
}

/* Extracts one of the four words of A.  The selector N must be immediate.  */
#if 0
static __inline int __attribute__((__always_inline__))
_mm_extract_pi16 (__m64 const __A, int const __N)
{
  return __builtin_ia32_vec_ext_v4hi ((__v4hi)__A, __N);
}

static __inline int __attribute__((__always_inline__))
_m_pextrw (__m64 const __A, int const __N)
{
  return _mm_extract_pi16 (__A, __N);
}
#else
#define _mm_extract_pi16(A, N)	__builtin_ia32_vec_ext_v4hi ((__v4hi)(A), (N))
#define _m_pextrw(A, N)		_mm_extract_pi16((A), (N))
#endif

/* Inserts word D into one of four words of A.  The selector N must be
   immediate.  */
#if 0
static __inline __m64 __attribute__((__always_inline__))
_mm_insert_pi16 (__m64 const __A, int const __D, int const __N)
{
  return (__m64) __builtin_ia32_vec_set_v4hi ((__v4hi)__A, __D, __N);
}

static __inline __m64 __attribute__((__always_inline__))
_m_pinsrw (__m64 const __A, int const __D, int const __N)
{
  return _mm_insert_pi16 (__A, __D, __N);
}
#else
#define _mm_insert_pi16(A, D, N) \
  ((__m64) __builtin_ia32_vec_set_v4hi ((__v4hi)(A), (D), (N)))
#define _m_pinsrw(A, D, N)	 _mm_insert_pi16((A), (D), (N))
#endif

/* Compute the element-wise maximum of signed 16-bit values.  */
static __inline __m64 __attribute__((__always_inline__))
_mm_max_pi16 (__m64 __A, __m64 __B)
{
  return (__m64) __builtin_ia32_pmaxsw ((__v4hi)__A, (__v4hi)__B);
}

static __inline __m64 __attribute__((__always_inline__))
_m_pmaxsw (__m64 __A, __m64 __B)
{
  return _mm_max_pi16 (__A, __B);
}

/* Compute the element-wise maximum of unsigned 8-bit values.  */
static __inline __m64 __attribute__((__always_inline__))
_mm_max_pu8 (__m64 __A, __m64 __B)
{
  return (__m64) __builtin_ia32_pmaxub ((__v8qi)__A, (__v8qi)__B);
}

static __inline __m64 __attribute__((__always_inline__))
_m_pmaxub (__m64 __A, __m64 __B)
{
  return _mm_max_pu8 (__A, __B);
}

/* Compute the element-wise minimum of signed 16-bit values.  */
static __inline __m64 __attribute__((__always_inline__))
_mm_min_pi16 (__m64 __A, __m64 __B)
{
  return (__m64) __builtin_ia32_pminsw ((__v4hi)__A, (__v4hi)__B);
}

static __inline __m64 __attribute__((__always_inline__))
_m_pminsw (__m64 __A, __m64 __B)
{
  return _mm_min_pi16 (__A, __B);
}

/* Compute the element-wise minimum of unsigned 8-bit values.  */
static __inline __m64 __attribute__((__always_inline__))
_mm_min_pu8 (__m64 __A, __m64 __B)
{
  return (__m64) __builtin_ia32_pminub ((__v8qi)__A, (__v8qi)__B);
}

static __inline __m64 __attribute__((__always_inline__))
_m_pminub (__m64 __A, __m64 __B)
{
  return _mm_min_pu8 (__A, __B);
}

/* Create an 8-bit mask of the signs of 8-bit values.  */
static __inline int __attribute__((__always_inline__))
_mm_movemask_pi8 (__m64 __A)
{
  return __builtin_ia32_pmovmskb ((__v8qi)__A);
}

static __inline int __attribute__((__always_inline__))
_m_pmovmskb (__m64 __A)
{
  return _mm_movemask_pi8 (__A);
}

/* Multiply four unsigned 16-bit values in A by four unsigned 16-bit values
   in B and produce the high 16 bits of the 32-bit results.  */
static __inline __m64 __attribute__((__always_inline__))
_mm_mulhi_pu16 (__m64 __A, __m64 __B)
{
  return (__m64) __builtin_ia32_pmulhuw ((__v4hi)__A, (__v4hi)__B);
}

static __inline __m64 __attribute__((__always_inline__))
_m_pmulhuw (__m64 __A, __m64 __B)
{
  return _mm_mulhi_pu16 (__A, __B);
}

/* Return a combination of the four 16-bit values in A.  The selector
   must be an immediate.  */
#if 0
static __inline __m64 __attribute__((__always_inline__))
_mm_shuffle_pi16 (__m64 __A, int __N)
{
  return (__m64) __builtin_ia32_pshufw ((__v4hi)__A, __N);
}

static __inline __m64 __attribute__((__always_inline__))
_m_pshufw (__m64 __A, int __N)
{
  return _mm_shuffle_pi16 (__A, __N);
}
#else
#define _mm_shuffle_pi16(A, N) \
  ((__m64) __builtin_ia32_pshufw ((__v4hi)(A), (N)))
#define _m_pshufw(A, N)		_mm_shuffle_pi16 ((A), (N))
#endif

/* Conditionally store byte elements of A into P.  The high bit of each
   byte in the selector N determines whether the corresponding byte from
   A is stored.  */
static __inline void __attribute__((__always_inline__))
_mm_maskmove_si64 (__m64 __A, __m64 __N, char *__P)
{
  __builtin_ia32_maskmovq ((__v8qi)__A, (__v8qi)__N, __P);
}

static __inline void __attribute__((__always_inline__))
_m_maskmovq (__m64 __A, __m64 __N, char *__P)
{
  _mm_maskmove_si64 (__A, __N, __P);
}

/* Compute the rounded averages of the unsigned 8-bit values in A and B.  */
static __inline __m64 __attribute__((__always_inline__))
_mm_avg_pu8 (__m64 __A, __m64 __B)
{
  return (__m64) __builtin_ia32_pavgb ((__v8qi)__A, (__v8qi)__B);
}

static __inline __m64 __attribute__((__always_inline__))
_m_pavgb (__m64 __A, __m64 __B)
{
  return _mm_avg_pu8 (__A, __B);
}

/* Compute the rounded averages of the unsigned 16-bit values in A and B.  */
static __inline __m64 __attribute__((__always_inline__))
_mm_avg_pu16 (__m64 __A, __m64 __B)
{
  return (__m64) __builtin_ia32_pavgw ((__v4hi)__A, (__v4hi)__B);
}

static __inline __m64 __attribute__((__always_inline__))
_m_pavgw (__m64 __A, __m64 __B)
{
  return _mm_avg_pu16 (__A, __B);
}

/* Compute the sum of the absolute differences of the unsigned 8-bit
   values in A and B.  Return the value in the lower 16-bit word; the
   upper words are cleared.  */
static __inline __m64 __attribute__((__always_inline__))
_mm_sad_pu8 (__m64 __A, __m64 __B)
{
  return (__m64) __builtin_ia32_psadbw ((__v8qi)__A, (__v8qi)__B);
}

static __inline __m64 __attribute__((__always_inline__))
_m_psadbw (__m64 __A, __m64 __B)
{
  return _mm_sad_pu8 (__A, __B);
}

/* Loads one cache line from address P to a location "closer" to the
   processor.  The selector I specifies the type of prefetch operation.  */
#if 0
static __inline void __attribute__((__always_inline__))
_mm_prefetch (void *__P, enum _mm_hint __I)
{
  __builtin_prefetch (__P, 0, __I);
}
#else
#define _mm_prefetch(P, I) \
  __builtin_prefetch ((P), 0, (I))
#endif

/* Stores the data in A to the address P without polluting the caches.  */
static __inline void __attribute__((__always_inline__))
_mm_stream_pi (__m64 *__P, __m64 __A)
{
  __builtin_ia32_movntq ((unsigned long long *)__P, (unsigned long long)__A);
}

/* Likewise.  The address must be 16-byte aligned.  */
static __inline void __attribute__((__always_inline__))
_mm_stream_ps (float *__P, __m128 __A)
{
  __builtin_ia32_movntps (__P, (__v4sf)__A);
}

/* Guarantees that every preceding store is globally visible before
   any subsequent store.  */
static __inline void __attribute__((__always_inline__))
_mm_sfence (void)
{
  __builtin_ia32_sfence ();
}

/* The execution of the next instruction is delayed by an implementation
   specific amount of time.  The instruction does not modify the
   architectural state.  */
static __inline void __attribute__((__always_inline__))
_mm_pause (void)
{
  __asm__ __volatile__ ("rep; nop" : : );
}

/* Transpose the 4x4 matrix composed of row[0-3].  */
#define _MM_TRANSPOSE4_PS(row0, row1, row2, row3)			\
do {									\
  __v4sf __r0 = (row0), __r1 = (row1), __r2 = (row2), __r3 = (row3);	\
  __v4sf __t0 = __builtin_ia32_unpcklps (__r0, __r1);			\
  __v4sf __t1 = __builtin_ia32_unpcklps (__r2, __r3);			\
  __v4sf __t2 = __builtin_ia32_unpckhps (__r0, __r1);			\
  __v4sf __t3 = __builtin_ia32_unpckhps (__r2, __r3);			\
  (row0) = __builtin_ia32_movlhps (__t0, __t1);				\
  (row1) = __builtin_ia32_movhlps (__t1, __t0);				\
  (row2) = __builtin_ia32_movlhps (__t2, __t3);				\
  (row3) = __builtin_ia32_movhlps (__t3, __t2);				\
} while (0)

/* For backward source compatibility.  */
#ifdef __SSE2__
#include <emmintrin.h>
#endif

#endif /* __SSE__ */
#endif /* _XMMINTRIN_H_INCLUDED */


code:
/*-
 * Copyright (c) 2006 Joseph Koshy
 * 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/lib/libelf/gelf.h 167315 2007-03-08 04:01:30Z jkoshy $
 */

#ifndef	_GELF_H_
#define	_GELF_H_

#include <sys/cdefs.h>

#include <libelf.h>
#include <osreldate.h>

typedef Elf64_Addr	GElf_Addr;	/* Addresses */
typedef Elf64_Half	GElf_Half;	/* Half words (16 bit) */
typedef Elf64_Off	GElf_Off;	/* Offsets */
typedef Elf64_Sword	GElf_Sword;	/* Signed words (32 bit) */
typedef Elf64_Sxword	GElf_Sxword;	/* Signed long words (64 bit) */
typedef Elf64_Word	GElf_Word;	/* Unsigned words (32 bit) */
typedef Elf64_Xword	GElf_Xword;	/* Unsigned long words (64 bit) */

typedef Elf64_Dyn	GElf_Dyn;	/* ".dynamic" section entries */
typedef Elf64_Ehdr	GElf_Ehdr;	/* ELF header */
typedef Elf64_Phdr	GElf_Phdr;	/* Program header */
typedef Elf64_Shdr	GElf_Shdr;	/* Section header */
typedef Elf64_Sym	GElf_Sym;	/* Symbol table entries */
typedef Elf64_Rel	GElf_Rel;	/* Relocation entries */
typedef Elf64_Rela	GElf_Rela;	/* Relocation entries with addend */

#if	__FreeBSD_version >= 700025
typedef	Elf64_Cap	GElf_Cap;	/* SW/HW capabilities */
typedef Elf64_Move	GElf_Move;	/* Move entries */
typedef Elf64_Syminfo	GElf_Syminfo;	/* Symbol information */
#endif

#define	GELF_M_INFO			ELF64_M_INFO
#define	GELF_M_SIZE			ELF64_M_SIZE
#define	GELF_M_SYM			ELF64_M_SYM

#define	GELF_R_INFO			ELF64_R_INFO
#define	GELF_R_SYM			ELF64_R_SYM
#define	GELF_R_TYPE			ELF64_R_TYPE
#define	GELF_R_TYPE_DATA		ELF64_R_TYPE_DATA
#define	GELF_R_TYPE_ID			ELF64_R_TYPE_ID
#define	GELF_R_TYPE_INFO		ELF64_R_TYPE_INFO

#define	GELF_ST_BIND			ELF64_ST_BIND
#define	GELF_ST_INFO			ELF64_ST_INFO
#define	GELF_ST_TYPE			ELF64_ST_TYPE
#define	GELF_ST_VISIBILITY		ELF64_ST_VISIBILITY

__BEGIN_DECLS
long		gelf_checksum(Elf *_elf);
size_t		gelf_fsize(Elf *_elf, Elf_Type _type, size_t _count,
			unsigned int _version);
int		gelf_getclass(Elf *_elf);
GElf_Dyn	*gelf_getdyn(Elf_Data *_data, int _index, GElf_Dyn *_dst);
GElf_Ehdr	*gelf_getehdr(Elf *_elf, GElf_Ehdr *_dst);
GElf_Phdr	*gelf_getphdr(Elf *_elf, int _index, GElf_Phdr *_dst);
GElf_Rel	*gelf_getrel(Elf_Data *_src, int _index, GElf_Rel *_dst);
GElf_Rela	*gelf_getrela(Elf_Data *_src, int _index, GElf_Rela *_dst);
GElf_Shdr	*gelf_getshdr(Elf_Scn *_scn, GElf_Shdr *_dst);
GElf_Sym	*gelf_getsym(Elf_Data *_src, int _index, GElf_Sym *_dst);
GElf_Sym	*gelf_getsymshndx(Elf_Data *_src, Elf_Data *_shindexsrc,
			int _index, GElf_Sym *_dst, Elf32_Word *_shindexdst);
void *		gelf_newehdr(Elf *_elf, int _class);
void *		gelf_newphdr(Elf *_elf, size_t _phnum);
int		gelf_update_dyn(Elf_Data *_dst, int _index, GElf_Dyn *_src);
int		gelf_update_ehdr(Elf *_elf, GElf_Ehdr *_src);
int		gelf_update_phdr(Elf *_elf, int _index, GElf_Phdr *_src);
int		gelf_update_rel(Elf_Data *_dst, int _index, GElf_Rel *_src);
int		gelf_update_rela(Elf_Data *_dst, int _index, GElf_Rela *_src);
int		gelf_update_shdr(Elf_Scn *_dst, GElf_Shdr *_src);
int		gelf_update_sym(Elf_Data *_dst, int _index, GElf_Sym *_src);
int		gelf_update_symshndx(Elf_Data *_symdst, Elf_Data *_shindexdst,
			int _index, GElf_Sym *_symsrc, Elf32_Word _shindexsrc);
Elf_Data 	*gelf_xlatetof(Elf *_elf, Elf_Data *_dst, const Elf_Data *_src, unsigned int _encode);
Elf_Data 	*gelf_xlatetom(Elf *_elf, Elf_Data *_dst, const Elf_Data *_src, unsigned int _encode);

#if	__FreeBSD_version >= 700025
GElf_Cap	*gelf_getcap(Elf_Data *_data, int _index, GElf_Cap *_cap);
GElf_Move	*gelf_getmove(Elf_Data *_src, int _index, GElf_Move *_dst);
GElf_Syminfo	*gelf_getsyminfo(Elf_Data *_src, int _index, GElf_Syminfo *_dst);
int		gelf_update_cap(Elf_Data *_dst, int _index, GElf_Cap *_src);
int		gelf_update_move(Elf_Data *_dst, int _index, GElf_Move *_src);
int		gelf_update_syminfo(Elf_Data *_dst, int _index, GElf_Syminfo *_src);
#endif
__END_DECLS

#endif	/* _GELF_H_ */

repo_name: veiledmerc/mira

license: mit


code:
/*-
 * Copyright (c) 2006 Ruslan Ermilov <ru@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/geom/cache/g_cache.h 210046 2010-07-14 08:22:00Z ru $
 */

#ifndef	_G_CACHE_H_
#define	_G_CACHE_H_

#include <sys/endian.h>

#define	G_CACHE_CLASS_NAME	"CACHE"
#define	G_CACHE_MAGIC		"GEOM::CACHE"
#define	G_CACHE_VERSION		1

#ifdef _KERNEL
#define	G_CACHE_TYPE_MANUAL	0
#define	G_CACHE_TYPE_AUTOMATIC	1

#define	G_CACHE_DEBUG(lvl, ...)	do {					\
	if (g_cache_debug >= (lvl)) {					\
		printf("GEOM_CACHE");					\
		if (g_cache_debug > 0)					\
			printf("[%u]", lvl);				\
		printf(": ");						\
		printf(__VA_ARGS__);					\
		printf("\n");						\
	}								\
} while (0)
#define	G_CACHE_LOGREQ(bp, ...)	do {					\
	if (g_cache_debug >= 2) {					\
		printf("GEOM_CACHE[2]: ");				\
		printf(__VA_ARGS__);					\
		printf(" ");						\
		g_print_bio(bp);					\
		printf("\n");						\
	}								\
} while (0)

#define	G_CACHE_BUCKETS		(1 << 3)
#define	G_CACHE_BUCKET(bno)	((bno) & (G_CACHE_BUCKETS - 1))

struct g_cache_softc {
	struct g_geom	*sc_geom;
	int		sc_type;
	u_int		sc_bshift;
	u_int		sc_bsize;
	off_t		sc_tail;
	struct mtx	sc_mtx;
	struct callout	sc_callout;
	LIST_HEAD(, g_cache_desc) sc_desclist[G_CACHE_BUCKETS];
	TAILQ_HEAD(, g_cache_desc) sc_usedlist;
	uma_zone_t	sc_zone;

	u_int		sc_maxent;		/* max entries */
	u_int		sc_nent;		/* allocated entries */
	u_int		sc_nused;		/* re-useable entries */
	u_int		sc_invalid;		/* invalid entries */

	uintmax_t	sc_reads;		/* #reads */
	uintmax_t	sc_readbytes;		/* bytes read */
	uintmax_t	sc_cachereads;		/* #reads from cache */
	uintmax_t	sc_cachereadbytes;	/* bytes read from cache */
	uintmax_t	sc_cachehits;		/* cache hits */
	uintmax_t	sc_cachemisses;		/* cache misses */
	uintmax_t	sc_cachefull;		/* #times a cache was full */
	uintmax_t	sc_writes;		/* #writes */
	uintmax_t	sc_wrotebytes;		/* bytes written */
};
#define	sc_name	sc_geom->name

struct g_cache_desc {
	off_t		d_bno;			/* block number */
	caddr_t		d_data;			/* data area */
	struct bio	*d_biolist;		/* waiters */
	time_t		d_atime;		/* access time */
	int		d_flags;		/* flags */
#define	D_FLAG_USED	(1 << 0)			/* can be reused */
#define	D_FLAG_INVALID	(1 << 1)			/* invalid */
	LIST_ENTRY(g_cache_desc) d_next;	/* list */
	TAILQ_ENTRY(g_cache_desc) d_used;	/* used list */
};

#define	G_CACHE_NEXT_BIO1(bp)	(bp)->bio_driver1
#define	G_CACHE_NEXT_BIO2(bp)	(bp)->bio_driver2
#define	G_CACHE_DESC1(bp)	(bp)->bio_caller1
#define	G_CACHE_DESC2(bp)	(bp)->bio_caller2

#endif	/* _KERNEL */

struct g_cache_metadata {
	char		md_magic[16];		/* Magic value. */
	uint32_t	md_version;		/* Version number. */
	char		md_name[16];		/* Cache value. */
	uint32_t	md_bsize;		/* Cache block size. */
	uint32_t	md_size;		/* Cache size. */
	uint64_t	md_provsize;		/* Provider's size. */
};

static __inline void
cache_metadata_encode(const struct g_cache_metadata *md, u_char *data)
{

	bcopy(md->md_magic, data, sizeof(md->md_magic));
	le32enc(data + 16, md->md_version);
	bcopy(md->md_name, data + 20, sizeof(md->md_name));
	le32enc(data + 36, md->md_bsize);
	le32enc(data + 40, md->md_size);
	le64enc(data + 44, md->md_provsize);
}

static __inline void
cache_metadata_decode(const u_char *data, struct g_cache_metadata *md)
{

	bcopy(data, md->md_magic, sizeof(md->md_magic));
	md->md_version = le32dec(data + 16);
	bcopy(data + 20, md->md_name, sizeof(md->md_name));
	md->md_bsize = le32dec(data + 36);
	md->md_size = le32dec(data + 40);
	md->md_provsize = le64dec(data + 44);
}

#endif	/* _G_CACHE_H_ */


code:
/*-
 * Copyright (c) 2004-2005 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/geom/concat/g_concat.h 155174 2006-02-01 12:06:01Z pjd $
 */

#ifndef	_G_CONCAT_H_
#define	_G_CONCAT_H_

#include <sys/endian.h>

#define	G_CONCAT_CLASS_NAME	"CONCAT"

#define	G_CONCAT_MAGIC		"GEOM::CONCAT"
/*
 * Version history:
 * 1 - Initial version number.
 * 2 - Added 'stop' command to gconcat(8).
 * 3 - Added md_provider field to metadata and '-h' option to gconcat(8).
 * 4 - Added md_provsize field to metadata.
 */
#define	G_CONCAT_VERSION	4

#ifdef _KERNEL
#define	G_CONCAT_TYPE_MANUAL	0
#define	G_CONCAT_TYPE_AUTOMATIC	1

#define	G_CONCAT_DEBUG(lvl, ...)	do {				\
	if (g_concat_debug >= (lvl)) {					\
		printf("GEOM_CONCAT");					\
		if (g_concat_debug > 0)					\
			printf("[%u]", lvl);				\
		printf(": ");						\
		printf(__VA_ARGS__);					\
		printf("\n");						\
	}								\
} while (0)
#define	G_CONCAT_LOGREQ(bp, ...)	do {				\
	if (g_concat_debug >= 2) {					\
		printf("GEOM_CONCAT[2]: ");				\
		printf(__VA_ARGS__);					\
		printf(" ");						\
		g_print_bio(bp);					\
		printf("\n");						\
	}								\
} while (0)

struct g_concat_disk {
	struct g_consumer	*d_consumer;
	struct g_concat_softc	*d_softc;
	off_t			 d_start;
	off_t			 d_end;
};

struct g_concat_softc {
	u_int		 sc_type;	/* provider type */
	struct g_geom	*sc_geom;
	struct g_provider *sc_provider;
	uint32_t	 sc_id;		/* concat unique ID */

	struct g_concat_disk *sc_disks;
	uint16_t	 sc_ndisks;
};
#define	sc_name	sc_geom->name
#endif	/* _KERNEL */

struct g_concat_metadata {
	char		md_magic[16];	/* Magic value. */
	uint32_t	md_version;	/* Version number. */
	char		md_name[16];	/* Concat name. */
	uint32_t	md_id;		/* Unique ID. */
	uint16_t	md_no;		/* Disk number. */
	uint16_t	md_all;		/* Number of all disks. */
	char		md_provider[16]; /* Hardcoded provider. */
	uint64_t	md_provsize;	/* Provider's size. */
};
static __inline void
concat_metadata_encode(const struct g_concat_metadata *md, u_char *data)
{

	bcopy(md->md_magic, data, sizeof(md->md_magic));
	le32enc(data + 16, md->md_version);
	bcopy(md->md_name, data + 20, sizeof(md->md_name));
	le32enc(data + 36, md->md_id);
	le16enc(data + 40, md->md_no);
	le16enc(data + 42, md->md_all);
	bcopy(md->md_provider, data + 44, sizeof(md->md_provider));
	le64enc(data + 60, md->md_provsize);
}
static __inline void
concat_metadata_decode(const u_char *data, struct g_concat_metadata *md)
{

	bcopy(data, md->md_magic, sizeof(md->md_magic));
	md->md_version = le32dec(data + 16);
	bcopy(data + 20, md->md_name, sizeof(md->md_name));
	md->md_id = le32dec(data + 36);
	md->md_no = le16dec(data + 40);
	md->md_all = le16dec(data + 42);
	bcopy(data + 44, md->md_provider, sizeof(md->md_provider));
	md->md_provsize = le64dec(data + 60);
}
#endif	/* _G_CONCAT_H_ */


code:
/*-
 * Copyright (c) 2005-2011 Pawel Jakub Dawidek <pawel@dawidek.net>
 * 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/geom/eli/g_eli.h 221629 2011-05-08 09:25:16Z pjd $
 */

#ifndef	_G_ELI_H_
#define	_G_ELI_H_

#include <sys/endian.h>
#include <sys/errno.h>
#include <sys/malloc.h>
#include <crypto/sha2/sha2.h>
#include <opencrypto/cryptodev.h>
#ifdef _KERNEL
#include <sys/bio.h>
#include <sys/libkern.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/queue.h>
#include <sys/tree.h>
#include <geom/geom.h>
#else
#include <stdio.h>
#include <string.h>
#include <strings.h>
#endif
#ifndef _OpenSSL_
#include <sys/md5.h>
#endif

#define	G_ELI_CLASS_NAME	"ELI"
#define	G_ELI_MAGIC		"GEOM::ELI"
#define	G_ELI_SUFFIX		".eli"

/*
 * Version history:
 * 0 - Initial version number.
 * 1 - Added data authentication support (md_aalgo field and
 *     G_ELI_FLAG_AUTH flag).
 * 2 - Added G_ELI_FLAG_READONLY.
 * 3 - Added 'configure' subcommand.
 * 4 - IV is generated from offset converted to little-endian
 *     (the G_ELI_FLAG_NATIVE_BYTE_ORDER flag will be set for older versions).
 * 5 - Added multiple encrypton keys and AES-XTS support.
 * 6 - Fixed usage of multiple keys for authenticated providers (the
 *     G_ELI_FLAG_FIRST_KEY flag will be set for older versions).
 */
#define	G_ELI_VERSION_00	0
#define	G_ELI_VERSION_01	1
#define	G_ELI_VERSION_02	2
#define	G_ELI_VERSION_03	3
#define	G_ELI_VERSION_04	4
#define	G_ELI_VERSION_05	5
#define	G_ELI_VERSION_06	6
#define	G_ELI_VERSION		G_ELI_VERSION_06

/* ON DISK FLAGS. */
/* Use random, onetime keys. */
#define	G_ELI_FLAG_ONETIME		0x00000001
/* Ask for the passphrase from the kernel, before mounting root. */
#define	G_ELI_FLAG_BOOT			0x00000002
/* Detach on last close, if we were open for writing. */
#define	G_ELI_FLAG_WO_DETACH		0x00000004
/* Detach on last close. */
#define	G_ELI_FLAG_RW_DETACH		0x00000008
/* Provide data authentication. */
#define	G_ELI_FLAG_AUTH			0x00000010
/* Provider is read-only, we should deny all write attempts. */
#define	G_ELI_FLAG_RO			0x00000020
/* RUNTIME FLAGS. */
/* Provider was open for writing. */
#define	G_ELI_FLAG_WOPEN		0x00010000
/* Destroy device. */
#define	G_ELI_FLAG_DESTROY		0x00020000
/* Provider uses native byte-order for IV generation. */
#define	G_ELI_FLAG_NATIVE_BYTE_ORDER	0x00040000
/* Provider uses single encryption key. */
#define	G_ELI_FLAG_SINGLE_KEY		0x00080000
/* Device suspended. */
#define	G_ELI_FLAG_SUSPEND		0x00100000
/* Provider uses first encryption key. */
#define	G_ELI_FLAG_FIRST_KEY		0x00200000

#define	G_ELI_NEW_BIO	255

#define	SHA512_MDLEN		64
#define	G_ELI_AUTH_SECKEYLEN	SHA256_DIGEST_LENGTH

#define	G_ELI_MAXMKEYS		2
#define	G_ELI_MAXKEYLEN		64
#define	G_ELI_USERKEYLEN	G_ELI_MAXKEYLEN
#define	G_ELI_DATAKEYLEN	G_ELI_MAXKEYLEN
#define	G_ELI_AUTHKEYLEN	G_ELI_MAXKEYLEN
#define	G_ELI_IVKEYLEN		G_ELI_MAXKEYLEN
#define	G_ELI_SALTLEN		64
#define	G_ELI_DATAIVKEYLEN	(G_ELI_DATAKEYLEN + G_ELI_IVKEYLEN)
/* Data-Key, IV-Key, HMAC_SHA512(Derived-Key, Data-Key+IV-Key) */
#define	G_ELI_MKEYLEN		(G_ELI_DATAIVKEYLEN + SHA512_MDLEN)
#define	G_ELI_OVERWRITES	5
/* Switch data encryption key every 2^20 blocks. */
#define	G_ELI_KEY_SHIFT		20

#ifdef _KERNEL
extern int g_eli_debug;
extern u_int g_eli_overwrites;
extern u_int g_eli_batch;

#define	G_ELI_CRYPTO_UNKNOWN	0
#define	G_ELI_CRYPTO_HW		1
#define	G_ELI_CRYPTO_SW		2

#define	G_ELI_DEBUG(lvl, ...)	do {					\
	if (g_eli_debug >= (lvl)) {					\
		printf("GEOM_ELI");					\
		if (g_eli_debug > 0)					\
			printf("[%u]", lvl);				\
		printf(": ");						\
		printf(__VA_ARGS__);					\
		printf("\n");						\
	}								\
} while (0)
#define	G_ELI_LOGREQ(lvl, bp, ...)	do {				\
	if (g_eli_debug >= (lvl)) {					\
		printf("GEOM_ELI");					\
		if (g_eli_debug > 0)					\
			printf("[%u]", lvl);				\
		printf(": ");						\
		printf(__VA_ARGS__);					\
		printf(" ");						\
		g_print_bio(bp);					\
		printf("\n");						\
	}								\
} while (0)

struct g_eli_worker {
	struct g_eli_softc	*w_softc;
	struct proc		*w_proc;
	u_int			 w_number;
	uint64_t		 w_sid;
	boolean_t		 w_active;
	LIST_ENTRY(g_eli_worker) w_next;
};

struct g_eli_softc {
	struct g_geom	*sc_geom;
	u_int		 sc_crypto;
	uint8_t		 sc_mkey[G_ELI_DATAIVKEYLEN];
	uint8_t		 sc_ekey[G_ELI_DATAKEYLEN];
	TAILQ_HEAD(, g_eli_key) sc_ekeys_queue;
	RB_HEAD(g_eli_key_tree, g_eli_key) sc_ekeys_tree;
	struct mtx	 sc_ekeys_lock;
	uint64_t	 sc_ekeys_total;
	uint64_t	 sc_ekeys_allocated;
	u_int		 sc_ealgo;
	u_int		 sc_ekeylen;
	uint8_t		 sc_akey[G_ELI_AUTHKEYLEN];
	u_int		 sc_aalgo;
	u_int		 sc_akeylen;
	u_int		 sc_alen;
	SHA256_CTX	 sc_akeyctx;
	uint8_t		 sc_ivkey[G_ELI_IVKEYLEN];
	SHA256_CTX	 sc_ivctx;
	int		 sc_nkey;
	uint32_t	 sc_flags;
	int		 sc_inflight;
	off_t		 sc_mediasize;
	size_t		 sc_sectorsize;
	u_int		 sc_bytes_per_sector;
	u_int		 sc_data_per_sector;

	/* Only for software cryptography. */
	struct bio_queue_head sc_queue;
	struct mtx	 sc_queue_mtx;
	LIST_HEAD(, g_eli_worker) sc_workers;
};
#define	sc_name		 sc_geom->name
#endif	/* _KERNEL */

struct g_eli_metadata {
	char		md_magic[16];	/* Magic value. */
	uint32_t	md_version;	/* Version number. */
	uint32_t	md_flags;	/* Additional flags. */
	uint16_t	md_ealgo;	/* Encryption algorithm. */
	uint16_t	md_keylen;	/* Key length. */
	uint16_t	md_aalgo;	/* Authentication algorithm. */
	uint64_t	md_provsize;	/* Provider's size. */
	uint32_t	md_sectorsize;	/* Sector size. */
	uint8_t		md_keys;	/* Available keys. */
	int32_t		md_iterations;	/* Number of iterations for PKCS#5v2. */
	uint8_t		md_salt[G_ELI_SALTLEN]; /* Salt. */
			/* Encrypted master key (IV-key, Data-key, HMAC). */
	uint8_t		md_mkeys[G_ELI_MAXMKEYS * G_ELI_MKEYLEN];
	u_char		md_hash[16];	/* MD5 hash. */
} __packed;
#ifndef _OpenSSL_
static __inline void
eli_metadata_encode(struct g_eli_metadata *md, u_char *data)
{
	MD5_CTX ctx;
	u_char *p;

	p = data;
	bcopy(md->md_magic, p, sizeof(md->md_magic)); p += sizeof(md->md_magic);
	le32enc(p, md->md_version);	p += sizeof(md->md_version);
	le32enc(p, md->md_flags);	p += sizeof(md->md_flags);
	le16enc(p, md->md_ealgo);	p += sizeof(md->md_ealgo);
	le16enc(p, md->md_keylen);	p += sizeof(md->md_keylen);
	le16enc(p, md->md_aalgo);	p += sizeof(md->md_aalgo);
	le64enc(p, md->md_provsize);	p += sizeof(md->md_provsize);
	le32enc(p, md->md_sectorsize);	p += sizeof(md->md_sectorsize);
	*p = md->md_keys;		p += sizeof(md->md_keys);
	le32enc(p, md->md_iterations);	p += sizeof(md->md_iterations);
	bcopy(md->md_salt, p, sizeof(md->md_salt)); p += sizeof(md->md_salt);
	bcopy(md->md_mkeys, p, sizeof(md->md_mkeys)); p += sizeof(md->md_mkeys);
	MD5Init(&ctx);
	MD5Update(&ctx, data, p - data);
	MD5Final(md->md_hash, &ctx);
	bcopy(md->md_hash, p, sizeof(md->md_hash));
}
static __inline int
eli_metadata_decode_v0(const u_char *data, struct g_eli_metadata *md)
{
	MD5_CTX ctx;
	const u_char *p;

	p = data + sizeof(md->md_magic) + sizeof(md->md_version);
	md->md_flags = le32dec(p);	p += sizeof(md->md_flags);
	md->md_ealgo = le16dec(p);	p += sizeof(md->md_ealgo);
	md->md_keylen = le16dec(p);	p += sizeof(md->md_keylen);
	md->md_provsize = le64dec(p);	p += sizeof(md->md_provsize);
	md->md_sectorsize = le32dec(p);	p += sizeof(md->md_sectorsize);
	md->md_keys = *p;		p += sizeof(md->md_keys);
	md->md_iterations = le32dec(p);	p += sizeof(md->md_iterations);
	bcopy(p, md->md_salt, sizeof(md->md_salt)); p += sizeof(md->md_salt);
	bcopy(p, md->md_mkeys, sizeof(md->md_mkeys)); p += sizeof(md->md_mkeys);
	MD5Init(&ctx);
	MD5Update(&ctx, data, p - data);
	MD5Final(md->md_hash, &ctx);
	if (bcmp(md->md_hash, p, 16) != 0)
		return (EINVAL);
	return (0);
}

static __inline int
eli_metadata_decode_v1v2v3v4v5v6(const u_char *data, struct g_eli_metadata *md)
{
	MD5_CTX ctx;
	const u_char *p;

	p = data + sizeof(md->md_magic) + sizeof(md->md_version);
	md->md_flags = le32dec(p);	p += sizeof(md->md_flags);
	md->md_ealgo = le16dec(p);	p += sizeof(md->md_ealgo);
	md->md_keylen = le16dec(p);	p += sizeof(md->md_keylen);
	md->md_aalgo = le16dec(p);	p += sizeof(md->md_aalgo);
	md->md_provsize = le64dec(p);	p += sizeof(md->md_provsize);
	md->md_sectorsize = le32dec(p);	p += sizeof(md->md_sectorsize);
	md->md_keys = *p;		p += sizeof(md->md_keys);
	md->md_iterations = le32dec(p);	p += sizeof(md->md_iterations);
	bcopy(p, md->md_salt, sizeof(md->md_salt)); p += sizeof(md->md_salt);
	bcopy(p, md->md_mkeys, sizeof(md->md_mkeys)); p += sizeof(md->md_mkeys);
	MD5Init(&ctx);
	MD5Update(&ctx, data, p - data);
	MD5Final(md->md_hash, &ctx);
	if (bcmp(md->md_hash, p, 16) != 0)
		return (EINVAL);
	return (0);
}
static __inline int
eli_metadata_decode(const u_char *data, struct g_eli_metadata *md)
{
	int error;

	bcopy(data, md->md_magic, sizeof(md->md_magic));
	md->md_version = le32dec(data + sizeof(md->md_magic));
	switch (md->md_version) {
	case G_ELI_VERSION_00:
		error = eli_metadata_decode_v0(data, md);
		break;
	case G_ELI_VERSION_01:
	case G_ELI_VERSION_02:
	case G_ELI_VERSION_03:
	case G_ELI_VERSION_04:
	case G_ELI_VERSION_05:
	case G_ELI_VERSION_06:
		error = eli_metadata_decode_v1v2v3v4v5v6(data, md);
		break;
	default:
		error = EINVAL;
		break;
	}
	return (error);
}
#endif	/* !_OpenSSL */

static __inline u_int
g_eli_str2ealgo(const char *name)
{

	if (strcasecmp("null", name) == 0)
		return (CRYPTO_NULL_CBC);
	else if (strcasecmp("null-cbc", name) == 0)
		return (CRYPTO_NULL_CBC);
	else if (strcasecmp("aes", name) == 0)
		return (CRYPTO_AES_XTS);
	else if (strcasecmp("aes-cbc", name) == 0)
		return (CRYPTO_AES_CBC);
	else if (strcasecmp("aes-xts", name) == 0)
		return (CRYPTO_AES_XTS);
	else if (strcasecmp("blowfish", name) == 0)
		return (CRYPTO_BLF_CBC);
	else if (strcasecmp("blowfish-cbc", name) == 0)
		return (CRYPTO_BLF_CBC);
	else if (strcasecmp("camellia", name) == 0)
		return (CRYPTO_CAMELLIA_CBC);
	else if (strcasecmp("camellia-cbc", name) == 0)
		return (CRYPTO_CAMELLIA_CBC);
	else if (strcasecmp("3des", name) == 0)
		return (CRYPTO_3DES_CBC);
	else if (strcasecmp("3des-cbc", name) == 0)
		return (CRYPTO_3DES_CBC);
	return (CRYPTO_ALGORITHM_MIN - 1);
}

static __inline u_int
g_eli_str2aalgo(const char *name)
{

	if (strcasecmp("hmac/md5", name) == 0)
		return (CRYPTO_MD5_HMAC);
	else if (strcasecmp("hmac/sha1", name) == 0)
		return (CRYPTO_SHA1_HMAC);
	else if (strcasecmp("hmac/ripemd160", name) == 0)
		return (CRYPTO_RIPEMD160_HMAC);
	else if (strcasecmp("hmac/sha256", name) == 0)
		return (CRYPTO_SHA2_256_HMAC);
	else if (strcasecmp("hmac/sha384", name) == 0)
		return (CRYPTO_SHA2_384_HMAC);
	else if (strcasecmp("hmac/sha512", name) == 0)
		return (CRYPTO_SHA2_512_HMAC);
	return (CRYPTO_ALGORITHM_MIN - 1);
}

static __inline const char *
g_eli_algo2str(u_int algo)
{

	switch (algo) {
	case CRYPTO_NULL_CBC:
		return ("NULL");
	case CRYPTO_AES_CBC:
		return ("AES-CBC");
	case CRYPTO_AES_XTS:
		return ("AES-XTS");
	case CRYPTO_BLF_CBC:
		return ("Blowfish-CBC");
	case CRYPTO_CAMELLIA_CBC:
		return ("CAMELLIA-CBC");
	case CRYPTO_3DES_CBC:
		return ("3DES-CBC");
	case CRYPTO_MD5_HMAC:
		return ("HMAC/MD5");
	case CRYPTO_SHA1_HMAC:
		return ("HMAC/SHA1");
	case CRYPTO_RIPEMD160_HMAC:
		return ("HMAC/RIPEMD160");
	case CRYPTO_SHA2_256_HMAC:
		return ("HMAC/SHA256");
	case CRYPTO_SHA2_384_HMAC:
		return ("HMAC/SHA384");
	case CRYPTO_SHA2_512_HMAC:
		return ("HMAC/SHA512");
	}
	return ("unknown");
}

static __inline void
eli_metadata_dump(const struct g_eli_metadata *md)
{
	static const char hex[] = "0123456789abcdef";
	char str[sizeof(md->md_mkeys) * 2 + 1];
	u_int i;

	printf("     magic: %s\n", md->md_magic);
	printf("   version: %u\n", (u_int)md->md_version);
	printf("     flags: 0x%x\n", (u_int)md->md_flags);
	printf("     ealgo: %s\n", g_eli_algo2str(md->md_ealgo));
	printf("    keylen: %u\n", (u_int)md->md_keylen);
	if (md->md_flags & G_ELI_FLAG_AUTH)
		printf("     aalgo: %s\n", g_eli_algo2str(md->md_aalgo));
	printf("  provsize: %ju\n", (uintmax_t)md->md_provsize);
	printf("sectorsize: %u\n", (u_int)md->md_sectorsize);
	printf("      keys: 0x%02x\n", (u_int)md->md_keys);
	printf("iterations: %u\n", (u_int)md->md_iterations);
	bzero(str, sizeof(str));
	for (i = 0; i < sizeof(md->md_salt); i++) {
		str[i * 2] = hex[md->md_salt[i] >> 4];
		str[i * 2 + 1] = hex[md->md_salt[i] & 0x0f];
	}
	printf("      Salt: %s\n", str);
	bzero(str, sizeof(str));
	for (i = 0; i < sizeof(md->md_mkeys); i++) {
		str[i * 2] = hex[md->md_mkeys[i] >> 4];
		str[i * 2 + 1] = hex[md->md_mkeys[i] & 0x0f];
	}
	printf("Master Key: %s\n", str);
	bzero(str, sizeof(str));
	for (i = 0; i < 16; i++) {
		str[i * 2] = hex[md->md_hash[i] >> 4];
		str[i * 2 + 1] = hex[md->md_hash[i] & 0x0f];
	}
	printf("  MD5 hash: %s\n", str);
}

static __inline u_int
g_eli_keylen(u_int algo, u_int keylen)
{

	switch (algo) {
	case CRYPTO_NULL_CBC:
		if (keylen == 0)
			keylen = 64 * 8;
		else {
			if (keylen > 64 * 8)
				keylen = 0;
		}
		return (keylen);
	case CRYPTO_AES_CBC:
	case CRYPTO_CAMELLIA_CBC:
		switch (keylen) {
		case 0:
			return (128);
		case 128:
		case 192:
		case 256:
			return (keylen);
		default:
			return (0);
		}
	case CRYPTO_AES_XTS:
		switch (keylen) {
		case 0:
			return (128);
		case 128:
		case 256:
			return (keylen);
		default:
			return (0);
		}
	case CRYPTO_BLF_CBC:
		if (keylen == 0)
			return (128);
		if (keylen < 128 || keylen > 448)
			return (0);
		if ((keylen % 32) != 0)
			return (0);
		return (keylen);
	case CRYPTO_3DES_CBC:
		if (keylen == 0 || keylen == 192)
			return (192);
		return (0);
	default:
		return (0);
	}
}

static __inline u_int
g_eli_hashlen(u_int algo)
{

	switch (algo) {
	case CRYPTO_MD5_HMAC:
		return (16);
	case CRYPTO_SHA1_HMAC:
		return (20);
	case CRYPTO_RIPEMD160_HMAC:
		return (20);
	case CRYPTO_SHA2_256_HMAC:
		return (32);
	case CRYPTO_SHA2_384_HMAC:
		return (48);
	case CRYPTO_SHA2_512_HMAC:
		return (64);
	}
	return (0);
}

#ifdef _KERNEL
int g_eli_read_metadata(struct g_class *mp, struct g_provider *pp,
    struct g_eli_metadata *md);
struct g_geom *g_eli_create(struct gctl_req *req, struct g_class *mp,
    struct g_provider *bpp, const struct g_eli_metadata *md,
    const u_char *mkey, int nkey);
int g_eli_destroy(struct g_eli_softc *sc, boolean_t force);

int g_eli_access(struct g_provider *pp, int dr, int dw, int de);
void g_eli_config(struct gctl_req *req, struct g_class *mp, const char *verb);

void g_eli_read_done(struct bio *bp);
void g_eli_write_done(struct bio *bp);
int g_eli_crypto_rerun(struct cryptop *crp);
void g_eli_crypto_ivgen(struct g_eli_softc *sc, off_t offset, u_char *iv,
    size_t size);

void g_eli_crypto_read(struct g_eli_softc *sc, struct bio *bp, boolean_t fromworker);
void g_eli_crypto_run(struct g_eli_worker *wr, struct bio *bp);

void g_eli_auth_read(struct g_eli_softc *sc, struct bio *bp);
void g_eli_auth_run(struct g_eli_worker *wr, struct bio *bp);
#endif

void g_eli_mkey_hmac(unsigned char *mkey, const unsigned char *key);
int g_eli_mkey_decrypt(const struct g_eli_metadata *md,
    const unsigned char *key, unsigned char *mkey, unsigned *nkeyp);
int g_eli_mkey_encrypt(unsigned algo, const unsigned char *key, unsigned keylen,
    unsigned char *mkey);
#ifdef _KERNEL
void g_eli_mkey_propagate(struct g_eli_softc *sc, const unsigned char *mkey);
#endif

int g_eli_crypto_encrypt(u_int algo, u_char *data, size_t datasize,
    const u_char *key, size_t keysize);
int g_eli_crypto_decrypt(u_int algo, u_char *data, size_t datasize,
    const u_char *key, size_t keysize);

struct hmac_ctx {
	SHA512_CTX	shactx;
	u_char		k_opad[128];
};

void g_eli_crypto_hmac_init(struct hmac_ctx *ctx, const uint8_t *hkey,
    size_t hkeylen);
void g_eli_crypto_hmac_update(struct hmac_ctx *ctx, const uint8_t *data,
    size_t datasize);
void g_eli_crypto_hmac_final(struct hmac_ctx *ctx, uint8_t *md, size_t mdsize);
void g_eli_crypto_hmac(const uint8_t *hkey, size_t hkeysize,
    const uint8_t *data, size_t datasize, uint8_t *md, size_t mdsize);

#ifdef _KERNEL
void g_eli_key_init(struct g_eli_softc *sc);
void g_eli_key_destroy(struct g_eli_softc *sc);
uint8_t *g_eli_key_hold(struct g_eli_softc *sc, off_t offset, size_t blocksize);
void g_eli_key_drop(struct g_eli_softc *sc, uint8_t *rawkey);
#endif
#endif	/* !_G_ELI_H_ */


code:
/*-
 * Copyright (c) 2005 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/geom/eli/pkcs5v2.h 155174 2006-02-01 12:06:01Z pjd $
 */

#ifndef _PKCS5V2_H_
#define	_PKCS5V2_H_
void pkcs5v2_genkey(uint8_t *key, unsigned keylen, const uint8_t *salt,
    size_t saltsize, const char *passphrase, u_int iterations);
#ifndef _KERNEL
int pkcs5v2_calculate(int usecs);
#endif
#endif	/* !_PKCS5V2_H_ */


code:
/*-
 * Copyright (c) 2004-2009 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/geom/gate/g_gate.h 220062 2011-03-27 19:56:55Z trociny $
 */

#ifndef _G_GATE_H_
#define _G_GATE_H_

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

#include <geom/geom.h>

#define	G_GATE_CLASS_NAME	"GATE"
#define	G_GATE_PROVIDER_NAME	"ggate"
#define	G_GATE_MOD_NAME		"ggate"
#define	G_GATE_CTL_NAME		"ggctl"

#define G_GATE_VERSION		2

/*
 * Maximum number of request that can be stored in
 * the queue when there are no workers.
 */
#define	G_GATE_MAX_QUEUE_SIZE	4096

#define	G_GATE_FLAG_READONLY	0x0001
#define	G_GATE_FLAG_WRITEONLY	0x0002
#define	G_GATE_FLAG_DESTROY	0x1000
#define	G_GATE_USERFLAGS	(G_GATE_FLAG_READONLY | G_GATE_FLAG_WRITEONLY)

/*
 * Pick unit number automatically in /dev/ggate<unit>.
 */
#define	G_GATE_UNIT_AUTO	(-1)
/*
 * Full provider name is given, so don't use ggate<unit>.
 */
#define	G_GATE_NAME_GIVEN	(-2)

#define G_GATE_CMD_CREATE	_IOWR('m', 0, struct g_gate_ctl_create)
#define G_GATE_CMD_DESTROY	_IOWR('m', 1, struct g_gate_ctl_destroy)
#define G_GATE_CMD_CANCEL	_IOWR('m', 2, struct g_gate_ctl_cancel)
#define G_GATE_CMD_START	_IOWR('m', 3, struct g_gate_ctl_io)
#define G_GATE_CMD_DONE		_IOWR('m', 4, struct g_gate_ctl_io)

#define	G_GATE_INFOSIZE		2048

#ifdef _KERNEL
/*
 * 'P:' means 'Protected by'.
 */
struct g_gate_softc {
	char			*sc_name;		/* P: (read-only) */
	int			 sc_unit;		/* P: (read-only) */
	int			 sc_ref;		/* P: g_gate_list_mtx */
	struct g_provider	*sc_provider;		/* P: (read-only) */
	uint32_t		 sc_flags;		/* P: sc_queue_mtx */

	struct bio_queue_head	 sc_inqueue;		/* P: sc_queue_mtx */
	struct bio_queue_head	 sc_outqueue;		/* P: sc_queue_mtx */
	struct mtx		 sc_queue_mtx;
	uint32_t		 sc_queue_count;	/* P: sc_queue_mtx */
	uint32_t		 sc_queue_size;		/* P: (read-only) */
	u_int			 sc_timeout;		/* P: (read-only) */
	struct callout		 sc_callout;		/* P: (modified only
							       from callout
							       thread) */
	uintptr_t		 sc_seq;		/* P: (modified only
							       from g_down
							       thread) */
	LIST_ENTRY(g_gate_softc) sc_next;		/* P: g_gate_list_mtx */
	char			 sc_info[G_GATE_INFOSIZE]; /* P: (read-only) */
};

#define	G_GATE_DEBUG(lvl, ...)	do {					\
	if (g_gate_debug >= (lvl)) {					\
		printf("GEOM_GATE");					\
		if (g_gate_debug > 0)					\
			printf("[%u]", lvl);				\
		printf(": ");						\
		printf(__VA_ARGS__);					\
		printf("\n");						\
	}								\
} while (0)
#define	G_GATE_LOGREQ(lvl, bp, ...)	do {				\
	if (g_gate_debug >= (lvl)) {					\
		printf("GEOM_GATE");					\
		if (g_gate_debug > 0)					\
			printf("[%u]", lvl);				\
		printf(": ");						\
		printf(__VA_ARGS__);					\
		printf(" ");						\
		g_print_bio(bp);					\
		printf("\n");						\
	}								\
} while (0)
#endif	/* !_KERNEL */

struct g_gate_ctl_create {
	u_int	gctl_version;
	off_t	gctl_mediasize;
	u_int	gctl_sectorsize;
	u_int	gctl_flags;
	u_int	gctl_maxcount;
	u_int	gctl_timeout;
	char	gctl_name[NAME_MAX];
	char	gctl_info[G_GATE_INFOSIZE];
	int	gctl_unit;	/* in/out */
};

struct g_gate_ctl_destroy {
	u_int	gctl_version;
	int	gctl_unit;
	int	gctl_force;
	char	gctl_name[NAME_MAX];
};

struct g_gate_ctl_cancel {
	u_int		gctl_version;
	int		gctl_unit;
	uintptr_t	gctl_seq;
	char		gctl_name[NAME_MAX];
};

struct g_gate_ctl_io {
	u_int		 gctl_version;
	int		 gctl_unit;
	uintptr_t	 gctl_seq;
	u_int		 gctl_cmd;
	off_t		 gctl_offset;
	off_t		 gctl_length;
	void		*gctl_data;
	int		 gctl_error;
};
#endif	/* !_G_GATE_H_ */


code:
/*-
 * Copyright (c) 2002 Poul-Henning Kamp
 * Copyright (c) 2002 Networks Associates Technology, Inc.
 * All rights reserved.
 *
 * This software was developed for the FreeBSD Project by Poul-Henning Kamp
 * and NAI Labs, the Security Research Division of Network Associates, Inc.
 * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
 * DARPA CHATS research program.
 *
 * 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. The names of the authors may not 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.
 *
 * $FreeBSD: release/9.0.0/sys/geom/geom.h 224147 2011-07-17 20:35:30Z pjd $
 */

#ifndef _GEOM_GEOM_H_
#define _GEOM_GEOM_H_

#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/sx.h>
#include <sys/queue.h>
#include <sys/ioccom.h>
#include <sys/conf.h>
#include <sys/module.h>

struct g_class;
struct g_geom;
struct g_consumer;
struct g_provider;
struct g_stat;
struct thread;
struct bio;
struct sbuf;
struct gctl_req;
struct g_configargs;

typedef int g_config_t (struct g_configargs *ca);
typedef void g_ctl_req_t (struct gctl_req *, struct g_class *cp, char const *verb);
typedef int g_ctl_create_geom_t (struct gctl_req *, struct g_class *cp, struct g_provider *pp);
typedef int g_ctl_destroy_geom_t (struct gctl_req *, struct g_class *cp, struct g_geom *gp);
typedef int g_ctl_config_geom_t (struct gctl_req *, struct g_geom *gp, const char *verb);
typedef void g_init_t (struct g_class *mp);
typedef void g_fini_t (struct g_class *mp);
typedef struct g_geom * g_taste_t (struct g_class *, struct g_provider *, int flags);
typedef int g_ioctl_t(struct g_provider *pp, u_long cmd, void *data, int fflag, struct thread *td);
#define G_TF_NORMAL		0
#define G_TF_INSIST		1
#define G_TF_TRANSPARENT	2
typedef int g_access_t (struct g_provider *, int, int, int);
/* XXX: not sure about the thread arg */
typedef void g_orphan_t (struct g_consumer *);

typedef void g_start_t (struct bio *);
typedef void g_spoiled_t (struct g_consumer *);
typedef void g_attrchanged_t (struct g_consumer *, const char *attr);
typedef void g_dumpconf_t (struct sbuf *, const char *indent, struct g_geom *,
    struct g_consumer *, struct g_provider *);

/*
 * The g_class structure describes a transformation class.  In other words
 * all BSD disklabel handlers share one g_class, all MBR handlers share
 * one common g_class and so on.
 * Certain operations are instantiated on the class, most notably the
 * taste and config_geom functions.
 */
struct g_class {
	const char		*name;
	u_int			version;
	u_int			spare0;
	g_taste_t		*taste;
	g_config_t		*config;
	g_ctl_req_t		*ctlreq;
	g_init_t		*init;
	g_fini_t		*fini;
	g_ctl_destroy_geom_t	*destroy_geom;
	/*
	 * Default values for geom methods
	 */
	g_start_t		*start;
	g_spoiled_t		*spoiled;
	g_attrchanged_t		*attrchanged;
	g_dumpconf_t		*dumpconf;
	g_access_t		*access;
	g_orphan_t		*orphan;
	g_ioctl_t		*ioctl;
	void			*spare1;
	void			*spare2;
	/*
	 * The remaining elements are private
	 */
	LIST_ENTRY(g_class)	class;
	LIST_HEAD(,g_geom)	geom;
};

#define G_VERSION_00	0x19950323
#define G_VERSION_01	0x20041207	/* add fflag to g_ioctl_t */
#define G_VERSION	G_VERSION_01

/*
 * The g_geom is an instance of a g_class.
 */
struct g_geom {
	char			*name;
	struct g_class		*class;
	LIST_ENTRY(g_geom)	geom;
	LIST_HEAD(,g_consumer)	consumer;
	LIST_HEAD(,g_provider)	provider;
	TAILQ_ENTRY(g_geom)	geoms;	/* XXX: better name */
	int			rank;
	g_start_t		*start;
	g_spoiled_t		*spoiled;
	g_attrchanged_t		*attrchanged;
	g_dumpconf_t		*dumpconf;
	g_access_t		*access;
	g_orphan_t		*orphan;
	g_ioctl_t		*ioctl;
	void			*spare0;
	void			*spare1;
	void			*softc;
	unsigned		flags;
#define	G_GEOM_WITHER		1
#define	G_GEOM_VOLATILE_BIO	2
};

/*
 * The g_bioq is a queue of struct bio's.
 * XXX: possibly collection point for statistics.
 * XXX: should (possibly) be collapsed with sys/bio.h::bio_queue_head.
 */
struct g_bioq {
	TAILQ_HEAD(, bio)	bio_queue;
	struct mtx		bio_queue_lock;
	int			bio_queue_length;
};

/*
 * A g_consumer is an attachment point for a g_provider.  One g_consumer
 * can only be attached to one g_provider, but multiple g_consumers
 * can be attached to one g_provider.
 */

struct g_consumer {
	struct g_geom		*geom;
	LIST_ENTRY(g_consumer)	consumer;
	struct g_provider	*provider;
	LIST_ENTRY(g_consumer)	consumers;	/* XXX: better name */
	int			acr, acw, ace;
	int			spoiled;
	struct devstat		*stat;
	u_int			nstart, nend;

	/* Two fields for the implementing class to use */
	void			*private;
	u_int			index;
};

/*
 * A g_provider is a "logical disk".
 */
struct g_provider {
	char			*name;
	LIST_ENTRY(g_provider)	provider;
	struct g_geom		*geom;
	LIST_HEAD(,g_consumer)	consumers;
	int			acr, acw, ace;
	int			error;
	TAILQ_ENTRY(g_provider)	orphan;
	off_t			mediasize;
	u_int			sectorsize;
	u_int			stripesize;
	u_int			stripeoffset;
	struct devstat		*stat;
	u_int			nstart, nend;
	u_int			flags;
#define G_PF_CANDELETE		0x1
#define G_PF_WITHER		0x2
#define G_PF_ORPHAN		0x4

	/* Two fields for the implementing class to use */
	void			*private;
	u_int			index;
};

/*
 * Descriptor of a classifier. We can register a function and
 * an argument, which is called by g_io_request() on bio's
 * that are not previously classified.
 */
struct g_classifier_hook {
	TAILQ_ENTRY(g_classifier_hook) link;
	int			(*func)(void *arg, struct bio *bp);
	void			*arg;
};

/* BIO_GETATTR("GEOM::setstate") argument values. */
#define G_STATE_FAILED		0
#define G_STATE_REBUILD		1
#define G_STATE_RESYNC		2
#define G_STATE_ACTIVE		3

/* geom_dev.c */
struct cdev;
void g_dev_print(void);
void g_dev_physpath_changed(void);
struct g_provider *g_dev_getprovider(struct cdev *dev);

/* geom_dump.c */
void g_trace(int level, const char *, ...);
#	define G_T_TOPOLOGY	1
#	define G_T_BIO		2
#	define G_T_ACCESS	4

/* geom_event.c */
typedef void g_event_t(void *, int flag);
#define EV_CANCEL	1
int g_post_event(g_event_t *func, void *arg, int flag, ...);
int g_waitfor_event(g_event_t *func, void *arg, int flag, ...);
void g_cancel_event(void *ref);
int g_attr_changed(struct g_provider *pp, const char *attr, int flag);
void g_orphan_provider(struct g_provider *pp, int error);
void g_waitidlelock(void);

/* geom_subr.c */
int g_access(struct g_consumer *cp, int nread, int nwrite, int nexcl);
int g_attach(struct g_consumer *cp, struct g_provider *pp);
int g_compare_names(const char *namea, const char *nameb);
void g_destroy_consumer(struct g_consumer *cp);
void g_destroy_geom(struct g_geom *pp);
void g_destroy_provider(struct g_provider *pp);
void g_detach(struct g_consumer *cp);
void g_error_provider(struct g_provider *pp, int error);
struct g_provider *g_provider_by_name(char const *arg);
int g_getattr__(const char *attr, struct g_consumer *cp, void *var, int len);
#define g_getattr(a, c, v) g_getattr__((a), (c), (v), sizeof *(v))
int g_handleattr(struct bio *bp, const char *attribute, const void *val,
    int len);
int g_handleattr_int(struct bio *bp, const char *attribute, int val);
int g_handleattr_off_t(struct bio *bp, const char *attribute, off_t val);
int g_handleattr_str(struct bio *bp, const char *attribute, const char *str);
struct g_consumer * g_new_consumer(struct g_geom *gp);
struct g_geom * g_new_geomf(struct g_class *mp, const char *fmt, ...);
struct g_provider * g_new_providerf(struct g_geom *gp, const char *fmt, ...);
int g_retaste(struct g_class *mp);
void g_spoil(struct g_provider *pp, struct g_consumer *cp);
int g_std_access(struct g_provider *pp, int dr, int dw, int de);
void g_std_done(struct bio *bp);
void g_std_spoiled(struct g_consumer *cp);
void g_wither_geom(struct g_geom *gp, int error);
void g_wither_geom_close(struct g_geom *gp, int error);
void g_wither_provider(struct g_provider *pp, int error);

#if defined(DIAGNOSTIC) || defined(DDB)
int g_valid_obj(void const *ptr);
#endif
#ifdef DIAGNOSTIC
#define G_VALID_CLASS(foo) \
    KASSERT(g_valid_obj(foo) == 1, ("%p is not a g_class", foo))
#define G_VALID_GEOM(foo) \
    KASSERT(g_valid_obj(foo) == 2, ("%p is not a g_geom", foo))
#define G_VALID_CONSUMER(foo) \
    KASSERT(g_valid_obj(foo) == 3, ("%p is not a g_consumer", foo))
#define G_VALID_PROVIDER(foo) \
    KASSERT(g_valid_obj(foo) == 4, ("%p is not a g_provider", foo))
#else
#define G_VALID_CLASS(foo) do { } while (0)
#define G_VALID_GEOM(foo) do { } while (0)
#define G_VALID_CONSUMER(foo) do { } while (0)
#define G_VALID_PROVIDER(foo) do { } while (0)
#endif

int g_modevent(module_t, int, void *);

/* geom_io.c */
struct bio * g_clone_bio(struct bio *);
struct bio * g_duplicate_bio(struct bio *);
void g_destroy_bio(struct bio *);
void g_io_deliver(struct bio *bp, int error);
int g_io_getattr(const char *attr, struct g_consumer *cp, int *len, void *ptr);
int g_io_flush(struct g_consumer *cp);
int g_register_classifier(struct g_classifier_hook *hook);
void g_unregister_classifier(struct g_classifier_hook *hook);
void g_io_request(struct bio *bp, struct g_consumer *cp);
struct bio *g_new_bio(void);
struct bio *g_alloc_bio(void);
void * g_read_data(struct g_consumer *cp, off_t offset, off_t length, int *error);
int g_write_data(struct g_consumer *cp, off_t offset, void *ptr, off_t length);
int g_delete_data(struct g_consumer *cp, off_t offset, off_t length);
void g_print_bio(struct bio *bp);

/* geom_kern.c / geom_kernsim.c */

#ifdef _KERNEL

extern struct sx topology_lock;

struct g_kerneldump {
	off_t		offset;
	off_t		length;
	struct dumperinfo di;
};

MALLOC_DECLARE(M_GEOM);

static __inline void *
g_malloc(int size, int flags)
{
	void *p;

	p = malloc(size, M_GEOM, flags);
	return (p);
}

static __inline void
g_free(void *ptr)
{

#ifdef DIAGNOSTIC
	if (sx_xlocked(&topology_lock)) {
		KASSERT(g_valid_obj(ptr) == 0,
		    ("g_free(%p) of live object, type %d", ptr,
		    g_valid_obj(ptr)));
	}
#endif
	free(ptr, M_GEOM);
}

#define g_topology_lock() 					\
	do {							\
		mtx_assert(&Giant, MA_NOTOWNED);		\
		sx_xlock(&topology_lock);			\
	} while (0)

#define g_topology_try_lock()	sx_try_xlock(&topology_lock)

#define g_topology_unlock()					\
	do {							\
		sx_xunlock(&topology_lock);			\
	} while (0)

#define g_topology_assert()					\
	do {							\
		sx_assert(&topology_lock, SX_XLOCKED);		\
	} while (0)

#define g_topology_assert_not()					\
	do {							\
		sx_assert(&topology_lock, SX_UNLOCKED);		\
	} while (0)

#define g_topology_sleep(chan, timo)				\
	sx_sleep(chan, &topology_lock, 0, "gtopol", timo)

#define DECLARE_GEOM_CLASS(class, name) 			\
	static moduledata_t name##_mod = {			\
		#name, g_modevent, &class			\
	};							\
	DECLARE_MODULE(name, name##_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST);

#endif /* _KERNEL */

/* geom_ctl.c */
int gctl_set_param(struct gctl_req *req, const char *param, void const *ptr, int len);
void gctl_set_param_err(struct gctl_req *req, const char *param, void const *ptr, int len);
void *gctl_get_param(struct gctl_req *req, const char *param, int *len);
char const *gctl_get_asciiparam(struct gctl_req *req, const char *param);
void *gctl_get_paraml(struct gctl_req *req, const char *param, int len);
int gctl_error(struct gctl_req *req, const char *fmt, ...) __printflike(2, 3);
struct g_class *gctl_get_class(struct gctl_req *req, char const *arg);
struct g_geom *gctl_get_geom(struct gctl_req *req, struct g_class *mpr, char const *arg);
struct g_provider *gctl_get_provider(struct gctl_req *req, char const *arg);

#endif /* _GEOM_GEOM_H_ */


code:
/*-
 * Copyright (c) 2003 Poul-Henning Kamp
 * 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. The names of the authors may not 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.
 *
 * $FreeBSD: release/9.0.0/sys/geom/geom_ctl.h 115624 2003-06-01 13:47:51Z phk $
 */

#ifndef _GEOM_GEOM_CTL_H_
#define _GEOM_GEOM_CTL_H_

#include <sys/ioccom.h>

/*
 * Version number.  Used to check consistency between kernel and libgeom.
 */
#define GCTL_VERSION	2

struct gctl_req_arg {
	u_int				nlen;
	char				*name;
	off_t				offset;
	int				flag;
	int				len;
	void				*value;
	/* kernel only fields */
	void				*kvalue;
};

#define GCTL_PARAM_RD		1	/* Must match VM_PROT_READ */
#define GCTL_PARAM_WR		2	/* Must match VM_PROT_WRITE */
#define GCTL_PARAM_RW		(GCTL_PARAM_RD | GCTL_PARAM_WR)
#define GCTL_PARAM_ASCII	4

/* These are used in the kernel only */
#define GCTL_PARAM_NAMEKERNEL	8
#define GCTL_PARAM_VALUEKERNEL	16
#define GCTL_PARAM_CHANGED	32

struct gctl_req {
	u_int				version;
	u_int				serial;
	u_int				narg;
	struct gctl_req_arg		*arg;
	u_int				lerror;
	char				*error;
	struct gctl_req_table		*reqt;

	/* kernel only fields */
	int				nerror;
	struct sbuf			*serror;
};

#define GEOM_CTL	_IOW('G', GCTL_VERSION, struct gctl_req)

#define PATH_GEOM_CTL	"geom.ctl"

#endif /* _GEOM_GEOM_CTL_H_ */


code:
/*-
 * Copyright (c) 2003 Poul-Henning Kamp
 * All rights reserved.
 *
 * This software was developed for the FreeBSD Project by Poul-Henning Kamp
 * and NAI Labs, the Security Research Division of Network Associates, Inc.
 * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
 * DARPA CHATS research program.
 *
 * 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. The names of the authors may not 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.
 *
 * $FreeBSD: release/9.0.0/sys/geom/geom_disk.h 223089 2011-06-14 17:10:32Z gibbs $
 */

#ifndef _GEOM_GEOM_DISK_H_
#define _GEOM_GEOM_DISK_H_

#ifdef _KERNEL

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

struct disk;

typedef	int	disk_open_t(struct disk *);
typedef	int	disk_close_t(struct disk *);
typedef	void	disk_strategy_t(struct bio *bp);
typedef	int	disk_getattr_t(struct bio *bp);
typedef	int	disk_ioctl_t(struct disk *, u_long cmd, void *data,
			int fflag, struct thread *td);
		/* NB: disk_ioctl_t SHALL be cast'able to d_ioctl_t */

struct g_geom;
struct devstat;

struct disk {
	/* Fields which are private to geom_disk */
	struct g_geom		*d_geom;
	struct devstat		*d_devstat;
	int			d_destroyed;

	/* Shared fields */
	u_int			d_flags;
	const char		*d_name;
	u_int			d_unit;
	struct bio_queue_head	*d_queue;
	struct mtx		*d_lock;

	/* Disk methods  */
	disk_open_t		*d_open;
	disk_close_t		*d_close;
	disk_strategy_t		*d_strategy;
	disk_ioctl_t		*d_ioctl;
	dumper_t		*d_dump;
	disk_getattr_t		*d_getattr;

	/* Info fields from driver to geom_disk.c. Valid when open */
	u_int			d_sectorsize;
	off_t			d_mediasize;
	u_int			d_fwsectors;
	u_int			d_fwheads;
	u_int			d_maxsize;
	u_int			d_stripeoffset;
	u_int			d_stripesize;
	char			d_ident[DISK_IDENT_SIZE];
	char			d_descr[DISK_IDENT_SIZE];
	uint16_t		d_hba_vendor;
	uint16_t		d_hba_device;
	uint16_t		d_hba_subvendor;
	uint16_t		d_hba_subdevice;

	/* Fields private to the driver */
	void			*d_drv1;
};

#define DISKFLAG_NEEDSGIANT	0x1
#define DISKFLAG_OPEN		0x2
#define DISKFLAG_CANDELETE	0x4
#define DISKFLAG_CANFLUSHCACHE	0x8

struct disk *disk_alloc(void);
void disk_create(struct disk *disk, int version);
void disk_destroy(struct disk *disk);
void disk_gone(struct disk *disk);
void disk_attr_changed(struct disk *dp, const char *attr, int flag);

#define DISK_VERSION_00		0x58561059
#define DISK_VERSION_01		0x5856105a
#define DISK_VERSION		DISK_VERSION_01

#endif /* _KERNEL */
#endif /* _GEOM_GEOM_DISK_H_ */


code:
/*-
 * Copyright (c) 2002 Poul-Henning Kamp
 * Copyright (c) 2002 Networks Associates Technology, Inc.
 * All rights reserved.
 *
 * This software was developed for the FreeBSD Project by Poul-Henning Kamp
 * and NAI Labs, the Security Research Division of Network Associates, Inc.
 * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
 * DARPA CHATS research program.
 *
 * 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. The names of the authors may not 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.
 *
 * $FreeBSD: release/9.0.0/sys/geom/geom_int.h 136946 2004-10-25 12:28:28Z phk $
 */

LIST_HEAD(class_list_head, g_class);
TAILQ_HEAD(g_tailq_head, g_geom);

extern int g_collectstats;
extern int g_debugflags;
/*
 * 1	G_T_TOPOLOGY
 * 2	G_T_BIO
 * 4	G_T_ACCESS
 * 8	(unused)
 * 16	Allow footshooting on rank#1 providers
 * 32	G_T_DETAILS
 */
#define G_F_DISKIOCTL	64
#define G_F_CTLDUMP	128

/* geom_dump.c */
void g_confxml(void *, int flag);
void g_conf_specific(struct sbuf *sb, struct g_class *mp, struct g_geom *gp, struct g_provider *pp, struct g_consumer *cp);
void g_confdot(void *, int flag);
void g_conftxt(void *, int flag);

/* geom_event.c */
void g_event_init(void);
void g_run_events(void);
void g_do_wither(void);

/* geom_subr.c */
extern struct class_list_head g_classes;
extern char *g_wait_event, *g_wait_sim, *g_wait_up, *g_wait_down;
int g_wither_washer(void);

/* geom_io.c */
void g_io_init(void);
void g_io_schedule_down(struct thread *tp);
void g_io_schedule_up(struct thread *tp);

/* geom_kern.c / geom_kernsim.c */
void g_init(void);
extern int g_shutdown;

/* geom_ctl.c */
void g_ctl_init(void);