Imported Genode release 11.11
This commit is contained in:
committed by
Christian Helmuth
parent
6bcc9aef0e
commit
da4e1feaa5
54
dde_ipxe/Makefile
Normal file
54
dde_ipxe/Makefile
Normal 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
18
dde_ipxe/README
Normal 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'.
|
||||
67
dde_ipxe/include/dde_ipxe/nic.h
Normal file
67
dde_ipxe/include/dde_ipxe/nic.h
Normal 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_ */
|
||||
49
dde_ipxe/lib/mk/dde_ipxe_nic.mk
Normal file
49
dde_ipxe/lib/mk/dde_ipxe_nic.mk
Normal 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)
|
||||
5
dde_ipxe/lib/mk/dde_ipxe_support.mk
Normal file
5
dde_ipxe/lib/mk/dde_ipxe_support.mk
Normal file
@@ -0,0 +1,5 @@
|
||||
LIB_DIR := $(REP_DIR)/src/lib/dde_ipxe
|
||||
|
||||
SRC_CC = dde_support.cc
|
||||
|
||||
vpath dde_support.cc $(LIB_DIR)
|
||||
42
dde_ipxe/patches/dde_ipxe.patch
Normal file
42
dde_ipxe/patches/dde_ipxe.patch
Normal 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 );
|
||||
136
dde_ipxe/src/drivers/nic/main.cc
Normal file
136
dde_ipxe/src/drivers/nic/main.cc
Normal 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;
|
||||
}
|
||||
|
||||
3
dde_ipxe/src/drivers/nic/target.mk
Normal file
3
dde_ipxe/src/drivers/nic/target.mk
Normal file
@@ -0,0 +1,3 @@
|
||||
TARGET := nic_drv
|
||||
LIBS := cxx env signal server dde_ipxe_nic
|
||||
SRC_CC = main.cc
|
||||
350
dde_ipxe/src/lib/dde_ipxe/dde.c
Normal file
350
dde_ipxe/src/lib/dde_ipxe/dde.c
Normal 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) { }
|
||||
86
dde_ipxe/src/lib/dde_ipxe/dde_support.cc
Normal file
86
dde_ipxe/src/lib/dde_ipxe/dde_support.cc
Normal 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);
|
||||
}
|
||||
30
dde_ipxe/src/lib/dde_ipxe/dummies.c
Normal file
30
dde_ipxe/src/lib/dde_ipxe/dummies.c
Normal 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; }
|
||||
1
dde_ipxe/src/lib/dde_ipxe/include/bits/byteswap.h
Normal file
1
dde_ipxe/src/lib/dde_ipxe/include/bits/byteswap.h
Normal file
@@ -0,0 +1 @@
|
||||
#include_next <bits/byteswap.h>
|
||||
1
dde_ipxe/src/lib/dde_ipxe/include/bits/compiler.h
Normal file
1
dde_ipxe/src/lib/dde_ipxe/include/bits/compiler.h
Normal file
@@ -0,0 +1 @@
|
||||
#include_next <bits/compiler.h>
|
||||
0
dde_ipxe/src/lib/dde_ipxe/include/bits/cpu.h
Normal file
0
dde_ipxe/src/lib/dde_ipxe/include/bits/cpu.h
Normal file
0
dde_ipxe/src/lib/dde_ipxe/include/bits/eltorito.h
Normal file
0
dde_ipxe/src/lib/dde_ipxe/include/bits/eltorito.h
Normal file
1
dde_ipxe/src/lib/dde_ipxe/include/bits/endian.h
Normal file
1
dde_ipxe/src/lib/dde_ipxe/include/bits/endian.h
Normal file
@@ -0,0 +1 @@
|
||||
#include_next <bits/endian.h>
|
||||
1
dde_ipxe/src/lib/dde_ipxe/include/bits/errfile.h
Normal file
1
dde_ipxe/src/lib/dde_ipxe/include/bits/errfile.h
Normal file
@@ -0,0 +1 @@
|
||||
#include_next <bits/errfile.h>
|
||||
1
dde_ipxe/src/lib/dde_ipxe/include/bits/io.h
Normal file
1
dde_ipxe/src/lib/dde_ipxe/include/bits/io.h
Normal file
@@ -0,0 +1 @@
|
||||
#include <env_dde_kit.h>
|
||||
0
dde_ipxe/src/lib/dde_ipxe/include/bits/nap.h
Normal file
0
dde_ipxe/src/lib/dde_ipxe/include/bits/nap.h
Normal file
3
dde_ipxe/src/lib/dde_ipxe/include/bits/pci_io.h
Normal file
3
dde_ipxe/src/lib/dde_ipxe/include/bits/pci_io.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#include <ipxe/io.h> /* some drivers do rely on this depency :-( */
|
||||
|
||||
#include <env_dde_kit.h>
|
||||
0
dde_ipxe/src/lib/dde_ipxe/include/bits/smbios.h
Normal file
0
dde_ipxe/src/lib/dde_ipxe/include/bits/smbios.h
Normal file
1
dde_ipxe/src/lib/dde_ipxe/include/bits/stdint.h
Normal file
1
dde_ipxe/src/lib/dde_ipxe/include/bits/stdint.h
Normal file
@@ -0,0 +1 @@
|
||||
#include_next <bits/stdint.h>
|
||||
1
dde_ipxe/src/lib/dde_ipxe/include/bits/string.h
Normal file
1
dde_ipxe/src/lib/dde_ipxe/include/bits/string.h
Normal file
@@ -0,0 +1 @@
|
||||
#include_next <bits/string.h>
|
||||
6
dde_ipxe/src/lib/dde_ipxe/include/bits/timer.h
Normal file
6
dde_ipxe/src/lib/dde_ipxe/include/bits/timer.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#include <ipxe/rdtsc_timer.h>
|
||||
|
||||
static inline unsigned long currticks ( void )
|
||||
{
|
||||
return __rdtsc_currticks();
|
||||
}
|
||||
1
dde_ipxe/src/lib/dde_ipxe/include/bits/uaccess.h
Normal file
1
dde_ipxe/src/lib/dde_ipxe/include/bits/uaccess.h
Normal file
@@ -0,0 +1 @@
|
||||
#include <env_dde_kit.h>
|
||||
0
dde_ipxe/src/lib/dde_ipxe/include/bits/umalloc.h
Normal file
0
dde_ipxe/src/lib/dde_ipxe/include/bits/umalloc.h
Normal file
68
dde_ipxe/src/lib/dde_ipxe/include/env_dde_kit.h
Normal file
68
dde_ipxe/src/lib/dde_ipxe/include/env_dde_kit.h
Normal 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__ */
|
||||
28
dde_ipxe/src/lib/dde_ipxe/local.h
Normal file
28
dde_ipxe/src/lib/dde_ipxe/local.h
Normal 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);
|
||||
337
dde_ipxe/src/lib/dde_ipxe/nic.c
Normal file
337
dde_ipxe/src/lib/dde_ipxe/nic.c
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user