/**
 * @file daic_global.h
 *
 * Daic-Global - Common definitions for all Diehl active ISDN controllers.
 *
 * Copyright: 2003 Thomas Wintergerst. All rights reserved.
 *
 * $FreeBSD$
 * $Id: daic_var.h,v 1.1.2.1 2006/02/28 21:35:17 thomas Exp $
 * $Project:    CAPI for BSD $
 * $Target:     daic - CAPI manager driver for Diehl active ISDN controllers $
 * @date        02.02.2003
 * @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 __DAIC_GLOBAL_H
#define __DAIC_GLOBAL_H

#include <sys/param.h>
#include <sys/types.h>
#include <sys/bus.h>
#include <machine/bus.h> /* needed before sys/rman.h */
#include <sys/rman.h>
#include <machine/resource.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/condvar.h>
#include <sys/socket.h> /* for net/if.h */
#include <net/if.h> /* struct ifqueue */
#include <c4b/kcapimgr/capi_drv.h>

#include <opt_daic.h>

#include <c4b/daic/daic_hwdefs.h>





/* === Public declarations =============================================== */





/* --- Several constants --- */

/** The name of the daic devices and the device class. */
#define DAIC_DEVICE_CLASS_NAME  "daic"

/** The maximum number of ports per board (a Quattro owns 4 ports). */
#define DAIC_MAX_PORTS          4

/** The maximum number of simultaneously registered applications. */
#ifndef DAIC_MAX_APPLICATIONS
#define DAIC_MAX_APPLICATIONS   30
#endif /* DAIC_MAX_APPLICATIONS */
#if DAIC_MAX_APPLICATIONS > 32
#error The maximum number of CAPI applications is (currently) limited to 32
#endif

/** The maximum number of PLCIs per port. */
#ifndef DAIC_MAX_PLCI_PER_PORT
#define DAIC_MAX_PLCI_PER_PORT  64
#endif /* DAIC_MAX_PLCI_PER_PORT */
#if DAIC_MAX_PLCI_PER_PORT < 30 || DAIC_MAX_PLCI_PER_PORT > 255
#error Invalid number of PLCIs per port, must be at least 30, at most 255
#endif

/** The maximum number of NCCIs per port. */
#ifndef DAIC_MAX_NCCI_PER_PORT
#define DAIC_MAX_NCCI_PER_PORT  128
#endif /* DAIC_MAX_NCCI_PER_PORT */
#if DAIC_MAX_NCCI_PER_PORT < DAIC_MAX_PLCI_PER_PORT || DAIC_MAX_NCCI_PER_PORT > 32767
#error Invalid number of NCICs per port, must be at least the number of PLCIs, at most 32767
#endif

/** The maximum number of NCCIs per PLCI. */
#ifndef DAIC_MAX_NCCI_PER_PLCI
#define DAIC_MAX_NCCI_PER_PLCI  4
#endif /* DAIC_MAX_NCCI_PER_PLCI */

/** The maunfacturer string for all Diehl active ISDN controllers. */
#define DAIC_MANUFACTURER_NAME  "Eicon Technology Corporation"

/** The version number of this device driver, major part. */
#define DAIC_DRIVER_VERSION_MAJOR       1

/** The version number of this device driver, minor part. */
#define DAIC_DRIVER_VERSION_MINOR       0

/** The name for the logging level as a tunable kernel parameter. */
#define DAIC_TUNABLE_LOGLEVEL \
   "capi." DAIC_DEVICE_CLASS_NAME ".loglevel"

/** Value for 1s delay in us for DELAY. */
#define DAIC_SEC_DELAY  1000000



/* --- Qualification for controller ids --- */

/** The identifier to mark a controller id as unused. */
#define DAIC_ID_QUALIFY_UNUSED  0

/** The identifier to mark a controller id assigned to the global id machine. */
#define DAIC_ID_QUALIFY_GID     1

/** The identifier to mark a controller id assigned to a PLCI state machine. */
#define DAIC_ID_QUALIFY_PLCI    2

/** The identifier to mark a controller id assigned to an NCCI state machine. */
#define DAIC_ID_QUALIFY_NCCI    3



/* --- Information about applications for each CAPI controller --- */

/**
 * The Register and Listen-Request information for each application per
 * controller.
 */
typedef struct
{
   unsigned  uApplID;           /**<
                                 * The application id for this entry. If this
                                 * value is zero, the entry is not used.
                                 */
   unsigned  uMaxBDataLen;      /**< The maximum data length from registration. */
   u_int32_t dwListenCipMask;   /**<
                                 * The CIP mask from the last Listen-Request.
                                 * If no Listen-Request is made, it is set to
                                 * zero.
                                 */
   u_int32_t dwListenInfoMask;  /**<
                                 * The info mask from the last Listen-Request.
                                 * If no Listen-Request is made, it is set to
                                 * zero.
                                 */
} DaicApplData_t;



