Library of Bus-Adapters
|
00001 #include "hal/CAENLinuxBusAdapter.hh" 00002 #include "CAENVMElib.h" 00003 #include <sstream> 00004 #include <iostream> 00005 #include <iomanip> 00006 #include <string.h> 00007 00008 00009 int32_t HAL::CAENLinuxBusAdapter::handleVX718UseCount_[8][8] = {{0,0,0,0,0,0,0,0}, 00010 {0,0,0,0,0,0,0,0}, 00011 {0,0,0,0,0,0,0,0}, 00012 {0,0,0,0,0,0,0,0}, 00013 {0,0,0,0,0,0,0,0}, 00014 {0,0,0,0,0,0,0,0}, 00015 {0,0,0,0,0,0,0,0}, 00016 {0,0,0,0,0,0,0,0}}; 00017 int32_t HAL::CAENLinuxBusAdapter::handleVX718_[8][8] = {{0,0,0,0,0,0,0,0}, 00018 {0,0,0,0,0,0,0,0}, 00019 {0,0,0,0,0,0,0,0}, 00020 {0,0,0,0,0,0,0,0}, 00021 {0,0,0,0,0,0,0,0}, 00022 {0,0,0,0,0,0,0,0}, 00023 {0,0,0,0,0,0,0,0}, 00024 {0,0,0,0,0,0,0,0}}; 00025 sem_t* HAL::CAENLinuxBusAdapter::handleSemaphore_ = 0; 00026 00035 HAL::CAENLinuxBusAdapter::CAENLinuxBusAdapter( CAENModel model, int unit, int chain, CAENPCCard pcCard ) 00036 throw (BusAdapterException) 00037 : unit_(unit), 00038 chain_(chain), 00039 model_(model) 00040 { 00041 00042 int status; 00043 int32_t handle; 00044 00045 // Initial check of parameters 00046 if ( unit > 7 || unit < 0 || chain > 7 || chain < 0 ) { 00047 std::stringstream errorMessage; 00048 errorMessage << "unit and chain parameters must be between 0 and 7 but they are " 00049 << unit << " and " << chain << "." << std::ends; 00050 throw (BusAdapterException( errorMessage.str(), __FILE__, __LINE__, __FUNCTION__ ) ); 00051 } 00052 00053 if ( handleSemaphore_ == 0 ) { 00054 handleSemaphore_ = new sem_t; 00055 sem_init( handleSemaphore_, 0, 0 ); 00056 } else { 00057 sem_wait( handleSemaphore_ ); 00058 } 00059 00060 V1718FwRelease_[0] = char(0); 00061 V2718FwRelease_[0] = char(0); 00062 AX818FwRelease_[0] = char(0); 00063 A2719FwRelease_[0] = char(0); 00064 VMELibRelease_[0] = char(0); 00065 00066 if ( pcCard == A3818 ) { 00067 pcCard_ = cvA3818; 00068 pcCardStr_ = "A3818"; 00069 } else if ( pcCard == A2818 ) { 00070 pcCard_ = cvA2818; 00071 pcCardStr_ = "A2818"; 00072 } else { 00073 // a software bug 00074 throw (BusAdapterException( "A HAL software bug: illegal pc card identifier set", 00075 __FILE__, __LINE__, __FUNCTION__ ) ); 00076 } 00077 00078 // collect all the firmware and software versions 00079 00080 if ( model == V2718 ) { // model V2718 00081 00082 // firmware version of the PCI board 00083 if( (status=CAENVME_Init(pcCard_, unit_, 0, &handle)) != cvSuccess ) { 00084 std::stringstream errorMessage; 00085 errorMessage << "Could not initialize CAENVME library for PC card (status: " 00086 << status 00087 << ")" 00088 << std::ends; 00089 sem_post(handleSemaphore_); 00090 throw (BusAdapterException( errorMessage.str(), __FILE__, __LINE__, __FUNCTION__ ) ); 00091 } 00092 if ( ( status = CAENVME_BoardFWRelease( handle, AX818FwRelease_ )) != cvSuccess ) { 00093 std::stringstream errorMessage; 00094 errorMessage << "Could not determine firmware version of " << pcCardStr_ << " (status: " 00095 << status 00096 << ")" 00097 << std::ends; 00098 sem_post(handleSemaphore_); 00099 throw (BusAdapterException( errorMessage.str(), __FILE__, __LINE__, __FUNCTION__ ) ); 00100 } 00101 00102 CAENVME_End( handle ); 00103 00104 // // The following must not be done since it sets the optical link add-on board 00105 // // in service mode: If at the same time another process tries to access the 00106 // // VME bus via the same optical link, it will get an error since the packet 00107 // // gets stuck in the optical link board which is in service mode. 00108 // 00109 // // firmware version of the optical link add-on board 00110 // if( (status=CAENVME_Init(cvA2719, unit_, 0, &handle_)) != cvSuccess ) { 00111 // std::stringstream errorMessage; 00112 // errorMessage << "Could not initialize CAENVME library with cvA2719 (status: " 00113 // << status 00114 // << ")" 00115 // << std::ends; 00116 // throw (BusAdapterException( errorMessage.str(), __FILE__, __LINE__, __FUNCTION__ ) ); 00117 // } 00118 // if ( ( status = CAENVME_BoardFWRelease( handle_, A2719FwRelease_ )) != cvSuccess ) { 00119 // std::stringstream errorMessage; 00120 // errorMessage << "Could not determine firmware version of cvA2719 (status: " 00121 // << status 00122 // << ")" 00123 // << std::ends; 00124 // throw (BusAdapterException( errorMessage.str(), __FILE__, __LINE__, __FUNCTION__ ) ); 00125 // } 00126 // CAENVME_End( handle_ ); 00127 strcpy( A2719FwRelease_, "not available" ) ; 00128 00129 // firmware version of the VME Controller board (optical link version) 00130 // This process must only call Init once!!! 00131 if ( handleVX718UseCount_[unit_][chain_] == 0 ) { 00132 if( (status=CAENVME_Init(cvV2718, unit_, chain_, &handleVX718_[unit_][chain_])) != cvSuccess ) { 00133 std::stringstream errorMessage; 00134 errorMessage << "Could not initialize CAENVME library with cvV2718 (status: " 00135 << status 00136 << ")" 00137 << std::ends; 00138 sem_post(handleSemaphore_); 00139 throw (BusAdapterException( errorMessage.str(), __FILE__, __LINE__, __FUNCTION__ ) ); 00140 } 00141 } 00142 00143 if ( ( status = CAENVME_BoardFWRelease( handleVX718_[unit_][chain_], V2718FwRelease_ )) != cvSuccess ) { 00144 std::stringstream errorMessage; 00145 errorMessage << "Could not determine firmware version of V2718 (status: " 00146 << status 00147 << ")" 00148 << std::ends; 00149 sem_post(handleSemaphore_); 00150 throw (BusAdapterException( errorMessage.str(), __FILE__, __LINE__, __FUNCTION__ ) ); 00151 } 00152 00153 } else { // V1718 00154 00155 00156 // firmware of the VME Controller board (USB version) 00157 if ( handleVX718UseCount_[unit_][chain_] == 0 ) { 00158 if( (status=CAENVME_Init(cvV1718, unit_, 0, &handleVX718_[unit_][chain_])) != cvSuccess ) { 00159 std::stringstream errorMessage; 00160 errorMessage << "Could not initialize CAENVME library with cvV1718 (status: " 00161 << status 00162 << ")" 00163 << std::ends; 00164 sem_post(handleSemaphore_); 00165 throw (BusAdapterException( errorMessage.str(), __FILE__, __LINE__, __FUNCTION__ ) ); 00166 } 00167 } 00168 if ( ( status = CAENVME_BoardFWRelease( handleVX718_[unit_][chain_], V1718FwRelease_ )) != cvSuccess ) { 00169 std::stringstream errorMessage; 00170 errorMessage << "Could not determine firmware version of V1718 (status: " 00171 << status 00172 << ")" 00173 << std::ends; 00174 sem_post(handleSemaphore_); 00175 throw (BusAdapterException( errorMessage.str(), __FILE__, __LINE__, __FUNCTION__ ) ); 00176 } 00177 } 00178 CAENVME_SWRelease( VMELibRelease_ ); 00179 handleVX718UseCount_[unit_][chain_]++; 00180 00181 sem_post(handleSemaphore_); 00182 00183 } 00184 00185 00186 00187 00188 HAL::CAENLinuxBusAdapter::~CAENLinuxBusAdapter() 00189 throw( BusAdapterException ){ 00190 00191 sem_wait( handleSemaphore_ ); 00192 handleVX718UseCount_[unit_][chain_]--; 00193 00194 00195 if ( handleVX718UseCount_[unit_][chain_] == 0 ) { 00196 // we are the last user: close down everything 00197 if (CAENVME_End( handleVX718_[unit_][chain_] ) != cvSuccess ) { 00198 std::string errorMessage( "Could not close the CAENVME library" ); 00199 sem_post( handleSemaphore_ ); 00200 throw (BusAdapterException( errorMessage, __FILE__, __LINE__, __FUNCTION__ ) ); 00201 } 00202 handleVX718_[unit_][chain_] = 0; 00203 sem_post( handleSemaphore_ ); 00204 sem_destroy( handleSemaphore_ ); 00205 handleSemaphore_ = 0; 00206 delete handleSemaphore_; 00207 00208 } else { 00209 00210 // somebody else is still using the busAdapter 00211 sem_post( handleSemaphore_ ); 00212 00213 } 00214 } 00215 00216 00217 00218 void HAL::CAENLinuxBusAdapter::openDevice(const VMEAddressTable& vmeAddressTable, 00219 uint32_t vmeBaseAddress, 00220 DeviceIdentifier** deviceIdentifierPtr, 00221 uint32_t* baseAddressPtr, 00222 bool doSwapping ) 00223 throw (BusAdapterException) { 00224 00225 *deviceIdentifierPtr= new HAL::CAENDeviceIdentifier( handleVX718_[unit_][chain_], 00226 doSwapping ); 00227 00228 *baseAddressPtr = vmeBaseAddress; 00229 } 00230 00231 00232 00233 void HAL::CAENLinuxBusAdapter::openDevice(const VMEAddressTable& vmeAddressTable, 00234 std::vector<uint32_t> vmeBaseAddresses, 00235 DeviceIdentifier** deviceIdentifierPtr, 00236 std::vector<uint32_t>* baseAddressesPtr, 00237 bool doSwapping ) 00238 throw (BusAdapterException) { 00239 00240 *deviceIdentifierPtr= new HAL::CAENDeviceIdentifier( handleVX718_[unit_][chain_], 00241 doSwapping ); 00242 00243 *baseAddressesPtr = vmeBaseAddresses; 00244 } 00245 00246 00247 00248 00249 void HAL::CAENLinuxBusAdapter::closeDevice( DeviceIdentifier* vmeDevice ) 00250 throw() { 00251 delete(vmeDevice); 00252 } 00253 00254 00255 00256 void HAL::CAENLinuxBusAdapter::read( DeviceIdentifier* vmeDevice, 00257 uint32_t address, 00258 uint32_t addressModifier, 00259 uint32_t dataWidth, 00260 uint32_t *resultPtr ) 00261 throw( BusAdapterException ) { 00262 00263 // The CAEN Adapter now supports byte swapping 00264 if ( dynamic_cast<HAL::CAENDeviceIdentifier*>(vmeDevice)->doSwapping() && 00265 dataWidth > 1 ) { 00266 dataWidth += 16; 00267 } 00268 00269 if( CAENVME_ReadCycle( handleVX718_[unit_][chain_], address, 00270 (void*)resultPtr, 00271 (CVAddressModifier)addressModifier, 00272 (CVDataWidth)dataWidth ) != cvSuccess ) { 00273 std::string errorMessage( "Could not read from CAEN BusAdapter" ); 00274 throw (BusAdapterException( errorMessage, __FILE__, __LINE__, __FUNCTION__ ) ); 00275 } 00276 } 00277 00278 void HAL::CAENLinuxBusAdapter::write( DeviceIdentifier* vmeDevice, 00279 uint32_t address, 00280 uint32_t addressModifier, 00281 uint32_t dataWidth, 00282 uint32_t data) 00283 throw( BusAdapterException ) { 00284 00285 // The CAEN Adapter now supports byte swapping 00286 if ( dynamic_cast<HAL::CAENDeviceIdentifier*>(vmeDevice)->doSwapping() && 00287 dataWidth > 1 ) { 00288 dataWidth += 16; 00289 } 00290 00291 if( CAENVME_WriteCycle( handleVX718_[unit_][chain_], address, 00292 (void*)(&data), 00293 (CVAddressModifier)addressModifier, 00294 (CVDataWidth)dataWidth ) != cvSuccess ) { 00295 std::string errorMessage( "Could not read from CAEN BusAdapter" ); 00296 throw (BusAdapterException( errorMessage, __FILE__, __LINE__, __FUNCTION__ ) ); 00297 } 00298 } 00299 00300 void HAL::CAENLinuxBusAdapter::resetBus( ) 00301 throw(BusAdapterException) { 00302 00303 if (CAENVME_SystemReset( handleVX718_[unit_][chain_] ) != cvSuccess ) { 00304 throw( BusAdapterException( "Cannot issue sysReset on VME crate", __FILE__, __LINE__, __FUNCTION__ )); 00305 } 00306 } 00307 00308 void HAL::CAENLinuxBusAdapter::readBlock( DeviceIdentifier *vmeDevice, 00309 uint32_t startAddress, 00310 uint32_t length, // in bytes 00311 uint32_t addressModifier, 00312 uint32_t dataWidth, 00313 char *buffer, 00314 HalAddressIncrement addressBehaviour ) 00315 throw( BusAdapterException, 00316 UnsupportedException ){ 00317 00318 int actualTransferred, status; 00319 00320 // The CAEN Adapter now supports byte swapping 00321 if ( dynamic_cast<HAL::CAENDeviceIdentifier*>(vmeDevice)->doSwapping() && 00322 dataWidth > 1 ) { 00323 dataWidth += 16; 00324 } 00325 00326 if ( addressBehaviour != HAL_DO_INCREMENT ) { 00327 00328 if ( (status = CAENVME_FIFOBLTReadCycle(handleVX718_[unit_][chain_], startAddress, (unsigned char *)buffer, 00329 (int) length, (CVAddressModifier) addressModifier, 00330 (CVDataWidth) dataWidth, &actualTransferred)) != cvSuccess ) { 00331 00332 throw( BusAdapterException( "Error during read block transfer (FIFO mode)", __FILE__, __LINE__, __FUNCTION__ )); 00333 00334 } 00335 00336 } else { 00337 00338 if ( (status = CAENVME_BLTReadCycle(handleVX718_[unit_][chain_], startAddress, (unsigned char *)buffer, 00339 (int) length, (CVAddressModifier) addressModifier, 00340 (CVDataWidth) dataWidth, &actualTransferred)) != cvSuccess ) { 00341 00342 throw( BusAdapterException( "Error during read block transfer", __FILE__, __LINE__, __FUNCTION__ )); 00343 } 00344 } 00345 00346 if ( (uint32_t)actualTransferred != length ) { 00347 std::stringstream message; 00348 message << "Block transfer has only transferred " << std::dec << actualTransferred 00349 << " bytes instead of the requested " << length 00350 << std::ends; 00351 throw( BusAdapterException( message.str(), __FILE__, __LINE__, __FUNCTION__ )); 00352 } 00353 } 00354 00355 void HAL::CAENLinuxBusAdapter::writeBlock( DeviceIdentifier *vmeDevice, 00356 uint32_t startAddress, 00357 uint32_t length, // in bytes 00358 uint32_t addressModifier, 00359 uint32_t dataWidth, 00360 char *buffer, 00361 HalAddressIncrement addressBehaviour ) 00362 throw( BusAdapterException, 00363 UnsupportedException ){ 00364 00365 int actualTransferred, status; 00366 00367 // The CAEN Adapter now supports byte swapping 00368 if ( dynamic_cast<HAL::CAENDeviceIdentifier*>(vmeDevice)->doSwapping() && 00369 dataWidth > 1 ) { 00370 dataWidth += 16; 00371 } 00372 00373 if ( addressBehaviour != HAL_DO_INCREMENT ) { 00374 00375 if ( (status = CAENVME_FIFOBLTWriteCycle(handleVX718_[unit_][chain_], startAddress, (unsigned char *)buffer, 00376 (int) length, (CVAddressModifier) addressModifier, 00377 (CVDataWidth) dataWidth, &actualTransferred)) != cvSuccess ) { 00378 00379 throw( BusAdapterException( "Error during write block transfer (FIFO mode)", __FILE__, __LINE__, __FUNCTION__ )); 00380 } 00381 00382 } else { 00383 00384 if ( (status = CAENVME_BLTWriteCycle(handleVX718_[unit_][chain_], startAddress, (unsigned char *)buffer, 00385 (int) length, (CVAddressModifier) addressModifier, 00386 (CVDataWidth) dataWidth, &actualTransferred)) != cvSuccess ) { 00387 00388 throw( BusAdapterException( "Error during write block transfer", __FILE__, __LINE__, __FUNCTION__ )); 00389 } 00390 00391 } 00392 00393 if ( (uint32_t)actualTransferred != length ) { 00394 std::stringstream message; 00395 message << "Block transfer has only transferred " << std::dec << actualTransferred 00396 << " bytes instead of the requested " << length 00397 << std::ends; 00398 throw( BusAdapterException( message.str(), __FILE__, __LINE__, __FUNCTION__ )); 00399 } 00400 } 00401 00402 void HAL::CAENLinuxBusAdapter::readVersions( std::ostream& os ) const { 00403 if ( model_ == V2718 ) { 00404 os << "V2718 firmware : " << V2718FwRelease_ << "\n" 00405 << pcCardStr_ << " firmware : " << AX818FwRelease_ << "\n" 00406 //<< "A2719 firmware : " << A2719FwRelease_ << "\n" 00407 << "VMELibRelease : " << VMELibRelease_ << "\n" 00408 << std::ends; 00409 } else { 00410 os << "V1718 firmware : " << V1718FwRelease_ << "\n" << std::ends; 00411 } 00412 } 00413 00414 void HAL::CAENLinuxBusAdapter::readDisplay( std::ostream& os ) const 00415 throw( BusAdapterException ) { 00416 00417 CVDisplay displayData; 00418 int status; 00419 if ( (status = CAENVME_ReadDisplay(handleVX718_[unit_][chain_], &displayData)) != cvSuccess ) { 00420 throw( BusAdapterException( "Could not read display.", __FILE__, __LINE__, __FUNCTION__ )); 00421 } 00422 00423 os << "Address : " << std::hex << std::setw(8) << std::setfill('0') << displayData.cvAddress << std::endl; 00424 os << "Data : " << std::hex << std::setw(8) << std::setfill('0') << displayData.cvData << std::endl; 00425 os << "AM : " << std::hex << std::setw(2) << std::setfill('0') << (uint32_t)displayData.cvAM << std::endl; 00426 os << std::endl; 00427 os << "DS0 : " << std::setw(1) << (0x01 & displayData.cvDS0) << std::endl; 00428 os << "DS1 : " << std::setw(1) << (0x01 & displayData.cvDS1) << std::endl; 00429 os << "AS : " << std::setw(1) << (0x01 & displayData.cvAS) << std::endl; 00430 os << "IACK : " << std::setw(1) << (0x01 & displayData.cvIACK) << std::endl; 00431 os << "WRITE : " << std::setw(1) << (0x01 & displayData.cvWRITE) << std::endl; 00432 os << "LWORD : " << std::setw(1) << (0x01 & displayData.cvLWORD) << std::endl; 00433 os << "DTACK : " << std::setw(1) << (0x01 & displayData.cvDTACK) << std::endl; 00434 os << "BERR : " << std::setw(1) << (0x01 & displayData.cvBERR) << std::endl; 00435 os << "SYSRES : " << std::setw(1) << (0x01 & displayData.cvSYSRES) << std::endl; 00436 os << "BR : " << std::setw(1) << (0x01 & displayData.cvBR) << std::endl; 00437 os << "BG : " << std::setw(1) << (0x01 & displayData.cvBG) << std::endl; 00438 } 00439 00440 00441 void HAL::CAENLinuxBusAdapter::enableIRQ( uint32_t mask ) const 00442 throw( BusAdapterException ) { 00443 int status; 00444 status = CAENVME_IRQEnable(handleVX718_[unit_][chain_], mask); 00445 if ( status != cvSuccess ) { 00446 std::stringstream message; 00447 message << "Could not enable Interrupts: CAEN error " << std::dec << status 00448 << std::ends; 00449 throw( BusAdapterException( message.str(), __FILE__, __LINE__, __FUNCTION__ )); 00450 } 00451 } 00452 00453 void HAL::CAENLinuxBusAdapter::disableIRQ( uint32_t mask ) const 00454 throw( BusAdapterException ) { 00455 int status; 00456 status = CAENVME_IRQDisable(handleVX718_[unit_][chain_], mask); 00457 if ( status != cvSuccess ) { 00458 std::stringstream message; 00459 message << "Could not disable Interrupts: CAEN error " << std::dec << status 00460 << std::ends; 00461 throw( BusAdapterException( message.str(), __FILE__, __LINE__, __FUNCTION__ )); 00462 } 00463 } 00464 00465 uint32_t HAL::CAENLinuxBusAdapter::checkIRQ( ) const 00466 throw( BusAdapterException ) { 00467 int status; 00468 CAEN_BYTE retval; 00469 status = CAENVME_IRQCheck(handleVX718_[unit_][chain_], &retval); 00470 if ( status != cvSuccess ) { 00471 std::stringstream message; 00472 message << "Could not check for Interrupts: CAEN error " << std::dec << status 00473 << std::ends; 00474 throw( BusAdapterException( message.str(), __FILE__, __LINE__, __FUNCTION__ )); 00475 } 00476 return (uint32_t)retval; 00477 } 00478 00479 uint32_t HAL::CAENLinuxBusAdapter::waitIRQ( uint32_t mask, uint32_t timeoutMs ) const 00480 throw( BusAdapterException ) { 00481 int status; 00482 status = CAENVME_IRQWait(handleVX718_[unit_][chain_], mask, timeoutMs); 00483 if ( status != cvSuccess ) { 00484 // // This currently means that there was either a problem 00485 // // or the timeout has fired. So we cannot assume that 00486 // // something went wrong. 00487 // 00488 // //std::stringstream message; 00489 // //message << "Could not wait for Interrupts: CAEN error " << std::dec << status 00490 // // << std::ends; 00491 // //throw( BusAdapterException( message.str(), __FILE__, __LINE__, __FUNCTION__ )); 00492 return 0; 00493 } 00494 uint32_t retmask = checkIRQ(); 00495 return retmask; 00496 } 00497 00498 void HAL::CAENLinuxBusAdapter::acknowledgeIRQ( uint32_t level, void* vector, uint32_t width ) const 00499 throw( BusAdapterException ) { 00500 int status; 00501 status = CAENVME_IACKCycle(handleVX718_[unit_][chain_], (CVIRQLevels)level, vector, (CVDataWidth)width); 00502 if ( status != cvSuccess ) { 00503 std::stringstream message; 00504 message << "Could not acknowledge Interrupt: CAEN error " << std::dec << status 00505 << std::ends; 00506 throw( BusAdapterException( message.str(), __FILE__, __LINE__, __FUNCTION__ )); 00507 } 00508 }