/****************************************************************************/
/* Copyright 1992 to 1996 MBARI                                             */
/****************************************************************************/
/* Summary  : IBC LPS Board Data Manager Functions for VxWorks              */
/* Filename : lpsDm.c                                                       */
/* Author   : Andrew Pearce                                                 */
/* Project  : Tiburon ROV                                                   */
/* Version  : Version 1.0                                                   */
/* Created  : 06/08/93                                                      */
/* Modified : 08/12/96                                                      */
/* Archived :                                                               */
/****************************************************************************/
/* Modification History:                                                    */
/* $Header: lpsDm.c,v 1.1 93/07/01 14:34:31 pean Exp $
 * $Log:        lpsDm.c,v $
 * Revision 1.1  93/07/01  14:34:31  14:34:31  pean (Andrew Pearce)
 * Initial revision
 *
 *
 */
/****************************************************************************/

#include <vxWorks.h>                /* vxWorks system declarations          */
#include <semLib.h>                 /* vxWorks semaphore 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      */

#include "microcmd.h"               /* Microcontroller commands             */
#include "timer.h"                  /* Microcontroler Timer Definitions     */
#include "ibc_card.h"               /* IBC Card Types                       */
#include "ibc_cmd.h"                /* IBC Serial Commands                  */
#include "filter.h"                 /* General Filter Routines              */
#include "low_pwr.h"                /* LPS Board Definitions                */

#include "microDm.h"                /* Micro Data Manager Items & Functions */
#include "switch.h"                 /* IBC Function Libarary Definitions    */
#include "lpsDm.h"                  /* Defines & Functions for lpsDm.c      */

/*****************************************************************************/
/* Function    : createIbcLpsDmItems                                         */
/* Purpose     : Initialize Data Manager Item Handles for IBC LPS Board      */
/* Inputs      : Pointer to structure containing IBC LPS Data Manager Handes */
/*               and IBC Data Concentrator Name                              */
/* Outputs     : None, but Data Manager Items change                         */
/*****************************************************************************/
    STATUS
