Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
S
Simple PCIe FMC carrier SPEC - Software
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
3
Issues
3
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Projects
Simple PCIe FMC carrier SPEC - Software
Commits
ac097472
Commit
ac097472
authored
Apr 24, 2019
by
Miguel Jimenez Lopez
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
tools: Remove DIO and NIC tools.
parent
a67dc039
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
0 additions
and
1484 deletions
+0
-1484
Makefile
tools/Makefile
+0
-2
stamp-frame.c
tools/stamp-frame.c
+0
-470
wr-dio-agent.c
tools/wr-dio-agent.c
+0
-157
wr-dio-cmd.c
tools/wr-dio-cmd.c
+0
-389
wr-dio-pps.c
tools/wr-dio-pps.c
+0
-126
wr-dio-ruler.c
tools/wr-dio-ruler.c
+0
-340
No files found.
tools/Makefile
View file @
ac097472
...
...
@@ -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)
...
...
tools/stamp-frame.c
deleted
100644 → 0
View file @
a67dc039
/*
* Copyright (C) 2010,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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netpacket/packet.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <arpa/inet.h>
#include "net_tstamp.h"
/* Actually, <linux/net_tstamp.h> */
#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'
);
}
/* FIX<E: Check that the actual data is what we sent */
__collect_data
(
&
msg
,
tstamp
);
return
ret
;
}
ssize_t
recv_and_stamp
(
int
sock
,
void
*
buf
,
size_t
len
,
int
flags
,
struct
ts_data
*
tstamp
)
{
int
ret
;
struct
msghdr
msg
;
struct
iovec
entry
;
struct
sockaddr_ll
from_addr
;
struct
{
struct
cmsghdr
cm
;
char
control
[
512
];
}
control
;
if
(
0
)
{
/* we can't really call recv, do it with cmsg alone */
ret
=
recv
(
sock
,
buf
,
len
,
flags
);
}
else
{
memset
(
&
msg
,
0
,
sizeof
(
msg
));
msg
.
msg_iov
=
&
entry
;
msg
.
msg_iovlen
=
1
;
entry
.
iov_base
=
buf
;
entry
.
iov_len
=
len
;
msg
.
msg_name
=
(
caddr_t
)
&
from_addr
;
msg
.
msg_namelen
=
sizeof
(
from_addr
);
msg
.
msg_control
=
&
control
;
msg
.
msg_controllen
=
sizeof
(
control
);
ret
=
recvmsg
(
sock
,
&
msg
,
0
);
if
(
ret
<
0
)
return
ret
;
if
(
getenv
(
"STAMP_VERBOSE"
))
{
int
b
;
printf
(
"recv %i ="
,
ret
);
for
(
b
=
0
;
b
<
ret
&&
b
<
20
;
b
++
)
printf
(
" %02x"
,
((
char
*
)
buf
)[
b
]
&
0xff
);
putchar
(
'\n'
);
}
__collect_data
(
&
msg
,
tstamp
);
}
return
ret
;
}
/* Add and subtract timespec */
void
ts_add
(
struct
timespec
*
t1
,
struct
timespec
*
t2
)
{
t1
->
tv_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] <ifname> [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
);
}
tools/wr-dio-agent.c
deleted
100644 → 0
View file @
a67dc039
/*
* 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"
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 <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
;
}
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] <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 %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
);
}
tools/wr-dio-cmd.c
deleted
100644 → 0
View file @
a67dc039
/*
* 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.
*/
#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"
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 <channel> <duration> <when> "
"[<period> <count>]
\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
;
}