os: use async IRQ and server lib in drivers

Use the new asynchronous IRQ interface in the mostly used drivers, e.g.:

* ahci_drv: x86/exynos5
* gpio_drv: imx53/omap4
* input_drv: imx53/dummy
* ps2_drv: x86/pl050
* timer_drv

Now, the Irq_session is requested from Gpio::Session:

From now on we use an asynchronous IRQ interface. To prevent triggering
another GPIO IRQ while currently handling the former one, IRQs must
now by acknowledged explicitly. While here, we also changed the GPIO
session interface regarding IRQ management. The generic GPIO component
now wraps the Irq_session managed by the backend instead of using the
GPIO backend methods directly. A client using the GPIO session may
request the Irq_session_capability by calling
'Gpio::Session::irq_session()' and can use this capability when using
a local Irq_session_client.

Issue #1456.
This commit is contained in:
Josef Söntgen 2015-04-14 13:56:26 +02:00 committed by Christian Helmuth
parent bfb47cfd4e
commit 85599c072f
53 changed files with 1114 additions and 758 deletions

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2011-2013 Genode Labs GmbH
* Copyright (C) 2011-2015 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.
@ -30,39 +30,62 @@ class Gpio::Session_component : public Genode::Rpc_object<Gpio::Session>
{
private:
Driver &_driver;
unsigned long _pin;
Genode::Signal_context_capability _sigh;
struct Irq_session_component : public Genode::Rpc_object<Genode::Irq_session>
{
Driver &_driver;
unsigned long _pin;
Irq_session_component(Driver &driver, unsigned long pin)
: _driver(driver), _pin(pin) { }
/***************************
** Irq_session interface **
***************************/
void ack_irq() override { _driver.ack_irq(_pin); }
void sigh(Genode::Signal_context_capability sigh) override {
_driver.register_signal(_pin, sigh); }
};
Genode::Rpc_entrypoint &_ep;
Driver &_driver;
unsigned long _pin;
Irq_session_component _irq_component;
Genode::Irq_session_capability _irq_cap;
public:
Session_component(Driver &driver, unsigned long gpio_pin)
: _driver(driver), _pin(gpio_pin) { }
Session_component(Genode::Rpc_entrypoint &ep,
Driver &driver,
unsigned long gpio_pin)
: _ep(ep), _driver(driver), _pin(gpio_pin),
_irq_component(_driver, _pin),
_irq_cap(_ep.manage(&_irq_component)) { }
~Session_component()
{
if (_sigh.valid())
_driver.unregister_signal(_pin);
}
~Session_component() { _ep.dissolve(&_irq_component); }
/************************************
/*****************************
** Gpio::Session interface **
************************************/
*****************************/
void direction(Direction d) { _driver.direction(_pin, (d == IN)); }
void write(bool level) { _driver.write(_pin, level); }
bool read() { return _driver.read(_pin); }
void irq_enable(bool enable) { _driver.irq_enable(_pin, enable); }
void irq_sigh(Genode::Signal_context_capability cap)
void debouncing(unsigned int us)
{
if (cap.valid()) {
_sigh = cap;
_driver.register_signal(_pin, cap);
}
if (us) {
_driver.debounce_time(_pin, us);
_driver.debounce_enable(_pin, true);
} else
_driver.debounce_enable(_pin, false);
}
void irq_type(Irq_type type)
Genode::Irq_session_capability irq_session(Irq_type type)
{
switch (type) {
case HIGH_LEVEL:
@ -77,15 +100,10 @@ class Gpio::Session_component : public Genode::Rpc_object<Gpio::Session>
case FALLING_EDGE:
_driver.falling_detect(_pin);
};
}
void debouncing(unsigned int us)
{
if (us) {
_driver.debounce_time(_pin, us);
_driver.debounce_enable(_pin, true);
} else
_driver.debounce_enable(_pin, false);
_driver.irq_enable(_pin, true);
return _irq_cap;
}
};
@ -94,7 +112,8 @@ class Gpio::Root : public Genode::Root_component<Gpio::Session_component>
{
private:
Driver &_driver;
Genode::Rpc_entrypoint &_ep;
Driver &_driver;
protected:
@ -114,7 +133,7 @@ class Gpio::Root : public Genode::Root_component<Gpio::Session_component>
throw Genode::Root::Quota_exceeded();
}
return new (md_alloc()) Session_component(_driver, pin);
return new (md_alloc()) Session_component(_ep, _driver, pin);
}
public:
@ -122,7 +141,7 @@ class Gpio::Root : public Genode::Root_component<Gpio::Session_component>
Root(Genode::Rpc_entrypoint *session_ep,
Genode::Allocator *md_alloc, Driver &driver)
: Genode::Root_component<Gpio::Session_component>(session_ep, md_alloc),
_driver(driver) { }
_ep(*session_ep), _driver(driver) { }
};

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2011-2013 Genode Labs GmbH
* Copyright (C) 2011-2015 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.
@ -92,6 +92,13 @@ struct Gpio::Driver
*/
virtual void irq_enable(unsigned gpio, bool enable) = 0;
/**
* Acknowledge IRQ for specified GPIO pin
*
* \param gpio corresponding gpio pin number
*/
virtual void ack_irq(unsigned gpio) = 0;
/**
* Register signal handler for interrupts
*

View File

@ -7,7 +7,7 @@
/*
* Copyright (C) 2012 Ksys Labs LLC
* Copyright (C) 2012-2013 Genode Labs GmbH
* Copyright (C) 2012-2015 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.
@ -27,15 +27,13 @@ struct Gpio::Session_client : Genode::Rpc_client<Session>
explicit Session_client(Session_capability session)
: Genode::Rpc_client<Session>(session) { }
void direction(Direction d) override { call<Rpc_direction>(d); }
void write(bool level) override { call<Rpc_write>(level); }
bool read() override { return call<Rpc_read>(); }
void debouncing(unsigned int us) override { call<Rpc_debouncing>(us); }
void irq_type(Irq_type it) override { call<Rpc_irq_type>(it); }
void irq_enable(bool enable) override { call<Rpc_irq_enable>(enable); }
void direction(Direction d) override { call<Rpc_direction>(d); }
void write(bool level) override { call<Rpc_write>(level); }
bool read() override { return call<Rpc_read>(); }
void debouncing(unsigned int us) override { call<Rpc_debouncing>(us); }
void irq_sigh(Genode::Signal_context_capability cap) override {
call<Rpc_irq_sigh>(cap); }
Genode::Irq_session_capability irq_session(Irq_type type) override {
return call<Rpc_irq_session>(type); }
};
#endif /* _INCLUDE__GPIO_SESSION_H__CLIENT_H_ */

View File

@ -7,7 +7,7 @@
/*
* Copyright (C) 2012 Ksys Labs LLC
* Copyright (C) 2012-2013 Genode Labs GmbH
* Copyright (C) 2012-2015 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.
@ -19,6 +19,7 @@
#include <base/signal.h>
#include <dataspace/capability.h>
#include <session/session.h>
#include <irq_session/capability.h>
namespace Gpio { struct Session; }
@ -62,42 +63,26 @@ struct Gpio::Session : Genode::Session
virtual void debouncing(unsigned int us) = 0;
/**
* Configure the type of interrupt for the GPIO pin
* Rquest IRQ session
*
* \param it type of IRQ
* \param type type of IRQ
*/
virtual void irq_type(Irq_type it) = 0;
/**
* Enable or disable the interrupt of the GPIO pin
*
* \param enable interrupt status( true - enable, false - disable)
*/
virtual void irq_enable(bool enable) = 0;
/**
* Register signal handler to be notified on interrupt
*
* \param cap capability of signal-context to handle GPIO interrupt
*/
virtual void irq_sigh(Genode::Signal_context_capability cap) = 0;
virtual Genode::Irq_session_capability irq_session(Irq_type type) = 0;
/*******************
** RPC interface **
*******************/
GENODE_RPC(Rpc_direction, void, direction, Direction);
GENODE_RPC(Rpc_write, void, write, bool);
GENODE_RPC(Rpc_read, bool, read);
GENODE_RPC(Rpc_debouncing, void, debouncing, unsigned int);
GENODE_RPC(Rpc_irq_type, void, irq_type, Irq_type);
GENODE_RPC(Rpc_irq_enable, void, irq_enable, bool);
GENODE_RPC(Rpc_irq_sigh, void, irq_sigh, Genode::Signal_context_capability);
GENODE_RPC(Rpc_direction, void, direction, Direction);
GENODE_RPC(Rpc_write, void, write, bool);
GENODE_RPC(Rpc_read, bool, read);
GENODE_RPC(Rpc_debouncing, void, debouncing, unsigned int);
GENODE_RPC(Rpc_irq_session, Genode::Irq_session_capability,
irq_session, Irq_type);
GENODE_RPC_INTERFACE(Rpc_direction, Rpc_write, Rpc_read,
Rpc_debouncing, Rpc_irq_type, Rpc_irq_enable,
Rpc_irq_sigh);
Rpc_debouncing, Rpc_irq_session);
};
#endif /* _INCLUDE__GPIO_SESSION__GPIO_SESSION_H_ */

View File

@ -1,5 +1,5 @@
SRC_CC += main.cc
LIBS += base alarm
LIBS += base alarm server
INC_DIR += $(REP_DIR)/src/drivers/timer/include
vpath main.cc $(REP_DIR)/src/drivers/timer

View File

@ -902,6 +902,8 @@ struct Sata_ahci : Attached_mmio
/* port 0 settings */
unsigned p0_speed;
Irq_connection p0_irq;
Genode::Signal_receiver p0_irq_rec;
Genode::Signal_context p0_irq_ctx;
enum { SATA_3_MAX_SPEED = 3 };
@ -922,7 +924,10 @@ struct Sata_ahci : Attached_mmio
dbc_stable_trials(5),
p0_speed(SATA_3_MAX_SPEED),
p0_irq(Genode::Board_base::SATA_IRQ)
{ }
{
p0_irq.sigh(p0_irq_rec.manage(&p0_irq_ctx));
p0_irq.ack_irq();
}
/**
* Clear all interrupts at port 0
@ -1145,7 +1150,7 @@ struct Sata_ahci : Attached_mmio
{
typedef typename P0IS_BIT::Bitfield_base P0is_bit;
write<P0ci>(1 << tag);
p0_irq.wait_for_irq();
p0_irq_rec.wait_for_signal();
if (!read<Is::Ips>()) {
PERR("ATA0 no IRQ raised");
return -1;
@ -1269,6 +1274,7 @@ struct Sata_ahci : Attached_mmio
printf("ATA0 supports UDMA-133 and NCQ with queue depth %u\n",
dev_id->queue_depth + 1);
write<Is::Ips>(1);
p0_irq.ack_irq();
/* destroy receive buffer DMA */
env()->rm_session()->detach(dev_id_virt);
@ -1300,6 +1306,7 @@ struct Sata_ahci : Attached_mmio
/* end command */
write<Is::Ips>(1);
p0_irq.ack_irq();
/* check for hidden blocks */
return max_native_addr + 1 != block_cnt;
@ -1344,6 +1351,7 @@ struct Sata_ahci : Attached_mmio
}
/* end command */
write<Is::Ips>(1);
p0_irq.ack_irq();
return 0;
}
@ -1668,7 +1676,7 @@ struct Sata_ahci : Attached_mmio
/* issue command and wait for completion */
write<P0sact>(1 << tag);
write<P0ci>(1 << tag);
p0_irq.wait_for_irq();
p0_irq_rec.wait_for_signal();
/* get port back ready and deteremine command state */
int ret = p0_handle_irqs(lba);
@ -1684,6 +1692,7 @@ struct Sata_ahci : Attached_mmio
return -1;
}
write<Is::Ips>(1);
p0_irq.ack_irq();
}
return ret;
}

View File

