Imported Genode release 11.11

This commit is contained in:
Genode Labs
2011-12-22 16:19:25 +01:00
committed by Christian Helmuth
parent 6bcc9aef0e
commit da4e1feaa5
2462 changed files with 320115 additions and 3 deletions

54
dde_ipxe/Makefile Normal file
View File

@@ -0,0 +1,54 @@
#
# \brief Fetch and patch iPXE source code
# \author Stefan Kalkowski
# \author Christian Helmuth
# \date 2011-08-12
#
VERBOSE ?= @
ECHO = @echo
GIT_URL = git://git.ipxe.org/ipxe.git
GIT_REV = 174df77359f22f3be2169e9bb04e8018015b5e94
CONTRIB_DIR = contrib
PATCH_FILE = patches/dde_ipxe.patch
#
# Print help information by default
#
help:
$(ECHO)
$(ECHO) "Prepare the dde_ipxe repository"
$(ECHO)
$(ECHO) "--- available commands ---"
$(ECHO) "prepare - fetch and patch iPXE source code"
$(ECHO) "clean - revert patch from iPXE souce code"
$(ECHO) "cleanall - remove iPXE souce code"
$(ECHO) "update-patch - updates patch for iPXE source code"
$(ECHO)
$(CONTRIB_DIR)/.git:
$(VERBOSE)git clone $(GIT_URL) $(CONTRIB_DIR)
prepare: $(CONTRIB_DIR)/.git clean
$(ECHO) "apply patch to '$(CONTRIB_DIR)/'"
$(VERBOSE)patch -p1 -d $(CONTRIB_DIR) -i $(realpath $(PATCH_FILE))
$(ECHO)
$(ECHO) "Preparation completed!"
$(ECHO) "Hint: don't forget to put '$(shell pwd)' "
$(ECHO) " as a repository into your build.conf"
$(ECHO)
update-patch:
$(ECHO) "producing a new diff and save it to '$(PATCH_FILE)'"
$(VERBOSE)(cd $(CONTRIB_DIR); LC_COLLATE=C git diff) > $(PATCH_FILE) || true
# $(VERBOSE)(cd $(CONTRIB_DIR); LC_COLLATE=C git diff) \
# | sed "s/\(^--- [^\t]*\).*/\\1/" \
# | sed "s/\(^+++ [^\t]*\).*/\\1/" \
# > $(PATCH_FILE) || true
clean:
$(VERBOSE)cd $(CONTRIB_DIR); git reset --hard $(GIT_REV)
$(VERBOSE)cd $(CONTRIB_DIR); git ls-files -o | xargs rm -rf
cleanall:
$(VERBOSE)rm -rf $(CONTRIB_DIR)

18
dde_ipxe/README Normal file
View File

@@ -0,0 +1,18 @@
This repository contains the Device Driver Environment for the
"donator OS" iPXE available from http://ipxe.org/.
For building DDE iPXE, you first need to fetch and patch the original
sources. The top-level makefile of this repository automates this
task. Just issue:
! make prepare
Now, you need to include the DDE iPXE repository into your Genode
build process. Just add the path to this directory to the
'REPOSITORIES' declaration of the 'etc/build.conf' file within your
build directory, for example
! REPOSITORIES += $(GENODE_DIR)/dde_ipxe
After successful build the DDE iPXE based ethernet driver is located
at 'bin/nic_drv'.

View File

@@ -0,0 +1,67 @@
/*
* \brief DDE iPXE NIC API
* \author Christian Helmuth
* \date 2010-09-05
*
*/
/*
* Copyright (C) 2010-2011 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _DDE_IPXE__NIC_H_
#define _DDE_IPXE__NIC_H_
/**
* Packet reception callback
*
* \param if_index index of the receiving network interface
* \param packet buffer containing the packet
* \param packet_len packet length
*/
typedef void (*dde_ipxe_nic_rx_cb)(unsigned if_index, const char *packet, unsigned packet_len);
/**
* Register packet reception callback
*
* \param cb new callback function
*
* \return old callback function pointer
*
* This registers a function pointer as rx callback. Incoming ethernet packets
* are passed to this function.
*/
extern dde_ipxe_nic_rx_cb dde_ipxe_nic_register_rx_callback(dde_ipxe_nic_rx_cb cb);
/**
* Send packet
*
* \param if_index index of the network interface to be used for sending
* \param packet buffer containing the packet
* \param packet_len packet length
*
* \return 0 on success, -1 otherwise
*/
extern int dde_ipxe_nic_tx(unsigned if_index, const char *packet, unsigned packet_len);
/**
* Get MAC address of device
*
* \param if_index index of the network interface
* \param out_mac_addr buffer for MAC address (buffer size must be 6 byte)
*
* \return 0 on success, -1 otherwise
*/
extern int dde_ipxe_nic_get_mac_addr(unsigned if_index, char *out_mac_addr);
/**
* Initialize network sub-system
*
* \return number of network devices
*/
extern int dde_ipxe_nic_init(void);
#endif /* _DDE_IPXE__NIC_H_ */

