Commit 2801106b authored by Aurelio Colosimo's avatar Aurelio Colosimo

code fromt ptp-proposal version 56d97349

code was pruned from specific "ptp-proposal" protocol and the
skeleton of IEEE-1588 states was made. Next step is to insert,
step by step, the structs defined in ptpd. Still something needs
to be removed or renamed, but this should be a fair starting point.
parents
*.map*
*.o
*.a
pproto.bin
*.patch
This diff is collapsed.
This diff is collapsed.
#!/bin/sh
# This trivially compiles all known-good configurations
function build_one () {
make -s clean
echo "####################"
echo "Build for " "$1"
make -s -k $2
test -f pproto.o && size pproto.o
test -f pproto && size pproto
}
function build_diags () {
build_one "arch \"$ARCH\", ext \"$PROTO_EXT\", no diag"
build_one "arch \"$ARCH\", ext \"$PROTO_EXT\", mini diag" HAS_DIAG=y
build_one "arch \"$ARCH\", ext \"$PROTO_EXT\", full diag" HAS_FULL_DIAG=y
}
function build_ext () {
unset PROTO_EXT
build_diags
#export PROTO_EXT=one
#build_diags
}
for var in HAS_DIAG HAS_FULL_DIAG CROSS_COMPILE ARCH; do
unset $var
done
# Build for default ARCH first
unset ARCH
build_ext
# Finally, loop over all archs, using our local names for compilers
PREFIX_bare_linux=""
PREFIX_spec="/opt/gcc-lm32/bin/lm32-elf-"
for a in bare-linux spec; do
export ARCH=$a
ARCH_=""
eval export CROSS_COMPILE="\${PREFIX_$(echo $ARCH | sed 's/-/_/g')}"
build_ext
done
#
# Alessandro Rubini for CERN, 2011 -- public domain
#
# classic cross-compilation tool-set
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
CC = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
# Instead of repeating "proto-daemon" over and over, bless it TARGET
TARGET = pproto
# The main target is the big object file.
all: $(TARGET).o
# CFLAGS to use. Both this Makefile (later) and app-makefile may grow CFLAGS
CFLAGS += -Wall -O2 -ggdb -Iinclude
# to avoid ifdef as much as possible, I use the kernel trick for OBJ variables
OBJ-y := state-machine.o
# include diagnostic objects
include diag/Makefile
# proto-standard is always included
include proto-standard/Makefile
# including the extension Makefile, if an extension is there
ifdef PROTO_EXT
include proto-ext-$(PROTO_EXT)/Makefile
endif
# Include arch code, the default is hosted GNU/Linux stuff
# we need this -I so <arch/endianness.h> can be found
ARCH ?= gnu-linux
CFLAGS += -Iarch-$(ARCH)/include
include arch-$(ARCH)/Makefile
# And this is the rule to build our target.o file. The architecture may
# build more stuff. Please note that ./MAKEALL looks for $(TARGET)
# (i.e., the ELF which is either the output or the input to objcopy -O binary)
#
# The object only depends on OBJ-y because each subdirs added needed
# libraries: see proto-standard/Makefile as an example.
$(TARGET).o: $(OBJ-y)
$(LD) -Map $(TARGET).map1 -r -o $@ $(OBJ-y) $(LIBS)
# Finally, "make clean" is expected to work
clean:
rm -f $$(find . -name '*.[oa]') *.bin $(TARGET) *~ $(TARGET).map*
# Alessandro Rubini for CERN, 2011 -- public domain
CFLAGS += -ffreestanding -Os
ARCH_LDFLAGS = -nostdlib -static -T $(ARCH).lds
# All files are under A (short for ARCH): I'm lazy
A := arch-$(ARCH)
LIBARCH := $A/libarch.a
OBJ-libarch := $A/bare-startup.o \
$A/main-loop.o \
$A/bare-socket.o \
$A/bare-io.o \
$A/syscalls.o
$(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_instance() ).
$(TARGET): $(TARGET).o $A/crt0.o $(LIBARCH)
$(CC) -Wl,-Map,$(TARGET).map2 $(ARCH_LDFLAGS) -o $@ $A/crt0.o \
$(TARGET).o -L$A -larch -L$D -lstd
/*
* Alessandro Rubini for CERN, 2011 -- public domain
*/
#include <pproto/pproto.h>
#include "bare-linux.h"
void pp_puts(const char *s)
{
sys_write(0, s, pp_strnlen(s, 300));
}
int pp_strnlen(const char *s, int maxlen)
{
int len = 0;
while (*(s++)) len++;
return len;
}
void *pp_memcpy(void * dest, const void *src, int count)
{
/* from u-boot-1.1.2 */
char *tmp = (char *) dest, *s = (char *) src;
while (count--)
*tmp++ = *s++;
return dest;
}
void pp_get_stamp(uint32_t *sptr)
{
*sptr = htonl(sys_time(0));
}
/* What follows has no prefix because it's only used by arch code */
char *strcpy(char *dest, const char *src)
{
/* from u-boot-1.1.2 */
char *tmp = dest;
while ((*dest++ = *src++) != '\0')
/* nothing */;
return tmp;
}
void *memset(void *s, int c, int count)
{
/* from u-boot-1.1.2 */
char *xs = (char *) s;
while (count--)
*xs++ = c;
return s;
}
void *memcpy(void *dest, const void *src, int count)
{
/* from u-boot-1.1.2 */
char *tmp = (char *) dest, *s = (char *) src;
while (count--)
*tmp++ = *s++;
return dest;
}
/*
* Alessandro Rubini for CERN, 2011 -- GNU LGPL v2.1 or later
*/
/*
* These are the functions provided by the various bare files
*/
extern int bare_open_ch(struct pp_instance *ppi, char *name);
extern int bare_recv_packet(struct pp_instance *ppi, void *pkt, int len);
extern int bare_send_packet(struct pp_instance *ppi, void *pkt, int len);
extern void bare_main_loop(struct pp_instance *ppi);
/* basics */
extern void *memset(void *s, int c, int count);
extern char *strcpy(char *dest, const char *src);
extern void *memcpy(void *dest, const void *src, int count);
/* syscalls */
struct bare_sockaddr;
extern int sys_write(int fd, const void *buf, int count);
extern void sys_exit(int exitval);
extern int sys_time(int tz);
extern int sys_select(int max, void *in, void *out, void *exc, void *tout);
extern int sys_ioctl(int fd, int cmd, void *arg);
extern int sys_socket(int domain, int type, int proto);
extern int sys_bind(int fd, const struct bare_sockaddr *addr, int addrlen);
extern int sys_recv(int fd, void *pkt, int plen, int flags);
extern int sys_send(int fd, void *pkt, int plen, int flags);
extern int bare_errno;
/* structures passed to syscalls */
#define IFNAMSIZ 16
struct bare_sockaddr {
uint16_t sa_family; /* address family, AF_xxx */
char sa_data[14]; /* 14 bytes of protocol address */
};
struct bare_ifreq {
union
{
char ifrn_name[IFNAMSIZ];
} ifr_ifrn;
union {
struct bare_sockaddr ifru_hwaddr;
int index;
} ifr_ifru;
};
struct bare_sockaddr_ll {
unsigned short int sll_family;
unsigned short int sll_protocol;
int sll_ifindex;
unsigned short int sll_hatype;
unsigned char sll_pkttype;
unsigned char sll_halen;
unsigned char sll_addr[8];
};
#define SIOCGIFINDEX 0x8933
#define SIOCGIFHWADDR 0x8927
/* other network stuff, bah.... */
struct bare_ethhdr {
unsigned char h_dest[6];
unsigned char h_source[6];
uint16_t h_proto;
} __attribute__((packed));
OUTPUT_FORMAT("elf32-i386")
OUTPUT_ARCH(i386)
ENTRY(_pproto_start)
SECTIONS
{
. = 0x10000000; /* A random address, non-standard by choice*/
_pproto_start = .;
.text : {
*(.boot)
*(.text)
}
.rodata : { *(.rodata) }
.data : { *(.data) }
.bss : {
. = ALIGN(16);
__bss_start = .;
*(.bss);
. = ALIGN(16);
__bss_end = .;
}
}
/*
* Alessandro Rubini for CERN, 2011 -- public domain
*/
/* Socket interface for bare Linux */
#include <pproto/pproto.h>
#include "bare-linux.h"
/* Receive and send is trivial */
int bare_recv_packet(struct pp_instance *ppi, void *pkt, int len)
{
return sys_recv(ppi->ch.fd, pkt, len, 0);
}
int bare_send_packet(struct pp_instance *ppi, void *pkt, int len)
{
return sys_send(ppi->ch.fd, pkt, len, 0);
}
int pp_recv_packet(struct pp_instance *ppi, void *pkt, int len)
__attribute__((alias("bare_recv_packet")));
int pp_send_packet(struct pp_instance *ppi, void *pkt, int len)
__attribute__((alias("bare_send_packet")));
#define PF_PACKET 17
#define SOCK_RAW 3
/* To open a channel we must bind to an interface and so on */
int bare_open_ch(struct pp_instance *ppi, char *ifname)
{
int sock, iindex;
struct bare_ifreq ifr;
struct bare_sockaddr_ll addr;
/* open socket */
sock = sys_socket(PF_PACKET, SOCK_RAW, PP_PROTO_NR);
if (sock < 0) {
pp_diag_error(ppi, bare_errno);
pp_diag_fatal(ppi, "socket()", "");
}
/* hw interface information */
memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_ifrn.ifrn_name, ifname);
if (sys_ioctl(sock, SIOCGIFINDEX, &ifr) < 0) {
pp_diag_error(ppi, bare_errno);
pp_diag_fatal(ppi, "ioctl(GIFINDEX)", "");
}
iindex = ifr.ifr_ifru.index;
if (sys_ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
pp_diag_error(ppi, bare_errno);
pp_diag_fatal(ppi, "ioctl(GIFHWADDR)", "");
}
memcpy(ppi->ch.addr, ifr.ifr_ifru.ifru_hwaddr.sa_data, 6);
/* bind and setsockopt */
memset(&addr, 0, sizeof(addr));
addr.sll_family = PF_PACKET;
addr.sll_protocol = htons(PP_PROTO_NR);
addr.sll_ifindex = iindex;
if (sys_bind(sock, (struct bare_sockaddr *)&addr, sizeof(addr)) < 0) {
pp_diag_error(ppi, bare_errno);
pp_diag_fatal(ppi, "bind", "");
}
ppi->ch.fd = sock;
return 0;
}
/*
* Alessandro Rubini for CERN, 2011 -- GNU LGPL v2.1 or later
*/
/*
* This is the startup thing for "freestanding" stuff under Linux.
* It must also clear the BSS as I'm too lazy to do that in asm
*/
#include <pproto/pproto.h>
#include "bare-linux.h"
extern int __bss_start, __bss_end;
void pproto_clear_bss(void)
{
int *ptr;
for (ptr = &__bss_start; ptr < &__bss_end; ptr++)
*ptr = 0;
}
static struct pp_instance ppi_static;
void pproto_main(void)
{
struct pp_instance *ppi = &ppi_static; /* no malloc, one instance */
pp_puts("bare: starting. Compiled on " __DATE__ "\n");
if (bare_open_ch(ppi, "eth0")) {
pp_diag_error(ppi, bare_errno);
pp_diag_fatal(ppi, "open_ch", "");
}
pp_open_instance(ppi,0);
bare_main_loop(ppi);
}
/*
* A stupid crt0.S for "freestanding" stuff on gnu/linux
* Alessandro Rubini for CERN, 2011 -- GNU GPL v2 or later
*/
.section .boot, "ax"
.extern pproto_main
call pproto_clear_bss /* In C, lazy me */
call pproto_main
.end
\ No newline at end of file
#ifndef __ARCH_H__
#define __ARCH_H__
/* Architecture-specific defines, included by top-level stuff */
/* please note that these have multiple evaluation of the argument */
#define htons(x) __bswap_16(x)
#define __bswap_16(x) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))
#define htonl(x) __bswap_32(x)
#define __bswap_32(x) ( \
(((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \
(((uint32_t)(x) & (uint32_t)0x0000ff00UL) << 8) | \
(((uint32_t)(x) & (uint32_t)0x00ff0000UL) >> 8) | \
(((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24))
#define ntohs htons
#define ntohl htonl
#endif /* __ARCH_H__ */
/*
* Alessandro Rubini for CERN, 2011 -- GNU LGPL v2.1 or later
*/
/*
* This is the main loop for "freestanding" stuff under Linux.
*/
#include <pproto/pproto.h>
#include "bare-linux.h"
/* Define other hackish stuff */
typedef struct {unsigned long bits[1024/32];} bare_fd_set;
#define FD_ZERO(p) memset(p, 0, sizeof(p))
#define FD_SET(bit, p) ((p)->bits[0] |= (1 << (bit)))
struct bare_timeval {unsigned long tv_sec; unsigned long tv_usec;};
#define NULL 0
void bare_main_loop(struct pp_instance *ppi)
{
int delay_ms;
/*
* The main loop here is based on select. While we are not
* doing anything else but the protocol, this allows extra stuff
* to fit.
*/
delay_ms = pp_state_machine(ppi, NULL, 0);
while (1) {
bare_fd_set set;
int i;
struct bare_timeval tv;
unsigned char packet[1500];
/* Wait for a packet or for the timeout */
tv.tv_sec = delay_ms / 1000;
tv.tv_usec = (delay_ms % 1000) * 1000;
again:
FD_ZERO(&set);
FD_SET(ppi->ch.fd, &set);
i = sys_select(ppi->ch.fd + 1, &set, NULL, NULL, &tv);
if (i < 0 && bare_errno != 4 /* EINTR */)
sys_exit(__LINE__);
if (i < 0)
continue;
if (i == 0) {
delay_ms = pp_state_machine(ppi, NULL, 0);
continue;
}
/*
* We got a packet. If it's not ours, continue consuming
* the pending timeout
*/
i = bare_recv_packet(ppi, packet, sizeof(packet));
/* FIXME
if (i < sizeof(struct pp_packet))
goto again;
*/
/* Warning: PP_PROTO_NR is endian-agnostic by design */
if ( ((struct bare_ethhdr *)packet)->h_proto
!= htons(PP_PROTO_NR))
goto again;
delay_ms = pp_state_machine(ppi, packet, i);
}
}
/*
* Alessandro Rubini for CERN, 2011 -- public domain
*/
#include <asm/unistd.h>
#include <pproto/pproto.h>
#include "bare-linux.h"
#include "syscalls.h"
int bare_errno;
struct sel_arg_struct {
unsigned long n;
void *inp, *outp, *exp;
void *tvp;
};
/*
* The following lines use defines from Torvalds (linux-2.4.0: see syscalls.h)
*/
_syscall3(int, write, int, fd, const void *, buf, int, count)
_syscall1(int, exit, int, exitcode)
_syscall1(int, time, void *, tz)
_syscall3(int, ioctl, int, fd, int, cmd, void *, arg)
_syscall1(int, select, struct sel_arg_struct *, as)
static _syscall2(int, socketcall, int, call, unsigned long *, args)
/*
* In the bare arch I'd better use sys_ prefixed names
*/
int sys_write(int fd, const void *buf, int count)
__attribute__((alias("write")));
void sys_exit(int exitval)
__attribute__((alias("exit")));
int sys_time(int tz)
__attribute__((alias("time")));
int sys_ioctl(int fd, int cmd, void *arg)
__attribute__((alias("ioctl")));
static struct sel_arg_struct as; /* declared as local, it won't work */
int sys_select(int max, void *in, void *out, void *exc, void *tout)
{
as.n = max;
as.inp = in;
as.outp = out;
as.exp = exc;
as.tvp = tout;
return select(&as);
}
/* i386 has the socketcall thing. Bah! */
#define SYS_SOCKET 1 /* sys_socket(2) */
#define SYS_BIND 2 /* sys_bind(2) */
#define SYS_CONNECT 3 /* sys_connect(2) */
#define SYS_LISTEN 4 /* sys_listen(2) */
#define SYS_ACCEPT 5 /* sys_accept(2) */
#define SYS_GETSOCKNAME 6 /* sys_getsockname(2) */
#define SYS_GETPEERNAME 7 /* sys_getpeername(2) */
#define SYS_SOCKETPAIR 8 /* sys_socketpair(2) */
#define SYS_SEND 9 /* sys_send(2) */
#define SYS_RECV 10 /* sys_recv(2) */
#define SYS_SENDTO 11 /* sys_sendto(2) */
#define SYS_RECVFROM 12 /* sys_recvfrom(2) */
#define SYS_SHUTDOWN 13 /* sys_shutdown(2) */
#define SYS_SETSOCKOPT 14 /* sys_setsockopt(2) */
#define SYS_GETSOCKOPT 15 /* sys_getsockopt(2) */
#define SYS_SENDMSG 16 /* sys_sendmsg(2) */
#define SYS_RECVMSG 17 /* sys_recvmsg(2) */
#define SYS_PACCEPT 18 /* sys_paccept(2) */
static unsigned long args[4];
int sys_socket(int domain, int type, int proto)
{
/*
* Strangely, this is not working for me:
* unsigned long args[3] = {domain, type, proto};
* So let's use an external thing. Who knows why...
*/
args[0] = domain;
args[1] = type;
args[2] = proto;
return socketcall(SYS_SOCKET, args);
}
int sys_bind(int fd, const struct bare_sockaddr *addr, int addrlen)
{
args[0] = fd;
args[1] = (unsigned long)addr;
args[2] = addrlen;
return socketcall(SYS_BIND, args);
}
int sys_recv(int fd, void *pkt, int plen, int flags)
{
args[0] = fd;
args[1] = (unsigned long)pkt;
args[2] = plen;
args[3] = flags;
return socketcall(SYS_RECV, args);
}
int sys_send(int fd, void *pkt, int plen, int flags)
{
args[0] = fd;
args[1] = (unsigned long)pkt;
args[2] = plen;
args[3] = flags;
return socketcall(SYS_SEND, args);
}
/*
* From: linux-2.4.0::include/asm-i386/unistd.h
*/
extern int bare_errno;
/*
* user-visible error numbers are in the range -1 - -4096
*/
#define __syscall_return(type, res) \
do { \
if ((unsigned long)(res) >= (unsigned long)(-4096)) { \
bare_errno = -(res); \
res = -1; \
} \
return (type) (res); \
} while (0)
/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
#define _syscall0(type,name) \
type name(void) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name)); \
__syscall_return(type,__res); \
}
#define _syscall1(type,name,type1,arg1) \
type name(type1 arg1) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(arg1))); \
__syscall_return(type,__res); \
}
#define _syscall2(type,name,type1,arg1,type2,arg2) \
type name(type1 arg1,type2 arg2) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2))); \
__syscall_return(type,__res); \
}
#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
type name(type1 arg1,type2 arg2,type3 arg3) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
"d" ((long)(arg3))); \
__syscall_return(type,__res); \
}
#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
"d" ((long)(arg3)),"S" ((long)(arg4))); \
__syscall_return(type,__res); \
}
#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
type5,arg5) \
type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
"d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5))); \
__syscall_return(type,__res); \
}
#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
type5,arg5,type6,arg6) \
type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \
{ \
long __res; \
__asm__ volatile ("push %%ebp ; movl %%eax,%%ebp ; movl %1,%%eax ; int $0x80 ; pop %%ebp" \
: "=a" (__res) \
: "i" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
"d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)), \
"0" ((long)(arg6))); \
__syscall_return(type,__res); \
}
# Alessandro Rubini for CERN, 2011 -- public domain
# All files are under A (short for ARCH): I'm lazy
A := arch-$(ARCH)
LIBARCH := $A/libarch.a
OBJ-libarch := $A/posix-startup.o \
$A/main-loop.o \
$A/posix-socket.o \
$A/posix-io.o
$(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_instance() ).
$(TARGET): $(TARGET).o $(LIBARCH)
$(CC) -Wl,-Map,$(TARGET).map2 -o $@ $(TARGET).o \
-L$A -larch -L$D -lstd
#ifndef __ARCH_H__
#define __ARCH_H__
/* Architecture-specific defines, included by top-level stuff */
#include <arpa/inet.h> /* ntohs etc */
#endif /* __ARCH_H__ */
/*
* Alessandro Rubini for CERN, 2011 -- public domain
*/
/*
* This is the main loop for posix stuff.
*/
#include <stdlib.h>
#include <errno.h>
#include <sys/select.h>
#include <linux/if_ether.h>
#include <pproto/pproto.h>
#include <pproto/diag.h>
#include "posix.h"
void posix_main_loop(struct pp_instance *ppi)
{
int delay_ms;
/*
* The main loop here is based on select. While we are not
* doing anything else but the protocol, this allows extra stuff
* to fit.
*/
delay_ms = pp_state_machine(ppi, NULL, 0);
while (1) {
fd_set set;
int i;
struct timeval tv;
unsigned char packet[1500];
/* Wait for a packet or for the timeout */
tv.tv_sec = delay_ms / 1000;
tv.tv_usec = (delay_ms % 1000) * 1000;
again:
FD_ZERO(&set);
FD_SET(ppi->ch.fd, &set);
i = select(ppi->ch.fd + 1, &set, NULL, NULL, &tv);
if (i < 0 && errno != EINTR)
exit(__LINE__);
if (i < 0)
continue;
if (i == 0) {
delay_ms = pp_state_machine(ppi, NULL, 0);
continue;
}
/*
* We got a packet. If it's not ours, continue consuming
* the pending timeout
*/
i = posix_recv_packet(ppi, packet, sizeof(packet));
/* FIXME
if (i < sizeof(struct pp_packet))
goto again;
*/
/* Warning: PP_PROTO_NR is endian-agnostic by design */
if ( ((struct ethhdr *)packet)->h_proto != htons(PP_PROTO_NR))
goto again;
delay_ms = pp_state_machine(ppi, packet, i);
}
}
/*
* Alessandro Rubini for CERN, 2011 -- public domain
*/
#define _GNU_SOURCE /* for strnlen */
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <pproto/pproto.h>
void pp_puts(const char *s)
{
fputs(s, stdout);
}
int pp_strnlen(const char *s, int maxlen)
{
return strnlen(s, maxlen);
}
void *pp_memcpy(void *d, const void *s, int count)
{
return memcpy(d, s, count);
}
void pp_get_stamp(uint32_t *sptr)
{
*sptr = htonl(time(NULL));
}
/*
* Alessandro Rubini for CERN, 2011 -- public domain
*/
/* Socket interface for GNU/Linux (and most likely other posix systems */
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netpacket/packet.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <pproto/pproto.h>
#include <pproto/diag.h>
#include "posix.h"
/* Receive and send is trivial */
int posix_recv_packet(struct pp_instance *ppi, void *pkt, int len)
{
return recv(ppi->ch.fd, pkt, len, 0);
}
int posix_send_packet(struct pp_instance *ppi, void *pkt, int len)
{
return send(ppi->ch.fd, pkt, len, 0);
}
int pp_recv_packet(struct pp_instance *ppi, void *pkt, int len)
__attribute__((alias("posix_recv_packet")));
int pp_send_packet(struct pp_instance *ppi, void *pkt, int len)
__attribute__((alias("posix_send_packet")));
/* To open a channel we must bind to an interface and so on */
int posix_open_ch(struct pp_instance *ppi, char *ifname)
{
int sock, iindex;
struct ifreq ifr;
struct sockaddr_ll addr;
/* open socket */
sock = socket(PF_PACKET, SOCK_RAW, PP_PROTO_NR);
if (sock < 0) {
pp_diag_error_str2(ppi, "socket()", strerror(errno));
return -1;
}
/* hw interface information */
memset (&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, ifname);
if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) {
pp_diag_error_str2(ppi, "SIOCGIFINDEX", strerror(errno));
close(sock);
return -1;
}
iindex = ifr.ifr_ifindex;
if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
pp_diag_error_str2(ppi, "SIOCGIFHWADDR", strerror(errno));
close(sock);
return -1;
}
memcpy(ppi->ch.addr, ifr.ifr_hwaddr.sa_data, 6);
/* bind and setsockopt */
memset(&addr, 0, sizeof(addr));
addr.sll_family = AF_PACKET;
addr.sll_protocol = htons(PP_PROTO_NR);
addr.sll_ifindex = iindex;
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
pp_diag_error_str2(ppi, "bind", strerror(errno));
close(sock);
return -1;
}
ppi->ch.fd = sock;
return 0;
}
/*
* Inits all the network stuff
* TODO: check with the posix_open_ch, maybe it's the same
*/
int posix_net_init(struct pp_instance *ppi)
{
return 0;
}
int pp_net_init(struct pp_instance *ppi)
__attribute__((alias("posix_net_init")));
/*
* 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 <stdlib.h>
#include <string.h>
#include <errno.h>
#include <pproto/pproto.h>
#include <pproto/diag.h>
#include "posix.h"
int main(int argc, char **argv)
{
struct pp_instance *ppi;
char *ifname;
/*
* Here, we may fork or whatever for each interface.
* To keep things simple, just run one thing for one interface.
*/
ifname = getenv("PPROTO_IF");
if (!ifname) ifname = "eth0";
/* We are hosted, so we can allocate */
ppi = calloc(1, sizeof(*ppi));
if (!ppi)
exit(__LINE__);
if (posix_open_ch(ppi, ifname)) {
pp_diag_fatal(ppi, "open_ch", strerror(errno));
}
pp_open_instance(ppi, NULL);
pp_parse_cmdline(ppi,argc,argv);
posix_main_loop(ppi);
return 0; /* never reached */
}
/*
* Alessandro Rubini for CERN, 2011 -- public domain
*/
/*
* These are the functions provided by the various posix files
*/
extern int posix_net_init(struct pp_instance *ppi);
extern int posix_open_ch(struct pp_instance *ppi, char *name);
extern int posix_recv_packet(struct pp_instance *ppi, void *pkt, int len);
extern int posix_send_packet(struct pp_instance *ppi, void *pkt, int len);
extern void posix_main_loop(struct pp_instance *ppi);
# Alessandro Rubini for CERN, 2011 -- public domain
CFLAGS += -ffreestanding -Os \
-ffunction-sections -fdata-sections \
-mmultiply-enabled -mbarrel-shift-enabled
ARCH_LDFLAGS = -nostdlib -static -T $(ARCH).lds
# All files are under A (short for ARCH): I'm lazy
A := arch-$(ARCH)
LIBARCH := $A/libarch.a
OBJ-libarch := $A/spec-startup.o \
$A/main-loop.o \
$A/spec-socket.o \
$A/spec-io.o \
$A/dev/uart.o \
$A/dev/timer.o \
$A/dev/endpoint.o \
$A/dev/minic.o
$(LIBARCH): $(OBJ-libarch)
$(AR) r $@ $^
all: $(TARGET) $(TARGET).bin
# to build the target, we need -lstd again, in case we call functions that
# were not selected yet (e.g., pp_open_instance() ).
$(TARGET): $(TARGET).o $A/crt0.o $(LIBARCH)
$(CC) -Wl,-Map,$(TARGET).map2 $(ARCH_LDFLAGS) -o $@ $A/crt0.o \
$(TARGET).o -L$A -larch -L$D -lstd
$(TARGET).bin: $(TARGET)
$(OBJCOPY) -O binary $^ $@
/****************************************************************************
**
** Name: crt0ram.S
**
** Description:
** Implements boot-code that calls LatticeDDInit (that calls main())
** Implements exception handlers (actually, redirectors)
**
** $Revision: $
**
** Disclaimer:
**
** This source code is intended as a design reference which
** illustrates how these types of functions can be implemented. It
** is the user's responsibility to verify their design for
** consistency and functionality through the use of formal
** verification methods. Lattice Semiconductor provides no warranty
** regarding the use or functionality of this code.
**
** --------------------------------------------------------------------
**
** Lattice Semiconductor Corporation
** 5555 NE Moore Court
** Hillsboro, OR 97214
** U.S.A
**
** TEL: 1-800-Lattice (USA and Canada)
** (503)268-8001 (other locations)
**
** web: http://www.latticesemi.com
** email: techsupport@latticesemi.com
**
** --------------------------------------------------------------------------
**
** Change History (Latest changes on top)
**
** Ver Date Description
** --------------------------------------------------------------------------
** 3.8 Apr-15-2011 Added __MICO_USER_<handler>_HANDLER__ preprocessor to
** allow customers to implement their own handlers for:
** DATA_ABORT, INST_ABORT
**
** 3.1 Jun-18-2008 Added __MICO_NO_INTERRUPTS__ preprocessor
** option to exclude invoking MicoISRHandler
** to reduce code-size in apps that don't use
** interrupts
**
** 3.0 Mar-25-2008 Added Header
**
**---------------------------------------------------------------------------
*****************************************************************************/
/*
* LatticeMico32 C startup code.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* From include/sys/signal.h */
#define SIGINT 2 /* interrupt */
#define SIGTRAP 5 /* trace trap */
#define SIGFPE 8 /* arithmetic exception */
#define SIGSEGV 11 /* segmentation violation */
//#define MICO32_FULL_CONTEXT_SAVE_RESTORE
/* Exception handlers - Must be 32 bytes long. */
.section .boot, "ax", @progbits
.global _start
_start:
.global _reset_handler
.type _reset_handler, @function
_reset_handler:
xor r0, r0, r0
wcsr IE, r0
wcsr IM, r0
mvhi r1, hi(_reset_handler)
ori r1, r1, lo(_reset_handler)
wcsr EBA, r1
calli _crt0
nop
.size _reset_handler, .-_reset_handler
.extern _irq_entry
.org 0xc0
.global _interrupt_handler
.type _interrupt_handler, @function
_interrupt_handler:
sw (sp+0), ra
calli _save_all
mvi r1, SIGINT
#ifndef __MICO_NO_INTERRUPTS__
calli _irq_entry
#else
wcsr IE, r0
#endif
bi _restore_all_and_return
nop
nop
nop
.org 0x100
.global _crt0
.type _crt0, @function
_crt0:
/* Clear r0 */
xor r0, r0, r0
/* Setup stack and global pointer */
mvhi sp, hi(_fstack)
ori sp, sp, lo(_fstack)
mvhi gp, hi(_gp)
ori gp, gp, lo(_gp)
mvhi r1, hi(_fbss)
ori r1, r1, lo(_fbss)
mvi r2, 0
mvhi r3, hi(_ebss)
ori r3, r3, lo(_ebss)
sub r3, r3, r1
calli memset
mvi r1, 0
mvi r2, 0
mvi r3, 0
calli main
loopf:
bi loopf
.global _save_all
.type _save_all, @function
_save_all:
#ifdef MICO32_FULL_CONTEXT_SAVE_RESTORE
addi sp, sp, -128
#else
addi sp, sp, -60
#endif
sw (sp+4), r1
sw (sp+8), r2
sw (sp+12), r3
sw (sp+16), r4
sw (sp+20), r5
sw (sp+24), r6
sw (sp+28), r7
sw (sp+32), r8
sw (sp+36), r9
sw (sp+40), r10
#ifdef MICO32_FULL_CONTEXT_SAVE_RESTORE
sw (sp+44), r11
sw (sp+48), r12
sw (sp+52), r13
sw (sp+56), r14
sw (sp+60), r15
sw (sp+64), r16
sw (sp+68), r17
sw (sp+72), r18
sw (sp+76), r19
sw (sp+80), r20
sw (sp+84), r21
sw (sp+88), r22
sw (sp+92), r23
sw (sp+96), r24
sw (sp+100), r25
sw (sp+104), r26
sw (sp+108), r27
sw (sp+120), ea
sw (sp+124), ba
/* ra and sp need special handling, as they have been modified */
lw r1, (sp+128)
sw (sp+116), r1
mv r1, sp
addi r1, r1, 128
sw (sp+112), r1
#else
sw (sp+52), ea
sw (sp+56), ba
/* ra and sp need special handling, as they have been modified */
lw r1, (sp+60)
sw (sp+48), r1
mv r1, sp
addi r1, r1, 60
sw (sp+44), r1
#endif
// xor r1, r1, r1
// wcsr ie, r1
ret
.size _save_all, .-_save_all
.global _restore_all_and_return
.type _restore_all_and_return, @function
/* Restore all registers and return from exception */
_restore_all_and_return:
// addi r1, r0, 2
// wcsr ie, r1
lw r1, (sp+4)
lw r2, (sp+8)
lw r3, (sp+12)
lw r4, (sp+16)
lw r5, (sp+20)
lw r6, (sp+24)
lw r7, (sp+28)
lw r8, (sp+32)
lw r9, (sp+36)
lw r10, (sp+40)
#ifdef MICO32_FULL_CONTEXT_SAVE_RESTORE
lw r11, (sp+44)
lw r12, (sp+48)
lw r13, (sp+52)
lw r14, (sp+56)
lw r15, (sp+60)
lw r16, (sp+64)
lw r17, (sp+68)
lw r18, (sp+72)
lw r19, (sp+76)
lw r20, (sp+80)
lw r21, (sp+84)
lw r22, (sp+88)
lw r23, (sp+92)
lw r24, (sp+96)
lw r25, (sp+100)
lw r26, (sp+104)
lw r27, (sp+108)
lw ra, (sp+116)
lw ea, (sp+120)
lw ba, (sp+124)
/* Stack pointer must be restored last, in case it has been updated */
lw sp, (sp+112)
#else
lw ra, (sp+48)
lw ea, (sp+52)
lw ba, (sp+56)
/* Stack pointer must be restored last, in case it has been updated */
lw sp, (sp+44)
#endif
nop
eret
.size _restore_all_and_return, .-_restore_all_and_return
/*
* Copyright 2011 Tomasz Wlostowski <tomasz.wlostowski@cern.ch> for CERN
* Modified by Alessandro Rubini for ptp-proposal/proto
*
* GNU LGPL 2.1 or later versions
*/
#include <pproto/pproto.h>
#include "../spec.h"
#include <hw/endpoint_regs.h>
#include <hw/endpoint_mdio.h>
#define UIS_PER_SERIAL_BIT 800
static int autoneg_enabled;
static volatile struct EP_WB *EP = (volatile struct EP_WB *) BASE_EP;
/* functions for accessing PCS registers */
static uint16_t pcs_read(int location)
{
EP->MDIO_CR = EP_MDIO_CR_ADDR_W(location >> 2);
while ((EP->MDIO_SR & EP_MDIO_SR_READY) == 0);
return EP_MDIO_SR_RDATA_R(EP->MDIO_SR) & 0xffff;
}
static void pcs_write(int location,
int value)
{
EP->MDIO_CR = EP_MDIO_CR_ADDR_W(location >> 2)
| EP_MDIO_CR_DATA_W(value)
| EP_MDIO_CR_RW;
while ((EP->MDIO_SR & EP_MDIO_SR_READY) == 0);
}
static void set_mac_addr(uint8_t dev_addr[])
{
EP->MACL = ((uint32_t)dev_addr[2] << 24)
| ((uint32_t)dev_addr[3] << 16)
| ((uint32_t)dev_addr[4] << 8)
| ((uint32_t)dev_addr[5]);
EP->MACH = ((uint32_t)dev_addr[0] << 8)
| ((uint32_t)dev_addr[1]);
}
void get_mac_addr(uint8_t dev_addr[])
{
dev_addr[5] = (uint8_t)(EP->MACL & 0x000000ff);
dev_addr[4] = (uint8_t)(EP->MACL & 0x0000ff00) >> 8;
dev_addr[3] = (uint8_t)(EP->MACL & 0x00ff0000) >> 16;
dev_addr[2] = (uint8_t)(EP->MACL & 0xff000000) >> 24;
dev_addr[1] = (uint8_t)(EP->MACH & 0x000000ff);
dev_addr[0] = (uint8_t)(EP->MACH & 0x0000ff00) >> 8;
}
void ep_init(uint8_t mac_addr[])
{
set_mac_addr(mac_addr);
EP->ECR = 0;
EP->DMCR = EP_DMCR_EN | EP_DMCR_N_AVG_W(DMTD_AVG_SAMPLES);
EP->RFCR = 3 << EP_RFCR_QMODE_SHIFT;
EP->TSCR = EP_TSCR_EN_TXTS | EP_TSCR_EN_RXTS;
EP->FCR = 0;
}
int ep_enable(int enabled, int autoneg)
{
uint16_t mcr;
if(!enabled)
{
EP->ECR = 0;
return 0;
}
EP->ECR = EP_ECR_TX_EN_FRA | EP_ECR_RX_EN_FRA | EP_ECR_RST_CNT;
autoneg_enabled = autoneg;
#if 1
pcs_write(MDIO_REG_MCR, MDIO_MCR_PDOWN); /* reset the PHY */
spec_udelay(2000 * 1000);
pcs_write(MDIO_REG_MCR, 0); /* reset the PHY */
// pcs_write(MDIO_REG_MCR, MDIO_MCR_RESET); /* reset the PHY */
#endif
pcs_write(MDIO_REG_ADVERTISE, 0);
mcr = MDIO_MCR_SPEED1000_MASK | MDIO_MCR_FULLDPLX_MASK;
if(autoneg)
mcr |= MDIO_MCR_ANENABLE | MDIO_MCR_ANRESTART;
pcs_write(MDIO_REG_MCR, mcr);
return 0;
}
int ep_link_up()
{
uint16_t flags = MDIO_MSR_LSTATUS;
volatile uint16_t msr;
if(autoneg_enabled)
flags |= MDIO_MSR_ANEGCOMPLETE;
msr = pcs_read(MDIO_REG_MSR);
msr = pcs_read(MDIO_REG_MSR);
return (msr & flags) == flags ? 1 : 0;
}
int ep_get_deltas(uint32_t *delta_tx, uint32_t *delta_rx)
{
// mprintf("called ep_get_deltas()\n");
*delta_tx = 0;
*delta_rx = 15000 - 7000 + 195000 + 32000
+ UIS_PER_SERIAL_BIT
* MDIO_WR_SPEC_BSLIDE_R(pcs_read(MDIO_REG_WR_SPEC))
+ 2800 - 9000;
return 0;
}
void ep_show_counters()
{
int i;
for(i=0;i<16;i++)
TRACE_DEV("cntr%d = %d\n", i, (int)(EP->RMON_RAM[i]));
}
int ep_get_psval(int32_t *psval)
{
uint32_t val;
val = EP->DMSR;
if(val & EP_DMSR_PS_RDY)
*psval = EP_DMSR_PS_VAL_R(val);
else
*psval = 0;
return val & EP_DMSR_PS_RDY;
}
int ep_cal_pattern_enable()
{
uint32_t val;
val = pcs_read(MDIO_REG_WR_SPEC);
val |= MDIO_WR_SPEC_TX_CAL;
pcs_write(MDIO_REG_WR_SPEC, val);
return 0;
}
int ep_cal_pattern_disable()
{
uint32_t val;
val = pcs_read(MDIO_REG_WR_SPEC);
val &= (~MDIO_WR_SPEC_TX_CAL);
pcs_write(MDIO_REG_WR_SPEC, val);
return 0;
}
/*
* Copyright 2011 Tomasz Wlostowski <tomasz.wlostowski@cern.ch> for CERN
* Modified by Alessandro Rubini for ptp-proposal/proto
*
* GNU LGPL 2.1 or later versions
*/
#include <pproto/pproto.h>
#include "../spec.h"
//#include "pps_gen.h" /* for pps_gen_get_time() */
#include <hw/minic_regs.h>
#define MINIC_DMA_TX_BUF_SIZE 1024
#define MINIC_DMA_RX_BUF_SIZE 2048
#define MINIC_MTU 256
#define F_COUNTER_BITS 4
#define F_COUNTER_MASK ((1<<F_COUNTER_BITS)-1)
#define RX_DESC_VALID(d) ((d) & (1<<31) ? 1 : 0)
#define RX_DESC_ERROR(d) ((d) & (1<<30) ? 1 : 0)
#define RX_DESC_HAS_OOB(d) ((d) & (1<<29) ? 1 : 0)
#define RX_DESC_SIZE(d) (((d) & (1<<0) ? -1 : 0) + (d & 0xfffe))
#define TX_DESC_VALID (1<<31)
#define TX_DESC_WITH_OOB (1<<30)
#define TX_DESC_HAS_OWN_MAC (1<<28)
#define RX_OOB_SIZE 6
#define REFCLK_FREQ 125000000
#define ETH_HEADER_SIZE 14
/* extracts the values of TS rising and falling edge ctrs from desc. header */
#define EXPLODE_WR_TIMESTAMP(raw, rc, fc) \
rc = (raw) & 0xfffffff; \
fc = (raw >> 28) & 0xf;
static volatile uint32_t dma_tx_buf[MINIC_DMA_TX_BUF_SIZE / 4];
static volatile uint32_t dma_rx_buf[MINIC_DMA_RX_BUF_SIZE / 4];
struct wr_minic {
volatile uint32_t *rx_head, *rx_base;
uint32_t rx_avail, rx_size;
volatile uint32_t *tx_head, *tx_base;
uint32_t tx_avail, tx_size;
int synced;
int syncing_counters;
int iface_up;
int tx_count, rx_count;
uint32_t cur_rx_desc;
};
static struct wr_minic minic;
static inline void minic_writel(uint32_t reg,uint32_t data)
{
*(volatile uint32_t *) (BASE_MINIC + reg) = data;
}
static inline uint32_t minic_readl(uint32_t reg)
{
return *(volatile uint32_t *)(BASE_MINIC + reg);
}
static void minic_new_rx_buffer()
{
minic.rx_head = minic.rx_base;
minic_writel(MINIC_REG_MCR, 0);
minic_writel(MINIC_REG_RX_ADDR, (uint32_t) minic.rx_base);
minic_writel(MINIC_REG_RX_AVAIL, (minic.rx_size - MINIC_MTU) >> 2);
if (0) {
TRACE_DEV("Size : %d Avail: %d\n",
(int)minic.rx_size,
(int)((minic.rx_size - MINIC_MTU) >> 2));
}
minic_writel(MINIC_REG_MCR, MINIC_MCR_RX_EN);
}
static void minic_new_tx_buffer()
{
minic.tx_head = minic.tx_base;
minic.tx_avail = (minic.tx_size - MINIC_MTU) >> 2;
minic_writel(MINIC_REG_TX_ADDR, (uint32_t) minic.tx_base);
}
void minic_init()
{
minic_writel(MINIC_REG_EIC_IDR, MINIC_EIC_IDR_RX);
minic_writel(MINIC_REG_EIC_ISR, MINIC_EIC_ISR_RX);
minic.rx_base = dma_rx_buf;
minic.rx_size = sizeof(dma_rx_buf);
minic.tx_base = dma_tx_buf;
minic.tx_size = sizeof(dma_tx_buf);
minic.tx_count = 0;
minic.rx_count = 0;
minic_new_rx_buffer();
minic_writel(MINIC_REG_EIC_IER, MINIC_EIC_IER_RX);
}
void minic_disable()
{
minic_writel(MINIC_REG_MCR, 0);
}
int minic_poll_rx()
{
uint32_t isr;
isr = minic_readl(MINIC_REG_EIC_ISR);
return (isr & MINIC_EIC_ISR_RX) ? 1 : 0;//>>1;
}
int minic_rx_frame(uint8_t *hdr, uint8_t *payload, uint32_t buf_size,
struct hw_timestamp *hwts)
{
uint32_t payload_size, num_words;
uint32_t desc_hdr;
uint32_t raw_ts;
uint32_t rx_addr_cur;
int n_recvd = 0;
if(! (minic_readl(MINIC_REG_EIC_ISR) & MINIC_EIC_ISR_RX))
return 0;
desc_hdr = *minic.rx_head;
if (0) {
TRACE_DEV("RX_FRAME_ENTER\n\nRxHead %x buffer at %x\n",
(int)minic.rx_head, (int)minic.rx_base);
}
/*
* invalid descriptor? Weird, the RX_ADDR seems to be
* saying something different. Ignore the packet and purge
* the RX buffer.
*/
if(!RX_DESC_VALID(desc_hdr))
{
/*
* invalid descriptor? Weird, the RX_ADDR seems to be
* saying something different. Ignore the packet and purge
* the RX buffer.
*/
TRACE_DEV("weird, invalid RX descriptor (%x, head %x)\n",
(int)desc_hdr, (int)minic.rx_head);
minic_new_rx_buffer();
return 0;
}
payload_size = RX_DESC_SIZE(desc_hdr);
num_words = ((payload_size + 3) >> 2) + 1;
if (0)
TRACE_DEV("NWords %d\n", (int)num_words);
/* valid packet */
if(!RX_DESC_ERROR(desc_hdr))
{
if(RX_DESC_HAS_OOB(desc_hdr) && hwts != NULL)
{
uint32_t counter_r, counter_f, counter_ppsg, utc;
int cntr_diff;
payload_size -= RX_OOB_SIZE;
/* fixme: ugly way of doing unaligned read */
memcpy(&raw_ts,
(uint8_t *)minic.rx_head + payload_size + 6,
4);
EXPLODE_WR_TIMESTAMP(raw_ts, counter_r, counter_f);
/* was pps_gen_get_time(&utc, &counter_ppsg); */
utc = counter_ppsg = 0;
if(counter_r > 3*125000000/4
&& counter_ppsg < 125000000/4)
utc--;
hwts->utc = utc & 0x7fffffff ;
cntr_diff = (counter_r & F_COUNTER_MASK) - counter_f;
if(cntr_diff == 1 || cntr_diff == (-F_COUNTER_MASK))
hwts->ahead = 1;
else
hwts->ahead = 0;
hwts->nsec = counter_r * 8;
}
n_recvd = (buf_size < payload_size ? buf_size : payload_size);
TRACE_DEV("minic_rx_frame [%d bytes] TS: %d.%d\n",
n_recvd, (int)hwts->utc, (int)hwts->nsec);
minic.rx_count++;
memcpy(hdr, (void*)minic.rx_head + 4, ETH_HEADER_SIZE);
memcpy(payload, (void*)minic.rx_head + 4 + ETH_HEADER_SIZE,
n_recvd - ETH_HEADER_SIZE);
minic.rx_head += num_words;
} else { // RX_DESC_ERROR
// TRACE_DEV("nwords_avant_err: %d\n", num_words);
minic.rx_head += num_words;
}
rx_addr_cur = minic_readl(MINIC_REG_RX_ADDR) & 0xffff;
if(rx_addr_cur < (uint32_t)minic.rx_head)
{
/* nothing new in the buffer? */
if (0) {
TRACE_DEV("MoreData? %x, head %x\n",
(int)rx_addr_cur, (int)minic.rx_head);
}
if(minic_readl(MINIC_REG_MCR) & MINIC_MCR_RX_FULL)
minic_new_rx_buffer();
minic_writel(MINIC_REG_EIC_ISR, MINIC_EIC_ISR_RX);
}
return n_recvd;
}
static uint16_t tx_oob_val = 0;
int minic_tx_frame(uint8_t *hdr, uint8_t *payload, uint32_t size,
struct hw_timestamp *hwts)
{
uint32_t d_hdr, mcr, nwords;
minic_new_tx_buffer();
TRACE_DEV("minic_tx_frame: head %x size %d\n",
(int)minic.tx_head, (int)size);
memset((void *)minic.tx_head, 0x0, size + 16);
memset((void *)minic.tx_head + 4, 0, size < 60 ? 60 : size);
memcpy((void *)minic.tx_head + 4, hdr, ETH_HEADER_SIZE);
memcpy((void *)minic.tx_head + 4 + ETH_HEADER_SIZE,
payload, size - ETH_HEADER_SIZE);
if(size < 60)
size = 60;
nwords = ((size + 1) >> 1) - 1;
if (0) { /* print the packet. We know payload follows header */
int i = size, j;
uint8_t *packet = hdr;
pp_printf("recvd: %i\n", i);
for (j = 0; j < 32 && j < i; j++)
pp_printf(" %02x", packet[j]);
pp_printf("\n");
}
if(hwts)
{
memcpy((void *) minic.tx_head + 4 + size, &tx_oob_val,
sizeof(uint16_t));
nwords++;
d_hdr = TX_DESC_WITH_OOB;
} else
d_hdr = 0;
d_hdr |= TX_DESC_VALID | nwords;
*(volatile uint32_t *)(minic.tx_head) = d_hdr;
*(volatile uint32_t *)(minic.tx_head + nwords) = 0;
mcr = minic_readl(MINIC_REG_MCR);
minic_writel(MINIC_REG_MCR, mcr | MINIC_MCR_TX_START);
if(hwts) /* wait for the timestamp */
{
uint32_t raw_ts;
uint16_t fid;
uint32_t counter_r, counter_f;
uint32_t utc;
uint32_t nsec;
uint8_t ts_tout;
ts_tout=0;
while( (minic_readl(MINIC_REG_TSFIFO_CSR)
& MINIC_TSFIFO_CSR_EMPTY ) && ts_tout<10)
ts_tout++;
raw_ts = minic_readl(MINIC_REG_TSFIFO_R0);
fid = (minic_readl(MINIC_REG_TSFIFO_R1) >> 5) & 0xffff;
if(fid != tx_oob_val)
{
TRACE_DEV("minic_tx_frame: unmatched fid %d vs %d\n",
fid, tx_oob_val);
}
EXPLODE_WR_TIMESTAMP(raw_ts, counter_r, counter_f);
utc = nsec = 0; /* was: pps_gen_get_time(&utc, &nsec); */
if(counter_r > 3*125000000/4 && nsec < 125000000/4)
utc--;
hwts->utc = utc;
hwts->ahead = 0;
hwts->nsec = counter_r * 8;
TRACE_DEV("minic_tx_frame [%d bytes] TS: %d.%d\n",
(int)size, (int)hwts->utc, (int)hwts->nsec);
minic.tx_count++;
}
tx_oob_val++;
return size;
}
void minic_get_stats(int *tx_frames, int *rx_frames)
{
*tx_frames = minic.tx_count;
*rx_frames = minic.rx_count;
}
/*
* Alessandro Rubini for CERN, 2011 -- GNU LGPL v2.1 or later
* based on code by Tomasz Wlostowski
*/
#include <pproto/pproto.h>
#include "../spec.h"
static uint32_t timer_get_tics(void)
{
return *(volatile uint32_t *)BASE_TIMER;
}
void spec_udelay(int usecs)
{
uint32_t start, end;
start = timer_get_tics();
/* It looks like the counter counts millisecs */
end = start + (usecs + 500) / 1000;
while ((signed)(end - timer_get_tics()) > 0)
;
}
/* return a seconds count from the counter above; horrible code */
int spec_time(void)
{
static uint32_t prev, secs;
static int rest; /* millisecs */
uint32_t tics = timer_get_tics();
if (!prev) {
prev = tics;
secs = 1293836400; /* jan 1st 2011 or a random number */
return secs;
}
rest += tics - prev;
secs += rest / 1000;
rest %= 1000;
prev = tics;
return secs;
}
/*
* Copyright 2011 Tomasz Wlostowski <tomasz.wlostowski@cern.ch> for CERN
* Modified by Alessandro Rubini for ptp-proposal/proto
*
* GNU LGPL 2.1 or later versions
*/
#include <stdint.h>
#include "../spec.h"
#include <hw/wb_vuart.h>
#define CALC_BAUD(baudrate) \
( ((( (unsigned long long)baudrate * 8ULL) << (16 - 7)) + \
(CPU_CLOCK >> 8)) / (CPU_CLOCK >> 7) )
static volatile struct UART_WB *uart = (volatile struct UART_WB *) BASE_UART;
void spec_uart_init(void)
{
uart->BCR = CALC_BAUD(UART_BAUDRATE);
}
void spec_putc(int c)
{
if(c == '\n')
spec_putc('\r');
while(uart->SR & UART_SR_TX_BUSY)
;
uart->TDR = c;
}
void spec_puts(const char *s)
{
while (*s)
spec_putc(*(s++));
}
int spec_testc(void)
{
return uart->SR & UART_SR_RX_RDY;
}
int spec_getc(void)
{
return uart ->RDR & 0xff;
}
#ifndef __ARCH_H__
#define __ARCH_H__
/* Architecture-specific defines, included by top-level stuff */
#define htons(x) (x)
#define htonl(x) (x)
#define ntohs htons
#define ntohl htonl
#endif /* __ARCH_H__ */
/*
* Copyright 2011 Tomasz Wlostowski <tomasz.wlostowski@cern.ch> for CERN
* Modified by Alessandro Rubini for ptp-proposal/proto
*
* GNU LGPL 2.1 or later versions
*/
#ifndef __GPIO_H
#define __GPIO_H
#include <stdint.h>
struct GPIO_WB
{
uint32_t CODR; /*Clear output register*/
uint32_t SODR; /*Set output register*/
uint32_t DDR; /*Data direction register (1 means out)*/
uint32_t PSR; /*Pin state register*/
};
static volatile struct GPIO_WB *__gpio = (volatile struct GPIO_WB *) BASE_GPIO;
static inline void gpio_out(int pin, int val)
{
if(val)
__gpio->SODR = (1<<pin);
else
__gpio->CODR = (1<<pin);
}
static inline void gpio_dir(int pin, int val)
{
if(val)
__gpio->DDR |= (1<<pin);
else
__gpio->DDR &= ~(1<<pin);
}
static inline int gpio_in(int pin)
{
return __gpio->PSR & (1<<pin) ? 1: 0;
}
#endif
This diff is collapsed.
/*
Register definitions for slave core: WR switch endpoint controller
* File : endpoint_regs.h
* Author : auto-generated by wbgen2 from ep_wishbone_controller.wb
* Created : Wed Apr 6 22:46:02 2011
* Standard : ANSI C
THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE ep_wishbone_controller.wb
DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
*/
#ifndef __WBGEN2_REGDEFS_EP_WISHBONE_CONTROLLER_WB
#define __WBGEN2_REGDEFS_EP_WISHBONE_CONTROLLER_WB
#include <inttypes.h>
#if defined( __GNUC__)
#define PACKED __attribute__ ((packed))
#else
#error "Unsupported compiler?"
#endif
#ifndef __WBGEN2_MACROS_DEFINED__
#define __WBGEN2_MACROS_DEFINED__
#define WBGEN2_GEN_MASK(offset, size) (((1<<(size))-1) << (offset))
#define WBGEN2_GEN_WRITE(value, offset, size) (((value) & ((1<<(size))-1)) << (offset))
#define WBGEN2_GEN_READ(reg, offset, size) (((reg) >> (offset)) & ((1<<(size))-1))
#define WBGEN2_SIGN_EXTEND(value, bits) (((value) & (1<<bits) ? ~((1<<(bits))-1): 0 ) | (value))
#endif
/* definitions for register: Endpoint Control Register */
/* definitions for field: Port identifier in reg: Endpoint Control Register */
#define EP_ECR_PORTID_MASK WBGEN2_GEN_MASK(0, 5)
#define EP_ECR_PORTID_SHIFT 0
#define EP_ECR_PORTID_W(value) WBGEN2_GEN_WRITE(value, 0, 5)
#define EP_ECR_PORTID_R(reg) WBGEN2_GEN_READ(reg, 0, 5)
/* definitions for field: Reset event counters in reg: Endpoint Control Register */
#define EP_ECR_RST_CNT WBGEN2_GEN_MASK(5, 1)
/* definitions for field: Transmit framer enable in reg: Endpoint Control Register */
#define EP_ECR_TX_EN_FRA WBGEN2_GEN_MASK(6, 1)
/* definitions for field: Receive deframer enable in reg: Endpoint Control Register */
#define EP_ECR_RX_EN_FRA WBGEN2_GEN_MASK(7, 1)
/* definitions for register: Timestamping Control Register */
/* definitions for field: Transmit timestamping enable in reg: Timestamping Control Register */
#define EP_TSCR_EN_TXTS WBGEN2_GEN_MASK(0, 1)
/* definitions for field: Receive timestamping enable in reg: Timestamping Control Register */
#define EP_TSCR_EN_RXTS WBGEN2_GEN_MASK(1, 1)
/* definitions for field: Timestamping counter synchronization start in reg: Timestamping Control Register */
#define EP_TSCR_CS_START WBGEN2_GEN_MASK(2, 1)
/* definitions for field: Timestamping counter synchronization done in reg: Timestamping Control Register */
#define EP_TSCR_CS_DONE WBGEN2_GEN_MASK(3, 1)
/* definitions for register: RX Deframer Control Register */
/* definitions for field: RX accept runts in reg: RX Deframer Control Register */
#define EP_RFCR_A_RUNT WBGEN2_GEN_MASK(0, 1)
/* definitions for field: RX accept giants in reg: RX Deframer Control Register */
#define EP_RFCR_A_GIANT WBGEN2_GEN_MASK(1, 1)
/* definitions for field: RX accept HP in reg: RX Deframer Control Register */
#define EP_RFCR_A_HP WBGEN2_GEN_MASK(2, 1)
/* definitions for field: RX accept fragments in reg: RX Deframer Control Register */
#define EP_RFCR_A_FRAG WBGEN2_GEN_MASK(3, 1)
/* definitions for field: RX 802.1q port mode in reg: RX Deframer Control Register */
#define EP_RFCR_QMODE_MASK WBGEN2_GEN_MASK(4, 2)
#define EP_RFCR_QMODE_SHIFT 4
#define EP_RFCR_QMODE_W(value) WBGEN2_GEN_WRITE(value, 4, 2)
#define EP_RFCR_QMODE_R(reg) WBGEN2_GEN_READ(reg, 4, 2)
/* definitions for field: Force 802.1q priority in reg: RX Deframer Control Register */
#define EP_RFCR_FIX_PRIO WBGEN2_GEN_MASK(6, 1)
/* definitions for field: Port-assigned 802.1x priority in reg: RX Deframer Control Register */
#define EP_RFCR_PRIO_VAL_MASK WBGEN2_GEN_MASK(8, 3)
#define EP_RFCR_PRIO_VAL_SHIFT 8
#define EP_RFCR_PRIO_VAL_W(value) WBGEN2_GEN_WRITE(value, 8, 3)
#define EP_RFCR_PRIO_VAL_R(reg) WBGEN2_GEN_READ(reg, 8, 3)
/* definitions for field: Port-assigned VID in reg: RX Deframer Control Register */
#define EP_RFCR_VID_VAL_MASK WBGEN2_GEN_MASK(16, 12)
#define EP_RFCR_VID_VAL_SHIFT 16
#define EP_RFCR_VID_VAL_W(value) WBGEN2_GEN_WRITE(value, 16, 12)
#define EP_RFCR_VID_VAL_R(reg) WBGEN2_GEN_READ(reg, 16, 12)
/* definitions for register: Flow Control Register */
/* definitions for field: RX Pause enable in reg: Flow Control Register */
#define EP_FCR_RXPAUSE WBGEN2_GEN_MASK(0, 1)
/* definitions for field: TX Pause enable in reg: Flow Control Register */
#define EP_FCR_TXPAUSE WBGEN2_GEN_MASK(1, 1)
/* definitions for field: TX pause threshold in reg: Flow Control Register */
#define EP_FCR_TX_THR_MASK WBGEN2_GEN_MASK(8, 8)
#define EP_FCR_TX_THR_SHIFT 8
#define EP_FCR_TX_THR_W(value) WBGEN2_GEN_WRITE(value, 8, 8)
#define EP_FCR_TX_THR_R(reg) WBGEN2_GEN_READ(reg, 8, 8)
/* definitions for field: TX pause quanta in reg: Flow Control Register */
#define EP_FCR_TX_QUANTA_MASK WBGEN2_GEN_MASK(16, 16)
#define EP_FCR_TX_QUANTA_SHIFT 16
#define EP_FCR_TX_QUANTA_W(value) WBGEN2_GEN_WRITE(value, 16, 16)
#define EP_FCR_TX_QUANTA_R(reg) WBGEN2_GEN_READ(reg, 16, 16)
/* definitions for register: Endpoint MAC address high part register */
/* definitions for register: Endpoint MAC address low part register */
/* definitions for register: DMTD Control Register */
/* definitions for field: DMTD Phase measurement enable in reg: DMTD Control Register */
#define EP_DMCR_EN WBGEN2_GEN_MASK(0, 1)
/* definitions for field: DMTD averaging samples in reg: DMTD Control Register */
#define EP_DMCR_N_AVG_MASK WBGEN2_GEN_MASK(16, 12)
#define EP_DMCR_N_AVG_SHIFT 16
#define EP_DMCR_N_AVG_W(value) WBGEN2_GEN_WRITE(value, 16, 12)
#define EP_DMCR_N_AVG_R(reg) WBGEN2_GEN_READ(reg, 16, 12)
/* definitions for register: DMTD Status register */
/* definitions for field: DMTD Phase shift value in reg: DMTD Status register */
#define EP_DMSR_PS_VAL_MASK WBGEN2_GEN_MASK(0, 24)
#define EP_DMSR_PS_VAL_SHIFT 0
#define EP_DMSR_PS_VAL_W(value) WBGEN2_GEN_WRITE(value, 0, 24)
#define EP_DMSR_PS_VAL_R(reg) WBGEN2_GEN_READ(reg, 0, 24)
/* definitions for field: DMTD Phase shift value ready in reg: DMTD Status register */
#define EP_DMSR_PS_RDY WBGEN2_GEN_MASK(24, 1)
/* definitions for register: MDIO Control Register */
/* definitions for field: MDIO Register Value in reg: MDIO Control Register */
#define EP_MDIO_CR_DATA_MASK WBGEN2_GEN_MASK(0, 16)
#define EP_MDIO_CR_DATA_SHIFT 0
#define EP_MDIO_CR_DATA_W(value) WBGEN2_GEN_WRITE(value, 0, 16)
#define EP_MDIO_CR_DATA_R(reg) WBGEN2_GEN_READ(reg, 0, 16)
/* definitions for field: MDIO Register Address in reg: MDIO Control Register */
#define EP_MDIO_CR_ADDR_MASK WBGEN2_GEN_MASK(16, 8)
#define EP_MDIO_CR_ADDR_SHIFT 16
#define EP_MDIO_CR_ADDR_W(value) WBGEN2_GEN_WRITE(value, 16, 8)
#define EP_MDIO_CR_ADDR_R(reg) WBGEN2_GEN_READ(reg, 16, 8)
/* definitions for field: MDIO Read/Write select in reg: MDIO Control Register */
#define EP_MDIO_CR_RW WBGEN2_GEN_MASK(31, 1)
/* definitions for register: MDIO Status Register */
/* definitions for field: MDIO Read Value in reg: MDIO Status Register */
#define EP_MDIO_SR_RDATA_MASK WBGEN2_GEN_MASK(0, 16)
#define EP_MDIO_SR_RDATA_SHIFT 0
#define EP_MDIO_SR_RDATA_W(value) WBGEN2_GEN_WRITE(value, 0, 16)
#define EP_MDIO_SR_RDATA_R(reg) WBGEN2_GEN_READ(reg, 0, 16)
/* definitions for field: MDIO Ready in reg: MDIO Status Register */
#define EP_MDIO_SR_READY WBGEN2_GEN_MASK(31, 1)
/* definitions for register: Identification register */
/* definitions for register: Debug/Status register */
/* definitions for field: Link status in reg: Debug/Status register */
#define EP_DSR_LSTATUS WBGEN2_GEN_MASK(0, 1)
/* definitions for field: Link activity in reg: Debug/Status register */
#define EP_DSR_LACT WBGEN2_GEN_MASK(1, 1)
/* definitions for RAM: Event counters memory */
#define EP_RMON_RAM_BYTES 0x00000080 /* size in bytes */
#define EP_RMON_RAM_WORDS 0x00000020 /* size in 32-bit words, 32-bit aligned */
PACKED struct EP_WB {
/* [0x0]: REG Endpoint Control Register */
uint32_t ECR;
/* [0x4]: REG Timestamping Control Register */
uint32_t TSCR;
/* [0x8]: REG RX Deframer Control Register */
uint32_t RFCR;
/* [0xc]: REG Flow Control Register */
uint32_t FCR;
/* [0x10]: REG Endpoint MAC address high part register */
uint32_t MACH;
/* [0x14]: REG Endpoint MAC address low part register */
uint32_t MACL;
/* [0x18]: REG DMTD Control Register */
uint32_t DMCR;
/* [0x1c]: REG DMTD Status register */
uint32_t DMSR;
/* [0x20]: REG MDIO Control Register */
uint32_t MDIO_CR;
/* [0x24]: REG MDIO Status Register */
uint32_t MDIO_SR;
/* [0x28]: REG Identification register */
uint32_t IDCODE;
/* [0x2c]: REG Debug/Status register */
uint32_t DSR;
/* padding to: 32 words */
uint32_t __padding_0[20];
/* [0x80 - 0xff]: RAM Event counters memory, 32 32-bit words, 32-bit aligned, word-addressable */
uint32_t RMON_RAM [32];
};
#endif
/*
Register definitions for slave core: Mini NIC for WhiteRabbit
* File : ../../../software/include/hw/minic_regs.h
* Author : auto-generated by wbgen2 from mini_nic.wb
* Created : Fri Aug 13 02:17:20 2010
* Standard : ANSI C
THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE mini_nic.wb
DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
*/
#ifndef __WBGEN2_REGDEFS_MINI_NIC_WB
#define __WBGEN2_REGDEFS_MINI_NIC_WB
#include <inttypes.h>
#if defined( __GNUC__)
#define PACKED __attribute__ ((packed))
#else
#error "Unsupported compiler?"
#endif
#ifndef __WBGEN2_MACROS_DEFINED__
#define __WBGEN2_MACROS_DEFINED__
#define WBGEN2_GEN_MASK(offset, size) (((1<<(size))-1) << (offset))
#define WBGEN2_GEN_WRITE(value, offset, size) (((value) & ((1<<(size))-1)) << (offset))
#define WBGEN2_GEN_READ(reg, offset, size) (((reg) >> (offset)) & ((1<<(size))-1))
#define WBGEN2_SIGN_EXTEND(value, bits) (((value) & (1<<bits) ? ~((1<<(bits))-1): 0 ) | (value))
#endif
/* definitions for register: miNIC Control Register */
/* definitions for field: TX DMA start in reg: miNIC Control Register */
#define MINIC_MCR_TX_START WBGEN2_GEN_MASK(0, 1)
/* definitions for field: TX DMA idle in reg: miNIC Control Register */
#define MINIC_MCR_TX_IDLE WBGEN2_GEN_MASK(1, 1)
/* definitions for field: TX DMA error in reg: miNIC Control Register */
#define MINIC_MCR_TX_ERROR WBGEN2_GEN_MASK(2, 1)
/* definitions for field: RX DMA ready in reg: miNIC Control Register */
#define MINIC_MCR_RX_READY WBGEN2_GEN_MASK(8, 1)
/* definitions for field: RX DMA buffer full in reg: miNIC Control Register */
#define MINIC_MCR_RX_FULL WBGEN2_GEN_MASK(9, 1)
/* definitions for field: RX DMA enable in reg: miNIC Control Register */
#define MINIC_MCR_RX_EN WBGEN2_GEN_MASK(10, 1)
/* definitions for register: TX DMA Address */
/* definitions for register: RX DMA Address */
/* definitions for register: RX buffer size register */
/* definitions for register: Debug register */
/* definitions for field: interrupt counter in reg: Debug register */
#define MINIC_DBGR_IRQ_CNT_MASK WBGEN2_GEN_MASK(0, 24)
#define MINIC_DBGR_IRQ_CNT_SHIFT 0
#define MINIC_DBGR_IRQ_CNT_W(value) WBGEN2_GEN_WRITE(value, 0, 24)
#define MINIC_DBGR_IRQ_CNT_R(reg) WBGEN2_GEN_READ(reg, 0, 24)
/* definitions for field: status of wb_irq_o line in reg: Debug register */
#define MINIC_DBGR_WB_IRQ_VAL WBGEN2_GEN_MASK(24, 1)
/* definitions for register: Interrupt disable register */
/* definitions for field: TX DMA interrupt in reg: Interrupt disable register */
#define MINIC_EIC_IDR_TX WBGEN2_GEN_MASK(0, 1)
/* definitions for field: RX DMA interrupt in reg: Interrupt disable register */
#define MINIC_EIC_IDR_RX WBGEN2_GEN_MASK(1, 1)
/* definitions for field: TX timestamp available in reg: Interrupt disable register */
#define MINIC_EIC_IDR_TXTS WBGEN2_GEN_MASK(2, 1)
/* definitions for register: Interrupt enable register */
/* definitions for field: TX DMA interrupt in reg: Interrupt enable register */
#define MINIC_EIC_IER_TX WBGEN2_GEN_MASK(0, 1)
/* definitions for field: RX DMA interrupt in reg: Interrupt enable register */
#define MINIC_EIC_IER_RX WBGEN2_GEN_MASK(1, 1)
/* definitions for field: TX timestamp available in reg: Interrupt enable register */
#define MINIC_EIC_IER_TXTS WBGEN2_GEN_MASK(2, 1)
/* definitions for register: Interrupt mask register */
/* definitions for field: TX DMA interrupt in reg: Interrupt mask register */
#define MINIC_EIC_IMR_TX WBGEN2_GEN_MASK(0, 1)
/* definitions for field: RX DMA interrupt in reg: Interrupt mask register */
#define MINIC_EIC_IMR_RX WBGEN2_GEN_MASK(1, 1)
/* definitions for field: TX timestamp available in reg: Interrupt mask register */
#define MINIC_EIC_IMR_TXTS WBGEN2_GEN_MASK(2, 1)
/* definitions for register: Interrupt status register */
/* definitions for field: TX DMA interrupt in reg: Interrupt status register */
#define MINIC_EIC_ISR_TX WBGEN2_GEN_MASK(0, 1)
/* definitions for field: RX DMA interrupt in reg: Interrupt status register */
#define MINIC_EIC_ISR_RX WBGEN2_GEN_MASK(1, 1)
/* definitions for field: TX timestamp available in reg: Interrupt status register */
#define MINIC_EIC_ISR_TXTS WBGEN2_GEN_MASK(2, 1)
/* definitions for register: FIFO 'TX timestamp FIFO' data output register 0 */
/* definitions for field: Timestamp value in reg: FIFO 'TX timestamp FIFO' data output register 0 */
#define MINIC_TSFIFO_R0_TSVAL_MASK WBGEN2_GEN_MASK(0, 32)
#define MINIC_TSFIFO_R0_TSVAL_SHIFT 0
#define MINIC_TSFIFO_R0_TSVAL_W(value) WBGEN2_GEN_WRITE(value, 0, 32)
#define MINIC_TSFIFO_R0_TSVAL_R(reg) WBGEN2_GEN_READ(reg, 0, 32)
/* definitions for register: FIFO 'TX timestamp FIFO' data output register 1 */
/* definitions for field: Port ID in reg: FIFO 'TX timestamp FIFO' data output register 1 */
#define MINIC_TSFIFO_R1_PID_MASK WBGEN2_GEN_MASK(0, 5)
#define MINIC_TSFIFO_R1_PID_SHIFT 0
#define MINIC_TSFIFO_R1_PID_W(value) WBGEN2_GEN_WRITE(value, 0, 5)
#define MINIC_TSFIFO_R1_PID_R(reg) WBGEN2_GEN_READ(reg, 0, 5)
/* definitions for field: Frame ID in reg: FIFO 'TX timestamp FIFO' data output register 1 */
#define MINIC_TSFIFO_R1_FID_MASK WBGEN2_GEN_MASK(5, 16)
#define MINIC_TSFIFO_R1_FID_SHIFT 5
#define MINIC_TSFIFO_R1_FID_W(value) WBGEN2_GEN_WRITE(value, 5, 16)
#define MINIC_TSFIFO_R1_FID_R(reg) WBGEN2_GEN_READ(reg, 5, 16)
/* definitions for register: FIFO 'TX timestamp FIFO' control/status register */
/* definitions for field: FIFO empty flag in reg: FIFO 'TX timestamp FIFO' control/status register */
#define MINIC_TSFIFO_CSR_EMPTY WBGEN2_GEN_MASK(17, 1)
/* [0x0]: REG miNIC Control Register */
#define MINIC_REG_MCR 0x00000000
/* [0x4]: REG TX DMA Address */
#define MINIC_REG_TX_ADDR 0x00000004
/* [0x8]: REG RX DMA Address */
#define MINIC_REG_RX_ADDR 0x00000008
/* [0xc]: REG RX buffer size register */
#define MINIC_REG_RX_AVAIL 0x0000000c
/* [0x10]: REG Debug register */
#define MINIC_REG_DBGR 0x00000010
/* [0x20]: REG Interrupt disable register */
#define MINIC_REG_EIC_IDR 0x00000020
/* [0x24]: REG Interrupt enable register */
#define MINIC_REG_EIC_IER 0x00000024
/* [0x28]: REG Interrupt mask register */
#define MINIC_REG_EIC_IMR 0x00000028
/* [0x2c]: REG Interrupt status register */
#define MINIC_REG_EIC_ISR 0x0000002c
/* [0x30]: REG FIFO 'TX timestamp FIFO' data output register 0 */
#define MINIC_REG_TSFIFO_R0 0x00000030
/* [0x34]: REG FIFO 'TX timestamp FIFO' data output register 1 */
#define MINIC_REG_TSFIFO_R1 0x00000034
/* [0x38]: REG FIFO 'TX timestamp FIFO' control/status register */
#define MINIC_REG_TSFIFO_CSR 0x00000038
#endif
/*
Register definitions for slave core: WR Switch PPS generator and RTC
* File : ../../../software/include/hw/pps_gen_regs.h
* Author : auto-generated by wbgen2 from wrsw_pps_gen.wb
* Created : Sat Sep 11 22:22:55 2010
* Standard : ANSI C
THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE wrsw_pps_gen.wb
DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
*/
#ifndef __WBGEN2_REGDEFS_WRSW_PPS_GEN_WB
#define __WBGEN2_REGDEFS_WRSW_PPS_GEN_WB
#if defined( __GNUC__)
#define PACKED __attribute__ ((packed))
#else
#error "Unsupported compiler?"
#endif
#ifndef __WBGEN2_MACROS_DEFINED__
#define __WBGEN2_MACROS_DEFINED__
#define WBGEN2_GEN_MASK(offset, size) (((1<<(size))-1) << (offset))
#define WBGEN2_GEN_WRITE(value, offset, size) (((value) & ((1<<(size))-1)) << (offset))
#define WBGEN2_GEN_READ(reg, offset, size) (((reg) >> (offset)) & ((1<<(size))-1))
#define WBGEN2_SIGN_EXTEND(value, bits) (((value) & (1<<bits) ? ~((1<<(bits))-1): 0 ) | (value))
#endif
/* definitions for register: Control Register */
/* definitions for field: Reset counter in reg: Control Register */
#define PPSG_CR_CNT_RST WBGEN2_GEN_MASK(0, 1)
/* definitions for field: Enable counter in reg: Control Register */
#define PPSG_CR_CNT_EN WBGEN2_GEN_MASK(1, 1)
/* definitions for field: Adjust offset in reg: Control Register */
#define PPSG_CR_CNT_ADJ WBGEN2_GEN_MASK(2, 1)
/* definitions for field: Set time in reg: Control Register */
#define PPSG_CR_CNT_SET WBGEN2_GEN_MASK(3, 1)
/* definitions for field: PPS Pulse width in reg: Control Register */
#define PPSG_CR_PWIDTH_MASK WBGEN2_GEN_MASK(4, 28)
#define PPSG_CR_PWIDTH_SHIFT 4
#define PPSG_CR_PWIDTH_W(value) WBGEN2_GEN_WRITE(value, 4, 28)
#define PPSG_CR_PWIDTH_R(reg) WBGEN2_GEN_READ(reg, 4, 28)
/* definitions for register: Nanosecond counter register */
/* definitions for register: UTC Counter register (least-significant part) */
/* definitions for register: UTC Counter register (most-significant part) */
/* definitions for register: Nanosecond adjustment register */
/* definitions for register: UTC Adjustment register (least-significant part) */
/* definitions for register: UTC Adjustment register (most-significant part) */
/* [0x0]: REG Control Register */
#define PPSG_REG_CR 0x00000000
/* [0x4]: REG Nanosecond counter register */
#define PPSG_REG_CNTR_NSEC 0x00000004
/* [0x8]: REG UTC Counter register (least-significant part) */
#define PPSG_REG_CNTR_UTCLO 0x00000008
/* [0xc]: REG UTC Counter register (most-significant part) */
#define PPSG_REG_CNTR_UTCHI 0x0000000c
/* [0x10]: REG Nanosecond adjustment register */
#define PPSG_REG_ADJ_NSEC 0x00000010
/* [0x14]: REG UTC Adjustment register (least-significant part) */
#define PPSG_REG_ADJ_UTCLO 0x00000014
/* [0x18]: REG UTC Adjustment register (most-significant part) */
#define PPSG_REG_ADJ_UTCHI 0x00000018
#endif
/*
Register definitions for slave core: WR Softcore PLL
* File : softpll_regs.h
* Author : auto-generated by wbgen2 from wr_softpll.wb
* Created : Sat Apr 9 13:29:44 2011
* Standard : ANSI C
THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE wr_softpll.wb
DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
*/
#ifndef __WBGEN2_REGDEFS_WR_SOFTPLL_WB
#define __WBGEN2_REGDEFS_WR_SOFTPLL_WB
#include <inttypes.h>
#if defined( __GNUC__)
#define PACKED __attribute__ ((packed))
#else
#error "Unsupported compiler?"
#endif
#ifndef __WBGEN2_MACROS_DEFINED__
#define __WBGEN2_MACROS_DEFINED__
#define WBGEN2_GEN_MASK(offset, size) (((1<<(size))-1) << (offset))
#define WBGEN2_GEN_WRITE(value, offset, size) (((value) & ((1<<(size))-1)) << (offset))
#define WBGEN2_GEN_READ(reg, offset, size) (((reg) >> (offset)) & ((1<<(size))-1))
#define WBGEN2_SIGN_EXTEND(value, bits) (((value) & (1<<bits) ? ~((1<<(bits))-1): 0 ) | (value))
#endif
/* definitions for register: SPLL Control/Status Register */
/* definitions for field: Tagger enable in reg: SPLL Control/Status Register */
#define SPLL_CSR_TAG_EN_MASK WBGEN2_GEN_MASK(0, 4)
#define SPLL_CSR_TAG_EN_SHIFT 0
#define SPLL_CSR_TAG_EN_W(value) WBGEN2_GEN_WRITE(value, 0, 4)
#define SPLL_CSR_TAG_EN_R(reg) WBGEN2_GEN_READ(reg, 0, 4)
/* definitions for field: Tag ready in reg: SPLL Control/Status Register */
#define SPLL_CSR_TAG_RDY_MASK WBGEN2_GEN_MASK(4, 4)
#define SPLL_CSR_TAG_RDY_SHIFT 4
#define SPLL_CSR_TAG_RDY_W(value) WBGEN2_GEN_WRITE(value, 4, 4)
#define SPLL_CSR_TAG_RDY_R(reg) WBGEN2_GEN_READ(reg, 4, 4)
/* definitions for register: HPLL Frequency Error */
/* definitions for register: DMPLL Tag ref */
/* definitions for register: DMPLL Tag fb */
/* definitions for register: HPLL DAC Output */
/* definitions for register: DMPLL DAC Output */
/* definitions for register: Deglitcher threshold */
/* definitions for register: Interrupt disable register */
/* definitions for field: Got a tag in reg: Interrupt disable register */
#define SPLL_EIC_IDR_TAG WBGEN2_GEN_MASK(0, 1)
/* definitions for register: Interrupt enable register */
/* definitions for field: Got a tag in reg: Interrupt enable register */
#define SPLL_EIC_IER_TAG WBGEN2_GEN_MASK(0, 1)
/* definitions for register: Interrupt mask register */
/* definitions for field: Got a tag in reg: Interrupt mask register */
#define SPLL_EIC_IMR_TAG WBGEN2_GEN_MASK(0, 1)
/* definitions for register: Interrupt status register */
/* definitions for field: Got a tag in reg: Interrupt status register */
#define SPLL_EIC_ISR_TAG WBGEN2_GEN_MASK(0, 1)
PACKED struct SPLL_WB {
/* [0x0]: REG SPLL Control/Status Register */
uint32_t CSR;
/* [0x4]: REG HPLL Frequency Error */
uint32_t PER_HPLL;
/* [0x8]: REG DMPLL Tag ref */
uint32_t TAG_REF;
/* [0xc]: REG DMPLL Tag fb */
uint32_t TAG_FB;
/* [0x10]: REG HPLL DAC Output */
uint32_t DAC_HPLL;
/* [0x14]: REG DMPLL DAC Output */
uint32_t DAC_DMPLL;
/* [0x18]: REG Deglitcher threshold */
uint32_t DEGLITCH_THR;
/* padding to: 8 words */
uint32_t __padding_0[1];
/* [0x20]: REG Interrupt disable register */
uint32_t EIC_IDR;
/* [0x24]: REG Interrupt enable register */
uint32_t EIC_IER;
/* [0x28]: REG Interrupt mask register */
uint32_t EIC_IMR;
/* [0x2c]: REG Interrupt status register */
uint32_t EIC_ISR;
};
#endif
/*
Register definitions for slave core: Simple Wishbone UART
* File : ../../../../software/include/hw/wb_uart.h
* Author : auto-generated by wbgen2 from uart.wb
* Created : Mon Feb 21 22:25:02 2011
* Standard : ANSI C
THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE uart.wb
DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
*/
#ifndef __WBGEN2_REGDEFS_UART_WB
#define __WBGEN2_REGDEFS_UART_WB
#include <inttypes.h>
#if defined( __GNUC__)
#define PACKED __attribute__ ((packed))
#else
#error "Unsupported compiler?"
#endif
#ifndef __WBGEN2_MACROS_DEFINED__
#define __WBGEN2_MACROS_DEFINED__
#define WBGEN2_GEN_MASK(offset, size) (((1<<(size))-1) << (offset))
#define WBGEN2_GEN_WRITE(value, offset, size) (((value) & ((1<<(size))-1)) << (offset))
#define WBGEN2_GEN_READ(reg, offset, size) (((reg) >> (offset)) & ((1<<(size))-1))
#define WBGEN2_SIGN_EXTEND(value, bits) (((value) & (1<<bits) ? ~((1<<(bits))-1): 0 ) | (value))
#endif
/* definitions for register: Status Register */
/* definitions for field: TX busy in reg: Status Register */
#define UART_SR_TX_BUSY WBGEN2_GEN_MASK(0, 1)
/* definitions for field: RX ready in reg: Status Register */
#define UART_SR_RX_RDY WBGEN2_GEN_MASK(1, 1)
/* definitions for register: Baudrate control register */
/* definitions for register: Transmit data regsiter */
/* definitions for field: Transmit data in reg: Transmit data regsiter */
#define UART_TDR_TX_DATA_MASK WBGEN2_GEN_MASK(0, 8)
#define UART_TDR_TX_DATA_SHIFT 0
#define UART_TDR_TX_DATA_W(value) WBGEN2_GEN_WRITE(value, 0, 8)
#define UART_TDR_TX_DATA_R(reg) WBGEN2_GEN_READ(reg, 0, 8)
/* definitions for register: Receive data regsiter */
/* definitions for field: Received data in reg: Receive data regsiter */
#define UART_RDR_RX_DATA_MASK WBGEN2_GEN_MASK(0, 8)
#define UART_RDR_RX_DATA_SHIFT 0
#define UART_RDR_RX_DATA_W(value) WBGEN2_GEN_WRITE(value, 0, 8)
#define UART_RDR_RX_DATA_R(reg) WBGEN2_GEN_READ(reg, 0, 8)
/* [0x0]: REG Status Register */
#define UART_REG_SR 0x00000000
/* [0x4]: REG Baudrate control register */
#define UART_REG_BCR 0x00000004
/* [0x8]: REG Transmit data regsiter */
#define UART_REG_TDR 0x00000008
/* [0xc]: REG Receive data regsiter */
#define UART_REG_RDR 0x0000000c
PACKED struct UART_WB {
/* [0x0]: REG Status Register */
uint32_t SR;
/* [0x4]: REG Baudrate control register */
uint32_t BCR;
/* [0x8]: REG Transmit data regsiter */
uint32_t TDR;
/* [0xc]: REG Receive data regsiter */
uint32_t RDR;
};
#endif
/*
Register definitions for slave core: Virtual UART
* File : wb_vuart.h
* Author : auto-generated by wbgen2 from wb_virtual_uart.wb
* Created : Wed Apr 6 23:02:01 2011
* Standard : ANSI C
THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE wb_virtual_uart.wb
DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
*/
#ifndef __WBGEN2_REGDEFS_WB_VIRTUAL_UART_WB
#define __WBGEN2_REGDEFS_WB_VIRTUAL_UART_WB
#include <inttypes.h>
#if defined( __GNUC__)
#define PACKED __attribute__ ((packed))
#else
#error "Unsupported compiler?"
#endif
#ifndef __WBGEN2_MACROS_DEFINED__
#define __WBGEN2_MACROS_DEFINED__
#define WBGEN2_GEN_MASK(offset, size) (((1<<(size))-1) << (offset))
#define WBGEN2_GEN_WRITE(value, offset, size) (((value) & ((1<<(size))-1)) << (offset))
#define WBGEN2_GEN_READ(reg, offset, size) (((reg) >> (offset)) & ((1<<(size))-1))
#define WBGEN2_SIGN_EXTEND(value, bits) (((value) & (1<<bits) ? ~((1<<(bits))-1): 0 ) | (value))
#endif
/* definitions for register: Status Register */
/* definitions for field: TX busy in reg: Status Register */
#define UART_SR_TX_BUSY WBGEN2_GEN_MASK(0, 1)
/* definitions for field: RX ready in reg: Status Register */
#define UART_SR_RX_RDY WBGEN2_GEN_MASK(1, 1)
/* definitions for register: Baudrate control register */
/* definitions for register: Transmit data regsiter */
/* definitions for field: Transmit data in reg: Transmit data regsiter */
#define UART_TDR_TX_DATA_MASK WBGEN2_GEN_MASK(0, 8)
#define UART_TDR_TX_DATA_SHIFT 0
#define UART_TDR_TX_DATA_W(value) WBGEN2_GEN_WRITE(value, 0, 8)
#define UART_TDR_TX_DATA_R(reg) WBGEN2_GEN_READ(reg, 0, 8)
/* definitions for register: Receive data regsiter */
/* definitions for field: Received data in reg: Receive data regsiter */
#define UART_RDR_RX_DATA_MASK WBGEN2_GEN_MASK(0, 8)
#define UART_RDR_RX_DATA_SHIFT 0
#define UART_RDR_RX_DATA_W(value) WBGEN2_GEN_WRITE(value, 0, 8)
#define UART_RDR_RX_DATA_R(reg) WBGEN2_GEN_READ(reg, 0, 8)
/* definitions for register: FIFO 'UART TX FIFO' data output register 0 */
/* definitions for field: Char sent by UART to TX in reg: FIFO 'UART TX FIFO' data output register 0 */
#define UART_DEBUG_R0_TX_MASK WBGEN2_GEN_MASK(0, 8)
#define UART_DEBUG_R0_TX_SHIFT 0
#define UART_DEBUG_R0_TX_W(value) WBGEN2_GEN_WRITE(value, 0, 8)
#define UART_DEBUG_R0_TX_R(reg) WBGEN2_GEN_READ(reg, 0, 8)
/* definitions for register: FIFO 'UART TX FIFO' control/status register */
/* definitions for field: FIFO full flag in reg: FIFO 'UART TX FIFO' control/status register */
#define UART_DEBUG_CSR_FULL WBGEN2_GEN_MASK(16, 1)
/* definitions for field: FIFO empty flag in reg: FIFO 'UART TX FIFO' control/status register */
#define UART_DEBUG_CSR_EMPTY WBGEN2_GEN_MASK(17, 1)
/* definitions for field: FIFO counter in reg: FIFO 'UART TX FIFO' control/status register */
#define UART_DEBUG_CSR_USEDW_MASK WBGEN2_GEN_MASK(0, 8)
#define UART_DEBUG_CSR_USEDW_SHIFT 0
#define UART_DEBUG_CSR_USEDW_W(value) WBGEN2_GEN_WRITE(value, 0, 8)
#define UART_DEBUG_CSR_USEDW_R(reg) WBGEN2_GEN_READ(reg, 0, 8)
PACKED struct UART_WB {
/* [0x0]: REG Status Register */
uint32_t SR;
/* [0x4]: REG Baudrate control register */
uint32_t BCR;
/* [0x8]: REG Transmit data regsiter */
uint32_t TDR;
/* [0xc]: REG Receive data regsiter */
uint32_t RDR;
/* [0x10]: REG FIFO 'UART TX FIFO' data output register 0 */
uint32_t DEBUG_R0;
/* [0x14]: REG FIFO 'UART TX FIFO' control/status register */
uint32_t DEBUG_CSR;
};
#endif
/* wb-gen file we use insist in using <inttypes.h>: work around them by now */
#include <stdint.h>
#ifndef __ARCH_SPEC_STDINT_H__
#define __ARCH_SPEC_STDINT_H__
/*
* We miss a stdint.h in our compiler, so provide some types here,
* knowing the CPU is 32-bits and uses LP32 model
*/
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned long uint32_t;
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed long int32_t;
#endif /* __ARCH_SPEC_STDINT_H__ */
/*
* Alessandro Rubini for CERN, 2011 -- GNU LGPL v2.1 or later
*/
/*
* This is the main loop for the Spec board
*/
#include <pproto/pproto.h>
#include "spec.h"
void spec_main_loop(struct pp_instance *ppi)
{
int i, delay_ms;
/*
* The main loop here is polling every ms. While we are not
* doing anything else but the protocol, this allows extra stuff
* to fit.
*/
delay_ms = pp_state_machine(ppi, NULL, 0);
while (1) {
unsigned char packet[1500];
/* Wait for a packet or for the timeout */
while (delay_ms && !minic_poll_rx()) {
spec_udelay(1000);
delay_ms--;
}
if (!minic_poll_rx()) {
delay_ms = pp_state_machine(ppi, NULL, 0);
continue;
}
/*
* We got a packet. If it's not ours, continue consuming
* the pending timeout
*/
i = spec_recv_packet(ppi, packet, sizeof(packet));
if (0) {
int j;
pp_printf("recvd: %i\n", i);
for (j = 0; j < 32 && j < i; j++)
pp_printf(" %02x", packet[j]);
pp_printf("\n");
}
if (i < sizeof(struct pp_packet) /* or minimum of all pckts */)
continue;
/* Warning: PP_PROTO_NR is endian-agnostic by design */
if ( ((struct spec_ethhdr *)packet)->h_proto !=
htons(PP_PROTO_NR))
continue;
delay_ms = pp_state_machine(ppi, packet, i);
}
}
/*
* Alessandro Rubini for CERN, 2011 -- public domain
*/
#include <pproto/pproto.h>
#include <hw/wb_uart.h>
#include "spec.h"
void pp_puts(const char *s)
{
spec_puts(s);
}
int pp_strnlen(const char *s, int maxlen)
{
int len = 0;
while (*(s++)) len++;
return len;
}
void *pp_memcpy(void * dest, const void *src, int count)
{
/* from u-boot-1.1.2 */
char *tmp = (char *) dest, *s = (char *) src;
while (count--)
*tmp++ = *s++;
return dest;
}
void pp_get_stamp(uint32_t *sptr)
{
*sptr = htonl(spec_time());
}
/* What follows has no prefix because it's only used by arch code */
char *strcpy(char *dest, const char *src)
{
/* from u-boot-1.1.2 */
char *tmp = dest;
while ((*dest++ = *src++) != '\0')
/* nothing */;
return tmp;
}
void *memset(void *s, int c, int count)
{
/* from u-boot-1.1.2 */
char *xs = (char *) s;
while (count--)
*xs++ = c;
return s;
}
void *memcpy(void *dest, const void *src, int count)
{
/* from u-boot-1.1.2 */
char *tmp = (char *) dest, *s = (char *) src;
while (count--)
*tmp++ = *s++;
return dest;
}
/*
* Alessandro Rubini for CERN, 2011 -- GNU LGPL v2.1 or later
*/
#include <pproto/pproto.h>
#include "spec.h"
#include "include/gpio.h"
int spec_errno;
/* This function should init the minic and get the mac address */
int spec_open_ch(struct pp_instance *ppi)
{
uint8_t fake_addr[] = {0x00, 0x10, 0x20, 0x30, 0x40, 0x50};
ep_init(fake_addr);
ep_enable(1,1);
minic_init();
memcpy(ppi->ch.addr, fake_addr, 6);
return 0;
}
/* To receive and send packets, we call the minic low-level stuff */
int spec_recv_packet(struct pp_instance *ppi, void *pkt, int len)
{
static int led = 0;
led ^= 1; /* blink one led at each rx event */
gpio_out(GPIO_PIN_LED_LINK, led);
return minic_rx_frame(pkt, pkt + 14, len - 14, NULL);
}
int spec_send_packet(struct pp_instance *ppi, void *pkt, int len)
{
static int led = 0;
led ^= 1; /* blink the other led at each tx event */
gpio_out(GPIO_PIN_LED_STATUS, led);
return minic_tx_frame(pkt, pkt + 14, len, NULL);
}
int pp_recv_packet(struct pp_instance *ppi, void *pkt, int len)
__attribute__((alias("spec_recv_packet")));
int pp_send_packet(struct pp_instance *ppi, void *pkt, int len)
__attribute__((alias("spec_send_packet")));
/*
* Alessandro Rubini for CERN, 2011 -- GNU LGPL v2.1 or later
*/
#include <pproto/pproto.h>
#include "spec.h"
#include "include/gpio.h"
static struct pp_instance ppi_static;
void pproto_main(void)
{
struct pp_instance *ppi = &ppi_static; /* no malloc, one instance */
spec_uart_init();
pp_puts("Spec: starting. Compiled on " __DATE__ "\n");
/* leds are off and button is input */
gpio_dir(GPIO_PIN_BTN1, 0);
gpio_dir(GPIO_PIN_LED_LINK, 1);
gpio_dir(GPIO_PIN_LED_STATUS, 1);
gpio_out(GPIO_PIN_LED_LINK, 0);
gpio_out(GPIO_PIN_LED_STATUS, 0);
if (spec_open_ch(ppi)) {
pp_diag_error(ppi, spec_errno);
pp_diag_fatal(ppi, "open_ch", "");
}
pp_open_instance(ppi);
spec_main_loop(ppi);
}
/* Our crt0.S is unchanged: it wants a "main" function, and "_irq_entry" too" */
int main(void) __attribute__((alias("pproto_main")));
void _irq_entry(void)
{
return;
}
/*
* Alessandro Rubini for CERN, 2011 -- GNU LGPL v2.1 or later
*/
#include <pproto/pproto.h>
/*
* These are the functions provided by the various bare files
*/
extern int spec_open_ch(struct pp_instance *ppi);
extern int spec_recv_packet(struct pp_instance *ppi, void *pkt, int len);
extern int spec_send_packet(struct pp_instance *ppi, void *pkt, int len);
extern void spec_main_loop(struct pp_instance *ppi);
extern void _irq_entry(void); /* unused, to make crt0.S happy */
extern int main(void); /* alias to pproto_main, so crt0.S is happy */
/* basics */
extern void *memset(void *s, int c, int count);
extern char *strcpy(char *dest, const char *src);
extern void *memcpy(void *dest, const void *src, int count);
/* syscall-lookalike */
extern int spec_time(void);
extern void spec_udelay(int usecs);
extern int spec_errno;
/* Dev stuff */
extern void spec_uart_init(void);
extern void spec_putc(int c);
extern void spec_puts(const char *s);
extern int spec_testc(void);
extern int spec_getc(void);
extern void minic_init(void);
extern int minic_poll_rx(void);
struct hw_timestamp;
extern int minic_rx_frame(uint8_t *hdr, uint8_t *payload, uint32_t buf_size,
struct hw_timestamp *hwts /* unused */);
extern int minic_tx_frame(uint8_t *hdr, uint8_t *payload, uint32_t size,
struct hw_timestamp *hwts /* unused */);
extern void ep_init(uint8_t mac_addr[]);
extern void get_mac_addr(uint8_t dev_addr[]);
extern int ep_enable(int enabled, int autoneg);
extern int ep_link_up();
extern int ep_get_deltas(uint32_t *delta_tx, uint32_t *delta_rx);
extern int ep_get_psval(int32_t *psval);
extern int ep_cal_pattern_enable();
extern int ep_cal_pattern_disable();
/* other network lstuff, bah.... */
struct spec_ethhdr {
unsigned char h_dest[6];
unsigned char h_source[6];
uint16_t h_proto;
} __attribute__((packed));
/* Low-level details (from board.h in wr-core-tools) */
#define BASE_UART 0x60800
#define BASE_GPIO 0x60400
#define BASE_TIMER 0x61000
#define BASE_PPSGEN 0x50000
#define BASE_EP 0x20000
#define BASE_MINIC 0x10000
#define BASE_SOFTPLL 0x40000
#define CPU_CLOCK 62500000ULL
#define UART_BAUDRATE 115200ULL /* not a real UART */
#define GPIO_PIN_LED_LINK 0
#define GPIO_PIN_LED_STATUS 1
#define GPIO_PIN_SCL_OUT 2
#define GPIO_PIN_SDA_OUT 3
#define GPIO_PIN_SDA_IN 4
#define GPIO_PIN_BTN1 5
#define GPIO_PIN_BTN2 6
/* hacks to use code imported from other places (wr-core-software) */
#define TRACE_DEV pp_printf
struct hw_timestamp {
int ahead;
uint32_t utc;
uint32_t nsec;
uint32_t phase;
};
#define DMTD_AVG_SAMPLES 256
#define DMTD_MAX_PHASE 16384
#define NULL 0
/*
* Simulator Link script for Lattice Mico32.
* Contributed by Jon Beniston <jon@beniston.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
OUTPUT_FORMAT("elf32-lm32")
ENTRY(_start)
/*INPUT() */
GROUP(-lgcc -lc)
MEMORY
{
ram : ORIGIN = 0x00000000, LENGTH = 0x10000
}
SECTIONS
{
.boot : { *(.boot) } > ram
/* Code */
.text :
{
. = ALIGN(4);
_ftext = .;
_ftext_rom = LOADADDR(.text);
*(.text .stub .text.* .gnu.linkonce.t.*)
*(.gnu.warning)
KEEP (*(.init))
KEEP (*(.fini))
/* Constructors and destructors */
KEEP (*crtbegin*.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend*.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
KEEP (*crtbegin*.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
KEEP (*(.jcr))
_etext = .;
} > ram =0
/* Exception handlers */
.eh_frame_hdr : { *(.eh_frame_hdr) } > ram
.eh_frame : { KEEP (*(.eh_frame)) } > ram
.gcc_except_table : { *(.gcc_except_table) *(.gcc_except_table.*) } > ram
/* Read-only data */
.rodata :
{
. = ALIGN(4);
_frodata = .;
_frodata_rom = LOADADDR(.rodata);
*(.rodata .rodata.* .gnu.linkonce.r.*)
*(.rodata1)
_erodata = .;
} > ram
/* Data */
.data :
{
. = ALIGN(4);
_fdata = .;
_fdata_rom = LOADADDR(.data);
*(.data .data.* .gnu.linkonce.d.*)
*(.data1)
SORT(CONSTRUCTORS)
_gp = ALIGN(16) + 0x7ff0;
*(.sdata .sdata.* .gnu.linkonce.s.*)
_edata = .;
} > ram
/* BSS */
.bss :
{
. = ALIGN(4);
_fbss = .;
*(.dynsbss)
*(.sbss .sbss.* .gnu.linkonce.sb.*)
*(.scommon)
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
_end = .;
PROVIDE (end = .);
} > ram
/* First location in stack is highest address in RAM */
PROVIDE(_fstack = ORIGIN(ram) + LENGTH(ram) - 4);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
}
# Alessandro Rubini for CERN, 2011 -- public domain
# Diagnostics: we have tree levels: none, full and limited
# full: use a complete printf and the diag code
OBJ-$(HAS_FULL_DIAG) += diag/diag-yes.o diag/diag-printf.o diag/printf-full.o
# limited: use a minimal printf (can't coexist with FULL_DIAG)
ifndef HAS_FULL_DIAG
OBJ-$(HAS_DIAG) += diag/diag-yes.o diag/diag-printf.o diag/printf-mini.o
endif
# no diagnostics: the diag-no.c file includes weak aliases to an empty func
OBJ-y += diag/diag-no.o
/*
* Alessandro Rubini for CERN, 2011 -- public domain
*/
#include <pproto/pproto.h>
/*
* Having no diagnostics, just make one function that returns 0 and alias
* all the rest to it (those returning void will have the caller ignore our 0)
*/
int pp_diag_nop(void)
{
return 0;
}
void pp_diag_fsm(struct pp_instance *ppi, int sequence, int plen)
__attribute__((weak,alias("pp_diag_nop")));
void pp_diag_trace(struct pp_instance *ppi, const char *f, int line)
__attribute__((weak,alias("pp_diag_nop")));
void pp_diag_error(struct pp_instance *ppi, int err)
__attribute__((weak,alias("pp_diag_nop")));
void pp_diag_error_str2(struct pp_instance *ppi, char *s1, char *s2)
__attribute__((weak,alias("pp_diag_nop")));
void pp_diag_fatal(struct pp_instance *ppi, char *s1, char *s2)
__attribute__((weak,alias("pp_diag_nop")));
void pp_diag_printf(struct pp_instance *ppi, char *fmt, ...)
__attribute__((weak,alias("pp_diag_nop")));
int pp_printf(const char *fmt, ...)
__attribute__((weak,alias("pp_diag_nop")));
/*
* Basic printf based on vprintf based on vsprintf
*
* Alessandro Rubini for CERN, 2011 -- public domain
* (please note that the vsprintf is not public domain but GPL)
*/
#include <stdarg.h>
#include <pproto/pproto.h>
#define PP_BUF 128 /* We prefer small targets */
static char print_buf[PP_BUF];
int pp_vprintf(const char *fmt, va_list args)
{
int ret;
ret = pp_vsprintf(print_buf, fmt, args);
pp_puts(print_buf);
return ret;
}
int pp_printf(const char *fmt, ...)
{
va_list args;
int r;
va_start(args, fmt);
r = pp_vprintf(fmt, args);
va_end(args);
return r;
}
/*
* Alessandro Rubini for CERN, 2011 -- public domain
*/
#include <pproto/pproto.h>
/*
* This has diagnostics. It calls pp_printf (which one, we don't know)
*/
void pp_diag_fsm(struct pp_instance *ppi, int sequence, int plen)
{
if (!sequence) {
/* enter with or without a packet len */
pp_printf("fsm for %p: ENTER %3i (packet len %i)\n",
ppi, ppi->state, plen);
return;
}
/* leave has one \n more, so different states are separate */
pp_printf("fsm for %p: LEAVE %3i (next: %3i in %i ms)\n\n",
ppi, ppi->state, ppi->next_state, ppi->next_delay);
}
void pp_diag_trace(struct pp_instance *ppi, const char *f, int line)
{
pp_printf("TRACE for %p: %s:%i\n", ppi, f, line);
}
void pp_diag_error(struct pp_instance *ppi, int err)
{
pp_printf("ERR for %p: %i\n", ppi, err);
}
void pp_diag_error_str2(struct pp_instance *ppi, char *s1, char *s2)
{
pp_printf("ERR for %p: %s %s\n", ppi, s1, s2);
}
void pp_diag_fatal(struct pp_instance *ppi, char *s1, char *s2)
{
pp_printf("FATAL for %p: %s %s\n", ppi, s1, s2);
while (1)
/* nothing more */;
}
void pp_diag_printf(struct pp_instance *ppi, char *fmt, ...)
{
va_list args;
char buf[128];
va_start(args, fmt);
pp_vsprintf(buf, fmt, args);
va_end(args);
pp_printf("MESSAGE for %p: %s", ppi, buf);
}
This diff is collapsed.
#include <stdarg.h>
/*
* minimal vsprintf: only %s and hex values
* Alessandro Rubini 2010, based on code in u-boot (from older Linux)
* GNU GPL version 2.
*/
int pp_vsprintf(char *buf, const char *fmt, va_list args)
{
int i, j;
static char hex[] = "0123456789abcdef";
char *s;
char *str = buf;
for (; *fmt ; ++fmt) {
if (*fmt != '%') {
*str++ = *fmt;
continue;
}
repeat:
fmt++; /* Skip '%' initially, other stuff later */
/* Skip the complete format string */
switch(*fmt) {
case '\0':
goto ret;
case '*':
/* should be precision, just eat it */
i = va_arg(args, int);
/* fall through: discard unknown stuff */
default:
goto repeat;
/* Special cases for conversions */
case 'c': /* char: supported */
*str++ = (unsigned char) va_arg(args, int);
break;
case 's': /* string: supported */
s = va_arg(args, char *);
while (*s)
*str++ = *s++;
break;
case 'n': /* number-thus-far: not supported */
break;
case '%': /* supported */
*str++ = '%';
break;
/* all integer (and pointer) are printed as <%08x> */
case 'o':
case 'x':
case 'X':
case 'd':
case 'i':
case 'u':
case 'p':
i = va_arg(args, int);
*str++ = '<';
for (j = 28; j >= 0; j -= 4)
*str++ = hex[(i>>j)&0xf];
*str++ = '>';
break;
}
}
ret:
*str = '\0';
return str - buf;
}
/*
* FIXME: header
*/
#ifndef __PTP_DEP_H__
#define __PTP_DEP_H__
/* Our printf, that is implemented internally */
extern int pp_printf(const char *fmt, ...)
__attribute__((format(printf,1,2)));
extern int pp_vsprintf(char *buf, const char *, va_list)
__attribute__ ((format (printf, 2, 0)));
/* We base on puts and a few more functions: each arch must have it */
extern void pp_puts(const char *s);
extern int pp_strnlen(const char *s, int maxlen);
extern void *pp_memcpy(void *d, const void *s, int count);
#endif /* __PTP_DEP_H__ */
/*
* FIXME
*/
#ifndef __PTP_DIAG_H__
#define __PTP_DIAG_H__
/*
* The diagnostic functions (diag-yes.c and diag-no.c).
*
* Use trace like "pp_diag_trace(ppi, __func__, __LINE__)".
* error gets an integer, the other ones two strings (so we can
* strerror(errno) together with the explanation. Avoid diag_printf if
* possible, for size reasons, but here it is anyways.
*/
extern void pp_diag_fsm(struct pp_instance *ppi, int sequence, int plen);
extern void pp_diag_trace(struct pp_instance *ppi, const char *f, int line);
extern void pp_diag_error(struct pp_instance *ppi, int err);
extern void pp_diag_error_str2(struct pp_instance *ppi, char *s1, char *s2);
extern void pp_diag_fatal(struct pp_instance *ppi, char *s1, char *s2);
extern void pp_diag_printf(struct pp_instance *ppi, char *fmt, ...)
__attribute__((format(printf,2,3)));
#endif /* __PTP_DIAG_H__ */
/*
* Alessandro Rubini for CERN, 2011 -- public domain
*/
#ifndef __PTP_PROTO_H__
#define __PTP_PROTO_H__
#include <stdint.h>
#include <stdarg.h>
#include <arch/arch.h> /* ntohs and so on */
/*
* This is the struct handling runtime options. Default values can be
* overridden by command line
*/
struct pp_runtime_opts {
/* TODO */
};
struct pp_net_path {
union {
int evt_sock;
void *custom;
};
int32_t gen_sock;
int32_t mcast_addr;
int32_t peer_mcast_addr;
int32_t ucast_addr;
};
extern struct pp_runtime_opts default_rt_opts; /* preinitialized
* with default values */
/*
* This is the communication channel. Either a socket (Posix stuff)
* or another implementation-specific thin, possibly allocated.
* For consistency, this is a struct not a union. gcc allows unnamed
* unions as structure fields, and we are gcc-specific anyways.
*/
struct pp_channel {
union {
int fd; /* Poisx wants fide descriptor */
void *custom; /* Other archs want other stuff */
};
void *arch_data; /* Other arch-private info, if any */
unsigned char addr[6]; /* Our own MAC address */
unsigned char peer[6]; /* Our peer's MAC address */
};
/*
* This is the structure for the standard protocol.
* Extensions may allocate a bigger structure that includes this one.
* The encompassing structure will be at the same address, or container_of()
* may be implemented and used
*/
struct pp_instance {
int state;
int next_state, next_delay; /* set by state processing */
void *arch_data; /* if arch needs it */
void *ext_data; /* if protocol ext needs it */
struct pp_channel ch;
struct pp_runtime_opts *rt_opts;
struct pp_clock *ppc;
};
/* The channel for an instance must be created and possibly destroyed. */
extern int pp_open_instance(struct pp_instance *ppi,
struct pp_runtime_opts *rt_opts);
extern int pp_close_instance(struct pp_instance *ppi);
extern int pp_parse_cmdline(struct pp_instance *ppi, int argc, char **argv);
/* network stuff */
extern int pp_net_init(struct pp_instance *ppi);
extern int pp_recv_packet(struct pp_instance *ppi, void *pkt, int len);
extern int pp_send_packet(struct pp_instance *ppi, void *pkt, int len);
/* Get a timestamp */
extern void pp_get_stamp(uint32_t *sptr);
/*
* The state machine itself is an array of these structures.
* Each state in the machine has an array item. Both functions are
* called (one is expected to be the standard one, the other the extension).
*
* The return value is 0 or a negative error code, but functions should
* also set the fields next_state and next_delay. Processing for the next
* state is entered when a packet arrives or when the delay expires.
*/
struct pp_state_table_item {
int state;
int (*f1)(struct pp_instance *ppi, uint8_t *packet, int plen);
int (*f2)(struct pp_instance *ppi, uint8_t *packet, int plen);
};
extern struct pp_state_table_item pp_state_table[]; /* 0-terminated */
enum pp_std_states {
PPS_END_OF_TABLE = 0,
PPS_INITIALIZING,
PPS_FAULTY,
PPS_DISABLED,
PPS_LISTENING,
PPS_PRE_MASTER,
PPS_MASTER,
PPS_PASSIVE,
PPS_UNCALIBRATED,
PPS_SLAVE,
};
/* Use a typedef, to avoid long prototypes -- I'm not sure I like it */
typedef int pp_action(struct pp_instance *ppi, uint8_t *packet, int plen);
/* Standard state-machine functions */
extern pp_action pp_initializing, pp_faulty, pp_disabled, pp_listening,
pp_pre_master, pp_master, pp_passive, pp_uncalibrated,
pp_slave;
/* The engine */
extern int pp_state_machine(struct pp_instance *ppi, uint8_t *packet, int plen);
/*
* FIXME
* What follows is the protocol itself. Definition of packet and such stuff.
* Whe talk raw sockets on PP_PROTO_NR.
*/
#define PP_PROTO_NR 0xcccc
#endif /* __PTP_PROTO_H__ */
# Makefile for an extended protocol.
# Alessandro Rubini for CERN, 2011 -- public domain
#
# We add to obj-y, and further undefined symbols are taken from libstd
# (i.e., code and data from the standard protocol)
P := proto-ext-$(PROTO_EXT)
OBJ-y += $P/ext-one.o
\ No newline at end of file
/*
* FIXME: header
*/
#include <pproto/pproto.h>
/* This is a placeholder for white rabbit extension. */
/* TODO */
# Hosted environment: build the final exectuable
# All files are under D: I'm lazy
D := proto-standard
LIBSTD := $D/libstd.a
LIBS += -L$D -lstd
OBJ-libstd := $D/state-table-default.o \
$D/state-initializing.o \
$D/state-faulty.o \
$D/state-disabled.o \
$D/state-listening.o \
$D/state-pre-master.o \
$D/state-master.o \
$D/state-passive.o \
$D/state-uncalibrated.o \
$D/state-slave.o \
$D/open-close.o
$(TARGET).o: $(LIBSTD)
$(LIBSTD): $(OBJ-libstd)
$(AR) r $@ $^
/*
* Alessandro Rubini for CERN, 2011 -- public domain
*/
#include <pproto/pproto.h>
/*
* This file deals with opening and closing an instance. The channel
* must already have been created. In practices, this initializes the
* state machine to the first state.
*
* A protocol extension can override none or both of these functions.
*/
struct pp_runtime_opts default_rt_opts = {
/* TODO */
};
struct pp_runtime_opts *pp_get_default_rt_opts()
{
return &default_rt_opts;
}
int pp_parse_cmdline(struct pp_instance *ppi, int argc, char **argv)
{
/* TODO: Check how to parse cmdline. We can not rely on getopt()
* function. Which are the really useful parameters?
* Every parameter should be contained in ppi->rt_opts and set here
*/
return 0;
}
int pp_open_instance(struct pp_instance *ppi, struct pp_runtime_opts *rt_opts)
{
if (rt_opts) {
ppi->rt_opts = rt_opts;
}
else {
ppi->rt_opts = &default_rt_opts;
}
ppi->state = PPS_INITIALIZING;
return 0;
}
int pp_close_instance(struct pp_instance *ppi)
{
/* Nothing to do by now */
return 0;
}
/*
* FIXME: header
*/
#include <pproto/pproto.h>
int pp_disabled(struct pp_instance *ppi, unsigned char *pkt, int plen)
{
/* TODO */
return 0;
}
/*
* FIXME: header
*/
#include <pproto/pproto.h>
#include <dep/dep.h>
/*
* Fault troubleshooting. Now only prints an error messages and comes back to
* PTP_INITIALIZING state
*/
int pp_faulty(struct pp_instance *ppi, unsigned char *pkt, int plen)
{
pp_printf("event FAULT_CLEARED\n");
ppi->next_state = 1000;
ppi->next_delay = PPS_INITIALIZING;
return 0;
}
/*
* FIXME: header
*/
#include <pproto/pproto.h>
#include <dep/dep.h>
/*
* Initializes network and other stuff
*/
int pp_initializing(struct pp_instance *ppi, unsigned char *pkt, int plen)
{
/* FIXME
if (pp_net_init(ppi) < 0)
goto failure;
*/
/* TODO initialize other stuff */
/* TODO copy &ppi->rt_opts to &ppi->ppc. Do it here, no real need for a
initData function */
/* TODO ARCH initTimer(); define a "timer" abstract object, define it for
all the archs and initialize it here */
/* TODO CHECK initClock(rtOpts, ptpClock); check what is it for */
/* TODO CHECK m1(ptpClock);*/
/* TODO initializes header of a packet msgPackHeader(ptpClock->msgObuf,
ptpClock); */
if (1) /* FIXME: implement above */
goto failure;
ppi->next_state = PPS_LISTENING;
return 0;
failure:
pp_printf("Failed to initialize network\n");
ppi->next_state = PPS_FAULTY;
return 0;
}
/*
* FIXME: header
*/
#include <pproto/pproto.h>
int pp_listening(struct pp_instance *ppi, unsigned char *pkt, int plen)
{
/* TODO */
return 0;
}
/*
* FIXME: header
*/
#include <pproto/pproto.h>
int pp_master(struct pp_instance *ppi, unsigned char *newpkt, int plen)
{
/* TODO */
return 0;
}
/*
* FIXME: header
*/
#include <pproto/pproto.h>
int pp_passive(struct pp_instance *ppi, unsigned char *pkt, int plen)
{
/* TODO */
return 0;
}
/*
* FIXME: header
*/
#include <pproto/pproto.h>
int pp_pre_master(struct pp_instance *ppi, unsigned char *pkt, int plen)
{
/* TODO */
return 0;
}
/*
* FIXME: header
*/
#include <pproto/pproto.h>
int pp_slave(struct pp_instance *ppi, unsigned char *_newpkt, int plen)
{
/* TODO */
return 0;
}
This diff is collapsed.
/*
* FIXME: header
*/
#include <pproto/pproto.h>
int pp_uncalibrated(struct pp_instance *ppi, unsigned char *pkt, int plen)
{
/* TODO */
return 0;
}
This diff is collapsed.
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