@ -370,6 +370,8 @@ class Ahci_device_base
Generic_ctrl *_ctrl; /* generic host control */
Ahci_port *_port; /* port base of device */
Irq_connection *_irq; /* device IRQ */
Genode::Signal_receiver _irq_rec; /* IRQ signal receiver */
Genode::Signal_context _irq_ctx; /* IRQ signal context */
size_t _block_cnt; /* number of blocks on device */
Command_list *_cmd_list; /* pointer to command list */
Command_table *_cmd_table; /* pointer to command table */
@ -453,7 +455,7 @@ class Ahci_device_base
while (!status) {
/* wait for interrupt */
_irq->wait_for_irq();
_irq_rec.wait_for_signal();
if (verbose)
PDBG("Int status (IRQ): global: %x port: %x error: %x",
@ -479,6 +481,8 @@ class Ahci_device_base
/* acknowledge global port interrupt */
_ctrl->hba_interrupt_ack();
_irq->ack_irq();
/* disable hba */
_port->hba_disable();
}

View File

@ -184,6 +184,10 @@ class Ahci_device : public Ahci_device_base
_disable_msi(pci_device);
device->_irq = new(env()->heap()) Irq_connection(intr & 0xff);
Genode::Signal_context_capability cap = device->_irq_rec.manage(&device->_irq_ctx);
device->_irq->sigh(cap);
device->_irq->ack_irq();
/* remember pci_device to be able to allocate ram memory which is dma able */
device->_pci_device_cap = device_cap;
device->_pci_device = pci_device;

View File

@ -113,7 +113,19 @@ class I2c_interface : public Attached_mmio
TX_DELAY_US = 1,
};
Irq_connection _irq;
Irq_connection _irq;
Genode::Signal_receiver _irq_rec;
Genode::Signal_context _irq_ctx;
/**
* Wait until the IRQ signal was received
*/
void _wait_for_irq()
{
_irq_rec.wait_for_signal();
_irq.ack_irq();
}
/**
* Stop a running transfer as master
@ -166,7 +178,7 @@ class I2c_interface : public Attached_mmio
write<Con>(con);
Stat::Busy::set(stat, 1);
write<Stat>(stat);
_irq.wait_for_irq();
_wait_for_irq();
if (_arbitration_error()) return -1;
return 0;
}
@ -196,6 +208,7 @@ class I2c_interface : public Attached_mmio
return 0;
}
public:
/**
@ -224,8 +237,13 @@ class I2c_interface : public Attached_mmio
Lc::Sda_out_delay::set(lc, 2);
Lc::Filter_en::set(lc, 1);
write<Lc>(lc);
_irq.sigh(_irq_rec.manage(&_irq_ctx));
_irq.ack_irq();
}
~I2c_interface() { _irq_rec.dissolve(&_irq_ctx); }
/**
* Transmit an I2C message as master
*
@ -252,7 +270,7 @@ class I2c_interface : public Attached_mmio
/* finish last byte and prepare for next one */
off++;
write<Con::Irq_pending>(0);
_irq.wait_for_irq();
_wait_for_irq();
if (_arbitration_error()) return -1;
}
/* end message transfer */
@ -285,7 +303,7 @@ class I2c_interface : public Attached_mmio
while (1)
{
/* receive next message byte */
_irq.wait_for_irq();
_wait_for_irq();
if (_arbitration_error()) return -1;
buf[off] = read<Ds>();
off++;
@ -619,14 +637,6 @@ class I2c_hdmi : public I2c_interface
}
};
/**
* Return singleton of device instance
*/
static I2c_hdmi * i2c_hdmi()
{
static I2c_hdmi s;
return &s;
}
/**
* Converts input stream from video mixer into HDMI packet stream for HDMI PHY
@ -942,12 +952,15 @@ class Hdmi : public Attached_mmio
write<Fp_3d::Value>(0);
}
I2c_hdmi _i2c_hdmi;
public:
/**
* Constructor
*/
Hdmi() : Attached_mmio(0x14530000, 0xa0000) { }
Hdmi()
: Attached_mmio(0x14530000, 0xa0000), _i2c_hdmi() { }
/**
* Initialize HDMI controller for video output only
@ -978,12 +991,12 @@ class Hdmi : public Attached_mmio
}
/* set-up HDMI PHY */
write<Phy_con_0::Pwr_off>(0);
if (i2c_hdmi()->stop_hdmi_phy()) return -1;
if (_i2c_hdmi.stop_hdmi_phy()) return -1;
write<Phy_rstout::Reset>(1);
delayer()->usleep(10000);
write<Phy_rstout::Reset>(0);
delayer()->usleep(10000);
if (i2c_hdmi()->setup_and_start_hdmi_phy(pixel_clk)) return -1;
if (_i2c_hdmi.setup_and_start_hdmi_phy(pixel_clk)) return -1;
/* reset HDMI CORE */
write<Core_rstout::Reset>(0);
@ -1095,15 +1108,6 @@ class Hdmi : public Attached_mmio
}
};
/**
* Return singleton of device instance
*/
static Hdmi * hdmi()
{
static Hdmi s;
return &s;
}
/*************************
** Framebuffer::Driver **
@ -1140,7 +1144,8 @@ int Framebuffer::Driver::_init_hdmi(addr_t fb_phys)
if (err) { return -1; }
/* set-up HDMI to feed connected device */
err = hdmi()->init_hdmi(_fb_width, _fb_height);
static Hdmi hdmi;
err = hdmi.init_hdmi(_fb_width, _fb_height);
if (err) { return -1; }
return 0;
}

View File

