/**
 * @file capi_drv.h
 *
 * Capi-Driver - kernel CAPI manager for *BSD: The CAPI manager interface for
 * CAPI hardware driver.
 *
 * Copyright: 2000-2003 Thomas Wintergerst. All rights reserved.
 *
 * $FreeBSD$
 * $Id: capi_drv.h,v 1.1.2.1 2006/02/28 21:35:24 thomas Exp $
 * Project  CAPI for BSD
 * Target   kcapimgr - The CAPI manager for *BSD
 * @date    01.01.2000
 * @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.
 *
 * All functions that a controller registers at the CAPI manager will be called
 * with internal mutexes held by the CAPI manager. This ensures that at most one
 * function call is active for a specific controller at any time. But note that
 * functions for different controllers may be called in parallel, even if they
 * are driven by the same device driver.
 *
 * </p>
 *
 * This header file defines the interface between the CAPI manager and the
 * controller driver modules. The drivers must provide some functions to be
 * called by the CAPI manager and the CAPI manager in turn provides procedures
 * to be called by the drivers.
 *
 * Each driver must register every controller it is responsible for. The
 * registration mainly consists of introducing a structure describing the
 * controller to the CAPI manager. This structure also contains pointers to
 * functions to be called by the CAPI manager when there are operations to
 * execute on the controller.
 *
 * CAPI does by specification not support multi-threading within an application.
 * But several applications may perform CAPI calls concurrently. So the CAPI
 * manager and the controller drivers must support multi-threading. This is even
 * true because of interrupt calls within the driver. Not only CAPI application
 * calls will be executed in driver code, but also interrupt calls for
 * controller events. As a conclusion the controller driver must protect its
 * internal structures for concurrent calls to the same controller.
 *
 * The CAPI manager functions kcapi_ctlr_receive_*_message() are certainly aware
 * of multi-threading. These functions simply store the specified mbuf into an
 * internal queue and wake up the CAPI manager thread to handle these messages.
 * The queue is protected by a mutex. So calls to these two functions are safe
 * in all cases.
 *
 * The other functions for controller register, release, enable and disable are
 * also protected against concurrent calls. But these functions may block other
 * calls in any direction. So the driver must be careful when calling these
 * functions.
 */

#ifndef __CAPI_DRV_H
#define __CAPI_DRV_H

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





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





/* --- Version numbers for dependencies to the CAPI manager module --- */

/** The major version number of the CAPI manager. */
#define CAPIMAN_VERSION_MAJOR   1

/** The minor version number of the CAPI manager. */
#define CAPIMAN_VERSION_MINOR   0



/* --- the privilege level for CAPI for BSD --- */

/**
 * Only for pre-REL-5.0: This macro should be used to switch to a higher
 * privilege level within C4B, in order to surround code lines that must not be
 * disturbed by interrupt routine calls.
 */
#define SPLC4B  splimp



/* --- types of CAPI driver functions to be called by the CAPI manager --- */

/**
 * Register an application at a controller.
 *
 * @param uDrvCtlrNum           I: Driver specific controller number.
 * @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              I/O: When calling this function the CAPI manager
 *                                 provides its assigned applicatoin id. On
 *                                 successful return the controller driver must
 *                                 fill in his assigned internal appl. id if it
 *                                 needs application id mapping. If no
 *                                 application id mapping is needed by the
 *                                 controller, this value must be left
 *                                 unchanged.
 *
 * @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.
 */
typedef unsigned (CAPIDrv_RegisterFct_t)
   (unsigned  uDrvCtlrNum,
    unsigned  uMaxLogicalConnections,
    unsigned  uMaxBDataBlocks,
    unsigned  uMaxBDataLen,
    unsigned *puApplID);

/**
 * Releasing an application at a controller.
 *
 * @param uDrvCtlrNum           I: Driver specific controller number.
 * @param uCtlrApplID           I: Controller specific application id from
 *                                 registration. If no application id mapping is
 *                                 needed, this is the public CAPI manager
 *                                 assigned id.
 *
 * @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.
 */
typedef unsigned (CAPIDrv_ReleaseFct_t)
   (unsigned uDrvCtlrNum,
    unsigned uCtlrApplID);

