block: use new server framework in block drivers

As a side effect, the entrypoints in the USB driver are merged into one thread.

Fixes #1027
This commit is contained in:
Stefan Kalkowski 2014-01-13 13:44:33 +01:00 committed by Christian Helmuth
parent 2e99c19601
commit 6a076ff621
34 changed files with 415 additions and 461 deletions

View File

@ -4,9 +4,12 @@
* \date 2013-02-20
*/
int main()
{
extern void start_usb_driver();
start_usb_driver();
return 0;
#include <os/server.h>
extern void start_usb_driver(Server::Entrypoint &e);
namespace Server {
char const *name() { return "usb_drv_ep"; }
size_t stack_size() { return 4*1024*sizeof(long); }
void construct(Entrypoint &e) { start_usb_driver(e); }
}

View File

@ -1,3 +1,3 @@
TARGET = usb_drv
SRC_CC = main.cc
LIBS = usb
LIBS = usb server

View File

@ -246,12 +246,11 @@ namespace Nic {
*/
Session_component(Dataspace_capability tx_ds,
Dataspace_capability rx_ds,
Rpc_entrypoint &ep,
Signal_receiver *sig_rec,
Server::Entrypoint &ep,
::Device *device)
:
Nic::Packet_allocator(Genode::env()->heap()),
Packet_session_component(tx_ds, rx_ds, this, ep, sig_rec),
Packet_session_component(tx_ds, rx_ds, this, ep),
_device(static_cast<Device *>(device)),
_tx_sink(Session_rpc_object::_tx.sink()),
_tx_alloc(true)
@ -296,10 +295,9 @@ namespace Nic {
{
public:
Root(Rpc_entrypoint *session_ep, Allocator *md_alloc,
Signal_receiver *sig_rec, Device *device)
:
Packet_root(session_ep, md_alloc, sig_rec, device) { }
Root(Server::Entrypoint &ep, Allocator *md_alloc,
Device *device)
: Packet_root(ep, md_alloc, device) { }
};
}

View File

@ -43,6 +43,7 @@ class Routine : public Genode::List<Routine>::Element
char *_stack; /* stack pointer */
static Routine *_current; /* currently scheduled object */
static Routine *_dead; /* object to remove */
static Routine *_main; /* main routine */
static bool _all; /* true when all objects must be scheduled */
@ -129,12 +130,16 @@ class Routine : public Genode::List<Routine>::Element
*
* If all is true, each object will be scheduled once.
*/
static void schedule(bool all = false) __attribute__((noinline))
static void schedule(bool all = false, bool main = false)
__attribute__((noinline))
{
if (!_list()->first())
if (!_list()->first() && !_main)
return;
Routine *next = _next(all);
if (_current == _main)
all = true;
Routine *next = main ? _main : _next(all);
if (next == _current) {
_check_dead();
@ -184,6 +189,22 @@ class Routine : public Genode::List<Routine>::Element
schedule();
}
static void main()
{
if (!_current)
return;
_list()->remove(_current);
_main = _current;
if (_main && _setjmp(_main->_env))
return;
schedule();
}
static void schedule_main() { schedule(false, true); }
/**
* True when 'schedule_all' has been called and is still in progress
*/

View File

@ -17,19 +17,17 @@
#include <base/env.h>
#include <base/printf.h>
#include <base/signal.h>
#include <os/server.h>
#include "routine.h"
/**
* This singelton currently received all signals
* This singleton currently received all signals
*/
class Service_handler
{
private:
Genode::Signal_receiver *_receiver;
Service_handler() { }
public:
@ -40,8 +38,6 @@ class Service_handler
return &_s;
}
void receiver(Genode::Signal_receiver *recv) { _receiver = recv; }
/**
* Dispatch for wait for signal
*/
@ -52,68 +48,54 @@ class Service_handler
return;
}
check_signal();
}
void check_signal(bool block = true)
{
while (_receiver->pending() || block) {
Genode::Signal s = _receiver->wait_for_signal();
/* handle signal IRQ, timer, or event signals */
static_cast<Genode::Signal_dispatcher_base *>(s.context())->dispatch(s.num());
block = false;
}
Routine::schedule_main();
}
};
/**
* Helper that holds sender and receiver
* Helper that holds sender and entrypoint
*/
class Signal_helper
{
private:
Genode::Signal_receiver *_receiver;
Genode::Signal_transmitter *_sender;
Server::Entrypoint &_ep;
Genode::Signal_transmitter _sender;
public:
Signal_helper(Genode::Signal_receiver *recv)
: _receiver(recv),
_sender(new (Genode::env()->heap()) Genode::Signal_transmitter()) { }
Signal_helper(Server::Entrypoint &ep) : _ep(ep) { }
Genode::Signal_receiver *receiver() const { return _receiver; }
Genode::Signal_transmitter *sender() const { return _sender; }
Server::Entrypoint &ep() { return _ep; }
Genode::Signal_transmitter &sender() { return _sender; }
};
namespace Timer
{
void init(Genode::Signal_receiver *recv);
void init(Server::Entrypoint &ep);
}
namespace Irq
{
void init(Genode::Signal_receiver *recv);
void init(Server::Entrypoint &ep);
void check_irq();
}
namespace Event
{
void init(Genode::Signal_receiver *recv);
void init(Server::Entrypoint &ep);
}
namespace Storage
{
void init(Genode::Signal_receiver *recv);
void init(Server::Entrypoint &ep);
}
namespace Nic
{
void init(Genode::Signal_receiver *recv);
void init(Server::Entrypoint &ep);
}
#endif /* _SIGNAL_H_ */

View File