@ -17,6 +17,7 @@
/* Genode includes */
#include <base/stdint.h>
#include <base/printf.h>
#include <os/server.h>
namespace Framebuffer
{

View File

@ -11,9 +11,6 @@
* under the terms of the GNU General Public License version 2.
*/
/* local includes */
#include <driver.h>
/* Genode includes */
#include <framebuffer_session/framebuffer_session.h>
#include <cap_session/connection.h>
@ -22,6 +19,10 @@
#include <base/sleep.h>
#include <os/config.h>
#include <os/static_root.h>
#include <os/server.h>
/* local includes */
#include <driver.h>
namespace Framebuffer
{
@ -111,47 +112,52 @@ class Framebuffer::Session_component
};
/**
* Program entrypoint
*/
int main(int, char **)
struct Main
{
using namespace Framebuffer;
Server::Entrypoint &ep;
Framebuffer::Driver driver;
/* default config */
size_t width = 1920;
size_t height = 1080;
Driver::Output output = Driver::OUTPUT_HDMI;
Main(Server::Entrypoint &ep)
: ep(ep), driver()
{
using namespace Framebuffer;
/* try to read custom user config */
try {
char out[5] = { };
Genode::Xml_node config_node = Genode::config()->xml_node();
config_node.attribute("width").value(&width);
config_node.attribute("height").value(&height);
config_node.attribute("output").value(out, sizeof(out));
if (!Genode::strcmp(out, "LCD")) {
output = Driver::OUTPUT_LCD;
/* default config */
size_t width = 1920;
size_t height = 1080;
Driver::Output output = Driver::OUTPUT_HDMI;
/* try to read custom user config */
try {
char out[5] = { 0 };
Genode::Xml_node config_node = Genode::config()->xml_node();
config_node.attribute("width").value(&width);
config_node.attribute("height").value(&height);
config_node.attribute("output").value(out, sizeof(out));
if (!Genode::strcmp(out, "LCD")) {
output = Driver::OUTPUT_LCD;
}
}
catch (...) {
PDBG("using default configuration: HDMI@%dx%d", width, height);
}
/* let entrypoint serve the framebuffer session and root interfaces */
static Session_component fb_session(driver, width, height, output);
static Static_root<Framebuffer::Session> fb_root(ep.manage(fb_session));
/* announce service and relax */
env()->parent()->announce(ep.manage(fb_root));
}
catch (...) {
PDBG("using default configuration: HDMI@%dx%d", width, height);
}
/* create server backend */
static Driver driver;
};
/* create server entrypoint */
enum { STACK_SIZE = 4096 };
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "fb_ep");
/* let entrypoint serve the framebuffer session and root interfaces */
static Session_component fb_session(driver, width, height, output);
static Static_root<Framebuffer::Session> fb_root(ep.manage(&fb_session));
/************
** Server **
************/
/* announce service and relax */
env()->parent()->announce(ep.manage(&fb_root));
sleep_forever();
return 0;
namespace Server {
char const *name() { return "fb_drv_ep"; }
size_t stack_size() { return 1024*sizeof(long); }
void construct(Entrypoint &ep) { static Main server(ep); }
}

View File

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

View File

@ -22,6 +22,7 @@
#include <gpio/driver.h>
#include <irq_session/connection.h>
#include <timer_session/connection.h>
#include <os/server.h>
/* local includes */
#include "gpio.h"
@ -34,6 +35,7 @@ class Imx53_driver : public Gpio::Driver
private:
enum {
PIN_SHIFT = 5,
MAX_BANKS = 7,
MAX_PINS = 32
};
@ -52,31 +54,44 @@ class Imx53_driver : public Gpio::Driver
{
public:
void handle_irq();
void handle_irq()
{
unsigned long status = _reg.read<Gpio_reg::Int_stat>();
for(unsigned i = 0; i < MAX_PINS; i++) {
if ((status & (1 << i)) && _irq_enabled[i] &&
_sig_cap[i].valid())
Genode::Signal_transmitter(_sig_cap[i]).submit();
}
}
private:
class Irq_handler : public Genode::Thread<4096>
class Irq_handler
{
private:
Genode::Irq_connection _irq;
Gpio_bank *_bank;
Genode::Irq_connection _irq;
Genode::Signal_rpc_member<Irq_handler> _dispatcher;
Gpio_bank *_bank;
void _handle(unsigned)
{
_bank->handle_irq();
_irq.ack_irq();
}
public:
Irq_handler(unsigned irq, Gpio_bank *bank)
: Genode::Thread<4096>("irq handler"),
_irq(irq), _bank(bank) { start(); }
void entry()
Irq_handler(Server::Entrypoint &ep,
unsigned irq, Gpio_bank *bank)
: _irq(irq), _dispatcher(ep, *this, &Irq_handler::_handle),
_bank(bank)
{
while (true) {
_irq.wait_for_irq();
_bank->handle_irq();
}
_irq.sigh(_dispatcher);
_irq.ack_irq();
}
};
Gpio_reg _reg;
@ -84,15 +99,14 @@ class Imx53_driver : public Gpio::Driver
Irq_handler _irqh_high;
Genode::Signal_context_capability _sig_cap[MAX_PINS];
bool _irq_enabled[MAX_PINS];
Genode::Lock _lock;
public:
Gpio_bank(Genode::addr_t base, Genode::size_t size,
unsigned irq_low, unsigned irq_high)
Gpio_bank(Server::Entrypoint &ep, Genode::addr_t base,
Genode::size_t size, unsigned irq_low, unsigned irq_high)
: _reg(base, size),
_irqh_low(irq_low, this),
_irqh_high(irq_high, this) { }
_irqh_low(ep, irq_low, this),
_irqh_high(ep, irq_high, this) { }
Gpio_reg* regs() { return &_reg; }
@ -102,20 +116,70 @@ class Imx53_driver : public Gpio::Driver
_irq_enabled[pin] = enable;
}
void ack_irq(int pin)
{
_reg.write<Gpio_reg::Int_stat>(1, pin);
}
void sigh(int pin, Genode::Signal_context_capability cap) {
_sig_cap[pin] = cap; }
};
Server::Entrypoint &_ep;
static Gpio_bank _gpio_bank[MAX_BANKS];
Gpio_bank _gpio_bank_0;
Gpio_bank _gpio_bank_1;
Gpio_bank _gpio_bank_2;
Gpio_bank _gpio_bank_3;
Gpio_bank _gpio_bank_4;
Gpio_bank _gpio_bank_5;
Gpio_bank _gpio_bank_6;
Gpio_bank *_gpio_bank(int gpio)
{
switch (gpio >> PIN_SHIFT) {
case 0:
return &_gpio_bank_0;
case 1:
return &_gpio_bank_1;
case 2:
return &_gpio_bank_2;
case 3:
return &_gpio_bank_3;
case 4:
return &_gpio_bank_4;
case 5:
return &_gpio_bank_5;
case 6:
return &_gpio_bank_6;
}
PERR("no Gpio_bank for pin %d available", gpio);
return 0;
}
int _gpio_bank_index(int gpio) { return gpio >> 5; }
int _gpio_index(int gpio) { return gpio & 0x1f; }
Imx53_driver()
Imx53_driver(Server::Entrypoint &ep)
:
_ep(ep),
_gpio_bank_0(_ep, Genode::Board_base::GPIO1_MMIO_BASE, Genode::Board_base::GPIO1_MMIO_SIZE,
Genode::Board_base::GPIO1_IRQL, Genode::Board_base::GPIO1_IRQH),
_gpio_bank_1(_ep, Genode::Board_base::GPIO2_MMIO_BASE, Genode::Board_base::GPIO2_MMIO_SIZE,
Genode::Board_base::GPIO2_IRQL, Genode::Board_base::GPIO2_IRQH),
_gpio_bank_2(_ep, Genode::Board_base::GPIO3_MMIO_BASE, Genode::Board_base::GPIO3_MMIO_SIZE,
Genode::Board_base::GPIO3_IRQL, Genode::Board_base::GPIO3_IRQH),
_gpio_bank_3(_ep, Genode::Board_base::GPIO4_MMIO_BASE, Genode::Board_base::GPIO4_MMIO_SIZE,
Genode::Board_base::GPIO4_IRQL, Genode::Board_base::GPIO4_IRQH),
_gpio_bank_4(_ep, Genode::Board_base::GPIO5_MMIO_BASE, Genode::Board_base::GPIO5_MMIO_SIZE,
Genode::Board_base::GPIO5_IRQL, Genode::Board_base::GPIO5_IRQH),
_gpio_bank_5(_ep, Genode::Board_base::GPIO6_MMIO_BASE, Genode::Board_base::GPIO6_MMIO_SIZE,
Genode::Board_base::GPIO6_IRQL, Genode::Board_base::GPIO6_IRQH),
_gpio_bank_6(_ep, Genode::Board_base::GPIO7_MMIO_BASE, Genode::Board_base::GPIO7_MMIO_SIZE,
Genode::Board_base::GPIO7_IRQL, Genode::Board_base::GPIO7_IRQH)
{
for (unsigned i = 0; i < MAX_BANKS; ++i) {
Gpio_reg *regs = _gpio_bank[i].regs();
Gpio_reg *regs = _gpio_bank(i << PIN_SHIFT)->regs();
for (unsigned j = 0; j < MAX_PINS; j++) {
regs->write<Gpio_reg::Int_conf>(Gpio_reg::Int_conf::LOW_LEVEL, j);
regs->write<Gpio_reg::Int_mask>(0, j);
@ -124,10 +188,10 @@ class Imx53_driver : public Gpio::Driver
}
}
public:
static Imx53_driver& factory();
static Imx53_driver &factory(Server::Entrypoint &ep);
/******************************
** Gpio::Driver interface **
@ -137,7 +201,7 @@ class Imx53_driver : public Gpio::Driver
{
if (verbose) PDBG("gpio=%d input=%d", gpio, input);
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs();
Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
gpio_reg->write<Gpio_reg::Dir>(input ? 0 : 1,
_gpio_index(gpio));
}
@ -146,7 +210,7 @@ class Imx53_driver : public Gpio::Driver
{
if (verbose) PDBG("gpio=%d level=%d", gpio, level);
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs();
Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
gpio_reg->write<Gpio_reg::Data>(level ? 1 : 0,
_gpio_index(gpio));
@ -156,7 +220,7 @@ class Imx53_driver : public Gpio::Driver
{
if (verbose) PDBG("gpio=%d", gpio);
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs();
Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
return gpio_reg->read<Gpio_reg::Pad_stat>(_gpio_index(gpio));
}
@ -174,7 +238,7 @@ class Imx53_driver : public Gpio::Driver
{
if (verbose) PDBG("gpio=%d", gpio);
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs();
Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
gpio_reg->write<Gpio_reg::Int_conf>(Gpio_reg::Int_conf::FAL_EDGE,
_gpio_index(gpio));
}
@ -183,7 +247,7 @@ class Imx53_driver : public Gpio::Driver
{
if (verbose) PDBG("gpio=%d", gpio);
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs();
Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
gpio_reg->write<Gpio_reg::Int_conf>(Gpio_reg::Int_conf::RIS_EDGE,
_gpio_index(gpio));
}
@ -192,7 +256,7 @@ class Imx53_driver : public Gpio::Driver
{
if (verbose) PDBG("gpio=%d", gpio);
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs();
Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
gpio_reg->write<Gpio_reg::Int_conf>(Gpio_reg::Int_conf::HIGH_LEVEL,
_gpio_index(gpio));
}
@ -201,7 +265,7 @@ class Imx53_driver : public Gpio::Driver
{
if (verbose) PDBG("gpio=%d", gpio);
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs();
Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
gpio_reg->write<Gpio_reg::Int_conf>(Gpio_reg::Int_conf::LOW_LEVEL,
_gpio_index(gpio));
}
@ -210,7 +274,14 @@ class Imx53_driver : public Gpio::Driver
{
if (verbose) PDBG("gpio=%d enable=%d", gpio, enable);
_gpio_bank[_gpio_bank_index(gpio)].irq(_gpio_index(gpio), enable);
_gpio_bank(gpio)->irq(_gpio_index(gpio), enable);
}
void ack_irq(unsigned gpio)
{
if (verbose) PDBG("gpio=%d ack_irq", gpio);
_gpio_bank(gpio)->ack_irq(_gpio_index(gpio));
}
void register_signal(unsigned gpio,
@ -218,59 +289,24 @@ class Imx53_driver : public Gpio::Driver
{
if (verbose) PDBG("gpio=%d", gpio);
_gpio_bank[_gpio_bank_index(gpio)].sigh(_gpio_index(gpio), cap); }
_gpio_bank(gpio)->sigh(_gpio_index(gpio), cap); }
void unregister_signal(unsigned gpio)
{
if (verbose) PDBG("gpio=%d", gpio);
Genode::Signal_context_capability cap;
_gpio_bank[_gpio_bank_index(gpio)].sigh(_gpio_index(gpio), cap);
_gpio_bank(gpio)->sigh(_gpio_index(gpio), cap);
}
bool gpio_valid(unsigned gpio) { return gpio < (MAX_PINS*MAX_BANKS); }
};
Imx53_driver::Gpio_bank Imx53_driver::_gpio_bank[Imx53_driver::MAX_BANKS] = {
{ Genode::Board_base::GPIO1_MMIO_BASE, Genode::Board_base::GPIO1_MMIO_SIZE,
Genode::Board_base::GPIO1_IRQL, Genode::Board_base::GPIO1_IRQH },
{ Genode::Board_base::GPIO2_MMIO_BASE, Genode::Board_base::GPIO2_MMIO_SIZE,
Genode::Board_base::GPIO2_IRQL, Genode::Board_base::GPIO2_IRQH },
{ Genode::Board_base::GPIO3_MMIO_BASE, Genode::Board_base::GPIO3_MMIO_SIZE,
Genode::Board_base::GPIO3_IRQL, Genode::Board_base::GPIO3_IRQH },
{ Genode::Board_base::GPIO4_MMIO_BASE, Genode::Board_base::GPIO4_MMIO_SIZE,
Genode::Board_base::GPIO4_IRQL, Genode::Board_base::GPIO4_IRQH },
{ Genode::Board_base::GPIO5_MMIO_BASE, Genode::Board_base::GPIO5_MMIO_SIZE,
Genode::Board_base::GPIO5_IRQL, Genode::Board_base::GPIO5_IRQH },
{ Genode::Board_base::GPIO6_MMIO_BASE, Genode::Board_base::GPIO6_MMIO_SIZE,
Genode::Board_base::GPIO6_IRQL, Genode::Board_base::GPIO6_IRQH },
{ Genode::Board_base::GPIO7_MMIO_BASE, Genode::Board_base::GPIO7_MMIO_SIZE,
Genode::Board_base::GPIO7_IRQL, Genode::Board_base::GPIO7_IRQH }
};
Imx53_driver& Imx53_driver::factory()
Imx53_driver &Imx53_driver::factory(Server::Entrypoint &ep)
{
static Imx53_driver driver;
static Imx53_driver driver(ep);
return driver;
}
void Imx53_driver::Gpio_bank::handle_irq()
{
Genode::Lock::Guard lock_guard(_lock);
unsigned long status = _reg.read<Gpio_reg::Int_stat>();
for(unsigned i = 0; i < MAX_PINS; i++) {
if ((status & (1 << i)) && _irq_enabled[i] &&
_sig_cap[i].valid())
Genode::Signal_transmitter(_sig_cap[i]).submit();
}
_reg.write<Gpio_reg::Int_stat>(0xffffffff);
}
#endif /* _DRIVER_H_ */

View File

@ -8,7 +8,7 @@
/*
* Copyright (C) 2012 Ksys Labs LLC
* Copyright (C) 2012-2013 Genode Labs GmbH
* Copyright (C) 2012-2015 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.
@ -20,35 +20,46 @@
#include <cap_session/connection.h>
#include <gpio/component.h>
#include <gpio/config.h>
#include <os/server.h>
/* local includes */
#include <driver.h>
int main(int, char **)
struct Main
{
using namespace Genode;
Server::Entrypoint &ep;
Genode::Sliced_heap sliced_heap;
Imx53_driver &driver;
Gpio::Root root;
printf("--- i.MX53 gpio driver ---\n");
Main(Server::Entrypoint &ep)
:
ep(ep),
sliced_heap(Genode::env()->ram_session(), Genode::env()->rm_session()),
driver(Imx53_driver::factory(ep)),
root(&ep.rpc_ep(), &sliced_heap, driver)
{
using namespace Genode;
Imx53_driver &driver = Imx53_driver::factory();
Gpio::process_config(driver);
printf("--- i.MX53 gpio driver ---\n");
/*
* Initialize server entry point
*/
enum { STACK_SIZE = 4096 };
static Cap_connection cap;
Sliced_heap sliced_heap(env()->ram_session(), env()->rm_session());
static Rpc_entrypoint ep(&cap, STACK_SIZE, "gpio_ep");
static Gpio::Root gpio_root(&ep, &sliced_heap, driver);
Gpio::process_config(driver);
/*
* Announce service
*/
env()->parent()->announce(ep.manage(&gpio_root));
/*
* Announce service
*/
env()->parent()->announce(ep.manage(root));
}
};
Genode::sleep_forever();
return 0;
/************
** Server **
************/
namespace Server {
char const *name() { return "gpio_drv_ep"; }
size_t stack_size() { return 1024*sizeof(long); }
void construct(Entrypoint &ep) { static Main server(ep); }
}

View File

@ -1,7 +1,7 @@
TARGET = gpio_drv
REQUIRES = imx53
SRC_CC = main.cc
LIBS = base config
LIBS = base config server
INC_DIR += $(PRG_DIR)
vpath main.cc $(PRG_DIR)

View File

@ -33,6 +33,7 @@ class Omap4_driver : public Gpio::Driver
private:
enum {
PIN_SHIFT = 5,
MAX_BANKS = 6,
MAX_PINS = 32
};
@ -47,44 +48,45 @@ class Omap4_driver : public Gpio::Driver
} _delayer;
class Gpio_bank : public Genode::Thread<4096>
class Gpio_bank
{
private:
Gpio_reg _reg;
Genode::Irq_connection _irq;
Genode::Signal_context_capability _sig_cap[MAX_PINS];
bool _irq_enabled[MAX_PINS];
Gpio_reg _reg;
Genode::Irq_connection _irq;
Genode::Signal_rpc_member<Gpio_bank> _dispatcher;
Genode::Signal_context_capability _sig_cap[MAX_PINS];
bool _irq_enabled[MAX_PINS];
void _handle(unsigned)
{
_reg.write<Gpio_reg::Irqstatus_0>(0xffffffff);
unsigned long status = _reg.read<Gpio_reg::Irqstatus_0>();
for(unsigned i = 0; i < MAX_PINS; i++) {
if ((status & (1 << i)) && _irq_enabled[i] &&
_sig_cap[i].valid())
Genode::Signal_transmitter(_sig_cap[i]).submit();
}
_irq.ack_irq();
}
public:
Gpio_bank(Genode::addr_t base, Genode::size_t size,
Gpio_bank(Server::Entrypoint &ep,
Genode::addr_t base, Genode::size_t size,
unsigned irq)
: Genode::Thread<4096>("irq handler"),
_reg(base, size), _irq(irq)
: _reg(base, size), _irq(irq),
_dispatcher(ep, *this, &Gpio_bank::_handle)
{
for (unsigned i = 0; i < MAX_PINS; i++)
_irq_enabled[i] = false;
start();
}
void entry()
{
unsigned long status;
while (true) {
_reg.write<Gpio_reg::Irqstatus_0>(0xffffffff);
_irq.wait_for_irq();
status = _reg.read<Gpio_reg::Irqstatus_0>();
for(unsigned i = 0; i < MAX_PINS; i++) {
if ((status & (1 << i)) && _irq_enabled[i] &&
_sig_cap[i].valid())
Genode::Signal_transmitter(_sig_cap[i]).submit();
}
}
_irq.sigh(_dispatcher);
_irq.ack_irq();
}
Gpio_reg* regs() { return &_reg; }
@ -100,28 +102,71 @@ class Omap4_driver : public Gpio::Driver
_irq_enabled[pin] = enable;
}
void ack_irq(int pin) { PDBG("not implemented"); }
void sigh(int pin, Genode::Signal_context_capability cap) {
_sig_cap[pin] = cap; }
};
Server::Entrypoint &_ep;
static Gpio_bank _gpio_bank[MAX_BANKS];
Gpio_bank _gpio_bank_0;
Gpio_bank _gpio_bank_1;
Gpio_bank _gpio_bank_2;
Gpio_bank _gpio_bank_3;
Gpio_bank _gpio_bank_4;
Gpio_bank _gpio_bank_5;
Gpio_bank *_gpio_bank(int gpio)
{
switch (gpio >> PIN_SHIFT) {
case 0:
return &_gpio_bank_0;
case 1:
return &_gpio_bank_1;
case 2:
return &_gpio_bank_2;
case 3:
return &_gpio_bank_3;
case 4:
return &_gpio_bank_4;
case 5:
return &_gpio_bank_5;
}
PERR("no Gpio_bank for pin %d available", gpio);
return 0;
}
int _gpio_bank_index(int gpio) { return gpio >> 5; }
int _gpio_index(int gpio) { return gpio & 0x1f; }
Omap4_driver()
Omap4_driver(Server::Entrypoint &ep)
:
_ep(ep),
_gpio_bank_0(_ep, Genode::Board_base::GPIO1_MMIO_BASE, Genode::Board_base::GPIO1_MMIO_SIZE,
Genode::Board_base::GPIO1_IRQ),
_gpio_bank_1(_ep, Genode::Board_base::GPIO2_MMIO_BASE, Genode::Board_base::GPIO2_MMIO_SIZE,
Genode::Board_base::GPIO2_IRQ),
_gpio_bank_2(_ep, Genode::Board_base::GPIO3_MMIO_BASE, Genode::Board_base::GPIO3_MMIO_SIZE,
Genode::Board_base::GPIO3_IRQ),
_gpio_bank_3(_ep, Genode::Board_base::GPIO4_MMIO_BASE, Genode::Board_base::GPIO4_MMIO_SIZE,
Genode::Board_base::GPIO4_IRQ),
_gpio_bank_4(_ep, Genode::Board_base::GPIO5_MMIO_BASE, Genode::Board_base::GPIO5_MMIO_SIZE,
Genode::Board_base::GPIO5_IRQ),
_gpio_bank_5(_ep, Genode::Board_base::GPIO6_MMIO_BASE, Genode::Board_base::GPIO6_MMIO_SIZE,
Genode::Board_base::GPIO6_IRQ)
{
for (int i = 0; i < MAX_BANKS; ++i) {
if (verbose)
PDBG("GPIO%d ctrl=%08x",
i+1, _gpio_bank[i].regs()->read<Gpio_reg::Ctrl>());
i+1, _gpio_bank(i << PIN_SHIFT)->regs()->read<Gpio_reg::Ctrl>());
}
}
public:
static Omap4_driver& factory();
static Omap4_driver& factory(Server::Entrypoint &ep);
/******************************
@ -132,7 +177,7 @@ class Omap4_driver : public Gpio::Driver
{
if (verbose) PDBG("gpio=%d input=%d", gpio, input);
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs();
Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
gpio_reg->write<Gpio_reg::Oe>(input ? 1 : 0, _gpio_index(gpio));
}
@ -140,7 +185,7 @@ class Omap4_driver : public Gpio::Driver
{
if (verbose) PDBG("gpio=%d level=%d", gpio, level);
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs();
Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
if (level)
gpio_reg->write<Gpio_reg::Setdataout>(1 << _gpio_index(gpio));
@ -152,7 +197,7 @@ class Omap4_driver : public Gpio::Driver
{
if (verbose) PDBG("gpio=%d", gpio);
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs();
Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
return gpio_reg->read<Gpio_reg::Datain>(_gpio_index(gpio));
}
@ -160,7 +205,7 @@ class Omap4_driver : public Gpio::Driver
{
if (verbose) PDBG("gpio=%d enable=%d", gpio, enable);
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs();
Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
gpio_reg->write<Gpio_reg::Debounceenable>(enable ? 1 : 0,
_gpio_index(gpio));
}
@ -178,7 +223,7 @@ class Omap4_driver : public Gpio::Driver
else
debounce = (us / 0x1f) - 1;
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs();
Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
gpio_reg->write<Gpio_reg::Debouncingtime::Time>(debounce);
}
@ -186,7 +231,7 @@ class Omap4_driver : public Gpio::Driver
{
if (verbose) PDBG("gpio=%d", gpio);
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs();
Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
gpio_reg->write<Gpio_reg::Leveldetect0> (0, _gpio_index(gpio));
gpio_reg->write<Gpio_reg::Leveldetect1> (0, _gpio_index(gpio));
gpio_reg->write<Gpio_reg::Fallingdetect>(1, _gpio_index(gpio));
@ -197,7 +242,7 @@ class Omap4_driver : public Gpio::Driver
{
if (verbose) PDBG("gpio=%d", gpio);
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs();
Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
gpio_reg->write<Gpio_reg::Leveldetect0> (0, _gpio_index(gpio));
gpio_reg->write<Gpio_reg::Leveldetect1> (0, _gpio_index(gpio));
gpio_reg->write<Gpio_reg::Fallingdetect>(0, _gpio_index(gpio));
@ -208,7 +253,7 @@ class Omap4_driver : public Gpio::Driver
{
if (verbose) PDBG("gpio=%d", gpio);
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs();
Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
gpio_reg->write<Gpio_reg::Leveldetect0> (0, _gpio_index(gpio));
gpio_reg->write<Gpio_reg::Leveldetect1> (1, _gpio_index(gpio));
gpio_reg->write<Gpio_reg::Fallingdetect>(0, _gpio_index(gpio));
@ -219,7 +264,7 @@ class Omap4_driver : public Gpio::Driver
{
if (verbose) PDBG("gpio=%d", gpio);
Gpio_reg *gpio_reg = _gpio_bank[_gpio_bank_index(gpio)].regs();
Gpio_reg *gpio_reg = _gpio_bank(gpio)->regs();
gpio_reg->write<Gpio_reg::Leveldetect0> (1, _gpio_index(gpio));
gpio_reg->write<Gpio_reg::Leveldetect1> (0, _gpio_index(gpio));
gpio_reg->write<Gpio_reg::Fallingdetect>(0, _gpio_index(gpio));
@ -230,7 +275,14 @@ class Omap4_driver : public Gpio::Driver
{
if (verbose) PDBG("gpio=%d enable=%d", gpio, enable);
_gpio_bank[_gpio_bank_index(gpio)].irq(_gpio_index(gpio), enable);
_gpio_bank(gpio)->irq(_gpio_index(gpio), enable);
}
void ack_irq(unsigned gpio)
{
if (verbose) PDBG("gpio=%d", gpio);
_gpio_bank(gpio)->ack_irq(_gpio_index(gpio));
}
void register_signal(unsigned gpio,
@ -238,39 +290,23 @@ class Omap4_driver : public Gpio::Driver
{
if (verbose) PDBG("gpio=%d", gpio);
_gpio_bank[_gpio_bank_index(gpio)].sigh(_gpio_index(gpio), cap); }
_gpio_bank(gpio)->sigh(_gpio_index(gpio), cap); }
void unregister_signal(unsigned gpio)
{
if (verbose) PDBG("gpio=%d", gpio);
Genode::Signal_context_capability cap;
_gpio_bank[_gpio_bank_index(gpio)].sigh(_gpio_index(gpio), cap);
_gpio_bank(gpio)->sigh(_gpio_index(gpio), cap);
}
bool gpio_valid(unsigned gpio) { return gpio < (MAX_PINS*MAX_BANKS); }
};
Omap4_driver::Gpio_bank Omap4_driver::_gpio_bank[Omap4_driver::MAX_BANKS] = {
{ Genode::Board_base::GPIO1_MMIO_BASE, Genode::Board_base::GPIO1_MMIO_SIZE,
Genode::Board_base::GPIO1_IRQ },
{ Genode::Board_base::GPIO2_MMIO_BASE, Genode::Board_base::GPIO2_MMIO_SIZE,
Genode::Board_base::GPIO2_IRQ },
{ Genode::Board_base::GPIO3_MMIO_BASE, Genode::Board_base::GPIO3_MMIO_SIZE,
Genode::Board_base::GPIO3_IRQ },
{ Genode::Board_base::GPIO4_MMIO_BASE, Genode::Board_base::GPIO4_MMIO_SIZE,
Genode::Board_base::GPIO4_IRQ },
{ Genode::Board_base::GPIO5_MMIO_BASE, Genode::Board_base::GPIO5_MMIO_SIZE,
Genode::Board_base::GPIO5_IRQ },
{ Genode::Board_base::GPIO6_MMIO_BASE, Genode::Board_base::GPIO6_MMIO_SIZE,
Genode::Board_base::GPIO6_IRQ },
};
Omap4_driver& Omap4_driver::factory()
Omap4_driver& Omap4_driver::factory(Server::Entrypoint &ep)
{
static Omap4_driver driver;
static Omap4_driver driver(ep);
return driver;
}

View File

@ -7,7 +7,7 @@
/*
* Copyright (C) 2012 Ksys Labs LLC
* Copyright (C) 2012-2013 Genode Labs GmbH
* Copyright (C) 2012-2015 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.
@ -19,35 +19,45 @@
#include <cap_session/connection.h>
#include <gpio/component.h>
#include <gpio/config.h>
#include <os/server.h>
/* local includes */
#include <driver.h>
int main(int, char **)
struct Main
{
using namespace Genode;
Server::Entrypoint &ep;
Genode::Sliced_heap sliced_heap;
Omap4_driver &driver;
Gpio::Root root;
printf("--- omap4 gpio driver ---\n");
Main(Server::Entrypoint &ep)
:
ep(ep),
sliced_heap(Genode::env()->ram_session(), Genode::env()->rm_session()),
driver(Omap4_driver::factory(ep)),
root(&ep.rpc_ep(), &sliced_heap, driver)
{
using namespace Genode;
Omap4_driver &driver = Omap4_driver::factory();
Gpio::process_config(driver);
printf("--- omap4 gpio driver ---\n");
/*
* Initialize server entry point
*/
enum { STACK_SIZE = 4096 };
static Cap_connection cap;
Sliced_heap sliced_heap(env()->ram_session(), env()->rm_session());
static Rpc_entrypoint ep(&cap, STACK_SIZE, "gpio_ep");
static Gpio::Root gpio_root(&ep, &sliced_heap, driver);
Gpio::process_config(driver);
/*
* Announce service
*/
env()->parent()->announce(ep.manage(&gpio_root));
/*
* Announce service
*/
env()->parent()->announce(ep.manage(root));
}
};
Genode::sleep_forever();
return 0;
/************
** Server **
************/
namespace Server {
char const *name() { return "gpio_drv_ep"; }
size_t stack_size() { return 1024*sizeof(long); }
void construct(Entrypoint &ep) { static Main server(ep); }
}

