mirror of
https://github.com/genodelabs/genode.git
synced 2025-03-22 03:55:26 +00:00
Remove zynq_qemu platform and zynq nic driver
Moved to separate repo at https://github.com/jschlatow/genode-zynq Fixes genodelabs/genode#4280
This commit is contained in:
parent
6ecae6adb3
commit
7917c5d9ec
@ -1 +0,0 @@
|
||||
arm_v7a
|
@ -1 +0,0 @@
|
||||
0x00100000
|
@ -1,14 +0,0 @@
|
||||
REP_INC_DIR += src/bootstrap/board/zynq_qemu
|
||||
|
||||
SRC_S += bootstrap/spec/arm/crt0.s
|
||||
|
||||
SRC_CC += bootstrap/board/zynq_qemu/platform.cc
|
||||
SRC_CC += bootstrap/spec/arm/cpu.cc
|
||||
SRC_CC += bootstrap/spec/arm/cortex_a9_mmu.cc
|
||||
SRC_CC += bootstrap/spec/arm/gicv2.cc
|
||||
SRC_CC += bootstrap/spec/arm/arm_v7_cpu.cc
|
||||
SRC_CC += hw/spec/32bit/memory_map.cc
|
||||
|
||||
NR_OF_CPUS = 1
|
||||
|
||||
include $(call select_from_repositories,lib/mk/bootstrap-hw.inc)
|
@ -1,11 +0,0 @@
|
||||
#
|
||||
# \brief Build config for Genodes core process
|
||||
# \author Johannes Schlatow
|
||||
# \date 2014-12-15
|
||||
#
|
||||
|
||||
# add C++ sources
|
||||
SRC_CC += platform_services.cc
|
||||
|
||||
# include less specific configuration
|
||||
include $(call select_from_repositories,lib/mk/spec/cortex_a9/core-hw.inc)
|
@ -1,13 +0,0 @@
|
||||
#
|
||||
# \brief Build config for Genodes core process
|
||||
# \author Johannes Schlatow
|
||||
# \date 2014-12-15
|
||||
#
|
||||
|
||||
# add include paths
|
||||
REP_INC_DIR += src/core/board/zynq_qemu
|
||||
|
||||
NR_OF_CPUS = 1
|
||||
|
||||
# include less specific configuration
|
||||
include $(call select_from_repositories,lib/mk/spec/arm_v7/core-hw-zynq.inc)
|
@ -1 +0,0 @@
|
||||
include $(GENODE_DIR)/repos/base-hw/recipes/src/base-hw_content.inc
|
@ -1 +0,0 @@
|
||||
2021-10-13 3233ce8f7b5f3246ace4fbdf810b1632cb147a1a
|
@ -1,2 +0,0 @@
|
||||
base-hw
|
||||
base
|
@ -1,30 +0,0 @@
|
||||
/*
|
||||
* \brief Zynq specific board definitions
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2017-02-20
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _SRC__BOOTSTRAP__SPEC__ZYNQ__BOARD_H_
|
||||
#define _SRC__BOOTSTRAP__SPEC__ZYNQ__BOARD_H_
|
||||
|
||||
#include <hw/spec/arm/zynq_qemu_board.h>
|
||||
#include <spec/arm/cortex_a9_actlr.h>
|
||||
#include <spec/arm/cortex_a9_page_table.h>
|
||||
#include <spec/arm/cpu.h>
|
||||
#include <hw/spec/arm/gicv2.h>
|
||||
|
||||
namespace Board {
|
||||
|
||||
using namespace Hw::Zynq_qemu_board;
|
||||
using Pic = Hw::Gicv2;
|
||||
static constexpr bool NON_SECURE = false;
|
||||
}
|
||||
|
||||
#endif /* _SRC__BOOTSTRAP__SPEC__ZYNQ__BOARD_H_ */
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* \brief Platform implementations specific for base-hw and Zynq
|
||||
* \author Johannes Schlatow
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2014-12-15
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
/* core includes */
|
||||
#include <platform.h>
|
||||
|
||||
using namespace Board;
|
||||
|
||||
|
||||
Bootstrap::Platform::Board::Board()
|
||||
:
|
||||
early_ram_regions(Memory_region { RAM_0_BASE + 0x1000,
|
||||
RAM_0_SIZE - 0x1000 }),
|
||||
late_ram_regions(Memory_region { RAM_0_BASE, 0x1000 }),
|
||||
core_mmio(Memory_region { CORTEX_A9_PRIVATE_MEM_BASE,
|
||||
CORTEX_A9_PRIVATE_MEM_SIZE },
|
||||
Memory_region { UART_BASE,
|
||||
UART_SIZE },
|
||||
Memory_region { PL310_MMIO_BASE,
|
||||
PL310_MMIO_SIZE })
|
||||
{ }
|
||||
|
||||
|
||||
bool Cpu::errata(Board::Cpu::Errata) { return false; }
|
||||
|
||||
|
||||
void Cpu::wake_up_all_cpus(void* ip)
|
||||
{
|
||||
struct Wakeup_generator : Genode::Mmio
|
||||
{
|
||||
struct Core1_boot_addr : Register<0x0, 32> { };
|
||||
|
||||
Wakeup_generator(void * const ip) : Mmio(CORE1_ENTRY)
|
||||
{
|
||||
write<Core1_boot_addr>((Genode::addr_t)ip);
|
||||
}
|
||||
};
|
||||
|
||||
Wakeup_generator wgen(ip);
|
||||
asm volatile("dsb\n"
|
||||
"sev\n");
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* \brief Board driver for core on Zynq
|
||||
* \author Johannes Schlatow
|
||||
* \author Stefan Kalkowski
|
||||
* \author Martin Stein
|
||||
* \date 2014-06-02
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__SPEC__ZYNQ_QEMU__BOARD_H_
|
||||
#define _CORE__SPEC__ZYNQ_QEMU__BOARD_H_
|
||||
|
||||
/* base-hw internal includes */
|
||||
#include <hw/spec/arm/gicv2.h>
|
||||
#include <hw/spec/arm/zynq_qemu_board.h>
|
||||
|
||||
/* base-hw Core includes */
|
||||
#include <spec/arm/cortex_a9_private_timer.h>
|
||||
#include <spec/cortex_a9/cpu.h>
|
||||
|
||||
namespace Board {
|
||||
|
||||
using namespace Hw::Zynq_qemu_board;
|
||||
|
||||
class Global_interrupt_controller { };
|
||||
class Pic : public Hw::Gicv2 { public: Pic(Global_interrupt_controller &) { } };
|
||||
|
||||
L2_cache & l2_cache();
|
||||
}
|
||||
|
||||
#endif /* _CORE__SPEC__ZYNQ_QEMU__BOARD_H_ */
|
@ -1,35 +0,0 @@
|
||||
/*
|
||||
* \brief Zynq specific board definitions
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2019-05-16
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2019 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _SRC__INCLUDE__HW__SPEC__ARM__ZYNQ_BOARD_H_
|
||||
#define _SRC__INCLUDE__HW__SPEC__ARM__ZYNQ_BOARD_H_
|
||||
|
||||
#include <drivers/defs/zynq_qemu.h>
|
||||
#include <drivers/uart/xilinx.h>
|
||||
#include <hw/spec/arm/cortex_a9.h>
|
||||
#include <hw/spec/arm/pl310.h>
|
||||
#include <hw/spec/arm/boot_info.h>
|
||||
|
||||
namespace Hw::Zynq_qemu_board {
|
||||
|
||||
using namespace Zynq_qemu;
|
||||
using L2_cache = Hw::Pl310;
|
||||
using Cpu_mmio = Hw::Cortex_a9_mmio<CORTEX_A9_PRIVATE_MEM_BASE>;
|
||||
using Serial = Genode::Xilinx_uart;
|
||||
|
||||
enum {
|
||||
UART_BASE = UART_0_MMIO_BASE,
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _SRC__INCLUDE__HW__SPEC__ARM__ZYNQ_BOARD_H_ */
|
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* \brief MMIO and IRQ definitions common to Xilinx Zynq platforms
|
||||
* \author Mark Albers
|
||||
* \author Timo Wischer
|
||||
* \author Johannes Schlatow
|
||||
* \date 2014-12-15
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__DRIVERS__DEFS__ZYNQ_H_
|
||||
#define _INCLUDE__DRIVERS__DEFS__ZYNQ_H_
|
||||
|
||||
namespace Zynq {
|
||||
enum {
|
||||
/* device IO memory */
|
||||
MMIO_0_BASE = 0xe0000000, /* IOP devices */
|
||||
MMIO_0_SIZE = 0x10000000,
|
||||
MMIO_1_BASE = 0xF8000000, /* Programmable register via APB */
|
||||
MMIO_1_SIZE = 0x02000000,
|
||||
QSPI_MMIO_BASE = 0xFC000000, /* Quad-SPI */
|
||||
QSPI_MMIO_SIZE = 0x01000000,
|
||||
OCM_MMIO_BASE = 0xFFFC0000, /* OCM upper address range */
|
||||
OCM_MMIO_SIZE = 0x00040000,
|
||||
|
||||
/* normal RAM */
|
||||
RAM_0_BASE = 0x00000000,
|
||||
|
||||
/* AXI */
|
||||
AXI_0_MMIO_BASE = 0x40000000, /* PL AXI Slave port #0 */
|
||||
AXI_0_MMIO_SIZE = 0x40000000,
|
||||
AXI_1_MMIO_BASE = 0x80000000, /* PL AXI Slave port #1 */
|
||||
AXI_1_MMIO_SIZE = 0x40000000,
|
||||
|
||||
/* UART controllers */
|
||||
UART_0_MMIO_BASE = MMIO_0_BASE,
|
||||
UART_SIZE = 0x1000,
|
||||
UART_CLOCK = 50*1000*1000,
|
||||
|
||||
/* CPU */
|
||||
CORTEX_A9_PRIVATE_MEM_BASE = 0xf8f00000,
|
||||
CORTEX_A9_PRIVATE_MEM_SIZE = 0x00002000,
|
||||
|
||||
/* entrypoint address of secondary cpu */
|
||||
CORE1_ENTRY = 0xfffffff0,
|
||||
|
||||
/* CPU cache */
|
||||
PL310_MMIO_BASE = MMIO_1_BASE + 0xF02000,
|
||||
PL310_MMIO_SIZE = 0x1000,
|
||||
|
||||
/* TTC (triple timer counter) */
|
||||
TTC0_MMIO_BASE = MMIO_1_BASE + 0x1000,
|
||||
TTC0_MMIO_SIZE = 0xfff,
|
||||
TTC0_IRQ_0 = 42,
|
||||
|
||||
/* Ethernet MAC PS */
|
||||
EMAC_0_MMIO_BASE = 0xE000B000,
|
||||
EMAC_0_MMIO_SIZE = 0x1000,
|
||||
EMAC_0_IRQ = 54,
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__DRIVERS__DEFS__ZYNQ_H_ */
|
@ -1,31 +0,0 @@
|
||||
/*
|
||||
* \brief Base driver for the Zynq (QEMU)
|
||||
* \author Johannes Schlatow
|
||||
* \date 2015-06-30
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__DRIVERS__DEFS__ZYNQ_QEMU_H_
|
||||
#define _INCLUDE__DRIVERS__DEFS__ZYNQ_QEMU_H_
|
||||
|
||||
#include <drivers/defs/zynq.h>
|
||||
|
||||
namespace Zynq_qemu {
|
||||
|
||||
using namespace Zynq;
|
||||
|
||||
enum {
|
||||
RAM_0_SIZE = 0x40000000, /* 1GiB */
|
||||
|
||||
CORTEX_A9_PRIVATE_TIMER_CLK = 100000000,
|
||||
CORTEX_A9_PRIVATE_TIMER_DIV = 100,
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__DRIVERS__DEFS__ZYNQ_QEMU_H_ */
|
@ -1,129 +0,0 @@
|
||||
/*
|
||||
* \brief Base UART driver for the Xilinx UART PS used on Zynq devices
|
||||
* \author Johannes Schlatow
|
||||
* \date 2014-12-15
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__DRIVERS__UART__XILINX_H_
|
||||
#define _INCLUDE__DRIVERS__UART__XILINX_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/mmio.h>
|
||||
|
||||
namespace Genode { class Xilinx_uart; }
|
||||
|
||||
/**
|
||||
* Base driver Xilinx UART PS module
|
||||
*/
|
||||
class Genode::Xilinx_uart: public Mmio
|
||||
{
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Control register
|
||||
*/
|
||||
struct Uart_cr : Register<0x00, 32>
|
||||
{
|
||||
struct Rx_reset : Bitfield<0, 1> { };
|
||||
struct Tx_reset : Bitfield<1, 1> { };
|
||||
struct Rx_enable : Bitfield<2, 1> { };
|
||||
struct Tx_enable : Bitfield<4, 1> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Mode register
|
||||
*/
|
||||
struct Uart_mr : Register<0x04, 32>
|
||||
{
|
||||
struct Clock_sel : Bitfield<0, 1> { };
|
||||
struct Parity : Bitfield<3, 3> { enum { NO_PARITY = 4 }; };
|
||||
};
|
||||
|
||||
/**
|
||||
* Baudgen register
|
||||
*/
|
||||
struct Uart_baudgen : Register<0x18, 32>
|
||||
{
|
||||
struct Clock_div : Bitfield<0, 16> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Status register
|
||||
*/
|
||||
struct Uart_sr : Register<0x2C, 32>
|
||||
{
|
||||
struct Tx_full : Bitfield<4, 1> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* FIFO register
|
||||
*/
|
||||
struct Uart_fifo : Register<0x30, 32>
|
||||
{
|
||||
struct Data : Bitfield<0, 8> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Bauddiv register
|
||||
*/
|
||||
struct Uart_bauddiv : Register<0x34, 32>
|
||||
{
|
||||
struct Bdiv : Bitfield<0,8> { };
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param base MMIO base address
|
||||
* \param clock reference clock
|
||||
* \param baud_rate targeted baud rate
|
||||
*/
|
||||
Xilinx_uart(addr_t const base, unsigned long const clock,
|
||||
unsigned long const baud_rate) : Mmio(base)
|
||||
{
|
||||
/* reset UART */
|
||||
Uart_cr::access_t uart_cr = 0;
|
||||
Uart_cr::Tx_reset::set(uart_cr, 1);
|
||||
Uart_cr::Rx_reset::set(uart_cr, 1);
|
||||
write<Uart_cr>(uart_cr);
|
||||
|
||||
/* set baud rate */
|
||||
constexpr unsigned div = 4;
|
||||
write<Uart_bauddiv::Bdiv>(div);
|
||||
write<Uart_baudgen::Clock_div>(clock / baud_rate / (div + 1));
|
||||
|
||||
/* set 8N1 */
|
||||
Uart_mr::access_t uart_mr = 0;
|
||||
Uart_mr::Parity::set(uart_mr, Uart_mr::Parity::NO_PARITY);
|
||||
write<Uart_mr>(uart_mr);
|
||||
|
||||
/* enable */
|
||||
uart_cr = 0;
|
||||
Uart_cr::Rx_enable::set(uart_cr, 1);
|
||||
Uart_cr::Tx_enable::set(uart_cr, 1);
|
||||
write<Uart_cr>(uart_cr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transmit ASCII char 'c'
|
||||
*/
|
||||
void put_char(char const c)
|
||||
{
|
||||
/* wait as long as the transmission buffer is full */
|
||||
while (read<Uart_sr::Tx_full>()) ;
|
||||
|
||||
/* transmit character */
|
||||
write<Uart_fifo::Data>(c);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__DRIVERS__UART__XILINX_H_ */
|
@ -1,3 +0,0 @@
|
||||
|
||||
Device drivers needed for scenarios
|
||||
using one network interface
|
@ -1,2 +0,0 @@
|
||||
_/src/zynq_nic_drv
|
||||
_/raw/drivers_nic-zynq
|
@ -1 +0,0 @@
|
||||
2021-10-13 8cfb35f5bb47321172f50d4c15cea9ef2edd3259
|
@ -1,4 +0,0 @@
|
||||
content: drivers.config
|
||||
|
||||
drivers.config:
|
||||
cp $(REP_DIR)/recipes/raw/drivers_nic-zynq/$@ $@
|
@ -1,24 +0,0 @@
|
||||
<config>
|
||||
|
||||
<parent-provides>
|
||||
<service name="IRQ"/>
|
||||
<service name="IO_MEM"/>
|
||||
<service name="ROM"/>
|
||||
<service name="PD"/>
|
||||
<service name="RM"/>
|
||||
<service name="CPU"/>
|
||||
<service name="LOG"/>
|
||||
<service name="Timer"/>
|
||||
<service name="Uplink"/>
|
||||
</parent-provides>
|
||||
|
||||
<default caps="100"/>
|
||||
|
||||
<start name="nic_drv">
|
||||
<binary name="zynq_nic_drv"/>
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<config mode="uplink_client"/>
|
||||
<route> <any-service> <parent/> </any-service> </route>
|
||||
</start>
|
||||
|
||||
</config>
|
@ -1 +0,0 @@
|
||||
2021-02-22 0a32b3922e6d0d7f2f6eb53464e7db38476ca355
|
@ -1,2 +0,0 @@
|
||||
SRC_DIR = src/drivers/nic/spec/zynq
|
||||
include $(GENODE_DIR)/repos/base/recipes/src/content.inc
|
@ -1 +0,0 @@
|
||||
2021-10-13 ca8cb8596f9f0e760807a398e6e5a535667e791d
|
@ -1,5 +0,0 @@
|
||||
base
|
||||
os
|
||||
nic_session
|
||||
uplink_session
|
||||
nic_driver
|
@ -1,115 +0,0 @@
|
||||
/*
|
||||
* \brief Base EMAC driver for the Xilinx EMAC PS used on Zynq devices
|
||||
* \author Timo Wischer
|
||||
* \author Johannes Schlatow
|
||||
* \date 2015-03-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__DRIVERS__NIC__GEM__BUFFER_DESCRIPTOR_H_
|
||||
#define _INCLUDE__DRIVERS__NIC__GEM__BUFFER_DESCRIPTOR_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/attached_ram_dataspace.h>
|
||||
#include <util/mmio.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
class Buffer_descriptor : protected Attached_ram_dataspace, protected Mmio
|
||||
{
|
||||
public:
|
||||
static const size_t BUFFER_DESC_SIZE = 0x08;
|
||||
static const size_t BUFFER_SIZE = 1600;
|
||||
|
||||
private:
|
||||
size_t _buffer_count;
|
||||
size_t _head_idx { 0 };
|
||||
size_t _tail_idx { 0 };
|
||||
|
||||
protected:
|
||||
typedef struct {
|
||||
uint32_t addr;
|
||||
uint32_t status;
|
||||
} descriptor_t;
|
||||
|
||||
descriptor_t* const _descriptors;
|
||||
|
||||
/* set the maximum descriptor index */
|
||||
inline
|
||||
void _max_index(size_t max_index) { _buffer_count = max_index+1; };
|
||||
|
||||
/* get the maximum descriptor index */
|
||||
inline
|
||||
unsigned _max_index() { return _buffer_count-1; }
|
||||
|
||||
inline
|
||||
void _advance_head()
|
||||
{
|
||||
_head_idx = (_head_idx+1) % _buffer_count;
|
||||
}
|
||||
|
||||
inline
|
||||
void _advance_tail()
|
||||
{
|
||||
_tail_idx = (_tail_idx+1) % (_buffer_count);
|
||||
}
|
||||
|
||||
inline
|
||||
descriptor_t& _head()
|
||||
{
|
||||
return _descriptors[_head_idx];
|
||||
}
|
||||
|
||||
inline
|
||||
descriptor_t& _tail()
|
||||
{
|
||||
return _descriptors[_tail_idx];
|
||||
}
|
||||
|
||||
size_t _queued() const
|
||||
{
|
||||
if (_head_idx >= _tail_idx)
|
||||
return _head_idx - _tail_idx;
|
||||
else
|
||||
return _head_idx + _buffer_count - _tail_idx;
|
||||
}
|
||||
|
||||
size_t _head_index() const { return _head_idx; }
|
||||
size_t _tail_index() const { return _tail_idx; }
|
||||
|
||||
void _reset_head() { _head_idx = 0; }
|
||||
void _reset_tail() { _tail_idx = 0; }
|
||||
|
||||
private:
|
||||
|
||||
/*
|
||||
* Noncopyable
|
||||
*/
|
||||
Buffer_descriptor(Buffer_descriptor const &);
|
||||
Buffer_descriptor &operator = (Buffer_descriptor const &);
|
||||
|
||||
|
||||
public:
|
||||
/*
|
||||
* start of the ram spave contains all buffer descriptors
|
||||
* after that the data spaces for the ethernet packages are following
|
||||
*/
|
||||
Buffer_descriptor(Genode::Env &env, const size_t buffer_count = 1)
|
||||
:
|
||||
Attached_ram_dataspace(env.ram(), env.rm(), BUFFER_DESC_SIZE * buffer_count, UNCACHED),
|
||||
Genode::Mmio( reinterpret_cast<addr_t>(local_addr<void>()) ),
|
||||
_buffer_count(buffer_count),
|
||||
_descriptors(local_addr<descriptor_t>())
|
||||
{ }
|
||||
|
||||
addr_t phys_addr() { return Dataspace_client(cap()).phys_addr(); }
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__DRIVERS__NIC__GEM__BUFFER_DESCRIPTOR_H_ */
|
File diff suppressed because it is too large
Load Diff
@ -1,115 +0,0 @@
|
||||
/*
|
||||
* \brief EMACPS NIC driver for Xilix Zynq-7000
|
||||
* \author Timo Wischer
|
||||
* \date 2015-03-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/attached_rom_dataspace.h>
|
||||
#include <base/component.h>
|
||||
#include <base/heap.h>
|
||||
#include <drivers/defs/zynq.h>
|
||||
#include <nic/root.h>
|
||||
|
||||
/* NIC driver includes */
|
||||
#include <drivers/nic/mode.h>
|
||||
|
||||
/* local includes */
|
||||
#include "cadence_gem.h"
|
||||
|
||||
namespace Server {
|
||||
using namespace Genode;
|
||||
|
||||
class Gem_session_component;
|
||||
struct Main;
|
||||
}
|
||||
|
||||
|
||||
Nic::Mac_address
|
||||
read_mac_addr_from_config(Genode::Attached_rom_dataspace &config_rom)
|
||||
{
|
||||
Nic::Mac_address mac_addr;
|
||||
|
||||
/* fall back to fake MAC address (unicast, locally managed) */
|
||||
mac_addr.addr[0] = 0x02;
|
||||
mac_addr.addr[1] = 0x00;
|
||||
mac_addr.addr[2] = 0x00;
|
||||
mac_addr.addr[3] = 0x00;
|
||||
mac_addr.addr[4] = 0x00;
|
||||
mac_addr.addr[5] = 0x01;
|
||||
|
||||
/* try using configured MAC address */
|
||||
try {
|
||||
Genode::Xml_node nic_config = config_rom.xml().sub_node("nic");
|
||||
mac_addr = nic_config.attribute_value("mac", mac_addr);
|
||||
Genode::log("Using configured MAC address ", mac_addr);
|
||||
} catch (...) { }
|
||||
|
||||
return mac_addr;
|
||||
}
|
||||
|
||||
|
||||
class Server::Gem_session_component : public Cadence_gem
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Attached_rom_dataspace _config_rom;
|
||||
|
||||
public:
|
||||
|
||||
Gem_session_component(Genode::size_t const tx_buf_size,
|
||||
Genode::size_t const rx_buf_size,
|
||||
Genode::Allocator &rx_block_md_alloc,
|
||||
Genode::Env &env)
|
||||
:
|
||||
Cadence_gem(tx_buf_size, rx_buf_size, rx_block_md_alloc, env,
|
||||
Zynq::EMAC_0_MMIO_BASE,
|
||||
Zynq::EMAC_0_MMIO_SIZE,
|
||||
Zynq::EMAC_0_IRQ),
|
||||
_config_rom(env, "config")
|
||||
{
|
||||
mac_address(read_mac_addr_from_config(_config_rom));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Server::Main
|
||||
{
|
||||
Env &_env;
|
||||
Heap _heap { _env.ram(), _env.rm() };
|
||||
Constructible<Nic::Root<Gem_session_component> > _nic_root { };
|
||||
Constructible<Uplink_client> _uplink_client { };
|
||||
|
||||
Main(Env &env) : _env(env)
|
||||
{
|
||||
Attached_rom_dataspace config_rom { _env, "config" };
|
||||
Nic_driver_mode const mode {
|
||||
read_nic_driver_mode(config_rom.xml()) };
|
||||
|
||||
switch (mode) {
|
||||
case Nic_driver_mode::NIC_SERVER:
|
||||
|
||||
_nic_root.construct(_env, _heap );
|
||||
_env.parent().announce(_env.ep().manage(*_nic_root));
|
||||
break;
|
||||
|
||||
case Nic_driver_mode::UPLINK_CLIENT:
|
||||
|
||||
_uplink_client.construct(
|
||||
_env, _heap, Zynq::EMAC_0_MMIO_BASE, Zynq::EMAC_0_MMIO_SIZE,
|
||||
Zynq::EMAC_0_IRQ, read_mac_addr_from_config(config_rom));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void Component::construct(Genode::Env &env) { static Server::Main main(env); }
|
@ -1,580 +0,0 @@
|
||||
/*
|
||||
* \brief Phy driver for Marvell chips
|
||||
* \author Johannes Schlatow
|
||||
* \author Timo Wischer
|
||||
* \date 2015-05-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__DRIVERS__NIC__GEM__MARVELL_PHY_H_
|
||||
#define _INCLUDE__DRIVERS__NIC__GEM__MARVELL_PHY_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <os/attached_mmio.h>
|
||||
#include <nic_session/nic_session.h>
|
||||
#include <timer_session/connection.h>
|
||||
|
||||
#include "phyio.h"
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
|
||||
enum Eth_speed {
|
||||
UNDEFINED,
|
||||
SPEED_10 = 10,
|
||||
SPEED_100 = 100,
|
||||
SPEED_1000 = 1000
|
||||
};
|
||||
|
||||
class MII_phy
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* \param _OFFSET Offset/number of the register.
|
||||
*
|
||||
* For further details See 'Genode::Register'.
|
||||
*/
|
||||
template <uint8_t _OFFSET>
|
||||
struct Phy_register : public Genode::Register<16>
|
||||
{
|
||||
enum {
|
||||
OFFSET = _OFFSET,
|
||||
};
|
||||
|
||||
typedef Phy_register<_OFFSET>
|
||||
Register_base;
|
||||
|
||||
/**
|
||||
* A region within a register
|
||||
*
|
||||
* \param _SHIFT Bit shift of the first bit within the
|
||||
* compound register.
|
||||
* \param _WIDTH bit width of the region
|
||||
*
|
||||
* For details see 'Genode::Register::Bitfield'.
|
||||
*/
|
||||
template <unsigned long _SHIFT, unsigned long _WIDTH>
|
||||
struct Bitfield : public Genode::Register<16>::
|
||||
template Bitfield<_SHIFT, _WIDTH>
|
||||
{
|
||||
typedef Bitfield<_SHIFT, _WIDTH> Bitfield_base;
|
||||
|
||||
/* back reference to containing register */
|
||||
typedef Phy_register<_OFFSET>
|
||||
Compound_reg;
|
||||
};
|
||||
};
|
||||
|
||||
/*************************
|
||||
* Generic MII registers *
|
||||
*************************/
|
||||
|
||||
/* Basic mode control register */
|
||||
struct Bmcr : Phy_register<0x00>
|
||||
{
|
||||
struct Resv : Bitfield<0, 6> { }; /* Unused... */
|
||||
struct Speed1000 : Bitfield<6, 1> { }; /* MSB of Speed (1000) */
|
||||
struct Ctst : Bitfield<7, 1> { }; /* Collision test */
|
||||
struct Fulldplx : Bitfield<8, 1> { }; /* Full duplex */
|
||||
struct Anrestart : Bitfield<9, 1> { }; /* Auto negotiation restart */
|
||||
struct Isolate : Bitfield<10,1> { }; /* Disconnect DP83840 from MII */
|
||||
struct Pdown : Bitfield<11,1> { }; /* Powerdown the DP83840 */
|
||||
struct Anenable : Bitfield<12,1> { }; /* Enable auto negotiation */
|
||||
struct Speed100 : Bitfield<13,1> { }; /* Select 100Mbps */
|
||||
struct Loopback : Bitfield<14,1> { }; /* TXD loopback bits */
|
||||
struct Reset : Bitfield<15,1> { }; /* Reset the DP83840 */
|
||||
};
|
||||
|
||||
/* Basic mode status register */
|
||||
struct Bmsr : Phy_register<0x01>
|
||||
{
|
||||
enum {
|
||||
INVALID = 0xFFFF
|
||||
};
|
||||
|
||||
struct Ercap : Bitfield<0, 1> { }; /* Ext-reg capability */
|
||||
struct Jcd : Bitfield<1, 1> { }; /* Jabber detected */
|
||||
struct Lstatus : Bitfield<2, 1> { }; /* Link status */
|
||||
struct Anegcapable : Bitfield<3, 1> { }; /* Able to do auto-negotiation */
|
||||
struct Rfault : Bitfield<4, 1> { }; /* Remote fault detected */
|
||||
struct Anegcomplete: Bitfield<5, 1> { }; /* Auto-negotiation complete */
|
||||
struct Resv : Bitfield<6, 1> { }; /* Unused... */
|
||||
struct Estaten : Bitfield<7, 1> { }; /* Extended Status in R15 */
|
||||
struct Half2_100 : Bitfield<8, 1> { }; /* Can do 100BASE-T2 HDX */
|
||||
struct Full2_100 : Bitfield<9, 1> { }; /* Can do 100BASE-T2 FDX */
|
||||
struct Half_10 : Bitfield<10,1> { }; /* Can do 10mbps, half-duplex */
|
||||
struct Full_10 : Bitfield<11,1> { }; /* Can do 10mbps, full-duplex */
|
||||
struct Half_100 : Bitfield<12,1> { }; /* Can do 100mbps, half-duplex */
|
||||
struct Full_100 : Bitfield<13,1> { }; /* Can do 100mbps, full-duplex */
|
||||
struct Base4_100 : Bitfield<14,1> { }; /* Can do 100mbps, 4k packets */
|
||||
};
|
||||
|
||||
/* ID register 1 */
|
||||
struct Idr1 : Phy_register<0x02> { };
|
||||
|
||||
/* ID register 2 */
|
||||
struct Idr2 : Phy_register<0x03> { };
|
||||
|
||||
/* Advertisement control reg */
|
||||
struct Advertise : Phy_register<0x04>
|
||||
{
|
||||
struct Csma : Bitfield<0, 1> { };
|
||||
struct Half_10 : Bitfield<5, 1> { }; /* Try for 10mbps half-duplex */
|
||||
struct FullX_1000 : Bitfield<5, 1> { }; /* Try for 1000BASE-X full-duplex */
|
||||
struct Full_10 : Bitfield<6, 1> { }; /* Try for 10mbps full-duplex */
|
||||
struct HalfX_1000 : Bitfield<6, 1> { }; /* Try for 1000BASE-X half-duplex */
|
||||
struct Half_100 : Bitfield<7, 1> { }; /* Try for 100mbps half-duplex */
|
||||
struct PauseX_1000 : Bitfield<7, 1> { }; /* Try for 1000BASE-X pause */
|
||||
struct Full_100 : Bitfield<8, 1> { }; /* Try for 100mbps full-duplex */
|
||||
struct AsymXPSE_1000: Bitfield<8, 1> { }; /* Try for 1000BASE-X asym pause */
|
||||
struct Base4_100 : Bitfield<9, 1> { }; /* Try for 100mbps 4k packets */
|
||||
struct Pause_cap : Bitfield<10,1> { }; /* Try for pause */
|
||||
struct Pause_asym : Bitfield<11,1> { }; /* Try for asymetrict pause */
|
||||
struct Rfault : Bitfield<13,1> { }; /* Say we can detect faults */
|
||||
struct Lpack : Bitfield<14,1> { }; /* Ack link partners response */
|
||||
struct Npage : Bitfield<15,1> { }; /* Next page bit */
|
||||
};
|
||||
|
||||
/* 1000BASE-T control */
|
||||
struct Ctrl1000 : Phy_register<0x09>
|
||||
{
|
||||
struct Half_1000 : Bitfield<8, 1> { }; /* Advertise 1000BASE-T full duplex */
|
||||
struct Full_1000 : Bitfield<9, 1> { }; /* Advertise 1000BASE-T half duplex */
|
||||
};
|
||||
};
|
||||
|
||||
class Marvel_phy : public MII_phy
|
||||
{
|
||||
public:
|
||||
class Phy_timeout_after_reset : public Genode::Exception {};
|
||||
|
||||
|
||||
private:
|
||||
|
||||
enum {
|
||||
PHY_AUTONEGOTIATE_TIMEOUT = 5000
|
||||
};
|
||||
|
||||
Timer::Connection &_timer;
|
||||
Phyio& _phyio;
|
||||
int8_t _phyaddr;
|
||||
bool _link_up;
|
||||
Eth_speed _eth_speed;
|
||||
|
||||
|
||||
/*************************
|
||||
* 88E1310 PHY registers *
|
||||
*************************/
|
||||
|
||||
struct Led_ctrl : Phy_register<16>
|
||||
{
|
||||
struct Data : Bitfield<0, 4> { };
|
||||
};
|
||||
|
||||
struct Irq_en : Phy_register<18> { };
|
||||
|
||||
struct RGMII_ctrl : Phy_register<21> { };
|
||||
|
||||
struct Page_select : Phy_register<22> { };
|
||||
|
||||
/* 88E1011 PHY Status Register */
|
||||
struct Phy_stat : Phy_register<0x11>
|
||||
{
|
||||
struct Link : Bitfield<10,1> { };
|
||||
struct Spddone : Bitfield<11,1> { };
|
||||
struct Duplex : Bitfield<13,1> { };
|
||||
struct Speed_100 : Bitfield<14,1> { };
|
||||
struct Speed_1000 : Bitfield<15,1> { };
|
||||
};
|
||||
|
||||
/**
|
||||
* Read register of detected PHY.
|
||||
*/
|
||||
inline uint16_t _phy_read(const uint8_t regnum) const
|
||||
{
|
||||
uint16_t val;
|
||||
_phyio.phy_read(_phyaddr, regnum, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write register of detected PHY.
|
||||
*/
|
||||
inline void _phy_write(const uint8_t regnum, const uint16_t data) const
|
||||
{
|
||||
_phyio.phy_write(_phyaddr, regnum, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read PHY register 'T'
|
||||
*/
|
||||
template <typename T>
|
||||
inline typename T::Register_base::access_t phy_read() const
|
||||
{
|
||||
typedef typename T::Register_base Register;
|
||||
return _phy_read(Register::OFFSET);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the bitfield 'T' of PHY register
|
||||
*/
|
||||
template <typename T>
|
||||
inline typename T::Bitfield_base::Compound_reg::access_t
|
||||
phy_read() const
|
||||
{
|
||||
typedef typename T::Bitfield_base Bitfield;
|
||||
typedef typename Bitfield::Compound_reg Register;
|
||||
return Bitfield::get(_phy_read(Register::OFFSET));
|
||||
}
|
||||
|
||||
/**
|
||||
* Write PHY register 'T'
|
||||
*/
|
||||
template <typename T>
|
||||
inline void phy_write(uint16_t const val) const
|
||||
{
|
||||
typedef typename T::Register_base Register;
|
||||
return _phy_write(Register::OFFSET, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect PHY address.
|
||||
*/
|
||||
void phy_detection()
|
||||
{
|
||||
/* check _phyaddr */
|
||||
if (_phyaddr != -1) {
|
||||
Bmsr::access_t phyreg = phy_read<Bmsr>();
|
||||
if ((phyreg != Bmsr::INVALID) &&
|
||||
Bmsr::Full_10::get(phyreg) &&
|
||||
Bmsr::Anegcapable::get(phyreg)) {
|
||||
/* Found a valid PHY address */
|
||||
log("default phy address ", (int)_phyaddr, " is valid");
|
||||
return;
|
||||
} else {
|
||||
log("PHY address is not setup correctly ", (int)_phyaddr);
|
||||
_phyaddr = -1;
|
||||
}
|
||||
}
|
||||
|
||||
log("detecting phy address");
|
||||
if (_phyaddr == -1) {
|
||||
/* detect the PHY address */
|
||||
for (int i = 31; i >= 0; i--) {
|
||||
_phyaddr = i;
|
||||
Bmsr::access_t phyreg = phy_read<Bmsr>();
|
||||
if ((phyreg != Bmsr::INVALID) &&
|
||||
Bmsr::Full_10::get(phyreg) &&
|
||||
Bmsr::Anegcapable::get(phyreg)) {
|
||||
/* Found a valid PHY address */
|
||||
log("found valid phy address, ", i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
warning("PHY is not detected");
|
||||
_phyaddr = -1;
|
||||
}
|
||||
|
||||
uint32_t get_phy_id()
|
||||
{
|
||||
uint32_t phy_id = 0;
|
||||
|
||||
/* Grab the bits from PHYIR1, and put them
|
||||
* in the upper half */
|
||||
phy_id = phy_read<Idr1>() << 16;
|
||||
|
||||
/* Grab the bits from PHYIR2, and put them in the lower half */
|
||||
phy_id |= phy_read<Idr2>();
|
||||
|
||||
return phy_id;
|
||||
}
|
||||
|
||||
void m88e1310_config()
|
||||
{
|
||||
/* LED link and activity */
|
||||
phy_write<Page_select>(0x0003);
|
||||
Led_ctrl::access_t led = phy_read<Led_ctrl>();
|
||||
Led_ctrl::Data::set(led, 0x1);
|
||||
phy_write<Led_ctrl>(led);
|
||||
|
||||
/* Set LED2/INT to INT mode, low active */
|
||||
phy_write<Page_select>(0x0003);
|
||||
Irq_en::access_t irq = phy_read<Irq_en>();
|
||||
irq = (irq & 0x77ff) | 0x0880;
|
||||
phy_write<Irq_en>(irq);
|
||||
|
||||
/* Set RGMII delay */
|
||||
phy_write<Page_select>(0x0002);
|
||||
RGMII_ctrl::access_t ctrl = phy_read<RGMII_ctrl>();
|
||||
ctrl |= 0x0030;
|
||||
phy_write<RGMII_ctrl>(ctrl);
|
||||
|
||||
/* Ensure to return to page 0 */
|
||||
phy_write<Page_select>(0x0000);
|
||||
|
||||
genphy_config_aneg();
|
||||
phy_reset();
|
||||
}
|
||||
|
||||
int genphy_config_aneg()
|
||||
{
|
||||
/**
|
||||
* Description: If auto-negotiation is enabled, we configure the
|
||||
* advertising, and then restart auto-negotiation. If it is not
|
||||
* enabled, then we write the BMCR.
|
||||
*/
|
||||
int result = genphy_config_advert();
|
||||
|
||||
if (result < 0) /* error */
|
||||
return result;
|
||||
|
||||
if (result == 0) {
|
||||
log("config not changed");
|
||||
/* Advertisment hasn't changed, but maybe aneg was never on to
|
||||
* begin with? Or maybe phy was isolated? */
|
||||
uint16_t ctl = phy_read<Bmcr>();
|
||||
|
||||
if (!Bmcr::Anenable::get(ctl) || Bmcr::Isolate::get(ctl))
|
||||
result = 1; /* do restart aneg */
|
||||
} else {
|
||||
log("config changed");
|
||||
}
|
||||
|
||||
/* Only restart aneg if we are advertising something different
|
||||
* than we were before. */
|
||||
if (result > 0)
|
||||
result = genphy_restart_aneg();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int genphy_config_advert()
|
||||
{
|
||||
/**
|
||||
* Description: Writes MII_ADVERTISE with the appropriate values,
|
||||
* after sanitizing the values to make sure we only advertise
|
||||
* what is supported. Returns < 0 on error, 0 if the PHY's advertisement
|
||||
* hasn't changed, and > 0 if it has changed.
|
||||
*/
|
||||
int changed = 0;
|
||||
|
||||
/* Setup standard advertisement */
|
||||
Advertise::access_t adv = phy_read<Advertise>();
|
||||
|
||||
Advertise::access_t oldadv = adv;
|
||||
|
||||
Advertise::Base4_100::set(adv, 0);
|
||||
Advertise::Pause_cap::set(adv, 1);
|
||||
Advertise::Pause_asym::set(adv, 1);
|
||||
Advertise::Half_10::set(adv, 1);
|
||||
Advertise::Full_10::set(adv, 1);
|
||||
Advertise::Half_100::set(adv, 1);
|
||||
Advertise::Full_100::set(adv, 1);
|
||||
|
||||
if (adv != oldadv) {
|
||||
phy_write<Advertise>(adv);
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
/* Configure gigabit if it's supported */
|
||||
adv = phy_read<Ctrl1000>();
|
||||
|
||||
oldadv = adv;
|
||||
|
||||
Ctrl1000::Full_1000::set(adv, 1);
|
||||
Ctrl1000::Half_1000::set(adv, 1);
|
||||
|
||||
if (adv != oldadv) {
|
||||
phy_write<Ctrl1000>(adv);
|
||||
changed = 1;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
int genphy_restart_aneg()
|
||||
{
|
||||
Bmcr::access_t ctl = phy_read<Bmcr>();
|
||||
Bmcr::Anenable::set(ctl, 1);
|
||||
Bmcr::Anrestart::set(ctl, 1);
|
||||
|
||||
/* Don't isolate the PHY if we're negotiating */
|
||||
Bmcr::Isolate::set(ctl, 0);
|
||||
|
||||
phy_write<Bmcr>(ctl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int phy_reset()
|
||||
{
|
||||
int timeout = 500;
|
||||
|
||||
Bmcr::access_t reg = phy_read<Bmcr>();
|
||||
Bmcr::Reset::set(reg, 1);
|
||||
phy_write<Bmcr>(reg);
|
||||
|
||||
/*
|
||||
* Poll the control register for the reset bit to go to 0 (it is
|
||||
* auto-clearing). This should happen within 0.5 seconds per the
|
||||
* IEEE spec.
|
||||
*/
|
||||
while (phy_read<Bmcr::Reset>() && timeout--) {
|
||||
_timer.msleep(1);
|
||||
}
|
||||
|
||||
if (phy_read<Bmcr::Reset>()) {
|
||||
warning("PHY reset timed out");
|
||||
throw Phy_timeout_after_reset();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int m88e1011s_startup()
|
||||
{
|
||||
genphy_update_link();
|
||||
m88e1xxx_parse_status();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int genphy_update_link()
|
||||
{
|
||||
/**
|
||||
* Description: Update the value in phydev->link to reflect the
|
||||
* current link value. In order to do this, we need to read
|
||||
* the status register twice, keeping the second value.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Wait if the link is up, and autonegotiation is in progress
|
||||
* (ie - we're capable and it's not done)
|
||||
*/
|
||||
Bmsr::access_t mii_reg = phy_read<Bmsr>();
|
||||
|
||||
/*
|
||||
* If we already saw the link up, and it hasn't gone down, then
|
||||
* we don't need to wait for autoneg again
|
||||
*/
|
||||
if (_link_up && Bmsr::Lstatus::get(mii_reg))
|
||||
return 0;
|
||||
|
||||
if ( Bmsr::Anegcapable::get(mii_reg) && !Bmsr::Anegcomplete::get(mii_reg) ) {
|
||||
int i = 0;
|
||||
|
||||
Genode::log("waiting for PHY auto negotiation to complete");
|
||||
while (!Bmsr::Anegcomplete::get(mii_reg)) {
|
||||
/*
|
||||
* Timeout reached ?
|
||||
*/
|
||||
if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
|
||||
warning(" TIMEOUT !");
|
||||
_link_up = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((i++ % 500) == 0)
|
||||
Genode::log(".");
|
||||
_timer.msleep(1);
|
||||
|
||||
mii_reg = phy_read<Bmsr>();
|
||||
}
|
||||
Genode::log(" done");
|
||||
_link_up = true;
|
||||
} else {
|
||||
/* Read the link a second time to clear the latched state */
|
||||
mii_reg = phy_read<Bmsr>();
|
||||
|
||||
if (Bmsr::Lstatus::get(mii_reg))
|
||||
_link_up = true;
|
||||
else
|
||||
_link_up = false;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int m88e1xxx_parse_status()
|
||||
{
|
||||
/**
|
||||
* Parse the 88E1011's status register for speed and duplex
|
||||
* information
|
||||
*/
|
||||
Phy_stat::access_t stat = phy_read<Phy_stat>();
|
||||
|
||||
if ( Phy_stat::Link::get(stat) &&
|
||||
!Phy_stat::Spddone::get(stat)) {
|
||||
int i = 0;
|
||||
|
||||
log("waiting for PHY realtime link");
|
||||
while (!phy_read<Phy_stat::Spddone>()) {
|
||||
/* Timeout reached ? */
|
||||
if (i > PHY_AUTONEGOTIATE_TIMEOUT) {
|
||||
warning(" TIMEOUT !");
|
||||
_link_up = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((i++ % 1000) == 0)
|
||||
Genode::log(".");
|
||||
_timer.msleep(1);
|
||||
}
|
||||
log(" done");
|
||||
_timer.msleep(500);
|
||||
} else {
|
||||
if (Phy_stat::Link::get(stat))
|
||||
_link_up = true;
|
||||
else
|
||||
_link_up = false;
|
||||
}
|
||||
|
||||
// TODO change emac configuration if half duplex
|
||||
|
||||
if (Phy_stat::Speed_1000::get(stat))
|
||||
_eth_speed = SPEED_1000;
|
||||
else if (Phy_stat::Speed_100::get(stat))
|
||||
_eth_speed = SPEED_100;
|
||||
else
|
||||
_eth_speed = SPEED_10;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
Marvel_phy(Phyio& phyio, Timer::Connection &timer)
|
||||
:
|
||||
_timer(timer),
|
||||
_phyio(phyio),
|
||||
_phyaddr(0),
|
||||
_link_up(false),
|
||||
_eth_speed(UNDEFINED)
|
||||
{ }
|
||||
|
||||
void init()
|
||||
{
|
||||
phy_detection();
|
||||
|
||||
uint32_t phy_id = get_phy_id();
|
||||
log("the found phy has the id ", Hex(phy_id));
|
||||
|
||||
phy_reset();
|
||||
m88e1310_config();
|
||||
m88e1011s_startup();
|
||||
}
|
||||
|
||||
Eth_speed eth_speed() { return _eth_speed; }
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__DRIVERS__NIC__GEM__MARVELL_PHY_H_ */
|
||||
|
@ -1,31 +0,0 @@
|
||||
/*
|
||||
* \brief Phy driver for Marvell chips
|
||||
* \author Timo Wischer
|
||||
* \date 2015-05-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__DRIVERS__NIC__GEM__PHYIO_H_
|
||||
#define _INCLUDE__DRIVERS__NIC__GEM__PHYIO_H_
|
||||
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
class Phyio
|
||||
{
|
||||
public:
|
||||
virtual void phy_write(const uint8_t phyaddr, const uint8_t regnum, const uint16_t data) = 0;
|
||||
virtual void phy_read(const uint8_t phyaddr, const uint8_t regnum, uint16_t &data) = 0;
|
||||
|
||||
virtual ~Phyio() { }
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__DRIVERS__NIC__GEM__PHYIO_H_ */
|
||||
|
@ -1,150 +0,0 @@
|
||||
/*
|
||||
* \brief Base EMAC driver for the Xilinx EMAC PS used on Zynq devices
|
||||
* \author Timo Wischer
|
||||
* \author Johannes Schlatow
|
||||
* \date 2015-03-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__DRIVERS__NIC__GEM__RX_BUFFER_DESCRIPTOR_H_
|
||||
#define _INCLUDE__DRIVERS__NIC__GEM__RX_BUFFER_DESCRIPTOR_H_
|
||||
|
||||
#include "buffer_descriptor.h"
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
struct Rx_buffer_source
|
||||
{
|
||||
virtual ~Rx_buffer_source() { }
|
||||
|
||||
virtual Dataspace_capability dataspace() = 0;
|
||||
|
||||
virtual Packet_descriptor alloc_packet(size_t size) = 0;
|
||||
};
|
||||
|
||||
|
||||
class Rx_buffer_descriptor : public Buffer_descriptor
|
||||
{
|
||||
private:
|
||||
|
||||
struct Addr : Register<0x00, 32> {
|
||||
struct Addr31to2 : Bitfield<2, 30> {};
|
||||
struct Wrap : Bitfield<1, 1> {};
|
||||
struct Used : Bitfield<0, 1> {};
|
||||
};
|
||||
struct Status : Register<0x04, 32> {
|
||||
struct Length : Bitfield<0, 13> {};
|
||||
struct Start_of_frame : Bitfield<14, 1> {};
|
||||
struct End_of_frame : Bitfield<15, 1> {};
|
||||
};
|
||||
|
||||
enum { MAX_BUFFER_COUNT = 1024 };
|
||||
|
||||
addr_t const _phys_base;
|
||||
|
||||
void _reset_descriptor(unsigned const i, addr_t phys_addr) {
|
||||
if (i > _max_index())
|
||||
return;
|
||||
|
||||
/* clear status */
|
||||
_descriptors[i].status = 0;
|
||||
|
||||
/* set physical buffer address and set not used by SW
|
||||
* last descriptor must be marked by Wrap bit
|
||||
*/
|
||||
_descriptors[i].addr =
|
||||
(phys_addr & Addr::Addr31to2::reg_mask())
|
||||
| Addr::Wrap::bits(i == _max_index());
|
||||
}
|
||||
|
||||
inline bool _head_available()
|
||||
{
|
||||
return Addr::Used::get(_head().addr)
|
||||
&& Status::Length::get(_head().status);
|
||||
}
|
||||
|
||||
public:
|
||||
Rx_buffer_descriptor(Genode::Env &env,
|
||||
Rx_buffer_source &source)
|
||||
: Buffer_descriptor(env, MAX_BUFFER_COUNT),
|
||||
_phys_base(Dataspace_client(source.dataspace()).phys_addr())
|
||||
{
|
||||
for (size_t i=0; i <= _max_index(); i++) {
|
||||
try {
|
||||
Nic::Packet_descriptor p = source.alloc_packet(BUFFER_SIZE);
|
||||
_reset_descriptor(i, _phys_base + p.offset());
|
||||
} catch (Nic::Session::Rx::Source::Packet_alloc_failed) {
|
||||
/* set new _buffer_count */
|
||||
_max_index(i-1);
|
||||
/* set wrap bit */
|
||||
_descriptors[_max_index()].addr |= Addr::Wrap::bits(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Genode::log("Initialised ", _max_index()+1, " RX buffer descriptors");
|
||||
}
|
||||
|
||||
bool reset_descriptor(Packet_descriptor pd)
|
||||
{
|
||||
addr_t const phys = _phys_base + pd.offset();
|
||||
|
||||
for (size_t i=0; i <= _max_index(); i++) {
|
||||
_advance_tail();
|
||||
if (Addr::Addr31to2::masked(_tail().addr) == phys) {
|
||||
_reset_descriptor(_tail_index(), phys);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
for (size_t i=0; i <= _max_index(); i++) {
|
||||
_descriptors[i].status = 0;
|
||||
Addr::Used::set(_descriptors[i].addr, 0);
|
||||
}
|
||||
_reset_head();
|
||||
}
|
||||
|
||||
bool next_packet()
|
||||
{
|
||||
if (_head_available())
|
||||
return true;
|
||||
|
||||
_advance_head();
|
||||
return _head_available();
|
||||
}
|
||||
|
||||
Nic::Packet_descriptor get_packet_descriptor()
|
||||
{
|
||||
if (!_head_available())
|
||||
return Nic::Packet_descriptor(0, 0);
|
||||
|
||||
const Status::access_t status = _head().status;
|
||||
if (!Status::Start_of_frame::get(status) || !Status::End_of_frame::get(status)) {
|
||||
warning("Packet split over more than one descriptor. Packet ignored!");
|
||||
|
||||
_reset_descriptor(_head_index(), _head().addr);
|
||||
return Nic::Packet_descriptor(0, 0);
|
||||
}
|
||||
|
||||
const size_t length = Status::Length::get(status);
|
||||
|
||||
/* reset status */
|
||||
_head().status = 0;
|
||||
|
||||
return Nic::Packet_descriptor((addr_t)Addr::Addr31to2::masked(_head().addr) - _phys_base, length);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__DRIVERS__NIC__GEM__RX_BUFFER_DESCRIPTOR_H_ */
|
@ -1,154 +0,0 @@
|
||||
/*
|
||||
* \brief Base EMAC driver for the Xilinx EMAC PS used on Zynq devices
|
||||
* \author Timo Wischer
|
||||
* \date 2015-03-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__DRIVERS__NIC__GEM__SYSTEM_CONTROL_H_
|
||||
#define _INCLUDE__DRIVERS__NIC__GEM__SYSTEM_CONTROL_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <os/attached_mmio.h>
|
||||
#include <timer_session/connection.h>
|
||||
|
||||
#include <drivers/defs/zynq.h>
|
||||
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
class System_control : private Genode::Attached_mmio
|
||||
{
|
||||
private:
|
||||
struct Lock : Register<0x4, 32> {
|
||||
enum { MAGIC = 0x767B };
|
||||
};
|
||||
struct Unlock : Register<0x8, 32> {
|
||||
enum { MAGIC = 0xDF0D };
|
||||
};
|
||||
struct Gem0_rclk_ctrl : Register<0x138, 32> { };
|
||||
struct Gem0_clk_ctrl : Register<0x140, 32> { };
|
||||
|
||||
struct Mio_pin_16 : Register<0x740, 32> {
|
||||
struct Tri_state_enable : Bitfield<0, 1> {};
|
||||
struct Level_0_mux : Bitfield<1, 1> {
|
||||
enum { ETH0 = 0b1 };
|
||||
};
|
||||
struct Fast_cmos_edge : Bitfield<8, 1> {};
|
||||
struct IO_type : Bitfield<9, 3> {
|
||||
enum { LVCMOS18 = 0b001 };
|
||||
};
|
||||
|
||||
static access_t FAST_LVCMOS18_ETH0() {
|
||||
return Fast_cmos_edge::bits(1) |
|
||||
IO_type::bits(IO_type::LVCMOS18) |
|
||||
Level_0_mux::bits(Level_0_mux::ETH0);
|
||||
}
|
||||
|
||||
static access_t FAST_LVCMOS18_ETH0_TRISTATE() {
|
||||
return FAST_LVCMOS18_ETH0() |
|
||||
Tri_state_enable::bits(1);
|
||||
}
|
||||
};
|
||||
struct Mio_pin_17 : Register<0x744, 32> { };
|
||||
struct Mio_pin_18 : Register<0x748, 32> { };
|
||||
struct Mio_pin_19 : Register<0x74C, 32> { };
|
||||
struct Mio_pin_20 : Register<0x750, 32> { };
|
||||
struct Mio_pin_21 : Register<0x754, 32> { };
|
||||
struct Mio_pin_22 : Register<0x758, 32> { };
|
||||
struct Mio_pin_23 : Register<0x75C, 32> { };
|
||||
struct Mio_pin_24 : Register<0x760, 32> { };
|
||||
struct Mio_pin_25 : Register<0x764, 32> { };
|
||||
struct Mio_pin_26 : Register<0x768, 32> { };
|
||||
struct Mio_pin_27 : Register<0x76C, 32> { };
|
||||
|
||||
struct Mio_pin_52 : Register<0x7D0, 32> {
|
||||
struct Level_3_mux : Bitfield<5, 3> {
|
||||
enum { MDIO0 = 0b100 };
|
||||
};
|
||||
|
||||
static access_t LVCMOS18_MDIO0() {
|
||||
return Mio_pin_16::IO_type::bits(Mio_pin_16::IO_type::LVCMOS18) |
|
||||
Level_3_mux::bits(Level_3_mux::MDIO0);
|
||||
}
|
||||
};
|
||||
struct Mio_pin_53 : Register<0x7D4, 32> { };
|
||||
|
||||
struct Gpio_b_ctrl : Register<0xB00, 32> {
|
||||
struct Vref_enable : Bitfield<0, 1> {};
|
||||
};
|
||||
|
||||
|
||||
class Lock_guard
|
||||
{
|
||||
private:
|
||||
System_control& _sys_ctrl;
|
||||
|
||||
void _unlock() { _sys_ctrl.write<Unlock>(Unlock::MAGIC); }
|
||||
void _lock() { _sys_ctrl.write<Lock>(Lock::MAGIC); }
|
||||
|
||||
public:
|
||||
Lock_guard(System_control& sys_ctrl) : _sys_ctrl(sys_ctrl)
|
||||
{
|
||||
_unlock();
|
||||
}
|
||||
|
||||
~Lock_guard()
|
||||
{
|
||||
_lock();
|
||||
}
|
||||
};
|
||||
|
||||
unsigned int old_data[0x300];
|
||||
|
||||
|
||||
Timer::Connection &_timer;
|
||||
|
||||
public:
|
||||
System_control(Genode::Env &env, Timer::Connection &timer) :
|
||||
Attached_mmio(env, Zynq::MMIO_1_BASE, 0xB80),
|
||||
_timer(timer)
|
||||
{
|
||||
Lock_guard lock(*this);
|
||||
|
||||
write<Mio_pin_16>(Mio_pin_16::FAST_LVCMOS18_ETH0());
|
||||
write<Mio_pin_17>(Mio_pin_16::FAST_LVCMOS18_ETH0());
|
||||
write<Mio_pin_18>(Mio_pin_16::FAST_LVCMOS18_ETH0());
|
||||
write<Mio_pin_19>(Mio_pin_16::FAST_LVCMOS18_ETH0());
|
||||
write<Mio_pin_20>(Mio_pin_16::FAST_LVCMOS18_ETH0());
|
||||
write<Mio_pin_21>(Mio_pin_16::FAST_LVCMOS18_ETH0());
|
||||
|
||||
write<Mio_pin_22>(Mio_pin_16::FAST_LVCMOS18_ETH0_TRISTATE());
|
||||
write<Mio_pin_23>(Mio_pin_16::FAST_LVCMOS18_ETH0_TRISTATE());
|
||||
write<Mio_pin_24>(Mio_pin_16::FAST_LVCMOS18_ETH0_TRISTATE());
|
||||
write<Mio_pin_25>(Mio_pin_16::FAST_LVCMOS18_ETH0_TRISTATE());
|
||||
write<Mio_pin_26>(Mio_pin_16::FAST_LVCMOS18_ETH0_TRISTATE());
|
||||
write<Mio_pin_27>(Mio_pin_16::FAST_LVCMOS18_ETH0_TRISTATE());
|
||||
|
||||
write<Mio_pin_52>(Mio_pin_52::LVCMOS18_MDIO0());
|
||||
write<Mio_pin_53>(Mio_pin_52::LVCMOS18_MDIO0());
|
||||
|
||||
// TODO possibly not needed because uboot do not enable this register
|
||||
/* enable internel VRef */
|
||||
write<Gpio_b_ctrl>(Gpio_b_ctrl::Vref_enable::bits(1));
|
||||
}
|
||||
|
||||
void set_clk(uint32_t clk, uint32_t rclk)
|
||||
{
|
||||
Lock_guard lock(*this);
|
||||
|
||||
write<Gem0_clk_ctrl>(clk);
|
||||
write<Gem0_rclk_ctrl>(rclk);
|
||||
|
||||
_timer.msleep(100);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__DRIVERS__NIC__GEM__SYSTEM_CONTROL_H_ */
|
@ -1,5 +0,0 @@
|
||||
REQUIRES = arm_v7
|
||||
TARGET = zynq_nic_drv
|
||||
SRC_CC = main.cc
|
||||
LIBS = base nic_driver
|
||||
INC_DIR += $(PRG_DIR)
|
@ -1,181 +0,0 @@
|
||||
/*
|
||||
* \brief Base EMAC driver for the Xilinx EMAC PS used on Zynq devices
|
||||
* \author Timo Wischer
|
||||
* \author Johannes Schlatow
|
||||
* \date 2015-03-10
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__DRIVERS__NIC__GEM__TX_BUFFER_DESCRIPTOR_H_
|
||||
#define _INCLUDE__DRIVERS__NIC__GEM__TX_BUFFER_DESCRIPTOR_H_
|
||||
|
||||
#include <base/log.h>
|
||||
#include <timer_session/connection.h>
|
||||
|
||||
#include "buffer_descriptor.h"
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
struct Tx_buffer_sink
|
||||
{
|
||||
virtual ~Tx_buffer_sink() { }
|
||||
|
||||
virtual Dataspace_capability dataspace() = 0;
|
||||
|
||||
virtual void acknowledge_packet(Packet_descriptor packet) = 0;
|
||||
|
||||
virtual bool packet_valid(Packet_descriptor packet) = 0;
|
||||
};
|
||||
|
||||
|
||||
class Tx_buffer_descriptor : public Buffer_descriptor
|
||||
{
|
||||
private:
|
||||
enum { BUFFER_COUNT = 1024 };
|
||||
|
||||
struct Addr : Register<0x00, 32> {};
|
||||
struct Status : Register<0x04, 32> {
|
||||
struct Length : Bitfield<0, 14> {};
|
||||
struct Last_buffer : Bitfield<15, 1> {};
|
||||
struct Wrap : Bitfield<30, 1> {};
|
||||
struct Used : Bitfield<31, 1> {};
|
||||
struct Chksum_err : Bitfield<20, 3> {};
|
||||
struct Crc_present: Bitfield<16, 1> {};
|
||||
struct Late_collision: Bitfield<26, 1> {};
|
||||
struct Corrupt: Bitfield<27, 1> {};
|
||||
struct Retry_limit: Bitfield<29, 1> {};
|
||||
};
|
||||
|
||||
Timer::Connection &_timer;
|
||||
|
||||
addr_t const _phys_base;
|
||||
|
||||
void _reset_descriptor(unsigned const i, addr_t phys_addr) {
|
||||
if (i > _max_index())
|
||||
return;
|
||||
|
||||
/* set physical buffer address */
|
||||
_descriptors[i].addr = phys_addr;
|
||||
|
||||
/* set used by SW, also we do not use frame scattering */
|
||||
_descriptors[i].status = Status::Used::bits(1) |
|
||||
Status::Last_buffer::bits(1);
|
||||
|
||||
/* last buffer must be marked by Wrap bit */
|
||||
if (i == _max_index())
|
||||
_descriptors[i].status |= Status::Wrap::bits(1);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
class Package_send_timeout : public Genode::Exception {};
|
||||
|
||||
Tx_buffer_descriptor(Genode::Env &env,
|
||||
Tx_buffer_sink &sink,
|
||||
Timer::Connection &timer)
|
||||
: Buffer_descriptor(env, BUFFER_COUNT), _timer(timer),
|
||||
_phys_base(Dataspace_client(sink.dataspace()).phys_addr())
|
||||
{
|
||||
for (size_t i=0; i <= _max_index(); i++) {
|
||||
/* configure all descriptors with address 0, which we
|
||||
* interpret as invalid */
|
||||
_reset_descriptor(i, 0x0);
|
||||
}
|
||||
}
|
||||
|
||||
void reset(Tx_buffer_sink &sink)
|
||||
{
|
||||
/* ack all packets that are still queued */
|
||||
submit_acks(sink, true);
|
||||
|
||||
/* reset head and tail */
|
||||
_reset_head();
|
||||
_reset_tail();
|
||||
}
|
||||
|
||||
void submit_acks(Tx_buffer_sink &sink, bool force=false)
|
||||
{
|
||||
/* the tail marks the descriptor for which we wait to
|
||||
* be handed over to software */
|
||||
for (size_t i=0; i < _queued(); i++) {
|
||||
/* stop if still in use by hardware */
|
||||
if (!Status::Used::get(_tail().status) && !force)
|
||||
break;
|
||||
|
||||
/* if descriptor has been configured properly */
|
||||
if (_tail().addr != 0) {
|
||||
/* build packet descriptor from buffer descriptor
|
||||
* and acknowledge packet */
|
||||
const size_t length = Status::Length::get(_tail().status);
|
||||
Nic::Packet_descriptor p((addr_t)_tail().addr - _phys_base, length);
|
||||
if (sink.packet_valid(p))
|
||||
sink.acknowledge_packet(p);
|
||||
else
|
||||
warning("Invalid packet descriptor");
|
||||
|
||||
/* erase address so that we don't send an ack again */
|
||||
_tail().addr = 0;
|
||||
|
||||
/* evaluate Tx status */
|
||||
if (Status::Retry_limit::get(_tail().status))
|
||||
warning("Retry limit exceeded");
|
||||
|
||||
if (Status::Corrupt::get(_tail().status))
|
||||
warning("Transmit frame corruption");
|
||||
|
||||
if (Status::Late_collision::get(_tail().status))
|
||||
warning("Late collision error");
|
||||
|
||||
if (Status::Crc_present::get(_tail().status))
|
||||
warning("CRC already present - this impedes checksum offloading");
|
||||
}
|
||||
|
||||
_advance_tail();
|
||||
}
|
||||
}
|
||||
|
||||
void add_to_queue(Nic::Packet_descriptor p)
|
||||
{
|
||||
/* the head marks the descriptor that we use next for
|
||||
* handing over the packet to hardware */
|
||||
if (p.size() > BUFFER_SIZE) {
|
||||
warning("Ethernet package to big. Not sent!");
|
||||
return;
|
||||
}
|
||||
|
||||
addr_t const packet_phys = _phys_base + p.offset();
|
||||
if (packet_phys & 0x1f) {
|
||||
warning("Packet is not aligned properly.");
|
||||
}
|
||||
|
||||
/* wait until the used bit is set (timeout after 10ms) */
|
||||
uint32_t timeout = 10000;
|
||||
while ( !Status::Used::get(_head().status) ) {
|
||||
if (timeout == 0) {
|
||||
throw Package_send_timeout();
|
||||
}
|
||||
timeout -= 1000;
|
||||
|
||||
/* TODO buffer is full, instead of sleeping we should
|
||||
* therefore wait for tx_complete interrupt */
|
||||
_timer.usleep(1000);
|
||||
}
|
||||
|
||||
_reset_descriptor(_head_index(), packet_phys);
|
||||
_head().status |= Status::Length::bits(p.size());
|
||||
|
||||
/* unset the used bit */
|
||||
_head().status &= Status::Used::clear_mask();
|
||||
|
||||
_advance_head();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__DRIVERS__NIC__GEM__TX_BUFFER_DESCRIPTOR_H_ */
|
5
tool/builddir/build.conf/repos_arm_v7
Normal file
5
tool/builddir/build.conf/repos_arm_v7
Normal file
@ -0,0 +1,5 @@
|
||||
#
|
||||
# Board-support for Xilinx Zynq-7000 SoC
|
||||
#
|
||||
#REPOSITORIES += $(GENODE_DIR)/repos/zynq
|
||||
|
@ -12,7 +12,6 @@ QEMU_RUN_OPT := --include power_on/qemu --include log/qemu
|
||||
# local variable for run-tool arguments that depend on the used board
|
||||
BOARD_RUN_OPT(pbxa9) = $(QEMU_RUN_OPT)
|
||||
BOARD_RUN_OPT(virt_qemu) = $(QEMU_RUN_OPT)
|
||||
BOARD_RUN_OPT(zynq_qemu) = $(QEMU_RUN_OPT)
|
||||
|
||||
##
|
||||
## Qemu arguments, effective when using the run tool's 'power_on/qemu' back end
|
||||
|
@ -87,7 +87,7 @@ $(BUILD_DIR)/etc:
|
||||
|
||||
BUILD_CONF_X86 := run_x86 run_boot_dir repos repos_x86
|
||||
BUILD_CONF_ARM_V6 := run_arm_v6 run_boot_dir repos
|
||||
BUILD_CONF_ARM_V7 := run_arm_v7 run_boot_dir repos
|
||||
BUILD_CONF_ARM_V7 := run_arm_v7 run_boot_dir repos repos_arm_v7
|
||||
BUILD_CONF(arm_v6) := $(BUILD_CONF_ARM_V6)
|
||||
BUILD_CONF(arm_v7a) := $(BUILD_CONF_ARM_V7)
|
||||
BUILD_CONF(arm_v8a) := run_arm_v8 run_boot_dir repos
|
||||
|
Loading…
x
Reference in New Issue
Block a user