@ -27,7 +27,7 @@ class Packet_session_component : public RPC
{
private:
Genode::Signal_dispatcher<Packet_session_component> _process_packet_dispatcher;
Genode::Signal_rpc_member<Packet_session_component> _dispatcher;
protected:
@ -36,37 +36,31 @@ class Packet_session_component : public RPC
public:
Packet_session_component(Genode::Dataspace_capability tx_ds,
Genode::Rpc_entrypoint &ep,
Genode::Signal_receiver *sig_rec)
:
RPC(tx_ds, ep),
_process_packet_dispatcher(*sig_rec, *this,
&Packet_session_component::_process_packets)
{
Server::Entrypoint &ep)
: RPC(tx_ds, ep.rpc_ep()),
_dispatcher(ep, *this, &Packet_session_component::_process_packets)
{
/*
* Register '_process_packets' dispatch function as signal
* handler for packet-avail and ready-to-ack signals.
*/
RPC::_tx.sigh_packet_avail(_process_packet_dispatcher);
RPC::_tx.sigh_ready_to_ack(_process_packet_dispatcher);
RPC::_tx.sigh_packet_avail(_dispatcher);
RPC::_tx.sigh_ready_to_ack(_dispatcher);
}
Packet_session_component(Genode::Dataspace_capability tx_ds,
Genode::Dataspace_capability rx_ds,
Genode::Range_allocator *rx_buffer_alloc,
Genode::Rpc_entrypoint &ep,
Genode::Signal_receiver *sig_rec)
:
RPC(tx_ds, rx_ds, rx_buffer_alloc, ep),
_process_packet_dispatcher(*sig_rec, *this,
&Packet_session_component::_process_packets)
{
Server::Entrypoint &ep)
: RPC(tx_ds, rx_ds, rx_buffer_alloc, ep.rpc_ep()),
_dispatcher(ep, *this, &Packet_session_component::_process_packets)
{
/*
* Register '_process_packets' dispatch function as signal
* handler for packet-avail and ready-to-ack signals.
*/
RPC::_tx.sigh_packet_avail(_process_packet_dispatcher);
RPC::_tx.sigh_ready_to_ack(_process_packet_dispatcher);
RPC::_tx.sigh_packet_avail(_dispatcher);
RPC::_tx.sigh_ready_to_ack(_dispatcher);
}
};
@ -85,9 +79,8 @@ class Packet_session_component : public RPC
{
private:
Genode::Rpc_entrypoint &_ep;
Genode::Signal_receiver *_sig_rec;
Device *_device;
Server::Entrypoint &_ep;
Device *_device;
protected:
@ -125,17 +118,15 @@ class Packet_session_component : public RPC
return new (ROOT_COMPONENT::md_alloc())
SESSION_COMPONENT(Backend_memory::alloc(tx_buf_size, CACHED),
Backend_memory::alloc(rx_buf_size, CACHED),
_ep, _sig_rec, _device);
_ep, _device);
}
public:
Packet_root(Genode::Rpc_entrypoint *session_ep, Genode::Allocator *md_alloc,
Genode::Signal_receiver *sig_rec, Device *device)
:
ROOT_COMPONENT(session_ep, md_alloc),
_ep(*session_ep), _sig_rec(sig_rec), _device(device)
{ }
Packet_root(Server::Entrypoint &ep, Genode::Allocator *md_alloc,
Device *device)
: ROOT_COMPONENT(&ep.rpc_ep(), md_alloc),
_ep(ep), _device(device) { }
};
#endif /* _SIGNAL__DISPATCHER_H_ */

View File

@ -14,11 +14,9 @@
/* Genode */
#include <base/rpc_server.h>
#include <base/printf.h>
#include <base/sleep.h>
#include <cap_session/connection.h>
#include <os/server.h>
#include <nic_session/nic_session.h>
/* Local */
@ -45,6 +43,7 @@ extern "C" void start_input_service(void *ep);
Routine *Routine::_current = 0;
Routine *Routine::_dead = 0;
Routine *Routine::_main = 0;
bool Routine::_all = false;
void breakpoint() { PDBG("BREAK"); }
@ -79,34 +78,22 @@ static void init(Services *services)
}
void start_usb_driver()
void start_usb_driver(Server::Entrypoint &ep)
{
/*
* Initialize server entry point
*/
enum { STACK_SIZE = 4096 };
static Cap_connection cap;
static Rpc_entrypoint ep_hid(&cap, STACK_SIZE, "usb_hid_ep");
static Signal_receiver recv;
Services services;
if (services.hid)
start_input_service(&ep_hid);
start_input_service(&ep.rpc_ep());
Timer::init(&recv);
Irq::init(&recv);
Event::init(&recv);
Service_handler::s()->receiver(&recv);
Storage::init(&recv);
Nic::init(&recv);
Timer::init(ep);
Irq::init(ep);
Event::init(ep);
Storage::init(ep);
Nic::init(ep);
Routine::add(0, 0, "Main", true);
Routine::current_use_first();
init(&services);
Routine::remove();
/* will never be reached */
sleep_forever();
Routine::main();
}

View File

@ -283,8 +283,8 @@ class Nic_device : public Nic::Device
static Nic_device *_nic = 0;
void Nic::init(Genode::Signal_receiver *recv) {
_signal = new (Genode::env()->heap()) Signal_helper(recv); }
void Nic::init(Server::Entrypoint &ep) {
_signal = new (Genode::env()->heap()) Signal_helper(ep); }
/***********************
@ -301,9 +301,7 @@ int register_netdev(struct net_device *ndev)
/* XXX: move to 'main' */
if (!announce) {
static Cap_connection cap_nic;
static Rpc_entrypoint ep_nic(&cap_nic, 4096, "usb_nic_ep");
static Nic::Root root(&ep_nic, env()->heap(), _signal->receiver(), nic);
static Nic::Root root(_signal->ep(), env()->heap(), nic);
announce = true;
@ -321,7 +319,7 @@ int register_netdev(struct net_device *ndev)
ndev->netdev_ops->ndo_change_mtu(ndev, 4000);
*/
_nic = nic;
env()->parent()->announce(ep_nic.manage(&root));
env()->parent()->announce(_signal->ep().rpc_ep().manage(&root));
}
return err;