/* --- The state machine data for the global id (D-channel access) --- */

/** The state values for the global id (D-channel access). */
typedef enum
{
   DAIC_GID_STATE_IDLE,         /**< Idle state, no global id assigned. */
   DAIC_GID_STATE_ASSIGN_REQ,   /**< Assign-Request pending for global id. */
   DAIC_GID_STATE_ASSIGN_OK,    /**<
                                 * Assign-Request completed, global id is valid.
                                 * Next step will be to send an Indicate-Request.
                                 */
   DAIC_GID_STATE_INDICATE_REQ, /**<
                                 * Global id is valid, an Indicate-Request is
                                 * pending to be informed about incoming calls.
                                 */
   DAIC_GID_STATE_ACTIVE,       /**<
                                 * Active state; global id is valid and we get
                                 * informed about incoming calls.
                                 */
   DAIC_GID_STATE_HANGUP_REQ,   /**<
                                 * A Hangup-Request is pending, normally because
                                 * of an incoming connection that cannot be
                                 * handled, eihter because we are out of PLCIs
                                 * or there is no application registered. After
                                 * the return code for the Hangup-Request the
                                 * signaling id will be removed to be safe.
                                 */
   DAIC_GID_STATE_IND_FAILED,   /**<
                                 * The Indicate-Request failed. The next step
                                 * is to remove the unuseable id.
                                 */
   DAIC_GID_STATE_REMOVE_REQ    /**<
                                 * The current global id will be removed because
                                 * it is not useable (indicate request failed).
                                 * A new global id will be requested.
                                 */
} DaicGlobalIdState_t;

/** The state information for the global id state machine (D-channel access). */
typedef struct
{
   DaicGlobalIdState_t state;   /**< The current state value. */
   unsigned            uId;     /**<
                                 * In states other than Idle and Assign-Request
                                 * this is the assigned global id through which
                                 * incoming calls are signaled.
                                 */
} DaicGlobalIdSmData_t;



/* --- The PLCI state machine data --- */

/** The state values for the PLCI state machine. */
typedef enum
{
   DAIC_PLCI_STATE_P0,          /**< Idle state, no action pending. */
   DAIC_PLCI_STATE_P0_1,        /**< Assign-Request pending, wait for rc. */
   DAIC_PLCI_STATE_P0_2,        /**< Call-Request pending, wait for rc. */
   DAIC_PLCI_STATE_P1,          /**< Got positive rc for Call-Request. */
   DAIC_PLCI_STATE_P1_1,        /**<
                                 * Got Call-Connected-Indication,
                                 * Assign-Request for network id is pending.
                                 */
   DAIC_PLCI_STATE_P2,          /**<
                                 * Got Indicate-Ind, applications are notified,
                                 * waiting for application response.
                                 */
   DAIC_PLCI_STATE_P4,          /**<
                                 * Got Connect-Response from application,
                                 * Call-Response is sent.
                                 */
   DAIC_PLCI_STATE_P4_1,        /**<
                                 * Got Call-Indication, Assign-Request for
                                 * network id is pending.
                                 */
   DAIC_PLCI_STATE_PACT,        /**<
                                 * Connection completely established, network id
                                 * for B-channel access was obtained and
                                 * Connect-Active-Indication is sent to the
                                 * application. The NCCI layer is now
                                 * responsible for proceeding with the call.
                                 */
   DAIC_PLCI_STATE_P5,          /**< Got Disconnect-Request, Hangup-Request sent.*/
   DAIC_PLCI_STATE_P6,          /**<
                                 * Got Hangup-Indication, wait for all NCCIs to
                                 * be released.
                                 */
   DAIC_PLCI_STATE_P6_1,        /**<
                                 * All NCCIs removed, Remove-Request for the
                                 * network id is pending.
                                 */
   DAIC_PLCI_STATE_P6_2,        /**<
                                 * Network id removed, Disconnect-Indication
                                 * sent, wait for Disconnect-Response.
                                 */
   DAIC_PLCI_STATE_P6_3,        /**<
                                 * Got Disconnect-Response, Remove-Request for
                                 * the signaling id is pending.
                                 */
   DAIC_PLCI_NUM_STATES         /**< Marker for the number of state values. */
} DaicPlciState_t;

/**
 * The B-Protocol information for a connection.
 *
 * Unfortunately the official CAPI structures are sometimes of variable length.
 * So we define our own versions here.
 */
