/*----------------------------------------------------------------------------*\ \*----------------------------------------------------------------------------*/ static pwr_tStatus IoCardSwap ( io_tCtx ctx, io_sAgent *ap, io_sRack *rp, io_sCard *cp, io_eEvent event ) { io_sLocal *local; io_sRackLocal *r_local = (io_sRackLocal *)(rp->Local); pwr_tUInt16 data = 0; pwr_sClass_Ssab_BaseDoCard *op; int i; qbus_io_read rb; int sts; switch ( event) { case io_eEvent_IoCommSwapInit: case io_eEvent_IoCommSwap: op = (pwr_sClass_Ssab_BaseDoCard *) cp->op; if (!cp->Local) { local = calloc( 1, sizeof(*local)); cp->Local = local; local->Address[0] = op->RegAddress; local->Address[1] = op->RegAddress + 2; local->Qbus_fp = ((io_sRackLocal *)(rp->Local))->Qbus_fp; local->FirstScan = 1; } for ( i = 0; i < 2; i++) { if (r_local->Qbus_fp != 0 && r_local->s == 0) { /* Write to local Q-bus */ rb.Address = local->Address[i]; sts = read( local->Qbus_fp, &rb, sizeof(rb)); } else { /* Ethernet I/O, Get data from current address */ data = bfbeth_get_data(r_local, (pwr_tUInt16) local->Address[i], &sts); /* Yes, we want to read this address the next time aswell */ bfbeth_set_read_req(r_local, (pwr_tUInt16) local->Address[i]); sts = 1; } } break; default: ; } return 1; }
/*----------------------------------------------------------------------------*\ \*----------------------------------------------------------------------------*/ static pwr_tStatus IoCardRead ( io_tCtx ctx, io_sAgent *ap, io_sRack *rp, io_sCard *cp ) { io_sLocal *local; io_sRackLocal *r_local = (io_sRackLocal *)(rp->Local); pwr_tUInt16 data = 0; pwr_sClass_Ssab_BaseDiCard *op; pwr_sClass_Ssab_RemoteRack *rrp; pwr_tUInt16 invmask; pwr_tUInt16 convmask; int i; int sts; qbus_io_read rb; int bfb_error = 0; pwr_tTime now; local = (io_sLocal *) cp->Local; op = (pwr_sClass_Ssab_BaseDiCard *) cp->op; for ( i = 0; i < 2; i++) { if ( i == 0) { convmask = op->ConvMask1; invmask = op->InvMask1; } else { convmask = op->ConvMask2; invmask = op->InvMask2; if ( !convmask) break; if ( op->MaxNoOfChannels == 16) break; } if (r_local->Qbus_fp != 0 && r_local->s == 0) { /* Read from local Q-bus */ rb.Address = local->Address[i]; sts = read( local->Qbus_fp, &rb, sizeof(rb)); data = (unsigned short) rb.Data; } else { /* Ethernet I/O, Get data from current address */ data = bfbeth_get_data(r_local, (pwr_tUInt16) local->Address[i], &sts); /* Yes, we want to read this address the next time aswell */ bfbeth_set_read_req(r_local, (pwr_tUInt16) local->Address[i]); if (sts == -1) { /* Error handling for ethernet Qbus-I/O */ rrp = (pwr_sClass_Ssab_RemoteRack *) rp->op; if (bfb_error == 0) { op->ErrorCount++; bfb_error = 1; if ( op->ErrorCount == op->ErrorSoftLimit) errh_Error( "IO Error soft limit reached on card '%s'", cp->Name); if ( op->ErrorCount == op->ErrorHardLimit) errh_Error( "IO Error hard limit reached on card '%s', stall action %d", cp->Name, rrp->StallAction); if ( op->ErrorCount >= op->ErrorHardLimit && rrp->StallAction == pwr_eSsabStallAction_ResetInputs ) { data = 0; sts = 1; } if ( op->ErrorCount >= op->ErrorHardLimit && rrp->StallAction == pwr_eSsabStallAction_EmergencyBreak ) { ctx->Node->EmergBreakTrue = 1; return IO__ERRDEVICE; } } if (sts == -1) continue; } else { op->ErrorCount = 0; } } if ( sts == -1) /* Error handling for local Qbus-I/O */ { /* Increase error count and check error limits */ time_GetTime( &now); if (op->ErrorCount > op->ErrorSoftLimit) { /* Ignore if some time has expired */ if (now.tv_sec - local->ErrTime.tv_sec < 600) op->ErrorCount++; } else op->ErrorCount++; local->ErrTime = now; if ( op->ErrorCount == op->ErrorSoftLimit) errh_Error( "IO Error soft limit reached on card '%s'", cp->Name); if ( op->ErrorCount >= op->ErrorHardLimit) { errh_Error( "IO Error hard limit reached on card '%s', IO stopped", cp->Name); ctx->Node->EmergBreakTrue = 1; return IO__ERRDEVICE; } continue; } /* Invert */ data = data ^ invmask; /* Filter ... */ if ( local->Filter[i].Found) io_DiFilter( local->Filter[i].sop, &data, local->Filter[i].Data); /* Move data to valuebase */ io_DiUnpackWord( cp, data, convmask, i); } return 1; }
/*----------------------------------------------------------------------------*\ \*----------------------------------------------------------------------------*/ static pwr_tStatus IoCardRead ( io_tCtx ctx, io_sAgent *ap, io_sRack *rp, io_sCard *cp ) { io_sLocal *local; pwr_tUInt16 wr_data[2]; pwr_tUInt16 re_data[2]; pwr_tUInt32 *wr_data_p; pwr_tUInt32 *re_data_p; pwr_sClass_Ssab_CO4uP *op; pwr_tInt32 numofword; int i; pwr_tInt16 co16_data; pwr_tInt32 newdiff,diff,co24_data; int sts, sts1, sts2; qbus_io_read rb; qbus_io_write wb; io_sRackLocal *r_local = (io_sRackLocal *)(rp->Local); pwr_tTime now; local = (io_sLocal *) cp->Local; op = (pwr_sClass_Ssab_CO4uP *) cp->op; for ( i = 0; i < op->MaxNoOfCounters; i++) { if ( !cp->chanlist[i].cop || !cp->chanlist[i].sop) continue; if ( op->ConvMask & (1 << i)) { /* Conversion is on */ if ( op->COWrFlag[i]) { /* New configuration of card */ wr_data_p = (pwr_tUInt32 *) &wr_data; *wr_data_p = op->SyncRawValue[i]; if ( op->SpeedMeasurement[i] == 1) wr_data[1] |= (1 << 8); if ( op->LengthMeasurement[i] == 1) wr_data[1] |= (1 << 10); if ( op->MulCount[i] == 2) wr_data[1] |= (1 << 11); if ( op->DivCount[i] == 16) wr_data[1] |= (1 << 9); if ( op->NoOfBits[i] == 16) wr_data[1] |= (1 << 12); if ( op->CopWrRough[i] == 1) wr_data[1] |= (1 << 13); if ( op->CopWrFine[i] == 1) wr_data[1] |= (1 << 14); if ( op->LoadWrReg[i] == 1) wr_data[1] |= (1 << 15); if (r_local->Qbus_fp != 0 && r_local->s == 0) { /* Write to local Q-bus */ wb.Address = local->Address + 4*i; wb.Data = wr_data[0]; sts = write( local->Qbus_fp, &wb, sizeof(wb)); if ( sts != -1) { wb.Address += 2; wb.Data = wr_data[1]; sts = write( local->Qbus_fp, &wb, sizeof(wb)); } } else { /* Ethernet I/O, Request a write to current address */ bfbeth_set_write_req(r_local, (pwr_tUInt16) (local->Address + 4*i), wr_data[0]); bfbeth_set_write_req(r_local, (pwr_tUInt16) (local->Address + 4*i + 2), wr_data[1]); sts = 1; } if ( sts == -1) { errh_Error( "IO init, Fatal write error, card '%s', IO i stopped", cp->Name); } op->COWrFlag[i] = 0; } if ( op->NoOfBits[i] == 24) numofword = 2; else numofword = 1; /* 16 bitscounter */ re_data_p = (pwr_tUInt32 *) &re_data; if (r_local->Qbus_fp != 0 && r_local->s == 0) { /* Read from local Q-bus */ rb.Address = local->Address + 4*i; sts1 = read( local->Qbus_fp, &rb, sizeof(rb)); re_data[0] = (unsigned short) rb.Data; } else { /* Ethernet I/O, Get data from current address */ re_data[0] = bfbeth_get_data(r_local, (pwr_tUInt16) (local->Address + 4*i), &sts1); /* Yes, we want to read this address the next time aswell */ bfbeth_set_read_req(r_local, (pwr_tUInt16) (local->Address + 4*i)); } if ( numofword == 2) { if (r_local->Qbus_fp != 0 && r_local->s == 0) { /* Read from local Q-bus */ rb.Address += 2; sts2 = read( local->Qbus_fp, &rb, sizeof(rb)); re_data[1] = (unsigned short) rb.Data; } else { /* Ethernet I/O, Get data from current address */ re_data[1] = bfbeth_get_data(r_local, (pwr_tUInt16) (local->Address + 4*i + 2), &sts2); /* Yes, we want to read this address the next time aswell */ bfbeth_set_read_req(r_local, (pwr_tUInt16) (local->Address + 4*i + 2)); } } else sts2 = 0; if ( sts1 == -1 || sts2 == -1) { #if 0 if ( io_fatal_error) { /* Activate emergency break */ errh_Error( "Fatal read error, card '%s', IO i stopped", cp->Name); ctx->Node->EmergBreakTrue = 1; return IO__ERRDEVICE; } #endif /* Increase error count and check error limits */ time_GetTime( &now); if (op->ErrorCount > op->ErrorSoftLimit) { /* Ignore if some time has expired */ if (now.tv_sec - local->ErrTime.tv_sec < 600) op->ErrorCount++; } else op->ErrorCount++; local->ErrTime = now; if ( op->ErrorCount == op->ErrorSoftLimit) errh_Error( "IO Error soft limit reached on card '%s'", cp->Name); if ( op->ErrorCount >= op->ErrorHardLimit) { errh_Error( "IO Error hard limit reached on card '%s', IO stopped", cp->Name); ctx->Node->EmergBreakTrue = 1; return IO__ERRDEVICE; } continue; } } /* No faults detected calculate countervalue and store them */ if (numofword == 1) /* 16 bits counter */ { co16_data = re_data[0]; /* If this is the first lap we dont have any correct saved countvalues. Therefor we save the new value. */ if ( local->FirstScan[i]) local->OldValue[i] = co16_data; /* Store the counter values into RTDB */ *(pwr_tUInt32 *) cp->chanlist[i].vbp = co16_data; /* Test if an abs-value should be calculated and stored */ if ( op->COAbsFlag[i] == TRUE) { /* Calculate difference between two readings*/ diff = co16_data - local->OldValue[i]; local->OldValue[i] = co16_data; /* Store new value */ /* Check if the counter is passing zero or max, and calculate if it is counting up or down */ if (diff < MIN16) /* Up count over maxlimit */ newdiff = MAXCO16 + diff; else if (diff > MAX16) newdiff = diff - MAXCO16; else newdiff = diff; /* Store the counter abs-values into RTDB */ *(pwr_tUInt32 *) cp->chanlist[i].abs_vbp += newdiff; } } else if (numofword == 2) /* 24 bits counter */ { co24_data = *re_data_p; /* If this is the first lap we dont have any correct saved countvalues. Therefor we save the new value. */ if ( local->FirstScan[i]) local->OldValue[i] = co24_data; /* Store the counter values into RTDB */ *(pwr_tUInt32 *) cp->chanlist[i].vbp = co24_data; /* Test if an abs-value should be calaulated and stored */ if ( op->COAbsFlag[i] == TRUE) { /* Calculate difference between two readings */ diff = co24_data - local->OldValue[i]; local->OldValue[i] = co24_data; /* Store new value */ /* Check if the counter is passing zero or max, and calculate if it is counting up or down */ if (diff < MIN24) /* Up count over maxlimit */ newdiff = MAXCO24 + diff; else if (diff > MAX24 ) newdiff = diff - MAXCO24 ; else newdiff = diff ; /* Store the counter abs-values into RTDB */ *(pwr_tUInt32 *) cp->chanlist[i].abs_vbp += newdiff; } } local->FirstScan[i] = 0; } return 1; }
/*----------------------------------------------------------------------------*\ \*----------------------------------------------------------------------------*/ static pwr_tStatus IoCardRead ( io_tCtx ctx, io_sAgent *ap, io_sRack *rp, io_sCard *cp ) { io_sLocal *local; io_sRackLocal *r_local = (io_sRackLocal *)(rp->Local); pwr_tInt16 data = 0; pwr_sClass_Ssab_BaseACard *op; pwr_sClass_Ssab_RemoteRack *rrp; int i; pwr_tFloat32 actvalue; io_sChannel *chanp; pwr_sClass_ChanAi *cop; pwr_sClass_Ai *sop; int sts; qbus_io_read rb; int bfb_error = 0; pwr_tTime now; local = (io_sLocal *) cp->Local; op = (pwr_sClass_Ssab_BaseACard *) cp->op; chanp = &cp->chanlist[0]; for ( i = 0; i < cp->ChanListSize; i++) { if ( !chanp->cop || !chanp->sop) { chanp++; continue; } cop = (pwr_sClass_ChanAi *) chanp->cop; sop = (pwr_sClass_Ai *) chanp->sop; if ( cop->CalculateNewCoef) AiRangeToCoef( chanp); if ( cop->ConversionOn) { if ( local->ScanCount[i] <= 1) { #if defined(OS_ELN) vaxc$establish(machfailread); #endif if (r_local->Qbus_fp != 0 && r_local->s == 0) { rb.Address = local->Address + 2*i; sts = read( local->Qbus_fp, &rb, sizeof(rb)); data = (unsigned short) rb.Data; } else { /* Ethernet I/O, Get data from current address */ data = bfbeth_get_data(r_local, (pwr_tUInt16) (local->Address + 2*i), &sts); /* Yes, we want to read this address the next time aswell */ bfbeth_set_read_req(r_local, (pwr_tUInt16) (local->Address + 2*i)); if (sts == -1) { /* Error handling for ethernet Qbus-I/O */ rrp = (pwr_sClass_Ssab_RemoteRack *) rp->op; if (bfb_error == 0) { op->ErrorCount++; bfb_error = 1; if ( op->ErrorCount == op->ErrorSoftLimit) errh_Error( "IO Error soft limit reached on card '%s'", cp->Name); if ( op->ErrorCount == op->ErrorHardLimit) errh_Error( "IO Error hard limit reached on card '%s', stall action %d", cp->Name, rrp->StallAction); if ( op->ErrorCount >= op->ErrorHardLimit && rrp->StallAction == pwr_eSsabStallAction_ResetInputs ) { data = 0; sts = 1; } if ( op->ErrorCount >= op->ErrorHardLimit && rrp->StallAction == pwr_eSsabStallAction_EmergencyBreak ) { ctx->Node->EmergBreakTrue = 1; return IO__ERRDEVICE; } } if (sts == -1) { chanp++; continue; } } else { op->ErrorCount = 0; } } if ( sts == -1) /* Error handling for local Qbus-I/O */ { #if 0 /* Exceptionhandler was called */ if ( io_fatal_error) { /* Activate emergency break */ errh_Error( "Fatal read error, card '%s', IO is stopped", cp->Name); ctx->Node->EmergBreakTrue = 1; return IO__ERRDEVICE; } #endif /* Increase error count and check error limits */ time_GetTime( &now); if (op->ErrorCount > op->ErrorSoftLimit) { /* Ignore if some time has expired */ if (now.tv_sec - local->ErrTime.tv_sec < 600) op->ErrorCount++; } else op->ErrorCount++; local->ErrTime = now; if ( op->ErrorCount == op->ErrorSoftLimit) errh_Error( "IO Error soft limit reached on card '%s'", cp->Name); if ( op->ErrorCount >= op->ErrorHardLimit) { errh_Error( "IO Error hard limit reached on card '%s', IO stopped", cp->Name); ctx->Node->EmergBreakTrue = 1; return IO__ERRDEVICE; } chanp++; continue; } /* Convert rawvalue to sigvalue and actualvalue */ sop->RawValue = data; sop->SigValue = data * cop->SigValPolyCoef1 + cop->SigValPolyCoef0; switch ( chanp->ChanClass) { case pwr_cClass_ChanAi: io_ConvertAi( cop, data, &actvalue); break; case pwr_cClass_ChanAit: io_ConvertAit( (pwr_sClass_ChanAit *) cop, data, &actvalue); break; } /* 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; local->ScanCount[i] = cop->ScanInterval + 1; } local->ScanCount[i]--; } chanp++; } return 1; }