// spin_unlock_irqrestore - ?
// wake_up_interruptible  - ?
// free_irq               - ?
// request_irq            - ?
// spin_lock_irqsave      - ?
// interruptible_sleep_on_timeout -?
// HZ                     - Количество прерываний сист. таймера за секунду
// jiffies                - Счетчик тиков системного таймера
// cif_wait_com           - пересмотреть для DOS32 !!!


#define T_Shedule 0       //Использовать для ожидания shedule

#include "complex.h"
#include "pci.h"
#include "cif_i.h"
#include "cif_rcs.h"
#include "cif.h"
#include "dpmi.h"
#include "screen.h"

//#ifndef HZ
//#define HZ 18
//#endif

#define PCI_SUB_VENDOR_ID 0x2C
#define PCI_SUB_SYSTEM_ID 0x2E

unsigned short get_CS();
#pragma aux get_CS = "mov  ax,cs" value[ax];

unsigned long           ulRegisterSave   = 0x0UL;
unsigned long           ulIrqCtrlRegSave = 0x0UL;
unsigned char           *IrqCtrlRegAddr;
unsigned short          cif_base         = 0x00;
unsigned char           bData            = 0x00;

/* ---------------------------------------------------------------------- */
/*  Locals                                                                */
/* ---------------------------------------------------------------------- */

#define DEV_IDENTIFIER_ANZ  4
#define DEV_IDENTIFIER_LEN  3
unsigned char abDevIdentifier[DEV_IDENTIFIER_ANZ][DEV_IDENTIFIER_LEN] = { {'C','I','F'},
                                                                          {'C','O','M'},
                                                                          {'C','O','P'},
                                                                          {'D','E','V'} };
unsigned char abTestDPM [DEV_IDENTIFIER_LEN] = { 0x55, 0xAA, 0x00 };

/* ------------------------------------------------------------------------------------ */
/*   driver state definitions                                                           */
/* ------------------------------------------------------------------------------------ */

#define INI_MSG_WAIT            0x00
#define INI_MSG_RUN             0x40
#define INI_MSG_RDY             0x80
#define INI_MSG_RDYRUN          0xC0

#define COM_FLAG_RDY            0x20

#define RESET_MSG_NON           0x00
#define RESET_MSG_RUN           0x01

#define EXCHGIO_NON             0x00
#define EXCHGIO_EQUAL           0x01
#define EXCHGIO_NOT_EQUAL       0x02

#ifndef CIF_NR_DEVS
#define CIF_NR_DEVS   4
#endif

static unsigned int addresses[] =
{
 0x10,       //PCI_BASE_ADDRESS_0
 0x14,       //PCI_BASE_ADDRESS_1
 0x18,       //PCI_BASE_ADDRESS_2
 0x1c,       //PCI_BASE_ADDRESS_3
 0x20,       //PCI_BASE_ADDRESS_4
 0x24,       //PCI_BASE_ADDRESS_5
 0
};

int cif_major   = CIF_MAJOR;
int cif_nr_devs = 0;// max: CIF_MAX_BOARDS;    /* number of cif devices */

controller *CIF_CTR[4] = {NULL,NULL,NULL,NULL};

DEV_INSTANCE *cif_devices;
int counter_interrupt=0;
int STAT_CIF[4] = {0,0,0,0};

struct Spar_bus
{
 unsigned char  bMax_Retry_Limit;
 unsigned char  bTQUI;
 unsigned short usTSL;
 unsigned char  bTSET;
 unsigned short usMin_TSDR;
 unsigned short usMax_TSDR;
 unsigned long  ulTTR;
 unsigned char  bG;
}Spar_bus1;

struct Spar_bus par_bus[] =
{
 {1,0, 100, 1,11,60 ,11520,10},      //0  9.6
 {1,0, 100, 1,11,60 ,11520,10},      //1  19.2
 {1,0, 100, 1,11,60 ,11520,10},      //2  93.75
 {1,0, 100, 1,11,60 ,11520,10},      //3  187.5
 {1,0, 200, 1,11,100,11520,10},      //4  500
 {1,0, 300, 1,11,150,11520,10},      //5  1000
 {1,0, 300, 1,11,150,11520,10},      //6  1500
 {2,3, 400, 4,11,250,13824, 1},      //7  3000
 {3,6, 600, 8,11,450,13824, 1},      //8  6000
 {4,9,1000,16,11,800,13824, 1},      //9  12000
};

//********* Prototipes **********************
short DevInitBoard ( unsigned short usDevNumber);
short DevGetInfo ( unsigned short usDevNumber, unsigned short usInfoArea,
                   unsigned short usSize, void *pvData);

//*************************************************************************
//* cif_scan_pci ()                                                       *
//* Scan PCI-bus / detect CIF50 boards                                    *
//*************************************************************************
int cif_scan_pci ()
{
 unsigned short usSubVendor, usSubSystem;
 DEV_INSTANCE *dev;

 if(!pci_bios_available())
 {
  int i = 0;
  unsigned long mask, curr, tmp;
  unsigned int ulDPMByteSize = 0x0UL, stat;
  unsigned short dev_index=0,index = 0;

  while(!pci_dev_find(dev_index, &stat, VENDOR_ID, DEVICE_ID))
  {
   PCIReadConfRegWord(stat,stat>>8,PCI_SUB_VENDOR_ID, &usSubVendor);
   PCIReadConfRegWord(stat,stat>>8,PCI_SUB_SYSTEM_ID, &usSubSystem);
   if( SUBVENDOR_ID == usSubVendor && SUBSYSTEM_ID == usSubSystem && index < 4)
   {
    ulDPMByteSize = 0x0UL;
    for(i=0; addresses[i]; i++)
    {
     PCIReadConfRegDword(stat,stat>>8,addresses[i], &curr);
     _asm{cli};
     if(i == 2) ulRegisterSave = curr;
     if(i == 1) cif_base = (unsigned short)(curr & 0xFFFFFFFE);
     if(i == 0) IrqCtrlRegAddr = curr;
     PCIWriteConfRegDword(stat,stat>>8,addresses[i], ~0);
     PCIReadConfRegDword(stat,stat>>8,addresses[i], &mask);
     PCIWriteConfRegDword(stat,stat>>8,addresses[i], curr);
     _asm{sti};
     if(i == 2) ulDPMByteSize = ~(mask & PCI_BASE_ADDRESS_IO_MASK) +1;
    }
//    if(!dpmi_map_physical(IrqCtrlRegAddr,0x50)) bData= IrqCtrlRegAddr[PCI_INTCTRLSTS_REG];
//    bData = (unsigned char)(bData | HW_INTERRUPT_ENABLE);//(bData & ~HW_INTERRUPT_ENABLE); // Desable Interrupt
//    if(!dpmi_map_physical(IrqCtrlRegAddr,0x50));
//     IrqCtrlRegAddr[PCI_INTCTRLSTS_REG]=IrqCtrlRegAddr[PCI_INTCTRLSTS_REG] | HW_INTERRUPT_ENABLE;
//    printf("test IRQ %x\n",IrqCtrlRegAddr[PCI_INTCTRLSTS_REG]);
//    eprintf(GRAY_,"CIF adr(%xh,%xh,%xh)",IrqCtrlRegAddr,cif_base,ulRegisterSave);
    if( cif_nr_devs == 0)
    {
     cif_devices = (DEV_INSTANCE *)malloc(sizeof (DEV_INSTANCE));
     if (!cif_devices) return 0;
     memset(cif_devices, 0, sizeof (DEV_INSTANCE)); cif_nr_devs++;
     dev = (DEV_INSTANCE *)cif_devices;             dev->next = NULL;
    }
    else
    {
     dev = (DEV_INSTANCE *)cif_devices;
     while ( dev->next) dev = (DEV_INSTANCE *)dev->next;
     dev->next = (DEV_INSTANCE *)malloc(sizeof(DEV_INSTANCE));
     if (!dev->next) return 0;
     memset(dev->next, 0, sizeof(DEV_INSTANCE));
     dev = (DEV_INSTANCE *)dev->next; dev->next = NULL; cif_nr_devs++;
    }
    PCIReadConfRegDword(stat,stat>>8,0x3c,&tmp); dev->usBoardIrq=tmp&0xff;
    dev->usBoard            = index;
    dev->ucPCIBusNumber     = stat;
    dev->IrqCtrlRegAddr     = (unsigned char *)IrqCtrlRegAddr;
    dev->usBoardIrq_scanned = dev->usBoardIrq;  // save it, needed while switching between irq and polling modes
    dev->ulBoardAddress     = ulRegisterSave & PCI_BASE_ADDRESS_IO_MASK;
    dev->ulDPMByteSize      = ulDPMByteSize;
    dev->ulDPMSize          = ulDPMByteSize / 1024;
    dev->bActive            = TRUE;
    dev->ucBusType          = BUS_TYPE_PCI;
    dev->usBoardIrq         = 0x00;           //No interrupt  !!
    index++;
   }
   dev_index++;
  }
  if(index == 0) return 0;
  return index;
 }
 return 0;
}

//*************************************************************************
//* Interrupt handler                                                     *
//*************************************************************************
//static void cif_interrupt(int irq, void *dev_id, struct pt_regs *regs)
__interrupt cif_interrupt()
{
 DEV_INSTANCE   *dev = cif_devices;
 unsigned char    bHostFlags;

 // Interrupt context can use plain spin_lock() form because
 // interrupts are disabled inside an interrupt handler.
 // spin_lock (&dev->mutex);

  // Clear device interrupt by reading the host flags
  bHostFlags = *(dev->pbHostFlags);
  dev->bHostFlags = bHostFlags;          // only for information
  dev->tStateInfo.IRQCnt++;              // increment irq counter

  if((bHostFlags & INI_MSG_RDY)==0x00)
  {
    /* Reset on DEV is running */
    dev->bMyDevFlags    = 0x00;
    dev->bReadMsgFlag   = HOST_MBX_EMPTY;
    dev->bWriteMsgFlag  = DEVICE_MBX_FULL;
    dev->bInitMsgFlag   = INI_MSG_WAIT;
    dev->bExIOFlag      = EXCHGIO_NON;
    dev->bStateFlag     = STATE_ERR_NON;
  }
  else
  {
   if(dev->bInitMsgFlag == INI_MSG_WAIT )    // get actual init state
    dev->bInitMsgFlag = (unsigned char)(bHostFlags & INI_MSG_RDYRUN);
   // check if message is available
   if(((bHostFlags ^ dev->bMyDevFlags) & HOSTCOM_FLAG) != 0x00 )
    dev->bReadMsgFlag = HOST_MBX_FULL;
   // check if mailbox to DEV is free
   if(((bHostFlags ^ dev->bMyDevFlags) & DEVACK_FLAG) == 0x00 )
    dev->bWriteMsgFlag = DEVICE_MBX_EMPTY;   // ACK-bit DEV  ==  COM-bit PC --> MBX emty
   // check if IO state equal or not equal
   if(((bHostFlags ^ dev->bMyDevFlags) & PDACK_FLAG) == 0x00 )
    dev->bExIOFlag = EXCHGIO_EQUAL;          // ACK-bit DEV  ==  COM-bit HOST
   else dev->bExIOFlag = EXCHGIO_NOT_EQUAL;  // ACK-bit DEV  !=  COM-bit HOST
   // check for State
   if(((bHostFlags ^ dev->bMyDevFlags) & STATEACK_FLAG) == 0x00 )
    dev->bStateFlag = STATE_ERR_NON;         // ACK-bit DEV  ==  COM-bit PC --> No error
   else dev->bStateFlag = STATE_ERR;         // ACK-bit DEV  ==  COM-bit PC --> No error
  } /* endif */
  //--------------------------------
  // Check application
  //--------------------------------
  // application must be logged in
  if (dev->usOpenCounter > 0)
  {
    //******************************************************************
    // check for read data
    //******************************************************************
    if((dev->bReadState == TRUE) && (dev->bReadMsgFlag != HOST_MBX_EMPTY))
    {
      // Applikation is waiting on read service, MSG is available
      dev->tStateInfo.ReadState = STATE_IN_IRQ;
      switch (dev->bReadMsgFlag)
      {
       case HOST_MBX_EMPTY: break;  // MBX is empty
       case HOST_MBX_SYSERR:        // System ERROR
        dev->bReadState = FALSE; set_flag(dev->pReadSemaphore);
        break;
       case HOST_MBX_FULL:          // Message available
        dev->bReadState = FALSE; set_flag(dev->pReadSemaphore);
        break;
      }
    }
    //******************************************************************
    // check for write data
    //******************************************************************
    if((dev->bWriteState == TRUE) && (dev->bWriteMsgFlag == DEVICE_MBX_EMPTY))
    {
     dev->tStateInfo.WriteState = STATE_IN_IRQ; dev->bWriteState = FALSE;
     set_flag(dev->pWriteSemaphore);
    }
    //******************************************************************
    // check for EXCHGIO state
    //******************************************************************
    if(dev->bExIOEqState == TRUE && dev->bExIOFlag == EXCHGIO_EQUAL)
    { dev->bExIOEqState = FALSE; set_flag(dev->pExIOSemaphore); }
    if(dev->bExIONeqState == TRUE && dev->bExIOFlag == EXCHGIO_NOT_EQUAL)
    { dev->bExIONeqState = FALSE; set_flag(dev->pExIOSemaphore); }
    //******************************************************************
    // check for COM state
    //******************************************************************
    if(dev->bCOMEqState == TRUE && (dev->bHostFlags&COM_FLAG_RDY) == 0)
    { dev->bCOMEqState = FALSE; set_flag(dev->pInitSemaphore); }
    if ( dev->bCOMNeqState == TRUE && (dev->bHostFlags & COM_FLAG_RDY) != 0)
    { dev->bCOMNeqState = FALSE; set_flag(dev->pInitSemaphore); }
    //******************************************************************
    // check for init state
    //******************************************************************
    if(dev->bInitState == TRUE && dev->bInitMsgFlag != INI_MSG_WAIT)
    { dev->bInitState = FALSE; set_flag(dev->pInitSemaphore); }
  }

  printf("H %u ", bHostFlags);
  printf("D %u ", *(dev->pbDevFlags));
  printf("M %u\n", dev->bMyDevFlags);
  //  spin_unlock (&dev->mutex);
  outp(0xA0,0x20); outp(0x20,0x20);
}

// pick the device
DEV_INSTANCE *cif_dev_get_at(unsigned short n)
{
  DEV_INSTANCE *dev = cif_devices;
  if(n >= cif_nr_devs) dev = NULL;
  else while (n--) dev = (DEV_INSTANCE *)dev->next;
  return dev;
}

// <ST> =================================================================================
//  Function: cif_set_irq_state
//            Enabable /Disable interrupt for PCI cards
//  ---------------------------------------------------------------------------------------
//  Input   : DeviceObject -
//  Output  : -
//  Return  : -
//  ================================================================================= <En>
void cif_set_irq_state( unsigned short usIntState, DEV_INSTANCE  *dev)
{
 unsigned char  bData;

 if(dev && (dev->ucBusType == BUS_TYPE_PCI) )
  if ( dev->usBoardIrq != 0 )
  {
   bData=dev->IrqCtrlRegAddr[PCI_INTCTRLSTS_REG];
   if(usIntState==HW_INTERRUPT_ENABLE) bData=(unsigned char)(bData|HW_INTERRUPT_ENABLE);
   else                                bData=(unsigned char)(bData & ~HW_INTERRUPT_ENABLE);
   dev->IrqCtrlRegAddr[PCI_INTCTRLSTS_REG]=bData;
  }
}