/**
 * Send a CAPI message to a controller.
 *
 * @param uDrvCtlrNum           I: Driver specific controller number.
 * @param uCtlrApplID           I: Controller specific application id from
 *                                 registration.
 * @param pmbMsg                I: The CAPI message to send. A Data-B3-Request
 *                                 contains the address of a second mbuf in the
 *                                 pmbMsg->m_next member. If the function call
 *                                 returns with CAPI_OK, the driver has taken
 *                                 over ownership of the mbuf(s). It is
 *                                 responsible to release it (them) when it
 *                                 (they) are not needed any more.
 *
 * @retval CAPI_OK              The driver accepted the message.
 * @retval Else                 An error occurred, the result is one of the CAPI
 *                              result values defined in capi_result.h.
 */
typedef unsigned (CAPIDrv_PutMessageFct_t)
   (unsigned     uDrvCtlrNum,
    unsigned     uCtlrApplID,
    struct mbuf *pmbMsg);

/**
 * 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. Even passive controllers may obtain the configuration for the
 * line the controller is attached to.
 *
 * 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. In general every driver that needs some download
 * will come with its own downloading program that indirectly calls this
 * function.
 *
 * @note This call is only allowed if the calling processes effective user id
 *       has superuser privileges.
 *
 * @param uUniqueCtlrNum        I: Unique controller number assigned by the CAPI
 *                                 manager on controller registration, to reset
 *                                 or download.
 * @param nNumDataBlocks        I: Number of data blocks to be sent to the
 *                                 controller. It is the length of the array at
 *                                 paDataBlocks.
 * @param paDataBlocks          I: Array of data blocks to be sent to the
 *                                 controller.
 *
 * @retval CAPI_OK              The download operation was successful.
 * @retval Else                 An error occurred, the result is one of the CAPI
 *                              result values defined in capi_result.h.
 */
typedef unsigned (CAPIDrv_ResetCtlrFct_t)
   (unsigned             uUniqueCtlrNum,
    size_t               nNumDataBlocks,
    CAPICtlrDataBlock_t *paDataBlocks);

/**
 * Send a notification message to a controller.
 *
 * Notification messages originate only in the addressed driver itself. They are
 * used to shorten CPU time needed for interrupt handlers. Lets assume a
 * controller signals incoming data by raising an interrupt. The interrupt
 * handler fetches the data from the controller i/o interface. All further
 * processing does not need to take place in interrupt context. So the driver
 * may create a message to itself with the just fetched data attached (hopefully
 * as an mbuf with its address stored in the member pmbMsg->m_next).
 * Further protocol layer processing like e.g. DTMF recognition for voice
 * connections will be handled out of interrupt context.
 *
 * A driver may create notification messages by calling
 * kcapi_ctlr_receive_notify_message().
 *
 * @param uDrvCtlrNum           I: Driver specific controller number.
 * @param pmbMsg                I: The notification message to send. The content
 *                                 of this message is defined exclusively by the
 *                                 driver. If the function call returns with
 *                                 CAPI_OK, the driver has taken over ownership
 *                                 of the mbuf(s). It is responsible to release
 *                                 it (them) when it (they) are not needed any
 *                                 more.
 *
 * @retval CAPI_OK              The driver accepted the message.
 * @retval Else                 An error occurred, the result is one of the CAPI
 *                              result values defined in capi_result.h
 */
typedef unsigned (CAPIDrv_PutNotifyMsgFct_t)
   (unsigned     uDrvCtlrNum,
    struct mbuf *pmbMsg);



/* --- information a driver must provide for a controller to register --- */

/**
 * The interface version implemented by the driver. This will be incremented if
 * new features added are reflected in the interface and specificly in the
 * following registration structure. The CAPI manager may support multiple
 * versions if this is useful for migration purposes.
 */
#define CAPI_DRIVER_IF_VERSION  3

/* some controller flags for registration */
#define CAPI_CTLRFLAG_NEED_APPL_ID_MAPPING      0x00000001UL
                                /**<
                                 * If this flag is not set, the controller (and
                                 * thus the driver) will simply accept the
                                 * application id assignment by the CAPI
                                 * manager. But if the controller (or its
                                 * driver) must maintain its own application
                                 * ids, this flag may be set to declare the need
                                 * for application id mapping in CAPI messages.
                                 */
