/**
 * @file capi_bsd.h
 *
 * CapiBsd - Specific definitions for CAPI under the *BSD operating systems.
 *
 * Copyright: 2002-2005 Thomas Wintergerst. All rights reserved.
 *
 * $Id: capi_bsd.h,v 1.1.2.1 2006/02/28 21:35:18 thomas Exp $
 * $Project:    CAPI $
 * $Target:     capi-header $
 * @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 __CAPI_BSD_H
#define __CAPI_BSD_H

#include <sys/types.h>
#include <sys/time.h>
#include <capi20.h>





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





/* --- Additional CAPI result values for the BSD operating system --- */

/** @{ */
/** Class 0x10xx - additional CAPI register errors. */
#define CRE_INVALID_PARAM       0x10F0
#define CRE_UNSUPPORTED_VERSION 0x10F1
#define CRE_TOO_MANY_CONTROLLERS 0x10F2
#define CRE_INVALID_CONTROLLER  0x10F3
#define CRE_RESET_NOT_SUPPORTED 0x10F4
#define CRE_NO_RIGHTS_TO_RESET  0x10F5
/** @} */

/** @{ */
/** Class 0x11xx - additional CAPI message exchange errors. */
#define CME_INVALID_PARAM       0x11F0
/** @} */



/* --- Additional CAPI definitions for BSD specific CAPI functions --- */

#include <capi_pack_on.h>

/** The maximum length of a controller device driver name. */
#define CAPI_CTLR_DRIVER_NAME_LEN       32

/** The maximum length of a controller name. */
#define CAPI_CTLR_NAME_LEN              32

/** The maximum length of a board type name. */
#define CAPI_CTLR_TYPE_NAME_LEN         32

/** Additional information about the driver of a controller. */
typedef struct
{
   cWORD    wCtlr;              /**<
                                 * Controller number registered at the CAPI
                                 * manager.
                                 */
   char     szCtlrName [CAPI_CTLR_NAME_LEN];
                                /**<
                                 * Unique controller name, e.g. "AVMB1-2" or
                                 * "AVMC4-1/3".
                                 */
   char     szCtlrTypeName [CAPI_CTLR_TYPE_NAME_LEN];
                                /**<
                                 * Board type name for the controller, e.g.
                                 * "AVM B1".
                                 */
   char     szDriverName [CAPI_CTLR_DRIVER_NAME_LEN];
                                /**<
                                 * Name of the controller device driver, e.g.
                                 * "avmaic".
                                 */
   cWORD    wDrvUnitNum;        /**<
                                 * Device unit number specific to the driver.
                                 * Usually the first controller for a driver
                                 * gets 0, second gets 1, a.s.o.
                                 */
   cWORD    wNumPorts;          /**<
                                 * Number of ISDN ports of the corresponding
                                 * adapter board. Not all boards have only one
                                 * port. There are boards with 2 or 4 ports as
                                 * well, e.g. the AVM-C2 or AVM-C4.
                                 */
   cWORD    wPortIdx;           /**<
                                 * The ISDN port index for the current
                                 * controller. E.g. for a AVM-C4 the 4 ports
                                 * are indexed from 0 to 3 and each port is
                                 * registered as its own CAPI controller.
                                 */
} CAPICtlrDriverInfo_t;

/** Structure for a data block to be sent to a controller for download. */
typedef struct
{
   size_t         nLenDataBlock;/**<
                                 * The length of the data in byte array
                                 * *paucDataBlock.
                                 */
   unsigned char *paucDataBlock;/**<
                                 * The address of the data block.
                                 */
} CAPICtlrDataBlock_t;

#include <capi_pack_off.h>



/* --- Definitions for supporting sysctl variables in the "capi" tree --- */

/* Note: It is only possible to create sysctl variables in the kernel
 *       environment and thus for kernel modules.
 */
#ifdef _KERNEL

#include <sys/sysctl.h>

SYSCTL_DECL (_capi);

#endif /* _KERNEL */



/* --- The ioctl interface to the kernel CAPI implementation --- */

/* Note: The CAPI result values for all ioctl requests are put into errno, if
 *       not successful. A successful call returns the direct result zero. If
 *       the direct ioctl result is negative, the CAPI info value is stored in
 *       errno. The same applies to the read and write system calls.
 */

