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 #pragma once
9 
10 #include <uhd/transport/nirio/nirio_driver_iface.h>
11 #include <uhd/transport/nirio/nirio_quirks.h>
12 #include <uhd/utils/noncopyable.hpp>
13 #include <stdint.h>
14 #include <boost/thread/locks.hpp>
15 #include <boost/thread/shared_mutex.hpp>
16 
17 #define NI_VENDOR_NUM   0x1093
18 
19 #define VERSION_BUILD_SHIFT     0
20 #define VERSION_PHASE_SHIFT     14
21 #define VERSION_MAINT_SHIFT     16
22 #define VERSION_UPGRD_SHIFT     20
23 #define VERSION_MAJOR_SHIFT     24
24 #define VERSION_BUILD_MASK      0x00003FFF
25 #define VERSION_PHASE_MASK      0x0000C000
26 #define VERSION_MAINT_MASK      0x000F0000
27 #define VERSION_UPGRD_MASK      0x00F00000
28 #define VERSION_MAJOR_MASK      0xFF000000
29 
30 #define GET_FIFO_MEMORY_TYPE(fifo_inst) (static_cast<uint16_t>(0x0100 | static_cast<uint16_t>(fifo_inst)))
31 
32 #define READER_LOCK \
33     boost::shared_lock<boost::shared_mutex> reader_lock(_synchronization);
34 
35 #define WRITER_LOCK \
36     boost::upgrade_lock<boost::shared_mutex> write_upgrade_lock(_synchronization);\
37     boost::upgrade_to_unique_lock<boost::shared_mutex> write_unique_lock(write_upgrade_lock);
38 
39 
40 namespace uhd { namespace niusrprio
41 {
42     enum nirio_version_t { CURRENT, OLDEST_COMPATIBLE };
43 
44     enum nirio_addr_space_t {
45        INVALID       = 0,
46        BUS_INTERFACE = 1,
47        FPGA          = 2,
48        BAR_WINDOW    = 3,
49     };
50 
51     typedef uint64_t nirio_u64_t;
52     typedef uint32_t nirio_u32_t;
53     typedef uint16_t nirio_u16_t;
54     typedef uint8_t nirio_u8_t;
55     typedef int32_t nirio_i32_t;
56 
57     typedef enum {
58         RIO_PRODUCT_NUMBER                  =  2UL, // 200
59         RIO_CURRENT_VERSION                 = 14UL, // 220
60         RIO_OLDEST_COMPATIBLE_VERSION       = 15UL, // 220
61         RIO_ADDRESS_SPACE                   = 25UL, // 230
62         RIO_IS_FPGA_PROGRAMMED              = 48UL, // 300
63         RIO_FPGA_DEFAULT_SIGNATURE_OFFSET   = 53UL, // 300 Default Offsets for FPGA
64                                                //     registers. Supplied by
65                                                //     the board driver on device
66                                                //     start.
67     } nirio_device_attribute32_t;
68 
69    typedef enum {
70       RIO_SCALAR_TYPE_IB = 1UL,
71       RIO_SCALAR_TYPE_IW = 2UL,
72       RIO_SCALAR_TYPE_IL = 3UL,
73       RIO_SCALAR_TYPE_IQ = 4UL,
74       RIO_SCALAR_TYPE_UB = 5UL,
75       RIO_SCALAR_TYPE_UW = 6UL,
76       RIO_SCALAR_TYPE_UL = 7UL,
77       RIO_SCALAR_TYPE_UQ = 8UL,
78    } nirio_scalar_type_t;
79 
map_int_to_scalar_type(uint32_t scalar_type_as_int)80    static inline nirio_scalar_type_t map_int_to_scalar_type(uint32_t scalar_type_as_int)
81    {
82       switch (scalar_type_as_int)
83       {
84       case 1: return RIO_SCALAR_TYPE_IB;
85       case 2: return RIO_SCALAR_TYPE_IW;
86       case 3: return RIO_SCALAR_TYPE_IL;
87       case 4: return RIO_SCALAR_TYPE_IQ;
88       case 5: return RIO_SCALAR_TYPE_UB;
89       case 6: return RIO_SCALAR_TYPE_UW;
90       case 7: return RIO_SCALAR_TYPE_UL;
91       case 8: return RIO_SCALAR_TYPE_UQ;
92       default: UHD_ASSERT_THROW(false); return RIO_SCALAR_TYPE_UL;
93       }
94    }
95 
96    enum fifo_direction_t {
97        INPUT_FIFO,
98        OUTPUT_FIFO
99    };
100 
101    struct nirio_fifo_info_t {
nirio_fifo_info_tnirio_fifo_info_t102        nirio_fifo_info_t(
103            uint32_t             arg_channel,
104            const char*         arg_name,
105            fifo_direction_t    arg_direction,
106            uint32_t             arg_base_addr,
107            uint32_t             arg_depth,
108            nirio_scalar_type_t         arg_scalar_type,
109            uint32_t            arg_bitWidth,
110            int32_t               arg_integerWordLength,
111            uint32_t             arg_version) :
112                channel(arg_channel),
113                name(arg_name),
114                direction(arg_direction),
115                base_addr(arg_base_addr),
116                depth(arg_depth),
117                scalar_type(arg_scalar_type),
118                bitWidth(arg_bitWidth),
119                integerWordLength(arg_integerWordLength),
120                version(arg_version)
121        {}
122 
123        uint32_t             channel;
124        std::string            name;
125        fifo_direction_t    direction;
126        uint32_t             base_addr;
127        uint32_t             depth;
128        nirio_scalar_type_t         scalar_type;
129        uint32_t            bitWidth;
130        int32_t             integerWordLength;
131        uint32_t             version;
132    };
133 
134     class UHD_API niriok_proxy : public uhd::noncopyable {
135     public:
136         typedef std::shared_ptr<niriok_proxy> sptr;
137 
138         static sptr make_and_open(const std::string& interface_path);
139 
140         niriok_proxy();
141         virtual ~niriok_proxy();
142 
143         //File operations
144         virtual nirio_status open(const std::string& interface_path) = 0;
145         virtual void close(void) = 0;
146 
147         virtual nirio_status reset() = 0;
148 
get_interface_num()149         uint32_t get_interface_num() { return _interface_num; }
150 
151         virtual nirio_status get_version(
152             nirio_version_t type,
153             uint32_t& major,
154             uint32_t& upgrade,
155             uint32_t& maintenance,
156             char& phase,
157             uint32_t& build) = 0;
158 
159         virtual nirio_status get_attribute(
160             const nirio_device_attribute32_t attribute,
161             uint32_t& attrValue) = 0;
162 
163         virtual nirio_status set_attribute(
164             const nirio_device_attribute32_t attribute,
165             const uint32_t value) = 0;
166 
167         virtual nirio_status peek(uint32_t offset, uint32_t& value) = 0;
168 
169         virtual nirio_status peek(uint32_t offset, uint64_t& value) = 0;
170 
171         virtual nirio_status poke(uint32_t offset, const uint32_t& value) = 0;
172 
173         virtual nirio_status poke(uint32_t offset, const uint64_t& value) = 0;
174 
175         virtual nirio_status map_fifo_memory(
176             uint32_t fifo_instance,
177             size_t size,
178             nirio_driver_iface::rio_mmap_t& map) = 0;
179 
180         virtual nirio_status unmap_fifo_memory(
181             nirio_driver_iface::rio_mmap_t& map) = 0;
182 
183         virtual nirio_status stop_all_fifos() = 0;
184 
get_rio_quirks()185         nirio_quirks& get_rio_quirks() {
186             return _rio_quirks;
187         }
188 
189         virtual nirio_status add_fifo_resource(const nirio_fifo_info_t& fifo_info) = 0;
190 
191         virtual nirio_status set_device_config() = 0;
192 
193         virtual nirio_status start_fifo(
194            uint32_t channel) = 0;
195 
196         virtual nirio_status stop_fifo(
197            uint32_t channel) = 0;
198 
199         virtual nirio_status configure_fifo(
200            uint32_t channel,
201            uint32_t requested_depth,
202            uint8_t requires_actuals,
203            uint32_t& actual_depth,
204            uint32_t& actual_size) = 0;
205 
206         virtual nirio_status wait_on_fifo(
207            uint32_t channel,
208            uint32_t elements_requested,
209            uint32_t scalar_type,
210            uint32_t bit_width,
211            uint32_t timeout,
212            uint8_t output,
213            void*& data_pointer,
214            uint32_t& elements_acquired,
215            uint32_t& elements_remaining) = 0;
216 
217         virtual nirio_status grant_fifo(
218            uint32_t channel,
219            uint32_t elements_to_grant) = 0;
220 
221         virtual nirio_status read_fifo(
222            uint32_t channel,
223            uint32_t elements_to_read,
224            void* buffer,
225            uint32_t buffer_datatype_width,
226            uint32_t scalar_type,
227            uint32_t bit_width,
228            uint32_t timeout,
229            uint32_t& number_read,
230            uint32_t& number_remaining) = 0;
231 
232         virtual nirio_status write_fifo(
233            uint32_t channel,
234            uint32_t elements_to_write,
235            void* buffer,
236            uint32_t buffer_datatype_width,
237            uint32_t scalar_type,
238            uint32_t bit_width,
239            uint32_t timeout,
240            uint32_t& number_remaining) = 0;
241 
242     protected:    //Members
243         nirio_driver_iface::rio_dev_handle_t    _device_handle;
244         uint32_t                                _interface_num;
245         nirio_quirks                            _rio_quirks;
246 
247         static boost::shared_mutex              _synchronization;
248 
249         // protected close function that doesn't acquire synchronization lock
250         virtual void _close() = 0;
251     };
252 
253     class niriok_scoped_addr_space : public uhd::noncopyable {
254     public:
niriok_scoped_addr_space(niriok_proxy::sptr proxy,nirio_addr_space_t addr_space,nirio_status & status)255         explicit niriok_scoped_addr_space(niriok_proxy::sptr proxy, nirio_addr_space_t addr_space, nirio_status& status) :
256             driver_proxy(proxy)
257         {
258             cache_status = driver_proxy->get_attribute(RIO_ADDRESS_SPACE, cached_addr_space);
259             nirio_status_chain(driver_proxy->set_attribute(RIO_ADDRESS_SPACE, addr_space), status);
260         }
261 
~niriok_scoped_addr_space()262         ~niriok_scoped_addr_space() {
263             if (nirio_status_not_fatal(cache_status))
264                 driver_proxy->set_attribute(RIO_ADDRESS_SPACE, cached_addr_space);
265         }
266 
267     private:
268         niriok_proxy::sptr driver_proxy;
269         uint32_t cached_addr_space;
270         nirio_status cache_status;
271     };
272 }}
273