Commit c43ce9d9 authored by Aurelio Colosimo's avatar Aurelio Colosimo Committed by Alessandro Rubini

arch-wrs: new directory for wrs architecture

This commit is just a copy of arch-unix, as it is in commit 97c0c129.
The only difference is in file names, as they have been renamed with
wrs- prefix

arch-wrs will host the stuff for WR switch architecture. It will
be very similar to arch-unix, with the only difference of using
wr switch HAL (Hardware Abstraction Layer) instead of the standard
unix "read/write/ioctl to dev" to drive the White Rabbit specific
hardware.
Signed-off-by: Aurelio Colosimo's avatarAurelio Colosimo <aurelio@aureliocolosimo.it>
parent ef25541c
# Alessandro Rubini for CERN, 2011 -- public domain
# All files are under A (short for ARCH): I'm lazy
A := arch-$(ARCH)
CFLAGS += -DCONFIG_PPSI_RUNTIME_VERBOSITY -Itools
LIBARCH := $A/libarch.a
OBJ-libarch := $A/wrs-startup.o \
$A/main-loop.o \
$A/wrs-io.o \
lib/cmdline.o \
lib/conf.o \
lib/libc-functions.o \
lib/dump-funcs.o \
lib/div64.o
# The user can set TIME=, but we pick unix time by default
TIME ?= unix
include time-$(TIME)/Makefile
# Unix time operations are always included as a fallback
include time-unix/Makefile
$(LIBARCH): $(OBJ-libarch)
$(AR) r $@ $^
all: $(TARGET)
# to build the target, we need -lstd again, in case we call functions that
# were not selected yet (e.g., pp_open_globals() ).
$(TARGET): $(TARGET).o $(LIBARCH)
$(CC) -Wl,-Map,$(TARGET).map2 -o $@ $(TARGET).o \
-L$A -larch -L$D -lstd -lrt
#ifndef __ARCH_H__
#define __ARCH_H__
/* Architecture-specific defines, included by top-level stuff */
#include <arpa/inet.h> /* ntohs etc */
#include <stdlib.h> /* abs */
#endif /* __ARCH_H__ */
#ifndef __PPSI_ARCH_CONSTANTS_H__
#define __PPSI_ARCH_CONSTANTS_H__
#ifndef __PPSI_CONSTANTS_H__
#Warning "Please include <ppsi/constants.h> before <arch/constants.h>"
#endif
/* nothing to do here, we keep project-wide defaults */
#endif /* __PPSI_ARCH_CONSTANTS_H__ */
/*
* Alessandro Rubini for CERN, 2011 -- public domain
*/
/*
* This is the main loop for unix stuff.
*/
#include <stdlib.h>
#include <errno.h>
#include <sys/select.h>
#include <linux/if_ether.h>
#include <ppsi/ppsi.h>
#include "ppsi-wrs.h"
/* Call pp_state_machine for each instance. To be called periodically,
* when no packets are incoming */
static int run_all_state_machines(struct pp_globals *ppg)
{
int j;
int delay_ms = 0, delay_ms_j;
for (j = 0; j < ppg->nlinks; j++) {
struct pp_instance *ppi = &ppg->pp_instances[j];
delay_ms_j = pp_state_machine(ppi, NULL, 0);
/* delay_ms is the least delay_ms among all instances */
if (delay_ms == 0)
delay_ms = delay_ms_j;
else
delay_ms = delay_ms_j < delay_ms ? delay_ms_j : delay_ms;
}
return delay_ms;
}
void unix_main_loop(struct pp_globals *ppg)
{
struct pp_instance *ppi;
int delay_ms;
int j;
/* Initialize each link's state machine */
for (j = 0; j < ppg->nlinks; j++) {
ppi = &ppg->pp_instances[j];
/*
* If we are sending or receiving raw ethernet frames,
* the ptp payload is one-eth-header bytes into the frame
*/
if (ppi->ethernet_mode)
NP(ppi)->ptp_offset = ETH_HLEN;
/*
* The main loop here is based on select. While we are not
* doing anything else but the protocol, this allows extra stuff
* to fit.
*/
ppi->is_new_state = 1;
}
delay_ms = run_all_state_machines(ppg);
while (1) {
int i;
if (ppg->ebest_updated) {
/* If Ebest was changed in previous loop, run best master
* clock before checking for new packets, which would affect
* port state again */
for (j = 0; j < ppg->nlinks; j++) {
int new_state;
struct pp_instance *ppi = &ppg->pp_instances[j];
new_state = bmc(ppi);
if (new_state != ppi->state) {
ppi->state = new_state;
ppi->is_new_state = 1;
}
}
ppg->ebest_updated = 0;
}
i = unix_net_check_pkt(ppg, delay_ms);
if (i < 0)
continue;
if (i == 0) {
delay_ms = run_all_state_machines(ppg);
continue;
}
/* If delay_ms is -1, the above unix_net_check_pkt will continue
* consuming the previous timeout (see its implementation).
* This ensures that every state machine is called at least once
* every delay_ms */
delay_ms = -1;
for (j = 0; j < ppg->nlinks; j++) {
ppi = &ppg->pp_instances[j];
if ((NP(ppi)->ch[PP_NP_GEN].pkt_present) ||
(NP(ppi)->ch[PP_NP_EVT].pkt_present)) {
/* We got some packets. If not ours, go on to the next ppi */
i = ppi->n_ops->recv(ppi, ppi->rx_frame,
PP_MAX_FRAME_LENGTH - 4,
&ppi->last_rcv_time);
ppi->last_rcv_time.seconds += DSPRO(ppi)->currentUtcOffset;
if (i < PP_MINIMUM_LENGTH) {
pp_diag(ppi, frames, 1, "Error or short packet: %d < %d\n", i,
PP_MINIMUM_LENGTH
);
continue;
}
pp_state_machine(ppi, ppi->rx_ptp,
i - NP(ppi)->ptp_offset);
}
}
}
}
/*
* Alessandro Rubini for CERN, 2011 -- public domain
*/
/*
* These are the functions provided by the various unix files
*/
#define POSIX_ARCH(ppg) ((struct unix_arch_data *)(ppg->arch_data))
struct unix_arch_data {
struct timeval tv;
};
extern int unix_net_check_pkt(struct pp_globals *ppg, int delay_ms);
extern void unix_main_loop(struct pp_globals *ppg);
/*
* Alessandro Rubini for CERN, 2011 -- public domain
*/
#include <stdio.h>
#include <ppsi/ppsi.h>
void pp_puts(const char *s)
{
fputs(s, stdout);
}
/*
* Alessandro Rubini for CERN, 2011 -- public domain
*/
/*
* This is the startup thing for hosted environments. It
* defines main and then calls the main loop.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <ppsi/ppsi.h>
#include "ppsi-wrs.h"
CONST_VERBOSITY int pp_diag_verbosity = 0;
/* FIXME: make MAX_LINKS and conf_path definable at compile time */
#define MAX_LINKS 32
#define CONF_PATH "/etc/ppsi.conf"
int main(int argc, char **argv)
{
struct pp_globals *ppg;
struct pp_instance *ppi;
int i = 0, ret;
struct stat conf_fs;
char *conf_buf;
int conf_fd;
int conf_len = 0;
setbuf(stdout, NULL);
/* We are hosted, so we can allocate */
ppg = calloc(1, sizeof(*ppg));
if (!ppg)
exit(__LINE__);
ppg->max_links = MAX_LINKS;
ppg->links = calloc(ppg->max_links, sizeof(struct pp_link));
conf_fd = open(CONF_PATH, O_RDONLY);
if ((stat(CONF_PATH, &conf_fs) < 0) ||
(conf_fd < 0)) {
pp_printf("Warning: could not open %s, default to one-link built-in "
"config\n", CONF_PATH);
conf_buf = "link 0\niface eth0";
conf_len = strlen(conf_buf);
}
else {
int r = 0, next_r;
conf_buf = calloc(1, conf_fs.st_size) + 1;
do {
next_r = conf_fs.st_size - r;
r = read(conf_fd, &conf_buf[conf_len], next_r);
if (r <= 0)
break;
conf_len = strlen(conf_buf);
} while (conf_len < conf_fs.st_size);
close(conf_fd);
}
ppg->rt_opts = &default_rt_opts;
if ((ret = pp_parse_conf(ppg, conf_buf, conf_len)) < 0) {
pp_printf("Fatal: Error in %s file at line %d\n", CONF_PATH, -ret);
exit(__LINE__);
}
ppg->defaultDS = calloc(1, sizeof(*ppg->defaultDS));
ppg->currentDS = calloc(1, sizeof(*ppg->currentDS));
ppg->parentDS = calloc(1, sizeof(*ppg->parentDS));
ppg->timePropertiesDS = calloc(1, sizeof(*ppg->timePropertiesDS));
ppg->arch_data = calloc(1, sizeof(struct unix_arch_data));
ppg->pp_instances = calloc(ppg->nlinks, sizeof(struct pp_instance));
if ((!ppg->defaultDS) || (!ppg->currentDS) || (!ppg->parentDS)
|| (!ppg->timePropertiesDS) || (!ppg->arch_data)
|| (!ppg->pp_instances))
exit(__LINE__);
ppg->servo = calloc(1, sizeof(*ppg->servo));
for (; i < ppg->nlinks; i++) {
struct pp_link *lnk = &ppg->links[i];
ppi = &ppg->pp_instances[i];
ppi->glbs = ppg;
ppi->iface_name = lnk->iface_name;
ppi->ethernet_mode = (lnk->proto == 0) ? 1 : 0;
if (lnk->role == 1) {
ppi->master_only = 1;
ppi->slave_only = 0;
}
else if (lnk->role == 2) {
ppi->master_only = 0;
ppi->slave_only = 1;
}
/* FIXME set ppi ext enable as defined in its pp_link */
ppi->portDS = calloc(1, sizeof(*ppi->portDS));
/* The following default names depend on TIME= at build time */
ppi->n_ops = &DEFAULT_NET_OPS;
ppi->t_ops = &DEFAULT_TIME_OPS;
if (!ppi->portDS)
exit(__LINE__);
}
if (pp_parse_cmdline(ppg, argc, argv) != 0)
return -1;
pp_open_globals(ppg);
unix_main_loop(ppg);
return 0; /* never reached */
}
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