Generic hardware access library
/home/cschwick/hal/generic/src/common/VME64xMappedWindow.cc
Go to the documentation of this file.
00001 #include "hal/VME64xMappedWindow.hh"
00002 #include <sstream>
00003 #include <iomanip>
00004 
00005 HAL::VME64xMappedWindow::VME64xMappedWindow( uint32_t slotId,
00006                                              uint32_t functionId,
00007                                              uint32_t mappedWindowId, 
00008                                              HAL::VMEConfigurationSpaceHandler* vmeConfigurationSpaceHandler )
00009   throw( HAL::NoSuchItemException, 
00010          HAL::IllegalOperationException,
00011          HAL::BusAdapterException,
00012          HAL::UnsupportedException,
00013          HAL::IllegalValueException )
00014   : slotId_( slotId ),
00015     functionId_( functionId ),
00016     mappedWindowId_( mappedWindowId ),
00017     vmeConfigurationSpaceHandlerRef_( vmeConfigurationSpaceHandler ) {
00018   
00019   // set the default values
00020   AM_ = 0;
00021   baseaddress_ = 0;
00022   ADER_ = 0;
00023   ADEM_ = 0;
00024   addressRank_ = 0;
00025   DAWPR_ = 0;
00026   canA32_ = false;
00027   canA24_ = false;
00028   canA16_ = false;
00029   dataAccessWidth_ = 0;
00030   configured_ = false;
00031   implemented_ = false;
00032 
00033   
00034   uint32_t amCapHigh, amCapLow;
00035   // retrieve raw function data from config space: The ADER is also read
00036   // in case one day we want to support fixed address functions (FAFs).
00037   std::stringstream ademItem;
00038   ademItem << "ADEM-F" << mappedWindowId;
00039   vmeConfigurationSpaceHandlerRef_->configRead(ademItem.str(), slotId, &ADEM_);
00040   std::stringstream widthItem;
00041   widthItem << "dataAccessWidth-F" << mappedWindowId;
00042   vmeConfigurationSpaceHandlerRef_->configRead(widthItem.str(), slotId, &DAWPR_);
00043   std::stringstream amcapLowItem;
00044   amcapLowItem << "AMCAP-F" << mappedWindowId << "-1";
00045   vmeConfigurationSpaceHandlerRef_->configRead(amcapLowItem.str(), slotId, &amCapHigh);
00046   std::stringstream amcapHighItem;
00047   amcapHighItem << "AMCAP-F" << mappedWindowId << "-0";
00048   vmeConfigurationSpaceHandlerRef_->configRead(amcapHighItem.str(), slotId, &amCapLow);
00049 
00050   // check if this function is implemented at all:
00051   if ( ADEM_ == 0x00 ) {
00052         return;
00053   }
00054   
00055   // decode the access width: 
00056   switch ( DAWPR_ ) {
00057   case 0x81:
00058   case 0x82:
00059         dataAccessWidth_ = 1;
00060         break;
00061   case 0x83:
00062         dataAccessWidth_ = 2;
00063         break;
00064   case 0x84:
00065         dataAccessWidth_ = 4;
00066         break;
00067   default:
00068         std::stringstream text;
00069         text << "DAWPR of " << std::hex << std::setw(2) << std::setfill('0') 
00070              << DAWPR_ << " is not supported (slot " << std::dec << slotId_ << ")\n"
00071              << "    (HAL::VME64xFunction::HAL::VME64xFunction)" << std::ends;
00072         throw( HAL::UnsupportedException( text.str(), __FILE__, __LINE__, __FUNCTION__ ) );
00073   }
00074   
00075   // build the unsorted list of valid Address Modifiers
00076   for ( int ic=0; ic<32; ic++ ) {
00077         if ( amCapHigh & (1<<ic) ) {
00078       AMCAP_.push_back( ic+32 );
00079       setAddressCapability(ic+32);
00080     }
00081         if ( amCapLow & (1<<ic) ) {
00082       AMCAP_.push_back( ic );
00083       setAddressCapability(ic);
00084     }
00085   }
00086   
00087   // Sort the list. The list should be sorted according to the criteria 
00088   // of preference which one to use: During the mapping od Plug and Play
00089   // modules the software must determine which AM to use out of the ones
00090   // offered by the module. The sorting procedure will put the one which
00091   // is the most desirable as the first AM. It is a Functor which defines
00092   // the order of the AMs.
00093   
00094   //  HAL::AMSortFunctor amSortFunctor;
00095   AMCAP_.sort( HAL::AMSortFunctor() );
00096   // calculate rank of needed Address Space
00097   if ( ADEM_ & 8 ) {
00098         std::stringstream text;
00099         text << "Fixed Address Functions are not supported by this software (slot " 
00100              << std::dec << slotId_ << ")\n"
00101              << "    (HAL::VME64xFunction::HAL::VME64xFunction)" << std::ends;
00102         throw( HAL::UnsupportedException( text.str(), __FILE__, __LINE__, __FUNCTION__ ));
00103   }
00104   if ( ADEM_ & 4 ) {
00105         std::stringstream text;
00106         text << "Dynamic Function sizing is not supported by this software (slot " 
00107              << std::dec << slotId_ << ")\n"
00108              << "   (HAL::VME64xFunction::HAL::VME64xFunction)" << std::ends;
00109         throw( HAL::UnsupportedException( text.str(), __FILE__, __LINE__, __FUNCTION__ ));
00110   }
00111   if ( ADEM_ & 1 ) {
00112         std::stringstream text;
00113         text << "64(40) bit addresses are not supported by this software (slot " 
00114              << std::dec << slotId_ << ")\n"
00115              << "   (HAL::VME64xFunction::HAL::VME64xFunction)" << std::ends;
00116         throw( HAL::UnsupportedException( text.str(), __FILE__, __LINE__, __FUNCTION__ ));
00117   }
00118   
00119   if ( (ADEM_ & (~0x0F)) == 0 ) {
00120         std::stringstream text;
00121         text << "No decoder-bits in ADEM set (slot " << std::dec << slotId_ 
00122              << ")\n    HAL::VME64xFunction::HAL::VME64xFunction)" << std::ends;
00123         throw( HAL::IllegalValueException( text.str(), __FILE__, __LINE__, __FUNCTION__ ) );
00124   }
00125   uint32_t memSize = (~(ADEM_ & (~0x0F))) + 1;
00126   addressRank_ = 8; // smallest possible rank according to spec.
00127   while ( ((1 << addressRank_) & memSize) == 0 ) {
00128         addressRank_++;
00129   }
00130   // do not forget:
00131   implemented_ = true;
00132 
00133   // if the module is enabled it means that it has been already configured
00134   // by somebody. Therefore the mapped windows must be read out of the ADER 
00135   // registers in order to avoid reconfiguration of this crate (It could be 
00136   // in use by another process.)
00137   if ( vmeConfigurationSpaceHandlerRef_->enabled( slotId_ ) ) {
00138         configFromHardware();
00139   } 
00140 }
00141 
00142 HAL::VME64xMappedWindow::VME64xMappedWindow( uint32_t slotId, 
00143                                              uint32_t baseAddress,
00144                                              uint32_t addressRank) 
00145   : slotId_(slotId),
00146     functionId_(0),
00147     mappedWindowId_(0),
00148     AMCAP_(0),
00149     baseaddress_(baseAddress),
00150     addressRank_(addressRank) {
00151   vmeConfigurationSpaceHandlerRef_ = (HAL::VMEConfigurationSpaceHandler*)0;
00152   AM_ = 0;
00153   ADEM_ = 0;
00154   DAWPR_ = 0;
00155   canA32_ = false;
00156   canA24_ = false;
00157   canA16_ = false;
00158   dataAccessWidth_ = 0;
00159   ADER_ = 0;
00160   implemented_ = true;
00161   configured_ = true;
00162 }
00163 
00164 HAL::VME64xMappedWindow::~VME64xMappedWindow() {
00165 }
00166 
00167 void HAL::VME64xMappedWindow::setAddressCapability( uint32_t AM ) {
00168   uint32_t code = AM & 0x38;
00169   if ( code == 0x38 ) {
00170     canA24_ = true;
00171   } else if( code == 0x28 ) {
00172     canA16_ = true;
00173   } else if( code == 0x08 ) {
00174     canA32_ = true;
00175   }
00176 }
00177 
00178 uint32_t HAL::VME64xMappedWindow::getDataAccessWidth() const {
00179   return dataAccessWidth_;
00180 }
00181 
00182 uint32_t HAL::VME64xMappedWindow::getAddressRank() const {
00183   return addressRank_;
00184 }
00185 
00186 uint32_t HAL::VME64xMappedWindow::getMappedWindowId() const {
00187   return mappedWindowId_;
00188 }
00189 
00190 uint32_t HAL::VME64xMappedWindow::getFunctionId() const {
00191   return functionId_;
00192 }
00193 
00194 uint32_t HAL::VME64xMappedWindow::getSlotId() const {
00195   return slotId_;
00196 }
00197 
00198 uint32_t HAL::VME64xMappedWindow::getAM() const {
00199   return AM_;
00200 }
00201 
00202 bool HAL::VME64xMappedWindow::canA32() const {
00203   return canA32_;
00204 }
00205 
00206 bool HAL::VME64xMappedWindow::canA24() const {
00207   return canA24_;
00208 }
00209 
00210 bool HAL::VME64xMappedWindow::canA16() const {
00211   return canA16_;
00212 }
00213 
00214 uint32_t HAL::VME64xMappedWindow::getBaseaddress() const {
00215   return baseaddress_;
00216 }
00217 
00218 bool HAL::VME64xMappedWindow::isConfigured() const {
00219   return configured_;
00220 }
00221 
00222 bool HAL::VME64xMappedWindow::isImplemented() const {
00223   return implemented_;
00224 }
00225 
00226 bool HAL::VME64xMappedWindow::hasAnotherWindow() const {
00227   return ((ADEM_ & 0x02) == 0x02);
00228 }
00229 
00230 const std::list< uint32_t>& HAL::VME64xMappedWindow::getSortedAMCAPList() const {
00231   return AMCAP_;
00232 }
00233 
00234 void HAL::VME64xMappedWindow::configFromHardware() 
00235   throw( HAL::NoSuchItemException, 
00236          HAL::IllegalOperationException,
00237          HAL::UnsupportedException,
00238          HAL::BusAdapterException ) {
00239   
00240   // read from the hardware
00241   std::stringstream item;
00242   item << "ADER-F" << mappedWindowId_;
00243   vmeConfigurationSpaceHandlerRef_->configRead( item.str(), slotId_, &ADER_ );
00244 
00245   // if ADER is 0 it means that this window has not been configured. 
00246   // In this case the software should try to reconfigure the window. 
00247   // Therefore we return without setting the configured flag.
00248   if ( ADER_ == 0 ) return;
00249 
00250   // check if the XAM codes are in used (they are not supported in this software)
00251   if ( ADER_ & 0x00000001 ) {
00252         std::stringstream text;
00253         text << "XAM bit found set in ADER but XAM codes are not supported by this software (slot " 
00254              << std::dec << slotId_ << ")\n"
00255              << "   (HAL::VME64xFunction::configFromHardware)" << std::ends;
00256         throw( HAL::UnsupportedException( text.str(), __FILE__, __LINE__, __FUNCTION__ ));
00257   }
00258   AM_ = (ADER_ & 0xfc ) >> 2;
00259   baseaddress_ = ADER_ & 0xffffff00; 
00260   configured_ = true;
00261 }
00262 
00263 void HAL::VME64xMappedWindow::setADER( uint32_t baseAddress,
00264                                   uint32_t AM )
00265   throw( HAL::NoSuchItemException, 
00266          HAL::IllegalOperationException,
00267          HAL::BusAdapterException ) {
00268   
00269   if ( ! vmeConfigurationSpaceHandlerRef_ ) {
00270     std::stringstream text;
00271     text << "Cannot set ADER for Window without Configuration Space!"
00272          << "(slotId " << std::dec << slotId_ << ")" 
00273          << "\n    (HAL::VME64xMappedWindow::setADER)\n" << std::ends; 
00274     throw( HAL::IllegalOperationException( text.str(), __FILE__, __LINE__, __FUNCTION__ ) );
00275   }
00276 
00277   ADER_ = baseAddress + (AM << 2);
00278 
00279   // write it into the hardware
00280   std::stringstream item;
00281   item << "ADER-F" << mappedWindowId_;
00282   vmeConfigurationSpaceHandlerRef_->configWrite( item.str(), slotId_, ADER_ );
00283   AM_ = AM;
00284   baseaddress_ = baseAddress;
00285   configured_ = true;
00286 }