/**
 * @file capidef.h
 *
 * CapiDefinitions - Tool-definitions for use with the CAPI20-header.
 *
 * Copyright: 2002-2003 Thomas Wintergerst. All rights reserved.
 *
 * $FreeBSD$
 * $Id: capidef.h,v 1.1.2.1 2006/02/28 21:35:20 thomas Exp $
 * $Project:    CAPI for BSD $
 * $Target:     CAPI headers $
 * @date        03.08.2002
 * @author      "Thomas Wintergerst" <twinterg@gmx.de>
 * <p>
 *
 * 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.
 *
 * </p>
 */

#ifndef __CAPIDEF_H
#define __CAPIDEF_H





/* === public declarations =============================================== */





/* --- macros for accessing elements of CAPI messages --- */

/* The CAPI messages and their parameters are defined to be layed out in what
 * is called "little endian" byte order (aka. Intel byte order). This is
 * expected by the CAPI library and the drivers for ISDN controllers. To create
 * this layout on machines with "big endian" byte order (aka. motorola byte
 * order) the following macro definitions may be used. On machines with Intel
 * byte order one may access the members of CAPI messages directly.
 */

/* Todo: To speed up reading and writing CAPI message fields on machines with
 *       Intel byte order one could test for big or little endian. According
 *       to the result the typedefs and macros should be defined as if
 *       WANT_MACHINE_INDEPENDANT_CAPI_DEFS was undefined.
 */

/* If the machine is not Intel-based, we must use the byte-array-based form of
 * the CAPI structure members.
 */
#if defined (__alpha__) || defined (__sparc64__)
#  ifndef WANT_MACHINE_INDEPENDANT_CAPI_DEFS
#     define WANT_MACHINE_INDEPENDANT_CAPI_DEFS
#  endif /* WANT_MACHINE_INDEPENDANT_CAPI_DEFS */
#endif /* __alpha__ || __sparc__ */



#ifdef WANT_MACHINE_INDEPENDANT_CAPI_DEFS



typedef unsigned char   cQWORD [8];
typedef unsigned char   cDWORD [4];
typedef unsigned char   cWORD [2];
typedef unsigned char   cBYTE;

#if defined (WIN32)

#define C_GET_BYTE(p)   (p)
#define C_GET_WORD(p)   ((unsigned short) (((p) [1] << 8) | (p) [0]))
#define C_GET_DWORD(p)  ((unsigned long) ((C_GET_WORD ((p) + 2) << 16) | C_GET_WORD (p)))
#define C_GET_QWORD(p)  ((unsigned __int64) ((C_GET_DWORD ((p) + 4) << 32) | C_GET_DWORD (p)))

/* Important: Use these macros only in fully braced blocks! Do not use them as
 *            the only statement (without enclosing braces) of an if-block!
 */
#define C_PUT_BYTE(p, v)        { (p) = (unsigned char) (v); }
#define C_PUT_WORD(p, v)        {                                                \
                                   (p)[0] = (unsigned char) ((v) & 0xff);        \
                                   (p)[1] = (unsigned char) (((v) >> 8) & 0xff); \
                                }
#define C_PUT_DWORD(p, v)       {                                       \
                                   C_PUT_WORD( (p), (v) & 0xffff );     \
                                   C_PUT_WORD( (p)+2, (v) >> 16 );      \
                                }
#define C_PUT_QWORD(p, v)       {                                       \
                                   C_PUT_DWORD ((p), (v) & 0xffffffff); \
                                   C_PUT_DWORD ((p) + 4, (v) >> 32);    \
                                }

#define C_LOW_PTR_DWORD( lp ) \
   ((DWORD) (((__int64) (lp)) & 0xFFFFFFFF))

#define C_HIGH_PTR_DWORD( lp ) \
   ((DWORD) (((__int64) (lp)) >> 32))

#define C_MAKE_QWORD( lw, hw ) \
   ((__int64) (lw) | ((__int64) (hw) << 32))

#else /* WIN32 */

#include <sys/param.h>

#define C_GET_BYTE(p)   (p)
#define C_GET_WORD(p)   ((u_int16_t) (((p) [1] << 8) | (p) [0]))
#define C_GET_DWORD(p)  ((u_int32_t) ((C_GET_WORD ((p) + 2) << 16) | C_GET_WORD (p)))
#define C_GET_QWORD(p)  ((u_int64_t) ((C_GET_DWORD ((p) + 4) << 32) | C_GET_DWORD (p)))

