Commit cf33ae1d authored by Alessandro Rubini's avatar Alessandro Rubini

Support for host builds.

This commit is not breaking the current status, but adds the
ability to build on the host, to simulate and (mainly) to help
me hack the networking code in a simpler/faster environment.

Missing features:
	- ptp
	- build in i386 (currently x86-64 is hardwired)

Also, this commit requires a change in ppsi, that I'm not going to
commit now: we must get rid of the main function (most of that
stuff is done win wrc_ptp.c, which we must replicate  in a unix-compatible
way).

This is the ppsi change

   --- a/arch-unix/Makefile
   +++ b/arch-unix/Makefile
   @@ -4,7 +4,7 @@ A := arch-$(ARCH)

    CFLAGS += -Itools

   -OBJ-y += $A/unix-startup.o \
   +OBJ-y += \
           $A/main-loop.o \
           $A/unix-io.o \
           $A/unix-conf.o \

Local changes in this commit:
      - adding CONFIG_HOST_PROCESS and the auto-generated opposites:
      CONFIG_LM32 and CONFIG_EMBEDDED_NODE (LM32 && NODE)

      - make some config option depend on !HOST_PROCESS

      - Makefile: some dependencies on HOST_PROCESS and the opposite

      - */*.mk: some dev and shell objects depend on
      CONFIG_EMBEDDED_NODE instead of CONFIG_WR_NODE (i.e.: both a
      node and an lm32)

      - new host/ subdir where some placeholders are placed

      - no sdb support on the host
Signed-off-by: Alessandro Rubini's avatarAlessandro Rubini <rubini@gnudd.com>
parent 212b4f57
......@@ -64,6 +64,17 @@ config VLAN_FOR_CLASS6
default 100 if VLAN
default 0
config HOST_PROCESS
boolean
default n
config LM32
boolean
default !HOST_PROCESS
config EMBEDDED_NODE
boolean
default LM32 && WR_NODE
# CONFIG_WR_SWITCH has no further options at all at this point
......@@ -86,12 +97,12 @@ config PPSI
default y
config UART
depends on WR_NODE
depends on EMBEDDED_NODE
boolean
default y
config W1
depends on WR_NODE
depends on EMBEDDED_NODE
boolean
default y
......@@ -164,8 +175,12 @@ config DEVELOPER
directly working on this package. Please don't use unless
you are a developer of wrpc-sw.
config RAMSIZE
config HOST_PROCESS
depends on DEVELOPER && WR_NODE
boolean "Build as a host process, to develop/debug network"
config RAMSIZE
depends on DEVELOPER && EMBEDDED_NODE
int "Size of the RAM in the FPGA for this program"
default 90112
help
......@@ -175,7 +190,7 @@ config RAMSIZE
choose your preferred value here.
config STACKSIZE
depends on DEVELOPER && WR_NODE
depends on DEVELOPER && EMBEDDED_NODE
int "Size of the stack area needed by this program"
default 2048
help
......@@ -197,7 +212,7 @@ config TEMP_POLL_INTERVAL
int "Poll interval, in seconds, for temperature sensors"
config CMD_LL
depends on DEVELOPER && WR_NODE
depends on DEVELOPER && EMBEDDED_NODE
bool "Build low-level commands for development/testing"
help
This enables low-level commands: "devmem" to read/write memory
......@@ -207,13 +222,13 @@ config CMD_LL
during the initial handshake
config FLASH_INIT
depends on WR_NODE && DEVELOPER
depends on DEVELOPER && EMBEDDED_NODE
default y
boolean "Read init commands from flash storage"
# CHECK_RESET for switch and node
config CHECK_RESET
depends on DEVELOPER
depends on DEVELOPER && !HOST_PROCESS
bool "Print a stack trace if reset happens"
help
If the CPU is following a NULL pointer, the program will
......@@ -222,7 +237,7 @@ config CHECK_RESET
then clears the stack (for next time) and restarts again.
config SPLL_FIFO_LOG
depends on DEVELOPER
depends on DEVELOPER && !HOST_PROCESS
bool "Add a circular buffer for spll logging, used by tools/wrpc-dump"
help
This option addrs 256 bytes to the wrpc bynary, to log
......@@ -273,7 +288,7 @@ config PPSI
Select this option for the ppsi engine (now only option)
config DETERMINISTIC_BINARY
depends on DEVELOPER && WR_NODE
depends on DEVELOPER && EMBEDDED_NODE
boolean "Build a binary that is the same every time"
help
This option is used to #ifdef __DATE__ and __TIME__ strings
......@@ -295,7 +310,7 @@ config UART
to how the gateware is built.
config UART_SW
depends on DEVELOPER && WR_NODE
depends on DEVELOPER && EMBEDDED_NODE
default !UART
boolean "Use software uart"
help
......
# Tomasz Wlostowski for CERN, 2011,2012
-include $(CURDIR)/.config
# Until we move CONFIG_LM32 to Kconfig, force it here
CONFIG_LM32 = y
CROSS_COMPILE ?= lm32-elf-
ifdef CONFIG_HOST_PROCESS
CROSS_COMPILE =
endif
export CROSS_COMPILE
CC = $(CROSS_COMPILE)gcc
......@@ -22,6 +24,7 @@ PPSI = ppsi
obj-$(CONFIG_LM32) = arch/lm32/crt0.o arch/lm32/irq.o
LDS-$(CONFIG_WR_NODE) = arch/lm32/ram.ld
LDS-$(CONFIG_WR_SWITCH) = arch/lm32/ram-wrs.ld
LDS-$(CONFIG_HOST_PROCESS) =
obj-$(CONFIG_WR_NODE) += wrc_main.o
obj-$(CONFIG_WR_SWITCH) += wrs_main.o
......@@ -49,13 +52,13 @@ cflags-y += \
-I$(PPSI)/arch-wrpc/include \
-I$(PPSI)/include
obj-ppsi = \
$(PPSI)/ppsi.o
obj-ppsi = $(PPSI)/ppsi.o
obj-$(CONFIG_PPSI) += $(obj-ppsi)
obj-$(CONFIG_PPSI) += \
# Below, CONFIG_PPSI is wrong, as we can't build these for the host
obj-$(CONFIG_EMBEDDED_NODE) += \
monitor/monitor_ppsi.o \
lib/ppsi-wrappers.o \
$(obj-ppsi)
lib/ppsi-wrappers.o
cflags-$(CONFIG_LM32) += -mmultiply-enabled -mbarrel-shift-enabled
ldflags-$(CONFIG_LM32) = -mmultiply-enabled -mbarrel-shift-enabled \
......@@ -73,6 +76,7 @@ include lib/lib.mk
include pp_printf/printf.mk
include dev/dev.mk
include softpll/softpll.mk
include host/host.mk
# ppsi already has div64 (the same one), so only pick it if not using ppsi.
ifndef CONFIG_PPSI
......@@ -121,6 +125,7 @@ endif
PPSI_USER_CFLAGS += -DDIAG_PUTS=uart_sw_write_string
PPSI-CFG-y = wrpc_defconfig
PPSI-CFG-$(CONFIG_HOST_PROCESS) = unix_defconfig
PPSI-FLAGS-$(CONFIG_LM32) = CONFIG_NO_PRINTF=y
$(obj-ppsi):
......@@ -142,6 +147,7 @@ $(OUTPUT).o: $(OBJS)
$(LD) $(WRC-O-FLAGS-y) -r $(OBJS) -T bigobj.lds -o $@
OBJCOPY-TARGET-$(CONFIG_LM32) = -O elf32-lm32 -B lm32
OBJCOPY-TARGET-$(CONFIG_HOST_PROCESS) = -O elf64-x86-64 -B i386
config.o: .config
sed '1,3d' .config > .config.bin
......
obj-$(CONFIG_WR_NODE) += \
# Those hardware-specific files should not be built for the host, even if
# most of them give no error no warning. The host has different implementations
obj-$(CONFIG_EMBEDDED_NODE) += \
dev/endpoint.o \
dev/ep_pfilter.o \
dev/i2c.o \
dev/temperature.o \
dev/minic.o \
dev/pps_gen.o \
dev/syscon.o \
dev/sfp.o \
dev/devicelist.o \
dev/rxts_calibrator.o \
dev/flash.o
obj-$(CONFIG_WR_NODE) += \
dev/pps_gen.o
obj-$(CONFIG_WR_SWITCH) += dev/timer-wrs.o dev/ad9516.o
obj-$(CONFIG_LEGACY_EEPROM) += dev/eeprom.o
......
#include "flash.h"
void flash_init(void)
{}
int flash_write(uint32_t addr, uint8_t *buf, int count)
{ return 0; }
int flash_read(uint32_t addr, uint8_t *buf, int count)
{ return 0; }
int flash_erase(uint32_t addr, int count)
{ return 0; }
#include "syscon.h"
#include "spll_common.h"
#include "hw/etherbone-config.h"
static struct SYSCON_WB _syscon;
volatile struct SYSCON_WB *syscon = &_syscon;
static unsigned char _pps[sizeof(struct PPSG_WB)];
unsigned char *BASE_PPS_GEN = (void *)&_pps;
static unsigned char _pll[sizeof(struct SPLL_WB)];
unsigned char *BASE_SOFTPLL = (void *)&_pll;
static unsigned char _ebone[EB_IPV4 + 4];
unsigned char *BASE_ETHERBONE_CFG = (void *)&_ebone;
#include "i2c.h"
void mi2c_init(uint8_t i2cif)
{}
uint8_t mi2c_devprobe(uint8_t i2cif, uint8_t i2c_addr)
{ return 0; }
void mi2c_start(uint8_t i2cif)
{}
void mi2c_repeat_start(uint8_t i2cif)
{}
void mi2c_stop(uint8_t i2cif)
{}
unsigned char mi2c_put_byte(uint8_t i2cif, unsigned char data)
{ return 1; }
void mi2c_get_byte(uint8_t i2cif, unsigned char *data, uint8_t last)
{ *data = 0; }
#include <stdio.h>
#include <w1.h>
struct w1_bus wrpc_w1_bus;
void wrpc_w1_init(void)
{ printf("%s\n", __func__); }
int w1_scan_bus(struct w1_bus *bus)
{ printf("%s\n", __func__); return 0; }
int w1_read_eeprom_bus(struct w1_bus *bus,
int offset, uint8_t *buffer, int blen)
{ return -1; }
int w1_write_eeprom_bus(struct w1_bus *bus,
int offset, const uint8_t *buffer, int blen)
{ return -1; }
int w1_erase_eeprom_bus(struct w1_bus *bus, int offset, int blen)
{ return -1; }
obj-$(CONFIG_HOST_PROCESS) += \
host/misc.o \
host/fake-i2c.o \
host/fake-w1.o \
host/fake-flash.o \
host/fake-hw.o \
host/ptp.o \
host/socket.o
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <time.h>
#include <termios.h>
#include <sys/select.h>
#include <sys/time.h>
#include "irq.h"
#include "uart.h"
#include "endpoint.h"
#include "pps_gen.h"
#include "rxts_calibrator.h"
uint32_t _endram;
int wrc_stat_running;
/* timer */
void usleep_init(void)
{ printf("%s\n", __func__); }
void timer_init(uint32_t enable)
{ printf("%s\n", __func__); }
void timer_delay(uint32_t tics)
{
usleep(tics * 1000);
}
uint32_t uptime_sec;
uint32_t timer_get_tics(void)
{
struct timeval tv;
uint64_t msecs;
gettimeofday(&tv, NULL);
msecs = tv.tv_sec * 1000 + tv.tv_usec / 1000;
return msecs;
}
void shw_pps_gen_get_time(uint64_t * seconds, uint32_t * nanoseconds)
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
if (seconds)
*seconds = ts.tv_sec;
if (nanoseconds)
*nanoseconds = ts.tv_nsec / NS_PER_CLOCK;
}
/* uart */
void uart_init_hw(void)
{
struct termios t;
printf("%s\n", __func__);
tcgetattr(STDIN_FILENO, &t);
cfmakeraw(&t);
t.c_oflag |= ONLCR | OPOST;
tcsetattr(STDIN_FILENO, 0, &t);
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stdin, NULL, _IONBF, 0);
printf("UART simulator on the host: use ctrl-C or ctrl-D to exit\n");
}
void uart_init_sw(void)
{ printf("%s\n", __func__); }
int uart_read_byte(void)
{
fd_set set;
int ret = -1;
struct timeval tv = {0, 0};
FD_ZERO(&set);
FD_SET(STDIN_FILENO, & set);
if (select(STDIN_FILENO + 1, &set, NULL, NULL, &tv) > 0)
ret = getchar();
/* Use ctrl-C and ctrl-D specially (hack!) */
if (ret == 3 || ret == 4) {
system("stty sane");
exit(0);
}
return ret;
}
/* unused stuff */
void disable_irq(void)
{ printf("%s\n", __func__); }
void enable_irq(void)
{ printf("%s\n", __func__); }
int wrc_mon_gui(void)
{ printf("%s\n", __func__); return 0;}
int wrc_log_stats(void)
{
static uint32_t last_jiffies;
if (!wrc_stat_running)
return 0;
if (!last_jiffies)
last_jiffies = timer_get_tics() - 1 - wrc_ui_refperiod;
if (time_before(timer_get_tics(), last_jiffies + wrc_ui_refperiod))
return 0;
last_jiffies = timer_get_tics();
printf("%s\n", __func__);
return 1;
}
void sdb_find_devices(void)
{ printf("%s\n", __func__); }
int calib_t24p(int mode, uint32_t *value)
{ return 0; }
int ep_get_bitslide(void)
{ return 0; }
int ep_enable(int enabled, int autoneg)
{ return 0; }
void ep_init(uint8_t mac_addr[])
{ printf("%s\n", __func__); }
void pfilter_init_default(void)
{}
#include "wrc_ptp.h"
int wrc_ptp_init(void)
{ return 0; }
int wrc_ptp_set_mode(int mode)
{ return 0; }
int wrc_ptp_get_mode(void)
{ return 0; }
int wrc_ptp_start(void)
{ return 0; }
int wrc_ptp_stop(void)
{ return 0; }
int wrc_ptp_update(void)
{ return 0; }
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <net/if_arp.h>
#include "include/types.h" /* with "types.h" I might get the standard one... */
#include "endpoint.h"
#include "ptpd_netif.h"
#include "minic.h"
#include "hw/pps_gen_regs.h"
static int dumpstruct(FILE *dest, char *name, void *ptr, int size)
{
int ret, i;
unsigned char *p = ptr;
if (!NET_IS_VERBOSE)
return 0;
ret = fprintf(dest, "dump %s at %p (size 0x%x)\n", name, ptr, size);
for (i = 0; i < size; ) {
ret += fprintf(dest, "%02x", p[i]);
i++;
ret += fprintf(dest, i & 3 ? " " : i & 0xf ? " " : "\n");
}
if (i & 0xf)
ret += fprintf(dest, "\n");
return ret;
}
static char ifname[16];
static char ethaddr[ETH_ALEN];
static int ethaddr_ok;
int sock;
void minic_init(void)
{
char *name = getenv("WRPC_MINIC");
struct ifreq ifr;
struct packet_mreq req;
struct sockaddr_ll addr;
int ethindex;
if (!name)
name = "eth0";
strcpy(ifname, name);
printf("%s: using %s as interface\n", __func__, ifname);
sock = socket(PF_PACKET, SOCK_RAW | SOCK_NONBLOCK, ETH_P_1588);
if (sock < 0) {
printf("%s: can`t open raw socket: %s\n",
__func__, strerror(errno));
}
memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, ifname);
if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) {
printf("%s: can`t get hw address of \"%s\": %s\n",
__func__, ifname, strerror(errno));
}
memcpy(ethaddr, &ifr.ifr_ifru.ifru_hwaddr.sa_data, ETH_ALEN);
ethaddr_ok = 1;
strcpy(ifr.ifr_name, ifname);
if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) {
printf("%s: can`t get index of \"%s\": %s\n",
__func__, ifname, strerror(errno));
}
ethindex = ifr.ifr_ifindex;
memset(&req, 0, sizeof(req));
req.mr_ifindex = ethindex;
req.mr_type = PACKET_MR_PROMISC;
if (setsockopt(sock, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
&req, sizeof(req)) < 0) {
printf("%s: can`t set \"%s\" to promiscuous mode: %s\n",
__func__, ifname, strerror(errno));
}
addr.sll_family = AF_PACKET;
addr.sll_protocol = htons(ETH_P_ALL);
addr.sll_ifindex = ifr.ifr_ifindex;
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
fprintf(stderr, "%s: can't bind to \"%s\": %s\n",
__func__, ifname, strerror(errno));
}
/* Finally, put the current date into the SEC counter of ppsg */
{
uint64_t utc = time(NULL);
uint32_t *ptr;
ptr = (void *)BASE_PPS_GEN
+ offsetof(struct PPSG_WB, CNTR_UTCLO);
*ptr = utc;
ptr = (void *)BASE_PPS_GEN
+ offsetof(struct PPSG_WB, CNTR_UTCHI);
*ptr = utc >> 32;
}
}
/* We have a problem: this is called before minic_init(), so we dup code */
void get_mac_addr(uint8_t dev_addr[])
{
char *name = getenv("WRPC_MINIC");
struct ifreq ifr;
if (ethaddr_ok) {
memcpy(dev_addr, ethaddr, ETH_ALEN);
return;
}
if (!name)
name = "eth0";
sock = socket(PF_PACKET, SOCK_RAW | SOCK_NONBLOCK, ETH_P_1588);
memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, name);
ioctl(sock, SIOCGIFHWADDR, &ifr);
memcpy(dev_addr, &ifr.ifr_ifru.ifru_hwaddr.sa_data, ETH_ALEN);
}
void set_mac_addr(uint8_t dev_addr[])
{
printf("%s: no implemented yet\n", __func__);
}
int minic_rx_frame(struct wr_ethhdr *hdr, uint8_t * payload, uint32_t buf_size,
struct hw_timestamp *hwts)
{
unsigned char frame[1500];
int ret;
ret = recv(sock, frame, sizeof(frame), MSG_DONTWAIT);
if (ret < 0 && errno == EAGAIN)
return 0;
memcpy(hdr, frame, 14);
dumpstruct(stdout, "rx header", hdr, 14);
ret -= 14;
dumpstruct(stdout, "rx payload", frame + 14, ret);
if (ret > buf_size) {
printf("warning: truncating frame to %i\n", buf_size);
ret = buf_size;
}
memcpy(payload, frame + 14, ret);
return ret;
}
int minic_tx_frame(struct wr_ethhdr_vlan *hdr, uint8_t * payload, uint32_t size,
struct hw_timestamp *hwts)
{
unsigned char frame[1500];
printf("%s\n", __func__);
dumpstruct(stdout, "tx header", hdr, 14);
dumpstruct(stdout, "tx payload", payload, size);
memcpy(frame, hdr, 14);
memcpy(frame + 14, payload, size);
return send(sock, frame, size + 14, 0);
}
int wrpc_get_port_state(struct hal_port_state *port, const char *port_name)
{
return 0;
}
int ep_link_up(uint16_t * lpa)
{
struct ifreq ifr;
strcpy(ifr.ifr_name, ifname);
if ( ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
ifr.ifr_flags = ~0; /* assume up, don't be messy */
}
if (ifr.ifr_flags & IFF_UP
&& ifr.ifr_flags & IFF_RUNNING)
return 1;
return 0;
}
obj-$(CONFIG_WR_NODE) += \
shell/shell.o \
shell/cmd_version.o \
shell/cmd_pll.o \
shell/cmd_sfp.o \
shell/cmd_stat.o \
shell/cmd_ptp.o \
shell/cmd_mode.o \
shell/cmd_help.o \
shell/cmd_mac.o \
shell/cmd_ps.o \
shell/cmd_refresh.o
obj-$(CONFIG_EMBEDDED_NODE) += \
shell/cmd_stat.o \
shell/cmd_sfp.o \
shell/cmd_pll.o \
shell/cmd_calib.o \
shell/cmd_time.o \
shell/cmd_gui.o \
shell/cmd_sdb.o \
shell/cmd_mac.o \
shell/cmd_ptrack.o \
shell/cmd_help.o \
shell/cmd_ps.o \
shell/cmd_refresh.o
obj-$(CONFIG_IP) += shell/cmd_ip.o
obj-$(CONFIG_PPSI) += shell/cmd_verbose.o
......
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