usb: use irq via platform driver or directly

Issue #1471
This commit is contained in:
Alexander Boettcher 2015-04-29 14:00:33 +02:00 committed by Christian Helmuth
parent 6dd9d349fc
commit a58bc84d3e
6 changed files with 101 additions and 37 deletions

View File

@ -18,6 +18,7 @@
#include <regulator/consts.h>
#include <regulator_session/connection.h>
#include <timer_session/connection.h>
#include <irq_session/connection.h>
#include <util/mmio.h>
/* Emulation */
@ -363,3 +364,15 @@ void platform_hcd_init(Services *services)
if (services->xhci)
xhci_setup(services);
}
Genode::Irq_session_capability platform_irq_activate(int irq)
{
try {
Genode::Irq_connection conn(irq);
conn.on_destruction(Genode::Irq_connection::KEEP_OPEN);
return conn;
} catch (...) { }
return Genode::Irq_session_capability();
}

View File

@ -17,6 +17,7 @@
#include <drivers/board_base.h>
#include <gpio_session/connection.h>
#include <io_mem_session/connection.h>
#include <irq_session/connection.h>
#include <util/mmio.h>
#include <extern_c_begin.h>
@ -320,3 +321,14 @@ void platform_hcd_init(Services *services)
platform_device_register(pdev);
}
Genode::Irq_session_capability platform_irq_activate(int irq)
{
try {
Genode::Irq_connection conn(irq);
conn.on_destruction(Genode::Irq_connection::KEEP_OPEN);
return conn;
} catch (...) { }
return Genode::Irq_session_capability();
}

View File

@ -13,6 +13,7 @@
/* Genode includes */
#include <io_mem_session/connection.h>
#include <irq_session/connection.h>
#include <util/mmio.h>
#include <platform_session/connection.h>
@ -228,3 +229,15 @@ void platform_hcd_init(Services *services)
platform_device_register(pdev);
}
Genode::Irq_session_capability platform_irq_activate(int irq)
{
try {
Genode::Irq_connection conn(irq);
conn.on_destruction(Genode::Irq_connection::KEEP_OPEN);
return conn;
} catch (...) { }
return Genode::Irq_session_capability();
}

View File

@ -19,6 +19,8 @@
#include <base/printf.h>
#include <os/config.h>
#include <util/xml_node.h>
#include <os/signal_rpc_dispatcher.h>
#include <irq_session/capability.h>
struct Services
{
@ -111,5 +113,6 @@ struct Services
};
void platform_hcd_init(Services *services);
Genode::Irq_session_capability platform_irq_activate(int irq);
#endif /* _PLATFORM_H_ */

View File

