/****************************************************************************/
/* Copyright 1992 to 1995 MBARI                                             */
/****************************************************************************/
/* Summary  : Virtual Serial Port Interface for VxWorks                     */
/* Filename : vspDm.c                                                       */
/* Author   : Douglas Au                                                    */
/* Project  : New ROV                                                       */
/* Version  : Version 1.0                                                   */
/* Created  : 08/10/94                                                      */
/* Modified : 01/31/95                                                      */
/* Archived :                                                               */
/****************************************************************************/
/* Modification History:                                                    */
/* Initial revision
 *
 */
/****************************************************************************/
#include <vxWorks.h>                /* vxWorks system declarations          */
#include <semLib.h>                 /* vxWorks semaphore functions          */
#include <rngLib.h>
#include <taskLib.h>                /* vxWorks task library functions       */
#include <wdLib.h>                  /* vxWorks watch dog timer functions    */
#include <systime.h>                /* vxWorks time and date functions      */
#include <msgQLib.h>                /* vxWorks Message Queue Library        */

#include <mbariTypes.h>             /* MBARI style guide type declarations  */
#include <mbariConst.h>             /* Miscellaneous MBARI constants        */

#include <sio32.h>                  /* SIO32 hardware and driver information*/
#include <sio32Server.h>            /* Sio32 server communication services  */
#include <sio32Client.h>            /* Sio32 client communication services  */
#include <powerTypes.h>             /* Power management Data Types          */
#include <powerDM.h>                /* Power/Switching Data Manager Items   */

#include <datamgr.h>                /* Data Manager declarations            */
#include <dm_errno.h>               /* Data Manager error declarations      */

#define Boolean MBool               /* Map microcontroller Boolean to MBool */

#include "microcmd.h"               /* Microcontroller commands             */
#include "ibc_card.h"               /* IBC Card Types                       */
#include "ibc_cmd.h"                /* IBC Serial Commands                  */
#include "filter.h"                 /* General Filter Routines              */

#include "microDm.h"                /* Micro Data Manager Items & Functions */
#include "switch.h"                 /* IBC Function Libarary Definitions    */
#include "ibc.h"                    /* IBC Communication Interface Functions*/
#include "vspDm.h"                  /* Defines & Functions for hpsDm.c      */
#include "vspCmd.h"

/*****************************************************************************/
/* Function    : createIbcVspDmItems                                         */
/* Purpose     : Initialize Data Manager Item Handles for Virtual Serial Port */
/* Inputs      : Pointer to structure containing IBC VSP Data Manager Handles*/
/*               and IBC Data Concentrator Name                              */
/* Outputs     : None, but Data Manager Items change                         */
/*****************************************************************************/
    STATUS