//*************************************************************************
//* cif_test_rdy_flag                                                     *
//* read DEV 'RDY' flag status                                            *
//* --------------------------------------------------------------------- *
//* Input   : ptGlobalDrv   - pointer to global DRV structure             *
//* Output  : -                                                           *
//* Return  : TRUE       - Hardware check passed                          *
//*           FALSE      - Hardware check failed                          *
//*************************************************************************
unsigned short cif_test_rdy_flag( DEV_INSTANCE * ptDevInst, unsigned short * usRcsError)
{
  unsigned short usRet = FALSE;
  *usRcsError = 0;            // clear RCS error

  // test RDY flag in DEV HostFlags
  if((*(ptDevInst->pbHostFlags) & INI_MSG_RDY) == 0)
  {
    // RDY flag not set, read RCS error byte
   if((*usRcsError=(unsigned short)ptDevInst->ptDpmAddress->tRcsInfo.RcsError)>=250)
   { *usRcsError = 0; ptDevInst->usSpecialRcsError = TRUE; usRet = TRUE; }
   else
   {
    ptDevInst->usSpecialRcsError = FALSE;
    *usRcsError = (unsigned short)ptDevInst->ptDpmAddress->tRcsInfo.RcsError;
    *usRcsError += DRV_RCS_ERROR_OFFSET;
   }
  }
  else usRet = TRUE; // RDY flag is set
  return usRet;
}

//*************************************************************************
//* cif_test_dpm_size                                                     *
//* compare the DPM size with the configuration                           *
//* --------------------------------------------------------------------- *
//* Input   : ptDevInst  - pointer to DEV instance                        *
//* Output  : -                                                           *
//* Return  : TRUE       - Watchdog check passed                          *
//*           FALSE      - Watchdog check failed                          *
//*************************************************************************
unsigned short cif_test_dpm_size( DEV_INSTANCE * ptDevInst)
{
  unsigned short usCifEntry;
  unsigned short usRet = FALSE;

  // Compare DPM size from the board with the configuration
  // Allow 1 KByte entry in CIF board
  // If BOOTSTRAPLOADER is running, this will show always DPMSize = 1,
  // so use the size which is konfigured !

  // Check if BOOTSTRAPLOADER is running
  if ( (ptDevInst->ptDpmAddress->tFiwInfo.FirmwareName[0] == 'B') &&
       (ptDevInst->ptDpmAddress->tFiwInfo.FirmwareName[1] == 'o') &&
       (ptDevInst->ptDpmAddress->tFiwInfo.FirmwareName[2] == 'o') &&
       (ptDevInst->ptDpmAddress->tFiwInfo.FirmwareName[3] == 't') &&
       (ptDevInst->ptDpmAddress->tFiwInfo.FirmwareName[4] == 's') &&
       (ptDevInst->ptDpmAddress->tFiwInfo.FirmwareName[5] == 't') &&
       (ptDevInst->ptDpmAddress->tFiwInfo.FirmwareName[6] == 'r') &&
       (ptDevInst->ptDpmAddress->tFiwInfo.FirmwareName[7] == 'a')  ) {
    // This is the BOOTSTRAPLOADER, use DPMSize like configured
    usRet = TRUE;
  }
  else
  if((usCifEntry = (unsigned short)(ptDevInst->ptDpmAddress->tDevInfo.DpmSize))== 1)
  {
   if(ptDevInst->ulDPMSize==2) usRet=TRUE; // Allow a DPMSize configuration of 2 KByte
  }
  else
  if(ptDevInst->ulDPMSize==(unsigned long)(ptDevInst->ptDpmAddress->tDevInfo.DpmSize) )
   usRet = TRUE;       // DPM size is equal to the configuration
  return usRet;
}

//*************************************************************************
//* cif_test_dpm_access                                                   *
//* read and write DEV identifier in the DEV DPM                          *
//* --------------------------------------------------------------------- *
//* Input   : ptGlobalDrv   - pointer to global DRV structure             *
//* Output  : -                                                           *
//* Return  : TRUE       - Hardware check passed                          *
//*           FALSE      - Hardware check failed                          *
//*************************************************************************
unsigned short cif_test_dpm_access( DEV_INSTANCE * ptDevInst)
{
  unsigned char  abOrgIdentifier[DEVNAMELEN];
  unsigned char  abTestString   [DEVNAMELEN];
  unsigned short usIdx = 0, usIdFound = 0, usRet = 0;

//  eprintf(GRAY_,"DPM_ACCESS %x - %x",ptDevInst->ptDpmAddress,ptDevInst->ptDpmAddress->tDevInfo.DevIdentifier);

  memcpy(abOrgIdentifier, ptDevInst->ptDpmAddress->tDevInfo.DevIdentifier, DEVNAMELEN);

//  printf("Dev. Identifier: %.3s\n", ptDevInst->ptDpmAddress->tDevInfo.DevIdentifier);
  for(usIdx=0,usIdFound=FALSE;(usIdx<DEV_IDENTIFIER_ANZ)&&(usIdFound==FALSE);usIdx++)
   if((abOrgIdentifier[0] == abDevIdentifier[usIdx][0]) &&
      (abOrgIdentifier[1] == abDevIdentifier[usIdx][1]) &&
      (abOrgIdentifier[2] == abDevIdentifier[usIdx][2])) usIdFound = TRUE;
  if(usIdFound==FALSE) usRet = FALSE;        // No Identifier found, return fault
  else
  {
   // DEV identifiere is OK, write test identifier
   memcpy(ptDevInst->ptDpmAddress->tDevInfo.DevIdentifier,abTestDPM, DEV_IDENTIFIER_LEN);
   // read test identifier
   memcpy(abTestString,ptDevInst->ptDpmAddress->tDevInfo.DevIdentifier,DEVNAMELEN);
   if((abTestString[0]!=abTestDPM[0])||
      (abTestString[1] != abTestDPM[1])||
      (abTestString[2] != abTestDPM[2])) usRet = FALSE; // Can't write test identifier
   else
   {
    // test identifiere is OK, write orignal identifier to dev DPM
    memcpy(ptDevInst->ptDpmAddress->tDevInfo.DevIdentifier,abOrgIdentifier, DEV_IDENTIFIER_LEN);
    // read original identifier
    memcpy(abTestString,ptDevInst->ptDpmAddress->tDevInfo.DevIdentifier, DEVNAMELEN);
    if((abTestString[0]!=abOrgIdentifier[0])||
       (abTestString[1] != abOrgIdentifier[1])||
       (abTestString[2] != abOrgIdentifier[2])) usRet = FALSE;  // Can't write original identifier
     else usRet = TRUE;
   }
  }
  return usRet;
}

//*************************************************************************
//* cif_test_hardware                                                     *
//* test that the DEV hardware is present and all things well             *
//*  - DEV DPM is accessable and DEV board is really at this address      *
//*  - RDY-Flags of the DEV present                                       *
//* ----------------------------------------------------------------------*
//* Input   : ptGlobalDrv   - pointer to global DRV structure             *
//* Output  : -                                                           *
//* Return  : TRUE   - Hardware check OK                                  *
//*           FALSE  - Hardware check failed                              *
//*************************************************************************
void cif_test_hardware( DEV_INSTANCE * ptDevInst)
{
//  eprintf(GRAY_,"Test Hardware");
  ptDevInst->sDrvInitError = 0;    // clear driver error
  if(cif_test_dpm_access( ptDevInst)==FALSE)
   ptDevInst->sDrvInitError = DRV_DEV_DPM_ACCESS_ERROR;
//  eprintf(GRAY_,"TEST_DPM_ACCESS");
  if(cif_test_rdy_flag(ptDevInst, &(ptDevInst->usRcsError))==FALSE)
   ptDevInst->sDrvInitError = DRV_DEV_NOT_READY;
//  eprintf(GRAY_,"TEST_RDY_FLAG");
  if(cif_test_dpm_size( ptDevInst)==FALSE)
   ptDevInst->sDrvInitError = DRV_DEV_DPMSIZE_MISMATCH;
//  eprintf(GRAY_,"TEST_DPM_SIZE");
}

// <ST> =================================================================================
//  Function: cif_check_hardware
//            test that the DEV hardware entries during the test at driver startup
//  ---------------------------------------------------------------------------------------
//  Input   : ptGlobalDrv   - pointer to global DRV structure
//  Output  : -
//  Return  : TRUE   - Hardware check OK
//            FALSE  - Hardware check failed
//  ================================================================================= <En>
unsigned short cif_check_hardware( DEV_INSTANCE * ptDevInst)
{
  unsigned short usRet = FALSE;

  // board is successfully initialized
  if ( ptDevInst->bActive != TRUE) // test on errors
  { ptDevInst->sDrvInitError = DRV_BOARD_NOT_INITIALIZED; usRet = FALSE; }
  else if ( ptDevInst->sDrvInitError != DRV_NO_ERROR) { usRet = FALSE; }
  else if ( ptDevInst->usRcsError != DRV_NO_ERROR) { usRet = FALSE; }
  else usRet = TRUE;
  return usRet;
}

// <ST> =================================================================================
//   Function: cif_test_com
//          test the device COM flag
//  ---------------------------------------------------------------------------------------
//  Input   : dev  - pointer to device instance
//  Output  : -
//  Return  : FALSE  = COM flag not set
//            TRUE   = COM flag set
//  ================================================================================= <En>
unsigned short  cif_test_com( DEV_INSTANCE * dev)
{
  if (dev->usBoardIrq != 0)
  { if(dev->bHostFlags & COM_FLAG_RDY) return (TRUE); else return (FALSE); }
  else if ( (*(dev->pbHostFlags) & COM_FLAG_RDY)) return (TRUE); else return (FALSE);
}

// <ST> =================================================================================
//  Function: cif_test_ready
//            test if device is ready
//  ---------------------------------------------------------------------------------------
//  Input   : dev  - pointer to device instance
//  Output  : -
//  Return  : FALSE  = device not ready
//            TRUE   = device ready
//  ================================================================================= <En>
unsigned short cif_test_ready( DEV_INSTANCE * dev)
{
 if(dev->usBoardIrq!=0)
 {
  // interrupt is running, do not read the flags from the DPM
  if((dev->usSpecialRcsError==TRUE)&&((dev->bInitMsgFlag & INI_MSG_RDY)==0)) return (TRUE);
  if ( dev->bInitMsgFlag & INI_MSG_RDY) return (TRUE);
  else return (FALSE);
 }
 else
 {
  if((dev->usSpecialRcsError==TRUE)&&((*(dev->pbHostFlags) & INI_MSG_RDY)==0)) return (TRUE);
  if((*(dev->pbHostFlags) & INI_MSG_RDY)) return (TRUE); else return (FALSE);
 }
}

// <ST> =================================================================================
//  Function: cif_get_devMBXinfo
//            returns the state of the send mailbox
//  ---------------------------------------------------------------------------------------
//  Input   : dev  - pointer to device instance
//  Output  : -
//  Return  : 0 = DEVICE_MBX_EMPTY
//            1 = DEVICE_MBX_FULL
//  ================================================================================= <En> */
unsigned short cif_get_devMBXinfo( DEV_INSTANCE * dev)
{
 if(dev->usBoardIrq==0)
 {
  // polling mode
  if ( ((*(dev->pbHostFlags) ^ *(dev->pbDevFlags)) & DEVCOM_FLAG) == 0x00) dev->bWriteMsgFlag = DEVICE_MBX_EMPTY;
  else dev->bWriteMsgFlag = DEVICE_MBX_FULL;
 }
 // return actual state, interrupt will set this flag also !
 return ((unsigned short)dev->bWriteMsgFlag);
}

// <ST> =================================================================================
//  Function: cif_get_hostMBXinfo
//            returns the state of the send mailbox
//  ---------------------------------------------------------------------------------------
//  Input   : dev  - pointer to device instance
//  Output  : -
//  Return  : 0 = HOST_MBX_EMPTY
//            1 = HOST_MBX_FULL
//  ================================================================================= <En> */
unsigned short  cif_get_hostMBXinfo( DEV_INSTANCE * dev)
{
 if (dev->usBoardIrq == 0)
 {
  // polling mode
  if ( ((*(dev->pbHostFlags) ^ *(dev->pbDevFlags)) & HOSTACK_FLAG) == 0x00) dev->bReadMsgFlag = HOST_MBX_EMPTY;
  else dev->bReadMsgFlag = HOST_MBX_FULL;
 }
 // return actual state, interrupt will set this flag also !
 return ((unsigned short)dev->bReadMsgFlag);
}

// <ST> =================================================================================
//  Function: cif_clear_host_state
//  ---------------------------------------------------------------------------------------
//  Input   : -
//  Output  : -
//  Return  : -
//  ================================================================================= <En>
void  cif_clear_host_state(DEV_INSTANCE * dev)
{
 if ( dev->usBoardIrq != 0) dev->bMyDevFlags &= (~NOTREADY_FLAG);
 else dev->bMyDevFlags = (unsigned char)(*(dev->pbDevFlags) & (~NOTREADY_FLAG));
 *(dev->pbDevFlags) = dev->bMyDevFlags;
}

// <ST> =================================================================================
//  Function: cif_set_host_state
//  ---------------------------------------------------------------------------------------
//  Input   : -
//  Output  : -
//  Return  : -
//  ================================================================================= <En>
void  cif_set_host_state(DEV_INSTANCE * dev)
{
 if ( dev->usBoardIrq != 0) dev->bMyDevFlags |= NOTREADY_FLAG;
 else dev->bMyDevFlags = (unsigned char)(*(dev->pbDevFlags) | NOTREADY_FLAG);
 *(dev->pbDevFlags)  = dev->bMyDevFlags;
}

// <ST> =================================================================================
//  Function: cif_boot_start
//            Device boot start
//  ---------------------------------------------------------------------------------------
//  Input   : -
//  Output  : -
//  Return  : -
//  ================================================================================= <En>
void  cif_boot_start( DEV_INSTANCE * dev)
{
  /* write WStart-Bit in DevFlags */
  dev->bMyDevFlags |= (RESET_FLAG | INIT_FLAG);
  *(dev->pbDevFlags) = dev->bMyDevFlags;
}

// <ST> =================================================================================
//  Function: cif_cold_start
//            Device cold start
//  ---------------------------------------------------------------------------------------
//  Input   : -
//  Output  : -
//  Return  : -
//  ================================================================================= <En>
void  cif_cold_start( DEV_INSTANCE * dev)
{
  dev->bMyDevFlags |= RESET_FLAG;
  *(dev->pbDevFlags) = dev->bMyDevFlags;
}

// <ST> =================================================================================
//  Function: cif_warm_start
//            Device warm start
//  ---------------------------------------------------------------------------------------
//  Input   : -
//  Output  : -
//  Return  : -
//  ================================================================================= <En>
void  cif_warm_start( DEV_INSTANCE * dev)
{
  /* write warm startm bit in DevFlags */
  dev->bMyDevFlags |= INIT_FLAG;
  *(dev->pbDevFlags) = dev->bMyDevFlags;
}

// <ST> =================================================================================
//  Function: cif_send_msg
//            Signal new message in DEV mailbox is available
//  ---------------------------------------------------------------------------------------
//  Input   : -
//  Output  : -
//  Return  : -
//  ================================================================================= <En> */
void  cif_send_msg( DEV_INSTANCE * dev)
{
 dev->bWriteMsgFlag = DEVICE_MBX_FULL;
 if(dev->usBoardIrq != 0) dev->bMyDevFlags  ^= DEVCOM_FLAG;
 else dev->bMyDevFlags = (unsigned char)(*(dev->pbDevFlags) ^ DEVCOM_FLAG);
 *(dev->pbDevFlags)  = dev->bMyDevFlags;
}