createIbcLpsDmItems( ibcLpsDmItems *lpsDmItems, const char* ibcDmPrefix,
    const char* ibcDataCon, Int16 lpsBoardNum )
{
    Int32   item;                   /* Counter for DM Item Initialization   */
    Errno   status;                 /* Result of dm_create function call    */
    const   char   itemPrefix[DM_ITEM_NAME_LEN];
                                    /* Data Manager Item Prefix Name        */

    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      */
    } lpsDmInit[] =

      { { &lpsDmItems->sw0Current,     "LPS Switch 0 Current",
                LPS_SW0_CURRENT_DM,              DM_INT16, 1 },

        { &lpsDmItems->sw1Current,    "LPS Switch 1 Current",
                LPS_SW1_CURRENT_DM,              DM_INT16, 1 },

        { &lpsDmItems->sw2Current,    "LPS Switch 2 Current",
                LPS_SW2_CURRENT_DM,              DM_INT16, 1 },

        { &lpsDmItems->sw3Current,    "LPS Switch 3 Current",
                LPS_SW3_CURRENT_DM,              DM_INT16, 1 },

        { &lpsDmItems->sw0CurrentWarnThresh,
              "LPS Switch 0 Current Warning Thresh",
               LPS_SW0_CURRENT_WARN_THRESH_DM,   DM_INT16, 1 },

        { &lpsDmItems->sw0CurrentAlarmThresh,
              "LPS Switch 0 Current Alarm Thresh",
              LPS_SW0_CURRENT_ALARM_THRESH_DM,   DM_INT16, 1 },

        { &lpsDmItems->sw1CurrentWarnThresh,
               "LPS Switch 1 Current Warning Thresh",
               LPS_SW1_CURRENT_WARN_THRESH_DM,   DM_INT16, 1 },

        { &lpsDmItems->sw1CurrentAlarmThresh,
                "LPS Switch 1 Current Alarm Thresh",
                LPS_SW1_CURRENT_ALARM_THRESH_DM, DM_INT16, 1 },

        { &lpsDmItems->sw2CurrentWarnThresh,
                "LPS Switch 2 Current Warning Thresh",
                LPS_SW2_CURRENT_WARN_THRESH_DM,  DM_INT16, 1 },

        { &lpsDmItems->sw2CurrentAlarmThresh,
                "LPS Switch 2 Current Alarm Thresh",
                LPS_SW2_CURRENT_ALARM_THRESH_DM, DM_INT16, 1 },

        { &lpsDmItems->sw3CurrentWarnThresh,
               "LPS Switch 3 Current Warning Thresh",
                LPS_SW3_CURRENT_WARN_THRESH_DM,  DM_INT16, 1 },

        { &lpsDmItems->sw3CurrentAlarmThresh,
                "LPS Switch 3 Current Alarm Thresh",
                LPS_SW3_CURRENT_ALARM_THRESH_DM, DM_INT16, 1 },

        { &lpsDmItems->vicorVoltageWarnThresh,
               "LPS Vicor Voltage Warning Thresh",
                LPS_VICOR_VOLTAGE_WARN_THRESH_DM, DM_NAT16, 1 },

        { &lpsDmItems->vicorVoltageAlarmThresh,
                "LPS Vicor Voltage Alarm Thresh",
                LPS_VICOR_VOLTAGE_ALARM_THRESH_DM,DM_NAT16, 1 },

        { &lpsDmItems->vicorVoltage,   "LPS Vicor Voltage",
                LPS_VICOR_VOLTAGE_DM,            DM_NAT16, 1 },

        { &lpsDmItems->vicorTemp,      "LPS Vicor Temperature",
                LPS_VICOR_TEMP_DM,               DM_INT16, 1 },

        { &lpsDmItems->vicorTempWarnThresh,
               "LPS Vicor Temperature Warning Thresh",
                LPS_VICOR_TEMP_WARN_THRESH_DM,   DM_INT16, 1 },

        { &lpsDmItems->vicorTempAlarmThresh,
                "LPS Vicor Temperature Alarm Thresh",
                LPS_VICOR_TEMP_ALARM_THRESH_DM,  DM_INT16, 1 },

        { &lpsDmItems->switchTemp, "LPS Switch Temperature",
                LPS_SWITCH_TEMP_DM,              DM_INT16, 1 },

        { &lpsDmItems->switchTempWarnThresh,
               "LPS Switch Temperature Warning Thresh",
                LPS_SWITCH_TEMP_WARN_THRESH_DM,  DM_INT16, 1 },

        { &lpsDmItems->switchTempAlarmThresh,
                "LPS Switch Temperature Alarm Thresh",
                LPS_SWITCH_TEMP_ALARM_THRESH_DM, DM_INT16, 1 },

        { &lpsDmItems->sw0CurrentAlarm,     "LPS Switch 0 Current Alarm",
                LPS_SW0_CURRENT_ALARM_DM,        DM_ENUM, 1 },

        { &lpsDmItems->sw1CurrentAlarm,     "LPS Switch 1 Current Alarm",
                LPS_SW1_CURRENT_ALARM_DM,        DM_ENUM, 1 },

        { &lpsDmItems->sw2CurrentAlarm,     "LPS Switch 2 Current Alarm",
                LPS_SW2_CURRENT_ALARM_DM,        DM_ENUM, 1 },

        { &lpsDmItems->sw3CurrentAlarm,     "LPS Switch 3 Current Alarm",
                LPS_SW3_CURRENT_ALARM_DM,        DM_ENUM, 1 },

        { &lpsDmItems->vicorVoltageAlarm,   "LPS Vicor Voltage Alarm",
                LPS_VICOR_VOLTAGE_ALARM_DM,      DM_ENUM, 1 },

        { &lpsDmItems->vicorTempAlarm,      "LPS Vicor Temperature Alarm",
                LPS_VICOR_TEMP_ALARM_DM,         DM_ENUM, 1 },

        { &lpsDmItems->switchTempAlarm,     "LPS Switch Temperature Alarm",
                LPS_SWITCH_TEMP_ALARM_DM,        DM_ENUM, 1 },

        { NO_ITEM, NULL, NULL, DM_ENDT, 0 } };

    sprintf(itemPrefix, "%sLPS%d.", ibcDmPrefix, lpsBoardNum);

                                    /* Clear list of Data Manager Item handles*/
    bzero(lpsDmItems, sizeof(ibcLpsDmItems));

                                   /* Initialize Data Manager Items from table*/
    for (item = 0; lpsDmInit[item].dmItem != NO_ITEM; item++)
    {
        if ((*lpsDmInit[item].dmItem =
             initMicroDmItem(itemPrefix, lpsDmInit[item].name,
             lpsDmInit[item].type, lpsDmInit[item].len)) == ERROR)

        {                           /* Error occurred so print message & exit */
            logMsg("%s: Error Initializing %s DM Item\n",
                ibcDataCon, lpsDmInit[item].errorMsg);
            return(ERROR);
        } /* if */
    } /* for */

    return(OK);                     /* All IBC CPU Data Mgr items initialized */
} /* createIbcLpsDmItems() */


    Void