View File

@ -23,14 +23,14 @@ class Event_context
{
private:
Genode::Signal_dispatcher<Event_context> _dispatcher;
Genode::Signal_rpc_member<Event_context> _dispatcher;
void _handle(unsigned) {
Routine::schedule_all(); }
Event_context()
: _dispatcher(*_signal->receiver(), *this, &Event_context::_handle) {
_signal->sender()->context(_dispatcher); }
: _dispatcher(_signal->ep(), *this, &Event_context::_handle) {
_signal->sender().context(_dispatcher); }
public:
@ -41,14 +41,14 @@ class Event_context
}
void submit() {
_signal->sender()->submit(); }
_signal->sender().submit(); }
char const *debug() { return "Event_context"; }
};
void Event::init(Genode::Signal_receiver *recv) {
_signal = new (Genode::env()->heap()) Signal_helper(recv); }
void Event::init(Server::Entrypoint &ep) {
_signal = new (Genode::env()->heap()) Signal_helper(ep); }
/**

View File

@ -48,7 +48,7 @@ class Irq_context : public Genode::List<Irq_context>::Element
unsigned int _irq; /* IRQ number */
Genode::List<Irq_handler> _handler_list; /* List of registered handlers */
Genode::Signal_dispatcher<Irq_context> _dispatcher;
Genode::Signal_rpc_member<Irq_context> _dispatcher;
static Genode::List<Irq_context> *_list()
{
@ -82,8 +82,8 @@ class Irq_context : public Genode::List<Irq_context>::Element
Irq_context *ctx = static_cast<Irq_context *>(irq);
/* set context & submit signal */
_signal->sender()->context(ctx->_dispatcher);
_signal->sender()->submit();
_signal->sender().context(ctx->_dispatcher);
_signal->sender().submit();
/* wait for interrupt to get acked at device side */
_irq_sync.lock();
@ -122,7 +122,7 @@ class Irq_context : public Genode::List<Irq_context>::Element
/* report IRQ to all clients */
for (Irq_handler *h = _handler_list.first(); h; h = h->next()) {
if (_handle_one(h))
if ((handled = _handle_one(h)))
break;
dde_kit_log(DEBUG_IRQ, "IRQ: %u ret: %u h: %p dev: %p", _irq, handled, h->handler, h->dev);
@ -143,7 +143,7 @@ class Irq_context : public Genode::List<Irq_context>::Element
Irq_context(unsigned int irq)
: _irq(irq),
_dispatcher(*_signal->receiver(), *this, &Irq_context::_handle)
_dispatcher(_signal->ep(), *this, &Irq_context::_handle)
{
/* register at DDE (shared) */
int ret = dde_kit_interrupt_attach(_irq, 0, 0, _dde_handler, this);
@ -184,8 +184,8 @@ class Irq_context : public Genode::List<Irq_context>::Element
};
void Irq::init(Genode::Signal_receiver *recv) {
_signal = new (Genode::env()->heap()) Signal_helper(recv); }
void Irq::init(Server::Entrypoint &ep) {
_signal = new (Genode::env()->heap()) Signal_helper(ep); }
void Irq::check_irq()

View File

@ -33,7 +33,7 @@ class Timer_context
timer_list *_timer; /* Linux timer */
dde_kit_timer *_dde_timer; /* DDE kit timer */
Genode::Signal_dispatcher<Timer_context> _dispatcher;
Genode::Signal_rpc_member<Timer_context> _dispatcher;
/* call timer function */
void _handle(unsigned) { _timer->function(_timer->data); }
@ -42,7 +42,7 @@ class Timer_context
Timer_context(timer_list *timer)
: _timer(timer), _dde_timer(0),
_dispatcher(*_signal->receiver(), *this, &Timer_context::_handle) {}
_dispatcher(_signal->ep(), *this, &Timer_context::_handle) {}
/* schedule next timeout */
void schedule(unsigned long expires)
@ -93,13 +93,13 @@ static void handler(void *timer)
Timer_context *t = static_cast<Timer_context *>(timer);
/* set context and submit */
_signal->sender()->context(t->cap());
_signal->sender()->submit();
_signal->sender().context(t->cap());
_signal->sender().submit();
}
void Timer::init(Genode::Signal_receiver *recv) {
_signal = new (Genode::env()->heap()) Signal_helper(recv); }
void Timer::init(Server::Entrypoint &ep) {
_signal = new (Genode::env()->heap()) Signal_helper(ep); }
/*******************

View File

@ -180,8 +180,8 @@ class Storage_device : public Genode::List<Storage_device>::Element,
};
void Storage::init(Genode::Signal_receiver *recv) {
_signal = new (Genode::env()->heap()) Signal_helper(recv); }
void Storage::init(Server::Entrypoint &ep) {
_signal = new (Genode::env()->heap()) Signal_helper(ep); }
struct Factory : Block::Driver_factory
@ -206,11 +206,8 @@ void scsi_add_device(struct scsi_device *sdev)
* XXX move to 'main'
*/
if (!announce) {
enum { STACK_SIZE = 1024 * sizeof(addr_t) };
static Cap_connection cap_stor;
static Rpc_entrypoint ep_stor(&cap_stor, STACK_SIZE, "usb_stor_ep");
static Block::Root root(&ep_stor, env()->heap(), factory, *_signal->receiver());
env()->parent()->announce(ep_stor.manage(&root));
static Block::Root root(_signal->ep(), env()->heap(), factory);
env()->parent()->announce(_signal->ep().rpc_ep().manage(&root));
announce = true;
}
}