View File

@ -1,7 +1,7 @@
TARGET = gpio_drv
REQUIRES = omap4
SRC_CC = main.cc
LIBS = base config
LIBS = base config server
INC_DIR += $(PRG_DIR)
vpath main.cc $(PRG_DIR)

View File

@ -6,7 +6,7 @@
*/
/*
* Copyright (C) 2006-2013 Genode Labs GmbH
* Copyright (C) 2006-2015 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.
@ -22,6 +22,7 @@
#include <input_session/input_session.h>
#include <input/event.h>
#include <base/printf.h>
#include <os/server.h>
using namespace Genode;
@ -71,28 +72,33 @@ namespace Input {
}
int main(int argc, char **argv)
struct Main
{
/* create dataspace for event buffer that is shared with the client */
try { ev_ds_cap = env()->ram_session()->alloc(MAX_EVENTS*sizeof(Input::Event)); }
catch (Ram_session::Alloc_failed) {
PERR("Could not allocate dataspace for event buffer");
return 1;
Server::Entrypoint &ep;
Input::Root root;
Main(Server::Entrypoint &ep)
: ep(ep), root(&ep.rpc_ep(), Genode::env()->heap())
{
/* create dataspace for event buffer that is shared with the client */
try { ev_ds_cap = env()->ram_session()->alloc(MAX_EVENTS*sizeof(Input::Event)); }
catch (Ram_session::Alloc_failed) {
PERR("Could not allocate dataspace for event buffer");
throw Genode::Exception();
}
/* tell parent about the service */
env()->parent()->announce(ep.manage(root));
}
};
/* initialize server entry point */
enum { STACK_SIZE = 4096 };
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "input_ep");
/* entry point serving input root interface */
static Input::Root input_root(&ep, env()->heap());
/************
** Server **
************/
/* tell parent about the service */
env()->parent()->announce(ep.manage(&input_root));
/* main's done - go to sleep */
sleep_forever();
return 0;
namespace Server {
char const *name() { return "input_drv_ep"; }
size_t stack_size() { return 1024*sizeof(long); }
void construct(Entrypoint &ep) { static Main server(ep); }
}