#if defined (CAPI_WANT_IOCTL) || defined (_KERNEL)

#include <sys/ioccom.h>



/** The CAPI device file name. */
#define CAPI_DEVICE_NAME        "/dev/capi20"



/**
 * CAPI registration.
 *
 * After opening CAPI_DEVICE_NAME (non-blocking mode) do this ioctl before all
 * other operations.
 */

typedef struct
{
   /* input parameters */
   unsigned uMaxLogicalConnections;
   unsigned uMaxBDataBlocks;
   unsigned uMaxBDataLen;

   /* result parameters */
   unsigned uApplID;
} capi_register_params_t;

#define C4BIOC_CAPI_REGISTER    _IOWR ('C', 1, capi_register_params_t)



/**
 * Releasing CAPI.
 *
 * Just close the file descriptor to CAPI_DEVICE_NAME.
 */



/**
 * Send a CAPI message.
 *
 * Do a write or writev system call to the file descriptor for
 * CAPI_DEVICE_NAME. The buffer to write must contain the CAPI message. If the
 * message is a Data-B3-Request, the data block must directly follow the
 * message (or it may be the second iovec in writev). Both the message and the
 * data block must be written in the same system call.
 */



/**
 * Receive a CAPI message.
 *
 * Do a read system call to the file descriptor for CAPI_DEVICE_NAME. The
 * buffer to read must be large enough to hold a CAPI message (CAPIMsg_t) and
 * directly appended a data block of the maximum length specified during
 * registration.
 */



/**
 * Ask for the manufacturer of an adapter.
 */

typedef struct
{
   /* input parameters */
   unsigned uCtlr;

   /* result parameters */
   unsigned char szBuffer [64];
} capi_get_manufacturer_params_t;

#define C4BIOC_CAPI_GET_MANUFACTURER \
                                _IOWR ('C', 6, capi_get_manufacturer_params_t)



/**
 * Get the version of the CAPI implementation.
 */

typedef struct
{
   /* input parameters */
   unsigned uCtlr;

   /* result parameters */
   unsigned uCAPIMajor;
   unsigned uCAPIMinor;
   unsigned uManufacturerMajor;
   unsigned uManufacturerMinor;
   unsigned uBSDMajor;
   unsigned uBSDMinor;
} capi_get_version_params_t;

#define C4BIOC_CAPI_GET_VERSION _IOWR ('C', 7, capi_get_version_params_t)



/**
 * Get the serial number of a controller.
 */

typedef struct
{
   /* input parameters */
   unsigned uCtlr;

   /* result parameters */
   char szBuffer [8];
} capi_get_serial_number_params_t;

#define C4BIOC_CAPI_GET_SERIAL_NUMBER \
                                _IOWR ('C', 8, capi_get_serial_number_params_t)



/**
 * Get the profile of a controller or the number of controllers.
 */

typedef struct
{
   /* input parameters */
   unsigned uCtlr;

   /* result parameters */
   CAPIProfileBuffer_t profile;
} capi_get_profile_params_t;

#define C4BIOC_CAPI_GET_PROFILE _IOWR ('C', 9, capi_get_profile_params_t)



/**
 * Get additional info about the driver of a controller.
 */

typedef struct
{
   /* input parameters */
   unsigned uCtlr;

   /* result parameters */
   CAPICtlrDriverInfo_t drvInfo;
} capi_get_ctlr_driver_info_params_t;

#define C4BIOC_CAPI_GET_CTLR_DRIVER_INFO          \
                                _IOWR ('C', 0x21, \
                                       capi_get_ctlr_driver_info_params_t)



/**
 * Reset and/or download the controller.
 *
 * This call is controller specific, its support is optional. But for active
 * ISDN adapters it is the only way to download the software and settings onto
 * the adapter. How many data blocks must be specified and what their contents
 * must look like is driver specific. You have to look at the specification for
 * the driver of the controller in question.
 *
 * @note This call is only allowed if the calling processes user id is 0 or the
 *       user is member of the group with id 0.
 */

