diff --git a/userspace/snmpd/Makefile b/userspace/snmpd/Makefile index d0209520d70e9c3a136239bf63598db6e0f7f5ea..34d1a6bc316a8e55795a4416ac34e1cb9ba1d3ae 100644 --- a/userspace/snmpd/Makefile +++ b/userspace/snmpd/Makefile @@ -30,6 +30,7 @@ SOURCES = \ snmp_mmap.c \ wrsScalar.c \ wrsStartCntGroup.c \ + wrsSpllStatusGroup.c \ wrsPstatsTable.c \ shmem.c \ wrsPtpDataTable.c \ diff --git a/userspace/snmpd/WR-SWITCH-MIB.txt b/userspace/snmpd/WR-SWITCH-MIB.txt index b69793039be0f1d5c96c0a8a64028c464c24078e..799bbcf2d3e15d1215aba5fd2e048badb005bd52 100644 --- a/userspace/snmpd/WR-SWITCH-MIB.txt +++ b/userspace/snmpd/WR-SWITCH-MIB.txt @@ -165,7 +165,82 @@ wrsStartCntRTUd OBJECT-TYPE "Number of RTU deamon starts" ::= { wrsStartCntGroup 3 } ---wrsSpllState OBJECT IDENTIFIER ::= { wrsExpertStatus 3 } +wrsSpllState OBJECT IDENTIFIER ::= { wrsExpertStatus 3 } +-- wrsSpllStatusGroup (.6.3.2) +wrsSpllStatusGroup OBJECT IDENTIFIER ::= { wrsSpllState 2 } + +wrsSpllMode OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Mode of Soft PLL" + ::= { wrsSpllStatusGroup 1 } + +wrsSpllIrqCnt OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Number of interrupts in Soft PLL" + ::= { wrsSpllStatusGroup 2 } + +wrsSpllSeqState OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Sequence state of Soft PLL" + ::= { wrsSpllStatusGroup 3 } + +wrsSpllAlignState OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Align state of Soft PLL" + ::= { wrsSpllStatusGroup 4 } + +wrsSpllHlock OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "HLock in Soft PLL" + ::= { wrsSpllStatusGroup 5 } + +wrsSpllMlock OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "MLock at Soft PLL" + ::= { wrsSpllStatusGroup 6 } + +wrsSpllHY OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "H_y at Soft PLL" + ::= { wrsSpllStatusGroup 7 } + +wrsSpllMY OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "M_y at Soft PLL" + ::= { wrsSpllStatusGroup 8 } + +wrsSpllDelCnt OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Del counter at Soft PLL" + ::= { wrsSpllStatusGroup 9 } + -- wrsPstatsTable (.6.1.4) wrsPstatsTable OBJECT-TYPE SYNTAX SEQUENCE OF WrsPstatsEntry diff --git a/userspace/snmpd/init.c b/userspace/snmpd/init.c index 58153a0be1c97bc279903b3e57d5c8a472d96872..cedb03f65e789503fe744f985be6cf5a3b894de1 100644 --- a/userspace/snmpd/init.c +++ b/userspace/snmpd/init.c @@ -9,6 +9,7 @@ #include "wrsSnmp.h" #include "snmp_shmem.h" #include "wrsStartCntGroup.h" +#include "wrsSpllStatusGroup.h" #include "wrsPstatsTable.h" #include "wrsPtpDataTable.h" #include "wrsCurrentTimeGroup.h" @@ -25,6 +26,7 @@ void init_wrsSnmp(void) init_shm(); init_wrsScalar(); init_wrsStartCntGroup(); + init_wrsSpllStatusGroup(); init_wrsPstatsTable(); init_wrsPtpDataTable(); init_wrsCurrentTimeGroup(); diff --git a/userspace/snmpd/softpll_ng.h b/userspace/snmpd/softpll_ng.h new file mode 100644 index 0000000000000000000000000000000000000000..6c3159903ca504654be55abc0b604ce0f9d5f77c --- /dev/null +++ b/userspace/snmpd/softpll_ng.h @@ -0,0 +1,151 @@ +/* + * This work is part of the White Rabbit project + * + * Copyright (C) 2010 - 2013 CERN (www.cern.ch) + * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> + * + * Released according to the GNU GPL, version 2 or any later version. + */ + +/* softpll_ng.h: public SoftPLL API header */ + +#ifndef __SOFTPLL_NG_H +#define __SOFTPLL_NG_H + +#include <stdint.h> + +/* SoftPLL operating modes, for mode parameter of spll_init(). */ + +/* Grand Master - lock to 10 MHz external reference */ +#define SPLL_MODE_GRAND_MASTER 1 + +/* Free running master - 125 MHz refrence free running, DDMTD locked to it */ +#define SPLL_MODE_FREE_RUNNING_MASTER 2 + +/* Slave mode - 125 MHz reference locked to one of the input clocks */ +#define SPLL_MODE_SLAVE 3 + +/* Disabled mode: SoftPLL inactive */ +#define SPLL_MODE_DISABLED 4 + +/* Shortcut for 'channels' parameter in various API functions to perform operation on all channels */ +#define SPLL_ALL_CHANNELS 0xffffffff + +/* Aux clock flags */ +#define SPLL_AUX_ENABLED (1<<0) /* Locking the particular aux channel to the WR reference is enabled */ +#define SPLL_AUX_LOCKED (1<<1) /* The particular aux clock is already locked to WR reference */ + +/* Phase detector types */ +#define SPLL_PD_DDMTD 0 +#define SPLL_PD_BANGBANG 1 + +/* Channels for spll_measure_frequency() */ +#define SPLL_OSC_REF 0 +#define SPLL_OSC_DMTD 1 +#define SPLL_OSC_EXT 2 + +/* Note on channel naming: + - ref_channel means a PHY recovered clock input. There can be one (as in WR core) or more (WR switch). + - out_channel means an output channel, which represents PLL feedback signal from a local, tunable oscillator. Every SPLL implementation + has at least one output channel, connected to the 125 / 62.5 MHz transceiver (WR) reference. This channel has always + index 0 and is compared against all reference channels by the phase tracking mechanism. +*/ + +/* PUBLIC API */ + +/* +Initializes the SoftPLL to work in mode (mode). Extra parameters depend on choice of the mode: +- for SPLL_MODE_GRAND_MASTER: non-zero (align_pps) value enables realignment of the WR reference rising edge to the + rising edge of 10 MHz external clock that comes immediately after a PPS pulse +- for SPLL_MODE_SLAVE: (ref_channel) indicates the reference channel to which we are locking our PLL. +*/ +void spll_init(int mode, int ref_channel, int align_pps); + +/* Disables the SoftPLL and cleans up stuff */ +void spll_shutdown(); + +/* Returns number of reference and output channels implemented in HW. */ +void spll_get_num_channels(int *n_ref, int *n_out); + +/* Starts locking output channel (out_channel) */ +void spll_start_channel(int out_channel); + +/* Stops locking output channel (out_channel) */ +void spll_stop_channel(int out_channel); + +/* Returns non-zero if output channel (out_channel) is locked to a WR reference */ +int spll_check_lock(int out_channel); + +/* Sets phase setpoint for given output channel. */ +void spll_set_phase_shift(int out_channel, int32_t value_picoseconds); + +/* Retreives the current phase shift and desired setpoint for given output channel */ +void spll_get_phase_shift(int out_channel, int32_t *current, int32_t *target); + +/* Returns non-zero if the given output channel is busy phase shifting to a new preset */ +int spll_shifter_busy(int out_channel); + +/* Returns phase detector type used by particular output channel. There are two phase detectors available: +- DDMTD: locks only 62.5 / 125 MHz. Provides independent phase shift control for each output. +- Bang-Bang: locks to any frequency that is a result of rational (M/N) multiplication of the reference frequency. + The frequency can be set by spll_set_aux_frequency(). BB detector follows phase setpoint of channel 0 (WR reference), + there is no per-output shift control. +*/ +int spll_get_phase_detector_type(int out_channel); + +/* Sets the aux clock freuency when a BB detector is in use. + Must be called prior to spll_start_channel(). If the frequency is out of available range, + returns negative value */ +int spll_set_aux_frequency(int out_channel, int32_t frequency); + +/* Enables/disables phase tracking on channel (ref_channel). Phase is always measured between + the WR local reference (out_channel 0) and ref_channel */ +void spll_enable_ptracker(int ref_channel, int enable); + +/* Reads tracked phase shift value for given reference channel */ +int spll_read_ptracker(int ref_channel, int32_t *phase_ps, int *enabled); + +/* Calls non-realtime update state machine. Must be called regularly (although + * it is not time-critical) in the main loop of the program if aux clocks or + * external reference are used in the design. */ +void spll_update(); + +/* Returns the status of given aux clock output (SPLL_AUX_) */ +int spll_get_aux_status(int out_channel); +const char *spll_get_aux_status_string(int channel); + +/* Debug/testing functions */ + +/* Returns how many time the PLL has de-locked since last call of spll_init() */ +int spll_get_delock_count(); + +void spll_show_stats(void); + +/* Sets VCXO tuning DAC corresponding to output (out_channel) to a given value */ +void spll_set_dac(int out_channel, int value); + +/* Returns current DAC sample value for output (out_channel) */ +int spll_get_dac(int out_channel); + +void check_vco_frequencies(); + +/* info reported through .stat section */ +struct spll_stats { + int magic; /* 0x5b1157a7 = SPLLSTAT ?;)*/ + int ver; /* version of the structure */ + int sequence; /* sequence number, so the host can retry */ + int mode; + int irq_cnt; + int seq_state; + int align_state; + int H_lock; + int M_lock; + int H_y, M_y; + int del_cnt; +}; + +/* This only exists in wr-switch, but we should use it always */ +extern struct spll_stats stats; + +#endif // __SOFTPLL_NG_H + diff --git a/userspace/snmpd/wrsSpllStatusGroup.c b/userspace/snmpd/wrsSpllStatusGroup.c new file mode 100644 index 0000000000000000000000000000000000000000..222af48cde574b2f712b163de47b0831a4894bf9 --- /dev/null +++ b/userspace/snmpd/wrsSpllStatusGroup.c @@ -0,0 +1,77 @@ +#include "wrsSnmp.h" +#include "wrsSpllStatusGroup.h" +#include "softpll_ng.h" +#include "snmp_mmap.h" + +#define FPGA_SPLL_STAT 0x10006800 +#define SPLL_MAGIC 0x5b1157a7 + +static struct spll_stats *spll_stats_p; + +static struct pickinfo wrsSpllStatus_pickinfo[] = { + FIELD(wrsSpllStatus_s, ASN_INTEGER, wrsSpllMode), + FIELD(wrsSpllStatus_s, ASN_COUNTER, wrsSpllIrqCnt), + FIELD(wrsSpllStatus_s, ASN_INTEGER, wrsSpllSeqState), + FIELD(wrsSpllStatus_s, ASN_INTEGER, wrsSpllAlignState), + FIELD(wrsSpllStatus_s, ASN_COUNTER, wrsSpllHlock), + FIELD(wrsSpllStatus_s, ASN_COUNTER, wrsSpllMlock), + FIELD(wrsSpllStatus_s, ASN_INTEGER, wrsSpllHY), + FIELD(wrsSpllStatus_s, ASN_INTEGER, wrsSpllMY), + FIELD(wrsSpllStatus_s, ASN_COUNTER, wrsSpllDelCnt), +}; + +struct wrsSpllStatus_s wrsSpllStatus_s; + +time_t wrsSpllStatus_data_fill(void) +{ + static time_t time_update; + time_t time_cur; + + time_cur = time(NULL); + if (time_update + && time_cur - time_update < WRSSPLLSTATUS_CACHE_TIMEOUT) { + /* cache not updated, return last update time */ + return time_update; + } + time_update = time_cur; + + memset(&wrsSpllStatus_s, 0, sizeof(wrsSpllStatus_s)); + + if (!spll_stats_p) /* first time, map the fpga space */ + spll_stats_p = create_map(FPGA_SPLL_STAT, + sizeof(*spll_stats_p)); + if (!spll_stats_p) { + /* unable to mmap */ + return time_update; + } + /* check magic number in SPLL stat memory */ + if (spll_stats_p->magic != SPLL_MAGIC) { + /* wrong magic */ + snmp_log(LOG_ERR, + "wrsSpllStatusGroup Wrong SPLL magic number\n"); + return time_update; + } + /* check version of SPLL's stat structure */ + if (spll_stats_p->ver == 1) { + wrsSpllStatus_s.wrsSpllMode = spll_stats_p->mode; + wrsSpllStatus_s.wrsSpllIrqCnt = spll_stats_p->irq_cnt; + wrsSpllStatus_s.wrsSpllSeqState = spll_stats_p->seq_state; + wrsSpllStatus_s.wrsSpllAlignState = spll_stats_p->align_state; + wrsSpllStatus_s.wrsSpllHlock = spll_stats_p->H_lock; + wrsSpllStatus_s.wrsSpllMlock = spll_stats_p->M_lock; + wrsSpllStatus_s.wrsSpllHY = spll_stats_p->H_y; + wrsSpllStatus_s.wrsSpllMY = spll_stats_p->M_y; + wrsSpllStatus_s.wrsSpllDelCnt = spll_stats_p->del_cnt; + } + /* there was an update, return current time */ + return time_update; +} + +#define GT_OID WRSSPLLSTATUS_OID +#define GT_PICKINFO wrsSpllStatus_pickinfo +#define GT_DATA_FILL_FUNC wrsSpllStatus_data_fill +#define GT_DATA_STRUCT wrsSpllStatus_s +#define GT_GROUP_NAME "wrsSpllStatusGroup" +#define GT_INIT_FUNC init_wrsSpllStatusGroup + +#include "wrsGroupTemplate.h" diff --git a/userspace/snmpd/wrsSpllStatusGroup.h b/userspace/snmpd/wrsSpllStatusGroup.h new file mode 100644 index 0000000000000000000000000000000000000000..f7ade224452abe1f881755e7cc87ff3e0518147d --- /dev/null +++ b/userspace/snmpd/wrsSpllStatusGroup.h @@ -0,0 +1,23 @@ +#ifndef WRS_SPLL_STATUS_GROUP_H +#define WRS_SPLL_STATUS_GROUP_H + +#define WRSSPLLSTATUS_CACHE_TIMEOUT 5 +#define WRSSPLLSTATUS_OID WRS_OID, 6, 3, 2 + +struct wrsSpllStatus_s { + int32_t wrsSpllMode; + int32_t wrsSpllIrqCnt; + int32_t wrsSpllSeqState; + int32_t wrsSpllAlignState; + int32_t wrsSpllHlock; + int32_t wrsSpllMlock; + int32_t wrsSpllHY; + int32_t wrsSpllMY; + int32_t wrsSpllDelCnt; +}; + +extern struct wrsSpllStatus_s wrsSpllStatus_s; +time_t wrsSpllStatus_data_fill(void); + +void init_wrsSpllStatusGroup(void); +#endif /* WRS_SPLL_STATUS_GROUP_H */