initIbcLpsProvider( ibcLpsDmItems* lpsItems, Period period )
{
    dm_start_provider(lpsItems->sw0Current,   period);
    dm_start_provider(lpsItems->sw1Current,   period);
    dm_start_provider(lpsItems->sw2Current,   period);
    dm_start_provider(lpsItems->sw3Current,   period);

    dm_start_provider(lpsItems->vicorVoltage, period);
    dm_start_provider(lpsItems->vicorTemp,    period);
    dm_start_provider(lpsItems->switchTemp,   period);
} /* initIbcLpsProvider() */

    Void
initIbcLpsAlarmProvider( ibcLpsDmItems* lpsItems )
{
    dm_start_provider(lpsItems->sw0CurrentAlarm, DM_STATIC);
    dm_start_provider(lpsItems->sw1CurrentAlarm, DM_STATIC);
    dm_start_provider(lpsItems->sw2CurrentAlarm, DM_STATIC);
    dm_start_provider(lpsItems->sw3CurrentAlarm, DM_STATIC);

    dm_start_provider(lpsItems->vicorTempAlarm,    DM_STATIC);
    dm_start_provider(lpsItems->vicorVoltageAlarm, DM_STATIC);
    dm_start_provider(lpsItems->switchTempAlarm,   DM_STATIC);
} /* initIbcLpsAlarmProvider() */

    DWord
initIbcLpsConsumer( ibcLpsDmItems* lpsItems, lpsUpdateBits *lpsBits,
    SEM_ID updateSem )
{
    DWord lpsGroup;

    lpsGroup = dm_create_group();    /* Create Data Manager Group for LPS  */

    dm_start_consumer(lpsItems->sw0CurrentWarnThresh,  DM_STATIC, updateSem);
    dm_start_consumer(lpsItems->sw0CurrentAlarmThresh, DM_STATIC, updateSem);
    dm_start_consumer(lpsItems->sw1CurrentWarnThresh,  DM_STATIC, updateSem);
    dm_start_consumer(lpsItems->sw1CurrentAlarmThresh, DM_STATIC, updateSem);
    dm_start_consumer(lpsItems->sw2CurrentWarnThresh,  DM_STATIC, updateSem);
    dm_start_consumer(lpsItems->sw2CurrentAlarmThresh, DM_STATIC, updateSem);
    dm_start_consumer(lpsItems->sw3CurrentWarnThresh,  DM_STATIC, updateSem);
    dm_start_consumer(lpsItems->sw3CurrentAlarmThresh, DM_STATIC, updateSem);

    dm_start_consumer(lpsItems->vicorVoltageWarnThresh,   DM_STATIC, updateSem);
    dm_start_consumer(lpsItems->vicorVoltageAlarmThresh,  DM_STATIC, updateSem);

    dm_start_consumer(lpsItems->vicorTempWarnThresh,   DM_STATIC, updateSem);
    dm_start_consumer(lpsItems->vicorTempAlarmThresh,  DM_STATIC, updateSem);
    dm_start_consumer(lpsItems->switchTempWarnThresh,  DM_STATIC, updateSem);
    dm_start_consumer(lpsItems->switchTempAlarmThresh, DM_STATIC, updateSem);

    dm_group_add_item(lpsGroup, lpsItems->sw0CurrentWarnThresh,
         &lpsBits->sw0CurWarnBit );

    dm_group_add_item(lpsGroup, lpsItems->sw0CurrentAlarmThresh,
         &lpsBits->sw0CurAlarmBit );

    dm_group_add_item(lpsGroup, lpsItems->sw1CurrentWarnThresh,
         &lpsBits->sw1CurWarnBit );

    dm_group_add_item(lpsGroup, lpsItems->sw1CurrentAlarmThresh,
         &lpsBits->sw1CurAlarmBit );

    dm_group_add_item(lpsGroup, lpsItems->sw2CurrentWarnThresh,
         &lpsBits->sw2CurWarnBit );

    dm_group_add_item(lpsGroup, lpsItems->sw2CurrentAlarmThresh,
         &lpsBits->sw2CurAlarmBit );

    dm_group_add_item(lpsGroup, lpsItems->sw3CurrentWarnThresh,
         &lpsBits->sw3CurWarnBit );

    dm_group_add_item(lpsGroup, lpsItems->sw3CurrentAlarmThresh,
         &lpsBits->sw3CurAlarmBit );

    dm_group_add_item(lpsGroup, lpsItems->vicorVoltageWarnThresh,
         &lpsBits->vicorVoltageWarnBit );

    dm_group_add_item(lpsGroup, lpsItems->vicorVoltageAlarmThresh,
         &lpsBits->vicorVoltageAlarmBit );

    dm_group_add_item(lpsGroup, lpsItems->vicorTempWarnThresh,
         &lpsBits->vicorTempWarnBit );

    dm_group_add_item(lpsGroup, lpsItems->vicorTempAlarmThresh,
         &lpsBits->vicorTempAlarmBit );

    dm_group_add_item(lpsGroup, lpsItems->switchTempWarnThresh,
         &lpsBits->switchTempWarnBit );

    dm_group_add_item(lpsGroup, lpsItems->switchTempAlarmThresh,
         &lpsBits->switchTempAlarmBit );

    return (lpsGroup);
} /* initIbcLpsConsumer() */

    STATUS
