mrfioc2  2.3.0
drvemRxBuf.cpp
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2010 Brookhaven Science Associates, as Operator of
3 * Brookhaven National Laboratory.
4 * Copyright (c) 2015 Paul Scherrer Institute (PSI), Villigen, Switzerland
5 * mrfioc2 is distributed subject to a Software License Agreement found
6 * in file LICENSE that is included with this distribution.
7 \*************************************************************************/
8 /*
9  * Author: Michael Davidsaver <mdavidsaver@gmail.com>
10  */
11 
12 
13 
14 #include <cstdio>
15 #include <errlog.h>
16 
17 #ifdef _WIN32
18  #include <Winsock2.h>
19  #pragma comment (lib, "Ws2_32.lib")
20 #endif
21 #include <callback.h>
22 #include <mrfCommonIO.h>
23 #include <mrfBitOps.h>
24 #include <epicsInterrupt.h>
25 
26 #define DATABUF_H_INC_LEVEL2
27 #include <epicsExport.h>
28 #include "evrRegMap.h"
29 #include "drvemRxBuf.h"
30 
31 mrmBufRx::mrmBufRx(const std::string& n, volatile void *b,unsigned int qdepth, unsigned int bsize)
32  :bufRxManager(n, qdepth, bsize)
33  ,base((volatile unsigned char *)b)
34 {
35 }
36 
38 {
39  BITSET(NAT,32,base, DataBufCtrl, DataBufCtrl_stop);
40 }
41 
42 bool
44 {
45  return (READ32(base, DataBufCtrl) & DataBufCtrl_mode) != 0;
46 }
47 
48 void
50 {
51  int key=epicsInterruptLock();
52  if (v) {
53  // start reception and switch to DBus+data
54  BITSET(NAT,32,base, DataBufCtrl, DataBufCtrl_mode|DataBufCtrl_rx);
55  } else {
56  BITSET(NAT,32,base, DataBufCtrl, DataBufCtrl_stop); // stop reception
57  BITCLR(NAT,32,base, DataBufCtrl, DataBufCtrl_mode); // switch to DBus only
58  }
59  epicsInterruptUnlock(key);
60 }
61 
62 /* This callback is required from the ISR.
63  * The RX interrupt is not diabled, but since reception is complete
64  * the RX enable bit in the data buffer RX control register is cleared.
65  * The no additional data will be received, or interrupt generated, until
66  * we re-enable it.
67  *
68  * Further, since the DataBufCtrl and DataRx(i) registers are not used anywhere else
69  * we can safely avoid locking while accessing them.
70  */
71 extern int evrMrmSeqRxDebug;
72 
73 void
74 mrmBufRx::drainbuf(CALLBACK* cb)
75 {
76 try {
77  void *vptr;
78  callbackGetUser(vptr,cb);
79  mrmBufRx& self=*static_cast<mrmBufRx*>(vptr);
80 
81  epicsUInt32 sts=READ32(self.base, DataBufCtrl);
82 
83  // Configured to send?
84  if (!(sts&DataBufCtrl_mode))
85  return;
86 
87  // Still receiving?
88  if (sts&DataBufCtrl_rx)
89  return;
90 
91  if (sts&DataBufCtrl_sumerr) {
92  self.haderror(2);
93 
94  } else {
95  unsigned int bsize;
96  epicsUInt8 *buf=self.getFree(&bsize);
97 
98  if (!buf) {
99  self.haderror(1);
100  } else {
101 
102  unsigned int rsize=sts&DataBufCtrl_len_mask;
103 
104  if (rsize>bsize) {
105  errlogPrintf("Received data buffer with size %u >= %u\n", rsize, bsize);
106  rsize=bsize;
107  }
108 
109  if(evrMrmSeqRxDebug>=1)
110  {
111  errlogPrintf("buffer %s: size=%u %08x %08x %08x %08x\n",
112  self.name().c_str(), rsize,
113  (unsigned)BE_READ32(self.base, DataRx(0)),
114  (unsigned)BE_READ32(self.base, DataRx(4)),
115  (unsigned)BE_READ32(self.base, DataRx(8)),
116  (unsigned)BE_READ32(self.base, DataRx(12)));
117  }
118 
119  /* keep buffer in big endian mode (as sent by EVG) */
120  for(unsigned int i=0; i<rsize; i+=4) {
121  *(epicsUInt32*)(buf+i) = BE_READ32(self.base, DataRx(i));
122  }
123  self.receive(buf, rsize);
124  }
125  }
126 
127  WRITE32(self.base, DataBufCtrl, sts|DataBufCtrl_rx);
128 } catch(std::exception& e) {
129  epicsPrintf("exception in mrmBufRx::drainbuf callback: %s\n", e.what());
130 }
131 }
static void drainbuf(CALLBACK *)
Definition: drvemRxBuf.cpp:74
#define BITCLR(ord, len, base, offset, mask)
Definition: mrfBitOps.h:26
virtual void dataRxEnable(bool) OVERRIDE FINAL
Definition: drvemRxBuf.cpp:49
#define READ32(base, offset)
Definition: mrfCommonIO.h:114
#define BE_READ32(base, offset)
Definition: mrfCommonIO.h:164
#define DataBufCtrl_rx
Definition: evrRegMap.h:121
#define DataBufCtrl_len_mask
Definition: evrRegMap.h:126
int evrMrmSeqRxDebug
Definition: drvem.cpp:62
#define DataBufCtrl_stop
Definition: evrRegMap.h:123
#define DataBufCtrl_sumerr
Definition: evrRegMap.h:124
#define DataBufCtrl_mode
Definition: evrRegMap.h:125
mrmBufRx(const std::string &, volatile void *base, unsigned int qdepth, unsigned int bsize=0)
Definition: drvemRxBuf.cpp:31
const std::string & name() const
Definition: object.h:393
unsigned int bsize()
Definition: bufrxmgr.h:28
#define BITSET(ord, len, base, offset, mask)
Definition: mrfBitOps.h:21
volatile unsigned char *const base
Definition: drvemRxBuf.h:34
#define WRITE32(base, offset, value)
Definition: mrfCommonIO.h:119
virtual ~mrmBufRx()
Definition: drvemRxBuf.cpp:37
virtual bool dataRxEnabled() const OVERRIDE FINAL
Definition: drvemRxBuf.cpp:43