/*
 ******************************************************************************
 *  Copyright 1995 DeltaLink bv. All Rights Reserved.
 ******************************************************************************
 *
 * DeltaLink Mailbox Communication Interface
 *
 * File         :   mci.h
 *
 * Version      :   3.00
 *
 * Developed by :   Leon Westervoort.
 *
 * This file contains data- and prototypes of the DeltaLink Mailbox
 * Communication Interface.
 *
 */
#ifndef _MCI_DEFS_INCLUDED /* { */
#define _MCI_DEFS_INCLUDED 1

#ifndef HPUX
/*#pragma pack(1)*/
#else
#pragma HP_ALIGN HPUX_WORD PUSH
#endif

/* Macro to compare two tags */

#define  MCI_CMPTAG( t1, t2) ( ! ( ((t1)->t_type == (t2)->t_type) && ((t1)->t_data == (t2)->t_data) ) )

/* define the MCI version */

#define   MCI_VERSION     0x03

/* define direction of data */

#define MCI_LOW_2_HIGH  0           /* LOW to HIGH addressing */
#define MCI_HIGH_2_LOW  1           /* HIGH to LOW addressing */

/* set the direction of the host */

#ifdef HOST_LOW_2_HIGH
#define HOST_DIRECTION MCI_LOW_2_HIGH
#else
#define HOST_DIRECTION MCI_HIGH_2_LOW
#endif

/* define the type of dataset identifying */

#define   MCI_TAG         0
#define   MCI_INDEX       1

/* define the maximum number of messages that can reside in a mailbox */

#define   MCI_MAX_MSG_COUNT   25000


/* define the different type of MCI mailboxes */

#define MCI_QUERY_CMD    0x00            /* MCI info message */
#define MCI_QUERY_RSP    0x01            /* MCI info message feed back */
#define MCI_QUERY_ERROR  0x09            /* MCI info message feed back */

#define MCI_READ_REQ     0x02            /* read request */
#define MCI_READ_RSP     0x03            /* read feed back */
#define MCI_READ_ERROR   0x0B            /* read feed back */

#define MCI_WRITE_REQ    0x04            /* write request */
#define MCI_WRITE_RSP    0x05            /* write feed back */
#define MCI_WRITE_ERROR  0x0D            /* write feed back */

#define MCI_RCV_ACT      0x06            /* unsolicited receive active */
#define MCI_RCV_RDY      0x07            /* unsolicited receive ready */
#define MCI_RCV_ERROR    0x0F            /* unsolicited receive ready */

#define MCI_MAX_TYPES    0x05            /* Maximum of mci types */

#define MCI_NO_FNC       0x00            /* No MCI functions supported */
#define MCI_QUERY_FNC    0x01            /* Query functionality */
#define MCI_READ_FNC     0x02            /* Read functionality */
#define MCI_WRITE_FNC    0x04            /* Query functionality */
#define MCI_RCV_FNC       0x08            /* Unsolicited Receive functionality */
#define MCI_ALL_FNC       0xFF            /* All functionalities */

/* define normal data write or encode data write */

#define MCI_NORMAL_WRITE    0
#define MCI_ENCODED_WRITE   1

/* define the different boundary addressing methods */

#define MCI_BIT_BND    0            /* boundaries on bit basis ( 1 char 1 bit ) */
#define MCI_BYTE_BND   1            /* boundaries on character basis ( 1 char ) */
#define MCI_WORD_BND   2            /* boundaries on word basis      ( 2 char ) */
#define MCI_LONG_BND   4            /* boundaries on long basis      ( 4 char ) */
#define MCI_DBL_BND    8            /* boundaries on double basis    ( 8 char ) */

/* define the info requests */

#define MCI_I_ALIVE     1           /* the sender of this message is alive */
#define MCI_I_DEAD      1           /* the sender of this message is dead */

/* MCI error numbers */

