Generic hardware access library
/home/cschwick/hal/generic/src/common/PCIAddressTable.cc
Go to the documentation of this file.
00001 #include "hal/PCIAddressTable.hh"
00002 #include <sstream>
00003 #include <iomanip>
00004 #include <vector>
00005 
00006 HAL::PCIAddressTable::PCIAddressTable( std::string name, 
00007                                        HAL::AddressTableReader& tableReader ) 
00008   : HAL::AddressTable( name ) {
00009   HAL::AddressTableItem* newTableItem;
00010   // fill the itemMap 
00011   while ( tableReader.next( &newTableItem ) ) {
00012     itemMap[newTableItem->getKey()] = newTableItem;
00013   }
00014   determineAddressBoundaries();
00015 }
00016 
00017 HAL::PCIAddressTable::~PCIAddressTable() {
00018 }
00019 
00020 void HAL::PCIAddressTable::print( std::ostream& os ) const {
00021   __gnu_cxx::hash_map<std::string, HAL::AddressTableItem*, HAL::HalHash<std::string> >::const_iterator it;
00022   os << "\n******************************************************************************************************" << std::endl;
00023   os << "*                   PCI Address Table : " << name << std::endl;
00024   os << "*                         item       AdrSpace BAR  address      mask  r  w  description"<< std::endl;
00025   os << "******************************************************************************************************" << std::endl;
00026   for( it=itemMap.begin(); it!=itemMap.end(); it++ ) {
00027     (*it).second->print();
00028   }
00029   os << "******************************************************************************************************\n" << std::endl;
00030  }
00031 
00032 void HAL::PCIAddressTable::getAddressBoundaries( uint32_t& minConfigAddress,
00033                                                  uint32_t& maxConfigAddress,
00034                                                  std::vector<uint32_t>& minAddresses,
00035                                                  std::vector<uint32_t>& maxAddresses ) const {
00036   minConfigAddress = minConfigAddress_;
00037   maxConfigAddress = maxConfigAddress_;
00038   minAddresses = minAddresses_;
00039   maxAddresses = maxAddresses_;
00040 }
00041 
00042 void HAL::PCIAddressTable::checkAddressLimits( std::string item,
00043                                           uint32_t offset ) const
00044   throw( HAL::NoSuchItemException,
00045          HAL::AddressOutOfLimitsException ) {
00046   const HAL::GeneralHardwareAddress& pciAddress = getGeneralHardwareAddress( item );
00047   uint32_t address = pciAddress.getAddress() + offset;
00048   uint32_t width = pciAddress.getDataWidth();
00049   if ( ( pciAddress.isConfigSpace() && 
00050          ( (address + width - 1) > maxConfigAddress_ || address < minConfigAddress_) ) || 
00051        ( pciAddress.isMemorySpace() && 
00052          ( (address + width - 1) > maxAddresses_[pciAddress.getMapId()] || address < minAddresses_[pciAddress.getMapId()]) )) {
00053     std::stringstream text;
00054     text << "The address is outside of the HAL::AddressTable range: \n"
00055                  << "               HAL::AddressTable : " << name << "\n"
00056                  << "                       item : " << item << "\n"
00057                  << "               offset (hex) : " << std::hex << offset << "\n"
00058                  << std::ends;
00059     throw ( HAL::AddressOutOfLimitsException( text.str(), __FILE__, __LINE__, __FUNCTION__ ) );
00060   }
00061 }
00062 
00063 void HAL::PCIAddressTable::checkAddressLimits( const HAL::GeneralHardwareAddress& pciAddress,
00064                                           uint32_t offset ) const
00065   throw( HAL::AddressOutOfLimitsException ) {
00066   uint32_t address = pciAddress.getAddress() + offset;
00067   uint32_t width = pciAddress.getDataWidth();
00068   if ( ( pciAddress.isConfigSpace() && 
00069          ( (address + width - 1) > maxConfigAddress_ || address < minConfigAddress_) ) || 
00070        ( pciAddress.isMemorySpace() && 
00071          ( (address + width - 1) > maxAddresses_[pciAddress.getMapId()] || address < minAddresses_[pciAddress.getMapId()]) )) {
00072     std::stringstream text;
00073     text << "The address is outside of the HAL::AddressTable range: \n"
00074          << "              HAL::AddressTable : " << name << "\n"
00075          << "              address (hex): " << std::hex << pciAddress.getAddress() << "\n"
00076          << "               offset (hex): " << std::hex << offset << "\n"
00077          << std::ends;
00078     throw ( HAL::AddressOutOfLimitsException( text.str(), __FILE__, __LINE__, __FUNCTION__ ) );
00079   }
00080 }
00081 
00082 void HAL::PCIAddressTable::determineAddressBoundaries() {
00083   __gnu_cxx::hash_map<std::string, HAL::AddressTableItem*, HAL::HalHash<std::string> >::const_iterator it;
00084   uint32_t address, barId;
00085   std::string key;
00086 
00087   // initialize the address boundary variables for the 
00088   // sorting algorithm below. The AddressesBoundaries for
00089   // each BAR are of course determined separately.
00090   maxConfigAddress_ = 0;
00091   minConfigAddress_ = ~0x00;
00092   for ( int ic = 0; ic < 6; ic++ ) {
00093         maxAddresses_.push_back(0);
00094         minAddresses_.push_back(~0x00);
00095   }
00096 
00097   // sort algorithm: scan all items in the AddressMap and 
00098   // memorize the largest and smallest addresses in configuration
00099   // space and memory space. 
00100   for ( it = itemMap.begin(); it != itemMap.end(); it++ ) {
00101     key = (*it).second->getKey();
00102     const HAL::GeneralHardwareAddress& pciAddress = getGeneralHardwareAddress( key );
00103       address = pciAddress.getAddress();
00104     if ( pciAddress.isConfigSpace() ) {
00105       if ( address >= maxConfigAddress_ ) maxConfigAddress_ = 
00106                                            address + pciAddress.getDataWidth() - 1;
00107           if ( address < minConfigAddress_ ) minConfigAddress_ = address;
00108     } else if ( pciAddress.isMemorySpace() ) {
00109       barId = pciAddress.getMapId();
00110       if ( address >= maxAddresses_[barId] ) maxAddresses_[barId] = 
00111                                               address + pciAddress.getDataWidth() - 1;
00112       if ( address < minAddresses_[barId] ) minAddresses_[barId] = address;
00113     }
00114   }  
00115 }