typedef struct
{
   /* input parameters */
   unsigned             uCtlr;
   size_t               nNumDataBlocks; /* number of entries in array
                                         * paDataBlocks, if necessary
                                         */
   CAPICtlrDataBlock_t *paDataBlocks;    /* array of data blocks to be sent to
                                          * the controller; the contents are
                                          * defined by the specific driver
                                          */
} capi_reset_ctlr_params_t;

#define C4BIOC_CAPI_RESET_CTLR   _IOW ('C', 0x22, capi_reset_ctlr_params_t)



#endif /* defined (CAPI_WANT_IOCTL) || defined (_KERNEL) */





/* === prototypes of interface functions ================================= */





/* --- CAPI functions of the shared library interface --- */

/* All the documentation and the remarks of the CAPI specification apply. */

#if ! defined (_KERNEL) && ! defined (CAPI_NO_SHARED_LIBRARY)

#ifdef __cplusplus
extern "C" {
#endif

/** The basename of the CAPI shared library. */
#define CAPI_SHLIB_BASENAME     "libcapi20.so"



/**
 * CAPI application registration.
 *
 * @param uMaxLogicalConnections
 *                              I: Maximum number of active B3-connections.
 * @param uMaxBDataBlocks       I: Maximum number of unacknowledged incoming
 *                                 data blocks per connection.
 * @param uMaxBDataLen          I: Maximum data block length to use.
 * @param puApplID              O: The application id assigned by the CAPI
 *                                 manager if the call is successful.
 *
 * @retval CAPI_OK              Application registration was successful.
 * @retval Else                 An error occurred, the result is one of the
 *                              CAPI result values defined in capi_result.h.
 */
unsigned capi20_register
   (unsigned  uMaxLogicalConnections,
    unsigned  uMaxBDataBlocks,
    unsigned  uMaxBDataLen,
    unsigned *puApplID);

typedef unsigned (*Capi20RegisterFctPtr_t)
   (unsigned  uMaxLogicalConnections,
    unsigned  uMaxBDataBlocks,
    unsigned  uMaxBDataLen,
    unsigned *puApplID);

/**
 * Releasing a CAPI application.
 *
 * @param uApplID               I: Application id from registration.
 *
 * @retval CAPI_OK              Application release was successful.
 * @retval Else                 An error occurred, the result is one of the
 *                              CAPI result values defined in capi_result.h.
 */
unsigned capi20_release
   (unsigned uApplID);

typedef unsigned (*Capi20ReleaseFctPtr_t)
   (unsigned uApplID);

/**
 * Send a CAPI message.
 *
 * @param uApplID               I: Application id from registration.
 * @param pMsg                  I: The CAPI message to send.
 *
 * @retval CAPI_OK              The message was accepted by CAPI.
 * @retval Else                 An error occurred, the result is one of the
 *                              CAPI result values defined in capi_result.h.
 */
unsigned capi20_put_message
   (unsigned   uApplID,
    CAPIMsg_t *pMsg);

typedef unsigned (*Capi20PutMessageFctPtr_t)
   (unsigned   uApplID,
    CAPIMsg_t *pMsg);

/**
 * Receive a CAPI message.
 *
 * @param uApplID               I: Application id from registration.
 * @param ppMsg                 O: Address of the CAPI message if the result is
 *                                 CAPI_OK.
 *
 * @retval CAPI_OK              A message was available and its address is
 *                              successfully returned in ppMsg. Note that this
 *                              message buffer will only be valid until the
 *                              next capi20_get_message() call.
 * @retval Else                 An error occurred, the result is one of the
 *                              CAPI result values defined in capi_result.h.
 */
unsigned capi20_get_message
   (unsigned    uApplID,
    CAPIMsg_t **ppMsg);

typedef unsigned (*Capi20GetMessageFctPtr_t)
   (unsigned    uApplID,
    CAPIMsg_t **ppMsg);

/**
 * Wait for an incoming CAPI message with timeout.
 *
 * @param uApplID               I: Application id from registration.
 * @param pTimeout              I: If NULL the call only returns if
 *                                 capi20_release() is called from another
 *                                 thread for the same application id. Else the
 *                                 call will return after the time specified
 *                                 has elapsed.
 *
 * @retval CAPI_OK              There is a new message to fetch via
 *                              capi20_get_message().
 * @retval CME_GET_QUEUE_EMPTY  A timeout was specified when calling this
 *                              function and the time has passed without a CAPI
 *                              message arriving.
 * @retval Else                 An error occurred, the result is one of the
 *                              CAPI result values defined in capi_result.h.
 */
unsigned capi20_wait_for_message
   (unsigned        uApplID,
    struct timeval *pTimeout);

typedef unsigned (*Capi20WaitForSignalFctPtr_t)
   (unsigned        uApplID,
    struct timeval *pTimeout);

/**
 * Ask for the manufacturer of a controller.
 *
 * @param uCtlr                 I: Controller number in question. If 0 is
 *                                 specified the manufacturer string of the
 *                                 CAPI manufacturer itself is returned in
 *                                 pszBuffer.
 * @param pszBuffer             O: Null terminated string for the manufacturer
 *                                 name. The buffer must be at least 64 bytes
 *                                 large.
 *
 * @retval CAPI_OK              The manufacturer string was successfully filled
 *                              into pszBuffer.
 * @retval Else                 An error occurred, the result is one of the
 *                              CAPI result values defined in capi_result.h.
 */
unsigned capi20_get_manufacturer
   (unsigned       uCtlr,
    unsigned char *pszBuffer);

typedef unsigned (*Capi20GetManufacturerFctPtr_t)
   (unsigned       uCtlr,
    unsigned char *pszBuffer);

/**
 * Get the version of the CAPI implementation.
 *
 * @note All output arguments may be NULL if the corresponding version data is
 *       not needed by the caller.
 *
 * @param uCtlr                 I: Controller number in question. If 0 is
 *                                 specified the version numbers for the CAPI
 *                                 manager itself are returned. As there is no
 *                                 distinction between firmware and driver
 *                                 software, the manufacturer and the BSD
 *                                 version numbers will be the same.
 * @param puCAPIMajor           O: Major CAPI version (2).
 * @param puCAPIMinor           O: Minor CAPI version (0).
 * @param puManufacturerMajor   O: Major version of the controller firmware. If
 *                                 the board is a passive one and thus runs no
 *                                 firmware, this value will be the same as the
 *                                 BSD version.
 * @param puManufacturerMinor   O: Minor version of the controller firmware. If
 *                                 the board is a passive one and thus runs no
 *                                 firmware, this value will be the same as the
 *                                 BSD version.
 * @param puBSDMajor            O: Major version of the controller device
 *                                 driver.
 * @param puBSDMinor            O: Minor version of the controller device
 *                                 driver.
 *
 * @retval CAPI_OK              The version information was successfully filled
 *                              into the argument addresses that are not NULL.
 * @retval Else                 An error occurred, the result is one of the
 *                              CAPI result values defined in capi_result.h.
 */
unsigned capi20_get_version
   (unsigned  uCtlr,
    unsigned *puCAPIMajor,
    unsigned *puCAPIMinor,
    unsigned *puManufacturerMajor,
    unsigned *puManufacturerMinor,
    unsigned *puBSDMajor,
    unsigned *puBSDMinor);

typedef unsigned (*Capi20GetVersionFctPtr_t)
   (unsigned  uCtlr,
    unsigned *puCAPIMajor,
    unsigned *puCAPIMinor,
    unsigned *puManufacturerMajor,
    unsigned *puManufacturerMinor,
    unsigned *puBSDMajor,
    unsigned *puBSDMinor);

/**
 * Get the serial number of a controller.
 *
 * @param uCtlr                 I: Controller number in question. If 0 is
 *                                 specified, the serial number of the CAPI
 *                                 manager itself is requested. As it does not
 *                                 support serial numbers, the result is an
 *                                 empty string.
 * @param pszBuffer             O: Null terminated string for the serial number
 *                                 of the controller. If the controller does
 *                                 not support serial numbers, this will result
 *                                 in an empty string. The buffer for the
 *                                 string must be at least 8 bytes large.
 *
 * @retval CAPI_OK              The serial number was successfully copied into
 *                              the buffer (even if it is empty).
 * @retval Else                 An error occurred, the result is one of the
 *                              CAPI result values defined in capi_result.h.
 */
unsigned capi20_get_serial_number
   (unsigned       uCtlr,
    unsigned char *pszBuffer);

typedef unsigned (*Capi20GetSerialNumberFctPtr_t)
   (unsigned       uCtlr,
    unsigned char *pszBuffer);

/**
 * Get the profile of a controller or the number of controllers.
 *
 * @param uCtlr                 I: Controller number in question. If 0 is
 *                                 specified, only the total number of
 *                                 installed controllers is returned in the
 *                                 profile buffer.
 * @param pProfile              O: This buffer receives the profile data if the
 *                                 result is CAPI_OK.
 *
 * @retval CAPI_OK              The profile buffer was successfully filled
 *                              (even if only with the number of installed
 *                              controllers).
 * @retval Else                 An error occurred, the result is one of the
 *                              CAPI result values defined in capi_result.h.
 */
unsigned capi20_get_profile
   (unsigned             uCtlr,
    CAPIProfileBuffer_t *pProfile);

typedef unsigned (*Capi20GetProfileFctPtr_t)
   (unsigned             uCtlr,
    CAPIProfileBuffer_t *pProfile);

/**
 * Get additional info about the driver of a controller.
 *
 * @param uCtlr                 I: Controller number in question. Note that
 *                                 here controller number 0 is not allowed.
 * @param pDrvInfo              O: This buffer receives the driver data if the
 *                                 result is CAPI_OK.
 *
 * @retval CAPI_OK              The driver data buffer was successfully filled.
 * @retval Else                 An error occurred, the result is one of the
 *                              CAPI result values defined in capi_result.h.
 */
unsigned capi20_get_ctlr_driver_info
   (unsigned              uCtlr,
    CAPICtlrDriverInfo_t *pDrvInfo);

typedef unsigned (*Capi20GetCtlrDriverInfoFctPtr_t)
   (unsigned              uCtlr,
    CAPICtlrDriverInfo_t *pDrvInfo);

/**
 * Reset and/or download the controller.
 *
 * This call is controller specific, its support is optional. But for active
 * ISDN adapters it is the only way to download the software and settings onto
 * the adapter. How many data blocks must be specified and what their contents
 * must look like is driver specific. You have to look at the specification for
 * the driver of the controller in question.
 *
 * If the number of data blocks to send down to the controller is specified as
 * null, the desired operation is only to reset the controller to disabled
 * state. No download is performed. After such a call the board is not usable
 * any more until another call to this function will download the firmware
 * again. This behaviour may be used to physically disable active boards so
 * they will in no way handle any ISDN connections any more.
 *
 * @note This call is only allowed if the calling processes user id is 0 or the
 *       user is member of the group with id 0.
 *
 * @param uCtlr                 I: Controller number to reset.
 * @param nNumDataBlocks        I: The number of data blocks to be sent to the
 *                                 controller. It is the length of the array at
 *                                 paDataBlocks.
 * @param paDataBlocks          I: The array of data blocks to be sent to the
 *                                 controller.
 *
 * @retval CAPI_OK              The reset operation was successful.
 * @retval Else                 An error occurred, the result is one of the
 *                              CAPI result values defined in capi_result.h.
 */
unsigned capi20_reset_ctlr
   (unsigned             uCtlr,
    size_t               nNumDataBlocks,
    CAPICtlrDataBlock_t *paDataBlocks);

typedef unsigned (*Capi20ResetCtlrFctPtr_t)
   (unsigned             uCtlr,
    size_t               nNumDataBlocks,
    CAPICtlrDataBlock_t *paDataBlocks);

/**
 * Test for installed CAPI and at least one controller.
 *
 * @param None.
 *
 * @retval CAPI_OK              There is at least one ISDN controller
 *                              installed.
 * @retval CRE_CAPI_NOT_INSTALLED
 *                              The CAPI subsystem (C4B) is basically loaded,
 *                              but no ISDN controller is registered, i.e. not
 *                              controller driver is loaded.
 * @retval Else                 An error occurred, the result is one of the
 *                              CAPI result values defined in capi_result.h.
 */
unsigned capi20_is_installed (void);

typedef unsigned (*Capi20IsInstalledFctPtr_t) (void);

/**
 * Get the file descriptor for an application id.
 *
 * @note It is recommended to use capi20_wait_for_message() instead of poll.
 *
 * @param uApplID               The application id from registration.
 *
 * @retval -1                   uApplID is not a valid application id for the
 *                              calling process.
 * @retval Else                 The open file descriptor to /dev/capi20 for the
 *                              application id specified is returned.
 */
int capi20_fileno
   (unsigned uApplID);

typedef int (*Capi20FilenoFctPtr_t)
   (unsigned uApplID);

#ifdef __cplusplus
}
#endif