View File

@@ -0,0 +1,49 @@
LIB_DIR := $(REP_DIR)/src/lib/dde_ipxe
CONTRIB_DIR := $(REP_DIR)/contrib/src
LIBS = dde_kit dde_ipxe_support
SRC_C = nic.c dde.c dummies.c
SRC_C += $(addprefix core/, iobuf.c)
SRC_C += $(addprefix arch/x86/core/, x86_string.c)
SRC_C += $(addprefix arch/i386/core/, rdtsc_timer.c)
SRC_C += $(addprefix net/, ethernet.c netdevice.c nullnet.c eth_slow.c)
SRC_C += $(addprefix drivers/bus/, pciextra.c)
SRC_C += $(addprefix drivers/net/, pcnet32.c) # TODO rtl8139.c eepro100.c virtio-net.c ns8390.c
SRC_C += $(addprefix drivers/net/e1000/, \
e1000.c e1000_82540.c e1000_82541.c e1000_82542.c e1000_82543.c \
e1000_api.c e1000_mac.c e1000_main.c e1000_manage.c e1000_nvm.c \
e1000_phy.c)
SRC_C += $(addprefix drivers/net/e1000e/, \
e1000e.c e1000e_80003es2lan.c e1000e_82571.c e1000e_ich8lan.c \
e1000e_mac.c e1000e_main.c e1000e_manage.c e1000e_nvm.c \
e1000e_phy.c)
INC_DIR += $(LIB_DIR)/include \
$(CONTRIB_DIR)/include $(CONTRIB_DIR) \
$(CONTRIB_DIR)/arch/x86/include \
$(CONTRIB_DIR)/arch/i386/include \
$(CONTRIB_DIR)/arch/i386/include/pcbios
CC_WARN = -Wall -Wno-address
CC_OPT += $(addprefix -fno-builtin-, putchar toupper tolower)
CC_OPT += -DARCH=i386 -DPLATFORM=pcbios -include compiler.h -DOBJECT=$(notdir $(*:.o=))
#
# Enable debugging of any iPXE object here via '-Ddebug_<object name>=<level>'.
# 'level' may be one of 1, 3, 7.
#
CC_OPT += -Ddebug_lib=7
#CC_OPT += -Ddebug_e1000_main=7 -Ddebug_e1000_82540=7 -Ddebug_netdevice=7
#CC_OPT += -Ddebug_e1000=7 -Ddebug_e1000_82540=7 -Ddebug_e1000_api=7
#CC_OPT += -Ddebug_e1000_main=7 -Ddebug_e1000_manage=7
#CC_OPT += -Ddebug_e1000_phy=7
#CC_OPT += -Ddebug_netdevice=7
vpath nic.c $(LIB_DIR)
vpath dde.c $(LIB_DIR)
vpath dummies.c $(LIB_DIR)
vpath %.c $(CONTRIB_DIR)

View File

@@ -0,0 +1,5 @@
LIB_DIR := $(REP_DIR)/src/lib/dde_ipxe
SRC_CC = dde_support.cc
vpath dde_support.cc $(LIB_DIR)

View File

