00001 #include "roc/UdpBoard.h"
00002
00003 #include <fstream>
00004 #include <arpa/inet.h>
00005 #include <string.h>
00006
00007 #include "roc/defines_roc.h"
00008 #include "roc/defines_udp.h"
00009
00010 roc::UdpBoard::UdpBoard() :
00011 roc::Board()
00012 {
00013
00014 fRunningUpload = -1;
00015 fUploadChecksum = 0;
00016
00017
00018
00019 addRegAddrMapping("ROC_ETH_HWV", ROC_ETH_HWV);
00020 addRegAddrMapping("ROC_ETH_SWV", ROC_ETH_SWV);
00021 addRegAddrMapping("ROC_ETH_OCM", ROC_ETH_OCM);
00022 addRegAddrMapping("ROC_ETH_CFG_READ", ROC_ETH_CFG_READ);
00023 addRegAddrMapping("ROC_ETH_CFG_WRITE", ROC_ETH_CFG_WRITE);
00024 addRegAddrMapping("ROC_ETH_FLASH_KIBFILE_FROM_DDR", ROC_ETH_FLASH_KIBFILE_FROM_DDR);
00025 addRegAddrMapping("ROC_ETH_SWITCHCONSOLE", ROC_ETH_SWITCHCONSOLE);
00026 addRegAddrMapping("ROC_ETH_START_DAQ", ROC_ETH_START_DAQ);
00027 addRegAddrMapping("ROC_ETH_STOP_DAQ", ROC_ETH_STOP_DAQ);
00028 addRegAddrMapping("ROC_ETH_IP_ADDRESS", ROC_ETH_IP_ADDRESS);
00029 addRegAddrMapping("ROC_ETH_NETMASK", ROC_ETH_NETMASK);
00030 addRegAddrMapping("ROC_ETH_MAC_ADDRESS_UPPER", ROC_ETH_MAC_ADDRESS_UPPER);
00031 addRegAddrMapping("ROC_ETH_MAC_ADDRESS_LOWER", ROC_ETH_MAC_ADDRESS_LOWER);
00032 addRegAddrMapping("ROC_ETH_MASTER_LOGIN", ROC_ETH_MASTER_LOGIN);
00033 addRegAddrMapping("ROC_ETH_MASTER_DATAPORT", ROC_ETH_MASTER_DATAPORT);
00034 addRegAddrMapping("ROC_ETH_MASTER_CTRLPORT", ROC_ETH_MASTER_CTRLPORT);
00035 addRegAddrMapping("ROC_ETH_BUFFER_FLUSH_TIMER", ROC_ETH_BUFFER_FLUSH_TIMER);
00036 addRegAddrMapping("ROC_ETH_MASTER_LOGOUT", ROC_ETH_MASTER_LOGOUT);
00037 addRegAddrMapping("ROC_ETH_MASTER_IP", ROC_ETH_MASTER_IP);
00038 addRegAddrMapping("ROC_ETH_RESTART_NETWORK", ROC_ETH_RESTART_NETWORK);
00039 addRegAddrMapping("ROC_ETH_CONSOLE_OUTPUT", ROC_ETH_CONSOLE_OUTPUT);
00040 addRegAddrMapping("ROC_ETH_LOST_ETHER_FRAMES", ROC_ETH_LOST_ETHER_FRAMES);
00041 addRegAddrMapping("ROC_ETH_UKNOWN_ETHER_FRAMES", ROC_ETH_UKNOWN_ETHER_FRAMES);
00042 addRegAddrMapping("ROC_ETH_SUSPEND_DAQ", ROC_ETH_SUSPEND_DAQ);
00043 addRegAddrMapping("ROC_ETH_FLASH_CLEAR_FILEBUFFER", ROC_ETH_FLASH_CLEAR_FILEBUFFER);
00044 addRegAddrMapping("ROC_ETH_CHECK_BITFILEBUFFER", ROC_ETH_CHECK_BITFILEBUFFER);
00045 addRegAddrMapping("ROC_ETH_CHECK_BITFILEFLASH0", ROC_ETH_CHECK_BITFILEFLASH0);
00046 addRegAddrMapping("ROC_ETH_CHECK_BITFILEFLASH1", ROC_ETH_CHECK_BITFILEFLASH1);
00047 addRegAddrMapping("ROC_ETH_CHECK_FILEBUFFER", ROC_ETH_CHECK_FILEBUFFER);
00048 addRegAddrMapping("ROC_ETH_TEMAC_PRINT", ROC_ETH_TEMAC_PRINT);
00049 addRegAddrMapping("ROC_ETH_TEMAC_REG0", ROC_ETH_TEMAC_REG0);
00050 addRegAddrMapping("ROC_ETH_OVERWRITE_SD_FILE", ROC_ETH_OVERWRITE_SD_FILE);
00051 addRegAddrMapping("ROC_ETH_CONSOLE_CMD", ROC_ETH_CONSOLE_CMD);
00052 addRegAddrMapping("ROC_ETH_CTRLPORT", ROC_ETH_CTRLPORT);
00053 addRegAddrMapping("ROC_ETH_DATAPORT", ROC_ETH_DATAPORT);
00054 addRegAddrMapping("ROC_ETH_BURST_LOOPCNT", ROC_ETH_BURST_LOOPCNT);
00055 addRegAddrMapping("ROC_ETH_OCM_LOOPCNT", ROC_ETH_OCM_LOOPCNT);
00056 addRegAddrMapping("ROC_ETH_STATBLOCK", ROC_ETH_STATBLOCK);
00057 addRegAddrMapping("ROC_ETH_DEBUGMSG", ROC_ETH_DEBUGMSG);
00058 addRegAddrMapping("ROC_ETH_HIGHWATER", ROC_ETH_HIGHWATER);
00059 addRegAddrMapping("ROC_ETH_LOWWATER", ROC_ETH_LOWWATER);
00060 addRegAddrMapping("ROC_ETH_NUMBUFALLOC", ROC_ETH_NUMBUFALLOC);
00061 }
00062
00063 roc::UdpBoard::~UdpBoard()
00064 {
00065 }
00066
00067 const char* roc::xmlTransferWindow = "RocTransferWindow";
00068
00069
00070
00071
00072 uint32_t roc::UdpBoard::getRocBackendVersion()
00073 {
00074 uint32_t val;
00075 get(ROC_ETH_HWV, val);
00076 return val;
00077 }
00078
00079
00080
00081 uint32_t roc::UdpBoard::getPowerPCVersion()
00082 {
00083 uint32_t val;
00084 get(ROC_ETH_SWV, val);
00085 return val;
00086 }
00087
00088
00089
00090
00091 int roc::UdpBoard::invokeDLM(unsigned num, double tmout)
00092 {
00093 return put(ROC_ETH_DLM, num, tmout);
00094 }
00095
00096
00097
00098 void roc::UdpBoard::BURST(uint32_t val)
00099 {
00100 put(ROC_ETH_OCM, val);
00101 }
00102
00103
00104
00105 bool roc::UdpBoard::getRocLowHighWater(int& lowWater, int& highWater)
00106 {
00107 uint32_t low, high;
00108 if (get(ROC_ETH_LOWWATER, low) != 0) return false;
00109 if (get(ROC_ETH_HIGHWATER, high) != 0) return false;
00110
00111 double k = 1024. / (UDP_PAYLOAD_OFFSET + MAX_UDP_PAYLOAD);
00112
00113 lowWater = int(low / k);
00114 highWater = int(high / k);
00115
00116 if (low/k - lowWater >= 0.5) lowWater++;
00117 if (high/k - highWater >= 0.5) highWater++;
00118
00119 return true;
00120 }
00121
00122
00123
00124 bool roc::UdpBoard::setRocLowHighWater(int lowWater, int highWater)
00125 {
00126 double k = 1024. / (UDP_PAYLOAD_OFFSET + MAX_UDP_PAYLOAD);
00127
00128 uint32_t low = uint32_t(lowWater * k);
00129 uint32_t high = uint32_t(highWater * k);
00130
00131 if (lowWater*k - low >= 0.5) low++;
00132 if (highWater*k - high >= 0.5) high++;
00133
00134 if ((low < 10) || (high < low + 10)) {
00135 Debug(-1, "Wrong values for high/low water markers");
00136 return false;
00137 }
00138
00139
00140 uint32_t curr_high;
00141 if (get(ROC_ETH_HIGHWATER, curr_high) != 0) return false;
00142 if (low > curr_high)
00143 if (put(ROC_ETH_HIGHWATER, low+1) != 0) return false;
00144
00145 if (put(ROC_ETH_LOWWATER, low) !=0) return false;
00146 if (put(ROC_ETH_HIGHWATER, high) != 0) return false;
00147
00148 return true;
00149 }
00150
00151
00152
00153 bool roc::UdpBoard::getRocBufferFlushTimer(uint32_t& bufferFlushTimer)
00154 {
00155 if (get(ROC_ETH_BUFFER_FLUSH_TIMER, bufferFlushTimer) != 0) return false;
00156 return true;
00157 }
00158
00159
00160
00161 bool roc::UdpBoard::setRocBufferFlushTimer(uint32_t bufferFlushTimer)
00162 {
00163 if (put(ROC_ETH_BUFFER_FLUSH_TIMER, bufferFlushTimer) != 0) return false;
00164 return true;
00165 }
00166
00167
00168
00169 void roc::UdpBoard::setConsoleOutput(bool terminal, bool network)
00170 {
00171 put(ROC_ETH_CONSOLE_OUTPUT, (terminal ? 1 : 0) | (network ? 2 : 0));
00172 }
00173
00174
00175
00176 void roc::UdpBoard::switchToConsole()
00177 {
00178 put(ROC_ETH_SWITCHCONSOLE, 1);
00179 }
00180
00181
00182
00183 int roc::UdpBoard::parseBitfileHeader(char* pBuffer, unsigned int nLen)
00184 {
00185 char* binBuffer;
00186
00187 if (nLen < 16) {
00188 Debug(-1, "parseBitfileHeader: Invalid filesize");
00189 return -1;
00190 }
00191
00192 if (*((unsigned short*) pBuffer) == 0x0900 && *((unsigned int*) (pBuffer + 2)) == 0xF00FF00F && *((unsigned int*) (pBuffer + 6)) == 0xF00FF00F) {
00193 Debug(1, "parseBitfileHeader: Bitfile found, skipping header...");
00194 if (*((unsigned int*) (pBuffer + 10)) != 0x61010000)
00195 {
00196 Debug(-1, "parseBitfileHeader: Corrupt file");
00197 return -1;
00198 }
00199
00200 unsigned int tmpLen = ntohs(*((unsigned short*) (pBuffer + 14)));
00201 unsigned int tmpPos = 13;
00202
00203 for (int i = 0;i < 4;i++)
00204 {
00205 if (nLen < tmpPos + 5 + tmpLen)
00206 {
00207 Debug(-1, "parseBitfileHeader: Invalid filesize");
00208 return -1;
00209 }
00210
00211 tmpPos += 3 + tmpLen;
00212 if (*((unsigned char*) (pBuffer + tmpPos)) != 0x62 + i) {
00213 Debug(-1, "parseBitfileHeader: Corrupt Bitfile");
00214 return -1;
00215 }
00216 tmpLen = ntohs(*((unsigned short*) (pBuffer + tmpPos + 1)));
00217 }
00218
00219 binBuffer = pBuffer + tmpPos + 5;
00220 } else {
00221 Debug(-1, "parseBitfileHeader: No Bitfile header found");
00222 binBuffer = pBuffer;
00223 }
00224
00225 if (*((unsigned int*) (binBuffer)) != 0xFFFFFFFF || *((unsigned int*) (binBuffer + 4)) != 0x665599AA) {
00226 Debug(-1, "parseBitfileHeader: Corrupt Binfile");
00227 return -1;
00228 }
00229 Debug(1, "parseBitfileHeader: Binfile checked");
00230
00231 return binBuffer - pBuffer -1;
00232 }
00233
00234
00235
00236 uint8_t roc::UdpBoard::calcBinXOR(const char* filename)
00237 {
00238 char* bitfileBuffer = new char[SC_BITFILE_BUFFER_SIZE];
00239 unsigned int size=0;
00240 int i = 0;
00241
00242 Debug(0, "Loading bitfile %s", filename);
00243
00244 std::ifstream bitfile;
00245 bitfile.open(filename, std::ios_base::in);
00246 if(!bitfile) {
00247 Debug(-1, "calcBinXOR: Cannot open file: %s", filename);
00248 return 0;
00249 }
00250
00251 uint8_t XORCheckSum = 0;
00252
00253 while(!bitfile.eof())
00254 {
00255 bitfile.read(bitfileBuffer + size++, 1);
00256 }
00257 size--;
00258
00259 int nBinPos = parseBitfileHeader(bitfileBuffer, size);
00260 if (nBinPos == -1)
00261 Debug(-1, "calcBinXOR: File does not seem to be a bit or bin file");
00262
00263 Debug(0, "Bitfilesize: %u + 512 bytes for the KIB header minus %d bytes for removed bitfile header", size, nBinPos);
00264
00265 int bytes = 0;
00266 for(i = 0; i < 6;i++)
00267 {
00268 XORCheckSum ^= (uint8_t)bitfileBuffer[nBinPos + i];
00269 bytes++;
00270 }
00271 Debug(0, "check started at %d", nBinPos);
00272 Debug(0, "XOR is %u bytes checkes %d", XORCheckSum, bytes);
00273
00274 delete [] bitfileBuffer;
00275
00276 return XORCheckSum;
00277 }
00278
00279
00280
00281 bool roc::UdpBoard::sendConsoleCommand(const char* cmd)
00282 {
00283 unsigned length = cmd ? strlen(cmd) + 1 : 0;
00284
00285 if ((length<2) || (length > sizeof(UdpMessageFull) - sizeof(UdpMessage))) return false;
00286
00287 return rawPut(ROC_ETH_CONSOLE_CMD, length, cmd) == 0;
00288 }
00289
00290 bool roc::UdpBoard::saveConfig(const char* filename)
00291 {
00292 uint32_t len = filename ? strlen(filename) + 1 : 0;
00293
00294 Debug(0, "Save config file %s on ROC",filename ? filename : "");
00295
00296 return rawPut(ROC_ETH_CFG_WRITE, len, filename, 10.) == 0;
00297 }
00298
00299 bool roc::UdpBoard::loadConfig(const char* filename)
00300 {
00301 uint32_t len = filename ? strlen(filename) + 1 : 0;
00302
00303 Debug(0, "Load config file %s on ROC",filename ? filename : "");
00304
00305 return rawPut(ROC_ETH_CFG_READ, len, filename, 10.) == 0;
00306 }
00307
00308
00309
00310 bool roc::UdpBoard::uploadDataToRoc(char* buf, unsigned datalen)
00311 {
00312 put(ROC_ETH_FLASH_CLEAR_FILEBUFFER, 1);
00313
00314 uint32_t maxsendsize = sizeof(UdpMessageFull) - sizeof(UdpMessage);
00315
00316 unsigned pos = 0;
00317
00318 while (pos < datalen) {
00319 uint32_t sendsize = datalen - pos;
00320 if (sendsize > maxsendsize) sendsize = maxsendsize;
00321
00322 if (rawPut(ROC_ETH_FLASH_DATA, sendsize, buf + pos)!=0) {
00323 Debug(-1, "uploadDataToRoc:: packet error with addr %u", pos);
00324 return false;
00325 }
00326
00327 pos += sendsize;
00328 }
00329 return true;
00330 }
00331
00332
00333
00334 int roc::UdpBoard::uploadSDfile(const char* filename, const char* sdfilename)
00335 {
00336 if (sdfilename == 0) sdfilename = filename;
00337
00338 if ((filename==0) || (strlen(filename)==0)) return -1;
00339
00340 std::ifstream bfile;
00341 bfile.open(filename, std::ios_base::in);
00342
00343 if(!bfile) {
00344 Debug(-1, "uploadSDfile: Cannot open file: %s", filename);
00345 return -1;
00346 }
00347
00348 bfile.seekg(0, std::ios::end);
00349 unsigned bufSize = bfile.tellg();
00350 if (bufSize == 0) {
00351 Debug(-1, "uploadSDfile: File is empty: %s", filename);
00352 return -1;
00353 }
00354
00355 bfile.seekg(0, std::ios::beg);
00356 char* buffer = new char [bufSize + 1024];
00357 if (buffer == 0) {
00358 Debug(-1, "uploadSDfile: Memory allocation error!");
00359 return -1;
00360 }
00361 memset(buffer, 0, bufSize + 1024);
00362 bfile.read(buffer + 1024, bufSize);
00363 bfile.close();
00364
00365 *((uint32_t*) buffer) = htonl(bufSize);
00366
00367 memcpy(buffer + 4, sdfilename, strlen(sdfilename) + 1);
00368
00369 bufSize+=1024;
00370
00371 uint8_t XORCheckSum = 0;
00372
00373 for(unsigned i = 0; i < bufSize; i++)
00374 XORCheckSum ^= buffer[i];
00375
00376 if (!uploadDataToRoc(buffer, bufSize)) {
00377 Debug(-1, "uploadSDfile: Fail to upload file %s to the ROC\n", filename);
00378 delete [] buffer;
00379 return -1;
00380 }
00381
00382 uint32_t ROCchecksum(0);
00383 get(ROC_ETH_CHECK_FILEBUFFER, ROCchecksum);
00384
00385 delete[] buffer;
00386
00387 if (ROCchecksum != XORCheckSum) {
00388 Debug(-1, "uploadSDfile: File XOR checks sum %u differ from uploaded %u",
00389 XORCheckSum, ROCchecksum);
00390 return -1;
00391 }
00392
00393
00394 double waittime = ((bufSize - 1024) / 4096 + 1.) * 1.5;
00395
00396 Debug(0, "Start %s file writing, please wait ~%2.0f sec", sdfilename, waittime);
00397
00398 if (!submitSwPut(ROC_ETH_OVERWRITE_SD_FILE, 1, waittime + 30.)) return -1;
00399
00400 fRunningUpload = 3;
00401 fUploadChecksum = 0;
00402
00403 return int(waittime + 40.);
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416 }
00417
00418
00419
00420 int roc::UdpBoard::uploadBitfile(const char* filename, int position)
00421 {
00422 Debug(0, "Start upload of file %s, position: %d ...\n", filename, position);
00423
00424
00425 if(position > 1) {
00426 Debug(-1, "uploadBitfile: Only fileposition 0 and 1 is supported, sorry!");
00427 return -1;
00428 }
00429
00430 std::ifstream bitfile;
00431 bitfile.open(filename, std::ios_base::in);
00432
00433 if(!bitfile) {
00434 Debug(-1, "uploadBitfile: Cannot open file: %s", filename);
00435 return -1;
00436 }
00437
00438 ISEBinfileHeader hdr;
00439 memset(&hdr, 0, sizeof(hdr));
00440 strcpy((char*)hdr.ident, "XBF");
00441 hdr.headerSize = htonl(sizeof(hdr));
00442 memcpy(hdr.bitfileName, filename, 64);
00443 hdr.timestamp = 0;
00444 hdr.XORCheckSum = 0;
00445
00446 bitfile.seekg(0, std::ios::end);
00447 unsigned bitfileSize = bitfile.tellg();
00448 bitfile.seekg(0, std::ios::beg);
00449 char* bitfileBuffer = new char [bitfileSize];
00450 if (bitfileBuffer == 0) {
00451 Debug(-1, "uploadBitfile: Memory allocation error!");
00452 return -1;
00453 }
00454 memset(bitfileBuffer, 0, bitfileSize);
00455 bitfile.read(bitfileBuffer, bitfileSize);
00456 bitfile.close();
00457
00458
00459 int nBinPos = parseBitfileHeader(bitfileBuffer, bitfileSize);
00460 if (nBinPos == -1) {
00461 Debug(-1, "uploadBitfile: File does not seem to be a bit or bin file");
00462 delete [] bitfileBuffer;
00463 return -1;
00464 }
00465
00466
00467 unsigned binfileSize = bitfileSize - nBinPos;
00468 Debug(0, "Binfile loaded, size is %u bytes.", binfileSize);
00469
00470 for(unsigned i = 0; i < binfileSize; i++)
00471 hdr.XORCheckSum ^= bitfileBuffer[nBinPos + i];
00472
00473
00474 hdr.binfileSize = htonl(binfileSize);
00475
00476 uint32_t uploadBufferSize = sizeof(hdr) + binfileSize;
00477
00478 char* buffer = new char[uploadBufferSize];
00479 if (buffer == 0) {
00480 delete [] bitfileBuffer;
00481 return -1;
00482 }
00483 memset(buffer, 0, uploadBufferSize);
00484
00485 memcpy(buffer, &hdr, sizeof(hdr));
00486 memcpy(buffer + sizeof(hdr), bitfileBuffer + nBinPos, binfileSize);
00487
00488 uint8_t XORbitfileCheckSum = 0;
00489 for(unsigned n = 0; n < uploadBufferSize; n++)
00490 XORbitfileCheckSum ^= buffer[n];
00491
00492 Debug(0, "XOR 8bit over Kib file is %u", XORbitfileCheckSum);
00493
00494 Debug(0, "Now uploading Bitfile to ROC.");
00495
00496 ISEBinfileHeader* testhdr = (ISEBinfileHeader*) buffer;
00497
00498 uint32_t testlen = ntohl(testhdr->binfileSize) + ntohl(testhdr->headerSize);
00499 if (testlen != uploadBufferSize)
00500 Debug(-1, "uploadBitfile: Size mismatch %u %u", testlen, uploadBufferSize);
00501
00502 if (!uploadDataToRoc(buffer, uploadBufferSize)) {
00503 Debug(-1, "uploadBitfile: Fail to upload file to the ROC");
00504 delete [] bitfileBuffer;
00505 delete [] buffer;
00506 return -1;
00507 }
00508
00509 uint32_t ROCchecksum(0);
00510
00511 get(ROC_ETH_CHECK_BITFILEBUFFER, ROCchecksum);
00512
00513 if(ROCchecksum != XORbitfileCheckSum) {
00514 Debug(-1, "uploadBitfile: checksum error between PowerPC and file !!!");
00515 delete [] bitfileBuffer;
00516 delete [] buffer;
00517 return -1;
00518 }
00519
00520 int upload_time = 170 * bitfileSize / 905408;
00521
00522 Debug(0, "Start flashing - wait ~ %d s.", upload_time);
00523
00524 if (!submitSwPut(ROC_ETH_FLASH_KIBFILE_FROM_DDR, position, upload_time + 30)) return -1;
00525
00526 fRunningUpload = position+1;
00527 fUploadChecksum = XORbitfileCheckSum;
00528
00529 return upload_time + 40;
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558 }
00559
00560 int roc::UdpBoard::checkUpload()
00561 {
00562 if (fRunningUpload==0) return 0;
00563
00564 int res = checkSwPut();
00565 if (res==1) return 1;
00566
00567 uint32_t ROCchecksum(0);
00568
00569 if (res==2)
00570 switch (fRunningUpload) {
00571 case 1:
00572 get(ROC_ETH_CHECK_BITFILEFLASH0, ROCchecksum);
00573 if (ROCchecksum != fUploadChecksum) res = -1;
00574 break;
00575 case 2:
00576 get(ROC_ETH_CHECK_BITFILEFLASH1, ROCchecksum);
00577 if (ROCchecksum != fUploadChecksum) res = -1;
00578 break;
00579 case 3: break;
00580 }
00581
00582 fRunningUpload = 0;
00583 fUploadChecksum = 0;
00584
00585 return res;
00586 }
00587