View File

@ -27,7 +27,7 @@ void tx_test() {
while (1) {
sk_buff *skb = alloc_skb(1066 + HEAD_ROOM, 0);
if (!skb) {
Service_handler::s()->check_signal(true);
Service_handler::s()->check_signal();
continue;
}
skb->len = 1066;

View File

@ -89,22 +89,24 @@ class Factory : public Block::Driver_factory
};
int main()
struct Main
{
enum { STACK_SIZE = 4*1024 };
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "http_block_ep");
Server::Entrypoint &ep;
struct Factory factory;
Block::Root root;
static Signal_receiver receiver;
static Factory driver_factory;
static Block::Root block_root(&ep, env()->heap(), driver_factory, receiver);
Main(Server::Entrypoint &ep)
: ep(ep), root(ep, Genode::env()->heap(), factory) {
Genode::env()->parent()->announce(ep.manage(root)); }
};
env()->parent()->announce(ep.manage(&block_root));
while (true) {
Signal s = receiver.wait_for_signal();
static_cast<Signal_dispatcher_base *>(s.context())->dispatch(s.num());
}
/************
** Server **
************/
return 0;
namespace Server {
char const *name() { return "http_blk_ep"; }
size_t stack_size() { return 2*1024*sizeof(long); }
void construct(Entrypoint &ep) { static Main server(ep); }
}

View File

@ -1,4 +1,4 @@
TARGET = http_blk
SRC_CC = main.cc http.cc
LIBS = libc libc_lwip_nic_dhcp
LIBS = libc libc_lwip_nic_dhcp server

View File

@ -16,6 +16,8 @@
#define _INCLUDE__BLOCK__COMPONENT_H_
#include <root/component.h>
#include <os/signal_rpc_dispatcher.h>
#include <os/server.h>
#include <block_session/rpc_object.h>
#include <block/driver.h>
@ -36,8 +38,8 @@ class Block::Session_component : public Block::Session_rpc_object
Driver &_driver;
Ram_dataspace_capability _rq_ds;
addr_t _rq_phys;
Signal_dispatcher<Session_component> _sink_ack;
Signal_dispatcher<Session_component> _sink_submit;
Signal_rpc_member<Session_component> _sink_ack;
Signal_rpc_member<Session_component> _sink_submit;
bool _req_queue_full;
bool _ack_queue_full;
Packet_descriptor _p_to_handle;
@ -146,20 +148,18 @@ class Block::Session_component : public Block::Session_rpc_object
* \param driver block driver backend
* \param driver_factory factory to create and destroy driver objects
* \param ep entrypoint handling this session component
* \param receiver signal receiver managing signals of the client
*/
Session_component(Ram_dataspace_capability rq_ds,
Driver &driver,
Driver_factory &driver_factory,
Rpc_entrypoint &ep,
Signal_receiver &receiver)
: Session_rpc_object(rq_ds, ep),
Server::Entrypoint &ep)
: Session_rpc_object(rq_ds, ep.rpc_ep()),
_driver_factory(driver_factory),
_driver(driver),
_rq_ds(rq_ds),
_rq_phys(Dataspace_client(_rq_ds).phys_addr()),
_sink_ack(receiver, *this, &Session_component::_ready_to_ack),
_sink_submit(receiver, *this, &Session_component::_packet_avail),
_sink_ack(ep, *this, &Session_component::_ready_to_ack),
_sink_submit(ep, *this, &Session_component::_packet_avail),
_req_queue_full(false),
_p_in_fly(0)
{
@ -224,14 +224,13 @@ class Block::Session_component : public Block::Session_rpc_object
/**
* Root component, handling new session requests
*/
class Block::Root :
public Genode::Root_component<Block::Session_component, Single_client>
class Block::Root : public Genode::Root_component<Block::Session_component,
Single_client>
{
private:
Driver_factory &_driver_factory;
Rpc_entrypoint &_ep;
Signal_receiver &_receiver;
Driver_factory &_driver_factory;
Server::Entrypoint &_ep;
protected:
@ -267,8 +266,7 @@ class Block::Root :
Ram_dataspace_capability ds_cap;
ds_cap = driver->alloc_dma_buffer(tx_buf_size);
return new (md_alloc())
Session_component(ds_cap, *driver, _driver_factory, _ep,
_receiver);
Session_component(ds_cap, *driver, _driver_factory, _ep);
}
public:
@ -276,18 +274,15 @@ class Block::Root :
/**
* Constructor
*
* \param session_ep entrypoint handling this root component
* \param ep entrypoint handling this root component
* \param md_alloc allocator to allocate session components
* \param driver_factory factory to create and destroy driver backend
* \param receiver signal receiver managing signals of the client
*/
Root(Rpc_entrypoint *session_ep, Allocator *md_alloc,
Driver_factory &driver_factory, Signal_receiver &receiver)
:
Root_component(session_ep, md_alloc),
_driver_factory(driver_factory), _ep(*session_ep),
_receiver(receiver)
{ }
Root(Server::Entrypoint &ep, Allocator *md_alloc,
Driver_factory &driver_factory)
: Root_component(&ep.rpc_ep(), md_alloc),
_driver_factory(driver_factory), _ep(ep) { }
};
#endif /* _INCLUDE__BLOCK__COMPONENT_H_ */

View File

