/**
 * @file ix1a_global.h
 *
 * IX1a-Global - Common definitions for all IX1 active controllers.
 *
 * Copyright: 2004 Thomas Wintergerst. All rights reserved.
 *
 * $FreeBSD$
 * $Id: ix1a_var.h,v 1.1.2.1 2006/02/28 21:35:24 thomas Exp $
 * $Project     CAPI for BSD $
 * $Target      ix1a - CAPI manager driver for IX1 active ISDN controllers $
 * @date        11.07.2004
 * @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 __IX1A_GLOBAL_H
#define __IX1A_GLOBAL_H

#include <sys/types.h>          /* size_t */
#include <sys/mbuf.h>
#include <sys/proc.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/condvar.h>
#include <sys/socket.h>         /* struct sockaddr for net/if.h */
#include <net/if.h>             /* struct if_queue */
#include <machine/bus.h>
#include <c4b/kcapimgr/capi_drv.h>

#include <opt_ix1a.h>
#include <c4b/ix1a/ix1a_hwdefs.h>





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





/* --- several constants --- */

/** The name of the ix1a devices and the device class. */
#define IX1A_DEVICE_CLASS_NAME          "ix1a"

/** The maximum number of ports per card (an Octo owns 4 ports). */
#define IX1A_MAX_PORTS                  4

/**
 * The maximum number of applications that can be registered at one board.
 *
 * This includes application number 0 that cannot be used, i.e. application ids
 * 1..<number - 1> are useable.
 */
#define IX1A_MAX_APPLICATIONS           36

/** The maunfacturer string for all IX1 active ISDN controllers. */
#define IX1A_MANUFACTURER_NAME          "Digi International, Inc."

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

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

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



/* --- possible states for an IX1 active ISDN controller --- */

/**
 * The possible states for a board .
 *
 * @note The order is important. "Ready" must be the lowest state number
 *       defining a working controller. States below it are regarded as
 *       "controller not working".
 */
typedef enum
{
   IX1A_STATE_UNKNOWN = 0,      /**<
                                 * Any state before a successful attach or after
                                 * a failed attach. */
   IX1A_STATE_INITIALISING,     /**<
                                 * Controller is beeing initialized (during
                                 * attach procedure).
                                 */
   IX1A_STATE_DOWN,             /**<
                                 * Controller was successfully initialized and
                                 * is now waiting for its firmware download.
                                 */
   IX1A_STATE_SET_BOOT_MODE,    /**<
                                 * Prepare the controller to receive the
                                 * bootstrap code.
                                 */
   IX1A_STATE_TEST_INT_WAITING, /**<
                                 * Board is told to generate test interrupt,
                                 * waiting for it. For boards that do not
                                 * support test interrupts we simply assume the
                                 * interrupt was successfully delivered.
                                 */
   IX1A_STATE_BOOTSTRAP_LOADING,/**<
                                 * The bootstrap code is loaded onto the board,
                                 * waiting for a generated interrupt.
                                 */
   IX1A_STATE_BOOTPARAM_LOADING,/**<
                                 * The parameter block for later firmware
                                 * loading is transfered to the board.
                                 */
   IX1A_STATE_FIRMWARE_LOADING, /**<
                                 * The firmware is beeing loaded onto the board.
                                 */
   IX1A_STATE_FIRMWARE_STARTING,/**<
                                 * Firmware start command is executing, wait for
                                 * board's ready message.
                                 */
   IX1A_STATE_READY,            /**< Controller is ready to perform requests. */
   IX1A_STATE_BUSY              /**<
                                 * Controller is currently unable to accept a
                                 * new message to execute.
                                 */
} Ix1aState_t;



/* --- data stored for installed boards --- */

/**
 * Resource data for the board.
 *
 * Most of the fields are only used for specific hardware. E.g. all ISA Hardware
 * uses only one i/o port and an irq for communication. The Basic PCI uses three
 * i/o ports and an irq, and last but not least the Primary PCI uses three
 * memory mapped i/o ranges and an irq.
 *
 * For each resource the first field is determined from the device data or PCI
 * configuration data. The resource id is defined by the board's hardware
 * interface. It id set within the code as a board specific constant. The
 * resource data structure is obtained as a result of allocating the the
 * respective at the resource manager. Through this data structure (that is used
 * like an opaque handle) a tag and a handle are obtained. These two values are
 * used to address data within the respective i/o range.
 */