/* Important: Use these macros only in fully braced blocks! Do not use them as
 *            the only statement (without enclosing braces) of an if-block!
 */
#define C_PUT_BYTE(p, v)        { (p) = (u_int8_t) (v); }
#define C_PUT_WORD(p, v)        {                                           \
                                   (p)[0] = (u_int8_t) ((v) & 0xff);        \
                                   (p)[1] = (u_int8_t) (((v) >> 8) & 0xff); \
                                }
#define C_PUT_DWORD(p, v)       {                                       \
                                   C_PUT_WORD( (p), (v) & 0xffff );     \
                                   C_PUT_WORD( (p)+2, (v) >> 16 );      \
                                }
#define C_PUT_QWORD(p, v)       {                                       \
                                   C_PUT_DWORD ((p), (v) & 0xffffffff); \
                                   C_PUT_DWORD ((p) + 4, (v) >> 32);    \
                                }

#if defined (__alpha__) || defined (__ia64__) || defined (__amd64__) || defined (__sparc64__)

#define C_LOW_PTR_DWORD( lp ) \
   ((u_int32_t) (((u_int64_t) (lp)) & 0xFFFFFFFF))

#define C_HIGH_PTR_DWORD( lp ) \
   ((u_int32_t) (((u_int64_t) (lp)) >> 32))

#else /* __alpha__ || __ia64__ || __amd64__ || __sparc64__ */

#define C_LOW_PTR_DWORD( p )    ((u_int32_t) (p))

#define C_HIGH_PTR_DWORD( p )   0

#endif /* __alpha__ || __ia64__ || __amd64__ || __sparc64__ */

#define C_MAKE_QWORD( lw, hw ) \
   ((u_int64_t) (lw) | ((u_int64_t) (hw) << 32))

#endif /* WIN32 */



#else /* WANT_MACHINE_INDEPENDANT_CAPI_DEFS */



#if defined (WIN32)

typedef unsigned __int64 cQWORD;
typedef unsigned long    cDWORD;
typedef unsigned short   cWORD;
typedef unsigned char    cBYTE;

#define C_LOW_PTR_DWORD( lp ) \
   ((cDWORD) (((cQWORD) (lp)) & 0xFFFFFFFF))

#define C_HIGH_PTR_DWORD( lp ) \
   ((cDWORD) (((cQWORD) (lp)) >> 32))

#else /* WIN32 */

#include <sys/param.h>

typedef u_int64_t cQWORD;
typedef u_int32_t cDWORD;
typedef u_int16_t cWORD;
typedef u_int8_t  cBYTE;

#if defined (__alpha__) || defined (__ia64__) || defined (__amd64__) || defined (__sparc64__)

#define C_LOW_PTR_DWORD( lp ) \
   ((cDWORD) (((cQWORD) (lp)) & 0xFFFFFFFF))

#define C_HIGH_PTR_DWORD( lp ) \
   ((cDWORD) (((cQWORD) (lp)) >> 32))

#else /* __alpha__ || __ia64__ || __amd64__ || __sparc64__ */

#define C_LOW_PTR_DWORD( lp )   ((cDWORD) (lp))

#define C_HIGH_PTR_DWORD( lp )  0

#endif /* __alpha__ || __ia64__ || __amd64__ || __sparc64__ */

#endif /* WIN32 */

#define C_GET_BYTE(p)   ((cBYTE) (p))
#define C_GET_WORD(p)   ((cWORD) (p))
#define C_GET_DWORD(p)  ((cDWORD) (p))
#define C_GET_QWORD(p)  ((cQWORD) (p))

#define C_PUT_BYTE(p, v)        (p) = (cBYTE) (v)
#define C_PUT_WORD(p, v)        (p) = (cWORD) (v)
#define C_PUT_DWORD(p, v)       (p) = (cDWORD) (v)
#define C_PUT_QWORD(p, v)       (p) = (cQWORD) (v)

#define C_MAKE_QWORD( lw, hw ) \
   ((cQWORD) (lw) | ((cQWORD) (hw) << 32))



#endif /* WANT_MACHINE_INDEPENDANT_CAPI_DEFS */



#include <capi_pack_on.h>



/** Helper definition to handle CAPI structs. */
typedef struct CAPIStruct
{
   cBYTE bLength;
   cWORD wExtLength;
} CAPIStruct_t;



#include <capi_pack_off.h>



#endif  /* __CAPIDEF_H */
