/*----------------------------------------------------------------------------*\ \*----------------------------------------------------------------------------*/ static pwr_tStatus IoCardWrite ( 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_BaseDoCard *op; pwr_tUInt16 invmask; pwr_tUInt16 testmask; pwr_tUInt16 testvalue; int i; qbus_io_write wb; int sts; pwr_tTime now; int bfb_error = 0; pwr_sClass_Ssab_RemoteRack *rrp; local = (io_sLocal *) cp->Local; op = (pwr_sClass_Ssab_BaseDoCard *) cp->op; #if defined(OS_ELN) vaxc$establish(machfailwrite); #endif for ( i = 0; i < 2; i++) { if ( i == 1 && op->MaxNoOfChannels <= 16) break; if ( ctx->Node->EmergBreakTrue && ctx->Node->EmergBreakSelect == FIXOUT) { if ( i == 0) data = op->FixedOutValue1; else data = op->FixedOutValue2; } else io_DoPackWord( cp, &data, i); if ( i == 0) { testmask = op->TestMask1; invmask = op->InvMask1; } else { testmask = op->TestMask2; invmask = op->InvMask2; if ( op->MaxNoOfChannels == 16) break; } /* Invert */ data = data ^ invmask; /* Filter Po signals */ if ( local->Filter[i].Found) io_PoFilter( local->Filter[i].sop, &data, local->Filter[i].Data); /* Testvalues */ if ( testmask) { if ( i == 0) testvalue = op->TestValue1; else testvalue = op->TestValue2; data = (data & ~ testmask) | (testmask & testvalue); } if (r_local->Qbus_fp != 0 && r_local->s == 0) { /* Write to local Q-bus */ wb.Data = data; wb.Address = local->Address[i]; sts = write( local->Qbus_fp, &wb, sizeof(wb)); } else { /* Ethernet I/O, Request a write to current address */ sts = 0; if ( !local->FirstScan) bfbeth_get_write_status(r_local, (pwr_tUInt16) local->Address[i], &sts); bfbeth_set_write_req(r_local, (pwr_tUInt16) local->Address[i], data); 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 ) { sts = 1; } if ( op->ErrorCount >= op->ErrorHardLimit && rrp->StallAction == pwr_eSsabStallAction_EmergencyBreak ) { ctx->Node->EmergBreakTrue = 1; return IO__ERRDEVICE; } } if (sts == -1) continue; } else if ( sts == 1) { op->ErrorCount = 0; } } /* Error handling for local Qbus-I/O */ if ( sts == -1) { /* 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; } } if ( local->FirstScan) local->FirstScan = 0; return 1; }
/*----------------------------------------------------------------------------*\ \*----------------------------------------------------------------------------*/ static pwr_tStatus IoCardWrite ( io_tCtx ctx, io_sAgent *ap, io_sRack *rp, io_sCard *cp ) { io_sLocal *local; io_sRackLocal *r_local = (io_sRackLocal *)(rp->Local); pwr_sClass_Ssab_BaseACard *op; int i; io_sChannel *chanp; pwr_sClass_ChanAo *cop; pwr_sClass_Ao *sop; pwr_tFloat32 value; int fixout; pwr_tUInt16 data; pwr_tFloat32 rawvalue; qbus_io_write wb; int sts; int bfb_error = 0; pwr_sClass_Ssab_RemoteRack *rrp; int remote; local = (io_sLocal *) cp->Local; op = (pwr_sClass_Ssab_BaseACard *) cp->op; fixout = ctx->Node->EmergBreakTrue && ctx->Node->EmergBreakSelect == FIXOUT; remote = !r_local->Qbus_fp && r_local->s; chanp = &cp->chanlist[0]; for ( i = 0; i < cp->ChanListSize; i++) { if ( !chanp->cop || !chanp->sop) { chanp++; continue; } cop = (pwr_sClass_ChanAo *) chanp->cop; sop = (pwr_sClass_Ao *) chanp->sop; /* Error handling for remote rack */ if ( remote) { sts = 0; if ( local->CheckWrite[i]) { local->CheckWrite[i] = 0; bfbeth_get_write_status(r_local, (pwr_tUInt16) (local->Address + 2*i), &sts); 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); ctx->IOHandler->CardErrorSoftLimit = 1; ctx->IOHandler->ErrorSoftLimitObject = cdh_ObjidToAref( cp->Objid); } if ( op->ErrorCount == op->ErrorHardLimit) { errh_Error( "IO Error hard limit reached on card '%s', stall action %d", cp->Name, rrp->StallAction); ctx->IOHandler->CardErrorHardLimit = 1; ctx->IOHandler->ErrorHardLimitObject = cdh_ObjidToAref( cp->Objid); } if ( op->ErrorCount >= op->ErrorHardLimit && rrp->StallAction == pwr_eSsabStallAction_ResetInputs ) { sts = 1; } if ( op->ErrorCount >= op->ErrorHardLimit && rrp->StallAction == pwr_eSsabStallAction_EmergencyBreak ) { ctx->Node->EmergBreakTrue = 1; return IO__ERRDEVICE; } } } } } /* Convert and write */ if ( *(pwr_tFloat32 *)chanp->vbp != local->OldValue[i] || local->WriteFirst > 0 || cop->CalculateNewCoef || fixout || cop->TestOn || local->OldTestOn[i] != cop->TestOn) { if ( fixout) value = cop->FixedOutValue; else if ( cop->TestOn) value = cop->TestValue; else value = *(pwr_tFloat32 *) chanp->vbp; if ( cop->CalculateNewCoef) AoRangeToCoef( chanp); /* Convert to rawvalue */ if ( value > cop->ActValRangeHigh) value = cop->ActValRangeHigh; else if ( value < cop->ActValRangeLow) value = cop->ActValRangeLow; rawvalue = cop->OutPolyCoef1 * value + cop->OutPolyCoef0; if ( rawvalue > 0) sop->RawValue = rawvalue + 0.5; else sop->RawValue = rawvalue - 0.5; data = sop->RawValue; if ( !remote) { wb.Data = data; wb.Address = local->Address + 2*i; 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 + 2*i), data); local->CheckWrite[i] = 1; if ( sts == 1) { op->ErrorCount = 0; local->OldValue[i] = value; local->OldTestOn[i] = cop->TestOn; } chanp++; continue; } /* Error handling for local rack */ if ( sts == -1) { /* Exceptionhandler was called */ #if 0 if ( io_fatal_error) { /* Activate emergency break */ errh_Error( "Fatal write error, card '%s', IO is stopped", cp->Name); ctx->Node->EmergBreakTrue = 1; return IO__ERRDEVICE; } #endif /* Increase error count and check error limits */ op->ErrorCount++; if ( op->ErrorCount == op->ErrorSoftLimit) { errh_Error( "IO Error soft limit reached on card '%s'", cp->Name); ctx->IOHandler->CardErrorSoftLimit = 1; ctx->IOHandler->ErrorSoftLimitObject = cdh_ObjidToAref( cp->Objid); } if ( op->ErrorCount >= op->ErrorHardLimit) { errh_Error( "IO Error hard limit reached on card '%s', IO stopped", cp->Name); ctx->Node->EmergBreakTrue = 1; ctx->IOHandler->CardErrorHardLimit = 1; ctx->IOHandler->ErrorHardLimitObject = cdh_ObjidToAref( cp->Objid); return IO__ERRDEVICE; } chanp++; continue; } else local->OldValue[i] = value; } local->OldTestOn[i] = cop->TestOn; chanp++; } if ( local->WriteFirst) local->WriteFirst--; if ( local->FirstScan) local->FirstScan = 0; /* Fix for qbus errors */ local->ErrScanCnt++; if ( local->ErrScanCnt >= local->ErrReset) { local->ErrScanCnt = 0; if ( op->ErrorCount > op->ErrorSoftLimit) op->ErrorCount--; } return 1; }