ibcConnectLpsDmItems( ibcLpsDmItems *lps,   switchEntry *device,
    const char *dataConName,  const char *itemName,   Nat16 lpsChan,
    char *current,            char *currentAlarm,
    char *currentWarnThresh,  char *currentAlarmThresh )
{
    if (current != NULL)
    {                               /* Current Data Manager Items             */
        if ( (device->currentDm = initMicroDmItem(POWER_DM_PREFIX,
                  current, DM_INT16, 1)) == ERROR) return(ERROR);

                                    /* Current Warning Thresh Dm Item         */
        if ( (device->currentWarnThreshDm = initMicroDmItem(POWER_DM_PREFIX,
                  currentWarnThresh, DM_INT16, 1)) == ERROR) return(ERROR);

                                    /* Current Alarm Thresh Dm Item           */
        if ( (device->currentAlarmThreshDm = initMicroDmItem(POWER_DM_PREFIX,
                  currentAlarmThresh, DM_INT16, 1)) == ERROR) return(ERROR);

                                    /* Current Alarm Status Dm Item           */
        if ( (device->currentAlarmDm = initMicroDmItem(POWER_DM_PREFIX,
                  currentAlarm, DM_ENUM, 1)) == ERROR) return(ERROR);

        switch (lpsChan)
        {
          case 0:
            dm_connect(lps->sw0Current,             device->currentDm);
            dm_connect(lps->sw0CurrentAlarm,        device->currentAlarmDm);
            dm_connect(device->currentWarnThreshDm, lps->sw0CurrentWarnThresh);
            dm_connect(device->currentAlarmThreshDm,lps->sw0CurrentAlarmThresh);
            break;

          case 1:
            dm_connect(lps->sw1Current,             device->currentDm);
            dm_connect(lps->sw1CurrentAlarm,        device->currentAlarmDm);
            dm_connect(device->currentWarnThreshDm, lps->sw1CurrentWarnThresh);
            dm_connect(device->currentAlarmThreshDm,lps->sw1CurrentAlarmThresh);
            break;

          case 2:
            dm_connect(lps->sw2Current,             device->currentDm);
            dm_connect(lps->sw2CurrentAlarm,        device->currentAlarmDm);
            dm_connect(device->currentWarnThreshDm, lps->sw2CurrentWarnThresh);
            dm_connect(device->currentAlarmThreshDm,lps->sw2CurrentAlarmThresh);
            break;

          case 3:
            dm_connect(lps->sw3Current,             device->currentDm);
            dm_connect(lps->sw3CurrentAlarm,        device->currentAlarmDm);
            dm_connect(device->currentWarnThreshDm, lps->sw3CurrentWarnThresh);
            dm_connect(device->currentAlarmThreshDm,lps->sw3CurrentAlarmThresh);
            break;

        } /* select */
    } /* if */

    lps->deviceSwitch[lpsChan] = device;
                                    /* Save switchEntry ptr in lps struct so  */
                                    /* we can set switch state to POWER_ERROR */
                                    /* when a current alarn occurs            */

    return(OK);
} /* ibcConnectLpsItems() */

    STATUS