#define CAPI_CTLRFLAG_REGISTER_AT_FIRST_PORT    0x00000002UL
                                /**<
                                 * Only for multi-port boards: The call
                                 * kcapi_register() may be handled in two ways.
                                 * Either it is executed for every port (i.e.
                                 * CAPI controller) as it is needed or the
                                 * application registration must only be
                                 * performed once and only at the first port of
                                 * a multi-port board. By default each port of a
                                 * multi-port board is treated like a
                                 * single-port board. If this flag is set, all
                                 * registrations are sent only to the first
                                 * CAPI controller of a multi-port board. In
                                 * this case the board is assumed to maintain
                                 * application registrations common to all its
                                 * ports. Namely the AVM-C4 uses this
                                 * application registration scheme.
				 */
#define CAPI_CTLRFLAG_RESET_FIRST_PORT          0x00000004UL
                                /**<
                                 * Only for multi-port boards: If this flag is
                                 * set, a kcapi_reset_ctlr() call is only
                                 * allowed to the first CAPI controller of a
                                 * multi-port board. All such calls to the other
                                 * ports are rejected. This will also make the
                                 * CAPI manager assume that all ports of a
                                 * multi-port board will be reset for a
                                 * kcapi_reset_ctlr() call and so will disable
                                 * all ports of the addressed board. But a
                                 * driver must still enable all ports
                                 * explicitly, it is not done automatically.
                                 * If this flag is not set, every port of a
                                 * multi-port board is treated independent of
                                 * each other (with respect to the reset and
                                 * disable operation).
                                 */

/**
 * The controller registration data structure.
 */
typedef struct
{
   unsigned             uIfVersion;     /**<
                                         * Interface version implemented by the
                                         * driver. It must be set to the current
                                         * value of CAPI_DRIVER_IF_VERSION.
                                         */
   const char          *pszCtlrName;    /**<
                                         * Unique controller name, e.g.
                                         * "AVMB1-2" of "AVMC4-1/3". To
                                         * distinguish one controller from the
                                         * others the driver shall provide a
                                         * unique board type name with a numeric
                                         * value incremented for each controller
                                         * it drives.
                                         */
   const char          *pszCtlrTypeName;/**<
                                         * Type name for the board, e.g.
                                         * "AVM B1"
                                         */
   const char          *pszDriverName;  /**<
                                         * Name of the controller driver device,
                                         * e.g. "avmaic".
                                         */
   unsigned             uDrvUnitNumber; /**<
                                         * Unit number specific to the device
                                         * driver. The first controller for a
                                         * driver usually gets 0, second gets 1,
                                         * a.s.o.
                                         */
   unsigned             uNumPorts;      /**<
                                         * Number of ISDN ports of the
                                         * corresponding adapter board. There
                                         * are boards with 2 or 4 ISDN ports,
                                         * e.g. the AVM-C2 or AVM-C4.
                                         */
   unsigned             uPortIdx;       /**<
                                         * 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.
                                         * @important The first port must be
                                         *    registered first, then the second
                                         *    a.s.o. The CAPI controller no.
                                         *    must be computable by the formular
                                         *    "<base CAPI ctlr. no.> + uPortIdx".
                                         */
   unsigned long        ulFlags;        /**<
                                         * Some flags to declare controller
                                         * behaviour, or-ed values of
                                         * CAPI_CTLRFLAG_*.
                                         */
   char                *pszManufacturer;/**<
                                         * The manufacturer of the board. This
                                         * string will be returned on calls to
                                         * kcapi_get_manufacturer().
                                         */
   unsigned             uDriverMajor;   /**<
                                         * Major version number for the driver.
                                         * This value will be returned as the
                                         * "uBSDMajor" for calls to
                                         * kcapi_get_version() for a specific
                                         * controller (i.e. uCtlr != 0).
                                         */
   unsigned             uDriverMinor;   /**<
                                         * Minor version number for the driver.
                                         * This value will be returned as the
                                         * "uBSDMinor" for calls to
                                         * kcapi_get_version() for a specific
                                         * controller (i.e. uCtlr != 0).
                                         */
   /**
    * For active controllers the following fields may only be known after
    * downloading and so after calling kcapi_ctlr_enable(). When calling
    * kcapi_ctlr_register() they must be set to zero in this case.
    */
   unsigned             uManufacturerMajor;
                                        /**<
                                         * Major version number of the
                                         * controller firmware. This value will
                                         * be returned as the
                                         * "uManufacturerMajor" in calls to
                                         * kcapi_get_version() for a specific
                                         * controller (i.e. uCtlr != 0).
                                         */
   unsigned             uManufacturerMinor;
                                        /**<
                                         * Minor version number of the
                                         * controller firmware. This value will
                                         * be returned as the
                                         * "uManufacturerMinor" in calls to
                                         * kcapi_get_version() for a specific
                                         * controller (i.e. uCtlr != 0).
                                         */
   unsigned char        szSerialNumber [8];
                                        /**<
                                         * Serial number of the board. If serial
                                         * numbers are not supported by this
                                         * driver or board, it must be set to
                                         * the empty string.
                                         */
   CAPIProfileBuffer_t  profile;        /**<
                                         * Buffer for the CAPI profile.
                                         */
   
   /**
    * The CAPI controller functions provided by the driver. The first three
    * functions are mandatory and must be set to existing function addresses.
    * The last two are optional. If the driver does not support their
    * functionality they must be set to NULL.
    */
   CAPIDrv_RegisterFct_t     *pfnRegister;
   CAPIDrv_ReleaseFct_t      *pfnRelease;
   CAPIDrv_PutMessageFct_t   *pfnPutMessage;
   CAPIDrv_ResetCtlrFct_t    *pfnResetCtlr;
   CAPIDrv_PutNotifyMsgFct_t *pfnPutNotifyMsg;
   
} CAPICtlrRegisterParams_t;





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





