Generic hardware access library
|
00001 #include "hal/VME64xCrate.hh" 00002 #include <sstream> 00003 #include <iomanip> 00004 #include <list> 00005 00006 HAL::VME64xCrate::VME64xCrate( HAL::VMEBusAdapterInterface& busAdapter, 00007 HAL::AddressTableContainerInterface& addressTableContainer, 00008 HAL::ModuleMapperInterface& moduleMapper) 00009 throw( HAL::HardwareProblemException, 00010 HAL::IllegalValueException, 00011 HAL::UnsupportedException) 00012 : mapped_(false), 00013 busAdapter_ ( busAdapter ), 00014 addressTableContainer_( addressTableContainer ), 00015 moduleMapper_( moduleMapper ), 00016 vmeConfigSpaceHandler_( busAdapter_ ), 00017 slotPtrVector_(MAX_NUMBER_OF_SLOTS) { 00018 00019 // Set default values for all pointers (this is used later in the 00020 // function which populates the slots with plug and play modules: The 00021 // plug and play algorithm is only tried in cases for which the pointer 00022 // to the slot Object is NULL. 00023 for ( int i=0; i<MAX_NUMBER_OF_SLOTS; i++ ) { 00024 slotPtrVector_[i] = (HAL::VMESlot*)0; 00025 } 00026 00027 configurePlugAndPlay(); 00028 } 00029 00030 HAL::VME64xCrate::VME64xCrate( HAL::VMEBusAdapterInterface& busAdapter, 00031 HAL::AddressTableContainerInterface& addressTableContainer, 00032 HAL::ModuleMapperInterface& moduleMapper, 00033 const HAL::StaticVMEConfiguration& staticConfiguration ) 00034 throw( HAL::HardwareProblemException, 00035 HAL::IllegalValueException, 00036 HAL::UnsupportedException ) 00037 : mapped_(false), 00038 busAdapter_ ( busAdapter ), 00039 addressTableContainer_( addressTableContainer ), 00040 moduleMapper_( moduleMapper ), 00041 vmeConfigSpaceHandler_( busAdapter_ ), 00042 slotPtrVector_(MAX_NUMBER_OF_SLOTS) { 00043 00044 // Set default values for all pointers (this is used later in the 00045 // function which populates the slots with plug and play modules: The 00046 // plug and play algorithm is only tried in cases for which no static 00047 // configuration has been given. This allows to inhibit the plug and 00048 // play mechanism for not correctly working modules by giving a static 00049 // configuration for the module. The initialization in addition allows 00050 // to check that there are not two items in the static configuration 00051 // for the same slot. 00052 for ( int i=0; i<MAX_NUMBER_OF_SLOTS; i++ ) { 00053 slotPtrVector_[i] = (HAL::VMESlot*)0; 00054 } 00055 00056 // Evaluate the static Configuration and populate the slots 00057 // which contain static VME configuration items. 00058 populateWithStaticConfiguration(staticConfiguration); 00059 00060 configurePlugAndPlay(); 00061 } 00062 00063 void HAL::VME64xCrate::configurePlugAndPlay() 00064 throw( HAL::IllegalValueException, 00065 HAL::UnsupportedException ) { 00066 // check Amnesia address first 00067 if ( vmeConfigSpaceHandler_.containsVME64xModule( 0x1e ) ) { 00068 std::stringstream text; 00069 text << "Module at Amnesia address 0x1e found. Correct the hardware error first" 00070 << std::ends; 00071 throw( HAL::HardwareProblemException( text.str() ) ); 00072 } 00073 00074 // Populate the slots which contain plug and play modules. Afterwards there is 00075 // a (poosible empty) HAL::VMESlot object for every possible slot. 00076 populateWithPlugAndPlay(); 00077 00078 // Build the memory Map of the crate: 00079 mapCrate(); 00080 00081 // Finally enable the VME64xModules 00082 enablePlugAndPlayModules(); 00083 00084 // sort the list of occupied address space 00085 occupiedItemList_.sort( MappedItemSorter() ); 00086 } 00087 00088 HAL::VMEDevice* HAL::VME64xCrate::getVMEDevice( uint32_t slotId ) const 00089 throw ( HAL::IllegalOperationException, 00090 HAL::IllegalValueException, 00091 HAL::UnsupportedException, 00092 HAL::BusAdapterException, 00093 HAL::NoSuchItemException ) { 00094 if (slotPtrVector_[slotId]->getContents() != SlotContents(EMPTY) ) { 00095 return slotPtrVector_[slotId]->getVMEDevice(); 00096 } 00097 return (HAL::VMEDevice*)0; 00098 } 00099 00100 00101 HAL::VMESlot* HAL::VME64xCrate::getVMESlot( uint32_t slotId ) const 00102 throw (HAL::IllegalValueException) { 00103 if ( slotId > MAX_NUMBER_OF_SLOTS ) { 00104 std::stringstream text; 00105 text << "Illegal slot Id : " << std::dec << slotId 00106 << " (must be less than " << MAX_NUMBER_OF_SLOTS << ")" 00107 << "\n (HAL::VME64xCrate::getVMESlot)" << std::ends; 00108 throw( HAL::IllegalValueException( text.str(), __FILE__, __LINE__, __FUNCTION__ ) ); 00109 } 00110 return slotPtrVector_[ slotId ]; 00111 } 00112 00113 00114 void 00115 HAL::VME64xCrate::populateWithStaticConfiguration( const HAL::StaticVMEConfiguration& staticConfiguration ) 00116 throw( HAL::IllegalValueException ) { 00117 HAL::VMESlot *newSlotPtr; 00118 std::list< HAL::StaticVMEItem* >::const_iterator it; 00119 for ( it = staticConfiguration.getListBegin(); 00120 it != staticConfiguration.getListEnd(); 00121 it++ ) { 00122 newSlotPtr = new HAL::VMESlot( *it, 00123 &busAdapter_, 00124 addressTableContainer_, 00125 moduleMapper_ ); 00126 // put the slot in the vector 00127 uint32_t slotId = (*it)->getSlotId(); 00128 if ( slotPtrVector_[ slotId ] ) { 00129 std::stringstream text; 00130 text << "Static configuration contains more than one entry for slot number" 00131 << std::dec << slotId 00132 << "\n (HAL::VME64xCrate::populateWithStaticConfiguration)" << std::ends; 00133 throw( HAL::IllegalValueException( text.str(), __FILE__, __LINE__, __FUNCTION__ ) ); 00134 } 00135 slotPtrVector_[ slotId ] = newSlotPtr; 00136 } 00137 } 00138 00139 00140 // only populate slots for which no static configuration has been given. 00141 // This enables to give the configuration for not correctly designed modules 00142 // by hand. This method makes sure that there is a HAL::VMESlot object for each 00143 // possible slot (it might be empty though) 00144 void HAL::VME64xCrate::populateWithPlugAndPlay() 00145 throw ( HAL::IllegalValueException, 00146 HAL::UnsupportedException ) { 00147 00148 HAL::VMESlot *newSlotPtr; 00149 00150 for ( int iSlot = 0; iSlot < MAX_NUMBER_OF_SLOTS; iSlot++ ) { 00151 if ( ! slotPtrVector_[ iSlot ] ) { 00152 newSlotPtr = new HAL::VMESlot( iSlot, 00153 &vmeConfigSpaceHandler_, 00154 addressTableContainer_, 00155 moduleMapper_ ); 00156 slotPtrVector_[iSlot] = newSlotPtr; 00157 } 00158 } 00159 } 00160 00161 void HAL::VME64xCrate::getAllWindows() { 00162 std::vector< HAL::VMESlot* >::const_iterator it; 00163 for ( it = slotPtrVector_.begin(); it != slotPtrVector_.end(); it++ ) { 00164 std::list< HAL::VME64xFunction* > functions = (*it)->getImplementedFunctions(); 00165 std::list< HAL::VME64xFunction* >::iterator funcIt; 00166 for( funcIt = functions.begin(); funcIt != functions.end(); funcIt++ ) { 00167 std::list<HAL::VME64xMappedWindow*> funcVectors = (*funcIt)->getMappedWindowPtrList(); 00168 windowList_.insert( windowList_.end(), funcVectors.begin(), funcVectors.end() ); 00169 } 00170 } 00171 WindowSorter sortFunctor; 00172 windowList_.sort(sortFunctor); 00173 makeOccupiedList(); 00174 } 00175 00176 // in principle one could map the A32 A24 A16 address spaces that they 00177 // overlap. But care should be taken since this could conflict with 00178 // standard vme modules which could respond to various address modifiers. 00179 // So the most stupid but most save algorithm is to first detemine 00180 // where the standard vme modules are and block the taken address space for 00181 // all AMs. Then the VME64x modules can be mapped around them. 00182 // 00183 void HAL::VME64xCrate::mapCrate() { 00184 // preparation: get a list of all windows mapped or to be mapped. 00185 // sort this list according to the requested address-space. 00186 // then fill the occupiedItemList_ with those windows which belong 00187 // to standard VME modules. This is done in one function: 00188 getAllWindows( ); 00189 // initialize constants: 00190 uint32_t A32Base = 0x00000000; 00191 uint32_t A24Base = 0x1000000; 00192 uint32_t A16Base = 0x10000; 00193 uint32_t A32Min = 0x1000000; 00194 uint32_t A24Min = 0x10000; 00195 uint32_t A16Min = 0x0; 00196 00197 // loop over all windows starting with the ones which need most memory: 00198 // independently map the three address spaces 00199 // Static windoes are not mapped since they respond with false to all 00200 // the canAxx() requests. 00201 std::list< HAL::VME64xMappedWindow * >::reverse_iterator winIt; 00202 for ( winIt = windowList_.rbegin(); winIt != windowList_.rend(); winIt++ ) { 00203 if ( (*winIt)->canA32() ) { 00204 mapWindow( *winIt, A32Base, A32Min ); 00205 } else if( (*winIt)->canA24() ) { 00206 mapWindow( *winIt, A24Base, A24Min ); 00207 } else if( (*winIt)->canA16() ) { 00208 mapWindow( *winIt, A16Base, A16Min ); 00209 } 00210 } 00211 mapped_ = true; 00212 } 00213 00214 void HAL::VME64xCrate::mapWindow( HAL::VME64xMappedWindow* windowPtr, 00215 uint32_t base, 00216 uint32_t baseMin ) { 00217 uint32_t rank = windowPtr->getAddressRank(); 00218 uint32_t space = 1 << rank; 00219 bool mapped = false; 00220 00221 // simulate a 33rd bit in the address in order to get rid of problems in case of A32: 00222 bool bit33 = true; 00223 while ( (!mapped) && ((base > space) || bit33) && ((base - space) > baseMin) ) { 00224 base = base - space; 00225 if( ! isOccupied( base, space, bit33) ) { 00226 MappedItem *item = new MappedItem(); 00227 item->baseAddress = base; 00228 item->startAddress = base; 00229 item->endAddress = base + space - 1; 00230 item->windowPtr = windowPtr; 00231 item->configured = true; 00232 occupiedItemList_.push_back( item ); 00233 uint32_t am = windowPtr->getSortedAMCAPList().front(); 00234 windowPtr->setADER( base, am); 00235 mapped = true; 00236 } 00237 bit33 = false; 00238 } 00239 if ( ! mapped ) { 00240 notMappedList_.push_back( windowPtr ); 00241 } 00242 } 00243 00248 bool HAL::VME64xCrate::isOccupied( uint32_t base, uint32_t space, bool bit33 ) { 00249 std::list< struct MappedItem * >::const_iterator it ; 00250 // as soon as an item is found which overlaps with the proposed base address 00251 // return true. 00252 for ( it=occupiedItemList_.begin(); it != occupiedItemList_.end(); it++ ) { 00253 // cout << hex << base << " " << space << " " << bit33 << " " << (*it)->startAddress << " " << (*it)->endAddress << endl; 00254 00255 // check for overlap: 1) check if the start address (=base) is in the range between the start- and endaddress of item 00256 // 2) check if the end address (=base + space) is in the range between the start- and endaddress of item 00257 if ( ((base <= (*it)->endAddress ) && base >= (*it)->startAddress ) || 00258 (((base + space - 1) <= (*it)->endAddress ) && (base + space - 1) >= (*it)->startAddress ) ) { 00259 // if ( ((base <= (*it)->endAddress || bit33) && base >= (*it)->startAddress ) || 00260 // (((base + space - 1) <= (*it)->endAddress || bit33) && (base + space - 1) >= (*it)->startAddress ) ) { 00261 //cout << "true" << endl; 00262 return true; 00263 } 00264 } 00265 //cout << "false" << endl; 00266 return false; 00267 } 00268 00269 // occupied windows are removed from the windowList_. 00270 // This is important in case that a crate is tried to be mapped 00271 // more than once. (E.g. by different applications or processes) 00272 void HAL::VME64xCrate::makeOccupiedList() { 00273 std::list< HAL::VME64xMappedWindow* > newList; 00274 std::list< HAL::VME64xMappedWindow* >::iterator it; 00275 struct MappedItem* item; 00276 for ( it = windowList_.begin(); it!= windowList_.end(); it++ ) { 00277 if ( (*it)->isConfigured() ) { 00278 item = new MappedItem(); 00279 item->baseAddress = (*it)->getBaseaddress(); 00280 item->startAddress = (*it)->getBaseaddress(); 00281 item->endAddress = item->baseAddress + (1 << (*it)->getAddressRank()) - 1; 00282 item->windowPtr = (*it); 00283 item->configured = true; 00284 occupiedItemList_.push_back( item ); 00285 } else { 00286 newList.push_back( *it ); 00287 } 00288 } 00289 windowList_ = newList; 00290 } 00291 00292 void HAL::VME64xCrate::enablePlugAndPlayModules() 00293 throw (HAL::IllegalOperationException ) { 00294 if ( ! mapped_ ) { 00295 std::stringstream text; 00296 text << "The crate has not yet mapped the memory space and therefore the\n" 00297 << "modules cannot be enabled!\n (HAL::VME64xCrate::enablePlugAndPlayModules)" 00298 << std::ends; 00299 throw( HAL::IllegalOperationException( text.str(), __FILE__, __LINE__, __FUNCTION__ ) ); 00300 } 00301 std::vector< HAL::VMESlot* >::iterator it; 00302 for ( it=slotPtrVector_.begin(); it != slotPtrVector_.end(); it++ ) { 00303 if ((*it)->getContents() == (SlotContents)VME64x ) { 00304 vmeConfigSpaceHandler_.enableVME64xModule( (*it)->getSlotId() ); 00305 } 00306 } 00307 } 00308 00309 void HAL::VME64xCrate::printAddressMap( std::ostream& out ) const { 00310 if ( notMappedList_.size() > 0 ) { 00311 out << "\n\nWARNING: the following items could not be mapped\n"; 00312 std::list< const HAL::VME64xMappedWindow* >::const_iterator itN; 00313 for( itN = notMappedList_.begin(); itN != notMappedList_.end(); itN++ ) { 00314 out << " slot Id : " << (*itN)->getSlotId() 00315 << " function Id : " << (*itN)->getFunctionId() 00316 << " map Id : " << (*itN)->getMappedWindowId(); 00317 } 00318 } 00319 00320 out << "\n\nList of mapped items (ordered by address space size) :\n\n"; 00321 std::list< struct MappedItem * >::const_iterator itM; 00322 for ( itM = occupiedItemList_.begin(); itM!= occupiedItemList_.end(); itM++ ) { 00323 uint32_t slotId = (*itM)->windowPtr->getSlotId(); 00324 uint32_t functionId = (*itM)->windowPtr->getFunctionId(); 00325 uint32_t mapId = (*itM)->windowPtr->getMappedWindowId(); 00326 uint32_t AM = (*itM)->windowPtr->getAM(); 00327 std::string serialNumber = slotPtrVector_[ slotId ]->getSerialNumber(); 00328 std::string typeId = slotPtrVector_[ slotId ]->getTypeId(); 00329 00330 // This is necessary since somehow setw gets confused if there are words containing 00331 // digits or +- signs. (It seems at least...) 00332 std::string text; 00333 text = " | type : " + typeId + " serial : " + serialNumber; 00334 uint32_t size = text.length(); 00335 int diff = 78-size; 00336 for ( ; diff > 0; diff-- ) text += " "; 00337 text += "|"; 00338 00339 out << std::hex << std::setw(8) << std::setfill('0') << (*itM)->endAddress; 00340 out <<" ---------------------------------------------------------------------\n" 00341 <<" | |\n" 00342 << text << "\n" 00343 <<" | |\n" 00344 <<" | slot ID : " << std::setw(2) << slotId << " |\n" 00345 <<" | function : " << std::setw(2) << functionId << " |\n" 00346 <<" | map ID : " << std::setw(2) << mapId << " |\n" 00347 <<" | AM : " << std::setw(2) << std::setfill('0') << AM << " |\n" 00348 <<" | |\n" 00349 << std::hex << std::setw(8) << std::setfill('0') << (*itM)->startAddress 00350 <<" ---------------------------------------------------------------------\n"; 00351 } 00352 out << "\n\n" << std::endl; 00353 }