LCOV - code coverage report
Current view: top level - uhallibs/src - ProtocolFlx.cpp (source / functions) Coverage Total Hit
Test: code.result Lines: 0.0 % 280 0
Test Date: 2025-12-21 13:07:08 Functions: 0.0 % 25 0

            Line data    Source code
       1              : /*
       2              : ---------------------------------------------------------------------------
       3              : 
       4              :     This file is part of uHAL.
       5              : 
       6              :     uHAL is a hardware access library and programming framework
       7              :     originally developed for upgrades of the Level-1 trigger of the CMS
       8              :     experiment at CERN.
       9              : 
      10              :     uHAL is free software: you can redistribute it and/or modify
      11              :     it under the terms of the GNU General Public License as published by
      12              :     the Free Software Foundation, either version 3 of the License, or
      13              :     (at your option) any later version.
      14              : 
      15              :     uHAL is distributed in the hope that it will be useful,
      16              :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      17              :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18              :     GNU General Public License for more details.
      19              : 
      20              :     You should have received a copy of the GNU General Public License
      21              :     along with uHAL.  If not, see <http://www.gnu.org/licenses/>.
      22              : 
      23              : 
      24              :       Andrew Rose, Imperial College, London
      25              :       email: awr01 <AT> imperial.ac.uk
      26              : 
      27              :       Marc Magrans de Abril, CERN
      28              :       email: marc.magrans.de.abril <AT> cern.ch
      29              : 
      30              :       Tom Williams, Rutherford Appleton Laboratory, Oxfordshire
      31              :       email: tom.williams <AT> cern.ch
      32              : 
      33              : ---------------------------------------------------------------------------
      34              : */
      35              : 
      36              : /**
      37              :         @file
      38              :         @author Alessandro Thea
      39              :         @date September 2019
      40              : */
      41              : 
      42              : #include "uhallibs/ProtocolFlx.hpp"
      43              : 
      44              : 
      45              : #include <algorithm>                                        // for min
      46              : #include <assert.h>
      47              : #include <cstdlib>
      48              : #include <fcntl.h>
      49              : #include <iomanip>                                          // for operator<<
      50              : #include <iostream>                                         // for operator<<
      51              : #include <sys/mman.h>
      52              : #include <sys/stat.h>
      53              : #include <sys/file.h>
      54              : #include <stdlib.h>                                         // for size_t, free
      55              : #include <string.h>                                         // for memcpy
      56              : #include <unistd.h>
      57              : 
      58              : #include <chrono>                                           // for operator>
      59              : #include <thread>                                           // for sleep_for
      60              : #include <filesystem>
      61              : 
      62              : #include "uhal/grammars/URI.hpp"                            // for URI
      63              : #include "uhal/log/LogLevels.hpp"                           // for BaseLogLevel
      64              : #include "uhal/log/log_inserters.integer.hpp"               // for uhal::Integer
      65              : #include "uhal/log/log_inserters.quote.hpp"                 // for uhal::Quote
      66              : #include "uhal/log/log.hpp"
      67              : #include "uhal/Buffers.hpp"
      68              : #include "uhal/ClientFactory.hpp"
      69              : 
      70              : #include "uhallibs/formatters.hpp"
      71              : 
      72              : #include "regmap/regmap-struct.h"
      73              : 
      74              : UHAL_REGISTER_EXTERNAL_CLIENT(uhallibs::Flx, "ipbusflx-2.0", "A client description")
      75              : 
      76              : 
      77              : namespace uhallibs {
      78              : 
      79              : 
      80              : //-----------------------------------------------------------------------------
      81            0 : regmap_register_t* Flx::Card::find_reg( const std::string& aName ) {
      82              : 
      83            0 :   regmap_register_t *reg;
      84            0 :   for (reg = regmap_registers; reg->name != NULL; reg++) {
      85            0 :     if (aName == reg->name) {
      86            0 :       return reg;
      87              :     }
      88              :   }
      89              : 
      90              :   return nullptr;
      91              : }
      92              : 
      93              : //-----------------------------------------------------------------------------
      94            0 : Flx::Card::Card(const std::string& aDevicePath, u_int aLockMask) :
      95            0 :   mPath(aDevicePath),
      96            0 :   mLockMask(aLockMask),
      97            0 :   mFlxCard(),
      98            0 :   mIsOpen(false) {
      99              : 
     100            0 :     const std::string prefix("/dev/flx");
     101            0 :     if ( aDevicePath.rfind(prefix, 0) != 0 ) {
     102              : 
     103            0 :       exception::FlxInvalidDevice lExc;
     104            0 :       log(lExc, "Invalid device path ", uhal::Quote(mPath));
     105            0 :       throw lExc;
     106              : 
     107            0 :     }
     108              : 
     109            0 :     std::string device_id_str = aDevicePath.substr(prefix.size()).data();
     110            0 :     try {
     111            0 :       mDeviceId = std::stoi(device_id_str);
     112            0 :     } catch (std::invalid_argument const& ex) {
     113              : 
     114            0 :       exception::FlxInvalidDevice lExc;
     115            0 :       log(lExc, "Invalid device id ", uhal::Quote(mPath));
     116            0 :       throw lExc;
     117              : 
     118            0 :     }
     119            0 : }
     120              : 
     121              : 
     122              : //-----------------------------------------------------------------------------
     123            0 : Flx::Card::~Card() {
     124            0 : }
     125              : 
     126              : 
     127              : //-----------------------------------------------------------------------------
     128            0 : void Flx::Card::open() {
     129              :   
     130            0 :   log(uhal::Debug(), "Flx::Card client Opening felix endpoint ", mDeviceId, " on ", mPath);
     131              : 
     132            0 :   if( access( mPath.c_str(), F_OK ) == -1 ) {
     133              : 
     134            0 :     exception::FlxInitialisationError lExc;
     135            0 :     log(lExc, "Failed to open device file ", uhal::Quote(mPath), "; errno=", uhal::Integer(errno), ", meaning ", uhal::Quote (strerror(errno)));
     136            0 :     throw lExc;
     137            0 :   }
     138              : 
     139            0 :   mFd = ::open(mPath.c_str(), O_RDWR);
     140            0 :   if (mFd < 0) {
     141              :     return;
     142              :   }
     143              : 
     144            0 :   mFlxCard.card_open(mDeviceId, mLockMask);
     145              : 
     146            0 :   mIsOpen = true;
     147              : }
     148              : 
     149              : 
     150              : //-----------------------------------------------------------------------------
     151            0 : void Flx::Card::close() {
     152              : 
     153            0 :   if (mIsOpen)
     154            0 :     mFlxCard.card_close();
     155              : 
     156            0 :   if (mFd != -1) {
     157            0 :     if (haveLock())
     158            0 :       unlock();
     159            0 :     int rc = ::close(mFd);
     160            0 :     mFd = -1;
     161            0 :     if (rc == -1)
     162            0 :       log (uhal::Error(), "Failed to close file ", uhal::Quote(mPath), "; errno=", uhal::Integer(errno), ", meaning ", uhal::Quote (strerror(errno)));
     163              :   }
     164            0 : }
     165              : 
     166              : 
     167              : //-----------------------------------------------------------------------------
     168            0 : const std::string& Flx::Card::getPath() const {
     169            0 :   return mPath;
     170              : }
     171              : 
     172              : //-----------------------------------------------------------------------------
     173            0 : int Flx::Card::getDeviceId() const {
     174            0 :   return mDeviceId;
     175              : }
     176              : 
     177              : //-----------------------------------------------------------------------------
     178            0 : void Flx::Card::read(const uint32_t aAddr, const uint32_t aNrWords, std::vector<uint32_t>& aValues) {
     179              : 
     180            0 :   if (!mIsOpen)
     181            0 :     open();
     182              : 
     183            0 :   flxcard_bar2_regs_t *bar2 = (flxcard_bar2_regs_t *) mFlxCard.openBackDoor( 2 );
     184              :   
     185              :   // +1 is ceiling rounding in integers
     186            0 :   uint32_t lNrReads64b = (aNrWords+1)/2;
     187            0 :   uint32_t lAddr = aAddr/2;
     188              : 
     189            0 :   for ( uint32_t i(0); i<lNrReads64b; i++) {
     190              :       // *lReadAddrPtr = lAddr+i;
     191            0 :       bar2->IPBUS_READ_ADDRESS = lAddr+i;
     192              :       // uint64_t lDataWord = *lReadDataPtr;
     193            0 :       uint64_t lDataWord = bar2->IPBUS_READ_DATA;
     194              :       // Split the 64b word in 32b chunks
     195            0 :       aValues.push_back(lDataWord & 0xffffffff);
     196            0 :       if ( 2*i+1 < aNrWords ) 
     197            0 :         aValues.push_back(lDataWord >> 32);
     198              :   }
     199              : 
     200            0 :   log(uhal::Debug(), "Flx::Card::read, ", aNrWords, " requested, ", aValues.size(), " read");
     201              : 
     202            0 : }
     203              : 
     204              : 
     205              : //-----------------------------------------------------------------------------
     206            0 : void Flx::Card::write(const uint32_t aAddr, const std::vector<std::pair<const uint8_t*, size_t> >& aData)
     207              : {
     208              : 
     209            0 :   if (!mIsOpen)
     210            0 :     open();
     211              : 
     212            0 :   flxcard_bar2_regs_t *bar2 = (flxcard_bar2_regs_t *) mFlxCard.openBackDoor( 2 );
     213              : 
     214            0 :   size_t lNrBytes = 0;
     215            0 :   for (size_t i = 0; i < aData.size(); i++)
     216            0 :     lNrBytes += aData.at(i).second;
     217              : 
     218            0 :   assert((lNrBytes % 4) == 0);
     219              : 
     220            0 :   char *allocated = NULL;
     221            0 :   posix_memalign((void **)&allocated, 4096/*alignment*/, lNrBytes + 4096);
     222            0 :   if (allocated == NULL) {
     223            0 :     exception::FlxCommunicationError lExc;
     224            0 :     log(lExc, "Failed to allocate ", uhal::Integer(lNrBytes + 4096), " bytes in File::write/2 function");
     225            0 :     throw lExc;
     226            0 :   }
     227              : 
     228              :   // data to write to register address
     229              :   char* buffer = allocated;
     230              :   size_t lNrBytesCopied = 0;
     231            0 :   for (size_t i = 0; i < aData.size(); i++) {
     232            0 :     memcpy(buffer + lNrBytesCopied, aData.at(i).first, aData.at(i).second);
     233            0 :     lNrBytesCopied += aData.at(i).second;
     234              :   }
     235              : 
     236            0 :   lNrBytesCopied = 0;
     237            0 :   uint32_t lAddr = aAddr/2;
     238              : 
     239            0 :   while (lNrBytesCopied < lNrBytes) {
     240            0 :     bar2->IPBUS_WRITE_ADDRESS = lAddr;
     241            0 :     char* lSrcPtr = buffer + lNrBytesCopied;
     242            0 :     if ((lNrBytes - lNrBytesCopied) >= 8) {
     243            0 :       bar2->IPBUS_WRITE_DATA.DATA = *(uint64_t*) lSrcPtr;
     244            0 :       lNrBytesCopied += 8;
     245              :     }
     246            0 :     else if ((lNrBytes - lNrBytesCopied) >= 4) {
     247            0 :       bar2->IPBUS_WRITE_DATA.DATA = uint64_t(*(uint32_t*) lSrcPtr);
     248            0 :       lNrBytesCopied += 4;
     249              :     }
     250              : 
     251            0 :     ++lAddr;
     252              :   }
     253              : 
     254            0 :   free(allocated);
     255            0 : }
     256              : 
     257            0 : bool Flx::Card::haveLock() const { return mLocked; }
     258              : 
     259              : 
     260            0 : void Flx::Card::lock() {
     261            0 :   if (flock(mFd, LOCK_EX) == -1) {
     262            0 :     ipc::exception::MutexError lExc;
     263            0 :     log(lExc, "Failed to lock device file ", uhal::Quote(mPath),
     264            0 :         "; errno=", uhal::Integer(errno), ", meaning ", uhal::Quote(strerror(errno)));
     265            0 :     throw lExc;
     266            0 :   }
     267            0 :   mLocked = true;
     268            0 : }
     269              : 
     270            0 : void Flx::Card::unlock() {
     271            0 :   if (flock(mFd, LOCK_UN) == -1) {
     272            0 :     log(uhal::Warning(), "Failed to unlock device file ", uhal::Quote(mPath),
     273            0 :         "; errno=", uhal::Integer(errno), ", meaning ", uhal::Quote(strerror(errno)));
     274              :   } else
     275            0 :     mLocked = false;
     276            0 : }
     277              : 
     278              : 
     279              : // Flx Transport
     280            0 : std::string Flx::getSharedMemName(const std::string& aPath)
     281              : {
     282            0 :   std::string lSanitizedPath(aPath);
     283            0 :   std::replace(lSanitizedPath.begin(), lSanitizedPath.end(), '/', ':');
     284              : 
     285            0 :   return "/uhal::ipbusflx-2.0::" + lSanitizedPath;
     286            0 : }
     287              : 
     288              : 
     289            0 : Flx::Flx ( const std::string& aId, const uhal::URI& aUri ) :
     290              :   IPbus< 2 , 0 > ( aId , aUri ),
     291            0 :   mConnected(false),
     292            0 :   mDeviceFile(aUri.mHostname, LOCK_NONE),
     293            0 :   mIPCMutex(getSharedMemName(aUri.mHostname)),
     294            0 :   mNumberOfPages(0),
     295            0 :   mPageSize(0),
     296            0 :   mIndexNextPage(0),
     297            0 :   mPublishedReplyPageCount(0),
     298            0 :   mReadReplyPageCount(0),
     299            0 :   mAsynchronousException ( NULL )
     300              : {
     301            0 :   mSleepDuration = std::chrono::microseconds(50);
     302              : 
     303            0 :   for (uhal::NameValuePairVectorType::const_iterator lIt = aUri.mArguments.begin(); lIt != aUri.mArguments.end(); lIt++) {
     304            0 :     if (lIt->first == "sleep") {
     305            0 :       mSleepDuration = std::chrono::microseconds(std::stoul(lIt->second));
     306            0 :       log (uhal::Notice() , "flx client with URI ", uhal::Quote (uri()), " : Inter-poll-/-interrupt sleep duration set to ", std::stoul(lIt->second), " us by URI 'sleep' attribute");
     307              :     }
     308              :     // else if (lIt->first == "offset") {
     309              :     //   const bool lIsHex = (lIt->second.find("0x") == 0) or (lIt->second.find("0X") == 0);
     310              :     //   const size_t lOffset = (lIsHex ? std::lexical_cast<HexTo<size_t> >(lIt->second) : std::stoul(lIt->second));
     311              :     //   mDeviceFile.setOffset(lOffset);
     312              :     //   log (uhal::Notice(), "flx client with URI ", uhal::Quote (uri()), " : Address offset set to ", uhal::Integer(lOffset, IntFmt<hex>()));
     313              :     // }
     314              :     else {
     315            0 :       log (uhal::Warning() , "Unknown attribute ", uhal::Quote (lIt->first), " used in URI ", uhal::Quote(uri()));
     316              :     }
     317              :   }
     318            0 : }
     319              : 
     320              : 
     321            0 : Flx::~Flx()
     322              : {
     323            0 :   disconnect();
     324            0 : }
     325              : 
     326              : 
     327            0 : void Flx::implementDispatch ( std::shared_ptr< uhal::Buffers > aBuffers )
     328              : {
     329            0 :   log(uhal::Debug(), "flx client (URI: ", uhal::Quote(uri()), ") : implementDispatch method called");
     330              : 
     331            0 :   if ( ! mConnected )
     332            0 :     connect();
     333              : 
     334            0 :   if ( mReplyQueue.size() == mNumberOfPages )
     335            0 :     read();
     336            0 :   write(aBuffers);
     337            0 : }
     338              : 
     339              : 
     340            0 : void Flx::Flush( )
     341              : {
     342            0 :   log(uhal::Debug(), "flx client (URI: ", uhal::Quote(uri()), ") : Flush method called");
     343            0 :   while ( !mReplyQueue.empty() )
     344            0 :     read();
     345              : 
     346            0 :   mDeviceFile.unlock();
     347              : 
     348            0 :   IPCScopedLock_t lLockGuard(*mIPCMutex);
     349            0 :   mIPCMutex->endSession();
     350              : 
     351            0 : }
     352              : 
     353              : 
     354            0 : void Flx::dispatchExceptionHandler()
     355              : {
     356              :   // FIXME: Adapt to PCIe implementation
     357              :   // log(uhal::Notice(), "flx client ", uhal::Quote(id()), " (URI: ", uhal::Quote(uri()), ") : closing device files since exception detected");
     358              : 
     359              :   // ClientInterface::returnBufferToPool ( mReplyQueue );
     360              :  
     361            0 :   mDeviceFile.unlock();
     362              : 
     363            0 :   disconnect();
     364              : 
     365            0 :   InnerProtocol::dispatchExceptionHandler();
     366            0 : }
     367              : 
     368              : 
     369            0 : uint32_t Flx::getMaxSendSize()
     370              : {
     371            0 :   if ( ! mConnected )
     372            0 :     connect();
     373              : 
     374            0 :   return (mPageSize - 1) * 4;
     375              : }
     376              : 
     377              : 
     378            0 : uint32_t Flx::getMaxReplySize()
     379              : {
     380            0 :   if ( ! mConnected )
     381            0 :     connect();
     382              : 
     383            0 :   return (mPageSize - 1) * 4;
     384              : }
     385              : 
     386              : 
     387            0 : void Flx::connect()
     388              : {
     389            0 :   IPCScopedLock_t lLockGuard(*mIPCMutex);
     390            0 :   connect(lLockGuard);
     391            0 : }
     392              : 
     393              : 
     394            0 : void Flx::connect(IPCScopedLock_t& aGuard)
     395              : {
     396              :     // Read current value of session counter when reading status info from FPGA
     397              :   // (So that can check whether this info is up-to-date later on, when sending next request packet)
     398            0 :   mIPCExternalSessionActive = mIPCMutex->isActive() and (not mDeviceFile.haveLock());
     399            0 :   mIPCSessionCount = mIPCMutex->getCounter();
     400              : 
     401            0 :   log ( uhal::Debug() , "flx client is opening device file " , uhal::Quote ( mDeviceFile.getPath() ) );
     402            0 :   std::vector<uint32_t> lValues;
     403            0 :   mDeviceFile.read(0x0, 4, lValues);
     404            0 :   log (uhal::Debug(), "Read status info from addr 0 (", uhal::Integer(lValues.at(0)), ", ", uhal::Integer(lValues.at(1)), ", ", uhal::Integer(lValues.at(2)), ", ", uhal::Integer(lValues.at(3)), "): ", PacketFmt((const uint8_t*)lValues.data(), 4 * lValues.size()));
     405            0 :   aGuard.unlock();
     406              : 
     407            0 :   mNumberOfPages = lValues.at(0);
     408              :   // mPageSize = std::min(uint32_t(4096), lValues.at(1));
     409            0 :   mPageSize = lValues.at(1);
     410            0 :   mIndexNextPage = lValues.at(2);
     411            0 :   mPublishedReplyPageCount = lValues.at(3);
     412            0 :   mReadReplyPageCount = mPublishedReplyPageCount;
     413              : 
     414            0 :   if (lValues.at(1) > 0xFFFF) {
     415            0 :     exception::FlxInitialisationError lExc;
     416            0 :     log (lExc, "Invalid page size, ", uhal::Integer(lValues.at(1)), ", reported in device file ", uhal::Quote(mDeviceFile.getPath()));
     417            0 :     throw lExc;
     418            0 :   }
     419              : 
     420            0 :   if (mIndexNextPage >= mNumberOfPages) {
     421            0 :     exception::FlxInitialisationError lExc;
     422            0 :     log (lExc, "Next page index, ", uhal::Integer(mIndexNextPage), ", reported in device file ", uhal::Quote(mDeviceFile.getPath()), " is inconsistent with number of pages, ", uhal::Integer(mNumberOfPages));
     423            0 :     throw lExc;
     424            0 :   }
     425              : 
     426            0 :   mConnected = true;
     427            0 :   log ( uhal::Info() , "flx client connected to device at ", uhal::Quote(mDeviceFile.getPath()), "; FPGA has ", uhal::Integer(mNumberOfPages), " pages, each of size ", uhal::Integer(mPageSize), " words, index ", uhal::Integer(mIndexNextPage), " should be filled next" );
     428            0 : }
     429              : 
     430              : 
     431            0 : void Flx::disconnect()
     432              : {
     433            0 :   log ( uhal::Debug() , "flx client is closing device file " , uhal::Quote ( mDeviceFile.getPath() ) );
     434            0 :   mDeviceFile.close();
     435            0 :   mConnected = false;
     436            0 : }
     437              : 
     438              : 
     439            0 : void Flx::write(const std::shared_ptr<uhal::Buffers>& aBuffers)
     440              : {
     441            0 :   if (not mDeviceFile.haveLock()) {  
     442            0 :     mDeviceFile.lock();
     443              : 
     444            0 :     IPCScopedLock_t lGuard(*mIPCMutex);
     445            0 :     mIPCMutex->startSession();
     446            0 :     mIPCSessionCount++;
     447              : 
     448            0 :     if (mIPCExternalSessionActive or (mIPCMutex->getCounter() != mIPCSessionCount)) {
     449            0 :       connect(lGuard);
     450              :     }
     451            0 :   }
     452              : 
     453            0 :   log (uhal::Info(), "flx client ", uhal::Quote(id()), " (URI: ", uhal::Quote(uri()), ") : writing ", uhal::Integer(aBuffers->sendCounter() / 4), "-word packet to page ", uhal::Integer(mIndexNextPage), " in ", uhal::Quote(mDeviceFile.getPath()));
     454              : 
     455            0 :   const uint32_t lHeaderWord = (0x10000 | (((aBuffers->sendCounter() / 4) - 1) & 0xFFFF));
     456            0 :   std::vector<std::pair<const uint8_t*, size_t> > lDataToWrite;
     457            0 :   lDataToWrite.push_back( std::make_pair(reinterpret_cast<const uint8_t*>(&lHeaderWord), sizeof lHeaderWord) );
     458            0 :   lDataToWrite.push_back( std::make_pair(aBuffers->getSendBuffer(), aBuffers->sendCounter()) );
     459              : 
     460            0 :   IPCScopedLock_t lGuard(*mIPCMutex);
     461            0 :   mDeviceFile.write(mIndexNextPage * mPageSize, lDataToWrite);
     462            0 :   log (uhal::Debug(), "Wrote " , uhal::Integer((aBuffers->sendCounter() / 4) + 1), " 32-bit words at address " , uhal::Integer(mIndexNextPage * 4 * mPageSize), " ... ", PacketFmt(lDataToWrite));
     463              : 
     464            0 :   mIndexNextPage = (mIndexNextPage + 1) % mNumberOfPages;
     465            0 :   mReplyQueue.push_back(aBuffers);
     466            0 : }
     467              : 
     468              : 
     469            0 : void Flx::read()
     470              : {
     471            0 :   const size_t lPageIndexToRead = (mIndexNextPage - mReplyQueue.size() + mNumberOfPages) % mNumberOfPages;
     472            0 :   SteadyClock_t::time_point lStartTime = SteadyClock_t::now();
     473              : 
     474            0 :   if (mReadReplyPageCount == mPublishedReplyPageCount)
     475              :   {
     476            0 :     uint32_t lHwPublishedPageCount = 0x0;
     477              : 
     478            0 :     std::vector<uint32_t> lValues;
     479            0 :     while ( true ) {
     480            0 :       IPCScopedLock_t lGuard(*mIPCMutex);
     481              :       // FIXME : Improve by simply adding dmaWrite method that takes uint32_t ref as argument (or returns uint32_t)
     482            0 :       mDeviceFile.read(0, 4, lValues);
     483            0 :       lHwPublishedPageCount = lValues.at(3);
     484              :       // log (uhal::Info(), "Read status info from addr 0 (", uhal::Integer(lValues.at(0)), ", ", uhal::Integer(lValues.at(1)), ", ", uhal::Integer(lValues.at(2)), ", ", uhal::Integer(lValues.at(3)), "): ", PacketFmt((const uint8_t*)lValues.data(), 4 * lValues.size()));
     485            0 :       log (uhal::Debug(), "Read status info from addr 0 (", uhal::Integer(lValues.at(0)), ", ", uhal::Integer(lValues.at(1)), ", ", uhal::Integer(lValues.at(2)), ", ", uhal::Integer(lValues.at(3)), "): ", PacketFmt((const uint8_t*)lValues.data(), 4 * lValues.size()));
     486              : 
     487            0 :       if (lHwPublishedPageCount != mPublishedReplyPageCount) {
     488            0 :         mPublishedReplyPageCount = lHwPublishedPageCount;
     489            0 :         break;
     490              :       }
     491              :       // FIXME: Throw if published page count is invalid number
     492              : 
     493            0 :       if (SteadyClock_t::now() - lStartTime > std::chrono::microseconds(getBoostTimeoutPeriod().total_microseconds())) {
     494            0 :         exception::FlxTimeout lExc;
     495            0 :         log(lExc, "Next page (index ", uhal::Integer(lPageIndexToRead), " count ", uhal::Integer(mPublishedReplyPageCount+1), ") of flx device '" + mDeviceFile.getPath() + "' is not ready after timeout period");
     496            0 :         throw lExc;
     497            0 :       }
     498              : 
     499            0 :       log(uhal::Debug(), "flx client ", uhal::Quote(id()), " (URI: ", uhal::Quote(uri()), ") : Trying to read page index ", uhal::Integer(lPageIndexToRead), " = count ", uhal::Integer(mReadReplyPageCount+1), "; published page count is ", uhal::Integer(lHwPublishedPageCount), "; sleeping for ", mSleepDuration.count(), "us");
     500            0 :       if (mSleepDuration > std::chrono::microseconds(0))
     501            0 :         std::this_thread::sleep_for( mSleepDuration );
     502            0 :       lValues.clear();
     503            0 :     }
     504              : 
     505            0 :     log(uhal::Info(), "flx client ", uhal::Quote(id()), " (URI: ", uhal::Quote(uri()), ") : Reading page ", uhal::Integer(lPageIndexToRead), " (published count ", uhal::Integer(lHwPublishedPageCount), ", surpasses required, ", uhal::Integer(mReadReplyPageCount + 1), ")");
     506            0 :   }
     507            0 :   mReadReplyPageCount++;
     508              :   
     509              :   // PART 1 : Read the page
     510            0 :   std::shared_ptr<uhal::Buffers> lBuffers = mReplyQueue.front();
     511            0 :   mReplyQueue.pop_front();
     512              : 
     513            0 :   uint32_t lNrWordsToRead(lBuffers->replyCounter() >> 2);
     514            0 :   lNrWordsToRead += 1;
     515              :  
     516            0 :   std::vector<uint32_t> lPageContents;
     517            0 :   IPCScopedLock_t lGuard(*mIPCMutex);
     518            0 :   mDeviceFile.read(4 + lPageIndexToRead * mPageSize, lNrWordsToRead , lPageContents);
     519            0 :   lGuard.unlock();
     520            0 :   log (uhal::Debug(), "Read " , uhal::Integer(lNrWordsToRead), " 32-bit words from address " , uhal::Integer(4 + lPageIndexToRead * 4 * mPageSize), " ... ", PacketFmt((const uint8_t*)lPageContents.data(), 4 * lPageContents.size()));
     521              : 
     522              :   // PART 2 : Transfer to reply buffer
     523            0 :   const std::deque< std::pair< uint8_t* , uint32_t > >& lReplyBuffers ( lBuffers->getReplyBuffer() );
     524            0 :   size_t lNrWordsInPacket = (lPageContents.at(0) >> 16) + (lPageContents.at(0) & 0xFFFF);
     525            0 :   if (lNrWordsInPacket != (lBuffers->replyCounter() >> 2))
     526            0 :     log (uhal::Warning(), "Expected reply packet to contain ", uhal::Integer(lBuffers->replyCounter() >> 2), " words, but it actually contains ", uhal::Integer(lNrWordsInPacket), " words");
     527              : 
     528            0 :   size_t lNrBytesCopied = 0;
     529            0 :   for ( std::deque< std::pair< uint8_t* , uint32_t > >::const_iterator lIt = lReplyBuffers.begin() ; lIt != lReplyBuffers.end() ; ++lIt )
     530              :   {
     531              :     // Don't copy more of page than was written to, for cases when less data received than expected
     532            0 :     if ( lNrBytesCopied >= 4*lNrWordsInPacket)
     533              :       break;
     534              : 
     535            0 :     size_t lNrBytesToCopy = std::min( lIt->second , uint32_t(4*lNrWordsInPacket - lNrBytesCopied) );
     536            0 :     memcpy ( lIt->first, &lPageContents.at(1 + (lNrBytesCopied / 4)), lNrBytesToCopy );
     537            0 :     lNrBytesCopied += lNrBytesToCopy;
     538              :   }
     539              : 
     540              : 
     541              :   // PART 3 : Validate the packet contents
     542            0 :   try
     543              :   {
     544            0 :     if ( uhal::exception::exception* lExc = ClientInterface::validate ( lBuffers ) ) //Control of the pointer has been passed back to the client interface
     545              :     {
     546            0 :       mAsynchronousException = lExc;
     547              :     }
     548              :   }
     549            0 :   catch ( uhal::exception::exception& aExc )
     550              :   {
     551            0 :     mAsynchronousException = new uhal::exception::ValidationError ();
     552            0 :     log ( *mAsynchronousException , "Exception caught during reply validation for flx device with URI " , uhal::Quote ( this->uri() ) , "; what returned: " , uhal::Quote ( aExc.what() ) );
     553            0 :   }
     554              : 
     555            0 :   if ( mAsynchronousException )
     556              :   {
     557            0 :     mAsynchronousException->throwAsDerivedType();
     558              :   }
     559            0 : }
     560              : 
     561              : 
     562              : } // end ns uhal
        

Generated by: LCOV version 2.0-1