@ -53,18 +53,10 @@ struct Genode::Signal_rpc_dispatcher_base : Genode::Signal_dispatcher_base
Proxy_component _proxy;
Capability<Proxy> _proxy_cap;
unsigned _nesting_level;
private:
/**
* To be implemented by the derived class
*/
virtual void dispatch_at_entrypoint(unsigned num) = 0;
protected:
Signal_rpc_dispatcher_base() : _proxy(*this), _nesting_level(0) { }
Signal_rpc_dispatcher_base() : _proxy(*this) { }
Capability<Proxy> proxy_cap() { return _proxy_cap; }
@ -94,26 +86,13 @@ struct Genode::Signal_rpc_dispatcher_base : Genode::Signal_dispatcher_base
/**
* Interface of Signal_dispatcher_base
*/
void dispatch(unsigned num)
{
/*
* Keep track of nesting levels to deal with nested signal
* dispatching. When called from within the RPC entrypoint, any
* attempt to perform a RPC call would lead to a deadlock. In
* this case, we call the 'dispatch' function directly.
*/
_nesting_level++;
void dispatch(unsigned num) {
proxy_cap().call<Proxy::Rpc_handle_signal>(num); }
/* called from the signal-receiving thread */
if (_nesting_level == 1)
proxy_cap().call<Proxy::Rpc_handle_signal>(num);
/* called from the context of the RPC entrypoint */
if (_nesting_level > 1)
dispatch_at_entrypoint(num);
_nesting_level--;
}
/**
* To be implemented by the derived class
*/
virtual void dispatch_at_entrypoint(unsigned num) = 0;
};

View File

@ -17,40 +17,47 @@
*/
/* Genode includes */
#include <cap_session/connection.h>
#include <block/component.h>
#include <os/server.h>
/* local includes */
#include <ahci_driver.h>
using namespace Genode;
int main()
{
printf("--- AHCI driver started ---\n");
struct Ahci_driver_factory : Block::Driver_factory
struct Main
{
Server::Entrypoint &ep;
struct Factory : Block::Driver_factory
{
Block::Driver *create() {
return new(env()->heap()) Ahci_driver(); }
void destroy(Block::Driver *driver) {
Genode::destroy(env()->heap(), static_cast<Ahci_driver *>(driver)); }
} driver_factory;
} factory;
enum { STACK_SIZE = 8128 };
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "block_ep");
Block::Root root;
static Signal_receiver receiver;
static Block::Root block_root(&ep, env()->heap(), driver_factory, receiver);
env()->parent()->announce(ep.manage(&block_root));
Main(Server::Entrypoint &ep)
: ep(ep), root(ep, Genode::env()->heap(), factory)
{
printf("--- AHCI driver started ---\n");
while (true) {
Signal s = receiver.wait_for_signal();
static_cast<Signal_dispatcher_base *>(s.context())->dispatch(s.num());
Genode::env()->parent()->announce(ep.manage(root));
}
};
return 0;
/************
** Server **
************/
namespace Server {
char const *name() { return "ahci_ep"; }
size_t stack_size() { return 2*1024*sizeof(long); }
void construct(Entrypoint &ep) { static Main server(ep); }
}

View File

@ -1,3 +1,3 @@
TARGET = ahci
LIBS += ahci
LIBS += ahci server
SRC_CC += empty.cc

View File

@ -13,9 +13,8 @@
*/
/* Genode includes */
#include <base/thread.h>
#include <cap_session/connection.h>
#include <os/config.h>
#include <os/server.h>
/* local includes */
#include "ata_device.h"
@ -65,22 +64,24 @@ struct Factory : Block::Driver_factory
};
int main()
struct Main
{
enum { STACK_SIZE = 8192 };
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "atapi_ep");
Server::Entrypoint &ep;
struct Factory factory;
Block::Root root;
static Signal_receiver receiver;
static Factory driver_factory;
static Block::Root block_root(&ep, env()->heap(), driver_factory, receiver);
Main(Server::Entrypoint &ep)
: ep(ep), root(ep, Genode::env()->heap(), factory) {
Genode::env()->parent()->announce(ep.manage(root)); }
};
env()->parent()->announce(ep.manage(&block_root));
while (true) {
Signal s = receiver.wait_for_signal();
static_cast<Signal_dispatcher_base *>(s.context())->dispatch(s.num());
}
/************
** Server **
************/
return 0;
namespace Server {
char const *name() { return "atapi_ep"; }
size_t stack_size() { return 2*1024*sizeof(long); }
void construct(Entrypoint &ep) { static Main server(ep); }
}

View File

@ -2,7 +2,7 @@ TARGET = atapi_drv
REQUIRES = x86
SRC_CC = main.cc ata_device.cc atapi_device.cc io.cc ata_bus_master.cc
SRC_C = mindrvr.c
LIBS = base config
LIBS = base config server
INC_DIR += $(PRG_DIR)/contrib $(PRG_DIR)

View File