/* --- CAPI manager functions to be called by drivers --- */

/**
 * Register a new controller at the CAPI manager.
 *
 * @param pCtlrRegParms         I: Registration data for the controller. The
 *                                 memory must be valid until
 *                                 kcapi_ctlr_release() was called. The content
 *                                 may only change until kcapi_ctlr_enable() is
 *                                 called (or between calls to
 *                                 kcapi_ctlr_disable() and kcapi_ctlr_enable()
 *                                 in this order).
 * @param puUniqueCtlrNum       O: The unique controller number (1 based)
 *                                 assigned by the CAPI manager. If controller
 *                                 number mapping is needed, this fact must be
 *                                 declared through the parameters of the
 *                                 function call to kcapi_ctlr_enable().
 *
 * @retval CAPI_OK              Controller registration was successful, a unique
 *                              controller id was assigned.
 * @retval Else                 An error occurred, the result is one of the CAPI
 *                              result values defined in capi_result.h
 */
unsigned kcapi_ctlr_register
   (CAPICtlrRegisterParams_t *pCtlrRegParams,
    unsigned                 *puUniqueCtlrNum);

/**
 * Declare a registered controller as ready for operation.
 *
 * @param uUniqueCtlrNum        I: Unique controller number from registration.
 * @param uDrvCtlrNum           I: If the controller does not need controller
 *                                 number mapping, this must be the same as the
 *                                 unique controller number. Else this value
 *                                 must be set to the driver specific controller
 *                                 number. The CAPI manager will map between the
 *                                 two controller numbers in every CAPI message
 *                                 exchanged between the controller and the CAPI
 *                                 manager in this case.
 *
 * @retval CAPI_OK              Enabling the controller was successful.
 * @retval Else                 An error occurred, the result is one of the CAPI
 *                              result values defined in capi_result.h
 */
unsigned kcapi_ctlr_enable
   (unsigned uUniqueCtlrNum,
    unsigned uDrvCtlrNum);

/**
 * Declare a registered controller as disabled for operation.
 *
 * @param uUniqueCtlrNum        I: Unique controller number from registration.
 *
 * @retval CAPI_OK              Disabling the controller was successful.
 * @retval Else                 An error occurred, the result is one of the CAPI
 *                              result values defined in capi_result.h
 */
unsigned kcapi_ctlr_disable
   (unsigned uUniqueCtlrNum);
   
