Initial revision

This commit is contained in:
cvs
2000-02-07 10:38:55 +00:00
commit fdc6b051c9
846 changed files with 230218 additions and 0 deletions

922
devexec.c Normal file
View File

@ -0,0 +1,922 @@
/*-------------------------------------------------------------------------
D E V I C E E X E C U T E R
Mark Koennecke, December 1996
Substantial rewrite: Mark Koennecke, February 1997
revised: Mark Koennecke, June 1997
revised for use with tasker: Mark Koennecke, September 1997
Copyright:
Labor fuer Neutronenstreuung
Paul Scherrer Institut
CH-5423 Villigen-PSI
The authors hereby grant permission to use, copy, modify, distribute,
and license this software and its documentation for any purpose, provided
that existing copyright notices are retained in all copies and that this
notice is included verbatim in any distributions. No written agreement,
license, or royalty fee is required for any of the authorized uses.
Modifications to this software may be copyrighted by their authors
and need not follow the licensing terms described here, provided that
the new terms are clearly indicated on the first page of each file where
they apply.
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.
-----------------------------------------------------------------------------*/
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "fortify.h"
#include "conman.h"
#include "Scommon.h"
#include "interface.h"
#include "nserver.h"
#include "motor.h"
#include "countdriv.h"
#include "counter.h"
#include "task.h"
#include "devexec.h"
#include "status.h"
#include "lld.h"
#include "event.h"
/*
#define DEBUG 1
*/
typedef struct _DevEntry {
void *pData;
pObjectDescriptor pDescriptor;
float fVal;
char *name;
} DevEntry, *pDevEntry;
/*-------------------------------------------------------------------------*/
static pDevEntry CreateDevEntry(pObjectDescriptor pDes, void *pData,
float fVal, char *name)
{
pDevEntry pNew = NULL;
assert(pDes);
pNew = (pDevEntry)malloc(sizeof(DevEntry));
if(!pNew)
{
return NULL;
}
pNew->pDescriptor = pDes;
pNew->pData = pData;
pNew->name = strdup(name);
pNew->fVal = fVal;
return pNew;
}
/*-------------------------------------------------------------------------*/
static void DeleteDevEntry(pDevEntry self)
{
assert(self);
if(self->name)
{
free(self->name);
}
free(self);
}
/* ----------------- The Executor himself ---------------------------------*/
typedef struct __EXELIST{
pObjectDescriptor pDes;
SConnection *pOwner;
int iList;
int iRun;
int iStop;
int iStatus;
int iEnd;
long lTask;
pTaskMan pTask;
} ExeList;
static pExeList pExecutor = NULL;
/*--------------------------------------------------------------------------*/
pExeList CreateExeList(pTaskMan pTask)
{
pExeList pRes = NULL;
assert(pTask);
pRes = (pExeList)malloc(sizeof(ExeList));
if(!pRes)
{
return NULL;
}
pRes->pOwner = NULL;
pRes->pDes = CreateDescriptor("DeviceExecutor");
if(!pRes->pDes)
{
free(pRes);
return NULL;
}
pRes->iList = LLDcreate(sizeof(pDevEntry));
if(pRes->iList == -1)
{
free(pRes);
return NULL;
}
pRes->iRun = 0;
pRes->iStatus = DEVDONE;
pRes->pTask = pTask;
pRes->lTask = -1;
return pRes;
}
/*-------------------------------------------------------------------------*/
void DeleteExeList(void *pData)
{
pExeList self;
assert(pData);
self = (pExeList)pData;
if(self->pDes)
DeleteDescriptor(self->pDes);
ClearExecutor(self);
LLDdelete(self->iList);
free(self);
}
/*------------------------------------------------------------------------*/
int StartDevice(pExeList self, char *name, pObjectDescriptor pDes,
void *pData, SConnection *pCon, float fNew)
{
pDevEntry pNew = NULL;
int iRet;
char pBueffel[132];
pIDrivable pDrivInt = NULL;
pICountable pCountInt = NULL;
assert(self);
assert(pDes);
assert(pCon);
/* may we? */
if(self->pOwner != NULL)
{
if(pCon != self->pOwner)
{
SCWrite(pCon,
"ERROR: somebody else is still driving, Request rejected",eError);
return 0;
}
}
else
{
self->pOwner = pCon;
}
/* well create a new entry */
self->iStop = 0;
pNew = CreateDevEntry(pDes,pData,fNew,name);
if(!pNew)
{
SCWrite(pCon,"ERROR: memory exhausted in Device Executor ",eError);
SCSetError(pCon,NOMEMORY);
return 0;
}
/* start it */
pDrivInt = pDes->GetInterface(pData,DRIVEID);
pCountInt = pDes->GetInterface(pData,COUNTID);
if(pDrivInt)
{
iRet = pDrivInt->SetValue(pData,pCon,fNew);
}
else if(pCountInt)
{
iRet = pCountInt->StartCount(pData,pCon);
}
else
{ /* this is a programmers error */
SCWrite(pCon,"ERROR: Programmer error in StartDevice ",eError);
iRet = 0;
}
/* check return status */
if(iRet == OKOK)
{
LLDnodeAppendFrom(self->iList,&pNew);
self->iRun = 1;
self->iStatus = DEVDONE;
/* if no task: start it */
if(self->lTask < 0)
{
self->lTask = TaskRegister(self->pTask,
DevExecTask,
DevExecSignal,
NULL,
self,
1);
self->iEnd = 0;
}
return 1;
}
else
{
sprintf(pBueffel,"ERROR: cannot start device %s",name);
SCWrite(pCon,pBueffel,eError);
SCSetError(self->pOwner,iRet);
DeleteDevEntry(pNew);
if(LLDcheck(self->iList) >= LIST_EMPTY)
{
self->pOwner = NULL;
}
return 0;
}
return 0;
}
/*--------------------------------------------------------------------------*/
int StartMotor(pExeList self, SicsInterp *pSics, SConnection *pCon,
char *name, float fVal)
{
pMotor pMot = NULL;
CommandList *pCom = NULL;
char pBueffel[256];
assert(self);
assert(pSics);
assert(name);
pCom = FindCommand(pSics,name);
if(!pCom)
{
sprintf(pBueffel,"ERROR: cannot find motor %s",name);
SCWrite(pCon,pBueffel,eError);
return 0;
}
pMot = (pMotor)pCom->pData;
if(!pMot)
{
sprintf(pBueffel,"ERROR: %s is no motor ",name);
SCWrite(pCon,pBueffel,eError);
return 0;
}
if(!pMot->pDescriptor)
{
sprintf(pBueffel,"ERROR: cannot find motor %s",name);
SCWrite(pCon,pBueffel,eError);
return 0;
}
if(!pMot->pDescriptor->GetInterface(pMot,DRIVEID))
{
sprintf(pBueffel,"ERROR: %s is no motor",name);
SCWrite(pCon,pBueffel,eError);
return 0;
}
return StartDevice(self,name,pMot->pDescriptor,(void *)pMot,pCon,fVal);
}
/*---------------------------------------------------------------------------*/
int StartCounter(pExeList self, SicsInterp *pSics,SConnection *pCon,
char *name)
{
pCounter pCter = NULL;
CommandList *pCom = NULL;
char pBueffel[256];
assert(self);
assert(pSics);
assert(name);
pCom = FindCommand(pSics,name);
if(!pCom)
{
sprintf(pBueffel,"ERROR: cannot find counter %s",name);
SCWrite(pCon,pBueffel,eError);
return 0;
}
pCter = (pCounter)pCom->pData;
if(!pCter)
{
sprintf(pBueffel,"ERROR: %s is no counter ",name);
SCWrite(pCon,pBueffel,eError);
return 0;
}
if(!pCter->pDes)
{
sprintf(pBueffel,"ERROR: cannot find counter %s",name);
SCWrite(pCon,pBueffel,eError);
return 0;
}
if(!pCter->pDes->GetInterface(pCter,COUNTID))
{
sprintf(pBueffel,"ERROR: %s is no counter",name);
SCWrite(pCon,pBueffel,eError);
return 0;
}
return StartDevice(self,name,pCter->pDes,(void *)pCter,
pCon,pCter->pDriv->fPreset);
}
/*--------------------------------------------------------------------------*/
int CheckExeList(pExeList self)
{
int iRet;
pDevEntry pDev = NULL;
pICountable pCountInt = NULL;
pIDrivable pDrivInt = NULL;
int eCode;
assert(self);
/* Sometimes this gets called, though nothing is running. There are
cases where this is feasible for maintainance, but in some cases it
is pure rubbish, because nothing runs. This will ne checkd here.
*/
if((self->pOwner == NULL) || (LLDcheck(self->iList) == LIST_EMPTY))
{
self->iRun = 0;
self->iEnd = 1;
self->iStop = 0;
return 1;
}
iRet = LLDnodePtr2First(self->iList);
while(iRet != 0)
{
LLDnodeDataTo(self->iList,&pDev);
if(pDev)
{
pDrivInt = pDev->pDescriptor->GetInterface(pDev->pData,DRIVEID);
pCountInt = pDev->pDescriptor->GetInterface(pDev->pData,COUNTID);
if(pDrivInt)
{
eCode = pDrivInt->CheckStatus(pDev->pData,self->pOwner);
}
else if(pCountInt)
{
eCode = pCountInt->CheckCountStatus(pDev->pData,self->pOwner);
}
switch(eCode)
{
case HWIdle:
case OKOK:
if(pCountInt)
{
pCountInt->TransferData(pDev->pData,self->pOwner);
}
else if(pDrivInt)
{
pDrivInt->iErrorCount = 0;
}
DeleteDevEntry(pDev);
LLDnodeDelete(self->iList);
iRet = LLDnodePtr2Prev(self->iList);
self->iStatus = DEVDONE;
break;
case HWFault: /* real HW error: burning, no net etc.. */
SCSetError(self->pOwner,iRet);
DeleteDevEntry(pDev);
LLDnodeDelete(self->iList);
self->iStatus = DEVERROR;
if(pDrivInt)
{
pDrivInt->iErrorCount++;
}
if(SCGetInterrupt(self->pOwner) != eContinue)
{
self->iStatus = DEVINT;
StopExe(self,"all");
return -1;
}
break;
case HWNoBeam:
SetStatus(eOutOfBeam);
if(SCGetInterrupt(self->pOwner) != eContinue)
{
self->iStatus = DEVINT;
return -1;
}
break;
case HWPause:
SetStatus(ePaused);
if(SCGetInterrupt(self->pOwner) != eContinue)
{
self->iStatus = DEVINT;
return -1;
}
break;
case HWBusy:
if(pCountInt)
{
SetStatus(eCounting);
}
else if(pDrivInt)
{
SetStatus(eDriving);
}
self->iStatus = DEVBUSY;
break;
case HWPosFault: /* cannot get somewhere... */
SCSetError(self->pOwner,eCode);
DeleteDevEntry(pDev);
LLDnodeDelete(self->iList);
self->iStatus = DEVERROR;
if(pDrivInt)
{
pDrivInt->iErrorCount++;
}
if(SCGetInterrupt(self->pOwner) != eContinue)
{
self->iStatus = DEVINT;
StopExe(self,"all");
return -1;
}
break;
}
}
iRet = LLDnodePtr2Next(self->iList);
}
iRet = LLDnodePtr2First(self->iList);
if(LLDcheck(self->iList) == LIST_EMPTY)
{
self->pOwner = NULL;
self->iEnd = 1;
self->iRun = 0;
self->lTask = -1;
return 1;
}
else
{
return 0;
}
}
/*---------------------------------------------------------------------------*/
int Wait4Success(pExeList self)
{
int iRet;
assert(self);
self->iRun = 0;
/* do nothing if not running */
if(self->lTask < 0)
{
printf("Wait4Success finished very, very badly\n");
return self->iStatus;
}
/* wait for Devexec task to finish */
TaskWait(self->pTask,self->lTask);
#ifdef DEBUG
printf("Wait4Success finished\n");
#endif
return self->iStatus;
}
/*--------------------------------------------------------------------------*/
int ListPending(pExeList self, SConnection *pCon)
{
int iRet,i;
char pBueffel[512];
pDevEntry pDev = NULL;
assert(self);
assert(pCon);
/* first make sure that the list is fully updated */
iRet = CheckExeList(self);
if(iRet == 1) /* nothing to do! */
{
SCWrite(pCon,"Machine idle",eStatus);
return 1;
}
else if(iRet == -1)
{
SCWrite(pCon,"Handling Interrupt",eStatus);
return 0;
}
/* search the list for entries */
iRet = LLDnodePtr2First(self->iList);
while(iRet != 0)
{
LLDnodeDataTo(self->iList,&pDev);
if(pDev)
{
sprintf(pBueffel,"\t%s %f",pDev->name,pDev->fVal);
SCWrite(pCon,pBueffel,eStatus);
}
iRet = LLDnodePtr2Next(self->iList);
}
return 1;
}
/* -----------------------------------------------------------------------*/
long GetDevexecID(pExeList self)
{
assert(self);
return self->lTask;
}
/*--------------------------------------------------------------------------*/
int StopExe(pExeList self, char *name)
{
int i, iRet;
pDevEntry pDev = NULL;
pIDrivable pDrivInt = NULL;
pICountable pCountInt = NULL;
assert(self);
/* if not active, nothing to do */
if((self->pOwner == NULL) || (LLDcheck(self->iList) == LIST_EMPTY))
{
self->iRun = 0;
return 1;
}
/*
check for stop flag. This is to stop unnecessary calls to StopExe.
There may be way to many, but each call is reasonable under certain
circumstances.
*/
if(self->iStop == 1)
{
return;
}
else
{
self->iStop = 1;
}
/* first the ALL case */
if(strcmp(name,"all") == 0)
{
iRet = LLDnodePtr2First(self->iList);
while(iRet != 0)
{
pDev = (pDevEntry)LLDnodePtr(self->iList);
if(pDev)
{
pDrivInt = pDev->pDescriptor->GetInterface(pDev->pData,DRIVEID);
pCountInt = pDev->pDescriptor->GetInterface(pDev->pData,COUNTID);
if(pDrivInt)
{
pDrivInt->Halt(pDev->pData);
}
else if(pCountInt)
{
pCountInt->Halt(pDev->pData);
}
}
iRet = LLDnodePtr2Next(self->iList);
}
SCWrite(self->pOwner,"ERROR: Full Stop called!!",eError);
if(SCGetInterrupt(self->pOwner) > eContinue)
{
self->iStatus = DEVINT;
}
return 1;
}
/* now the special case: a well defined command */
iRet = LLDnodePtr2First(self->iList);
while(iRet != 0)
{
pDev = (pDevEntry)LLDnodePtr(self->iList);
if(pDev)
{
if(strcmp(pDev->name,name) == 0)
{
pDrivInt = pDev->pDescriptor->GetInterface(pDev->pData,DRIVEID);
pCountInt = pDev->pDescriptor->GetInterface(pDev->pData,COUNTID);
if(pDrivInt)
{
pDrivInt->Halt(pDev->pData);
}
else if(pCountInt)
{
pDrivInt->Halt(pDev->pData);
}
return 1;
}
}
iRet = LLDnodePtr2Next(self->iList);
}
return 0;
}
/*-------------------------------------------------------------------------*/
int StopExeWait(pExeList self)
{
StopExe(self,"all");
Wait4Success(self);
return 1;
}
/*--------------------------------------------------------------------------*/
int PauseExecution(pExeList self)
{
int i, iRet, iRes;
pDevEntry pDev = NULL;
pICountable pCountInt = NULL;
assert(self);
/* step through the list */
iRes = 0;
iRet = LLDnodePtr2First(self->iList);
while(iRet != 0)
{
pDev = (pDevEntry)LLDnodePtr(self->iList);
if(pDev)
{
pCountInt = pDev->pDescriptor->GetInterface(pDev->pData,COUNTID);
if(pCountInt)
{
iRet = pCountInt->Pause(pDev->pData,self->pOwner);
if(!iRet)
{
iRes = 0;
}
}
}
iRet = LLDnodePtr2Next(self->iList);
}
SetStatus(ePaused);
return iRes;
}
/*------------------------------------------------------------------------*/
int IsCounting(pExeList self)
{
int iRet;
pDevEntry pDev = NULL;
pICountable pCountInt = NULL;
assert(self);
/* step through the list */
iRet = LLDnodePtr2First(self->iList);
while(iRet != 0)
{
pDev = (pDevEntry)LLDnodePtr(self->iList);
if(pDev)
{
pCountInt = pDev->pDescriptor->GetInterface(pDev->pData,COUNTID);
if(pCountInt)
{
return 1;
}
}
iRet = LLDnodePtr2Next(self->iList);
}
return 0;
}
/*--------------------------------------------------------------------------*/
int ContinueExecution(pExeList self)
{
int i, iRet, iRes;
pDevEntry pDev = NULL;
pICountable pCountInt = NULL;
assert(self);
/* step through the list */
iRes = 0;
iRet = LLDnodePtr2First(self->iList);
while(iRet != 0)
{
pDev = (pDevEntry)LLDnodePtr(self->iList);
if(pDev)
{
pCountInt = pDev->pDescriptor->GetInterface(pDev->pData,COUNTID);
if(pCountInt)
{
iRet = pCountInt->Continue(pDev->pData,self->pOwner);
if(!iRet)
{
iRes = 0;
}
}
}
iRet = LLDnodePtr2Next(self->iList);
}
SetStatus(eCounting);
return iRes;
}
/*------------------------------------------------------------------------*/
void ClearExecutor(pExeList self)
{
int iRet;
pDevEntry pDev = NULL;
assert(self);
iRet = LLDnodePtr2First(self->iList);
while(iRet != 0)
{
pDev = (pDevEntry)LLDnodePtr(self->iList);
if(pDev)
{
DeleteDevEntry(pDev);
}
LLDnodeDelete(self->iList);
iRet = LLDnodePtr2Prev(self->iList);
iRet = LLDnodePtr2Next(self->iList);
}
if(self->pOwner)
{
if(SCGetInterrupt(self->pOwner) > eContinue)
{
self->iStatus = DEVINT;
}
}
self->pOwner = NULL;
self->iEnd = 1;
self->lTask = -1;
self->iRun = 0;
}
/*-------------------------------------------------------------------------*/
int StopCommand(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[])
{
pExeList self = NULL;
int iRet;
char pBueffel[132];
assert(pCon);
assert(pSics);
assert(pData);
/* check Privilege: Muggers may do it */
if(!SCMatchRights(pCon,usMugger))
{
SCWrite(pCon,"ERROR: NO Privilege to Stop operation ",eError);
return 0;
}
argtolower(argc,argv);
self = (pExeList)pData;
if(argc < 2)
{
ListPending(self,pCon);
return 1;
}
iRet = StopExe(self,argv[1]);
if(!iRet)
{
sprintf(pBueffel,"ERROR: %s not found, so could not halt", argv[1]);
SCWrite(pCon,pBueffel,eError);
}
return iRet;
}
/*--------------------------------------------------------------------------*/
int ListExe(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[])
{
return ListPending((pExeList)pData,pCon);
}
/*--------------------------------------------------------------------------
Usage:
Success
*/
int Success(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[])
{
int iRet;
Status eOld;
eOld = GetStatus();
SetStatus(eRunning);
iRet = Wait4Success((pExeList)pData);
if(iRet == DEVINT)
{
if(SCGetInterrupt(pCon) == eAbortOperation)
{
SCSetInterrupt(pCon,eContinue);
iRet = 0;
}
}
else if(iRet == DEVDONE)
{
SCWrite(pCon,"All done",eStatus);
iRet = 1;
}
else if(iRet = DEVERROR)
{
SCWrite(pCon,"Finished with Problems",eStatus);
iRet = 1;
}
SetStatus(eEager);
return iRet;
}
/*--------------------------------------------------------------------------*/
int isInRunMode(pExeList self)
{
assert(self);
return self->iRun;
}
/*--------------------------------------------------------------------------*/
SConnection *GetExeOwner(pExeList self)
{
if(self == NULL)
return NULL;
return self->pOwner;
}
/*--------------------------------------------------------------------------*/
int DevExecTask(void *pData)
{
pExeList self = NULL;
int iRet;
self = (pExeList)pData;
/* am I bound to end ? */
if(self->iEnd)
{
self->lTask = -1;
SetStatus(eEager);
return 0;
}
iRet = CheckExeList(self);
switch(iRet)
{
case -1: /* some problem */
if(SCGetInterrupt(self->pOwner) != eContinue)
{
SCWrite(self->pOwner,"ERROR: aborting operation due to HW problem",
eError);
StopExe(self,"all");
#ifdef DEBUG
printf("DevExecTask found an error\n");
#endif
return 1;
}
else
{
return 1;
}
break;
case 1: /* Success */
self->lTask = -1;
self->iEnd = 1;
SetStatus(eEager);
#ifdef DEBUG
printf("DevExecTask finishes on success\n");
#endif
return 0;
break;
default: /* continue, still busy */
return 1;
}
/* should not get here */
return 1;
}
/*---------------------------------------------------------------------------*/
void DevExecSignal(void *pEL, int iSignal, void *pSigData)
{
int *iInt;
pExeList self = NULL;
self = (pExeList)pEL;
assert(self);
if(iSignal == SICSINT)
{
iInt = (int *)pSigData;
if(*iInt != eContinue)
{
if(self->pOwner)
{
SCWrite(self->pOwner,"ERROR: Interrupting Current Hardware Operation",
eError);
SCSetInterrupt(self->pOwner,*iInt);
}
StopExe(self,"all");
}
}
}