createIbcVspDmItems( ibcVspDmItems *vspDmItems, const char* ibcDmPrefix,
                    const char* ibcDataCon, Int16 quadSerBoardNum)
{
    Int32   item;                   /* Counter for DM Item Initialization   */
    Errno   status;                 /* Result of dm_create function call    */
    const   char   itemPrefix[MAX_NMLEN];/* Data Manager Item Prefix Name   */
    char dmItemName[DM_ITEM_NAME_LEN];         /* Complete item name string */

    struct                          /* Data Manager Item Table for table    */
    {                               /* driven item initialization           */
        DM_Item *dmItem;            /* pointer to actual dm item handle     */
        char    *errorMsg;          /* Message to display of dmCreate fails */
        char    *name;              /* Data Manager Item Name               */
        DM_Type type;               /* Data Manager Item Type               */
        DM_Num  len;                /* Data Manager Item Element Count      */
    } vspDmInit[] =

      { { &vspDmItems->vspBaud,         "VSP Baud Rate",
              VSP_BAUD_DM,                 DM_NAT16, 1 },

        { &vspDmItems->vspData,         "VSP Data Bits",
              VSP_DATA_BITS_DM,            DM_NAT16, 1 },

        { &vspDmItems->vspStop,         "VSP Stop Bits",
              VSP_STOP_BITS_DM,            DM_NAT16, 1 },

        { &vspDmItems->vspPar,          "VSP Parity",
              VSP_PARITY_DM,               DM_NAT16, 1 },

        { &vspDmItems->vspMsgReceived,  "VSP Message Received Flag",
              VSP_MSG_RECEIVED_DM,         DM_EMPTY, 0 },

        { &vspDmItems->vspHandshake,    "VSP Handshake Mode",
              VSP_HANDSHAKE_DM,            DM_MBOOL, 1 },

        { &vspDmItems->vspProtocol,     "VSP Protocol",
              VSP_PROTOCOL_DM,             DM_NAT16, 1 },

        { &vspDmItems->vspBreak,        "VSP Break Character Received Flag",
              VSP_BREAK_DM,                DM_NAT16, 1 },

        { &vspDmItems->vspError,        "VSP Error Flag",
              VSP_ERROR_DM,                DM_NAT16, 0 },

        { NO_ITEM, NULL, NULL, DM_ENDT, 0 } };

    sprintf(itemPrefix, "%sVSP%d.", ibcDmPrefix, quadSerBoardNum);

                                    /* Clear list of Data Manager Item handles*/
    bzero(vspDmItems, sizeof(ibcVspDmItems));

                                   /* Initialize Data Manager Items from table*/
    for (item = 0; vspDmInit[item].dmItem != NO_ITEM; item++)
    {
        if ((*vspDmInit[item].dmItem =
             initMicroDmItem(itemPrefix, vspDmInit[item].name,
             vspDmInit[item].type, vspDmInit[item].len)) == ERROR)

        {                           /* Error occurred so print message & exit */
            logMsg("%s: Error Initializing %s DM Item\n",
                ibcDataCon, vspDmInit[item].errorMsg);
            return(ERROR);
        } /* if */
    } /* for */


                                    /* Build name from name prefix & name     */
    sprintf(dmItemName, "%sVSP%d.%s", ibcDmPrefix, quadSerBoardNum,
               VSP_MSGOUT_DM );
                                    /* Initilize VSP MsgOut DM Item           */
    status = dm_create(dmItemName, 1, &vspDmItems->vspMsgOut,
                       DM_NAT16, 1, DM_CHAR, MAX_PACKET_LEN, DM_ENDT);

                                    /* Treat item exists the same as success  */
    if ( (status != SUCCESS) && (status != EDM_NAME_EXISTS) )
    {                               /* Error occurred so print message & exit */
        logMsg("%s: Error Initializing %s DM Item\n",
                ibcDataCon, vspDmInit[item].errorMsg);
        return(ERROR);
    } /* if */

                                       /* Build name from name prefix & name  */
    sprintf(dmItemName, "%sVSP%d.%s", ibcDmPrefix, quadSerBoardNum,
                 VSP_MSGIN_DM );
                                       /* Initilize VSP MsgIn DM Item         */
    status = dm_create(dmItemName, 1, &vspDmItems->vspMsgIn,
                       DM_NAT16, 1, DM_CHAR, MAX_PACKET_LEN, DM_ENDT);

                                    /* Treat item exists the same as success  */
    if ( (status != SUCCESS) && (status != EDM_NAME_EXISTS) )
    {                               /* Error occurred so print message & exit */
        logMsg("%s: Error Initializing %s DM Item\n",
                ibcDataCon, vspDmInit[item].errorMsg);
        return(ERROR);
    } /* if */
    return(OK);                     /* All IBC CPU Data Mgr items initialized */
} /* createIbcVspDmItems() */

    Void
initIbcVspProvider( ibcVspDmItems* vspItems )
{
    dm_start_provider(vspItems->vspMsgIn, DM_STATIC);
    dm_start_provider(vspItems->vspMsgReceived, DM_STATIC);
    dm_start_provider(vspItems->vspError, DM_STATIC);
} /* initIbcVspProvider() */

    DWord
