upgrade to newest metalsvm
This commit is contained in:
parent
7724b70d55
commit
c78b0e9f56
7 changed files with 1397 additions and 0 deletions
108
Makefile.example
Normal file
108
Makefile.example
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
TOPDIR = $(shell pwd)
|
||||||
|
ARCH = x86
|
||||||
|
NAME = metalsvm
|
||||||
|
LWIPDIRS = lwip/src/arch lwip/src/api lwip/src/core lwip/src/core/ipv4 lwip/src/netif
|
||||||
|
DRIVERDIRS = drivers/net drivers/char
|
||||||
|
KERNDIRS = libkern kernel mm fs arch/$(ARCH)/kernel arch/$(ARCH)/mm arch/$(ARCH)/scc $(LWIPDIRS) $(DRIVERDIRS)
|
||||||
|
SUBDIRS = $(KERNDIRS)
|
||||||
|
|
||||||
|
CC_FOR_TARGET=gcc
|
||||||
|
CXX_FOR_TARGET=g++
|
||||||
|
GCC_FOR_TARGET=gcc
|
||||||
|
AR_FOR_TARGET=ar
|
||||||
|
AS_FOR_TARGET=as
|
||||||
|
LD_FOR_TARGET=ld
|
||||||
|
NM_FOR_TARGET=nm
|
||||||
|
OBJDUMP_FOR_TARGET=objdump
|
||||||
|
OBJCOPY_FOR_TARGET=objcopy
|
||||||
|
RANLIB_FOR_TARGET=ranlib
|
||||||
|
STRIP_FOR_TARGET=strip
|
||||||
|
READELF_FOR_TARGET=readelf
|
||||||
|
NASM = nasm
|
||||||
|
EMU=qemu
|
||||||
|
GDB=gdb
|
||||||
|
|
||||||
|
MAKE = make
|
||||||
|
NASMFLAGS = -felf32 -g
|
||||||
|
INCLUDE = -I$(TOPDIR)/include -I$(TOPDIR)/arch/$(ARCH)/include -I$(TOPDIR)/lwip/src/include -I$(TOPDIR)/lwip/src/include/ipv4 -I$(TOPDIR)/drivers
|
||||||
|
# Compiler options for final code
|
||||||
|
CFLAGS = -g -m32 -march=i586 -Wall -O2 -fno-builtin -fstrength-reduce -fomit-frame-pointer -finline-functions -nostdinc $(INCLUDE) -fno-stack-protector
|
||||||
|
# Compiler options for debuuging
|
||||||
|
#CFLAGS = -g -O -m32 -march=i586 -Wall -fno-builtin -DWITH_FRAME_POINTER -nostdinc $(INCLUDE) -fno-stack-protector
|
||||||
|
ARFLAGS = rsv
|
||||||
|
RM = rm -rf
|
||||||
|
LDFLAGS = -T link.ld -z max-page-size=4096 --defsym __BUILD_DATE=$(shell date +'%Y%m%d') --defsym __BUILD_TIME=$(shell date +'%H%M%S')
|
||||||
|
STRIP_DEBUG = --strip-debug
|
||||||
|
KEEP_DEBUG = --only-keep-debug
|
||||||
|
|
||||||
|
# Prettify output
|
||||||
|
V = 0
|
||||||
|
ifeq ($V,0)
|
||||||
|
Q = @
|
||||||
|
P = > /dev/null
|
||||||
|
endif
|
||||||
|
|
||||||
|
default: all
|
||||||
|
|
||||||
|
all: newlib tools $(NAME).elf
|
||||||
|
|
||||||
|
newlib:
|
||||||
|
$(MAKE) ARCH=$(ARCH) LDFLAGS="-m32" CFLAGS="-m32 -O2 -march=i586 -fno-stack-protector" NASMFLAGS="$(NASMFLAGS)" CC_FOR_TARGET=$(CC_FOR_TARGET) \
|
||||||
|
CXX_FOR_TARGET=$(CXX_FOR_TARGET) \
|
||||||
|
GCC_FOR_TARGET=$(GCC_FOR_TARGET) \
|
||||||
|
AR_FOR_TARGET=$(AR_FOR_TARGET) \
|
||||||
|
AS_FOR_TARGET=$(AS_FOR_TARGET) \
|
||||||
|
LD_FOR_TARGET=$(LD_FOR_TARGET) \
|
||||||
|
NM_FOR_TARGET=$(NM_FOR_TARGET) \
|
||||||
|
OBJDUMP_FOR_TARGET=$(OBJDUMP_FOR_TARGET) \
|
||||||
|
OBJCOPY_FOR_TARGET=$(OBJCOPY_FOR_TARGET) \
|
||||||
|
RANLIB_FOR_TARGET=$(RANLIB_FOR_TARGET) \
|
||||||
|
STRIP_FOR_TARGET=$(STRIP_FOR_TARGET) \
|
||||||
|
READELF_FOR_TARGET=$(READELF_FOR_TARGET) -C newlib
|
||||||
|
|
||||||
|
tools:
|
||||||
|
$(MAKE) -C tools
|
||||||
|
|
||||||
|
$(NAME).elf:
|
||||||
|
$Q$(LD_FOR_TARGET) $(LDFLAGS) -o $(NAME).elf $^
|
||||||
|
@echo [OBJCOPY] $(NAME).sym
|
||||||
|
$Q$(OBJCOPY_FOR_TARGET) $(KEEP_DEBUG) $(NAME).elf $(NAME).sym
|
||||||
|
@echo [OBJCOPY] $(NAME).elf
|
||||||
|
$Q$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $(NAME).elf
|
||||||
|
|
||||||
|
qemu: newlib tools $(NAME).elf
|
||||||
|
qemu -smp 2 -net nic,model=rtl8139 -net user,hostfwd=tcp::12345-:7 -net dump -kernel metalsvm.elf -initrd tools/initrd.img
|
||||||
|
|
||||||
|
qemudbg: newlib tools $(NAME).elf
|
||||||
|
qemu -S -s -smp 2 -net nic,model=rtl8139 -net user,hostfwd=tcp::12345-:7 -net dump -kernel metalsvm.elf -initrd tools/initrd.img
|
||||||
|
|
||||||
|
gdb: $(NAME).elf
|
||||||
|
make qemudbg > /dev/null &
|
||||||
|
$(GDB) -x script.gdb
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$Q$(RM) $(NAME).elf $(NAME).sym *~
|
||||||
|
$Q$(MAKE) -C tools clean
|
||||||
|
@echo Cleaned.
|
||||||
|
|
||||||
|
veryclean: clean
|
||||||
|
$Q$(MAKE) -C newlib veryclean
|
||||||
|
@echo Very cleaned
|
||||||
|
|
||||||
|
#depend:
|
||||||
|
# for i in $(SUBDIRS); do $(MAKE) -k -C $$i depend; done
|
||||||
|
|
||||||
|
%.o : %.c
|
||||||
|
@echo [CC] $@
|
||||||
|
$Q$(CC_FOR_TARGET) -c -D__KERNEL__ $(CFLAGS) -o $@ $<
|
||||||
|
@echo [DEP] $*.dep
|
||||||
|
$Q$(CC_FOR_TARGET) -MF $*.dep -MT $*.o -MM $(CFLAGS) $<
|
||||||
|
|
||||||
|
|
||||||
|
%.o : %.asm
|
||||||
|
@echo [ASM] $@
|
||||||
|
$Q$(NASM) $(NASMFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
.PHONY: default all clean emu gdb newlib tools
|
||||||
|
|
||||||
|
include $(addsuffix /Makefile,$(SUBDIRS))
|
108
MakefileSCC
Normal file
108
MakefileSCC
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
TOPDIR = $(shell pwd)
|
||||||
|
ARCH = x86
|
||||||
|
NAME = metalsvm
|
||||||
|
LWIPDIRS = lwip/src/api lwip/src/core lwip/src/core/ipv4 lwip/src/netif
|
||||||
|
DRIVERDIRS = drivers/net drivers/char
|
||||||
|
KERNDIRS = libkern kernel mm fs arch/$(ARCH)/kernel arch/$(ARCH)/mm arch/$(ARCH)/scc $(LWIPDIRS) $(DRIVERDIRS)
|
||||||
|
SUBDIRS = $(KERNDIRS)
|
||||||
|
|
||||||
|
CC_FOR_TARGET=i386-unknown-linux-gnu-gcc
|
||||||
|
CXX_FOR_TARGET=i386-unknown-linux-gnu-g++
|
||||||
|
GCC_FOR_TARGET=i386-unknown-linux-gnu-gcc
|
||||||
|
AR_FOR_TARGET=i386-unknown-linux-gnu-ar
|
||||||
|
AS_FOR_TARGET=i386-unknown-linux-gnu-as
|
||||||
|
LD_FOR_TARGET=i386-unknown-linux-gnu-ld
|
||||||
|
NM_FOR_TARGET=i386-unknown-linux-gnu-nm
|
||||||
|
OBJDUMP_FOR_TARGET=i386-unknown-linux-gnu-objdump
|
||||||
|
OBJCOPY_FOR_TARGET=i386-unknown-linux-gnu-objcopy
|
||||||
|
RANLIB_FOR_TARGET=i386-unknown-linux-gnu-ranlib
|
||||||
|
STRIP_FOR_TARGET=i386-unknown-linux-gnu-strip
|
||||||
|
READELF_FOR_TARGET=i386-unknown-linux-gnu-readelf
|
||||||
|
NASM = nasm
|
||||||
|
EMU=qemu
|
||||||
|
GDB=gdb
|
||||||
|
|
||||||
|
MAKE = make
|
||||||
|
NASMFLAGS = -felf32 -g
|
||||||
|
INCLUDE = -I$(TOPDIR)/include -I$(TOPDIR)/arch/$(ARCH)/include -I$(TOPDIR)/lwip/src/include -I$(TOPDIR)/lwip/src/include/ipv4 -I$(TOPDIR)/drivers
|
||||||
|
# Compiler options for final code
|
||||||
|
CFLAGS = -g -m32 -march=i586 -Wall -O2 -fno-zero-initialized-in-bss -fno-builtin -fstrength-reduce -fomit-frame-pointer -finline-functions -nostdinc $(INCLUDE)
|
||||||
|
# Compiler options for debuuging
|
||||||
|
#CFLAGS = -g -O -m32 -march=i586 -Wall -fno-zero-initialized-in-bss -fno-builtin -DWITH_FRAME_POINTER -nostdinc $(INCLUDE)
|
||||||
|
ARFLAGS = rsv
|
||||||
|
RM = rm -rf
|
||||||
|
LDFLAGS = -T link.ld -z max-page-size=4096 --defsym __BUILD_DATE=$(shell date +'%Y%m%d') --defsym __BUILD_TIME=$(shell date +'%H%M%S')
|
||||||
|
STRIP_DEBUG = --strip-debug
|
||||||
|
KEEP_DEBUG = --only-keep-debug
|
||||||
|
|
||||||
|
# Prettify output
|
||||||
|
V = 0
|
||||||
|
ifeq ($V,0)
|
||||||
|
Q = @
|
||||||
|
P = > /dev/null
|
||||||
|
endif
|
||||||
|
|
||||||
|
default: all
|
||||||
|
|
||||||
|
all: newlib tools $(NAME).elf
|
||||||
|
|
||||||
|
newlib:
|
||||||
|
$(MAKE) ARCH=$(ARCH) LDFLAGS="-m32" CFLAGS="-m32 -O2 -march=i586 " NASMFLAGS="$(NASMFLAGS)" CC_FOR_TARGET=$(CC_FOR_TARGET) \
|
||||||
|
CXX_FOR_TARGET=$(CXX_FOR_TARGET) \
|
||||||
|
GCC_FOR_TARGET=$(GCC_FOR_TARGET) \
|
||||||
|
AR_FOR_TARGET=$(AR_FOR_TARGET) \
|
||||||
|
AS_FOR_TARGET=$(AS_FOR_TARGET) \
|
||||||
|
LD_FOR_TARGET=$(LD_FOR_TARGET) \
|
||||||
|
NM_FOR_TARGET=$(NM_FOR_TARGET) \
|
||||||
|
OBJDUMP_FOR_TARGET=$(OBJDUMP_FOR_TARGET) \
|
||||||
|
OBJCOPY_FOR_TARGET=$(OBJCOPY_FOR_TARGET) \
|
||||||
|
RANLIB_FOR_TARGET=$(RANLIB_FOR_TARGET) \
|
||||||
|
STRIP_FOR_TARGET=$(STRIP_FOR_TARGET) \
|
||||||
|
READELF_FOR_TARGET=$(READELF_FOR_TARGET) -C newlib
|
||||||
|
|
||||||
|
tools:
|
||||||
|
$(MAKE) -C tools
|
||||||
|
|
||||||
|
$(NAME).elf:
|
||||||
|
$Q$(LD_FOR_TARGET) $(LDFLAGS) -o $(NAME).elf $^
|
||||||
|
@echo [OBJCOPY] $(NAME).sym
|
||||||
|
$Q$(OBJCOPY_FOR_TARGET) $(KEEP_DEBUG) $(NAME).elf $(NAME).sym
|
||||||
|
@echo [OBJCOPY] $(NAME).elf
|
||||||
|
$Q$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $(NAME).elf
|
||||||
|
|
||||||
|
qemu: newlib tools $(NAME).elf
|
||||||
|
qemu -smp 2 -net nic,model=rtl8139 -net user,hostfwd=tcp::12345-:7 -net dump -kernel metalsvm.elf -initrd tools/initrd.img
|
||||||
|
|
||||||
|
qemudbg: newlib tools $(NAME).elf
|
||||||
|
qemu -S -s -smp 2 -net nic,model=rtl8139 -net user,hostfwd=tcp::12345-:7 -net dump -kernel metalsvm.elf -initrd tools/initrd.img
|
||||||
|
|
||||||
|
gdb: $(NAME).elf
|
||||||
|
make qemudbg > /dev/null &
|
||||||
|
$(GDB) -x script.gdb
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$Q$(RM) $(NAME).elf $(NAME).sym *~
|
||||||
|
$Q$(MAKE) -C tools clean
|
||||||
|
@echo Cleaned.
|
||||||
|
|
||||||
|
veryclean: clean
|
||||||
|
$Q$(MAKE) -C newlib veryclean
|
||||||
|
@echo Very cleaned
|
||||||
|
|
||||||
|
#depend:
|
||||||
|
# for i in $(SUBDIRS); do $(MAKE) -k -C $$i depend; done
|
||||||
|
|
||||||
|
%.o : %.c
|
||||||
|
@echo [CC] $@
|
||||||
|
$Q$(CC_FOR_TARGET) -c -D__KERNEL__ $(CFLAGS) -o $@ $<
|
||||||
|
@echo [DEP] $*.dep
|
||||||
|
$Q$(CC_FOR_TARGET) -MF $*.dep -MT $*.o -MM $(CFLAGS) $<
|
||||||
|
|
||||||
|
|
||||||
|
%.o : %.asm
|
||||||
|
@echo [ASM] $@
|
||||||
|
$Q$(NASM) $(NASMFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
.PHONY: default all clean emu gdb newlib tools
|
||||||
|
|
||||||
|
include $(addsuffix /Makefile,$(SUBDIRS))
|
775
drivers/net/rckemac.c
Normal file
775
drivers/net/rckemac.c
Normal file
|
@ -0,0 +1,775 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2011 Stefan Lankes, Chair for Operating Systems,
|
||||||
|
* RWTH Aachen University
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* This file is part of MetalSVM.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This eMAC driver required at least sccKit 1.4.0 and based on
|
||||||
|
* the eMAC Driver Description (section 9.6.5) in the
|
||||||
|
* SccKit 1.4.0 User’s Guide (Revision 0.92 Part 9).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <metalsvm/stddef.h>
|
||||||
|
#include <metalsvm/stdio.h>
|
||||||
|
#include <metalsvm/string.h>
|
||||||
|
#include <metalsvm/processor.h>
|
||||||
|
#include <metalsvm/mailbox.h>
|
||||||
|
#include <metalsvm/page.h>
|
||||||
|
#include <metalsvm/time.h>
|
||||||
|
#include <asm/io.h>
|
||||||
|
#include <asm/irq.h>
|
||||||
|
#include <asm/RCCE.h>
|
||||||
|
#include <asm/RCCE_lib.h>
|
||||||
|
#include <asm/SCC_API.h>
|
||||||
|
#if defined(CONFIG_LWIP) && defined(CONFIG_ROCKCREEK)
|
||||||
|
#include <lwip/sys.h>
|
||||||
|
#include <lwip/stats.h>
|
||||||
|
#include <lwip/netif.h>
|
||||||
|
#include <netif/etharp.h>
|
||||||
|
#include <net/rckemac.h>
|
||||||
|
|
||||||
|
/* Limits */
|
||||||
|
#define BUFFER_ORDER 9
|
||||||
|
#define BUFFER_NUM (1 << BUFFER_ORDER)
|
||||||
|
#define BUFFER_SIZE (BUFFER_NUM * PAGE_SIZE)
|
||||||
|
|
||||||
|
#define EMAC0 0x01
|
||||||
|
#define EMAC1 0x02
|
||||||
|
#define EMAC2 0x04
|
||||||
|
#define EMAC3 0x08
|
||||||
|
|
||||||
|
#define EMAC_IPCONF 0x3200
|
||||||
|
#define EMAC_RX_CONTROL 0x9000
|
||||||
|
#define EMAC_TX_CONTROL 0x9900
|
||||||
|
|
||||||
|
/* IP configuration - offsets */
|
||||||
|
#define CONFIG_FLOW_CONTROL_ADD 0xC0
|
||||||
|
#define TRANSMITTER_ADDRESS 0x80
|
||||||
|
#define RECEIVER1_ADDRESS 0x40
|
||||||
|
#define CONFIG_ADD 0x100
|
||||||
|
#define ADD_FILTER_MOD 0x190
|
||||||
|
|
||||||
|
/* EMAC RX */
|
||||||
|
#define EMAC_RX_BUFFER_START_ADDRESS 0x0000
|
||||||
|
#define EMAC_RX_BUFFER_READ_OFFSET 0x0100
|
||||||
|
#define EMAC_RX_BUFFER_WRITE_OFFSET 0x0200
|
||||||
|
#define EMAC_RX_BUFFER_SIZE 0x0300
|
||||||
|
#define EMAC_RX_BUFFER_THRESHOLD 0x0400
|
||||||
|
#define EMAC_RX_MODE 0x0500
|
||||||
|
#define EMAC_RX_NETWORK_PORT_MAC_ADDRESS_HI 0x0600
|
||||||
|
#define EMAC_RX_NETWORK_PORT_MAC_ADDRESS_LO 0x0700
|
||||||
|
#define EMAC_RX_NETWORK_PORT_ENABLE 0x0800
|
||||||
|
|
||||||
|
/* EMAC TX */
|
||||||
|
#define EMAC_TX_BUFFER_START_ADDRESS 0x0000
|
||||||
|
#define EMAC_TX_BUFFER_READ_OFFSET 0x0100
|
||||||
|
#define EMAC_TX_BUFFER_WRITE_OFFSET 0x0200
|
||||||
|
#define EMAC_TX_BUFFER_SIZE 0x0300
|
||||||
|
#define EMAC_TX_MODE 0x0400
|
||||||
|
#define EMAC_TX_NETWORK_PORT_ENABLE 0x0500
|
||||||
|
|
||||||
|
// Using of LVT1 as interrupt line
|
||||||
|
#define EMAC_IRQ_MASK 0x00000001
|
||||||
|
#define EMAC_IRQ_NR 3
|
||||||
|
#define EMAC_LVT APIC_LVT1
|
||||||
|
#define EMAC_IRQ_CONFIG 1
|
||||||
|
|
||||||
|
#define IRQ_STATUS 0xD000
|
||||||
|
#define IRQ_MASK 0xD200
|
||||||
|
#define IRQ_RESET 0xD400
|
||||||
|
#define IRQ_CONFIG 0xD800
|
||||||
|
|
||||||
|
/* Cache line wrappers */
|
||||||
|
#define CLINE_SHIFT 5
|
||||||
|
#define CLINE_SIZE (1UL << CLINE_SHIFT)
|
||||||
|
#define CLINE_MASK (~(CLINE_SIZE - 1))
|
||||||
|
#define CLINE_ALIGN(_x) (((_x) + CLINE_SIZE - 1) & CLINE_MASK)
|
||||||
|
#define CLINE_PACKETS(_x) (CLINE_ALIGN(_x) >> CLINE_SHIFT)
|
||||||
|
|
||||||
|
/* Flush */
|
||||||
|
#define CL1FLUSH __asm__ volatile (".byte 0x0F; .byte 0x0A;\n")
|
||||||
|
|
||||||
|
/* Read 16bit from buffer */
|
||||||
|
#define U16(_addr) (256 * (*((uint8_t*) (_addr + 1))) + (*((uint8_t*)(_addr))))
|
||||||
|
|
||||||
|
#define MAC_ADDRESS 0x00454D414331ULL
|
||||||
|
#define MAC_HI(_x) ((((_x) >> 32)) & 0xFFFF)
|
||||||
|
#define MAC_LO(_x) (((_x) ) & 0xFFFFFFFF)
|
||||||
|
|
||||||
|
static struct netif* mynetif;
|
||||||
|
|
||||||
|
static int read_emac(int num_emac, int offset, int core)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = *((volatile int*) (FPGA_BASE + num_emac * 0x1000 + offset + core * 4));
|
||||||
|
/* no error: read twice, as xilinx ip need some time... */
|
||||||
|
ret = *((volatile int*) (FPGA_BASE + num_emac * 0x1000 + offset + core * 4));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_emac(int num_emac, int offset, int core, int value)
|
||||||
|
{
|
||||||
|
*((volatile int*) (FPGA_BASE + num_emac * 0x1000 + offset + core * 4)) = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @return error code
|
||||||
|
* - ERR_OK: packet transferred to hardware
|
||||||
|
* - ERR_CONN: no link or link failure
|
||||||
|
* - ERR_IF: could not transfer to link (hardware buffer full?)
|
||||||
|
*/
|
||||||
|
static err_t rckemacif_output(struct netif* netif, struct pbuf* p)
|
||||||
|
{
|
||||||
|
rckemacif_t* rckemacif = netif->state;
|
||||||
|
uint32_t i;
|
||||||
|
struct pbuf *q;
|
||||||
|
void *addr;
|
||||||
|
uint16_t read_offset;
|
||||||
|
int rest;
|
||||||
|
int packets;
|
||||||
|
int sum = 0;
|
||||||
|
|
||||||
|
/* check for over/underflow */
|
||||||
|
if (BUILTIN_EXPECT((p->tot_len < 20) || (p->tot_len > 1536), 0)) {
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_output: illegal packet length %d => drop\n", p->len));
|
||||||
|
return ERR_IF;
|
||||||
|
}
|
||||||
|
|
||||||
|
rckemacif->tx_write_offset++;
|
||||||
|
/* check if we need to wrap */
|
||||||
|
if (rckemacif->tx_write_offset > rckemacif->tx_buffer_max)
|
||||||
|
rckemacif->tx_write_offset = 1;
|
||||||
|
|
||||||
|
packets = CLINE_PACKETS(p->tot_len + 2);
|
||||||
|
|
||||||
|
read_offset = read_emac(rckemacif->num_emac, EMAC_TX_CONTROL+EMAC_TX_BUFFER_READ_OFFSET, rckemacif->core);
|
||||||
|
#if 1
|
||||||
|
again:
|
||||||
|
if (read_offset < rckemacif->tx_write_offset) {
|
||||||
|
sum = rckemacif->tx_buffer_max - rckemacif->tx_write_offset + read_offset - 1;
|
||||||
|
} else if (read_offset > rckemacif->tx_write_offset) {
|
||||||
|
sum = read_offset - rckemacif->tx_write_offset - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sum < packets) {
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, ("Warning: not enough space available, retrying...\n"));
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
addr = rckemacif->tx_buffer + rckemacif->tx_write_offset * 32;
|
||||||
|
|
||||||
|
/* Set frame length */
|
||||||
|
((uint8_t*)addr)[0] = p->tot_len % 256;
|
||||||
|
((uint8_t*)addr)[1] = p->tot_len / 256;
|
||||||
|
|
||||||
|
#if ETH_PAD_SIZE
|
||||||
|
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (rckemacif->tx_write_offset + packets - 1 <= rckemacif->tx_buffer_max) {
|
||||||
|
/*
|
||||||
|
* q traverses through linked list of pbuf's
|
||||||
|
* This list MUST consist of a single packet ONLY
|
||||||
|
*/
|
||||||
|
for (q=p, i=0; q!=0; q=q->next) {
|
||||||
|
memcpy(((uint8_t*)addr) + 2 + i, q->payload, q->len);
|
||||||
|
i += q->len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* increment write ptr */
|
||||||
|
rckemacif->tx_write_offset += packets - 1;
|
||||||
|
} else {
|
||||||
|
/* wrap in offsets. first copy to the end, second at the starting
|
||||||
|
* point
|
||||||
|
*/
|
||||||
|
int bytes_left = p->tot_len;
|
||||||
|
int bytes_to_copy = (rckemacif->tx_buffer_max - rckemacif->tx_write_offset + 1) * 32 - 2;
|
||||||
|
int sz = 0;
|
||||||
|
|
||||||
|
if (bytes_left < bytes_to_copy)
|
||||||
|
bytes_to_copy = bytes_left;
|
||||||
|
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, ("special case: copy last %d bytes\n", bytes_to_copy));
|
||||||
|
|
||||||
|
q = p; i = 0;
|
||||||
|
while ((q != 0) && (i < bytes_to_copy)) {
|
||||||
|
sz = q->len > bytes_to_copy-i ? bytes_to_copy-i : q->len;
|
||||||
|
memcpy(((uint8_t*) addr) + 2 + i, q->payload, sz);
|
||||||
|
bytes_left -= sz;
|
||||||
|
i += sz;
|
||||||
|
if (i < bytes_to_copy)
|
||||||
|
q = q->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bytes_left != 0) {
|
||||||
|
rckemacif->tx_write_offset = 1;
|
||||||
|
addr = rckemacif->tx_buffer + 32;
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, ("special case: copy remaining %d bytes\n", bytes_left));
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
if (sz < q->len) {
|
||||||
|
memcpy((uint8_t*) addr, q->payload + sz, q->len - sz);
|
||||||
|
bytes_left -= (q->len - sz);
|
||||||
|
i = q->len - sz;
|
||||||
|
}
|
||||||
|
for(q=q->next; (q != 0); q = q->next) {
|
||||||
|
memcpy(((uint8_t*) addr) + i, q->payload, q->len);
|
||||||
|
i += q->len;
|
||||||
|
}
|
||||||
|
|
||||||
|
rest = bytes_left % 32;
|
||||||
|
if (rest != 0)
|
||||||
|
rest = 32 - rest;
|
||||||
|
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, ("Rest is %d\n", rest));
|
||||||
|
rckemacif->tx_write_offset += CLINE_PACKETS(bytes_left + rest) - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*((volatile int*) rckemacif->tx_buffer) = 2;
|
||||||
|
|
||||||
|
/* set new write offset */
|
||||||
|
//LWIP_DEBUGF(NETIF_DEBUG, ("Update tx write offset: %d (read offset %d)\n", rckemacif->tx_write_offset, read_offset));
|
||||||
|
write_emac(rckemacif->num_emac, EMAC_TX_CONTROL+EMAC_TX_BUFFER_WRITE_OFFSET, rckemacif->core, rckemacif->tx_write_offset);
|
||||||
|
|
||||||
|
#if ETH_PAD_SIZE
|
||||||
|
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LINK_STATS_INC(link.xmit);
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rckemacif_rx_handler(struct netif* netif, unsigned int write_offset)
|
||||||
|
{
|
||||||
|
rckemacif_t* rckemacif = netif->state;
|
||||||
|
unsigned short read_offset;
|
||||||
|
unsigned int counter;
|
||||||
|
volatile void *addr;
|
||||||
|
uint16_t i, length;
|
||||||
|
struct pbuf *p;
|
||||||
|
struct pbuf* q;
|
||||||
|
|
||||||
|
if (write_offset > rckemacif->rx_buffer_max) {
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, ("Warning, write offset > buffer max!! (%d > %d)\n", write_offset, rckemacif->rx_buffer_max));
|
||||||
|
read_offset = 1;
|
||||||
|
write_emac(rckemacif->num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_READ_OFFSET, rckemacif->core, read_offset);
|
||||||
|
rckemacif->rx_read_offset = read_offset;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
if ((write_offset != 0) && (rckemacif->rx_read_offset != write_offset)) {
|
||||||
|
read_offset = rckemacif->rx_read_offset;
|
||||||
|
read_offset++;
|
||||||
|
if (read_offset < 1 || read_offset > rckemacif->rx_buffer_max) {
|
||||||
|
read_offset = 1;
|
||||||
|
}
|
||||||
|
addr = rckemacif->rx_buffer + read_offset * 32;
|
||||||
|
|
||||||
|
length = U16(addr);
|
||||||
|
|
||||||
|
// Check for over/underflow
|
||||||
|
if ((length < 20) || (length > 1536)) {
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_rx_handler(): illegal packet length %d => drop\n", length));
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, ("start read at %d; write_offset at %d; addr: %p, packet len: %d\n", read_offset, write_offset, addr, length));
|
||||||
|
|
||||||
|
read_offset = write_offset;
|
||||||
|
#if 1
|
||||||
|
kprintf("Buffer:\n");
|
||||||
|
for (i = 0; i < 32; i++) {
|
||||||
|
kprintf("%2.2x ", ((char*)addr)[i] & 0xFF);
|
||||||
|
}
|
||||||
|
kprintf("\n");
|
||||||
|
|
||||||
|
kprintf("Buffer0:\n");
|
||||||
|
for (i = 0; i < 32; i++) {
|
||||||
|
kprintf("%2.2x ", ((char*)rckemacif->rx_buffer)[i] & 0xFF);
|
||||||
|
}
|
||||||
|
kprintf("\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LINK_STATS_INC(link.memerr);
|
||||||
|
LINK_STATS_INC(link.drop);
|
||||||
|
|
||||||
|
goto rxDone;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ETH_PAD_SIZE
|
||||||
|
length += ETH_PAD_SIZE; /* allow room for Ethernet padding */
|
||||||
|
#endif
|
||||||
|
//LWIP_DEBUGF(NETIF_DEBUG, ("length %u, read_offset %u, write_offset %u\n", length, read_offset, write_offset));
|
||||||
|
|
||||||
|
p = pbuf_alloc(PBUF_RAW, length, PBUF_POOL);
|
||||||
|
if (p) {
|
||||||
|
#if ETH_PAD_SIZE
|
||||||
|
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
|
||||||
|
#endif
|
||||||
|
if (read_offset < write_offset) {
|
||||||
|
for (q=p, counter=0; q!=NULL; q=q->next) {
|
||||||
|
for(i=0; i<q->len; i++, counter++) {
|
||||||
|
((uint8_t*) q->payload)[i] = ((uint8_t*)addr)[2 + counter];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
read_offset += CLINE_PACKETS(p->len + 2) - 1;
|
||||||
|
} else {
|
||||||
|
int rest;
|
||||||
|
int bytesLeft = length;
|
||||||
|
int bytesToCopy = length;
|
||||||
|
|
||||||
|
/* rest to the end of buffer - 2 bytes length information */
|
||||||
|
rest = (rckemacif->rx_buffer_max - read_offset + 1) * 32 - 2;
|
||||||
|
if (length > rest)
|
||||||
|
bytesToCopy = rest;
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, ("bytes to copy: %d, bytesLeft: %d\n", bytesToCopy, bytesLeft));
|
||||||
|
|
||||||
|
for (q=p, counter=0; q!=NULL; q=q->next) {
|
||||||
|
for(i=0; i<q->len; i++, counter++) {
|
||||||
|
if (counter < bytesToCopy)
|
||||||
|
((uint8_t*) q->payload)[i] = ((uint8_t*)addr)[2 + counter];
|
||||||
|
else
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
bytesLeft -= bytesToCopy;
|
||||||
|
|
||||||
|
if (bytesLeft != 0) {
|
||||||
|
addr = rckemacif->rx_buffer + 0x20;
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, ("copying from %p, left: %d (%x)\n", addr, bytesLeft, ((uint8_t*)addr)[0]));
|
||||||
|
for(counter=0; (i<q->len) && (counter < bytesLeft); i++, counter++)
|
||||||
|
((uint8_t*) q->payload)[i] = ((uint8_t*)addr)[counter];
|
||||||
|
for(q=q->next; (q!=NULL) && (counter < bytesLeft); q=q->next) {
|
||||||
|
for(i=0; (i<q->len) && (counter < bytesLeft); i++, counter++) {
|
||||||
|
((uint8_t*) q->payload)[i] = ((uint8_t*)addr)[counter];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
read_offset = CLINE_PACKETS(bytesLeft);
|
||||||
|
} else {
|
||||||
|
read_offset += CLINE_PACKETS(p->len + 2) - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ETH_PAD_SIZE
|
||||||
|
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
|
||||||
|
#endif
|
||||||
|
mailbox_ptr_post(&rckemacif->mbox, (void*)p);
|
||||||
|
LINK_STATS_INC(link.recv);
|
||||||
|
} else {
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_rx_inthandler: not enough memory!\n"));
|
||||||
|
LINK_STATS_INC(link.memerr);
|
||||||
|
LINK_STATS_INC(link.drop);
|
||||||
|
}
|
||||||
|
|
||||||
|
rxDone:
|
||||||
|
/* set new read pointer */
|
||||||
|
//LWIP_DEBUGF(NETIF_DEBUG, ("Update rx read offset: %d\n", read_offset));
|
||||||
|
write_emac(rckemacif->num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_READ_OFFSET, rckemacif->core, read_offset);
|
||||||
|
rckemacif->rx_read_offset = read_offset;
|
||||||
|
} else break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rckemacif_handler(struct state* s)
|
||||||
|
{
|
||||||
|
unsigned int status, tmp;
|
||||||
|
unsigned int write_offset;
|
||||||
|
rckemacif_t* rckemacif = mynetif->state;
|
||||||
|
|
||||||
|
status = *((volatile int*) (FPGA_BASE + IRQ_STATUS + rckemacif->core * 2 * 4));
|
||||||
|
// read twice to be sure
|
||||||
|
status = *((volatile int*) (FPGA_BASE + IRQ_STATUS + rckemacif->core * 2 * 4));
|
||||||
|
if (!(status & (1 << rckemacif->num_emac))) {
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_handler: no interrupt\n"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nexttry:
|
||||||
|
/* check for updated write offset */
|
||||||
|
CL1FLUSH;
|
||||||
|
write_offset = *((volatile unsigned int*) (rckemacif->rx_buffer)) & 0xFFFF;
|
||||||
|
//write_offset = read_emac(rckemacif->num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_WRITE_OFFSET, rckemacif->core);
|
||||||
|
if ((write_offset != 0) && (rckemacif->rx_read_offset != write_offset)) {
|
||||||
|
rckemacif_rx_handler(mynetif, write_offset);
|
||||||
|
goto nexttry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set interrupt bit */
|
||||||
|
tmp = *((volatile unsigned int*) rckemacif->irq_address);
|
||||||
|
tmp &= ~(EMAC_IRQ_MASK);
|
||||||
|
*((volatile unsigned int*) rckemacif->irq_address) = tmp;
|
||||||
|
|
||||||
|
/* Reset */
|
||||||
|
*((volatile unsigned*) (FPGA_BASE + IRQ_RESET + rckemacif->core * 2 * 4)) = (1 << rckemacif->num_emac);
|
||||||
|
}
|
||||||
|
|
||||||
|
err_t rckemacif_wait(struct netif* netif, uint32_t poll)
|
||||||
|
{
|
||||||
|
rckemacif_t* rckemacif = netif->state;
|
||||||
|
struct eth_hdr *ethhdr;
|
||||||
|
struct pbuf *p = NULL;
|
||||||
|
err_t err = ERR_OK;
|
||||||
|
|
||||||
|
if (poll) {
|
||||||
|
if (mailbox_ptr_tryfetch(&(rckemacif->mbox), (void**) &p))
|
||||||
|
return err;
|
||||||
|
} else {
|
||||||
|
mailbox_ptr_fetch(&(rckemacif->mbox), (void**) &p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* points to packet payload, which starts with an Ethernet header */
|
||||||
|
ethhdr = p->payload;
|
||||||
|
|
||||||
|
//LWIP_DEBUGF(NETIF_DEBUG, ("Got packet of type 0x%x!\n", htons(ethhdr->type)));
|
||||||
|
|
||||||
|
switch (htons(ethhdr->type)) {
|
||||||
|
/* IP or ARP packet? */
|
||||||
|
case ETHTYPE_ARP:
|
||||||
|
case ETHTYPE_IP:
|
||||||
|
#if PPPOE_SUPPORT
|
||||||
|
/* PPPoE packet? */
|
||||||
|
case ETHTYPE_PPPOEDISC:
|
||||||
|
case ETHTYPE_PPPOE:
|
||||||
|
#endif /* PPPOE_SUPPORT */
|
||||||
|
/* full packet send to tcpip_thread to process */
|
||||||
|
if ((err = mynetif->input(p, mynetif)) != ERR_OK) {
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_poll: IP input error\n"));
|
||||||
|
pbuf_free(p);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pbuf_free(p);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err_t rckemacif_init(struct netif* netif)
|
||||||
|
{
|
||||||
|
rckemacif_t* rckemacif;
|
||||||
|
int num_emac;
|
||||||
|
int macPorts;
|
||||||
|
int i, tmp, x, y, z, core;
|
||||||
|
uint64_t tile_offset;
|
||||||
|
uint16_t write_offset;
|
||||||
|
uint16_t read_offset;
|
||||||
|
int mode;
|
||||||
|
int subdest;
|
||||||
|
int route;
|
||||||
|
|
||||||
|
LWIP_ASSERT("netif != NULL", (netif != NULL));
|
||||||
|
|
||||||
|
// Find out who I am...
|
||||||
|
tmp = ReadConfigReg(CRB_OWN+MYTILEID);
|
||||||
|
x = (tmp>>3) & 0x0f; // bits 06:03
|
||||||
|
y = (tmp>>7) & 0x0f; // bits 10:07
|
||||||
|
z = (tmp ) & 0x07; // bits 02:00
|
||||||
|
core = 12 * y + 2 * x + z;
|
||||||
|
|
||||||
|
rckemacif = kmalloc(sizeof(rckemacif_t));
|
||||||
|
if (!rckemacif) {
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_init: out of memory\n"));
|
||||||
|
return ERR_MEM;
|
||||||
|
}
|
||||||
|
memset(rckemacif, 0, sizeof(rckemacif_t));
|
||||||
|
rckemacif->core = core;
|
||||||
|
|
||||||
|
/* allocate the receive buffer */
|
||||||
|
rckemacif->rx_buffer = mem_allocation(BUFFER_SIZE, MAP_KERNEL_SPACE|MAP_NO_CACHE);
|
||||||
|
if (!(rckemacif->rx_buffer)) {
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_init: out of memory\n"));
|
||||||
|
kfree(rckemacif, sizeof(rckemacif_t));
|
||||||
|
return ERR_MEM;
|
||||||
|
}
|
||||||
|
memset(rckemacif->rx_buffer, 0x00, 0x20);
|
||||||
|
memset(rckemacif->rx_buffer + 0x20, 0xDA, BUFFER_SIZE - 0x20);
|
||||||
|
rckemacif->rx_buffer_max = CLINE_PACKETS(BUFFER_SIZE) - 1;
|
||||||
|
|
||||||
|
/* allocate the send buffers */
|
||||||
|
rckemacif->tx_buffer = mem_allocation(BUFFER_SIZE, MAP_KERNEL_SPACE|MAP_NO_CACHE);
|
||||||
|
if (!(rckemacif->tx_buffer)) {
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_init: out of memory\n"));
|
||||||
|
kfree(rckemacif->rx_buffer, BUFFER_SIZE);
|
||||||
|
kfree(rckemacif, sizeof(rckemacif_t));
|
||||||
|
return ERR_MEM;
|
||||||
|
}
|
||||||
|
memset(rckemacif->tx_buffer, 0x00, 0x20);
|
||||||
|
memset(rckemacif->tx_buffer + 0x20, 0xDA, BUFFER_SIZE - 0x20);
|
||||||
|
rckemacif->tx_buffer_max = CLINE_PACKETS(BUFFER_SIZE) - 1;
|
||||||
|
|
||||||
|
mailbox_ptr_init(&rckemacif->mbox);
|
||||||
|
netif->state = rckemacif;
|
||||||
|
|
||||||
|
/* Depending on core location read own private data
|
||||||
|
* (offset, subdest, route)
|
||||||
|
*/
|
||||||
|
if (z == 0) {
|
||||||
|
tmp = ReadConfigReg(CRB_OWN + LUT0);
|
||||||
|
rckemacif->irq_address = (void*) (CRB_OWN + GLCFG0);
|
||||||
|
} else {
|
||||||
|
tmp = ReadConfigReg(CRB_OWN + LUT1);
|
||||||
|
rckemacif->irq_address = (void*) (CRB_OWN + GLCFG1);
|
||||||
|
}
|
||||||
|
tile_offset = (uint64_t)((uint64_t) tmp & 0x3FF) << 24;
|
||||||
|
subdest = (tmp >> 10) & 0x07;
|
||||||
|
route = (tmp >> 13) & 0xFF;
|
||||||
|
mode = (subdest << 8) + route;
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, ("tile_offset = 0x%llx\n", tile_offset));
|
||||||
|
|
||||||
|
/* get fpga/sccKit port settings */
|
||||||
|
tmp = *((volatile int*)(FPGA_BASE + 0x822C));
|
||||||
|
tmp = *((volatile int*)(FPGA_BASE + 0x822C));
|
||||||
|
macPorts = ((tmp >> 9 ) & 0xFF);
|
||||||
|
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_init: eMAC0: %s eMAC1: %s eMAC2: %s eMAC3: %s\n",
|
||||||
|
(macPorts & EMAC0) != 0 ? "present" : "-",
|
||||||
|
(macPorts & EMAC1) != 0 ? "present" : "-",
|
||||||
|
(macPorts & EMAC2) != 0 ? "present" : "-",
|
||||||
|
(macPorts & EMAC3) != 0 ? "present" : "-"));
|
||||||
|
|
||||||
|
// determine device and emac number
|
||||||
|
num_emac=0;
|
||||||
|
while (((macPorts & (1 << num_emac)) == 0) && (num_emac < 4))
|
||||||
|
num_emac++;
|
||||||
|
if (num_emac >= 4)
|
||||||
|
return ERR_ARG;
|
||||||
|
mynetif = netif;
|
||||||
|
rckemacif->num_emac = num_emac;
|
||||||
|
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_init: used eMAC device %d\n", num_emac));
|
||||||
|
|
||||||
|
tmp = read_emac(num_emac, EMAC_IPCONF+TRANSMITTER_ADDRESS, 0);
|
||||||
|
tmp = read_emac(num_emac, EMAC_IPCONF+RECEIVER1_ADDRESS, 0);
|
||||||
|
|
||||||
|
if (core == 0) {
|
||||||
|
/* Only core 0 initialize the xilinx port */
|
||||||
|
int flow_control = 0;
|
||||||
|
int transmitter_addr = 0;
|
||||||
|
int receiver1_addr = 0;
|
||||||
|
int config_add = 0;
|
||||||
|
int add_filter_mod = 0;
|
||||||
|
|
||||||
|
/* Disable tx and rx flow control of eMAC */
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, ("Disabling tx/rx flow control of eMAC%d\n", num_emac));
|
||||||
|
flow_control = read_emac(num_emac, EMAC_IPCONF+CONFIG_FLOW_CONTROL_ADD, 0);
|
||||||
|
|
||||||
|
/* Set top 3 bits of the flow control configuration to zero,
|
||||||
|
* therefore disabling tx and rx flow control
|
||||||
|
*/
|
||||||
|
flow_control &= 0x7FFFFFF;
|
||||||
|
write_emac(num_emac, EMAC_IPCONF+CONFIG_FLOW_CONTROL_ADD, 0, flow_control);
|
||||||
|
|
||||||
|
/* Sanity check */
|
||||||
|
flow_control = read_emac(num_emac, EMAC_IPCONF+CONFIG_FLOW_CONTROL_ADD, 0);
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, (" CONFIG_FLOW_CONTROL_ADD set: 0x%x\n", flow_control));
|
||||||
|
|
||||||
|
/* Setting the tx configuration bit to enable the transmitter and
|
||||||
|
* set to full duplex mode.
|
||||||
|
*/
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, ("Setting rx configuration of eMAC%d\n", num_emac));
|
||||||
|
transmitter_addr = read_emac(num_emac, EMAC_IPCONF+TRANSMITTER_ADDRESS, 0);
|
||||||
|
|
||||||
|
/* Now set the relevant bits and write back into the register:
|
||||||
|
* 26 (half duplex) = 0, 28 (transmit enable) = 1, 31 (reset) = 0
|
||||||
|
*/
|
||||||
|
transmitter_addr &= ~(1 << 31);
|
||||||
|
transmitter_addr &= ~(1 << 26);
|
||||||
|
transmitter_addr |= (1 << 28);
|
||||||
|
write_emac(num_emac, EMAC_IPCONF+TRANSMITTER_ADDRESS, 0, transmitter_addr);
|
||||||
|
|
||||||
|
transmitter_addr = read_emac(num_emac, EMAC_IPCONF+TRANSMITTER_ADDRESS, 0);
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, (" TRANSMITTER_ADDRESS set: %x\n", transmitter_addr));
|
||||||
|
|
||||||
|
/* Setting the rx configuration bit to enable the transmitter and
|
||||||
|
* set to full duplex mode.
|
||||||
|
*/
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, ("Setting IP configuration of EMAC%d\n", num_emac));
|
||||||
|
|
||||||
|
/* Read the current config value from the register */
|
||||||
|
receiver1_addr = read_emac(num_emac, EMAC_IPCONF+RECEIVER1_ADDRESS, 0);
|
||||||
|
|
||||||
|
/* Now set the relevant bits and write back into the register:
|
||||||
|
* 25 = 1, 26 = 0, 28 = 1, 31 = 0
|
||||||
|
*/
|
||||||
|
/* Length/Type Error Check Disable */
|
||||||
|
receiver1_addr |= (1 << 25);
|
||||||
|
/* Disable Half Duplex => Full Duplex */
|
||||||
|
receiver1_addr &= ~(1 << 26);
|
||||||
|
/* Receiver enable */
|
||||||
|
receiver1_addr |= (1 << 28);
|
||||||
|
/* Reset */
|
||||||
|
receiver1_addr &= ~(1 << 31);
|
||||||
|
write_emac(num_emac, EMAC_IPCONF+RECEIVER1_ADDRESS, 0, receiver1_addr);
|
||||||
|
|
||||||
|
receiver1_addr = read_emac(num_emac, EMAC_IPCONF+RECEIVER1_ADDRESS, 0);
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, (" RECEIVER1_ADDRESS set: %x\n", receiver1_addr));
|
||||||
|
|
||||||
|
/* Setting the speed to eMAC to 1Gb/s */
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, ("Setting speed of EMAC%d to 1Gb/s\n", num_emac));
|
||||||
|
|
||||||
|
/* Read the current config value from register */
|
||||||
|
config_add = read_emac(num_emac, EMAC_IPCONF+CONFIG_ADD, 0);
|
||||||
|
|
||||||
|
/* Now set the relevant bits and write back into the register:
|
||||||
|
* 31 = 1, 30 = 0
|
||||||
|
*/
|
||||||
|
/* MAC Speed Configuration: 00 - 10Mbps, 01 - 100Mbps, 10 - 1Gbps */
|
||||||
|
config_add |= (1 << 31);
|
||||||
|
config_add &= ~(1 << 30);
|
||||||
|
write_emac(num_emac, EMAC_IPCONF+CONFIG_ADD, 0, config_add);
|
||||||
|
|
||||||
|
config_add = read_emac(num_emac, EMAC_IPCONF+CONFIG_ADD, 0);
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, (" CONFIG_ADD set: %x\n", config_add));
|
||||||
|
|
||||||
|
/* Read the current config addr filter mode */
|
||||||
|
add_filter_mod = read_emac(num_emac, EMAC_IPCONF+ADD_FILTER_MOD, 0);
|
||||||
|
|
||||||
|
/* Not set the relevant bits and write back into the register:
|
||||||
|
* 31 (promiscuous mode) = 1 not working, but thats ok!
|
||||||
|
*/
|
||||||
|
add_filter_mod |= (1 << 31);
|
||||||
|
write_emac(num_emac, EMAC_IPCONF+ADD_FILTER_MOD, 0, add_filter_mod);
|
||||||
|
|
||||||
|
add_filter_mod = read_emac(num_emac, EMAC_IPCONF+ADD_FILTER_MOD, 0);
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, (" ADD_FILTER_MOD set: %x\n", add_filter_mod));
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(3);
|
||||||
|
|
||||||
|
/* Start address */
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, (" RX Buffer %p (%lx phys)\n", rckemacif->rx_buffer, virt_to_phys((uint32_t)rckemacif->rx_buffer)));
|
||||||
|
|
||||||
|
/**** Receiver configuration ****/
|
||||||
|
|
||||||
|
uint64_t addr_offset = (tile_offset + (uint64_t) virt_to_phys((uint32_t) rckemacif->rx_buffer)) >> 5;
|
||||||
|
write_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_START_ADDRESS, core, (uint32_t) addr_offset);
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, (" RX Buffer set to @%x\n", read_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_START_ADDRESS, core)));
|
||||||
|
|
||||||
|
/* Get buffer write offset */
|
||||||
|
write_offset = read_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_WRITE_OFFSET, core);
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, (" RX Buffer write offset at: %d\n", write_offset));
|
||||||
|
|
||||||
|
/* Set buffer read offset to write offset */
|
||||||
|
write_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_READ_OFFSET, core, write_offset);
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, (" RX Buffer read offset set to: %d\n", read_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_READ_OFFSET, core)));
|
||||||
|
rckemacif->rx_read_offset = write_offset;
|
||||||
|
|
||||||
|
/* Size */
|
||||||
|
write_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_SIZE, core, rckemacif->rx_buffer_max);
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, (" RX Size set to %d\n", read_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_SIZE, core)));
|
||||||
|
|
||||||
|
/* Threshold */
|
||||||
|
write_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_THRESHOLD, core, 0x01);
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, (" RX Threshold set to %x\n", read_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_BUFFER_THRESHOLD, core)));
|
||||||
|
|
||||||
|
/* Route */
|
||||||
|
write_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_MODE, core, (z << 24) | (((y << 4) | x) << 16) | mode);
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, (" RX Mode set to %x\n", read_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_MODE, core)));
|
||||||
|
|
||||||
|
// determine mac address
|
||||||
|
uint32_t mac1 = *((volatile uint32_t*)(FPGA_BASE+0x7E00));
|
||||||
|
uint32_t mac2 = *((volatile uint32_t*)(FPGA_BASE+0x7E04));
|
||||||
|
uint64_t mac = (((unsigned long long)mac1) << 32) + (unsigned long long) mac2;
|
||||||
|
if (mac == 0x00)
|
||||||
|
mac = MAC_ADDRESS;
|
||||||
|
/* Calculate mac address of core depending on selected emac device */
|
||||||
|
mac = mac + (1 << num_emac) * 0x100 + core;
|
||||||
|
|
||||||
|
for (i=0; i<6; i++)
|
||||||
|
mynetif->hwaddr[5-i] = (mac >> (i*8)) & 0xFF;
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, ("rckemacif_init: MAC address "));
|
||||||
|
for (i=0; i<6; i++)
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, ("%02x ", mynetif->hwaddr[i]));
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, ("\n"));
|
||||||
|
|
||||||
|
write_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_NETWORK_PORT_MAC_ADDRESS_HI, core, MAC_HI(mac));
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, (" MAC1 set to %x\n", read_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_NETWORK_PORT_MAC_ADDRESS_HI, core)));
|
||||||
|
write_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_NETWORK_PORT_MAC_ADDRESS_LO, core, MAC_LO(mac));
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, (" MAC2 set to %x\n", read_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_NETWORK_PORT_MAC_ADDRESS_LO, core)));
|
||||||
|
|
||||||
|
/* Activate network port by setting enable bit */
|
||||||
|
write_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_NETWORK_PORT_ENABLE, core, 0x01);
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, (" RX Port enable set to %x\n", read_emac(num_emac, EMAC_RX_CONTROL + EMAC_RX_NETWORK_PORT_ENABLE, core)));
|
||||||
|
|
||||||
|
/**** Transfer configuration ****/
|
||||||
|
|
||||||
|
/* Start address */
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, (" TX Buffer %p (%lx phys)\n", rckemacif->tx_buffer, virt_to_phys((uint32_t)rckemacif->tx_buffer)));
|
||||||
|
write_emac(num_emac, EMAC_TX_CONTROL + EMAC_TX_BUFFER_START_ADDRESS, core, (uint32_t) (((uint64_t) virt_to_phys((uint32_t)rckemacif->tx_buffer) + tile_offset) >> 5));
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, (" TX Buffer set to @%x\n", read_emac(num_emac, EMAC_TX_CONTROL + EMAC_TX_BUFFER_START_ADDRESS, core)));
|
||||||
|
|
||||||
|
/* Get buffer read offset */
|
||||||
|
read_offset = read_emac(num_emac, EMAC_TX_CONTROL + EMAC_TX_BUFFER_READ_OFFSET, core);
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, (" TX Buffer read offset at: %d\n", read_offset));
|
||||||
|
|
||||||
|
/* Set buffer write offset to read offset */
|
||||||
|
write_emac(num_emac, EMAC_TX_CONTROL + EMAC_TX_BUFFER_WRITE_OFFSET, core, read_offset);
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, (" TX Buffer write offset set to: %d\n", read_emac(num_emac, EMAC_TX_CONTROL+ EMAC_TX_BUFFER_WRITE_OFFSET, core)));
|
||||||
|
rckemacif->tx_write_offset = read_offset;
|
||||||
|
|
||||||
|
/* Size */
|
||||||
|
write_emac(num_emac, EMAC_TX_CONTROL + EMAC_TX_BUFFER_SIZE, core, rckemacif->tx_buffer_max);
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, (" TX Size set to %d\n", read_emac(num_emac, EMAC_TX_CONTROL + EMAC_TX_BUFFER_SIZE, core)));
|
||||||
|
|
||||||
|
/* Route */
|
||||||
|
write_emac(num_emac, EMAC_TX_CONTROL + EMAC_TX_MODE, core, mode);
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, (" TX Mode set to %x\n", read_emac(num_emac, EMAC_TX_CONTROL + EMAC_TX_MODE, core)));
|
||||||
|
|
||||||
|
/* Activate network port by setting enable bit */
|
||||||
|
write_emac(num_emac, EMAC_TX_CONTROL + EMAC_TX_NETWORK_PORT_ENABLE, core, 0x01);
|
||||||
|
LWIP_DEBUGF(NETIF_DEBUG, (" TX Port enable set to %x\n", read_emac(num_emac, EMAC_TX_CONTROL + EMAC_TX_NETWORK_PORT_ENABLE, core)));
|
||||||
|
|
||||||
|
// set interrupt handler (INTR/LINT0)
|
||||||
|
irq_install_handler(125, rckemacif_handler);
|
||||||
|
|
||||||
|
/* Enable interrupt */
|
||||||
|
tmp = *((volatile int*) (FPGA_BASE + IRQ_MASK + core * 2 * 4));
|
||||||
|
*((volatile int*) (FPGA_BASE + IRQ_MASK + core * 2 * 4)) = tmp & ~(1 << num_emac);
|
||||||
|
*((volatile int*) (FPGA_BASE + IRQ_CONFIG + core * 4)) = EMAC_IRQ_CONFIG;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the snmp variables and counters inside the struct netif.
|
||||||
|
* The last argument should be replaced with your link speed, in units
|
||||||
|
* of bits per second.
|
||||||
|
*/
|
||||||
|
NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 1000 /* speed */);
|
||||||
|
|
||||||
|
/* administrative details */
|
||||||
|
netif->name[0] = 'e';
|
||||||
|
netif->name[1] = 'n';
|
||||||
|
netif->num = 0;
|
||||||
|
/* downward functions */
|
||||||
|
netif->output = etharp_output;
|
||||||
|
netif->linkoutput = rckemacif_output;
|
||||||
|
/* maximum transfer unit */
|
||||||
|
netif->mtu = 1500;
|
||||||
|
/* broadcast capability */
|
||||||
|
netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
|
||||||
|
/* hardware address length */
|
||||||
|
netif->hwaddr_len = 6;
|
||||||
|
|
||||||
|
rckemacif->ethaddr = (struct eth_addr *)netif->hwaddr;
|
||||||
|
|
||||||
|
return ERR_OK;
|
||||||
|
}
|
||||||
|
#endif
|
61
drivers/net/rckemac.h
Normal file
61
drivers/net/rckemac.h
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2011 Stefan Lankes, Chair for Operating Systems,
|
||||||
|
* RWTH Aachen University
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* This file is part of MetalSVM.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __HAVE_RCKEMAC_H__
|
||||||
|
#define __HAVE_RCKEMAC_H__
|
||||||
|
|
||||||
|
#include <metalsvm/stddef.h>
|
||||||
|
#include <metalsvm/mailbox.h>
|
||||||
|
|
||||||
|
#if defined(CONFIG_LWIP) && defined(CONFIG_ROCKCREEK)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper struct to hold private data used to operate your ethernet interface.
|
||||||
|
*/
|
||||||
|
typedef struct rckemacif {
|
||||||
|
struct eth_addr *ethaddr;
|
||||||
|
/* Add whatever per-interface state that is needed here. */
|
||||||
|
uint8_t* rx_buffer;
|
||||||
|
uint32_t rx_buffer_max;
|
||||||
|
uint32_t rx_read_offset;
|
||||||
|
uint8_t* tx_buffer;
|
||||||
|
uint32_t tx_buffer_max;
|
||||||
|
uint32_t tx_write_offset;
|
||||||
|
void* irq_address;
|
||||||
|
uint32_t core;
|
||||||
|
uint32_t num_emac;
|
||||||
|
mailbox_ptr_t mbox;
|
||||||
|
} rckemacif_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wait for incoming messages.
|
||||||
|
*
|
||||||
|
* poll = 0 : wait blocks until a message is received
|
||||||
|
* poll != 0: non-blocking wait
|
||||||
|
*/
|
||||||
|
err_t rckemacif_wait(struct netif* netif, uint32_t poll);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the eMAC network driver
|
||||||
|
*/
|
||||||
|
err_t rckemacif_init(struct netif* netif);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
88
include/metalsvm/config.h.example
Normal file
88
include/metalsvm/config.h.example
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2010 Stefan Lankes, Chair for Operating Systems,
|
||||||
|
* RWTH Aachen University
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* This file is part of MetalSVM.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CONFIG_H__
|
||||||
|
#define __CONFIG_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define METALSVM_VERSION "0.1"
|
||||||
|
#define MAX_TASKS 16
|
||||||
|
#define MAX_CORES 4
|
||||||
|
#define MAX_FNAME 128
|
||||||
|
#define DEFAULT_STACK_SIZE (32*1024)
|
||||||
|
#define KERNEL_STACK_SIZE 8192
|
||||||
|
#define KMSG_SIZE (128*1024)
|
||||||
|
#define PAGE_SIZE 4096
|
||||||
|
#define PAGE_SHIFT 12
|
||||||
|
#define CACHE_LINE 64
|
||||||
|
#define MAILBOX_SIZE 8
|
||||||
|
#define TIMER_FREQ 100 /* in HZ */
|
||||||
|
#define CLOCK_TICK_RATE 1193182 /* 8254 chip's internal oscillator frequency */
|
||||||
|
#define INT_SYSCALL 0x80
|
||||||
|
#define KERNEL_SPACE (1*1024*1024*1024)
|
||||||
|
#define VIDEO_MEM_ADDR 0xB8000 // the video memora address
|
||||||
|
|
||||||
|
#define BYTE_ORDER LITTLE_ENDIAN
|
||||||
|
|
||||||
|
/*
|
||||||
|
* address space / (page_size * sizeof(uint8_t))
|
||||||
|
* x86_32 => 4 GB / (4096 * 8)
|
||||||
|
*/
|
||||||
|
#define BITMAP_SIZE 1048576
|
||||||
|
|
||||||
|
#define CONFIG_PCI
|
||||||
|
#define CONFIG_LWIP
|
||||||
|
#define CONFIG_VGA
|
||||||
|
#define CONFIG_KEYBOARD
|
||||||
|
#define CONFIG_MULTIBOOT
|
||||||
|
//#define CONFIG_ROCKCREEK
|
||||||
|
|
||||||
|
// RCCE specific flags
|
||||||
|
#define SCC
|
||||||
|
#define MS_BAREMETAL
|
||||||
|
//#define GORY
|
||||||
|
#define SHMADD
|
||||||
|
#define SHMDBG
|
||||||
|
//#define SHMADD_CACHEABLE
|
||||||
|
/* default values for 16 GB system */
|
||||||
|
#define PRIVATE_MEM1_START 0x00000000
|
||||||
|
#define PRIVATE_MEM1_END 0x13FFFFFF
|
||||||
|
#define PRIVATE_MEM2_START 0xFF000000
|
||||||
|
#define PRIVATE_MEM2_END 0xFFFFFFFF
|
||||||
|
#define SCC_BOOTINFO 0x80000
|
||||||
|
|
||||||
|
#define BUILTIN_EXPECT(exp, b) __builtin_expect((exp), (b))
|
||||||
|
//#define BUILTIN_EXPECT(exp, b) (exp)
|
||||||
|
#define NORETURN __attribute__((noreturn))
|
||||||
|
#define STDCALL __attribute__((stdcall))
|
||||||
|
|
||||||
|
#define HAVE_ARCH_MEMSET
|
||||||
|
#define HAVE_ARCH_MEMCPY
|
||||||
|
#define HAVE_ARCH_STRLEN
|
||||||
|
#define HAVE_ARCH_STRCPY
|
||||||
|
#define HAVE_ARCH_STRNCPY
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
4
lwip/src/arch/Makefile
Normal file
4
lwip/src/arch/Makefile
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
C_source := sys_arch.c
|
||||||
|
MODULE := lwip_src_arch
|
||||||
|
|
||||||
|
include $(TOPDIR)/Makefile.inc
|
253
lwip/src/arch/sys_arch.c
Normal file
253
lwip/src/arch/sys_arch.c
Normal file
|
@ -0,0 +1,253 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2011 Stefan Lankes, Chair for Operating Systems,
|
||||||
|
* RWTH Aachen University
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* This file is part of MetalSVM.
|
||||||
|
*/
|
||||||
|
#include <metalsvm/stddef.h>
|
||||||
|
#include <metalsvm/time.h>
|
||||||
|
|
||||||
|
#include "lwip/debug.h"
|
||||||
|
#include "lwip/sys.h"
|
||||||
|
#include "lwip/opt.h"
|
||||||
|
#include "lwip/stats.h"
|
||||||
|
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FALSE
|
||||||
|
#define FALSE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Returns the current time in milliseconds,
|
||||||
|
* may be the same as sys_jiffies or at least based on it. */
|
||||||
|
u32_t
|
||||||
|
sys_now(void)
|
||||||
|
{
|
||||||
|
return (get_clock_tick() / TIMER_FREQ) * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32_t
|
||||||
|
sys_jiffies(void)
|
||||||
|
{
|
||||||
|
return (get_clock_tick() / TIMER_FREQ) * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !NO_SYS
|
||||||
|
|
||||||
|
/* sys_init(): init needed system resources
|
||||||
|
* Note: At the moment there are none
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
sys_init(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sleep for some ms. Timeouts are NOT processed while sleeping.
|
||||||
|
*
|
||||||
|
* @param ms number of milliseconds to sleep
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
sys_msleep(u32_t ms)
|
||||||
|
{
|
||||||
|
if (ms > 0) {
|
||||||
|
sys_sem_t delaysem;
|
||||||
|
err_t err = sys_sem_new(&delaysem, 0);
|
||||||
|
if (err == ERR_OK) {
|
||||||
|
sys_arch_sem_wait(&delaysem, ms);
|
||||||
|
sys_sem_free(&delaysem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sys_thread_new(): Spawns a new thread with given attributes as supportet
|
||||||
|
* Note: In MetalSVM this is realized as kernel tasks
|
||||||
|
*/
|
||||||
|
sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio)
|
||||||
|
{
|
||||||
|
tid_t tmp;
|
||||||
|
create_kernel_task(&tmp,thread,arg);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sys_sem_free(): destroy's given semaphore
|
||||||
|
* and releases system resources.
|
||||||
|
* This semaphore also gets invalid.
|
||||||
|
*/
|
||||||
|
void sys_sem_free(sys_sem_t* sem)
|
||||||
|
{
|
||||||
|
sem->valid = FALSE;
|
||||||
|
sem_destroy(&sem->sem);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sys_sem_valid(): returns if semaphore is valid
|
||||||
|
* at the moment
|
||||||
|
*/
|
||||||
|
int sys_sem_valid(sys_sem_t* sem)
|
||||||
|
{
|
||||||
|
return sem->valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sys_sem_new(): creates a new semaphre with given count.
|
||||||
|
* This semaphore becomes valid
|
||||||
|
*/
|
||||||
|
err_t sys_sem_new(sys_sem_t* sem,u8_t count)
|
||||||
|
{
|
||||||
|
sem->valid = TRUE;
|
||||||
|
return sem_init(&sem->sem,count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sys_sem_set_invalid(): this semapohore becomes invalid
|
||||||
|
* Note: this does not mean it is destroyed
|
||||||
|
*/
|
||||||
|
void sys_sem_set_invalid(sys_sem_t * sem)
|
||||||
|
{
|
||||||
|
sem->valid = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sys_sem_signal(): this semaphore is signaled
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void sys_sem_signal(sys_sem_t* sem)
|
||||||
|
{
|
||||||
|
sem_post(&sem->sem);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sys_arch_sem_wait): wait for the given semaphore for
|
||||||
|
* a given timeout
|
||||||
|
* Note: timeout = 0 means wait forever
|
||||||
|
*/
|
||||||
|
u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
if (!timeout)
|
||||||
|
return sem_wait(&sem->sem);
|
||||||
|
while (timeout)
|
||||||
|
{
|
||||||
|
err = sem_trywait(&sem->sem);
|
||||||
|
if (err != -1)
|
||||||
|
return err;
|
||||||
|
timeout--;
|
||||||
|
}
|
||||||
|
return SYS_ARCH_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sys_mbox_valid() : returns if the given mailbox
|
||||||
|
* is valid
|
||||||
|
*/
|
||||||
|
int sys_mbox_valid(sys_mbox_t * mbox)
|
||||||
|
{
|
||||||
|
return mbox->valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sys_arch_mbox_fetch(): wait for the given mailbox for a specified
|
||||||
|
* amount of time.
|
||||||
|
* Note: timeout = 0 means wait forever
|
||||||
|
*/
|
||||||
|
u32_t sys_arch_mbox_fetch(sys_mbox_t * mbox, void **msg, u32_t timeout)
|
||||||
|
{
|
||||||
|
if (!timeout)
|
||||||
|
return mailbox_ptr_fetch(&mbox->mailbox,msg);
|
||||||
|
|
||||||
|
while(timeout)
|
||||||
|
{
|
||||||
|
if (!mailbox_ptr_tryfetch(&mbox->mailbox,msg))
|
||||||
|
return 0;
|
||||||
|
timeout--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SYS_ARCH_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sys_mbox_free() : free the given mailbox, release the system resources
|
||||||
|
* and set mbox to invalid
|
||||||
|
*/
|
||||||
|
void sys_mbox_free(sys_mbox_t* mbox)
|
||||||
|
{
|
||||||
|
mbox->valid = FALSE;
|
||||||
|
mailbox_ptr_destroy(&mbox->mailbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sys_arch_mbox_tryfetch(): poll for new data in mailbox
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
u32_t sys_arch_mbox_tryfetch(sys_mbox_t* mbox, void** msg)
|
||||||
|
{
|
||||||
|
return mailbox_ptr_tryfetch(&mbox->mailbox,msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sys_mbox_new(): create a new mailbox with a minimum size of "size"
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
err_t sys_mbox_new(sys_mbox_t* mbox,int size)
|
||||||
|
{
|
||||||
|
mbox->valid = TRUE;
|
||||||
|
return mailbox_ptr_init(&mbox->mailbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sys_mbox_set_invalid(): set the given mailbox to invald
|
||||||
|
* Note: system resources are NOT freed
|
||||||
|
*/
|
||||||
|
void sys_mbox_set_invalid(sys_mbox_t* mbox)
|
||||||
|
{
|
||||||
|
mbox->valid = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sys_mbox_trypost(): try to post data to the mailbox
|
||||||
|
* Note: There is at the moment no try post implemented
|
||||||
|
* so we use the normal post instead
|
||||||
|
*/
|
||||||
|
err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
|
||||||
|
{
|
||||||
|
return mailbox_ptr_post(&mbox->mailbox,msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sys_mbox_post(): post new data to the mailbox
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void sys_mbox_post(sys_mbox_t* mbox,void* msg)
|
||||||
|
{
|
||||||
|
mailbox_ptr_post(&mbox->mailbox,msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sys_mutex_lock(): lock the given mutex
|
||||||
|
* Note: There is no specific mutex in MetalSVM
|
||||||
|
* so we use a semaphore with 1 element
|
||||||
|
*/
|
||||||
|
void sys_mutex_lock(sys_mutex_t* mutex)
|
||||||
|
{
|
||||||
|
sem_wait(mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sys_mutex_unlock(): unlock the given mutex
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void sys_mutex_unlock(sys_mutex_t* mutex)
|
||||||
|
{
|
||||||
|
sem_post(mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sys_mutex_new(): create a new mutex
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
err_t sys_mutex_new(sys_mutex_t * mutex)
|
||||||
|
{
|
||||||
|
sem_init(mutex,1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !NO_SYS */
|
Loading…
Add table
Reference in a new issue