#define MCI_BAD_TYPE        50          /* bad message type */
#define MCI_NOT_FOUND       51          /* message with dataset control tag not found in queue */
#define MCI_NO_QUERY        52          /* no messages available to query */
#define MCI_BAD_RCVMBX      53          /* bad receive mailbox tag */
#define MCI_BAD_SNDMBX      54          /* bad mailbox send tag */
#define MCI_BAD_CTRL        55          /* bad dataset control tag */
#define MCI_NOT_ADJUST      56          /* message cannot be adjusted */
#define MCI_CDE_SIZE        57          /* operation to big for variable */
#define MCI_UNKNOWN_BOUND   58          /* unknown boundary */
#define MCI_FNC_NOT_SUPPORT 59          /* function not supported */
#define MCI_WRONG_INDEX     60          /* no message for this index present */
#define MCI_DS_NOT_DEFINED  61          /* the received remote dataset was not defined on this system */
#define MCI_NOT_REGISTERED  62          /* the received dataset was not registered */
#define MCI_MSG_NOT_QUEUED  63          /* WARNING: the message is not queued */
#define MCI_MSG_REJECTED    64          /* the message is rejected due through problems in the remote MCI */
#define MCI_BIT_ADDRESSING  65          /* illegal method of addressing bits on bit boundary */
#define MCI_X_WRITE         66          /* element cannot be written */ 
#define MCI_BUFFER          67          /* invalid buffer specified */ 
#define MCI_BLOCK           68          /* block write function possible */
#define MCI_MAX_MESSAGE     69          /* max. number of messaes in mailbox */

/*
 * MCI system information 
 */
typedef struct _MCISYSTEM {

  id_t      task_id;                        /* FactoryLink task id of this MCI application */

  TAG       mbx;                            /* MCI mailbox of this MCI application */
  char      station_id;                     /* local station id number of this MCI user */

  ushort    functions;                      /* functions supported by the MCI application */

} MCISYSTEM;

/*
 * lay-out of the MCI Message 
 */
typedef struct _MCIMSG {

  MBXMSG  mbx;              /* FactoryLink Mailbox Message */

  TAG     snd_mbx;          /*  mailbox tag to send to */

  MSG     buffer;            /* buffer information for this MCI message */

  uint    i;                /* i element in queue */
  uchar   rel_addr;         /* relative or absolute addressing ( 0 = absolute) */

} MCIMSG;

/* 
 * general lay-out of a MCI dataset
 */
typedef struct _MCIDS {

  char    name[ MAX_TAG_NAME + MAX_DIM_LENGTH +1];  /* tag name of dataset control tag */

  ushort  start;                                    /* start address */
  ushort  len;                                      /* length of data depending on boundary */

  uchar    boundary;                                /* boundary addressing */
  uchar    bnd_dir;                                 /* direction of boundary data */
  uchar    bit_dir;                                 /* direction of bit data */
  uchar    bnd_offset;                              /* addressing offset of boundary data */
  uchar    bit_offset;                              /* addressing offset of bit data */

  uint    ds_index;                                 /* index into dataset control tag array */

  ushort  origination;                              /* ds came from queue or from trigger */

  MCIMSG  msg;                                      /* pointer to MCI message */

  void    *u_data;                                  /* pointer to additional user dataset information */
  int     (*u_fnc)( struct _MCIDS *);               /* pointer to user function which will be called with events */

} MCIDS;

/*
 * message type and number of commands definition defined in element
 * 'MM_TYPE'
 */
typedef struct _MCITYPE {

  u16 type:            4;    /* type of MCI message */

  u16 ident:           1;    /* use of MSG CTRL tag or address */
  u16 more:           1;    /* more data to come: yes or no  */
  u16 org_host_dir:    1;    /* set the originating host direction  */
  u16 reserved:       1;    /* reserved  */

  u16 station_id:      8;   /* station id of the sender of this message */

} MCITYPE; 

/*
 * Definition of the 'MM_USER1' element in the MBXMSG structure
 */