typedef struct
{
   /* Basic PCI: i/o header (cmd2) */
   int                 iIoBaseHeader;   /**< I/o header: I/o Port number. */
   int                 iRidIoHeader;    /**< I/o header: Resource id. */
   struct resource    *pResIoHeader;    /**< I/o header: Allocated resource data. */
   bus_space_tag_t     ioTagHeader;     /**< I/o header: I/o tag. */
   bus_space_handle_t  ioHandleHeader;  /**< I/o header: I/o handle. */
   
   /* ISA: i/o base, Basic PCI: i/o data */
   int                 iIoBaseData;     /**< I/o data: I/o Port number. */
   int                 iRidIoData;      /**< I/o data: Resource id. */
   struct resource    *pResIoData;      /**< I/o data: Allocated resource data. */
   bus_space_tag_t     ioTagData;       /**< I/o data: I/o tag. */
   bus_space_handle_t  ioHandleData;    /**< I/o data: I/o handle. */

   /* Basic PCI: i/o command (cmd1, shm offset) */
   int                 iIoBaseCmd;      /**< I/o command: I/o Port number. */
   int                 iRidIoCmd;       /**< I/o command: Resource id. */
   struct resource    *pResIoCmd;       /**< I/o command: Allocated resource data. */
   bus_space_tag_t     ioTagCmd;        /**< I/o command: I/o tag. */
   bus_space_handle_t  ioHandleCmd;     /**< I/o command: I/o handle. */

   /* Primary PCI: Shared memory */
   unsigned long       ulMemBaseShm;    /**< SHM: Physical memory base address. */
   unsigned long       ulMemSizeShm;    /**< SHM: Size of physical memory. */
   int                 iRidMemShm;      /**< SHM: Resource id. */
   struct resource    *pResMemShm;      /**< SHM: Allocated resource data. */
   bus_space_tag_t     memTagShm;       /**< SHM: Memory tag. */
   bus_space_handle_t  memHandleShm;    /**< SHM: Memory handle. */
   
   /* Primary PCI: GAL memory */
   unsigned long       ulMemBaseGal;    /**< GAL: Physical memory base address. */
   unsigned long       ulMemSizeGal;    /**< GAL: Size of physical memory. */
   int                 iRidMemGal;      /**< GAL: Resource id. */
   struct resource    *pResMemGal;      /**< GAL: Allocated resource data. */
   bus_space_tag_t     memTagGal;       /**< GAL: Memory tag. */
   bus_space_handle_t  memHandleGal;    /**< GAL: Memory handle. */
   
   /* Primary PCI: Memory mapped register (mmr) */
   unsigned long       ulMemBaseMmr;    /**< MMR: Physical memory base address. */
   unsigned long       ulMemSizeMmr;    /**< MMR: Size of physical memory. */
   int                 iRidMemMmr;      /**< MMR: Resource id. */
   struct resource    *pResMemMmr;      /**< MMR: Allocated resource data. */
   bus_space_tag_t     memTagMmr;       /**< MMR: Memory tag. */
   bus_space_handle_t  memHandleMmr;    /**< MMR: Memory handle. */

   /* assigned IRQ */
   int                 iIrq;		       /**< Assigned irq number. */
   int                 iRidIrq;         /**< Irq resource id. */
   struct resource    *pResIrq;         /**< Allocated irq resource data. */
   void               *hIrqCookie;      /**< Needed to setup/teardown the irq. */
   int                 fIrqSetup;       /**< Flag for completed bus_setup_intr() call. */
} Ix1aResourceInfo_t;