// <ST> =================================================================================
//  Function: cif_quit_msg
//            Signal message is read from the PC
//  ---------------------------------------------------------------------------------------
//  Input   : -
//  Output  : -
//  Return  : -
//  ================================================================================= <En> */
void  cif_quit_msg(  DEV_INSTANCE * dev)
{
 dev->bReadMsgFlag = HOST_MBX_EMPTY;
 if(dev->usBoardIrq != 0) dev->bMyDevFlags ^= HOSTACK_FLAG;     // interrupt mode
 else   dev->bMyDevFlags    = (unsigned char)(*(dev->pbDevFlags) ^ HOSTACK_FLAG); // polling mode
 *(dev->pbDevFlags)  = dev->bMyDevFlags;
}

unsigned short jiffies()
{
 unsigned short ret;
 union REGS pregs;

 pregs.h.ah=0;
 int386(0x1A, &pregs, &pregs);
 ret=pregs.w.cx; ret=ret<<16; ret=pregs.w.dx;
 return(ret);
}

long ms_to_jiffies( unsigned long ulTimeout)
{ return((long)((ulTimeout*HZ)/1000)); }

//***********************************************************************
//*  Function: cif_wait_com                                             *
//*            waits for the COM bit                                    *
//*  Input   : dev  - pointer to device instance                        *
//*            ulTimeout - Timeout                                      *
//*  Output  : -                                                        *
//*  Return  : FALSE = Timeout                                          *
//*            TRUE  = No Timeout                                       *
//***********************************************************************
unsigned short cif_wait_com(DEV_INSTANCE * dev, unsigned long ulTimeout)     //????
{
 long           rtimeout = 0; // rest timeout from interruptible_sleep_on_timeout( ... );
 long           timeout  = ms_to_jiffies( ulTimeout);
 unsigned long  expire   = 0;
 unsigned short usRet    = FALSE;

 if(dev->usBoardIrq != 0)
 {
  // interrupt is active
  //rtimeout=interruptible_sleep_on_timeout( &(dev->pInitSemaphore), timeout);
  // see .../kernel/sched.h
  rtimeout=clear_flag_wait_set(dev->pInitSemaphore, timeout);
  if (!rtimeout) usRet = FALSE;
  else           usRet = TRUE;
 }
 else
 {
  // poll function
  expire = timeout+jiffies();
  if(dev->bCOMNeqState==TRUE) // wait for COM bit is set (not equal)
  {
   while( (((*(dev->pbHostFlags)^ *(dev->pbDevFlags)) & COM_FLAG_RDY)==0x00) &&(jiffies() <= expire))
     if(T_Shedule) schedule(); else t_delay(1);
   if( ((*(dev->pbHostFlags)^ *(dev->pbDevFlags)) & COM_FLAG_RDY)==0x00 ) usRet=FALSE; else usRet = TRUE;
  }
  else  // wait for COM bit is clear
  {
   while( (((*(dev->pbHostFlags)^ *(dev->pbDevFlags)) & COM_FLAG_RDY)!=0x00) && (jiffies() <= expire))
     if(T_Shedule) schedule(); else t_delay(1);
   if( ((*(dev->pbHostFlags)^ *(dev->pbDevFlags)) & COM_FLAG_RDY)!=0x00 ) usRet=FALSE; else usRet = TRUE;
  }
 }
 return usRet;
}

//***********************************************************************
//*  Function: cif_wait_reset                                           *
//*            returns the state of the send mailbox                    *
//*  Input   : dev  - pointer to device instance                        *
//*  Output  : -                                                        *
//*  Return  : FALSE = Timeout                                          *
//*            TRUE  = No Timeout                                       *
//***********************************************************************
unsigned short  cif_wait_reset( DEV_INSTANCE * dev, unsigned long ulTimeout)
{
 long  timeout  = ms_to_jiffies( ulTimeout);
 long  rtimeout = 0;
 unsigned long  expire   = 0;
 unsigned short usRet    = TRUE;

 expire = timeout + jiffies();
 if (dev->usBoardIrq !=0)
 { // interrupt function
   // wait for reset is active, DevFlags == 0
  while( ((*(dev->pbDevFlags) & (INIT_FLAG | RESET_FLAG)) != 0x00) &&(jiffies() <= expire ) )
    if(T_Shedule) schedule(); else t_delay(1);
  if( (*(dev->pbDevFlags) & (INIT_FLAG | RESET_FLAG)) != 0x00 ) usRet = FALSE;    // timeout
  else
  {
//  rtimeout = interruptible_sleep_on_timeout( &(dev->pInitSemaphore), timeout);
   rtimeout=clear_flag_wait_set(dev->pInitSemaphore, timeout);
   if(!rtimeout) usRet = FALSE;
   else          usRet = TRUE;
  }
 }
 else
 {  // poll function
    // wait for reset is active, DevFlags == 0
  while( ((*(dev->pbDevFlags) & (INIT_FLAG | RESET_FLAG)) != 0x00) &&(jiffies() <= expire) )
    if(T_Shedule) schedule(); else t_delay(1);
  if( (*(dev->pbDevFlags) & (INIT_FLAG | RESET_FLAG)) != 0x00 ) usRet = FALSE;
  else
  { // wait for RDY is set
   expire = jiffies() + timeout;
   while( ((*(dev->pbHostFlags) & INI_MSG_RDY) == 0x00) &&(jiffies() <= expire) )
     if(T_Shedule) schedule(); else t_delay(1);
   if( (*(dev->pbHostFlags) & INI_MSG_RDY) == 0x00 ) usRet = FALSE;     // timeout
  }
  // update bInitMsgFlag from DPM, like in interrupt
  dev->bMyDevFlags  = *(dev->pbDevFlags);
  dev->bInitMsgFlag = (unsigned char) (*(dev->pbHostFlags) & INI_MSG_RDYRUN);
 }
 return usRet;
}

//***********************************************************************
//*  Function: cif_wait_put_msg                                         *
//*            wait function for PutMessage                             *
//*  Input   : dev  - pointer to device instance                        *
//*            ulTimeout - Timeout                                      *
//*  Output  : -                                                        *
//*  Return  : FALSE = timeout                                          *
//*            TRUE  = no timeout                                       *
//***********************************************************************
unsigned short  cif_wait_put_msg( DEV_INSTANCE * dev, unsigned long ulTimeout)
{
  long  timeout = ms_to_jiffies( ulTimeout);
  unsigned long  expire  = 0;
  unsigned short usRet   = FALSE;

  if (dev->usBoardIrq != 0)
  {
    // wait timeout, FALSE == timeout
//  interruptible_sleep_on_timeout( &(dev->pWriteSemaphore), timeout);
   clear_flag_wait_set(dev->pWriteSemaphore, timeout);
   if( dev->bWriteMsgFlag == DEVICE_MBX_EMPTY) usRet = TRUE;
  }
  else
  {
   // wait for mailbox is empty
   expire =  timeout + jiffies();
   while( (((*(dev->pbHostFlags)^ *(dev->pbDevFlags)) & DEVACK_FLAG) != 0x00) && (jiffies() <= expire ) )
     if(T_Shedule) schedule(); else t_delay(1);
   if( ((*(dev->pbHostFlags)^ *(dev->pbDevFlags)) & DEVACK_FLAG) != 0x00 ) usRet = FALSE; // timeout
   else                      usRet = TRUE;  // no timeout
  }
  return usRet;
}

//***********************************************************************
//*  Function: cif_wait_get_msg                                         *
//*            wait function for GetMessage                             *
//*  Input   : dev  - pointer to device instance                        *
//*            ulTimeout - Timeout                                      *
//*  Output  : -                                                        *
//*  Return  : FALSE = Timeout                                          *
//*            TRUE  = No Timeout                                       *
//***********************************************************************
unsigned short  cif_wait_get_msg( DEV_INSTANCE * dev, unsigned long ulTimeout)
{
  long   timeout = ms_to_jiffies( ulTimeout);
  unsigned long   expire  = 0;
  unsigned short  usRet   = FALSE;

  if (dev->usBoardIrq != 0)
  {
   // No Message available, wait for Message
   // wait timeout, FALSE == timeout
//   interruptible_sleep_on_timeout( &(dev->pReadSemaphore), timeout);
   clear_flag_wait_set(dev->pReadSemaphore, timeout);
   if( dev->bReadMsgFlag == HOST_MBX_FULL) usRet = TRUE;
  }
  else
  {
   // wait for message is available
   expire = timeout + jiffies();
   while( (((*(dev->pbHostFlags)^ *(dev->pbDevFlags)) & HOSTCOM_FLAG) == 0x00) && (jiffies() <= expire) )
     if(T_Shedule) schedule(); else t_delay(1);
   if( ((*(dev->pbHostFlags)^ *(dev->pbDevFlags)) & HOSTCOM_FLAG) == 0x00 )  usRet = FALSE; // timeout
   else                    usRet = TRUE;  // no timeout
  }
  return usRet;
}

//*************************************************************************
//* cif_drv_load()                                                        *
//* Device Driver Load                                                    *
//*  Input   :                                                            *
//*  Output  :                                                            *
//*  Return  : bSuccess  TRUE   - at least one board is initialized       *
//*                      FALSE  - no board is initialized                 *
//*************************************************************************
int cif_drv_load (void)
{
// int            result = 0;
  char           k,k1;
  int            bSuccess = 0; // no board available
  unsigned short usIdx = 0;
  DEV_INSTANCE * dev = NULL;
  _dpmi_paddr    i_addr;

  if(cif_nr_devs > 0)
  {
   for ( usIdx = 0; usIdx < cif_nr_devs/*CIF_MAX_BOARDS*/; usIdx++)
   {
    dev=cif_dev_get_at(usIdx);
    if(dev->bActive == TRUE)
    {
//     eprintf(GRAY_,"Drv load");

     dev->pDpmBase=dev->ulBoardAddress;
     dev->ptDpmAddress=dev->ulBoardAddress+dev->ulDPMByteSize-1024;
     if(dpmi_map_physical(dev->ptDpmAddress,1024,(unsigned long *)&dev->ptDpmAddress)) dev->bActive=FALSE;
     dev->pbDpmSendArea=dev->ulBoardAddress;
//     eprintf(GRAY_,"Drv map1 %d",dev->bActive);
     if(dpmi_map_physical(dev->pbDpmSendArea,(dev->ulDPMByteSize - 1024)/2,(unsigned long *)&dev->pbDpmSendArea)) dev->bActive=FALSE;
     dev->pbDpmReceiveArea=dev->ulBoardAddress+(dev->ulDPMByteSize - 1024)/2;
//     eprintf(GRAY_,"Drv map2 %d",dev->bActive);
     if(dpmi_map_physical(dev->pbDpmReceiveArea,(dev->ulDPMByteSize - 1024)/2,(unsigned long *)&dev->pbDpmReceiveArea)) dev->bActive=FALSE;
     // all parameters successfully read. Initialize instance No. usIdx
     dev->usRcsError    = 0;  // RCS-Error during startup
     dev->sDrvInitError = 0;  // DRV-Error during startup
     // pointers to the DEV dpm cells
     dev->pbHostFlags = &(dev->ptDpmAddress->HostFlags);
     dev->pbDevFlags  = &(dev->ptDpmAddress->DevFlags);
     // initialize start states
     dev->usOpenCounter  = 0;
     dev->bInitMsgFlag   = INI_MSG_WAIT;       // Init state
     dev->bReadMsgFlag   = HOST_MBX_EMPTY;     // Read state
     dev->bWriteMsgFlag  = DEVICE_MBX_EMPTY;   // write state
     dev->bExIOFlag      = EXCHGIO_NON;        // IO state
     dev->bStateFlag     = STATE_ERR_NON;      // State field
//     eprintf(GRAY_,"Drv map3 %d",dev->bActive);

     dev->pInitSemaphore=create_flag(NULL,"CIFInSem");
     dev->pReadSemaphore=create_flag(NULL,"CIFRdSem");
     dev->pWriteSemaphore=create_flag(NULL,"CIFWrSem");
     dev->pExIOSemaphore=create_flag(NULL,"CIFExIOSem");

//     eprintf(GRAY_,"Create Semafore");
//     OldIRQ = DPMI_getvect(0x0A);

     // request IRQ, register interrupt handler and BHs
     if (dev->usBoardIrq != 0)
     {
      i_addr.offset32=cif_interrupt; i_addr.selector=get_CS();
//      eprintf(GRAY_,"Get IRQ %d",dev->usBoardIrq);
      if(!dpmi_setvect(0x68+dev->usBoardIrq,&i_addr))
      {
       k1=1; k=inp(0xA1); k1<<=(10-8); outp(0xA1,k&(k1^0xFF));
       if(dev->ucBusType==BUS_TYPE_PCI) cif_set_irq_state(HW_INTERRUPT_ENABLE, dev);

//       eprintf(GRAY_,"Get IRQ OK");
      }
     }
     cif_test_hardware( dev);

// virtual board address is allocated
//     printf("V-IRQ                     = %p \n", dev->pvVirtualIrq );
//     printf("V-DPM base address        = %p \n", dev->pDpmBase );
//     printf("V-DPM send area address   = %p \n", dev->pbDpmSendArea);
//     printf("V-DPM recive area address = %p \n", dev->pbDpmReceiveArea);
//     printf("V-DPM last kByte          = %p \n", dev->ptDpmAddress);
//     printf("Initialisation OK\n");
        // one board is initialized
     bSuccess = 1;
    }
   }  // end for
  }
  if(!bSuccess)
  {
   dpmi_free_map_physical(dev->ptDpmAddress);
   dpmi_free_map_physical(dev->pbDpmReceiveArea);
   dpmi_free_map_physical(dev->pbDpmSendArea);
  }
  return bSuccess;
}

//*************************************************************************
//* cif_drv_unload                                                        *
//* Device Driver Unload                                                  *
//*************************************************************************
BOOL cif_drv_unload (void)
{
  DEV_INSTANCE *  dev = cif_devices;

  while(dev)
  {               // deallocate memory, free irq
   if(dev->usBoardIrq)
   {
    cif_set_irq_state( HW_INTERRUPT_DISABLE, dev);
//      free_irq( (unsigned int)(dev->usBoardIrq), dev);
   }
   if((dev->bActive==TRUE) && (dev->pDpmBase!=NULL))
   {
      dpmi_free_map_physical( dev->ptDpmAddress);
      dpmi_free_map_physical( dev->pbDpmReceiveArea);
      dpmi_free_map_physical( dev->pbDpmSendArea);
   }
   dev = (DEV_INSTANCE *)dev->next;
  }
  return (TRUE); // always TRUE if driver is static
}