typedef struct
{
   u_int16_t wB1Prot;
   u_int16_t wB2Prot;
   u_int16_t wB3Prot;
   struct
   {
      u_int8_t bAddrA;
      u_int8_t bAddrB;
      u_int8_t bModuloMode;
      u_int8_t bWindowSize;
   } b2Cfg;
   struct
   {
      u_int16_t wLIC;
      u_int16_t wHIC;
      u_int16_t wLTC;
      u_int16_t wHTC;
      u_int16_t wLOC;
      u_int16_t wHOC;
      u_int16_t wModuloMode;
      u_int16_t wWindowSize;
   } b3Cfg;
   u_int16_t wBChnOp;           /**<
                                 * One of the B-channel operation values. Only
                                 * the explicit values for DTE or DCE may be
                                 * stored here. This field will be set according
                                 * to the B-Protocol structure parsed and the
                                 * message it is contained in.
                                 */
} DaicBProtocolData_t;

/** @name Some flags to control an PLCI */
/** @{ */

/**
 * Flag for a received Hangup-Indication.
 *
 * This flag is set by the interrupt handler, if a Hangup-Indication is
 * received. If it is set, no more messages may be sent to the board for this
 * signaling id (including linked network ids).
 */
#define DAIC_PLCI_FLAG_GOT_HANGUP       0x00000001

/**
 * Flag for a received Abort-Request.
 *
 * This flag will be set if a connection must be aborted, but there is a
 * controller request pending. During the reception of any return code, the
 * state machine must look at this flag and abort the connection if it is set.
 */
#define DAIC_PLCI_FLAG_GOT_ABORT_REQ    0x00000002

/**
 * Flag for a pending controller request.
 *
 * Flag for an open controller request, and if we are waiting for the return
 * code. If this flag is set, no other controller request may be sent and no
 * CAPI message may be handled.
 */
#define DAIC_PLCI_FLAG_REQUEST_PENDING  0x00000004

/**
 * Flag for a sent Alert-Request.
 *
 * Alert-Requests may be sent for incoming calls. But as a call is signaled to
 * multiple applications, all of them are allowed to send a CAPI Alert-Request.
 * This flag is set at the first time an Alert-Request is sent out to a port.
 * If it is set, all other Alert-Requests must be ignored (or confirmed with
 * info value CIV_ALERT_ALREADY_SENT).
 */
#define DAIC_PLCI_FLAG_ALERTING_SENT    0x00000008

/** @} */

/** The state information for the PLCI state machine (signalling layer). */
typedef struct
{
   DaicPlciState_t state;       /**< The current state value. */
   unsigned        uPlci;       /**<
                                 * The PLCI for this entry, i.e. the index into
                                 * the PLCI data array.
                                 */
   u_int32_t       dwCid;       /**<
                                 * The CID for CAPI messages including the
                                 * controller number and the PLCI.
                                 */
   unsigned        uSigId;      /**< The signalling id assigned by the board. */
   unsigned        uNetId;      /**<
                                 * The network id assigned by the board for
                                 * B-channel access after connection
                                 * establishment.
                                 */
   unsigned        uApplID;     /**<
                                 * The application id assigned to this PLCI. If
                                 * no application is assigned yet (e.g. until a
                                 * Connect-Response is received for an incoming
                                 * call), this field is null.
                                 */
   int             iApplDataIdx;/**<
                                 * If an application id is assigned, this is the
                                 * corresponding index into the application data
                                 * array.
                                 */
   unsigned long   ulApplIdxBitField;
                                /**<
                                 * For an incoming call all matching
                                 * applications must get a Connect-Indication.
                                 * This field contains a bit mask of all
                                 * applications that received this message. This
                                 * information is necessary to send all
                                 * applications a Disconnect-Indication, if the
                                 * call expires or gets assigned explicitly to
                                 * a single application. A bit in this mask
                                 * corresponds to the index into the application
                                 * data array, i.e. bit 0 is index 0, etc.
                                 */
   DaicBProtocolData_t
                   bprot;       /**<
                                 * The B-channel protocols specified in the
                                 * Connect-Request or -Response. These settings
                                 * must be memorized until the NCCI is allocated
                                 * the the B3-connection shall be established.
                                 */
   size_t          nNumNcci;    /**<
                                 * The current number of active NCCIs for this
                                 * PLCI.
                                 */
   unsigned long   ulFlags;     /**
                                 * Some flags to control PLCI operation. Values
                                 * from DAIC_PLCI_FLAGS_*.
                                 */
   unsigned        uDisconnectCause;
                                /**<
                                 * This field is set to the reason value for the
                                 * Disconnect-Indication to be sent to the
                                 * application.
                                 */
   unsigned        uAbortCause; /**<
                                 * This field is set to the cause value to
                                 * attach to a hangup request if the flag
                                 * DAIC_PLCI_FLAG_GOT_ABORT_REQ is set. It is
                                 * only used if an abort request cannot be
                                 * handled immediately but only after the
                                 * currently pending request is finished.
                                 */
   unsigned        uCurrRequest;/**<
                                 * If the flag DAIC_PLCI_FLAG_REQUEST_PENDING
                                 * is set, this is the request for which we are
                                 * awaiting the result.
                                 */
   struct mbuf    *pmbCurrCapiMsg;
                                /**<
                                 * If fRequestPending is set and this request is
                                 * linked to a CAPI message that is still
                                 * needed, this field points to the mbuf
                                 * containing the CAPI message. This is needed
                                 * to be able to send a valid confirmation
                                 * message for a CAPI request. The message mbuf
                                 * will be released not later than the confirm
                                 * message is sent.
                                 */
   unsigned        uCurrCapiReqMsgNum;
                                /**<
                                 * If a CAPI request is executed and the
                                 * corresponding confirm is pending, this field
                                 * is set to the message number of the request.
                                 */
   struct ifqueue  msgQueue;    /**<
                                 * This queue is used to hold CAPI messages and
                                 * controller indications that cannot be
                                 * evaluated at once because of the current
                                 + state. I.e. this signalling id may have a
                                 * request pending on the controller and is
                                 * waiting for the return code. Only one request
                                 * per id is possible. To distinguish between
                                 * indications and CAPI messages, the mbuf type
                                 * MT_CONTROL is used for controller messages
                                 * (MT_DATA is used for CAPI messages).
                                 */
} DaicPlciData_t;