@ -11,9 +11,13 @@
* under the terms of the GNU General Public License version 2.
*/
/* Genode inludes */
/* Genode base includes */
#include <ram_session/client.h>
#include <base/object_pool.h>
#include <irq_session/connection.h>
/* Genode os includes */
#include <os/server.h>
#include <pci_session/connection.h>
#include <pci_device/client.h>
@ -29,7 +33,7 @@ struct bus_type pci_bus_type;
/**
* Scan PCI bus and probe for HCDs
*/
class Pci_driver
class Pci_driver : public Genode::List<Pci_driver>::Element
{
private:
@ -53,9 +57,12 @@ class Pci_driver
{
using namespace Pci;
_dev = new (Genode::env()->heap()) pci_dev;
Device_client client(_cap);
uint8_t bus, dev, func;
client.bus_address(&bus, &dev, &func);
_dev = new (Genode::env()->heap()) pci_dev;
_dev->devfn = ((uint16_t)bus << 8) | (0xff & PCI_DEVFN(dev, func));
_dev->vendor = client.vendor_id();
_dev->device = client.device_id();
_dev->class_ = client.class_code();
@ -105,6 +112,8 @@ class Pci_driver
/* enable bus master */
cmd |= 0x4;
client.config_write(CMD, cmd, Device::ACCESS_16BIT);
_drivers().insert(this);
}
/**
@ -135,6 +144,12 @@ class Pci_driver
}
}
static Genode::List<Pci_driver> & _drivers()
{
static Genode::List<Pci_driver> _list;
return _list;
}
public:
Pci_driver(pci_driver *drv, Pci::Device_capability cap,
@ -157,6 +172,8 @@ class Pci_driver
dde_kit_release_io(r->start, (r->end - r->start) + 1);
}
_drivers().remove(this);
destroy(Genode::env()->heap(), _dev);
}
@ -176,8 +193,20 @@ class Pci_driver
Pci::Device_client client(_cap);
client.config_write(devfn, val, _access_size(val));
}
};
static Genode::Irq_session_capability irq_cap(unsigned irq)
{
for (Pci_driver *d = _drivers().first(); d; d = d->next()) {
if (d->_dev && d->_dev->irq != irq)
continue;
Pci::Device_client client(d->_cap);
return client.irq(0);
}
return Genode::Irq_session_capability();
}
};
/********************************
** Backend memory definitions **
@ -401,3 +430,13 @@ void Backend_memory::free(Genode::Ram_dataspace_capability cap)
memory_pool.remove_locked(o);
destroy(env()->heap(), o);
}
/*****************************************
** Platform specific irq cap discovery **
*****************************************/
Genode::Irq_session_capability platform_irq_activate(int irq)
{
return Pci_driver::irq_cap(irq);
}

View File

@ -12,19 +12,17 @@
*/
#include <signal.h>
#include <irq_session/client.h>
#include <extern_c_begin.h>
#include <lx_emul.h>
#include <extern_c_end.h>
extern "C" {
#include <dde_kit/interrupt.h>
}
#include <platform.h>
#include<timer_session/connection.h>
/* our local incarnation of sender and receiver */
static Signal_helper *_signal = 0;
static Genode::Lock _irq_sync(Genode::Lock::LOCKED);
/**
* This contains the Linux-driver handlers
@ -52,6 +50,8 @@ 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_rpc_member<Irq_context> _dispatcher;
Genode::Irq_session_capability _irq_cap;
Genode::Irq_session_client _irq_client;
static Genode::List<Irq_context> *_list()
{
@ -72,26 +72,6 @@ class Irq_context : public Genode::List<Irq_context>::Element
return 0;
}
/* called by the DDE kit upon IRQ */
static void _dde_handler(void *irq)
{
/*
* Make sure there is only one interrupt handled at a time, since dde_kit
* will use one thread per IRQ
*/
static Genode::Lock handler_lock;
Genode::Lock::Guard guard(handler_lock);
Irq_context *ctx = static_cast<Irq_context *>(irq);
/* set context & submit signal */
_signal->sender().context(ctx->_dispatcher);
_signal->sender().submit();
/* wait for interrupt to get acked at device side */
_irq_sync.lock();
}
/**
* Call one IRQ handler
*/
@ -129,8 +109,8 @@ class Irq_context : public Genode::List<Irq_context>::Element
break;
}
/* interrupt should be acked at device now */
_irq_sync.unlock();
/* ack interrupt */
_irq_client.ack_irq();
if (handled)
Routine::schedule_all();
@ -144,14 +124,18 @@ class Irq_context : public Genode::List<Irq_context>::Element
Irq_context(unsigned int irq)
: _irq(irq),
_dispatcher(_signal->ep(), *this, &Irq_context::_handle)
_dispatcher(_signal->ep(), *this, &Irq_context::_handle),
_irq_cap(platform_irq_activate(_irq)),
_irq_client(_irq_cap)
{
/* register at DDE (shared) */
int ret = dde_kit_interrupt_attach(_irq, 0, 0, _dde_handler, this);
if (ret)
PERR("Interrupt attach return %d for IRQ %u", ret, irq);
if (!_irq_cap.valid()) {
PERR("Interrupt %d attach failed", irq);
return;
}
_irq_client.sigh(_dispatcher);
_irq_client.ack_irq();
dde_kit_interrupt_enable(_irq);
_list()->insert(this);
}