@@ -0,0 +1,42 @@
diff --git a/src/arch/i386/include/ipxe/rdtsc_timer.h b/src/arch/i386/include/ipxe/rdtsc_timer.h
index 472e140..d5095a7 100644
--- a/src/arch/i386/include/ipxe/rdtsc_timer.h
+++ b/src/arch/i386/include/ipxe/rdtsc_timer.h
@@ -30,7 +30,10 @@ static inline __always_inline unsigned long
TIMER_INLINE ( rdtsc, currticks ) ( void ) {
unsigned long ticks;
- __asm__ __volatile__ ( "rdtsc\n\t"
+ __asm__ __volatile__ (
+ "mfence\n\t"
+ "rdtsc\n\t"
+ "mfence\n\t"
"shrdl %1, %%edx, %%eax\n\t"
: "=a" ( ticks ) : "i" ( TSC_SHIFT ) : "edx" );
return ticks;
diff --git a/src/include/assert.h b/src/include/assert.h
index 40a00a2..8bae55c 100644
--- a/src/include/assert.h
+++ b/src/include/assert.h
@@ -29,7 +29,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
* to the printf symbol.
*/
extern int __attribute__ (( format ( printf, 1, 2 ) ))
-assert_printf ( const char *fmt, ... ) asm ( "printf" );
+assert_printf ( const char *fmt, ... ) asm ( "ipxe_printf" );
/**
* Assert a condition at run-time.
diff --git a/src/include/compiler.h b/src/include/compiler.h
index feea516..d5163b6 100644
--- a/src/include/compiler.h
+++ b/src/include/compiler.h
@@ -271,7 +271,7 @@ REQUEST_EXPANDED ( CONFIG_SYMBOL );
* to the printf symbol.
*/
extern int __attribute__ (( format ( printf, 1, 2 ) ))
-dbg_printf ( const char *fmt, ... ) asm ( "printf" );
+dbg_printf ( const char *fmt, ... ) asm ( "ipxe_printf" );
extern void dbg_autocolourise ( unsigned long id );
extern void dbg_decolourise ( void );

View File

@@ -0,0 +1,136 @@
/*
* \brief NIC driver based on iPXE
* \author Christian Helmuth
* \date 2011-11-17
*/
/*
* Copyright (C) 2011 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* Genode */
#include <base/env.h>
#include <base/sleep.h>
#include <base/printf.h>
#include <cap_session/connection.h>
#include <nic/component.h>
/* DDE */
extern "C" {
#include <dde_ipxe/nic.h>
}
namespace Ipxe {
class Driver : public Nic::Driver
{
public:
static Driver *instance;
static void dde_rx_handler(unsigned if_index,
const char *packet,
unsigned packet_len)
{
instance->rx_handler(packet, packet_len);
}
private:
Nic::Mac_address _mac_addr;
Nic::Rx_buffer_alloc &_alloc;
public:
Driver(Nic::Rx_buffer_alloc &alloc)
: _alloc(alloc)
{
PINF("--- init iPXE NIC");
int cnt = dde_ipxe_nic_init();
PINF(" number of devices: %d", cnt);
PINF("--- init rx_callbacks");
dde_ipxe_nic_register_rx_callback(dde_rx_handler);
PINF("--- get MAC address");
dde_ipxe_nic_get_mac_addr(1, _mac_addr.addr);
PINF(" %02x:%02x:%02x:%02x:%02x:%02x",
_mac_addr.addr[0], _mac_addr.addr[1], _mac_addr.addr[2],
_mac_addr.addr[3], _mac_addr.addr[4], _mac_addr.addr[5]);
}
void rx_handler(const char *packet, unsigned packet_len)
{
void *buffer = _alloc.alloc(packet_len);
Genode::memcpy(buffer, packet, packet_len);
_alloc.submit();
}
/***************************
** Nic::Driver interface **
***************************/
Nic::Mac_address mac_address() { return _mac_addr; }
void tx(char const *packet, Genode::size_t size)
{
if (dde_ipxe_nic_tx(1, packet, size))
PWRN("Sending packet failed!");
}
/******************************
** Irq_activation interface **
******************************/
void handle_irq(int) { /* not used */ }
};
class Driver_factory : public Nic::Driver_factory
{
Nic::Driver *create(Nic::Rx_buffer_alloc &alloc)
{
Driver::instance = new (Genode::env()->heap()) Ipxe::Driver(alloc);
return Driver::instance;
}
void destroy(Nic::Driver *)
{
Genode::destroy(Genode::env()->heap(), Driver::instance);
Driver::instance = 0;
}
};
} /* namespace Ipxe */
Ipxe::Driver * Ipxe::Driver::instance = 0;
int main(int, char **)
{
using namespace Genode;
printf("--- iPXE NIC driver started ---\n");
/**
* Factory used by 'Nic::Root' at session creation/destruction time
*/
static Ipxe::Driver_factory driver_factory;
enum { STACK_SIZE = 4096 };
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "nic_ep");
static Nic::Root nic_root(&ep, env()->heap(), driver_factory);
env()->parent()->announce(ep.manage(&nic_root));
sleep_forever();
return 0;
}

View File

@@ -0,0 +1,3 @@
TARGET := nic_drv
LIBS := cxx env signal server dde_ipxe_nic
SRC_CC = main.cc

View File

@@ -0,0 +1,350 @@
/*
* \brief DDE iPXE emulation implementation
* \author Christian Helmuth
* \date 2010-09-13
*/
/*
* Copyright (C) 2010-2011 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* DDE kit */
#include <dde_kit/memory.h>
#include <dde_kit/resources.h>
#include <dde_kit/pci.h>
#include <dde_kit/pgtab.h>
#include <dde_kit/lock.h>
#include <dde_kit/timer.h>
/* iPXE */
#include <stdlib.h>
#include <ipxe/io.h>
#include <ipxe/uaccess.h>
#include <ipxe/malloc.h>
#include <ipxe/pci.h>
#include <ipxe/settings.h>
#include <ipxe/netdevice.h>
#include "local.h"
/**********************************
** Memory pool in DDE kit slabs **
**********************************/
enum { SLAB_128, SLAB_256, SLAB_512, SLAB_1024, SLAB_2048, SLAB_4096, SLAB_20480, NUM_SLABS };
static struct dde_kit_slab *slabs[NUM_SLABS];
static inline void *alloc_from_slab(size_t size)
{
size_t *p = 0;
size_t alloc_size = size + sizeof(size_t);
if (alloc_size <= 128)
p = dde_kit_slab_alloc(slabs[SLAB_128]);
else if (alloc_size <= 256)
p = dde_kit_slab_alloc(slabs[SLAB_256]);
else if (alloc_size <= 512)
p = dde_kit_slab_alloc(slabs[SLAB_512]);
else if (alloc_size <= 1024)
p = dde_kit_slab_alloc(slabs[SLAB_1024]);
else if (alloc_size <= 2048)
p = dde_kit_slab_alloc(slabs[SLAB_2048]);
else if (alloc_size <= 4096)
p = dde_kit_slab_alloc(slabs[SLAB_4096]);
else if (alloc_size <= 20480)
p = dde_kit_slab_alloc(slabs[SLAB_20480]);
else
LOG("allocation of size %d too big", size);
if (p) {
*p = alloc_size;
p++;
}
return p;
}
static inline void free_in_slab(void *p0)
{
size_t *p = (size_t *)p0 - 1;
if (*p <= 128)
dde_kit_slab_free(slabs[SLAB_128], p);
else if (*p <= 256)
dde_kit_slab_free(slabs[SLAB_256], p);
else if (*p <= 512)
dde_kit_slab_free(slabs[SLAB_512], p);
else if (*p <= 1024)
dde_kit_slab_free(slabs[SLAB_1024], p);
else if (*p <= 2048)
dde_kit_slab_free(slabs[SLAB_2048], p);
else if (*p <= 4096)
dde_kit_slab_free(slabs[SLAB_4096], p);
else if (*p <= 20480)
dde_kit_slab_free(slabs[SLAB_20480], p);
else
LOG("deallocation at %p not possible", p0);
}
void slab_init(void)
{
slabs[SLAB_128] = dde_kit_slab_init(128);
slabs[SLAB_256] = dde_kit_slab_init(256);
slabs[SLAB_512] = dde_kit_slab_init(512);
slabs[SLAB_1024] = dde_kit_slab_init(1024);
slabs[SLAB_2048] = dde_kit_slab_init(2048);
slabs[SLAB_4096] = dde_kit_slab_init(4096);
slabs[SLAB_20480] = dde_kit_slab_init(20480);
}
/************
** stdlib **
************/
void *zalloc(size_t size)
{
char *buf = alloc_from_slab(size);
if (buf)
memset(buf, 0, size);
return buf;
}
void * malloc(size_t size)
{
return alloc_from_slab(size);
}
void free(void *p)
{
free_in_slab(p);
}
/*********************
** Time and Timers **
*********************/
void udelay (unsigned long usecs)
{
static int init = 0;
extern void __rdtsc_udelay(unsigned long usecs);
/*
* On first udelay, the rdtsc implementation is calibrated. Therefore, we
* force a delay of 10ms to get sane values.
*/
if (!init) {
__rdtsc_udelay(10000);
init = 1;
} else {
__rdtsc_udelay(usecs);
}
}
void mdelay (unsigned long msecs)
{
dde_kit_thread_msleep(msecs);
}
int ipxe_printf(const char *format, ...)
{
/* replace unsupported '%#' with 'x%' in format string */
char *new_format = (char *)malloc(strlen(format) + 1);
if (!new_format)
return -1;
memcpy(new_format, format, strlen(format) + 1);
{
int off;
char *f;
for (off = 0, f = new_format; *f; off++, f++)
if (f[0] == '%' && f[1] == '#') {
f[0] = 'x';
f[1] = '%';
}
}
va_list va;
va_start(va, format);
dde_kit_vprintf(new_format, va);
va_end(va);
free(new_format);
return 0;
}
/***********************************
** RAM and I/O memory management **
***********************************/
void iounmap(volatile const void *io_addr)
{
LOG("io_addr = %p", io_addr);
/* XXX DDE kit always releases the whole region */
dde_kit_release_mem((dde_kit_addr_t) io_addr, 1);
}
void * ioremap(unsigned long bus_addr, size_t len)
{
LOG("bus_addr = %p len = %x", (void *)bus_addr, len);
dde_kit_addr_t vaddr;
int ret = dde_kit_request_mem(bus_addr, len, 0, &vaddr);
return ret ? 0 : (void *)vaddr;
}
unsigned long user_to_phys(userptr_t userptr, off_t offset)
{
return dde_kit_pgtab_get_physaddr((void *)userptr) + offset;
}
userptr_t virt_to_user(volatile const void *addr)
{
return trivial_virt_to_user(addr);
}
unsigned long phys_to_bus(unsigned long phys_addr)
{
return phys_addr;
}
/*******************
** PCI subsystem **
*******************/
int pci_read_config_byte(struct pci_device *pci, unsigned int where, uint8_t *value)
{
dde_kit_pci_readb(PCI_BUS(pci->busdevfn), PCI_SLOT(pci->busdevfn), PCI_FUNC(pci->busdevfn),
where, value);
return 0;
}
int pci_read_config_word(struct pci_device *pci, unsigned int where, uint16_t *value)
{
dde_kit_pci_readw(PCI_BUS(pci->busdevfn), PCI_SLOT(pci->busdevfn), PCI_FUNC(pci->busdevfn),
where, value);
return 0;
}
int pci_read_config_dword(struct pci_device *pci, unsigned int where, uint32_t *value)
{
dde_kit_pci_readl(PCI_BUS(pci->busdevfn), PCI_SLOT(pci->busdevfn), PCI_FUNC(pci->busdevfn),
where, value);
return 0;
}
int pci_write_config_byte(struct pci_device *pci, unsigned int where, uint8_t value)
{
dde_kit_pci_writeb(PCI_BUS(pci->busdevfn), PCI_SLOT(pci->busdevfn), PCI_FUNC(pci->busdevfn),
where, value);
return 0;
}
int pci_write_config_word(struct pci_device *pci, unsigned int where, uint16_t value)
{
dde_kit_pci_writew(PCI_BUS(pci->busdevfn), PCI_SLOT(pci->busdevfn), PCI_FUNC(pci->busdevfn),
where, value);
return 0;
}
int pci_write_config_dword(struct pci_device *pci, unsigned int where, uint32_t value)
{
dde_kit_pci_writel(PCI_BUS(pci->busdevfn), PCI_SLOT(pci->busdevfn), PCI_FUNC(pci->busdevfn),
where, value);
return 0;
}
unsigned long pci_bar_start(struct pci_device *pci, unsigned int reg)
{
/*
* XXX We do not check for 64-bit BARs here.
*/
uint32_t val;
pci_read_config_dword(pci, reg, &val);
if ((val & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY)
return val & PCI_BASE_ADDRESS_MEM_MASK;
else
return val & PCI_BASE_ADDRESS_IO_MASK;
}
/* drivers/bus/pci.c */
void adjust_pci_device ( struct pci_device *pci ) {
unsigned short new_command, pci_command = 0;
pci_read_config_word(pci, PCI_COMMAND, &pci_command);
new_command = pci_command | PCI_COMMAND_MASTER | PCI_COMMAND_MEM | PCI_COMMAND_IO;
if (pci_command != new_command) {
LOG("PCI BIOS has not enabled device " FMT_BUSDEVFN "! "
"Updating PCI command %04x->%04x\n", PCI_BUS(pci->busdevfn),
PCI_SLOT(pci->busdevfn), PCI_FUNC (pci->busdevfn),
pci_command, new_command);
pci_write_config_word(pci, PCI_COMMAND, new_command);
}
unsigned char pci_latency;
pci_read_config_byte ( pci, PCI_LATENCY_TIMER, &pci_latency);
if ( pci_latency < 32 ) {
LOG("PCI device " FMT_BUSDEVFN " latency timer is unreasonably "
"low at %d. Setting to 32.\n", PCI_BUS(pci->busdevfn),
PCI_SLOT ( pci->busdevfn ), PCI_FUNC ( pci->busdevfn ),
pci_latency );
pci_write_config_byte ( pci, PCI_LATENCY_TIMER, 32);
}
}
/***********************
** Device management **
***********************/
int register_settings(struct settings *settings, struct settings *parent,
const char *name)
{
return 0;
}
void unregister_settings(struct settings *settings) { }
void ref_increment(struct refcnt *refcnt) { }
void ref_decrement(struct refcnt *refcnt) { }

View File

@@ -0,0 +1,86 @@
/*
* \brief Functions not offered by Genode's DDE-kit
* \author Sebastian Sumpf
* \date 2010-10-21
*/
/*
* Copyright (C) 2010-2011 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <base/allocator_avl.h>
#include <base/env.h>
#include <base/printf.h>
#include <dataspace/client.h>
#include <timer_session/connection.h>
#include <util/misc_math.h>
extern "C" {
#include <dde_kit/pgtab.h>
}
using namespace Genode;
/*******************************************
** Support for aligned memory allocation **
*******************************************/
enum { BACKING_STORE_SIZE = 1024 * 1024 };
Allocator_avl *allocator()
{
static Allocator_avl _avl(env()->heap());
return &_avl;
}
void __attribute__((constructor)) init()
{
try {
Dataspace_capability ds_cap = env()->ram_session()->alloc(BACKING_STORE_SIZE);
addr_t base = (addr_t)env()->rm_session()->attach(ds_cap);
/* add to allocator */
allocator()->add_range(base, BACKING_STORE_SIZE);
/* add to DDE-kit page tables */
addr_t phys = Dataspace_client(ds_cap).phys_addr();
dde_kit_pgtab_set_region_with_size((void *)base, phys, BACKING_STORE_SIZE);
} catch (...) {
PERR("Initialization of block memory failed!");
}
}
extern "C" void *alloc_memblock(size_t size, size_t align)
{
void *ptr;
allocator()->alloc_aligned(size, &ptr, log2(align));
return ptr;
}
extern "C" void free_memblock(void *p, size_t size)
{
allocator()->free(p, size);
}
/***********
** Timer **
***********/
extern "C" void timer2_udelay(unsigned long usecs)
{
/*
* This function is called only once during rdtsc calibration (usecs will be
* 10000, see dde.c 'udelay'. We do not use DDE timers here, since Genode's
* timer connection is the precised one around.
*/
Timer::Connection timer;
timer.msleep(usecs / 1000);
}

View File

@@ -0,0 +1,30 @@
/*
* \brief DDE iPXE dummy implementations
* \author Christian Helmuth
* \date 2010-09-13
*/
/*
* Copyright (C) 2010-2011 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include "local.h"
int snprintf(char *buf, __SIZE_TYPE__ size, const char *fmt, ...) { TRACE; return 0; }
void clear_settings() { TRACE; }
void netdev_settings_operations() { TRACE; }
void dbg_autocolourise(unsigned long id) { }
void dbg_decolourise() { }
void strerror() { TRACE; }
int strcmp(const char *s1, const char *s2) { TRACE; return 0; }
/* for eepro100.c */
void init_spi_bit_basher() { TRACE; }
void nvs_read() { TRACE; }
void threewire_detect_address_len() { TRACE; }
void threewire_read() { TRACE; }
void threewire_write() { TRACE; }

View File

@@ -0,0 +1 @@
#include_next <bits/byteswap.h>

View File

@@ -0,0 +1 @@
#include_next <bits/compiler.h>

View File

@@ -0,0 +1 @@
#include_next <bits/endian.h>

View File

@@ -0,0 +1 @@
#include_next <bits/errfile.h>

View File

@@ -0,0 +1 @@
#include <env_dde_kit.h>

View File

@@ -0,0 +1,3 @@
#include <ipxe/io.h> /* some drivers do rely on this depency :-( */
#include <env_dde_kit.h>

View File

@@ -0,0 +1 @@
#include_next <bits/stdint.h>

View File

@@ -0,0 +1 @@
#include_next <bits/string.h>

View File

@@ -0,0 +1,6 @@
#include <ipxe/rdtsc_timer.h>
static inline unsigned long currticks ( void )
{
return __rdtsc_currticks();
}

View File

@@ -0,0 +1 @@
#include <env_dde_kit.h>

View File

@@ -0,0 +1,68 @@
#ifndef __ENV_DDE_KIT_H__
#define __ENV_DDE_KIT_H__
/* bits/io.h */
#include <dde_kit/resources.h>
static inline uint8_t inb(volatile uint8_t *io_addr)
{
return dde_kit_inb((dde_kit_addr_t) io_addr);
}
static inline uint16_t inw(volatile uint16_t *io_addr)
{
return dde_kit_inw((dde_kit_addr_t) io_addr);
}
static inline uint32_t inl(volatile uint32_t *io_addr)
{
return dde_kit_inl((dde_kit_addr_t) io_addr);
}
static inline void outb(uint8_t data, volatile uint8_t *io_addr)
{
dde_kit_outb((dde_kit_addr_t) io_addr, data);
}
static inline void outw(uint16_t data, volatile uint16_t *io_addr)
{
dde_kit_outw((dde_kit_addr_t) io_addr, data);
}
static inline void outl(uint32_t data, volatile uint32_t *io_addr)
{
dde_kit_outl((dde_kit_addr_t) io_addr, data);
}
static inline uint16_t readw(volatile uint16_t *io_addr)
{
return *io_addr;
}
static inline uint32_t readl(volatile uint32_t *io_addr)
{
return *io_addr;
}
static inline void writew(uint16_t data, volatile uint16_t *io_addr)
{
*io_addr = data;
}
static inline void writel(uint32_t data, volatile uint32_t *io_addr)
{
*io_addr = data;
}
static inline void mb(void)
{
asm volatile ("lock; addl $0, 0(%%esp)" : : : "memory");
}
#endif /* __ENV_DDE_KIT_H__ */

View File

@@ -0,0 +1,28 @@
/*
* \brief DDE iPXE local helpers
* \author Christian Helmuth
* \date 2010-09-13
*/
/*
* Copyright (C) 2010-2011 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <dde_kit/assert.h>
#include <dde_kit/printf.h>
#define FMT_BUSDEVFN "%02x:%02x.%x"
#define LOG(fmt, ...) \
do { \
dde_kit_log(1, "\033[36m" fmt "\033[0m", ##__VA_ARGS__ ); \
} while (0)
#define TRACE dde_kit_printf("\033[35m%s not implemented\033[0m\n", __func__)
#define ASSERT(x) dde_kit_assert(x)
extern void slab_init(void);

View File

@@ -0,0 +1,337 @@
/*
* \brief DDE iPXE NIC API implementation
* \author Christian Helmuth
* \date 2010-09-13
*/
/*
* Copyright (C) 2010-2011 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* DDE kit */
#include <dde_kit/pci.h>
#include <dde_kit/lock.h>
#include <dde_kit/semaphore.h>
#include <dde_kit/timer.h>
#include <dde_kit/interrupt.h>
#include <dde_kit/dde_kit.h>
/* iPXE */
#include <stdlib.h>
#include <ipxe/netdevice.h>
#include <ipxe/pci.h>
#include <ipxe/iobuf.h>
#include <dde_ipxe/nic.h>
#include "local.h"
/**
* DDE iPXE mutual exclusion lock
*/
static struct dde_kit_lock *ipxe_lock;
#define ENTER dde_kit_lock_lock(ipxe_lock)
#define LEAVE dde_kit_lock_unlock(ipxe_lock)
/**
* Bottom-half activation semaphore
*/
static struct dde_kit_sem *bh_sema;
/**
* Network device driven by iPXE
*/
static struct net_device *net_dev;
/**
* RX callback function pointer
*/
static dde_ipxe_nic_rx_cb rx_callback;
/**
* Known iPXE driver structures (located in the driver binaries)
*/
extern struct pci_driver
e1000_82540_driver, e1000_82541_driver, e1000_82542_driver, e1000_82543_driver,
e1000e_80003es2lan_driver, e1000e_82571_driver, e1000e_ich8lan_driver,
// ifec_driver,
// rtl8139_driver,
// nepci_driver,
pcnet32_driver;
/**
* Driver database (used for probing)
*/
static struct pci_driver *pci_drivers[] = {
&e1000_82540_driver, &e1000_82541_driver, &e1000_82542_driver, &e1000_82543_driver,
&e1000e_80003es2lan_driver, &e1000e_82571_driver, &e1000e_ich8lan_driver,
// &ifec_driver,
// &rtl8139_driver,
// &nepci_driver,
&pcnet32_driver
};
/**
* Update BARs of PCI device
*/
static void pci_read_bases(struct pci_device *pci_dev)
{
uint32_t bar;
int reg;
for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4) {
pci_read_config_dword(pci_dev, reg, &bar);
if (bar & PCI_BASE_ADDRESS_SPACE_IO) {
if (!pci_dev->ioaddr) {
pci_dev->ioaddr = bar & PCI_BASE_ADDRESS_IO_MASK;
dde_kit_addr_t base = bar & PCI_BASE_ADDRESS_IO_MASK;
dde_kit_size_t size = pci_bar_size(pci_dev, reg);
dde_kit_request_io(base, size);
}
} else {
if (!pci_dev->membase)
pci_dev->membase = bar & PCI_BASE_ADDRESS_MEM_MASK;
/* Skip next BAR if 64-bit */
if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64)
reg += 4;
}
}
}
/**
* Probe one PCI device
*/
static int probe_pci_device(struct pci_device *pci_dev)
{
int j;
for (j = 0; j < sizeof(pci_drivers)/sizeof(*pci_drivers); j++) {
struct pci_driver *driver = pci_drivers[j];
int i;
for (i = 0; i < driver->id_count; i++) {
struct pci_device_id *id = &driver->ids[i];
if ((id->vendor != PCI_ANY_ID) && (id->vendor != pci_dev->vendor))
continue;
if ((id->device != PCI_ANY_ID) && (id->device != pci_dev->device))
continue;
pci_set_driver(pci_dev, driver, id);
LOG("using driver %s", pci_dev->id->name);
int ret = driver->probe(pci_dev);
if (ret != 0) {
LOG("probe failed for %s", pci_dev->id->name);
continue;
}
return 0;
}
}
LOG("no driver found");
return -1;
}
enum { NO_DEVICE_FOUND = ~0U };
/**
* Scan the PCI bus
*
* \return PCI location of NIC found; NO_DEVICE_FOUND otherwise
*/
static unsigned scan_pci(void)
{
int ret, bus = 0, dev = 0, fun = 0;
for (ret = dde_kit_pci_first_device(&bus, &dev, &fun);
ret == 0;
ret = dde_kit_pci_next_device(&bus, &dev, &fun)) {
dde_kit_uint32_t class_code;
dde_kit_pci_readl(bus, dev, fun, PCI_CLASS_REVISION, &class_code);
class_code >>= 8;
if (PCI_BASE_CLASS(class_code) != PCI_BASE_CLASS_NETWORK)
continue;
dde_kit_uint16_t vendor, device;
dde_kit_pci_readw(bus, dev, fun, PCI_VENDOR_ID, &vendor);
dde_kit_pci_readw(bus, dev, fun, PCI_DEVICE_ID, &device);
dde_kit_uint8_t rev, irq;
dde_kit_pci_readb(bus, dev, fun, PCI_REVISION_ID, &rev);
dde_kit_pci_readb(bus, dev, fun, PCI_INTERRUPT_LINE, &irq);
LOG("Found: " FMT_BUSDEVFN " %04x:%04x (rev %02x) IRQ %02x",
bus, dev, fun, vendor, device, rev, irq);
struct pci_device *pci_dev = zalloc(sizeof(*pci_dev));
ASSERT(pci_dev != 0);
pci_dev->busdevfn = PCI_BUSDEVFN(bus, dev, fun);
pci_dev->vendor = vendor;
pci_dev->device = device;
pci_dev->class = class_code;
pci_dev->irq = irq;
pci_read_bases(pci_dev);
pci_dev->dev.desc.bus_type = BUS_TYPE_PCI;
pci_dev->dev.desc.location = pci_dev->busdevfn;
pci_dev->dev.desc.vendor = pci_dev->vendor;
pci_dev->dev.desc.device = pci_dev->device;
pci_dev->dev.desc.class = pci_dev->class;
pci_dev->dev.desc.ioaddr = pci_dev->ioaddr;
pci_dev->dev.desc.irq = pci_dev->irq;
/* we found our device -> break loop */
if (!probe_pci_device(pci_dev))
return pci_dev->dev.desc.location;
/* free device if no driver was found */
free(pci_dev);
}
return NO_DEVICE_FOUND;
}
/**
* IRQ handler registered at DDE kit
*/
static void irq_handler(void *p)
{
ENTER;
netdev_poll(net_dev);
dde_kit_sem_up(bh_sema);
LEAVE;
}
/**
* Bottom-half handler executed in separate thread
*
* Calls RX callback if appropriate.
*/
static void bh_handler(void *p)
{
while (1) {
dde_kit_sem_down(bh_sema);
ENTER;
struct io_buffer *iobuf;
while ((iobuf = netdev_rx_dequeue(net_dev))) {
LEAVE;
if (rx_callback)
rx_callback(1, iobuf->data, iob_len(iobuf));
ENTER;
free_iob(iobuf);
}
LEAVE;
}
}
/************************
** API implementation **
************************/
dde_ipxe_nic_rx_cb dde_ipxe_nic_register_rx_callback(dde_ipxe_nic_rx_cb cb)
{
ENTER;
dde_ipxe_nic_rx_cb old = rx_callback;
rx_callback = cb;
LEAVE;
return old;
}
int dde_ipxe_nic_tx(unsigned if_index, const char *packet, unsigned packet_len)
{
if (if_index != 1)
return -1;
ENTER;
struct io_buffer *iobuf = alloc_iob(packet_len);
LEAVE;
memcpy(iob_put(iobuf, packet_len), packet, packet_len);
ENTER;
netdev_poll(net_dev);
netdev_tx(net_dev, iob_disown(iobuf));
LEAVE;
return 0;
}
int dde_ipxe_nic_get_mac_addr(unsigned if_index, char *out_mac_addr)
{
if (if_index != 1)
return -1;
ENTER;
out_mac_addr[0] = net_dev->hw_addr[0];
out_mac_addr[1] = net_dev->hw_addr[1];
out_mac_addr[2] = net_dev->hw_addr[2];
out_mac_addr[3] = net_dev->hw_addr[3];
out_mac_addr[4] = net_dev->hw_addr[4];
out_mac_addr[5] = net_dev->hw_addr[5];
LEAVE;
return 0;
}
int dde_ipxe_nic_init(void)
{
dde_kit_init();
dde_kit_timer_init(0, 0);
dde_kit_pci_init();
dde_kit_lock_init(&ipxe_lock);
slab_init();
ENTER;
/* scan all pci devices and drivers */
unsigned location = scan_pci();
if (location == NO_DEVICE_FOUND)
return 0;
/* find and open iPXE NIC device */
net_dev = find_netdev_by_location(BUS_TYPE_PCI, location);
if (netdev_open(net_dev)) {
LOG("opening device " FMT_BUSDEVFN " failed",
PCI_BUS(net_dev->dev->desc.location),
PCI_SLOT(net_dev->dev->desc.location),
PCI_FUNC(net_dev->dev->desc.location));
return 0;
}
/* initialize IRQ handler and enable interrupt/bottom-half handling */
bh_sema = dde_kit_sem_init(0);
dde_kit_thread_create(bh_handler, 0, "bh_handler");
int err = dde_kit_interrupt_attach(net_dev->dev->desc.irq, 0,
0, irq_handler, 0);
if (err) {
LOG("attaching to IRQ %02x failed", net_dev->dev->desc.irq);
return 0;
}
netdev_irq(net_dev, 1);
LEAVE;
/* always report 1 device was found */
return 1;
}