updateIbcLpsDm( sio32Chan *sio32DataChan, Word boardAddr, ibcLpsDmItems *lps )
{
    Int16 lpsCurrents[LPS_MAX_CHANS];
    Int16 vicorTemp, switchTemp;
    Nat16 lpsVoltage;

    if (IBC_LPS_GetCurrents( sio32DataChan, boardAddr, lpsCurrents) != OK)
        return (ERROR);

    if (IBC_LPS_GetTemperatures( sio32DataChan, boardAddr,
                &vicorTemp, &switchTemp ) != OK) return (ERROR);

    if (IBC_LPS_GetVoltage( sio32DataChan, boardAddr, &lpsVoltage ) != OK)
        return (ERROR);

                                    /* Write actual Currents to Data Manager */
    writeDmItem(lps->sw0Current, &lpsCurrents[0], sizeof(lpsCurrents[0]) );
    writeDmItem(lps->sw1Current, &lpsCurrents[1], sizeof(lpsCurrents[1]) );
    writeDmItem(lps->sw2Current, &lpsCurrents[2], sizeof(lpsCurrents[2]) );
    writeDmItem(lps->sw3Current, &lpsCurrents[3], sizeof(lpsCurrents[3]) );

    writeDmItem(lps->vicorTemp,  &vicorTemp,  sizeof(vicorTemp) );
    writeDmItem(lps->switchTemp, &switchTemp, sizeof(switchTemp) );

    return (writeDmItem(lps->vicorVoltage, &lpsVoltage, sizeof(lpsVoltage) ));
} /* updateIbcLpsDm() */

    STATUS
updateIbcLpsAlarmsDm( sio32Chan *sio32DataChan, Word boardAddr,
     ibcLpsDmItems *lps )
{
    ibcAlarm currentAlarms[LPS_MAX_CHANS];
    ibcAlarm vicorTempAlarm, switchTempAlarm, lpsVoltageAlarm;

    if (IBC_LPS_GetAlarmStatus( sio32DataChan, boardAddr, currentAlarms,
        &vicorTempAlarm, &switchTempAlarm, &lpsVoltageAlarm ) != OK)
        return (ERROR);

                                    /* Write alarm status to Data Manager */
    writeDmItem(lps->sw0CurrentAlarm,
                &currentAlarms[0], sizeof(currentAlarms[0]) );

    writeDmItem(lps->sw1CurrentAlarm,
                &currentAlarms[1], sizeof(currentAlarms[1]) );

    writeDmItem(lps->sw2CurrentAlarm,
                &currentAlarms[2], sizeof(currentAlarms[2]) );

    writeDmItem(lps->sw3CurrentAlarm,
                &currentAlarms[3], sizeof(currentAlarms[3]) );

    writeDmItem(lps->vicorTempAlarm,  &vicorTempAlarm, sizeof(vicorTempAlarm) );
    writeDmItem(lps->switchTempAlarm, &switchTempAlarm,sizeof(switchTempAlarm));

    return (writeDmItem(lps->vicorVoltageAlarm, &lpsVoltageAlarm,
                sizeof(lpsVoltageAlarm) ));
} /* updateIbcLpsAlarmsDm() */

/****************************************************************************/
/* Function    : writeLpsCurrentThresholds                                  */
/* Purpose     : Get LPS current thresholds from dm and send to LPS Board   */
/* Inputs      : Sio32 channel, LPS Board item handle structure             */
/* Outputs     : Returns OK or ERROR                                        */
/****************************************************************************/
    STATUS
writeLpsCurrentThresholds( sio32Chan* sio32DataChan, Word boardAddr,
    ibcLpsDmItems* lpsItems )
{
    Int16 warn[LPS_MAX_CHANS], alarm[LPS_MAX_CHANS];
                                        /* Read Current Thresholds from dmgr*/
    dm_read( lpsItems->sw0CurrentWarnThresh, (char *) &warn[0],
            sizeof(warn[0]), (DM_Time *) NULL);

    dm_read( lpsItems->sw0CurrentAlarmThresh, (char *) &alarm[0],
            sizeof(alarm[0]), (DM_Time *) NULL);

    dm_read( lpsItems->sw1CurrentWarnThresh, (char *) &warn[1],
            sizeof(warn[1]), (DM_Time *) NULL);

    dm_read( lpsItems->sw1CurrentAlarmThresh, (char *) &alarm[1],
            sizeof(alarm[1]), (DM_Time *) NULL);

    dm_read( lpsItems->sw2CurrentWarnThresh, (char *) &warn[2],
            sizeof(warn[2]), (DM_Time *) NULL);

    dm_read( lpsItems->sw2CurrentAlarmThresh, (char *) &alarm[2],
            sizeof(alarm[2]), (DM_Time *) NULL);

    dm_read( lpsItems->sw3CurrentWarnThresh, (char *) &warn[3],
            sizeof(warn[3]), (DM_Time *) NULL);

    dm_read( lpsItems->sw3CurrentAlarmThresh, (char *) &alarm[3],
            sizeof(alarm[3]), (DM_Time *) NULL);

    return (IBC_LPS_SetCurrentThresh( sio32DataChan, boardAddr, warn, alarm) );
} /* writeLpsCurrentThresholds() */

