00001 #include "roc/AbbDevice.h"
00002
00003 #include <iostream>
00004 #include <fstream>
00005 #include <stdio.h>
00006
00007 #include "dabc/Manager.h"
00008 #include "dabc/Port.h"
00009 #include "dabc/Command.h"
00010 #include "dabc/CommandsSet.h"
00011
00012 #include "base/Url.h"
00013
00014 #include "roc/defines_roc.h"
00015 #include "roc/defines_optic.h"
00016 #include "roc/Commands.h"
00017 #include "roc/Board.h"
00018
00019 #include "roc/AbbTransport.h"
00020 #include "roc/AbbBoard.h"
00021
00022 #include "ABBdaemon.h"
00023
00024 const char* roc::OpticPathPar = "OpticPath";
00025
00026 enum { PUT_BIT = 0x80000000 };
00027
00028 roc::AbbDevice::AbbDevice(const char* name, const char* thrdname, dabc::Command cmd) :
00029 dabc::Device(name),
00030 fContext(),
00031 fTransport(0),
00032 fDaqRunning(false),
00033 fPathes(),
00034 fUseDlmForStartStopDaq(true)
00035 {
00036 if (!dabc::mgr()->MakeThreadFor(this, thrdname)) return;
00037
00038
00039 fUseDlmForStartStopDaq = Cfg(roc::xmlUseDLM, cmd).AsBool(false);
00040
00041 fContext.CreateDaemon();
00042
00043 DOUT2(("Create ABB device name:%s useDLM:%s", GetName(), DBOOL(fUseDlmForStartStopDaq)));
00044 }
00045
00046 roc::AbbDevice::~AbbDevice()
00047 {
00048 DOUT2(("Destroy ABB device %s", GetName()));
00049 }
00050
00051 void roc::AbbDevice::ObjectCleanup()
00052 {
00053 if (fTransport) {
00054 fTransport->fDevice = 0;
00055 fTransport = 0;
00056 }
00057
00058 dabc::Device::ObjectCleanup();
00059 }
00060
00061 const char* roc::AbbDevice::ClassName() const
00062 {
00063 return roc::typeAbbDevice;
00064 }
00065
00066 unsigned roc::AbbDevice::GetOpticPath(const char* abburl)
00067 {
00068
00069
00070
00071
00072
00073
00074 base::Url url(abburl);
00075 if (!url.GetProtocol().empty() && (url.GetProtocol()!="optic")) return UndefinedOpticPath;
00076
00077
00078
00079 if ((url.GetHostName().length()<4) || (url.GetHostName().length()>5)) return UndefinedOpticPath;
00080
00081 if (url.GetHostName().find("abb", 0) != 0) return UndefinedOpticPath;
00082
00083 unsigned path = 0;
00084
00085 switch (url.GetHostName()[3]) {
00086 case '0': path = 0; break;
00087 case '1': path = 0x20; break;
00088 default: return UndefinedOpticPath;
00089 }
00090
00091 if (url.GetHostName().length() == 5)
00092 switch (url.GetHostName()[4]) {
00093 case '0': path = path | 0; break;
00094 case '1': path = path | 1; break;
00095 case '2': path = path | 2; break;
00096 case '3': path = path | 3; break;
00097 default: return UndefinedOpticPath;
00098 }
00099
00100 return path;
00101 }
00102
00103 unsigned roc::AbbDevice::GetOpticRetPath(unsigned path)
00104 {
00105 if (path==UndefinedOpticPath) return 0x8000;
00106
00107 return path & 0x20 ? 0x8020 : 0x8000;
00108 }
00109
00110
00111 int roc::AbbDevice::ExecuteCommand(dabc::Command cmd)
00112 {
00113 uint32_t path = cmd.GetUInt(OpticPathPar, 0x0);
00114 uint32_t retpath = GetOpticRetPath(path);
00115 uint32_t hwtyp = cmd.GetUInt("HwTyp", 0x0);
00116
00117 bool isnewnx = (hwtyp >> 16) == base::kind_newNX;
00118
00119 uint32_t res = 0;
00120
00121
00122
00123 if (cmd.IsName(CmdPut::CmdName())) {
00124 uint32_t addr = cmd.GetUInt(AddrPar, 0);
00125 uint32_t value = cmd.GetUInt(ValuePar, 0);
00126
00127 res = fContext.daemon()->submitPut(path, retpath, addr, value);
00128
00129 DOUT2(("ABB::submitPut addr:%04x value:%04x res = %u", addr, value, res));
00130 cmd.SetUInt(ErrNoPar, res);
00131 return cmd_bool(res==0);
00132 } else
00133
00134 if (cmd.IsName(CmdGet::CmdName())) {
00135 uint32_t addr = cmd.GetUInt(AddrPar, 0);
00136 uint32_t value = 0;
00137
00138 res = fContext.daemon()->submitGet(path, retpath, addr, &value);
00139
00140 DOUT2(("ABB::submitGet addr:%04x value:%04x res = %u", addr, value, res));
00141
00142 cmd.SetUInt(ValuePar, value);
00143 cmd.SetUInt(ErrNoPar, res);
00144
00145 return (res==0) ? dabc::cmd_true : dabc::cmd_false;
00146
00147 } else
00148 if (cmd.IsName(CmdDLM::CmdName())) {
00149 uint32_t addr = cmd.GetUInt(AddrPar, 0);
00150
00151 res = fContext.daemon()->submitPutDLM(addr);
00152
00153 cmd.SetUInt(ErrNoPar, res);
00154 return (res==0) ? dabc::cmd_true : dabc::cmd_false;
00155
00156 } else
00157 if (cmd.IsName(CmdNOper::CmdName())) {
00158
00159 base::OperList* lst = (base::OperList*) cmd.GetPtr(OperListPar, 0);
00160
00161 lst->setErrorOper(-1);
00162 lst->setErrorCode(0);
00163
00164 DOUT2(("Start CmdNOper %d", lst->number()));
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220 uint32_t *addrs = new uint32_t[lst->number()];
00221 uint32_t *values = new uint32_t[lst->number()];
00222 uint32_t *retvals = new uint32_t[lst->number()];
00223 for (int n=0;n<lst->number();n++) {
00224 addrs[n] = lst->oper(n).addr;
00225 values[n] = lst->oper(n).value;
00226 retvals[n] = 0;
00227 if (lst->oper(n).isput) addrs[n] = addrs[n] | PUT_BIT;
00228 }
00229
00230 try {
00231 res = fContext.daemon()->submitNOper(path, retpath, lst->number(), addrs, values, retvals);
00232
00233 for (int n=0;n<lst->number();n++) {
00234 if (!lst->oper(n).isput)
00235 lst->oper(n).value = values[n];
00236 }
00237
00238 } catch (abbdaemon::ABBexception e) {
00239 EOUT(("Problem with NOper %s", e.what()));
00240 res = base::Board::operErrBuild(roc::Board::kHostError, 0);
00241 for (int n=0;n<lst->number();n++)
00242 EOUT(("Oper %d retval = %u\n", n, retvals[n]));
00243
00244 lst->setErrorOper(1);
00245 lst->setErrorCode(1);
00246 }
00247
00248 for (int n=0;n<lst->number();n++)
00249 DOUT2(("Oper %d retval = %08x\n", n, retvals[n]));
00250
00251 delete[] addrs;
00252 delete[] values;
00253 delete[] retvals;
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 DOUT2(("Did CmdNOper %d", lst->number()));
00271
00272
00273
00274
00275
00276 cmd.SetUInt(ErrNoPar, res);
00277 return (res==0) ? dabc::cmd_true : dabc::cmd_false;
00278 } else
00279
00280 if (cmd.IsName("StartABBTransport")) {
00281 fDaqRunning = true;
00282
00283 fContext.daemon()->submitReset();
00284
00285 DOUT2(("roc::AbbDevice::StartABBTransport path = 0x%02x transport %p", path, fTransport));
00286
00287 if (isnewnx) {
00288 DOUT0(("!!Start DAQ for new NX readout!!"));
00289
00290 uint32_t addrs[3], values[3], retvals[3];
00291
00292 addrs[0] = ROC_NX_FIFO_RESET | PUT_BIT; values[0] = 1;
00293 addrs[1] = ROC_NX_FIFO_RESET | PUT_BIT; values[1] = 0;
00294 addrs[2] = ROC_OPTICS_START_DAQ | PUT_BIT; values[1] = 0;
00295
00296 try {
00297 res = fContext.daemon()->submitNOper(path, retpath, 3, addrs, values, retvals);
00298
00299 } catch (abbdaemon::ABBexception e) {
00300 EOUT(("Problem with StartDAQ NOper %s", e.what()));
00301 res = base::Board::operErrBuild(roc::Board::kHostError, 0);
00302 }
00303
00304 } else {
00305
00306 if (path == UndefinedOpticPath) {
00307
00308 if (fUseDlmForStartStopDaq || (fPathes.size()==0)) {
00309 DOUT0(("Issue DLM 8"));
00310 res = fContext.daemon()->submitPutDLM(8);
00311 } else {
00312 DOUT0(("Replace DLM 8 with PUTs num %u", fPathes.size()));
00313 for (unsigned n=0;n<fPathes.size();n++)
00314 if (res==0)
00315 res = fContext.daemon()->submitPut(fPathes[n], GetOpticRetPath(fPathes[n]), ROC_CMD_LST_NR, 0);
00316 }
00317 } else {
00318 res = fContext.daemon()->submitPut(path, retpath, ROC_CMD_LST_NR, 0);
00319 }
00320
00321 DOUT0(("Start DAQ res = %u", res));
00322 }
00323
00324 return (res==0) ? dabc::cmd_true : dabc::cmd_false;
00325 } else
00326
00327 if (cmd.IsName("SuspendBoardDaq")) {
00328
00329 if (isnewnx) {
00330 DOUT0(("!!Suspend DAQ for new NX readout!!"));
00331 res = fContext.daemon()->submitPut(path, retpath, ROC_OPTICS_STOP_DAQ, 0);
00332
00333 } else {
00334 res = fContext.daemon()->submitPut(path, retpath, ROC_CMD_LST_NR, 1);
00335 }
00336 return (res==0) ? dabc::cmd_true : dabc::cmd_false;
00337 } else
00338
00339 if (cmd.IsName("StopABBTransport")) {
00340 fDaqRunning = false;
00341
00342 DOUT2(("StopABBTransport 0x%02x", path));
00343
00344 if (isnewnx) {
00345 DOUT0(("!!Stop DAQ for new NX readout!!"));
00346
00347 res = fContext.daemon()->submitPut(path, retpath, ROC_OPTICS_STOP_DAQ, 0);
00348
00349 } else {
00350
00351 if (path == UndefinedOpticPath) {
00352
00353 if (fUseDlmForStartStopDaq || (fPathes.size()==0)) {
00354 DOUT0(("Issue DLM 9"));
00355 res = fContext.daemon()->submitPutDLM(9);
00356 } else {
00357 DOUT0(("Replace DLM 9 with PUTs num %u", fPathes.size()));
00358 for (unsigned n=0;n<fPathes.size();n++)
00359 if (res==0)
00360 res = fContext.daemon()->submitPut(fPathes[n], GetOpticRetPath(fPathes[n]), ROC_CMD_LST_NR, 1);
00361 }
00362
00363 } else {
00364 res = fContext.daemon()->submitPut(path, retpath, ROC_CMD_LST_NR, 1);
00365 }
00366 }
00367
00368 return (res==0) ? dabc::cmd_true : dabc::cmd_false;
00369 } else
00370
00371 if (cmd.IsName("SetFlushTimeout")) {
00372 if (fTransport==0) {
00373 EOUT(("No ABB transports - cannot setup flush timeout"));
00374 return dabc::cmd_false;
00375 }
00376
00377 fTransport->Submit(cmd);
00378
00379 return dabc::cmd_postponed;
00380 } else
00381
00382 if (cmd.IsName("AddExtraBoard")) {
00383
00384 unsigned path = GetOpticPath(cmd.GetStr(roc::xmlBoardAddr, "abb0"));
00385
00386 uint32_t rocid(0), res(1);
00387
00388 if (path != UndefinedOpticPath) {
00389 fPathes.push_back(path);
00390 res = fContext.daemon()->submitGet(path, GetOpticRetPath(path), ROC_ROCID, &rocid);
00391 if (res!=0) EOUT(("Cannot get ROCID from specified ROC path %u", path));
00392 }
00393
00394 return res!=0 ? dabc::cmd_false : rocid + 256;
00395 } else
00396
00397 if (cmd.IsName(CmdGetBoardPtr::CmdName())) {
00398
00399 unsigned path = GetOpticPath(cmd.GetStr(roc::xmlBoardAddr, "abb0"));
00400
00401 if (path==UndefinedOpticPath) return dabc::cmd_false;
00402
00403 roc::AbbBoard* brd = new roc::AbbBoard(this, path, base::roleControl);
00404 if (!brd->initAbbBoard()) { delete brd; return dabc::cmd_false; }
00405
00406 cmd.SetPtr(CmdGetBoardPtr::Board(), brd);
00407
00408 return dabc::cmd_true;
00409 } else
00410
00411 if (cmd.IsName(CmdReturnBoardPtr::CmdName())) {
00412 roc::AbbBoard* brd = (roc::AbbBoard*) cmd.GetPtr(CmdReturnBoardPtr::Board());
00413 if (brd!=0) delete brd;
00414 return dabc::cmd_true;
00415 }
00416
00417 return dabc::Device::ExecuteCommand(cmd);
00418 }
00419
00420 dabc::Transport* roc::AbbDevice::CreateTransport(dabc::Command cmd, dabc::Reference port)
00421 {
00422 if (fContext.daemon() == 0) return 0;
00423
00424 if (fTransport!=0) {
00425 EOUT(("There are transports already created !!!!"));
00426 return 0;
00427 }
00428
00429 std::string spath = cmd.GetStdStr(roc::xmlBoardAddr, "abb0");
00430 unsigned path = GetOpticPath(spath.c_str());
00431
00432 uint32_t brdid(0), hwtyp(0);
00433
00434 DOUT2(("roc::AbbDevice::CreateTransport path 0x%02x", path));
00435
00436 if (path != UndefinedOpticPath) {
00437
00438 fPathes.push_back(path);
00439
00440 uint32_t res = fContext.daemon()->submitGet(path, GetOpticRetPath(path), base::addr_BoardId, &brdid);
00441 if (res!=0) { EOUT(("Cannot get board ID from path %s", spath.c_str())); return 0; }
00442
00443 res = fContext.daemon()->submitGet(path, GetOpticRetPath(path), base::addr_HardwareType, &hwtyp);
00444 if (res!=0) { EOUT(("Cannot get hardware type from path %s", spath.c_str())); return 0; }
00445
00446 DOUT2(("roc::AbbDevice::CreateTransport brdid %u hwtyp 0x%08x", (unsigned) brdid, (unsigned) hwtyp));
00447
00448 } else
00449 DOUT2(("Create transport with undefined path"));
00450
00451 fTransport = new AbbTransport(this, port, path, brdid, hwtyp, cmd);
00452
00453 return fTransport;
00454 }