AFHBA404
AFHBA404 connects ACQ2106 to PCI-Express
rtm-t-stream.cpp
Go to the documentation of this file.
1 /* ------------------------------------------------------------------------- */
2 /* rtm-t-stream.so RTM-T PCIe Host Side stream access */
3 /* ------------------------------------------------------------------------- */
4 /* Copyright (C) 2010 Peter Milne, D-TACQ Solutions Ltd
5  * <Peter dot Milne at D hyphen TACQ dot com>
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of Version 2 of the GNU General Public License
9  as published by the Free Software Foundation;
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19 /* ------------------------------------------------------------------------- */
20 
21 
26 #include <stdio.h>
27 #include <unistd.h>
28 #include <errno.h>
29 #include <stdlib.h>
30 #include <sys/eventfd.h>
31 #include <sys/ioctl.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <sys/time.h>
35 #include <fcntl.h>
36 
37 #include "local.h"
38 #include "rtm-t_ioctl.h"
39 #include "RTM_T_Device.h"
40 
41 #include "rtm-t-stream.h"
42 
43 #define DBG(args...) //fprintf(stderr, args)
44 
45 #ifdef __GNUC__
46 #define LIKELY(x) (__builtin_expect(!!(x), 1))
47 #define UNLIKELY(x) (__builtin_expect(!!(x), 0))
48 #else
49 #define LIKELY(x) (x)
50 #define UNLIKELY(x) (x)
51 #endif
52 
53 #define SBDN RTM_T_Device::MAXBUF
54 typedef struct {
56  int stop;
57  int nbuf;
58  int ibuf;
59  struct StreamBufferDef sbd[SBDN];
61 
62 
63 #define TEST_NULLPTR(ptr) do{if UNLIKELY(!ptr){fprintf(stderr, "NULL pointer error");return -1;}}while(0)
64 #define ERROR_START(errorcode, message) do{\
65  perror(message " error");\
66  if (stream && stream->dev)\
67  delete stream->dev;\
68  if (stream)\
69  free(stream);\
70  return errorcode;\
71 }while(0)
72 
73 #include <poll.h>
74 #define CHECK(i) (pfds[i].revents & POLLIN)
75 #define CHECK_STOP CHECK(0)
76 #define CHECK_FD CHECK(1)
77 static int fetch_buffers(STREAM_P const stream)
78 {
79  stream->ibuf = 0;
80  const int fd = stream->dev->getDeviceHandle();
81  struct pollfd pfds[2] = {
82  { .fd=stream->stop, .events=POLLIN },
83  { .fd=fd, .events=POLLIN },
84  };
85  const int ready = poll(pfds, 2, -1);
86  if LIKELY(ready > 0)
87  {
88  if LIKELY(!CHECK_STOP && CHECK_FD)
89  {
90  const int nread = read(fd, stream->sbd, SBDN*SBDSZ);
91  DBG("nread=%d\n", nread);
92  if UNLIKELY(nread < 0)
93  {
94  perror("read error");
95  return -1;
96  }
97  else
98  {
99  stream->nbuf = nread/SBDSZ;
100  return 0;
101  }
102  }
103  else
104  {
105  stream->nbuf = 0;
106  return 0; // end if stream
107  }
108  }
109  else if (ready < -1)
110  {
111  perror("poll error");
112  return -1;
113  }
114  else
115  {
116  stream->nbuf = 0;
117  return 0; // timeout == -1 so end if stream ?
118  }
119 }
120 
121 static inline int get_bufno(StreamBufferDef* sbd)
122 {
124  {
125  fprintf(stderr, "ERROR NOT IBUF_MAGIC %08x %08x\n",
126  sbd->ibuf, sbd->esta);
127  exit(1);
128  }
129  return sbd->ibuf&IBUF_IBUF;
130 }
131 
132 static inline int release_buffer(void *const handle, const int bufno)
133 {
134  return write(((STREAM_P)handle)->dev->getDeviceHandle(), &bufno, sizeof(int)) != sizeof(int);
135 }
136 
137 EXPORT int RtmStreamStart(void **handle, const int devnum, const int NBUFS, int *const maxlen)
138 {
139  TEST_NULLPTR(handle);
140  STREAM_P const stream = (STREAM_P)malloc(sizeof(STREAM));
141  if UNLIKELY(!stream)
142  ERROR_START(1, "malloc");
143  if UNLIKELY((stream->stop = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK)) < 0)
144  ERROR_START(2, "eventfd");
145  RTM_T_Device *dev = stream->dev = new RTM_T_Device(devnum);
146  if UNLIKELY(!dev)
147  ERROR_START(3, "RTM_T_Device");
148  const int fp = dev->getDeviceHandle();
149  const int rc = NBUFS
150  ? ioctl(fp, RTM_T_START_STREAM_MAX, &NBUFS)
151  : ioctl(fp, RTM_T_START_STREAM);
152  if UNLIKELY(rc)
153  ERROR_START(4, "ioctl");
154  stream->nbuf = 0;
155  stream->ibuf = 0;
156  if (maxlen)
157  *maxlen = dev->maxlen;
158  *handle = (void*)stream;
159  return 0;
160 }
161 
162 EXPORT int RtmStreamStop(void *handle)
163 {
164  TEST_NULLPTR(handle);
165  STREAM_P const stream = (STREAM_P)handle;
166  const uint64_t value = 1;
167  return write(stream->stop, &value, sizeof(value)) != sizeof(value);
168 }
169 
170 
171 EXPORT int RtmStreamClose(void *handle)
172 {
173  TEST_NULLPTR(handle);
174  STREAM_P const stream = (STREAM_P)handle;
175  delete stream->dev;
176  close(stream->stop);
177  free(handle);
178  return 0;
179 }
180 
181 EXPORT int RtmStreamGetBuffer(void *handle, void *const buf, const int buflen)
182 {
183  TEST_NULLPTR(handle);
184  TEST_NULLPTR(buf);
185  STREAM_P const stream = (STREAM_P)handle;
186  if (stream->ibuf == stream->nbuf)
187  {
188  DBG("update ibuf=%d nbuf=%d\n", stream->ibuf, stream->nbuf);
189  if (fetch_buffers(stream))
190  {
191  perror("fetch error");
192  return -1;
193  }
194  if UNLIKELY(!stream->nbuf)
195  {
196  return 1;
197  }
198  }
199  const int bufno = get_bufno(&stream->sbd[stream->ibuf++]);
200  DBG("ibuf=%d nbuf=%d bufno=%d\n", stream->ibuf, stream->nbuf, bufno);
201  memcpy(buf, stream->dev->getHostBufferMapping(bufno), buflen);
202  return release_buffer(stream, bufno);
203 }
DBG
#define DBG(args...)
Definition: rtm-t-stream.cpp:43
RtmStreamClose
EXPORT int RtmStreamClose(void *handle)
Definition: rtm-t-stream.cpp:171
SBDSZ
#define SBDSZ
Definition: rtm-t_ioctl.h:127
local.h
IBUF_IBUF
#define IBUF_IBUF
Definition: rtm-t_ioctl.h:125
StreamBufferDef::ibuf
u32 ibuf
Definition: rtm-t_ioctl.h:118
STREAM
#define STREAM
Definition: acq-fiber-hba.c:431
ERROR_START
#define ERROR_START(errorcode, message)
Definition: rtm-t-stream.cpp:64
rtm-t-stream.h
SBDN
#define SBDN
Definition: rtm-t-stream.cpp:53
LIKELY
#define LIKELY(x)
Definition: rtm-t-stream.cpp:49
RtmStreamStart
EXPORT int RtmStreamStart(void **handle, const int devnum, const int NBUFS, int *const maxlen)
Definition: rtm-t-stream.cpp:137
RTM_T_Device::maxlen
const unsigned maxlen
Definition: RTM_T_Device.h:46
StreamBufferDef::esta
u32 esta
Definition: rtm-t_ioctl.h:119
RTM_T_START_STREAM_MAX
#define RTM_T_START_STREAM_MAX
ioctl Start High Throughput Streaming specify max buffers.
Definition: rtm-t_ioctl.h:85
RTM_T_Device::getDeviceHandle
const int getDeviceHandle(void)
Definition: RTM_T_Device.h:56
CHECK_STOP
#define CHECK_STOP
Definition: rtm-t-stream.cpp:75
rtm-t_ioctl.h
STREAM::dev
RTM_T_Device * dev
Definition: rtm-t-stream.cpp:55
CHECK_FD
#define CHECK_FD
Definition: rtm-t-stream.cpp:76
STREAM_P
struct STREAM * STREAM_P
EXPORT
#define EXPORT
Definition: rtm-t-stream.h:21
TEST_NULLPTR
#define TEST_NULLPTR(ptr)
Definition: rtm-t-stream.cpp:63
NBUFS
int NBUFS
Definition: rtm-t-stream-disk.cpp:84
RtmStreamStop
EXPORT int RtmStreamStop(void *handle)
Definition: rtm-t-stream.cpp:162
STREAM::nbuf
int nbuf
Definition: rtm-t-stream.cpp:57
rtm-t-stream.stream
stream
Definition: rtm-t-stream.py:44
RTM_T_START_STREAM
#define RTM_T_START_STREAM
ioctl Start High Throughput Streaming
Definition: rtm-t_ioctl.h:79
STREAM::stop
int stop
Definition: rtm-t-stream.cpp:56
RTM_T_Device.h
RTM_T_Device
Definition: RTM_T_Device.h:17
IBUF_MAGIC_MASK
#define IBUF_MAGIC_MASK
Definition: rtm-t_ioctl.h:122
StreamBufferDef
Definition: rtm-t_ioctl.h:117
STREAM
Definition: rtm-t-stream.cpp:54
UNLIKELY
#define UNLIKELY(x)
Definition: rtm-t-stream.cpp:50
IBUF_MAGIC
#define IBUF_MAGIC
Definition: rtm-t_ioctl.h:121
RtmStreamGetBuffer
EXPORT int RtmStreamGetBuffer(void *handle, void *const buf, const int buflen)
Definition: rtm-t-stream.cpp:181