Generic hardware access library
/home/cschwick/hal/generic/src/common/VMEConfigurationSpaceHandler.cc
Go to the documentation of this file.
00001 #include "hal/VMEConfigurationSpaceHandler.hh"
00002 #include <sstream>
00003 #include <iostream>
00004 #include <iomanip>
00005 
00006 HAL::VMEConfigurationSpaceHandler::VMEConfigurationSpaceHandler( HAL::VMEBusAdapterInterface& busAdapter ) 
00007   : busAdapter_(busAdapter) {
00008   
00009   HAL::VMEConfigurationSpaceAddressReader configurationReader;
00010   configurationAddressTablePtr_ = new HAL::VMEAddressTable("VME64x Configuration Space", 
00011                                                            configurationReader);
00012   vmeDevicePtr_ = new HAL::VMEConfigurationSpaceDevice( *configurationAddressTablePtr_,
00013                                                         busAdapter );
00014 }
00015 
00016 HAL::VMEConfigurationSpaceHandler::~VMEConfigurationSpaceHandler() {
00017   delete vmeDevicePtr_;
00018   delete configurationAddressTablePtr_;
00019 }
00020 
00021 uint32_t HAL::VMEConfigurationSpaceHandler::calculateOffset( uint32_t slot ) const {
00022   return ( slot * VME64X_CONFIGURATIONSPACE_SIZE );
00023 }
00024 
00025 void HAL::VMEConfigurationSpaceHandler::configWrite( std::string item,
00026                                                      uint32_t slot,
00027                                                      uint32_t data,
00028                                                      HalVerifyOption verifyFlag,
00029                                                      uint32_t offset ) const
00030   throw( HAL::NoSuchItemException, 
00031          HAL::IllegalOperationException,
00032          HAL::BusAdapterException ) {
00033   offset += calculateOffset( slot );
00034   vmeDevicePtr_->write( item, data, verifyFlag, offset );
00035 }
00036 
00037 void HAL::VMEConfigurationSpaceHandler::saveWrite( std::string item,
00038                                                    uint32_t slot,
00039                                                    uint32_t data,
00040                                                    HalVerifyOption verifyFlag,
00041                                                    uint32_t offset ) const {
00042   try {
00043     configWrite( item, slot, data, verifyFlag, offset );
00044   } catch ( HAL::BusAdapterException& e ) {
00045     std::cout << "Internal error while accessing the configuration space via the busAdapter\n    (HAL::VMEConfigurationSpaceHandler::saveWrite)" << std::endl;
00046     std::cout << e.what() << std::endl;
00047     exit (-1);
00048   } catch( HAL::HardwareAccessException& e ) {
00049     std::cout << "Internal program error in HAL::VMEConfigurationSpaceHandler::saveWrite: "
00050          << "\ncaught exception:\n"
00051          << e.what() << std::endl;
00052     exit(-1);
00053   }
00054 }
00055 
00056 void HAL::VMEConfigurationSpaceHandler::configRead( std::string item,
00057                                                     uint32_t slot,
00058                                                     uint32_t* resultPtr,
00059                                                     uint32_t offset ) const
00060   throw( HAL::NoSuchItemException, 
00061          HAL::IllegalOperationException,
00062          HAL::BusAdapterException ) {
00063   offset += calculateOffset( slot );
00064   vmeDevicePtr_->read( item, resultPtr, offset );
00065 }
00066 
00067 void HAL::VMEConfigurationSpaceHandler::saveRead(std::string item,
00068                                                  uint32_t slot,
00069                                                  uint32_t* resultPtr,
00070                                                  uint32_t offset ) const {
00071   try {
00072     configRead( item, slot, resultPtr, offset );
00073   } catch ( HAL::BusAdapterException& e ) {
00074     std::cout << "Internal Error while accessing the configuration space via the busAdapter\n    (HAL::VMEConfigurationSpaceHandler::saveRead)" << std::endl;
00075     std::cout << e.what() << std::endl;
00076     exit ( -1 );
00077   } catch( HAL::HardwareAccessException& e ) {
00078     std::cout << "Internal program error in HAL::VMEConfigurationSpaceHandler::saveRead: "
00079          << "\ncaught exception:\n"
00080          << e.what() << std::endl;
00081     exit(-1);
00082   }
00083 }
00084 
00085 bool 
00086 HAL::VMEConfigurationSpaceHandler::containsVME64xModule( uint32_t slot ) const 
00087         throw (HAL::IllegalValueException) {
00088   uint32_t CRIdentifier, CRspecificationId;
00089   bool result;
00090   try{
00091     configRead( "CR", slot, &CRIdentifier ); 
00092     configRead( "specificationId", slot, &CRspecificationId ); 
00093   } catch ( HAL::BusAdapterException& e ) {
00094     CRIdentifier = 0;
00095   } catch( HAL::HardwareAccessException& e ) {
00096     std::cout << "Internal program error in HAL::VMEConfigurationSpaceHandler::containsVME64xModule "
00097          << "\ncaught exception:\n"
00098          << e.what() << std::endl;
00099     exit(-1);
00100   }
00101   if ( (CRIdentifier == 0x4352) & (CRspecificationId==0x02) ) {
00102     result = true;
00103   } else {
00104     result = false;
00105   }
00106   return result;
00107 }
00108 
00109 bool 
00110 HAL::VMEConfigurationSpaceHandler::functionIsImplemented( uint32_t slotId, 
00111                                                           uint32_t functionId ) const {
00112 
00113   std::ostringstream item;
00114   uint32_t ADEM;
00115 
00116   // retrieve raw function data from config space: The ADER is also read
00117   // in case one day we want to support fixed address functions (FAFs).
00118   //  item << "ADEM-F" << setw(1)<< setfill('0') << functionId << ends;
00119   //  item << "ADEM-F" << dec << setw(1) << functionId << ends;
00120   item << "ADEM-F" << std::setw(1) << functionId;
00121   try {
00122     configRead(item.str(), slotId, &ADEM);
00123   } catch ( HAL::BusAdapterException& e ) {
00124     return false;
00125   } catch ( HAL::HardwareAccessException& e ) {
00126     std::cout << "Internal program error (HAL::VMEConfigurationSpaceHandler::functionIsImplemented)" << std::endl;
00127     std::cout << e.what() << std::endl;
00128     exit(-1);
00129   }
00130   // check if this function is implemented at all:
00131   if ( ADEM == 0x00 ) {
00132     return false;
00133   }
00134   return true;
00135 }
00136 
00137 void HAL::VMEConfigurationSpaceHandler::checkVME64xConfigSpace( uint32_t slot ) const
00138   throw( HAL::IllegalOperationException ) {
00139   if ( ! containsVME64xModule( slot ) ) {
00140         std::stringstream text;
00141         text << "There is no VME64x Module in slot" << std::dec << slot
00142              << "\n    (HAL::VMEConfigurationSpaceHandler::checkVME64xConfigSpace)"
00143              << std::ends;
00144         throw( HAL::IllegalOperationException( text.str(), __FILE__, __LINE__, __FUNCTION__ ) );
00145   }
00146 }
00147 
00148 uint32_t HAL::VMEConfigurationSpaceHandler::getUserROMInterval( uint32_t slot ) const {
00149   uint32_t byteInterval, romWidth;
00150   saveRead( "CRWidth", slot, &romWidth );
00151   if ( romWidth == 0x81 ) {
00152         byteInterval = 4;
00153   } else if( romWidth == 0x82 ) {
00154         byteInterval = 2;
00155   } else {
00156         byteInterval = 1;
00157   }
00158   return byteInterval;
00159 };
00160 
00161 void HAL::VMEConfigurationSpaceHandler::readROMBlock( uint32_t slot, 
00162                                                       uint32_t startAdr, 
00163                                                       uint32_t endAdr, 
00164                                                       std::vector<unsigned char>* data ) const {
00165   // The configuration region which is valid for readout is given by the
00166   // field "Configuration ROM data access width". The value of this field
00167   // determines which bytes are considered during the checksum building.
00168   // The region above 0x1000 is the User region. Which bytes are used is 
00169   // specified in the field "Configuration ROM data access width".
00170   //
00171   // In the specified part of the ROM only every 4th byte is valid and has 
00172   // to be taken into account when building the checksum. But modules must
00173   // deliver 00 on bytes which are not defined. Therefore the checksum does
00174   // not change if these bytes are also taken in consideration while building
00175   // the checksum.
00176   uint32_t ic, offset, readData;
00177   uint32_t userROMInterval = getUserROMInterval( slot );
00178 
00179   // it must be considered that the area up to 0xfff is only every 4th byte.
00180   for ( ic=0, offset = startAdr; offset <= endAdr; ic++, offset += userROMInterval ) {
00181     saveRead( "romStart", slot, &readData, offset );
00182         data->push_back((unsigned char)readData);
00183   }
00184 }
00185 
00186 
00187 bool HAL::VMEConfigurationSpaceHandler::checksumOk( uint32_t slot ) const 
00188   throw( HAL::IllegalOperationException ) {
00189   checkVME64xConfigSpace( slot );
00190   uint32_t romLength;
00191   saveRead( "romLength", slot, &romLength );
00192   uint32_t userROMInterval = getUserROMInterval( slot );
00193   std::vector<unsigned char> CRRom;
00194   uint32_t endAdr = userROMInterval * (romLength - 1) + 7;
00195   readROMBlock( slot, 0x07, endAdr, &CRRom );
00196   // build checksum
00197   uint32_t checksum = 0;
00198   for ( uint32_t ic=0; ic<romLength; ic++ ) {
00199     checksum += (uint32_t)CRRom[ic];
00200   }
00201 
00202   // now the spec is not clear...what the hell should be an
00203   // eight bit 2s complement binary checksum ???? Probably they
00204   // want a 2s complement of the checksum in order to be able 
00205   // to add it to the checksum and test for 0.
00206   checksum &= 0x00ff;
00207   uint32_t romChecksum;
00208   saveRead( "checksum", slot, &romChecksum ); 
00209   return ( (0xff & (checksum + romChecksum)) == 0);
00210 }
00211  
00212 std::string HAL::VMEConfigurationSpaceHandler::readSerialNumber( uint32_t slot ) const
00213   throw( HAL::IllegalOperationException ) {
00214 
00215   checkVME64xConfigSpace( slot );
00216   uint32_t size, startAdr, endAdr, userROMInterval;
00217   saveRead( "serialNumberStart", slot, &startAdr );
00218   saveRead( "serialNumberEnd", slot, &endAdr );
00219   userROMInterval = getUserROMInterval( slot );
00220   size = (endAdr - startAdr + userROMInterval) / userROMInterval;
00221   std::vector<unsigned char> serialChar;
00222   readROMBlock( slot, startAdr, endAdr, &serialChar );
00223   size = serialChar.size();
00224   char chararr[ size + 1 ];
00225   for ( uint32_t ic = 0; ic < size; ic++ ) {
00226     chararr[ic] = serialChar[ic];
00227   }
00228   chararr [ size ] = (char)0x00;
00229   std::string result( (char*)chararr );
00230   return result;
00231 }
00232 
00233 void HAL::VMEConfigurationSpaceHandler::enableVME64xModule( uint32_t slotId ) const 
00234   throw( HAL::IllegalOperationException ) {
00235   checkVME64xConfigSpace( slotId );
00236   saveWrite( "bitSet", slotId, 0x10 );
00237 }
00238 
00239 void HAL::VMEConfigurationSpaceHandler::disableVME64xModule( uint32_t slotId ) const 
00240   throw( HAL::IllegalOperationException ) {
00241   checkVME64xConfigSpace( slotId );
00242   saveWrite( "bitClear", slotId, 0x10 );
00243 }
00244 
00245 bool HAL::VMEConfigurationSpaceHandler::enabled( uint32_t slotId ) const 
00246   throw( HAL::IllegalOperationException ) {
00247   checkVME64xConfigSpace( slotId );
00248   uint32_t result;
00249   saveRead( "bitSet", slotId, &result);
00250   return ( (result & 0x10) == 0x10 ); 
00251 }
00252 
00253 HAL::VMEBusAdapterInterface& HAL::VMEConfigurationSpaceHandler::getBusAdapter() const {
00254   return busAdapter_;
00255 }