/****************************************************************************/
/* Function    : writeLpsVoltageThresholds                                  */
/* Purpose     : Get LPS Voltage thresholds from dm & send to LPS Board     */
/* Inputs      : Sio32 channel, LPS Board item handle structure             */
/* Outputs     : Returns OK or ERROR                                        */
/****************************************************************************/
    STATUS
writeLpsVoltageThresholds( sio32Chan* sio32DataChan, Word boardAddr,
    ibcLpsDmItems* lpsItems )
{
    Nat16 vicorVoltageWarn,  vicorVoltageAlarm;

                                        /* Read Voltage Thresholds from dmgr*/
    dm_read( lpsItems->vicorVoltageWarnThresh, (char *) &vicorVoltageWarn,
            sizeof(vicorVoltageWarn), (DM_Time *) NULL);

    dm_read( lpsItems->vicorVoltageAlarmThresh, (char *) &vicorVoltageAlarm,
            sizeof(vicorVoltageAlarm), (DM_Time *) NULL);

    return (IBC_LPS_SetVoltageThresh( sio32DataChan, boardAddr,
        vicorVoltageWarn, vicorVoltageAlarm) );
} /* writeLpsVoltageThresholds() */

/****************************************************************************/
/* Function    : setLpsVoltageThresh                                        */
/* Purpose     : Set LPS Voltage thresholds in dm                           */
/* Inputs      : LPS Board item handle structure & Warning/Alarm Values     */
/* Outputs     : Returns OK or ERROR                                        */
/****************************************************************************/
    STATUS
setLpsVoltageThresh(sio32Chan *sio32DataChan, Word boardAddr,
    ibcLpsDmItems *lpsItems, Nat16 voltageWarn, Nat16 voltageAlarm )
{
                                        /* Write Voltage Thresholds to dmgr */
    urgentWriteDmItem( lpsItems->vicorVoltageWarnThresh, &voltageWarn,
            sizeof(voltageWarn) );

    urgentWriteDmItem( lpsItems->vicorVoltageAlarmThresh, &voltageAlarm,
            sizeof(voltageAlarm) );

    return (IBC_LPS_SetVoltageThresh( sio32DataChan, boardAddr,
        voltageWarn, voltageAlarm) );
} /* setLpsVoltageThresh() */

/****************************************************************************/
/* Function    : writeLpsTempThresholds                                     */
/* Purpose     : Get LPS temperature thresholds from dm & send to LPS Board */
/* Inputs      : Sio32 channel, LPS Board item handle structure             */
/* Outputs     : Returns OK or ERROR                                        */
/****************************************************************************/
    STATUS
writeLpsTempThresholds( sio32Chan *sio32DataChan, Word boardAddr,
    ibcLpsDmItems* lpsItems )
{
    Int16 vicorTempWarn,  vicorTempAlarm;
    Int16 switchTempWarn, switchTempAlarm;

                                        /* Read Temp Thresholds from dmgr   */
    dm_read( lpsItems->vicorTempWarnThresh, (char *) &vicorTempWarn,
            sizeof(vicorTempWarn), (DM_Time *) NULL);

    dm_read( lpsItems->vicorTempAlarmThresh, (char *) &vicorTempAlarm,
            sizeof(vicorTempAlarm), (DM_Time *) NULL);

    dm_read( lpsItems->switchTempWarnThresh, (char *) &switchTempWarn,
            sizeof(switchTempWarn), (DM_Time *) NULL);

    dm_read( lpsItems->switchTempAlarmThresh, (char *) &switchTempAlarm,
            sizeof(switchTempAlarm), (DM_Time *) NULL);

    return (IBC_LPS_SetTempThresh( sio32DataChan, boardAddr,
        vicorTempWarn,  vicorTempAlarm, switchTempWarn, switchTempAlarm ) );
} /* writeLpsTempThresholds() */