#endif /* ! defined (_KERNEL) && ! defined (CAPI_NO_SHARED_LIBRARY) */



/* --- The interface to the kernel CAPI manager --- */

#if defined (_KERNEL)

#include <sys/mbuf.h>

/**
 * CAPI application registration.
 *
 * @param uMaxLogicalConnections
 *                              I: Maximum number of active B3-connections.
 * @param uMaxBDataBlocks       I: Maximum number of unacknowledged incoming
 *                                 data blocks per connection.
 * @param uMaxBDataLen          I: Maximum data block length to use.
 * @param puApplID              O: The application id assigned by the CAPI
 *                                 manager if the call is successful.
 *
 * @retval CAPI_OK              Application registration was successful.
 * @retval Else                 An error occurred, the result is one of the CAPI
 *                              result values defined in capi_result.h.
 */
unsigned kcapi_register
   (unsigned  uMaxLogicalConnections,
    unsigned  uMaxBDataBlocks,
    unsigned  uMaxBDataLen,
    unsigned *puApplID);

/**
 * Releasing a CAPI application.
 *
 * @param uApplID               I: Application id from registration.
 *
 * @retval CAPI_OK              Application release was successful.
 * @retval Else                 An error occurred, the result is one of the CAPI
 *                              result values defined in capi_result.h
 */