initIbcVspConsumer( ibcVspDmItems* vspItems, vspUpdateBits *vspBits,
    SEM_ID updateSem )
{
    DWord vspGroup;

    vspGroup = dm_create_group();    /* Create Data Manager Group for Vsp  */

    dm_start_consumer(vspItems->vspBaud, DM_STATIC, updateSem);
    dm_start_consumer(vspItems->vspData, DM_STATIC, updateSem);
    dm_start_consumer(vspItems->vspStop, DM_STATIC, updateSem);
    dm_start_consumer(vspItems->vspPar,  DM_STATIC, updateSem);
    dm_start_consumer(vspItems->vspMsgOut, DM_STATIC, updateSem);
    dm_start_consumer(vspItems->vspHandshake, DM_STATIC, updateSem);
    dm_start_consumer(vspItems->vspProtocol, DM_STATIC, updateSem);
    dm_start_consumer(vspItems->vspBreak, DM_STATIC, updateSem);

    dm_group_add_item(vspGroup, vspItems->vspBaud,
         &vspBits->baudBit );

    dm_group_add_item(vspGroup, vspItems->vspData,
         &vspBits->dataBit );

    dm_group_add_item(vspGroup, vspItems->vspStop,
         &vspBits->stopBit );

    dm_group_add_item(vspGroup, vspItems->vspPar,
         &vspBits->parityBit );

    dm_group_add_item(vspGroup, vspItems->vspMsgOut,
         &vspBits->msgOutBit );

    dm_group_add_item(vspGroup, vspItems->vspHandshake,
         &vspBits->handshakeBit );

    dm_group_add_item(vspGroup, vspItems->vspProtocol,
         &vspBits->protocolBit );

    dm_group_add_item(vspGroup, vspItems->vspBreak,
         &vspBits->breakBit );

    return (vspGroup);
} /* initIbcVspConsumer() */


/*****************************************************************************/
/* Function    : updateIbcVspDmItems                                         */
/* Purpose     : Reads Vsp parameters from IBC & update Data Manager         */
/* Inputs      : Array of Data Manager Item handles & serial chan structure  */
/* Outputs     : None, but Data Manager Items change                         */
/*****************************************************************************/
    Void
updateIbcVspDmItems( sio32Chan* sio32DataChan, Word boardAddr, Word chan,
    ibcVspDmItems *vspItems, const char* ibcDataCon )
{
    Nat16 baud, data, stop, par;
    Boolean handshake;
    Int16 proto;

    if (IBC_VSP_Open (sio32DataChan, boardAddr, chan) == ERROR)
       logMsg("%s:Error Openning VSP\n", ibcDataCon);

                         /* Read VSP parameters from dmgr*/
        dm_read( vspItems->vspBaud, (char *) &baud,
            sizeof(baud), (DM_Time *) NULL);

        dm_read( vspItems->vspData, (char *) &data,
            sizeof(data), (DM_Time *) NULL);

        dm_read( vspItems->vspStop, (char *) &stop,
            sizeof(stop), (DM_Time *) NULL);

        dm_read( vspItems->vspPar, (char *) &par,
            sizeof(par), (DM_Time *) NULL);

        dm_read( vspItems->vspHandshake, (char *) &handshake,
            sizeof(handshake), (DM_Time *) NULL);

        dm_read( vspItems->vspProtocol, (char *) &proto,
            sizeof(proto), (DM_Time *) NULL);
                                /*Check for valid data */
   if (baud | data | stop == 0)

   {                            /* if 0 then set parms per IBC hardware  */
       if (IBC_VSP_GetLineParm( sio32DataChan, boardAddr, chan, &baud, &data,
              &stop, &par, &handshake, &proto) == ERROR)
             logMsg("%s:Error Reading VSP Line Parameteres\n", ibcDataCon);

                                /*VSP initial values*/
       urgentWriteDmItem( vspItems->vspBaud, &baud, sizeof(baud));

       urgentWriteDmItem( vspItems->vspData, &data, sizeof(data));

       urgentWriteDmItem( vspItems->vspStop, &stop, sizeof(stop));

       urgentWriteDmItem( vspItems->vspPar, &par, sizeof(par));

       urgentWriteDmItem( vspItems->vspHandshake, &handshake,  sizeof(handshake));

       urgentWriteDmItem( vspItems->vspProtocol, &proto,  sizeof(proto));
    }
    else                        /* else set parms per Data Manager values */

       if (IBC_VSP_SetLineParm( sio32DataChan, boardAddr, chan, baud,
                                     data, stop, par, handshake, proto )== ERROR)
         logMsg("Error Setting up VSP\n");

} /* updateIbcVspDmItems() */


     Void