// <ST> =================================================================================
//  Function: cif_get_msg_status
//  ---------------------------------------------------------------------------------------
//  Input   : dev  - pointer to DEV_INSTANCE
//  Output  : -
//  Return  : -
//  ================================================================================= <En>
void  cif_get_msg_status( DEV_INSTANCE * dev, unsigned char InByte)
{
 dev->bHostFlags = InByte;              // only for information
 dev->tStateInfo.IRQCnt++;              // increment irq counter

 if((InByte & INI_MSG_RDY) == 0x00)
 {
    /* Reset on DEV is running */
    dev->bMyDevFlags    = 0x00;
    dev->bReadMsgFlag   = HOST_MBX_EMPTY;
    dev->bWriteMsgFlag  = DEVICE_MBX_FULL;
    dev->bInitMsgFlag   = INI_MSG_WAIT;
    dev->bExIOFlag      = EXCHGIO_NON;
    dev->bStateFlag     = STATE_ERR_NON;
 }
 else
 {
   if(dev->bInitMsgFlag == INI_MSG_WAIT)
   {
    // get actual init state
    dev->bInitMsgFlag = (unsigned char)(InByte & INI_MSG_RDYRUN);
   }
   // check if message is available
   if(((InByte^dev->bMyDevFlags) & HOSTCOM_FLAG) != 0x00)
    dev->bReadMsgFlag = HOST_MBX_FULL;      /* ACK-bit DEV != COM-bit PC   --> message inside */
   // check if mailbox to DEV is free
   if(((InByte ^ dev->bMyDevFlags) & DEVACK_FLAG)== 0x00)
    dev->bWriteMsgFlag = DEVICE_MBX_EMPTY;  /* ACK-bit DEV  ==  COM-bit PC --> MBX emty */
   // check if IO state equal or not equal
   if(((InByte ^ dev->bMyDevFlags) & PDACK_FLAG) == 0x00)
    dev->bExIOFlag = EXCHGIO_EQUAL;         /* ACK-bit DEV  ==  COM-bit HOST */
   else dev->bExIOFlag = EXCHGIO_NOT_EQUAL; /* ACK-bit DEV  !=  COM-bit HOST */
   // check for State
   if(((InByte ^ dev->bMyDevFlags) & STATEACK_FLAG) == 0x00 )
    dev->bStateFlag = STATE_ERR_NON;        /* ACK-bit DEV  ==  COM-bit PC --> No error */
   else dev->bStateFlag = STATE_ERR;        /* ACK-bit DEV  ==  COM-bit PC --> No error */
 } /* endif */

 // application must be logged in
 if (dev->usOpenCounter > 0)
 {
  //******************************************************************
  // check for read data
  //******************************************************************
  if((dev->bReadState == TRUE) && (dev->bReadMsgFlag != HOST_MBX_EMPTY))
  { // application is waiting
    // Applikation is waiting on read service, MSG is available
    dev->tStateInfo.ReadState   = STATE_IN_IRQ;
    switch (dev->bReadMsgFlag)
    {
      case HOST_MBX_EMPTY:           // MBX is empty
         /* Nothing to do */
         break;
      case HOST_MBX_SYSERR:          // System ERROR
         dev->bReadState = FALSE; set_flag(dev->pReadSemaphore);
         break;
      case HOST_MBX_FULL:           /* Message available */
        dev->bReadState = FALSE; set_flag(dev->pReadSemaphore);
        break;
    }
  }

  //******************************************************************
  // check for write data
  //******************************************************************
  if ( (dev->bWriteState == TRUE) && (dev->bWriteMsgFlag == DEVICE_MBX_EMPTY)  )
  {
   dev->tStateInfo.WriteState = STATE_IN_IRQ; dev->bWriteState = FALSE;
   set_flag(dev->pWriteSemaphore);
  }

  //******************************************************************
  // check for EXCHGIO state
  //******************************************************************
  if(dev->bExIOEqState == TRUE)
   if (dev->bExIOFlag == EXCHGIO_EQUAL)
   { dev->bExIOEqState = FALSE; set_flag(dev->pExIOSemaphore); }
  if ( dev->bExIONeqState == TRUE )
   if (dev->bExIOFlag == EXCHGIO_NOT_EQUAL)
   { dev->bExIONeqState = FALSE; set_flag(dev->pExIOSemaphore); }

  //******************************************************************
  // check for COM state
  //******************************************************************
  if(dev->bCOMEqState == TRUE)
   if((dev->bHostFlags & COM_FLAG_RDY) == 0)
   { dev->bCOMEqState = FALSE; set_flag(dev->pInitSemaphore); }
  if(dev->bCOMNeqState == TRUE)
   if ( (dev->bHostFlags & COM_FLAG_RDY) != 0)
   { dev->bCOMNeqState = FALSE; set_flag(dev->pInitSemaphore); }
  //******************************************************************
  // check for init state
  //******************************************************************
  if(dev->bInitState == TRUE)
   if ( dev->bInitMsgFlag != INI_MSG_WAIT)
   { dev->bInitState = FALSE; set_flag(dev->pInitSemaphore); }
 }
}

//***********************************************************************
//***********************************************************************
//**              Driver Functions                                     **
//***********************************************************************
//***********************************************************************
int ioctlinitdrv(DEVIO_RESETCMD* tBuffer)
{
 DEV_INSTANCE  *dev = NULL;

 tBuffer->sError = 0;    // clear error
 if(tBuffer->usBoard >= cif_nr_devs ) tBuffer->sError = DRV_BOARD_NOT_INITIALIZED;
 else
 if((dev=(DEV_INSTANCE *)cif_dev_get_at(tBuffer->usBoard))==NULL)
  tBuffer->sError = DRV_BOARD_NOT_INITIALIZED;
 else
 {
  // lets application open
  if(dev->usOpenCounter==0)
  {
   // 1st time INITDRV is called, run hardware test for this board
   // Reset error -14 is available
   if(dev->sDrvInitError==DRV_DEV_OS_VERSION_ERROR) dev->sDrvInitError = DRV_NO_ERROR;
   if(cif_check_hardware(dev)==FALSE)
   {
    // hardwaretest failed
    if (dev->usRcsError!=0) tBuffer->sError = dev->usRcsError;  // RCS error ocurred
    else tBuffer->sError = dev->sDrvInitError;                  // or real init error
   }
   else
   {
    // 1st time INITDRV is called
    cif_get_msg_status( dev,*(dev->pbHostFlags));// read Board state flags
    dev->bMyDevFlags = *(dev->pbDevFlags);  // store actual flags in internal structure
    // Board is available
    dev->usOpenCounter++;                           // add number of logged applications
   }
  }    // DRV is running
  else dev->usOpenCounter++;      // new application logged in
  // return DPM size
  tBuffer->ulDpmSize = (unsigned long)(dev->ptDpmAddress->tDevInfo.DpmSize);
  // store OpenCount for information display
  dev->tStateInfo.OpenCnt = dev->usOpenCounter;
 }
 // return length of output data
 return(sizeof(DEVIO_RESETCMD));
}

int ioctlexitdrv(DEVIO_EXITCMD *tBuffer)
{
 DEVIO_EXITCMD *pExitCmd;
 DEV_INSTANCE  *dev = NULL;

 pExitCmd=tBuffer;
 pExitCmd->sError = 0;    // clear error
 if(pExitCmd->usBoard >= cif_nr_devs) pExitCmd->sError = DRV_BOARD_NOT_INITIALIZED;
 else if((dev=(DEV_INSTANCE *)cif_dev_get_at( pExitCmd->usBoard))==NULL)
  pExitCmd->sError = DRV_BOARD_NOT_INITIALIZED;
 else if(dev->usOpenCounter == 0)
 {
  pExitCmd->usDrvOpenCount = dev->usOpenCounter;
  pExitCmd->sError = DRV_BOARD_NOT_INITIALIZED;
 }
 else
 {
  /* check for open read/write */
  if(dev->usOpenCounter==1)
  {
   // disable interrupt until we are ready
//   spin_lock_irqsave ( &dev->mutex, flags); //spin_lock_irq ( &dev->mutex_ioctl);
   _asm{cli};
   if(dev->bReadState==TRUE)
   { dev->bReadState = FALSE; set_flag(dev->pReadSemaphore); }
   if(dev->bWriteState==TRUE)
   { dev->bWriteState=FALSE; set_flag(dev->pWriteSemaphore); }
   if(dev->bInitState == TRUE)
   { dev->bInitState = FALSE; set_flag(dev->pInitSemaphore); }
   if((dev->bExIOEqState == TRUE)||(dev->bExIONeqState==TRUE))
   { dev->bInitState = FALSE; set_flag(dev->pInitSemaphore); }
   if((dev->bCOMEqState == TRUE)||(dev->bCOMNeqState == TRUE))
   { dev->bInitState = FALSE; set_flag(dev->pInitSemaphore); }
   // enable interrupt we are ready
//   spin_unlock_irqrestore ( &dev->mutex, flags); //spin_unlock_irq ( &dev->mutex_ioctl);
   _asm{sti};
  } /* endif */
  dev->usOpenCounter--;    // Number of applications
  dev->tStateInfo.OpenCnt = dev->usOpenCounter;
  // return OpenCounter for application interface
  pExitCmd->usDrvOpenCount = dev->usOpenCounter;
 }
 return(sizeof(DEVIO_EXITCMD));
}

int ioctlgetinfo(DEVIO_GETDEVINFOCMD * tBuffer)
{
 int lRet;
 DEVIO_GETDEVINFOCMD *ptGetInfoCmd,*pvData;
 DEV_INSTANCE  *dev = NULL;

 pvData=ptGetInfoCmd=tBuffer;
 ptGetInfoCmd->sError = 0;    // clear error

 // setup length of output datas
 lRet = sizeof(ptGetInfoCmd->sError);
 // Board must be installed, then all info functions available
 if(ptGetInfoCmd->usBoard >= cif_nr_devs)
 { ptGetInfoCmd->sError = DRV_BOARD_NOT_INITIALIZED; lRet = 0; }
 else
 if((dev=(DEV_INSTANCE *)cif_dev_get_at(ptGetInfoCmd->usBoard))==NULL)
 { ptGetInfoCmd->sError = DRV_BOARD_NOT_INITIALIZED; lRet = 0; }
 else
 {
  //----------------------------------
  // all things well lets work
  //----------------------------------
  // read the InfoArea
  switch ( ptGetInfoCmd->usInfoArea)
  {
   case GET_DRIVER_INFO:
     if (dev->usBoardIrq!=0)
     {
      // copy actual state information, interrupt is running
      dev->tStateInfo.HostFlags    = dev->bHostFlags;   // only for information
      dev->tStateInfo.MyDevFlags   = dev->bMyDevFlags;  // only for information
      dev->tStateInfo.InitMsgFlag  = dev->bInitMsgFlag; // only for information
      dev->tStateInfo.ReadMsgFlag  = dev->bReadMsgFlag; // only for information
      dev->tStateInfo.WriteMsgFlag = dev->bWriteMsgFlag;// only for information
     }
     else
     {
      // copy actual state information, polling is activ
      dev->tStateInfo.HostFlags    = *(dev->pbHostFlags); // only for information
      dev->tStateInfo.MyDevFlags   = *(dev->pbDevFlags);  // only for information
      dev->tStateInfo.InitMsgFlag  = dev->bInitMsgFlag;   // only for information;
      dev->tStateInfo.ReadMsgFlag  = dev->bReadMsgFlag;   // only for information;
      dev->tStateInfo.WriteMsgFlag = dev->bWriteMsgFlag;  // only for information;
     }
     memcpy((unsigned char *)(pvData->pabInfoData), (unsigned char *)&(dev->tStateInfo),
            ptGetInfoCmd->usInfoLen);
     lRet += ptGetInfoCmd->usInfoLen; break;       // return length of all output data
   case GET_VERSION_INFO:
     memcpy((unsigned char *)(pvData->pabInfoData), (unsigned char *)&(dev->ptDpmAddress->tDevVersion),
            ptGetInfoCmd->usInfoLen);
     lRet += ptGetInfoCmd->usInfoLen; break;       // return length of all output data
   case GET_FIRMWARE_INFO:
     memcpy((unsigned char *)(pvData->pabInfoData), (unsigned char *)&(dev->ptDpmAddress->tFiwInfo),
            ptGetInfoCmd->usInfoLen);
     lRet += ptGetInfoCmd->usInfoLen; break;       // return length of all output data
   case GET_TASK_INFO:
     memcpy((unsigned char *)(pvData->pabInfoData), (unsigned char *)&(dev->ptDpmAddress->tTaskInfo),
            ptGetInfoCmd->usInfoLen);
     lRet += ptGetInfoCmd->usInfoLen; break;       // return length of all output data
   case GET_RCS_INFO:
     memcpy((unsigned char *)(pvData->pabInfoData), (unsigned char *)&(dev->ptDpmAddress->tRcsInfo),
            ptGetInfoCmd->usInfoLen);
     lRet += ptGetInfoCmd->usInfoLen; break;       // return length of all output data
   case GET_DEV_INFO:
     memcpy((unsigned char *)(pvData->pabInfoData), (unsigned char *)&(dev->ptDpmAddress->tDevInfo),
            ptGetInfoCmd->usInfoLen);
     lRet += ptGetInfoCmd->usInfoLen; break;
   case GET_IO_INFO:
     ptGetInfoCmd->pabInfoData = (unsigned char *)malloc(ptGetInfoCmd->usInfoLen);
     ((IOINFO *)(ptGetInfoCmd->pabInfoData))->bComBit         =(unsigned char)cif_test_com(dev);
     ((IOINFO *)(ptGetInfoCmd->pabInfoData))->bIOExchangeMode =(unsigned char)((dev->ptDpmAddress->tRcsInfo.DriverType & 0xF0) >> 4);
     ((IOINFO *)(ptGetInfoCmd->pabInfoData))->ulIOExchangeCnt = dev->tStateInfo.ExIOCnt;
     memcpy((unsigned char *)(pvData->pabInfoData),(unsigned char *)(ptGetInfoCmd->pabInfoData),
            ptGetInfoCmd->usInfoLen);
     lRet += ptGetInfoCmd->usInfoLen; free(ptGetInfoCmd->pabInfoData); break;
   case GET_IO_SEND_DATA:
     memcpy((unsigned char *)(pvData->pabInfoData), (unsigned char *)dev->pbDpmSendArea,
            ptGetInfoCmd->usInfoLen);
     lRet += ptGetInfoCmd->usInfoLen; break;
   default:                                         // InfoArea unknown
     ptGetInfoCmd->sError = DRV_PARAMETER_UNKNOWN; lRet = 0;
  }
 }
 return(lRet);
}

int ioctlsethost(DEVIO_TRIGGERCMD *tBuffer)
{
 DEVIO_TRIGGERCMD *ptGetTriggerCmd;
 DEV_INSTANCE  *dev = NULL;

 ptGetTriggerCmd=tBuffer;
 ptGetTriggerCmd->sError = 0;                    // clear error
 // at last one application must be init
 if(ptGetTriggerCmd->usBoard>=cif_nr_devs) ptGetTriggerCmd->sError = DRV_BOARD_NOT_INITIALIZED;
 else
 if((dev=(DEV_INSTANCE *)cif_dev_get_at( ptGetTriggerCmd->usBoard))==NULL)
  ptGetTriggerCmd->sError = DRV_BOARD_NOT_INITIALIZED;
 else if(dev->usOpenCounter==0)            ptGetTriggerCmd->sError = DRV_BOARD_NOT_INITIALIZED;
 else if(cif_test_ready(dev)==FALSE)      ptGetTriggerCmd->sError = DRV_DEV_NOT_READY;
 else if((dev->bCOMEqState!=FALSE)||(dev->bCOMNeqState!=FALSE))
  ptGetTriggerCmd->sError = DRV_CMD_ACTIVE;
 else
 {
  // clear host ready and wait for COM-bit is set
  if(ptGetTriggerCmd->usMode==HOST_READY)
  {
   // disable interrupt until we are ready
   // The process context must use spin_lock_irq() because it knows that
   // interrupts are always enabled while executing the device ioctl() method.
   //spin_lock_irqsave ( &dev->mutex, flags); //spin_lock_irq ( &dev->mutex_ioctl);
   _asm{cli};
   // clear host ready bit in bDevFlags and write it
   cif_clear_host_state(dev);
   // test if COM bit is set
   if(cif_test_com(dev)==TRUE)
   {
    // COM bit is set
    // enable interrupt we are ready
    // spin_unlock_irqrestore ( &dev->mutex, flags); //spin_unlock_irq( &dev->mutex_ioctl);
    _asm{sti};
   }
   else if ( ptGetTriggerCmd->ulTimeout == 0L )
   {
    // No Timeout, don't wait for the COM-Bit
    // enable interrupt we are ready
    //spin_unlock_irqrestore ( &dev->mutex, flags); //spin_unlock_irq( &dev->mutex_ioctl);
    _asm{sti};
   }
   else
   {
    // we have to wait for the COM-bit
    dev->bCOMNeqState = TRUE;
    // enable interrupt we are ready
    //spin_unlock_irqrestore ( &dev->mutex, flags); //spin_unlock_irq( &dev->mutex_ioctl);
    _asm{sti};
    if(cif_wait_com(dev, ptGetTriggerCmd->ulTimeout)==FALSE) ptGetTriggerCmd->sError = DRV_DEV_NO_COM_FLAG;
    dev->bCOMNeqState = FALSE;
   }
  }
  else
  {
   // disable interrupt until we are ready
   //spin_lock_irqsave ( &dev->mutex, flags); //spin_lock_irq ( &dev->mutex_ioctl);
   _asm{cli};
   // set host ready bit in bDevFlags and write it
   cif_set_host_state(dev);
   // test if COM bit is clear
   if(cif_test_com(dev) == FALSE)
   {
    // COM bit is clear
    // enable interrupt we are ready
    //spin_unlock_irqrestore ( &dev->mutex, flags); //spin_unlock_irq( &dev->mutex_ioctl);
    _asm{sti};
   }
   else
   if(ptGetTriggerCmd->ulTimeout== 0L)
   {
    // No Timeout, don't wait for the COM-Bit
    // enable interrupt we are ready
    //spin_unlock_irqrestore ( &dev->mutex, flags); //spin_unlock_irq ( &dev->mutex_ioctl);
    _asm{sti};
   }
   else
   {
    // we have to wait for COM-bit is clear
    dev->bCOMEqState = TRUE;
    // enable interrupt we are ready
//    spin_unlock_irqrestore ( &dev->mutex, flags); //spin_unlock_irq ( &dev->mutex_ioctl);
    _asm{sti};
    if(cif_wait_com( dev, ptGetTriggerCmd->ulTimeout) == FALSE)
     ptGetTriggerCmd->sError = DRV_DEV_NO_COM_FLAG;
   }
   dev->bCOMEqState = FALSE;
  }
 }
 return(sizeof(ptGetTriggerCmd->sError));
}

