Line data Source code
1 : #ifndef DEVICE_H_
2 : #define DEVICE_H_
3 :
4 : #include <cstdint>
5 : #include <sys/types.h>
6 : #include <string>
7 :
8 : #include "flxcard/FlxCard.h"
9 : #include "cmem_buffer.hpp"
10 : #include "config/config.hpp"
11 : #include "elink.hpp"
12 :
13 : #define MAX_BROADCAST_CHANNELS (32)
14 : #define MAX_BROADCAST_ELINKS (1 + 32 + 64)
15 :
16 : #define TOFLX_EOM_MASK_RM4 0x0001
17 : #define TOFLX_EOM_SHIFT_RM4 0
18 : #define TOFLX_LENGTH_MASK_RM4 0x001E
19 : #define TOFLX_LENGTH_SHIFT_RM4 1
20 : #define TOFLX_ELINK_MASK_RM4 0xFFE0
21 : #define TOFLX_ELINK_SHIFT_RM4 5
22 : #define TOFLX_LENGTH_MASK 0x001F
23 : #define TOFLX_ELINK_SHIFT 5
24 : #define TOFLX_LENGTH_MASK_HDR32 0x003F
25 : #define TOFLX_ELINK_SHIFT_HDR32 6
26 : #define TOFLX_LENGTH_MASK_HDR32_8B 0x000000FF
27 : #define TOFLX_ELINK_SHIFT_HDR32_8B 8
28 :
29 :
30 : enum flx_fromhost_format {
31 : FROMHOST_FORMAT_REGMAP4,
32 : FROMHOST_FORMAT_5BIT_LENGTH,
33 : FROMHOST_FORMAT_HDR32_PACKET32,
34 : FROMHOST_FORMAT_HDR32_PACKET64,
35 : // Header with 8-bit fields (see FLX-2294):
36 : FROMHOST_FORMAT_HDR32_PACKET32_8B,
37 : FROMHOST_FORMAT_HDR32_PACKET64_8B,
38 : FROMHOST_FORMAT_HDR32_PACKET128_8B,
39 : UN_INITIALIZED
40 : };
41 :
42 : enum flx_tohost_format {
43 : TOHOST_SUBCHUNK_TRAILER,
44 : TOHOST_SUBCHUNK_HEADER
45 : };
46 :
47 : /**
48 : * Abstract base class that represents a Felix device.
49 : * The two implementations are FlxDevice and FileDevice.
50 : * FlxDevice manages one PCIe endpoint of a physical FELIX card.
51 : * FileDevice emulates the hardware.
52 : */
53 : class Device
54 : {
55 : protected:
56 : unsigned m_device_number;
57 : uint8_t m_vid;
58 : uint16_t m_did, m_cid;
59 : u_int m_firmware_type;
60 : flx_fromhost_format m_fromHostDataFormat {UN_INITIALIZED};
61 : flx_tohost_format m_toHostDataFormat {TOHOST_SUBCHUNK_TRAILER};
62 :
63 : /**
64 : * @return value of BROADCAST_ENABLE_GEN register
65 : * @param channel the link to be checked
66 : */
67 : virtual uint64_t get_broadcast_enable_gen(u_int channel) = 0;
68 :
69 : /**
70 : * Check if the e-link has streams enabled
71 : * @param channel (lp)GBT link
72 : * @param egroup (lp)GBT e-group
73 : * @param epath (lp)GBT e-path
74 : */
75 : virtual bool elink_has_stream_id(u_int channel, u_int egroup, u_int epath) = 0;
76 :
77 : public:
78 :
79 : /**
80 : * Constructor of abstract class to be used by implementation.
81 : * The constructor allocates the object, does not interact with hardware.
82 : *
83 : * @param dev_no Device number, as use dby the flx driver.
84 : * @param vid Version of felix resource identifier (fid)
85 : * @param did Detector ID of felix resource identifier
86 : * @param cid Connect ID of felix resource identifier, maps to the PCIe endpoint
87 : */
88 : Device(unsigned dev_no, uint8_t vid, uint16_t did, uint16_t cid);
89 :
90 : /**
91 : * Opens the device, maps and reads registers, sets resource locks.
92 : * @param lock_mask to lock resources at driver level
93 : */
94 : virtual int open_device(u_int lock_mask) = 0;
95 :
96 : /**
97 : * Releases the device.
98 : */
99 : virtual void close_device() = 0;
100 :
101 : /**
102 : * @return whether if this PCIe endpoint is the primary,
103 : * where all registers are available.
104 : */
105 : virtual bool is_primary() = 0;
106 :
107 : /**
108 : * @return the card type: 709, 710, 711, 712, 182, 155.
109 : */
110 : virtual unsigned int get_card_model() = 0;
111 :
112 : /**
113 : * @return number of PCIe endpoints for the card
114 : */
115 : virtual unsigned int get_card_endpoints() = 0;
116 :
117 : /**
118 : * @return the firmware register map version, read from the
119 : * register REG_MAP_VERSION
120 : */
121 : virtual u_int get_regmap_version() = 0;
122 :
123 : /**
124 : * @return the firmware type as reported in the register FIRMWARE_MODE
125 : */
126 0 : virtual u_int get_firmware_type(){return m_firmware_type;}
127 :
128 : /**
129 : * @return the number of links for the PCie endpoint as reported in
130 : * the register NUM_OF_CHANNELS
131 : */
132 : virtual u_int get_number_of_channels() = 0;
133 :
134 : /**
135 : * @return whether GBT wide mode is used
136 : */
137 : virtual bool get_wide_mode() = 0;
138 :
139 : /**
140 : * @return the ToHost block size as read from the BLOCKSIZE register
141 : */
142 : virtual u_int get_block_size() = 0;
143 :
144 : /**
145 : * @return the ToHost trailer/header size. Derived from CHUNK_TRAILER_32B.
146 : */
147 : virtual u_int get_trailer_size() = 0;
148 :
149 : /**
150 : * @return the FromHost data format, as in FROMHOST_DATA_FORMAT.
151 : */
152 : virtual flx_fromhost_format get_fromhost_data_format() = 0;
153 :
154 : /**
155 : * @return the ToHost data format, as in TOHOST_DATA_FORMAT.
156 : */
157 : virtual flx_tohost_format get_tohost_data_format() = 0;
158 :
159 : /**
160 : * @return the identifier of the FromHoist DMA buffer, to be used by
161 : * felix-toflx.
162 : */
163 : virtual int get_fromhost_dmaid() = 0;
164 :
165 : /**
166 : * @return the identifier of the Trickle configuration DMA buffer.
167 : */
168 : virtual int get_trickle_dmaid() = 0;
169 :
170 : /**
171 : * @return the maximum size supported for a TLP block
172 : */
173 : virtual int dma_max_tlp_bytes() = 0;
174 :
175 : /**
176 : * \defgroup Registers
177 : * @{
178 : * Functions to interact with the device registers
179 : */
180 : /**
181 : * Set a new value for the given register
182 : * @param key register name
183 : * @param value register value
184 : */
185 : virtual void set_register(const char *key, uint64_t value) = 0;
186 :
187 : /**
188 : * Get the current value of the fiven register
189 : * @param key register name
190 : */
191 : virtual uint64_t get_register(const char *key) = 0;
192 :
193 : /**
194 : * @return if the given register exists
195 : * @param key register name
196 : */
197 : virtual bool check_register(const char *key) = 0;
198 : /**
199 : * @}
200 : */
201 :
202 : /**
203 : * \defgroup Interrupts
204 : * @{
205 : * Functions to configure or wait for MSI-X interrupts
206 : */
207 : /**
208 : * Cancel wait requests for the given MSI-X interrupt
209 : * @param i Interrupt number
210 : */
211 : virtual void cancel_irq(int i) = 0;
212 :
213 : /**
214 : * Wait for the given interrupt. This function blocks.
215 : * @param i Interrupt number
216 : */
217 : virtual void irq_wait(int i) = 0;
218 :
219 : /**
220 : * Arm the given interrupt.
221 : * @param i interrupt number
222 : */
223 : virtual void irq_enable(int i) = 0;
224 :
225 : /**
226 : * Disarm the given interrupt.
227 : * @param i interrupt number
228 : */
229 : virtual void irq_disable(int i) = 0;
230 : /**
231 : * @}
232 : */
233 :
234 : /**
235 : * \defgroup E-link configuration
236 : * @{
237 : * Functions related to e-link configuration including broadcast
238 : */
239 : /**
240 : * Return the list of enabled e-links for the given DMA id.
241 : * @param dmaid dma buffer identifier
242 : */
243 : virtual std::vector<Elink> read_enabled_elinks(int dmaid) = 0;
244 :
245 : /**
246 : * Return the list of e-links enabled of a given type.
247 : * @param dmaid dma buffer identifier
248 : * @param t e-link type e.g. DAQ, DCS, TTC2H...
249 : */
250 : std::vector<Elink> get_enabled_elinks_of_type(int dmaid, elink_type_t t);
251 :
252 : /**
253 : * @return the device number.
254 : */
255 235 : unsigned get_device_number(){return m_device_number;}
256 :
257 : /**
258 : * @return the lock mask for DMA resources
259 : * @param dmaids list of DMA buffers in use
260 : */
261 : unsigned int make_dma_lock_mask(const std::vector<int>& dmaids);
262 :
263 : /**
264 : * @return the number of broadcast e-links
265 : * @param broadcast_elinks list of DMA buffers in use
266 : * @param num_of_channels list of DMA buffers in use
267 : */
268 : u_int get_broadcast_elinks(uint64_t broadcast_elinks[], uint32_t num_of_channels);
269 :
270 : /**
271 : * @return (?)
272 : * @param elink list of DMA buffers in use
273 : */
274 : static int64_t broadcast_for(uint64_t elink);
275 :
276 : /**
277 : * @return the level of broadcast: link, channel, e-liink
278 : * @param elink broadcast e-link
279 : */
280 : static int broadcast_type(uint64_t elink);
281 :
282 : /**
283 : * @return the level of broadcast: link, channel, e-liink
284 : * @param elink broadcast e-link
285 : */
286 : static const std::string broadcast_type_str(uint64_t elink);
287 :
288 : /**
289 : * @brief read broadcast_elinks and broadcast_enable_registers
290 : * @param broadcast_elinks array of broadcast enabled e-links per link
291 : * @param broadcast_enable_registers register values for each link
292 : * @param num_of_channels number of device links
293 : * @return the number of broadcast links
294 : */
295 : static u_int broadcast_elinks(uint64_t broadcast_elinks[], const uint64_t broadcast_enable_registers[], uint32_t num_of_channels);
296 :
297 : /**
298 : * Return the e-link type given the encoding used
299 : * @param encoding e-link encoding
300 : */
301 : static const std::string get_elink_type_str(elink_type_t encoding);
302 :
303 : /**
304 : * Compare the software register map version with hardware one
305 : */
306 : bool has_wrong_rm();
307 :
308 : /**
309 : * Firmware does not implement ToHost (lp)GBT e-links
310 : */
311 : bool is_full_mode();
312 :
313 : /**
314 : * Firmware implements ToHost (lp)GBT e-links
315 : */
316 : bool is_lpgbt_mode();
317 :
318 : /**
319 : * Firmware implements ToHost (lp)GBT e-links
320 : */
321 : uint64_t get_elink(u_int channel, u_int egroup, u_int epath);
322 :
323 : /**
324 : * Firmware implements ToHost (lp)GBT e-links
325 : * @param elink elink number
326 : */
327 : uint32_t get_channel(uint32_t elink);
328 :
329 : /**
330 : * Firmware implements ToHost (lp)GBT e-links
331 : * @param is_to_flx true if the DMA is a FromHost one
332 : * @param elink elink number
333 : */
334 : uint32_t get_egroup(uint32_t elink);
335 :
336 : /**
337 : * Firmware implements ToHost (lp)GBT e-links
338 : */
339 : uint32_t get_epath(uint32_t elink);
340 :
341 : /**
342 : * Firmware implements ToHost (lp)GBT e-links
343 : * @param is_to_flx true if the DMA is a FromHost one
344 : */
345 : u_int get_egroups_per_channel(u_int is_to_flx);
346 :
347 : /**
348 : * Firmware implements ToHost (lp)GBT e-links
349 : * @param is_to_flx true if the DMA is a FromHost one
350 : */
351 : u_int get_epaths_per_egroup(u_int is_to_flx);
352 :
353 : /**
354 : * Firmware implements ToHost (lp)GBT e-links
355 : */
356 : u_int get_ctrl_elinks_per_channel();
357 : /**
358 : * @}
359 : */
360 :
361 : /**
362 : * \defgroup DMA operations
363 : * @{
364 : * Functions related to DMA read/write operations
365 : */
366 : /**
367 : * @return true is the DMA buffer is enabled
368 : * @param dmaid true if the DMA is a FromHost one
369 : */
370 : virtual bool dma_enabled(int dmaid) = 0;
371 :
372 : /**
373 : * @brief set up ToHost (circular) DMA buffer
374 : * @param dmaid DMA buffer number
375 : */
376 : virtual void dma_to_host(DmaBuffer* buf, int dmaid) = 0;
377 :
378 : /**
379 : * @brief set up FromHost (circular) DMA buffer
380 : * @param dmaid DMA buffer number
381 : */
382 : virtual void dma_from_host(DmaBuffer* buf, int dmaid) = 0;
383 :
384 :
385 : /**
386 : * @brief Set up FromHost (circular) DMA buffer for trickle mode.
387 : * @param buf DMA buffer pointer.
388 : * @param dmaid DMA buffer identifier.
389 : * @param config_size Size of the trickle configuration message.
390 : */
391 : virtual void dma_from_host_trickle(DmaBuffer* buf, int dmaid, size_t config_size) = 0;
392 :
393 : /**
394 : * @brief set up FromHost (non-circular) DMA buffer
395 : * @param dmaid DMA buffer number
396 : */
397 : virtual void dma_set_oneshot(DmaBuffer* buf, int dmaid, size_t config_size) = 0;
398 :
399 : /**
400 : * @return pointer managed by firmware (wr for ToHost, rd for FromHost)
401 : * @param dmaid DMA buffer number
402 : */
403 : virtual uint64_t dma_get_fw_ptr(int dmaid) = 0;
404 :
405 : /**
406 : * @return pointer managed by software (rd for ToHost, wr for FromHost)
407 : * @param dmaid DMA buffer number
408 : */
409 : virtual uint64_t dma_get_sw_ptr(int dmaid) = 0;
410 :
411 : /**
412 : * @brief set new value for pointer managed by software (rd for ToHost, wr for FromHost)
413 : * @param dmaid DMA buffer number
414 : * @param p_absolute birtual memory address
415 : */
416 : virtual void dma_set_sw_ptr(int dmaid, uint64_t p_absolute) = 0;
417 :
418 : /**
419 : * @return whether sw and fw pointers are have wrapped around the
420 : * circular buffer the the same number of times.
421 : * @param dmaid DMA buffer number
422 : */
423 : virtual bool dma_cmp_even_bits(int dmaid) = 0;
424 :
425 : /**
426 : * @brief stop DMA buffer data transfer operations
427 : * @param dmaid DMA buffer number
428 : */
429 : virtual void dma_stop(unsigned int dmaid) = 0;
430 : /**
431 : * @}
432 : */
433 :
434 : /**
435 : * @return hardware monitoring data
436 : */
437 : virtual monitoring_data_t hw_get_monitoring_data( unsigned int mon_mask = 0xFFF ) = 0;
438 : };
439 :
440 :
441 : /**
442 : * FlxDevice represents a PCIe endpoint of a physical FELIX card.
443 : * */
444 : class FlxDevice : public Device
445 : {
446 : private:
447 : FlxCard m_dev;
448 : encoding_t elink_get_encoding(u_int channel, u_int egroup, u_int epath, bool is_to_flx);
449 : bool elink_is_in_dma(local_elink_t elink, int dmaid);
450 : bool elink_is_enabled(u_int channel, u_int egroup, u_int epath, bool is_to_flx);
451 :
452 : local_elink_t get_ec_elink(bool is_to_flx, u_int channel);
453 : local_elink_t get_ic_elink(bool is_to_flx, u_int channel);
454 : local_elink_t get_aux_elink(bool is_to_flx, u_int channel);
455 :
456 : bool elink_is_ic_enabled(bool is_to_flx, u_int channel);
457 : bool elink_is_ec_enabled(bool is_to_flx, u_int channel);
458 : bool elink_is_aux_enabled(bool is_to_flx, u_int channel);
459 :
460 : uint64_t get_broadcast_enable_gen(u_int channel) override;
461 : bool elink_has_stream_id(u_int channel, u_int egroup, u_int epath) override;
462 :
463 : public:
464 : FlxDevice(Config& cfg, unsigned device);
465 : explicit FlxDevice(unsigned dev_no);
466 :
467 : int open_device(u_int lock_mask) override;
468 : void close_device() override;
469 : bool is_primary() override;
470 :
471 : unsigned int get_card_model() override;
472 : unsigned int get_card_endpoints() override;
473 : u_int get_regmap_version() override;
474 : u_int get_number_of_channels() override;
475 : bool get_wide_mode() override;
476 : u_int get_block_size() override;
477 : u_int get_trailer_size() override;
478 : flx_fromhost_format get_fromhost_data_format() override;
479 : flx_tohost_format get_tohost_data_format() override;
480 : int get_fromhost_dmaid() override;
481 : int get_trickle_dmaid() override;
482 : int dma_max_tlp_bytes() override;
483 :
484 : //Registers
485 : void set_register(const char *key, uint64_t value) override;
486 : uint64_t get_register(const char *key) override;
487 : bool check_register(const char *key) override;
488 :
489 : //Interrupts
490 : void cancel_irq(int i) override;
491 : void irq_wait(int i) override;
492 : void irq_enable(int i) override;
493 : void irq_disable(int i) override;
494 :
495 : //Elinks
496 : std::vector<Elink> read_enabled_elinks(int dmaid) override;
497 :
498 : //DMA operations
499 : bool dma_enabled(int dmaid) override;
500 : void dma_to_host(DmaBuffer* buf, int dmaid) override; //start_circular_dma
501 : void dma_from_host(DmaBuffer* buf, int dmaid) override;
502 : void dma_from_host_trickle(DmaBuffer* buf, int dmaid, size_t config_size) override;
503 : void dma_set_oneshot(DmaBuffer* buf, int dmaid, size_t config_size) override;
504 : uint64_t dma_get_fw_ptr(int dmaid) override; //dma_get_current_address
505 : uint64_t dma_get_sw_ptr(int dmaid) override;
506 : void dma_set_sw_ptr(int dmaid, uint64_t p_phys) override; //dma_set_ptr
507 : bool dma_cmp_even_bits(int dmaid) override;
508 : void dma_stop(unsigned int dmaid) override;
509 :
510 : //HW monitor
511 : monitoring_data_t hw_get_monitoring_data( unsigned int mon_mask = 0xFFF ) override;
512 : };
513 :
514 :
515 : /**
516 : * FileDevice represents a PCIe endpoint of a FELIX card emulated in software.
517 : * */
518 32 : class FileDevice : public Device
519 : {
520 : private:
521 : u_int m_locks;
522 : u_int m_regmap;
523 : u_int m_channels;
524 : u_int m_block_size;
525 : u_int m_trailer_size; //determined in open_device
526 : bool m_wide_mode;
527 : int m_max_tlp_bytes;
528 : int m_toflx_dmaid;
529 : int m_trickle_dmaid;
530 : uint32_t m_status_leds;
531 : int m_busy;
532 : std::map<int, std::vector<Elink>> m_enabled_elinks;
533 :
534 : uint64_t get_broadcast_enable_gen(u_int channel) override;
535 : bool elink_has_stream_id(u_int channel, u_int egroup, u_int epath) override;
536 :
537 : public:
538 : FileDevice(ConfigFile& cfg, unsigned device);
539 : explicit FileDevice(unsigned dev_no);
540 : int open_device(u_int lock_mask) override;
541 5 : void close_device() override {return;}
542 12 : bool is_primary() override {return not (m_device_number % 2);}
543 0 : unsigned int get_card_endpoints() override {return 2;}
544 0 : unsigned int get_card_model() override {return 712;}
545 37 : u_int get_regmap_version() override {return m_regmap;}
546 0 : u_int get_number_of_channels() override {return m_channels;}
547 0 : bool get_wide_mode() override {return m_wide_mode;}
548 68 : u_int get_block_size() override {return m_block_size;}
549 0 : u_int get_trailer_size() override {return m_trailer_size;}
550 5 : flx_fromhost_format get_fromhost_data_format() override {return m_fromHostDataFormat;}
551 58 : flx_tohost_format get_tohost_data_format() override {return m_toHostDataFormat;}
552 4 : int get_fromhost_dmaid() override {return m_toflx_dmaid;}
553 1 : int get_trickle_dmaid() override {return m_trickle_dmaid;}
554 0 : int dma_max_tlp_bytes() override {return m_max_tlp_bytes;}
555 :
556 : //Used for felix-register tests
557 : void set_register(const char *key, uint64_t value) override;
558 : uint64_t get_register(const char *key) override;
559 0 : bool check_register(const char *key) override {return true;}
560 :
561 : //Interrupts
562 0 : void cancel_irq(int i) override {return;}
563 0 : void irq_wait(int i) override {return;}
564 0 : void irq_enable(int i) override {return;}
565 0 : void irq_disable(int i) override {return;}
566 :
567 : //Elinks
568 : std::vector<Elink> read_enabled_elinks(int dmaid) override;
569 : void add_enabled_elink(Elink e, int dmaid);
570 :
571 : //DMA operations
572 : bool dma_enabled(int dmaid) override;
573 : void dma_to_host(DmaBuffer* buf, int dmaid) override; //start_circular_dma
574 : // Remaining functions not implemented,
575 : // buffer to be managed by DmaBufferReader/Writer
576 0 : void dma_from_host(DmaBuffer* buf, int dmaid) override {return;};
577 0 : void dma_from_host_trickle(DmaBuffer* buf, int dmaid, size_t config_size) override {return;};
578 0 : void dma_set_oneshot(DmaBuffer* buf, int dmaid, size_t config_size) override {return;};
579 0 : uint64_t dma_get_fw_ptr(int dmaid) override {return 0;} //dma_get_current_address
580 0 : uint64_t dma_get_sw_ptr(int dmaid) override {return 0;}
581 0 : void dma_set_sw_ptr(int dmaid, uint64_t p_phys) override {return;}//dma_set_ptr
582 0 : bool dma_cmp_even_bits(int dmaid) override {return false;}
583 0 : void dma_stop(unsigned int dmaid) override {return;}
584 :
585 : //HW monitor
586 : monitoring_data_t hw_get_monitoring_data( unsigned int mon_mask = 0xFFF ) override;
587 :
588 : };
589 :
590 : #endif /* DEVICE_H_ */
|