dde_ipxe: remove dde_kit

A long long time ago, in a galaxy^W^W^W we used DDE kit to ease the
porting of purely C based drivers. By now it became clear, that we
do not gain that much by following this approach. DDE kit contains
much generic functionality, which is not used or rather not needed
by most ported drivers. Hence, we implement a slim C wrapper on top
of Genode's C++ APIs, that is especially tailored to the driver.

In addition to removing the dependency on DDE kit, the iPXE driver
now uses the server framework and the newly introduced signal based
IRQ handling.

Issue #1456.
This commit is contained in:
Josef Söntgen 2015-03-26 13:47:14 +01:00 committed by Christian Helmuth
parent 09e96dfdcd
commit 9606abc146
17 changed files with 956 additions and 460 deletions

View File

@ -15,6 +15,10 @@
#ifndef _DDE_IPXE__NIC_H_
#define _DDE_IPXE__NIC_H_
#ifdef __cplusplus
extern "C" {
#endif
/**
* Link-state change callback
*/
@ -74,8 +78,14 @@ extern int dde_ipxe_nic_link_state(unsigned if_index);
/**
* Initialize network sub-system
*
* \param ep pointer to Server::Entrypoint
*
* \return number of network devices
*/
extern int dde_ipxe_nic_init(void);
extern int dde_ipxe_nic_init(void *ep);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* _DDE_IPXE__NIC_H_ */

View File

@ -1,8 +1,7 @@
LIB_DIR := $(REP_DIR)/src/lib/dde_ipxe
IPXE_CONTRIB_DIR := $(call select_from_ports,dde_ipxe)/src/lib/dde_ipxe/src
LIBS = dde_kit dde_ipxe_support
SRC_CC = dde_support.cc
SRC_C = nic.c dde.c dummies.c
SRC_C += $(addprefix core/, iobuf.c string.c bitops.c list.c random.c)
@ -21,7 +20,7 @@ INC_DIR += $(IPXE_CONTRIB_DIR)/include $(IPXE_CONTRIB_DIR) \
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=))
CC_C_OPT += -DARCH=i386 -DPLATFORM=pcbios -include compiler.h -DOBJECT=$(notdir $(*:.o=))
#
# Enable debugging of any iPXE object here via '-Ddebug_<object name>=<level>'.
@ -35,6 +34,7 @@ CC_OPT += -Ddebug_lib=7
vpath nic.c $(LIB_DIR)
vpath dde.c $(LIB_DIR)
vpath dummies.c $(LIB_DIR)
vpath dde_support.cc $(LIB_DIR)
vpath %.c $(IPXE_CONTRIB_DIR)

View File

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

View File

