예제 #1
0
pwr_tStatus
proc_Start (
  proc_sProcess *p
)
{
  pwr_tStatus sts = PROC__SUCCESS;
  char **argv;

  p->pid = fork();
  if (p->pid) {
    if (p->pid == -1) {
      errh_Error("Could not start %s, %m\nfile: %s", p->name, errno_GetStatus(), p->file);	
    } else {
      errh_Info("Started %s, prio: %d, pid: %d\nfile: %s", p->name, p->p_prio, (int)p->pid, p->file);	
    }
  } else {
    sts = proc_SetPriority(p->p_prio);
    if (EVEN(sts)) errh_Warning("%s: error setprio, %m\nfile: %s", p->name, sts, p->file);
    argv = co_StrToArgv(p->file, p->arg);
    execvp(p->file, argv);
    errh_Error("%s: error execvp, %m\nfile: %s", p->name, errno_GetStatus(), p->file);
    exit(EXIT_FAILURE);
  }

  return sts;
}
예제 #2
0
파일: rt_cvols.c 프로젝트: hfuhuang/proview
void
cvols_Notify (
  cvol_sNotify		*nmp
)
{
  pwr_tStatus		lsts;
  pool_sQlink		*nl;
  gdb_sNode		*np;
  qcom_sQid		tgt;
  qcom_sPut		put;

  gdb_AssumeLocked;

  if (gdbroot->db->nethandler.qix == 0)
    return;

  tgt.qix = net_cProcHandler;

  gdb_Unlock;

    /* Send to all nodes that have mounted affected volume.

       NOTA BENE !!!
	  In this version we send to all known nodes. */

    for (
      nl = pool_Qsucc(NULL, gdbroot->pool, &gdbroot->db->nod_lh);
      nl != &gdbroot->db->nod_lh;
      nl = pool_Qsucc(NULL, gdbroot->pool, nl)
    ) {
      np = pool_Qitem(nl, gdb_sNode, nod_ll);
      if (np == gdbroot->my_node || np == gdbroot->no_node) continue;
      if (!np->flags.b.active) continue; /* Todo !!! What happens with consistency ? */

      tgt.nid = np->nid;

      if (!net_Put(&lsts, &tgt, &nmp->msg, nmp->subtype, 0, nmp->size, 0))
	errh_Warning("Notify: error %x sending subtype %s to node %s", lsts, "Notify", np->name); 
    }

    /* Submit to the NETH ACP to check if any subscriptions are affected.  */

    put.type.b	= net_cMsgClass;
    put.type.s	= nmp->subtype;
    put.reply	= qcom_cNQid;
    put.data  	= (char *)&nmp->msg;
    put.size	= nmp->size;
    nmp->msg.hdr.hdr.xdr = 0;
    nmp->msg.hdr.hdr.msn = 0;
    nmp->msg.hdr.hdr.nid = gdbroot->my_node->nid;

    qcom_Put(&lsts, &qcom_cQnacp, &put);

  gdb_Lock;

}
예제 #3
0
파일: rt_neth.c 프로젝트: Strongc/proview
static void
bugError (
  qcom_sGet 	*get
)
{

  errh_Warning("Unexpected message type <%d:%d> received from %x @ %s",
    get->type.b, get->type.s, get->pid,
    cdh_NodeIdToString(NULL, get->sender.nid, 0, 0));
}
예제 #4
0
static pwr_tStatus IoCardWrite( io_tCtx ctx,
				io_sAgent *ap,
				io_sRack	*rp,
				io_sCard	*cp)
{
  io_sLocalSPI_Slave *local = (io_sLocalSPI_Slave *)cp->Local;
  pwr_sClass_SPI_Slave *op = (pwr_sClass_SPI_Slave *)cp->op;
  int sts;
  int i;

  io_bus_card_write( ctx, cp, local->output_area,
		     local->byte_ordering, pwr_eFloatRepEnum_FloatIEEE);
    
  // sts = write( local->fd, local->output_area, local->output_area_size);
  for ( i = 0; i < local->output_area_size; i++) {
    sts = write( local->fd, &local->output_area[i], 1);
    if ( sts != 1)
      break;
  }
  if ( sts < 0) {
    op->ErrorCount++;
    if ( !local->writeerror_logged) {
      errh_Error( "SPI write error errno %d, '%s'", errno, cp->Name);
      local->writeerror_logged = 1;
    }
    op->Status = IOM__SPI_WRITEERROR;
  }
  // else if ( sts != local->output_area_size) {
  else if ( sts == 0) {
    op->ErrorCount++;
    if ( !local->writeerror_logged) {
      errh_Error( "SPI write buffer unexpected size %d, '%s'", sts, cp->Name);
      local->writeerror_logged = 1;
    }
    op->Status = IOM__SPI_WRITEERROR;
  }
  else {
    local->writeerror_logged = 0;
    op->Status = IOM__SPI_NORMAL;
  }

  if ( op->ErrorSoftLimit && 
       op->ErrorCount == op->ErrorSoftLimit && !local->softlimit_logged) {
    errh_Warning( "IO Card ErrorSoftLimit reached, '%s'", cp->Name);
    local->softlimit_logged = 1;
  }
  if ( op->ErrorHardLimit && op->ErrorCount >= op->ErrorHardLimit) {
    errh_Error( "IO Card ErrorHardLimit reached '%s', IO stopped", cp->Name);
    ctx->Node->EmergBreakTrue = 1;
    return IO__ERRDEVICE;
  }    

  return IO__SUCCESS;
}
예제 #5
0
JNIEXPORT void JNICALL Java_jpwr_rt_Errh_warning
  (JNIEnv *env, jobject object, jstring jmsg)
{
  char		*cstr;
  const char 	*msg;

  msg = (*env)->GetStringUTFChars( env, jmsg, 0);
  cstr = (char *)msg;

  errh_Warning( cstr);
  (*env)->ReleaseStringUTFChars( env, jmsg, cstr);
}
예제 #6
0
static pwr_tStatus IoCardRead( io_tCtx ctx,
                               io_sAgent *ap,
                               io_sRack	*rp,
                               io_sCard	*cp)
{
    io_sLocalAiDevice *local = (io_sLocalAiDevice *)cp->Local;
    pwr_sClass_OneWire_AiDevice *op = (pwr_sClass_OneWire_AiDevice *)cp->op;
    char str[256];
    char *s;
    pwr_tUInt32 error_count = op->Super.ErrorCount;

    if ( op->ScanInterval > 1) {
        if ( local->interval_cnt != 0) {
            local->interval_cnt++;
            if ( local->interval_cnt >= op->ScanInterval)
                local->interval_cnt = 0;
            return IO__SUCCESS;
        }
        local->interval_cnt++;
    }

    if ( cp->chanlist[0].cop && cp->chanlist[0].sop) {
        io_sChannel *chanp = &cp->chanlist[0];
        pwr_sClass_ChanAi *cop = (pwr_sClass_ChanAi *)chanp->cop;
        pwr_sClass_Ai *sop = (pwr_sClass_Ai *)chanp->sop;
        pwr_tFloat32 actvalue;

        if ( cop->CalculateNewCoef)
            // Request to calculate new coefficients
            io_AiRangeToCoef( chanp);

        fflush( local->value_fp);
        fgets( str, sizeof(str), local->value_fp);
        fgets( str, sizeof(str), local->value_fp);
        rewind( local->value_fp);

        if ( strcmp( op->ValueSearchString, "") == 0)
            s = str;
        else
            s = strstr( str, op->ValueSearchString);
        if ( s) {
            switch ( op->ChAi.Representation) {

            case pwr_eDataRepEnum_Float32:
            case pwr_eDataRepEnum_Float64: {
                pwr_tFloat32 fvalue;

                sscanf( s+strlen(op->ValueSearchString), "%f", &fvalue);

                if ( op->ErrorValue != 0 && fabs( op->ErrorValue - fvalue) > FLT_EPSILON ) {
                    /* TODO Check CRC Probably power loss...
                       op->Super.ErrorCount++; */
                }

                actvalue = cop->SensorPolyCoef0 + cop->SensorPolyCoef1 * fvalue;

                // Filter
                if ( sop->FilterType == 1 &&
                        sop->FilterAttribute[0] > 0 &&
                        sop->FilterAttribute[0] > ctx->ScanTime) {
                    actvalue = *(pwr_tFloat32 *)chanp->vbp + ctx->ScanTime / sop->FilterAttribute[0] *
                               (actvalue - *(pwr_tFloat32 *)chanp->vbp);
                }

                *(pwr_tFloat32 *)chanp->vbp = actvalue;
                sop->SigValue = cop->SigValPolyCoef1 * fvalue + cop->SigValPolyCoef0;
                sop->RawValue = fvalue;
                op->Status = IO__SUCCESS;
                break;
            }
            default: {
                pwr_tInt32 ivalue;

                sscanf( s+strlen(op->ValueSearchString), "%d", &ivalue);

                io_ConvertAi32( cop, ivalue, &actvalue);

                if ( op->ErrorValue != 0 && fabs( op->ErrorValue - ivalue) > FLT_EPSILON ) {
                    /* TODO Check CRC Probably power loss...
                       op->Super.ErrorCount++; */
                }

                // Filter
                if ( sop->FilterType == 1 &&
                        sop->FilterAttribute[0] > 0 &&
                        sop->FilterAttribute[0] > ctx->ScanTime) {
                    actvalue = *(pwr_tFloat32 *)chanp->vbp + ctx->ScanTime / sop->FilterAttribute[0] *
                               (actvalue - *(pwr_tFloat32 *)chanp->vbp);
                }

                *(pwr_tFloat32 *)chanp->vbp = actvalue;
                sop->SigValue = cop->SigValPolyCoef1 * ivalue + cop->SigValPolyCoef0;
                sop->RawValue = ivalue;
                op->Status = IO__SUCCESS;
            }
            }
        }
        else {
            op->Super.ErrorCount++;
            op->Status = IO__SEARCHSTRING;
        }
    }

    if ( op->Super.ErrorCount >= op->Super.ErrorSoftLimit &&
            error_count < op->Super.ErrorSoftLimit) {
        errh_Warning( "IO Card ErrorSoftLimit reached, '%s'", cp->Name);
        ctx->IOHandler->CardErrorSoftLimit = 1;
        ctx->IOHandler->ErrorSoftLimitObject = cdh_ObjidToAref( cp->Objid);
    }
    if ( op->Super.ErrorCount >= op->Super.ErrorHardLimit) {
        errh_Error( "IO Card ErrorHardLimit reached '%s', IO stopped", cp->Name);
        ctx->Node->EmergBreakTrue = 1;
        op->Status = IO__ERRDEVICE;
        ctx->IOHandler->CardErrorHardLimit = 1;
        ctx->IOHandler->ErrorHardLimitObject = cdh_ObjidToAref( cp->Objid);
        return IO__ERRDEVICE;
    }

    return IO__SUCCESS;
}
예제 #7
0
파일: rt_qini.c 프로젝트: jordibrus/proview
int
qini_ParseFile (
  FILE		*f,
  tree_sTable	*ntp,
  int		*warnings,
  int		*errors,
  int		*fatals
)
{
  pwr_tStatus	sts = 1;
  int		n;
  char		*s;
  char		buffer[256];
  int		error = 0;
  char		name[80];
  char		s_nid[80];
  char		s_naddr[80];
  char		s_port[80];
  char		s_connection[80];
  char		s_min_resend_time[80];
  char		s_max_resend_time[80];
  pwr_tNodeId	nid;
  struct in_addr	naddr;
  qini_sNode	*nep;
  struct arpreq	arpreq;

  while ((s = fgets(buffer, sizeof(buffer) - 1, f)) != NULL) {

    if (*s == '#' || *s == '!') {
      s++;
      continue;
    }

    n = sscanf(s, "%s %s %s %s %s %s %s", name, s_nid, s_naddr, s_port, s_connection,
	       s_min_resend_time, s_max_resend_time);
    if (n < 3) {
      errh_Error("error in line, <wrong number of arguments>, skip to next line.\n>> %s", s);
      (*errors)++;
      continue;
    }

    sts = cdh_StringToVolumeId(s_nid, (pwr_tVolumeId *)&nid);
    if (EVEN(sts)) {
      errh_Error("error in line, <node identity>, skip to next line.\n>> %s", s);
      (*errors)++;
      continue;
    }

    sts = net_StringToAddr( s_naddr, &naddr);
    if ( EVEN(sts)) {
      errh_Error("error in line, <network address>, skip to next line.\n>> %s", s);
      (*errors)++;
      continue;
    }

#if 0
    naddr.s_addr = inet_network(s_naddr);
#if defined(OS_VMS) 
    if (naddr.s_addr == (in_addr_t)-1) {
#else
    if (naddr.s_addr == (unsigned int)-1) {
#endif
      /* Try name instead */
      struct addrinfo hints;
      struct addrinfo *res;
      int err;

      memset((void*)&hints, 0, sizeof(hints));
      hints.ai_socktype = SOCK_STREAM;

      err = getaddrinfo(s_naddr, 0, &hints, &res);
      if ( err < 0) {
	errh_Error("error in line, <network address>, skip to next line.\n>> %s", s);
	(*errors)++;
	continue;
      }
      switch ( res->ai_family) {
      case AF_INET:
	// memcpy( &naddr.s_addr, (char *)&res->ai_addr->sa_data + 2, 4);
	memcpy( &naddr.s_addr, &((struct sock_addr_in *)res->ai_addr)->sin_addr, 4);
	naddr.s_addr = ntohl( naddr.s_addr);
	break;
      case AF_INET6:
	break;
      }
      freeaddrinfo( res);
    }
#endif

    nep = tree_Find(&sts, ntp, &nid);
    if (nep != NULL) {
      errh_Warning("node is allready defined: %s, skip to next line", s);
      (*warnings)++;
      continue;
    } else {
      nep = tree_Insert(&sts, ntp, &nid);
    }

    strcpy(nep->name, name);
    nep->naddr.s_addr = htonl(naddr.s_addr);
    if (n > 3) nep->port = htons(atoi(s_port));
    if (n > 4) nep->connection = atoi(s_connection);
    if (n > 5) nep->min_resend_time = atoi(s_min_resend_time);
    if (n > 6) nep->max_resend_time = atoi(s_max_resend_time);
    memset(&arpreq, 0, sizeof(arpreq));
    memcpy(&arpreq.arp_pa.sa_data, &naddr, sizeof(naddr));
    inet_GetArpEntry(&sts, 0, &arpreq);
  }

  return error;
}

pwr_tBoolean
qini_BuildDb (
  pwr_tStatus		*sts,
  tree_sTable		*nodes,
  qini_sNode		*me,
#if 0 /* change when new class NetConfig is deined */
  pwr_sNetConfig	*cp,
#else
  void			*cp,
#endif
  qcom_tBus		bus
)
{
  qdb_sInit		init;
  qdb_sNode		*np;
  qini_sNode		*nep;
  void			*p;
  qdb_sAppl		*ap;

  memset(&init, 0, sizeof(init));

  init.nid	      = me->nid;
  init.bus	      = bus;
  init.nodes	      = nodes->nNode;
#if 0	/* change when new class NetConfig is deined */
  init.queues	      = cp->Queues;
  init.applications   = cp->Applications;
  init.sbufs	      = cp->SmallCount;
  init.mbufs	      = cp->MediumCount;
  init.lbufs	      = cp->LargeCount;
  init.size_sbuf      = cp->SmallSize;
  init.size_mbuf      = cp->MediumSize;
  init.size_lbuf      = cp->LargeSize;
#endif

  p = qdb_CreateDb(sts, &init);
  if (p == NULL) return NO;

  qdb_ScopeLock {

    for (nep = tree_Minimum(sts, nodes); nep != NULL; nep = tree_Successor(sts, nodes, nep)) {
      np = addNode(nep);
    }

    ap = qdb_AddAppl(NULL, YES);

    qdb->exportque = addQueue(NULL, qdb_cIexport, "export", qdb_eQue_private, qdb_mQue_system);
    addQueue(ap, qcom_cInetEvent, "netEvent", qdb_eQue_forward, qdb_mQue_system);
    addQueue(ap, qcom_cIapplEvent, "applEvent", qdb_eQue_forward, qdb_mQue_system);
    addQueue(ap, qcom_cImhAllHandlers, "allHandlers", qdb_eQue_forward, qdb_mQue_broadcast);
    addQueue(ap, qcom_cImhAllOutunits, "allOutunits", qdb_eQue_forward, qdb_mQue_broadcast);
    addQueue(ap, qcom_cIhdServer, "hdServer", qdb_eQue_forward, qdb_mQue_broadcast);
    addQueue(ap, qcom_cIhdClient, "hdClient", qdb_eQue_forward, qdb_mQue_broadcast);
#if !defined OS_CYGWIN
    addQueue(NULL, qcom_cInacp, "nacp", qdb_eQue_private, qdb_mQue_system);
#endif
    addQueue(ap, qcom_cIini, "ini", qdb_eQue_forward, qdb_mQue_system | qdb_mQue_event);

  } qdb_ScopeUnlock;

  return (YES);
}
예제 #8
0
gdb_sVolume *
cvolcm_ConnectVolume (
  pwr_tStatus		*sts,
  gdb_sVolume		*vp,
  net_sGvolume		*gvp,
  gdb_sNode		*np
)
{
  gdb_sTouchQ		*tqp;
  gdb_sVolume		*ovp;

  gdb_AssumeLocked;

  if (vp->g.nid != pwr_cNNodeId && vp->g.nid != np->nid) {
    errh_Error("Volume %s (%s) is loaded from another node.\nCurrent: %s, new: %s",
      vp->g.name.orig, cdh_VolumeIdToString(NULL, vp->g.vid, 1, 0),
      cdh_NodeIdToString(NULL, vp->g.nid, 1, 0),
      cdh_NodeIdToString(NULL, np->nid, 1, 0));
    return NULL;
  }

  vp->g = *gvp;

  pwr_Assert(vp->g.nid != pwr_cNNodeId);

  vp->l.nr = pool_Reference(NULL, gdbroot->pool, np);

  /* Add volume name to hash table.  */

  ovp = hash_Search(NULL, gdbroot->vn_ht, &vp->g.name);
  if (ovp != NULL) {
    if (ovp != vp) {
      errh_Warning("Volume name allready exist: %s, vid: %x\n", vp->g.name.orig, vp->g.vid);
      hash_Remove(NULL, gdbroot->vn_ht, ovp);
      ovp = hash_Insert(sts, gdbroot->vn_ht, vp);
      pwr_Assert(ovp == vp);  
    }
  } else {
    ovp = hash_Insert(sts, gdbroot->vn_ht, vp);
    pwr_Assert(ovp == vp);  
  }
  vp->l.flags.b.inVnTable = 1;

  pwr_Assert(!vp->l.flags.b.inOwnList);  
  pool_QinsertPred(sts, gdbroot->pool, &vp->l.own_ll, &np->own_lh);
  vp->l.flags.b.inOwnList = 1;

  /* Initiate touch queues.  */

  tqp = &vp->u.c.cacheLock;
  pool_Qinit(NULL, gdbroot->pool, &tqp->lh);
  tqp->lc_max = 0;
  tqp->flags.b.cacheLock = 1;
  tqp->next = pool_cNRef;

  tqp = &vp->u.c.cacheVol;
  pool_Qinit(NULL, gdbroot->pool, &tqp->lh);
#if defined OS_ELN
  tqp->lc_max = 100;
#else
  tqp->lc_max = 200;
#endif
  tqp->flags.b.cacheVol = 1;
  tqp->next = pool_Reference(NULL, gdbroot->pool, &np->cacheNode);

  vp->l.flags.b.isConnected = 1;
  vp->l.flags.b.isCached = 1;
  vp->l.flags.b.netCached = 1;
  vp->l.flags.b.remote = 1;
  
  return vp;
}
예제 #9
0
static pwr_tStatus IoCardWrite( io_tCtx ctx,
				io_sAgent *ap,
				io_sRack	*rp,
				io_sCard	*cp)
{
  io_sLocalAoDevice *local = (io_sLocalAoDevice *)cp->Local;
  pwr_sClass_OneWire_AoDevice *op = (pwr_sClass_OneWire_AoDevice *)cp->op;
  char str[80];
  pwr_tUInt32 error_count = op->Super.ErrorCount;
  int num;

  if ( op->ScanInterval > 1) {
    if ( local->interval_cnt != 0) {
      local->interval_cnt++;
      if ( local->interval_cnt >= op->ScanInterval)
        local->interval_cnt = 0;
      return IO__SUCCESS;
    }
    local->interval_cnt++;
  }

  if ( cp->chanlist[0].cop && cp->chanlist[0].sop) {
    io_sChannel *chanp = &cp->chanlist[0];
    pwr_sClass_ChanAo *cop = (pwr_sClass_ChanAo *)chanp->cop;
    pwr_sClass_Ao *sop = (pwr_sClass_Ao *)chanp->sop;

    if ( cop->CalculateNewCoef)
      // Request to calculate new coefficients
      io_AoRangeToCoef( chanp);

    switch ( op->ChAo.Representation) {

    case pwr_eDataRepEnum_Float32:
    case pwr_eDataRepEnum_Float64: {
      pwr_tFloat32 fvalue;

      fvalue = *(pwr_tFloat32 *)cp->chanlist[0].vbp * cop->OutPolyCoef1 + cop->OutPolyCoef0;
      if ( fvalue > cop->ActValRangeHigh)
        fvalue = cop->ActValRangeHigh;
      else if ( fvalue < cop->ActValRangeLow)
        fvalue = cop->ActValRangeLow;

      if ( fvalue > 0)
        sop->RawValue = fvalue + 0.5;
      else
        sop->RawValue = fvalue - 0.5;

      if ( strcmp( op->Format, "") == 0 )
	num = snprintf( str, sizeof(str), "%f", fvalue);
      else
	num = snprintf( str, sizeof(str), op->Format, fvalue);

      if ( num == 0)
	op->Super.ErrorCount++;
      
      break;
    }
    default: {
      pwr_tInt32 ivalue;
      pwr_tFloat32 fvalue;

      fvalue = *(pwr_tFloat32 *)cp->chanlist[0].vbp * cop->OutPolyCoef1 + cop->OutPolyCoef0;
      if ( fvalue > cop->ActValRangeHigh)
        fvalue = cop->ActValRangeHigh;
      else if ( fvalue < cop->ActValRangeLow)
        fvalue = cop->ActValRangeLow;

      if ( fvalue > 0)
        ivalue = sop->RawValue = fvalue + 0.5;
      else
        ivalue = sop->RawValue = fvalue - 0.5;

      if ( strcmp( op->Format, "") == 0 )
	num = snprintf( str, sizeof(str), "%d", ivalue);
      else
	num = snprintf( str, sizeof(str), op->Format, ivalue);

      if ( num == 0)
	op->Super.ErrorCount++;
    }
    }

    if ( num) {
      fprintf( local->value_fp, "%s", str);
      fflush( local->value_fp);
      rewind( local->value_fp);
    }
  }
  if ( op->Super.ErrorCount >= op->Super.ErrorSoftLimit && 
       error_count < op->Super.ErrorSoftLimit) {
    errh_Warning( "IO Card ErrorSoftLimit reached, '%s'", cp->Name);
  }
  if ( op->Super.ErrorCount >= op->Super.ErrorHardLimit) {
    errh_Error( "IO Card ErrorHardLimit reached '%s', IO stopped", cp->Name);
    ctx->Node->EmergBreakTrue = 1;
    return IO__ERRDEVICE;
  }    

  return IO__SUCCESS;
}
예제 #10
0
static pwr_tStatus IoCardWrite( io_tCtx ctx,
			       io_sAgent *ap,
			       io_sRack	*rp,
			       io_sCard	*cp)
{
  io_sLocal_K8055 *local = (io_sLocal_K8055 *)cp->Local;
  pwr_sClass_Velleman_K8055_Board *op = (pwr_sClass_Velleman_K8055_Board *)cp->op;
  unsigned char data[9];
  char endpoint = 0x1;
  int size = 8;
  int tsize;
  unsigned char m;
  int i;
  int sts;
  pwr_tUInt32 error_count = op->Super.ErrorCount;

  memset( data, 0, sizeof(data));
  data[0] = 0x5;

  // Handle Do
  m = 1;
  unsigned char do_value = 0;
  for ( i = 0; i < 8; i++) {
    if ( cp->chanlist[i+9].sop) {
      if ( *(pwr_tBoolean *)cp->chanlist[i+9].vbp)
	do_value |= m;
    }
    m = m << 1;
  }
  data[1] = do_value;

  // Handle Ao
  for ( i = 0; i < 2; i++) {
    if ( cp->chanlist[i+7].sop) {
      io_sChannel *chanp = &cp->chanlist[i+7];
      pwr_sClass_ChanAo *cop = (pwr_sClass_ChanAo *)chanp->cop;


      if ( cop->CalculateNewCoef)
	// Request to calculate new coefficients
	io_AoRangeToCoef( chanp);

      float fvalue = *(pwr_tFloat32 *)chanp->vbp * cop->OutPolyCoef1 + cop->OutPolyCoef0;
      int ivalue = (int)fvalue;
      if ( ivalue < 0)
	ivalue = 0;
      else if (ivalue > 255)
	ivalue = 255;

      data[i+2] = ivalue;
    }
  }

  sts = libusb_interrupt_transfer( local->libusb_device, endpoint, data, size, &tsize, 100);
  if ( sts != 0 || tsize != size) {
    op->Super.ErrorCount++;
    if ( sts != 0 && sts != last_usblib_sts) {
      errh_Error( "K8055 libusb transfer error %d", sts);
      last_usblib_sts = sts;
    }
    return IO__SUCCESS;
  }

  if ( op->Super.ErrorCount >= op->Super.ErrorSoftLimit && 
       error_count < op->Super.ErrorSoftLimit) {
    errh_Warning( "IO Card ErrorSoftLimit reached, '%s'", cp->Name);
  }
  if ( op->Super.ErrorCount >= op->Super.ErrorHardLimit) {
    errh_Error( "IO Card ErrorHardLimit reached '%s', IO stopped", cp->Name);
    ctx->Node->EmergBreakTrue = 1;
    return IO__ERRDEVICE;
  }    

  return IO__SUCCESS;
}
예제 #11
0
static pwr_tStatus IoCardRead( io_tCtx ctx,
			       io_sAgent *ap,
			       io_sRack	*rp,
			       io_sCard	*cp)
{
  io_sLocal_K8055 *local = (io_sLocal_K8055 *)cp->Local;
  pwr_sClass_Velleman_K8055_Board *op = (pwr_sClass_Velleman_K8055_Board *)cp->op;
  unsigned char data[9];
  char endpoint = 0x81;
  int size = 8;
  int tsize;
  unsigned char m;
  int sts;
  int i;
  pwr_tUInt32 error_count = op->Super.ErrorCount;

  // You have to read twice to get the latest ?????
  sts = libusb_interrupt_transfer( local->libusb_device, endpoint, data, 8, &tsize, 100);
  sts = libusb_interrupt_transfer( local->libusb_device, endpoint, data, 8, &tsize, 100);
  if ( sts != 0 || tsize != size) {
    op->Super.ErrorCount++;
    if ( sts != 0 && sts != last_usblib_sts) {
      errh_Error( "K8055 libusb transfer error %d", sts);
      last_usblib_sts = sts;
    }
    return IO__SUCCESS;
  }
  else {

    // Handle Ai
    for ( i = 0; i < 2; i++) {
      if ( cp->chanlist[i].sop) {
	io_sChannel *chanp = &cp->chanlist[i];
	pwr_sClass_ChanAi *cop = (pwr_sClass_ChanAi *)chanp->cop;
	pwr_sClass_Ai *sop = (pwr_sClass_Ai *)chanp->sop;
	pwr_tFloat32 actvalue;
	int ivalue = data[i+2];

	if ( cop->CalculateNewCoef)
	  // Request to calculate new coefficients
	  io_AiRangeToCoef( chanp);

	io_ConvertAi( cop, ivalue, &actvalue);

	// Filter
	if ( sop->FilterType == 1 &&
	     sop->FilterAttribute[0] > 0 &&
	     sop->FilterAttribute[0] > ctx->ScanTime) {
	  actvalue = *(pwr_tFloat32 *)chanp->vbp + ctx->ScanTime / sop->FilterAttribute[0] *
	    (actvalue - *(pwr_tFloat32 *)chanp->vbp);
	}

	*(pwr_tFloat32 *)chanp->vbp = actvalue;
	sop->SigValue = cop->SigValPolyCoef1 * ivalue + cop->SigValPolyCoef0;
	sop->RawValue = ivalue;
      }
    }

    // Handle Di
    for ( i = 0; i < 5; i++) {
      switch ( i) {
      case 0: m = 16; break;
      case 1: m = 32; break;
      case 2: m = 1; break;
      case 3: m = 64; break;
      case 4: m = 128; break;
      }
      if ( cp->chanlist[i+2].sop)
	*(pwr_tBoolean *)cp->chanlist[i+2].vbp = ((data[0] & m) != 0);
    }
  }

  if ( op->Super.ErrorCount >= op->Super.ErrorSoftLimit && 
       error_count < op->Super.ErrorSoftLimit) {
    errh_Warning( "IO Card ErrorSoftLimit reached, '%s'", cp->Name);
  }
  if ( op->Super.ErrorCount >= op->Super.ErrorHardLimit) {
    errh_Error( "IO Card ErrorHardLimit reached '%s', IO stopped", cp->Name);
    ctx->Node->EmergBreakTrue = 1;
    return IO__ERRDEVICE;
  }    

  return IO__SUCCESS;
}
예제 #12
0
/*----------------------------------------------------------------------------*\
  Read method for the Powerlink master
  \*----------------------------------------------------------------------------*/
static pwr_tStatus IoAgentRead( io_tCtx ctx, io_sAgent *ap) {	
  io_sLocalEpl_MN *local = (io_sLocalEpl_MN *)ap->Local;
  io_sLocalEpl_CN *local1;
  pwr_sClass_Epl_MN *op = (pwr_sClass_Epl_MN *)ap->op;
  io_sRack *rp;
  io_sCard *cp;
  pwr_tUInt32 error_count = 0;
  int ret = IO__SUCCESS;
  
  if(!ap->Local)
    return ret;
	
  // Remeber the time when this functions was called the first time
  if( local->init == 0) {
    clock_gettime(CLOCK_REALTIME, &local->boot);
    local->init = 1;
  }

  // Time now (tps = time when bad state occurred)
  clock_gettime(CLOCK_REALTIME, &local->tpe);
  
  error_count = op->ErrorCount;
  // Add to error count if agent changed from good to bad state and setup is complete
  if( local->prevState == pwr_eEplNmtState_EplNmtMsOperational && op->NmtState != pwr_eEplNmtState_EplNmtMsOperational && ( (local->tpe).tv_sec - (local->boot).tv_sec) >= op->StartupTimeout)
    op->ErrorCount++;
  
  // Copy Powerlink process image to temp memory (only if stallaction=resetinputs else tmp_area=input_area)
  if( local->inputResetEnabled)
    memcpy( local->tmp_area , local->input_area, local->input_area_size);
	
  // If no bad state and were still in startup there can be no error (else remember when error occurred)
  if( op->NmtState == pwr_eEplNmtState_EplNmtMsOperational || ( (local->tpe).tv_sec - (local->boot).tv_sec) < op->StartupTimeout) {
    (local->tps).tv_sec = 0;
    local->timeoutStatus = 0;
  }
  else if( (local->tps).tv_sec == 0) {
    clock_gettime(CLOCK_REALTIME, &local->tps);
  }

  // Agent error soft limit reached, tell log (once)
  if ( op->ErrorCount >= op->ErrorSoftLimit && error_count < op->ErrorSoftLimit) {
    errh_Warning( "IO Agent ErrorSoftLimit reached, '%s'", ap->Name);
  }	
	
  // Agent error hard limit reached, tell log (once)	
  if ( op->ErrorCount >= op->ErrorHardLimit && error_count < op->ErrorHardLimit) {
		
    if( op->StallAction == pwr_eStallActionEnum_EmergencyBreak) {
      errh_Error( "IO Agent ErrorHardLimit reached '%s', IO stopped", ap->Name);
    }
    else
      errh_Error( "IO Agent ErrorHardLimit reached '%s'", ap->Name);
  }

  // Agent timeout has elapsed, tell log (once)	
  if( ( (local->tpe).tv_sec - (local->tps).tv_sec) >= op->Timeout && local->timeoutStatus == 0 && (local->tps).tv_sec != 0) {
	  
    local->timeoutStatus = 1;
    if( op->StallAction == pwr_eStallActionEnum_EmergencyBreak) {
      errh_Error( "IO Agent timeout time elapsed '%s', IO stopped", ap->Name);
    }
    else if( op->StallAction == pwr_eStallActionEnum_ResetInputs) {
      errh_Error( "IO Agent timeout time elapsed '%s', IO input area reset", ap->Name);
    }
    else
      errh_Error( "IO Agent timeout time elapsed '%s'", ap->Name);
	
  }
		
  // Agent error hard limit reached, take action (always)	
  if ( op->ErrorCount >= op->ErrorHardLimit) {
		
    if( op->StallAction == pwr_eStallActionEnum_EmergencyBreak) {
      ctx->Node->EmergBreakTrue = 1;
      errh_SetStatus(PWR__SRVFATAL);
      IoAgentClose(ctx, ap);
    }
    ret = IO__ERRDEVICE;
  }
  
  // Agent timeout time elapsed, take action (always)	
  if ( ( (local->tpe).tv_sec - (local->tps).tv_sec) >= op->Timeout && (local->tps).tv_sec != 0) {
		
    if( op->StallAction == pwr_eStallActionEnum_EmergencyBreak) {
      ctx->Node->EmergBreakTrue = 1;
      errh_SetStatus(PWR__SRVFATAL);
      IoAgentClose(ctx, ap);
    }
    else if( op->StallAction == pwr_eStallActionEnum_ResetInputs) {
      memset( local->tmp_area, 0, local->input_area_size);
    }
    ret = IO__ERRDEVICE;
  }
  
  // Remember agent state til next scan
  local->prevState = op->NmtState;
	
  // Loop through all slaves
  for ( rp = ap->racklist; rp; rp = rp->next) {
		
    ((pwr_sClass_Epl_CN *)rp->op)->Status = ((pwr_sClass_Epl_CN *)rp->op)->NmtState == pwr_eEplNmtState_EplNmtCsOperational ? IOM__EPL_OPER : IOM__EPL_NOOPER;
    local1 = (io_sLocalEpl_CN *)rp->Local;
    // Time now (tps = time when bad state occurred)
    clock_gettime(CLOCK_REALTIME, &local1->tpe);
		
    error_count = ((pwr_sClass_Epl_CN *)rp->op)->ErrorCount;
    // Add to error count if slave changed from good to bad state and setup is complete
    if( local1->prevState == pwr_eEplNmtState_EplNmtCsOperational && ((pwr_sClass_Epl_CN *)rp->op)->NmtState != pwr_eEplNmtState_EplNmtCsOperational && ( (local1->tpe).tv_sec - (local->boot).tv_sec) >= op->StartupTimeout)
      ((pwr_sClass_Epl_CN *)rp->op)->ErrorCount++;
	  	
    // Save time when bad state occurs
    if( ( (pwr_sClass_Epl_CN *)rp->op)->NmtState == pwr_eEplNmtState_EplNmtCsOperational || ( (local1->tpe).tv_sec - (local->boot).tv_sec) < op->StartupTimeout) {
      (local1->tps).tv_sec = 0;
      local1->timeoutStatus = 0;	
    }
    else if( (local1->tps).tv_sec == 0)
      clock_gettime(CLOCK_REALTIME, &local1->tps);
						
    // Slave error soft limit reached, tell log (once)
    if ( ((pwr_sClass_Epl_CN *)rp->op)->ErrorCount >= ((pwr_sClass_Epl_CN *)rp->op)->ErrorSoftLimit && error_count < ((pwr_sClass_Epl_CN *)rp->op)->ErrorSoftLimit) {
      errh_Warning( "IO Rack ErrorSoftLimit reached, '%s'", rp->Name);
    }
			
    // Slave error hard limit reached, tell log (once)
    if ( ((pwr_sClass_Epl_CN *)rp->op)->ErrorCount >= ((pwr_sClass_Epl_CN *)rp->op)->ErrorHardLimit && error_count < ((pwr_sClass_Epl_CN *)rp->op)->ErrorHardLimit) {
		
      if( ((pwr_sClass_Epl_CN *)rp->op)->StallAction == pwr_eStallActionEnum_EmergencyBreak) {
	errh_Error( "IO Rack ErrorHardLimit reached '%s', IO stopped", rp->Name);
      }
      else
	errh_Error( "IO Rack ErrorHardLimit reached '%s'", rp->Name);
    }
    
    // Slave timeout has elapsed, tell log (once)	
    if( ( (local1->tpe).tv_sec - (local1->tps).tv_sec) >= ((pwr_sClass_Epl_CN *)rp->op)->Timeout && local1->timeoutStatus == 0 && (local1->tps).tv_sec != 0) {
      local1->timeoutStatus = 1;	
      if( ((pwr_sClass_Epl_CN *)rp->op)->StallAction == pwr_eStallActionEnum_EmergencyBreak) {
	errh_Error( "Rack timeout time elapsed '%s', IO stopped", rp->Name);
      }
      else if( ((pwr_sClass_Epl_CN *)rp->op)->StallAction == pwr_eStallActionEnum_ResetInputs) {
	errh_Error( "Rack timeout time elapsed '%s', IO input area reset", rp->Name);
      }
      else
	errh_Error( "Rack timeout time elapsed '%s'", rp->Name);
    }
		
    // Slave error hard limit reached, take action (always)
    if ( ((pwr_sClass_Epl_CN *)rp->op)->ErrorCount >= ((pwr_sClass_Epl_CN *)rp->op)->ErrorHardLimit) {
      if( ((pwr_sClass_Epl_CN *)rp->op)->StallAction == pwr_eStallActionEnum_EmergencyBreak) {
	ctx->Node->EmergBreakTrue = 1;
	errh_SetStatus(PWR__SRVFATAL);
	IoAgentClose(ctx, ap);
      }
      ret = IO__ERRDEVICE;
    }
    
    // Slave timeout elapsed, take action (always)
    if( ( (local1->tpe).tv_sec - (local1->tps).tv_sec) >= ((pwr_sClass_Epl_CN *)rp->op)->Timeout && (local1->tps).tv_sec != 0) {
      if( ((pwr_sClass_Epl_CN *)rp->op)->StallAction == pwr_eStallActionEnum_EmergencyBreak) {
	ctx->Node->EmergBreakTrue = 1;
	errh_SetStatus(PWR__SRVFATAL);
	IoAgentClose(ctx, ap);
      }
      else if( ((pwr_sClass_Epl_CN *)rp->op)->StallAction == pwr_eStallActionEnum_ResetInputs) {
	memset( local->tmp_area + ((pwr_sClass_Epl_CN *)rp->op)->InputAreaOffset, 0, ((pwr_sClass_Epl_CN *)rp->op)->InputAreaSize);
      }
      ret = IO__ERRDEVICE;
    }
	
    // Remeber slave state til next scan	
    local1->prevState = ((pwr_sClass_Epl_CN *)rp->op)->NmtState;
		
    // Update Proview chan-objects with data from Powerlink process image
    for ( cp = rp->cardlist; cp; cp = cp->next) {
      io_bus_card_read( ctx, rp, cp, local->tmp_area, 0, ((io_sLocalEpl_CN *)rp->Local)->byte_ordering, pwr_eFloatRepEnum_FloatIEEE);
    }					
  }

  return ret;
}
예제 #13
0
static pwr_tStatus IoCardRead( io_tCtx ctx,
			       io_sAgent *ap,
			       io_sRack	*rp,
			       io_sCard	*cp)
{
  io_sLocalUSB_Joystick *local = (io_sLocalUSB_Joystick *)cp->Local;
  pwr_sClass_USB_Joystick *op = (pwr_sClass_USB_Joystick *)cp->op;
  struct js_event js;
  int idx;
  int value;


  while ( read( local->fd, &js, sizeof(struct js_event)) == sizeof(struct js_event))  {
    // printf("Event: type %d, time %d, number %d, value %d\n", js.type, js.time, js.number, js.value);

    switch ( js.type) {
    case 129:
    case 1:
      /* Buttons */
      idx = js.number;

      if ( js.number < KEY_MAX - BTN_MISC)
	idx = local->button_map[js.number];
      else
	break;
	  
      *(pwr_tBoolean *)cp->chanlist[idx].vbp = (js.value != 0);

      break;
    case 130:
    case 2: {
      io_sChannel *chanp;
      pwr_sClass_ChanAi *cop;
      pwr_sClass_Ai *sop;
      pwr_tFloat32 actvalue;
      int ivalue;

      /* Axes */
      idx = js.number;
      value = js.value;

      if ( js.number < ABS_MAX) {
	idx = local->axis_map[js.number];
	ivalue = js.value;
      }
      else
	break;
      
      chanp = &cp->chanlist[idx];
      cop = (pwr_sClass_ChanAi *)chanp->cop;
      sop = (pwr_sClass_Ai *)chanp->sop;

      if ( cop->CalculateNewCoef)
	// Request to calculate new coefficients
	io_AiRangeToCoef( chanp);

      io_ConvertAi( cop, ivalue, &actvalue);

      // Filter
      if ( sop->FilterType == 1 &&
	   sop->FilterAttribute[0] > 0 &&
	   sop->FilterAttribute[0] > ctx->ScanTime) {
	actvalue = *(pwr_tFloat32 *)chanp->vbp + ctx->ScanTime / sop->FilterAttribute[0] *
	  (actvalue - *(pwr_tFloat32 *)chanp->vbp);
      }

      *(pwr_tFloat32 *)chanp->vbp = actvalue;
      sop->SigValue = cop->SigValPolyCoef1 * ivalue + cop->SigValPolyCoef0;
      sop->RawValue = ivalue;
      
      break;
    }
    }
  }
    
  if (errno != EAGAIN) {
    op->ErrorCount++;
  }

  if ( op->ErrorCount == op->ErrorSoftLimit) {
    errh_Warning( "IO Card ErrorSoftLimit reached, '%s'", cp->Name);
    ctx->IOHandler->CardErrorSoftLimit = 1;
    ctx->IOHandler->ErrorSoftLimitObject = cdh_ObjidToAref( cp->Objid);
  }
  if ( op->ErrorCount >= op->ErrorHardLimit) {
    errh_Error( "IO Card ErrorHardLimit reached '%s', IO stopped", cp->Name);
    ctx->Node->EmergBreakTrue = 1;
    ctx->IOHandler->CardErrorHardLimit = 1;
    ctx->IOHandler->ErrorHardLimitObject = cdh_ObjidToAref( cp->Objid);
    return IO__ERRDEVICE;
  }    

  return IO__SUCCESS;
}
예제 #14
0
void *handle_events(void *ptr) {
  agent_args           *args;
  io_sAgentLocal       *local;
  io_sAgent            *ap;
  short                          sts;
  T_PROFI_DEVICE_HANDLE *hDevice;
  pwr_sClass_Pb_Profiboard *op;
  char                     s [128];

  USIGN8                   con_ind_buffer [256];
  USIGN16                  con_ind_buffer_len = 256;
  T_PROFI_SERVICE_DESCR    con_ind_sdb;
  T_DP_GET_SLAVE_DIAG_CON  *get_slave_diag_con_ptr;
  struct timespec rqtp = {0, 10000000}; // 10 ms  

  args = (agent_args *) ptr;
  local = (io_sAgentLocal *) args->local;
  ap = args->ap;

  hDevice = (T_PROFI_DEVICE_HANDLE *) ap->Local;
  op = (pwr_sClass_Pb_Profiboard *) ap->op;

  /* If everything is fine we should be in state OPERATE
     Make a poll to see if there are diagnostics, the answer also tell us
     if there are any hardware faults. In that case, make a reset and a new init. */
    
  while (1) {
    
    if (op->DisableBus) exit(0);

    pthread_mutex_lock(&local->mutex);

    con_ind_buffer_len = 256;
    sts = profi_rcv_con_ind (  hDevice, &con_ind_sdb, con_ind_buffer, &con_ind_buffer_len);
    
    if (sts == CON_IND_RECEIVED) {
      if (con_ind_sdb.primitive == CON) {
	if (con_ind_sdb.result == POS) {
	  switch (con_ind_sdb.service) {
	    /*--------------------------------------------------------------*/
	    
	  case DP_ACT_PARAM_LOC: {
	    
	    if (op->Status == PB__NOTINIT) {
	      op->Status = PB__STOPPED;
	      errh_Info( "Profibus DP Master %s to state STOPPED", ap->Name);
	      dp_act_param_loc(hDevice, DP_OP_MODE_CLEAR);
	    }
	    else if (op->Status == PB__STOPPED) {
	      op->Status = PB__CLEARED;
	      errh_Info( "Profibus DP Master %s to state CLEARED", ap->Name);
	      dp_act_param_loc(hDevice, DP_OP_MODE_OPERATE);
	    }
	    else if (op->Status == PB__CLEARED) {
	      errh_Info( "Profibus DP Master %s to state OPERATE", ap->Name);
	      op->Status = PB__NORMAL;

              if (!local->slave_diag_requested && local->parallel_service) {
                if (dp_get_slave_diag(hDevice)) {
                  local->slave_diag_requested = op->Diag[3] = PB_TRUE;
                  local->parallel_service = PB_FALSE;
                } 
              }

	    }
	    
	    break;
	  } /* case DP_ACT_PARAM_LOC */
	    
	    /*--------------------------------------------------------------*/
	    
	  case DP_GET_SLAVE_DIAG: {
	    get_slave_diag_con_ptr = (T_DP_GET_SLAVE_DIAG_CON FAR*) con_ind_buffer;
	    
	    dp_get_slave_diag_con (get_slave_diag_con_ptr, ap->racklist, op->Diag[1]);
	    op->Diag[2]++;
	    
	    local->slave_diag_requested = op->Diag[3] = PB_FALSE;
	    
	    if (get_slave_diag_con_ptr->diag_entries < 0) {
	      errh_Warning( "Profibus - diagnostic circular buffer owerflow.");
	    }
	    
	    if (get_slave_diag_con_ptr->diag_entries) {
	      local->slave_diag_requested = op->Diag[3] = PB_TRUE;
	      dp_get_slave_diag (hDevice);
	    }
	    break;
	  } /* case DP_GET_SLAVE_DIAG */
	    
	    /*--------------------------------------------------------------*/
	    
	  default: {
	    break;
	  } /* deafult service */
	  } /* switch */
	} /* if POS */
	else {
	  op->Status = PB__NOTINIT;
	  errh_Error( "Profibus DP Master %s - %x neg con rec", ap->Name, *((unsigned short *) con_ind_buffer) );      
	} /* else POS */
      } /* if CON */
      else if (con_ind_sdb.primitive == IND) {
	if (con_ind_sdb.result == POS) {
	  switch (con_ind_sdb.service) {
	  case FMB_FM2_EVENT: {
	    switch (((T_FMB_FM2_EVENT_IND FAR*) con_ind_buffer)->reason) {
	    case FM2_FAULT_ADDRESS     : sprintf (s, "Duplicate address recognized"); break;
	    case FM2_FAULT_PHY         : sprintf (s, "Phys.layer is malfunctioning"); break;
	    case FM2_FAULT_TTO         : sprintf (s, "Time out on bus detected    "); break;
	    case FM2_FAULT_SYN         : sprintf (s, "No receiver synchronization "); break;
	    case FM2_FAULT_OUT_OF_RING : sprintf (s, "Station out of ring         "); break;
	    case FM2_GAP_EVENT         : sprintf (s, "New station in ring         "); break;
	      
	    default                    : sprintf (s, "Unknown reason code received");
	      
	    } /* switch reason */
	    
	    errh_Info( "Profibus DP Master %s - %s", ap->Name, s );      
	    
	    break;
	  } /* case FMB_FM2_EVENT */
	    
	    /*--------------------------------------------------------------*/
	    
	  case DP_ACT_PARAM_LOC: {
	    USIGN8 usif_state;
	    usif_state = ((T_DP_ACT_PARAM_IND FAR*) con_ind_buffer)->activate;
	    
	    switch (usif_state) {
	    case DP_OP_MODE_STOP   : {
	      op->Status = PB__STOPPED;
	      sprintf (s, "Mode changed to STOP");
	      break;
	    }
	    case DP_OP_MODE_CLEAR  : {
	      op->Status = PB__CLEARED;
	      sprintf (s, "Mode changed to CLEAR");
	      break;
	    }
	    case DP_OP_MODE_OPERATE: { 
	      op->Status = PB__NORMAL;
	      sprintf (s, "Mode changed to OPERATE");
	      break;
	    }
	    }
	    
	    errh_Info( "Profibus DP Master %s - %s", ap->Name, s );      
	    
	    if (usif_state == DP_OP_MODE_STOP) {
	      usif_state = DP_OP_MODE_CLEAR;
	      
	      dp_act_param_loc(hDevice, DP_OP_MODE_CLEAR);
	    }
	    else if (usif_state == DP_OP_MODE_CLEAR) {
	      usif_state = DP_OP_MODE_OPERATE;
	      
	      dp_act_param_loc (hDevice, DP_OP_MODE_OPERATE);
	    }
	    
	    break;
	  } /* case DP_ACT_PARAM_LOC */
	    
	    /*--------------------------------------------------------------*/
	    
	  case DP_GET_SLAVE_DIAG: {
	    get_slave_diag_con_ptr = (T_DP_GET_SLAVE_DIAG_CON FAR*) con_ind_buffer;
	    
	    dp_get_slave_diag_con (get_slave_diag_con_ptr, ap->racklist, op->Diag[1]);
	    
	    op->Diag[0]++;
	    
	    if (get_slave_diag_con_ptr->diag_entries < 0) {
	      errh_Warning( "Profibus - diagnostic circular buffer owerflow.");
	    }
	    
	    if ( (get_slave_diag_con_ptr->diag_entries) &&
		 (! local->slave_diag_requested              ) ) {
              if (op->Status == PB__NORMAL) {
                if (dp_get_slave_diag(hDevice)) {
                  local->slave_diag_requested = op->Diag[3] = PB_TRUE;
                } else {
                  errh_Warning( "Profibus - Request for diag failed.");
                }
              } else {
                local->parallel_service = PB_TRUE;
              }
	    }
	    
	    break;
	  } /* case DP_GET_SLAVE_DIAG */
	    
	    /*--------------------------------------------------------------*/
	    
	  default: {
	    break;
	  } /* deafult service */
	  } /* switch */
	} /* if POS */
	else {
	  op->Status = PB__NOTINIT;
	  errh_Error( "Profibus DP Master %s - %x neg ind rec", ap->Name,  *((unsigned short *) con_ind_buffer) );      
	} /* else POS */
      } /* if IND */
    } else if (sts != NO_CON_IND_RECEIVED) {
      op->Status = PB__NOTINIT;
    } else {
      if (local->slave_diag_requested) {
	//	errh_Info( "Profibus - Diag re-request");
	//	dp_get_slave_diag(hDevice);
      }
    }    
    pthread_mutex_unlock(&local->mutex);

    nanosleep(&rqtp, NULL);
  }
  

}