Commit 95b2b969 authored by Alessandro Rubini's avatar Alessandro Rubini

tools: add wr-dio-agent

Signed-off-by: Alessandro Rubini's avatarAlessandro Rubini <rubini@gnudd.com>
parent 64739dd8
......@@ -6,7 +6,7 @@ LIB = libspec.a
LIBOBJ = speclib.o loader-ll.o
PROGS = spec-cl spec-fwloader spec-vuart specmem
PROGS += wr-dio-cmd wr-dio-pps wr-dio-ruler
PROGS += wr-dio-cmd wr-dio-pps wr-dio-agent wr-dio-ruler
all: $(LIB) $(PROGS)
......
/*
* Copyright (C) 2012 CERN (www.cern.ch)
* Author: Alessandro Rubini <rubini@gnudd.com>
*
* 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 <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/if_ether.h>
#include <net/if.h>
#include <netpacket/packet.h>
#include "wr_nic/wr-nic.h"
#include "wr-dio.h"
#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 <TAB> 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;
}
/* 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) {
fprintf(stderr, "%s: Use \"%s <wr-if>\"\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 %i)\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);
}
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