Commit e78838e8 authored by Alessandro Rubini's avatar Alessandro Rubini

Merge branch 'new-config'

parents 57dbe28f 7b2f47f7
......@@ -145,3 +145,224 @@ config KEEP_ROOTFS
If unsusre, say N.
endmenu
menu "Port Timing Configuration"
config PORT00_PARAMS
string "Parameters for the first port"
default "name=wr0,tx=0,rx=160000,role=slave,fiber=0"
help
This item, and the following ones, are used to assign the
constant delays (likely from calibration), port roles and
type of fiber for each of the ports. Please refer to the
user manual for more information.
config PORT01_PARAMS
string "Parameters for the second port"
default "name=wr1,tx=0,rx=160000,role=slave,fiber=0"
config PORT02_PARAMS
string "Parameters for a further port"
default "name=wr2,tx=0,rx=160000,role=master,fiber=0"
config PORT03_PARAMS
string "Parameters for a further port"
default "name=wr3,tx=0,rx=160000,role=master,fiber=0"
config PORT04_PARAMS
string "Parameters for a further port"
default "name=wr4,tx=0,rx=161200,role=master,fiber=0"
config PORT05_PARAMS
string "Parameters for a further port"
default "name=wr5,tx=0,rx=161200,role=master,fiber=0"
config PORT06_PARAMS
string "Parameters for a further port"
default "name=wr6,tx=0,rx=161200,role=master,fiber=0"
config PORT07_PARAMS
string "Parameters for a further port"
default "name=wr7,tx=0,rx=161200,role=master,fiber=0"
config PORT08_PARAMS
string "Parameters for a further port"
default "name=wr8,tx=0,rx=161200,role=master,fiber=0"
config PORT09_PARAMS
string "Parameters for a further port"
default "name=wr9,tx=0,rx=161200,role=master,fiber=0"
config PORT10_PARAMS
string "Parameters for a further port"
default "name=wr10,tx=0,rx=161200,role=master,fiber=0"
config PORT11_PARAMS
string "Parameters for a further port"
default "name=wr11,tx=0,rx=161200,role=master,fiber=0"
config PORT12_PARAMS
string "Parameters for a further port"
default "name=wr12,tx=0,rx=161200,role=master,fiber=0"
config PORT13_PARAMS
string "Parameters for a further port"
default "name=wr13,tx=0,rx=161200,role=master,fiber=0"
config PORT14_PARAMS
string "Parameters for a further port"
default "name=wr14,tx=0,rx=161200,role=master,fiber=0"
config PORT15_PARAMS
string "Parameters for a further port"
default "name=wr15,tx=0,rx=161200,role=master,fiber=0"
config PORT16_PARAMS
string "Parameters for a further port"
default "name=wr16,tx=0,rx=161200,role=master,fiber=0"
config PORT17_PARAMS
string "Parameters for a further port"
default "name=wr17,tx=0,rx=161200,role=master,fiber=0"
endmenu
menu "SFP and Media Timing Configuration"
config SFP00_PARAMS
string "Parameters for one SFP device type"
default "name=AXGE-1254-0531,tx=10,rx=10,wl_txrx=1310+1490"
help
This parameter, and the following ones, are used to
configure the timing parameters of a specific SFP
tranceiver. The tranceiver name is autodected for each port
in the White Rabbit Switch, and you need one configuration
entry for each tranceiver type that is installed in your
device.
config SFP01_PARAMS
string "Parameters for one SFP device type"
default "name=AXGE-3454-0531,tx=10,rx=10,wl_txrx=1490+1310"
config SFP02_PARAMS
string "Parameters for one SFP device type"
config SFP03_PARAMS
string "Parameters for one SFP device type"
config SFP04_PARAMS
string "Parameters for one SFP device type"
config SFP05_PARAMS
string "Parameters for one SFP device type"
config SFP06_PARAMS
string "Parameters for one SFP device type"
config SFP07_PARAMS
string "Parameters for one SFP device type"
config SFP08_PARAMS
string "Parameters for one SFP device type"
config SFP09_PARAMS
string "Parameters for one SFP device type"
config FIBER00_PARAMS
string "Alpha parameters for fiber type 0"
default "alpha_1310_1490=2.6787e-04"
help
This parameter, and the following ones, specify the physical
features of your fiber type. You need to specify the alpha
value for each pair of wavelengths you are using. The index
("00" onwards) is used to match the port
(CONFIG_PORTxx_PARAMS) with one of several installed fiber
types.
config FIBER01_PARAMS
string "Alpha parameters for fiber type 1"
default "alpha_1310_1490=2.6787e-04"
config FIBER02_PARAMS
string "Alpha parameters for fiber type 2"
default "alpha_1310_1490=2.6787e-04"
config FIBER03_PARAMS
string "Alpha parameters for fiber type 3"
default "alpha_1310_1490=2.6787e-04"
endmenu
choice
prompt "Timing Mode"
default TIME_BC
config TIME_GM
bool "Grand-Master"
help
This options selects the White Rabbit Switch as a grandmaster,
i.e. it uses its input channels to track an Atomic or GPS and
claim to be a PTP authoritative source on the network.
config TIME_FM
bool "Free-Running Master"
help
The White Rabbit Switch pretends to be a master on his PTP
network, but it doesn't sync to an external source. Its own
internal clocks and counters are used to drive timing.
config TIME_BC
bool "Boundary Clock"
help
The White Rabbit Switch is a normal PTP Boundary Clock: it is
slave on one of its ports and master on the other ones, according
to the standard Best Master Clock algorithm.
endchoice
choice
prompt "PTP Port Assignment"
default PTP_WR_DEFAULT if TIME_BC
default PTP_WR_MASTER
config PTP_WR_DEFAULT
bool "Raw Ethernet, WR on, Slave on wr0/wr1, Master on other ports"
help
You can choose between one from a set of predefined
configuration files from your PTP server running in the
switch, or define your own custom configuration file.
The default setting for boundary clock forces ports wr0 and
wr1 to be PTP slaves and all other ports to be master, in
Ethernet mode and with full WR protocol extensions. The default
for a Grand-Master or Free-Running master has all ports as
master ports.
Other predefined choices select more flexible configuration used
mainly for test purposes. Any special need can be addressed by
providing your own ppsi.conf file, that you should copy
to your switch.
config PTP_WR_MASTER
bool "Raw Ethernet, WR on, Master on all ports"
config PTP_WR_AUTO
bool "Raw Ethernet, WR on, Auto master/slave on all ports"
config PTP_WR_AUTO_UDP
bool "UDP mode, WR on, Auto master/slave on all ports"
config PTP_NONWR_UDP_ALL
bool "UDP mode, No WR, all ports (including eth0)"
config PTP_CUSTOM
bool "Custom ppsi.conf"
endchoice
config PTP_CUSTOM_FILENAME
string "Pathname for your custom ppsi.conf"
depends on PTP_CUSTOM
default "/wr/etc/ppsi-custom.conf"
......@@ -34,6 +34,7 @@ cat > $TMPSCRIPT << EOF
. $WRS_BASE_DIR/../.config
mkdir -p $TMPFS/wr/etc
cp $WRS_BASE_DIR/../.config $TMPFS/wr/etc/dot-config
cp $WRS_BASE_DIR/../Kconfig $TMPFS/wr/etc/Kconfig
cp -r $rootfs_vanilla/* $TMPFS
cp -r $WRS_OUTPUT_DIR/images/wr/* $TMPFS/wr
......
......@@ -35,7 +35,7 @@
@setchapternewpage off
@set update-month November 2014
@set update-month December 2014
@c the release name below is substituted at build time
@set release __RELEASE_GIT_ID__
......@@ -210,14 +210,8 @@ public in an exported library. The library code rusted over the years,
and we can't trust it any more without some clean up. I'm personally
scared every time I look in that code base.
@item The @i{mini-ipc} mechanism is showing its limits. We are communicating
too much information, and the polling mechanism used in some processes
introduces significant delays. Most of the communication is just
about reporting status, so this should be brought to a shared-memory
area with a well-defined structure. Again, this allows simulation and
development off-switch, with fault injection.
@item Whenever @i{ipc} is used for actions, rather than just status passing,
which is now shmem-based,
we should audit the processes to ensure the are based on @i{select}
rather than a timely poll. Actually, the HAL process is using quite
a lot of cpu time, and it could do much better.
......@@ -227,14 +221,21 @@ interface with gateware is now simpler than it was, but software still
has remnants of old data structure. Also, the multi-threaded approach
is overkill, and the program could benefit from a simplification.
@item We need to sort out configuration files. I especially plan to
get rid of @i{lua}; it is only used to set internal variables in the @i{lua}
data structures, that are then queried. This means if you set an unused
item (e.g. because of a typo or some old wishful-thinking documents) it won't
have any effect and it will report no error. The best action may be move
all configurations to the PPSi config file -- the delays and all the rest
are PTP-specific anyways, and PPSi supports per-architecture configuration
items.
@item The SFP code needs to be cleaned up. There is unsafe string
management in 16-wide non-terminated fields, and we don't really
report all the information we have (we should copy to shmem so to
get it out, at least). Also, using the device name without the vendor
name is unsafe: some vendors use generic device names.
@item The @t{TRACE} support it not really working. We have serious
warning messages that were never reported. We should really print
everything to stderr and let syslog manage it (according to user
configuration: this is already in dot-config).
@item Default values, when configuration is missing, are badly chosen.
For example, @i{alpha} is always positive for an unknown SFP, but we
should rather have zero (or a positive/negative thing according the
the wavelength, if known).
@end itemize
......
......@@ -476,8 +476,161 @@ value is changed by the web interface, proper action is taken.
unknown facility names will generate a runtime error on the switch.
All three strings default to ``@t{daemon.info}''.
@item CONFIG_PORT00_PARAMS
@itemx CONFIG_PORT01_PARAMS
@itemx ...
@itemx CONFIG_PORT17_PARAMS
These configuration items are used to set up port parameters;
this includes the delays, the PTP role (not currently used,
though) and the fiber type as an integer index. Most likely
the default values work for you. See @ref{Timing Configuration}
for details.
@item CONFIG_SFP00_PARAMS
@itemx ...
@itemx CONFIG_SFP09_PARAMS
Configuration for @sc{sfp} models. You should fill values for
all @sc{sfp} models you are using in your @sc{wrs} and all
wavelengths you are using. See @ref{Timing Configuration}
for details.
@item CONFIG_FIBER00_PARAMS
@itemx ...
@itemx CONFIG_FIBER03_PARAMS
Configuration for fiber types. You are expected to have no more
than 4 fiber types installed in your deployment (if more, you need
to add items to the @i{dot-config} file). See @ref{Timing
Configuration} for details.
@item CONFIG_TIME_GM
@itemx CONFIG_TIME_FM
@itemx CONFIG_TIME_BC
The type of PTP clock this switch is. Only one of the three
items should be set (running ``@t{make menuconfig}'' offers
them as an exclusive choice). The options select a grand-master
with external reference, from GPS or Cesium or both; a free-running
master, used for isolated acquisition networks, withouth an
external reference; or a normal ``boundary-clock'' device that
is slave on some ports and master on other ports.
@item CONFIG_PTP_*
We support a set of PPSi configuration files, for different PTP
roles. The default option being selected by @i{Kconfig} is
@t{PTP_WR_DEFAULT} for @t{TIME_BC} devices and @t{PTP_WR_MASTER}
for @t{GM} and @t{FM} devices. The former configuration selects
a mandated slave PTP role on ports @t{wr0} and @t{wr1}, and
mandated master on all other ports; the latter conifiguration
is master on all ports. Please see the help provided within
@i{Kconfig} for more details about the various options we support.
@item CONFIG_PTP_CUSTOM_FILENAME
If you chose @t{CONFIG_PTP_CUSTOM} in the choice above, you
can provide your own filename for the PPSi configuration file;
the chosen name is expected to be intalled in the @sc{wrs}
filesystem.
@end table
@c ==========================================================================
@node Timing Configuration
@section Timing Configuration
This section describes how timing configuration works in the switch.
Please note that up to version 4.1 (included) of @t{wr-switch-sw} things
were different and not really documented.
Timing configuration now depends on three sets of @i{dot-config}
variables: per-port information, per-sfp information and fiber
description.
This is, for explanation's sake, an example of such items:
@smallexample
CONFIG_PORT09_PARAMS="name=wr9,tx=226214,rx=226758,role=slave,fiber=2"
CONFIG_SFP00_PARAMS="name=AXGE-1254-0531,tx=0,rx=0,wl_txrx=1310+1490"
CONFIG_FIBER02_PARAMS="alpha_1310_1490=2.6787e-04"
@end smallexample
When making timing calculation for port @t{wr9}, assuming the
auto-detected @sc{sfp} model is``AXGE-1254-0531'', the software
uses configuration in the following way:
@itemize @bullet
@item The port has known tx and rx delays (around 226ns); the
values depend on trace length and other hardware-specific details
and are determined by a calibration procedure. These values are
used as constant delays in the @i{tx} and @i{rx} directions.
@item The port is also configured as slave (information not used
at this point) and is deployed using fiber type 2 -- this number
is just a local enumeration of fiber types; most likely you'll be
using type ``0'' in every port.
@item The transceiver installed uses 1310nm light for tx
and 1490nm light for rx (this is part of the specification of the
transceiver, but cannot be auto-detected). Moreover it has 0 constant
delay in both tx and rx, determined by calibration.
@item The fiber type being used (type 2 here), when driven
with 1310nm and 1490nm wavelengths, features an @i{alpha} parameter of
0.00026787 (i.e. a ratio of 1.00026787) between the speed of light in
the two directions. This value depends on both the fiber type and
wavelength, and is determined, again, by calibration.
@end itemize
Please note that only one alpha value is provided, because the
opposite one (@t{alpha_1490_1310}) is calculated by software.
@subheading Other Deployments
The example above matches the choices we make at CERN, where our
White Rabbit networks are all run with a single monomodal fiber
and 1310/1490 light.
If you are using dual-fiber transceivers, which is acceptable for
short links, you use the same wavelength in both direction, over two
fibers of the same length. In this case you may choose to avoid
writing the @t{wl_txrx} parameter in @sc{sfp} configuration and the
@t{alpha_XX_XX} parameter in fiber configuration. The missing
parameters will cause warning messages on the console, but are not
fatal, and a default alpha of 0 is used.
If you are using a pair of transceivers with different wavelengths,
and long fibers, you should provide an appropriate value of alpha,
according to laboratory measures on your fiber type. The
@t{CONFIG_FIBERxx_PARAMS} items are parsed as a list of
comma-separated assignments, so you can specify and number of
wavelength pairs. The accuracy of your value depends on the length
of the fiber link. For a 10km fiber (100us round-trip) you need to know
alpha up to 1e-7 if you want the related uncertainty to be
less than 10ps.
@subheading Calibration
Calibration of per-port and per-@sc{sfp} delays is described in the
White Rabbit wiki:
@url{http://www.ohwr.org/projects/white-rabbit/wiki/Calibration}. The
procedure can measure the total constant delays, but splitting between
the what depends on the port and what depends on the transceiver is
arbitrary (also, the split between the tx and rx paths is arbitrary).
The delays used in this example come from values listed in the above
web page, and you should not be surprised by the fact that the
transceiver specifies the delays as zero. By performing the
calibration procedure using this very transceiver type, the hardware
engineers decided to assign the whole of the delay to the port (any
split of the measured value is equally right). Other transceiver
types can be calibrated to either positive or negative values, to cope
with the @i{difference} between them and the @t{AXGE} devices.
@c ############################################################################
@node Booting with Barebox
@chapter Booting with Barebox
......
OBJS = trace.o init.o fpga_io.o util.o pps_gen.o i2c.o shw_io.o i2c_bitbang.o \
i2c_fpga_reg.o pio.o libshw_i2c.o i2c_sfp.o fan.o i2c_io.o hwiu.o \
ptpd_netif.o hal_client.o \
shmem.o hal_shmem.o rt_client.o
shmem.o hal_shmem.o rt_client.o \
dot-config.o
LIB = libwr.a
......
/* Alessandro Rubini for CERN, 2014 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h>
#include <libwr/config.h>
/* All strings here are strdup'd and then split; you can't free(3) them */
struct cfg_item {
char *name;
char *value;
struct cfg_item *subcfg;
struct cfg_item *next;
};
static struct cfg_item *libwr_cfg;
static int libwr_subcfg(struct cfg_item *c)
{
struct cfg_item *subc;
c->subcfg = NULL;
char *rest, *s;
if (!strchr(c->value, '='))
return 0;
/* Very lazily, strdup this again, and then modify in place */
rest = strdup(c->value);
if (!rest)
return -1;
do {
subc = calloc(1, sizeof(*c));
if (!subc)
return -1;
subc->name = rest;
/* Trim this and save trailing text */
s = strchr(rest, ',');
if (s) {
rest = s + 1;
*s = '\0';
} else {
rest = NULL;
}
/* split between name and value */
s = strchr(subc->name, '=');
if (s) {
subc->value = s + 1;
*s = '\0';
}
/* store and continue, if more is there */
subc->next = c->subcfg;
c->subcfg = subc;
} while (rest);
return 0;
}
/* Parse a line into name=value and subcfg. Assume dot-config format */
static int libwr_cfg_line(char *line)
{
struct cfg_item *c;
char name[512], value[512];
if (line[0] == '#')
return 0;
if (strlen(line) < 2)
return 0;
if (sscanf(line, "CONFIG_%[^=]=%[^\n]", name, value) != 2) {
errno = EINVAL;
return -1;
}
c = malloc(sizeof(*c));
if (!c)
return -1;
c->subcfg = NULL;
c->name = strdup(name);
c->value = strdup(value);
if (!c->name || !c->value)
return -1;
/* Strip quotes */
if (c->value[0] == '"')
c->value++;
if (c->value[strlen(c->value) - 1] == '"')
c->value[strlen(c->value) - 1] = '\0';
libwr_subcfg(c);
c->next = libwr_cfg;
libwr_cfg = c;
return 0;
}
int libwr_cfg_read_file(char *dotconfig)
{
char s[512];
FILE *f;
int lineno = 0;
f = fopen(dotconfig, "r");
if (!f)
return -1;
while (fgets(s, sizeof(s), f)) {
lineno++;
if (libwr_cfg_line(s) < 0)
return -lineno;
}
fclose(f);
return 0;
}
int libwr_cfg_dump(FILE *output)
{
struct cfg_item *c = libwr_cfg;
struct cfg_item *subc = libwr_cfg;
while (c) {
fprintf(output, "name=\"%s\"\n value=\"%s\"\n",
c->name, c->value);
subc = c->subcfg;
while (subc) {
fprintf(output, " name=\"%s\"\n"
" value=\"%s\"\n",
subc->name, subc->value);
subc = subc->next;
}
c = c->next;
}
return 0;
}
int libwr_cfg_read_verify_file(char *dotconfig, char *kconfig)
{
FILE *f;
int errors = 0;
char s[256], name[256];
struct cfg_item *c;
struct kc {
char *name;
struct kc *next;
} *all_configs = NULL, *kc, *next;
if (libwr_cfg_read_file(dotconfig))
return -1;
/* Read Kconfig and store all config names */
f = fopen(kconfig, "r");
if (!f)
return -1;
while (fgets(s, sizeof(s), f)) {
if (sscanf(s, "config %s", name) != 1)
continue;
kc = malloc(sizeof(*kc));
if (!kc)
return -1;
kc->name = strdup(name);
kc->next = all_configs;
all_configs = kc;
}
fclose(f);
/* Verify all configs, complain if missing */
for (c = libwr_cfg; c; c = c->next) {
for (kc = all_configs; kc; kc = kc->next)
if (!strcmp(c->name, kc->name))
break;
if (!kc) {
fprintf(stderr, "Configuration \"%s\" not found\n",
c->name);
errors++;
}
}
/* Free all kconfig allocs */
for (kc = all_configs; kc; kc = next) {
next = kc->next;
free(kc->name);
free(kc);
}
if (errors) {
errno = EINVAL;
return -1;
}
return 0;
}
char *libwr_cfg_get(char *cfgname)
{
struct cfg_item *c;
for (c = libwr_cfg; c; c = c->next)
if (!strcmp(cfgname, c->name))
return c->value;
return NULL;
}
char *libwr_cfg_get2(char *cfgname, char *subname)
{
struct cfg_item *c, *subc;
for (c = libwr_cfg; c; c = c->next)
if (!strcmp(cfgname, c->name)) {
for (subc = c->subcfg; subc; subc = subc->next)
if (!strcmp(subname, subc->name))
return subc->value;
}
return NULL;
}
int libwr_cfg_convert2(char *cfgname, char *subname,
enum libwr_convert conv, void *ret, ...)
{
double *dptr = ret;
int *iptr = ret;
char real_cfgname[128];
char *value;
va_list args;
char ch;
va_start(args, ret);
vsprintf(real_cfgname, cfgname, args);
va_end(args);
value = libwr_cfg_get2(real_cfgname, subname);
if (!value) {
errno = ENOENT;
return -1;
}
errno = EINVAL;
switch(conv) {
case LIBWR_INT:
if (sscanf(value, "%i%c", iptr, &ch) != 1)
return -1;
return 0;
case LIBWR_STRING:
strcpy(ret, value);
return 0;
case LIBWR_DOUBLE:
if (sscanf(value, "%lf%c", dptr, &ch) != 1)
return -1;
return 0;
}
return -1; /* never */
}
......@@ -9,13 +9,10 @@
#include <unistd.h>
#include <errno.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include <libwr/pio.h>
#include <libwr/trace.h>
#include <libwr/util.h>
#include <libwr/config.h>
#include "i2c.h"
#include "i2c_sfp.h"
......@@ -547,70 +544,64 @@ int shw_sfp_read_verify_header(int num, struct shw_sfp_header *head)
static struct shw_sfp_caldata *shw_sfp_cal_list = NULL;
int shw_sfp_read_db(char *filename)
/* local helper */
static void __err_msg(int index, char *pname, char *pvalue)
{
lua_State *L = luaL_newstate();
struct shw_sfp_caldata *sfp;
luaL_openlibs(L);
if (luaL_loadfile(L, filename) || lua_pcall(L, 0, 0, 0)) {
printf("cannot run configuration file: %s",
lua_tostring(L, -1));
return -1;
}
fprintf(stderr, "Config item \"SFP%02i_PARAMS\": parameter \"%s\" ",
index, pname);
if (pvalue)
fprintf(stderr, "is wrong (\"%s\")\n", pvalue);
else
fprintf(stderr, "is not specified\n");
}
lua_getglobal(L, "sfpdb");
if (!lua_istable(L, -1)) {
printf("`sfpdb' should be a table\n");
return -1;
}
lua_pushnil(L);
while (lua_next(L, -2)) {
if (!lua_istable(L, -1)) {
lua_pop(L, 1);
continue;
int shw_sfp_read_db(void)
{
struct shw_sfp_caldata *sfp;
char s[128];
int error, val, index;
for (index = 0; ; index++) {
error = libwr_cfg_convert2("SFP%02i_PARAMS", "name",
LIBWR_STRING, s, index);
if (error)
return 0; /* no more, no error */
sfp = calloc(1, sizeof(*sfp));
strncpy(sfp->part_num, s, sizeof(sfp->part_num));
sfp->vendor_serial[0] = 0;
sfp->flags = SFP_FLAG_CLASS_DATA; /* never used */
/* These are uint32_t as I write this. So use "int val" */
val = 0;
error = libwr_cfg_convert2("SFP%02i_PARAMS", "tx",
LIBWR_INT, &val, index);
if (error)
__err_msg(index, "tx", NULL);
sfp->delta_tx = val;
val = 0;
error = libwr_cfg_convert2("SFP%02i_PARAMS", "rx",
LIBWR_INT, &val, index);
if (error)
__err_msg(index, "rx", NULL);
sfp->delta_rx = val;
/* We also store the wavelength, used to get alpha */
error = libwr_cfg_convert2("SFP%02i_PARAMS", "wl_txrx",
LIBWR_STRING, &s, index);
if (error)
__err_msg(index, "wl_txrx", NULL);
if (sscanf(s, "%i+%i", &sfp->tx_wl, &sfp->rx_wl) != 2) {
sfp->tx_wl = 0;
__err_msg(index, "wl_txrx", s);
}
const char *sfp_pn = 0;
const char *sfp_vs = 0;
int vals[2] = { 0, 0 };
double alpha = 0;
lua_pushnil(L);
while (lua_next(L, -2)) {
const char *key = lua_tostring(L, -2);
if (strcmp(key, "part_num") == 0)
sfp_pn = lua_tostring(L, -1);
else if (strcmp(key, "part_serial") == 0)
sfp_vs = lua_tostring(L, -1);
else if (strcmp(key, "alpha") == 0)
alpha = lua_tonumber(L, -1);
else if (strcmp(key, "delta_tx") == 0)
vals[0] = lua_tointeger(L, -1);
else if (strcmp(key, "delta_rx") == 0)
vals[1] = lua_tointeger(L, -1);
lua_pop(L, 1);
}
lua_pop(L, 1);
sfp = malloc(sizeof(struct shw_sfp_caldata));
strncpy(sfp->part_num, sfp_pn, sizeof(sfp->part_num));
if (!sfp_vs || strcmp(sfp_vs, "") == 0) {
sfp->vendor_serial[0] = 0;
sfp->flags |= SFP_FLAG_CLASS_DATA;
} else {
strcpy(sfp->vendor_serial, sfp_vs);
sfp->flags |= SFP_FLAG_DEVICE_DATA;
}
sfp->alpha = alpha;
sfp->delta_tx = vals[0];
sfp->delta_rx = vals[1];
/* Alpha is filled later, per-port, in hal_port_insert_sfp() */
/* link and continue */
sfp->next = shw_sfp_cal_list;
shw_sfp_cal_list = sfp;
}
lua_pop(L, 1);
lua_close(L);
return 0;
}
......
#ifndef __LIBWR_CONFIG_H__
#define __LIBWR_CONFIG_H__
/* Read a dot-config file, return 0 or -line, the unparsable line in file */
int libwr_cfg_read_file(char *dotconfig);
/* Diagnostic tool */
int libwr_cfg_dump(FILE *output);
/* Read a dot-config, verifying with Kconfig to complain for wrong names */
int libwr_cfg_read_verify_file(char *dotconfig, char *kconfig);
/* cfg_get() works for CONFIG_NTP_SERVER. Returns NULL or static storage. */
char *libwr_cfg_get(char *cfgname);
/* cfg_get2(), as above but with suboptions like "name=AXGE-3454-0531". */
char *libwr_cfg_get2(char *cfgname, char *subname);
/* We only convert the following types */
enum libwr_convert {
LIBWR_INT,
LIBWR_STRING,
LIBWR_DOUBLE,
};
/*
* The following is the most flexible one: subname can be NULL,
* and the cfgname is a printf-format string (e.g. "PORT%02i_PARAMS");
* finally, the value is sscanf'd in the library, with error check.
* Returns 0 or -1 with errno set to EINVAL.
*/
int libwr_cfg_convert2(char *cfgname, char *subname,
enum libwr_convert, void *ret, ...)
__attribute__((format(printf, 1, 5)));
#endif /* __LIBWR_CONFIG_H__ */
......@@ -71,8 +71,8 @@ struct hal_port_state {
/* port FSM state (HAL_PORT_STATE_xxxx) */
int state;
/* unused */
int index;
/* fiber type, used to get alpha for SFP frequency */
int fiber_index;
/* 1: PLL is locked to this port */
int locked;
......@@ -92,7 +92,7 @@ struct hal_port_state {
};
/* This is the overall structure stored in shared memory */
#define HAL_SHMEM_VERSION 1
#define HAL_SHMEM_VERSION 2 /* Version 2 because sfp calib changed */
struct hal_shmem_header {
int nports;
struct hal_port_state *ports;
......
......@@ -23,12 +23,21 @@
struct shw_sfp_caldata {
int flags;
char part_num[16]; /* part number of device as found in DB */
/*
* Part number used to identify it. Serial number because we
* may specify per-specimen delays, but it is not used at this
* point in time
*/
char part_num[16];
char vendor_serial[16];
/* Callibration data */
double alpha;
uint32_t delta_tx;
uint32_t delta_rx;
/* wavelengths, used to get alpha from fiber type */
int tx_wl;
int rx_wl;
/* and link as a list */
struct shw_sfp_caldata *next;
};
......@@ -87,8 +96,8 @@ static inline void shw_sfp_set_generic(int num, int status, int type)
shw_sfp_gpio_set(num, state);
}
/* Load the db from a file */
int shw_sfp_read_db(char *filename);
/* Load the db from dot-config to internal structures */
int shw_sfp_read_db(void);
/* Read and verify the header all at once. returns -1 on failure */
int shw_sfp_read_verify_header(int num, struct shw_sfp_header *head);
......
ppsi @ 12bd4376
Subproject commit f49685ec07132da80b8aec32a2d50d143d23e13d
Subproject commit 12bd4376a1eed963eed143cda3e140cc55cb7ccb
......@@ -45,12 +45,15 @@ if [ -n "$CONFIG_DOTCONF_URL" ]; then
echo "Invalid URL for dot-config: \"$URL\"" >& 2
;;
esac
# If it exists and it is not empty or awfully small, trust it
# If it exists, it is not empty or too small, and the checker is happy..
if [ -f $tmpconfig ] &&
[ $(cat $tmpconfig | wc -c) -gt 200 ]; then
[ $(cat $tmpconfig | wc -c) -gt 200 ] &&
/wr/bin/wrs_checkcfg $tmpconfig /wr/etc/Kconfig; then
echo "Using newly-downloaded dot-config from $URL"
# copy it in place to use the new file (unless it is identical)
cmp -s $tmpconfig $dotconfig || cp $tmpconfig $dotconfig
fi
fi
# Finally, apply what we have, be it old or new
. /wr/bin/apply_dot-config
/wr/bin/apply_dot-config
......@@ -75,3 +75,13 @@ set | tr -d \' | grep CONFIG_WRS_LOG | sed 's/=/ /' | while read varname value;
done
copy_conf /wr/sbin/start-daemons.sh
# Select a ppsi configuration file
for n in /wr/etc/ppsi-conf-pool/*; do
cfg=CONFIG_PTP_$(basename $n)
if [ "$cfg" = "y" ]; then
cp $n /wr/etc/ppsi.conf
fi
done
if [ "$CONFIG_PTP_CUSTOM" = "y" ]; then
cp "$CONFIG_PTP_CUSTOM_FILENAME" /wr/etc/ppsi.conf
fi
\ No newline at end of file
# Autoselection of port mode, including eth0 (both raw and udp, for variety)
# Global settings
clock-class 187
clock-accuracy 254
port eth-udp
proto udp
iface eth0
role auto
extension none
port eth-raw
proto raw
iface eth0
role auto
extension none
port wr0
proto udp
iface wr0
role auto
extension none
port wr1
proto udp
iface wr1
role auto
extension none
port wr2
proto udp
iface wr2
role auto
extension none
port wr3
proto udp
iface wr3
role auto
extension none
port wr4
proto udp
iface wr4
role auto
extension none
port wr5
proto udp
iface wr5
role auto
extension none
port wr6
proto udp
iface wr6
role auto
extension none
port wr7
proto udp
iface wr7
role auto
extension none
port wr8
proto udp
iface wr8
role auto
extension none
port wr9
proto udp
iface wr9
role auto
extension none
port wr10
proto udp
iface wr10
role auto
extension none
port wr11
proto udp
iface wr11
role auto
extension none
port wr12
proto udp
iface wr12
role auto
extension none
port wr13
proto udp
iface wr13
role auto
extension none
port wr14
proto udp
iface wr14
role auto
extension none
port wr15
proto udp
iface wr15
role auto
extension none
port wr16
proto udp
iface wr16
role auto
extension none
port wr17
proto udp
iface wr17
role auto
extension none
# Autoselection of port modepgrandmasters
# Global settings
clock-class 187
clock-accuracy 254
port wr0
iface wr0
role auto
extension whiterabbit
port wr1
iface wr1
role auto
extension whiterabbit
port wr2
iface wr2
role auto
extension whiterabbit
port wr3
iface wr3
role auto
extension whiterabbit
port wr4
iface wr4
role auto
extension whiterabbit
port wr5
iface wr5
role auto
extension whiterabbit
port wr6
iface wr6
role auto
extension whiterabbit
port wr7
iface wr7
role auto
extension whiterabbit
port wr8
iface wr8
role auto
extension whiterabbit
port wr9
iface wr9
role auto
extension whiterabbit
port wr10
iface wr10
role auto
extension whiterabbit
port wr11
iface wr11
role auto
extension whiterabbit
port wr12
iface wr12
role auto
extension whiterabbit
port wr13
iface wr13
role auto
extension whiterabbit
port wr14
iface wr14
role auto
extension whiterabbit
port wr15
iface wr15
role auto
extension whiterabbit
port wr16
iface wr16
role auto
extension whiterabbit
port wr17
iface wr17
role auto
extension whiterabbit
# Autoselection of port mode
# Global settings
clock-class 187
clock-accuracy 254
port wr0
proto udp
iface wr0
role auto
extension whiterabbit
port wr1
proto udp
iface wr1
role auto
extension whiterabbit
port wr2
proto udp
iface wr2
role auto
extension whiterabbit
port wr3
proto udp
iface wr3
role auto
extension whiterabbit
port wr4
proto udp
iface wr4
role auto
extension whiterabbit
port wr5
proto udp
iface wr5
role auto
extension whiterabbit
port wr6
proto udp
iface wr6
role auto
extension whiterabbit
port wr7
proto udp
iface wr7
role auto
extension whiterabbit
port wr8
proto udp
iface wr8
role auto
extension whiterabbit
port wr9
proto udp
iface wr9
role auto
extension whiterabbit
port wr10
proto udp
iface wr10
role auto
extension whiterabbit
port wr11
proto udp
iface wr11
role auto
extension whiterabbit
port wr12
proto udp
iface wr12
role auto
extension whiterabbit
port wr13
proto udp
iface wr13
role auto
extension whiterabbit
port wr14
proto udp
iface wr14
role auto
extension whiterabbit
port wr15
proto udp
iface wr15
role auto
extension whiterabbit
port wr16
proto udp
iface wr16
role auto
extension whiterabbit
port wr17
proto udp
iface wr17
role auto
extension whiterabbit
# Default for boundary clocks
# Global settings
clock-class 187
clock-accuracy 254
port slave0
iface wr0
role slave
extension whiterabbit
port slave1
iface wr1
role slave
extension whiterabbit
port master2
iface wr2
role master
extension whiterabbit
port master3
iface wr3
role master
extension whiterabbit
port master4
iface wr4
role master
extension whiterabbit
port master5
iface wr5
role master
extension whiterabbit
port master6
iface wr6
role master
extension whiterabbit
port master7
iface wr7
role master
extension whiterabbit
port master8
iface wr8
role master
extension whiterabbit
port master9
iface wr9
role master
extension whiterabbit
port master10
iface wr10
role master
extension whiterabbit
port master11
iface wr11
role master
extension whiterabbit
port master12
iface wr12
role master
extension whiterabbit
port master13
iface wr13
role master
extension whiterabbit
port master14
iface wr14
role master
extension whiterabbit
port master15
iface wr15
role master
extension whiterabbit
port master16
iface wr16
role master
extension whiterabbit
port master17
iface wr17
role master
extension whiterabbit
# Default for grandmasters
# Global settings
clock-class 187
clock-accuracy 254
port master0
iface wr0
role master
extension whiterabbit
port master1
iface wr1
role master
extension whiterabbit
port master2
iface wr2
role master
extension whiterabbit
port master3
iface wr3
role master
extension whiterabbit
port master4
iface wr4
role master
extension whiterabbit
port master5
iface wr5
role master
extension whiterabbit
port master6
iface wr6
role master
extension whiterabbit
port master7
iface wr7
role master
extension whiterabbit
port master8
iface wr8
role master
extension whiterabbit
port master9
iface wr9
role master
extension whiterabbit
port master10
iface wr10
role master
extension whiterabbit
port master11
iface wr11
role master
extension whiterabbit
port master12
iface wr12
role master
extension whiterabbit
port master13
iface wr13
role master
extension whiterabbit
port master14
iface wr14
role master
extension whiterabbit
port master15
iface wr15
role master
extension whiterabbit
port master16
iface wr16
role master
extension whiterabbit
port master17
iface wr17
role master
extension whiterabbit
# Autoselection of port modepgrandmasters
# Global settings
clock-class 187
clock-accuracy 254
port wr0
iface wr0
role auto
extension whiterabbit
port wr1
iface wr1
role auto
extension whiterabbit
port wr2
iface wr2
role auto
extension whiterabbit
port wr3
iface wr3
role auto
extension whiterabbit
port wr4
iface wr4
role auto
extension whiterabbit
port wr5
iface wr5
role auto
extension whiterabbit
port wr6
iface wr6
role auto
extension whiterabbit
port wr7
iface wr7
role auto
extension whiterabbit
port wr8
iface wr8
role auto
extension whiterabbit
port wr9
iface wr9
role auto
extension whiterabbit
port wr10
iface wr10
role auto
extension whiterabbit
port wr11
iface wr11
role auto
extension whiterabbit
port wr12
iface wr12
role auto
extension whiterabbit
port wr13
iface wr13
role auto
extension whiterabbit
port wr14
iface wr14
role auto
extension whiterabbit
port wr15
iface wr15
role auto
extension whiterabbit
port wr16
iface wr16
role auto
extension whiterabbit
port wr17
iface wr17
role auto
extension whiterabbit
-- The VENDOR_SERIAL field can be set to an empty string to provide class-level
-- information as opposed to device-level information.
sfpdb = {
{
part_num = "AXGE-1254-0531",
alpha = 2.67871791665542e-04,
delta_tx = 10,
delta_rx = 10
},
{
part_num = "AXGE-3454-0531",
alpha = -2.67800055584799e-04,
delta_tx = 10,
delta_rx = 10
},
}
global = {
sfp_database_path = "/wr/etc/sfp_database.conf";
};
timing = {
pps_width = 100000; -- PPS pulse width
-- use_nmea = 1; -- take UTC seconds from NMEA GPS clock connected to /dev/ttyS2
-- mode = "GrandMaster"; -- grand-master with external reference
};
ports = {
wr0 = {
phy_rx_min = 160000; -- minimal RX latency introduced by the PHY (in picoseconds)
phy_tx_min = 0;
mac_addr = "auto";
mode = "wr_slave";
};
wr1 = {
phy_rx_min = 160000; -- minimal RX latency introduced by the PHY (in picoseconds)
phy_tx_min = 0;
mac_addr = "auto";
mode = "wr_master";
};
wr2 = {
phy_rx_min = 160000; -- minimal RX latency introduced by the PHY (in picoseconds)
phy_tx_min = 0;
mac_addr = "auto";
mode = "wr_master";
};
wr3 = {
phy_rx_min = 160000; -- minimal RX latency introduced by the PHY (in picoseconds)
phy_tx_min = 0;
mac_addr = "auto";
mode = "wr_master";
};
wr4 = {
phy_rx_min = 161200; -- minimal RX latency introduced by the PHY (in picoseconds)
phy_tx_min = 0;
mac_addr = "auto";
mode = "wr_master";
};
wr5 = {
phy_rx_min = 161200; -- minimal RX latency introduced by the PHY (in picoseconds)
phy_tx_min = 0;
mac_addr = "auto";
mode = "wr_master";
};
wr6 = {
phy_rx_min = 161200; -- minimal RX latency introduced by the PHY (in picoseconds)
phy_tx_min = 0;
mac_addr = "auto";
mode = "wr_master";
};
wr7 = {
phy_rx_min = 161200; -- minimal RX latency introduced by the PHY (in picoseconds)
phy_tx_min = 0;
mac_addr = "auto";
mode = "wr_master";
};
wr8 = {
phy_rx_min = 161200; -- minimal RX latency introduced by the PHY (in picoseconds)
phy_tx_min = 0;
mac_addr = "auto";
mode = "wr_master";
};
wr9 = {
phy_rx_min = 161200; -- minimal RX latency introduced by the PHY (in picoseconds)
phy_tx_min = 0;
mac_addr = "auto";
mode = "wr_master";
};
wr10 = {
phy_rx_min = 161200; -- minimal RX latency introduced by the PHY (in picoseconds)
phy_tx_min = 0;
mac_addr = "auto";
mode = "wr_master";
};
wr11 = {
phy_rx_min = 161200; -- minimal RX latency introduced by the PHY (in picoseconds)
phy_tx_min = 0;
mac_addr = "auto";
mode = "wr_master";
};
wr12 = {
phy_rx_min = 161200; -- minimal RX latency introduced by the PHY (in picoseconds)
phy_tx_min = 0;
mac_addr = "auto";
mode = "wr_master";
};
wr13 = {
phy_rx_min = 161200; -- minimal RX latency introduced by the PHY (in picoseconds)
phy_tx_min = 0;
mac_addr = "auto";
mode = "wr_master";
};
wr14 = {
phy_rx_min = 161200; -- minimal RX latency introduced by the PHY (in picoseconds)
phy_tx_min = 0;
mac_addr = "auto";
mode = "wr_master";
};
wr15 = {
phy_rx_min = 161200; -- minimal RX latency introduced by the PHY (in picoseconds)
phy_tx_min = 0;
mac_addr = "auto";
mode = "wr_master";
};
wr16 = {
phy_rx_min = 161200; -- minimal RX latency introduced by the PHY (in picoseconds)
phy_tx_min = 0;
mac_addr = "auto";
mode = "wr_master";
};
wr17 = {
phy_rx_min = 161200; -- minimal RX latency introduced by the PHY (in picoseconds)
phy_tx_min = 0;
mac_addr = "auto";
mode = "wr_master";
};
};
......@@ -19,3 +19,4 @@ wrs_dump_shmem
sdb-read
nbtee
wrs_auxclk
wrs_checkcfg
......@@ -5,6 +5,7 @@ TOOLS += wrs_vlans wrs_dump_shmem
TOOLS += sdb-read
TOOLS += nbtee
TOOLS += wrs_auxclk
TOOLS += wrs_checkcfg
WR_INSTALL_ROOT ?= /usr/lib/white-rabbit
......@@ -44,7 +45,7 @@ endif
LDFLAGS = -L../mini-rpc \
-L../libwr \
-L../libsdb \
-lwr -lminipc -lsdbfs -llua -lm -ldl
-lwr -lminipc -lsdbfs -lm -ldl
all: $(TOOLS)
......
/* Alessandro Rubini for CERN, 2014 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <libwr/config.h>
int main(int argc, char **argv)
{
int err, verbose = 0;
me_lazy:
if (argc < 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
fprintf(stderr, "%s: Use: \"%s [-v] <dotcfg> [<Kconfig>]\"\n",
argv[0], argv[0]);
exit(1);
}
if (!strcmp(argv[1], "-v")) {
verbose++;
argv++;
argc--;
goto me_lazy;
}
if (access(argv[1], R_OK) < 0) {
fprintf(stderr, "%s: %s: %s\n", argv[0], argv[1],
strerror(errno));
exit(1);
}
if (argc == 2) {
err = libwr_cfg_read_file(argv[1]);
if (err) {
fprintf(stderr, "%s: Error in %s:%i: %s\n", argv[0],
argv[1], -err, strerror(errno));
exit(1);
}
if (verbose)
libwr_cfg_dump(stdout);
exit(0);
}
if (access(argv[2], R_OK) < 0) {
fprintf(stderr, "%s: %s: %s\n", argv[0], argv[2],
strerror(errno));
exit(1);
}
err = libwr_cfg_read_verify_file(argv[1], argv[2]);
if (verbose)
libwr_cfg_dump(stdout);
if (err)
exit(1); /* messages already printed */
exit(0);
return 0;
}
......@@ -188,7 +188,7 @@ struct dump_info hal_port_info [] = {
DUMP_FIELD(int, hw_addr_auto),
DUMP_FIELD(int, mode),
DUMP_FIELD(int, state),
DUMP_FIELD(int, index),
DUMP_FIELD(int, fiber_index),
DUMP_FIELD(int, locked),
/* these fields are defined as uint32_t but we prefer %i to %x */
DUMP_FIELD(int, calib.phy_rx_min),
......@@ -207,7 +207,9 @@ struct dump_info hal_port_info [] = {
DUMP_FIELD(double, calib.sfp.alpha),
DUMP_FIELD(uint32_t, calib.sfp.delta_tx),
DUMP_FIELD(uint32_t, calib.sfp.delta_rx),
DUMP_FIELD(pointer, calib.sfp.next),
DUMP_FIELD(int, calib.sfp.tx_wl),
DUMP_FIELD(int, calib.sfp.rx_wl),
DUMP_FIELD(pointer, calib.sfp.next),
DUMP_FIELD(uint32_t, phase_val),
DUMP_FIELD(int, phase_val_valid),
......
OBJS = hal_exports.o hal_main.o hal_ports.o hal_config.o hal_timing.o
OBJS = hal_exports.o hal_main.o hal_ports.o hal_timing.o
BINARY = wrsw_hal
......@@ -27,7 +27,7 @@ ifdef WRS_HAL_DEBUG
endif
LDFLAGS = -L../libwr -L../mini-rpc \
-lminipc -llua -lm -ldl -lwr
-lminipc -lm -ldl -lwr
all: $(BINARY)
......
/* Wrapper code for handling Lua configuration files */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include <libwr/trace.h>
#define HAL_CONFIG_FILE "/wr/etc/wrsw_hal.conf"
static lua_State *cfg_file = NULL;
static char *extra_cmdline = NULL;
static char *hal_config_file = HAL_CONFIG_FILE;
/* Sets the path to the HAL config file */
void hal_config_set_config_file(const char *str)
{
hal_config_file = strdup(str);
}
/* Appends extra Lua code to the contents of the configuration file to
be parsed. Can be used to execute inline config given as a command
line parameter. */
int hal_config_extra_cmdline(const char *str)
{
extra_cmdline = strdup(str);
return 0;
}
/* Parses the HAL configuration file */
int hal_parse_config()
{
int ret;
TRACE(TRACE_INFO, "Parsing wrsw_hal configuration file: %s", HAL_CONFIG_FILE);
cfg_file = lua_open();
luaL_openlibs(cfg_file);
/* Just execute the config file as a regular Lua script. The
contents of the file will be ordinary Lua variables
accessible via lua_State. */
ret = luaL_dofile(cfg_file, hal_config_file);
/* Declare a Lua "helper" function for regexp searching global
variables - it's much easier to implement in Lua than in
plain C. */
ret |= luaL_dostring(cfg_file, "\
function get_var(name) \
local t = _G \
for w in name:gmatch(\"([%w_]+)\\.?\") do \
t = t[w] \
end \
return t \
end");
/* Execute extra code from the command line */
if (extra_cmdline)
ret |= luaL_dostring(cfg_file, extra_cmdline);
if (ret) {
TRACE(TRACE_ERROR, "Error parsing the configuration file: %s",
lua_tostring(cfg_file, -1));
return -1;
}
return 0;
}
/* Looks up for a global variable (name). If it's found, it is pushed
on the Lua stack and the function returns 0, otherwise a negative
error code is returned. */
static int global_get_var(const char *name)
{
lua_getglobal(cfg_file, "get_var");
lua_pushstring(cfg_file, name);
if (lua_pcall(cfg_file, 1, 1, 0) != 0)
return -1;
return 0;
}
/* Retreives an integer variable (name) and stores it at
(value). Returns 0 on success, -1 if the variable was not found or
has invalid format. */
int hal_config_get_int(const char *name, int *value)
{
if (global_get_var(name) < 0)
return -1;
if (!lua_isnumber(cfg_file, -1))
return -1;
*value = (int)lua_tonumber(cfg_file, -1);
return 0;
}
/* Same as above, but for double floating point numbers. */
int hal_config_get_double(const char *name, double *value)
{
if (global_get_var(name) < 0)
return -1;
if (!lua_isnumber(cfg_file, -1))
return -1;
*value = (double)lua_tonumber(cfg_file, -1);
return 0;
}
/* Same as above, but for null-terminated strings */
int hal_config_get_string(const char *name, char *value, int max_len)
{
if (global_get_var(name) < 0)
return -1;
if (!lua_isstring(cfg_file, -1))
return -1;
strncpy(value, lua_tostring(cfg_file, -1), max_len);
return 0;
}
/* Iterates a particular section (section) in the config file for its
* subsections. For a file containing:
ports = {
wru0 = {
...
};
wr1 = {
...
};
wr2 = {
...
};
};
calling hal_config_iterate("ports", 0, sub, strlen(sub)) will
return 1 and sub == "wr0",
calling hal_config_iterate("ports", 1, sub, strlen(sub)) will
return 1 and sub == "wr1",
hal_config_iterate("ports", 3, sub, strlen(sub)) will return 0, as
there will be no more subsections in the "ports" section.
*/
int hal_config_iterate(const char *section, int index, char *subsection,
int max_len)
{
int i = 0;
if (global_get_var(section) < 0)
return -1;
lua_pushnil(cfg_file); /* first key */
while (lua_next(cfg_file, -2) != 0) {
/* uses 'key' (at index -2) and 'value' (at index -1) */
char *key_type = (char *)lua_typename(cfg_file,
lua_type(cfg_file, -1));
if (!strcmp(key_type, "table") && i == index) {
strncpy(subsection, lua_tostring(cfg_file, -2),
max_len);
return 1;
} else if (!strcmp(key_type, "string") && i == index) {
strncpy(subsection, lua_tostring(cfg_file, -1),
max_len);
return 1;
}
i++;
/* removes 'value'; keeps 'key' for next iteration */
lua_pop(cfg_file, 1);
}
return 0;
}
......@@ -14,6 +14,7 @@
#include <libwr/switch_hw.h>
#include <libwr/shw_io.h>
#include <libwr/sfp_lib.h>
#include <libwr/config.h>
#include "wrsw_hal.h"
#include <rt_ipc.h>
......@@ -72,14 +73,15 @@ static void hal_deamonize();
/* Main initialization function */
static int hal_init()
{
char sfp_db_path[1024];
//trace_log_stderr();
TRACE(TRACE_INFO, "HAL initializing...");
memset(cleanup_cb, 0, sizeof(cleanup_cb));
libwr_cfg_read_file("/wr/etc/dot-config"); /* FIXME: accept -f */
shw_sfp_read_db();
/* Set up trap for some signals - the main purpose is to
prevent the hardware from working when the HAL is shut down
- launching the HAL on already initialized HW will freeze
......@@ -89,19 +91,6 @@ static int hal_init()
signal(SIGTERM, sighandler);
signal(SIGILL, sighandler);
assert_init(hal_parse_config());
if (!hal_config_get_string("global.sfp_database_path",
sfp_db_path, sizeof(sfp_db_path))) {
if (shw_sfp_read_db(sfp_db_path) < 0) {
TRACE(TRACE_ERROR, "Can't read SFP database (%s)",
sfp_db_path);
} else {
TRACE(TRACE_INFO, "Loaded SFP database (%s)",
sfp_db_path);
}
}
/* Low-level hw init, init non-kernel drivers */
assert_init(shw_init());
......@@ -174,32 +163,19 @@ static void show_help()
{
printf("WR Switch Hardware Abstraction Layer daemon (wrsw_hal)\n\
Usage: wrsw_hal [options], where [options] can be:\n\
-f : force FPGA firmware reload\n\
-d : fork into background (daemon mode)\n\
-x [code]: execute arbitrary Lua [code] before loading configuration file\n\
-c [file]: specify your own config file\n\n");
-d : fork into background (daemon mode)\n");
}
static void hal_parse_cmdline(int argc, char *argv[])
{
int opt;
while ((opt = getopt(argc, argv, "dfhx:c:")) != -1) {
while ((opt = getopt(argc, argv, "dh")) != -1) {
switch (opt) {
case 'd':
daemon_mode = 1;
break;
case 'x':
hal_config_extra_cmdline(optarg);
break;
case 'c':
hal_config_set_config_file(optarg);
break;
// case 'f':
// shw_fpga_force_firmware_reload();
// break;
case 'h':
show_help();
exit(0);
......
This diff is collapsed.
......@@ -7,6 +7,7 @@
#include <unistd.h>
#include <libwr/switch_hw.h>
#include <libwr/config.h>
#include "wrsw_hal.h"
#include "timeout.h"
......@@ -20,8 +21,16 @@ static int timing_mode;
int hal_init_timing()
{
char str[128];
timeout_t lock_tmo;
static struct {
char *cfgname;
int modevalue;
} *m, modes[] = {
{"TIME_GM", HAL_TIMING_MODE_GRAND_MASTER},
{"TIME_FM", HAL_TIMING_MODE_FREE_MASTER},
{"TIME_BC", HAL_TIMING_MODE_BC},
{NULL, HAL_TIMING_MODE_BC /* default */},
};
if (rts_connect() < 0) {
TRACE(TRACE_ERROR,
......@@ -29,29 +38,14 @@ int hal_init_timing()
return -1;
}
if (hal_config_get_string("timing.mode", str, sizeof(str)) < 0) {
TRACE(TRACE_INFO,
"Not timing mode specified in the config file. "
"Defaulting to Boundary Clock.");
timing_mode = HAL_TIMING_MODE_BC;
strcpy(str, "BoundaryClock");
} else {
if (!strcasecmp(str, "GrandMaster") || !strcasecmp(str, "GM"))
timing_mode = HAL_TIMING_MODE_GRAND_MASTER;
else if (!strcasecmp(str, "FreeMaster")
|| !strcasecmp(str, "FM"))
timing_mode = HAL_TIMING_MODE_FREE_MASTER;
else if (!strcasecmp(str, "BoundaryClock")
|| !strcasecmp(str, "BC"))
timing_mode = HAL_TIMING_MODE_BC;
else {
TRACE(TRACE_ERROR, "Unrecognized timing mode '%s'",
str);
return -1;
}
}
for (m = modes; m->cfgname; m++)
if (libwr_cfg_get(m->cfgname))
break;
timing_mode = m->modevalue;
TRACE(TRACE_INFO, "Timing mode: %s", str);
if (!m->cfgname)
fprintf(stderr, "%s: no config variable set, defaults used\n",
__func__);
/* initialize the RT Subsys */
switch (timing_mode) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment