diff --git a/tools/Makefile b/tools/Makefile index fd213e725648cc04445e0e5635fb1c432d918eb8..beb0e6ce60fe7c57e8555c9bb18f72abb14ed819 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -24,8 +24,6 @@ LIBOBJ = speclib.o loader-ll.o LIBSHARED = libspec.so PROGS = spec-cl spec-fwloader spec-vuart specmem -PROGS += wr-dio-cmd wr-dio-pps wr-dio-agent wr-dio-ruler -PROGS += stamp-frame all: $(LIB) $(PROGS) $(LIBSHARED) diff --git a/tools/stamp-frame.c b/tools/stamp-frame.c deleted file mode 100644 index 822d8aac87d7d99fd799e16752834faf060550ff..0000000000000000000000000000000000000000 --- a/tools/stamp-frame.c +++ /dev/null @@ -1,470 +0,0 @@ -/* - * Copyright (C) 2010,2012 CERN (www.cern.ch) - * Author: Alessandro Rubini - * - * Released to the public domain as sample code to be customized. - * - * This work is part of the White Rabbit project, a research effort led - * by CERN, the European Institute for Nuclear Research. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "net_tstamp.h" /* Actually, */ - -#ifndef SO_TIMESTAMPNS -# define SO_TIMESTAMPNS 35 -# define SCM_TIMESTAMPNS SO_TIMESTAMPNS -#endif - -#ifndef SO_TIMESTAMPING -# define SO_TIMESTAMPING 37 -# define SCM_TIMESTAMPING SO_TIMESTAMPING -#endif - -#ifndef SIOCSHWTSTAMP -# define SIOCSHWTSTAMP 0x89b0 -#endif - -#ifndef ETH_P_1588 -# define ETH_P_1588 0x88F7 -#endif - -static char git_version[] = "version: " GIT_VERSION; - -/* This structure is used to collect stamping information */ -struct ts_data { - struct timespec ns; - struct timespec hw[3]; /* software, hw-sys, hw-raw */ - int error; -}; - -/* We can print such stamp info. Returns -1 with errno set on error */ -int print_stamp(FILE *out, char *prefix, struct ts_data *tstamp, FILE *err) -{ - int i; - static char *names[] = {"sw ", "hw-sys", "hw-raw"}; - - if (tstamp->error) { - if (err) - fprintf(err, "%s: %s\n", prefix, strerror(errno)); - errno = tstamp->error; - return -1; - } - fprintf(out, "%s ns: %10li.%09li\n", prefix, tstamp->ns.tv_sec, - tstamp->ns.tv_nsec); - for (i = 0; i < 3; i++) - fprintf(out, "%s %s: %10li.%09li\n", prefix, names[i], - tstamp->hw[i].tv_sec, - tstamp->hw[i].tv_nsec); - fprintf(out, "\n"); - return 0; -} - - -/* - * This function opens a socket and configures it for stamping. - * It is a library function, in a way, and was used as such - * when part of the "testing" programs of wr-switch-sw - */ -int make_stamping_socket(FILE *errchan, char *argv0, char *ifname, - int tx_type, int rx_filter, int bits, - unsigned char *macaddr) -{ - struct ifreq ifr; - struct sockaddr_ll addr; - struct hwtstamp_config hwconfig; - int sock, iindex, enable = 1; - - sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); - if (sock < 0 && errchan) - fprintf(errchan, "%s: socket(): %s\n", argv0, - strerror(errno)); - if (sock < 0) - return sock; - - memset (&ifr, 0, sizeof(ifr)); - strcpy(ifr.ifr_name, ifname); - - /* hw interface information */ - if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) { - if (errchan) - fprintf(errchan, "%s: SIOCGIFINDEX(%s): %s\n", argv0, - ifname, strerror(errno)); - close(sock); - return -1; - } - - iindex = ifr.ifr_ifindex; - if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) { - if (errchan) - fprintf(errchan, "%s: SIOCGIFHWADDR(%s): %s\n", argv0, - ifname, strerror(errno)); - close(sock); - return -1; - } - memcpy(macaddr, ifr.ifr_hwaddr.sa_data, 6); - - /* Also, enable stamping for the hw interface */ - memset(&hwconfig, 0, sizeof(hwconfig)); - hwconfig.tx_type = tx_type; - hwconfig.rx_filter = rx_filter; - ifr.ifr_data = (void *)&hwconfig; - if (ioctl(sock, SIOCSHWTSTAMP, &ifr) < 0) { - if (errchan) - fprintf(errchan, "%s: SIOCSHWSTAMP(%s): %s\n", argv0, - ifname, strerror(errno)); - close(sock); - return -1; - } - - /* bind and setsockopt */ - memset(&addr, 0, sizeof(addr)); - addr.sll_family = AF_PACKET; - addr.sll_protocol = htons(ETH_P_ALL); - addr.sll_ifindex = iindex; - addr.sll_pkttype = PACKET_OUTGOING; - if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - if (errchan) - fprintf(errchan, "%s: SIOCSHWSTAMP(%s): %s\n", argv0, - ifname, strerror(errno)); - close(sock); - return -1; - } - if (setsockopt(sock, SOL_SOCKET, SO_TIMESTAMP, - &enable, sizeof(enable)) < 0) { - if (errchan) - fprintf(errchan, "%s: setsockopt(TIMESTAMP): %s\n", - argv0, strerror(errno)); - close(sock); - return -1; - } - if (setsockopt(sock, SOL_SOCKET, SO_TIMESTAMPING, - &bits, sizeof(bits)) < 0) { - if (errchan) - fprintf(errchan, "%s: setsockopt(TIMESTAMPING): %s\n", - argv0, strerror(errno)); - close(sock); - return -1; - } - return sock; -} - -/* - * Another "library" function, actually only used by the following two - */ -static void __collect_data(struct msghdr *msgp, struct ts_data *tstamp) -{ - struct cmsghdr *cm; - struct timespec *tsptr; - - if (!tstamp) - return; - memset(tstamp, 0, sizeof(*tstamp)); - - /* Extract data from the cmsg */ - for (cm = CMSG_FIRSTHDR(msgp); cm; cm = CMSG_NXTHDR(msgp, cm)) { - tsptr = (struct timespec *)CMSG_DATA(cm); - if (0) { - printf("level %i, type %i, len %zi\n", cm->cmsg_level, - cm->cmsg_type, cm->cmsg_len); - } - if (cm->cmsg_level != SOL_SOCKET) - continue; - if (cm->cmsg_type == SO_TIMESTAMPNS) - tstamp->ns = *tsptr; - if (cm->cmsg_type == SO_TIMESTAMPING) - memcpy(tstamp->hw, tsptr, sizeof(tstamp->hw)); - } -} - -/* - * These functions are like send/recv but handle stamping too. - */ -ssize_t send_and_stamp(int sock, void *buf, size_t len, int flags, - struct ts_data *tstamp) -{ - struct msghdr msg; /* this line and more from timestamping.c */ - struct iovec entry; - struct sockaddr_ll from_addr; - struct { - struct cmsghdr cm; - char control[512]; - } control; - char data[3*1024]; - int i, j, ret; - - ret = send(sock, buf, len, flags); - if (ret < 0) - return ret; - - /* Then, get back from the error queue */ - memset(&msg, 0, sizeof(msg)); - msg.msg_iov = &entry; - msg.msg_iovlen = 1; - entry.iov_base = data; - entry.iov_len = sizeof(data); - msg.msg_name = (caddr_t)&from_addr; - msg.msg_namelen = sizeof(from_addr); - msg.msg_control = &control; - msg.msg_controllen = sizeof(control); - - j = 100; /* number of trials */ - while ( (i = recvmsg(sock, &msg, MSG_ERRQUEUE)) < 0 && j--) - usleep(10000); /* retry for 1 second */ - if (i < 0) { - if (tstamp) { - memset(tstamp, 0, sizeof(*tstamp)); - tstamp->error = ETIMEDOUT; - } - return ret; - } - if (getenv("STAMP_VERBOSE")) { - int b; - printf("send %i =", i); - for (b = 0; b < i && b < 20; b++) - printf(" %02x", data[b] & 0xff); - putchar('\n'); - } - - /* FIXtv_sec += t2->tv_sec; - t1->tv_nsec += t2->tv_nsec; - if (t1->tv_nsec > 1000 * 1000 * 1000) { - t1->tv_nsec -= 1000 * 1000 * 1000; - t1->tv_sec++; - } -} - -void ts_sub(struct timespec *t1, struct timespec *t2) -{ - t1->tv_sec -= t2->tv_sec; - t1->tv_nsec -= t2->tv_nsec; - if (t1->tv_nsec < 0) { - t1->tv_nsec += 1000 * 1000 * 1000; - t1->tv_sec--; - } -} - - -/* - * Ok, the library-like part is over, we are at main now - */ -#define STAMP_PROTO 0xf001 - -/* This is the frame we are exchanging back and forth */ -struct frame { - struct ether_header h; - uint16_t phase; /* 0 = transmit, 1 = tx follow up */ - struct timespec ts[4]; - unsigned char filler[64]; /* to reach minimum size for sure */ -}; - -void report_times(struct timespec *ts) -{ - struct timespec rtt, tmp, fw, bw; - int i; - - for (i = 0; i < 4; i++) - printf("timestamp T%i: %9li.%09li\n", i+1, - ts[i].tv_sec, ts[i].tv_nsec); - - /* calculate round trip time, forward, backward */ - rtt = ts[3]; - ts_sub(&rtt, &ts[0]); - tmp = ts[2]; - ts_sub(&tmp, &ts[1]); - ts_sub(&rtt, &tmp); - - fw = ts[1]; - ts_sub(&fw, &ts[0]); - bw = ts[3]; - ts_sub(&bw, &ts[2]); - - printf("round trip time: %9li.%09li\n", rtt.tv_sec, rtt.tv_nsec); - printf("forward time: %9li.%09li\n", fw.tv_sec, fw.tv_nsec); - printf("backward time: %9li.%09li\n", bw.tv_sec, bw.tv_nsec); -} - -/* send a frame, and then again after filling the tx time at offset given */ -void send_one_with_followup(int sock, struct frame *f, unsigned char *mac, - int offset) -{ - struct ts_data stamp; - - /* Fill ether header */ - memset(&f->h.ether_dhost, 0xff, ETH_ALEN); /* broadcast */ - memcpy(&f->h.ether_shost, mac, ETH_ALEN); - f->h.ether_type = htons(STAMP_PROTO); - - f->phase = 0; - if (send_and_stamp(sock, f, sizeof(*f), 0, &stamp) < 0) - fprintf(stderr, "send_and_stamp: %s\n", strerror(errno)); - f->phase = 1; - f->ts[offset] = stamp.hw[2]; /* hw raw */ - if (send_and_stamp(sock, f, sizeof(*f), 0, NULL) < 0) - fprintf(stderr, "send_and_stamp: %s\n", strerror(errno)); - - if (getenv("STAMP_PRINT_ALL")) - print_stamp(stdout, "send", &stamp, stderr); -} - -/* receive a frame, timestamping it, and receive the followup too; save ts */ -void recv_one_with_followup(int sock, struct frame *f, unsigned char *mac, - int offset) -{ - struct ts_data stamp; - int ret; - - while (1) { /* repeat until a good frame is received */ - ret = recv_and_stamp(sock, f, sizeof(*f), MSG_TRUNC, &stamp); - if (ret < 0) { - fprintf(stderr, "recv_and_stamp: %s\n", - strerror(errno)); - continue; - } - if (ret != sizeof(*f)) - continue; - if (ntohs(f->h.ether_type) != STAMP_PROTO) - continue; - if (f->phase != 0) - continue; - break; - } - /* receive another one, lazily don't wait */ - if (recv_and_stamp(sock, f, sizeof(*f), MSG_TRUNC, NULL) < 0) - fprintf(stderr, "recv_and_stamp: %s\n", - strerror(errno)); - f->ts[offset] = stamp.hw[2]; - - if (getenv("STAMP_PRINT_ALL")) - print_stamp(stdout, "recv", &stamp, stderr); - -} - -static void print_version(char *pname) -{ - printf("%s %s\n", pname, git_version); -} - -int main(int argc, char **argv) -{ - static struct frame f; - int sock; - unsigned char macaddr[6]; - int listenmode = 0; - int howto = SOF_TIMESTAMPING_MASK; /* everything */ - - if ((argc == 2) && (!strcmp(argv[1], "-V"))) { - print_version(argv[0]); - exit(0); - } - - /* From ./net_tstamp.h, these are the "howto" values - * - * SOF_TIMESTAMPING_TX_HARDWARE = 1, - * SOF_TIMESTAMPING_TX_SOFTWARE = 2 - * SOF_TIMESTAMPING_RX_HARDWARE = 4, - * SOF_TIMESTAMPING_RX_SOFTWARE = 8, - * SOF_TIMESTAMPING_SOFTWARE = 16, - * SOF_TIMESTAMPING_SYS_HARDWARE = 32, - * SOF_TIMESTAMPING_RAW_HARDWARE = 64, - */ - - if (argc == 3 && !strcmp(argv[2], "listen")) { - listenmode = 1; - argc--; - } - if (argc != 2) { - fprintf(stderr, "%s: Use \"%s [-V] [listen]\n", argv[0], - argv[0]); - exit(1); - } - - printf("%s: Using interface %s, with all timestamp options active\n", - argv[0], argv[1]); - - /* Create a socket to use for stamping, use the library code above */ - sock = make_stamping_socket(stderr, argv[0], argv[1], - HWTSTAMP_TX_ON, HWTSTAMP_FILTER_ALL, - howto, macaddr); - if (sock < 0) /* message already printed */ - exit(1); - - if (listenmode) { - /* forever reply */ - while (1) { - recv_one_with_followup(sock, &f, macaddr, 1); - send_one_with_followup(sock, &f, macaddr, 2); - } - } - - /* send mode: send first, then receive, then print */ - send_one_with_followup(sock, &f, macaddr, 0); - recv_one_with_followup(sock, &f, macaddr, 3); - - report_times(f.ts); - - exit(0); -} - diff --git a/tools/wr-dio-agent.c b/tools/wr-dio-agent.c deleted file mode 100644 index f6b985e887d3ec5eefa763d8fa159b396ea2b961..0000000000000000000000000000000000000000 --- a/tools/wr-dio-agent.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (C) 2012 CERN (www.cern.ch) - * Author: Alessandro Rubini - * - * Released to the public domain as sample code to be customized. - * - * This work is part of the White Rabbit project, a research effort led - * by CERN, the European Institute for Nuclear Research. - */ - -/* Typical use: "wr-dio-agent wr1" */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "wr_nic/wr-nic.h" -#include "wr-dio.h" - -static char git_version[] = "version: " GIT_VERSION; - -#define RULER_PROTO 0x5752 /* WR */ - -/* - * Lazily, use global variables, so the code has less parameter passing. - * Everything in this file is using "agent_" as a prefix, to ease the - * reader -- and remember that aligns at 8 spaces, not 4. - */ -char *agent_prgname; -int agent_sock; -char *agent_ifname; -struct ifreq agent_ifr; - - -/* Boring network stuff extracted from main function */ -static int agent_open_wr_sock(char *name) -{ - struct sockaddr_ll addr; - int sock, ifindex; - - sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); - if (sock < 0) { - fprintf(stderr, "%s: socket(): %s\n", - agent_prgname, strerror(errno)); - return -1; - } - - memset(&agent_ifr, 0, sizeof(agent_ifr)); - strncpy(agent_ifr.ifr_name, name, sizeof(agent_ifr.ifr_name)); - if (ioctl(sock, PRIV_MEZZANINE_ID, &agent_ifr) < 0 - /* EAGAIN is special: it means we have no ID to check yet */ - && errno != EAGAIN) { - fprintf(stderr, "%s: ioctl(PRIV_MEZZANINE_ID(%s)): %s\n", - agent_prgname, name, strerror(errno)); - close(sock); - return -1; - } - - /* Retieve the interfaceindex */ - if (ioctl(sock, SIOCGIFINDEX, &agent_ifr) < 0) { - fprintf(stderr, "%s: SIOCGIFINDEX(%s): %s\n", agent_prgname, - name, strerror(errno)); - close(sock); - return -1; - } - ifindex = agent_ifr.ifr_ifindex; - - /* Bind to the interface, so to be able to receive */ - memset(&addr, 0, sizeof(addr)); - addr.sll_family = AF_PACKET; - addr.sll_protocol = htons(RULER_PROTO); - addr.sll_ifindex = ifindex; - addr.sll_pkttype = PACKET_BROADCAST; /* that's what ruler sends */ - if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - fprintf(stderr, "%s: bind(%s): %s\n", agent_prgname, - name, strerror(errno)); - close(sock); - return -1; - } - - /* save in globals for later */ - agent_sock = sock; - return 0; -} - -static void print_version(char *pname) -{ - printf("%s %s\n", pname, git_version); -} - -/* And a simple main with the loop inside */ -int main(int argc, char **argv) -{ - int len; - /* We are receiving stuff in this frame */ - static struct frame { - struct ether_header h; - unsigned char pad[2]; - struct wr_dio_cmd cmd; - } f; - - if ((argc == 2) && (!strcmp(argv[1], "-V"))) { - print_version(argv[0]); - exit(0); - } - - if (argc != 2) { - fprintf(stderr, "%s: Use \"%s [-V] \"\n", - argv[0], argv[0]); - exit(1); - } - agent_prgname = argv[0]; - - /* All functions print error messages by themselves, so just exit */ - if (agent_open_wr_sock(argv[1]) < 0) - exit(1); - - while (1) { - len = recv(agent_sock, &f, sizeof(f), MSG_TRUNC); - if (len != sizeof(f)) { - fprintf(stderr, "%s: recevied unexpected frame length" - " (%i instead of %zu)\n", agent_prgname, len, - sizeof(f)); - continue; - } - if (ntohs(f.h.ether_type) != RULER_PROTO) { - fprintf(stderr, "%s: received unexpected eth type" - " (%04x instead of %04x)\n", agent_prgname, - ntohs(f.h.ether_type), RULER_PROTO); - continue; - } - - if (0) - printf("command %i, ch %i, t %li.%09li\n", - f.cmd.command, f.cmd.channel, f.cmd.t[0].tv_sec, - f.cmd.t[0].tv_nsec); - - /* Then simply pass it to the hardware */ - agent_ifr.ifr_data = (void *)&f.cmd; - if (ioctl(agent_sock, PRIV_MEZZANINE_CMD, &agent_ifr) < 0) { - fprintf(stderr, "%s: ioctl(PRIV_MEZZANINE_CMD(%s)): " - "%s\n", agent_prgname, agent_ifname, - strerror(errno)); - return -1; - } - } - exit(0); -} diff --git a/tools/wr-dio-cmd.c b/tools/wr-dio-cmd.c deleted file mode 100644 index 2c22e4877bc7d8866ef227d928236fead8c9de1e..0000000000000000000000000000000000000000 --- a/tools/wr-dio-cmd.c +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Copyright (C) 2012 CERN (www.cern.ch) - * Author: Alessandro Rubini - * - * Released to the public domain as sample code to be customized. - * - * This work is part of the White Rabbit project, a research effort led - * by CERN, the European Institute for Nuclear Research. - */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "wr_nic/wr-nic.h" -#include "wr-dio.h" - -static char git_version[] = "version: " GIT_VERSION; - -char *prgname; -char c; -int sock; -char *ifname; -struct ifreq ifr; - -struct wr_dio_cmd _cmd; -struct wr_dio_cmd *cmd = &_cmd; - -static int parse_ts(char *s, struct timespec *ts) -{ - int i, n; - unsigned long nano; - char c; - - /* - * Hairy: if we scan "%ld%lf", the 0.009999 will become 9998 micro. - * Thus, scan as integer and string, so we can count leading zeros - */ - - nano = 0; - ts->tv_sec = 0; - ts->tv_nsec = 0; - - if ( (i = sscanf(s, "%ld.%ld%c", &ts->tv_sec, &nano, &c)) == 1) - return 0; /* seconds only */ - if (i == 3) - return -1; /* trailing crap */ - if (i == 0) - if (sscanf(s, ".%ld%c", &nano, &c) != 1) - return -1; /* leading or trailing crap */ - - s = strchr(s, '.') + 1; - n = strlen(s); - if (n > 9) - return -1; /* too many decimals */ - while (n < 9) { - nano *= 10; - n++; - } - ts->tv_nsec = nano; - return 0; -} - -static int scan_pulse(int argc, char **argv) -{ - char c; - - if (argc != 4 && argc != 6) { - fprintf(stderr, "%s: %s: wrong number of arguments\n", - prgname, argv[0]); - fprintf(stderr, " Use: %s " - "[ ]\n", argv[0]); - return -1; - } - if (sscanf(argv[1], "%hi%c", &cmd->channel, &c) != 1 - || cmd->channel > 4) { - fprintf(stderr, "%s: %s: not a channel number \"%s\"\n", - prgname, argv[0], argv[1]); - return -1; - } - - /* Duration is first time argument but position 1 for ioctl */ - if (parse_ts(argv[2], cmd->t + 1) < 0) { - fprintf(stderr, "%s: %s: invalid time \"%s\"\n", - prgname, argv[0], argv[2]); - return -1; - } - if (cmd->t[1].tv_sec) { - fprintf(stderr, "%s: %s: duration must be < 1s (got \"%s\")\n", - prgname, argv[0], argv[2]); - return -1; - } - - /* Next argument is the "when", position 0 in ioctl timestamp array */ - if (!strcmp(argv[3], "now")) { - cmd->flags |= WR_DIO_F_NOW; - } else { - char *s2 = argv[3]; - - if (s2[0] == '+') { - cmd->flags |= WR_DIO_F_REL; - s2++; - } - - if (parse_ts(s2, cmd->t) < 0) { - fprintf(stderr, "%s: %s: invalid time \"%s\"\n", - prgname, argv[0], argv[3]); - return -1; - } - } - - /* If argc is 6, we have period and count */ - if (argc == 6) { - cmd->flags |= WR_DIO_F_LOOP; - - if (parse_ts(argv[4], cmd->t + 2) < 0) { - fprintf(stderr, "%s: %s: invalid time \"%s\"\n", - prgname, argv[0], argv[4]); - return -1; - } - if (sscanf(argv[5], "%i%c", &cmd->value, &c) != 1) { - fprintf(stderr, "%s: %s: invalid count \"%s\"\n", - prgname, argv[0], argv[5]); - return -1; - } - } - - ifr.ifr_data = (void *)cmd; - if (ioctl(sock, PRIV_MEZZANINE_CMD, &ifr) < 0) { - fprintf(stderr, "%s: ioctl(PRIV_MEZZANINE_CMD(%s)): %s\n", - prgname, ifname, strerror(errno)); - return -1; - } - return 0; -} - -static int scan_stamp(int argc, char **argv, int ismask) -{ - int i, ch; - char c; - - cmd->flags = 0; - if (argc == 3 && !strcmp(argv[2], "wait")) { - cmd->flags = WR_DIO_F_WAIT; - argc = 2; - } - if (argc == 1) { - ismask = 1; - ch = 0x1f; - } else if (argc == 2) { - if (sscanf(argv[1], "%i%c", &ch, &c) != 1) { - fprintf(stderr, "%s: %s: not a channel \"%s\"\n", - prgname, argv[0], argv[1]); - exit(1); - } - if (ch < 0 || ch > 31 || (!ismask && ch > 4)) { - fprintf(stderr, "%s: %s: out of range channel \"%s\"\n", - prgname, argv[0], argv[1]); - exit(1); - } - } else { - fprintf(stderr, "%s: %s: wrong number of arguments\n", - prgname, argv[0]); - if (ismask) - fprintf(stderr, " Use: %s []\n", - argv[0]); - else - fprintf(stderr, " Use: %s [] [wait]\n", - argv[0]); - return -1; - } - if (ismask) - cmd->flags = WR_DIO_F_MASK; - - while (1) { - cmd->channel = ch; - errno = 0; - ifr.ifr_data = (void *)cmd; - if (ioctl(sock, PRIV_MEZZANINE_CMD, &ifr) < 0 ) { - if (errno == EAGAIN) - break; - fprintf(stderr, "%s: ioctl(PRIV_MEZZANINE_CMD(%s)): " - "%s\n", prgname, ifname, strerror(errno)); - return -1; - } - for (i = 0; i < cmd->nstamp; i++) - printf("ch %i, %9li.%09li\n", cmd->channel, - (long)cmd->t[i].tv_sec, cmd->t[i].tv_nsec); - } - return 0; -} - -static int one_mode(int c, int index) -{ - if (c == '-') - return 0; - cmd->channel |= 1 << index; - - //Add error message for channel 0 - if(index==0 && strchr("dD01",c)) - { - fprintf(stderr, "Error: Only p/P modes are available as ouput mode for channel 0\n"); - return -1; - } - - switch(c) { - case 'D': - cmd->value |= WR_DIO_INOUT_TERM << index; - case 'd': - cmd->value |= WR_DIO_INOUT_DIO << index; - cmd->value |= WR_DIO_INOUT_OUTPUT << index; - break; - - case 'C': - cmd->value |= WR_DIO_INOUT_TERM << index; - case 'c': - cmd->value |= WR_DIO_INOUT_DIO << index; - cmd->value |= WR_DIO_INOUT_VALUE << index; - if(index!=4) - fprintf(stdout, "Warning: Clock mode is only available for last channel (ch4)\n," - "(on other channel it corresponds to input mode without interruptions)\n"); - break; - - case 'P': - cmd->value |= WR_DIO_INOUT_TERM << index; - case 'p': - cmd->value |= WR_DIO_INOUT_DIO << index; - cmd->value |= WR_DIO_INOUT_VALUE << index; - cmd->value |= WR_DIO_INOUT_OUTPUT << index; - break; - - case 'I': - cmd->value |= WR_DIO_INOUT_TERM << index; - case 'i': - break; - - case '1': - cmd->value |= WR_DIO_INOUT_VALUE << index; - case '0': - cmd->value |= WR_DIO_INOUT_OUTPUT << index; - break; - - default: - fprintf(stderr, "%s: mode: invalid mode '%c'\n", - prgname, c); - return -1; - } - return 0; -} - - -static int scan_inout(int argc, char **argv) -{ - int i, ch; - char c; - - cmd->flags = WR_DIO_F_MASK; - cmd->channel = 0; - cmd->value = 0; - - if (argc == 2) { - if (strlen(argv[1]) != 5) { - fprintf(stderr, "%s: %s: wrong argument \"%s\"\n", - prgname, argv[0], argv[1]); - exit(1); - } - for (i = 0; i < 5; i++) - if (one_mode(argv[1][i], i) < 0) - return -1; - } else { - if (argc < 3 || argc > 11 || ((argc & 1) == 0)) { - fprintf(stderr, "%s: %s: wrong number of arguments\n", - prgname, argv[0]); - return -1; - } - while (argc >= 3) { - if (sscanf(argv[1], "%i%c", &ch, &c) != 1 - || ch < 0 || ch > 4) { - fprintf(stderr, "%s: mode: invalid channel " - "\"%s\"\n", prgname, argv[1]); - return -1; - } - if (strlen(argv[2]) != 1) { - fprintf(stderr, "%s: mode: invalid mode " - "\"%s\"\n", prgname, argv[2]); - return -1; - } - if (one_mode(argv[2][0], ch) < 0) - return -1; - argv += 2; - argc -= 2; - } - } - ifr.ifr_data = (void *)cmd; - if (ioctl(sock, PRIV_MEZZANINE_CMD, &ifr) < 0) { - fprintf(stderr, "%s: ioctl(PRIV_MEZZANINE_CMD(%s)): %s\n", - prgname, ifname, strerror(errno)); - return -1; - } - return 0; -} - -static void print_version(char *pname) -{ - printf("%s %s\n", pname, git_version); -} - -int main(int argc, char **argv) -{ - - prgname = argv[0]; - argv++, argc--; - - if ((argc == 2) && (!strcmp(argv[1], "-V"))) { - print_version(argv[0]); - exit(0); - } - - if (argc < 2) { - fprintf(stderr, "%s: use \"%s [-V] [...]\"\n", - prgname, prgname); - exit(1); - } - - ifname = argv[0]; - argv++, argc--; - - sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); - if (sock < 0) { - fprintf(stderr, "%s: socket(): %s\n", - prgname, strerror(errno)); - exit(1); - } - - memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); - if (ioctl(sock, PRIV_MEZZANINE_ID, &ifr) < 0 - /* EAGAIN is special: it means we have no ID to check yet */ - && errno != EAGAIN) { - fprintf(stderr, "%s: ioctl(PRIV_MEZZANINE_ID(%s)): %s\n", - prgname, ifname, strerror(errno)); - } - - /* - * Parse the command line: - * - * pulse . . - * pulse . now - * pulse . +. - * - * stamp [] - * stampm [] - * - * mode <01234> - * mode [...] - */ - if (!strcmp(argv[0], "pulse")) { - cmd->command = WR_DIO_CMD_PULSE; - if (scan_pulse(argc, argv) < 0) - exit(1); - } else if (!strcmp(argv[0], "stamp")) { - cmd->command = WR_DIO_CMD_STAMP; - if (scan_stamp(argc, argv, 0 /* no mask */) < 0) - exit(1); - } else if (!strcmp(argv[0], "stampm")) { - cmd->command = WR_DIO_CMD_STAMP; - if (scan_stamp(argc, argv, 1 /* mask */) < 0) - exit(1); - } else if (!strcmp(argv[0], "mode")) { - cmd->command = WR_DIO_CMD_INOUT; - if (scan_inout(argc, argv) < 0) - exit(1); - } else { - fprintf(stderr, "%s: unknown command \"%s\"\n", prgname, - argv[0]); - exit(1); - } - - ifr.ifr_data = (void *)cmd; - exit(0); -} diff --git a/tools/wr-dio-pps.c b/tools/wr-dio-pps.c deleted file mode 100644 index cd5ba018a6c754f23e182b8659550353c4a8c86e..0000000000000000000000000000000000000000 --- a/tools/wr-dio-pps.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2012 CERN (www.cern.ch) - * Author: Alessandro Rubini - * - * Released to the public domain as sample code to be customized. - * - * This work is part of the White Rabbit project, a research effort led - * by CERN, the European Institute for Nuclear Research. - */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "wr_nic/wr-nic.h" -#include "wr-dio.h" - -/** - * This takes two arguments: interface name and channel number - * - * This simple tools just show an example of how to program with wr-nic/dio. - * If you want to measure WR timing we suggest to use the hardwire PPS on channel 0 - * that gives a more accurate precision. - **/ - -static char git_version[] = "version: " GIT_VERSION; - -static void print_version(char *pname) -{ - printf("%s %s\n", pname, git_version); -} - -int main(int argc, char **argv) -{ - struct wr_dio_cmd _cmd; - struct wr_dio_cmd *cmd = &_cmd; - struct ifreq ifr; - char *prgname = argv[0]; - char *ifname = "wr0"; - int sock, ch, charg = 1; - char c; - - if ((argc == 2) && (!strcmp(argv[1], "-V"))) { - print_version(argv[0]); - exit(0); - } - - if (argc < 2 || argc > 3) { - fprintf(stderr, "%s: Use \"%s [] \"\n", - prgname, prgname); - exit(1); - } - if (argc == 3) { - ifname = argv[1]; - charg++; - } - if (sscanf(argv[charg], "%i%c", &ch, &c) != 1) { - fprintf(stderr, "%s: Not a channel number \"%s\"\n", - prgname, argv[charg]); - exit(1); - } - if (ch < 1 || ch > 4) { - fprintf(stderr, "%s: Out of range channel number \"%s\"\n", - prgname, argv[charg]); - exit(1); - } - - fprintf(stderr, "%s: Using interface \"%s\" and channel %i for " - "pps output\n", prgname, ifname, ch); - - - /* The following is standard stuff to access wr-nic */ - - sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); - if (sock < 0) { - fprintf(stderr, "%s: socket(): %s\n", - prgname, strerror(errno)); - exit(1); - } - - memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); - if (ioctl(sock, PRIV_MEZZANINE_ID, &ifr) < 0 - /* EAGAIN is special: it means we have no ID to check yet */ - && errno != EAGAIN) { - fprintf(stderr, "%s: ioctl(PRIV_MEZZANINE_ID(%s)): %s\n", - prgname, ifname, strerror(errno)); - } - - - /* Fill the command structure */ - - memset(cmd, 0, sizeof(*cmd)); - - cmd->command = WR_DIO_CMD_PULSE; - cmd->channel = ch; - cmd->flags = WR_DIO_F_REL | WR_DIO_F_LOOP; - /* Number of loops: -1 <=> Inf */ - cmd->value = -1; - /* 2s delay to have time to send and process this command */ - cmd->t[0].tv_sec = 2; - /* 1ms pulse width */ - cmd->t[1].tv_nsec = 1000 * 1000; - /* Loop period */ - cmd->t[2].tv_sec = 1; - - - /* Give it to the driver and we are done */ - - ifr.ifr_data = (void *)cmd; - if (ioctl(sock, PRIV_MEZZANINE_CMD, &ifr) < 0) { - fprintf(stderr, "%s: ioctl(PRIV_MEZZANINE_CMD(%s)): %s\n", - prgname, ifname, strerror(errno)); - exit(1); - } - - exit(0); -} diff --git a/tools/wr-dio-ruler.c b/tools/wr-dio-ruler.c deleted file mode 100644 index 5b17cb6cc4b4019cf88b903a68c8c3613c345e23..0000000000000000000000000000000000000000 --- a/tools/wr-dio-ruler.c +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Copyright (C) 2012 CERN (www.cern.ch) - * Author: Alessandro Rubini - * - * Released to the public domain as sample code to be customized. - * - * This work is part of the White Rabbit project, a research effort led - * by CERN, the European Institute for Nuclear Research. - */ - -/* Typical use: "wr-dio-ruler wr1 IN0 L3+0.001 R3+0.001 L4+0.002" */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "wr_nic/wr-nic.h" -#include "wr-dio.h" - -static char git_version[] = "version: " GIT_VERSION; - -#define RULER_PROTO 0x5752 /* WR */ -/* - * Lazily, use global variables, so the code has less parameter passing. - * Everything in this file is using "ruler_" as a prefix, to ease the - * reader -- and remember that aligns at 8 spaces, not 4. - */ -char *ruler_prgname; -int ruler_sock; -char *ruler_ifname; -struct wr_dio_cmd ruler_cmd; -struct ifreq ruler_ifr; -unsigned char ruler_macaddr[ETH_ALEN]; - -struct ruler_action { - int isremote; - int channel; - struct timespec delay; -}; - -/* Boring parsing separated to a separate function (same code as elsewhere) */ -static int parse_ts(char *s, struct timespec *ts) -{ - int i, n; - unsigned long nano; - char c; - - /* - * Hairy: if we scan "%ld%lf", the 0.009999 will become 9998 micro. - * Thus, scan as integer and string, so we can count leading zeros - */ - - nano = 0; - ts->tv_sec = 0; - ts->tv_nsec = 0; - - if ( (i = sscanf(s, "%ld.%ld%c", &ts->tv_sec, &nano, &c)) == 1) - return 0; /* seconds only */ - if (i == 3) - return -1; /* trailing crap */ - if (i == 0) - if (sscanf(s, ".%ld%c", &nano, &c) != 1) - return -1; /* leading or trailing crap */ - - s = strchr(s, '.') + 1; - n = strlen(s); - if (n > 9) - return -1; /* too many decimals */ - while (n < 9) { - nano *= 10; - n++; - } - ts->tv_nsec = nano; - return 0; -} - - -/* Boring network stuff extracted from main function */ -static int ruler_open_wr_sock(char *name) -{ - struct sockaddr_ll addr; - int sock, ifindex; - - sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); - if (sock < 0) { - fprintf(stderr, "%s: socket(): %s\n", - ruler_prgname, strerror(errno)); - return -1; - } - - memset(&ruler_ifr, 0, sizeof(ruler_ifr)); - strncpy(ruler_ifr.ifr_name, name, sizeof(ruler_ifr.ifr_name)); - if (ioctl(sock, PRIV_MEZZANINE_ID, &ruler_ifr) < 0 - /* EAGAIN is special: it means we have no ID to check yet */ - && errno != EAGAIN) { - fprintf(stderr, "%s: ioctl(PRIV_MEZZANINE_ID(%s)): %s\n", - ruler_prgname, name, strerror(errno)); - close(sock); - return -1; - } - - /* Retrieve the local MAC address to send correct Ethernet frames */ - if (ioctl(sock, SIOCGIFHWADDR, &ruler_ifr) < 0) { - fprintf(stderr, "%s: SIOCGIFHWADDR(%s): %s\n", ruler_prgname, - name, strerror(errno)); - close(sock); - return -1; - } - memcpy(ruler_macaddr, ruler_ifr.ifr_hwaddr.sa_data, - sizeof(ruler_macaddr)); - - /* Retieve the interfaceindex */ - if (ioctl(sock, SIOCGIFINDEX, &ruler_ifr) < 0) { - fprintf(stderr, "%s: SIOCGIFINDEX(%s): %s\n", ruler_prgname, - name, strerror(errno)); - close(sock); - return -1; - } - ifindex = ruler_ifr.ifr_ifindex; - - /* Bind to the interface, so to be able to send */ - memset(&addr, 0, sizeof(addr)); - addr.sll_family = AF_PACKET; - addr.sll_protocol = htons(RULER_PROTO); - addr.sll_ifindex = ifindex; - addr.sll_pkttype = PACKET_OUTGOING; - if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - fprintf(stderr, "%s: bind(%s): %s\n", ruler_prgname, - name, strerror(errno)); - close(sock); - return -1; - } - - /* save in globals for later */ - ruler_sock = sock; - ruler_ifname = name; - return 0; -} - -/* The channel being monitored will be configured as input */ -static int ruler_config_in(char *chname) -{ - int ch; - char c; - - if (sscanf(chname, "IN%i%c", &ch, &c) != 1) { - fprintf(stderr, "%s: Argument \"%s\" must be \"IN\"\n", - ruler_prgname, chname); - return -1; - } - if (ch < 0 || ch > 4) { - fprintf(stderr, "%s: Out of range channel number in \"%s\"\n", - ruler_prgname, chname); - return -1; - } - return ch; -} - -/* Actions are allocated in an array and returned for later use */ -static struct ruler_action *ruler_build_actions(int nact, char **strings) -{ - struct ruler_action *act; - char *s; - int i, ch; - char lr, c; - - act = calloc(nact, sizeof(*act)); - if (!act) { - fprintf(stderr, "%s: %s\n", ruler_prgname, strerror(errno)); - return NULL; - } - for (i = 0; i < nact; i++) { - if (sscanf(strings[i], "%c%i+%c\n", &lr, &ch, &c) != 3) { - fprintf(stderr, "%s: Wrong argument \"%s\"\n", - ruler_prgname, strings[i]); - free(act); - return NULL; - } - if (lr != 'L' && lr != 'R') { - fprintf(stderr, "%s: Wrong argument \"%s\"\n", - ruler_prgname, strings[i]); - free(act); - return NULL; - } - if (ch < 0 || ch > 4) { - fprintf(stderr, "%s: Out of range channel in \"%s\"\n", - ruler_prgname, strings[i]); - free(act); - return NULL; - } - s = strchr(strings[i], '+') + 1; - if (parse_ts(s, &act[i].delay) < 0) { - fprintf(stderr, "%s: Wrong time \"%s\" in \"%s\"\n", - ruler_prgname, s, strings[i]); - free(act); - return NULL; - } - - if (lr == 'L') - act[i].isremote = 0; - else - act[i].isremote = 1; - act[i].channel = ch; - } - - for (i = 0; i < nact; i++) { - fprintf(stderr, "%s: configured for %s channel %i, " - "delay %li.%09li\n", ruler_prgname, - act[i].isremote ? "remote" : " local", - act[i].channel, - act[i].delay.tv_sec, act[i].delay.tv_nsec); - } - return act; -} - -/* The main loop will wait for an event... */ -static int ruler_wait_event(int inch, struct timespec *ts) -{ - ruler_cmd.command = WR_DIO_CMD_STAMP; - ruler_cmd.flags = WR_DIO_F_WAIT; - ruler_cmd.channel = inch; - - ruler_ifr.ifr_data = (void *)&ruler_cmd; - if (ioctl(ruler_sock, PRIV_MEZZANINE_CMD, &ruler_ifr) < 0 ) { - fprintf(stderr, "%s: ioctl(PRIV_MEZZANINE_CMD(%s)): " - "%s\n", ruler_prgname, ruler_ifname, strerror(errno)); - return -1; - } - /* Assume it's only one stamp */ - *ts = ruler_cmd.t[0]; - return 0; -} - -/* ...and run all actions when the event happens */ -static int ruler_run_actions(int nact, struct timespec *ts, - struct ruler_action *actions) -{ - int i; - - /* We are building stuff in this frame, to possibly send it */ - static struct frame { - struct ether_header h; - unsigned char pad[2]; - struct wr_dio_cmd cmd; - } f; - - /* Most parameters are unchanged over actions */ - memset(&f.h.ether_dhost, 0xff, ETH_ALEN); /* broadcast */ - memcpy(&f.h.ether_shost, ruler_macaddr, ETH_ALEN); - f.h.ether_type = ntohs(RULER_PROTO); - f.cmd.t[1].tv_nsec = 1000 * 1000; /* 1ms*/ - - f.cmd.command = WR_DIO_CMD_PULSE; - - for (i = 0; i < nact; i++) { - f.cmd.channel = actions[i].channel; - f.cmd.t[0] = *ts; - /* add the requested delay */ - f.cmd.t[0].tv_sec += actions[i].delay.tv_sec; - f.cmd.t[0].tv_nsec += actions[i].delay.tv_nsec; - if (f.cmd.t[0].tv_nsec > 1000 * 1000 * 1000) { - f.cmd.t[0].tv_nsec -= 1000 * 1000 * 1000; - f.cmd.t[0].tv_sec++; - } - - if (actions[i].isremote) { - if (send(ruler_sock, &f, sizeof(f), 0) < 0) { - fprintf(stderr, "%s: send(): %s\n", - ruler_prgname, strerror(errno)); - return -1; - } - continue; - } - - /* local */ - ruler_ifr.ifr_data = (void *)&f.cmd; - if (ioctl(ruler_sock, PRIV_MEZZANINE_CMD, &ruler_ifr) < 0) { - fprintf(stderr, "%s: ioctl(PRIV_MEZZANINE_CMD(%s)): " - "%s\n", ruler_prgname, ruler_ifname, - strerror(errno)); - return -1; - } - } - return 0; -} - -static void print_version(char *pname) -{ - printf("%s %s\n", pname, git_version); -} - -/* Finally, a main function to wrap it all */ -int main(int argc, char **argv) -{ - struct ruler_action *actions; - struct timespec ts; - int inch; - - if ((argc == 2) && (!strcmp(argv[1], "-V"))) { - print_version(argv[0]); - exit(0); - } - - if (argc < 4) { - fprintf(stderr, "%s: Use \"%s [-V] IN " - "{L,R}+ [...]\n", - argv[0], argv[0]); - exit(1); - } - ruler_prgname = argv[0]; - - /* All functions print error messages by themselves, so just exit */ - if (ruler_open_wr_sock(argv[1]) < 0) - exit(1); - - inch = ruler_config_in(argv[2]); - if (inch < 0) - exit(1); - - actions = ruler_build_actions(argc - 3, argv + 3); - if (!actions) - exit(1); - - while(1) { - if (ruler_wait_event(inch, &ts) < 0) - exit(1); - if (ruler_run_actions(argc - 3, &ts, actions) < 0) - exit(1); - } - exit(0); -}