@ -14,29 +14,3 @@ index 472e140..d5095a7 100644
"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 655cbdc..a8016c8 100644
--- a/src/include/assert.h
+++ b/src/include/assert.h
@@ -31,7 +31,7 @@ extern unsigned int assertion_failures;
* 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 e555924..b430e37 100644
--- a/src/include/compiler.h
+++ b/src/include/compiler.h
@@ -263,7 +263,7 @@ REQUEST_EXPANDED ( CONFIG_SYMBOL );
/** printf() for debugging */
extern void __attribute__ (( format ( printf, 1, 2 ) ))
-dbg_printf ( const char *fmt, ... );
+dbg_printf ( const char *fmt, ... ) asm ( "ipxe_printf" );
extern void dbg_autocolourise ( unsigned long id );
extern void dbg_decolourise ( void );
extern void dbg_hex_dump_da ( unsigned long dispaddr,

View File

@ -1 +1 @@
7f8c6baa921f6939d49c2804b5b8c4b16981f261
dd11e6a750e68271c2e7d293e9c1d272f7bc78e0

View File

@ -17,11 +17,9 @@
#include <base/printf.h>
#include <cap_session/connection.h>
#include <nic/component.h>
#include <os/server.h>
/* DDE */
extern "C" {
#include <dde_ipxe/nic.h>
}
namespace Ipxe {
@ -34,6 +32,8 @@ namespace Ipxe {
private:
Server::Entrypoint &_ep;
Nic::Mac_address _mac_addr;
Nic::Rx_buffer_alloc &_alloc;
Nic::Driver_notification &_notify;
@ -49,11 +49,12 @@ namespace Ipxe {
public:
Driver(Nic::Rx_buffer_alloc &alloc, Nic::Driver_notification &notify)
: _alloc(alloc), _notify(notify)
Driver(Server::Entrypoint &ep, Nic::Rx_buffer_alloc &alloc,
Nic::Driver_notification &notify)
: _ep(ep), _alloc(alloc), _notify(notify)
{
PINF("--- init iPXE NIC");
int cnt = dde_ipxe_nic_init();
int cnt = dde_ipxe_nic_init(&ep);
PINF(" number of devices: %d", cnt);
PINF("--- init callbacks");
@ -104,47 +105,58 @@ namespace Ipxe {
void handle_irq(int) { /* not used */ }
};
class Driver_factory : public Nic::Driver_factory
{
Nic::Driver *create(Nic::Rx_buffer_alloc &alloc,
Nic::Driver_notification &notify)
{
Driver::instance = new (Genode::env()->heap()) Ipxe::Driver(alloc, notify);
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 **)
struct Main
{
using namespace Genode;
Server::Entrypoint &ep;
Genode::Sliced_heap sliced_heap;
printf("--- iPXE NIC driver started ---\n");
struct Factory : public Nic::Driver_factory
{
Server::Entrypoint &ep;
/**
* Factory used by 'Nic::Root' at session creation/destruction time
*/
static Ipxe::Driver_factory driver_factory;
Factory(Server::Entrypoint &ep) : ep(ep) { }
enum { STACK_SIZE = 2*sizeof(addr_t)*1024 };
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "nic_ep");
Nic::Driver *create(Nic::Rx_buffer_alloc &alloc,
Nic::Driver_notification &notify)
{
Ipxe::Driver::instance = new (Genode::env()->heap()) Ipxe::Driver(ep, alloc, notify);
return Ipxe::Driver::instance;
}
static Nic::Root nic_root(&ep, env()->heap(), driver_factory);
env()->parent()->announce(ep.manage(&nic_root));
void destroy(Nic::Driver *)
{
Genode::destroy(Genode::env()->heap(), Ipxe::Driver::instance);
Ipxe::Driver::instance = 0;
}
} factory;
sleep_forever();
return 0;
Nic::Root root;
Main(Server::Entrypoint &ep)
:
ep(ep),
sliced_heap(Genode::env()->ram_session(), Genode::env()->rm_session()),
factory(ep),
root(&ep.rpc_ep(), &sliced_heap, factory)
{
PINF("--- iPXE NIC driver started ---\n");
Genode::env()->parent()->announce(ep.manage(root));
}
};
/************
** Server **
************/
namespace Server {
char const *name() { return "nic_drv_ep"; }
size_t stack_size() { return 2*1024*sizeof(long); }
void construct(Entrypoint &ep) { static Main server(ep); }
}

View File

@ -1,3 +1,3 @@
TARGET = nic_drv
LIBS = dde_ipxe_nic
LIBS = base server dde_ipxe_nic
SRC_CC = main.cc

View File

@ -11,12 +11,13 @@
* under the terms of the GNU General Public License version 2.
*/
/* Genode */
/* Genode include */
#include <base/env.h>
#include <base/sleep.h>
#include <base/printf.h>
#include <cap_session/connection.h>
#include <nic/component.h>
#include <os/server.h>
#include <nic/stat.h>
#include <nic/packet_allocator.h>
@ -56,11 +57,12 @@ namespace Ipxe {
public:
Driver(Nic::Rx_buffer_alloc &alloc, Nic::Driver_notification &notify)
Driver(Server::Entrypoint &ep, Nic::Rx_buffer_alloc &alloc,
Nic::Driver_notification &notify)
: _alloc(alloc), _notify(notify), _stat(_timer)
{
PINF("--- init iPXE NIC");
int cnt = dde_ipxe_nic_init();
int cnt = dde_ipxe_nic_init(&ep);
PINF(" number of devices: %d", cnt);
PINF("--- init callbacks");
@ -119,57 +121,61 @@ namespace Ipxe {
void handle_irq(int) { /* not used */ }
};
class Driver_factory : public Nic::Driver_factory
{
Nic::Driver *create(Nic::Rx_buffer_alloc &alloc, Nic::Driver_notification &notify)
{
Driver::instance = new (Genode::env()->heap()) Ipxe::Driver(alloc, notify);
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 **)
struct Main
{
using namespace Genode;
Server::Entrypoint &ep;
Genode::Sliced_heap sliced_heap;
printf("--- iPXE NIC driver started ---\n");
struct Factory : public Nic::Driver_factory
{
Server::Entrypoint &ep;
/**
* Factory used by 'Nic::Root' at session creation/destruction time
*/
static Ipxe::Driver_factory driver_factory;
Factory(Server::Entrypoint &ep) : ep(ep) { }
enum { STACK_SIZE = 2*sizeof(addr_t)*1024 };
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "nic_ep");
Nic::Driver *create(Nic::Rx_buffer_alloc &alloc,
Nic::Driver_notification &notify)
{
Ipxe::Driver::instance = new (Genode::env()->heap()) Ipxe::Driver(ep, alloc, notify);
return Ipxe::Driver::instance;
}
static Nic::Root nic_root(&ep, env()->heap(), driver_factory);
env()->parent()->announce(ep.manage(&nic_root));
void destroy(Nic::Driver *)
{
Genode::destroy(Genode::env()->heap(), Ipxe::Driver::instance);
Ipxe::Driver::instance = 0;
}
} factory;
/*
Genode::size_t tx_buf_size = 64*1024;
Genode::size_t rx_buf_size = 64*1024;
session("ram_quota=%zd, tx_buf_size=%zd, rx_buf_size=%zd",
6*4096 + tx_buf_size + rx_buf_size,
tx_buf_size, rx_buf_size))
*/
nic_root.session("ram_quota=155648, tx_buf_size=65536, rx_buf_size=65536",
Affinity());
Nic::Root root;
sleep_forever();
return 0;
Main(Server::Entrypoint &ep)
:
ep(ep),
sliced_heap(Genode::env()->ram_session(), Genode::env()->rm_session()),
factory(ep),
root(&ep.rpc_ep(), &sliced_heap, factory)
{
PINF("--- iPXE NIC driver started ---\n");
Genode::env()->parent()->announce(ep.manage(root));
root.session("ram_quota=155648, tx_buf_size=65536, rx_buf_size=65536",
Genode::Affinity());
}
};
/************
** Server **
************/
namespace Server {
char const *name() { return "nic_drv_stat_ep"; }
size_t stack_size() { return 2*1024*sizeof(long); }
void construct(Entrypoint &ep) { static Main server(ep); }
}

View File

@ -1,3 +1,3 @@
TARGET = nic_drv_stat
LIBS = dde_ipxe_nic net-stat
LIBS = base server dde_ipxe_nic net-stat
SRC_CC = main.cc

View File

@ -1,24 +1,17 @@
/*
* \brief DDE iPXE emulation implementation
* \author Christian Helmuth
* \author Josef Soentgen
* \date 2010-09-13
*/
/*
* Copyright (C) 2010-2013 Genode Labs GmbH
* Copyright (C) 2010-2015 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>
@ -28,92 +21,35 @@
#include <ipxe/settings.h>
#include <ipxe/netdevice.h>
#include <ipxe/timer2.h>
/* local includes */
#include <dde_support.h>
#include "local.h"
/***********************************
** Wrapper to DDE support in C++ **
***********************************/
#include "dde_support.h"
void *alloc_memblock(size_t size, size_t align, size_t offset) { return dde_alloc_memblock(size, align, offset); }
void free_memblock(void *p, size_t size) { dde_free_memblock(p, size); }
void timer2_udelay(unsigned long usecs) { dde_timer2_udelay(usecs); }
/**********************************
** 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 %zd too big", size);
if (p) {
*p = alloc_size;
p++;
}
return p;
}
#define PDBG(fmt, ...) dde_printf(fmt "\n", ##__VA_ARGS__)
static inline void free_in_slab(void *p0)
{
size_t *p = (size_t *)p0 - 1;
/***************************
** DMA memory allocation **
***************************/
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 *alloc_memblock(size_t size, size_t align, size_t offset) {
return dde_dma_alloc(size, align, offset); }
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);
}
void free_memblock(void *p, size_t size) {
dde_dma_free(p, size); }
/**********************
** Slab memory pool **
**********************/
static inline void *alloc_from_slab(size_t size) {
return dde_slab_alloc(size); }
static inline void free_in_slab(void *p) {
dde_slab_free(p); }
/************
@ -131,23 +67,23 @@ void *zalloc(size_t size)
}
void * malloc(size_t size)
{
return alloc_from_slab(size);
}
void *malloc(size_t size) {
return alloc_from_slab(size); }
void free(void *p)
{
free_in_slab(p);
}
void free(void *p) {
free_in_slab(p); }
/*********************
** Time and Timers **
*********************/
void udelay (unsigned long usecs)
void timer2_udelay(unsigned long usecs) {
dde_udelay(usecs); }
void udelay(unsigned long usecs)
{
static int init = 0;
@ -166,13 +102,11 @@ void udelay (unsigned long usecs)
}
void mdelay (unsigned long msecs)
{
dde_kit_thread_msleep(msecs);
}
void mdelay(unsigned long msecs) {
dde_mdelay(msecs); }
int ipxe_printf(const char *format, ...)
int printf(const char *format, ...)
{
/* replace unsupported '%#' with 'x%' in format string */
char *new_format = (char *)malloc(strlen(format) + 1);
@ -192,7 +126,7 @@ int ipxe_printf(const char *format, ...)
va_list va;
va_start(va, format);
dde_kit_vprintf(new_format, va);
dde_vprintf(new_format, va);
va_end(va);
free(new_format);
@ -207,17 +141,16 @@ int ipxe_printf(const char *format, ...)
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);
dde_release_iomem((dde_addr_t) io_addr, 1);
}
void * ioremap(unsigned long bus_addr, size_t len)
void *ioremap(unsigned long bus_addr, size_t len)
{
LOG("bus_addr = %p len = %zx", (void *)bus_addr, len);
dde_kit_addr_t vaddr;
dde_addr_t vaddr;
int ret = dde_kit_request_mem(bus_addr, len, 0, &vaddr);
int ret = dde_request_iomem(bus_addr, len, 0, &vaddr);
return ret ? 0 : (void *)vaddr;
}
@ -225,7 +158,7 @@ void * ioremap(unsigned long bus_addr, size_t len)
unsigned long user_to_phys(userptr_t userptr, off_t offset)
{
return dde_kit_pgtab_get_physaddr((void *)userptr) + offset;
return dde_dma_get_physaddr((void *)userptr) + offset;
}
@ -247,54 +180,42 @@ unsigned long phys_to_bus(unsigned long phys_addr)
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);
dde_pci_readb(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);
dde_pci_readw( 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);
dde_pci_readl(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);
dde_pci_writeb(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);
dde_pci_writew(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);
dde_pci_writel( where, value);
return 0;
}

View File

@ -1,72 +1,73 @@
/*
* \brief Functions not offered by Genode's DDE-kit
* \brief DDE iPXE wrappers to C++ backend
* \author Sebastian Sumpf
* \author Josef Soentgen
* \date 2010-10-21
*/
/*
* Copyright (C) 2010-2013 Genode Labs GmbH
* Copyright (C) 2010-2015 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.
*/
/*
* The build system picks up stdarg.h from iPXE instead of the one
* provided by GCC. This header contains the FILE_LICENCE macro which
* is defined by iPXE's compiler.h.
*/
#define FILE_LICENCE(x)
/* Genode includes */
#include <base/allocator_avl.h>
#include <base/env.h>
#include <base/printf.h>
#include <base/slab.h>
#include <base/sleep.h>
#include <dataspace/client.h>
#include <io_mem_session/connection.h>
#include <io_port_session/connection.h>
#include <irq_session/connection.h>
#include <os/server.h>
#include <pci_device/client.h>
#include <pci_session/connection.h>
#include <rm_session/connection.h>
#include <timer_session/connection.h>
#include <util/misc_math.h>
extern "C" {
#include <dde_kit/pci.h>
#include "dde_support.h"
}
using namespace Genode;
/***************************************************
** Support for aligned and DMA memory allocation **
***************************************************/
enum { BACKING_STORE_SIZE = 1024 * 1024 };
/* local includes */
#include <dde_support.h>
static Allocator_avl& allocator()
//using namespace Genode;
/****************
** Migriation **
****************/
static Server::Entrypoint *_ep;
extern "C" void dde_init(void *ep)
{
static Allocator_avl _avl(env()->heap());
return _avl;
}
extern "C" int dde_mem_init(int bus, int dev, int func)
{
try {
addr_t base = dde_kit_pci_alloc_dma_buffer(bus, dev, func,
BACKING_STORE_SIZE);
/* add to allocator */
allocator().add_range(base, BACKING_STORE_SIZE);
} catch (...) {
return false;
}
return true;
}
extern "C" void *dde_alloc_memblock(dde_kit_size_t size, dde_kit_size_t align,
dde_kit_size_t offset)
{
void *ptr;
if (allocator().alloc_aligned(size, &ptr, log2(align)).is_error()) {
PERR("memory allocation failed in alloc_memblock (size=%zd, align=%zx,"
" offset=%zx)", size, align, offset);
return 0;
}
return ptr;
_ep = (Server::Entrypoint*)ep;
}
extern "C" void dde_free_memblock(void *p, dde_kit_size_t size)
/************
** printf **
************/
extern "C" void dde_vprintf(const char *fmt, va_list va) {
Genode::vprintf(fmt, va); }
extern "C" void dde_printf(const char *fmt, ...)
{
allocator().free(p, size);
va_list args;
va_start(args, fmt);
dde_vprintf(fmt, args);
va_end(args);
}
@ -74,7 +75,7 @@ extern "C" void dde_free_memblock(void *p, dde_kit_size_t size)
** Timer **
***********/
extern "C" void dde_timer2_udelay(unsigned long usecs)
extern "C" void dde_udelay(unsigned long usecs)
{
/*
* This function is called only once during rdtsc calibration (usecs will be
@ -84,3 +85,551 @@ extern "C" void dde_timer2_udelay(unsigned long usecs)
Timer::Connection timer;
timer.usleep(usecs);
}
/***************************
** locking/synchronizing **
***************************/
/**
* DDE iPXE mutual exclusion lock
*/
static Genode::Lock _ipxe_lock;
extern "C" void dde_lock_enter(void) { _ipxe_lock.lock(); }
extern "C" void dde_lock_leave(void) { _ipxe_lock.unlock(); }
extern "C" void dde_mdelay(unsigned long msecs)
{
/*
* Using one static timer connection here is safe because
* this function is only called while initializing the device
* and only be the same thread.
*/
static Timer::Connection timer;
timer.msleep(msecs);
}
/******************
** PCI handling **
******************/
struct Pci_driver
{
enum {
PCI_BASE_CLASS_NETWORK = 0x02,
CLASS_MASK = 0xff0000,
CLASS_NETWORK = PCI_BASE_CLASS_NETWORK << 16
};
Pci::Connection _pci;
Pci::Device_capability _cap;
Pci::Device_capability _last_cap;
struct Region
{
Genode::addr_t base;
Genode::addr_t mapped_base;
} _region;
template <typename T>
Pci::Device::Access_size _access_size(T t)
{
switch (sizeof(T)) {
case 1:
return Pci::Device::ACCESS_8BIT;
case 2:
return Pci::Device::ACCESS_16BIT;
default:
return Pci::Device::ACCESS_32BIT;
}
}
void _bus_address(int *bus, int *dev, int *fun)
{
Pci::Device_client client(_cap);
unsigned char b, d, f;
client.bus_address(&b, &d, &f);
*bus = b;
*dev = d;
*fun = f;
}
Pci_driver() { }
template <typename T>
void config_read(unsigned int devfn, T *val)
{
Pci::Device_client client(_cap);
*val = client.config_read(devfn, _access_size(*val));
}
template <typename T>
void config_write(unsigned int devfn, T val)
{
Pci::Device_client client(_cap);
client.config_write(devfn, val, _access_size(val));
}
int first_device(int *bus, int *dev, int *fun)
{
_cap = _pci.first_device(CLASS_NETWORK, CLASS_MASK);
_bus_address(bus, dev, fun);
return 0;
}
int next_device(int *bus, int *dev, int *fun)
{
_last_cap = _cap;
_cap = _pci.next_device(_cap, CLASS_NETWORK, CLASS_MASK);
_bus_address(bus, dev, fun);
if (_last_cap.valid())
_pci.release_device(_last_cap);
return 0;
}
Genode::addr_t alloc_dma_memory(Genode::size_t size)
{
try {
using namespace Genode;
/* trigger that the device gets assigned to this driver */
_pci.config_extended(_cap);
Ram_dataspace_capability ram_cap;
ram_cap = _pci.alloc_dma_buffer(_cap, size);
_region.mapped_base = (Genode::addr_t)env()->rm_session()->attach(ram_cap);
_region.base = Dataspace_client(ram_cap).phys_addr();
return _region.mapped_base;
} catch (...) { return 0; }
}
Genode::addr_t virt_to_phys(Genode::addr_t virt) {
return virt - _region.mapped_base + _region.base; }
};
static Pci_driver& pci_drv()
{
static Pci_driver _pci_drv;
return _pci_drv;
}
extern "C" int dde_pci_first_device(int *bus, int *dev, int *fun) {
return pci_drv().first_device(bus, dev, fun); }
extern "C" int dde_pci_next_device(int *bus, int *dev, int *fun) {
return pci_drv().next_device(bus, dev, fun); }
extern "C" void dde_pci_readb(int pos, dde_uint8_t *val) {
pci_drv().config_read(pos, val); }
extern "C" void dde_pci_readw(int pos, dde_uint16_t *val) {
pci_drv().config_read(pos, val); }
extern "C" void dde_pci_readl(int pos, dde_uint32_t *val) {
pci_drv().config_read(pos, val); }
extern "C" void dde_pci_writeb(int pos, dde_uint8_t val) {
pci_drv().config_write(pos, val); }
extern "C" void dde_pci_writew(int pos, dde_uint16_t val) {
pci_drv().config_write(pos, val); }
extern "C" void dde_pci_writel(int pos, dde_uint32_t val) {
pci_drv().config_write(pos, val); }
/************************
** Interrupt handling **
************************/
struct Irq_handler
{
Server::Entrypoint &ep;
Genode::Irq_connection irq;
Genode::Signal_rpc_member<Irq_handler> dispatcher;
typedef void (*irq_handler)(void*);
irq_handler handler;
void *priv;
void handle(unsigned)
{
handler(priv);
irq.ack_irq();
}
Irq_handler(Server::Entrypoint &ep, int irqnr,
irq_handler handler, void *priv)
:
ep(ep), irq(irqnr), dispatcher(ep, *this, &Irq_handler::handle),
handler(handler), priv(priv)
{
irq.sigh(dispatcher);
/* intial ack so that we will receive IRQ signals */
irq.ack_irq();
}
};
static Irq_handler *_irq_handler;
extern "C" int dde_interrupt_attach(int irq, void(*handler)(void *), void *priv)
{
if (_irq_handler) {
PERR("Irq_handler already registered");
Genode::sleep_forever();
}
try {
_irq_handler = new (Genode::env()->heap())
Irq_handler(*_ep, irq, handler, priv);
} catch (...) { return -1; }
return 0;
}
/***************************************************
** Support for aligned and DMA memory allocation **
***************************************************/
enum { BACKING_STORE_SIZE = 1024 * 1024 };
static Genode::Allocator_avl& allocator()
{
static Genode::Allocator_avl _avl(Genode::env()->heap());
return _avl;
}
extern "C" int dde_dma_mem_init()
{
try {
Genode::addr_t base = pci_drv().alloc_dma_memory(BACKING_STORE_SIZE);
/* add to allocator */
allocator().add_range(base, BACKING_STORE_SIZE);
} catch (...) { return false; }
return true;
}
extern "C" void *dde_dma_alloc(dde_size_t size, dde_size_t align,
dde_size_t offset)
{
void *ptr;
if (allocator().alloc_aligned(size, &ptr, Genode::log2(align)).is_error()) {
PERR("memory allocation failed in alloc_memblock (size=%zu, align=%zx,"
" offset=%zx)", (Genode::size_t)size, (Genode::size_t)align, (Genode::size_t)offset);
return 0;
}
return ptr;
}
extern "C" void dde_dma_free(void *p, dde_size_t size) {
allocator().free(p, size); }
extern "C" dde_addr_t dde_dma_get_physaddr(void *virt) {
return pci_drv().virt_to_phys((Genode::addr_t)virt); }
/**************
** I/O port **
**************/
static Genode::Io_port_connection *_io_port;
extern "C" void dde_request_io(dde_addr_t base, dde_size_t size)
{
using namespace Genode;
if (_io_port) {
PERR("Io_port_connection already open");
sleep_forever();
}
_io_port = new (env()->heap()) Io_port_connection(base, size);
}
extern "C" dde_uint8_t dde_inb(dde_addr_t port) {
return _io_port->inb(port); }
extern "C" dde_uint16_t dde_inw(dde_addr_t port) {
return _io_port->inw(port); }
extern "C" dde_uint32_t dde_inl(dde_addr_t port) {
return _io_port->inl(port); }
extern "C" void dde_outb(dde_addr_t port, dde_uint8_t data) {
_io_port->outb(port, data); }
extern "C" void dde_outw(dde_addr_t port, dde_uint16_t data) {
_io_port->outw(port, data); }
extern "C" void dde_outl(dde_addr_t port, dde_uint32_t data) {
_io_port->outl(port, data); }
/**********************
** Slab memory pool **
**********************/
struct Slab_backend_alloc : public Genode::Allocator,
public Genode::Rm_connection
{
enum {
VM_SIZE = 512 * 1024,
BLOCK_SIZE = 64 * 1024,
ELEMENTS = VM_SIZE / BLOCK_SIZE,
};
Genode::addr_t _base;
Genode::Ram_dataspace_capability _ds_cap[ELEMENTS];
int _index;
Genode::Allocator_avl _range;
Genode::Ram_session &_ram;
bool _alloc_block()
{
using namespace Genode;
if (_index == ELEMENTS) {
PERR("Slab-backend exhausted!");
return false;
}
try {
_ds_cap[_index] = _ram.alloc(BLOCK_SIZE);
Rm_connection::attach_at(_ds_cap[_index], _index * BLOCK_SIZE, BLOCK_SIZE, 0);
} catch (...) { return false; }
/* return base + offset in VM area */
Genode::addr_t block_base = _base + (_index * BLOCK_SIZE);
++_index;
_range.add_range(block_base, BLOCK_SIZE);
return true;
}
Slab_backend_alloc(Genode::Ram_session &ram)
:
Rm_connection(0, VM_SIZE),
_index(0), _range(Genode::env()->heap()), _ram(ram)
{
/* reserver attach us, anywere */
_base = Genode::env()->rm_session()->attach(dataspace());
}
Genode::addr_t start() const { return _base; }
Genode::addr_t end() const { return _base + VM_SIZE - 1; }
/*************************
** Allocator interface **
*************************/
bool alloc(Genode::size_t size, void **out_addr)
{
bool done = _range.alloc(size, out_addr);
if (done)
return done;
done = _alloc_block();
if (!done) {
PERR("Backend allocator exhausted\n");
return false;
}
return _range.alloc(size, out_addr);
}
void free(void *addr, Genode::size_t size) { }
Genode::size_t overhead(Genode::size_t size) const { return 0; }
bool need_size_for_free() const { return false; }
};
struct Slab_alloc : public Genode::Slab
{
/*
* Each slab block in the slab contains about 8 objects (slab entries)
* as proposed in the paper by Bonwick and block sizes are multiples of
* page size.
*/
static Genode::size_t _calculate_block_size(Genode::size_t object_size)
{
Genode::size_t block_size = 8 * (object_size + sizeof(Genode::Slab_entry))
+ sizeof(Genode::Slab_block);
return Genode::align_addr(block_size, 12);
}
Slab_alloc(Genode::size_t object_size, Slab_backend_alloc &allocator)
: Slab(object_size, _calculate_block_size(object_size), 0, &allocator) { }
/**
* Convenience slabe-entry allocation
*/
Genode::addr_t alloc()
{
Genode::addr_t result;
return (Slab::alloc(slab_size(), (void **)&result) ? result : 0);
}
};
struct Slab
{
enum {
SLAB_START_LOG2 = 5, /* 32 B */
SLAB_STOP_LOG2 = 10, /* 1 KiB */
NUM_SLABS = (SLAB_STOP_LOG2 - SLAB_START_LOG2) + 1,
};
Slab_backend_alloc &_back_alloc;
Slab_alloc *_allocator[NUM_SLABS];
Genode::addr_t _start;
Genode::addr_t _end;
Slab(Slab_backend_alloc &alloc)
: _back_alloc(alloc), _start(alloc.start()), _end(alloc.end())
{
for (unsigned i = 0; i < NUM_SLABS; i++)
_allocator[i] = new (Genode::env()->heap())
Slab_alloc(1U << (SLAB_START_LOG2 + i), alloc);
}
void *alloc(Genode::size_t size)
{
using namespace Genode;
size += sizeof(Genode::addr_t);
int msb = Genode::log2(size);
if (size > (1U << msb))
msb++;
if (size < (1U << SLAB_START_LOG2))
msb = SLAB_STOP_LOG2;
if (msb > SLAB_STOP_LOG2)
return 0;
Genode::addr_t addr = _allocator[msb - SLAB_START_LOG2]->alloc();
if (!addr)
return 0;
*(Genode::addr_t*)addr = msb - SLAB_START_LOG2;
addr += sizeof(Genode::addr_t);
return (void*)addr;
}
void free(void *p)
{
using namespace Genode;
Genode::addr_t *addr = ((Genode::addr_t *)p)-1;
unsigned index = *(unsigned*)(addr);
_allocator[index]->free((void*)(addr));
}
};
static ::Slab& slab()
{
static ::Slab_backend_alloc sb(*Genode::env()->ram_session());
static ::Slab s(sb);
return s;
}
extern "C" void *dde_slab_alloc(dde_size_t size) {
return slab().alloc(size); }
extern "C" void dde_slab_free(void *p) {
slab().free(p); }
/****************
** I/O memory **
****************/
struct Io_memory
{
Genode::Io_mem_connection _mem;
Genode::Io_mem_dataspace_capability _mem_ds;
Genode::addr_t _vaddr;
Io_memory(Genode::addr_t base, Genode::size_t size, bool wc)
:
_mem(base, size, wc),
_mem_ds(_mem.dataspace())
{
if (!_mem_ds.valid())
throw Genode::Exception();
_vaddr = Genode::env()->rm_session()->attach(_mem_ds);
_vaddr |= base & 0xfff;
}
Genode::addr_t vaddr() const { return _vaddr; }
};
static Io_memory *_io_mem;
extern "C" int dde_request_iomem(dde_addr_t start, dde_size_t size, int wc,
dde_addr_t *vaddr)
{
if (_io_mem) {
PERR("Io_memory already requested");
Genode::sleep_forever();
}
try {
_io_mem = new (Genode::env()->heap()) Io_memory(start, size, !!wc);
} catch (...) { return -1; }
*vaddr = _io_mem->vaddr();
return 0;
}
extern "C" int dde_release_iomem(dde_addr_t start, dde_size_t size)
{
try {
destroy(Genode::env()->heap(), _io_mem);
_io_mem = 0;
return 0;
} catch (...) { return -1; }
}

View File

@ -1,26 +0,0 @@
/*
* \brief DDE iPXE wrappers to C++ backend
* \author Christian Helmuth
* \date 2013-01-07
*/
/*
* Copyright (C) 2010-2013 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_SUPPORT_H_
#define _DDE_SUPPORT_H_
#include <dde_kit/types.h>
void *dde_alloc_memblock(dde_kit_size_t size, dde_kit_size_t align,
dde_kit_size_t offset);
void dde_free_memblock(void *p, dde_kit_size_t size);
void dde_timer2_udelay(unsigned long usecs);
int dde_mem_init(int bus, int dev, int func);
#endif /* _DDE_SUPPORT_H_ */

View File

@ -11,7 +11,9 @@
* under the terms of the GNU General Public License version 2.
*/
#include "local.h"
#include <dde_support.h>
#define TRACE dde_printf("\033[35m%s not implemented\033[0m\n", __func__)
int snprintf(char *buf, __SIZE_TYPE__ size, const char *fmt, ...) { TRACE; return 0; }

View File

@ -0,0 +1,128 @@
/*
* \brief DDE iPXE wrappers to C++ backend
* \author Christian Helmuth
* \author Josef Soentgen
* \date 2013-01-07
*/
/*
* Copyright (C) 2010-2015 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_SUPPORT_H_
#define _DDE_SUPPORT_H_
#ifdef __cplusplus
extern "C" {
#endif
typedef unsigned long dde_addr_t;
typedef unsigned long dde_size_t;
typedef unsigned char dde_uint8_t;
typedef unsigned short dde_uint16_t;
typedef unsigned int dde_uint32_t;
/*****************
** Initialization
*****************/
void dde_init(void *ep);
/***********
** Timer **
***********/
void dde_udelay(unsigned long usecs);
void dde_mdelay(unsigned long msecs);
/************
** printf **
************/
typedef __builtin_va_list va_list;
void dde_vprintf(const char *fmt, va_list va) __attribute__ ((format (printf, 1, 0)));
void dde_printf(const char *fmt, ...);
/***************************************************
** Support for aligned and DMA memory allocation **
***************************************************/
int dde_dma_mem_init();
void *dde_dma_alloc(dde_size_t size, dde_size_t align, dde_size_t offset);
void dde_dma_free(void *p, dde_size_t size);
dde_addr_t dde_dma_get_physaddr(void *virt);
/***************************
** locking/synchronizing **
***************************/
void dde_lock_enter(void);
void dde_lock_leave(void);
/************************
** Interrupt handling **
************************/
int dde_interrupt_attach(int irq, void (*handler)(void *), void *priv);
/******************
** PCI handling **
******************/
int dde_pci_first_device(int *, int *, int *);
int dde_pci_next_device(int *, int *, int *);
void dde_pci_readb(int, dde_uint8_t *);
void dde_pci_readw(int, dde_uint16_t *);
void dde_pci_readl(int, dde_uint32_t *);
void dde_pci_writeb(int, dde_uint8_t);
void dde_pci_writew(int, dde_uint16_t);
void dde_pci_writel(int, dde_uint32_t);
/**************
** I/O port **
**************/
void dde_request_io(dde_addr_t, dde_size_t);
dde_uint8_t dde_inb(dde_addr_t);
dde_uint16_t dde_inw(dde_addr_t);
dde_uint32_t dde_inl(dde_addr_t);
void dde_outb(dde_addr_t, dde_uint8_t);
void dde_outw(dde_addr_t, dde_uint16_t);
void dde_outl(dde_addr_t, dde_uint32_t);
/**********************
** Slab memory pool **
**********************/
void *dde_slab_alloc(dde_size_t);
void dde_slab_free(void *);
/****************
** I/O memory **
****************/
int dde_request_iomem(dde_addr_t, dde_size_t, int, dde_addr_t *);
int dde_release_iomem(dde_addr_t, dde_size_t);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* _DDE_SUPPORT_H_ */

View File

@ -3,36 +3,36 @@
/* bits/io.h */
#include <dde_kit/resources.h>
#include <dde_support.h>
static inline uint8_t inb(volatile uint8_t *io_addr)
{
return dde_kit_inb((dde_kit_addr_t) io_addr);
return dde_inb((dde_addr_t) io_addr);
}
static inline uint16_t inw(volatile uint16_t *io_addr)
{
return dde_kit_inw((dde_kit_addr_t) io_addr);
return dde_inw((dde_addr_t) io_addr);
}
static inline uint32_t inl(volatile uint32_t *io_addr)
{
return dde_kit_inl((dde_kit_addr_t) io_addr);
return dde_inl((dde_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);
dde_outb((dde_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);
dde_outw((dde_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);
dde_outl((dde_addr_t) io_addr, data);
}

View File

@ -11,18 +11,9 @@
* 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__ ); \
dde_printf("\033[36m" fmt "\033[0m\n", ##__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

@ -5,20 +5,12 @@
*/
/*
* Copyright (C) 2010-2013 Genode Labs GmbH
* Copyright (C) 2010-2015 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>
@ -26,32 +18,15 @@
#include <ipxe/iobuf.h>
#include <dde_ipxe/nic.h>
/* local includes */
#include "local.h"
#include "dde_support.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;
#include <dde_support.h>
/**
* Network device driven by iPXE
*/
static struct net_device *net_dev;
/**
* Link-state change detected
*/
static int link_state_changed;
/**
* Callback function pointers
*/
@ -68,7 +43,7 @@ extern struct pci_driver
pcnet32_driver;
/**
* Driver database (used for probing)
* Driver database (used for probing)PCI_BASE_CLASS_NETWORK
*/
static struct pci_driver *pci_drivers[] = {
&realtek_driver,
@ -91,9 +66,9 @@ static void pci_read_bases(struct pci_device *pci_dev)
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);
dde_addr_t base = bar & PCI_BASE_ADDRESS_IO_MASK;
dde_size_t size = pci_bar_size(pci_dev, reg);
dde_request_io(base, size);
}
} else {
if (!pci_dev->membase)
@ -149,27 +124,26 @@ enum { NO_DEVICE_FOUND = ~0U };
static unsigned scan_pci(void)
{
int ret, bus = 0, dev = 0, fun = 0;
for (ret = dde_kit_pci_first_device(&bus, &dev, &fun);
for (ret = dde_pci_first_device(&bus, &dev, &fun);
ret == 0;
ret = dde_kit_pci_next_device(&bus, &dev, &fun)) {
ret = dde_pci_next_device(&bus, &dev, &fun)) {
dde_kit_uint32_t class_code;
dde_kit_pci_readl(bus, dev, fun, PCI_CLASS_REVISION, &class_code);
dde_uint32_t class_code;
dde_pci_readl(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);
dde_uint16_t vendor, device;
dde_pci_readw(PCI_VENDOR_ID, &vendor);
dde_pci_readw(PCI_DEVICE_ID, &device);
dde_uint8_t rev, irq;
dde_pci_readb(PCI_REVISION_ID, &rev);
dde_pci_readb(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;
@ -200,57 +174,33 @@ static unsigned scan_pci(void)
/**
* IRQ handler registered at DDE kit
* IRQ handler registered at DDE
*/
static void irq_handler(void *p)
{
ENTER;
dde_lock_enter();
/* check for the link-state to change on each interrupt */
int link_ok = netdev_link_ok(net_dev);
/* poll the device for packets and also link-state changes */
netdev_poll(net_dev);
dde_kit_sem_up(bh_sema);
link_state_changed = (link_ok != netdev_link_ok(net_dev));
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;
/* report link-state changes */
if (link_state_changed) {
LEAVE;
if (link_callback)
link_callback();
ENTER;
link_state_changed = 0;
}
struct io_buffer *iobuf;
while ((iobuf = netdev_rx_dequeue(net_dev))) {
LEAVE;
dde_lock_leave();
if (rx_callback)
rx_callback(1, iobuf->data, iob_len(iobuf));
ENTER;
dde_lock_enter();
free_iob(iobuf);
}
LEAVE;
}
dde_lock_leave();
if (link_ok != netdev_link_ok(net_dev))
/* report link-state changes */
if (link_callback)
link_callback();
}
@ -261,12 +211,12 @@ static void bh_handler(void *p)
void dde_ipxe_nic_register_callbacks(dde_ipxe_nic_rx_cb rx_cb,
dde_ipxe_nic_link_cb link_cb)
{
ENTER;
dde_lock_enter();
rx_callback = rx_cb;
link_callback = link_cb;
LEAVE;
dde_lock_leave();
}
@ -275,12 +225,11 @@ int dde_ipxe_nic_link_state(unsigned if_index)
if (if_index != 1)
return -1;
ENTER;
dde_lock_enter();
int link_state = netdev_link_ok(net_dev);
LEAVE;
dde_lock_leave();
return link_state;
}
@ -290,22 +239,22 @@ int dde_ipxe_nic_tx(unsigned if_index, const char *packet, unsigned packet_len)
if (if_index != 1)
return -1;
ENTER;
dde_lock_enter();
struct io_buffer *iobuf = alloc_iob(packet_len);
LEAVE;
dde_lock_leave();
if (!iobuf)
return -1;
memcpy(iob_put(iobuf, packet_len), packet, packet_len);
ENTER;
dde_lock_enter();
netdev_poll(net_dev);
netdev_tx(net_dev, iob_disown(iobuf));
LEAVE;
dde_lock_leave();
return 0;
}
@ -315,7 +264,7 @@ int dde_ipxe_nic_get_mac_addr(unsigned if_index, char *out_mac_addr)
if (if_index != 1)
return -1;
ENTER;
dde_lock_enter();
out_mac_addr[0] = net_dev->hw_addr[0];
out_mac_addr[1] = net_dev->hw_addr[1];
@ -324,26 +273,16 @@ int dde_ipxe_nic_get_mac_addr(unsigned if_index, char *out_mac_addr)
out_mac_addr[4] = net_dev->hw_addr[4];
out_mac_addr[5] = net_dev->hw_addr[5];
LEAVE;
dde_lock_leave();
return 0;
}
int dde_ipxe_nic_init(void)
int dde_ipxe_nic_init(void *ep)
{
dde_kit_init();
dde_kit_timer_init(0, 0);
enum {
CLASS_MASK = 0xff0000,
CLASS_NETWORK = PCI_BASE_CLASS_NETWORK << 16
};
dde_kit_pci_init(CLASS_NETWORK, CLASS_MASK);
dde_init(ep);
dde_kit_lock_init(&ipxe_lock);
slab_init();
ENTER;
dde_lock_enter();
/* scan all pci devices and drivers */
unsigned location = scan_pci();
@ -353,10 +292,8 @@ int dde_ipxe_nic_init(void)
/* find iPXE NIC device */
net_dev = find_netdev_by_location(BUS_TYPE_PCI, location);
/* initialize memory backend allocator for nic driver */
if (!dde_mem_init(PCI_BUS(net_dev->dev->desc.location),
PCI_SLOT(net_dev->dev->desc.location),
PCI_FUNC(net_dev->dev->desc.location))) {
/* initialize DMA memory backend allocator for nic driver */
if (!dde_dma_mem_init()) {
LOG("initialization of block memory failed!");
return 0;
}
@ -370,18 +307,15 @@ int dde_ipxe_nic_init(void)
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);
/* initialize IRQ handler */
int err = dde_interrupt_attach(net_dev->dev->desc.irq, irq_handler, 0);
if (err) {
LOG("attaching to IRQ %02x failed", net_dev->dev->desc.irq);
return 0;
}
netdev_irq(net_dev, 1);
LEAVE;
dde_lock_leave();
/* always report 1 device was found */
return 1;