/*****************************************************************************/
/* Function    : updateIbcLpsDmItems                                         */
/* Purpose     : Reads LPS Board parameters from IBC & update Data Manager   */
/* Inputs      : Array of Data Manager Item handles & serial chan structure  */
/* Outputs     : None, but Data Manager Items change                         */
/*****************************************************************************/
    Void
updateIbcLpsDmItems( sio32Chan* sio32DataChan, Word boardAddr,
    ibcLpsDmItems* lps, const char* ibcDataCon )
{
    Int16 warn[LPS_MAX_CHANS], alarm[LPS_MAX_CHANS];
    Int16 vicorTempWarn,    vicorTempAlarm;
    Nat16 vicorVoltageWarn, vicorVoltageAlarm;
    Int16 switchTempWarn,   switchTempAlarm;

    if (IBC_LPS_GetCurrentThresh( sio32DataChan, boardAddr, warn, alarm )
        == ERROR)
        logMsg("%s: Error reading LPS Current Alarm Threshold\n", ibcDataCon);

                                /* LPS Current Alarm Threshold initial values*/
    urgentWriteDmItem( dm_get_connect(lps->sw0CurrentWarnThresh),
                      &warn[0],  sizeof(Int16));

    urgentWriteDmItem( dm_get_connect(lps->sw0CurrentAlarmThresh),
                      &alarm[0], sizeof(Int16));

    urgentWriteDmItem( dm_get_connect(lps->sw1CurrentWarnThresh),
                      &warn[1],  sizeof(Int16));

    urgentWriteDmItem( dm_get_connect(lps->sw1CurrentAlarmThresh),
                      &alarm[1], sizeof(Int16));

    urgentWriteDmItem( dm_get_connect(lps->sw2CurrentWarnThresh),
                      &warn[2],  sizeof(Int16));

    urgentWriteDmItem( dm_get_connect(lps->sw2CurrentAlarmThresh),
                      &alarm[2], sizeof(Int16));

    urgentWriteDmItem( dm_get_connect(lps->sw3CurrentWarnThresh),
                      &warn[3],  sizeof(Int16));

    urgentWriteDmItem( dm_get_connect(lps->sw3CurrentAlarmThresh),
                      &alarm[3], sizeof(Int16));


    if (IBC_LPS_GetVoltageThresh( sio32DataChan, boardAddr,
             &vicorVoltageWarn, &vicorVoltageAlarm ) == ERROR)
        logMsg("%s: Error reading LPS Voltage Alarm Threshold\n", ibcDataCon);

                         /* Use urgent open here as another task is provider*/
    urgentWriteDmItem( lps->vicorVoltageWarnThresh,
                      &vicorVoltageWarn, sizeof(vicorVoltageWarn));

    urgentWriteDmItem( lps->vicorVoltageAlarmThresh,
                      &vicorVoltageAlarm, sizeof(vicorVoltageAlarm));


    if (IBC_LPS_GetTempThresh( sio32DataChan, boardAddr, &vicorTempWarn,
            &vicorTempAlarm, &switchTempWarn, &switchTempAlarm ) == ERROR)
        logMsg("%s: Error reading LPS Temperature Alarm Threshold\n",
               ibcDataCon);

                         /* Use urgent open here as another task is provider*/
    urgentWriteDmItem(
       lps->vicorTempWarnThresh, &vicorTempWarn, sizeof(vicorTempWarn));

    urgentWriteDmItem(
       lps->vicorTempAlarmThresh, &vicorTempAlarm, sizeof(vicorTempAlarm));

    urgentWriteDmItem(
       lps->switchTempWarnThresh, &switchTempWarn, sizeof(switchTempWarn));

    urgentWriteDmItem(
       lps->switchTempAlarmThresh, &switchTempAlarm, sizeof(switchTempAlarm));

} /* updateIbcLpsDmItems() */

    Void