View File

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

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
* Copyright (C) 2013-2015 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.
@ -16,7 +16,6 @@
/* Genode includes */
#include <base/env.h>
#include <base/thread.h>
#include <base/signal.h>
#include <gpio_session/connection.h>
@ -29,7 +28,7 @@ namespace Input {
}
class Input::Tablet_driver : Genode::Thread<8192>
class Input::Tablet_driver
{
private:
@ -38,69 +37,66 @@ class Input::Tablet_driver : Genode::Thread<8192>
GPIO_BUTTON = 132,
};
Event_queue &_ev_queue;
Gpio::Connection _gpio_ts;
Gpio::Connection _gpio_bt;
Genode::Signal_receiver _receiver;
Genode::Signal_context _ts_rx;
Genode::Signal_context _bt_rx;
Genode::Signal_context_capability _ts_sig_cap;
Genode::Signal_context_capability _bt_sig_cap;
Touchscreen _touchscreen;
Buttons _buttons;
Event_queue &_ev_queue;
Gpio::Connection _gpio_ts;
Gpio::Connection _gpio_bt;
Genode::Irq_session_client _irq_ts;
Genode::Irq_session_client _irq_bt;
Genode::Signal_rpc_member<Tablet_driver> _ts_dispatcher;
Genode::Signal_rpc_member<Tablet_driver> _bt_dispatcher;
Touchscreen _touchscreen;
Buttons _buttons;
Genode::Signal_context_capability _init_ts_gpio()
void _handle_ts(unsigned)
{
Genode::Signal_context_capability ret = _receiver.manage(&_ts_rx);
_touchscreen.event(_ev_queue);
_irq_ts.ack_irq();
}
void _handle_bt(unsigned)
{
_buttons.event(_ev_queue);
_irq_bt.ack_irq();
}
Tablet_driver(Server::Entrypoint &ep, Event_queue &ev_queue)
:
_ev_queue(ev_queue),
_gpio_ts(GPIO_TOUCH),
_gpio_bt(GPIO_BUTTON),
_irq_ts(_gpio_ts.irq_session(Gpio::Session::LOW_LEVEL)),
_irq_bt(_gpio_bt.irq_session(Gpio::Session::FALLING_EDGE)),
_ts_dispatcher(ep, *this, &Tablet_driver::_handle_ts),
_bt_dispatcher(ep, *this, &Tablet_driver::_handle_bt),
_touchscreen(ep), _buttons(ep)
{
/* GPIO touchscreen handling */
_gpio_ts.direction(Gpio::Session::OUT);
_gpio_ts.write(true);
_gpio_ts.direction(Gpio::Session::IN);
_gpio_ts.irq_sigh(_ts_sig_cap);
_gpio_ts.irq_type(Gpio::Session::LOW_LEVEL);
_gpio_ts.irq_enable(true);
return ret;
}
Genode::Signal_context_capability _init_bt_gpio()
{
Genode::Signal_context_capability ret = _receiver.manage(&_bt_rx);
_irq_ts.sigh(_ts_dispatcher);
_irq_ts.ack_irq();
/* GPIO button handling */
_gpio_bt.direction(Gpio::Session::OUT);
_gpio_bt.write(true);
_gpio_bt.direction(Gpio::Session::IN);
_gpio_bt.irq_sigh(_bt_sig_cap);
_gpio_bt.irq_type(Gpio::Session::FALLING_EDGE);
_gpio_bt.irq_enable(true);
return ret;
}
Tablet_driver(Event_queue &ev_queue)
: Thread("touchscreen_signal_handler"),
_ev_queue(ev_queue),
_gpio_ts(GPIO_TOUCH),
_gpio_bt(GPIO_BUTTON),
_ts_sig_cap(_init_ts_gpio()),
_bt_sig_cap(_init_bt_gpio()) { start(); }
_irq_bt.sigh(_bt_dispatcher);
_irq_bt.ack_irq();
}
public:
static Tablet_driver* factory(Event_queue &ev_queue);
void entry()
{
while (true) {
Genode::Signal sig = _receiver.wait_for_signal();
if (sig.context() == &_ts_rx)
_touchscreen.event(_ev_queue);
else if (sig.context() == &_bt_rx)
_buttons.event(_ev_queue);
}
}
static Tablet_driver* factory(Server::Entrypoint &ep, Event_queue &ev_queue);
};
Input::Tablet_driver* Input::Tablet_driver::factory(Event_queue &ev_queue)
Input::Tablet_driver* Input::Tablet_driver::factory(Server::Entrypoint &ep,
Event_queue &ev_queue)
{
static Input::Tablet_driver driver(ev_queue);
static Input::Tablet_driver driver(ep, ev_queue);
return &driver;
}

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
* Copyright (C) 2013-2015 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.
@ -36,6 +36,7 @@ class Input::Touchscreen {
enum I2c_addresses { I2C_ADDR = 0x4 };
enum Finger_state { PRESSED, RELEASED };
Irq_handler _irq_handler;
Genode::Attached_io_mem_dataspace _i2c_ds;
I2c::I2c _i2c;
Genode::uint8_t _buf[10];
@ -43,11 +44,14 @@ class Input::Touchscreen {
public:
Touchscreen() : _i2c_ds(Genode::Board_base::I2C_3_BASE,
Genode::Board_base::I2C_3_SIZE),
_i2c((Genode::addr_t)_i2c_ds.local_addr<void>(),
Genode::Board_base::I2C_3_IRQ),
_state(RELEASED)
Touchscreen(Server::Entrypoint &ep)
:
_irq_handler(ep, Genode::Board_base::I2C_3_IRQ),
_i2c_ds(Genode::Board_base::I2C_3_BASE,
Genode::Board_base::I2C_3_SIZE),
_i2c((Genode::addr_t)_i2c_ds.local_addr<void>(),
_irq_handler),
_state(RELEASED)
{
/* ask for touchscreen firmware version */
Genode::uint8_t cmd[10] = { 0x03, 0x03, 0xa, 0x01, 0x41 };

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
* Copyright (C) 2013-2015 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.
@ -17,7 +17,9 @@
/* Genode includes */
#include <util/mmio.h>
#include <timer_session/connection.h>
#include <irq_session/connection.h>
/* local includes */
#include "irq_handler.h"
namespace I2c
{
@ -61,11 +63,10 @@ class I2c::I2c : Genode::Mmio
class No_ack : Genode::Exception {};
class No_irq : Genode::Exception {};
Timer::Connection _timer;
Genode::Irq_connection _irq;
Timer::Connection _timer;
Irq_handler &_irq_handler;
void _busy() { while (!read<Status::Busy>()); }
@ -101,15 +102,19 @@ class I2c::I2c : Genode::Mmio
{
write<Data>(value);
_irq.wait_for_irq();
if (!read<Status::Irq>()) throw No_irq();
do { _irq_handler.wait(); }
while (!read<Status::Irq>());
write<Status::Irq>(0);
if (read<Status::Rcv_ack>()) throw No_ack();
_irq_handler.ack();
}
public:
I2c(Genode::addr_t const base, unsigned irq) : Mmio(base), _irq(irq)
I2c(Genode::addr_t const base, Irq_handler &irq_handler)
: Mmio(base), _irq_handler(irq_handler)
{
write<Control>(0);
write<Status>(0);
@ -128,9 +133,7 @@ class I2c::I2c : Genode::Mmio
_stop();
return;
} catch(No_ack) {
} catch(No_irq) {
}
} catch(No_ack) { }
_stop();
}
}
@ -150,8 +153,9 @@ class I2c::I2c : Genode::Mmio
for (Genode::size_t i = 0; i < num; i++) {
_irq.wait_for_irq();
if (!read<Status::Irq>()) throw No_irq();
do { _irq_handler.wait(); }
while (!read<Status::Irq>());
write<Status::Irq>(0);
if (i == num-1) {
@ -167,8 +171,7 @@ class I2c::I2c : Genode::Mmio
_stop();
return;
} catch(No_irq) {
}
} catch(No_ack) { }
_stop();
}
}

View File

@ -0,0 +1,48 @@
/*
* \brief Input-interrupt handler
* \author Josef Soentgen
* \date 2015-04-08
*/
/*
* Copyright (C) 2015 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _IRQ_HANDLER_H_
#define _IRQ_HANDLER_H_
/* Genode includes */
#include <irq_session/connection.h>
#include <os/server.h>
class Irq_handler
{
private:
Genode::Irq_connection _irq;
Genode::Signal_receiver _sig_rec;
Genode::Signal_dispatcher<Irq_handler> _dispatcher;
void _handle(unsigned) { }
public:
Irq_handler(Server::Entrypoint &ep, int irq_number)
:
_irq(irq_number),
_dispatcher(_sig_rec, *this, &Irq_handler::_handle)
{
_irq.sigh(_dispatcher);
_irq.ack_irq();
}
void wait() { _sig_rec.wait_for_signal(); }
void ack() { _irq.ack_irq(); }
};
#endif /* _IRQ_HANDLER_H_ */

View File