ibcVspUpdateCheck( sio32Chan* sio32DataChan, Word boardAddr, Word chan,
     ibcVspDmItems* vspItems, vspUpdateBits *vspBits, DM_Group vspGroup )
{
    DWord   vspGroupBits;           /* Holds dm_group_changes bit vector     */
    Int16   baud;
    Nat16   data, stop, par, numOfBytes;
    Boolean handshake;
    Int16   proto;
    Nat16   mode;

    messageStruct msgOut;

                           /* Ask Data Manager If VSP items changed */
    if ( (vspGroupBits = dm_get_group_changes(vspGroup)) == (DWord) 0)
        return;
                          /* Check for Break Character              */
    if  (vspGroupBits & vspBits->breakBit)
    {
       dm_read( vspItems->vspBreak, (char *) &mode,
            sizeof(mode), (DM_Time *) NULL);

       if( IBC_VSP_SendBreak( sio32DataChan, boardAddr, chan, mode) == ERROR)
             logMsg("%s:Error Sending VSP Break\n", chan);
    }
                         /* Check for Msgout                        */
    if  (vspGroupBits & vspBits->msgOutBit)
    {
       dm_read( vspItems->vspMsgOut, (char *) &msgOut,
            sizeof(msgOut), (DM_Time *) NULL);

       if( IBC_VSP_Write( sio32DataChan, boardAddr, chan, msgOut.buffer,
           msgOut.len)==ERROR)

         logMsg("%s:Error writing VSP\n", chan);
    }

                          /* VSP Parameters                           */
    if ( (vspGroupBits & vspBits->baudBit) ||
         (vspGroupBits & vspBits->dataBit)  ||
         (vspGroupBits & vspBits->stopBit) ||
         (vspGroupBits & vspBits->parityBit) ||
         (vspGroupBits & vspBits->handshakeBit) ||
         (vspGroupBits & vspBits->protocolBit) )

    {                            /* Read VSP parameters from dmgr*/
        dm_read( vspItems->vspBaud, (char *) &baud,
            sizeof(baud), (DM_Time *) NULL);

        dm_read( vspItems->vspData, (char *) &data,
            sizeof(data), (DM_Time *) NULL);

        dm_read( vspItems->vspStop, (char *) &stop,
            sizeof(stop), (DM_Time *) NULL);

        dm_read( vspItems->vspPar, (char *) &par,
            sizeof(par), (DM_Time *) NULL);

        dm_read( vspItems->vspHandshake, (char *) &handshake,
            sizeof(handshake), (DM_Time *) NULL);

        dm_read( vspItems->vspProtocol, (char *) &proto,
            sizeof(proto), (DM_Time *) NULL);

      if (IBC_VSP_SetLineParm( sio32DataChan, boardAddr, chan, baud, data, stop,
                              par, handshake, proto )== ERROR)
         logMsg("Error Setting up VSP\n");

    } /* if */
} /* ibcVspUpdateCheck() */


    MBool
processIbcVspSRQ( Word srqRequest, Byte* buffer, Word quadSerBoardAddr,
    Word chan, ibcVspDmItems *vsp )
{
    Word boardAddr;                 /* IBC Board Address                      */
    Word status;                    /* IBC Alarm Status Word                  */
    ibcAlarm alarmStatus;           /* IBC Alarm Status                       */
    messageStruct msgIn;
    Int16 len;

    switch (srqRequest)
    {
        case QUAD_SER_BYTES_IN_BUF_SRQ:
            wordsFromBuf(buffer, 4, &srqRequest, &boardAddr, &chan, &len );

            if (boardAddr != quadSerBoardAddr)
                return(FALSE);          /* Address missmatch                 */
                                        /* Range Check Length                */
            len =  min(len, MAX_PACKET_LEN);

            bcopy(buffer + (sizeof(Word) * 4), msgIn.buffer, len);

            if (len < MAX_PACKET_LEN)
                msgIn.buffer[len] = '\0';
            msgIn.len = len;

            writeDmItem(vsp->vspMsgIn, &msgIn, sizeof(msgIn));

                           /* Post Trip Event Data Manager Item */
            writeDmItem(vsp->vspMsgReceived, NULL, 0);
                                        /* Set msgReceived */
            break;

        case QUAD_SER_RECV_ERROR_SRQ:

            writeDmItem(vsp->vspError, NULL, 0);
            break;

        default:
            return(FALSE);              /* SRQ Request not recognized        */

    } /* switch */

    return(TRUE);                       /* SRQ Request recognized            */
} /* processIbcVspSRQ() */



