unsigned kcapi_release
   (unsigned uApplID);

/**
 * Send a CAPI message.
 *
 * @param uApplID               I: Application id from registration.
 * @param pmbMsg                I: The mbuf for the CAPI message to send. For
 *                                 Data-B3-Requests the data block must be
 *                                 stored in a second mbuf. The address of this
 *                                 mbuf must be stored in pmbMsg->m_next. If the
 *                                 function call returns CAPI_OK, the ownership
 *                                 of the mbuf goes to the CAPI manager. The
 *                                 calling application must not access any data
 *                                 in the mbuf(s) thereafter. The CAPI manager
 *                                 will release the mbuf(s) when it is (they
 *                                 are) not needed any more.
 *
 * @retval CAPI_OK              The message was accepted by CAPI.
 * @retval CME_PUT_QUELE_FULL   The send queue of the addressed controller is
 *                              filled up, try again later.
 * @retval Else                 An error occurred, the result is one of the CAPI
 *                              result values defined in capi_result.h
 */
unsigned kcapi_put_message
   (unsigned     uApplID,
    struct mbuf *pmbMsg);

/**
 * Receive a CAPI message.
 *
 * @param uApplID               I: Application id from registration.
 * @param ppmbMsg               O: The address of an mbuf containing a CAPI
 *                                 message if the function result is CAPI_OK.
 *                                 If the message is a Data-B3-Indication the
 *                                 data block is stored in a second mbuf whose
 *                                 address is stored into (*ppmbMsg)->m_next.
 *                                 The calling application is responsible for
 *                                 releasing the mbuf(s) when they are no longer
 *                                 needed. After calling this function
 *                                 successfully the CAPI manager will not access
 *                                 any data in the mbuf(s) returned.
 *
 * @retval CAPI_OK              A CAPI message was available, the address of its
 *                              surrounding mbuf is returned in ppmbMsg.
 * @retval CME_GET_QUEUE_OVERFLOW
 *                              A CAPI message or data block was lost, maybe
 *                              because of low system resources.
 * @retval Else                 An error occurred, the result is one of the CAPI
 *                              result values defined in capi_result.h
 */