typedef struct _MM_USER1 {

  u16 src_station:    8;   /* station id of the source of this message */
  u16 sequence:        8;   /* job sequence number */

} MM_USER1;

/*
 * lay-out for info header which will be placed before the user data
 */
typedef struct _MCIHDR {

  struct {                      /* structure with info of dataset */

    u16   version:    4;          /* version of MCI used */
    u16   handling:    1;          /* encoded or normal write */

    u16   reserved0:  3;          /* reserved */

    u16   bnd_dir:    1;          /* direction of boundary data */
    u16   bit_dir:    1;          /* direction of bit data */

    u16   bnd_start:  1;          /* start of boundary data */
    u16   bit_start:  1;          /* start of bit data */

    u16   boundary:    4;          /* boundary of basic data element */

  } i;

  u16       len;                 /* length of data */
  u16       start;               /* start address of data  */
  u16       cde;                 /* conversion code */

} MCIHDR;

extern uint          _Mci_q_num_active;            /* total number of active messages in the queue */

/*
 * functions prototypes of the MCI library
 */

#define    MCI_FNC_RTYPE                  int (***)( void *, VAL )
#define    MCI_FNC_ATYPE                  int (**)( void *, VAL )
#define    MCI_FNC_TYPE                  int (*)( void *, VAL )

int           Mci_Init                  ( MCISYSTEM *);
int           Mci_Exit                  ( void);

int            Mci_Recv                   ( MCISYSTEM *, MCIDS *);
int            Mci_Send                   ( MCISYSTEM *, MCIDS *);
int           Mci_Send_Error            ( MCISYSTEM *, MCIDS *, u16);
void           Mci_Mirror                ( char *, ushort);
void           Mci_Cast                  ( MCIDS *, char);
void           Mci_Place_Data            ( MCIDS *, char);
int            Mci_Get_CDE_Size          ( ushort);
int           Mci_Buffer_Alloc          ( MSG *);

MCIDS *       Mci_Ds_Register           ( MCIDS *);
MCIDS *       Mci_Ds_R_Search           ( TAG *);
int           Mci_Ds_Prepare            ( MCIDS *, MSG *);
int           Mci_Ds_Query              ( MCIDS *);
int           Mci_Ds_Queried            ( MCIDS *);
int           Mci_Ds_Remove             ( MCISYSTEM *, MCIDS *);
int           Mci_Ds_Trigger            ( MCISYSTEM *, MCIDS *);
int           Mci_Ds_Adjust             ( MCIDS *);
int           Mci_Ds_Evaluate_Write     ( MCIDS *);
int           Mci_Equal_Data            ( MCIDS *);

int           Mci_Event_Retrieve        ( TAG **, void ***, u32 *, MCI_FNC_RTYPE);
int           Mci_Event_Mbx             ( void *, VAL);
int           Mci_Event_Ds              ( void *, VAL);
int           Mci_Event_Query_Cmd       ( MCIDS *);
int           Mci_Event_Query_Rsp       ( MCIDS *);
int           Mci_Event_Check           ( void);

int           Mci_Q_Init                ( MCISYSTEM * );
int           Mci_Q_Num                 ( MCISYSTEM *, uint *);
int           Mci_Q_Query               ( MCISYSTEM *, MCIDS *);
int           Mci_Q_Ds_Num_Srch         ( MCISYSTEM *, MCIDS *, uint);
#define       Mci_Q_Ds_Srch( s, d)         Mci_Q_Ds_Num_Srch( (s), (d), _Mci_q_num_active)
int           Mci_Q_Msg_Remove          ( MCISYSTEM *, MCIDS *);
int           Mci_Q_Num_Mbx             ( MCISYSTEM *, TAG, uint*);

/* function which operates on the MCIHDR structure */

#define Mci_Get_Version( m)           ( ((MCIHDR *)(m)->msg.mbx.mm_msg.m_ptr)->i.version)
#define Mci_Set_Version( m, v)        ( ((MCIHDR *)(m)->msg.mbx.mm_msg.m_ptr)->i.version = (v))