int ioctlgetparameter(DEVIO_GETPARAMETERCMD *tBuffer)
{
 int lRet;
 DEVIO_GETPARAMETERCMD *pGetParamCmd;
 DEV_INSTANCE  *dev = NULL;

 pGetParamCmd=tBuffer;
 pGetParamCmd->sError = 0;    // clear error
 // length of output data
 lRet = sizeof(pGetParamCmd->sError);
 if(pGetParamCmd->usBoard >= cif_nr_devs)
 { pGetParamCmd->sError = DRV_BOARD_NOT_INITIALIZED; lRet = -1; }
 else if((dev=(DEV_INSTANCE *)cif_dev_get_at(pGetParamCmd->usBoard))==NULL)
 { pGetParamCmd->sError = DRV_BOARD_NOT_INITIALIZED; lRet = -1; }
 else if(dev->usOpenCounter==0)
 { pGetParamCmd->sError = DRV_BOARD_NOT_INITIALIZED; lRet = -1; }
 else
 {
  switch (pGetParamCmd->usTaskParamNum)
  {
   case 1:   // Task 1
     memcpy((unsigned char *)&(pGetParamCmd->TaskParameter[0]),
            (unsigned char *)&(dev->ptDpmAddress->tKpt1Param),
            pGetParamCmd->usTaskParamLen);
     lRet += pGetParamCmd->usTaskParamLen; break;
   case 2:   // Task 2
     memcpy((unsigned char *)&(pGetParamCmd->TaskParameter[0]),
            (unsigned char *)&(dev->ptDpmAddress->tKpt2Param),
            pGetParamCmd->usTaskParamLen);
     lRet += pGetParamCmd->usTaskParamLen; break;
   default:  // parameter error
     pGetParamCmd->sError = DRV_USR_NUMBER_INVALID; lRet = -1;
     break;
  }
 }
 return(lRet);
}

int ioctlparameter(DEVIO_PUTPARAMETERCMD *tBuffer)
{
 DEVIO_PUTPARAMETERCMD *pPutParamCmd;
 DEV_INSTANCE  *dev = NULL;

 pPutParamCmd=tBuffer;
 pPutParamCmd->sError = 0;    // clear error
 if(pPutParamCmd->usBoard >= cif_nr_devs) pPutParamCmd->sError = DRV_BOARD_NOT_INITIALIZED;
 else if((dev = (DEV_INSTANCE *)cif_dev_get_at( pPutParamCmd->usBoard))==NULL)
  pPutParamCmd->sError = DRV_BOARD_NOT_INITIALIZED;
 else if(dev->usOpenCounter==0) pPutParamCmd->sError = DRV_BOARD_NOT_INITIALIZED;
 else
 {
  switch (pPutParamCmd->usTaskParamNum)
  {
   case 1:   // Task 1
     memcpy ( (unsigned char *)&(dev->ptDpmAddress->tKpt1Param),
              (unsigned char *)&(pPutParamCmd->TaskParameter),
              pPutParamCmd->usTaskParamLen);
     break;
   case 2:   // Task 2
     memcpy ( (unsigned char *)&(dev->ptDpmAddress->tKpt2Param),
              (unsigned char *)&(pPutParamCmd->TaskParameter),
              pPutParamCmd->usTaskParamLen);
     break;
   case 3:   // Task 3
     memcpy ( (unsigned char *)&(dev->ptDpmAddress->tDevMbx),
              (unsigned char *)&(pPutParamCmd->TaskParameter),
              pPutParamCmd->usTaskParamLen);
     break;
   case 4:   // Task 4
     memcpy ( (unsigned char *)&(dev->ptDpmAddress->tDevMbx) + sizeof(TASKPARAM),
              (unsigned char *)&(pPutParamCmd->TaskParameter),
              pPutParamCmd->usTaskParamLen);
     break;
   case 5:   // Task 5
     memcpy ( (unsigned char *)&(dev->ptDpmAddress->tDevMbx) + ( 2 * sizeof(TASKPARAM)),
              (unsigned char *)&(pPutParamCmd->TaskParameter),
              pPutParamCmd->usTaskParamLen);
     break;
   case 6:   // Task 6
     memcpy ( (unsigned char *)&(dev->ptDpmAddress->tDevMbx) + ( 3 * sizeof(TASKPARAM)),
              (unsigned char *)&(pPutParamCmd->TaskParameter),
              pPutParamCmd->usTaskParamLen);
     break;
   case 7:   // Task 7
     memcpy ( (unsigned char *)&(dev->ptDpmAddress->tDevMbx) + ( 4 * sizeof(TASKPARAM)),
              (unsigned char *)&(pPutParamCmd->TaskParameter),
              pPutParamCmd->usTaskParamLen);
     break;
   default:  // parameter error
     pPutParamCmd->sError = DRV_USR_NUMBER_INVALID;
     break;
  }
 }
 return(sizeof(DEVIO_PUTPARAMETERCMD));
}

int ioctlresetdev(DEVIO_RESETCMD *tBuffer)
{
 DEVIO_RESETCMD *pResetCmd;
 DEV_INSTANCE  *dev = NULL;

 pResetCmd=tBuffer;
 pResetCmd->sError = 0;    // clear error
 // is DEV board installed an driver activ
 if(pResetCmd->usBoard >= cif_nr_devs) pResetCmd->sError = DRV_BOARD_NOT_INITIALIZED;
 else if((dev=(DEV_INSTANCE *)cif_dev_get_at(pResetCmd->usBoard))==NULL)
  pResetCmd->sError = DRV_BOARD_NOT_INITIALIZED;
 else if(dev->usOpenCounter==0)        pResetCmd->sError = DRV_BOARD_NOT_INITIALIZED;
 else if(dev->bInitState!=FALSE)       pResetCmd->sError = DRV_CMD_ACTIVE;
 else
 {
  // disable interrupt until we are ready
  //spin_lock_irqsave ( &dev->mutex, flags); //spin_lock_irq ( &dev->mutex);
  _asm{cli};
  if(pResetCmd->usMode==4)      cif_boot_start(dev);   // boot
  else if(pResetCmd->usMode==3) cif_warm_start(dev);   // warm boot
  else                          cif_cold_start(dev);   // cold boot

  // wait for RDY is gone and init state OK
  dev->bInitState = TRUE;    // start init

  // enable interrupt we are ready
  //spin_unlock_irqrestore ( &dev->mutex, flags); //spin_unlock_irq ( &dev->mutex_ioctl);
  _asm{sti};
  // Wait for reset is running
  if(cif_wait_reset(dev, pResetCmd->ulTimeout)==FALSE) pResetCmd->sError = DRV_DEV_RESET_TIMEOUT;
  else
  {
   //  No Timeout, test actual state
   switch ( dev->bInitMsgFlag )
   {
    case INI_MSG_RDYRUN:
    case INI_MSG_RDY:
      // Init is ready
      pResetCmd->sError = DRV_NO_ERROR;
      break;
    default:
      pResetCmd->sError = DRV_INIT_STATE_ERROR;
      break;
   }
  }
  dev->bInitState = FALSE;   // stop init
 }
 return(sizeof(DEVIO_RESETCMD));
}

int ioctlputmsg(DEVIO_PUTMESSAGECMD *tBuffer)
{
 DEVIO_PUTMESSAGECMD *pPutMsgCmd;
 DEV_INSTANCE        *dev = NULL;

 pPutMsgCmd=tBuffer;
 pPutMsgCmd->sError = 0;   // Clear error
 // at last one application must be init
 if(pPutMsgCmd->usBoard >= cif_nr_devs) pPutMsgCmd->sError = DRV_BOARD_NOT_INITIALIZED;
 else if((dev=(DEV_INSTANCE *)cif_dev_get_at( pPutMsgCmd->usBoard))==NULL)
  pPutMsgCmd->sError = DRV_BOARD_NOT_INITIALIZED;
 else if(dev->usOpenCounter == 0)       pPutMsgCmd->sError = DRV_BOARD_NOT_INITIALIZED;
 else
 {
  // set driver info data
  dev->tStateInfo.WriteCnt++;
  dev->tStateInfo.LastFunction = FKT_WRITE;

//----------- (7_04_2002 RomanS) -----------
  while(dev->tStateInfo.WriteState==STATE_WAIT) if(T_Shedule) schedule(); else t_delay(1);
//------------------------------------------
  dev->tStateInfo.WriteState = STATE_IN;
  if(cif_test_ready(dev)==FALSE)   pPutMsgCmd->sError = DRV_DEV_NOT_READY;
  else if(dev->bWriteState!=FALSE) pPutMsgCmd->sError = DRV_CMD_ACTIVE;
  else
  {
//   spin_lock_irqsave ( &dev->mutex, flags);      //spin_lock_irq ( &dev->mutex_ioctl);
   _asm{cli};
   if(cif_get_devMBXinfo(dev)==DEVICE_MBX_EMPTY) // check if mailbox is free
   {
    memcpy( (unsigned char *)&(dev->ptDpmAddress->tDevMbx),
            (unsigned char *)&(pPutMsgCmd->tMsg),
            (unsigned short)(pPutMsgCmd->tMsg.ln + 8));
    cif_send_msg(dev);
//    spin_unlock_irqrestore ( &dev->mutex, flags); //spin_unlock_irq ( &dev->mutex_ioctl);
    _asm{sti};
   }
   else if (pPutMsgCmd->ulTimeout==0L)
   {
//    spin_unlock_irqrestore ( &dev->mutex, flags); //spin_unlock_irq ( &dev->mutex_ioctl);
    _asm{sti};
    pPutMsgCmd->sError = DRV_DEV_MAILBOX_FULL;
   }
   else // we have to wait for MBX empty
   {
    dev->tStateInfo.WriteState = STATE_WAIT;
    dev->bWriteState = TRUE;
//    spin_unlock_irqrestore ( &dev->mutex, flags); //spin_unlock_irq ( &dev->mutex_ioctl);
    _asm{sti};
    if(cif_wait_put_msg(dev, pPutMsgCmd->ulTimeout)==FALSE)  // timeout in Ticks, 1 Tick = 1/TZ msec
     pPutMsgCmd->sError = DRV_DEV_PUT_TIMEOUT;
    else
    {
     memcpy( (unsigned char *)&(dev->ptDpmAddress->tDevMbx),
             (unsigned char *)&(pPutMsgCmd->tMsg),
             (unsigned short)(pPutMsgCmd->tMsg.ln + 8));
//     spin_lock_irqsave ( &dev->mutex, flags); //spin_lock_irq ( &dev->mutex_ioctl);
     _asm{cli};
     cif_send_msg(dev);
//     spin_unlock_irqrestore ( &dev->mutex, flags); //spin_unlock_irq ( &dev->mutex_ioctl);
     _asm{sti};
    }
    dev->bWriteState = FALSE;
   }
  }
  dev->tStateInfo.WriteState = STATE_OUT;
 }
 return(sizeof(DEVIO_PUTMESSAGECMD));
}