/* --- The NCCI state machine data --- */

/** The state values for the NCCI state machine. */
typedef enum
{
   DAIC_NCCI_STATE_N0,          /**< Idle state, no action pending. */
   DAIC_NCCI_STATE_N1,          /**<
                                 * Active connection establishment,
                                 * Connect-B3-Request pending, waiting for
                                 * controller Connect-Ack-Indication.
                                 */
   DAIC_NCCI_STATE_N2,          /**<
                                 * Passive connection establishment,
                                 * Connect-B3-Indication sent, waiting for
                                 * Connect-B3-Response.
                                 */
   DAIC_NCCI_STATE_N2_1,        /**<
                                 * Got Connect-B3-Response, controller
                                 * Connect-Ack-Request pending.
                                 */
   DAIC_NCCI_STATE_NACT,        /**<
                                 * Connection established, data communication
                                 * possible.
                                 */
   DAIC_NCCI_STATE_N4,          /**<
                                 * Active connection release, waiting for
                                 * controller Disconnect-(Ack-)Indication.
                                 */
   DAIC_NCCI_STATE_N5,          /**<
                                 * Connection completely released, got
                                 * controller Disconnect-(Ack-)Indication,
                                 * Disconnect-B3-Indication sent, waiting for a
                                 * Disconnect-B3-Response. If we received a
                                 * Disconnect-Indication, a
                                 * Disconnect-Ack-Request is pending and its
                                 * return code will be evaluated before the
                                 * Disconnect-B3-Response (CAPI messages are
                                 * only handled when no controller request is
                                 * pending and return codes bypass the queue).
                                 */
   DAIC_NCCI_NUM_STATES         /**< Marker for the number of state values. */
} DaicNcciState_t;

/** @name Some flags to control an NCCI */
/** @{ */

/**
 * Flag for a received Disconnect-Indication.
 *
 * This flag is set by the interrupt handler, if a Disconnect-Indication is
 * received. If it is set, no more messages may be sent to the board for this
 * network id.
 */
#define DAIC_NCCI_FLAG_GOT_DISCONNECT   0x00000001

/**
 * Flag for a received Abort-Request.
 *
 * This flag will be set if a connection must be aborted, but there is a
 * controller request pending. During the reception of any return code, the
 * state machine must look at this flag and abort the connection if it is set.
 */
#define DAIC_NCCI_FLAG_GOT_ABORT_REQ    0x00000002

/**
 * Flag for a pending controller request.
 *
 * Flag for an open controller request, and if we are waiting for the return
 * code. If this flag is set, no other controller request may be sent and no
 * CAPI message may be handled.
 */
#define DAIC_NCCI_FLAG_REQUEST_PENDING  0x00000004

/**
 * Flag for a pending Reset-B3-Request/-Indication.
 *
 * This flag is set when a Reset-B3-Request or controller Reset-Indication is
 * enqueued for this NCCI. If this flag is set, all Data-B3-Requests are
 * discarded until the Reset-B3-Request or Reset-Indication is handled. Then
 * this flag will be reset.
 */
#define DAIC_NCCI_FLAG_GOT_RESET        0x00000008

/** Flag for the usage of an NCPI (currently only for ISO-8208). */
#define DAIC_NCCI_FLAG_USE_NCPI         0x00000010

/** Flag for possible switching from T.70 to T.90. */
#define DAIC_NCCI_FLAG_T90_ENABLE       0x00000020

/**
 * This flag is set for voice connections, i.e. when transparent B-channel
 * protocols are used.
 */
#define DAIC_NCCI_FLAG_TRANSPARENT      0x00000040

/** @} */