unsigned kcapi_get_message
   (unsigned      uApplID,
    struct mbuf **ppmbMsg);

/**
 * Register callback function for incoming messages.
 *
 * The callback function if provided is called each time a new CAPI message is
 * delivered to the application. The callback function should not perform long
 * operations, because this would possibly block other CAPI applications. It is
 * allowed to call kcapi_get_message() or kcapi_put_message() within the
 * callcack function. But calling kcapi_register() or kcapi_release() is
 * definitly not allowed.
 *
 * @param uApplID               I: Application id from registration.
 * @param pfnCallback           I: The function to be called if new CAPI
 *                                 messages arrive for the application. If this
 *                                 argument is NULL, a formerly registered
 *                                 callback function is unregistered.
 * @param dwParam/qwParam       I: The additional parameter to be passed as the
 *                                 second parameter of the callback function.
 *
 * @retval CAPI_OK              The callback function was successfully
 *                              registered.
 * @retval Else                 An error occurred, the result is one of the CAPI
 *                              result values defined in capi_result.h
 */
#if defined(__alpha__) || defined (__ia64__) || defined (__amd64__) || defined (__sparc64__)
unsigned kcapi_set_signal
   (unsigned  uApplID,
    void (*pfnCallback) (unsigned uApplID, u_int64_t qwParam),
    u_int64_t qwParam);
