/*-------------------------------------------------------------------------

		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");
         }
      }
   }
   