/** The state information for the NCCI state machine (network layer). */
typedef struct
{
   DaicNcciState_t state;       /**< The current state value. */
   unsigned        uNcci;       /**<
                                 * The NCCI value for this entry, i.e. the index
                                 * into the NCCI data array.
                                 */
   unsigned        uPlci;       /**< The PLCI value this NCCI is assigned to. */
   u_int32_t       dwCid;       /**<
                                 * The CID for CAPI messages including the
                                 * controller number, the PLCI and the NCCI.
                                 */
   unsigned        uNetId;      /**< The network id assigned by the board. */
   unsigned        uNetCh;      /**<
                                 * The channel in the context of the network id.
                                 */
   unsigned        uApplID;     /**<
                                 * The application id assigned to this NCCI. It
                                 * is possible that no application is assigned
                                 * to an NCCI when it performs a release with
                                 * still open connections.
                                 */
   unsigned        uMaxDataLen; /**<
                                 * The maximum length of a data block, from
                                 * application registration.
                                 */
   unsigned long   ulFlags;     /**< Some flags to control operation. */   
   unsigned        uDisconnectReason;
                                /**<
                                 * This field is set to the reason value for the
                                 * Disconnect-B3-Indication to be sent to the
                                 * application.
                                 */
   unsigned        uCurrRequest;/**<
                                 * If the flag DAIC_NCCI_FLAG_REQUEST_PENDING
                                 * is set, this is the request for which we are
                                 * awaiting the result.
                                 */
   struct mbuf    *pmbCurrCapiMsg;
                                /**<
                                 * If fRequestPending is set and this request is
                                 * linked to a CAPI message that is still
                                 * needed, this field points to the mbuf
                                 * containing the CAPI message. This is needed
                                 * to be able to send a valid confirmation
                                 * message for a CAPI request. The message mbuf
                                 * will be released not later than the confirm
                                 * message is sent.
                                 */
   unsigned        uCurrCapiReqMsgNum;
                                /**<
                                 * If a CAPI request is executed and the
                                 * corresponding confirm is pending, this field
                                 * is set to the message number of the request.
                                 */
   size_t          nNumPendingDataRc;
                                /**<
                                 * If pmbCurrCapiMsg points to an mbuf with a
                                 * Data-B3-Request and a controller request for
                                 * the data block is pending, this field
                                 * contains the current number of return codes
                                 * that must be received. As a data block may
                                 * have to be split over several controller
                                 * requests, the controller will send several
                                 * return codes for a single application data
                                 * block. As soon as the last return code is
                                 * received, the application will get a
                                 * Data-B3-Confirmation. The confirmation result
                                 * to report is stored in uDataB3ReqResult.
                                 */
   unsigned        uDataB3ReqResult;
                                /**<
                                 * This field is used to store an error code to
                                 * be sent within a Data-B3-Confirm message to
                                 * the application. This is necessary because a
                                 * data block may be sent as several portions
                                 * (the controller can only handle up to 270
                                 * bytes at a time) and each of the controller
                                 * requests may fail. The first stored error
                                 * remains until the last data block portion is
                                 * sent.
                                 */
   struct mbuf    *pmbReceiveData;
                                /**<
                                 * If a data block is currently received through
                                 * More-Data-Indications from the controller,
                                 * the mbuf to store the data fragments is
                                 * stored here. It is valid until the final
                                 * Data-Indication is received.
                                 *
                                 * For voice connections (transparent protocols)
                                 * this mbuf is allocated with the data length
                                 * requested by the application. It collects
                                 * several Data-Indications
                                 * (More-Data-Indications are not signaled for
                                 * voice connections) until it is filled.
                                 */
   unsigned        uCurrReceiveData;
                                /**<
                                 * If pmbReceiveData points to an mbuf, this
                                 * field contains the current fill index of the
                                 * data mbuf (i.e. the number of bytes in it).
                                 */
   unsigned        uDataIndHandle;
                                /**<
                                 * This field makes up the handle for every
                                 * Data-B3-Indication. It is incremented after
                                 * every Data-B3-Indication sent to the
                                 * application.
                                 */
   struct ifqueue  capiMsgQueue;/**<
                                 * This queue is used to hold CAPI messages that
                                 * cannot be evaluated at once because of the
                                 * current state. I.e. this NCCI may have a
                                 * request pending on the controller and is
                                 * waiting for the return code. Only one request
                                 * per id/channel is possible.
                                 */
   struct ifqueue  indMsgQueue; /**<
                                 * This queue is used to hold controller
                                 * indications that cannot be evaluated at once
                                 * because of the current state. I.e. this NCCI
                                 * may have a request pending on the controller
                                 * and is waiting for the return code. Only one
                                 * request per id/channel is possible.
                                 *
                                 * There is a separate queue for indications,
                                 * because a boost of CAPI messages (e.g.
                                 * Data-B3-Requests or -Responses) could prevent
                                 * indications from beeing processed in time.
                                 * And the application queue could be flooded
                                 * with messages when the queued indications are
                                 * processed, thus filling up the receive queue
                                 * for the application.
                                 */
} DaicNcciData_t;



