Generic hardware access library
/home/cschwick/hal/generic/src/common/PCIDevice.cc
Go to the documentation of this file.
00001 #include "hal/PCIDevice.hh"
00002 #include <sstream>
00003 #include <iomanip>
00004 
00005 HAL::PCIDevice::PCIDevice( HAL::PCIAddressTable & addressTable,
00006                            HAL::PCIBusAdapterInterface & pciBusAdapter,
00007                            uint32_t vendorID,
00008                            uint32_t deviceID,
00009                            uint32_t index,
00010                            bool swapFlag )
00011   : HAL::HardwareDevice( addressTable ),
00012     pciAddressTable( addressTable ),
00013     pciBusAdapter( pciBusAdapter ) {
00014 
00015   pciBusAdapter.findDeviceByVendor( vendorID, deviceID, index, pciAddressTable,
00016                                     &deviceIdentifierPtr, baseRegisters, swapFlag );
00017 }
00018 
00019 HAL::PCIDevice::PCIDevice( HAL::PCIAddressTable & addressTable,
00020                       HAL::PCIBusAdapterInterface & pciBusAdapter,
00021                       uint32_t vendorID,
00022                       uint32_t deviceID,
00023                       uint32_t index,
00024                       std::vector<uint32_t>& baseAddresses,
00025                       uint32_t command )
00026   : HAL::HardwareDevice( addressTable ),
00027     pciAddressTable( addressTable ),
00028     pciBusAdapter( pciBusAdapter ) {
00029 
00030   baseRegisters = baseAddresses;
00031   pciBusAdapter.findDeviceByVendor( vendorID, deviceID, index, pciAddressTable,
00032                             &deviceIdentifierPtr, baseRegisters );
00033   pciBusAdapter.configWrite(*deviceIdentifierPtr,
00034                             0x00000004,
00035                             command);
00036 }
00037 
00038 HAL::PCIDevice::PCIDevice( HAL::PCIAddressTable & addressTable,
00039                       HAL::PCIBusAdapterInterface & pciBusAdapter,
00040                       const PCILocationIdentifier& location,
00041                       bool swapFlag )
00042   : HAL::HardwareDevice( addressTable ),
00043     pciAddressTable( addressTable ),
00044     pciBusAdapter( pciBusAdapter ) {
00045 
00046   pciBusAdapter.findDeviceByBus( location.busID, location.slotID, location.functionID, 
00047                                  pciAddressTable, &deviceIdentifierPtr, baseRegisters, swapFlag );
00048 }
00049 
00050 HAL::PCIDevice::~PCIDevice() {
00051   pciBusAdapter.closeDevice( deviceIdentifierPtr );
00052 }
00053 
00054 uint32_t HAL::PCIDevice::getItemAddress( std::string item ) const 
00055   throw ( HAL::NoSuchItemException,
00056           HAL::IllegalOperationException ) {
00057   const HAL::GeneralHardwareAddress& pciAddress = 
00058     pciAddressTable.getGeneralHardwareAddress( item );
00059   if ( ! pciAddress.isMemorySpace() ) {
00060     std::string text = "Operation only allowed for Memory Space Items\n     (HAL::PCIDevice::getItemAddress)";
00061     throw (HAL::IllegalOperationException( text, __FILE__, __LINE__, __FUNCTION__ ) );
00062   }
00063   uint32_t address = pciAddress.getAddress();
00064   uint32_t barId = pciAddress.getMapId();
00065   return (address + baseRegisters[barId]);
00066 }
00067 
00068 void HAL::PCIDevice::hardwareWrite( const HAL::GeneralHardwareAddress& pciAddress, 
00069                                     uint32_t data,
00070                                     uint32_t offset ) const
00071   throw (HAL::IllegalValueException,
00072          HAL::BusAdapterException) {
00073     if ( pciAddress.isConfigSpace() ) {
00074       pciBusAdapter.configWrite( *deviceIdentifierPtr, pciAddress.getAddress() + offset, data );
00075     } else {
00076       pciBusAdapter.write( *deviceIdentifierPtr, 
00077                            pciAddress.getComputedAddress( baseRegisters) + offset,
00078                            data);
00079     }
00080 }
00081 
00082 void HAL::PCIDevice::hardwareRead( const HAL::GeneralHardwareAddress& pciAddress, 
00083                                    uint32_t* result,
00084                                    uint32_t offset ) const
00085   throw (HAL::IllegalValueException,
00086          HAL::BusAdapterException) {
00087 
00088   if ( pciAddress.isConfigSpace() ) {
00089     pciBusAdapter.configRead( *deviceIdentifierPtr, pciAddress.getAddress() + offset, result );
00090   } else {
00091     pciBusAdapter.read( *deviceIdentifierPtr, 
00092                         pciAddress.getComputedAddress( baseRegisters) + offset,
00093                         result);
00094   }
00095 }
00096 
00097 void HAL::PCIDevice::hardwareWriteBlock( const HAL::GeneralHardwareAddress& pciAddress,
00098                                          uint32_t length,
00099                                          char *buffer,
00100                                          HalAddressIncrement addressBehaviour,
00101                                          uint32_t offset) const
00102   throw (HAL::IllegalValueException, 
00103          HAL::UnsupportedException, 
00104          HAL::IllegalOperationException,
00105          HAL::BusAdapterException) {
00106 
00107   if ( !pciAddress.isMemorySpace() ) {
00108     std::string text = "Only implemented for Memory Space\n     (HAL::PCIDevice::writeBlock)";
00109     throw( HAL::IllegalOperationException( text, __FILE__, __LINE__, __FUNCTION__ ) );
00110   }
00111 
00112   if ( (length) % sizeof(uint32_t) != 0 ) {
00113     std::string text = "the length is not a multiple of the data width!\n     (HAL::PCIDevice::writeBlock)";
00114     throw( HAL::IllegalValueException( text, __FILE__, __LINE__, __FUNCTION__ ) );
00115   }
00116 
00117   uint32_t barId = pciAddress.getMapId();
00118   if ( barId < 0 || barId > 6 ) {
00119     std::stringstream text;
00120     text << "barId out of range :" << barId
00121          << "\n    must be between 0 and 5"
00122          << "\n    (HAL::PCIDevice::writeBlock)" << std::ends;
00123     throw (HAL::IllegalValueException( text.str(), __FILE__, __LINE__, __FUNCTION__ ));
00124   }
00125   if ( baseRegisters[barId]  == 0 ) {
00126     std::stringstream text;
00127     text << "barId " << std::dec << barId 
00128          << " cannot be used since it is not mapped.\n"
00129          << "    This is because no item with this barId is in the HAL::AddressTable."
00130          << "    (HAL::PCIDevice::writeBlock)" << std::ends;
00131     throw (HAL::IllegalValueException( text.str(), __FILE__, __LINE__, __FUNCTION__ ) );
00132   }
00133 
00134   uint32_t startAddress = pciAddress.getAddress() + baseRegisters[barId] + offset;
00135   if ( (startAddress) % sizeof(uint32_t) != 0 ) {
00136     std::stringstream text;
00137     text  << "the startaddress must be aligned for the data width " 
00138           << std::dec << sizeof(uint32_t) << ".\n"
00139           << "     But the start address is " 
00140           << std::hex << std::setw(8) << std::setfill('0') << startAddress 
00141           << "\n     (HAL::PCIDevice::writeBlock)" << std::ends;
00142     throw( HAL::IllegalValueException( text.str(), __FILE__, __LINE__, __FUNCTION__ ) );
00143   }
00144   pciBusAdapter.writeBlock( *deviceIdentifierPtr, 
00145                             startAddress,
00146                             length,
00147                             buffer,
00148                             addressBehaviour);
00149 }
00150 
00151 
00152 void HAL::PCIDevice::hardwareReadBlock( const HAL::GeneralHardwareAddress& pciAddress,
00153                                         uint32_t length,
00154                                         char *buffer,
00155                                         HalAddressIncrement addressBehaviour,
00156                                         uint32_t offset) const
00157   throw (HAL::IllegalValueException, 
00158          HAL::UnsupportedException, 
00159          HAL::IllegalOperationException,
00160          HAL::BusAdapterException) {
00161 
00162   if ( !pciAddress.isMemorySpace() ) {
00163     std::string text = "Only implemented for Memory Space\n     (HAL::PCIDevice::readBlock)";
00164     throw( HAL::IllegalOperationException( text, __FILE__, __LINE__, __FUNCTION__ ) );
00165   }
00166 
00167   if ( (length) % sizeof(uint32_t) != 0 ) {
00168     std::string text = "the length is not a multiple of the data width!\n     (HAL::PCIDevice::readBlock)";
00169     throw( HAL::IllegalValueException( text, __FILE__, __LINE__, __FUNCTION__ ) );
00170   }
00171 
00172   uint32_t barId = pciAddress.getMapId();
00173   if ( barId < 0 || barId > 6 ) {
00174     std::stringstream text;
00175     text << "barId out of range :" << barId
00176          << "\n    must be between 0 and 5"
00177          << "\n    (HAL::PCIDevice::readBlock)" << std::ends;
00178     throw (HAL::IllegalValueException( text.str(), __FILE__, __LINE__, __FUNCTION__ ));
00179   }
00180   if ( baseRegisters[barId]  == 0 ) {
00181     std::stringstream text;
00182     text << "barId " << std::dec << barId 
00183          << " cannot be used since it is not mapped.\n"
00184          << "    This is because no item with this barId is in the HAL::AddressTable."
00185          << "    (HAL::PCIDevice::readBlock)" << std::ends;
00186     throw (HAL::IllegalValueException( text.str(), __FILE__, __LINE__, __FUNCTION__ ) );
00187   }
00188 
00189   uint32_t startAddress = pciAddress.getAddress() + baseRegisters[barId] + offset;
00190   if ( (startAddress) % sizeof(uint32_t) != 0 ) {
00191     std::stringstream text;
00192     text << "the startaddress must be aligned for the data width " 
00193          << std::dec << sizeof(uint32_t) << ".\n"
00194          << "     But the start address is " 
00195          << std::hex << std::setw(8) << std::setfill('0') << startAddress 
00196          << "\n     (HAL::PCIDevice::readBlock)" << std::ends;
00197     throw( HAL::IllegalValueException( text.str(), __FILE__, __LINE__, __FUNCTION__ ) );
00198   }
00199   pciBusAdapter.readBlock( *deviceIdentifierPtr, 
00200                            startAddress,
00201                            length,
00202                            buffer,
00203                            addressBehaviour);
00204 }
00205 
00206 
00207 void HAL::PCIDevice::memoryWrite( uint32_t address,
00208                                   uint32_t barId,
00209                                   uint32_t data ) const
00210   throw (HAL::IllegalValueException,
00211          HAL::BusAdapterException) {
00212   if ( barId < 0 || barId > 6 ) {
00213     std::stringstream text;
00214     text << "barId out of range :" << barId
00215          << "\n    must be between 0 and 5"
00216          << "\n    (HAL::PCIDevice::memoryWrite)" << std::ends;
00217     throw (HAL::IllegalValueException( text.str(), __FILE__, __LINE__, __FUNCTION__ ));
00218   }
00219   if ( baseRegisters[barId]  == 0 ) {
00220     std::stringstream text;
00221     text << "barId " << std::dec << barId 
00222          << " cannot be used since it is not mapped.\n"
00223          << "    This is because no item with this barId is in the HAL::AddressTable."
00224          << "    (HAL::PCIDevice::memoryWrite)" << std::ends;
00225     throw (HAL::IllegalValueException( text.str(), __FILE__, __LINE__, __FUNCTION__ ) );
00226   }
00227   pciBusAdapter.write( *deviceIdentifierPtr, address + baseRegisters[barId], data );
00228 }
00229 
00230 void HAL::PCIDevice::memoryRead( uint32_t address,
00231                                  uint32_t barId,
00232                                  uint32_t* result ) const 
00233   throw (HAL::IllegalValueException,
00234          HAL::BusAdapterException) {
00235   if ( barId < 0 || barId > 6 ) {
00236     std::stringstream text;
00237     text << "barId out of range :" << barId
00238          << "\n    must be between 0 and 5"
00239          << "\n    (HAL::PCIDevice::memoryWrite)" << std::ends;
00240     throw (HAL::IllegalValueException( text.str(), __FILE__, __LINE__, __FUNCTION__ ));
00241   }
00242   if ( baseRegisters[barId]  == 0 ) {
00243     std::stringstream text;
00244     text << "barId " << std::dec << barId 
00245          << " cannot be used since it is not mapped.\n"
00246          << "    This is because no item with this barId is in the HAL::AddressTable.\n"
00247          << "    (HAL::PCIDevice::memoryRead)" << std::ends;
00248     throw (HAL::IllegalValueException( text.str(), __FILE__, __LINE__, __FUNCTION__ ) );
00249   }
00250   pciBusAdapter.read( *deviceIdentifierPtr, address + baseRegisters[barId], result );
00251 }
00252 
00253 uint32_t HAL::PCIDevice::getPCIBusAddress( uint32_t iBar )
00254   throw (HAL::BusAdapterException) {
00255   return deviceIdentifierPtr->getPCIBusAddress( iBar );
00256 }
00257 
00258 
00259 // Hannes Sakulin: To accelerate the JAL (not to be used by users !!!)
00260 void HAL::PCIDevice::configWrite( uint32_t address,
00261                              uint32_t data ) const
00262   throw (BusAdapterException) {
00263   pciBusAdapter.configWrite( *deviceIdentifierPtr, address, data );
00264 }
00265 
00266 // Hannes Sakulin: To accelerate the JAL (not to be used by users !!!)
00267 void HAL::PCIDevice::configRead( uint32_t address,
00268                             uint32_t* result ) const 
00269   throw (BusAdapterException) {
00270   pciBusAdapter.configRead( *deviceIdentifierPtr, address, result );
00271 }
00272