Initial revision
This commit is contained in:
922
devexec.c
Normal file
922
devexec.c
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user