00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <signal.h>
00025 #include <sys/types.h>
00026
00027 #include "RCCVmeInterface.h"
00028 #include "cmem_rcc/cmem_rcc.h"
00029
00030 using namespace SctPixelRod;
00031
00032 long RCCVmeInterface::m_busErrors = 0;
00033 int RCCVmeInterface::m_irqId[8] = { -1, -1, -1, -1, -1, -1, -1, -1};
00034 sigset_t RCCVmeInterface::m_sigMask;
00035
00036 long RCCVmeInterface::m_interruptData = 0;
00037 RCCVmeInterface* RCCVmeInterface::m_if = NULL;
00038 unsigned char RCCVmeInterface::m_softVectMask[256];
00039 VmeInterruptHandler* RCCVmeInterface::m_hardIH[8][256][10];
00040 VmeInterruptHandler* RCCVmeInterface::m_softIH[32][10];
00041 void RCCVmeInterface::m_exitHandler(int signum) {
00042 delete m_if;
00043 exit(0);
00044 }
00045
00046 void RCCVmeInterface::m_busErrorHandler(int signum) {
00047 RCCVmeInterface::m_busErrors++;
00048 }
00049
00050 void RCCVmeInterface::m_interruptHandler(int signum) {
00051 int is, smask;
00052 unsigned int i;
00053 static VME_InterruptInfo_t info[8];
00054
00055
00056 int level = SIGRTMAX - signum;
00057 VME_InterruptInfoGet(m_irqId[level],&info[level]);
00058 int vec = info[level].vector;
00059
00060
00061
00062 m_softVectMask[vec] = 0;
00063 m_if->m_interruptData = 0;
00064 for (i=0; i<10; i++) {
00065 if (m_hardIH[level][vec][i] != 0) {
00066 if (m_hardIH[level][vec][i]->getActive()) {
00067 m_hardIH[level][vec][i]->interruptHandler(vec, 0, info[level].multiple);
00068 }
00069 }
00070 }
00071
00072
00073 smask = m_softVectMask[vec];
00074 for (is=0; is<32; is++) {
00075 if ((smask & (1 << is)) != 0) {
00076 for (i=0; i<10; i++) {
00077 if (m_softIH[is][i] != 0) {
00078 if (m_softIH[is][i]->getActive()) {
00079 m_softIH[is][i]->interruptHandler(vec, is, info[level].multiple);
00080 }
00081 }
00082 }
00083 }
00084 }
00085
00086
00087 if (info[level].type == VME_INT_RORA) {
00088 VME_InterruptReenable(m_irqId[level]);
00089 }
00090 }
00091
00092 RCCVmeInterface::RCCVmeInterface() {
00093 int ret;
00094 int i,j,k;
00095
00096
00097 m_ok = false;
00098
00099
00100 m_lastErrcode = VME_Open();
00101
00102 if (m_lastErrcode != 0)
00103 throw VmeException(VmeException::INIT_ERROR, m_lastErrcode);
00104
00105
00106 ret = CMEM_Open();
00107 ret = CMEM_SegmentAllocate(0x10000, "VmeInterface DMA", &m_dmaBuf);
00108 if (ret) {
00109 m_dmaBufSize = 0;
00110 } else {
00111 m_dmaBufSize = 0x10000;
00112 }
00113
00114 struct sigaction sa;
00115 sigemptyset(&sa.sa_mask);
00116 sa.sa_flags = 0;
00117 sa.sa_handler = m_busErrorHandler;
00118 ret = sigaction(SIGBUS, &sa, NULL);
00119 m_lastErrcode = VME_BusErrorRegisterSignal(SIGBUS);
00120 m_lastErrcode = VME_BusErrorInfoGet(&m_busErrInfo);
00121
00122 sigemptyset(&sa.sa_mask);
00123 sa.sa_flags = 0;
00124 sa.sa_handler = m_interruptHandler;
00125 for (i=0; i<8; i++) sigaction(SIGRTMAX-i, &sa, NULL);
00126
00127 sigemptyset(&sa.sa_mask);
00128 sa.sa_flags = 0;
00129 sa.sa_handler = m_exitHandler;
00130 ret = sigaction(SIGTERM, &sa, NULL);
00131 ret = sigaction(SIGINT, &sa, NULL);
00132
00133 sigemptyset(&m_sigMask);
00134 for (i=0; i<8; i++) sigaddset(&m_sigMask, SIGRTMAX-i);
00135
00136 for (i=0; i<8; i++) m_irq[i].number_of_items = 0;
00137 for (i=0; i<10; i++) {
00138 for (k=0; k<256; k++) {
00139 for (j=0; j<8; j++) {
00140 m_hardIH[j][k][i] = 0;
00141 }
00142 }
00143 for (k=0; k<32; k++) {
00144 m_softIH[k][i] = 0;
00145 }
00146 }
00147
00148 m_if = this;
00149
00150 m_ok = true;
00151 };
00152
00153
00154 RCCVmeInterface::~RCCVmeInterface() {
00155 std::cerr << "Deleting VmeInterface..." << std::endl;
00156
00157 if (m_dmaBufSize != 0) {
00158 std::cout << " Releasing DMA buffer" << std::endl;
00159 CMEM_SegmentFree(m_dmaBuf);
00160 }
00161 CMEM_Close();
00162
00163 int i;
00164 for (i=0; i<8; i++) {
00165 if (m_irq[i].number_of_items > 0) {
00166 std::cout << " Unlinking interrupt handlers for level " << i << std::endl;
00167 m_lastErrcode = VME_InterruptRegisterSignal(m_irqId[i], 0);
00168 m_lastErrcode = VME_InterruptUnlink(m_irqId[i]);
00169 m_irq[i].number_of_items = 0;
00170 }
00171 }
00172
00173 unsigned int ip;
00174 for (ip=0; ip<m_ports.size(); ip++) {
00175 if (m_ports[ip] != NULL) {
00176 std::cout << " Unmapping port " << ip << std::endl;
00177 VME_MasterUnmap(m_ports[ip]->getHandle());
00178 m_ports[ip] = NULL;
00179 }
00180 }
00181
00182 VME_Close();
00183 m_ok = false;
00184 };
00185
00186 void RCCVmeInterface::declareInterruptHandler(VmeInterruptHandler &handler) {
00187 unsigned char vect = handler.getInterruptVector();
00188 unsigned char softvec = handler.getInterruptSoftVect();
00189 unsigned int level = handler.getInterruptLevel();
00190 if (softvec == 0) {
00191 if (level <= 0 || level > 7) return;
00192
00193 unsigned int i,nh=0;
00194 for (i=0; i<10; i++) {
00195 if (&handler == m_hardIH[level][vect][i]) return;
00196 if (m_hardIH[level][vect][i] != 0) nh++;
00197 }
00198 for (i=0; i<10; i++) {
00199 if (m_hardIH[level][vect][i] == 0) {
00200 m_hardIH[level][vect][i] = &handler;
00201 nh++;
00202 break;
00203 }
00204 }
00205 if (nh == 1) {
00206
00207 if (m_irq[level].number_of_items > 0) {
00208 m_lastErrcode = VME_InterruptRegisterSignal(m_irqId[level], 0);
00209 m_lastErrcode = VME_InterruptUnlink(m_irqId[level]);
00210 }
00211 m_irq[level].list_of_items[m_irq[level].number_of_items].vector = vect;
00212 m_irq[level].list_of_items[m_irq[level].number_of_items].level = level;
00213 if (level == 6) {
00214 m_irq[level].list_of_items[m_irq[level].number_of_items].type = VME_INT_RORA;
00215 } else {
00216 m_irq[level].list_of_items[m_irq[level].number_of_items].type = VME_INT_ROAK;
00217 }
00218 m_irq[level].number_of_items++;
00219 m_lastErrcode = VME_InterruptLink(&m_irq[level], &m_irqId[level]);
00220 m_lastErrcode = VME_InterruptRegisterSignal(m_irqId[level], SIGRTMAX-level);
00221 }
00222 } else if (softvec > 0 && softvec <= 32) {
00223
00224 unsigned int i;
00225 for (i=0; i<10; i++) {
00226 if (&handler == m_softIH[softvec-1][i]) return;
00227 }
00228 for (i=0; i<10; i++) {
00229 if (m_softIH[softvec-1][i] == 0) {
00230 m_softIH[softvec-1][i] = &handler;
00231 break;
00232 }
00233 }
00234 }
00235 }
00236
00237 void RCCVmeInterface::cleanInterruptHandlers() {
00238
00239 int i,j,k;
00240 for (i=0; i<8; i++) {
00241 if (m_irq[i].number_of_items > 0) {
00242 m_lastErrcode = VME_InterruptUnlink(m_irqId[i]);
00243 m_lastErrcode = VME_InterruptRegisterSignal(m_irqId[i], 0);
00244 m_irq[i].number_of_items = 0;
00245 }
00246 }
00247 for (i=0; i<10; i++) {
00248 for (k=0; k<256; k++) {
00249 for (j=0; j<8; j++) {
00250 m_hardIH[j][k][i] = 0;
00251 }
00252 }
00253 for (k=0; k<32; k++) {
00254 m_softIH[k][i] = 0;
00255 }
00256 }
00257 }
00258
00259 void RCCVmeInterface::removeInterruptHandler(VmeInterruptHandler &handler) {
00260 char vect = handler.getInterruptVector();
00261 char softvec = handler.getInterruptSoftVect();
00262 int level = handler.getInterruptLevel();
00263 if (softvec == 0) {
00264 int i, nh=0;
00265
00266 for (i=0; i<10; i++) {
00267 if (&handler == m_hardIH[level][vect][i]) {
00268 m_hardIH[level][vect][i] = 0;
00269 break;
00270 }
00271 for (i=0; i<10; i++) {
00272 if (m_hardIH[level][vect][i] !=0) nh++;
00273 }
00274 }
00275 if (nh == 0) {
00276
00277 int iv;
00278 bool found = false;
00279 for (iv=0; iv<m_irq[level].number_of_items; iv++) {
00280 if (found) m_irq[level].list_of_items[iv-1] = m_irq[level].list_of_items[iv];
00281 if (vect == m_irq[level].list_of_items[iv].vector) found = true;
00282 }
00283 if (found) {
00284
00285 if (m_irq[level].number_of_items > 0) {
00286 m_lastErrcode = VME_InterruptUnlink(m_irqId[level]);
00287 m_lastErrcode = VME_InterruptRegisterSignal(m_irqId[level], 0);
00288 }
00289
00290 if (--m_irq[level].number_of_items == 0) {
00291 m_irqId[level] = -1;
00292 } else {
00293 m_lastErrcode = VME_InterruptLink(&m_irq[level], &m_irqId[level]);
00294 m_lastErrcode = VME_InterruptRegisterSignal(m_irqId[level], 0);
00295 }
00296 }
00297 }
00298 } else if (softvec > 0 && softvec <= 32) {
00299 int i;
00300
00301 for (i=0; i<10; i++) {
00302 if (&handler == m_softIH[softvec-1][i]) {
00303 m_softIH[softvec-1][i]=0;
00304 return;
00305 }
00306 }
00307 }
00308 }
00309
00310 void RCCVmeInterface::reEnableInterrupt() {
00311 int i;
00312 for (i=0; i<8; i++) VME_InterruptReenable(m_irqId[i]);
00313 }
00314
00315 void RCCVmeInterface::blockInterruptNotification() {
00316 pthread_sigmask(SIG_BLOCK, &m_sigMask, NULL);
00317 }
00318
00319 void RCCVmeInterface::resumeInterruptNotification() {
00320 pthread_sigmask(SIG_UNBLOCK, &m_sigMask, NULL);
00321 }
00322
00323 unsigned char RCCVmeInterface::read8 (const unsigned long handle, const unsigned long offset) {
00324 u_char ldata;
00325 VME_ReadFastUChar(handle ,offset, &ldata);
00326 busErrorReport(handle);
00327 return ldata;
00328 }
00329
00330 unsigned char RCCVmeInterface::readS8 (const unsigned long handle, const unsigned long offset) {
00331 u_char ldata;
00332 VME_ErrorCode_t ret;
00333 ret = VME_ReadSafeUChar(handle ,offset, &ldata);
00334 if (ret != VME_SUCCESS) throw VmeException(VmeException::BUS_ERROR, VME_BUSERROR);
00335 return ldata;
00336 }
00337
00338 unsigned short RCCVmeInterface::read16 (const unsigned long handle, const unsigned long offset) {
00339 u_short ldata;
00340 VME_ReadFastUShort(handle ,offset, &ldata);
00341 busErrorReport(handle);
00342 return ldata;
00343 }
00344
00345 unsigned short RCCVmeInterface::readS16 (const unsigned long handle, const unsigned long offset) {
00346 u_short ldata;
00347 VME_ErrorCode_t ret;
00348 ret = VME_ReadSafeUShort(handle ,offset, &ldata);
00349 if (ret != VME_SUCCESS) throw VmeException(VmeException::BUS_ERROR, VME_BUSERROR);
00350 return ldata;
00351 }
00352
00353 unsigned long RCCVmeInterface::read32 (const unsigned long handle, const unsigned long offset) {
00354 u_int ldata;
00355 VME_ReadFastUInt(handle ,offset, &ldata);
00356 busErrorReport(handle);
00357 return ldata;
00358 }
00359
00360 unsigned long RCCVmeInterface::readS32 (const unsigned long handle, const unsigned long offset) {
00361 u_int ldata;
00362 VME_ErrorCode_t ret;
00363 ret = VME_ReadSafeUInt(handle ,offset, &ldata);
00364 if (ret != VME_SUCCESS) throw VmeException(VmeException::BUS_ERROR, VME_BUSERROR);
00365 return ldata;
00366 }
00367
00368 void RCCVmeInterface::write8 (const unsigned long handle, const unsigned long offset, const unsigned char value) {
00369 VME_WriteFastUChar(handle ,offset, value);
00370 busErrorReport(handle);
00371 }
00372
00373 void RCCVmeInterface::writeS8 (const unsigned long handle, const unsigned long offset, const unsigned char value) {
00374 VME_ErrorCode_t ret;
00375 ret = VME_WriteSafeUChar(handle ,offset, value);
00376 if (ret != VME_SUCCESS) throw VmeException(VmeException::BUS_ERROR, VME_BUSERROR);
00377 }
00378
00379 void RCCVmeInterface::write16(const unsigned long handle, const unsigned long offset, const unsigned short value) {
00380 VME_WriteFastUShort(handle ,offset, value);
00381 busErrorReport(handle);
00382 }
00383
00384 void RCCVmeInterface::writeS16 (const unsigned long handle, const unsigned long offset, const unsigned short value) {
00385 VME_ErrorCode_t ret;
00386 ret = VME_WriteSafeUShort(handle ,offset, value);
00387 if (ret != VME_SUCCESS) throw VmeException(VmeException::BUS_ERROR, VME_BUSERROR);
00388 }
00389
00390 void RCCVmeInterface::write32(const unsigned long handle, const unsigned long offset, const unsigned long value) {
00391 VME_WriteFastUInt(handle ,offset, value);
00392 busErrorReport(handle);
00393 }
00394
00395 void RCCVmeInterface::writeS32 (const unsigned long handle, const unsigned long offset, const unsigned long value) {
00396 VME_ErrorCode_t ret;
00397 ret = VME_WriteSafeUInt(handle ,offset, value);
00398 if (ret != VME_SUCCESS) throw VmeException(VmeException::BUS_ERROR, VME_BUSERROR);
00399 }
00400
00401 void RCCVmeInterface::blockRead32 (VmePort &port, const unsigned long offset, unsigned long *buf, const long len) {
00402 if (port.getAddrMod() == A16) {
00403
00404 return;
00405 }
00406 m_btList.number_of_items = 1;
00407 m_btList.list_of_items[0].vmebus_address = port.getBaseAddress()+offset;
00408 m_btList.list_of_items[0].size_requested = len;
00409 m_btList.list_of_items[0].control_word = VME_DMA_D32R | m_RCCAddrMod(port.getAddrMod());
00410 m_blockTransferRead(buf);
00411 busErrorReport(port);
00412 }
00413
00414 void RCCVmeInterface::blockRead64 (VmePort &port, const unsigned long offset, unsigned long *buf, const long len) {
00415 if (port.getAddrMod() == A16) {
00416
00417 return;
00418 }
00419 m_btList.number_of_items = 1;
00420 m_btList.list_of_items[0].vmebus_address = port.getBaseAddress()+offset;
00421 m_btList.list_of_items[0].size_requested = len;
00422 m_btList.list_of_items[0].control_word = VME_DMA_D64R | m_RCCAddrMod(port.getAddrMod());
00423 m_blockTransferRead(buf);
00424 busErrorReport(port);
00425 }
00426
00427 void RCCVmeInterface::blockWrite32(VmePort &port, const unsigned long offset, const unsigned long *buf, const long len) {
00428 if (port.getAddrMod() == A16) {
00429
00430 return;
00431 }
00432 m_btList.number_of_items = 1;
00433 m_btList.list_of_items[0].vmebus_address = port.getBaseAddress()+offset;
00434 m_btList.list_of_items[0].size_requested = len;
00435 m_btList.list_of_items[0].control_word = VME_DMA_D32W | m_RCCAddrMod(port.getAddrMod());
00436 m_blockTransferWrite(buf);
00437 busErrorReport(port);
00438 }
00439
00440 void RCCVmeInterface::blockWrite64(VmePort &port, const unsigned long offset, const unsigned long *buf, const long len) {
00441 if (port.getAddrMod() == A16) {
00442
00443 return;
00444 }
00445 m_btList.number_of_items = 1;
00446 m_btList.list_of_items[0].vmebus_address = port.getBaseAddress()+offset;
00447 m_btList.list_of_items[0].size_requested = len;
00448 m_btList.list_of_items[0].control_word = VME_DMA_D64W | m_RCCAddrMod(port.getAddrMod());
00449 m_blockTransferWrite(buf);
00450 busErrorReport(port);
00451 }
00452
00453 void RCCVmeInterface::m_blockTransferRead(unsigned long *buf) {
00454 unsigned long ret;
00455
00456 long vmebusAddr = m_btList.list_of_items[0].vmebus_address;
00457 if (vmebusAddr%4 != 0) throw VmeException(VmeException::MAP_ERROR, VMEADD_MISALIGNED);
00458
00459
00460 long size = m_btList.list_of_items[0].size_requested;
00461 if (size%8 != 0) m_btList.list_of_items[0].size_requested+=8-size%8;
00462 if (size > m_dmaBufSize) {
00463 CMEM_SegmentFree(m_dmaBuf);
00464 ret = CMEM_SegmentAllocate(size+0x1000, "VmeInterface DMA", &m_dmaBuf);
00465 if (ret) {
00466 m_dmaBufSize = 0;
00467 throw VmeException(VmeException::MAP_ERROR, DMAMEM_ALLOC_ERROR);
00468 } else {
00469 m_dmaBufSize = size+0x1000;
00470 }
00471 }
00472
00473 unsigned long pcidma;
00474 unsigned long *bdma;
00475 CMEM_SegmentPhysicalAddress(m_dmaBuf, &pcidma);
00476 CMEM_SegmentVirtualAddress (m_dmaBuf, (unsigned long*)&bdma);
00477 if (pcidma%4 != 0) throw VmeException(VmeException::MAP_ERROR, PCIADD_MISALIGNED);
00478 if ((pcidma-vmebusAddr)%8 != 0) throw VmeException(VmeException::MAP_ERROR, PCI_VME_MISALIGNED);
00479 m_btList.list_of_items[0].system_iobus_address = pcidma;
00480
00481 ret = VME_BlockTransfer(&m_btList, 10000);
00482
00483
00484
00485
00486
00487 if (ret) {
00488 throw VmeException(VmeException::MAP_ERROR, BT_READ_ERROR+ret);
00489 }
00490
00491 int i;
00492 for (i=0; i<(size>>2); i++) {
00493 buf[i] = bdma[i];
00494 }
00495 }
00496
00497 void RCCVmeInterface::m_blockTransferWrite(const unsigned long *buf) {
00498 unsigned long ret;
00499
00500 long vmebusAddr = m_btList.list_of_items[0].vmebus_address;
00501 if (vmebusAddr%4 != 0) throw VmeException(VmeException::MAP_ERROR, VMEADD_MISALIGNED);
00502
00503
00504 long size = m_btList.list_of_items[0].size_requested;
00505 if (size%8 != 0) m_btList.list_of_items[0].size_requested+=8-size%8;
00506 if (size > m_dmaBufSize) {
00507 CMEM_SegmentFree(m_dmaBuf);
00508 ret = CMEM_SegmentAllocate(size+0x1000, "VmeInterface DMA", &m_dmaBuf);
00509 if (ret) {
00510 m_dmaBufSize = 0;
00511 throw VmeException(VmeException::MAP_ERROR, DMAMEM_ALLOC_ERROR);
00512 } else {
00513 m_dmaBufSize = size+0x1000;
00514 }
00515 }
00516
00517 int i;
00518 unsigned long pcidma;
00519 unsigned long *bdma;
00520 CMEM_SegmentPhysicalAddress(m_dmaBuf, &pcidma);
00521 CMEM_SegmentVirtualAddress(m_dmaBuf, (unsigned long *)&bdma);
00522 if (pcidma%4 != 0) throw VmeException(VmeException::MAP_ERROR, PCIADD_MISALIGNED);
00523 if ((pcidma-vmebusAddr)%8 != 0) throw VmeException(VmeException::MAP_ERROR, PCI_VME_MISALIGNED);
00524 for (i=0; i<(size>>2); i++) {
00525 bdma[i] = buf[i];
00526 }
00527
00528 m_btList.list_of_items[0].system_iobus_address = pcidma;
00529
00530 ret = VME_BlockTransfer(&m_btList, 10000);
00531
00532
00533
00534
00535
00536 if (ret) {
00537 throw VmeException(VmeException::MAP_ERROR, BT_WRITE_ERROR+ret);
00538 }
00539 }
00540
00541 unsigned long RCCVmeInterface::registerPort(VmePort &port) {
00542 int handle;
00543 int ret;
00544 unsigned int ip;
00545 VME_MasterMap_t master_map = {0x0, 0x1000, VME_A32, 0};
00546
00547 master_map.vmebus_address = port.getBaseAddress();
00548 master_map.window_size = port.getMapSize();
00549 master_map.address_modifier = m_RCCAddrMod(port.getAddrMod());
00550 ret = VME_MasterMap(&master_map, &handle);
00551
00552 for (ip=0; ip<m_ports.size(); ip++) {
00553 if (m_ports[ip] == NULL) {
00554 m_ports[ip] = &port;
00555 return handle;
00556 }
00557 }
00558 m_ports.push_back(&port);
00559 return handle;
00560 }
00561
00562 void RCCVmeInterface::deletePort(VmePort &port) {
00563 unsigned int ip;
00564 int handle = port.getHandle();
00565 VME_MasterUnmap(handle);
00566 for (ip=0; ip<m_ports.size(); ip++) {
00567 if (m_ports[ip] == &port) {
00568 m_ports[ip] = NULL;
00569 }
00570 }
00571 }
00572
00573 void *RCCVmeInterface::getPortMap(const unsigned long handle) {
00574 u_int value;
00575 VME_MasterMapVirtualAddress(handle, &value);
00576 return (void *)value;
00577 }
00578
00579 int RCCVmeInterface::m_RCCAddrMod(VmeInterface::AddrMod mod) {
00580 switch (mod) {
00581 case A16:
00582 return VME_A16;
00583 break;
00584 case A24:
00585 return VME_A24;
00586 break;
00587 case A32:
00588 default:
00589 return VME_A32;
00590 break;
00591 };
00592 }
00593
00594 void RCCVmeInterface::busErrorReport() {
00595
00596 if (getBusErrors() != 0) throw VmeException(VmeException::BUS_ERROR, VME_BUSERROR);
00597 }
00598
00599 void RCCVmeInterface::busErrorReport(const unsigned long handle) {
00600 if (getBusErrors() != 0) {
00601
00602 unsigned int ip;
00603 for (ip=0; ip<m_ports.size(); ip++) {
00604 if (handle == m_ports[ip]->getHandle()) {
00605 if (m_ports[ip]->getExceptionTrapping()) {
00606 throw VmeException(VmeException::BUS_ERROR, VME_BUSERROR, m_ports[ip]);
00607 }
00608 }
00609 }
00610 }
00611 }
00612
00613 void RCCVmeInterface::busErrorReport(VmePort &port) {
00614 if (getBusErrors() != 0) throw VmeException(VmeException::BUS_ERROR, VME_BUSERROR, &port);
00615 }
00616
00617 std::string RCCVmeInterface::getErrorMessage(const long errcod) {
00618 char err[256];
00619 VME_ErrorString(errcod, err);
00620 return err;
00621 }
00622
00623 long RCCVmeInterface::getBusErrors() {
00624 long be = m_busErrors;
00625 m_busErrors = 0;
00626 VME_BusErrorInfoGet(&m_busErrInfo);
00627 return be;
00628 }