/* --- Translation of controller ids into PLCIs and NCCIs --- */

/**
 * Table entry to translate signaling and network ids into PLCIs and NCCIs.
 *
 * For every port of an ISDN board a translation table must be maintained to
 * map controller ids to PLCIs, NCCIs or the global id state machine. Such a
 * table is made up of an array of 256 entries of this structure.
 *
 * The entries of the table are indexed by the assigned controller id. If the
 * qualification of the respective entry is "unused", the id with this index is
 * currently not assigned. Other qualifications mark an assigned id as belonging
 * to the global id state machine (to wait for incoming calls), to a PLCI state
 * machine or to an NCCI state machine. The later is not quite true, because
 * a single network id can stand for multiple NCCIs. The other two
 * qualifications are for signaling ids.
 *
 * No additional data is stored for signaling ids for the global id state
 * machine. For signaling id belonging to a PLCI state machine the corresponding
 * PLCI value is stored. Network ids require even more additional routing data.
 * As a network id is only useable with a channel number, there are some entries
 * to store channel numbers. For easier handling this is a fixed number and a
 * compilation option. Each time a NL_CONNECT or a NL_CONNECT_ACK indication is
 * received, the new channel number and the corresponding NCCI are entered in a
 * free entry in the array. As a simple "hash" rule the channel number is used
 * as the starting point to look either for a free entry or for the channel for
 * which a message is received.
 */
typedef struct
{
   int iQualify;                /**<
                                 * Qualification of the id, one of
                                 * DAIC_ID_QUALIFY_*.
                                 */
   unsigned uPlci;              /**<
                                 * If the id used as the index to address this
                                 * entry represents a signaling id for a PLCI or
                                 * a network id, this field contains the PLCI
                                 * value the id is assigned to.
                                 */
   /**
    * If the id use as the index to address this entry represents a network id,
    * this structure contains the channel number and the assigned NCCI. These
    * values are valid as soon as a channel is assigned to the network id
    * (NL_CONNECT or NL_CONNECT_ACK indication). If an entry is unused, the
    * channel id is zero (the NCCI as well).
    */
   struct
   {
      unsigned uChId;
      unsigned uNcci;
   } aNcciInfo [DAIC_MAX_NCCI_PER_PLCI];
} DaicIdTransTableEntry_t;



/* --- Data maintained for installed boards --- */

/**
 * The different board types supported.
 *
 * @note These values correspond with the card type value delivered by the board
 *       itself. The board value must be incremented by 1 to get the values of
 *       this enumeration.
 *
 * @attention If this definition is modified, the corresponding string table in
 *            daic_misc.c must be changed accordingly.
 */
typedef enum
{
   DAIC_CARD_TYPE_UNKNOWN,
   DAIC_CARD_TYPE_S,
   DAIC_CARD_TYPE_SX,
   DAIC_CARD_TYPE_SCOM,
   DAIC_CARD_TYPE_QUADRO,
   DAIC_CARD_TYPE_S2M,
   DAIC_NUM_CARD_TYPES
} DaicCardType_t;

/** The state values for the board as a whole. */
typedef enum
{
   DAIC_BOARD_STATE_UNKNOWN,    /**<
                                 * Any state before a successful probe/attach
                                 * or after a failed probe/attach.
                                 */
   DAIC_BOARD_STATE_DOWN,       /**<
                                 * State after a successful attach or after a
                                 * reset, board registered at the CAPI manager.
                                 */
   DAIC_BOARD_STATE_BOOTSTRAP_LOADING,
                                /**<
                                 * Boostrap load in progress (but not during
                                 * probe operation).
                                 */
   DAIC_BOARD_STATE_FIRMWARE_LOADING,
                                /**< Firmware load in progress. */
   DAIC_BOARD_STATE_RUNNING     /**< Board is active and running. */
} DaicBoardState_t;

/** Resource information maintained for a board. */
typedef struct
{
   int                 iRidMem; /**< Memory resource id. */
   unsigned long       ulMemBase;
                                /**< Memory base address. */
   unsigned long       ulMemSize;
                                /**< Number of bytes at ulMemBase. */
   struct resource    *pResMem; /**<
                                 * If not null: the allocated memory bus
                                 * resource.
                                 */
   bus_space_tag_t     memTag;  /**<
                                 * The bus tag during probe and after attach.
                                 */
   bus_space_handle_t  memHandle;
                                /**<
                                 * The bus handle during probe and after attach.
                                 */
   
   int                 iRidIrq; /**< IRQ resource id. */
   int                 iIrq;    /**< The assigned irq number. */
   struct resource    *pResIrq; /**<
                                 * If not null: the allocated irq bus resource.
                                 */
   void               *hIrqCookie;
                                /**< Needed to setup/teardown the irq. */
} DaicResourceInfo_t;

