From 2b1a70d66df76b6577f497d87d87cf291113760f Mon Sep 17 00:00:00 2001 From: Johannes Schlatow Date: Fri, 4 Sep 2015 11:31:59 +0200 Subject: [PATCH] nic: replace Nic driver interface in the zynq network driver Ref #1667 --- repos/os/src/drivers/nic/gem/cadence_gem.h | 96 ++++++++++++++-------- repos/os/src/drivers/nic/gem/main.cc | 94 +++++++++++++-------- repos/os/src/drivers/nic/gem/marvell_phy.h | 1 - repos/os/src/drivers/nic/gem/target.mk | 2 +- 4 files changed, 125 insertions(+), 68 deletions(-) diff --git a/repos/os/src/drivers/nic/gem/cadence_gem.h b/repos/os/src/drivers/nic/gem/cadence_gem.h index 8cf344a82a..127a73d818 100644 --- a/repos/os/src/drivers/nic/gem/cadence_gem.h +++ b/repos/os/src/drivers/nic/gem/cadence_gem.h @@ -1,5 +1,6 @@ /* * \brief Base EMAC driver for the Xilinx EMAC PS used on Zynq devices + * \author Johannes Schlatow * \author Timo Wischer * \date 2015-03-10 */ @@ -17,9 +18,11 @@ /* Genode includes */ #include #include -#include #include +#include +#include +/* local includes */ #include "system_control.h" #include "tx_buffer_descriptor.h" #include "rx_buffer_descriptor.h" @@ -31,7 +34,12 @@ namespace Genode /** * Base driver Xilinx EMAC PS module */ - class Cadence_gem : private Genode::Attached_mmio, public Nic::Driver, public Phyio + class Cadence_gem + : + private Genode::Attached_mmio, + public Nic::Session_component, + public Phyio, + public Genode::Irq_handler { private: /** @@ -261,9 +269,6 @@ namespace Genode Tx_buffer_descriptor _tx_buffer; Rx_buffer_descriptor _rx_buffer; - Nic::Rx_buffer_alloc& _rx_buffer_alloc; - Nic::Driver_notification &_notify; - enum { IRQ_STACK_SIZE = 4096 }; const Genode::Irq_activation _irq_activation; @@ -285,17 +290,6 @@ namespace Genode ); - /* 2. set mac address */ - Nic::Mac_address mac; - mac.addr[5] = 0x12; - mac.addr[4] = 0x34; - mac.addr[3] = 0x56; - mac.addr[2] = 0x78; - mac.addr[1] = 0x9A; - mac.addr[0] = 0xBC; - mac_address(mac); - - write( _rx_buffer.phys_addr() ); write( _tx_buffer.phys_addr() ); @@ -411,11 +405,15 @@ namespace Genode * * \param base MMIO base address */ - Cadence_gem(addr_t const base, size_t const size, const int irq, Nic::Rx_buffer_alloc& alloc, - Nic::Driver_notification ¬ify) : + Cadence_gem(Genode::size_t const tx_buf_size, + Genode::size_t const rx_buf_size, + Genode::Allocator &rx_block_md_alloc, + Genode::Ram_session &ram_session, + Server::Entrypoint &ep, + addr_t const base, size_t const size, const int irq) + : Genode::Attached_mmio(base, size), - _rx_buffer_alloc(alloc), - _notify(notify), + Session_component(tx_buf_size, rx_buf_size, rx_block_md_alloc, ram_session, ep), _irq_activation(irq, *this, IRQ_STACK_SIZE), _phy(*this) { @@ -444,7 +442,7 @@ namespace Genode } - void mac_address(const Nic::Mac_address mac) + void mac_address(const Nic::Mac_address &mac) { const uint32_t* const low_addr_pointer = reinterpret_cast(&mac.addr[0]); const uint16_t* const high_addr_pointer = reinterpret_cast(&mac.addr[4]); @@ -453,9 +451,34 @@ namespace Genode write(*high_addr_pointer); } - /*************************** - ** Nic::Driver interface ** - ***************************/ + + bool _send() + { + if (!_tx.sink()->ready_to_ack()) + return false; + + if (!_tx.sink()->packet_avail()) + return false; + + Genode::Packet_descriptor packet = _tx.sink()->get_packet(); + if (!packet.valid()) { + PWRN("Invalid tx packet"); + return true; + } + + char *src = (char *)_tx.sink()->packet_content(packet); + + _tx_buffer.add_to_queue(src, packet.size()); + write(Control::start_tx()); + + _tx.sink()->acknowledge_packet(packet); + return true; + } + + + /************************************** + ** Nic::Session_component interface ** + **************************************/ virtual Nic::Mac_address mac_address() { @@ -475,10 +498,12 @@ namespace Genode return true; } - virtual void tx(char const *packet, Genode::size_t size) + void _handle_packet_stream() override { - _tx_buffer.add_to_queue(packet, size); - write(Control::start_tx()); + while (_rx.source()->ack_avail()) + _rx.source()->release_packet(_rx.source()->get_acked_packet()); + + while (_send()) ; } /****************************** @@ -492,19 +517,28 @@ namespace Genode const Interrupt_status::access_t status = read(); const Rx_status::access_t rxStatus = read(); + /* FIXME strangely, this handler is also called without any status bit set in Interrupt_status */ if ( Interrupt_status::Rx_complete::get(status) ) { while (_rx_buffer.package_available()) { // TODO use this buffer directly as the destination for the DMA controller // to minimize the overrun errors const size_t buffer_size = _rx_buffer.package_length(); - char* const buffer = static_cast( _rx_buffer_alloc.alloc(buffer_size) ); + + /* allocate rx packet buffer */ + Nic::Packet_descriptor p; + try { + p = _rx.source()->alloc_packet(buffer_size); + } catch (Session::Rx::Source::Packet_alloc_failed) { return; } + + char *dst = (char *)_rx.source()->packet_content(p); + /* * copy data from rx buffer to new allocated buffer. * Has to be copied, * because the extern allocater possibly is using the cache. */ - if ( _rx_buffer.get_package(buffer, buffer_size) != buffer_size ) { + if ( _rx_buffer.get_package(dst, buffer_size) != buffer_size ) { PWRN("Package not fully copiied. Package ignored."); return; } @@ -514,7 +548,7 @@ namespace Genode write(1); /* comit buffer to system services */ - _rx_buffer_alloc.submit(); + _rx.source()->submit_packet(p); } /* check, if there was lost some packages */ @@ -527,8 +561,6 @@ namespace Genode /* reset reveive complete interrupt */ write(Rx_status::Frame_reveived::bits(1)); write(Interrupt_status::Rx_complete::bits(1)); - } else { - PWRN("IRQ %d with unkown reasone recevied (status: %08x).", irq_number, status); } } }; diff --git a/repos/os/src/drivers/nic/gem/main.cc b/repos/os/src/drivers/nic/gem/main.cc index ff641f2bf0..f099f8489e 100644 --- a/repos/os/src/drivers/nic/gem/main.cc +++ b/repos/os/src/drivers/nic/gem/main.cc @@ -14,47 +14,73 @@ /* Genode includes */ #include #include -#include #include +#include +#include +#include + +#include #include "cadence_gem.h" - -int main(int, char **) +class Gem_session_component +: + public Cadence_gem { - using namespace Genode; + 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::Ram_session &ram_session, + Server::Entrypoint &ep) + : + Cadence_gem(tx_buf_size, rx_buf_size, rx_block_md_alloc, ram_session, ep, + Board_base::EMAC_0_MMIO_BASE, + Board_base::EMAC_0_MMIO_SIZE, + Board_base::EMAC_0_IRQ) + { + Nic::Mac_address mac_addr; - printf("--- Xilinx Ethernet MAC PS NIC driver started ---\n"); + /* try using configured MAC address */ + try { + Genode::Xml_node nic_config = Genode::config()->xml_node().sub_node("nic"); + nic_config.attribute("mac").value(&mac_addr); + PINF("Using configured MAC address \"%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] ); + } catch (...) { + /* 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; + } - /** - * Factory used by 'Nic::Root' at session creation/destruction time - */ - struct Emacps_driver_factory : Nic::Driver_factory + /* set mac address */ + mac_address(mac_addr); + } +}; + +namespace Server { struct Main; } + +struct Server::Main +{ + Entrypoint &ep; + Nic::Root nic_root{ ep, *Genode::env()->heap() }; + + Main(Entrypoint &ep) : ep(ep) { - Nic::Driver *create(Nic::Rx_buffer_alloc &alloc, - Nic::Driver_notification ¬ify) - { - return new (env()->heap()) - Cadence_gem(Board_base::EMAC_0_MMIO_BASE, - Board_base::EMAC_0_MMIO_SIZE, - Board_base::EMAC_0_IRQ, - alloc, notify); - } + Genode::env()->parent()->announce(ep.manage(nic_root)); + } +}; - void destroy(Nic::Driver *driver) - { - Genode::destroy(env()->heap(), static_cast(driver)); - } - } 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)); - - Genode::sleep_forever(); - return 0; -} +char const * Server::name() { return "nic_ep"; } +size_t Server::stack_size() { return 2*1024*sizeof(long); } +void Server::construct(Entrypoint &ep) { static Main main(ep); } diff --git a/repos/os/src/drivers/nic/gem/marvell_phy.h b/repos/os/src/drivers/nic/gem/marvell_phy.h index 60ee49e35e..c1bb13b7ab 100644 --- a/repos/os/src/drivers/nic/gem/marvell_phy.h +++ b/repos/os/src/drivers/nic/gem/marvell_phy.h @@ -18,7 +18,6 @@ /* Genode includes */ #include #include -#include #include #include "phyio.h" diff --git a/repos/os/src/drivers/nic/gem/target.mk b/repos/os/src/drivers/nic/gem/target.mk index 0c277f4f53..c516e09f8a 100644 --- a/repos/os/src/drivers/nic/gem/target.mk +++ b/repos/os/src/drivers/nic/gem/target.mk @@ -1,5 +1,5 @@ REQUIRES = cadence_gem TARGET = nic_drv SRC_CC = main.cc -LIBS = base +LIBS = base server config INC_DIR += $(PRG_DIR)