@ -13,52 +13,48 @@
/* Genode includes */
#include <base/printf.h>
#include <cap_session/connection.h>
#include <regulator_session/connection.h>
#include <os/server.h>
/* local includes */
#include <driver.h>
int main(int argc, char **argv)
struct Main
{
using namespace Genode;
Server::Entrypoint &ep;
printf("--- Arndale eMMC card driver ---\n");
/**
* Factory used by 'Block::Root' at session creation/destruction time
*/
struct Driver_factory : Block::Driver_factory
struct Factory : Block::Driver_factory
{
Block::Driver *create()
{
bool use_dma = true;
return new (env()->heap()) Block::Exynos5_driver(use_dma);
}
Block::Driver *create() {
return new (Genode::env()->heap()) Block::Exynos5_driver(true); }
void destroy(Block::Driver *driver)
{
Genode::destroy(env()->heap(),
static_cast<Block::Exynos5_driver *>(driver));
}
void destroy(Block::Driver *driver) {
Genode::destroy(Genode::env()->heap(),
static_cast<Block::Exynos5_driver *>(driver)); }
} factory;
} driver_factory;
Regulator::Connection regulator;
Block::Root root;
enum { STACK_SIZE = 8192 };
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "block_ep");
static Regulator::Connection mmc0_regulator(Regulator::CLK_MMC0);
mmc0_regulator.state(true);
Main(Server::Entrypoint &ep)
: ep(ep), regulator(Regulator::CLK_MMC0),
root(ep, Genode::env()->heap(), factory)
{
Genode::printf("--- Arndale eMMC card driver ---\n");
static Signal_receiver receiver;
static Block::Root block_root(&ep, env()->heap(), driver_factory, receiver);
env()->parent()->announce(ep.manage(&block_root));
while (true) {
Signal s = receiver.wait_for_signal();
static_cast<Signal_dispatcher_base *>(s.context())->dispatch(s.num());
Genode::env()->parent()->announce(ep.manage(root));
regulator.state(true);
}
};
return 0;
/************
** Server **
************/
namespace Server {
char const *name() { return "sd_card_ep"; }
size_t stack_size() { return 2*1024*sizeof(long); }
void construct(Entrypoint &ep) { static Main server(ep); }
}

View File

@ -1,5 +1,5 @@
TARGET = sd_card_drv
REQUIRES = exynos5
SRC_CC = main.cc
LIBS = base
LIBS = base server
INC_DIR += $(PRG_DIR) $(PRG_DIR)/..

View File

@ -13,53 +13,45 @@
/* Genode includes */
#include <base/printf.h>
#include <cap_session/connection.h>
#include <os/server.h>
/* local includes */
#include <driver.h>
/*
* MMC1: IRQ 83
*/
int main(int argc, char **argv)
struct Main
{
using namespace Genode;
Server::Entrypoint &ep;
printf("--- OMAP4 SD card driver ---\n");
/**
* Factory used by 'Block::Root' at session creation/destruction time
*/
struct Driver_factory : Block::Driver_factory
struct Factory : Block::Driver_factory
{
Block::Driver *create()
{
bool use_dma = true;
return new (env()->heap()) Block::Omap4_driver(use_dma);
}
Block::Driver *create() {
return new (Genode::env()->heap()) Block::Omap4_driver(true); }
void destroy(Block::Driver *driver)
{
Genode::destroy(env()->heap(),
static_cast<Block::Omap4_driver *>(driver));
}
void destroy(Block::Driver *driver) {
Genode::destroy(Genode::env()->heap(),
static_cast<Block::Omap4_driver *>(driver)); }
} factory;
} driver_factory;
Block::Root root;
enum { STACK_SIZE = 4096 };
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "block_ep");
Main(Server::Entrypoint &ep)
: ep(ep), root(ep, Genode::env()->heap(), factory)
{
Genode::printf("--- OMAP4 SD card driver ---\n");
static Signal_receiver receiver;
static Block::Root block_root(&ep, env()->heap(), driver_factory, receiver);
env()->parent()->announce(ep.manage(&block_root));
while (true) {
Signal s = receiver.wait_for_signal();
static_cast<Signal_dispatcher_base *>(s.context())->dispatch(s.num());
Genode::env()->parent()->announce(ep.manage(root));
}
};
return 0;
/************
** Server **
************/
namespace Server {
char const *name() { return "sd_card_ep"; }
size_t stack_size() { return 2*1024*sizeof(long); }
void construct(Entrypoint &ep) { static Main server(ep); }
}

View File

@ -1,5 +1,5 @@
TARGET = sd_card_drv
REQUIRES = omap4
SRC_CC = main.cc
LIBS = base
LIBS = base server
INC_DIR += $(PRG_DIR) $(PRG_DIR)/..

View File

@ -11,32 +11,28 @@
* under the terms of the GNU General Public License version 2.
*/
/* Genode includes */
#include <base/printf.h>
#include <cap_session/connection.h>
#include <block/component.h>
#include <pl180_defs.h>
#include <os/server.h>
/* local includes */
#include <pl180_defs.h>
#include "pl180.h"
#include "sd_card.h"
int main(int argc, char **argv)
struct Main
{
using namespace Genode;
Server::Entrypoint &ep;
printf("--- PL180 MMC/SD card driver started ---\n");
/**
* Factory used by 'Block::Root' at session creation/destruction time
*/
struct Pl180_driver_factory : Block::Driver_factory
struct Factory : Block::Driver_factory
{
Block::Driver *create()
{
Pl180 *pl180 = new (env()->heap())
Pl180 *pl180 = new (Genode::env()->heap())
Pl180(PL180_PHYS, PL180_SIZE);
Sd_card *sd_card = new (env()->heap())
Sd_card *sd_card = new (Genode::env()->heap())
Sd_card(*pl180);
return sd_card;
@ -47,24 +43,29 @@ int main(int argc, char **argv)
Sd_card *sd_card = static_cast<Sd_card *>(driver);
Pl180 *pl180 = static_cast<Pl180 *>(&sd_card->host_driver());
Genode::destroy(env()->heap(), sd_card);
Genode::destroy(env()->heap(), pl180);
Genode::destroy(Genode::env()->heap(), sd_card);
Genode::destroy(Genode::env()->heap(), pl180);
}
} factory;
} driver_factory;
Block::Root root;
enum { STACK_SIZE = 4096 };
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "block_ep");
Main(Server::Entrypoint &ep)
: ep(ep), root(ep, Genode::env()->heap(), factory)
{
Genode::printf("--- PL180 MMC/SD card driver started ---\n");
static Signal_receiver receiver;
static Block::Root block_root(&ep, env()->heap(), driver_factory, receiver);
env()->parent()->announce(ep.manage(&block_root));
while (true) {
Signal s = receiver.wait_for_signal();
static_cast<Signal_dispatcher_base *>(s.context())->dispatch(s.num());
Genode::env()->parent()->announce(ep.manage(root));
}
};
return 0;
/************
** Server **
************/
namespace Server {
char const *name() { return "sd_card_ep"; }
size_t stack_size() { return 2*1024*sizeof(long); }
void construct(Entrypoint &ep) { static Main server(ep); }
}