/** Data stored for each port of a card (cards may contain more than one port). */
typedef struct _ix1a_portdata
{
   char                     szCtlrPortName [CAPI_CTLR_NAME_LEN];
                                /**
                                 * Port name for CAPI registration, should
                                 * contain card type, unit number and port
                                 * number, e.g. "IX1-Octo-1/3".
                                 */
   unsigned                 uUniqueCapiCtlrNum;
                                /**
                                 * CAPI controller number assigned by the CAPI
                                 * manager. If 0 the controller is not
                                 * registered at the CAPI manager.
                                 */
   unsigned                 uDriverCapiCtlrNum;
                                /**
                                 * Driver specific CAPI controller number. It
                                 * may be different from the CAPI manager
                                 * assigned controller number if there are
                                 * Octo boards in the system. These boards
                                 * require their controller numbers to start at
                                 * 1, 5, 9, etc.
                                 */
   CAPICtlrRegisterParams_t regParams;
                                /**
                                 * Data for registering the ISDN port as a
                                 * controller at the CAPI manager.
                                 */
} Ix1aPortData_t;

/** The device specific softc structure. */
typedef struct _ix1a_sc
{
   int                iUnit;    /**< Unit number for device. */
   Ix1aResourceInfo_t resInfo;  /**<
                                 * Summary of i/o, memory and irq resources for
                                 * the board.
                                 */
   Ix1aCardType_t     cardType; /**< Card type, IX1A_CARD_TYPE_*. */
   int                iJumperSetting;
                                /**< Jumper setting for ISA boards. */
   int                iBoardRevision;
                                /**<
                                 * Board revision as delivered from the board.
                                 */
   char               szCardName [CAPI_CTLR_NAME_LEN];
                                /**<
                                 * Card name for log output, should contain
                                 * card type and unit number, e.g.
                                 * "Datafire-Basic-1".
                                 */
   char               szDriverName [CAPI_CTLR_DRIVER_NAME_LEN];
                                /**< Driver name, "ix1a". */
   Ix1aState_t        state;    /**<
                                 * Current state of the board, IX1A_STATE_*.
                                 */
   size_t             nNumBChnsPerPort;
                                /**< Number of B-channels of each port. */
   size_t             nPorts;   /**<
                                 * Number of (CAPI-)controllers, normally 1,
                                 * but an Octo owns 4.
                                 */
   Ix1aPortData_t     aPortData [IX1A_MAX_PORTS];
                                /**<
                                 * Array of data for the controllers, number of
                                 * used records is in nPorts.
                                 */
   char               szManufacturer [64];
                                /**<
                                 * Manufacturer string from the board. Before
                                 * firmware download this is set to a fixed
                                 * string. After download this field is set
                                 * from information delivered by the board.
                                 */
   char               szSerialNo [16];
                                /**<
                                 * The board's serial number as delivered by
                                 * the board after the firmware startup.
                                 */
   char               szPureSerialNo [16];
                                /**<
                                 * The board's serial number as a pure digit
                                 * string (the original contains "-" chars).
                                 */
   char               szVersionString [64];
                                /**<
                                 * The version string delivered by the board.
                                 */
   u_int8_t           abCapiProfile [64];
                                /**<
                                 * The CAPI profile buffer for the board. The
                                 * content is mostly delivered by the board
                                 * after the firmware startup.
                                 */

   /* fields for CAPI message exchange within the board shared memory, only
    * valid after a successful firmware download
    */
   unsigned           uShmSizeFVFlag;
                                /**<
                                 * The length (in bytes) of the F/V flag before
                                 * every message in the shared memory. For
                                 * Primary boards it is four bytes long, for
                                 * others only two. The relevant information is
                                 * in all cases in the first byte.
                                 */
   unsigned           uShmMsgLen;
                                /**<
                                 * The message grid length for the CAPI message
                                 * read and write buffers, including the
                                 * preceeding F/V flag.
                                 */
   size_t             nNumNcci; /**<
                                 * The maximum number of NCCIs the board
                                 * supports. This value also determines the
                                 * length of the NCCI flow control table.
                                 */
   size_t             nNumAppl; /**<
                                 * The maximum number of applications that may
                                 * be registered to the board. The application
                                 * numbers must lie between and excluding 0 and
                                 * this value. It will be limited to the number
                                 * of entries available in the array auApplMap
                                 * (disregarding entry 0).
                                 */
   unsigned           auApplMap [IX1A_MAX_APPLICATIONS];
                                /**<
                                 * The application id map for the board. An IX1
                                 * board only accepts application ids up to a
                                 * board (firmware) specific maximum. So we
                                 * need to translate the CAPI manager assigned
                                 * application id to a controller specific one.
                                 * The controller specific id is used as the
                                 * index into this array. The value at the
                                 * addressed position is the CAPI manager
                                 * assigned application id, null if unused.
                                 * Index null is used to store the last
                                 * assigned application id, so we can assign
                                 * controller specific application ids by the
                                 * round robin method.
                                 */
   unsigned           uShmOfsFirstReadMsg;
                                /**<
                                 * The shared memory offset of the first CAPI
                                 * message position to be read from the read
                                 * buffer.
                                 */
   unsigned           uShmOfsLastReadMsg;
                                /**<
                                 * The shared memory offset of the last valid
                                 * CAPI message position to be read from the
                                 * read buffer.
                                 */
   unsigned           uShmOfsFirstWriteMsg;
                                /**<
                                 * The shared memory offset of the first CAPI
                                 * message position to be written to the write
                                 * buffer.
                                 */
   unsigned           uShmOfsLastWriteMsg;
                                /**<
                                 * The shared memory offset of the last valid
                                 * CAPI message position to be read from the
                                 * read buffer.
                                 */
   unsigned           uShmOfsCurrReadMsg;
                                /**<
                                 * The shared memory offset for the next
                                 * position to try to read a CAPI message from
                                 * (read buffer is organised as a ring buffer).
                                 */
   unsigned           uShmOfsCurrWriteMsg;
                                /**<
                                 * The shared memory offset for the next
                                 * position to try to write a CAPI message to
                                 * (write buffer is organised as a ring
                                 * buffer).
                                 */
   unsigned           uShmOfsPrimNcciFc;
                                /**<
                                 * Primary PCI only: The shared memory offset
                                 * for the NCCI flow control table. There are
                                 * nNumNcci bytes at this position, containing
                                 * either IX1A_SHM_PLNC_OK or
                                 * IX1A_SHM_PLNC_FULL.
                                 */

   /* fields for communication between user processes and the interrupt routine
    */
   int                fIntrActive;
                                /**<
                                 * Flag for a currently active interrupt
                                 * routine (0 - false, 1 - true).
                                 */
   int                fOpInProgress;
                                /**<
                                 * Flag for a running send operation, possibly
                                 * with someone waiting for a result (0 - false,
                                 * 1 - true).
                                 */
   int                fWaitingForRc;
                                /**<
                                 * - 1
                                 *    There is someone waiting for cvNotify.
                                 * - 0
                                 *    No one waiting.
                                 */
   unsigned           uRc;      /**<
                                 * Result of requests to the controller.
                                 */
   struct mtx         mtxAccess;/**< Mutex to access board data. */
   struct cv          cvNotify; /**<
                                 * Condition variable to wait for results in
                                 * uRc. To wait on it or for it to be signaled
                                 * the access mutex must be held.
                                 */
} Ix1aSc_t;



/**
 * Mapping from driver specific CAPI controller number to the port data.
 *
 * @note CAPI defines a maximum of 127 controller numbers from 1 to 127 (0 is
 *       not used).
 */
extern Ix1aPortData_t *e_apMapDrvCtlrToPortData [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_iIx1aLogLevel;
 
/** The macro for log output with driver unit number. */
#define DBG( level, iUnit, fmt, args... )                        \
   if ((level) <= e_iIx1aLogLevel)                               \
   {                                                             \
      printf (IX1A_DEVICE_CLASS_NAME "%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_iIx1aLogLevel)                         \
   {                                                       \
      printf (IX1A_DEVICE_CLASS_NAME ": %c %s: " fmt "\n", \
              LOG_CHARS [level], __FUNCTION__ , ## args);  \
   }





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





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





#endif /* __IX1A_GLOBAL_H */
