2406 lines
74 KiB
C
2406 lines
74 KiB
C
/* devXxDg535Gpib.c */
|
||
/* share/src/devOpt $Id$ */
|
||
/*
|
||
* Author: Ned D. Arnold
|
||
* Date: 05-28-91
|
||
*
|
||
* Experimental Physics and Industrial Control System (EPICS)
|
||
*
|
||
* Copyright 1988, 1989, the Regents of the University of California,
|
||
* and the University of Chicago Board of Governors.
|
||
*
|
||
* This software was produced under U.S. Government contracts:
|
||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||
*
|
||
* Initial development by:
|
||
* The Controls and Automation Group (AT-8)
|
||
* Ground Test Accelerator
|
||
* Accelerator Technology Division
|
||
* Los Alamos National Laboratory
|
||
*
|
||
* Co-developed with
|
||
* The Controls and Computing Group
|
||
* Accelerator Systems Division
|
||
* Advanced Photon Source
|
||
* Argonne National Laboratory
|
||
*
|
||
* All rights reserved. No part of this publication may be reproduced,
|
||
* stored in a retrieval system, transmitted, in any form or by any
|
||
* means, electronic, mechanical, photocopying, recording, or otherwise
|
||
* without prior written permission of Los Alamos National Laboratory
|
||
* and Argonne National Laboratory.
|
||
*
|
||
* Modification Log:
|
||
* -----------------
|
||
* .01 05-30-91 nda Initial Release
|
||
* .02 06-18-91 nda init_rec_mbbo must return(2) if no init value
|
||
* .03 07-02-91 nda renamed String/StringOut DSET's to Si/So
|
||
* .04 07-11-91 jrw added the callbackRequest to process()
|
||
* .05 07-15-91 jrw redesigned init processing... more generic
|
||
* .06 11-01-91 jrw major rework to fit into new GPIB driver
|
||
* .07 11-11-91 jrw added new version of SRQ support
|
||
* ...
|
||
*/
|
||
|
||
|
||
/* devDg535Gpib.c - Device Support Routines */
|
||
/* includes support for the following device types : */
|
||
|
||
#define DSET_AI devAiDg535Gpib
|
||
#define DSET_AO devAoDg535Gpib
|
||
#define DSET_BI devBiDg535Gpib
|
||
#define DSET_BO devBoDg535Gpib
|
||
#define DSET_MBBO devMbbiDg535Gpib
|
||
#define DSET_MBBI devMbboDg535Gpib
|
||
#define DSET_SI devSiDg535Gpib
|
||
#define DSET_SO devSoDg535Gpib
|
||
|
||
#include <vxWorks.h>
|
||
#include <taskLib.h>
|
||
#include <rngLib.h>
|
||
#include <types.h>
|
||
#include <stdioLib.h>
|
||
|
||
#include <alarm.h>
|
||
#include <cvtTable.h>
|
||
#include <dbDefs.h>
|
||
#include <dbAccess.h>
|
||
#include <devSup.h>
|
||
#include <recSup.h>
|
||
#include <drvSup.h>
|
||
#include <link.h>
|
||
#include <module_types.h>
|
||
#include <dbCommon.h>
|
||
#include <aiRecord.h>
|
||
#include <aoRecord.h>
|
||
#include <biRecord.h>
|
||
#include <boRecord.h>
|
||
#include <mbbiRecord.h>
|
||
#include <mbboRecord.h>
|
||
#include <stringinRecord.h>
|
||
#include <stringoutRecord.h>
|
||
|
||
#include <drvGpibInterface.h>
|
||
|
||
extern struct {
|
||
long number;
|
||
DRVSUPFUN report;
|
||
DRVSUPFUN init;
|
||
int (*qGpibReq)();
|
||
int (*registerSrqCallback)();
|
||
int (*writeIb)();
|
||
int (*readIb)();
|
||
int (*writeIbCmd)();
|
||
int (*ioctl)();
|
||
} drvGpib;
|
||
|
||
long init_dev_sup();
|
||
long init_rec_ai();
|
||
long read_ai();
|
||
long init_rec_ao();
|
||
long write_ao();
|
||
long init_rec_bi();
|
||
long read_bi();
|
||
long init_rec_bo();
|
||
long write_bo();
|
||
long init_rec_mbbi();
|
||
long read_mbbi();
|
||
long init_rec_mbbo();
|
||
long write_mbbo();
|
||
long init_rec_stringin();
|
||
long read_stringin();
|
||
long init_rec_stringout();
|
||
long write_stringout();
|
||
long init_rec_xx();
|
||
|
||
long report();
|
||
|
||
int aiGpibWork(), aiGpibSrq(), aiGpibFinish();
|
||
int aoGpibWork();
|
||
int biGpibWork(), biGpibSrq(), biGpibFinish();
|
||
int boGpibWork();
|
||
int mbbiGpibWork(), mbbiGpibSrq(), mbbiGpibFinish();
|
||
int mbboGpibWork();
|
||
int stringinGpibWork(), stringinGpibSrq(), stringinGpibFinish();
|
||
int stringoutGpibWork();
|
||
int xxGpibWork();
|
||
|
||
int srqHandler();
|
||
|
||
void processCallback();
|
||
void callbackRequest();
|
||
|
||
/******************************************************************************
|
||
*
|
||
* Define all the dset's.
|
||
*
|
||
* Note that the dset names are provided via the #define lines at the top of
|
||
* the file.
|
||
*
|
||
* Other than for the debugging flag, these DSETs are the only items that
|
||
* will appear in the global name space within the IOC.
|
||
*
|
||
******************************************************************************/
|
||
/* ai dset*/
|
||
typedef struct {
|
||
long number;
|
||
DEVSUPFUN report;
|
||
DEVSUPFUN init;
|
||
DEVSUPFUN init_record;
|
||
DEVSUPFUN get_ioint_info;
|
||
DEVSUPFUN read_ai;
|
||
DEVSUPFUN special_linconv;
|
||
} gDset;
|
||
|
||
gDset DSET_AI = { 6, report, init_dev_sup, init_rec_ai, NULL, read_ai, NULL };
|
||
gDset DSET_AO = { 6, NULL, NULL, init_rec_ao, NULL, write_ao, NULL };
|
||
gDset DSET_BI = { 5, NULL, NULL, init_rec_bi, NULL, read_bi };
|
||
gDset DSET_BO = { 5, NULL, NULL, init_rec_bo, NULL, write_bo };
|
||
gDset DSET_MBBI = { 5, NULL, NULL, init_rec_mbbi, NULL, read_mbbi };
|
||
gDset DSET_MBBO = { 5, NULL, NULL, init_rec_mbbo, NULL, write_mbbo };
|
||
gDset DSET_SI = { 5, NULL, NULL, init_rec_stringin, NULL, read_stringin };
|
||
gDset DSET_SO = { 5, NULL, NULL, init_rec_stringout, NULL, write_stringout };
|
||
|
||
/******************************************************************************
|
||
*
|
||
* This section defines any device-type specific data areas.
|
||
*
|
||
******************************************************************************/
|
||
/*#define RESPONDS_2_WRITES */ /* if GPIB machine responds to writes */
|
||
#define _SRQSUPPORT_ /* for srq support */
|
||
|
||
#define TIME_WINDOW 600 /* 10 seconds on a getTick call */
|
||
|
||
int dg535Debug = 0;
|
||
extern int ibSrqDebug;
|
||
|
||
static char UDF[10] = "Undefined";
|
||
static char pOK[3] = "OK";
|
||
|
||
/* forward declarations of some custom convert routines */
|
||
|
||
int setDelay(); /* used to set delay */
|
||
int rdDelay(); /* used to place string in .DESC field */
|
||
|
||
/******************************************************************************
|
||
*
|
||
* This structure holds device-related data on a per-device basis and is
|
||
* referenced by the gpibDpvt structures. They are built using a linked
|
||
* list entered from hwpvtHead. This linked list is only for this specific
|
||
* device type (other gpib devices may have their own lists.)
|
||
*
|
||
******************************************************************************/
|
||
struct hwpvt {
|
||
struct hwpvt *next; /* to next structure for same type device */
|
||
|
||
int linkType; /* is a GPIB_IO, BBGPIB_IO... from link.h */
|
||
int link; /* link number */
|
||
int bug; /* used only on BBGPIB_IO links */
|
||
int device; /* gpib device number */
|
||
|
||
unsigned long tmoVal; /* time last timeout occurred */
|
||
unsigned long tmoCount; /* total number of timeouts since boot time */
|
||
|
||
/* No semaphore guards here because can inly be mod'd by the linkTask */
|
||
int (*srqCallback)(); /* filled by cmds expecting SRQ callbacks */
|
||
caddr_t parm; /* filled in by cmds expecting SRQ callbacks */
|
||
};
|
||
static struct hwpvt *hwpvtHead = NULL; /* pointer to first hwpvt in chain */
|
||
|
||
/******************************************************************************
|
||
*
|
||
* This structure will be attached to each pv (via psub->dpvt) to store the
|
||
* appropriate head.workStart pointer, callback address to record support,
|
||
* gpib link #, device address, and command information.
|
||
*
|
||
******************************************************************************/
|
||
|
||
struct gpibDpvt {
|
||
struct dpvtGpibHead head; /* fields used by the GPIB driver */
|
||
|
||
short parm; /* parameter index into gpib commands */
|
||
char *rsp; /* for read/write message error Responses*/
|
||
char *msg; /* for read/write messages */
|
||
struct dbCommon *precord; /* record this dpvt is part of */
|
||
void (*process)(); /* callback to perform forward db processing */
|
||
int processPri; /* process callback's priority */
|
||
long linkType; /* GPIB_IO, BBGPIB_IO... */
|
||
struct hwpvt *phwpvt; /* pointer to per-device private area */
|
||
};
|
||
|
||
/******************************************************************************
|
||
*
|
||
* This is used to define the strings that are used for button labels.
|
||
* These strings are put into the record's znam & onam foelds if the
|
||
* record is a BI or BO type and into the zrst, onst... fields of an
|
||
* MBBI or MBBO record.
|
||
*
|
||
* Before these strings are placed into the record, the record is
|
||
* check to see if there is already a string defined (could be user-entered
|
||
* with DCT.) If there is already a string present, it will be preserved.
|
||
*
|
||
* There MUST ALWAYS be 2 and only 2 entries in the names.item list
|
||
* for BI and BO records if a name list is being specified for them here.
|
||
* The names.count field is ignored for BI and BO record types, but
|
||
* should be properly specified as 2 for future compatibility.
|
||
*
|
||
* NOTE:
|
||
* If a name string is filled in an an MBBI/MBBO record, it's corresponding
|
||
* value will be filled in as well. For this reason, there MUST be
|
||
* a value array and a valid nobt value for every MBBI/MBBO record that
|
||
* contains an item array!
|
||
*
|
||
******************************************************************************/
|
||
|
||
struct names {
|
||
int count; /* CURRENTLY only used for MBBI and MBBO */
|
||
char **item;
|
||
unsigned long *value; /* CURRENTLY only used for MBBI and MBBO */
|
||
short nobt; /* CURRENTLY only used for MBBI and MBBO */
|
||
};
|
||
|
||
static char *offOnList[] = { "Off", "On" };
|
||
static struct names offOn = { 2, offOnList, NULL, 1 };
|
||
|
||
static char *disableEnableList[] = { "Disable", "Enable" };
|
||
static struct names disableEnable = { 2, disableEnableList, NULL, 1 };
|
||
|
||
static char *resetList[] = { "Reset", "Reset" };
|
||
static struct names reset = { 2, resetList, NULL, 1 };
|
||
|
||
static char *lozHizList[] = { "50 OHM", "IB_Q_HIGH Z" };
|
||
static struct names lozHiz = {2, lozHizList, NULL, 1};
|
||
|
||
static char *invertNormList[] = { "INVERT", "NORM" };
|
||
static struct names invertNorm = { 2, invertNormList, NULL, 1 };
|
||
|
||
static char *fallingRisingList[] = { "FALLING", "RISING" };
|
||
static struct names fallingRising = { 2, fallingRisingList, NULL, 1 };
|
||
|
||
static char *singleShotList[] = { "SINGLE", "SHOT" };
|
||
static struct names singleShot = { 2, singleShotList, NULL, 1 };
|
||
|
||
static char *clearList[] = { "CLEAR", "CLEAR" };
|
||
static struct names clear = { 2, clearList, NULL, 1 };
|
||
|
||
static char *tABCDList[] = { "T", "A", "B", "C", "D" };
|
||
static unsigned long tABCDVal[] = { 1, 2, 3, 5, 6 };
|
||
static struct names tABCD = { 5, tABCDList, tABCDVal, 3 };
|
||
|
||
static char *ttlNimEclVarList[] = { "TTL", "NIM", "ECL", "VAR" };
|
||
static unsigned long ttlNimEclVarVal[] = { 0, 1, 2, 3 };
|
||
static struct names ttlNimEclVar = { 4, ttlNimEclVarList,
|
||
ttlNimEclVarVal, 2 };
|
||
|
||
static char *intExtSsBmStopList[] = { "INTERNAL", "EXTERNAL",
|
||
"SINGLE SHOT", "BURST MODE", "STOP" };
|
||
static unsigned long intExtSsBmStopVal[] = { 0, 1, 2, 3, 2 };
|
||
static struct names intExtSsBm = { 4, intExtSsBmStopList,
|
||
intExtSsBmStopVal, 2 };
|
||
static struct names intExtSsBmStop = { 5, intExtSsBmStopList,
|
||
intExtSsBmStopVal, 3 };
|
||
|
||
/* Channel Names, used to derive string representation of programmed delay */
|
||
|
||
char *pchanName[8] = {" ", "T + ", "A + ", "B + ", " ", "C + ", "D + ", " "};
|
||
|
||
/******************************************************************************
|
||
*
|
||
* The following #define statements enumerate the record types that
|
||
* are supported by this device support module. These are used by the init
|
||
* routines when they to type checking against the records that have
|
||
* been defined for use with this type of GPIB device.
|
||
*
|
||
******************************************************************************/
|
||
|
||
#define GPIB_AO 1
|
||
#define GPIB_AI 2
|
||
#define GPIB_BO 3
|
||
#define GPIB_BI 4
|
||
#define GPIB_MBBO 5
|
||
#define GPIB_MBBI 6
|
||
#define GPIB_SI 7
|
||
#define GPIB_SO 8
|
||
|
||
/******************************************************************************
|
||
*
|
||
* Enumeration of gpib command types supported by this device type.
|
||
*
|
||
******************************************************************************/
|
||
|
||
#define GPIBREAD 1
|
||
#define GPIBWRITE 2
|
||
#define GPIBCMD 3
|
||
#define GPIBCNTL 4
|
||
#define GPIBSOFT 5
|
||
#define GPIBREADW 6
|
||
#define GPIBRAWREAD 7
|
||
|
||
/******************************************************************************
|
||
*
|
||
* The next structure defines the GPIB command and format statements to
|
||
* extract or send data to a GPIB Instrument. Each transaction type is
|
||
* described below :
|
||
*
|
||
* GPIBREAD : (1) The cmd string is sent to the instrument
|
||
* (2) Data is read from the inst into a buffer (gpibDpvt.msg)
|
||
* (3) The important data is extracted from the buffer using the
|
||
* format string.
|
||
*
|
||
* GPIBWRITE: (1) An ascii string is generated using the format string and
|
||
* contents of the gpibDpvt->dbAddr->precord->val
|
||
* (2) The ascii string is sent to the instrument
|
||
*
|
||
* GPIBCMD : (1) The cmd string is sent to the instrument
|
||
*
|
||
* GPIBCNTL : (1) The control string is sent to the instrument (ATN active)
|
||
*
|
||
* GPIBSOFT : (1) No GPIB activity involved - normally retrieves internal data
|
||
*
|
||
* GPIBREADW : (1) The cmd string is sent to the instrument
|
||
* (2) Wait for SRQ
|
||
* (3) Data is read from the inst into a buffer (gpibDpvt.msg)
|
||
* (4) The important data is extracted from the buffer using the
|
||
* format string.
|
||
*
|
||
* GPIBRAWREAD: Used internally with GPIBREADW. Not useful from cmd table.
|
||
*
|
||
* If a particular GPIB message does not fit one of these formats, a custom
|
||
* routine may be provided. Store a pointer to this routine in the
|
||
* gpibCmd.convert field to use it rather than the above approaches.
|
||
*
|
||
******************************************************************************/
|
||
|
||
struct gpibCmd {
|
||
int rec_typ; /* enum - GPIB_AO GPIB_AI GPIB_BO... */
|
||
int type; /* enum - GPIBREAD, GPIBWRITE, GPIBCMND */
|
||
short pri; /* priority of gpib request--IB_Q_HIGH or IB_Q_LOW*/
|
||
char *sta; /* status string */
|
||
char *cmd; /* CONSTANT STRING to send to instrument */
|
||
char *format; /* string used to generate or interpret msg*/
|
||
short rspLen; /* room for response error message*/
|
||
short msgLen; /* room for return data message length*/
|
||
|
||
int (*convert)(); /* custom routine for wierd conversions */
|
||
int P1; /* parameter used in convert*/
|
||
int P2; /* parameter user in convert*/
|
||
char **P3; /* pointer to array containing pointers to
|
||
strings */
|
||
struct names *namelist; /* pointer to button label strings */
|
||
};
|
||
|
||
/******************************************************************************
|
||
*
|
||
* Array of structures that define all GPIB messages
|
||
* supported for this type of instrument.
|
||
*
|
||
******************************************************************************/
|
||
|
||
#define FILL {0,0,IB_Q_LOW, UDF,NULL,NULL,0,0,NULL,0,0,NULL,NULL }
|
||
#define FILL10 FILL,FILL,FILL,FILL,FILL,FILL,FILL,FILL,FILL,FILL
|
||
|
||
static struct gpibCmd gpibCmds[] =
|
||
{
|
||
/* Param 0, (model) */
|
||
FILL,
|
||
|
||
/* Channel A Delay and Output */
|
||
/* Param 1, write A delay */
|
||
{GPIB_AO, GPIBWRITE, IB_Q_HIGH, UDF, "DT 2\n", "DT 2,?,%.12lf\n", 0, 32,
|
||
setDelay, 0, 0, NULL, NULL},
|
||
|
||
/* Param 2, currently undefined */
|
||
FILL,
|
||
|
||
/* Param 3, read A Delay */
|
||
{GPIB_AI, GPIBREAD, IB_Q_LOW, UDF, "DT 2\n", NULL, 0, 32,
|
||
rdDelay, 0, 0, NULL, NULL },
|
||
|
||
/* Param 4, not yet implemented */
|
||
FILL,
|
||
|
||
/* Param 5, set A delay reference channel */
|
||
{GPIB_MBBO, GPIBWRITE, IB_Q_HIGH, UDF, "DT 2\n", "DT 2,%u,", 0, 32,
|
||
setDelay, 0, 0, NULL, &tABCD},
|
||
|
||
/* Param 6, read A delay reference */
|
||
{GPIB_MBBI, GPIBREAD, IB_Q_LOW, UDF, "DT 2\n", NULL, 0, 32,
|
||
rdDelay, 0, 0, NULL, &tABCD},
|
||
|
||
/* Param 7, set A output mode */
|
||
{GPIB_MBBO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "OM 2,%u\n", 0, 32,
|
||
NULL, 0, 0, NULL, &ttlNimEclVar},
|
||
|
||
/* Param 8, read A output mode */
|
||
{GPIB_MBBI, GPIBREAD, IB_Q_LOW, UDF, "OM 2\n", "%lu", 0, 32,
|
||
NULL, 0, 0, NULL, &ttlNimEclVar},
|
||
|
||
/* Param 9, set A output amplitude */
|
||
{GPIB_AO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "OA 2,%.1f\n", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 10, read A output amplitude */
|
||
{GPIB_AI, GPIBREAD, IB_Q_LOW, UDF, "OA 2\n", "%lf", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 11, set A output offset */
|
||
{GPIB_AO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "OO 2,%.1f\n", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 12, read A output offset */
|
||
{GPIB_AI, GPIBREAD, IB_Q_LOW, UDF, "OO 2\n", "%lf", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 13, set A output Termination */
|
||
{GPIB_BO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "TZ 2,%u\n", 0, 32,
|
||
NULL, 0, 0, NULL, &lozHiz},
|
||
|
||
/* Param 14, read A output Termination */
|
||
{GPIB_BI, GPIBREAD, IB_Q_LOW, UDF, "TZ 2\n", "%lu", 0, 32,
|
||
NULL, 0, 0, NULL, &lozHiz},
|
||
|
||
/* Param 15, set A output Polarity */
|
||
{GPIB_BO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "OP 2,%u\n", 0, 32,
|
||
NULL, 0, 0, NULL, &invertNorm},
|
||
|
||
/* Param 16, read A output Polarity */
|
||
{GPIB_BI, GPIBREAD, IB_Q_LOW, UDF, "OP 2\n", "%lu", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Channel B Delay and Output */
|
||
/* Param 17, write B delay */
|
||
{GPIB_AO, GPIBWRITE, IB_Q_HIGH, UDF, "DT 3\n", "DT 3,?,%.12lf\n", 0, 32,
|
||
setDelay, 0, 0, NULL, NULL},
|
||
|
||
/* Param 18, currently undefined */
|
||
FILL,
|
||
|
||
/* Param 19, read B Delay */
|
||
{GPIB_AI, GPIBREAD, IB_Q_LOW, UDF, "DT 3\n", NULL, 0, 32,
|
||
rdDelay, 0, 0, NULL, NULL},
|
||
|
||
/* Param 20, not yet implemented */
|
||
FILL,
|
||
|
||
/* Param 21, set B delay reference channel */
|
||
{GPIB_MBBO, GPIBWRITE, IB_Q_HIGH, UDF, "DT 3\n", "DT 3,%u,", 0, 32,
|
||
setDelay, 0, 0, NULL, &tABCD},
|
||
|
||
/* Param 22, read B delay reference */
|
||
{GPIB_MBBI, GPIBREAD, IB_Q_LOW, UDF, "DT 3\n", NULL, 0, 32,
|
||
rdDelay, 0 ,0, NULL, &tABCD},
|
||
|
||
/* Param 23, set B output mode */
|
||
{GPIB_MBBO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "OM 3,%u\n", 0, 32,
|
||
NULL, 0, 0, NULL, &ttlNimEclVar},
|
||
|
||
/* Param 24, read B output mode */
|
||
{GPIB_MBBI, GPIBREAD, IB_Q_LOW, UDF, "OM 3\n", "%lu", 0 ,32,
|
||
NULL, 0, 0, NULL, &ttlNimEclVar},
|
||
|
||
/* Param 25, set B output amplitude */
|
||
{GPIB_AO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "OA 3,%.1f\n", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 26, read B output amplitude */
|
||
{GPIB_AI, GPIBREAD, IB_Q_LOW, UDF, "OA 3\n", "%lf", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 27, set B output offset */
|
||
{GPIB_AO, GPIBWRITE, IB_Q_HIGH, NULL, "OO 3,%.1f\n", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 28, read B output offset */
|
||
{GPIB_AI, GPIBREAD, IB_Q_LOW, UDF, "OO 3\n", "%lf", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 29, set B output Termination */
|
||
{GPIB_BO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "TZ 3,%u\n", 0, 32,
|
||
NULL, 0, 0, NULL, &lozHiz},
|
||
|
||
/* Param 30, read B output Termination */
|
||
{GPIB_BI, GPIBREAD, IB_Q_LOW, UDF, "TZ 3\n", "%lu", 0, 32,
|
||
NULL, 0, 0, NULL, &lozHiz},
|
||
|
||
/* Param 31, set B output Polarity */
|
||
{GPIB_BO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "OP 3,%u\n", 0, 32,
|
||
NULL, 0, 0, NULL, &invertNorm},
|
||
|
||
/* Param 32, read B output Polarity */
|
||
{GPIB_BI, GPIBREAD, IB_Q_LOW, UDF, "OP 3\n", "%lu", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Channel AB Outputs */
|
||
/* Param 33, set AB output mode */
|
||
{GPIB_MBBO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "OM 4,%u\n", 0, 32,
|
||
NULL, 0, 0, NULL, &ttlNimEclVar},
|
||
|
||
/* Param 34, read AB output mode */
|
||
{GPIB_MBBI, GPIBREAD, IB_Q_LOW, UDF, "OM 4\n", "%lu", 0, 32,
|
||
NULL, 0, 0, NULL, &ttlNimEclVar},
|
||
|
||
/* Param 35, set AB output amplitude */
|
||
{GPIB_AO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "OA 4,%.1f\n", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 36, read AB output amplitude */
|
||
{GPIB_AI, GPIBREAD, IB_Q_LOW, UDF, "OA 4\n", "%lf", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 37, set AB output offset */
|
||
{GPIB_AO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "OO 4,%.1f\n", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 38, read AB output offset */
|
||
{GPIB_AI, GPIBREAD, IB_Q_LOW, UDF, "OO 4\n", "%lf", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 39, set AB output Termination */
|
||
{GPIB_BO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "TZ 4,%u\n", 0, 32,
|
||
NULL, 0, 0, NULL, &lozHiz},
|
||
|
||
/* Param 40, read AB output Termination */
|
||
{GPIB_BI, GPIBREAD, IB_Q_LOW, UDF, "TZ 4\n", "%lu", 0, 32,
|
||
NULL, 0, 0, NULL, &lozHiz},
|
||
|
||
/* Param 41, set AB output Polarity */
|
||
{GPIB_BO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "OP 4,%u\n", 0, 32,
|
||
NULL, 0, 0, NULL, &invertNorm},
|
||
|
||
/* Param 42, read AB output Polarity */
|
||
{GPIB_BI, GPIBREAD, IB_Q_LOW, UDF, "OP 4\n", "%lu", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Channel C Delay and Output */
|
||
/* Param 43, write C delay */
|
||
{GPIB_AO, GPIBWRITE, IB_Q_HIGH, UDF, "DT 5\n", "DT 5,?,%.12lf\n", 0, 32,
|
||
setDelay, 0, 0, NULL, NULL},
|
||
|
||
/* Param 44, currently undefined */
|
||
FILL,
|
||
|
||
/* Param 45, read C Delay */
|
||
{GPIB_AI, GPIBREAD, IB_Q_LOW, UDF, "DT 5\n", NULL, 0, 32,
|
||
rdDelay, 0, 0, NULL, NULL},
|
||
|
||
/* Param 46, not yet implemented */
|
||
FILL,
|
||
|
||
/* Param 47, set C delay reference channel */
|
||
{GPIB_MBBO, GPIBWRITE, IB_Q_HIGH, UDF, "DT 5\n", "DT 5,%u,", 0, 32,
|
||
setDelay, 0, 0, NULL, &tABCD},
|
||
|
||
/* Param 48, read C delay reference */
|
||
{GPIB_MBBI, GPIBREAD, IB_Q_LOW, UDF, "DT 5\n", NULL, 0, 32,
|
||
rdDelay, 0, 0, NULL, &tABCD},
|
||
|
||
/* Param 49, set C output mode */
|
||
{GPIB_MBBO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "OM 5,%u\n", 0, 32,
|
||
NULL, 0, 0, NULL, &ttlNimEclVar},
|
||
|
||
/* Param 50, read C output mode */
|
||
{GPIB_MBBI, GPIBREAD, IB_Q_LOW, UDF, "OM 5\n", "%lu", 0, 32,
|
||
NULL, 0, 0, NULL, &ttlNimEclVar},
|
||
|
||
/* Param 51, set C output amplitude */
|
||
{GPIB_AO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "OA 5,%.1f\n", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 52, read C output amplitude */
|
||
{GPIB_AI, GPIBREAD, IB_Q_LOW, UDF, "OA 5\n", "%lf", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 53, set C output offset */
|
||
{GPIB_AI, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "OO 5,%.1f\n", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 54, read C output offset */
|
||
{GPIB_AI, GPIBREAD, IB_Q_LOW, UDF, "OO 5\n", "%lf", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 55, set C output Termination */
|
||
{GPIB_BO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "TZ 5,%u\n", 0, 32,
|
||
NULL, 0, 0, NULL, &lozHiz},
|
||
|
||
/* Param 56, read C utput Termination */
|
||
{GPIB_BI, GPIBREAD, IB_Q_LOW, UDF, "TZ 5\n", "%lu", 0, 32,
|
||
NULL, 0, 0, NULL, &lozHiz},
|
||
|
||
/* Param 57, set C output Polarity */
|
||
{GPIB_BO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "OP 5,%u\n", 0, 32,
|
||
NULL, 0, 0, NULL, &invertNorm},
|
||
|
||
/* Param 58, read C output Polarity */
|
||
{GPIB_BI, GPIBREAD, IB_Q_LOW, UDF, "OP 5\n", "%lu", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Channel D Delay and Output */
|
||
/* Param 59, write D delay */
|
||
{GPIB_AO, GPIBWRITE, IB_Q_HIGH, UDF, "DT 6\n", "DT 6,?,%.12lf\n", 0, 32,
|
||
setDelay, 0, 0, NULL, NULL},
|
||
|
||
/* Param 60, currently undefined */
|
||
FILL,
|
||
|
||
/* Param 61, read D Delay */
|
||
{GPIB_AI, GPIBREAD, IB_Q_LOW, UDF, "DT 6\n", NULL, 0, 32,
|
||
rdDelay, 0, 0, NULL, NULL},
|
||
|
||
/* Param 62, not yet implemented */
|
||
FILL,
|
||
|
||
/* Param 63, set D delay reference channel */
|
||
{GPIB_MBBO, GPIBWRITE, IB_Q_HIGH, UDF, "DT 6\n", "DT 6,%u,", 0, 32,
|
||
setDelay, 0, 0, NULL, &tABCD},
|
||
|
||
/* Param 64, read D delay reference */
|
||
{GPIB_MBBI, GPIBREAD, IB_Q_LOW, UDF, "DT 6\n", NULL, 0, 32,
|
||
rdDelay, 0 ,0, NULL, &tABCD},
|
||
|
||
/* Param 65, set D output mode */
|
||
{GPIB_MBBI, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "OM 6,%u\n", 0, 32,
|
||
NULL, 0, 0, NULL, &ttlNimEclVar},
|
||
|
||
/* Param 66, read D output mode */
|
||
{GPIB_MBBI, GPIBREAD, IB_Q_LOW, UDF, "OM 6\n", "%lu", 0, 32,
|
||
NULL, 0, 0, NULL, &ttlNimEclVar},
|
||
|
||
/* Param 67, set D output amplitude */
|
||
{GPIB_AO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "OA 6,%.1f\n", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 68, read D output amplitude */
|
||
{GPIB_AI, GPIBREAD, IB_Q_LOW, UDF, "OA 6\n", "%lf", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 69, set D output offset */
|
||
{GPIB_AO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "OO 6,%.1f\n", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 70, read D output offset */
|
||
{GPIB_AI, GPIBREAD, IB_Q_LOW, UDF, "OO 6\n", "%lf", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 71, set D output Termination */
|
||
{GPIB_BO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "TZ 6,%u\n", 0, 32,
|
||
NULL, 0, 0, NULL, &lozHiz},
|
||
|
||
/* Param 72, read D output Termination */
|
||
{GPIB_BI, GPIBREAD, IB_Q_LOW, UDF, "TZ 6\n", "%lu", 0, 32,
|
||
NULL, 0, 0, NULL, &lozHiz},
|
||
|
||
/* Param 73, set D output Polarity */
|
||
{GPIB_BO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "OP 6,%u\n", 0, 32,
|
||
NULL, 0, 0, NULL, &invertNorm},
|
||
|
||
/* Param 74, read D output Polarity */
|
||
{GPIB_BI, GPIBREAD, IB_Q_LOW, UDF, "OP 6\n", "%lu", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Channel CD Outputs */
|
||
/* Param 75, set CD output mode */
|
||
{GPIB_MBBO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "OM 7,%u\n", 0, 32,
|
||
NULL, 0, 0, NULL, &ttlNimEclVar},
|
||
|
||
/* Param 76, read CD output mode */
|
||
{GPIB_MBBI, GPIBREAD, IB_Q_LOW, UDF, "OM 7\n", "%lu", 0, 32,
|
||
NULL, 0, 0, NULL, &ttlNimEclVar},
|
||
|
||
/* Param 77, set CD output amplitude */
|
||
{GPIB_AO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "OA 7,%.1f\n", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 78, read CD output amplitude */
|
||
{GPIB_AI, GPIBREAD, IB_Q_LOW, UDF, "OA 7\n", "%lf", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 79, set CD output offset */
|
||
{GPIB_AI, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "OO 7,%.1f\n", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 80, read CD output offset */
|
||
{GPIB_AI, GPIBREAD, IB_Q_LOW, UDF, "OO 7\n", "%lf", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 81, set CD output Termination */
|
||
{GPIB_BO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "TZ 7,%u\n", 0, 32,
|
||
NULL, 0, 0, NULL, &lozHiz},
|
||
|
||
/* Param 82, read CD output Termination */
|
||
{GPIB_BI, GPIBREAD, IB_Q_LOW, UDF, "TZ 7\n", "%lu", 0, 32,
|
||
NULL, 0, 0, NULL, &lozHiz},
|
||
|
||
/* Param 83, set CD output Polarity */
|
||
{GPIB_BO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "OP 7,%u\n", 0, 32,
|
||
NULL, 0, 0, NULL, &invertNorm},
|
||
|
||
/* Param 84, read CD output Polarity */
|
||
{GPIB_BI, GPIBREAD, IB_Q_LOW, UDF, "OP 7\n", "%lu", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Trigger Settings */
|
||
/* Param 85, set Trig Mode */
|
||
{GPIB_MBBO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "TM %u\n", 0, 32,
|
||
NULL, 0, 0, NULL, &intExtSsBmStop},
|
||
|
||
/* Param 86, read Trig Mode */
|
||
{GPIB_MBBI, GPIBREAD, IB_Q_LOW, UDF, "TM \n", "%lu", 0, 32,
|
||
NULL, 0, 0, NULL, &intExtSsBm},
|
||
|
||
/* Param 87, set Trig Rate */
|
||
{GPIB_AO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "TR 0,%.3lf\n", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 88, read Trig Rate */
|
||
{GPIB_AI, GPIBREAD, IB_Q_LOW, UDF, "TR 0\n", "%lf", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 89, set Burst Rate */
|
||
{GPIB_AO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "TR 1,%.3lf\n", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 90, read Burst Rate */
|
||
{GPIB_AI, GPIBREAD, IB_Q_LOW, UDF, "TR 1\n", "%lf", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 91, set Burst Count */
|
||
{GPIB_AO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "BC %01.0lf\n", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 92, read Burst Count */
|
||
{GPIB_AI, GPIBREAD, IB_Q_LOW, UDF, "BC \n", "%lf", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 93, set Burst Period */
|
||
{GPIB_AO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "BP %01.0lf\n", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 94, read Burst Period */
|
||
{GPIB_AI, GPIBREAD, IB_Q_LOW, UDF, "BP \n", "%lf", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 95, set Trig Input Z */
|
||
{GPIB_BO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "TZ 0,%u\n", 0, 32,
|
||
NULL, 0, 0, NULL, &lozHiz},
|
||
|
||
/* Param 96, read Trig Input Z */
|
||
{GPIB_BI, GPIBREAD, IB_Q_LOW, UDF, "TZ 0\n", "%lu", 0, 32,
|
||
NULL, 0, 0, NULL, &lozHiz},
|
||
|
||
/* Param 97, set Trig Input slope */
|
||
{GPIB_BO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "TS %u\n", 0, 32,
|
||
NULL, 0, 0, NULL, &fallingRising},
|
||
|
||
/* Param 98, read Trig Input slope */
|
||
{GPIB_BI, GPIBREAD, IB_Q_LOW, UDF, "TS \n", "%lu", 0, 32,
|
||
NULL, 0, 0, NULL, &fallingRising},
|
||
|
||
/* Param 99, set Trig Input level */
|
||
{GPIB_AO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "TL %.2lf\n", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 100, read Trig Input Level */
|
||
{GPIB_AI, GPIBREAD, IB_Q_LOW, UDF, "TL \n", "%lf", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 101, generate Single Trig */
|
||
{GPIB_BO, GPIBCMD, IB_Q_HIGH, UDF, "SS \n", NULL, 0, 32,
|
||
NULL, 0, 0, NULL, &singleShot},
|
||
|
||
/* Param 102, Store Setting # */
|
||
{GPIB_AO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "ST %01.0lf\n", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 103, Recall Setting # */
|
||
{GPIB_AO, GPIBWRITE, IB_Q_HIGH, UDF, NULL, "RC %01.0lf\n", 0, 32,
|
||
NULL, 0, 0, NULL, NULL},
|
||
|
||
/* Param 104, Recall Setting # */
|
||
{GPIB_BO, GPIBCMD, IB_Q_HIGH, UDF, "CL \n", NULL, 0, 32,
|
||
NULL, 0, 0, NULL, &clear}
|
||
};
|
||
|
||
|
||
/* The following is the number of elements in the command array above. */
|
||
#define NUMPARAMS sizeof(gpibCmds)/sizeof(struct gpibCmd)
|
||
|
||
#define GPIBMSGLENGTH 32 /* used by the delay routines only */
|
||
|
||
/******************************************************************************
|
||
*
|
||
* Unique message interpretaion for reading Channel Delays :
|
||
* The command to read the delay setting returns a string with two arguments.
|
||
* This routine extracts both arguments and assigns them appropriately. Also,
|
||
* a string is generated with the format CHAN + xxx.xxxxxxxxxxxx and stored
|
||
* in the .DESC field of the ai record. (ex: T + .000000500000) If either
|
||
* parameter has changed, a db_post_event is issued for the .DESC field (ai
|
||
* record only).
|
||
*
|
||
******************************************************************************/
|
||
|
||
static int rdDelay(pdpvt)
|
||
struct gpibDpvt *pdpvt;
|
||
{
|
||
int status;
|
||
double delay;
|
||
unsigned long chan;
|
||
unsigned short monitor_mask = 0;
|
||
|
||
struct aiRecord *pai= (struct aiRecord *)(pdpvt->precord);
|
||
struct mbbiRecord *pmbbi= (struct mbbiRecord *)(pdpvt->precord);
|
||
|
||
if(dg535Debug)
|
||
logMsg("rdDelay : returned msg :%s\n",pdpvt->msg);
|
||
|
||
/* Change the "," in returned string to a " " to separate fields */
|
||
pdpvt->msg[1] = 0x20;
|
||
|
||
/* scan response string for chan reference & delay value */
|
||
status = sscanf(pdpvt->msg, "%ld%lf", &chan, &delay);
|
||
|
||
if(dg535Debug)
|
||
logMsg("rdDelay :sscanf status = %d\n",status);
|
||
|
||
switch (pdpvt->parm)
|
||
{
|
||
case 3: /* A Delay monitor, must be an ai record */
|
||
case 19: /* B Delay monitor, must be an ai record */
|
||
case 45: /* C Delay monitor, must be an ai record */
|
||
case 61: /* D Delay monitor, must be an ai record */
|
||
if (status == 2) /* make sure both parameters were assigned */
|
||
{
|
||
/* check if delay or reference channel has changed */
|
||
if ((pai->val != delay) || (pai->desc[0] != pchanName[chan][0]))
|
||
{
|
||
monitor_mask = DBE_VALUE;
|
||
}
|
||
/* assign new delay to value field*/
|
||
pai->val = delay;
|
||
strcpy(pai->desc, pchanName[chan]);
|
||
strcat(pai->desc, &((pdpvt->msg)[3]));
|
||
if(dg535Debug)
|
||
logMsg("rdDelay : %s",pai->desc);
|
||
if (monitor_mask)
|
||
{
|
||
db_post_events(pai, pai->desc, monitor_mask);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (pai->nsev < VALID_ALARM)
|
||
{
|
||
pai->nsev = VALID_ALARM;
|
||
pai->nsta = READ_ALARM;
|
||
}
|
||
}
|
||
break;
|
||
|
||
case 6: /* A Delay Reference monitor, must be an mbbi record */
|
||
case 22: /* B Delay Reference monitor, must be an mbbi record */
|
||
case 48: /* C Delay Reference monitor, must be an mbbi record */
|
||
case 64: /* D Delay Reference monitor, must be an mbbi record */
|
||
if (status == 2) /* make sure both parameters were assigned */
|
||
{
|
||
pmbbi->rval = chan;
|
||
}
|
||
else
|
||
{
|
||
if (pmbbi->nsev < VALID_ALARM)
|
||
{
|
||
pmbbi->nsev = VALID_ALARM;
|
||
pmbbi->nsta = READ_ALARM;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
return(OK);
|
||
}
|
||
|
||
/******************************************************************************
|
||
*
|
||
* Unique message generation for writing channel Delays :
|
||
* The command to set the channel delay requires two parameters: The channel
|
||
* # to reference from and the time delay. Since changing either of these
|
||
* parameters requires the command to be sent, the current state of other
|
||
* parameter must be determined. This is done by reading the delay (which
|
||
* returns both parameters), changing one of the paramaters, and sending
|
||
* the command back.
|
||
*
|
||
* WARNING!!!!!
|
||
* This function modifies the gpibCmds table!!! This is not a very nice
|
||
* thing to do! It is OK to do if only one dg535 is out there. But it will NOT
|
||
* work if there are more because modifying the gpibCmds table removes
|
||
* the re-entrant properties of this routine!!!! This should be
|
||
* re-designed to use a local temporary storage area.
|
||
*
|
||
******************************************************************************/
|
||
|
||
static int setDelay(pdpvt)
|
||
struct gpibDpvt *pdpvt;
|
||
{
|
||
int status;
|
||
char curChan;
|
||
char tempMsg[GPIBMSGLENGTH];
|
||
|
||
struct aoRecord *pao= (struct aoRecord *)(pdpvt->precord);
|
||
struct mbboRecord *pmbbo= (struct mbboRecord *)(pdpvt->precord);
|
||
|
||
if(dg535Debug)
|
||
logMsg("setDelay : returned msg :%s\n",pdpvt->msg);
|
||
|
||
/* adjust the gpibCmd to do a GPIBREAD of the current
|
||
* delay setting first.
|
||
*/
|
||
|
||
gpibCmds[pdpvt->parm].type = GPIBREAD;
|
||
|
||
/* go read the current delay setting */
|
||
if(xxGpibWork(pdpvt, gpibCmds[pdpvt->parm].type) == ERROR)
|
||
{ /* abort operation if read failed */
|
||
gpibCmds[pdpvt->parm].type = GPIBWRITE; /* set back to write */
|
||
return(ERROR); /* return, signalling an error */
|
||
}
|
||
|
||
/* Due to a fluke in the DG535, read again to insure accurate data */
|
||
|
||
if(xxGpibWork(pdpvt, gpibCmds[pdpvt->parm].type) == ERROR) /* go read the current delay setting */
|
||
{ /* abort operation if read failed */
|
||
gpibCmds[pdpvt->parm].type = GPIBWRITE; /* set back to write */
|
||
return(ERROR); /* return, signalling an error */
|
||
}
|
||
|
||
/* change one of the two parameters ... */
|
||
|
||
switch(pdpvt->parm)
|
||
{
|
||
case 1: /* changing time delay */
|
||
case 17:
|
||
case 43:
|
||
case 59:
|
||
curChan = pdpvt->msg[0]; /* save current chan reference */
|
||
/* generate new delay string (correct rounding error) */
|
||
sprintf(pdpvt->msg,gpibCmds[pdpvt->parm].format, (pao->val + 1.0e-13));
|
||
pdpvt->msg[5] = curChan; /* replace "?" with current chan */
|
||
break;
|
||
|
||
case 5: /* changing reference channel */
|
||
case 21:
|
||
case 47:
|
||
case 63:
|
||
strcpy(tempMsg, &((pdpvt->msg)[3])); /* save current delay setting */
|
||
/* generate new channel reference */
|
||
sprintf(pdpvt->msg, gpibCmds[pdpvt->parm].format, (unsigned int)pmbbo->rval);
|
||
strcat(pdpvt->msg, tempMsg); /* append current delay setting */
|
||
break;
|
||
}
|
||
|
||
gpibCmds[pdpvt->parm].type = GPIBWRITE; /* set cmnd back to write */
|
||
|
||
return(OK); /* aoGpibWork or mbboGpibWork will call xxGpibWork */
|
||
}
|
||
/**************************************************************************
|
||
*
|
||
* This should be the end of device specific modifications.
|
||
*
|
||
**************************************************************************/
|
||
|
||
/******************************************************************************
|
||
*
|
||
* Print a report of operating statistics for all devices supported by this
|
||
* module.
|
||
*
|
||
******************************************************************************/
|
||
static long
|
||
report()
|
||
{
|
||
struct hwpvt *phwpvt;
|
||
|
||
printf("DG535 device support loaded:\n");
|
||
|
||
phwpvt = hwpvtHead;
|
||
|
||
while (phwpvt != NULL)
|
||
{
|
||
if (phwpvt->linkType == GPIB_IO)
|
||
printf(" NI-link %d, node %d, timeouts %ld\n", phwpvt->link, phwpvt->device, phwpvt->tmoCount);
|
||
else if (phwpvt->linkType == BBGPIB_IO)
|
||
printf(" BB-link %d, bug %d, node %d, timeouts %ld\n", phwpvt->link, phwpvt->bug, phwpvt->device, phwpvt->tmoCount);
|
||
|
||
phwpvt = phwpvt->next;
|
||
}
|
||
return(0);
|
||
}
|
||
|
||
|
||
/******************************************************************************
|
||
*
|
||
* Initialization for device support
|
||
* This is called one time before any records are initialized with a parm
|
||
* value of 0. And then again AFTER all record-level init is complete
|
||
* with a param value of 1.
|
||
*
|
||
******************************************************************************/
|
||
static long
|
||
init_dev_sup()
|
||
{
|
||
|
||
static char firstTime = 1;
|
||
|
||
if (!firstTime)
|
||
{
|
||
return(OK);
|
||
}
|
||
firstTime = 0;
|
||
logMsg("dg535 Device Support Initializing ...\n");
|
||
|
||
return(OK);
|
||
}
|
||
|
||
/******************************************************************************
|
||
*
|
||
* Initialization routines.
|
||
*
|
||
******************************************************************************/
|
||
/******************************************************************************
|
||
*
|
||
* ai record init
|
||
*
|
||
******************************************************************************/
|
||
|
||
static long
|
||
init_rec_ai(pai, process)
|
||
struct aiRecord *pai;
|
||
void (*process)();
|
||
{
|
||
long result;
|
||
|
||
/* Do common initialization */
|
||
if (result = init_rec_xx((caddr_t) pai, &pai->inp, GPIB_AI))
|
||
{
|
||
return(result);
|
||
}
|
||
/* Do initialization of other fields in the record that are unique
|
||
* to this record type */
|
||
|
||
((struct gpibDpvt *)pai->dpvt)->head.workStart = aiGpibWork;
|
||
|
||
return(0);
|
||
}
|
||
|
||
/******************************************************************************
|
||
*
|
||
* ao record init
|
||
*
|
||
******************************************************************************/
|
||
|
||
static long
|
||
init_rec_ao(pao, process)
|
||
struct aoRecord *pao;
|
||
void (*process)();
|
||
{
|
||
long result;
|
||
|
||
/* do common initialization */
|
||
if (result = init_rec_xx((caddr_t) pao, &pao->out, GPIB_AO))
|
||
{
|
||
return(result);
|
||
}
|
||
/* do initialization of other fields in the record that are unique
|
||
* to this record type */
|
||
|
||
((struct gpibDpvt *)pao->dpvt)->head.workStart = aoGpibWork;
|
||
|
||
return(0);
|
||
}
|
||
|
||
/******************************************************************************
|
||
*
|
||
* bi record init
|
||
*
|
||
******************************************************************************/
|
||
|
||
static long
|
||
init_rec_bi(pbi, process)
|
||
struct biRecord *pbi;
|
||
void (*process)();
|
||
{
|
||
long result;
|
||
|
||
/* Do common initialization */
|
||
if (result = init_rec_xx((caddr_t) pbi, &pbi->inp, GPIB_BI))
|
||
{
|
||
return(result);
|
||
}
|
||
/* Do initialization of other fields in the record that are unique
|
||
* to this record type */
|
||
|
||
((struct gpibDpvt *)pbi->dpvt)->head.workStart = biGpibWork;
|
||
|
||
/* See if there are names asociated with the record that should */
|
||
/* be filled in */
|
||
if (gpibCmds[((struct gpibDpvt *)pbi->dpvt)->parm].namelist != NULL)
|
||
{
|
||
if (pbi->znam[0] == '\0')
|
||
{
|
||
strcpy(pbi->znam, gpibCmds[((struct gpibDpvt *)pbi->dpvt)->parm].namelist->item[0]);
|
||
}
|
||
if (pbi->onam[0] == '\0')
|
||
{
|
||
strcpy(pbi->onam, gpibCmds[((struct gpibDpvt *)pbi->dpvt)->parm].namelist->item[1]);
|
||
}
|
||
}
|
||
return(0);
|
||
}
|
||
|
||
/******************************************************************************
|
||
*
|
||
* bo record init
|
||
*
|
||
******************************************************************************/
|
||
|
||
static long
|
||
init_rec_bo(pbo, process)
|
||
struct boRecord *pbo;
|
||
void (*process)();
|
||
{
|
||
long result;
|
||
|
||
/* do common initialization */
|
||
if (result = init_rec_xx((caddr_t) pbo, &pbo->out, GPIB_BO))
|
||
{
|
||
return(result);
|
||
}
|
||
/* do initialization of other fields in the record that are unique
|
||
* to this record type */
|
||
|
||
((struct gpibDpvt *)pbo->dpvt)->head.workStart = boGpibWork;
|
||
|
||
/* see if there are names asociated with the record that should */
|
||
/* be filled in */
|
||
if (gpibCmds[((struct gpibDpvt *)pbo->dpvt)->parm].namelist != NULL)
|
||
{
|
||
if (pbo->znam[0] == '\0')
|
||
{
|
||
strcpy(pbo->znam, gpibCmds[((struct gpibDpvt *)pbo->dpvt)->parm].namelist->item[0]);
|
||
}
|
||
if (pbo->onam[0] == '\0')
|
||
{
|
||
strcpy(pbo->onam, gpibCmds[((struct gpibDpvt *)pbo->dpvt)->parm].namelist->item[1]);
|
||
}
|
||
}
|
||
return(0);
|
||
}
|
||
|
||
/******************************************************************************
|
||
*
|
||
* mbbi record init
|
||
*
|
||
******************************************************************************/
|
||
|
||
static long
|
||
init_rec_mbbi(pmbbi, process)
|
||
struct mbbiRecord *pmbbi;
|
||
void (*process)();
|
||
{
|
||
long result;
|
||
char message[100];
|
||
struct gpibDpvt *dpvt; /* pointer to gpibDpvt, not yet assigned */
|
||
int name_ct; /* for filling in the name strings */
|
||
char *name_ptr; /* index into name list array */
|
||
unsigned long *val_ptr; /* indev into the value list array */
|
||
|
||
/* do common initialization */
|
||
if (result = init_rec_xx((caddr_t)pmbbi, &pmbbi->inp, GPIB_MBBI))
|
||
{
|
||
return(result);
|
||
}
|
||
|
||
dpvt = (struct gpibDpvt *)pmbbi->dpvt; /* init pointer to gpibDpvt */
|
||
|
||
/* do initialization of other fields in the record that are unique
|
||
* to this record type */
|
||
|
||
dpvt->head.workStart = mbbiGpibWork;
|
||
|
||
/* see if there are names asociated with the record that should */
|
||
/* be filled in */
|
||
if (gpibCmds[dpvt->parm].namelist != NULL)
|
||
{
|
||
if (gpibCmds[dpvt->parm].namelist->value == NULL)
|
||
{
|
||
sprintf(message, "devDg535Gpib: MBBI value list wrong for param #%d\n", dpvt->parm);
|
||
logMsg(message);
|
||
return(ERROR);
|
||
}
|
||
pmbbi->nobt = gpibCmds[dpvt->parm].namelist->nobt;
|
||
name_ct = 0; /* current name string element */
|
||
name_ptr = pmbbi->zrst; /* first name string element */
|
||
val_ptr = &(pmbbi->zrvl); /* first value element */
|
||
while (name_ct < gpibCmds[dpvt->parm].namelist->count)
|
||
{
|
||
if (name_ptr[0] == '\0')
|
||
{
|
||
strcpy(name_ptr, gpibCmds[dpvt->parm].namelist->item[name_ct]);
|
||
*val_ptr = gpibCmds[dpvt->parm].namelist->value[name_ct];
|
||
}
|
||
name_ct++;
|
||
name_ptr += sizeof(pmbbi->zrst);
|
||
val_ptr++;
|
||
}
|
||
}
|
||
return(0);
|
||
}
|
||
|
||
/******************************************************************************
|
||
*
|
||
* mbbo record init
|
||
*
|
||
******************************************************************************/
|
||
|
||
static long
|
||
init_rec_mbbo(pmbbo, process)
|
||
struct mbboRecord *pmbbo;
|
||
void (*process)();
|
||
{
|
||
long result;
|
||
char message[100];
|
||
struct gpibDpvt *dpvt; /* pointer to gpibDpvt, not yet assigned */
|
||
int name_ct; /* for filling in the name strings */
|
||
char *name_ptr; /* index into name list array */
|
||
unsigned long *val_ptr; /* indev into the value list array */
|
||
|
||
/* do common initialization */
|
||
if (result = init_rec_xx((caddr_t)pmbbo, &pmbbo->out, GPIB_MBBO))
|
||
{
|
||
return(result);
|
||
}
|
||
|
||
dpvt = (struct gpibDpvt *)pmbbo->dpvt; /* init pointer to gpibDpvt */
|
||
|
||
/* do initialization of other fields in the record that are unique
|
||
* to this record type */
|
||
|
||
dpvt->head.workStart = mbboGpibWork;
|
||
|
||
/* see if there are names asociated with the record that should */
|
||
/* be filled in */
|
||
if (gpibCmds[dpvt->parm].namelist != NULL)
|
||
{
|
||
if (gpibCmds[dpvt->parm].namelist->value == NULL)
|
||
{
|
||
sprintf(message, "devDg535Gpib: MBBO value list wrong for param #%d\
|
||
n", dpvt->parm);
|
||
logMsg(message);
|
||
return(ERROR);
|
||
}
|
||
|
||
pmbbo->nobt = gpibCmds[dpvt->parm].namelist->nobt;
|
||
name_ct = 0; /* current name string element */
|
||
name_ptr = pmbbo->zrst; /* first name string element */
|
||
val_ptr = &(pmbbo->zrvl); /* first value element */
|
||
while (name_ct < gpibCmds[dpvt->parm].namelist->count)
|
||
{
|
||
if (name_ptr[0] == '\0')
|
||
{
|
||
strcpy(name_ptr, gpibCmds[dpvt->parm].namelist->item[name_ct]);
|
||
*val_ptr = gpibCmds[dpvt->parm].namelist->value[name_ct];
|
||
}
|
||
name_ct++;
|
||
name_ptr += sizeof(pmbbo->zrst);
|
||
val_ptr++;
|
||
}
|
||
}
|
||
return(2);
|
||
}
|
||
|
||
/******************************************************************************
|
||
*
|
||
* stringin record init
|
||
*
|
||
******************************************************************************/
|
||
|
||
static long
|
||
init_rec_stringin(pstringin, process)
|
||
struct stringinRecord *pstringin;
|
||
void (*process)();
|
||
{
|
||
long result;
|
||
struct gpibDpvt *dpvt; /* pointer to gpibDpvt, not yet assigned */
|
||
|
||
/* do common initialization */
|
||
if (result = init_rec_xx((caddr_t) pstringin, &pstringin->inp, GPIB_SI))
|
||
{
|
||
return(result);
|
||
}
|
||
dpvt = (struct gpibDpvt *)pstringin->dpvt; /* init pointer to gpibDpvt */
|
||
|
||
/* do initialization of other fields in the record that are unique
|
||
* to this record type */
|
||
|
||
dpvt->head.workStart = stringinGpibWork;
|
||
|
||
return(0);
|
||
}
|
||
|
||
/******************************************************************************
|
||
*
|
||
* stringout record init
|
||
*
|
||
******************************************************************************/
|
||
|
||
static long
|
||
init_rec_stringout(pstringout, process)
|
||
struct stringoutRecord *pstringout;
|
||
void (*process)();
|
||
{
|
||
long result;
|
||
struct gpibDpvt *dpvt; /* pointer to gpibDpvt, not yet assigned */
|
||
|
||
/* do common initialization */
|
||
if (result = init_rec_xx((caddr_t) pstringout, &pstringout->out, GPIB_SO))
|
||
{
|
||
return(result);
|
||
}
|
||
|
||
dpvt = (struct gpibDpvt *)pstringout->dpvt; /* init pointer to gpibDpvt */
|
||
|
||
/* do initialization of other fields in the record that are unique
|
||
* to this record type */
|
||
|
||
dpvt->head.workStart = stringoutGpibWork;
|
||
|
||
return(0);
|
||
}
|
||
|
||
/******************************************************************************
|
||
*
|
||
* This init routine is common to all record types
|
||
*
|
||
******************************************************************************/
|
||
static long
|
||
init_rec_xx(prec, plink, rec_typ)
|
||
struct dbCommon *prec;
|
||
struct link *plink;
|
||
int rec_typ;
|
||
{
|
||
struct gpibDpvt *pdpvt;
|
||
struct dbCommon *pdbCommon = (struct dbCommon *)prec;
|
||
char message[100];
|
||
struct gpibCmd *pCmd;
|
||
char foundIt;
|
||
int bbnode;
|
||
|
||
/* allocate space for the private structure */
|
||
pdpvt = (struct gpibDpvt *) malloc(sizeof(struct gpibDpvt));
|
||
prec->dpvt = (void *) pdpvt;
|
||
|
||
pdpvt->precord = prec;
|
||
pdpvt->parm = -1; /* In case the sscanf fails */
|
||
pdpvt->linkType = plink->type;
|
||
|
||
switch (plink->type) {
|
||
case GPIB_IO: /* Is a straight Network Instruments link */
|
||
pdpvt->head.link = plink->value.gpibio.link; /* NI link number */
|
||
pdpvt->head.device = plink->value.gpibio.addr; /* gpib dev address */
|
||
sscanf(plink->value.gpibio.parm, "%hd", &(pdpvt->parm));
|
||
pdpvt->head.bitBusDpvt = NULL; /* no bitbus data needed */
|
||
bbnode = -1;
|
||
break;
|
||
|
||
case BBGPIB_IO: /* Is a bitbus -> gpib link */
|
||
pdpvt->head.device = plink->value.bbgpibio.gpibaddr; /* dev address */
|
||
sscanf(plink->value.bbgpibio.parm, "%hd", &(pdpvt->parm));
|
||
pdpvt->head.bitBusDpvt = (struct dpvtBitBusHead *) malloc(sizeof(struct dpvtBitBusHead));
|
||
pdpvt->head.bitBusDpvt->txMsg = (struct bitBusMsg *) malloc(sizeof(struct bitBusMsg));
|
||
pdpvt->head.bitBusDpvt->rxMsg = (struct bitBusMsg *) malloc(sizeof(struct bitBusMsg));
|
||
pdpvt->head.bitBusDpvt->txMsg->node = plink->value.bbgpibio.bbaddr; /* bug node address */
|
||
bbnode = plink->value.bbgpibio.bbaddr;
|
||
pdpvt->head.bitBusDpvt->link = plink->value.bbgpibio.link; /* bug link number */
|
||
pdpvt->head.link = plink->value.bbgpibio.link;
|
||
pdpvt->head.bitBusDpvt->rxMaxLen = sizeof(struct bitBusMsg);
|
||
break;
|
||
|
||
default:
|
||
strcpy(message, pdbCommon->name);
|
||
strcat(message,": init_record : GPIB link type is invalid");
|
||
errMessage(S_db_badField, message);
|
||
return(S_db_badField);
|
||
break;
|
||
}
|
||
/* Try to find the hardware private structure */
|
||
foundIt = 0;
|
||
pdpvt->phwpvt = hwpvtHead;
|
||
while ((pdpvt->phwpvt != NULL) && !foundIt)
|
||
{
|
||
if (pdpvt->phwpvt->linkType == plink->type &&
|
||
pdpvt->phwpvt->link == pdpvt->head.link &&
|
||
pdpvt->phwpvt->device == pdpvt->head.device)
|
||
if (plink->type == BBGPIB_IO)
|
||
{
|
||
if (pdpvt->phwpvt->bug == pdpvt->head.bitBusDpvt->txMsg->node)
|
||
foundIt = 1;
|
||
}
|
||
else
|
||
foundIt = 1;
|
||
else
|
||
pdpvt->phwpvt = pdpvt->phwpvt->next; /* check the next one */
|
||
}
|
||
if (!foundIt)
|
||
{ /* I couldn't find it. Allocate a new one */
|
||
pdpvt->phwpvt = (struct hwpvt *) malloc(sizeof (struct hwpvt));
|
||
pdpvt->phwpvt->next = hwpvtHead; /* put at the top of the list */
|
||
hwpvtHead = pdpvt->phwpvt;
|
||
|
||
pdpvt->phwpvt->linkType = plink->type;
|
||
pdpvt->phwpvt->link = pdpvt->head.link;
|
||
pdpvt->phwpvt->device = pdpvt->head.device;
|
||
|
||
if (pdpvt->phwpvt->linkType == BBGPIB_IO)
|
||
pdpvt->phwpvt->bug = pdpvt->head.bitBusDpvt->txMsg->node;
|
||
|
||
pdpvt->phwpvt->tmoVal = 0;
|
||
pdpvt->phwpvt->tmoCount = 0;
|
||
pdpvt->phwpvt->srqCallback = NULL;
|
||
pdpvt->phwpvt->parm = (caddr_t)NULL;
|
||
}
|
||
|
||
/* Check for valid GPIB address */
|
||
if ((pdpvt->head.device < 0) || (pdpvt->head.device >= IBAPERLINK))
|
||
{
|
||
strcpy(message, pdbCommon->name);
|
||
strcat(message,": init_record : GPIB address out of range");
|
||
errMessage(S_db_badField,message);
|
||
return(S_db_badField);
|
||
}
|
||
|
||
/* Check for valid param entry */
|
||
if ((pdpvt->parm < 0) || (pdpvt->parm > NUMPARAMS))
|
||
{
|
||
strcpy(message, pdbCommon->name);
|
||
strcat(message,": init_record : Parameter # out of range");
|
||
errMessage(S_db_badField,message);
|
||
return(S_db_badField);
|
||
}
|
||
|
||
/* make sure that the record type matches the GPIB port type (jrw) */
|
||
if (gpibCmds[pdpvt->parm].rec_typ != rec_typ )
|
||
{
|
||
strcpy(message, pdbCommon->name);
|
||
strcat(message,": init_record: record type invalid for spec'd param #");
|
||
errMessage(S_db_badField,message);
|
||
return(S_db_badField);
|
||
}
|
||
|
||
pCmd = &gpibCmds[pdpvt->parm];
|
||
if(pCmd->msgLen > 0)
|
||
pdpvt->msg = (char *)(malloc(pCmd->msgLen));
|
||
if(pCmd->rspLen > 0)
|
||
pdpvt->rsp = (char *)(malloc(pCmd->rspLen));
|
||
|
||
#ifdef _SRQSUPPORT_
|
||
/*
|
||
* Ok to re-register a handler for the same device, just don't do it after
|
||
* init time is over!
|
||
*/
|
||
(*(drvGpib.registerSrqCallback))(pdpvt->linkType, pdpvt->head.link,
|
||
bbnode, pdpvt->head.device, srqHandler, pdpvt->phwpvt);
|
||
#endif
|
||
|
||
/* fill in the required stuff for the callcack task (jrw) */
|
||
pdpvt->process = processCallback;
|
||
pdpvt->processPri = priorityLow;
|
||
|
||
return(0);
|
||
}
|
||
|
||
/******************************************************************************
|
||
*
|
||
* These are the functions that are called to actually communicate with
|
||
* the GPIB device.
|
||
*
|
||
******************************************************************************/
|
||
static long
|
||
read_ai(pai)
|
||
struct aiRecord *pai;
|
||
{
|
||
struct gpibDpvt *pdpvt = (struct gpibDpvt *)(pai->dpvt);
|
||
struct gpibCmd *pCmd;
|
||
|
||
pCmd = &gpibCmds[pdpvt->parm];
|
||
if (pai->pact)
|
||
{
|
||
if (dg535Debug)
|
||
logMsg("read_ai with PACT = 1\n");
|
||
return(2); /* work is all done, return '2' to indicate val */
|
||
}
|
||
else if (pCmd->type == GPIBSOFT)
|
||
{
|
||
(*pCmd->convert)(pdpvt,pCmd->P1,pCmd->P2, pCmd->P3);
|
||
return(0);
|
||
}
|
||
else
|
||
{ /* put pointer to dpvt field on ring buffer */
|
||
if (dg535Debug)
|
||
logMsg("read_ai with PACT = 0\n");
|
||
if((*(drvGpib.qGpibReq))(pdpvt->linkType, pdpvt->head.link, pdpvt, pCmd->pri) == ERROR)
|
||
{
|
||
setPvSevr(pai,MAJOR_ALARM,VALID_ALARM);
|
||
return(0);
|
||
}
|
||
return(1);
|
||
}
|
||
}
|
||
|
||
static long
|
||
write_ao(pao)
|
||
struct aoRecord *pao;
|
||
{
|
||
struct gpibDpvt *pdpvt = (struct gpibDpvt *)(pao->dpvt);
|
||
struct gpibCmd *pCmd;
|
||
|
||
pCmd = &gpibCmds[pdpvt->parm];
|
||
|
||
if (pao->pact)
|
||
{
|
||
return(0); /* work is all done, finish processing */
|
||
}
|
||
else if (pCmd->type == GPIBSOFT)
|
||
{
|
||
(*pCmd->convert)(pdpvt,pCmd->P1,pCmd->P2, pCmd->P3);
|
||
return(0);
|
||
}
|
||
else
|
||
{ /* put pointer to dvpt field on ring buffer */
|
||
if((*(drvGpib.qGpibReq))(pdpvt->linkType, pdpvt->head.link, pdpvt, pCmd->pri) == ERROR)
|
||
{
|
||
setPvSevr(pao,WRITE_ALARM,VALID_ALARM);
|
||
return(0);
|
||
}
|
||
return(1);
|
||
}
|
||
}
|
||
|
||
static long
|
||
read_bi(pbi)
|
||
struct biRecord *pbi;
|
||
{
|
||
struct gpibDpvt *pdpvt = (struct gpibDpvt *)(pbi->dpvt);
|
||
struct gpibCmd *pCmd;
|
||
|
||
pCmd = &gpibCmds[pdpvt->parm];
|
||
|
||
if (pbi->pact)
|
||
{
|
||
return(0); /* work is all done, finish processing */
|
||
}
|
||
else if (pCmd->type == GPIBSOFT)
|
||
{
|
||
(*pCmd->convert)(pdpvt,pCmd->P1,pCmd->P2, pCmd->P3);
|
||
return(0);
|
||
}
|
||
else
|
||
{ /* put pointer to dvpt field on ring buffer */
|
||
if((*(drvGpib.qGpibReq))(pdpvt->linkType, pdpvt->head.link, pdpvt, pCmd->pri) == ERROR)
|
||
{
|
||
setPvSevr(pbi,READ_ALARM,VALID_ALARM);
|
||
return(0);
|
||
}
|
||
return(1);
|
||
}
|
||
}
|
||
|
||
|
||
static long
|
||
write_bo(pbo)
|
||
struct boRecord *pbo;
|
||
{
|
||
struct gpibDpvt *pdpvt = (struct gpibDpvt *)(pbo->dpvt);
|
||
struct gpibCmd *pCmd;
|
||
|
||
pCmd = &gpibCmds[pdpvt->parm];
|
||
|
||
if (pbo->pact)
|
||
{
|
||
return(0); /* work is all done, finish processing */
|
||
}
|
||
else if (pCmd->type == GPIBSOFT)
|
||
{
|
||
(*pCmd->convert)(pdpvt,pCmd->P1,pCmd->P2, pCmd->P3);
|
||
return(0);
|
||
}
|
||
else
|
||
{ /* put pointer to dvpt field on ring buffer */
|
||
if((*(drvGpib.qGpibReq))(pdpvt->linkType, pdpvt->head.link, pdpvt, pCmd->pri) == ERROR)
|
||
{
|
||
setPvSevr(pbo,WRITE_ALARM,VALID_ALARM);
|
||
return(0);
|
||
}
|
||
return(1);
|
||
}
|
||
}
|
||
|
||
static long
|
||
read_mbbi(pmbbi)
|
||
struct mbbiRecord *pmbbi;
|
||
{
|
||
struct gpibDpvt *pdpvt = (struct gpibDpvt *)(pmbbi->dpvt);
|
||
struct gpibCmd *pCmd;
|
||
|
||
pCmd = &gpibCmds[pdpvt->parm];
|
||
|
||
if (pmbbi->pact)
|
||
{
|
||
return(0); /* work is all done, finish processing */
|
||
}
|
||
else if (pCmd->type == GPIBSOFT)
|
||
{
|
||
(*pCmd->convert)(pdpvt,pCmd->P1,pCmd->P2, pCmd->P3);
|
||
return(0);
|
||
}
|
||
else
|
||
{ /* put pointer to dvpt field on ring buffer */
|
||
if((*(drvGpib.qGpibReq))(pdpvt->linkType, pdpvt->head.link, pdpvt, pCmd->pri) == ERROR)
|
||
{
|
||
setPvSevr(pmbbi,READ_ALARM,VALID_ALARM);
|
||
return(0);
|
||
}
|
||
return(1);
|
||
}
|
||
}
|
||
|
||
|
||
static long
|
||
write_mbbo(pmbbo)
|
||
struct mbboRecord *pmbbo;
|
||
{
|
||
struct gpibDpvt *pdpvt = (struct gpibDpvt *)(pmbbo->dpvt);
|
||
struct gpibCmd *pCmd;
|
||
|
||
pCmd = &gpibCmds[pdpvt->parm];
|
||
|
||
if (pmbbo->pact)
|
||
{
|
||
return(0); /* work is all done, finish processing */
|
||
}
|
||
else if (pCmd->type == GPIBSOFT)
|
||
{
|
||
(*pCmd->convert)(pdpvt,pCmd->P1,pCmd->P2, pCmd->P3);
|
||
return(0);
|
||
}
|
||
else
|
||
{ /* put pointer to dvpt field on ring buffer */
|
||
if((*(drvGpib.qGpibReq))(pdpvt->linkType, pdpvt->head.link, pdpvt, pCmd->pri) == ERROR)
|
||
{
|
||
setPvSevr(pmbbo,WRITE_ALARM,VALID_ALARM);
|
||
return(0);
|
||
}
|
||
return(1);
|
||
}
|
||
}
|
||
|
||
static long
|
||
read_stringin(pstringin)
|
||
struct stringinRecord *pstringin;
|
||
{
|
||
struct gpibDpvt *pdpvt = (struct gpibDpvt *)(pstringin->dpvt);
|
||
struct gpibCmd *pCmd;
|
||
|
||
pCmd = &gpibCmds[pdpvt->parm];
|
||
if (pstringin->pact)
|
||
{
|
||
if (dg535Debug)
|
||
logMsg("read_stringin with PACT = 1\n");
|
||
return(2); /* work is all done, return '2' to indicate val */
|
||
}
|
||
else if (pCmd->type == GPIBSOFT)
|
||
{
|
||
(*pCmd->convert)(pdpvt,pCmd->P1,pCmd->P2, pCmd->P3);
|
||
return(0);
|
||
}
|
||
else
|
||
{ /* put pointer to dvpt field on ring buffer */
|
||
if (dg535Debug)
|
||
logMsg("read_stringin with PACT = 0\n");
|
||
if((*(drvGpib.qGpibReq))(pdpvt->linkType, pdpvt->head.link, pdpvt, pCmd->pri) == ERROR)
|
||
{
|
||
setPvSevr(pstringin,MAJOR_ALARM,VALID_ALARM);
|
||
return(0);
|
||
}
|
||
return(1);
|
||
}
|
||
}
|
||
|
||
static long
|
||
write_stringout(pstringout)
|
||
struct stringoutRecord *pstringout;
|
||
{
|
||
struct gpibDpvt *pdpvt = (struct gpibDpvt *)(pstringout->dpvt);
|
||
struct gpibCmd *pCmd;
|
||
|
||
pCmd = &gpibCmds[pdpvt->parm];
|
||
|
||
if (pstringout->pact)
|
||
{
|
||
return(0); /* work is all done, finish processing */
|
||
}
|
||
else if (pCmd->type == GPIBSOFT)
|
||
{
|
||
(*pCmd->convert)(pdpvt,pCmd->P1,pCmd->P2, pCmd->P3);
|
||
return(0);
|
||
}
|
||
else
|
||
{ /* put pointer to dvpt field on ring buffer */
|
||
if((*(drvGpib.qGpibReq))(pdpvt->linkType, pdpvt->head.link, pdpvt, pCmd->pri) == ERROR)
|
||
{
|
||
setPvSevr(pstringout,WRITE_ALARM,VALID_ALARM);
|
||
return(0);
|
||
}
|
||
return(1);
|
||
}
|
||
}
|
||
|
||
/******************************************************************************
|
||
*
|
||
* Routines that do the actual GPIB work. They are called by the linkTask.
|
||
*
|
||
******************************************************************************/
|
||
|
||
static int
|
||
aiGpibWork(pdpvt)
|
||
struct gpibDpvt *pdpvt;
|
||
{
|
||
struct aiRecord *pai= ((struct aiRecord *)(pdpvt->precord));
|
||
struct gpibCmd *pCmd = &gpibCmds[pdpvt->parm];
|
||
|
||
/* go send predefined cmd msg and read response into msg[] */
|
||
|
||
if(dg535Debug)
|
||
logMsg("aiGpibWork: starting ...\n");
|
||
|
||
if (xxGpibWork(pdpvt, pCmd->type) == ERROR)
|
||
{
|
||
setPvSevr(pai,READ_ALARM,VALID_ALARM);
|
||
|
||
if(dg535Debug)
|
||
logMsg("aiGpibWork: calling process ...\n");
|
||
|
||
pdpvt->head.header.callback.finishProc = pdpvt->process;
|
||
pdpvt->head.header.callback.priority = pdpvt->processPri;
|
||
callbackRequest(pdpvt);
|
||
}
|
||
else
|
||
{
|
||
if (pCmd->type != GPIBREADW)
|
||
aiGpibFinish(pdpvt); /* If not waiting on SRQ, finish */
|
||
else
|
||
{
|
||
pdpvt->phwpvt->srqCallback = aiGpibSrq; /* mark the handler */
|
||
pdpvt->phwpvt->parm = (caddr_t)pdpvt; /* mark the handler */
|
||
return(BUSY); /* indicate device still in use */
|
||
}
|
||
}
|
||
return(IDLE); /* indicate device is now idle */
|
||
}
|
||
|
||
static int
|
||
aiGpibSrq(pdpvt, srqStatus)
|
||
struct gpibDpvt *pdpvt;
|
||
int srqStatus;
|
||
{
|
||
if (dg535Debug || ibSrqDebug)
|
||
logMsg("aiGpibSrq(0x%08.8X, 0x%02.2X): processing srq\n", pdpvt, srqStatus);
|
||
|
||
/* do actual SRQ processing in here */
|
||
|
||
pdpvt->phwpvt->srqCallback = NULL; /* unmark the handler */
|
||
pdpvt->phwpvt->parm = (caddr_t)NULL;
|
||
|
||
aiGpibFinish(pdpvt); /* and finish the processing */
|
||
return(IDLE); /* indicate device now idle */
|
||
}
|
||
|
||
static int
|
||
aiGpibFinish(pdpvt)
|
||
struct gpibDpvt *pdpvt;
|
||
{
|
||
double value;
|
||
struct aiRecord *pai = ((struct aiRecord *)(pdpvt->precord));
|
||
struct gpibCmd *pCmd = &gpibCmds[pdpvt->parm];
|
||
|
||
if (pCmd->convert != NULL)
|
||
{
|
||
if(dg535Debug)
|
||
logMsg("aiGpibWork: calling convert ...\n");
|
||
(*(pCmd->convert))(pdpvt,pCmd->P1,pCmd->P2, pCmd->P3);
|
||
if(dg535Debug)
|
||
logMsg("aiGpibWork: returned from convert ...\n");
|
||
}
|
||
else /* interpret msg with predefined format and write into .val */
|
||
{
|
||
/* scan response string, return value will be 1 if successful */
|
||
if(sscanf(pdpvt->msg,pCmd->format,&value))
|
||
{
|
||
pai->val = value;
|
||
}
|
||
else /* sscanf did not find or assign the parameter */
|
||
{
|
||
setPvSevr(pai,READ_ALARM,VALID_ALARM);
|
||
}
|
||
}
|
||
if(dg535Debug)
|
||
logMsg("aiGpibWork: calling process ...\n");
|
||
|
||
pdpvt->head.header.callback.finishProc = pdpvt->process;
|
||
pdpvt->head.header.callback.priority = pdpvt->processPri;
|
||
callbackRequest(pdpvt);
|
||
|
||
return(0);
|
||
}
|
||
|
||
static int
|
||
aoGpibWork(pdpvt)
|
||
struct gpibDpvt *pdpvt;
|
||
{
|
||
int cnvrtStat = OK;
|
||
struct aoRecord *pao= ((struct aoRecord *)(pdpvt->precord));
|
||
struct gpibCmd *pCmd = &gpibCmds[pdpvt->parm];
|
||
|
||
/* generate command string to be sent */
|
||
|
||
/* call convert routine, if defined */
|
||
if (pCmd->convert != NULL)
|
||
{
|
||
cnvrtStat = (*(pCmd->convert))(pdpvt, pCmd->P1,pCmd->P2, pCmd->P3);
|
||
}
|
||
else /* generate msg using predefined format and current val */
|
||
{
|
||
sprintf(pdpvt->msg, pCmd->format, pao->val);
|
||
}
|
||
|
||
/* go access board with this message, unless convert was unsuccessful */
|
||
if ((cnvrtStat == ERROR) || (xxGpibWork(pdpvt, pCmd->type) == ERROR))
|
||
{
|
||
setPvSevr(pao,WRITE_ALARM,VALID_ALARM);
|
||
}
|
||
|
||
pdpvt->head.header.callback.finishProc = pdpvt->process;
|
||
pdpvt->head.header.callback.priority = pdpvt->processPri;
|
||
callbackRequest(pdpvt); /* jrw */
|
||
}
|
||
|
||
static int
|
||
biGpibWork(pdpvt)
|
||
struct gpibDpvt *pdpvt;
|
||
{
|
||
struct biRecord *pbi= ((struct biRecord *)(pdpvt->precord));
|
||
struct gpibCmd *pCmd = &gpibCmds[pdpvt->parm];
|
||
|
||
/* go send predefined cmd msg and read response into msg[] */
|
||
|
||
if (xxGpibWork(pdpvt, pCmd->type) == ERROR)
|
||
{
|
||
setPvSevr(pbi,READ_ALARM,VALID_ALARM);
|
||
|
||
if(dg535Debug)
|
||
logMsg("aiGpibWork: calling process ...\n");
|
||
|
||
pdpvt->head.header.callback.finishProc = pdpvt->process;
|
||
pdpvt->head.header.callback.priority = pdpvt->processPri;
|
||
callbackRequest(pdpvt);
|
||
}
|
||
else /* interpret response that came back */
|
||
{
|
||
if (pCmd->type != GPIBREADW)
|
||
biGpibFinish(pdpvt); /* If not waiting on SRQ, finish */
|
||
else
|
||
{
|
||
pdpvt->phwpvt->srqCallback = biGpibSrq; /* mark the handler */
|
||
pdpvt->phwpvt->parm = (caddr_t)pdpvt; /* mark the handler */
|
||
return(BUSY); /* indicate device still in use */
|
||
}
|
||
}
|
||
return(IDLE);
|
||
}
|
||
|
||
static int
|
||
biGpibSrq(pdpvt, srqStatus)
|
||
struct gpibDpvt *pdpvt;
|
||
int srqStatus;
|
||
{
|
||
if (dg535Debug || ibSrqDebug)
|
||
logMsg("biGpibSrq(0x%08.8X, 0x%02.2X): processing srq\n", pdpvt, srqStatus);
|
||
|
||
/* do actual SRQ processing in here */
|
||
|
||
pdpvt->phwpvt->srqCallback = NULL; /* unmark the handler */
|
||
pdpvt->phwpvt->parm = (caddr_t)NULL; /* unmark the handler */
|
||
|
||
biGpibFinish(pdpvt); /* and finish the processing */
|
||
return(IDLE); /* indicate device now idle */
|
||
}
|
||
|
||
static int
|
||
biGpibFinish(pdpvt)
|
||
struct gpibDpvt *pdpvt;
|
||
{
|
||
unsigned long value;
|
||
struct biRecord *pbi= ((struct biRecord *)(pdpvt->precord));
|
||
struct gpibCmd *pCmd = &gpibCmds[pdpvt->parm];
|
||
|
||
if (pCmd->convert != NULL)
|
||
{
|
||
(*(pCmd->convert))(pdpvt,pCmd->P1,pCmd->P2, pCmd->P3);
|
||
}
|
||
else /* interpret msg with predefined format and write into .rval */
|
||
{
|
||
/* scan response string, return value will be 1 if successful */
|
||
if(sscanf(pdpvt->msg,pCmd->format, &value))
|
||
{
|
||
pbi->rval = value;
|
||
}
|
||
else /* sscanf did not find or assign the parameter */
|
||
{
|
||
setPvSevr(pbi,READ_ALARM,VALID_ALARM);
|
||
}
|
||
}
|
||
|
||
pdpvt->head.header.callback.finishProc = pdpvt->process;
|
||
pdpvt->head.header.callback.priority = pdpvt->processPri;
|
||
callbackRequest(pdpvt); /* jrw */
|
||
|
||
return(0);
|
||
}
|
||
|
||
|
||
static int
|
||
boGpibWork(pdpvt)
|
||
struct gpibDpvt *pdpvt;
|
||
{
|
||
int cnvrtStat = OK;
|
||
int strStat = OK;
|
||
struct boRecord *pbo= ((struct boRecord *)(pdpvt->precord));
|
||
struct gpibCmd *pCmd = &gpibCmds[pdpvt->parm];
|
||
|
||
/* generate command string to be sent */
|
||
|
||
/* call convert routine, if defined */
|
||
if (pCmd->convert != NULL)
|
||
{
|
||
cnvrtStat = (*(pCmd->convert))(pdpvt,pCmd->P1,pCmd->P2, pCmd->P3);
|
||
}
|
||
else /* generate msg using predefined format and current val */
|
||
{
|
||
sprintf(pdpvt->msg, pCmd->format, (unsigned int)pbo->val);
|
||
}
|
||
|
||
/* go access board with this message, unless convert was unsuccessful */
|
||
if ((cnvrtStat == ERROR) || (xxGpibWork(pdpvt, pCmd->type) == ERROR))
|
||
{
|
||
setPvSevr(pbo,WRITE_ALARM,VALID_ALARM);
|
||
}
|
||
|
||
pdpvt->head.header.callback.finishProc = pdpvt->process;
|
||
pdpvt->head.header.callback.priority = pdpvt->processPri;
|
||
callbackRequest(pdpvt);
|
||
}
|
||
|
||
static int
|
||
mbbiGpibWork(pdpvt)
|
||
struct gpibDpvt *pdpvt;
|
||
{
|
||
struct mbbiRecord *pmbbi= ((struct mbbiRecord *)(pdpvt->precord));
|
||
struct gpibCmd *pCmd = &gpibCmds[pdpvt->parm];
|
||
|
||
/* go send predefined cmd msg and read string response into msg[] */
|
||
|
||
if (xxGpibWork(pdpvt, pCmd->type) == ERROR)
|
||
{
|
||
setPvSevr(pmbbi,WRITE_ALARM,VALID_ALARM);
|
||
|
||
if(dg535Debug)
|
||
logMsg("mbbiGpibWork: calling process ...\n");
|
||
|
||
pdpvt->head.header.callback.finishProc = pdpvt->process;
|
||
pdpvt->head.header.callback.priority = pdpvt->processPri;
|
||
callbackRequest(pdpvt);
|
||
}
|
||
else
|
||
{
|
||
if (pCmd->type != GPIBREADW)
|
||
mbbiGpibFinish(pdpvt); /* If not waiting on SRQ, finish */
|
||
else
|
||
{
|
||
pdpvt->phwpvt->srqCallback = mbbiGpibSrq; /* mark the handler */
|
||
pdpvt->phwpvt->parm = (caddr_t)pdpvt; /* mark the handler */
|
||
return(BUSY); /* indicate device still in use */
|
||
}
|
||
}
|
||
return(IDLE);
|
||
}
|
||
|
||
static int
|
||
mbbiGpibSrq(pdpvt, srqStatus)
|
||
struct gpibDpvt *pdpvt;
|
||
int srqStatus;
|
||
{
|
||
if (dg535Debug || ibSrqDebug)
|
||
logMsg("mbbiGpibSrq(0x%08.8X, 0x%02.2X): processing srq\n", pdpvt, srqStatus);
|
||
|
||
/* do actual SRQ processing in here */
|
||
|
||
pdpvt->phwpvt->srqCallback = NULL; /* unmark the handler */
|
||
pdpvt->phwpvt->parm = (caddr_t)NULL; /* unmark the handler */
|
||
|
||
mbbiGpibFinish(pdpvt); /* and finish the processing */
|
||
return(IDLE); /* indicate device now idle */
|
||
}
|
||
|
||
static int
|
||
mbbiGpibFinish(pdpvt)
|
||
struct gpibDpvt *pdpvt;
|
||
{
|
||
unsigned long value;
|
||
struct mbbiRecord *pmbbi= ((struct mbbiRecord *)(pdpvt->precord));
|
||
struct gpibCmd *pCmd = &gpibCmds[pdpvt->parm];
|
||
|
||
if (pCmd->convert != NULL)
|
||
{
|
||
(*(pCmd->convert))(pdpvt,pCmd->P1,pCmd->P2, pCmd->P3);
|
||
}
|
||
else /* interpret msg with predefined format and write into .rval */
|
||
{
|
||
/* scan response string, return value will be 1 if successful */
|
||
if(sscanf(pdpvt->msg, pCmd->format, &value))
|
||
{
|
||
pmbbi->rval = value;
|
||
}
|
||
else /* sscanf did not find or assign the parameter */
|
||
{
|
||
setPvSevr(pmbbi,READ_ALARM,VALID_ALARM);
|
||
}
|
||
}
|
||
pdpvt->head.header.callback.finishProc = pdpvt->process;
|
||
pdpvt->head.header.callback.priority = pdpvt->processPri;
|
||
callbackRequest(pdpvt);
|
||
|
||
return(0);
|
||
}
|
||
|
||
static int
|
||
mbboGpibWork(pdpvt)
|
||
struct gpibDpvt *pdpvt;
|
||
{
|
||
int cnvrtStat = OK;
|
||
int strStat = OK;
|
||
struct mbboRecord *pmbbo= ((struct mbboRecord *)(pdpvt->precord));
|
||
struct gpibCmd *pCmd = &gpibCmds[pdpvt->parm];
|
||
|
||
/* generate command string to be sent */
|
||
|
||
/* call convert routine, if defined */
|
||
if (pCmd->convert != NULL)
|
||
{
|
||
cnvrtStat = (*(pCmd->convert))(pdpvt,pCmd->P1,pCmd->P2, pCmd->P3);
|
||
}
|
||
else /* generate msg using predefined format and current val */
|
||
{
|
||
sprintf(pdpvt->msg, pCmd->format, (unsigned int)pmbbo->rval);
|
||
}
|
||
|
||
/* go access board with this message, unless convert was unsuccessful */
|
||
if ((cnvrtStat == ERROR) || (xxGpibWork(pdpvt, pCmd->type) == ERROR))
|
||
{
|
||
setPvSevr(pmbbo,WRITE_ALARM,VALID_ALARM);
|
||
}
|
||
|
||
pdpvt->head.header.callback.finishProc = pdpvt->process;
|
||
pdpvt->head.header.callback.priority = pdpvt->processPri;
|
||
callbackRequest(pdpvt); /* jrw */
|
||
}
|
||
|
||
static int
|
||
stringinGpibWork(pdpvt)
|
||
struct gpibDpvt *pdpvt;
|
||
{
|
||
struct stringinRecord *pstringin=((struct stringinRecord*)(pdpvt->precord));
|
||
struct gpibCmd *pCmd = &gpibCmds[pdpvt->parm];
|
||
|
||
/* go send predefined cmd msg and read response into msg[] */
|
||
|
||
if(dg535Debug)
|
||
logMsg("stringinGpibWork: starting ...\n");
|
||
|
||
if (xxGpibWork(pdpvt, pCmd->type) == ERROR)
|
||
{
|
||
if(dg535Debug)
|
||
logMsg("stringinGpibWork: error in xxGpibWork ...\n");
|
||
setPvSevr(pstringin,READ_ALARM,VALID_ALARM);
|
||
|
||
pdpvt->head.header.callback.finishProc = pdpvt->process;
|
||
pdpvt->head.header.callback.priority = pdpvt->processPri;
|
||
callbackRequest(pdpvt); /* jrw */
|
||
}
|
||
else
|
||
{
|
||
if (pCmd->type != GPIBREADW)
|
||
stringinGpibFinish(pdpvt); /* If not waiting on SRQ, finish */
|
||
else
|
||
{
|
||
pdpvt->phwpvt->srqCallback = stringinGpibSrq; /* mark the handler */
|
||
pdpvt->phwpvt->parm = (caddr_t)pdpvt; /* mark the handler */
|
||
return(BUSY); /* indicate device still in use */
|
||
}
|
||
}
|
||
return(IDLE);
|
||
}
|
||
|
||
static int
|
||
stringinGpibSrq(pdpvt, srqStatus)
|
||
struct gpibDpvt *pdpvt;
|
||
int srqStatus;
|
||
{
|
||
if (dg535Debug || ibSrqDebug)
|
||
logMsg("stringinGpibSrq(0x%08.8X, 0x%02.2X): processing srq\n", pdpvt, srqStatus);
|
||
|
||
/* do actual SRQ processing in here */
|
||
|
||
pdpvt->phwpvt->srqCallback = NULL; /* unmark the handler */
|
||
pdpvt->phwpvt->parm = (caddr_t)NULL; /* unmark the handler */
|
||
|
||
stringinGpibFinish(pdpvt); /* and finish the processing */
|
||
return(IDLE); /* indicate device now idle */
|
||
}
|
||
|
||
static int
|
||
stringinGpibFinish(pdpvt)
|
||
struct gpibDpvt *pdpvt;
|
||
{
|
||
struct stringinRecord *pstringin=((struct stringinRecord*)(pdpvt->precord));
|
||
struct gpibCmd *pCmd = &gpibCmds[pdpvt->parm];
|
||
|
||
if (pCmd->convert != NULL)
|
||
{
|
||
if(dg535Debug)
|
||
logMsg("stringinGpibWork: calling convert ...\n");
|
||
(*(pCmd->convert))(pdpvt,pCmd->P1,pCmd->P2, pCmd->P3);
|
||
if(dg535Debug)
|
||
logMsg("stringinGpibWork: returned from convert ...\n");
|
||
}
|
||
else /* interpret msg with predefined format and write into .val */
|
||
{
|
||
/* scan response string, return value will be 1 if successful */
|
||
strncpy(pstringin->val,pdpvt->msg,39);
|
||
pstringin->val[40] = '\0';
|
||
}
|
||
pdpvt->head.header.callback.finishProc = pdpvt->process;
|
||
pdpvt->head.header.callback.priority = pdpvt->processPri;
|
||
callbackRequest(pdpvt); /* jrw */
|
||
|
||
return(0);
|
||
}
|
||
|
||
static int
|
||
stringoutGpibWork(pdpvt)
|
||
struct gpibDpvt *pdpvt;
|
||
{
|
||
int cnvrtStat = OK;
|
||
struct stringoutRecord *pstringout= ((struct stringoutRecord *)(pdpvt->precord));
|
||
struct gpibCmd *pCmd = &gpibCmds[pdpvt->parm];
|
||
|
||
/* generate command string to be sent */
|
||
|
||
/* call convert routine, if defined */
|
||
if (pCmd->convert != NULL)
|
||
{
|
||
cnvrtStat = (*(pCmd->convert))(pdpvt, pCmd->P1, pCmd->P2, pCmd->P3);
|
||
}
|
||
else /* generate msg using predefined format and current val */
|
||
{
|
||
strncpy(pdpvt->msg, pstringout->val, 40);
|
||
}
|
||
|
||
/* go access board with this message, unless convert was unsuccessful */
|
||
if ((cnvrtStat == ERROR) || (xxGpibWork(pdpvt, pCmd->type) == ERROR))
|
||
{
|
||
setPvSevr(pstringout,WRITE_ALARM,VALID_ALARM);
|
||
}
|
||
|
||
pdpvt->head.header.callback.finishProc = pdpvt->process;
|
||
pdpvt->head.header.callback.priority = pdpvt->processPri;
|
||
callbackRequest(pdpvt); /* jrw */
|
||
}
|
||
|
||
static int
|
||
xxGpibWork(pdpvt, cmdType)
|
||
struct gpibDpvt *pdpvt;
|
||
int cmdType;
|
||
{
|
||
int status; /* for GPIBREAD, contains ERROR or # of bytes read */
|
||
struct gpibCmd *pCmd = &gpibCmds[pdpvt->parm];
|
||
short ibnode = pdpvt->head.device;
|
||
short bbnode; /* In case is a bitbus->gpib type link */
|
||
|
||
/* If is a BBGPIB_IO link, the bug address is needed */
|
||
if (pdpvt->linkType == BBGPIB_IO)
|
||
bbnode = pdpvt->head.bitBusDpvt->txMsg->node;
|
||
|
||
/*
|
||
* check to see if this node has timed out within last 10 sec
|
||
*/
|
||
if(tickGet() < (pdpvt->phwpvt->tmoVal +TIME_WINDOW) )
|
||
{
|
||
if (dg535Debug)
|
||
logMsg("dg535-xxGpibWork(): timeout flush\n");
|
||
return(ERROR);
|
||
}
|
||
switch (cmdType)
|
||
{
|
||
case GPIBWRITE: /* write the message to the GPIB listen adrs */
|
||
if(dg535Debug)
|
||
logMsg("xxGpibWork : processing GPIBWRITE\n");
|
||
status = (*(drvGpib.writeIb))(pdpvt->linkType, pdpvt->head.link,
|
||
bbnode, ibnode, pdpvt->msg, strlen(pdpvt->msg));
|
||
|
||
/*
|
||
* use for devices which respond to write commands
|
||
*/
|
||
#ifdef RESPONDS_2_WRITES
|
||
if (status == ERROR)
|
||
{
|
||
break;
|
||
}
|
||
status = (*(drvGpib.readIb))(pdpvt->linkType, pdpvt->head.link,
|
||
bbnode, ibnode, pdpvt->rsp, pCmd->rspLen);
|
||
#endif
|
||
break;
|
||
|
||
case GPIBREAD: /* write the command string */
|
||
if(dg535Debug)
|
||
logMsg("xxGpibWork : processing GPIBREAD\n");
|
||
status = (*(drvGpib.writeIb))(pdpvt->linkType, pdpvt->head.link,
|
||
bbnode, ibnode, pCmd->cmd, strlen(pCmd->cmd));
|
||
if (status == ERROR)
|
||
{
|
||
break;
|
||
}
|
||
/* This falls thru to the raw read code below! */
|
||
|
||
case GPIBRAWREAD: /* for SRQs, read the data w/o a sending a command */
|
||
|
||
/* read the instrument */
|
||
status = (*(drvGpib.readIb))(pdpvt->linkType, pdpvt->head.link,
|
||
bbnode, ibnode, pdpvt->msg, pCmd->msgLen);
|
||
if (status == ERROR)
|
||
{
|
||
break;
|
||
}
|
||
else if (status >( (pCmd->msgLen) - 1) ) /* check length of resp */
|
||
{
|
||
logMsg("GPIB Response length equaled allocated space !!!\n");
|
||
pdpvt->msg[(pCmd->msgLen)-1] = '\0'; /* place \0 at end */
|
||
}
|
||
else
|
||
{
|
||
pdpvt->msg[status] = '\0'; /* terminate response with \0 */
|
||
}
|
||
break;
|
||
|
||
case GPIBREADW: /* for SRQs, write the command first */
|
||
case GPIBCMD: /* write the cmd to the GPIB listen adrs */
|
||
status = (*(drvGpib.writeIb))(pdpvt->linkType, pdpvt->head.link,
|
||
bbnode, ibnode, pCmd->cmd, strlen(pCmd->cmd));
|
||
break;
|
||
case GPIBCNTL: /* send cmd with atn line active */
|
||
status = (*(drvGpib.writeIbCmd))(pdpvt->linkType, pdpvt->head.link,
|
||
bbnode, pCmd->cmd, strlen(pCmd->cmd));
|
||
break;
|
||
}
|
||
if(dg535Debug)
|
||
logMsg("xxGpibWork : done, status = %d\n",status);
|
||
|
||
/* if error occurrs then mark it with time */
|
||
if(status == ERROR)
|
||
{
|
||
(pdpvt->phwpvt->tmoCount)++; /* count number of timeouts */
|
||
pdpvt->phwpvt->tmoVal = tickGet(); /* set last timeout time */
|
||
}
|
||
return(status);
|
||
}
|
||
|
||
/******************************************************************************
|
||
*
|
||
* This is invoked by the linkTask when an SRQ is detected from a device
|
||
* operated by this module.
|
||
*
|
||
* It calls the work routine associated with the type of record expecting
|
||
* the SRQ response.
|
||
*
|
||
* No semaphore locks are needed around the references to anything in the
|
||
* hwpvt structure, because it is static unless modified by the linkTask.
|
||
*
|
||
******************************************************************************/
|
||
|
||
#ifdef _SRQSUPPORT_
|
||
|
||
static int srqHandler(phwpvt, srqStatus)
|
||
struct hwpvt *phwpvt;
|
||
int srqStatus; /* The poll response from the device */
|
||
{
|
||
if (dg535Debug || ibSrqDebug)
|
||
logMsg("srqHandler(0x%08.8X, 0x%02.2X): called\n", phwpvt, srqStatus);
|
||
|
||
/* Invoke the command-type specific SRQ handler */
|
||
if (phwpvt->srqCallback != NULL)
|
||
return((*(phwpvt->srqCallback))(phwpvt->parm, srqStatus));
|
||
|
||
logMsg("Unsolicited SRQ rec'd from link %d, device %d, status = 0x%02.2X\n",
|
||
phwpvt->link, phwpvt->device, srqStatus);
|
||
|
||
return(IDLE);
|
||
}
|
||
|
||
#endif /* _SRQSUPPORT_ */
|
||
|
||
/******************************************************************************
|
||
*
|
||
* This function is called by the callback task. The callback task
|
||
* calls it after being given the 'go ahead' by callbackRequest()
|
||
* function calls made in the xxxWork routines defined above.
|
||
*
|
||
* The reason it is done this way is because the process() call may
|
||
* recursively call itself when records are chained and the callback
|
||
* task's stack is larger... just for this purpose. (jrw)
|
||
*
|
||
******************************************************************************/
|
||
|
||
static void
|
||
processCallback(pDpvt)
|
||
struct gpibDpvt *pDpvt;
|
||
{
|
||
if(dg535Debug)
|
||
logMsg("processCallback: calling process\n");
|
||
|
||
dbScanLock(pDpvt->precord);
|
||
(*(struct rset *)(pDpvt->precord->rset)).process(pDpvt->precord->pdba);
|
||
dbScanUnlock(pDpvt->precord);
|
||
}
|
||
|
||
/******************************************************************************
|
||
*
|
||
* This function is used to set alarm status information.
|
||
*
|
||
******************************************************************************/
|
||
static long
|
||
setPvSevr(pPv, status, severity)
|
||
struct dbCommon *pPv;
|
||
short severity;
|
||
short status;
|
||
{
|
||
if (severity > pPv->nsev )
|
||
{
|
||
pPv->nsta = status;
|
||
pPv->nsev = severity;
|
||
}
|
||
}
|