/** Data stored for one port of a board (boards may contain more than one port).
 */
typedef struct _daic_portdata
{
   struct _daic_sc          *pSc;
                                /**<
                                 * Address of the surrounding softc structure.
                                 */
   unsigned                  iUnit;
                                /**<
                                 * The unit number within the driver, this port
                                 * is a member of.
                                 */
   unsigned                  uPortIdx;
                                /**<
                                 * Index of this port into the port data array
                                 * of the softc structure.
                                 */
   char                      szCtlrPortName [CAPI_CTLR_NAME_LEN];
                                /**<
                                 * Port name for CAPI registration. It should
                                 * contain card type, unit number and port
                                 * number, e.g. "Quadro-1/3".
                                 */
   unsigned                  uUniqueCapiCtlrNum;
                                /**<
                                 * The controller no. of the port assigned by
                                 * the CAPI manager. Null means this port is not
                                 * registered.
                                 */
   unsigned                  uCapiIndMsgNum;
                                /**<
                                 * The current message number for CAPI
                                 * indications.
                                 */

   size_t                    nBChns;
                                /**< Number of available B-channels. */

   CAPICtlrRegisterParams_t  regParams;
                                /**<
                                 * Data for registering the ISDN port as a
                                 * controller at the CAPI manager.
                                 */

   /* some board specific shared memory register offsets */
   unsigned long             ulBaseOffset;
                                /**<
                                 * Basic offset into the shared memory for all
                                 * operations. For single-port boards this is 0,
                                 * for a Quadro each port has its own offset for
                                 * its own memory registers.
                                 */
   unsigned long             ulIntAckOffset;
                                /**< Offset of the irq (ack.) register. */
   unsigned long             ulStopCpuOffset;
                                /**< Offset of the STOPCPU register. */
   unsigned long             ulStartCpuOffset;
                                /**< Offset of the STARTCPU register. */

   /* state machine data for each of the different layers */
   DaicGlobalIdSmData_t      globIdData;
                                /**<
                                 * Global id state machine data (D-channel
                                 * access).
                                 */
   size_t                    nNumPlci;
                                /**< The current number of PLCIs in use. */
   unsigned                  uLastAllocatedPlci;
                                /**<
                                 * The last allocated PLCI value. Any time if a
                                 * new PLCI is allocated, this value is
                                 * incremented (modulo the array length of
                                 * aPlciData). Starting from this position a
                                 * free PLCI entry is looked for (entry 0 is
                                 * left out).
                                 */
   DaicPlciData_t            aPlciData [DAIC_MAX_PLCI_PER_PORT + 1];
                                /**<
                                 * PLCI state machine data. The array is indexed
                                 * by the PLCI value. The first entry (PLCI 0)
                                 * is not used.
                                 */
   unsigned                  uLastAllocatedNcci;
                                /**<
                                 * The last allocated NCCI value. Any time if a
                                 * new NCCI is allocated, this value is
                                 * incremented (modulo the array length of
                                 * aNcciData). Starting from this position a
                                 * free NCCI entry is looked for (entry 0 is
                                 * left out).
                                 */
   DaicNcciData_t            aNcciData [DAIC_MAX_NCCI_PER_PORT + 1];
                                /**<
                                 * NCCI state machine data. The array is indexed
                                 * by the NCCI value. The first entry (NCCI 0)
                                 * is not used.
                                 */
   DaicApplData_t            aApplData [DAIC_MAX_APPLICATIONS];
                                /**<
                                 * Data the controller needs to know about each
                                 * registered CAPI application. The application
                                 * id is not related to the array index.
                                 */
   DaicIdTransTableEntry_t   aIdTransTable [256];
                                /**<
                                 * The translation table for controller ids into
                                 * PLCIs and NCCIs. A given controller id for a
                                 * return code or an indication is used as an
                                 * index into this table. The addressed entry
                                 * specifies if the id is used as the global
                                 * signaling id, for a PLCI or together with the
                                 * channel id as an NCCI. This is needed to
                                 * forward a return code or an indication to the
                                 * state machine in response. The table is
                                 * updated in the dispatch module in reaction to
                                 * dispatching specific CAPI or controller
                                 * messages.
                                 */

   /* information needed to handle assign return codes */
   int                       fAssignPending;
                                /**< Flag for a pending assign request. */
   unsigned                  uAssignReqQualification;
                                /**<
                                 * The purpose the id to assign shall serve (one
                                 * of DAIC_ID_QUALIFY_*). This information is
                                 * needed to dispatch the return code to the
                                 * responsible state machine. If the id should
                                 * be a signaling or network id for a PLCI, the
                                 * field uAssignReqPlci contains the PLCI value.
                                 */
   unsigned                  uAssignReqPlci;
                                /**<
                                 * If the pending Assign-Request shall deliver a
                                 * signaling or network id for a PLCI, this
                                 * field contains the corresponding PLCI value.
                                 */
   int                       iReadyInt;
                                /**<
                                 * Number of times a Ready-Interrupt is
                                 * requested from the port. This is used to let
                                 * the board tell us when the current request is
                                 * handled so far that it is able to accept the
                                 * next one. There might be a remarkable amount
                                 * of time between accepting a request and the
                                 * delivery of its return code.
                                 */
   int                       iIrqProbe;
                                /**<
                                 * Flag to declare IRQ probe operation. This
                                 * will be evaluated and incremented by the
                                 * interrupt routine.
                                 */

   struct ifqueue            reqQueue;
                                /**< The queue for requests to execute. */
} DaicPortData_t;

