diff --git a/repos/os/include/pci_device/pci_device.h b/repos/os/include/pci_device/pci_device.h
index 3d76376622..db3f9ee1fe 100644
--- a/repos/os/include/pci_device/pci_device.h
+++ b/repos/os/include/pci_device/pci_device.h
@@ -16,17 +16,28 @@
#include
#include
+#include
#include
#include
+#include
/* os includes */
#include
+
namespace Pci { struct Device; }
struct Pci::Device : Platform::Device
{
+ /*********************
+ ** Exception types **
+ *********************/
+
+ class Alloc_failed : public Genode::Exception { };
+ class Quota_exceeded : public Alloc_failed { };
+
+
class Resource
{
private:
diff --git a/repos/os/include/pci_session/client.h b/repos/os/include/pci_session/client.h
index cfa45ecdf0..d0117fd5ba 100644
--- a/repos/os/include/pci_session/client.h
+++ b/repos/os/include/pci_session/client.h
@@ -14,9 +14,11 @@
#ifndef _INCLUDE__PCI_SESSION__CLIENT_H_
#define _INCLUDE__PCI_SESSION__CLIENT_H_
-#include
#include
+#include
+#include
+
namespace Pci { struct Session_client; }
@@ -45,6 +47,9 @@ struct Pci::Session_client : public Genode::Rpc_client
void free_dma_buffer(Genode::Ram_dataspace_capability cap) override {
call(cap); }
+
+ Device_capability device(String const &device) override {
+ return call(device); }
};
#endif /* _INCLUDE__PCI_SESSION__CLIENT_H_ */
diff --git a/repos/os/include/pci_session/pci_session.h b/repos/os/include/pci_session/pci_session.h
index b6937514d4..3625f1c8a1 100644
--- a/repos/os/include/pci_session/pci_session.h
+++ b/repos/os/include/pci_session/pci_session.h
@@ -14,13 +14,16 @@
#ifndef _INCLUDE__PCI_SESSION__PCI_SESSION_H_
#define _INCLUDE__PCI_SESSION__PCI_SESSION_H_
-#include
+/* base */
#include
#include
+/* os */
+#include
+
namespace Pci {
- typedef Genode::Capability Device_capability;
+ typedef Genode::Capability Device_capability;
struct Session;
}
@@ -61,9 +64,16 @@ struct Pci::Session : Genode::Session
*/
virtual Genode::Io_mem_dataspace_capability config_extended(Device_capability) = 0;
+ typedef Genode::Rpc_in_buffer<8> String;
+
/**
- * Allocate memory suitable for DMA.
+ * Provide non-PCI device known by unique name.
*/
+ virtual Device_capability device(String const &string) = 0;
+
+ /**
+ * Allocate memory suitable for DMA.
+ */
virtual Genode::Ram_dataspace_capability alloc_dma_buffer(Genode::size_t) = 0;
/**
@@ -71,6 +81,7 @@ struct Pci::Session : Genode::Session
*/
virtual void free_dma_buffer(Genode::Ram_dataspace_capability) = 0;
+
/*********************
** RPC declaration **
*********************/
@@ -88,10 +99,14 @@ struct Pci::Session : Genode::Session
Genode::size_t);
GENODE_RPC(Rpc_free_dma_buffer, void, free_dma_buffer,
Genode::Ram_dataspace_capability);
+ GENODE_RPC_THROW(Rpc_device, Device_capability, device,
+ GENODE_TYPE_LIST(Pci::Device::Quota_exceeded),
+ String const &);
GENODE_RPC_INTERFACE(Rpc_first_device, Rpc_next_device,
Rpc_release_device, Rpc_config_extended,
- Rpc_alloc_dma_buffer, Rpc_free_dma_buffer);
+ Rpc_alloc_dma_buffer, Rpc_free_dma_buffer,
+ Rpc_device);
};
#endif /* _INCLUDE__PCI_SESSION__PCI_SESSION_H_ */
diff --git a/repos/os/src/drivers/pci/nonpci_devices.cc b/repos/os/src/drivers/pci/nonpci_devices.cc
new file mode 100644
index 0000000000..938caa285a
--- /dev/null
+++ b/repos/os/src/drivers/pci/nonpci_devices.cc
@@ -0,0 +1,93 @@
+/*
+ * \brief Non PCI devices, e.g. PS2
+ * \author Alexander Boettcher
+ */
+
+/*
+ * 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.
+ */
+
+#include
+#include "pci_session_component.h"
+
+
+namespace Nonpci { class Ps2; }
+
+class Nonpci::Ps2 : public Pci::Device_component
+{
+ private:
+
+ enum {
+ IRQ_KEYBOARD = 1,
+ IRQ_MOUSE = 12,
+ };
+
+ Genode::Irq_connection _irq_mouse;
+
+ public:
+
+ Ps2(Genode::Rpc_entrypoint * ep, Pci::Session_component * session)
+ :
+ Pci::Device_component(ep, IRQ_KEYBOARD),
+ _irq_mouse(IRQ_MOUSE)
+ { }
+
+ Genode::Irq_session_capability irq(Genode::uint8_t virt_irq) override
+ {
+ switch (virt_irq) {
+ case 0:
+ return Device_component::irq(virt_irq);
+ case 1:
+ return _irq_mouse.cap();
+ default:
+ return Genode::Irq_session_capability();
+ }
+ }
+};
+
+
+/**
+ * PCI session component devices which are non PCI devices, e.g. PS2
+ */
+Pci::Device_capability Pci::Session_component::device(String const &name) {
+
+ if (!name.is_valid_string())
+ return Device_capability();
+
+ using namespace Genode;
+
+ char const * device_name = name.string();
+ const char * devices [] = { "PS2" };
+ unsigned devices_i = 0;
+
+ for (; devices_i < sizeof(devices) / sizeof(devices[0]); devices_i++)
+ if (!strcmp(device_name, devices[devices_i]))
+ break;
+
+ if (devices_i >= sizeof(devices) / sizeof(devices[0])) {
+ PERR("unknown '%s' device name", device_name);
+ return Device_capability();
+ }
+
+ try {
+ Device_component * dev = nullptr;
+
+ switch(devices_i) {
+ case 0:
+ dev = new (_md_alloc) Nonpci::Ps2(_ep, this);
+ break;
+ default:
+ return Device_capability();
+ }
+
+ _device_list.insert(dev);
+ return _ep->manage(dev);
+ } catch (Genode::Allocator::Out_of_memory) {
+ throw Pci::Device::Quota_exceeded();
+ } catch (Genode::Parent::Service_denied) {
+ return Device_capability();
+ }
+}
diff --git a/repos/os/src/drivers/pci/pci_device_component.h b/repos/os/src/drivers/pci/pci_device_component.h
index 23f15fdd90..a7b6a62cb4 100644
--- a/repos/os/src/drivers/pci/pci_device_component.h
+++ b/repos/os/src/drivers/pci/pci_device_component.h
@@ -57,6 +57,16 @@ class Pci::Device_component : public Genode::Rpc_object,
_ep->manage(&_irq_session);
}
+ /**
+ * Constructor for non PCI devices
+ */
+ Device_component(Genode::Rpc_entrypoint *ep, unsigned irq)
+ :
+ _config_space(~0UL), _io_mem(0), _ep(ep), _irq_session(irq)
+ {
+ _ep->manage(&_irq_session);
+ }
+
/**
* De-constructor
*/
diff --git a/repos/os/src/drivers/pci/pci_session_component.h b/repos/os/src/drivers/pci/pci_session_component.h
index 9db1e4084d..75a788f884 100644
--- a/repos/os/src/drivers/pci/pci_session_component.h
+++ b/repos/os/src/drivers/pci/pci_session_component.h
@@ -14,65 +14,26 @@
#ifndef _PCI_SESSION_COMPONENT_H_
#define _PCI_SESSION_COMPONENT_H_
+/* base */
#include
-#include
+#include
#include
+/* os */
#include
-
#include
+#include
+/* local */
#include "pci_device_component.h"
#include "pci_config_access.h"
#include "pci_device_pd_ipc.h"
namespace Pci {
+ bool bus_valid(int bus = 0);
+}
- /**
- * Check if given PCI bus was found on initial scan
- *
- * This tremendously speeds up further scans by other drivers.
- */
- bool bus_valid(int bus = 0)
- {
- struct Valid_buses
- {
- bool valid[Device_config::MAX_BUSES];
-
- void scan_bus(Config_access &config_access, int bus = 0)
- {
- for (int dev = 0; dev < Device_config::MAX_DEVICES; ++dev) {
- for (int fun = 0; fun < Device_config::MAX_FUNCTIONS; ++fun) {
-
- /* read config space */
- Device_config config(bus, dev, fun, &config_access);
-
- if (!config.valid())
- continue;
-
- /*
- * There is at least one device on the current bus, so
- * we mark it as valid.
- */
- valid[bus] = true;
-
- /* scan behind bridge */
- if (config.is_pci_bridge()) {
- int sub_bus = config.read(&config_access,
- 0x19, Device::ACCESS_8BIT);
- scan_bus(config_access, sub_bus);
- }
- }
- }
- }
-
- Valid_buses() { Config_access c; scan_bus(c); }
- };
-
- static Valid_buses buses;
-
- return buses.valid[bus];
- }
+namespace Pci {
class Session_component : public Genode::Rpc_object
{
@@ -335,6 +296,8 @@ namespace Pci {
if (ram.valid())
_ram->free(ram);
}
+
+ Device_capability device(String const &name) override;
};
diff --git a/repos/os/src/drivers/pci/session.cc b/repos/os/src/drivers/pci/session.cc
new file mode 100644
index 0000000000..c2e7951c6d
--- /dev/null
+++ b/repos/os/src/drivers/pci/session.cc
@@ -0,0 +1,60 @@
+/*
+ * \brief PCI-session component
+ * \author Norman Feske
+ * \date 2008-01-28
+ */
+
+/*
+ * Copyright (C) 2008-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.
+ */
+
+#include "pci_session_component.h"
+
+/**
+ * Check if given PCI bus was found on initial scan
+ *
+ * This tremendously speeds up further scans by other drivers.
+ */
+bool Pci::bus_valid(int bus)
+{
+ struct Valid_buses
+ {
+ bool valid[Device_config::MAX_BUSES];
+
+ void scan_bus(Config_access &config_access, int bus = 0)
+ {
+ for (int dev = 0; dev < Device_config::MAX_DEVICES; ++dev) {
+ for (int fun = 0; fun < Device_config::MAX_FUNCTIONS; ++fun) {
+
+ /* read config space */
+ Device_config config(bus, dev, fun, &config_access);
+
+ if (!config.valid())
+ continue;
+
+ /*
+ * There is at least one device on the current bus, so
+ * we mark it as valid.
+ */
+ valid[bus] = true;
+
+ /* scan behind bridge */
+ if (config.is_pci_bridge()) {
+ int sub_bus = config.read(&config_access,
+ 0x19, Device::ACCESS_8BIT);
+ scan_bus(config_access, sub_bus);
+ }
+ }
+ }
+ }
+
+ Valid_buses() { Config_access c; scan_bus(c); }
+ };
+
+ static Valid_buses buses;
+
+ return buses.valid[bus];
+}
diff --git a/repos/os/src/drivers/pci/x86/target.mk b/repos/os/src/drivers/pci/x86/target.mk
index b3c3c97e21..3988fe7876 100644
--- a/repos/os/src/drivers/pci/x86/target.mk
+++ b/repos/os/src/drivers/pci/x86/target.mk
@@ -1,6 +1,6 @@
TARGET = pci_drv
REQUIRES = x86
-SRC_CC = main.cc irq.cc
+SRC_CC = main.cc irq.cc nonpci_devices.cc session.cc
LIBS = base config
INC_DIR = $(PRG_DIR)/..