View File

@ -1,6 +1,6 @@
TARGET = sd_card_drv
REQUIRES = pl180
SRC_CC = main.cc
LIBS = base
LIBS = base server
INC_DIR += $(PRG_DIR)

View File

@ -47,6 +47,36 @@ static Genode::Signal_receiver &global_sig_rec()
}
static void wait_and_dispatch_one_signal(bool entrypoint)
{
/*
* We call the signal dispatcher outside of the scope of 'Signal'
* object because we block the RPC interface in the input handler
* when the kill mode gets actived. While kill mode is active, we
* do not serve incoming RPC requests but we need to stay responsive
* to user input. Hence, we wait for signals in the input dispatcher
* in this case. An already existing 'Signal' object would lock the
* signal receiver and thereby prevent this nested way of signal
* handling.
*/
Signal_rpc_dispatcher_base *dispatcher = 0;
unsigned num = 0;
{
Signal sig = global_sig_rec().wait_for_signal();
dispatcher = dynamic_cast<Signal_rpc_dispatcher_base *>(sig.context());
num = sig.num();
}
if (!dispatcher)
return;
if (entrypoint)
dispatcher->dispatch_at_entrypoint(num);
else
dispatcher->dispatch(num);
}
Signal_context_capability Entrypoint::manage(Signal_rpc_dispatcher_base &dispatcher)
{
return dispatcher.manage(global_sig_rec(), global_rpc_ep());
@ -62,30 +92,8 @@ void Server::Entrypoint::dissolve(Signal_rpc_dispatcher_base &dispatcher)
Server::Entrypoint::Entrypoint() : _rpc_ep(global_rpc_ep()) { }
void Server::wait_and_dispatch_one_signal()
{
/*
* We call the signal dispatcher outside of the scope of 'Signal'
* object because we block the RPC interface in the input handler
* when the kill mode gets actived. While kill mode is active, we
* do not serve incoming RPC requests but we need to stay responsive
* to user input. Hence, we wait for signals in the input dispatcher
* in this case. An already existing 'Signal' object would lock the
* signal receiver and thereby prevent this nested way of signal
* handling.
*/
Signal_dispatcher_base *dispatcher = 0;
unsigned num = 0;
{
Signal sig = global_sig_rec().wait_for_signal();
dispatcher = dynamic_cast<Signal_dispatcher_base *>(sig.context());
num = sig.num();
}
if (dispatcher)
dispatcher->dispatch(num);
}
void Server::wait_and_dispatch_one_signal() {
::wait_and_dispatch_one_signal(true); }
namespace Server {
@ -116,10 +124,10 @@ int main(int argc, char **argv)
/* call Server::construct in the context of the entrypoint */
Capability<Server::Constructor> constructor_cap = ep.manage(constructor);
constructor_cap.call<Server::Constructor::Rpc_construct>();
/* process incoming signals */
for (;;)
Server::wait_and_dispatch_one_signal();
wait_and_dispatch_one_signal(false);
}

View File

@ -14,7 +14,7 @@
#include <base/exception.h>
#include <base/printf.h>
#include <os/config.h>
#include <cap_session/connection.h>
#include <os/server.h>
#include <rom_session/connection.h>
#include <block/component.h>
#include <block/driver.h>
@ -81,50 +81,51 @@ class Rom_blk : public Block::Driver
};
struct Factory : Block::Driver_factory
struct Main
{
Block::Driver *create()
Server::Entrypoint &ep;
struct Factory : Block::Driver_factory
{
char file[64];
size_t blk_sz = 512;
Block::Driver *create()
{
char file[64];
size_t blk_sz = 512;
try {
config()->xml_node().attribute("file").value(file, sizeof(file));
config()->xml_node().attribute("block_size").value(&blk_sz);
try {
config()->xml_node().attribute("file").value(file, sizeof(file));
config()->xml_node().attribute("block_size").value(&blk_sz);
}
catch (...) { }
PINF("Using file=%s as device with block size %zx.", file, blk_sz);
try {
return new (Genode::env()->heap()) Rom_blk(file, blk_sz);
} catch(Rom_connection::Rom_connection_failed) {
PERR("Cannot open file %s.", file);
}
throw Root::Unavailable();
}
catch (...) { }
PINF("Using file=%s as device with block size %zx.", file, blk_sz);
void destroy(Block::Driver *driver) {
Genode::destroy(env()->heap(), driver); }
} factory;
try {
return new (Genode::env()->heap()) Rom_blk(file, blk_sz);
} catch(Rom_connection::Rom_connection_failed) {
PERR("Cannot open file %s.", file);
}
throw Root::Unavailable();
}
Block::Root root;
void destroy(Block::Driver *driver) {
Genode::destroy(env()->heap(), driver); }
Main(Server::Entrypoint &ep)
: ep(ep), root(ep, Genode::env()->heap(), factory) {
Genode::env()->parent()->announce(ep.manage(root)); }
};
int main()
{
enum { STACK_SIZE = 8192 };
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "rom_blk_ep");
/************
** Server **
************/
static Signal_receiver receiver;
static Factory driver_factory;
static Block::Root block_root(&ep, env()->heap(), driver_factory, receiver);
env()->parent()->announce(ep.manage(&block_root));
while (true) {
Signal s = receiver.wait_for_signal();
static_cast<Signal_dispatcher_base *>(s.context())->dispatch(s.num());
}
return 0;
namespace Server {
char const *name() { return "rom_blk_ep"; }
size_t stack_size() { return 2*1024*sizeof(long); }
void construct(Entrypoint &ep) { static Main server(ep); }
}