int ioctlgetmsg(DEVIO_GETMESSAGECMD *tBuffer,unsigned char n_task)
{
 unsigned short      usMsgLen;
 DEVIO_GETMESSAGECMD *pGetMsgCmd;
 DEV_INSTANCE        *dev =  NULL;
 TASK_BOX            *t_box= NULL;

 pGetMsgCmd=tBuffer;
 pGetMsgCmd->sError = 0; // Clear error
 // at last one application must be init
 if(pGetMsgCmd->usBoard >= cif_nr_devs) pGetMsgCmd->sError = DRV_BOARD_NOT_INITIALIZED;
 else if((dev = (DEV_INSTANCE *)cif_dev_get_at( pGetMsgCmd->usBoard))==NULL)
  pGetMsgCmd->sError = DRV_BOARD_NOT_INITIALIZED;
 else if(dev->usOpenCounter==0)         pGetMsgCmd->sError = DRV_BOARD_NOT_INITIALIZED;
 else
 {
  dev->tStateInfo.ReadCnt++;
  dev->tStateInfo.LastFunction = FKT_READ;

//----------- (7_04_2002 RomanS) -----------
  if(dev->tStateInfo.ReadState==STATE_WAIT)
  {
//   eprintf(GRAY_,"TEST: GET WAIT %d",n_task);
   t_box=dev->task_boxes;
   while(t_box && t_box->n_task!=n_task) t_box=t_box->next;
   if(!t_box) {pGetMsgCmd->sError = DRV_DEV_NOT_READY; return(sizeof(DEVIO_GETMESSAGECMD)); }
   if(t_box->n_mesage || pGetMsgCmd->ulTimeout)
    while(dev->tStateInfo.ReadState==STATE_WAIT)
    {
     if(t_box->n_mesage)
     {
      usMsgLen=(unsigned short)(t_box->buf.ln + 8);
      memcpy((unsigned char *)&(pGetMsgCmd->tMsg),(unsigned char *)&(t_box->buf),(unsigned short)usMsgLen);
      t_box->n_mesage--;
      return(sizeof(DEVIO_GETMESSAGECMD));
     }
     if(T_Shedule) schedule(); else t_delay(1);
    }
   else {pGetMsgCmd->sError = DRV_DEV_GET_NO_MESSAGE; return(sizeof(DEVIO_GETMESSAGECMD));}
  }
//-----------------------------------------
  dev->tStateInfo.ReadState = FKT_READ;
  if(cif_test_ready(dev)==FALSE)  pGetMsgCmd->sError = DRV_DEV_NOT_READY;
  else if(dev->bReadState!=FALSE) pGetMsgCmd->sError = DRV_CMD_ACTIVE;
  else
  {
   for(;;)
   {
    t_box=dev->task_boxes;
    while(t_box && t_box->n_task!=n_task) t_box=t_box->next;
    if(!t_box) {pGetMsgCmd->sError = DRV_DEV_NOT_READY; break; }
    if(t_box->n_mesage)
    {
     usMsgLen=(unsigned short)(t_box->buf.ln + 8);
     memcpy( (unsigned char *)&(pGetMsgCmd->tMsg),
             (unsigned char *)&(t_box->buf),
             (unsigned short)usMsgLen);
     t_box->n_mesage--; break;
    }
//   spin_lock_irqsave ( &dev->mutex, flags);
    _asm{cli};
    if(cif_get_hostMBXinfo(dev)==HOST_MBX_FULL)  // no activ service, if a message available, read it
    {
     usMsgLen=(unsigned short)(dev->ptDpmAddress->tPcMbx.ln + 8);
     if(n_task==dev->ptDpmAddress->tPcMbx.nr)
     {
      memcpy( (unsigned char *)&(pGetMsgCmd->tMsg),
              (unsigned char *)&(dev->ptDpmAddress->tPcMbx),
              (unsigned short)usMsgLen);
      cif_quit_msg(dev); break;
//    spin_unlock_irqrestore ( &dev->mutex, flags);
      _asm{sti};
     }
     else
     {
      t_box=dev->task_boxes;
      while(t_box && t_box->n_task!=dev->ptDpmAddress->tPcMbx.nr) t_box=t_box->next;
      if(!t_box) { cif_quit_msg(dev); continue; }
//      {pGetMsgCmd->sError = DRV_DEV_NOT_READY; break; }
      memcpy ( (unsigned char *)&(t_box->buf),
               (unsigned char *)&(dev->ptDpmAddress->tPcMbx),
               (unsigned short)usMsgLen);
      t_box->n_mesage++;
      cif_quit_msg(dev); continue;
     }
    }
    else if(pGetMsgCmd->ulTimeout == 0L)
    {
//    spin_unlock_irqrestore ( &dev->mutex, flags);
     _asm{sti};
     pGetMsgCmd->sError = DRV_DEV_GET_NO_MESSAGE; break;
    }
    else
    {
     dev->bReadState = TRUE;
     dev->tStateInfo.ReadState = STATE_WAIT;
//    spin_unlock_irqrestore ( &dev->mutex, flags);
     _asm{sti};
     if(cif_wait_get_msg(dev,pGetMsgCmd->ulTimeout)==FALSE) // Timeout in Ticks, 1 Tick = 1/TZ msec
     { pGetMsgCmd->sError = DRV_DEV_GET_TIMEOUT; dev->bReadState = FALSE; break; }
     else
     {
      usMsgLen = (unsigned short)(dev->ptDpmAddress->tPcMbx.ln + 8);
      if(n_task==dev->ptDpmAddress->tPcMbx.nr)
      {
       memcpy( (unsigned char *)&(pGetMsgCmd->tMsg),
               (unsigned char *)&(dev->ptDpmAddress->tPcMbx),
               (unsigned short)usMsgLen);
//     spin_lock_irqsave ( &dev->mutex, flags);
       _asm{cli};
       cif_quit_msg(dev); dev->bReadState = FALSE; break;
//     spin_unlock_irqrestore ( &dev->mutex, flags);
       _asm{sti};
      }
      else
      {
       t_box=dev->task_boxes;
       while(t_box && t_box->n_task!=dev->ptDpmAddress->tPcMbx.nr) t_box=t_box->next;
       if(!t_box) { cif_quit_msg(dev); dev->bReadState = FALSE; continue; }
//       {pGetMsgCmd->sError = DRV_DEV_NOT_READY; dev->bReadState = FALSE; break; }
       memcpy ( (unsigned char *)&(t_box->buf),
                (unsigned char *)&(dev->ptDpmAddress->tPcMbx),
                (unsigned short)usMsgLen);
       t_box->n_mesage++;
       cif_quit_msg(dev); dev->bReadState = FALSE; continue;
      }
     }
//     dev->bReadState = FALSE;  // delete pending action
    }
   }
  }
  dev->tStateInfo.ReadState = STATE_OUT;
 }
 return(sizeof(DEVIO_GETMESSAGECMD));
}

int ioctltaskstate(DEVIO_GETTASKSTATECMD *tBuffer)
{
 DEVIO_GETTASKSTATECMD *pGetTskStateCmd;
 DEV_INSTANCE  *dev = NULL;

 pGetTskStateCmd=tBuffer;
 pGetTskStateCmd->sError = 0;    // clear error
 // at last one application must be init
 if(pGetTskStateCmd->ucBoard >= cif_nr_devs) pGetTskStateCmd->sError = DRV_BOARD_NOT_INITIALIZED;
 else if((dev=(DEV_INSTANCE *)cif_dev_get_at( pGetTskStateCmd->ucBoard))==NULL)
  pGetTskStateCmd->sError = DRV_BOARD_NOT_INITIALIZED;
 else if(dev->usOpenCounter==0)              pGetTskStateCmd->sError = DRV_BOARD_NOT_INITIALIZED;
 else
 {
  if(pGetTskStateCmd->usStateNum==1)
   memcpy ( (unsigned char *)&(pGetTskStateCmd->TaskState[0]),
            (unsigned char *)&(dev->ptDpmAddress->tKpt1State),
            pGetTskStateCmd->usStateLen);
  else
   memcpy ( (unsigned char *)&(pGetTskStateCmd->TaskState[0]),
            (unsigned char *)&(dev->ptDpmAddress->tKpt2State),
            pGetTskStateCmd->usStateLen);
 }
 return(sizeof(DEVIO_GETTASKSTATECMD));
}

//************************************************************************
//************************************************************************
//**                API-Functions                                       **
//************************************************************************
//************************************************************************

typedef struct DEV_DPM_SIZEtag {
  unsigned long ulDpmSize;
  unsigned long ulDpmIOSize;
} DEV_DPM_SIZE;

DEV_DPM_SIZE tDevDPMSize[MAX_DEV_BOARDS] = { {0L,0L},
                                             {0L,0L},
                                             {0L,0L},
                                             {0L,0L} }; // DPM size of each board

// <ST> =================================================================================
//  Function: DevInitBoard
//            initializes a DEV board
//  ---------------------------------------------------------------------------------------
//  Input   : usDevNumber   - number of the DEV board (0..3)
//            *pDevAddress  - not used
//  Output  : -
//  Return  : DRV_NO_ERROR     - function successfull
//            != DRV_NO_ERROR  - function failed
//  ================================================================================= <En>
short DevInitBoard ( unsigned short usDevNumber)
{
 DEVIO_RESETCMD  tBuffer;
 short           sRet = DRV_NO_ERROR;

 if (usDevNumber >= CIF_NR_DEVS) sRet = DRV_USR_DEV_NUMBER_INVALID;
 else
 {
  // clear all data buffers
  tBuffer.usBoard = usDevNumber;
  tBuffer.sError  = sRet;

  if(!ioctlinitdrv(&tBuffer)) sRet = DRV_USR_COMM_ERR;
//  if ( !ioctl(hDevDrv, CIF_IOCTLINITDRV, &tBuffer) ) sRet = DRV_USR_COMM_ERR;
  else
  {
   sRet = tBuffer.sError;
   if(sRet == DRV_NO_ERROR)
   {
    // Save the DPM size for further function calls and calculate the length
    // of the DPM-IO data area
    tDevDPMSize[usDevNumber].ulDpmSize    = tBuffer.ulDpmSize;
    tDevDPMSize[usDevNumber].ulDpmIOSize  = ((tBuffer.ulDpmSize * 1024) - 1024) /2;
   }
  }
 }
 return sRet;
}

// <ST> =================================================================================
//  Function: DevExitBoard
//            closes the connection to a DEV board
//  ---------------------------------------------------------------------------------------
//  Input   : usDevNumber - number of the DEV board (0..3)
//  Output  : -
//  Return  : DRV_NO_ERROR     - function successfull
//           != DRV_NO_ERROR  - function failed
//  ================================================================================= <En>
short DevExitBoard ( unsigned short usDevNumber)
{
 DEVIO_EXITCMD   tBuffer;
 short           sRet = DRV_NO_ERROR;

 if(usDevNumber>=MAX_DEV_BOARDS) sRet = DRV_USR_DEV_NUMBER_INVALID;
 else
 {
  tBuffer.usBoard        = usDevNumber;
//  if(!ioctl(hDevDrv, CIF_IOCTLEXITDRV, &tBuffer)) sRet = DRV_USR_COMM_ERR;
  if(!ioctlexitdrv(&tBuffer)) sRet = DRV_USR_COMM_ERR;
  else                        sRet = tBuffer.sError;
 }
 return sRet;
}

// <ST> =================================================================================
//  Function: DevGetInfo
//            read the differnt information areas from a DEV board
//  ---------------------------------------------------------------------------------------
//  Input   : usDevNumber   - number of the DEV board       (0..3)
//            usInfoArea    - 1..n
//            usSize        - size of the users data buffer
//            pvData        - pointer to users data buffer
//  Output  : -
//  Return  : DRV_NO_ERROR     - function successfull
//            != DRV_NO_ERROR  - function failed
//================================================================================= <En>

short DevGetInfo ( unsigned short usDevNumber, unsigned short usInfoArea,
                   unsigned short usSize, void *pvData)
{
 DEVIO_GETDEVINFOCMD tBuffer;
 short               sRet = DRV_NO_ERROR;

 // valid handle available, driver is open
 if(usDevNumber >= CIF_NR_DEVS) sRet = DRV_USR_DEV_NUMBER_INVALID;
 else if ( usSize == 0)         sRet = DRV_USR_SIZE_ZERO;
 else
 {
  // test area spezific data
  switch ( usInfoArea)
  {
   case GET_VERSION_INFO: if(usSize>sizeof(VERSIONINFO)) sRet = DRV_USR_SIZE_TOO_LONG; break;
   case GET_DRIVER_INFO:  if(usSize>sizeof(DRIVERINFO))  sRet = DRV_USR_SIZE_TOO_LONG; break;
   case GET_FIRMWARE_INFO:if(usSize>sizeof(FIRMWAREINFO))sRet = DRV_USR_SIZE_TOO_LONG; break;
   case GET_RCS_INFO:     if(usSize>sizeof(RCSINFO))     sRet = DRV_USR_SIZE_TOO_LONG; break;
   case GET_DEV_INFO:     if(usSize>sizeof(DEVINFO))     sRet = DRV_USR_SIZE_TOO_LONG; break;
   case GET_TASK_INFO:    if(usSize>sizeof(TASKINFO))    sRet = DRV_USR_SIZE_TOO_LONG; break;
   case GET_IO_INFO:      if(usSize>sizeof(IOINFO))      sRet = DRV_USR_SIZE_TOO_LONG; break;
   case GET_IO_SEND_DATA: if(usSize>tDevDPMSize[usDevNumber].ulDpmIOSize) sRet = DRV_USR_SIZE_TOO_LONG;
     break;
   default: sRet = DRV_USR_INFO_AREA_INVALID;
  }
  if(sRet==DRV_NO_ERROR)
  {
   // set output buffer
   tBuffer.usBoard       = usDevNumber;
   tBuffer.usInfoArea    = usInfoArea;
   tBuffer.usInfoLen     = usSize;
   tBuffer.pabInfoData   = pvData;   // needed in kernel-space to copy data back to it!
   tBuffer.sError        = sRet;
   // activate function
   if(!ioctlgetinfo(&tBuffer)) sRet = DRV_USR_COMM_ERR;
//   if ( !ioctl(hDevDrv, CIF_IOCTLGETINFO, &tBuffer) ) sRet = DRV_USR_COMM_ERR;
   else sRet = tBuffer.sError;
  }
 }
 return sRet;
}

// <ST> =================================================================================
//  Function: DevSetHostState
//            set the host state
//  ---------------------------------------------------------------------------------------
//  Input   : usDevNumber   - number of the DEV board       (0..3)
//            usMode        - 0 = Host not ready, 1 = Host ready
//  Output  : -
//  Return  : DRV_NO_ERROR     - function successfull
//            != DRV_NO_ERROR  - function failed
//  ================================================================================= <En>

short  DevSetHostState ( unsigned short usDevNumber, unsigned short usMode, unsigned long  ulTimeout)
{
 DEVIO_TRIGGERCMD     tBuffer;
 short                sRet = DRV_NO_ERROR;

 if ( usDevNumber >= MAX_DEV_BOARDS) sRet = DRV_USR_DEV_NUMBER_INVALID;
 else if ( usMode > HOST_READY)      sRet = DRV_USR_MODE_INVALID;
 else
 {
  // set output buffer
  tBuffer.usBoard   = usDevNumber;
  tBuffer.usMode    = usMode;
  tBuffer.ulTimeout = ulTimeout;
  tBuffer.sError    = sRet;
  if(!ioctlsethost(&tBuffer)) sRet = DRV_USR_COMM_ERR;
  else sRet = tBuffer.sError;
 }
 return sRet;
}

// <ST> =================================================================================
//  Function: DevGetTaskParameter
//            reads the task parameters from task 1 and 2
//  ---------------------------------------------------------------------------------------
//  Input   : usDevNumber   - number of the DEV board       (0..3)
//            usArea        - 1,2
//            usSize        - size of the users data buffer
//            pvData        - pointer to users data buffer
//  Output  : -
//  Return  : DRV_NO_ERROR     - function successfull
//            != DRV_NO_ERROR  - function failed
//  ================================================================================= <En>

short  DevGetTaskParameter  ( unsigned short usDevNumber, unsigned short usNumber,
                              unsigned short usSize, void *pvData)
{
 DEVIO_GETPARAMETERCMD   tBuffer;
 short                   sRet = DRV_NO_ERROR;

 if (usDevNumber >= MAX_DEV_BOARDS)        sRet = DRV_USR_DEV_NUMBER_INVALID;
 else if ((usNumber < 1)||(usNumber > 2))  sRet = DRV_USR_NUMBER_INVALID;
 else if (usSize == 0)                     sRet = DRV_USR_SIZE_ZERO;
 else if (usSize > sizeof(TASKPARAM))      sRet = DRV_USR_SIZE_TOO_LONG;
 else
 {
  // set command buffer
  tBuffer.usBoard        = usDevNumber;
  tBuffer.usTaskParamNum = usNumber;
  tBuffer.usTaskParamLen = usSize;
  //tBuffer.ptTaskParam    = pvData;
  tBuffer.sError         = sRet;
  // activate function
//  if ( !ioctl(hDevDrv, CIF_IOCTLGETPARAMETER, &tBuffer)) sRet = DRV_USR_COMM_ERR;
  if (!ioctlgetparameter(&tBuffer)) sRet = DRV_USR_COMM_ERR;
  else
  {
   memcpy ( (unsigned char *)pvData, (unsigned char *)&(tBuffer.TaskParameter), usSize);
   sRet = tBuffer.sError;
  }
 }
 return sRet;
}