#define Mci_Get_Handling( m)          ( ((MCIHDR *)(m)->msg.mbx.mm_msg.m_ptr)->i.handling)
#define Mci_Set_Handling( m, v)       ( ((MCIHDR *)(m)->msg.mbx.mm_msg.m_ptr)->i.handling = (v))

#define Mci_Set_Bnd_Dir( m, v)        ( (( MCIHDR *)((m)->msg.mbx.mm_msg.m_ptr))->i.bnd_dir = (v))
#define Mci_Get_Bnd_Dir( m)           ( ( uchar)(( MCIHDR *)((m)->msg.mbx.mm_msg.m_ptr))->i.bnd_dir)

#define Mci_Set_Bit_Dir( m, v)        ( (( MCIHDR *)((m)->msg.mbx.mm_msg.m_ptr))->i.bit_dir = (v))
#define Mci_Get_Bit_Dir( m)           ( ( uchar)(( MCIHDR *)((m)->msg.mbx.mm_msg.m_ptr))->i.bit_dir)

#define Mci_Set_Bnd_Offset( m, v)     ( (( MCIHDR *)((m)->msg.mbx.mm_msg.m_ptr))->i.bnd_start = (v))
#define Mci_Get_Bnd_Offset( m)        ( ( uchar)(( MCIHDR *)((m)->msg.mbx.mm_msg.m_ptr))->i.bnd_start)

#define Mci_Set_Bit_Offset( m, v)     ( (( MCIHDR *)((m)->msg.mbx.mm_msg.m_ptr))->i.bit_start = (v))
#define Mci_Get_Bit_Offset( m)        ( ( uchar)(( MCIHDR *)((m)->msg.mbx.mm_msg.m_ptr))->i.bit_start)

#define Mci_Set_Boundary( m, v)       ( (( MCIHDR *)((m)->msg.mbx.mm_msg.m_ptr))->i.boundary = (v))
#define Mci_Get_Boundary( m)          ( ( uchar)(( MCIHDR *)((m)->msg.mbx.mm_msg.m_ptr))->i.boundary)

#define Mci_Set_Start( m, v)          ( ((MCIHDR *)(m)->msg.mbx.mm_msg.m_ptr)->start = (v))
#define Mci_Get_Start( m)             ( ((MCIHDR *)(m)->msg.mbx.mm_msg.m_ptr)->start )

#define Mci_Set_Len( m, v)            ( ((MCIHDR *)(m)->msg.mbx.mm_msg.m_ptr)->len = (v))
#define Mci_Get_Len( m)               ( ((MCIHDR *)(m)->msg.mbx.mm_msg.m_ptr)->len )

#define Mci_Set_CDE( m, v)            ( ((MCIHDR *)(m)->msg.mbx.mm_msg.m_ptr)->cde = (v))
#define Mci_Get_CDE( m)               ( ((MCIHDR *)(m)->msg.mbx.mm_msg.m_ptr)->cde )


/* prototypes which opreate on the MCI_SYSTEM structure */

#define Mci_Sys_Get_Task_Id( s)       ( (s)->task_id)
#define Mci_Sys_Set_Task_Id( s, v)    ( (s)->task_id = (v))

#define Mci_Sys_Get_Station_Id( s)    ( (s)->station_id)
#define Mci_Sys_Set_Station_Id( s, v) ( (s)->station_id = (v))

#define Mci_Sys_Get_Mbx( s)           ( (s)->mbx)
#define Mci_Sys_Set_Mbx( s, v)        ( memcpy( &(s)->mbx, &(v), sizeof( TAG)) )

#define Mci_Sys_Get_Functions( s)     ( (s)->functions)
#define Mci_Sys_Set_Functions( s, v)  ( (s)->functions |= (v))


/* prototypes which opreate on the MCIMSG structure */