#else /* __alpha__ || __ia64__ || __amd64__ || __sparc64__ */
unsigned kcapi_set_signal
   (unsigned  uApplID,
    void (*pfnCallback) (unsigned uApplID, u_int32_t dwParam),
    u_int32_t dwParam);
#endif /* __alpha__ || __ia64__ || __amd64__ || __sparc64__ */

/**
 * Ask for the manufacturer of a controller.
 *
 * @param uCtlr                 I: Controller number in question. If 0 is
 *                                 specified the manufacturer string of the CAPI
 *                                 manufacturer itself is returned in pszBuffer.
 * @param pszBuffer             O: Null terminated string for the manufacturer
 *                                 name. The buffer must be at least 64 bytes
 *                                 large.
 *
 * @retval CAPI_OK              The manufacturer string was successfully filled
 *                              into pszBuffer.
 * @retval Else                 An error occurred, the result is one of the CAPI
 *                              result values defined in capi_result.h
 */
unsigned kcapi_get_manufacturer
   (unsigned       uCtlr,
    unsigned char *pszBuffer);

/**
 * Get the version of the CAPI implementation.
 *
 * @note All output arguments may be NULL if the corresponding version data is
 *       not needed by the caller.
 *
 * @param uCtlr                 I: Controller number in question. If 0 is
 *                                 specified the version numbers for the CAPI
 *                                 manager itself are returned. As there is no
 *                                 distinction between firmware and driver
 *                                 software, the manufacturer and the BSD
 *                                 version numbers will be the same.
 * @param puCAPIMajor           O: Major CAPI version (2).
 * @param puCAPIMinor           O: Minor CAPI version (0).
 * @param puManufacturerMajor   O: Major version of the controller firmware. If
 *                                 the board is a passive one and thus runs no
 *                                 firmware, this value will be the same as the
 *                                 BSD version.
 * @param puManufacturerMinor   O: Minor version of the controller firmware. If
 *                                 the board is a passive one and thus runs no
 *                                 firmware, this value will be the same as the
 *                                 BSD version.
 * @param puBSDMajor            O: Major version of the controller device driver.
 * @param puBSDMinor            O: Minor version of the controller device driver.
 *
 * @retval CAPI_OK              The version information was successfully filled
 *                              into the argument addresses that are not NULL.
 * @retval Else                 An error occurred, the result is one of the CAPI
 *                              result values defined in capi_result.h
 */
unsigned kcapi_get_version
   (unsigned  uCtlr,
    unsigned *puCAPIMajor,
    unsigned *puCAPIMinor,
    unsigned *puManufacturerMajor,
    unsigned *puManufacturerMinor,
    unsigned *puBSDMajor,
    unsigned *puBSDMinor);