// <ST> =================================================================================
//  Function: DevPutTaskParameter
//            write communication parameters
//  ---------------------------------------------------------------------------------------
//  Input   : usDevNumber   - number of the DEV board       (0..3)
//            usNumber      - number of the parameter area  (1..7)
//            usSize        - size of the parameter area    ( >0, <= max.Size)
//            pvData        - pointer to task parameter buffer
//  Output  : -
//  Return  : DRV_NO_ERROR     - function successfull
//            != DRV_NO_ERROR  - function failed
//  ================================================================================= <En>
short  DevPutTaskParameter  ( unsigned short usDevNumber, unsigned short usNumber,
                              unsigned short usSize, void *pvData)
{
 DEVIO_PUTPARAMETERCMD tBuffer;
 short                 sRet = DRV_NO_ERROR;

 if (usDevNumber >= MAX_DEV_BOARDS)       sRet = DRV_USR_DEV_NUMBER_INVALID;
 else if ((usNumber < 1)||(usNumber > 7)) sRet = DRV_USR_NUMBER_INVALID;
 else if (usSize == 0)                    sRet = DRV_USR_SIZE_ZERO;
 else if ( usSize > sizeof(TASKPARAM))    sRet = DRV_USR_SIZE_TOO_LONG;
 else
 {
  // set command buffer
  tBuffer.usBoard         = usDevNumber;
  tBuffer.usTaskParamNum  = usNumber;
  tBuffer.usTaskParamLen  = usSize;
  memcpy ((unsigned char *)&(tBuffer.TaskParameter),(unsigned char *)pvData, usSize);
  tBuffer.sError          = sRet;
  // activate function
//  if(!ioctl(hDevDrv, CIF_IOCTLPARAMETER, &tBuffer)) sRet = DRV_USR_COMM_ERR;
  if(!ioctlparameter(&tBuffer)) sRet = DRV_USR_COMM_ERR;
  else sRet = tBuffer.sError;
 }
 return sRet;
}

// <ST> =================================================================================
//  Function: DevReset
//            reset a DEV board
//  ---------------------------------------------------------------------------------------
//  Input   : usDevNumber   - number of the DEV board (0..3)
//            usMode        - reset mode              (2,3)
//            ulTimeout     - function timeout in milliseconds
//  Output  : -
//  Return  : DRV_NO_ERROR     - function successfull
//            != DRV_NO_ERROR  - function failed
//  ================================================================================= <En>
short DevReset ( unsigned char  usDevNumber, unsigned short usMode, unsigned long  ulTimeout)
{
 DEVIO_RESETCMD      tBuffer;
 short               sRet = DRV_NO_ERROR;

 if(usDevNumber >= MAX_DEV_BOARDS) sRet = DRV_USR_DEV_NUMBER_INVALID;
 else if((usMode != COLDSTART) && (usMode != WARMSTART) && (usMode != BOOTSTART))
  sRet = DRV_USR_MODE_INVALID;
 else
 {
  // set output buffer
  tBuffer.usBoard   = usDevNumber;
  tBuffer.usMode    = usMode;
  tBuffer.ulTimeout = ulTimeout;
  tBuffer.sError    = sRet;
//  if(!ioctl(hDevDrv, CIF_IOCTLRESETDEV, &tBuffer)) sRet = DRV_USR_COMM_ERR;
  if(!ioctlresetdev(&tBuffer)) sRet = DRV_USR_COMM_ERR;
  else sRet = tBuffer.sError;
 }
 return sRet;
}

// <ST> =================================================================================
//  Function: DevPutMessage
//            send a message to a DEV board
//  ---------------------------------------------------------------------------------------
//  Input   : usDevNumber   - number of the DEV board (0..3)
//            ptMessage     - pointer to users message
//            ulTimeout     - function timeout in milliseconds
//  Output  : -
//  Return  : DRV_NO_ERROR     - function successfull
//            != DRV_NO_ERROR  - function failed
//  ================================================================================= <En>
short  DevPutMessage ( unsigned short usDevNumber, MSG_STRUC *ptMessage, unsigned long ulTimeout)
{
 DEVIO_PUTMESSAGECMD  tBuffer;
 short                sRet = DRV_NO_ERROR;

 // valid handle available, driver is open
 if(usDevNumber >= MAX_DEV_BOARDS) sRet = DRV_USR_DEV_NUMBER_INVALID;
 else
 {
  // set output buffer
  tBuffer.usBoard   = usDevNumber;
  tBuffer.ulTimeout = ulTimeout;
  memcpy( &tBuffer.tMsg, ptMessage, sizeof(MSG_STRUC));
  tBuffer.sError    = sRet;
  // activate function
//  if(!ioctl(hDevDrv, CIF_IOCTLPUTMSG, &tBuffer)) sRet = DRV_USR_COMM_ERR;
  if(!ioctlputmsg(&tBuffer)) sRet = DRV_USR_COMM_ERR;
  else sRet = tBuffer.sError;
 }
 return sRet;
}

// <ST> =================================================================================
//  Function: DevGetMessage
//            read a message from a DEV board
//  ---------------------------------------------------------------------------------------
//  Input   : usDevNumber   - number of the DEV board     (0..3)
//            usSize        - size of the users data area (>0..<= sizeof(MSG_STRUC))
//            ptMessage     - pointer to the users data buffer
//            ulTimeout     - function timeout in milliseconds
//  Output  : -
//  Return  : DRV_NO_ERROR     - function successfull
//            != DRV_NO_ERROR  - function failed
//  ================================================================================= <En>
short  DevGetMessage ( unsigned short usDevNumber, unsigned short usSize, MSG_STRUC *ptMessage,
                       unsigned long  ulTimeout, unsigned char n_task)
{
 DEVIO_GETMESSAGECMD   tBuffer;
 short                 sRet = DRV_NO_ERROR;

 if(usDevNumber >= MAX_DEV_BOARDS) sRet = DRV_USR_DEV_NUMBER_INVALID;
 else if(usSize==0 || usSize>sizeof(MSG_STRUC)) sRet = DRV_USR_SIZE_INVALID;
 else
 {
  // set output buffer
  tBuffer.usBoard   = usDevNumber;
  tBuffer.ulTimeout = ulTimeout;
  tBuffer.sError    = sRet;
  // activate function
//  if ( !ioctl(hDevDrv, CIF_IOCTLGETMSG, &tBuffer)) sRet = DRV_USR_COMM_ERR;
  if (!ioctlgetmsg(&tBuffer,n_task)) sRet = DRV_USR_COMM_ERR;
  else
  {
    memcpy( ptMessage, &tBuffer.tMsg, sizeof(MSG_STRUC));
    sRet = tBuffer.sError;
  }
 }
 return sRet;
}

// <ST> =================================================================================
//  Function: DevGetTaskState
//            read a task state field form a DEV board
//  ---------------------------------------------------------------------------------------
//  Input   : usDevNumber   - number of the DEV board       (0..3)
//            usNumber      - number of the status field    (1,2)
//            usSize        - size of the users data buffer (>0..<= 64)
//            pvData        - pointer to users data buffer
//  Output  : -
//  Return  : DRV_NO_ERROR     - function successfull
//            != DRV_NO_ERROR  - function failed
//  ================================================================================= <En>
short  DevGetTaskState( unsigned short usDevNumber, unsigned short usNumber,
                        unsigned short usSize, void *pvData)
{
 DEVIO_GETTASKSTATECMD   tBuffer;
 short                   sRet = DRV_NO_ERROR;

 if(usDevNumber >= MAX_DEV_BOARDS)       sRet = DRV_USR_DEV_NUMBER_INVALID;
 else if(usNumber < 1 || usNumber > 2  ) sRet = DRV_USR_NUMBER_INVALID;
 else if(usSize == 0)                    sRet = DRV_USR_SIZE_ZERO;
 else if(usSize > sizeof(TASKSTATE) )    sRet = DRV_USR_SIZE_TOO_LONG;
 else
 {
  // set command buffer
  tBuffer.ucBoard     = usDevNumber;
  tBuffer.usStateNum  = usNumber;
  tBuffer.usStateLen  = usSize;
  //memcpy( tBuffer.TaskState, pvData, usSize);
  tBuffer.sError      = sRet;
  // activate function
//  if (!ioctl(hDevDrv, CIF_IOCTLTASKSTATE, &tBuffer)) sRet = DRV_USR_COMM_ERR;
  if (!ioctltaskstate(&tBuffer)) sRet = DRV_USR_COMM_ERR;
  else { memcpy( pvData, tBuffer.TaskState, usSize); sRet = tBuffer.sError; }
 }
 return sRet;
}


//*************************************************************************
//*************************************************************************
//**                    Global functions                                 **
//*************************************************************************
//*************************************************************************

unsigned char SendReceiveMessage(unsigned short board, RCS_MESSAGE *ptMsg)
{
 short           sRet;
 if((sRet=DevPutMessage(board,(MSG_STRUC *)ptMsg, 200L))==DRV_NO_ERROR)
 {
  if((sRet = DevGetMessage(board,sizeof(RCS_MESSAGE),(MSG_STRUC *)ptMsg, 200L,ptMsg->nr))==DRV_NO_ERROR)
   return( ptMsg->f );
  else return(3);
 }
 else return(3);
 return( 0 );
}

//*************************************************************************
//* enable_CIF()                                                          *
//* Search and init CIF                                                   *
//*************************************************************************

DPM_PLC_PARAMETER      DPParameter;         // Parameters for DP protocolls
DPM_DIAGNOSTICS        tTaskState;
DRIVERINFO             tDriverInfo;

void enable_CIF()
{
 DDLM_DOWNLOAD_REQUEST  *ptDownloadRequest;
 DPM_BUS_DP             *ptBusDpm;
 RCS_MESSAGE            tMsg;

 int res = 0,i;
 unsigned char task_opr;

 for(i=0;i<c_num;i++) if(c_ptr[i].typcontr==CIF50) break;
 if(i>=c_num) return;
 // scan pci bus for Hilscher boards
 res=cif_scan_pci();
// eprintf(GRAY_,"Scan Err %d",res);
 if(cif_nr_devs==0) return;
 else if(!cif_drv_load()) {cif_nr_devs=0; return;}
 else
 {
//  eprintf(GRAY_,"CIF OK!");
  eprintf(GREEN_,"%x CIF50-Board(s) detected\n", res);
  for(i=0;i<c_num;i++)
   if(c_ptr[i].typcontr==CIF50 && c_ptr[i].nomport<cif_nr_devs)
   {
    if(DevInitBoard(c_ptr[i].nomport) != DRV_NO_ERROR)
    {
      eprintf(GRAY_,"DevInitBoard  RetWert = %5d \n", res );
      STAT_CIF[c_ptr[i].nomport]=-1;
      CIF_CTR[c_ptr[i].nomport] = NULL;
    }
    // Write parameters to communication board
    //Set Host state CP
    DevSetHostState(c_ptr[i].nomport,HOST_READY,0L);

    memset(&DPParameter,0,sizeof(DPM_PLC_PARAMETER));
    DPParameter.bMode=DPM_SET_MODE_UNCONTROLLED;
    DPParameter.bFormat=1;//DPM_FORMAT_MOTROLA;
    DPParameter.usWatchDogTime=1000;
    DevPutTaskParameter(c_ptr[i].nomport, 1, sizeof(DPM_PLC_PARAMETER), &DPParameter );
     //Reset CP
    DevReset(c_ptr[i].nomport, WARMSTART, 5000L);
    // download the bus parameter for 1.5Mbaud
    DevGetInfo(c_ptr[i].nomport, GET_DRIVER_INFO, sizeof(DRIVERINFO), &tDriverInfo);
    task_opr=0;
    RegTaskForCIF(c_ptr[i].nomport,task_opr);
    if((tDriverInfo.HostFlags & 0x40 )!= 0)
    {
//   // clear data base in DEVICE
     tMsg.rx = 0;      // task = OS-Task
     tMsg.tx = 16;
     tMsg.ln = 2;
     tMsg.nr = task_opr;
     tMsg.a  = 0;
     tMsg.f  = 0;
     tMsg.b  = RCS_B_LOADFKT;      // command data base access
     tMsg.e  = 0;
     tMsg.d[0] = 4;    // mode clear data base
     tMsg.d[1] = 8;    // startsegment = 8
     res=DevPutMessage(c_ptr[i].nomport, (MSG_STRUC *)&tMsg, 200L);
     while((res=DevGetMessage(c_ptr[i].nomport,sizeof(tMsg),(MSG_STRUC *)&tMsg,0,task_opr))==DRV_DEV_GET_NO_MESSAGE) continue;
    }

    tMsg.rx = 3;                                        // task = DPM-Task
    tMsg.tx = 16;
    tMsg.ln = sizeof( DDLM_DOWNLOAD_REQUEST );
    tMsg.nr = task_opr;
    tMsg.a  = 0;
    tMsg.f  = 0;
    tMsg.b  = DDLM_Download;
    tMsg.e  = 0;
    ptDownloadRequest=(DDLM_DOWNLOAD_REQUEST*) &tMsg.d;
    ptDownloadRequest->bReq_Add = 0;
    ptDownloadRequest->bArea_Code = DPM_DEVICE_PRM;
    ptDownloadRequest->usAdd_Offset = 0;
    ptBusDpm = ( DPM_BUS_DP* )&ptDownloadRequest->abData;
    ptBusDpm->usBus_Para_Len = sizeof( DPM_BUS_DP ) ;
    ptBusDpm->bFDL_Add          = c_ptr[i].basaddr;
    ptBusDpm->bBaudrate         = c_ptr[i].baud;
    ptBusDpm->usTSL             = par_bus[c_ptr[i].baud].usTSL;            //300;
    ptBusDpm->usMin_TSDR        = par_bus[c_ptr[i].baud].usMin_TSDR;       //11;
    ptBusDpm->usMax_TSDR        = par_bus[c_ptr[i].baud].usMax_TSDR;       //150;
    ptBusDpm->bTQUI             = par_bus[c_ptr[i].baud].bTQUI;            //0;
    ptBusDpm->bTSET             = par_bus[c_ptr[i].baud].bTSET;            //1;
    ptBusDpm->ulTTR             = par_bus[c_ptr[i].baud].ulTTR;            //2021;
    ptBusDpm->bG                = par_bus[c_ptr[i].baud].bG;               //10;
    ptBusDpm->bHSA              = 126;
    ptBusDpm->bMax_Retry_Limit  = par_bus[c_ptr[i].baud].bMax_Retry_Limit; //1;
    ptBusDpm->Bp_Flag.bReserved = 0;
    ptBusDpm->Bp_Flag.bError_Action_Flag  = 0;
    ptBusDpm->usMin_Slave_Intervall       = 0;
    ptBusDpm->usPoll_Timeout              = 10;
    ptBusDpm->usData_Control_Time         = 120;
    ptBusDpm->bAlarm_Max        = 0;
    ptBusDpm->bMax_User_Global_Control = 0;
    ptBusDpm->abOctet[0] = 0;
    ptBusDpm->abOctet[1] = 0;
    ptBusDpm->abOctet[2] = 0;
    ptBusDpm->abOctet[3] = 0;
    tMsg.ln = sizeof(DPM_BUS_DP)+sizeof(DDLM_DOWNLOAD_REQUEST)- DPM_MAX_LEN_DATA_UNIT;
    SendReceiveMessage(c_ptr[i].nomport,(RCS_MESSAGE*)&tMsg);
    do { DevGetTaskState(c_ptr[i].nomport,2,sizeof( tTaskState ),&tTaskState); }
    while(tTaskState.bDPM_state!=OPERATE);
    CIF_CTR[c_ptr[i].nomport] = c_ptr+i;
   }
 }
}

//*************************************************************************
//* RegTaskForCIF()                                                       *
//* Registr task for CIF                                                  *
//*************************************************************************
int RegTaskForCIF(unsigned short usDevNumber,unsigned char task_n)
//int Check_CIF(unsigned short usDevNumber)
{
 DEV_INSTANCE  *dev = NULL;
 TASK_BOX      *task;

 if(usDevNumber >= cif_nr_devs) return(DRV_BOARD_NOT_INITIALIZED);
 else if((dev = (DEV_INSTANCE *)cif_dev_get_at(usDevNumber))==NULL) return(DRV_BOARD_NOT_INITIALIZED);
 else if(dev->usOpenCounter==0) return(DRV_BOARD_NOT_INITIALIZED);
 else
 {
  if(!dev->task_boxes) { dev->task_boxes=calloc(sizeof(TASK_BOX),1); dev->task_boxes->n_task=task_n; }
  else
  {
   task=dev->task_boxes;
   if(task->n_task==task_n) return(DRV_NO_ERROR);
   while(task->next)
   {
    if(task->n_task==task_n) return(DRV_NO_ERROR);
    task=task->next;
   }
   task->next=calloc(sizeof(TASK_BOX),1); task=task->next->n_task=task_n;
  }
 }
// if(usDevNumber < cif_nr_devs && STAT_CIF[usDevNumber]==0) return(1);
 return(DRV_NO_ERROR);
}

