1 //
2 // Copyright 2013-2014 Ettus Research LLC
3 // Copyright 2018 Ettus Research, a National Instruments Company
4 //
5 // SPDX-License-Identifier: GPL-3.0-or-later
6 //
7
8 #include <uhd/transport/nirio/niriok_proxy_impl_v1.h>
9 #include <cstring>
10
11 // "push" and "pop" introduced in GCC 4.6; works with all clang
12 #if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 3) && (__GNUC_MINOR__ > 5)
13 # pragma GCC diagnostic push
14 #endif
15 #if defined(__clang__) || defined(__GNUC__)
16 # pragma GCC diagnostic ignored "-Wmissing-field-initializers"
17 #endif
18
19 // CTL_CODE macro for non-win OSes
20 #ifndef UHD_PLATFORM_WIN32
21 # define CTL_CODE(a, controlCode, b, c) (controlCode)
22 #endif
23
24 const uint32_t NIRIO_IOCTL_BASE = 0x800;
25
26 const uint32_t NIRIO_IOCTL_SYNCOP = CTL_CODE(FILE_DEVICE_UNKNOWN,
27 NIRIO_IOCTL_BASE + 4,
28 METHOD_OUT_DIRECT,
29 FILE_READ_DATA | FILE_WRITE_DATA);
30 ///< The synchronous operation code. Note: We
31 /// must use METHOD_OUT_DIRECT on the syncOp()
32 /// IOCTL to ensure the contents of the output
33 /// block are available in the kernel.
34
35 const uint32_t NIRIO_IOCTL_GET_IFACE_NUM = CTL_CODE(FILE_DEVICE_UNKNOWN,
36 NIRIO_IOCTL_BASE + 6,
37 METHOD_BUFFERED,
38 FILE_READ_DATA); ///< Get the interface number for a device
39
40 // const uint32_t NIRIO_IOCTL_GET_SESSION =
41 // CTL_CODE(FILE_DEVICE_UNKNOWN,
42 // NIRIO_IOCTL_BASE + 8,
43 // METHOD_BUFFERED,
44 // FILE_READ_ACCESS); ///< Gets a previously opened session to a device
45
46 const uint32_t NIRIO_IOCTL_POST_OPEN = CTL_CODE(FILE_DEVICE_UNKNOWN,
47 NIRIO_IOCTL_BASE + 9,
48 METHOD_BUFFERED,
49 FILE_READ_ACCESS); ///< Called after opening a session
50
51 const uint32_t NIRIO_IOCTL_PRE_CLOSE = CTL_CODE(FILE_DEVICE_UNKNOWN,
52 NIRIO_IOCTL_BASE + 10,
53 METHOD_BUFFERED,
54 FILE_READ_ACCESS); ///< Called before closing a session
55
56 namespace uhd { namespace niusrprio {
57 // -------------------------------
58 // Function Codes: defined as integers rather than enums because they
59 // are going to be carried accross boundaries so size matters
60
61 struct NIRIO_FUNC
62 {
63 static const uint32_t GET32 = 0x00000001;
64 static const uint32_t SET32 = 0x00000002;
65 static const uint32_t SET_DRIVER_CONFIG = 0x00000007;
66 static const uint32_t FIFO = 0x00000008;
67 static const uint32_t IO = 0x0000000A;
68 static const uint32_t FIFO_STOP_ALL = 0x0000000C;
69 static const uint32_t ADD_RESOURCE = 0x0000000D;
70 static const uint32_t GET_STRING = 0x0000000E;
71 static const uint32_t SET_STRING = 0x0000000F;
72 static const uint32_t DOWNLOAD = 0x00000013;
73 static const uint32_t RESET = 0x00000014;
74 };
75
76 struct NIRIO_RESOURCE
77 {
78 static const uint32_t INPUT_FIFO = 0xD0000001;
79 static const uint32_t OUTPUT_FIFO = 0xD0000002;
80 };
81
82 struct NIRIO_FIFO
83 {
84 static const uint32_t CONFIGURE = 0x80000001;
85 static const uint32_t START = 0x80000002;
86 static const uint32_t STOP = 0x80000003;
87 static const uint32_t READ = 0x80000004;
88 static const uint32_t WRITE = 0x80000005;
89 static const uint32_t WAIT = 0x80000006;
90 static const uint32_t GRANT = 0x80000007;
91 };
92
93 struct NIRIO_IO
94 {
95 static const uint32_t POKE64 = 0xA0000005;
96 static const uint32_t POKE32 = 0xA0000006;
97 static const uint32_t POKE16 = 0xA0000007;
98 static const uint32_t POKE8 = 0xA0000008;
99 static const uint32_t PEEK64 = 0xA0000009;
100 static const uint32_t PEEK32 = 0xA000000A;
101 static const uint32_t PEEK16 = 0xA000000B;
102 static const uint32_t PEEK8 = 0xA000000C;
103 static const uint32_t READ_BLOCK = 0xA000000D;
104 static const uint32_t WRITE_BLOCK = 0xA000000E;
105 static const uint32_t GET_IO_WINDOW = 0xA000000F;
106 static const uint32_t GET_IO_WINDOW_SIZE = 0xA0000010;
107 };
108
109 struct nirio_ioctl_packet_t
110 {
nirio_ioctl_packet_tuhd::niusrprio::nirio_ioctl_packet_t111 nirio_ioctl_packet_t(
112 void* const _outBuf, const uint32_t _outSize, const int32_t _statusCode)
113 {
114 outBuf._64BitField = 0;
115 outBuf.pointer = _outBuf;
116 outSize = _outSize;
117 statusCode = _statusCode;
118 };
119
120 union {
121 void* pointer;
122 uint64_t _64BitField;
123 } outBuf;
124
125 uint32_t outSize;
126 int32_t statusCode;
127 };
128
129 struct nirio_syncop_in_params_t
130 {
131 uint32_t function;
132 uint32_t subfunction;
133
134 union {
135 struct
136 {
137 uint32_t attribute;
138 uint32_t value;
139 } attribute32;
140
141 struct
142 {
143 uint32_t attribute;
144 uint64_t value;
145 } attribute64;
146
147 struct
148 {
149 uint32_t attribute;
150 } attributeStr;
151
152 struct
153 {
154 uint32_t attribute;
155 } download;
156
157 union {
158 struct
159 {
160 uint32_t reserved_field_0_0_0;
161 } reserved_field_0_0;
162 struct
163 {
164 uint32_t reserved_field_0_1_0;
165 uint32_t reserved_field_0_1_1;
166 } reserved_field_0_1;
167 struct
168 {
169 uint32_t reserved_field_0_2_0;
170 } reserved_field_0_2;
171 } reserved_field_0;
172
173 union {
174 struct
175 {
176 uint32_t channel;
177 uint32_t baseAddress;
178 uint32_t depthInSamples;
179 uint32_t version;
180 } fifo;
181 struct
182 {
183 uint32_t channel;
184 uint32_t baseAddress;
185 uint32_t depthInSamples;
186 uint32_t version;
187 uint32_t scalarType;
188 uint32_t bitWidth;
189 } fifoWithDataType;
190 struct
191 {
192 uint64_t rangeBaseAddress;
193 uint32_t rangeSizeInBytes;
194 uint32_t rangeAttribute;
195 } atomic; // obsolete
196 } add;
197
198 struct
199 {
200 uint32_t channel;
201
202 union {
203 struct
204 {
205 uint32_t requestedDepth;
206 uint8_t requiresActuals;
207 } config;
208 struct
209 {
210 uint32_t timeout;
211 } read;
212 struct
213 {
214 uint32_t timeout;
215 uint32_t scalarType;
216 uint32_t bitWidth;
217 } readWithDataType;
218 struct
219 {
220 uint32_t timeout;
221 } write;
222 struct
223 {
224 uint32_t timeout;
225 uint32_t scalarType;
226 uint32_t bitWidth;
227 } writeWithDataType;
228 struct
229 {
230 uint32_t elementsRequested;
231 uint32_t scalarType;
232 uint32_t bitWidth;
233 uint32_t timeout;
234 uint8_t output;
235 } wait;
236 struct
237 {
238 uint32_t elements;
239 } grant;
240 } op;
241 } fifo;
242
243 struct
244 {
245 uint64_t reserved_field_1_0;
246 uint32_t reserved_field_1_1;
247 uint32_t reserved_field_1_2;
248 } reserved_field_1; // Obsolete
249
250 struct
251 {
252 uint32_t offset;
253 union {
254 uint64_t value64;
255 uint32_t value32;
256 uint16_t value16;
257 uint8_t value8;
258 } value;
259 union {
260 uint32_t sizeToMap;
261 } memoryMappedIoWindow;
262 } io;
263
264 struct
265 {
266 uint32_t reserved_field_2_0;
267 uint32_t reserved_field_2_1;
268 } reserved_field_2;
269
270 struct
271 {
272 uint32_t reserved_field_3_0;
273 } reserved_field_3;
274
275 union {
276 struct
277 {
278 uint32_t reserved_field_4_0;
279 int32_t reserved_field_4_1;
280 } wait;
281 } reserved_field_4;
282
283 } params;
284
285 uint32_t inbufByteLen;
286
287 union {
288 const void* pointer;
289 uint64_t _64BitField;
290 } inbuf;
291 };
292
init_syncop_in_params(nirio_syncop_in_params_t & param,const void * const buf,const uint32_t len)293 static inline void init_syncop_in_params(
294 nirio_syncop_in_params_t& param, const void* const buf, const uint32_t len)
295 {
296 param.inbuf._64BitField = 0;
297 param.inbuf.pointer = buf;
298 param.inbufByteLen = len;
299 }
300
301 struct nirio_syncop_out_params_t
302 {
303 union {
304 struct
305 {
306 uint32_t value;
307 } attribute32;
308
309 struct
310 {
311 uint64_t value;
312 } attribute64;
313
314 union {
315 struct
316 {
317 uint32_t reserved_field_0_0;
318 } enable;
319 } reserved_field_0;
320
321 struct
322 {
323 union {
324 struct
325 {
326 uint32_t actualDepth;
327 uint32_t actualSize;
328 } config;
329 struct
330 {
331 uint32_t numberRead;
332 uint32_t numberRemaining;
333 } read;
334 struct
335 {
336 uint32_t numberRemaining;
337 } write;
338 struct
339 {
340 union {
341 void* pointer;
342 uint64_t _64BitField;
343 } elements;
344 } wait;
345 } op;
346 } fifo;
347
348 struct
349 {
350 union {
351 union {
352 uint64_t value64;
353 uint32_t value32;
354 uint16_t value16;
355 uint8_t value8;
356 } value;
357 union {
358 void* memoryMappedAddress;
359 uint64_t _64BitField;
360 } memoryMappedIoWindow;
361 union {
362 uint32_t size;
363 } memoryMappedIoWindowSize;
364 };
365 } io;
366
367 uint32_t stringLength;
368
369 struct
370 {
371 uint32_t reserved_field_1_0;
372 } reserved_field_1;
373
374 } params;
375
376 uint32_t outbufByteLen;
377
378 union {
379 void* pointer;
380 uint64_t _64BitField;
381 } outbuf;
382 };
383
init_syncop_out_params(nirio_syncop_out_params_t & param,void * buf,uint32_t len)384 static inline void init_syncop_out_params(
385 nirio_syncop_out_params_t& param, void* buf, uint32_t len)
386 {
387 param.outbuf._64BitField = 0;
388 param.outbuf.pointer = buf;
389 param.outbufByteLen = len;
390 }
391
392 //-------------------------------------------------------
393 // niriok_proxy_impl_v1
394 //-------------------------------------------------------
niriok_proxy_impl_v1()395 niriok_proxy_impl_v1::niriok_proxy_impl_v1() {}
396
~niriok_proxy_impl_v1()397 niriok_proxy_impl_v1::~niriok_proxy_impl_v1()
398 {
399 close();
400 }
401
open(const std::string & interface_path)402 nirio_status niriok_proxy_impl_v1::open(const std::string& interface_path)
403 {
404 WRITER_LOCK
405
406 if (interface_path.empty())
407 return NiRio_Status_ResourceNotFound;
408
409 // close if already open.
410 // use non-locking _close since we already have the lock
411 _close();
412
413 nirio_status status = NiRio_Status_Success;
414 nirio_status_chain(
415 nirio_driver_iface::rio_open(interface_path, _device_handle), status);
416 if (nirio_status_not_fatal(status)) {
417 nirio_status_chain(nirio_driver_iface::rio_ioctl(
418 _device_handle, NIRIO_IOCTL_POST_OPEN, NULL, 0, NULL, 0),
419 status);
420 nirio_ioctl_packet_t out(&_interface_num, sizeof(_interface_num), 0);
421 nirio_status_chain(
422 nirio_driver_iface::rio_ioctl(
423 _device_handle, NIRIO_IOCTL_GET_IFACE_NUM, NULL, 0, &out, sizeof(out)),
424 status);
425
426 if (nirio_status_fatal(status))
427 _close();
428 }
429 return status;
430 }
431
close(void)432 void niriok_proxy_impl_v1::close(void)
433 {
434 WRITER_LOCK
435
436 _close();
437 }
438
439 // this protected _close doesn't acquire the lock, so it can be used in methods
440 // that already have the lock
_close()441 void niriok_proxy_impl_v1::_close()
442 {
443 if (nirio_driver_iface::rio_isopen(_device_handle)) {
444 nirio_driver_iface::rio_ioctl(
445 _device_handle, NIRIO_IOCTL_PRE_CLOSE, NULL, 0, NULL, 0);
446 nirio_driver_iface::rio_close(_device_handle);
447 }
448 }
449
reset()450 nirio_status niriok_proxy_impl_v1::reset()
451 {
452 READER_LOCK
453
454 nirio_syncop_in_params_t in = {};
455 nirio_syncop_out_params_t out = {};
456
457 in.function = NIRIO_FUNC::RESET;
458
459 return sync_operation(&in, sizeof(in), &out, sizeof(out));
460 }
461
get_version(nirio_version_t type,uint32_t & major,uint32_t & upgrade,uint32_t & maintenance,char & phase,uint32_t & build)462 nirio_status niriok_proxy_impl_v1::get_version(nirio_version_t type,
463 uint32_t& major,
464 uint32_t& upgrade,
465 uint32_t& maintenance,
466 char& phase,
467 uint32_t& build)
468 {
469 nirio_device_attribute32_t version_attr =
470 (type == CURRENT) ? RIO_CURRENT_VERSION : RIO_OLDEST_COMPATIBLE_VERSION;
471 uint32_t raw_version = 0;
472 nirio_status status = get_attribute(version_attr, raw_version);
473
474 major = (raw_version & VERSION_MAJOR_MASK) >> VERSION_MAJOR_SHIFT;
475 upgrade = (raw_version & VERSION_UPGRD_MASK) >> VERSION_UPGRD_SHIFT;
476 maintenance = (raw_version & VERSION_MAINT_MASK) >> VERSION_MAINT_SHIFT;
477 build = (raw_version & VERSION_BUILD_MASK) >> VERSION_BUILD_SHIFT;
478
479 uint32_t phase_num = (raw_version & VERSION_PHASE_MASK) >> VERSION_PHASE_SHIFT;
480 switch (phase_num) {
481 case 0:
482 phase = 'd';
483 break;
484 case 1:
485 phase = 'a';
486 break;
487 case 2:
488 phase = 'b';
489 break;
490 case 3:
491 phase = 'f';
492 break;
493 }
494
495 return status;
496 }
497
sync_operation(const void * writeBuffer,size_t writeBufferLength,void * readBuffer,size_t readBufferLength)498 nirio_status niriok_proxy_impl_v1::sync_operation(const void* writeBuffer,
499 size_t writeBufferLength,
500 void* readBuffer,
501 size_t readBufferLength)
502 {
503 READER_LOCK
504
505 nirio_ioctl_packet_t out(readBuffer, readBufferLength, 0);
506 nirio_status ioctl_status = nirio_driver_iface::rio_ioctl(_device_handle,
507 NIRIO_IOCTL_SYNCOP,
508 writeBuffer,
509 writeBufferLength,
510 &out,
511 sizeof(out));
512 if (nirio_status_fatal(ioctl_status))
513 return ioctl_status;
514
515 return out.statusCode;
516 }
517
get_attribute(const nirio_device_attribute32_t attribute,uint32_t & attrValue)518 nirio_status niriok_proxy_impl_v1::get_attribute(
519 const nirio_device_attribute32_t attribute, uint32_t& attrValue)
520 {
521 nirio_syncop_in_params_t in = {};
522 nirio_syncop_out_params_t out = {};
523
524 in.function = NIRIO_FUNC::GET32;
525 in.params.attribute32.attribute = static_cast<uint32_t>(attribute);
526
527 nirio_status status = sync_operation(&in, sizeof(in), &out, sizeof(out));
528
529 attrValue = out.params.attribute32.value;
530 return status;
531 }
532
set_attribute(const nirio_device_attribute32_t attribute,const uint32_t value)533 nirio_status niriok_proxy_impl_v1::set_attribute(
534 const nirio_device_attribute32_t attribute, const uint32_t value)
535 {
536 nirio_syncop_in_params_t in = {};
537 nirio_syncop_out_params_t out = {};
538
539 in.function = NIRIO_FUNC::SET32;
540 in.params.attribute32.attribute = static_cast<uint32_t>(attribute);
541 in.params.attribute32.value = value;
542
543 return sync_operation(&in, sizeof(in), &out, sizeof(out));
544 }
545
peek(uint32_t offset,uint32_t & value)546 nirio_status niriok_proxy_impl_v1::peek(uint32_t offset, uint32_t& value)
547 {
548 if (offset % 4 != 0)
549 return NiRio_Status_MisalignedAccess;
550
551 nirio_syncop_in_params_t in = {};
552 nirio_syncop_out_params_t out = {};
553
554 in.function = NIRIO_FUNC::IO;
555 in.subfunction = NIRIO_IO::PEEK32;
556 in.params.io.offset = offset;
557
558 nirio_status status = sync_operation(&in, sizeof(in), &out, sizeof(out));
559 value = out.params.io.value.value32;
560 return status;
561 }
562
peek(uint32_t offset,uint64_t & value)563 nirio_status niriok_proxy_impl_v1::peek(uint32_t offset, uint64_t& value)
564 {
565 if (offset % 8 != 0)
566 return NiRio_Status_MisalignedAccess;
567
568 nirio_syncop_in_params_t in = {};
569 nirio_syncop_out_params_t out = {};
570
571 in.function = NIRIO_FUNC::IO;
572 in.subfunction = NIRIO_IO::PEEK64;
573 in.params.io.offset = offset;
574
575 nirio_status status = sync_operation(&in, sizeof(in), &out, sizeof(out));
576 value = out.params.io.value.value64;
577 return status;
578 }
579
poke(uint32_t offset,const uint32_t & value)580 nirio_status niriok_proxy_impl_v1::poke(uint32_t offset, const uint32_t& value)
581 {
582 if (offset % 4 != 0)
583 return NiRio_Status_MisalignedAccess;
584
585 nirio_syncop_in_params_t in = {};
586 nirio_syncop_out_params_t out = {};
587
588 in.function = NIRIO_FUNC::IO;
589 in.subfunction = NIRIO_IO::POKE32;
590 in.params.io.offset = offset;
591 in.params.io.value.value32 = value;
592
593 return sync_operation(&in, sizeof(in), &out, sizeof(out));
594 }
595
poke(uint32_t offset,const uint64_t & value)596 nirio_status niriok_proxy_impl_v1::poke(uint32_t offset, const uint64_t& value)
597 {
598 if (offset % 8 != 0)
599 return NiRio_Status_MisalignedAccess;
600
601 nirio_syncop_in_params_t in = {};
602 nirio_syncop_out_params_t out = {};
603
604 in.function = NIRIO_FUNC::IO;
605 in.subfunction = NIRIO_IO::POKE64;
606 in.params.io.offset = offset;
607 in.params.io.value.value64 = value;
608
609 return sync_operation(&in, sizeof(in), &out, sizeof(out));
610 }
611
map_fifo_memory(uint32_t fifo_instance,size_t size,nirio_driver_iface::rio_mmap_t & map)612 nirio_status niriok_proxy_impl_v1::map_fifo_memory(
613 uint32_t fifo_instance, size_t size, nirio_driver_iface::rio_mmap_t& map)
614 {
615 READER_LOCK
616
617 return nirio_driver_iface::rio_mmap(
618 _device_handle, GET_FIFO_MEMORY_TYPE(fifo_instance), size, true, map);
619 }
620
unmap_fifo_memory(nirio_driver_iface::rio_mmap_t & map)621 nirio_status niriok_proxy_impl_v1::unmap_fifo_memory(nirio_driver_iface::rio_mmap_t& map)
622 {
623 READER_LOCK
624
625 return nirio_driver_iface::rio_munmap(map);
626 }
627
stop_all_fifos()628 nirio_status niriok_proxy_impl_v1::stop_all_fifos()
629 {
630 nirio_syncop_in_params_t in = {};
631 nirio_syncop_out_params_t out = {};
632
633 in.function = NIRIO_FUNC::FIFO_STOP_ALL;
634
635 return sync_operation(&in, sizeof(in), &out, sizeof(out));
636 }
637
add_fifo_resource(const nirio_fifo_info_t & fifo_info)638 nirio_status niriok_proxy_impl_v1::add_fifo_resource(const nirio_fifo_info_t& fifo_info)
639 {
640 nirio_syncop_in_params_t in = {};
641 nirio_syncop_out_params_t out = {};
642
643 in.function = NIRIO_FUNC::ADD_RESOURCE;
644 if (fifo_info.direction == OUTPUT_FIFO)
645 in.subfunction = NIRIO_RESOURCE::OUTPUT_FIFO;
646 else
647 in.subfunction = NIRIO_RESOURCE::INPUT_FIFO;
648
649 in.params.add.fifoWithDataType.channel = fifo_info.channel;
650 in.params.add.fifoWithDataType.baseAddress = fifo_info.base_addr;
651 in.params.add.fifoWithDataType.depthInSamples = fifo_info.depth;
652 in.params.add.fifoWithDataType.scalarType =
653 static_cast<uint32_t>(fifo_info.scalar_type);
654 in.params.add.fifoWithDataType.bitWidth = fifo_info.bitWidth;
655 in.params.add.fifoWithDataType.version = fifo_info.version;
656 // fifo_info.integerWordLength is not needed by the v1 kernel interface
657
658 return sync_operation(&in, sizeof(in), &out, sizeof(out));
659 }
660
set_device_config()661 nirio_status niriok_proxy_impl_v1::set_device_config()
662 {
663 nirio_syncop_in_params_t in = {};
664 nirio_syncop_out_params_t out = {};
665
666 in.function = NIRIO_FUNC::SET_DRIVER_CONFIG;
667 in.subfunction = 0;
668
669 return sync_operation(&in, sizeof(in), &out, sizeof(out));
670 }
671
start_fifo(uint32_t channel)672 nirio_status niriok_proxy_impl_v1::start_fifo(uint32_t channel)
673 {
674 nirio_syncop_in_params_t in = {};
675 nirio_syncop_out_params_t out = {};
676
677 in.function = NIRIO_FUNC::FIFO;
678 in.subfunction = NIRIO_FIFO::START;
679
680 in.params.fifo.channel = channel;
681
682 return sync_operation(&in, sizeof(in), &out, sizeof(out));
683 }
684
stop_fifo(uint32_t channel)685 nirio_status niriok_proxy_impl_v1::stop_fifo(uint32_t channel)
686 {
687 nirio_syncop_in_params_t in = {};
688 nirio_syncop_out_params_t out = {};
689
690 in.function = NIRIO_FUNC::FIFO;
691 in.subfunction = NIRIO_FIFO::STOP;
692
693 in.params.fifo.channel = channel;
694
695 return sync_operation(&in, sizeof(in), &out, sizeof(out));
696 }
697
configure_fifo(uint32_t channel,uint32_t requested_depth,uint8_t requires_actuals,uint32_t & actual_depth,uint32_t & actual_size)698 nirio_status niriok_proxy_impl_v1::configure_fifo(uint32_t channel,
699 uint32_t requested_depth,
700 uint8_t requires_actuals,
701 uint32_t& actual_depth,
702 uint32_t& actual_size)
703 {
704 nirio_status status = NiRio_Status_Success;
705
706 nirio_syncop_in_params_t in = {};
707 nirio_syncop_out_params_t out = {};
708
709 in.function = NIRIO_FUNC::FIFO;
710 in.subfunction = NIRIO_FIFO::CONFIGURE;
711
712 in.params.fifo.channel = channel;
713 in.params.fifo.op.config.requestedDepth = requested_depth;
714 in.params.fifo.op.config.requiresActuals = requires_actuals;
715
716 status = sync_operation(&in, sizeof(in), &out, sizeof(out));
717 if (nirio_status_fatal(status))
718 return status;
719
720 actual_depth = out.params.fifo.op.config.actualDepth;
721 actual_size = out.params.fifo.op.config.actualSize;
722
723 return status;
724 }
725
wait_on_fifo(uint32_t channel,uint32_t elements_requested,uint32_t scalar_type,uint32_t bit_width,uint32_t timeout,uint8_t output,void * & data_pointer,uint32_t & elements_acquired,uint32_t & elements_remaining)726 nirio_status niriok_proxy_impl_v1::wait_on_fifo(uint32_t channel,
727 uint32_t elements_requested,
728 uint32_t scalar_type,
729 uint32_t bit_width,
730 uint32_t timeout,
731 uint8_t output,
732 void*& data_pointer,
733 uint32_t& elements_acquired,
734 uint32_t& elements_remaining)
735 {
736 nirio_status status = NiRio_Status_Success;
737
738 nirio_syncop_in_params_t in = {};
739 uint32_t stuffed[2];
740 nirio_syncop_out_params_t out = {};
741 init_syncop_out_params(out, stuffed, sizeof(stuffed));
742
743 in.function = NIRIO_FUNC::FIFO;
744 in.subfunction = NIRIO_FIFO::WAIT;
745
746 in.params.fifo.channel = channel;
747 in.params.fifo.op.wait.elementsRequested = elements_requested;
748 in.params.fifo.op.wait.scalarType = scalar_type;
749 in.params.fifo.op.wait.bitWidth = bit_width;
750 in.params.fifo.op.wait.output = output;
751 in.params.fifo.op.wait.timeout = timeout;
752
753 status = sync_operation(&in, sizeof(in), &out, sizeof(out));
754 if (nirio_status_fatal(status))
755 return status;
756
757 data_pointer = out.params.fifo.op.wait.elements.pointer;
758 elements_acquired = stuffed[0];
759 elements_remaining = stuffed[1];
760
761 return status;
762 }
763
grant_fifo(uint32_t channel,uint32_t elements_to_grant)764 nirio_status niriok_proxy_impl_v1::grant_fifo(
765 uint32_t channel, uint32_t elements_to_grant)
766 {
767 nirio_syncop_in_params_t in = {};
768 nirio_syncop_out_params_t out = {};
769
770 in.function = NIRIO_FUNC::FIFO;
771 in.subfunction = NIRIO_FIFO::GRANT;
772
773 in.params.fifo.channel = channel;
774 in.params.fifo.op.grant.elements = elements_to_grant;
775
776 return sync_operation(&in, sizeof(in), &out, sizeof(out));
777 }
778
read_fifo(uint32_t channel,uint32_t elements_to_read,void * buffer,uint32_t buffer_datatype_width,uint32_t scalar_type,uint32_t bit_width,uint32_t timeout,uint32_t & number_read,uint32_t & number_remaining)779 nirio_status niriok_proxy_impl_v1::read_fifo(uint32_t channel,
780 uint32_t elements_to_read,
781 void* buffer,
782 uint32_t buffer_datatype_width,
783 uint32_t scalar_type,
784 uint32_t bit_width,
785 uint32_t timeout,
786 uint32_t& number_read,
787 uint32_t& number_remaining)
788 {
789 nirio_status status = NiRio_Status_Success;
790
791 nirio_syncop_in_params_t in = {};
792 nirio_syncop_out_params_t out = {};
793 init_syncop_out_params(out, buffer, elements_to_read * buffer_datatype_width);
794
795 in.function = NIRIO_FUNC::FIFO;
796 in.subfunction = NIRIO_FIFO::READ;
797
798 in.params.fifo.channel = channel;
799 in.params.fifo.op.readWithDataType.timeout = timeout;
800 in.params.fifo.op.readWithDataType.scalarType = scalar_type;
801 in.params.fifo.op.readWithDataType.bitWidth = bit_width;
802
803 status = sync_operation(&in, sizeof(in), &out, sizeof(out));
804 if (nirio_status_fatal(status) && (status != NiRio_Status_FifoTimeout))
805 return status;
806
807 number_read = out.params.fifo.op.read.numberRead;
808 number_remaining = out.params.fifo.op.read.numberRemaining;
809
810 return status;
811 }
812
write_fifo(uint32_t channel,uint32_t elements_to_write,void * buffer,uint32_t buffer_datatype_width,uint32_t scalar_type,uint32_t bit_width,uint32_t timeout,uint32_t & number_remaining)813 nirio_status niriok_proxy_impl_v1::write_fifo(uint32_t channel,
814 uint32_t elements_to_write,
815 void* buffer,
816 uint32_t buffer_datatype_width,
817 uint32_t scalar_type,
818 uint32_t bit_width,
819 uint32_t timeout,
820 uint32_t& number_remaining)
821 {
822 nirio_status status = NiRio_Status_Success;
823
824 nirio_syncop_in_params_t in = {};
825 init_syncop_in_params(in, buffer, elements_to_write * buffer_datatype_width);
826 nirio_syncop_out_params_t out = {};
827
828 in.function = NIRIO_FUNC::FIFO;
829 in.subfunction = NIRIO_FIFO::WRITE;
830
831 in.params.fifo.channel = channel;
832 in.params.fifo.op.writeWithDataType.timeout = timeout;
833 in.params.fifo.op.writeWithDataType.scalarType = scalar_type;
834 in.params.fifo.op.writeWithDataType.bitWidth = bit_width;
835
836 status = sync_operation(&in, sizeof(in), &out, sizeof(out));
837 if (nirio_status_fatal(status) && (status != NiRio_Status_FifoTimeout))
838 return status;
839
840 number_remaining = out.params.fifo.op.write.numberRemaining;
841
842 return status;
843 }
844
845 }} // namespace uhd::niusrprio
846
847 #if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 3) && (__GNUC_MINOR__ > 5)
848 # pragma GCC diagnostic pop
849 #endif
850