@ -7,7 +7,7 @@
*/
/*
* Copyright (C) 2006-2013 Genode Labs GmbH
* Copyright (C) 2006-2015 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.
@ -22,40 +22,47 @@
#include <input/component.h>
#include <input/root.h>
#include <base/printf.h>
#include <os/server.h>
/* local includes */
#include <driver.h>
using namespace Genode;
int main(int argc, char **argv)
struct Main
{
/* initialize server entry point */
enum { STACK_SIZE = 4096 };
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "input_ep");
Server::Entrypoint &ep;
static Input::Session_component session;
Input::Session_component session;
Input::Root_component root;
Platform::Connection plat_drv;
switch (plat_drv.revision()) {
case Platform::Session::SMD:
plat_drv.enable(Platform::Session::I2C_2);
plat_drv.enable(Platform::Session::I2C_3);
plat_drv.enable(Platform::Session::BUTTONS);
Input::Tablet_driver::factory(session.event_queue());
break;
default:
PWRN("No input driver available for this board");
Main(Server::Entrypoint &ep)
: ep(ep), root(ep.rpc_ep(), session)
{
Platform::Connection plat_drv;
switch (plat_drv.revision()) {
case Platform::Session::SMD:
plat_drv.enable(Platform::Session::I2C_2);
plat_drv.enable(Platform::Session::I2C_3);
plat_drv.enable(Platform::Session::BUTTONS);
Input::Tablet_driver::factory(ep, session.event_queue());
break;
default:
PWRN("No input driver available for this board");
}
/* tell parent about the service */
env()->parent()->announce(ep.manage(root));
}
};
/* entry point serving input root interface */
static Input::Root_component root(ep, session);
/************
** Server **
************/
/* tell parent about the service */
env()->parent()->announce(ep.manage(&root));
/* main's done - go to sleep */
sleep_forever();
return 0;
namespace Server {
char const *name() { return "input_drv_ep"; }
size_t stack_size() { return 2*1024*sizeof(long); }
void construct(Entrypoint &ep) { static Main server(ep); }
}

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
* Copyright (C) 2013-2015 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.
@ -45,16 +45,19 @@ class Input::Buttons {
POWER = 8,
};
Irq_handler _irq_handler;
Genode::Attached_io_mem_dataspace _i2c_ds;
I2c::I2c _i2c;
Genode::uint8_t _state;
public:
Buttons() : _i2c_ds(Genode::Board_base::I2C_2_BASE,
Buttons(Server::Entrypoint &ep) :
_irq_handler(ep, Genode::Board_base::I2C_2_IRQ),
_i2c_ds(Genode::Board_base::I2C_2_BASE,
Genode::Board_base::I2C_2_SIZE),
_i2c((Genode::addr_t)_i2c_ds.local_addr<void>(),
Genode::Board_base::I2C_2_IRQ),
_irq_handler),
_state(0)
{
static Genode::uint8_t init_cmd[][2] = {

View File

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

View File

@ -14,37 +14,43 @@
#ifndef _IRQ_HANDLER_H_
#define _IRQ_HANDLER_H_
/* Genode includes */
#include <base/thread.h>
#include <irq_session/connection.h>
#include <os/server.h>
/* local includes */
#include "input_driver.h"
class Irq_handler : Genode::Thread<4096>
class Irq_handler
{
private:
Genode::Irq_connection _irq;
Input_driver &_input_driver;
Genode::Irq_connection _irq;
Genode::Signal_rpc_member<Irq_handler> _dispatcher;
Input_driver &_input_driver;
void _handle(unsigned)
{
_irq.ack_irq();
while (_input_driver.event_pending())
_input_driver.handle_event();
}
public:
Irq_handler(int irq_number, Input_driver &input_driver)
Irq_handler(Server::Entrypoint &ep,
int irq_number, Input_driver &input_driver)
:
Thread("irq_handler"),
_irq(irq_number),
_dispatcher(ep, *this, &Irq_handler::_handle),
_input_driver(input_driver)
{
start();
_irq.sigh(_dispatcher);
_irq.ack_irq();
}
void entry()
{
while (1) {
_irq.wait_for_irq();
while (_input_driver.event_pending())
_input_driver.handle_event();
}
}
};
#endif /* _IRQ_HANDLER_H_ */

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2007-2013 Genode Labs GmbH
* Copyright (C) 2007-2015 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.
@ -15,52 +15,52 @@
#define _IRQ_HANDLER_H_
/* Genode includes */
#include <base/thread.h>
#include <irq_session/connection.h>
#include <os/server.h>
/* local includes */
#include "input_driver.h"
#include "serial_interface.h"
class Irq_handler : Genode::Thread<4096>
class Irq_handler
{
private:
Genode::Irq_connection _irq;
Serial_interface *_channel;
Input_driver &_input_driver;
Genode::Irq_connection _irq;
Genode::Signal_rpc_member<Irq_handler> _dispatcher;
Serial_interface *_channel;
Input_driver &_input_driver;
void _handle(unsigned)
{
_irq.ack_irq();
#ifdef __CODEZERO__
/*
* (Re-)enable device interrupt because Codezero tends to
* disable it in its IRQ handler.
*/
_channel->enable_irq();
#endif
/* check for pending PS/2 input */
while (_input_driver.event_pending())
_input_driver.handle_event();
}
public:
Irq_handler(int irq_number, Serial_interface *channel, Input_driver &input_driver)
Irq_handler(Server::Entrypoint &ep,
int irq_number, Serial_interface *channel,
Input_driver &input_driver)
:
Thread("irq_handler"),
_irq(irq_number),
_dispatcher(ep, *this, &Irq_handler::_handle),
_channel(channel),
_input_driver(input_driver)
{
start();
}
void entry()
{
while (1) {
#ifdef __CODEZERO__
/*
* (Re-)enable device interrupt because Codezero tends to
* disable it in its IRQ handler.
*/
_channel->enable_irq();
#endif
/* check for pending PS/2 input */
while (_input_driver.event_pending())
_input_driver.handle_event();
/* block for new PS/2 data */
_irq.wait_for_irq();
}
_irq.sigh(_dispatcher);
_irq.ack_irq();
}
};

View File

@ -18,6 +18,7 @@
#include <input/component.h>
#include <input/root.h>
#include <cap_session/connection.h>
#include <os/server.h>
/* local includes */
#include "ps2_keyboard.h"
@ -28,34 +29,38 @@
using namespace Genode;
int main(int argc, char **argv)
struct Main
{
Pl050 pl050;
Server::Entrypoint &ep;
Serial_interface *kbd = pl050.kbd_interface();
Serial_interface *aux = pl050.aux_interface();
Pl050 pl050;
Input::Session_component session;
Input::Root_component root;
/*
* Initialize server entry point
*/
enum { STACK_SIZE = 4096 };
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "ps2_ep");
Ps2_mouse ps2_mouse;
Ps2_keyboard ps2_keybd;
static Input::Session_component session;
static Input::Root_component root(ep, session);
Irq_handler ps2_mouse_irq;
Irq_handler ps2_keybd_irq;
Ps2_mouse ps2_mouse(*aux, session.event_queue());
Ps2_keyboard ps2_keybd(*kbd, session.event_queue(), true);
Main(Server::Entrypoint &ep)
: ep(ep), root(ep.rpc_ep(), session),
ps2_mouse(*pl050.aux_interface(), session.event_queue()),
ps2_keybd(*pl050.kbd_interface(), session.event_queue(), true),
ps2_mouse_irq(ep, PL050_MOUSE_IRQ, pl050.aux_interface(), ps2_mouse),
ps2_keybd_irq(ep, PL050_KEYBD_IRQ, pl050.kbd_interface(), ps2_keybd)
{
env()->parent()->announce(ep.manage(root));
}
};
Irq_handler ps2_mouse_irq(PL050_MOUSE_IRQ, aux, ps2_mouse);
Irq_handler ps2_keybd_irq(PL050_KEYBD_IRQ, kbd, ps2_keybd);
/*
* Let the entry point serve the input root interface
*/
env()->parent()->announce(ep.manage(&root));
/************
** Server **
************/
Genode::sleep_forever();
return 0;
namespace Server {
char const *name() { return "ps2_drv_ep"; }
size_t stack_size() { return 1024*sizeof(long); }
void construct(Entrypoint &ep) { static Main server(ep); }
}

View File

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

View File

@ -11,13 +11,16 @@
* under the terms of the GNU General Public License version 2.
*/
/* Genode includes */
#include <base/env.h>
#include <base/printf.h>
#include <base/sleep.h>
#include <input/component.h>
#include <input/root.h>
#include <cap_session/connection.h>
#include <os/server.h>
/* local includes */
#include "i8042.h"
#include "ps2_keyboard.h"
#include "ps2_mouse.h"
@ -26,31 +29,39 @@
using namespace Genode;
int main(int argc, char **argv)
struct Main
{
I8042 i8042;
Server::Entrypoint &ep;
Serial_interface *kbd = i8042.kbd_interface();
Serial_interface *aux = i8042.aux_interface();
I8042 i8042;
Input::Session_component session;
Input::Root_component root;
/*
* Initialize server entry point
*/
enum { STACK_SIZE = 4096 };
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "ps2_ep");
Ps2_mouse ps2_mouse;
Ps2_keyboard ps2_keybd;
static Input::Session_component session;
static Input::Root_component root(ep, session);
Irq_handler ps2_mouse_irq;
Irq_handler ps2_keybd_irq;
Ps2_mouse ps2_mouse(*aux, session.event_queue());
Ps2_keyboard ps2_keybd(*kbd, session.event_queue(), i8042.kbd_xlate());
Main(Server::Entrypoint &ep)
: ep(ep), root(ep.rpc_ep(), session),
ps2_mouse(*i8042.aux_interface(), session.event_queue()),
ps2_keybd(*i8042.kbd_interface(), session.event_queue(),
i8042.kbd_xlate()),
ps2_mouse_irq(ep, 12, ps2_mouse),
ps2_keybd_irq(ep, 1, ps2_keybd)
{
env()->parent()->announce(ep.manage(root));
}
};
Irq_handler ps2_mouse_irq(12, ps2_mouse);
Irq_handler ps2_keybd_irq( 1, ps2_keybd);
env()->parent()->announce(ep.manage(&root));
/************
** Server **
************/
Genode::sleep_forever();
return 0;
namespace Server {
char const *name() { return "ps2_drv_ep"; }
size_t stack_size() { return 1024*sizeof(long); }
void construct(Entrypoint &ep) { static Main server(ep); }
}

View File