/**
 * Releasing a CAPI controller.
 *
 * @param uUniqueCtlrNum        I: Unique controller number to be released.
 *                                 After this call no message exchange or
 *                                 function calls may occur between this
 *                                 controller and the CAPI manager.
 *
 * @retval CAPI_OK              Releasing the controller was successful.
 * @retval Else                 An error occurred, the result is one of the CAPI
 *                              result values defined in capi_result.h
 */
unsigned kcapi_ctlr_release
   (unsigned uUniqueCtlrNum);

/**
 * Receive a CAPI message from a controller.
 *
 * @note Lost CAPI messages may be signalled with an empty mbuf, i.e. an mbuf
 *       with the member m_len set to zero.
 *
 * @important This function must be called with C4B privilege level or even
 *            interrupt context.
 *
 * @param uUniqueCtlrNum        I: The unique controller number this message is
 *                                 from.
 * @param uCtlrApplID           I: The controller specific application id from
 *                                 application registration.
 * @param pmbMsg                I: A pointer to an mbuf for the incoming CAPI
 *                                 message. A Data-B3-Indication contains the
 *                                 address of another mbuf in the pmbMsg->m_next
 *                                 member. The CAPI manager is responsible for
 *                                 releasing the mbuf(s) when they are no longer
 *                                 needed.
 *
 * @return Nothing.
 */
void kcapi_ctlr_receive_capi_message
   (unsigned     uUniqueCtlrNum,
    unsigned     uCtlrApplID,
    struct mbuf *pmbMsg);

/**
 * Receive a message for passing it throuch protocol stacks from a controller.
 *
 * This function is used by a CAPI driver to pass a notification message to
 * itself. It is usually called in interrupt context, e.g. when a controller
 * signals the reception or transmission of data. The message is stored into the
 * CAPI manager message queue for driver messages. The message thread then
 * passes the message to the driver for handling out of interrupt context. This
 * is used to keep the code executed in interrupt context as short as possible.
 *
 * Notification messages are passed to the driver through the driver provided
 * function of the prototype (*CAPIDrv_PutNotifyMsgFct_t)(). If the driver wants
 * to use notification messages, it must set the corresponding member of the
 * controller registration structure to a valid function address. Otherwise
 * notification messages will be discarded by the CAPI manager because it does
 * not know how to deliver them to the driver.
 *
 * @attention The mbuf for this message must be allocated using
 *            kcapi_get_ctlr_notify_mbuf(). If regular data is to be transfered,
 *            it shall be stored into an additional mbuf allocated with
 *            kcapi_get_mbuf() and attached to the main notification mbuf,
 *            preferably using the member m_next. As the notification mbuf is
 *            not of type MT_DATA, it must not be passed to network layers as
 *            e.g. i4b.
 *
 * @param uUniqueCtlrNum        I: The unique controller number for the
 *                                 controller needing work.
 * @param pmbMsg                I: The address of an mbuf with the message to
 *                                 pass to a handling function of a CAPI driver.
 *                                 After passing the mbuf to this function the
 *                                 CAPI manager is responsible for releasing it
 *                                 until the CAPI manager forwarded it to the
 *                                 handling function of the driver.
 *
 * @return Nothing.
 */
void kcapi_ctlr_receive_notify_message
   (unsigned     uUniqueCtlrNum,
    struct mbuf *pmbMsg);

/**
 * Allocate a new mbuf for a controller notification message.
 *
 * @note Mbufs allocated with this function should be released by calling
 *       kcapi_free_mbuf().
 *
 * @attention Mbufs of this type must not be used for normal data! If a data
 *            block is to be transfered through a notification message, the data
 *            mbuf must be attached as a second mbuf to the notification mbuf,
 *            preferably using the member m_next that is released automatically
 *            when releasing the main mbuf.
 *
 * @param nLen                  I: The size of the new mbuf in bytes. If an mbuf
 *                                 is returned by this function, its m_len
 *                                 member is already set to this value.
 *
 * @return NULL                 Unable to allocate an mbuf, out of mbufs.
 * @return Else                 A pointer to the allocated mbuf.
 */
struct mbuf *kcapi_get_ctlr_notify_mbuf
   (size_t nLen);



#endif /* __CAPI_DRV_H */