/** The daic device specific softc structure, data stored for each board. */
typedef struct _daic_sc
{
   int                 iUnit;   /**< Unit number for the device. */
   DaicBoardState_t    state;   /**< Current state of the board. */
   DaicCardType_t      cardType;/**< The identified card type. */
   char                szCardName [CAPI_CTLR_NAME_LEN];
                                /**<
                                 * Card name for log output, should contain card
                                 * type and unit number, e.g. "SCOM-1"
                                 */
   char                szDriverName [CAPI_CTLR_DRIVER_NAME_LEN];
                                /**< Driver name, "daic". */
   DaicResourceInfo_t  resInfo; /**<
                                 * Information about assigned hardware
                                 * resources.
                                 */
   unsigned long       ulOnBoardMemory;
                                /**<
                                 * On-board memory of the controller board in
                                 * KB.
                                 */

   size_t              nPorts;  /**<
                                 * The number of ISDN ports (that memory is
                                 * allocated for).
                                 */
   size_t              nPortsInitialized;
                                /**<
                                 * The number of ports currently initialized.
                                 * This value will grow from 0 to nPorts when
                                 * downloading the controller.
                                 */
   DaicPortData_t     *apPortData [DAIC_MAX_PORTS];
                                /**<
                                 * Port specific data for the board. Only nPorts
                                 * number of entries starting at index 0 are
                                 * allocated memory.
                                 */

   /* fields for communication between user processes and the interrupt routine
    */
   int                 fIntrActive;
                                /**<
                                 * Flag for a currently active interrupt
                                 * routine.
                                 */
   int                 fOpInProgress;
                                /**<
                                 * Flag for a call from the CAPI manager in
                                 * progress. If this flag is set, no other call
                                 * from the CAPI manager will get board access
                                 * over the mutex. This is used to let an
                                 * operation release the mutex (e.g. while
                                 * waiting for some event) without beeing
                                 * interrupted by another call into the driver.
                                 */
   struct mtx          mtxAccess;
                                /**<
                                 * Lock for exclusive board data access. This
                                 * lock is always obtained when an external
                                 * driver function is called by the CAPI manager
                                 * and the interrupt routine is called. So all
                                 * operations are done with exclusive board
                                 * access.
                                 */
   struct cv           cvNotify;/**<
                                 * When waiting for an event during an operation
                                 * (normally reported through the interrupt
                                 * routine), the waiter will wait on this
                                 * condition object to be signalled.
                                 */
} DaicSc_t;

/**
 * Mapping from CAPI controller number to the port data.
 * @note CAPI defines a maximum of 127 controller number from 1 to 127.
 */
extern DaicPortData_t *e_apDaicMapCapiCtlrToPortData [128];



/* --- the logging functionality --- */

/** The logging levels supported. */
#define LOG_ALWAYS      0
#define LOG_ERROR       1
#define LOG_INFO        2
#define LOG_TRACE       3
#define LOG_DEBUG       4
#define LOG_DATAMSG     5
#define LOG_IRQ         6

/**
 * Characters to mark log messages with their severity.
 *
 * @note The array-string is indexed by the log level.
 */
#define LOG_CHARS       "AEMTDDI"

/** The current logging level. */
extern int e_iDaicLogLevel;

/** The macro for log output with driver unit number. */
#define DBG( level, iUnit, fmt, args... )                        \
   if ((level) <= e_iDaicLogLevel)                               \
   {                                                             \
      printf ("daic%d: %c %s: " fmt "\n",                        \
              iUnit, LOG_CHARS [level], __FUNCTION__ , ## args); \
   }

/** The macro for log output with no unit number available. */
#define DBG0( level, fmt, args... )                       \
   if ((level) <= e_iDaicLogLevel)                        \
   {                                                      \
      printf ("daic: %c %s: " fmt "\n",                   \
              LOG_CHARS [level], __FUNCTION__ , ## args); \
   }





/* === Prototypes of interface functions ================================= */





#endif /* __DAIC_GLOBAL_H */
