/* devCommonGpib.c */ /* share/src/devOpt $Id$ */ /* * Author: John Winans * Origional Author: Ned D. Arnold * Date: 11-20-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 * .08 11-17-91 jrw changed to support SR620 * .09 11-20-91 jrw redesigned as a library * .10 11-22-91 jrw removed output formatting for all but GPIBWRITEs * .11 01-10-92 jrw changed return from GPIBSOFT (propagated, was 0) * .12 02-05-92 jba Changed process parameter from precord->pdba to precord * .13 02-18-92 jrw Changed return from the AO init function to 2 * .14 02-26-92 jrw added return codes to the output work functions * .15 02-27-92 jrw added the setting of PACT to 1 when init fails * .16 04-08-92 jrw reordered initXx to clean up SRQ init code * .17 04-30-92 jrw added waveform record support * .18 07-10-92 jrw initXx endless loop looking for hwpvt * * WISH LIST: * It would be nice to read and write directly to/from the val field * when operating on SI and SO records. The strncpy looks like a waste. */ /* This MUST be deleted when the new dbScanner stuff is put into EPICS! */ /* any existing databases will also have to be changed from passive, to */ /* I/O event scanned for magic SRQ processing */ #define SCAN_IO_EVENT 0 /* This should be in an epicsH header file */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef VALID_ALARM #define VALID_ALARM INVALID_ALARM #endif /* * This external structure contains the entry points to the GPIB drver. */ extern struct { long number; DRVSUPFUN report; /* call this to get stats about the link */ DRVSUPFUN init; /* do NOT call this... epics calls it */ int (*qGpibReq)(); int (*registerSrqCallback)(); int (*writeIb)(); int (*readIb)(); int (*writeIbCmd)(); int (*ioctl)(); } drvGpib; extern int ibSrqDebug; /****************************************************************************** * * Print a report of operating statistics for all devices supported by this * module. * ******************************************************************************/ long devGpibLib_report(dset) gDset *dset; { struct hwpvt *phwpvt; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(dset->funPtr[dset->number]); phwpvt = parmBlock->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. * ******************************************************************************/ long devGpibLib_initDevSup(parm, dset) int parm; /* set to 0 on pre-rec init call, and 1 on post-rec init call */ gDset *dset; /* pointer to dset used to reference the init function */ { struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(dset->funPtr[dset->number]); if ((parm == 0) && *parmBlock->debugFlag) printf("%s: Device Support Initializing ...\n", parmBlock->name); return(OK); } /****************************************************************************** * * Initialization routines. * ******************************************************************************/ /****************************************************************************** * * ai record init * ******************************************************************************/ long devGpibLib_initAi(pai, process) struct aiRecord *pai; void (*process)(); { long result; char message[100]; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pai->dset))->funPtr[pai->dset->number]); /* Do common initialization */ if (result = devGpibLib_initXx((caddr_t) pai, &pai->inp)) { return(result); } /* make sure the command type makes sendse for the record type */ if (parmBlock->gpibCmds[((struct gpibDpvt *)pai->dpvt)->parm].type != GPIBREAD && parmBlock->gpibCmds[((struct gpibDpvt *)pai->dpvt)->parm].type != GPIBSOFT && parmBlock->gpibCmds[((struct gpibDpvt *)pai->dpvt)->parm].type != GPIBRAWREAD && parmBlock->gpibCmds[((struct gpibDpvt *)pai->dpvt)->parm].type != GPIBREADW) { sprintf(message, "%s: devGpibLib_initAi: invalid command type for an AI record in param %d\n", pai->name, ((struct gpibDpvt *)pai->dpvt)->parm); errMessage(S_db_badField, message); pai->pact = TRUE; return(S_db_badField); } return(0); } /****************************************************************************** * * ao record init * ******************************************************************************/ long devGpibLib_initAo(pao, process) struct aoRecord *pao; void (*process)(); { long result; char message[100]; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pao->dset))->funPtr[pao->dset->number]); /* do common initialization */ if (result = devGpibLib_initXx((caddr_t) pao, &pao->out)) { return(result); } /* make sure the command type makes sendse for the record type */ if (parmBlock->gpibCmds[((struct gpibDpvt *)pao->dpvt)->parm].type != GPIBWRITE && parmBlock->gpibCmds[((struct gpibDpvt *)pao->dpvt)->parm].type != GPIBSOFT && parmBlock->gpibCmds[((struct gpibDpvt *)pao->dpvt)->parm].type != GPIBCMD && parmBlock->gpibCmds[((struct gpibDpvt *)pao->dpvt)->parm].type != GPIBCNTL) { sprintf(message, "%s: devGpibLib_initAo: invalid command type for an AO record in param %d\n", pao->name, ((struct gpibDpvt *)pao->dpvt)->parm); errMessage(S_db_badField, message); pao->pact = TRUE; return(S_db_badField); } return(2); /* Don't let record processing do an RVAL to VAL conversion */ } /****************************************************************************** * * li record init * ******************************************************************************/ long devGpibLib_initLi(pli, process) struct longinRecord *pli; void (*process)(); { long result; char message[100]; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pli->dset))->funPtr[pli->dset->number]); /* Do common initialization */ if (result = devGpibLib_initXx((caddr_t) pli, &pli->inp)) { return(result); } /* make sure the command type makes sendse for the record type */ if (parmBlock->gpibCmds[((struct gpibDpvt *)pli->dpvt)->parm].type != GPIBREAD && parmBlock->gpibCmds[((struct gpibDpvt *)pli->dpvt)->parm].type != GPIBSOFT && parmBlock->gpibCmds[((struct gpibDpvt *)pli->dpvt)->parm].type != GPIBRAWREAD && parmBlock->gpibCmds[((struct gpibDpvt *)pli->dpvt)->parm].type != GPIBREADW) { sprintf(message, "%s: devGpibLib_initLi: invalid command type for an LI record in param %d\n", pli->name, ((struct gpibDpvt *)pli->dpvt)->parm); errMessage(S_db_badField, message); pli->pact = TRUE; return(S_db_badField); } return(0); } /****************************************************************************** * * lo record init * ******************************************************************************/ long devGpibLib_initLo(plo, process) struct longoutRecord *plo; void (*process)(); { long result; char message[100]; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(plo->dset))->funPtr[plo->dset->number]); /* do common initialization */ if (result = devGpibLib_initXx((caddr_t) plo, &plo->out)) { return(result); } if (parmBlock->gpibCmds[((struct gpibDpvt *)plo->dpvt)->parm].type != GPIBWRITE && parmBlock->gpibCmds[((struct gpibDpvt *)plo->dpvt)->parm].type != GPIBSOFT && parmBlock->gpibCmds[((struct gpibDpvt *)plo->dpvt)->parm].type != GPIBCMD && parmBlock->gpibCmds[((struct gpibDpvt *)plo->dpvt)->parm].type != GPIBCNTL) { sprintf(message, "%s: devGpibLib_initLo: invalid command type for an LO record in param %d\n", plo->name, ((struct gpibDpvt *)plo->dpvt)->parm); errMessage(S_db_badField, message); plo->pact = TRUE; return(S_db_badField); } return(0); } /****************************************************************************** * * bi record init * ******************************************************************************/ long devGpibLib_initBi(pbi, process) struct biRecord *pbi; void (*process)(); { long result; char message[100]; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset *)(pbi->dset))->funPtr[pbi->dset->number]); /* Do common initialization */ if (result = devGpibLib_initXx((caddr_t) pbi, &pbi->inp)) { return(result); } /* make sure the command type makes sendse for the record type */ if (parmBlock->gpibCmds[((struct gpibDpvt *)pbi->dpvt)->parm].type != GPIBREAD && parmBlock->gpibCmds[((struct gpibDpvt *)pbi->dpvt)->parm].type != GPIBSOFT && parmBlock->gpibCmds[((struct gpibDpvt *)pbi->dpvt)->parm].type != GPIBEFASTI && parmBlock->gpibCmds[((struct gpibDpvt *)pbi->dpvt)->parm].type != GPIBEFASTIW && parmBlock->gpibCmds[((struct gpibDpvt *)pbi->dpvt)->parm].type != GPIBRAWREAD && parmBlock->gpibCmds[((struct gpibDpvt *)pbi->dpvt)->parm].type != GPIBREADW) { sprintf(message, "%s: devGpibLib_initLi: invalid command type for an BI record in param %d\n", pbi->name, ((struct gpibDpvt *)pbi->dpvt)->parm); errMessage(S_db_badField, message); pbi->pact = TRUE; return(S_db_badField); } /* See if there are names asociated with the record that should */ /* be filled in */ if (parmBlock->gpibCmds[((struct gpibDpvt *)pbi->dpvt)->parm].namelist != NULL) { if (pbi->znam[0] == '\0') { strcpy(pbi->znam, parmBlock->gpibCmds[((struct gpibDpvt *)pbi->dpvt)->parm].namelist->item[0]); } if (pbi->onam[0] == '\0') { strcpy(pbi->onam, parmBlock->gpibCmds[((struct gpibDpvt *)pbi->dpvt)->parm].namelist->item[1]); } } return(0); } /****************************************************************************** * * bo record init * ******************************************************************************/ long devGpibLib_initBo(pbo, process) struct boRecord *pbo; void (*process)(); { long result; char message[100]; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset *)(pbo->dset))->funPtr[pbo->dset->number]); /* do common initialization */ if (result = devGpibLib_initXx((caddr_t) pbo, &pbo->out)) { return(result); } if (parmBlock->gpibCmds[((struct gpibDpvt *)pbo->dpvt)->parm].type != GPIBWRITE && parmBlock->gpibCmds[((struct gpibDpvt *)pbo->dpvt)->parm].type != GPIBSOFT && parmBlock->gpibCmds[((struct gpibDpvt *)pbo->dpvt)->parm].type != GPIBCMD && parmBlock->gpibCmds[((struct gpibDpvt *)pbo->dpvt)->parm].type != GPIBEFASTO && parmBlock->gpibCmds[((struct gpibDpvt *)pbo->dpvt)->parm].type != GPIBCNTL) { sprintf(message, "%s: devGpibLib_initBo: invalid command type for an BO record in param %d\n", pbo->name, ((struct gpibDpvt *)pbo->dpvt)->parm); errMessage(S_db_badField, message); pbo->pact = TRUE; return(S_db_badField); } /* see if there are names asociated with the record that should */ /* be filled in */ if (parmBlock->gpibCmds[((struct gpibDpvt *)pbo->dpvt)->parm].namelist != NULL) { if (pbo->znam[0] == '\0') { strcpy(pbo->znam, parmBlock->gpibCmds[((struct gpibDpvt *)pbo->dpvt)->parm].namelist->item[0]); } if (pbo->onam[0] == '\0') { strcpy(pbo->onam, parmBlock->gpibCmds[((struct gpibDpvt *)pbo->dpvt)->parm].namelist->item[1]); } } return(0); } /****************************************************************************** * * mbbi record init * ******************************************************************************/ long devGpibLib_initMbbi(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 */ struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pmbbi->dset))->funPtr[pmbbi->dset->number]); /* do common initialization */ if (result = devGpibLib_initXx((caddr_t)pmbbi, &pmbbi->inp)) { return(result); } /* make sure the command type makes sendse for the record type */ if (parmBlock->gpibCmds[((struct gpibDpvt *)pmbbi->dpvt)->parm].type != GPIBREAD && parmBlock->gpibCmds[((struct gpibDpvt *)pmbbi->dpvt)->parm].type != GPIBSOFT && parmBlock->gpibCmds[((struct gpibDpvt *)pmbbi->dpvt)->parm].type != GPIBEFASTI && parmBlock->gpibCmds[((struct gpibDpvt *)pmbbi->dpvt)->parm].type != GPIBEFASTIW && parmBlock->gpibCmds[((struct gpibDpvt *)pmbbi->dpvt)->parm].type != GPIBRAWREAD && parmBlock->gpibCmds[((struct gpibDpvt *)pmbbi->dpvt)->parm].type != GPIBREADW) { sprintf(message, "%s: devGpibLib_initLi: invalid command type for an MBBI record in param %d\n", pmbbi->name, ((struct gpibDpvt *)pmbbi->dpvt)->parm); errMessage(S_db_badField, message); pmbbi->pact = TRUE; return(S_db_badField); } dpvt = (struct gpibDpvt *)pmbbi->dpvt; /* init pointer to gpibDpvt */ /* do initialization of other fields in the record that are unique * to this record type */ /* see if there are names asociated with the record that should */ /* be filled in */ if (parmBlock->gpibCmds[dpvt->parm].namelist != NULL) { if (parmBlock->gpibCmds[dpvt->parm].namelist->value == NULL) { sprintf(message, "%s: init_rec_mbbi: MBBI value list wrong for param #%d\n", pmbbi->name, dpvt->parm); errMessage(S_db_badField, message); pmbbi->pact = TRUE; return(S_db_badField); } pmbbi->nobt = parmBlock->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 < parmBlock->gpibCmds[dpvt->parm].namelist->count) { if (name_ptr[0] == '\0') { strcpy(name_ptr, parmBlock->gpibCmds[dpvt->parm].namelist->item[name_ct]); *val_ptr = parmBlock->gpibCmds[dpvt->parm].namelist->value[name_ct]; } name_ct++; name_ptr += sizeof(pmbbi->zrst); val_ptr++; } } return(0); } /****************************************************************************** * * mbbo record init * ******************************************************************************/ long devGpibLib_initMbbo(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; /* index into the value list array */ struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pmbbo->dset))->funPtr[pmbbo->dset->number]); /* do common initialization */ if (result = devGpibLib_initXx((caddr_t)pmbbo, &pmbbo->out)) { return(result); } if (parmBlock->gpibCmds[((struct gpibDpvt *)pmbbo->dpvt)->parm].type != GPIBWRITE && parmBlock->gpibCmds[((struct gpibDpvt *)pmbbo->dpvt)->parm].type != GPIBSOFT && parmBlock->gpibCmds[((struct gpibDpvt *)pmbbo->dpvt)->parm].type != GPIBCMD && parmBlock->gpibCmds[((struct gpibDpvt *)pmbbo->dpvt)->parm].type != GPIBEFASTO && parmBlock->gpibCmds[((struct gpibDpvt *)pmbbo->dpvt)->parm].type != GPIBCNTL) { sprintf(message, "%s: devGpibLib_initMbbo: invalid command type for an MBBO record in param %d\n", pmbbo->name, ((struct gpibDpvt *)pmbbo->dpvt)->parm); errMessage(S_db_badField, message); pmbbo->pact = TRUE; return(S_db_badField); } dpvt = (struct gpibDpvt *)pmbbo->dpvt; /* init pointer to gpibDpvt */ /* do initialization of other fields in the record that are unique * to this record type */ /* see if there are names asociated with the record that should */ /* be filled in */ if (parmBlock->gpibCmds[dpvt->parm].namelist != NULL) { if (parmBlock->gpibCmds[dpvt->parm].namelist->value == NULL) { sprintf(message, "%s: init_rec_mbbo: MBBO value list wrong for param #%d\n", pmbbo->name, dpvt->parm); errMessage(S_db_badField, message); pmbbo->pact = TRUE; return(S_db_badField); } pmbbo->nobt = parmBlock->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 < parmBlock->gpibCmds[dpvt->parm].namelist->count) { if (name_ptr[0] == '\0') { strcpy(name_ptr, parmBlock->gpibCmds[dpvt->parm].namelist->item[name_ct]); *val_ptr = parmBlock->gpibCmds[dpvt->parm].namelist->value[name_ct]; } name_ct++; name_ptr += sizeof(pmbbo->zrst); val_ptr++; } } return(2); } /****************************************************************************** * * stringin record init * ******************************************************************************/ long devGpibLib_initSi(psi, process) struct stringinRecord *psi; void (*process)(); { long result; struct gpibDpvt *dpvt; /* pointer to gpibDpvt, not yet assigned */ char message[100]; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(psi->dset))->funPtr[psi->dset->number]); /* do common initialization */ if (result = devGpibLib_initXx((caddr_t) psi, &psi->inp)) { return(result); } /* make sure the command type makes sendse for the record type */ if (parmBlock->gpibCmds[((struct gpibDpvt *)psi->dpvt)->parm].type != GPIBREAD && parmBlock->gpibCmds[((struct gpibDpvt *)psi->dpvt)->parm].type != GPIBSOFT && parmBlock->gpibCmds[((struct gpibDpvt *)psi->dpvt)->parm].type != GPIBRAWREAD && parmBlock->gpibCmds[((struct gpibDpvt *)psi->dpvt)->parm].type != GPIBREADW) { sprintf(message, "%s: devGpibLib_initLi: invalid command type for an SI record in param %d\n", psi->name, ((struct gpibDpvt *)psi->dpvt)->parm); errMessage(S_db_badField, message); psi->pact = TRUE; return(S_db_badField); } return(0); } /****************************************************************************** * * stringout record init * ******************************************************************************/ long devGpibLib_initSo(pso, process) struct stringoutRecord *pso; void (*process)(); { long result; struct gpibDpvt *dpvt; /* pointer to gpibDpvt, not yet assigned */ char message[100]; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pso->dset))->funPtr[pso->dset->number]); /* do common initialization */ if (result = devGpibLib_initXx((caddr_t) pso, &pso->out)) { return(result); } /* do initialization of other fields in the record that are unique * to this record type */ if (parmBlock->gpibCmds[((struct gpibDpvt *)pso->dpvt)->parm].type != GPIBWRITE && parmBlock->gpibCmds[((struct gpibDpvt *)pso->dpvt)->parm].type != GPIBSOFT && parmBlock->gpibCmds[((struct gpibDpvt *)pso->dpvt)->parm].type != GPIBCMD && parmBlock->gpibCmds[((struct gpibDpvt *)pso->dpvt)->parm].type != GPIBCNTL) { sprintf(message, "%s: devGpibLib_initSo: invalid command typefor a SO record in param %d\n", pso->name, ((struct gpibDpvt *)pso->dpvt)->parm); errMessage(S_db_badField, message); pso->pact = TRUE; return(S_db_badField); } return(0); } /****************************************************************************** * * This init routine is common to all record types * ******************************************************************************/ long devGpibLib_initXx(prec, plink) struct dbCommon *prec; struct link *plink; { struct devGpibParmBlock *parmBlock; struct gpibDpvt *pdpvt; struct dbCommon *pdbCommon = (struct dbCommon *)prec; char message[100]; struct gpibCmd *pCmd; char foundIt; parmBlock = (struct devGpibParmBlock *)(((gDset*)(prec->dset))->funPtr[prec->dset->number]); if (*parmBlock->debugFlag) printf("initXx dealing with record >%s< device >%s<\n", prec->name, parmBlock->name); /* allocate space for the private structure */ pdpvt = (struct gpibDpvt *) malloc(sizeof(struct gpibDpvt)); prec->dpvt = (void *) pdpvt; pdpvt->head.dmaTimeout = parmBlock->dmaTimeout; 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 */ 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.data = (unsigned char *) malloc(BB_MAX_DAT_LEN); pdpvt->head.bitBusDpvt->rxMsg.data = (unsigned char *) malloc(BB_MAX_DAT_LEN); pdpvt->head.bitBusDpvt->txMsg.node = plink->value.bbgpibio.bbaddr; /* bug node address */ 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); sprintf(message,": init_record : GPIB link type %ld is invalid", plink->type); errMessage(S_db_badField, message); prec->pact = TRUE; /* keep record from being processed */ return(S_db_badField); break; } /* Try to find the hardware private structure */ if (*parmBlock->debugFlag > 5) printf("%s: looking for hwpvt structure for link %d device %d\n", parmBlock->name, pdpvt->head.link, pdpvt->head.device); foundIt = 0; pdpvt->phwpvt = parmBlock->hwpvtHead; while ((pdpvt->phwpvt != NULL) && !foundIt) { if (*parmBlock->debugFlag > 5) printf("%s: Checking hwpvt 0x%08.8X, type %d, link %d, device %d\n", parmBlock->name, pdpvt->phwpvt, pdpvt->phwpvt->linkType, pdpvt->phwpvt->link, pdpvt->phwpvt->device); 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 pdpvt->phwpvt = pdpvt->phwpvt->next; } else foundIt = 1; else pdpvt->phwpvt = pdpvt->phwpvt->next; /* check the next one */ } if (!foundIt) { /* I couldn't find it. Allocate a new one */ if (*parmBlock->debugFlag) printf("%s: allocating a hwpvt structure for link %d device %d\n", parmBlock->name, pdpvt->head.link, pdpvt->head.device); pdpvt->phwpvt = (struct hwpvt *) malloc(sizeof (struct hwpvt)); pdpvt->phwpvt->next = parmBlock->hwpvtHead; /* put in the list */ parmBlock->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->unsolicitedDpvt = NULL; pdpvt->phwpvt->parm = (caddr_t)NULL; if (*parmBlock->debugFlag) printf("issuing IBGENLINK ioctl for link %d\n", pdpvt->phwpvt->link); /* Tell the driver we are going to use this link some time */ (*(drvGpib.ioctl))(pdpvt->phwpvt->linkType, pdpvt->phwpvt->link, pdpvt->phwpvt->bug, IBGENLINK, -1, NULL); } /* Fill in the dpvt->ibLink field (The driver uses it) */ if (*parmBlock->debugFlag) printf("initXx doing an ioctl-IBGETLINK for record >%s< device >%s<\n", prec->name, parmBlock->name); (*(drvGpib.ioctl))(pdpvt->phwpvt->linkType, pdpvt->phwpvt->link, pdpvt->phwpvt->bug, IBGETLINK, -1, &(pdpvt->head.pibLink)); if (*parmBlock->debugFlag) printf("ioctl-IBGETLINK returned 0x%08.8X\n", pdpvt->head.pibLink); if (*parmBlock->debugFlag > 5) printf("initXx checking GPIB address for record >%s< device >%s<\n", prec->name, parmBlock->name); /* 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); prec->pact = TRUE; /* keep record from being processed */ return(S_db_badField); } if (*parmBlock->debugFlag > 5) printf("initXx checking param entry for record >%s< device >%s<\n", prec->name, parmBlock->name); /* Check for valid param entry */ if ((pdpvt->parm < 0) || (pdpvt->parm > parmBlock->numparams)) { strcpy(message, pdbCommon->name); strcat(message,": init_record : GPIB parameter # out of range"); errMessage(S_db_badField,message); prec->pact = TRUE; /* keep record from being processed */ return(S_db_badField); } if (*parmBlock->debugFlag > 5) printf("initXx checking record coherency for record >%s< device >%s<\n", prec->name, parmBlock->name); /* make sure that the record type matches the GPIB port type (jrw) */ if (parmBlock->gpibCmds[pdpvt->parm].rec_typ != (gDset *)prec->dset ) { sprintf(message, "%s: init_record: record type invalid for spec'd GPIB param #%d", pdbCommon->name, pdpvt->parm); errMessage(S_db_badField,message); prec->pact = TRUE; /* keep record from being processed */ return(S_db_badField); } pCmd = &(parmBlock->gpibCmds[pdpvt->parm]); if(pCmd->msgLen > 0) pdpvt->msg = (char *)(malloc(pCmd->msgLen)); if(pCmd->rspLen > 0) pdpvt->rsp = (char *)(malloc(pCmd->rspLen)); if(parmBlock->srqHandler != NULL) { /* If user spec'd the process on unsolicited SRQ parameter mark it */ if (pdpvt->parm == parmBlock->magicSrq) { if (pdpvt->phwpvt->unsolicitedDpvt != NULL) { strcpy(message, pdbCommon->name); strcat(message,": init_record: can only have 1 SRQ scanned record per GPIB device"); errMessage(S_db_badField,message); prec->pact = TRUE; /* keep record from being processed */ return(S_db_badField); } if (pdbCommon->scan == SCAN_IO_EVENT) { pdpvt->phwpvt->unsolicitedDpvt = pdpvt; } } /* * Ok to re-register a handler for the same device. * Just don't do it after init time is over! */ (*(drvGpib.registerSrqCallback))(pdpvt->head.pibLink, pdpvt->head.device, parmBlock->srqHandler, pdpvt->phwpvt); } /* fill in the work routine pointer */ pdpvt->head.workStart = (int (*)()) (((gDset*)(prec->dset))->funPtr[(((gDset*)(prec->dset))->number) + 1]); return(0); } /****************************************************************************** * * These are the functions that are called to actually communicate with * the GPIB device. * * They are called by record-processing to perform an I/O operation. In the * GPIB case, all I/O is done via anynchronous processing, so all these * functions do is queue requests for the driver to take care of when it is * ready. * ******************************************************************************/ /****************************************************************************** * * read_ai() * ******************************************************************************/ long devGpibLib_readAi(pai) struct aiRecord *pai; { struct gpibDpvt *pdpvt = (struct gpibDpvt *)(pai->dpvt); struct gpibCmd *pCmd; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pai->dset))->funPtr[pai->dset->number]); pCmd = &(parmBlock->gpibCmds[pdpvt->parm]); if (pai->pact) { return(2); /* work is all done, return '2' to indicate val */ } else if (pCmd->type == GPIBSOFT) { return((*pCmd->convert)(pdpvt,pCmd->P1,pCmd->P2, pCmd->P3)); } else { /* put pointer to dpvt field on transaction fifo */ if((*(drvGpib.qGpibReq))(pdpvt, pCmd->pri) == ERROR) { devGpibLib_setPvSevr(pai,MAJOR_ALARM,VALID_ALARM); return(0); } pai->pact = TRUE; return(0); } } /****************************************************************************** * * write_ao() * ******************************************************************************/ long devGpibLib_writeAo(pao) struct aoRecord *pao; { struct gpibDpvt *pdpvt = (struct gpibDpvt *)(pao->dpvt); struct gpibCmd *pCmd; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pao->dset))->funPtr[pao->dset->number]); pCmd = &parmBlock->gpibCmds[pdpvt->parm]; if (pao->pact) { return(0); /* work is all done, finish processing */ } else if (pCmd->type == GPIBSOFT) { return((*pCmd->convert)(pdpvt,pCmd->P1,pCmd->P2, pCmd->P3)); } else { /* put pointer to dvpt field on transaction fifo */ if((*(drvGpib.qGpibReq))(pdpvt, pCmd->pri) == ERROR) { devGpibLib_setPvSevr(pao,WRITE_ALARM,VALID_ALARM); return(0); } pao->pact = TRUE; return(0); } } /****************************************************************************** * * read_li() * ******************************************************************************/ long devGpibLib_readLi(pli) struct longinRecord *pli; { struct gpibDpvt *pdpvt = (struct gpibDpvt *)(pli->dpvt); struct gpibCmd *pCmd; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pli->dset))->funPtr[pli->dset->number]); pCmd = &parmBlock->gpibCmds[pdpvt->parm]; if (pli->pact) { return(2); /* work is all done, return '2' to indicate val */ } else if (pCmd->type == GPIBSOFT) { return((*pCmd->convert)(pdpvt,pCmd->P1,pCmd->P2, pCmd->P3)); } else { /* put pointer to dpvt field on transaction fifo */ if((*(drvGpib.qGpibReq))(pdpvt, pCmd->pri) == ERROR) { devGpibLib_setPvSevr(pli,MAJOR_ALARM,VALID_ALARM); return(0); } pli->pact = TRUE; return(0); } } /****************************************************************************** * * write_lo() * ******************************************************************************/ long devGpibLib_writeLo(plo) struct longoutRecord *plo; { struct gpibDpvt *pdpvt = (struct gpibDpvt *)(plo->dpvt); struct gpibCmd *pCmd; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(plo->dset))->funPtr[plo->dset->number]); pCmd = &parmBlock->gpibCmds[pdpvt->parm]; if (plo->pact) { return(0); /* work is all done, finish processing */ } else if (pCmd->type == GPIBSOFT) { return((*pCmd->convert)(pdpvt,pCmd->P1,pCmd->P2, pCmd->P3)); } else { /* put pointer to dvpt field on transaction fifo */ if((*(drvGpib.qGpibReq))(pdpvt, pCmd->pri) == ERROR) { devGpibLib_setPvSevr(plo,WRITE_ALARM,VALID_ALARM); return(0); } plo->pact = TRUE; return(0); } } /****************************************************************************** * * read_bi() * ******************************************************************************/ long devGpibLib_readBi(pbi) struct biRecord *pbi; { struct gpibDpvt *pdpvt = (struct gpibDpvt *)(pbi->dpvt); struct gpibCmd *pCmd; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pbi->dset))->funPtr[pbi->dset->number]); pCmd = &parmBlock->gpibCmds[pdpvt->parm]; if (pbi->pact) { return(0); /* work is all done, finish processing */ } else if (pCmd->type == GPIBSOFT) { return((*pCmd->convert)(pdpvt,pCmd->P1,pCmd->P2, pCmd->P3)); } else { /* put pointer to dvpt field on transaction fifo */ if((*(drvGpib.qGpibReq))(pdpvt, pCmd->pri) == ERROR) { devGpibLib_setPvSevr(pbi,READ_ALARM,VALID_ALARM); return(0); } pbi->pact = TRUE; return(0); } } /****************************************************************************** * * write_bo() * ******************************************************************************/ long devGpibLib_writeBo(pbo) struct boRecord *pbo; { struct gpibDpvt *pdpvt = (struct gpibDpvt *)(pbo->dpvt); struct gpibCmd *pCmd; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pbo->dset))->funPtr[pbo->dset->number]); if (*parmBlock->debugFlag) printf("devGpibLib_writeBo() entered\n"); pCmd = &parmBlock->gpibCmds[pdpvt->parm]; if (pbo->pact) { return(0); /* work is all done, finish processing */ } else if (pCmd->type == GPIBSOFT) { return((*pCmd->convert)(pdpvt,pCmd->P1,pCmd->P2, pCmd->P3)); } else { /* put pointer to dvpt field on transaction fifo */ if((*(drvGpib.qGpibReq))(pdpvt, pCmd->pri) == ERROR) { devGpibLib_setPvSevr(pbo,WRITE_ALARM,VALID_ALARM); return(0); } pbo->pact = TRUE; return(0); } } /****************************************************************************** * * read_mbbi() * ******************************************************************************/ long devGpibLib_readMbbi(pmbbi) struct mbbiRecord *pmbbi; { struct gpibDpvt *pdpvt = (struct gpibDpvt *)(pmbbi->dpvt); struct gpibCmd *pCmd; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pmbbi->dset))->funPtr[pmbbi->dset->number]); pCmd = &parmBlock->gpibCmds[pdpvt->parm]; if (pmbbi->pact) { return(0); /* work is all done, finish processing */ } else if (pCmd->type == GPIBSOFT) { return((*pCmd->convert)(pdpvt,pCmd->P1,pCmd->P2, pCmd->P3)); } else { /* put pointer to dvpt field on transaction fifo */ if((*(drvGpib.qGpibReq))(pdpvt, pCmd->pri) == ERROR) { devGpibLib_setPvSevr(pmbbi,READ_ALARM,VALID_ALARM); return(0); } pmbbi->pact = TRUE; return(0); } } /****************************************************************************** * * write_mbbo() * ******************************************************************************/ long devGpibLib_writeMbbo(pmbbo) struct mbboRecord *pmbbo; { struct gpibDpvt *pdpvt = (struct gpibDpvt *)(pmbbo->dpvt); struct gpibCmd *pCmd; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pmbbo->dset))->funPtr[pmbbo->dset->number]); pCmd = &parmBlock->gpibCmds[pdpvt->parm]; if (pmbbo->pact) { return(0); /* work is all done, finish processing */ } else if (pCmd->type == GPIBSOFT) { return((*pCmd->convert)(pdpvt,pCmd->P1,pCmd->P2, pCmd->P3)); } else { /* put pointer to dvpt field on transaction fifo */ if((*(drvGpib.qGpibReq))(pdpvt, pCmd->pri) == ERROR) { devGpibLib_setPvSevr(pmbbo,WRITE_ALARM,VALID_ALARM); return(0); } pmbbo->pact = TRUE; return(0); } } /****************************************************************************** * * read_stringin() * ******************************************************************************/ long devGpibLib_readSi(psi) struct stringinRecord *psi; { struct gpibDpvt *pdpvt = (struct gpibDpvt *)(psi->dpvt); struct gpibCmd *pCmd; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(psi->dset))->funPtr[psi->dset->number]); pCmd = &parmBlock->gpibCmds[pdpvt->parm]; if (psi->pact) { return(2); /* work is all done, return '2' to indicate val */ } else if (pCmd->type == GPIBSOFT) { return((*pCmd->convert)(pdpvt,pCmd->P1,pCmd->P2, pCmd->P3)); } else { /* put pointer to dvpt field on transaction fifo */ if((*(drvGpib.qGpibReq))(pdpvt, pCmd->pri) == ERROR) { devGpibLib_setPvSevr(psi,MAJOR_ALARM,VALID_ALARM); return(0); } psi->pact = TRUE; return(0); } } /****************************************************************************** * * write_stringout() * ******************************************************************************/ long devGpibLib_writeSo(pso) struct stringoutRecord *pso; { struct gpibDpvt *pdpvt = (struct gpibDpvt *)(pso->dpvt); struct gpibCmd *pCmd; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pso->dset))->funPtr[pso->dset->number]); pCmd = &parmBlock->gpibCmds[pdpvt->parm]; if (pso->pact) { return(0); /* work is all done, finish processing */ } else if (pCmd->type == GPIBSOFT) { return((*pCmd->convert)(pdpvt,pCmd->P1,pCmd->P2, pCmd->P3)); } else { /* put pointer to dvpt field on transaction fifo */ if((*(drvGpib.qGpibReq))(pdpvt, pCmd->pri) == ERROR) { devGpibLib_setPvSevr(pso,WRITE_ALARM,VALID_ALARM); return(0); } pso->pact = TRUE; return(0); } } /****************************************************************************** * * Routines that do the actual GPIB work. They are called by the linkTask in * response to work requests passed in from the read_xx and write_xx functions * above. * ******************************************************************************/ /****************************************************************************** * * devGpibLib_aiGpibWork() * ******************************************************************************/ int devGpibLib_aiGpibWork(pdpvt) struct gpibDpvt *pdpvt; { struct aiRecord *pai= ((struct aiRecord *)(pdpvt->precord)); struct gpibCmd *pCmd; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pai->dset))->funPtr[pai->dset->number]); pCmd = &(parmBlock->gpibCmds[pdpvt->parm]); /* go send predefined cmd msg and read response into msg[] */ if(*(parmBlock->debugFlag)) printf("devGpibLib_aiGpibWork: starting ...command type = %d\n",pCmd->type); if (devGpibLib_xxGpibWork(pdpvt, pCmd->type, -1) == ERROR) { devGpibLib_setPvSevr(pai,READ_ALARM,VALID_ALARM); pdpvt->head.header.callback.callback = devGpibLib_processCallback; pdpvt->head.header.callback.priority = priorityLow; callbackRequest(&pdpvt->head.header.callback); } else { if (pCmd->type != GPIBREADW) devGpibLib_aiGpibFinish(pdpvt); /* If not waiting on SRQ, finish */ else { if (*(parmBlock->debugFlag) || ibSrqDebug) printf("%s: marking srq Handler for READW operation\n", parmBlock->name); pdpvt->phwpvt->srqCallback = (int (*)())(((gDset*)(pai->dset))->funPtr[pai->dset->number + 2]); pdpvt->phwpvt->parm = (caddr_t)pdpvt; /* mark the handler */ return(BUSY); /* indicate device still in use */ } } return(IDLE); /* indicate device is now idle */ } /****************************************************************************** * * devGpibLib_aiGpibSrq() * ******************************************************************************/ int devGpibLib_aiGpibSrq(pdpvt, srqStatus) struct gpibDpvt *pdpvt; int srqStatus; { struct aiRecord *pai= ((struct aiRecord *)(pdpvt->precord)); struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pai->dset))->funPtr[pai->dset->number]); if (*parmBlock->debugFlag || ibSrqDebug) printf("devGpibLib_aiGpibSrq(0x%08.8X, 0x%02.2X): processing srq\n", pdpvt, srqStatus); pdpvt->phwpvt->srqCallback = NULL; /* unmark the handler */ pdpvt->phwpvt->parm = (caddr_t)NULL; /* read the response back */ if (devGpibLib_xxGpibWork(pdpvt, GPIBRAWREAD, -1) == ERROR) { devGpibLib_setPvSevr(pai,READ_ALARM,VALID_ALARM); pdpvt->head.header.callback.callback = devGpibLib_processCallback; pdpvt->head.header.callback.priority = priorityLow; callbackRequest(&pdpvt->head.header.callback); } devGpibLib_aiGpibFinish(pdpvt); /* and finish the processing */ return(IDLE); /* indicate device now idle */ } /****************************************************************************** * * devGpibLib_aiGpibFinish() * ******************************************************************************/ int devGpibLib_aiGpibFinish(pdpvt) struct gpibDpvt *pdpvt; { double value; struct aiRecord *pai = ((struct aiRecord *)(pdpvt->precord)); struct devGpibParmBlock *parmBlock; struct gpibCmd *pCmd; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pai->dset))->funPtr[pai->dset->number]); pCmd = &(parmBlock->gpibCmds[pdpvt->parm]); if (pCmd->convert != NULL) { if(*parmBlock->debugFlag) printf("devGpibLib_aiGpibWork: calling convert ...\n"); (*(pCmd->convert))(pdpvt,pCmd->P1,pCmd->P2, pCmd->P3); } 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; pai->udf = FALSE; } else /* sscanf did not find or assign the parameter */ { devGpibLib_setPvSevr(pai,READ_ALARM,VALID_ALARM); } } pdpvt->head.header.callback.callback = devGpibLib_processCallback; pdpvt->head.header.callback.priority = priorityLow; callbackRequest(&pdpvt->head.header.callback); return(0); } /****************************************************************************** * * devGpibLib_aoGpibWork() * ******************************************************************************/ int devGpibLib_aoGpibWork(pdpvt) struct gpibDpvt *pdpvt; { int cnvrtStat = OK; struct aoRecord *pao= ((struct aoRecord *)(pdpvt->precord)); struct devGpibParmBlock *parmBlock; struct gpibCmd *pCmd; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pao->dset))->funPtr[pao->dset->number]); pCmd = &(parmBlock->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 */ { if (pCmd->type == GPIBWRITE) /* only if needs formatting */ sprintf(pdpvt->msg, pCmd->format, pao->val); } /* go access board with this message, unless convert was unsuccessful */ if ((cnvrtStat == ERROR) || (devGpibLib_xxGpibWork(pdpvt, pCmd->type, -1) == ERROR)) { devGpibLib_setPvSevr(pao,WRITE_ALARM,VALID_ALARM); } pdpvt->head.header.callback.callback = devGpibLib_processCallback; pdpvt->head.header.callback.priority = priorityLow; callbackRequest(&pdpvt->head.header.callback); return(IDLE); } /****************************************************************************** * * devGpibLib_liGpibWork() * ******************************************************************************/ int devGpibLib_liGpibWork(pdpvt) struct gpibDpvt *pdpvt; { struct longinRecord *pli= ((struct longinRecord *)(pdpvt->precord)); struct devGpibParmBlock *parmBlock; struct gpibCmd *pCmd; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pli->dset))->funPtr[pli->dset->number]); pCmd = &(parmBlock->gpibCmds[pdpvt->parm]); /* go send predefined cmd msg and read response into msg[] */ if(*parmBlock->debugFlag) printf("devGpibLib_liGpibWork: starting ...\n"); if (devGpibLib_xxGpibWork(pdpvt, pCmd->type, -1) == ERROR) { devGpibLib_setPvSevr(pli,READ_ALARM,VALID_ALARM); pdpvt->head.header.callback.callback = devGpibLib_processCallback; pdpvt->head.header.callback.priority = priorityLow; callbackRequest(&pdpvt->head.header.callback); } else { if (pCmd->type != GPIBREADW) devGpibLib_liGpibFinish(pdpvt); /* If not waiting on SRQ, finish */ else { pdpvt->phwpvt->srqCallback = (int(*)())(((gDset*)(pli->dset))->funPtr[pli->dset->number + 2]); pdpvt->phwpvt->parm = (caddr_t)pdpvt; /* mark the handler */ return(BUSY); /* indicate device still in use */ } } return(IDLE); /* indicate device is now idle */ } /****************************************************************************** * * devGpibLib_liGpibSrq() * ******************************************************************************/ int devGpibLib_liGpibSrq(pdpvt, srqStatus) struct gpibDpvt *pdpvt; int srqStatus; { struct longinRecord *pli= ((struct longinRecord *)(pdpvt->precord)); struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pli->dset))->funPtr[pli->dset->number]); if (*parmBlock->debugFlag || ibSrqDebug) printf("devGpibLib_liGpibSrq(0x%08.8X, 0x%02.2X): processing srq\n", pdpvt, srqStatus); pdpvt->phwpvt->srqCallback = NULL; /* unmark the handler */ pdpvt->phwpvt->parm = (caddr_t)NULL; /* do actual SRQ processing in here */ /* read the response back */ if (devGpibLib_xxGpibWork(pdpvt, GPIBRAWREAD, -1) == ERROR) { devGpibLib_setPvSevr(pli,READ_ALARM,VALID_ALARM); pdpvt->head.header.callback.callback = devGpibLib_processCallback; pdpvt->head.header.callback.priority = priorityLow; callbackRequest(&pdpvt->head.header.callback); } devGpibLib_liGpibFinish(pdpvt); /* and finish the processing */ return(IDLE); /* indicate device now idle */ } /****************************************************************************** * * devGpibLib_liGpibFinish() * ******************************************************************************/ int devGpibLib_liGpibFinish(pdpvt) struct gpibDpvt *pdpvt; { unsigned long value; struct longinRecord *pli = ((struct longinRecord *)(pdpvt->precord)); struct gpibCmd *pCmd; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pli->dset))->funPtr[pli->dset->number]); pCmd = &(parmBlock->gpibCmds[pdpvt->parm]); if (pCmd->convert != NULL) { if(*parmBlock->debugFlag) printf("devGpibLib_liGpibWork: calling convert ...\n"); (*(pCmd->convert))(pdpvt,pCmd->P1,pCmd->P2, pCmd->P3); } 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)) { pli->val = value; pli->udf = FALSE; } else /* sscanf did not find or assign the parameter */ { devGpibLib_setPvSevr(pli,READ_ALARM,VALID_ALARM); } } pdpvt->head.header.callback.callback = devGpibLib_processCallback; pdpvt->head.header.callback.priority = priorityLow; callbackRequest(&pdpvt->head.header.callback); return(0); } /****************************************************************************** * * devGpibLib_loGpibWork() * ******************************************************************************/ int devGpibLib_loGpibWork(pdpvt) struct gpibDpvt *pdpvt; { int cnvrtStat = OK; struct longoutRecord *plo= ((struct longoutRecord *)(pdpvt->precord)); struct gpibCmd *pCmd; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(plo->dset))->funPtr[plo->dset->number]); pCmd = &(parmBlock->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 */ { if (pCmd->type == GPIBWRITE) /* only if needs formatting */ sprintf(pdpvt->msg, pCmd->format, plo->val); } /* go access board with this message, unless convert was unsuccessful */ if ((cnvrtStat == ERROR) || (devGpibLib_xxGpibWork(pdpvt, pCmd->type, -1) == ERROR)) { devGpibLib_setPvSevr(plo,WRITE_ALARM,VALID_ALARM); } pdpvt->head.header.callback.callback = devGpibLib_processCallback; pdpvt->head.header.callback.priority = priorityLow; callbackRequest(&pdpvt->head.header.callback); return(IDLE); } /****************************************************************************** * * devGpibLib_biGpibWork() * ******************************************************************************/ int devGpibLib_biGpibWork(pdpvt) struct gpibDpvt *pdpvt; { struct biRecord *pbi= ((struct biRecord *)(pdpvt->precord)); struct gpibCmd *pCmd; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pbi->dset))->funPtr[pbi->dset->number]); pCmd = &(parmBlock->gpibCmds[pdpvt->parm]); /* go send predefined cmd msg and read response into msg[] */ if (devGpibLib_xxGpibWork(pdpvt, pCmd->type, -1) == ERROR) { devGpibLib_setPvSevr(pbi,READ_ALARM,VALID_ALARM); pdpvt->head.header.callback.callback = devGpibLib_processCallback; pdpvt->head.header.callback.priority = priorityLow; callbackRequest(&pdpvt->head.header.callback); } else /* interpret response that came back */ { if (pCmd->type != GPIBREADW && pCmd->type != GPIBEFASTIW) devGpibLib_biGpibFinish(pdpvt); /* If not waiting on SRQ, finish */ else { pdpvt->phwpvt->srqCallback = (int(*)())(((gDset*)(pbi->dset))->funPtr[pbi->dset->number + 2]); pdpvt->phwpvt->parm = (caddr_t)pdpvt; /* mark the handler */ return(BUSY); /* indicate device still in use */ } } return(IDLE); } /****************************************************************************** * * devGpibLib_biGpibSrq() * ******************************************************************************/ int devGpibLib_biGpibSrq(pdpvt, srqStatus) struct gpibDpvt *pdpvt; int srqStatus; { struct biRecord *pbi= ((struct biRecord *)(pdpvt->precord)); struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pbi->dset))->funPtr[pbi->dset->number]); if (*parmBlock->debugFlag || ibSrqDebug) printf("devGpibLib_biGpibSrq(0x%08.8X, 0x%02.2X): processing srq\n", pdpvt, srqStatus); pdpvt->phwpvt->srqCallback = NULL; /* unmark the handler */ pdpvt->phwpvt->parm = (caddr_t)NULL; /* unmark the handler */ /* read the response back */ if (devGpibLib_xxGpibWork(pdpvt, GPIBRAWREAD, -1) == ERROR) { devGpibLib_setPvSevr(pbi,READ_ALARM,VALID_ALARM); pdpvt->head.header.callback.callback = devGpibLib_processCallback; pdpvt->head.header.callback.priority = priorityLow; callbackRequest(&pdpvt->head.header.callback); } devGpibLib_biGpibFinish(pdpvt); /* and finish the processing */ return(IDLE); /* indicate device now idle */ } /****************************************************************************** * * devGpibLib_biGpibFinish() * ******************************************************************************/ int devGpibLib_biGpibFinish(pdpvt) struct gpibDpvt *pdpvt; { unsigned long value; int status; struct biRecord *pbi= ((struct biRecord *)(pdpvt->precord)); struct gpibCmd *pCmd; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pbi->dset))->funPtr[pbi->dset->number]); pCmd = &(parmBlock->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 */ { if (pCmd->type == GPIBEFASTI || pCmd->type == GPIBEFASTIW) { /* Check the response against enumerations */ if ((status = checkEnums(pdpvt->msg, pCmd->P3)) >= 0) pbi->rval = status; else devGpibLib_setPvSevr(pbi,READ_ALARM,VALID_ALARM); } else { /* 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 */ devGpibLib_setPvSevr(pbi,READ_ALARM,VALID_ALARM); } } pdpvt->head.header.callback.callback = devGpibLib_processCallback; pdpvt->head.header.callback.priority = priorityLow; callbackRequest(&pdpvt->head.header.callback); /* jrw */ return(0); } /****************************************************************************** * * devGpibLib_boGpibWork() * ******************************************************************************/ int devGpibLib_boGpibWork(pdpvt) struct gpibDpvt *pdpvt; { int cnvrtStat = OK; int strStat = OK; struct boRecord *pbo= ((struct boRecord *)(pdpvt->precord)); struct gpibCmd *pCmd; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pbo->dset))->funPtr[pbo->dset->number]); pCmd = &(parmBlock->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 */ { if (pCmd->type == GPIBWRITE) /* only if needs formatting */ sprintf(pdpvt->msg, pCmd->format, (unsigned int)pbo->val); } /* go access board with this message, unless convert was unsuccessful */ if ((cnvrtStat == ERROR) || (devGpibLib_xxGpibWork(pdpvt, pCmd->type, pbo->val? 1 : 0) == ERROR)) { devGpibLib_setPvSevr(pbo,WRITE_ALARM,VALID_ALARM); } pdpvt->head.header.callback.callback = devGpibLib_processCallback; pdpvt->head.header.callback.priority = priorityLow; callbackRequest(&pdpvt->head.header.callback); return(IDLE); } /****************************************************************************** * * devGpibLib_mbbiGpibWork() * ******************************************************************************/ int devGpibLib_mbbiGpibWork(pdpvt) struct gpibDpvt *pdpvt; { struct mbbiRecord *pmbbi= ((struct mbbiRecord *)(pdpvt->precord)); struct gpibCmd *pCmd; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pmbbi->dset))->funPtr[pmbbi->dset->number]); pCmd = &(parmBlock->gpibCmds[pdpvt->parm]); /* go send predefined cmd msg and read string response into msg[] */ if (devGpibLib_xxGpibWork(pdpvt, pCmd->type, -1) == ERROR) { devGpibLib_setPvSevr(pmbbi,WRITE_ALARM,VALID_ALARM); pdpvt->head.header.callback.callback = devGpibLib_processCallback; pdpvt->head.header.callback.priority = priorityLow; callbackRequest(&pdpvt->head.header.callback); } else { if (pCmd->type != GPIBREADW) devGpibLib_mbbiGpibFinish(pdpvt); /* If not waiting on SRQ, finish */ else { pdpvt->phwpvt->srqCallback = (int(*)())(((gDset*)(pmbbi->dset))->funPtr[pmbbi->dset->number + 2]); pdpvt->phwpvt->parm = (caddr_t)pdpvt; /* mark the handler */ return(BUSY); /* indicate device still in use */ } } return(IDLE); } /****************************************************************************** * * devGpibLib_mbbiGpibSrq() * ******************************************************************************/ int devGpibLib_mbbiGpibSrq(pdpvt, srqStatus) struct gpibDpvt *pdpvt; int srqStatus; { struct mbbiRecord *pmbbi= ((struct mbbiRecord *)(pdpvt->precord)); struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pmbbi->dset))->funPtr[pmbbi->dset->number]); if (*parmBlock->debugFlag || ibSrqDebug) printf("devGpibLib_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 */ /* read the response back */ if (devGpibLib_xxGpibWork(pdpvt, GPIBRAWREAD, -1) == ERROR) { devGpibLib_setPvSevr(pmbbi,READ_ALARM,VALID_ALARM); pdpvt->head.header.callback.callback = devGpibLib_processCallback; pdpvt->head.header.callback.priority = priorityLow; callbackRequest(&pdpvt->head.header.callback); } devGpibLib_mbbiGpibFinish(pdpvt); /* and finish the processing */ return(IDLE); /* indicate device now idle */ } /****************************************************************************** * * devGpibLib_mbbiGpibFinish() * ******************************************************************************/ int devGpibLib_mbbiGpibFinish(pdpvt) struct gpibDpvt *pdpvt; { unsigned long value; int status; struct mbbiRecord *pmbbi= ((struct mbbiRecord *)(pdpvt->precord)); struct gpibCmd *pCmd; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pmbbi->dset))->funPtr[pmbbi->dset->number]); pCmd = &(parmBlock->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 */ { if (pCmd->type == GPIBEFASTI || pCmd->type == GPIBEFASTIW) { /* Check the response against enumerations */ if ((status = checkEnums(pdpvt->msg, pCmd->P3)) >= 0) pmbbi->rval = status; else devGpibLib_setPvSevr(pmbbi,READ_ALARM,VALID_ALARM); } else { /* 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 */ devGpibLib_setPvSevr(pmbbi,READ_ALARM,VALID_ALARM); } } pdpvt->head.header.callback.callback = devGpibLib_processCallback; pdpvt->head.header.callback.priority = priorityLow; callbackRequest(&pdpvt->head.header.callback); return(0); } /****************************************************************************** * * devGpibLib_mbboGpibWork() * ******************************************************************************/ int devGpibLib_mbboGpibWork(pdpvt) struct gpibDpvt *pdpvt; { int cnvrtStat = OK; int strStat = OK; struct mbboRecord *pmbbo= ((struct mbboRecord *)(pdpvt->precord)); struct gpibCmd *pCmd; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pmbbo->dset))->funPtr[pmbbo->dset->number]); pCmd = &(parmBlock->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 */ { if (pCmd->type == GPIBWRITE) /* only if needs formatting */ sprintf(pdpvt->msg, pCmd->format, (unsigned int)pmbbo->rval); } /* go access board with this message, unless convert was unsuccessful */ /* NOTE the use of val instead of rval for the EFASTO operation index! */ if ((cnvrtStat == ERROR) || (devGpibLib_xxGpibWork(pdpvt, pCmd->type, pmbbo->val) == ERROR)) { devGpibLib_setPvSevr(pmbbo,WRITE_ALARM,VALID_ALARM); } pdpvt->head.header.callback.callback = devGpibLib_processCallback; pdpvt->head.header.callback.priority = priorityLow; callbackRequest(&pdpvt->head.header.callback); /* jrw */ return(IDLE); } /****************************************************************************** * * devGpibLib_stringinGpibWork() * ******************************************************************************/ int devGpibLib_stringinGpibWork(pdpvt) struct gpibDpvt *pdpvt; { struct stringinRecord *psi=((struct stringinRecord*)(pdpvt->precord)); struct gpibCmd *pCmd; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(psi->dset))->funPtr[psi->dset->number]); pCmd = &(parmBlock->gpibCmds[pdpvt->parm]); /* go send predefined cmd msg and read response into msg[] */ if(*parmBlock->debugFlag) printf("devGpibLib_stringinGpibWork: starting ...\n"); if (devGpibLib_xxGpibWork(pdpvt, pCmd->type, -1) == ERROR) { devGpibLib_setPvSevr(psi,READ_ALARM,VALID_ALARM); pdpvt->head.header.callback.callback = devGpibLib_processCallback; pdpvt->head.header.callback.priority = priorityLow; callbackRequest(&pdpvt->head.header.callback); /* jrw */ } else { if (pCmd->type != GPIBREADW) devGpibLib_stringinGpibFinish(pdpvt); /* If not waiting on SRQ, finish */ else { pdpvt->phwpvt->srqCallback = (int(*)())(((gDset*)(psi->dset))->funPtr[psi->dset->number + 2]); pdpvt->phwpvt->parm = (caddr_t)pdpvt; /* mark the handler */ return(BUSY); /* indicate device still in use */ } } return(IDLE); } /****************************************************************************** * * devGpibLib_stringinGpibSrq() * ******************************************************************************/ int devGpibLib_stringinGpibSrq(pdpvt, srqStatus) struct gpibDpvt *pdpvt; int srqStatus; { struct stringinRecord *psi= ((struct stringinRecord *)(pdpvt->precord)); struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(psi->dset))->funPtr[psi->dset->number]); if (*parmBlock->debugFlag || ibSrqDebug) printf("devGpibLib_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 */ /* read the response back */ if (devGpibLib_xxGpibWork(pdpvt, GPIBRAWREAD, -1) == ERROR) { devGpibLib_setPvSevr(psi,READ_ALARM,VALID_ALARM); pdpvt->head.header.callback.callback = devGpibLib_processCallback; pdpvt->head.header.callback.priority = priorityLow; callbackRequest(&pdpvt->head.header.callback); } devGpibLib_stringinGpibFinish(pdpvt); /* and finish the processing */ return(IDLE); /* indicate device now idle */ } /****************************************************************************** * * devGpibLib_stringinGpibFinish() * ******************************************************************************/ int devGpibLib_stringinGpibFinish(pdpvt) struct gpibDpvt *pdpvt; { struct stringinRecord *psi=((struct stringinRecord*)(pdpvt->precord)); struct gpibCmd *pCmd; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(psi->dset))->funPtr[psi->dset->number]); pCmd = &(parmBlock->gpibCmds[pdpvt->parm]); if (pCmd->convert != NULL) { (*(pCmd->convert))(pdpvt,pCmd->P1,pCmd->P2, pCmd->P3); } else { /* BUG -- why can't we just read it into the val field? */ /* BUG -- length should not be hard coded here */ strncpy(psi->val,pdpvt->msg,39); psi->val[40] = '\0'; psi->udf = FALSE; } pdpvt->head.header.callback.callback = devGpibLib_processCallback; pdpvt->head.header.callback.priority = priorityLow; callbackRequest(&pdpvt->head.header.callback); /* jrw */ return(0); } /****************************************************************************** * * devGpibLib_stringoutGpibWork() * ******************************************************************************/ int devGpibLib_stringoutGpibWork(pdpvt) struct gpibDpvt *pdpvt; { int cnvrtStat = OK; struct stringoutRecord *pso= ((struct stringoutRecord *)(pdpvt->precord)); struct gpibCmd *pCmd; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pso->dset))->funPtr[pso->dset->number]); pCmd = &(parmBlock->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 { /* BUG -- why can't we just write it from the val field? */ strncpy(pdpvt->msg, pso->val, 40); } /* go access board with this message, unless convert was unsuccessful */ if ((cnvrtStat == ERROR) || (devGpibLib_xxGpibWork(pdpvt, pCmd->type, -1) == ERROR)) { devGpibLib_setPvSevr(pso,WRITE_ALARM,VALID_ALARM); } pdpvt->head.header.callback.callback = devGpibLib_processCallback; pdpvt->head.header.callback.priority = priorityLow; callbackRequest(&pdpvt->head.header.callback); /* jrw */ return(IDLE); } /****************************************************************************** * * devGpibLib_xxGpibWork() * * Generic function used to read and write strings to the GPIB instruments * by calling the device driver. * ******************************************************************************/ int devGpibLib_xxGpibWork(pdpvt, cmdType, val) struct gpibDpvt *pdpvt; int cmdType; unsigned short val; /* used for EFAST operations only */ { int status = OK; short ibnode = pdpvt->head.device; short bbnode = -1; /* In case is a bitbus->gpib type link */ struct gpibCmd *pCmd; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pdpvt->precord->dset))->funPtr[pdpvt->precord->dset->number]); pCmd = &(parmBlock->gpibCmds[pdpvt->parm]); /* 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 + parmBlock->timeWindow) ) { if (*parmBlock->debugFlag) printf("devGpibLib_xxGpibWork(): timeout flush\n"); return(ERROR); } switch (cmdType) { case GPIBWRITE: /* write the message to the GPIB listen adrs */ status = (*(drvGpib.writeIb))(pdpvt->head.pibLink, ibnode, pdpvt->msg, strlen(pdpvt->msg), pdpvt->head.dmaTimeout); if ((status != ERROR) && (parmBlock->respond2Writes) != -1) { /* device responds to write commands, read the response */ if (parmBlock->respond2Writes > 0) { taskDelay(parmBlock->respond2Writes); } status = (*(drvGpib.readIb))(pdpvt->head.pibLink, ibnode, pdpvt->rsp, pCmd->rspLen, pdpvt->head.dmaTimeout); /* if user specified a secondary convert routine, call it */ if (parmBlock->wrConversion != NULL) status = (*(parmBlock->wrConversion))(status, pdpvt); } break; case GPIBREAD: /* write the command string */ case GPIBEFASTI: status = (*(drvGpib.writeIb))(pdpvt->head.pibLink, ibnode, pCmd->cmd, strlen(pCmd->cmd), pdpvt->head.dmaTimeout); if (status == ERROR) { break; } /* This is probably not the best way to do this... */ /* because the read turnaround time delay should be independant of */ /* the responds to writes flag. */ if (parmBlock->respond2Writes > 0) { taskDelay(parmBlock->respond2Writes); } /* NOTICE -- 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->head.pibLink, ibnode, pdpvt->msg, pCmd->msgLen, pdpvt->head.dmaTimeout); if (status == ERROR) { break; } else if (status >( (pCmd->msgLen) - 1) ) /* check length of resp */ { /* This may or may not be an error */ printf("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 GPIBEFASTIW: status = (*(drvGpib.writeIb))(pdpvt->head.pibLink, ibnode, pCmd->cmd, strlen(pCmd->cmd), pdpvt->head.dmaTimeout); break; case GPIBCMD: /* write the cmd to the GPIB listen adrs */ status = (*(drvGpib.writeIb))(pdpvt->head.pibLink, ibnode, pCmd->cmd, strlen(pCmd->cmd), pdpvt->head.dmaTimeout); if ((status != ERROR) && (parmBlock->respond2Writes) != -1) { /* device responds to write commands, read the response */ if (parmBlock->respond2Writes > 0) { taskDelay(parmBlock->respond2Writes); } status = (*(drvGpib.readIb))(pdpvt->head.pibLink, ibnode, pdpvt->rsp, pCmd->rspLen, pdpvt->head.dmaTimeout); /* if user specified a secondary convert routine, call it */ if (parmBlock->wrConversion != NULL) status = (*(parmBlock->wrConversion))(status, pdpvt); } break; case GPIBCNTL: /* send cmd with atn line active */ status = (*(drvGpib.writeIbCmd))(pdpvt->head.pibLink, pCmd->cmd, strlen(pCmd->cmd)); break; case GPIBEFASTO: /* write the enumerated cmd from the P3 array */ if (pCmd->P3[val] != NULL) { status = (*(drvGpib.writeIb))(pdpvt->head.pibLink,ibnode, pCmd->P3[val], strlen(pCmd->P3[val]), pdpvt->head.dmaTimeout); if ((status != ERROR) && (parmBlock->respond2Writes) != -1) { /* device responds to write commands, read the response */ if (parmBlock->respond2Writes > 0) { taskDelay(parmBlock->respond2Writes); } status = (*(drvGpib.readIb))(pdpvt->head.pibLink, ibnode, pdpvt->rsp, pCmd->rspLen, pdpvt->head.dmaTimeout); /* if user specified a secondary convert routine, call it */ if (parmBlock->wrConversion != NULL) status = (*(parmBlock->wrConversion))(status, pdpvt); } } break; } if(*parmBlock->debugFlag) printf("devGpibLib_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 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 GpibWork 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. * ******************************************************************************/ void devGpibLib_processCallback(pDpvt) struct gpibDpvt *pDpvt; { dbScanLock(pDpvt->precord); (*(struct rset *)(pDpvt->precord->rset)).process(pDpvt->precord); dbScanUnlock(pDpvt->precord); } /****************************************************************************** * * This function is used to set alarm status information. * ******************************************************************************/ long devGpibLib_setPvSevr(pPv, status, severity) struct dbCommon *pPv; unsigned short severity; short status; { if (severity > pPv->nsev ) { pPv->nsta = status; pPv->nsev = severity; } } /****************************************************************************** * * This function is used to parse enumerated response strings. * * Only as many bytes as are found in the enums array elements are compared * when searching for a match. The \0 at the end of the enums array elements * is not considered in the comparison. * ******************************************************************************/ int checkEnums(msg, enums) char *msg; char **enums; { int i; int j; i = 0; while (enums[i] != NULL) /* check each enum until match found */ { /* will stop on first match */ j = 0; /* only check as much as found in enums[i] */ while (enums[i][j] && enums[i][j] == msg[j]) j++; if (enums[i][j] == '\0') return(i); /* found, return index */ i++; } return(-1); /* not found, return error */ } /****************************************************************************** * * wf record init * ******************************************************************************/ long devGpibLib_initWf(pwf, process) struct waveformRecord *pwf; void (*process)(); { long result; char message[100]; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pwf->dset))->funPtr[pwf->dset->number]); /* Do common initialization */ if (result = devGpibLib_initXx((caddr_t) pwf, &(pwf->inp) )) { return(result); } /* make sure the command type makes sendse for the record type */ if (parmBlock->gpibCmds[((struct gpibDpvt *)pwf->dpvt)->parm].type != GPIBREAD && parmBlock->gpibCmds[((struct gpibDpvt *)pwf->dpvt)->parm].type != GPIBSOFT && parmBlock->gpibCmds[((struct gpibDpvt *)pwf->dpvt)->parm].type != GPIBREADW) { sprintf(message, "%s: devGpibLib_initWf: invalid command type for an WF record in param %d\n", pwf->name, ((struct gpibDpvt *)pwf->dpvt)->parm); errMessage(S_db_badField, message); pwf->pact = TRUE; return(S_db_badField); } return(0); } /****************************************************************************** * * These are the functions that are called to actually communicate with * the GPIB device. * * They are called by record-processing to perform an I/O operation. In the * GPIB case, all I/O is done via anynchronous processing, so all these * functions do is queue requests for the driver to take care of when it is * ready. * ******************************************************************************/ /****************************************************************************** * * read_wf() * ******************************************************************************/ long devGpibLib_readWf(pwf) struct waveformRecord *pwf; { struct gpibDpvt *pdpvt = (struct gpibDpvt *)(pwf->dpvt); struct gpibCmd *pCmd; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pwf->dset))->funPtr[pwf->dset->number]); pCmd = &(parmBlock->gpibCmds[pdpvt->parm]); if (pwf->pact) { return(2); /* work is all done, return '2' to indicate val */ } else if (pCmd->type == GPIBSOFT) { return((*pCmd->convert)(pdpvt,pCmd->P1,pCmd->P2, pCmd->P3)); } else { /* put pointer to dpvt field on ring buffer */ if((*(drvGpib.qGpibReq))(pdpvt, pCmd->pri) == ERROR) { devGpibLib_setPvSevr(pwf,MAJOR_ALARM,VALID_ALARM); return(0); } pwf->pact = TRUE; return(0); } } /****************************************************************************** * * Routines that do the actual GPIB work. They are called by the linkTask in * response to work requests passed in from the read_xx and write_xx functions * above. * ******************************************************************************/ /****************************************************************************** * * devGpibLib_wfGpibWork() * ******************************************************************************/ int devGpibLib_wfGpibWork(pdpvt) struct gpibDpvt *pdpvt; { struct waveformRecord *pwf= ((struct waveformRecord *)(pdpvt->precord)); struct gpibCmd *pCmd; struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pwf->dset))->funPtr[pwf->dset->number]); pCmd = &(parmBlock->gpibCmds[pdpvt->parm]); /* go send predefined cmd msg and read response into msg[] */ if(*(parmBlock->debugFlag)) printf("devGpibLib_wfGpibWork: starting ...command type = %d\n",pCmd->type); if (devGpibLib_xxGpibWork(pdpvt, pCmd->type, -1) == ERROR) { devGpibLib_setPvSevr(pwf,READ_ALARM,VALID_ALARM); pdpvt->head.header.callback.callback = devGpibLib_processCallback; pdpvt->head.header.callback.priority = priorityLow; callbackRequest((void *)pdpvt); } else { if (pCmd->type != GPIBREADW) devGpibLib_wfGpibFinish(pdpvt); /* If not waiting on SRQ, finish */ else { if (*(parmBlock->debugFlag) || ibSrqDebug) printf("%s: marking srq Handler for READW operation\n", parmBlock->name); pdpvt->phwpvt->srqCallback = (int (*)())(((gDset*)(pwf->dset))->funPtr[pwf->dset->number + 2]); pdpvt->phwpvt->parm = (caddr_t)pdpvt; /* mark the handler */ return(BUSY); /* indicate device still in use */ } } return(IDLE); /* indicate device is now idle */ } /****************************************************************************** * * devGpibLib_wfGpibSrq() * ******************************************************************************/ int devGpibLib_wfGpibSrq(pdpvt, srqStatus) struct gpibDpvt *pdpvt; int srqStatus; { struct waveformRecord *pwf= ((struct waveformRecord *)(pdpvt->precord)); struct devGpibParmBlock *parmBlock; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pwf->dset))->funPtr[pwf->dset->number]); if (*parmBlock->debugFlag || ibSrqDebug) printf("devGpibLib_wfGpibSrq(0x%08.8X, 0x%02.2X): processing srq\n", pdpvt, srqStatus); pdpvt->phwpvt->srqCallback = NULL; /* unmark the handler */ pdpvt->phwpvt->parm = (caddr_t)NULL; /* read the response back */ if (devGpibLib_xxGpibWork(pdpvt, GPIBRAWREAD, -1) == ERROR) { devGpibLib_setPvSevr(pwf,READ_ALARM,VALID_ALARM); pdpvt->head.header.callback.callback = devGpibLib_processCallback; pdpvt->head.header.callback.priority = priorityLow; callbackRequest((void *)pdpvt); } devGpibLib_wfGpibFinish(pdpvt); /* and finish the processing */ return(IDLE); /* indicate device now idle */ } /****************************************************************************** * * devGpibLib_wfGpibFinish() * ******************************************************************************/ int devGpibLib_wfGpibFinish(pdpvt) struct gpibDpvt *pdpvt; { double value; struct waveformRecord *pwf = ((struct waveformRecord *)(pdpvt->precord)); struct devGpibParmBlock *parmBlock; struct gpibCmd *pCmd; parmBlock = (struct devGpibParmBlock *)(((gDset*)(pwf->dset))->funPtr[pwf->dset->number]); pCmd = &(parmBlock->gpibCmds[pdpvt->parm]); if (pCmd->convert != NULL) { if(*parmBlock->debugFlag) printf("devGpibLib_wfGpibWork: calling convert ...\n"); (*(pCmd->convert))(pdpvt,pCmd->P1,pCmd->P2, pCmd->P3); } else /* for waveforms no standard conversion is supplied */ { devGpibLib_setPvSevr(pwf,READ_ALARM,VALID_ALARM); } pdpvt->head.header.callback.callback = devGpibLib_processCallback; pdpvt->head.header.callback.priority = priorityLow; callbackRequest((void *)pdpvt); return(0); }