Generic hardware access library
|
00001 #include "hal/VMESlot.hh" 00002 #include "hal/VME64xDevice.hh" 00003 00004 #include <sstream> 00005 #include <iomanip> 00006 #include <ext/hash_map> 00007 00008 HAL::VMESlot::VMESlot( HAL::StaticVMEItem* staticVME, 00009 HAL::VMEBusAdapterInterface* busAdapterPtr, 00010 HAL::AddressTableContainerInterface& addressTableContainer, 00011 HAL::ModuleMapperInterface& moduleMapper ) 00012 throw( HAL::IllegalValueException ) 00013 : busAdapterPtr_(busAdapterPtr), 00014 addressTableContainer_(addressTableContainer), 00015 moduleMapper_(moduleMapper), 00016 windowVector_(NUMBER_OF_VME64XFUNCTIONS) { 00017 00018 // initialization of variables 00019 configAdapterPtr_ = (HAL::VMEConfigurationSpaceHandler*)0; 00020 for ( int i=0; i<NUMBER_OF_VME64XFUNCTIONS; i++ ) { 00021 windowVector_.push_back( (HAL::VME64xMappedWindow*)0 ); 00022 } 00023 slotId_ = staticVME->getSlotId(); 00024 serialNumber_ = staticVME->getSerialNumber(); 00025 contents_ = (HAL::SlotContents)VME; 00026 00027 // get database info: typeId and baseaddress 00028 uint32_t baseAddress = moduleMapper.getBaseaddress( serialNumber_ ); 00029 typeId_ = moduleMapper.getTypeId( serialNumber_ ); 00030 00031 // get HAL::AddressTable and related info 00032 HAL::VMEAddressTable& addressTable = addressTableContainer_.getVMETableFromSerialNumber( serialNumber_ ); 00033 std::vector<uint32_t> minAddresses, maxAddresses; 00034 addressTable.getAddressBoundaries( minAddresses, maxAddresses ); 00035 00036 // for standard vme modules only the first entry in the vectors is relevant: 00037 // the minimal addressRank in VME64x is 256 bytes Therefore we start 00038 // with that addressRank here. 00039 uint32_t addressRank = 8; 00040 while ( (1u<<(addressRank)) <= maxAddresses[0] ) addressRank++; 00041 00042 HAL::VME64xFunction* functionPtr = new HAL::VME64xFunction( slotId_, baseAddress, addressRank ); 00043 functionPtrs_.push_back( functionPtr ); 00044 00045 // fill the windowVector of the slot 00046 00047 std::list< HAL::VME64xMappedWindow* >::const_iterator it; 00048 it = functionPtr->getMappedWindowPtrList().begin(); 00049 windowVector_[0] = *it; 00050 00051 } 00052 00053 HAL::VMESlot::VMESlot( uint32_t slotId, 00054 HAL::VMEConfigurationSpaceHandler* configAdapterPtr, 00055 HAL::AddressTableContainerInterface& addressTableContainer, 00056 HAL::ModuleMapperInterface& moduleMapper, 00057 bool ignoreChecksumError ) 00058 throw(HAL::IllegalValueException, 00059 HAL::UnsupportedException ) 00060 : slotId_(slotId), 00061 configAdapterPtr_(configAdapterPtr), 00062 addressTableContainer_(addressTableContainer), 00063 moduleMapper_(moduleMapper_), 00064 windowVector_(NUMBER_OF_VME64XFUNCTIONS) { 00065 00066 // initialization of variables 00067 busAdapterPtr_ = &(configAdapterPtr->getBusAdapter()); 00068 for ( int i=0; i<NUMBER_OF_VME64XFUNCTIONS; i++ ) { 00069 windowVector_.push_back( (HAL::VME64xMappedWindow*)0 ); 00070 } 00071 00072 typeId_ = ""; 00073 serialNumber_ = ""; 00074 00075 // If there is no VME64x module we assume the slot is empty. 00076 if ( ! configAdapterPtr->containsVME64xModule( slotId ) ) { 00077 contents_ = (HAL::SlotContents)EMPTY; 00078 return; 00079 } else { 00080 if ( (! ignoreChecksumError) && (! configAdapterPtr->checksumOk( slotId )) ) { 00081 std::stringstream text; 00082 text << "Found VME64x module in slot " << std::dec << slotId 00083 << " but checksum is corrupted" << std::ends; 00084 throw( HAL::IllegalValueException( text.str(), __FILE__, __LINE__, __FUNCTION__ ) ); 00085 } 00086 contents_ = (HAL::SlotContents)VME64x; 00087 } 00088 00089 // get the serial Number of this module 00090 // it is needed later when the HAL::VMEDevice is created. 00091 // in case of old VME modules it is set from the configration 00092 // given in the constructor: 00093 serialNumber_ = configAdapterPtr_->readSerialNumber( slotId_ ); 00094 typeId_ = moduleMapper.getTypeId( serialNumber_ ); 00095 00096 // get the functions of the module in this slot: 00097 HAL::VME64xFunction* functionPtr; 00098 uint32_t funcId = 0; 00099 bool atLeastOneValidFunction = false; 00100 00101 // Go through all possible functions and see if they are implemented. 00102 // Implemented functions are put into the list fucntionPtrs_ 00103 // and all mapped windows are put into the windowVector_. 00104 while ( funcId < NUMBER_OF_VME64XFUNCTIONS ) { 00105 if ( configAdapterPtr_->functionIsImplemented( slotId_, funcId )) { 00106 functionPtr = new HAL::VME64xFunction( slotId_, 00107 funcId, 00108 configAdapterPtr_ ); 00109 functionPtrs_.push_back( functionPtr ); 00110 atLeastOneValidFunction = true; 00111 funcId += functionPtr->getNumberOfMappedWindows(); 00112 00113 // fill the windowVector of the slot 00114 00115 std::list< HAL::VME64xMappedWindow* >::const_iterator it; 00116 std::list< HAL::VME64xMappedWindow* > windowList = functionPtr->getMappedWindowPtrList(); 00117 for( it = windowList.begin(); it != windowList.end(); it++ ) { 00118 windowVector_[(*it)->getMappedWindowId()] = *it; 00119 } 00120 } else { 00121 funcId++; 00122 } 00123 } 00124 00125 if ( ! atLeastOneValidFunction ) { 00126 std::stringstream text; 00127 text << "No valid function found in VME64x module of slot " 00128 << std::dec << slotId_ 00129 << ".\n (HAL::VMESlot::VMESlot)" << std::ends; 00130 00131 // clean up what we have generated before throwing an exception. 00132 00133 std::list< HAL::VME64xFunction* >::iterator it; 00134 for ( it=functionPtrs_.begin(); it != functionPtrs_.end(); it++ ) { 00135 delete *it; 00136 } 00137 functionPtrs_.clear(); 00138 throw( HAL::IllegalValueException( text.str(), __FILE__, __LINE__, __FUNCTION__ )); 00139 } 00140 00141 } 00142 00143 HAL::VMESlot::~VMESlot() { 00144 std::list< HAL::VME64xFunction* >::iterator it; 00145 for ( it = functionPtrs_.begin(); it != functionPtrs_.end(); it++) { 00146 delete *it; 00147 } 00148 } 00149 00150 enum HAL::SlotContents HAL::VMESlot::getContents() const { 00151 return contents_; 00152 } 00153 00154 std::string HAL::VMESlot::getTypeId() const { 00155 return typeId_; 00156 } 00157 00158 std::string HAL::VMESlot::getSerialNumber() const { 00159 return serialNumber_; 00160 } 00161 00162 uint32_t HAL::VMESlot::getSlotId() const { 00163 return slotId_; 00164 } 00165 00166 00167 HAL::VMEDevice* HAL::VMESlot::getVMEDevice() const 00168 throw( HAL::IllegalOperationException, 00169 HAL::IllegalValueException, 00170 HAL::UnsupportedException, 00171 HAL::BusAdapterException, 00172 HAL::NoSuchItemException ) { 00173 00174 HAL::VMEDevice* module; 00175 00176 if ( contents_ == EMPTY ) { 00177 std::stringstream text; 00178 text << "This slot (" << std::dec << slotId_ 00179 << "is empty and contains no module" 00180 << "\n (HAL::VMESlot::getVMEDevice)" << std::ends; 00181 throw( HAL::IllegalOperationException( text.str(), __FILE__, __LINE__, __FUNCTION__ ) ); 00182 } 00183 00184 HAL::VMEAddressTable& addressTable = 00185 addressTableContainer_.getVMETableFromSerialNumber( serialNumber_ ); 00186 00187 // VME64x module: 00188 if ( contents_ == VME64x ) { 00189 00190 checkVME64xTable( addressTable ); 00191 // try to build the module if not yet there: 00192 std::vector <uint32_t> baseaddresses(NUMBER_OF_VME64XFUNCTIONS); 00193 for ( int ic=0; ic<NUMBER_OF_VME64XFUNCTIONS; ic++ ) { 00194 if (windowVector_[ic]) { 00195 baseaddresses[ic] = windowVector_[ic]->getBaseaddress(); 00196 } else { 00197 baseaddresses[ic] = 0; 00198 } 00199 } 00200 00201 module = new HAL::VME64xDevice( addressTable, 00202 *busAdapterPtr_, 00203 baseaddresses, 00204 false, 00205 *this ); 00206 00207 // normal VME module: 00208 } else { 00209 uint32_t baseaddress = moduleMapper_.getBaseaddress( serialNumber_ ); 00210 module = new HAL::VMEDevice( addressTable, 00211 *busAdapterPtr_, 00212 baseaddress ); 00213 } 00214 00215 return module; 00216 } 00217 00218 00219 // nothing should go wrong here since if the constructor survived 00220 // there should be 8 valid VME64Function* in the functionPtrs_. 00221 std::list< HAL::VME64xFunction* > HAL::VMESlot::getImplementedFunctions() const { 00222 std::list< HAL::VME64xFunction* > result; 00223 std::list< HAL::VME64xFunction* >::const_iterator it; 00224 for ( it = functionPtrs_.begin(); it != functionPtrs_.end(); it++ ) { 00225 if ( (*it)->isImplemented() ) { 00226 result.push_back( *it ); 00227 } 00228 } 00229 return result; 00230 } 00231 00232 void HAL::VMESlot::checkVME64xTable( HAL::VMEAddressTable& table ) const 00233 throw (HAL::IllegalValueException) { 00234 00235 // First go through the items of the table and see if the AMs in the 00236 // table are really offered by the corresponding function. In case 00237 // of standard VME modules there is one single function implemented of which 00238 // the configuration-settings are given to this class in the constructor. 00239 // This might have been done already during the mapping of the crate. 00240 // But it depends on the chosen strategy so it is better to check it 00241 // here once just before the HAL::VMEDevice is created. 00242 uint32_t mapId; 00243 __gnu_cxx::hash_map<std::string, HAL::AddressTableItem*, HAL::HalHash<std::string> >::const_iterator it; 00244 for ( it=table.getItemListBegin(); it != table.getItemListEnd(); it++ ) { 00245 mapId = (*it).second->getGeneralHardwareAddress().getMapId(); 00246 00247 // is the function implemented and configured ? 00248 if ( ! ( windowVector_[mapId] && windowVector_[mapId]->isConfigured() ) ) { 00249 std::stringstream text; 00250 text << "HAL::AddressTableItem " << (*it).first 00251 << " uses non-implemented or not-configured function " << std::dec << mapId 00252 << ".\n (HAL::VMESlot::checkVME64xTable)" << std::ends; 00253 throw( HAL::IllegalValueException( text.str(), __FILE__, __LINE__, __FUNCTION__ ) ); 00254 } 00255 00256 // configure the HardwareAddress to work with the correct AM and dataWidth: 00257 00258 uint32_t AM = windowVector_[mapId]->getAM(); 00259 uint32_t width = windowVector_[mapId]->getDataAccessWidth(); 00260 try { 00261 HAL::VME64xHardwareAddress& vme64xAddress = 00262 dynamic_cast< HAL::VME64xHardwareAddress& >((*it).second->getGeneralHardwareAddress()); 00263 00264 // nothing needs to be done for configspace since the am is already set correctly in the 00265 // constructor of the vme64xhardwareaddress and the width has also been set already. 00266 if ( vme64xAddress.isMemorySpace() ) { 00267 vme64xAddress.setWindowConfiguration( AM, width ); 00268 } 00269 } catch ( std::bad_cast ) { 00270 std::stringstream text; 00271 text << "The address table does not contain VME64x items!" 00272 << "\n (HAL::VMESlot::checkVME64xTable)" << std::ends; 00273 throw( HAL::IllegalValueException( text.str(), __FILE__, __LINE__, __FUNCTION__ )); 00274 } 00275 } 00276 00277 00278 // now that the data widths have been set for all items in the 00279 // address table the boundaries for the various base addresses 00280 // have to be redetermined. 00281 table.determineAddressBoundaries(); 00282 00283 // Now check the limits of the address tables against what is 00284 // demanded by the functions in the hardware. This test only has 00285 // to be done for VME64x modules. It must be done after the data 00286 // widths have been set for the various address map items since the 00287 // width is needed in the calculation of address boundaries in the 00288 // call "table.getAddressBoundaries". 00289 if ( contents_ == VME64x ) { 00290 std::vector< uint32_t > minAddresses, maxAddresses; 00291 table.getAddressBoundaries( minAddresses, maxAddresses ); 00292 00293 // loop over all functions of this slot 00294 std::list< HAL::VME64xFunction* >::const_iterator itf; 00295 for ( itf = functionPtrs_.begin(); itf != functionPtrs_.end(); itf++ ) { 00296 00297 // loop over all mapped windows of the function 00298 std::list< HAL::VME64xMappedWindow* > windowList = (*itf)->getMappedWindowPtrList(); 00299 std::list< HAL::VME64xMappedWindow* >::const_iterator itw; 00300 for ( itw = windowList.begin(); itw != windowList.end(); itw++ ) { 00301 00302 uint32_t windowDemand = 1 << (*itw)->getAddressRank(); 00303 uint32_t windowId = (*itw)->getMappedWindowId(); 00304 00305 if ( windowDemand <= maxAddresses[windowId] ) { 00306 std::stringstream text; 00307 text << "mapped window number " << std::dec << windowId 00308 << " demands less memory than required in HAL::AddressTable " 00309 << "(hex):\n" << std::hex << std::setw(8) << std::setfill('0') << windowDemand 00310 << " <= " << maxAddresses[windowId] 00311 << "\n (HAL::VMESlot::checkVME64xTable)" << std::ends; 00312 throw( HAL::IllegalValueException( text.str(), __FILE__, __LINE__, __FUNCTION__ )); 00313 } 00314 } 00315 } 00316 } 00317 00318 } 00319 00320 00321 void HAL::VMESlot::stdConfigRead( std::string item, 00322 uint32_t* resultPtr, 00323 uint32_t offset ) const 00324 throw( HAL::NoSuchItemException, 00325 HAL::IllegalOperationException, 00326 HAL::BusAdapterException ) 00327 { 00328 if ( ! configAdapterPtr_ ) 00329 { 00330 std::stringstream text; 00331 text << "No ConfigurationSpace Adapter available for slot " << std::dec << slotId_ 00332 << " .\nProbbably this means that there is no VME64x modules plugged into this slot." 00333 << std::ends; 00334 throw( HAL::IllegalOperationException( text.str(), __FILE__, __LINE__, __FUNCTION__ )); 00335 } 00336 configAdapterPtr_->configRead( item, slotId_, resultPtr, offset ); 00337 } 00338 00339 void HAL::VMESlot::stdConfigWrite( std::string item, 00340 uint32_t data, 00341 HalVerifyOption verifyFlag, 00342 uint32_t offset ) const 00343 throw( HAL::NoSuchItemException, 00344 HAL::IllegalOperationException, 00345 HAL::BusAdapterException ) 00346 { 00347 if ( ! configAdapterPtr_ ) 00348 { 00349 std::stringstream text; 00350 text << "No ConfigurationSpace Adapter available for slot " << std::dec << slotId_ 00351 << " .\nProbbably this means that there is no VME64x modules plugged into this slot." 00352 << std::ends; 00353 throw( HAL::IllegalOperationException( text.str(), __FILE__, __LINE__, __FUNCTION__ )); 00354 } 00355 configAdapterPtr_->configWrite( item, slotId_, data, verifyFlag, offset ); 00356 }