/* * \brief Genode C API framebuffer functions of the L4Linux support library * \author Stefan Kalkowski * \date 2009-06-08 */ /* * Copyright (C) 2009-2013 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. */ /* Genode includes */ #include #include #include #include #include #include #include #include #include #include #include namespace Fiasco { #include #include #include #include } #define TX_BENCH 0 #define RX_BENCH 0 /** * Debugging/Tracing */ #if TX_BENCH | RX_BENCH struct Counter : public Genode::Thread<8192> { int cnt; Genode::size_t size; void entry() { Timer::Connection _timer; int interval = 5; while(1) { _timer.msleep(interval * 1000); PDBG("LX Packets %d/s bytes/s: %d", cnt / interval, size / interval); cnt = 0; size = 0; } } void inc(Genode::size_t s) { cnt++; size += s; } Counter() : Thread("net-counter"), cnt(0), size(0) { start(); } }; #else struct Counter { inline void inc(Genode::size_t s) { } }; #endif static Nic::Connection *nic() { enum { PACKET_SIZE = Nic::Packet_allocator::DEFAULT_PACKET_SIZE, BUF_SIZE = Nic::Session::QUEUE_SIZE * PACKET_SIZE, }; static Nic::Connection *n = 0; static bool initialized = false; if (initialized) return n; try { Linux::Irq_guard guard; static Nic::Packet_allocator tx_block_alloc(Genode::env()->heap()); static Nic::Connection nic(&tx_block_alloc, BUF_SIZE, BUF_SIZE); n = &nic; } catch(...) { } initialized = true; return n; } namespace { class Signal_thread : public Genode::Thread<8192> { private: Fiasco::l4_cap_idx_t _cap; Genode::Lock *_sync; protected: void entry() { using namespace Fiasco; using namespace Genode; Signal_receiver receiver; Signal_context rx; Signal_context_capability cap(receiver.manage(&rx)); nic()->rx_channel()->sigh_ready_to_ack(cap); nic()->rx_channel()->sigh_packet_avail(cap); _sync->unlock(); while (true) { receiver.wait_for_signal(); if (l4_error(l4_irq_trigger(_cap)) != -1) PWRN("IRQ net trigger failed\n"); } } public: Signal_thread(Fiasco::l4_cap_idx_t cap, Genode::Lock *sync) : Genode::Thread<8192>("net-signal-thread"), _cap(cap), _sync(sync) { start(); } }; } using namespace Fiasco; extern "C" { static FASTCALL void (*receive_packet)(void*, void*, unsigned long) = 0; static void *net_device = 0; void genode_net_start(void *dev, FASTCALL void (*func)(void*, void*, unsigned long)) { receive_packet = func; net_device = dev; } l4_cap_idx_t genode_net_irq_cap() { Linux::Irq_guard guard; static Genode::Native_capability cap = L4lx::vcpu_connection()->alloc_irq(); static Genode::Lock lock(Genode::Lock::LOCKED); static Signal_thread th(cap.dst(), &lock); lock.lock(); return cap.dst(); } void genode_net_stop() { net_device = 0; receive_packet = 0; } void genode_net_mac(void* mac, unsigned long size) { Linux::Irq_guard guard; using namespace Genode; Nic::Mac_address m = nic()->mac_address(); memcpy(mac, &m.addr, min(sizeof(m.addr), (size_t)size)); } int genode_net_tx(void* addr, unsigned long len) { Linux::Irq_guard guard; static Counter counter; try { Nic::Packet_descriptor packet = nic()->tx()->alloc_packet(len); void* content = nic()->tx()->packet_content(packet); Genode::memcpy((char *)content, addr, len); nic()->tx()->submit_packet(packet); counter.inc(len); return 0; /* 'Packet_alloc_failed' */ } catch(...) { return 1; } } int genode_net_tx_ack_avail() { return nic()->tx()->ack_avail(); } void genode_net_tx_ack() { Linux::Irq_guard guard; Nic::Packet_descriptor packet = nic()->tx()->get_acked_packet(); nic()->tx()->release_packet(packet); } void genode_net_rx_receive() { Linux::Irq_guard guard; static Counter counter; if (nic()) { while(nic()->rx()->packet_avail()) { Nic::Packet_descriptor p = nic()->rx()->get_packet(); if (receive_packet && net_device) receive_packet(net_device, nic()->rx()->packet_content(p), p.size()); counter.inc(p.size()); nic()->rx()->acknowledge_packet(p); } } } int genode_net_ready() { return nic() ? 1 : 0; } void *genode_net_memcpy(void *dst, void const *src, unsigned long size) { return Genode::memcpy(dst, src, size); } }