Library of Bus-Adapters
|
00001 #include "hal/PCILinuxBusAdapter.hh" 00002 00003 #include <sstream> 00004 #include <iomanip> 00005 00006 HAL::PCILinuxBusAdapter::PCILinuxBusAdapter() throw (HAL::BusAdapterException) 00007 try 00008 : PCIBusAdapterInterface(), 00009 pciBus_() {} 00010 catch ( xpci::exception::IOError &e ) { 00011 std::string err = std::string( e.what() ); 00012 throw BusAdapterException( e.what(), __FILE__, __LINE__, __FUNCTION__ ); 00013 } 00014 00015 HAL::PCILinuxBusAdapter::~PCILinuxBusAdapter() { 00016 } 00017 00018 void HAL::PCILinuxBusAdapter::findDeviceByBus( uint32_t busID, 00019 uint32_t slotID, 00020 uint32_t functionID, 00021 const PCIAddressTable& pciAddressTable, 00022 PCIDeviceIdentifier** deviceIdentifierPtr, 00023 std::vector<uint32_t>& baseAddresses, 00024 bool swapFlag ) 00025 throw (BusAdapterException, 00026 NoSuchDeviceException) { 00027 00028 xpci::Address deviceConfigAddress = 00029 xpci::Address::getConfigSpaceAddressByBus(busID, slotID, functionID); 00030 00031 findDevice( deviceConfigAddress, 00032 pciAddressTable, 00033 deviceIdentifierPtr, 00034 baseAddresses, 00035 swapFlag ); 00036 } 00037 00038 void HAL::PCILinuxBusAdapter::findDeviceByVendor( uint32_t vendorID, 00039 uint32_t deviceID, 00040 uint32_t index, 00041 const PCIAddressTable& pciAddressTable, 00042 PCIDeviceIdentifier** deviceIdentifierPtr, 00043 std::vector<uint32_t>& baseAddresses, 00044 bool swapFlag ) 00045 throw (BusAdapterException, 00046 NoSuchDeviceException) { 00047 00048 xpci::Address deviceConfigAddress = 00049 xpci::Address::getConfigSpaceAddressByVendor(vendorID, deviceID, index); 00050 00051 findDevice( deviceConfigAddress, 00052 pciAddressTable, 00053 deviceIdentifierPtr, 00054 baseAddresses, 00055 swapFlag ); 00056 } 00057 00058 void HAL::PCILinuxBusAdapter::findDevice( xpci::Address& deviceConfigAddress, 00059 const PCIAddressTable& pciAddressTable, 00060 PCIDeviceIdentifier** deviceIdentifierPtr, 00061 std::vector<uint32_t>& baseAddresses, 00062 bool swapFlag ) 00063 throw (BusAdapterException, 00064 NoSuchDeviceException) { 00065 00066 *deviceIdentifierPtr = (PCIDeviceIdentifier*) 0; // default: unvalid 00067 00068 // check if the device has been found, otherwise throw exception 00069 try { 00070 uint32_t val; 00071 pciBus_.read (deviceConfigAddress, 0x00000010, val); 00072 } catch ( xpci::exception::IOError e) { 00073 std::stringstream text; 00074 text << "Could not find PCI device \n" 00075 << std::ends; 00076 std::string textStr = text.str(); 00077 throw ( NoSuchDeviceException( textStr, __FILE__, __LINE__, __FUNCTION__ )); 00078 } 00079 HAL::PCILinuxDeviceIdentifier* newIdentifierPtr = 00080 new HAL::PCILinuxDeviceIdentifier(deviceConfigAddress, swapFlag); 00081 uint32_t minConfigAddress, maxConfigAddress; 00082 std::vector<uint32_t> minAddresses, maxAddresses; 00083 pciAddressTable.getAddressBoundaries( minConfigAddress, maxConfigAddress, 00084 minAddresses, maxAddresses ); 00085 baseAddresses.clear(); 00086 00087 try { 00088 for ( int ix = 0; ix<6; ix++ ) { 00089 xpci::Address ba = pciBus_.BAR(ix, deviceConfigAddress); 00090 baseAddresses.push_back(ba.getAddress()); 00091 } 00092 } catch ( xpci::exception::IOError &e ) { 00093 throw BusAdapterException( e.what(), __FILE__, __LINE__, __FUNCTION__ ); 00094 } 00095 00096 00097 *deviceIdentifierPtr = newIdentifierPtr; 00098 } 00099 00100 void HAL::PCILinuxBusAdapter::configWrite( PCIDeviceIdentifier& pciDevice, 00101 uint32_t address, 00102 uint32_t data) 00103 throw( BusAdapterException ){ 00104 if ( (address%4 != 0) ) { 00105 std::stringstream text; 00106 text << "address or length not aligned to 4 byte boundary " 00107 << "\n address (hex) : " << std::hex << address 00108 << std::ends; 00109 throw( BusAdapterException( text.str(), __FILE__, __LINE__, __FUNCTION__ ) ); 00110 } 00111 xpci::Address pciConfigAddress 00112 = (dynamic_cast<HAL::PCILinuxDeviceIdentifier&>(pciDevice)).getConfigAddress(); 00113 try { 00114 pciBus_.write(pciConfigAddress, address, data); 00115 } catch( xpci::exception::IOError &e ) { 00116 std::stringstream text; 00117 text << "error during write to address " 00118 << std::hex << address 00119 << " (data : " << data << ")" 00120 << std::ends; 00121 throw( BusAdapterException( text.str(), __FILE__, __LINE__, __FUNCTION__ ) ); 00122 } 00123 } 00124 00125 void HAL::PCILinuxBusAdapter::configRead( PCIDeviceIdentifier& pciDevice, 00126 uint32_t address, 00127 uint32_t* data) 00128 throw( BusAdapterException ){ 00129 if ( (address%4 != 0) ) { 00130 std::stringstream text; 00131 text << "address or length not aligned to 4 byte boundary " 00132 << "\n address (hex) : " << std::hex << address 00133 << std::ends; 00134 throw( BusAdapterException( text.str(), __FILE__, __LINE__, __FUNCTION__ ) ); 00135 } 00136 xpci::Address pciConfigAddress 00137 = (dynamic_cast<HAL::PCILinuxDeviceIdentifier&>(pciDevice)).getConfigAddress(); 00138 try { 00139 uint32_t val; 00140 pciBus_.read(pciConfigAddress, address, val); 00141 *data = val; 00142 } catch( xpci::exception::IOError &e ) { 00143 std::stringstream text; 00144 text << "error during read from address " 00145 << std::hex << address 00146 << std::ends; 00147 throw( BusAdapterException( text.str(), __FILE__, __LINE__, __FUNCTION__ ) ); 00148 } 00149 } 00150 00151 void HAL::PCILinuxBusAdapter::write( PCIDeviceIdentifier& device, 00152 uint32_t address, 00153 uint32_t data ) 00154 throw( BusAdapterException ) { 00155 if ( (address%4 != 0) ) { 00156 std::stringstream text; 00157 text << "address or length not aligned to 4 byte boundary " 00158 << "\n address (hex) : " << std::hex << address 00159 << std::ends; 00160 throw( BusAdapterException( text.str(), __FILE__, __LINE__, __FUNCTION__ ) ); 00161 } 00162 00163 xpci::Address pciAddress = xpci::Address::getMemorySpaceAddress( address ); 00164 try { 00165 if ( device.doSwap() ){ 00166 pciBus_.write( pciAddress, 0, bswap_32(data) ); 00167 } else { 00168 pciBus_.write( pciAddress, 0, data ); 00169 } 00170 } catch( xpci::exception::IOError &e ) { 00171 std::stringstream text; 00172 text << "error during write to address " 00173 << std::hex << address 00174 << " (data : " << data << ")" 00175 << std::ends; 00176 throw( BusAdapterException( text.str(), __FILE__, __LINE__, __FUNCTION__ ) ); 00177 } 00178 } 00179 00180 void HAL::PCILinuxBusAdapter::read( PCIDeviceIdentifier& device, 00181 uint32_t address, 00182 uint32_t* result ) 00183 throw( BusAdapterException ) { 00184 if ( (address%4 != 0) ) { 00185 std::stringstream text; 00186 text << "address or length not aligned to 4 byte boundary " 00187 << "\n address (hex) : " << std::hex << address 00188 << std::ends; 00189 throw( BusAdapterException( text.str(), __FILE__, __LINE__, __FUNCTION__ ) ); 00190 } 00191 00192 xpci::Address pciAddress = xpci::Address::getMemorySpaceAddress( address ); 00193 try { 00194 if ( device.doSwap() ){ 00195 uint32_t val; 00196 pciBus_.read( pciAddress, 0 , val ); 00197 *result = bswap_32( val ); 00198 } else { 00199 uint32_t val; 00200 pciBus_.read( pciAddress, 0, val ); 00201 *result = val; 00202 } 00203 } catch( xpci::exception::IOError &e ) { 00204 std::stringstream text; 00205 text << "error during read from address " 00206 << std::hex << address 00207 << std::ends; 00208 throw( BusAdapterException( text.str(), __FILE__, __LINE__, __FUNCTION__ ) ); 00209 } 00210 00211 } 00212 00213 void HAL::PCILinuxBusAdapter::writeBlock( PCIDeviceIdentifier& device, 00214 uint32_t startAddress, 00215 uint32_t length, 00216 char *buffer, 00217 HalAddressIncrement addressBehaviour) 00218 throw( BusAdapterException ) { 00219 // let's require the address to be aligned to 32 bit and then read 00220 // uint32_ts 00221 if ( (startAddress%4 != 0) || 00222 (length%4 != 0) ) { 00223 std::stringstream text; 00224 text << "Start address or length not aligned to 4 byte boundary " 00225 << "\n StartAddress (hex) : " << std::hex << startAddress 00226 << "\n BlockLength (hex) : " << std::hex << length 00227 << std::ends; 00228 std::string textStr = text.str(); 00229 throw( BusAdapterException( textStr, __FILE__, __LINE__, __FUNCTION__ ) ); 00230 } 00231 00232 uint32_t* sourcePtr = (uint32_t*) buffer; 00233 uint32_t nWords = length/4; 00234 uint32_t ioff=0; 00235 xpci::Address pciAddress = xpci::Address::getMemorySpaceAddress( startAddress ); 00236 00237 try { 00238 if ( device.doSwap() ) { 00239 00240 if ( addressBehaviour == HAL_DO_INCREMENT ) { 00241 for ( uint32_t ic = 0; ic<nWords; ic++, sourcePtr++, ioff+=4 ) { 00242 pciBus_.write( pciAddress, ioff, bswap_32(*sourcePtr) ); 00243 } 00244 } else { // do not increment destination address 00245 for (uint32_t ic = 0; ic<nWords; ic++, sourcePtr++ ) { 00246 pciBus_.write( pciAddress, 0, bswap_32(*sourcePtr) ); 00247 } 00248 } 00249 00250 } else { 00251 if ( addressBehaviour == HAL_DO_INCREMENT ) { 00252 for ( uint32_t ic = 0; ic<nWords; ic++, ioff+=4, sourcePtr++ ) { 00253 pciBus_.write( pciAddress, ioff, *sourcePtr ); 00254 } 00255 } else { // do not increment destination address 00256 for (uint32_t ic = 0; ic<nWords; ic++, sourcePtr++ ) { 00257 pciBus_.write( pciAddress, 0, *sourcePtr ); 00258 } 00259 } 00260 } 00261 } catch( xpci::exception::IOError &e ) { 00262 std::stringstream text; 00263 text << "error during writeBlock to address " 00264 << std::hex << startAddress 00265 << std::ends; 00266 throw( BusAdapterException( text.str(), __FILE__, __LINE__, __FUNCTION__ ) ); 00267 } 00268 } 00269 00270 void HAL::PCILinuxBusAdapter::readBlock( PCIDeviceIdentifier& device, 00271 uint32_t startAddress, 00272 uint32_t length, 00273 char *buffer, 00274 HalAddressIncrement addressBehaviour) 00275 throw( BusAdapterException ) { 00276 // let's require the address to be aligned to 32 bit and then read 00277 // uint32_ts 00278 if ( (startAddress%4 != 0) || 00279 (length%4 != 0) ) { 00280 std::stringstream text; 00281 text << "Start address or length not aligned to 4 byte boundary " 00282 << "\n StartAddress (hex) : " << std::hex << startAddress 00283 << "\n BlockLength (hex) : " << std::hex << length 00284 << std::ends; 00285 std::string textStr = text.str(); 00286 throw( BusAdapterException( textStr, __FILE__, __LINE__, __FUNCTION__ ) ); 00287 } 00288 00289 uint32_t* destPtr = (uint32_t*) buffer; 00290 uint32_t nWords = length/4; 00291 uint32_t ioff = 0; 00292 xpci::Address pciAddress = xpci::Address::getMemorySpaceAddress( startAddress ); 00293 try { 00294 if ( device.doSwap() ){ 00295 // byte swapping 00296 if ( addressBehaviour == HAL_DO_INCREMENT ) { 00297 for ( uint32_t ic = 0; ic<nWords; ic++, destPtr++, ioff+=4 ) { 00298 uint32_t val; 00299 pciBus_.read( pciAddress, ioff, val ); 00300 *destPtr = bswap_32( val ); 00301 } 00302 } else { // do not increment source address 00303 for (uint32_t ic = 0; ic<nWords; ic++, destPtr++ ) { 00304 uint32_t val; 00305 pciBus_.read( pciAddress, 0, val ); 00306 *destPtr = bswap_32( val ); 00307 } 00308 } 00309 // no byte swapping 00310 } else { 00311 if ( addressBehaviour == HAL_DO_INCREMENT ) { 00312 for ( uint32_t ic = 0; ic<nWords; ic++, destPtr++, ioff+=4 ) { 00313 uint32_t val; 00314 pciBus_.read( pciAddress, ioff , val ); 00315 *destPtr = val; 00316 } 00317 } else { // do not increment source address 00318 for (uint32_t ic = 0; ic<nWords; ic++, destPtr++ ) { 00319 uint32_t val; 00320 pciBus_.read( pciAddress, 0, val ); 00321 *destPtr = val; 00322 } 00323 } 00324 } 00325 } catch( xpci::exception::IOError &e ) { 00326 std::stringstream text; 00327 text << "error during readBlock from startAddress " 00328 << std::hex << startAddress 00329 << std::ends; 00330 throw( BusAdapterException( text.str(), __FILE__, __LINE__, __FUNCTION__ ) ); 00331 } 00332 } 00333 00334 void HAL::PCILinuxBusAdapter::closeDevice( PCIDeviceIdentifier* deviceIdentifierPtr ) 00335 throw() { 00336 delete(deviceIdentifierPtr); // this destroys the maps !!! 00337 } 00338