/**
 * Get the serial number of a controller.
 *
 * @param uCtlr                 I: Controller number in question. If 0 is
 *                                 specified, the serial number of the CAPI
 *                                 manager itself is requested. As it does not
 *                                 support serial numbers, the result is an
 *                                 empty string.
 * @param pszBuffer             O: Null terminated string for the serial number
 *                                 of the controller. If the controller does not
 *                                 support serial numbers, this will result in
 *                                 an empty string. The buffer for the string
 *                                 must be at least 8 bytes large.
 *
 * @retval CAPI_OK              The serial number was successfully copied into
 *                              the buffer (even if it is empty).
 * @retval Else                 An error occurred, the result is one of the CAPI
 *                              result values defined in capi_result.h
 */
unsigned kcapi_get_serial_number
   (unsigned       uCtlr,
    unsigned char *pszBuffer);

/**
 * Get the profile of a controller or the number of controllers.
 *
 * @param uCtlr                 I: Controller number in question. If 0 is
 *                                 specified, only the total number of installed
 *                                 controllers is returned in the profile
 *                                 buffer.
 * @param pProfile              O: This buffer receives the profile data if the
 *                                 result is CAPI_OK.
 *
 * @retval CAPI_OK              The profile buffer was successfully filled (even
 *                              if only with the number of installed
 *                              controllers).
 * @retval Else                 An error occurred, the result is one of the CAPI
 *                              result values defined in capi_result.h
 */
unsigned kcapi_get_profile
   (unsigned             uCtlr,
    CAPIProfileBuffer_t *pProfile);

/**
 * Get additional info about the driver of a controller.
 *
 * @param uCtlr                 I: Controller number in question. Note that here
 *                                 controller number 0 is not allowed.
 * @param pDrvInfo              O: This buffer receives the driver data if the
 *                                 result is CAPI_OK.
 *
 * @retval CAPI_OK              The driver data buffer was successfully filled.
 * @retval Else                 An error occurred, the result is one of the CAPI
 *                              result values defined in capi_result.h
 */
unsigned kcapi_get_ctlr_driver_info
   (unsigned              uCtlr,
    CAPICtlrDriverInfo_t *pDrvInfo);

/**
 * Reset and/or download the controller.
 *
 * This call is controller specific, its support is optional. But for active
 * ISDN adapters it is the only way to download the software and settings onto
 * the adapter. How many data blocks must be specified and what their contents
 * must look like is driver specific. You have to look at the specification for
 * the driver of the controller in question.
 *
 * If the number of data blocks to send down to the controller is specified as
 * null, the desired operation is only to reset the controller to disabled
 * state. No download is performed. After such a call the board is not usable
 * any more until another call to this function will download the firmware
 * again. This behaviour may be used to physically disable active boards so they
 * will in no way handle any ISDN connections any more.
 *
 * @note This call is only allowed if the calling processes user id is 0 or the
 *       user is member of the group with id 0.
 *
 * @param uCtlr                 I: Controller number to reset.
 * @param nNumDataBlocks        I: The number of data blocks to be sent to the
 *                                 controller. It is the length of the array at
 *                                 paDataBlocks.
 * @param paDataBlocks          I: The array of data blocks to be sent to the
 *                                 controller.
 *
 * @retval CAPI_OK              The reset operation was successful.
 * @retval Else                 An error occurred, the result is one of the CAPI
 *                              result values defined in capi_result.h
 */
unsigned kcapi_reset_ctlr
   (unsigned             uCtlr,
    size_t               nNumDataBlocks,
    CAPICtlrDataBlock_t *paDataBlocks);



/* --- helper functions for mbuf handling --- */

/**
 * Allocate a new general mbuf of the specified length.
 */
extern struct mbuf *kcapi_get_mbuf
   (size_t nLen);

/**
 * Release an mbuf.
 */
static __inline void kcapi_free_mbuf
   (struct mbuf *pmbMsg);



#endif /* defined (_KERNEL) */





/* === definition of inline functions ==================================== */





#if defined (_KERNEL)

/**
 * Release an mbuf.
 */

static __inline void kcapi_free_mbuf
   (struct mbuf *pmbMsg)
{
   if (pmbMsg)
   {
      m_freem (pmbMsg);
   }

} /* kcapi_free_mbuf */

#endif /* defined (_KERNEL) */





#endif /* __CAPI_BSD_H */