//*************************************************************************
//* UnregTaskForCIF()                                                     *
//* Registr task for CIF                                                  *
//*************************************************************************
int UnregTaskForCIF(unsigned short usDevNumber,unsigned char task_n)
//int Check_CIF(unsigned short usDevNumber)
{
 DEV_INSTANCE  *dev = NULL;
 TASK_BOX      *task;

 if(usDevNumber >= cif_nr_devs) return(DRV_BOARD_NOT_INITIALIZED);
 else if((dev = (DEV_INSTANCE *)cif_dev_get_at(usDevNumber))==NULL) return(DRV_BOARD_NOT_INITIALIZED);
 else if(dev->usOpenCounter==0) return(DRV_BOARD_NOT_INITIALIZED);
 else if(dev->task_boxes)       return(DRV_NO_ERROR);
 else
 {
  if(dev->task_boxes->n_task==task_n) dev->task_boxes=dev->task_boxes->next;
  task=dev->task_boxes;
  while(task->next && task->next->n_task!=task_n) task=task->next;
  if(!task->next) return(DRV_NO_ERROR);
  task->next=task->next->next;
 }
 return(DRV_NO_ERROR);
}

//*************************************************************************
//* disable_CIF()                                                         *
//* Free CIF memory                                                       *
//*************************************************************************
void disable_CIF()
{
 int i;
 DEV_INSTANCE *next = NULL;

 if(cif_nr_devs != 0)
 {
  cif_drv_unload();
  for(i=0;i<c_num;i++)
   if(c_ptr[i].typcontr==CIF50 && c_ptr[i].nomport<cif_nr_devs)
    DevExitBoard(c_ptr[i].nomport);        // Device number
  for(;cif_devices;cif_devices=next) {next=cif_devices->next; free(cif_devices); }
//  printf( "DevExitBoard        RetWert = %5d \n", res);
 }
}

//*************************************************************************
//* insert_CIF()                                                          *
//* Insert specific controller parameters                                 *
//*************************************************************************
void insert_CIF(controller *ctr,int n_contr,char *Basa,int mode)
{
  char str[256];

  if(mode==InsContr)
  {
   GetFieldItDbf(Basa,n_contr,"SPEED",str); ctr[n_contr].baud= atoi(str);
   if(ctr[n_contr].baud >= sizeof(par_bus)/sizeof(Spar_bus1)) ctr[n_contr].baud=sizeof(par_bus)/sizeof(Spar_bus1);
   GetFieldItDbf(Basa,n_contr,"PORT",str);  ctr[n_contr].nomport=atoi(str);
   GetFieldItDbf(Basa,n_contr,"ADRES",str); ctr[n_contr].basaddr=atoi(str);
  }
}

//*************************************************************************
//* GetDB_CIF()                                                           *
//*                                                                       *
//*************************************************************************
int GetDB_CIF(char n_port,char n_st,char n_task,int n_db,long offset, int len,char *buffer)
{
 RCS_MESSAGE            tMsg;
 int res, e_try = 4;

 if(len>240) return(-1);
 if(n_port>=cif_nr_devs || CIF_CTR[n_port] == NULL) return(-2);

 request_resource(CIF_CTR[n_port]->port_rsc,0*HZ);     // захват поpта-pесурса

// eprintf(GRAY_,"Dev = %xh; St = %xh; Task = %xh; DB = %d; DBoffs = %d; Len = %d",n_port,n_st,n_task,n_db,offset,len);
 do
 {
   e_try--;
   while(!DevGetMessage(n_port,sizeof(RCS_MESSAGE),(MSG_STRUC *)&tMsg, 0L,n_task));

   tMsg.rx = 3;
   tMsg.tx = 16;
   tMsg.ln = 8;
   tMsg.nr = n_task;
   tMsg.a  = 0;
   tMsg.f  = 0;
   tMsg.b  = MPI_Read_Write_DB;
   tMsg.e  = 0;
   tMsg.d[0] = n_st;                            //PB адрес контроллера
   tMsg.d[1] = (unsigned char)(offset>>8);      //Старший байт смещения
   tMsg.d[2] = (unsigned char)n_db;             //Младший байт номера BD
   tMsg.d[3] = (unsigned char)(n_db>>8);        //Старший байт номера BD
   tMsg.d[4] = (unsigned char)offset;           //Младший байт смещения
   tMsg.d[5] = (unsigned char)len;              //Длина сообщения
   tMsg.d[6] = TASK_TDT_UINT8;
   tMsg.d[7] = TASK_TFC_READ;
   res=DevPutMessage(n_port,&tMsg, 200L);
   if(res==DRV_DEV_PUT_TIMEOUT)
   {
     while(!DevGetMessage(n_port,sizeof(RCS_MESSAGE),(MSG_STRUC *)&tMsg, 0L,n_task));
     release_resource(CIF_CTR[n_port]->port_rsc);
     return(-3);
   }
   if(res==DRV_NO_ERROR)
     res=DevGetMessage(n_port,sizeof(RCS_MESSAGE),(MSG_STRUC *)&tMsg, 200L,n_task);
 }
 while( (tMsg.f == 0x02 || tMsg.f == 0x39) && e_try > 0 );
// if(res=SendReceiveMessage(n_port,(RCS_MESSAGE*)&tMsg))
// { eprintf(RED_,"Get Data err %d",res); return(-3); }
 release_resource(CIF_CTR[n_port]->port_rsc);

 if(res==DRV_DEV_GET_TIMEOUT) return(-4);
 memcpy(buffer,tMsg.d+8,len);
 return(tMsg.f);
}

//*************************************************************************
//* PutDB_CIF()                                                           *
//*                                                                       *
//*************************************************************************
int PutDB_CIF(char n_port,char n_st,char n_task,int n_db,long offset, int len,char *buffer)
{
 RCS_MESSAGE            tMsg;
 int res, e_try = 4;

 if(len>240) return(-1);
 if(n_port>=cif_nr_devs || CIF_CTR[n_port] == NULL) return(-2);
 request_resource(CIF_CTR[n_port]->port_rsc,0*HZ);     // захват поpта-pесурса

 do
 {
   e_try--;

   tMsg.rx = 3;
   tMsg.tx = 16;
   tMsg.ln = len+8;
   tMsg.nr = n_task;
   tMsg.a  = 0;
   tMsg.f  = 0;
   tMsg.b  = MPI_Read_Write_DB;
   tMsg.e  = 0;
   tMsg.d[0] = n_st;                            //PB адрес контроллера
   tMsg.d[1] = (unsigned char)(offset>>8);      //Старший байт смещения
   tMsg.d[2] = (unsigned char)n_db;             //Младший байт номера BD
   tMsg.d[3] = (unsigned char)(n_db>>8);        //Старший байт номера BD
   tMsg.d[4] = (unsigned char)offset;           //Младший байт смещения
   tMsg.d[5] = (unsigned char)len;              //Длина сообщения
   tMsg.d[6] = TASK_TDT_UINT8;
   tMsg.d[7] = TASK_TFC_WRITE;
   memcpy(tMsg.d+8,buffer,len);
   res=DevPutMessage(n_port,&tMsg,200L);
   if(res==DRV_DEV_PUT_TIMEOUT)
   {
     while(!DevGetMessage(n_port,sizeof(RCS_MESSAGE),(MSG_STRUC *)&tMsg, 0L,n_task));
     release_resource(CIF_CTR[n_port]->port_rsc);
     return(-3);
   }
   if(res==DRV_NO_ERROR) res=DevGetMessage(n_port,sizeof(RCS_MESSAGE),(MSG_STRUC *)&tMsg, 200L,n_task);
 }
 while( (tMsg.f == 0x02 || tMsg.f == 0x39) && e_try > 0 );
 release_resource(CIF_CTR[n_port]->port_rsc);
// if(SendReceiveMessage(n_port,(RCS_MESSAGE*)&tMsg)) return(-3);
 if(res==DRV_DEV_GET_TIMEOUT) return(-4);
 return(tMsg.f);
}

//*************************************************************************
//* MPI_disconnect_CIF                                                    *
//*                                                                       *
//*************************************************************************
int MPI_disconnect_CIF(char n_port,char n_task)
{
 RCS_MESSAGE            tMsg;
 int res;

 if(n_port>=cif_nr_devs || CIF_CTR[n_port] == NULL) return(-2);
 request_resource(CIF_CTR[n_port]->port_rsc,0*HZ);     // захват поpта-pесурса

 tMsg.rx = 3;
 tMsg.tx = 16;
 tMsg.ln = 0;
 tMsg.nr = n_task;
 tMsg.a  = 0;
 tMsg.f  = 0;
 tMsg.b  = MPI_Disconnect;
 tMsg.e  = 0;
 res=DevPutMessage(n_port,&tMsg,200L);
 if(res==DRV_DEV_PUT_TIMEOUT)
 {
   while(!DevGetMessage(n_port,sizeof(RCS_MESSAGE),(MSG_STRUC *)&tMsg, 0L,n_task));
   release_resource(CIF_CTR[n_port]->port_rsc);
   return(-3);
 }
 if(res==DRV_NO_ERROR)
   res=DevGetMessage(n_port,sizeof(RCS_MESSAGE),(MSG_STRUC *)&tMsg, 200L,n_task);

 release_resource(CIF_CTR[n_port]->port_rsc);

 if(res==DRV_DEV_GET_TIMEOUT) return(-4);
 return(tMsg.f);
}

//*************************************************************************
//* FindSt_CIF()                                                          *
//*                                                                       *
//*************************************************************************
int FindSt_CIF(char n_port,char n_st,char n_task)
{
  int res;
  RCS_MESSAGE            tMsg;
  RCS_TELEGRAMHEADER_10  *ptRcsTelegramheader10;
  DEV_INSTANCE  *dev = NULL;

  if(n_port>=cif_nr_devs || CIF_CTR[n_port] == NULL) return(-2);
  request_resource(CIF_CTR[n_port]->port_rsc,0*HZ);     // захват поpта-pесурса

  if((dev = (DEV_INSTANCE *)cif_dev_get_at(n_port))==NULL)
  {
    release_resource(CIF_CTR[n_port]->port_rsc);
    return(-1);
  }
  if(dev->usOpenCounter==0)
  {
    release_resource(CIF_CTR[n_port]->port_rsc);
    return(-1);
  }
  if((1*HZ+dev->last_jiffies)<jiffies())
  {
    tMsg.rx = 7;  // task = FDL-Task
    tMsg.tx = 16;
    tMsg.ln = sizeof( RCS_TELEGRAMHEADER_10 );
    tMsg.nr = n_task;
    tMsg.a  = 0;
    tMsg.f  = 0;
    tMsg.b  = DDLM_Life_List;
    tMsg.e  = 0;
    ptRcsTelegramheader10=(RCS_TELEGRAMHEADER_10*)&tMsg.d;
    ptRcsTelegramheader10->device_adr = 0;                       //char
    ptRcsTelegramheader10->data_area  = 0;                       //char
    ptRcsTelegramheader10->data_adr   = 0;                       //short
    ptRcsTelegramheader10->data_idx   = 0;                       //char
    ptRcsTelegramheader10->data_cnt   = DPM_MAX_NUM_DEVICES;     //char
    ptRcsTelegramheader10->data_idx   = 0;                       //char
    ptRcsTelegramheader10->data_type  = TASK_TDT_STRING;         //char
    ptRcsTelegramheader10->function   = TASK_TFC_READ;           //char
    res=DevPutMessage(n_port,&tMsg,200L);
    if(res==DRV_DEV_PUT_TIMEOUT)
    {
      while(!DevGetMessage(n_port,sizeof(RCS_MESSAGE),(MSG_STRUC *)&tMsg, 0L,n_task));
      release_resource(CIF_CTR[n_port]->port_rsc);
      return(-3);
    }
    if(res==DRV_NO_ERROR)
      res=DevGetMessage(n_port,sizeof(RCS_MESSAGE),(MSG_STRUC *)&tMsg, 200L,n_task);
    if(res==DRV_DEV_GET_TIMEOUT)
    {
      release_resource(CIF_CTR[n_port]->port_rsc);
      return(-4);
    }
    if(tMsg.f)
    {
      release_resource(CIF_CTR[n_port]->port_rsc);
      return(-5);
    }
    memcpy(dev->abLifeList,(void*)&tMsg.d[sizeof(RCS_TELEGRAMHEADER_10)],sizeof(dev->abLifeList));
    dev->last_jiffies=jiffies();
  }
  release_resource(CIF_CTR[n_port]->port_rsc);
  if(dev->abLifeList[n_st]==0x30)
  {
//   while(!DevGetMessage(n_port,sizeof(RCS_MESSAGE),(MSG_STRUC *)&tMsg, 0L,n_task));
//   while(!DevGetMessage(n_port,sizeof(RCS_MESSAGE),(MSG_STRUC *)&tMsg, 0L,n_task|0x80));
   return(1);
  }
  return(0);
}

//*************************************************************************
//* GetStatContrCIF                                                       *
//* Open CIF driver                                                       *
//*************************************************************************
int GetStatContrCIF(char n_port,char n_task)
{
 RCS_MESSAGE            tMsg;
 int res;

 if(n_port>=cif_nr_devs || CIF_CTR[n_port] == NULL) return(-2);
 request_resource(CIF_CTR[n_port]->port_rsc,0*HZ);     // захват поpта-pесурса

 while(!DevGetMessage(n_port,sizeof(RCS_MESSAGE),(MSG_STRUC *)&tMsg, 0L,n_task));

 tMsg.rx = 3;
 tMsg.tx = 16;
 tMsg.ln = 0;
 tMsg.nr = n_task;
 tMsg.a  = 0;
 tMsg.f  = 0;
 tMsg.b  = MPI_Get_OP_Status;
 tMsg.e  = 0;
 res=DevPutMessage(n_port,&tMsg,200L);
 if(res==DRV_DEV_PUT_TIMEOUT)
 {
   while(!DevGetMessage(n_port,sizeof(RCS_MESSAGE),(MSG_STRUC *)&tMsg, 0L,n_task));
   release_resource(CIF_CTR[n_port]->port_rsc);
   return(-3);
 }
 if(res==DRV_NO_ERROR)
   res=DevGetMessage(n_port,sizeof(RCS_MESSAGE),(MSG_STRUC *)&tMsg, 200L,n_task);
 release_resource(CIF_CTR[n_port]->port_rsc);
 if(res==DRV_DEV_GET_TIMEOUT) return(-4);
 return(*(short *)tMsg.d);
}

//*************************************************************************
//* cif_open                                                              *
//* Open CIF driver                                                       *
//*************************************************************************
//int cif_open(short CIF_nmb)
//{
// if (CIF_nmb >= cif_nr_devs) return -ENODEV;
// MOD_INC_USE_COUNT;
// return 0;          /* success */
//}

//*************************************************************************
//* cif_release                                                           *
//* Close CIF driver                                                      *
//*************************************************************************
//int cif_release(struct inode *inode, struct file *filp)
//{ MOD_DEC_USE_COUNT; return (0); }

//void enable_CIF()
//{
// int res = 0,i,j;
// union REGS *pregs;