View File

@ -1,3 +1,3 @@
TARGET = rom_blk
SRC_CC = main.cc
LIBS = base config
LIBS = base config server

View File

@ -32,11 +32,17 @@ class Driver : public Block::Driver
Genode::size_t _number;
Genode::size_t _size;
Req_buffer _packets;
Genode::Signal_dispatcher<Driver> _ack;
Genode::Ram_dataspace_capability _blk_ds;
unsigned char *_blk_buf;
void _handle_ack(unsigned)
public:
Driver(Genode::size_t number, Genode::size_t size)
: _number(number), _size(size),
_blk_ds(Genode::env()->ram_session()->alloc(number*size)),
_blk_buf(Genode::env()->rm_session()->attach(_blk_ds)) {}
void handler(unsigned)
{
while (!_packets.empty()) {
Block::Packet_descriptor p = _packets.get();
@ -44,17 +50,6 @@ class Driver : public Block::Driver
}
}
public:
Driver(Genode::size_t number, Genode::size_t size,
Genode::Signal_receiver &receiver)
: _number(number), _size(size),
_ack(receiver, *this, &Driver::_handle_ack),
_blk_ds(Genode::env()->ram_session()->alloc(number*size)),
_blk_buf(Genode::env()->rm_session()->attach(_blk_ds)) {}
Genode::Signal_context_capability handler() { return _ack; }
/*******************************
** Block::Driver interface **
@ -98,52 +93,54 @@ class Driver : public Block::Driver
};
struct Factory : Block::Driver_factory
struct Main
{
Genode::Signal_receiver &receiver;
::Driver *driver;
Server::Entrypoint &ep;
Factory(Genode::Signal_receiver &r) : receiver(r)
struct Factory : Block::Driver_factory
{
Genode::size_t blk_nr = 1024;
Genode::size_t blk_sz = 512;
::Driver *driver;
try {
Genode::config()->xml_node().attribute("sectors").value(&blk_nr);
Genode::config()->xml_node().attribute("block_size").value(&blk_sz);
Factory()
{
Genode::size_t blk_nr = 1024;
Genode::size_t blk_sz = 512;
try {
Genode::config()->xml_node().attribute("sectors").value(&blk_nr);
Genode::config()->xml_node().attribute("block_size").value(&blk_sz);
}
catch (...) { }
driver = new (Genode::env()->heap()) Driver(blk_nr, blk_sz);
}
catch (...) { }
driver = new (Genode::env()->heap()) Driver(blk_nr, blk_sz, receiver);
}
Block::Driver *create() { return driver; }
void destroy(Block::Driver *driver) { }
void destroy(Block::Driver *driver) { }
} factory;
Block::Root root;
Timer::Connection timer;
Server::Signal_rpc_member<Driver> dispatcher = { ep, *factory.driver,
&Driver::handler };
Main(Server::Entrypoint &ep)
: ep(ep), root(ep, Genode::env()->heap(), factory)
{
timer.sigh(dispatcher);
timer.trigger_periodic(10000);
Genode::env()->parent()->announce(ep.manage(root));
}
};
int main()
{
using namespace Genode;
/************
** Server **
************/
enum { STACK_SIZE = 2048 * sizeof(Genode::addr_t) };
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "test_blk_ep");
static Signal_receiver receiver;
static Factory driver_factory(receiver);
static Block::Root block_root(&ep, env()->heap(), driver_factory, receiver);
env()->parent()->announce(ep.manage(&block_root));
static Timer::Connection timer;
timer.sigh(driver_factory.driver->handler());
timer.trigger_periodic(10000);
while (true) {
Signal s = receiver.wait_for_signal();
static_cast<Signal_dispatcher_base *>(s.context())->dispatch(s.num());
}
return 0;
namespace Server {
char const *name() { return "blk_srv_ep"; }
size_t stack_size() { return 2*1024*sizeof(long); }
void construct(Entrypoint &ep) { static Main server(ep); }
}

View File

@ -1,3 +1,3 @@
TARGET = test-blk-srv
SRC_CC = main.cc
LIBS = base config
LIBS = base config server

View File

@ -15,10 +15,8 @@
*/
#include <base/printf.h>
#include <cap_session/connection.h>
#include <framebuffer_session/connection.h>
#include <block/component.h>
#include <block/driver.h>
class Driver : public Block::Driver
{
@ -109,24 +107,24 @@ struct Factory : Block::Driver_factory
};
int main()
struct Main
{
using namespace Genode;
Server::Entrypoint &ep;
struct Factory factory;
Block::Root root;
enum { STACK_SIZE = 2048 * sizeof(Genode::addr_t) };
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "fb_block_ep");
Main(Server::Entrypoint &ep)
: ep(ep), root(ep, Genode::env()->heap(), factory) {
Genode::env()->parent()->announce(ep.manage(root)); }
};
static Signal_receiver receiver;
static Factory driver_factory;
static Block::Root block_root(&ep, env()->heap(), driver_factory, receiver);
env()->parent()->announce(ep.manage(&block_root));
/************
** Server **
************/
while (true) {
Signal s = receiver.wait_for_signal();
static_cast<Signal_dispatcher_base *>(s.context())->dispatch(s.num());
}
return 0;
namespace Server {
char const *name() { return "fb_blk_ep"; }
size_t stack_size() { return 2*1024*sizeof(long); }
void construct(Entrypoint &ep) { static Main server(ep); }
}

View File

@ -1,3 +1,3 @@
TARGET = test-fb_blk_adapter
SRC_CC = main.cc
LIBS = base
LIBS = base server