#define Mci_Get_Type( m)              ( (( MCITYPE *)&(m)->msg.mbx.mm_type)->type)
#define Mci_Set_Type( m, v)           ( (( MCITYPE *)&(m)->msg.mbx.mm_type)->type = ( u16)(v))

#define Mci_Get_Org_Host_Dir( m)      ( (( MCITYPE *)&(m)->msg.mbx.mm_type)->org_host_dir)
#define Mci_Set_Org_Host_Dir( m, v)   ( (( MCITYPE *)&(m)->msg.mbx.mm_type)->org_host_dir = (v))

#define Mci_Get_Station_Id( m)         ( ( char)(( MCITYPE *)&(m)->msg.mbx.mm_type)->station_id)
#define Mci_Set_Station_Id( m, v)      ( (( MCITYPE *)&(m)->msg.mbx.mm_type)->station_id = ( char)(v))

#define Mci_Get_Job_Sequence( m)      ( (( MM_USER1 *)&(m)->msg.mbx.mm_user1)->sequence )
#define Mci_Set_Job_Sequence( m, v)   ( (( MM_USER1 *)&(m)->msg.mbx.mm_user1)->sequence = ( u8)(v) )

#define Mci_Get_Src_Station( m)       ( (( MM_USER1 *)&(m)->msg.mbx.mm_user1)->src_station )
#define Mci_Set_Src_Station( m, v)    ( (( MM_USER1 *)&(m)->msg.mbx.mm_user1)->src_station = ( u8)(v) )

#define Mci_Get_Ds_Ctrl( m)           ( ( TAG *)&((m)->msg.mbx.mm_user2) )
#define Mci_Set_Ds_Ctrl( m, v)        ( memcpy( ( char *)&(m)->msg.mbx.mm_user2, ( char *)&(v), sizeof( TAG)))

#define Mci_Get_R_Buffer( m)           ( &(m)->msg.buffer)
#define Mci_Set_R_Buffer( m, v)       ( memcpy( &(m)->msg.buffer, (v), sizeof( MSG)) )

#define Mci_Get_T_Buffer( m)           ( &(m)->msg.mbx.mm_msg)
#define Mci_Set_T_Buffer( m, v)       ( memcpy( &(m)->msg.mbx.mm_msg, (v), sizeof( MSG)) )

#define Mci_Get_U_Buffer( m)          ( ( char *)(m)->msg.mbx.mm_msg.m_ptr + sizeof( MCIHDR))
#define Mci_Reset_Buffer( m)          ( memset( ( char *)&((m)->msg.mbx.mm_msg), 0x00, sizeof( MSG)) )

#define Mci_Get_Snd_Mbx( m)           ( (m)->msg.snd_mbx )
#define Mci_Set_Snd_Mbx( m, v)        ( memcpy( &(m)->msg.snd_mbx, ( char *)&(v), sizeof( TAG)))

#define Mci_Get_Index( m)             ( (m)->msg.i )
#define Mci_Set_Index( m, v)          ( (m)->msg.i = (v))

#define Mci_Get_Active( )             ( _Mci_q_num_active ) 
#define Mci_Set_Active( v)            ( _Mci_q_num_active = 0) 

/* prototypes which operates on the MCIDS structure */

#define Mci_Get_Name( m)              ( (m)->name)
#define Mci_Set_Name( m, v)           ( strcpy( (m)->name, (v)) )

#define Mci_Get_Udata_Ptr( m)          ( (m)->u_data)
#define Mci_Set_Udata_Ptr( m, v)       ( (m)->u_data = (v) )

#define Mci_Get_Ufnc_Ptr( m)          ( (m)->u_fnc)
#define Mci_Set_Ufnc_Ptr( m, v)       ( (m)->u_fnc = (v) )

#ifndef HPUX
/*#pragma pack()*/
#else
#pragma HP_ALIGN POP
#endif

#endif /* _MCI_DEFS_INCLUDED */