ibcLpsUpdateCheck( sio32Chan* sio32DataChan, Word boardAddr,
    ibcLpsDmItems* lpsItems, lpsUpdateBits *lpsBits, DM_Group lpsGroup )
{
    DWord   lpsGroupBits;           /* Holds dm_group_changes bit vector     */

                                    /* Ask Data Manager If LPS items changed */
    if ( (lpsGroupBits = dm_get_group_changes(lpsGroup)) == (DWord) 0)
        return;

                                    /* LPS Board Current Thresholds          */
    if ( (lpsGroupBits & lpsBits->sw0CurWarnBit)  ||
         (lpsGroupBits & lpsBits->sw0CurAlarmBit) ||
         (lpsGroupBits & lpsBits->sw1CurWarnBit)  ||
         (lpsGroupBits & lpsBits->sw1CurAlarmBit) ||
         (lpsGroupBits & lpsBits->sw2CurWarnBit)  ||
         (lpsGroupBits & lpsBits->sw2CurAlarmBit) ||
         (lpsGroupBits & lpsBits->sw3CurWarnBit)  ||
         (lpsGroupBits & lpsBits->sw3CurAlarmBit) )

         writeLpsCurrentThresholds( sio32DataChan, boardAddr, lpsItems );


    if ( (lpsGroupBits & lpsBits->vicorVoltageWarnBit)   ||
         (lpsGroupBits & lpsBits->vicorVoltageAlarmBit) )

         writeLpsVoltageThresholds( sio32DataChan, boardAddr, lpsItems );


    if ( (lpsGroupBits & lpsBits->vicorTempWarnBit)   ||
         (lpsGroupBits & lpsBits->vicorTempAlarmBit)  ||
         (lpsGroupBits & lpsBits->switchTempWarnBit)  ||
         (lpsGroupBits & lpsBits->switchTempAlarmBit) )

         writeLpsTempThresholds( sio32DataChan, boardAddr, lpsItems );

} /* ibcLpsUpdateCheck() */

    MBool
processIbcLpsSRQ( Word srqRequest, Byte* buffer, Word lpsBoardAddr,
    ibcLpsDmItems* lps )
{
    Word boardAddr;                 /* IBC Board Address                      */
    Word channel;                   /* IBC Board Channel Number               */
    Word status;                    /* IBC Alarm Status Word                  */
    ibcAlarm alarmStatus;           /* IBC Alarm Status                       */

    switch (srqRequest)
    {
        case LPS_CURRENT_ALARM_SRQ:
            wordsFromBuf(buffer, 4, &srqRequest, &status, &boardAddr, &channel);
            alarmStatus = (ibcAlarm) status;

            if (boardAddr != lpsBoardAddr)
                return(FALSE);          /* Address missmatch                 */

            switch (channel)
            {
                case 0:
                    writeDmItem(lps->sw0CurrentAlarm,
                                &alarmStatus, sizeof(alarmStatus));
                    break;

                case 1:
                    writeDmItem(lps->sw1CurrentAlarm,
                                &alarmStatus, sizeof(alarmStatus));
                    break;

                case 2:
                    writeDmItem(lps->sw2CurrentAlarm,
                                &alarmStatus, sizeof(alarmStatus));
                    break;

                case 3:
                    writeDmItem(lps->sw3CurrentAlarm,
                                &alarmStatus, sizeof(alarmStatus));
                    break;
            }; /* switch */

            if (alarmStatus == MICRO_ALARM)
                ibcSwitchPowerError(lps->deviceSwitch[channel]);

            break;

        case LPS_VICOR_TEMP_ALARM_SRQ:
            wordsFromBuf(buffer, 3, &srqRequest, &status, &boardAddr);
            alarmStatus = (ibcAlarm) status;
            writeDmItem(lps->vicorTempAlarm,
                        &alarmStatus, sizeof(alarmStatus));

            if (alarmStatus == MICRO_ALARM)
                for (channel = 0; channel < LPS_MAX_CHANS; channel++)
                    ibcSwitchPowerError(lps->deviceSwitch[channel]);
            break;

        case LPS_SW3_TEMP_ALARM_SRQ:
            wordsFromBuf(buffer, 3, &srqRequest, &status, &boardAddr);
            alarmStatus = (ibcAlarm) status;
            writeDmItem(lps->switchTempAlarm,
                        &alarmStatus, sizeof(alarmStatus));

            if (alarmStatus == MICRO_ALARM)
                for (channel = 0; channel < LPS_MAX_CHANS; channel++)
                    ibcSwitchPowerError(lps->deviceSwitch[channel]);

            break;

        case LPS_VOLTAGE_ALARM_SRQ:
            wordsFromBuf(buffer, 3, &srqRequest, &status, &boardAddr);
            alarmStatus = (ibcAlarm) status;
            writeDmItem(lps->vicorVoltageAlarm,
                        &alarmStatus, sizeof(alarmStatus));
            break;

        default:
            return(FALSE);              /* SRQ Request not recognized        */

    } /* switch */

    return(TRUE);                       /* SRQ Request recognized            */
} /* processIbcLpsSRQ() */