@ -1,6 +1,6 @@
TARGET = ps2_drv
REQUIRES = x86 ps2
SRC_CC = main.cc
LIBS = base
LIBS = base server
INC_DIR = $(PRG_DIR)/..

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
* Copyright (C) 2015 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.
@ -19,6 +19,7 @@
#include <base/printf.h>
#include <timer_session/connection.h>
#include <block/component.h>
#include <os/server.h>
/* local includes */
#include <dwmmc.h>
@ -54,6 +55,8 @@ class Block::Exynos5_driver : public Block::Driver
};
Server::Entrypoint &_ep;
/* display sub system registers */
Attached_io_mem_dataspace _mmio;
@ -64,10 +67,11 @@ class Block::Exynos5_driver : public Block::Driver
public:
Exynos5_driver(bool use_dma)
Exynos5_driver(Server::Entrypoint &ep, bool use_dma)
:
_ep(ep),
_mmio(MSH_BASE, MSH_SIZE),
_controller((addr_t)_mmio.local_addr<void>(),
_controller(ep, (addr_t)_mmio.local_addr<void>(),
_delayer, use_dma),
_use_dma(use_dma)
{

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
* Copyright (C) 2015 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.
@ -318,7 +318,9 @@ struct Exynos5_msh_controller : private Dwmmc, Sd_card::Host_controller
Delayer &_delayer;
Sd_card::Card_info _card_info;
Genode::Irq_connection _irq;
Genode::Irq_connection _irq;
Genode::Signal_receiver _irq_rec;
Genode::Signal_context _irq_ctx;
Sd_card::Card_info _init()
{
@ -464,10 +466,21 @@ struct Exynos5_msh_controller : private Dwmmc, Sd_card::Host_controller
return true;
}
void _wait_for_irq()
{
/*
* Acknowledge the IRQ first to implicitly activate
* receiving of further IRQ signals on the first usage
* of this method.
*/
_irq.ack_irq();
_irq_rec.wait_for_signal();
}
bool _wait_for_transfer_complete()
{
while (1) {
_irq.wait_for_irq();
_wait_for_irq();
if (read<Rintsts::Data_transfer_over>()) {
write<Rintsts>(~0U);
@ -491,11 +504,13 @@ struct Exynos5_msh_controller : private Dwmmc, Sd_card::Host_controller
}
}
public:
enum { IRQ_NUMBER = Genode::Board_base::SDMMC0_IRQ };
Exynos5_msh_controller(Genode::addr_t const mmio_base, Delayer &delayer,
Exynos5_msh_controller(Server::Entrypoint &ep,
Genode::addr_t const mmio_base, Delayer &delayer,
bool use_dma)
: Dwmmc(mmio_base),
_idmac_desc_ds(Genode::env()->ram_session(),
@ -505,8 +520,10 @@ struct Exynos5_msh_controller : private Dwmmc, Sd_card::Host_controller
_idmac_desc_phys(Genode::Dataspace_client(_idmac_desc_ds.cap()).phys_addr()),
_delayer(delayer), _card_info(_init()), _irq(IRQ_NUMBER)
{
_irq.sigh(_irq_rec.manage(&_irq_ctx));
}
~Exynos5_msh_controller() { _irq_rec.dissolve(&_irq_ctx); }
bool _issue_command(Sd_card::Command_base const &command)
{

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
* Copyright (C) 2015 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.
@ -26,8 +26,12 @@ struct Main
struct Factory : Block::Driver_factory
{
Server::Entrypoint &ep;
Factory(Server::Entrypoint &ep) : ep(ep) { }
Block::Driver *create() {
return new (Genode::env()->heap()) Block::Exynos5_driver(true); }
return new (Genode::env()->heap()) Block::Exynos5_driver(ep, true); }
void destroy(Block::Driver *driver) {
Genode::destroy(Genode::env()->heap(),
@ -38,7 +42,7 @@ struct Main
Block::Root root;
Main(Server::Entrypoint &ep)
: ep(ep), regulator(Regulator::CLK_MMC0),
: ep(ep), factory(ep), regulator(Regulator::CLK_MMC0),
root(ep, Genode::env()->heap(), factory)
{
Genode::printf("--- Arndale eMMC card driver ---\n");

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2012-2013 Genode Labs GmbH
* Copyright (C) 2012-2015 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.
@ -16,6 +16,7 @@
#include <base/printf.h>
#include <timer_session/connection.h>
#include <os/attached_ram_dataspace.h>
#include <os/server.h>
/* local includes */
#include <driver.h>
@ -86,81 +87,93 @@ static void run_benchmark(Block::Driver &driver,
}
int main(int argc, char **argv)
struct Main
{
using namespace Genode;
printf("--- i.MX53 SD card benchmark ---\n");
bool const use_dma = true;
static Block::Imx53_driver driver(use_dma);
static Timer::Connection timer;
long const request_sizes[] = {
512, 1024, 2048, 4096, 8192, 16384, 32768, 64*1024, 128*1024, 0 };
/* total size of communication buffer */
size_t const buffer_size = 10 * 1024 * 1024;
/* allocate read/write buffer */
static Attached_ram_dataspace buffer(env()->ram_session(), buffer_size, Genode::UNCACHED);
char * const buffer_virt = buffer.local_addr<char>();
addr_t const buffer_phys = Dataspace_client(buffer.cap()).phys_addr();
/*
* Benchmark reading from SD card
*/
printf("\n-- reading from SD card --\n");
struct Read : Operation
Main(Server::Entrypoint &ep)
{
void operator () (Block::Driver &driver,
addr_t number, size_t count, addr_t phys, char *virt)
{
Block::Packet_descriptor p;
if (driver.dma_enabled())
driver.read_dma(number, count, phys, p);
else
driver.read(number, count, virt, p);
}
} read_operation;
using namespace Genode;
for (unsigned i = 0; request_sizes[i]; i++) {
run_benchmark(driver, timer, buffer_virt, buffer_phys, buffer_size,
request_sizes[i], read_operation);
printf("--- i.MX53 SD card benchmark ---\n");
bool const use_dma = true;
static Block::Imx53_driver driver(use_dma);
static Timer::Connection timer;
long const request_sizes[] = {
512, 1024, 2048, 4096, 8192, 16384, 32768, 64*1024, 128*1024, 0 };
/* total size of communication buffer */
size_t const buffer_size = 10 * 1024 * 1024;
/* allocate read/write buffer */
static Attached_ram_dataspace buffer(env()->ram_session(), buffer_size, Genode::UNCACHED);
char * const buffer_virt = buffer.local_addr<char>();
addr_t const buffer_phys = Dataspace_client(buffer.cap()).phys_addr();
/*
* Benchmark reading from SD card
*/
printf("\n-- reading from SD card --\n");
struct Read : Operation
{
void operator () (Block::Driver &driver,
addr_t number, size_t count, addr_t phys, char *virt)
{
Block::Packet_descriptor p;
if (driver.dma_enabled())
driver.read_dma(number, count, phys, p);
else
driver.read(number, count, virt, p);
}
} read_operation;
for (unsigned i = 0; request_sizes[i]; i++) {
run_benchmark(driver, timer, buffer_virt, buffer_phys, buffer_size,
request_sizes[i], read_operation);
}
/*
* Benchmark writing to SD card
*
* We write back the content of the buffer, which we just filled during the
* read benchmark. If both read and write succeed, the SD card will retain
* its original content.
*/
printf("\n-- writing to SD card --\n");
struct Write : Operation
{
void operator () (Block::Driver &driver,
addr_t number, size_t count, addr_t phys, char *virt)
{
Block::Packet_descriptor p;
if (driver.dma_enabled())
driver.write_dma(number, count, phys, p);
else
driver.write(number, count, virt, p);
}
} write_operation;
for (unsigned i = 0; request_sizes[i]; i++)
run_benchmark(driver, timer, buffer_virt, buffer_phys, buffer_size,
request_sizes[i], write_operation);
printf("\n--- i.MX53 SD card benchmark finished ---\n");
}
};
/*
* Benchmark writing to SD card
*
* We write back the content of the buffer, which we just filled during the
* read benchmark. If both read and write succeed, the SD card will retain
* its original content.
*/
printf("\n-- writing to SD card --\n");
/************
** Server **
************/
struct Write : Operation
{
void operator () (Block::Driver &driver,
addr_t number, size_t count, addr_t phys, char *virt)
{
Block::Packet_descriptor p;
if (driver.dma_enabled())
driver.write_dma(number, count, phys, p);
else
driver.write(number, count, virt, p);
}
} write_operation;
for (unsigned i = 0; request_sizes[i]; i++)
run_benchmark(driver, timer, buffer_virt, buffer_phys, buffer_size,
request_sizes[i], write_operation);
printf("\n--- i.MX53 SD card benchmark finished ---\n");
sleep_forever();
return 0;
namespace Server {
char const *name() { return "sd_card_bench_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_bench
REQUIRES = imx53
SRC_CC = main.cc
LIBS = base
LIBS = base server
INC_DIR += $(PRG_DIR)/.. $(PRG_DIR)/../..

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2012-2013 Genode Labs GmbH
* Copyright (C) 2012-2015 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.
@ -20,6 +20,7 @@
#include <timer_session/connection.h>
#include <block/component.h>
#include <drivers/board_base.h>
#include <os/server.h>
/* local includes */
#include <esdhcv2.h>

View File

@ -414,11 +414,13 @@ struct Esdhcv2_controller : private Esdhcv2, public Sd_card::Host_controller
BURST_WORDS = 8,
};
Genode::Irq_connection _irq;
Delayer & _delayer;
Sd_card::Card_info _card_info;
bool const _use_dma;
Adma2::Table _adma2_table;
Genode::Irq_connection _irq;
Genode::Signal_receiver _irq_rec;
Genode::Signal_context _irq_ctx;
Delayer & _delayer;
Sd_card::Card_info _card_info;
bool const _use_dma;
Adma2::Table _adma2_table;
/**
* Print 'err' and throw detection-error exception
@ -569,6 +571,20 @@ struct Esdhcv2_controller : private Esdhcv2, public Sd_card::Host_controller
return card_info;
}
/**
* Wait until we received the IRQ signal
*/
void _wait_for_irq()
{
/*
* Acknowledge the IRQ first to implicitly activate
* receiving of further IRQ signals on the first usage
* of this method.
*/
_irq.ack_irq();
_irq_rec.wait_for_signal();
}
/*
* Wait till sending a new command is allowed
*
@ -596,7 +612,7 @@ struct Esdhcv2_controller : private Esdhcv2, public Sd_card::Host_controller
*/
bool _wait_for_cmd_complete()
{
_irq.wait_for_irq();
_wait_for_irq();
if (read<Irqstat>() != Irqstat::Cc::reg_mask()) {
PWRN("received unexpected host signal");
reset_command(_delayer);
@ -634,7 +650,7 @@ struct Esdhcv2_controller : private Esdhcv2, public Sd_card::Host_controller
bool _wait_for_mbc_complete(bool const r)
{
/* wait for a signal */
_irq.wait_for_irq();
_wait_for_irq();
Irqstat::access_t const irq = read<Irqstat>();
/*
@ -741,9 +757,13 @@ struct Esdhcv2_controller : private Esdhcv2, public Sd_card::Host_controller
Esdhcv2_controller(addr_t const mmio_base, unsigned const irq,
Delayer & delayer, bool const use_dma)
:
Esdhcv2(mmio_base), _irq(irq), _delayer(delayer),
_card_info(_init()), _use_dma(use_dma)
{ }
Esdhcv2(mmio_base), _irq(irq),
_delayer(delayer), _card_info(_init()), _use_dma(use_dma)
{
_irq.sigh(_irq_rec.manage(&_irq_ctx));
}
~Esdhcv2_controller() { _irq_rec.dissolve(&_irq_ctx); }
/****************************************

View File

@ -25,6 +25,10 @@ struct Main
struct Factory : Block::Driver_factory
{
Server::Entrypoint &ep;
Factory(Server::Entrypoint &ep) : ep(ep) { }
Block::Driver *create() {
return new (Genode::env()->heap()) Block::Imx53_driver(true); }
@ -36,7 +40,7 @@ struct Main
Block::Root root;
Main(Server::Entrypoint &ep)
: ep(ep), root(ep, Genode::env()->heap(), factory)
: ep(ep), factory(ep), root(ep, Genode::env()->heap(), factory)
{
Genode::printf("--- Imx53 SD card driver ---\n");
@ -54,4 +58,3 @@ namespace Server {
size_t stack_size() { return 2*1024*sizeof(long); }
void construct(Entrypoint &ep) { static Main server(ep); }
}

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2012-2013 Genode Labs GmbH
* Copyright (C) 2012-2015 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.
@ -77,80 +77,92 @@ static void run_benchmark(Block::Driver &driver,
}
int main(int argc, char **argv)
struct Main
{
using namespace Genode;
printf("--- OMAP4 SD card benchmark ---\n");
bool const use_dma = false;
static Block::Omap4_driver driver(use_dma);
static Timer::Connection timer;
long const request_sizes[] = {
512, 1024, 2048, 4096, 8192, 16384, 32768, 64*1024, 128*1024, 0 };
/* total size of communication buffer */
size_t const buffer_size = 10*1024*1024;
/* allocate read/write buffer */
static Attached_ram_dataspace buffer(env()->ram_session(), buffer_size, Genode::UNCACHED);
char * const buffer_virt = buffer.local_addr<char>();
addr_t const buffer_phys = Dataspace_client(buffer.cap()).phys_addr();
/*
* Benchmark reading from SD card
*/
printf("\n-- reading from SD card --\n");
struct Read : Operation
Main(Server::Entrypoint &ep)
{
void operator () (Block::Driver &driver,
addr_t number, size_t count, addr_t phys, char *virt)
using namespace Genode;
printf("--- OMAP4 SD card benchmark ---\n");
bool const use_dma = false;
static Block::Omap4_driver driver(use_dma);
static Timer::Connection timer;
long const request_sizes[] = {
512, 1024, 2048, 4096, 8192, 16384, 32768, 64*1024, 128*1024, 0 };
/* total size of communication buffer */
size_t const buffer_size = 10*1024*1024;
/* allocate read/write buffer */
static Attached_ram_dataspace buffer(env()->ram_session(), buffer_size, Genode::UNCACHED);
char * const buffer_virt = buffer.local_addr<char>();
addr_t const buffer_phys = Dataspace_client(buffer.cap()).phys_addr();
/*
* Benchmark reading from SD card
*/
printf("\n-- reading from SD card --\n");
struct Read : Operation
{
Block::Packet_descriptor p;
if (driver.dma_enabled())
driver.read_dma(number, count, phys, p);
else
driver.read(number, count, virt, p);
}
} read_operation;
void operator () (Block::Driver &driver,
addr_t number, size_t count, addr_t phys, char *virt)
{
Block::Packet_descriptor p;
if (driver.dma_enabled())
driver.read_dma(number, count, phys, p);
else
driver.read(number, count, virt, p);
}
} read_operation;
for (unsigned i = 0; request_sizes[i]; i++)
run_benchmark(driver, timer, buffer_virt, buffer_phys, buffer_size,
request_sizes[i], read_operation);
for (unsigned i = 0; request_sizes[i]; i++)
run_benchmark(driver, timer, buffer_virt, buffer_phys, buffer_size,
request_sizes[i], read_operation);
/*
* Benchmark writing to SD card
*
* We write back the content of the buffer, which we just filled during the
* read benchmark. If both read and write succeed, the SD card will retain
* its original content.
*/
/*
* Benchmark writing to SD card
*
* We write back the content of the buffer, which we just filled during the
* read benchmark. If both read and write succeed, the SD card will retain
* its original content.
*/
printf("\n-- writing to SD card --\n");
printf("\n-- writing to SD card --\n");
struct Write : Operation
{
void operator () (Block::Driver &driver,
addr_t number, size_t count, addr_t phys, char *virt)
struct Write : Operation
{
Block::Packet_descriptor p;
if (driver.dma_enabled())
driver.write_dma(number, count, phys, p);
else
driver.write(number, count, virt, p);
}
} write_operation;
void operator () (Block::Driver &driver,
addr_t number, size_t count, addr_t phys, char *virt)
{
Block::Packet_descriptor p;
if (driver.dma_enabled())
driver.write_dma(number, count, phys, p);
else
driver.write(number, count, virt, p);
}
} write_operation;
for (unsigned i = 0; request_sizes[i]; i++)
run_benchmark(driver, timer, buffer_virt, buffer_phys, buffer_size,
request_sizes[i], write_operation);
for (unsigned i = 0; request_sizes[i]; i++)
run_benchmark(driver, timer, buffer_virt, buffer_phys, buffer_size,
request_sizes[i], write_operation);
printf("\n--- OMAP4 SD card benchmark finished ---\n");
sleep_forever();
return 0;
printf("\n--- OMAP4 SD card benchmark finished ---\n");
}
};
/************
** Server **
************/
namespace Server {
char const *name() { return "sd_card_bench_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_bench
REQUIRES = omap4
SRC_CC = main.cc
LIBS = base
LIBS = base server
INC_DIR += $(PRG_DIR)/.. $(PRG_DIR)/../..

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2012-2013 Genode Labs GmbH
* Copyright (C) 2012-2015 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.
@ -19,6 +19,7 @@
#include <base/printf.h>
#include <timer_session/connection.h>
#include <block/component.h>
#include <os/server.h>
/* local includes */
#include <mmchs.h>

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2012-2013 Genode Labs GmbH
* Copyright (C) 2012-2015 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.
@ -25,6 +25,10 @@ struct Main
struct Factory : Block::Driver_factory
{
Server::Entrypoint &ep;
Factory(Server::Entrypoint &ep) : ep(ep) { }
Block::Driver *create() {
return new (Genode::env()->heap()) Block::Omap4_driver(true); }
@ -36,7 +40,7 @@ struct Main
Block::Root root;
Main(Server::Entrypoint &ep)
: ep(ep), root(ep, Genode::env()->heap(), factory)
: ep(ep), factory(ep), root(ep, Genode::env()->heap(), factory)
{
Genode::printf("--- OMAP4 SD card driver ---\n");
@ -54,4 +58,3 @@ namespace Server {
size_t stack_size() { return 2*1024*sizeof(long); }
void construct(Entrypoint &ep) { static Main server(ep); }
}

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2012-2013 Genode Labs GmbH
* Copyright (C) 2012-2015 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.
@ -500,7 +500,9 @@ struct Omap4_hsmmc_controller : private Mmchs, public Sd_card::Host_controller
Adma_desc::access_t * const _adma_desc;
Genode::addr_t const _adma_desc_phys;
Genode::Irq_connection _irq;
Genode::Irq_connection _irq;
Genode::Signal_receiver _irq_rec;
Genode::Signal_context _irq_ctx;
Sd_card::Card_info _init()
{
@ -729,7 +731,12 @@ struct Omap4_hsmmc_controller : private Mmchs, public Sd_card::Host_controller
* running processes.
*/
for (;;) {
_irq.wait_for_irq();
/*
* We ack the IRQ first to implicitly active receiving
* IRQ signals when entering this loop for the first time.
*/
_irq.ack_irq();
_irq_rec.wait_for_signal();
/* check for transfer completion */
if (read<Stat::Tc>() == 1) {
@ -748,6 +755,7 @@ struct Omap4_hsmmc_controller : private Mmchs, public Sd_card::Host_controller
}
}
public:
enum { IRQ_NUMBER = Genode::Board_base::HSMMC_IRQ };
@ -768,7 +776,11 @@ struct Omap4_hsmmc_controller : private Mmchs, public Sd_card::Host_controller
_adma_desc(_adma_desc_ds.local_addr<Adma_desc::access_t>()),
_adma_desc_phys(Genode::Dataspace_client(_adma_desc_ds.cap()).phys_addr()),
_irq(IRQ_NUMBER)
{ }
{
_irq.sigh(_irq_rec.manage(&_irq_ctx));
}
~Omap4_hsmmc_controller() { _irq_rec.dissolve(&_irq_ctx); }
/****************************************

27
repos/os/src/drivers/timer/hw/platform_timer.h Executable file → Normal file
View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2012-2013 Genode Labs GmbH
* Copyright (C) 2012-2015 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.
@ -16,6 +16,7 @@
/* Genode includes */
#include <irq_session/connection.h>
#include <os/server.h>
/* Local includes */
#include <platform_timer_base.h>
@ -30,10 +31,13 @@ class Platform_timer : public Platform_timer_base,
enum { MAX_TIMER_IRQS_PER_MS = 1 };
unsigned long const _max_timeout_us; /* maximum timeout in microsecs */
unsigned long mutable _curr_time_us; /* accumulate already measured timeouts */
unsigned long mutable _init_value; /* mark last processed timer value */
Genode::Lock mutable _update_curr_time_lock; /* serialize curr_time access */
unsigned long const _max_timeout_us; /* maximum timeout in microsecs */
unsigned long mutable _curr_time_us; /* accumulate already measured timeouts */
unsigned long mutable _init_value; /* mark last processed timer value */
Genode::Lock mutable _update_curr_time_lock; /* serialize curr_time access */
Genode::Signal_receiver _irq_rec;
Genode::Signal_context _irq_ctx;
public:
@ -45,7 +49,12 @@ class Platform_timer : public Platform_timer_base,
Irq_connection(Platform_timer_base::IRQ),
_max_timeout_us(tics_to_us(max_value())),
_curr_time_us(0), _init_value(0)
{ }
{
Irq_connection::sigh(_irq_rec.manage(&_irq_ctx));
Irq_connection::ack_irq();
}
~Platform_timer() { _irq_rec.dissolve(&_irq_ctx); }
/**
* Refresh and return our instance-own "now"-time in microseconds
@ -109,7 +118,11 @@ class Platform_timer : public Platform_timer_base,
/**
* Await the lastly scheduled timeout
*/
void wait_for_timeout(Genode::Thread_base *) { wait_for_irq(); }
void wait_for_timeout(Genode::Thread_base *)
{
_irq_rec.wait_for_signal();
Irq_connection::ack_irq();
}
};
#endif /* _OS__SRC__DRIVERS__TIMER__HW__PLATFORM_TIMER_H_ */

View File

@ -14,12 +14,15 @@
#ifndef _TIMER_ROOT_H_
#define _TIMER_ROOT_H_
/* Genode includes */
#include <util/arg_string.h>
#include <base/printf.h>
#include <base/heap.h>
#include <root/component.h>
#include <cap_session/cap_session.h>
#include <os/server.h>
/* local includes */
#include "timer_session_component.h"
@ -56,12 +59,12 @@ class Timer::Root_component : public Genode::Root_component<Session_component>
* The 'cap' argument is not used by the single-threaded server
* variant.
*/
Root_component(Genode::Rpc_entrypoint *session_ep,
Genode::Allocator *md_alloc,
Genode::Cap_session *cap)
Root_component(Server::Entrypoint &ep,
Genode::Allocator *md_alloc,
Genode::Cap_session *cap)
:
Genode::Root_component<Session_component>(session_ep, md_alloc),
_timeout_scheduler(&_platform_timer, session_ep)
Genode::Root_component<Session_component>(&ep.rpc_ep(), md_alloc),
_timeout_scheduler(&_platform_timer, &ep.rpc_ep())
{ }
};

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2009-2013 Genode Labs GmbH
* Copyright (C) 2009-2015 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.
@ -14,8 +14,9 @@
#ifndef _PLATFORM_TIMER_H_
#define _PLATFORM_TIMER_H_
/* Genode inludes **/
/* Genode inludes */
#include <base/thread.h>
#include <os/server.h>
class Platform_timer

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2009-2013 Genode Labs GmbH
* Copyright (C) 2009-2015 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.
@ -14,8 +14,10 @@
#ifndef _PLATFORM_TIMER_H_
#define _PLATFORM_TIMER_H_
/* Genode includes */
#include <io_port_session/connection.h>
#include <irq_session/connection.h>
#include <os/server.h>
class Platform_timer
{
@ -64,6 +66,8 @@ class Platform_timer
unsigned long mutable _curr_time_usec;
Genode::uint16_t mutable _counter_init_value;
bool mutable _handled_wrap;
Genode::Signal_receiver _irq_rec;
Genode::Signal_context _irq_ctx;
/**
* Set PIT counter value
@ -111,8 +115,13 @@ class Platform_timer
/* operate PIT in one-shot mode */
_io_port.outb(PIT_CMD_PORT, PIT_CMD_SELECT_CHANNEL_0 |
PIT_CMD_ACCESS_LO_HI | PIT_CMD_MODE_IRQ);
_timer_irq.sigh(_irq_rec.manage(&_irq_ctx));
_timer_irq.ack_irq();
}
~Platform_timer() { _irq_rec.dissolve(&_irq_ctx); }
/**
* Return current time-counter value in microseconds
*
@ -188,7 +197,8 @@ class Platform_timer
*/
void wait_for_timeout(Genode::Thread_base *blocking_thread)
{
_timer_irq.wait_for_irq();
_irq_rec.wait_for_signal();
_timer_irq.ack_irq();
}
};

View File

@ -5,50 +5,52 @@
*/
/*
* Copyright (C) 2006-2013 Genode Labs GmbH
* Copyright (C) 2006-2015 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 <base/env.h>
#include <base/sleep.h>
#include <base/heap.h>
#include <cap_session/connection.h>
#include <os/server.h>
/* local includes */
#include "timer_root.h"
using namespace Genode;
using namespace Timer;
/**
* Main program
*/
int main(int argc, char **argv)
struct Main
{
/*
* Initialize server entry point that serves the root interface.
*/
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "timer_ep");
Server::Entrypoint &ep;
Sliced_heap sliced_heap;
Timer::Root_component root;
/*
* Use sliced heap to allocate each session component at a separate
* dataspace.
*/
static Sliced_heap sliced_heap(env()->ram_session(), env()->rm_session());
Main(Server::Entrypoint &ep)
:
ep(ep),
sliced_heap(Genode::env()->ram_session(), Genode::env()->rm_session()),
root(ep, &sliced_heap, 0)
{
/*
* Announce timer service at our parent.
*/
env()->parent()->announce(ep.manage(root));
}
};
/*
* Create root interface for timer service
*/
static Timer::Root_component timer_root(&ep, &sliced_heap, &cap);
/*
* Announce timer service at our parent.
*/
env()->parent()->announce(ep.manage(&timer_root));
/************
** Server **
************/
sleep_forever();
return 0;
namespace Server {
char const *name() { return "timer_drv_ep"; }
size_t stack_size() { return 1024*sizeof(long); }
void construct(Entrypoint &ep) { static Main server(ep); }
}

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2014-2014 Genode Labs GmbH
* Copyright (C) 2014-2015 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.
@ -14,7 +14,9 @@
#ifndef _PLATFORM_TIMER_H_
#define _PLATFORM_TIMER_H_
/* Genode includes */
#include <os/attached_rom_dataspace.h>
#include <os/server.h>
#include <trace/timestamp.h>
class Platform_timer

View File

@ -6,7 +6,7 @@
/*
* Copyright (C) 2012 Ksys Labs LLC
* Copyright (C) 2012-2013 Genode Labs GmbH
* Copyright (C) 2012-2015 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.
@ -15,10 +15,12 @@
#ifndef _GPIO_TEST_H_
#define _GPIO_TEST_H_
#include <gpio_session/connection.h>
#include <base/signal.h>
#include <util/mmio.h>
/* Genode includes */
#include <base/printf.h>
#include <base/signal.h>
#include <gpio_session/connection.h>
#include <irq_session/client.h>
#include <util/mmio.h>
using namespace Genode;
@ -63,7 +65,6 @@ Gpio_test::Gpio_test()
{
/* initialize GPIO_121 */
_gpio_button.debouncing(31*100);
_gpio_button.irq_sigh(sig_rec.manage(&sig_ctx));
}
@ -102,35 +103,49 @@ bool Gpio_test::irq_test()
{
printf("---------- IRQ test ----------\n");
_gpio_button.irq_type(Gpio::Session::FALLING_EDGE);
_gpio_button.irq_enable(true);
{
Genode::Irq_session_client
irq(_gpio_button.irq_session(Gpio::Session::FALLING_EDGE));
irq.sigh(sig_rec.manage(&sig_ctx));
/*
* Before any IRQs will be delivered to us, we have to signalize
* that we are ready to handle them by calling 'ack_irq()'.
*/
irq.ack_irq();
_gpio_led1.write(true);
_gpio_led2.write(false);
_gpio_led1.write(true);
_gpio_led2.write(false);
printf("\nPush and hold button...\n");
printf("\nPush and hold button...\n");
wait_for_signal();
_gpio_button.irq_enable(false);
wait_for_signal();
irq.ack_irq();
}
printf("OK\n");
_gpio_button.irq_type(Gpio::Session::RISING_EDGE);
_gpio_button.irq_enable(true);
{
Genode::Irq_session_client
irq(_gpio_button.irq_session(Gpio::Session::RISING_EDGE));
irq.sigh(sig_rec.manage(&sig_ctx));
_gpio_led1.write(false);
_gpio_led2.write(true);
_gpio_led1.write(false);
_gpio_led2.write(true);
printf("\nRelease button...\n");
printf("\nRelease button...\n");
wait_for_signal();
_gpio_button.irq_enable(false);
wait_for_signal();
irq.ack_irq();
}
printf("OK\n");
_gpio_button.irq_type(Gpio::Session::HIGH_LEVEL);
{
Genode::Irq_session_client
irq(_gpio_button.irq_session(Gpio::Session::HIGH_LEVEL));
irq.sigh(sig_rec.manage(&sig_ctx));
}
return true;
}