From 1006571c855c95602f72ed3f7248a9f1b72419b0 Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Fri, 17 Apr 2015 13:40:32 +0200 Subject: [PATCH] pci: provide io_ports via device interface Issue #1487 --- repos/os/include/pci_device/client.h | 3 ++ repos/os/include/pci_device/pci_device.h | 24 ++++++++++-- repos/os/src/drivers/pci/nonpci_devices.cc | 19 +++++++++- repos/os/src/drivers/pci/pci_device.cc | 38 +++++++++++++++++++ .../os/src/drivers/pci/pci_device_component.h | 32 +++++++++++++++- repos/os/src/drivers/pci/x86/target.mk | 2 +- repos/os/src/lib/dde_kit/pci.cc | 1 + 7 files changed, 112 insertions(+), 7 deletions(-) create mode 100644 repos/os/src/drivers/pci/pci_device.cc diff --git a/repos/os/include/pci_device/client.h b/repos/os/include/pci_device/client.h index 9cf24c298..982c64bba 100644 --- a/repos/os/include/pci_device/client.h +++ b/repos/os/include/pci_device/client.h @@ -50,6 +50,9 @@ struct Pci::Device_client : public Genode::Rpc_client Genode::Irq_session_capability irq(Genode::uint8_t id) override { return call(id); } + + Genode::Io_port_session_capability io_port(Genode::uint8_t id) override { + return call(id); } }; #endif /* _INCLUDE__PCI_DEVICE__CLIENT_H_ */ diff --git a/repos/os/include/pci_device/pci_device.h b/repos/os/include/pci_device/pci_device.h index db3f9ee1f..8e6a0eb26 100644 --- a/repos/os/include/pci_device/pci_device.h +++ b/repos/os/include/pci_device/pci_device.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -165,6 +166,12 @@ struct Pci::Device : Platform::Device virtual void config_write(unsigned char address, unsigned value, Access_size size) = 0; + /** + * Query Io_port of specified bar + * + * \param id index of according PCI resource of the device + */ + virtual Genode::Io_port_session_capability io_port(Genode::uint8_t id) = 0; /* * The base classes are defined as follows: @@ -211,10 +218,21 @@ struct Pci::Device : Platform::Device GENODE_RPC(Rpc_config_write, void, config_write, unsigned char, unsigned, Access_size); GENODE_RPC(Rpc_irq, Genode::Irq_session_capability, irq, Genode::uint8_t); + GENODE_RPC_THROW(Rpc_io_port, Genode::Io_port_session_capability, io_port, + GENODE_TYPE_LIST(Quota_exceeded), + Genode::uint8_t); - GENODE_RPC_INTERFACE(Rpc_bus_address, Rpc_vendor_id, Rpc_device_id, - Rpc_class_code, Rpc_resource, Rpc_config_read, - Rpc_config_write, Rpc_irq); + typedef Genode::Meta::Type_tuple + > > > > > > > > Rpc_functions; }; #endif /* _INCLUDE__PCI_DEVICE__PCI_DEVICE_H_ */ diff --git a/repos/os/src/drivers/pci/nonpci_devices.cc b/repos/os/src/drivers/pci/nonpci_devices.cc index afd27685a..a10461306 100644 --- a/repos/os/src/drivers/pci/nonpci_devices.cc +++ b/repos/os/src/drivers/pci/nonpci_devices.cc @@ -23,16 +23,23 @@ class Nonpci::Ps2 : public Pci::Device_component enum { IRQ_KEYBOARD = 1, IRQ_MOUSE = 12, + + ACCESS_WIDTH = 1, + REG_DATA = 0x60, + REG_STATUS = 0x64, }; Genode::Irq_connection _irq_mouse; + Genode::Io_port_connection _data; + Genode::Io_port_connection _status; public: Ps2(Genode::Rpc_entrypoint * ep, Pci::Session_component * session) : Pci::Device_component(ep, session, IRQ_KEYBOARD), - _irq_mouse(IRQ_MOUSE) + _irq_mouse(IRQ_MOUSE), + _data(REG_DATA, ACCESS_WIDTH), _status(REG_STATUS, ACCESS_WIDTH) { } Genode::Irq_session_capability irq(Genode::uint8_t virt_irq) override @@ -46,6 +53,16 @@ class Nonpci::Ps2 : public Pci::Device_component return Genode::Irq_session_capability(); } } + + Genode::Io_port_session_capability io_port(Genode::uint8_t io_port) override + { + if (io_port == 0) + return _data.cap(); + if (io_port == 1) + return _status.cap(); + + return Genode::Io_port_session_capability(); + } }; diff --git a/repos/os/src/drivers/pci/pci_device.cc b/repos/os/src/drivers/pci/pci_device.cc new file mode 100644 index 000000000..e76e84f27 --- /dev/null +++ b/repos/os/src/drivers/pci/pci_device.cc @@ -0,0 +1,38 @@ +/* + * \brief PCI device component implementation + * \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 "pci_session_component.h" +#include "pci_device_component.h" + +Genode::Io_port_session_capability Pci::Device_component::io_port(Genode::uint8_t v_id) +{ + Genode::uint8_t max = sizeof(_io_port_conn) / sizeof(_io_port_conn[0]); + Genode::uint8_t i = 0, r_id = 0; + + for (Resource res = resource(0); i < max; i++, res = resource(i)) + { + if (res.type() != Resource::IO) + continue; + + if (v_id != r_id) { + r_id ++; + continue; + } + + if (_io_port_conn[v_id] == nullptr) + _io_port_conn[v_id] = new (_slab_ioport) Genode::Io_port_connection(res.base(), res.size()); + + return _io_port_conn[v_id]->cap(); + } + + return Genode::Io_port_session_capability(); +} diff --git a/repos/os/src/drivers/pci/pci_device_component.h b/repos/os/src/drivers/pci/pci_device_component.h index b13496904..8e0a099f7 100644 --- a/repos/os/src/drivers/pci/pci_device_component.h +++ b/repos/os/src/drivers/pci/pci_device_component.h @@ -40,6 +40,16 @@ class Pci::Device_component : public Genode::Rpc_object, Pci::Session_component *_session; Irq_session_component _irq_session; + enum { + IO_BLOCK_SIZE = sizeof(Genode::Io_port_connection) * + Device::NUM_RESOURCES + 32 + 8 * sizeof(void *) + }; + Genode::Tslab _slab_ioport; + Genode::Slab_block _slab_ioport_block; + char _slab_ioport_block_data[IO_BLOCK_SIZE]; + + Genode::Io_port_connection *_io_port_conn [Device::NUM_RESOURCES]; + enum { PCI_IRQ = 0x3c }; public: @@ -54,9 +64,16 @@ class Pci::Device_component : public Genode::Rpc_object, _device_config(device_config), _config_space(addr), _io_mem(0), _ep(ep), _session(session), _irq_session(_device_config.read(&_config_access, PCI_IRQ, - Pci::Device::ACCESS_8BIT)) + Pci::Device::ACCESS_8BIT)), + _slab_ioport(0, &_slab_ioport_block) { _ep->manage(&_irq_session); + + for (unsigned i = 0; i < Device::NUM_RESOURCES; i++) + _io_port_conn[i] = nullptr; + + if (_slab_ioport.num_elem() != Device::NUM_RESOURCES) + PERR("incorrect amount of space for io port resources"); } /** @@ -66,9 +83,13 @@ class Pci::Device_component : public Genode::Rpc_object, Pci::Session_component * session, unsigned irq) : _config_space(~0UL), _io_mem(0), _ep(ep), _session(session), - _irq_session(irq) + _irq_session(irq), + _slab_ioport(0, &_slab_ioport_block) { _ep->manage(&_irq_session); + + for (unsigned i = 0; i < Device::NUM_RESOURCES; i++) + _io_port_conn[i] = nullptr; } /** @@ -77,6 +98,11 @@ class Pci::Device_component : public Genode::Rpc_object, ~Device_component() { _ep->dissolve(&_irq_session); + + for (unsigned i = 0; i < Device::NUM_RESOURCES; i++) { + if (_io_port_conn[i]) + Genode::destroy(_slab_ioport, _io_port_conn[i]); + } } /**************************************** @@ -139,6 +165,8 @@ class Pci::Device_component : public Genode::Rpc_object, return Genode::Irq_session_capability(); return _irq_session.cap(); } + + Genode::Io_port_session_capability io_port(Genode::uint8_t) override; }; #endif /* _PCI_DEVICE_COMPONENT_H_ */ diff --git a/repos/os/src/drivers/pci/x86/target.mk b/repos/os/src/drivers/pci/x86/target.mk index 3988fe787..756fcf9a5 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 nonpci_devices.cc session.cc +SRC_CC = main.cc irq.cc pci_device.cc nonpci_devices.cc session.cc LIBS = base config INC_DIR = $(PRG_DIR)/.. diff --git a/repos/os/src/lib/dde_kit/pci.cc b/repos/os/src/lib/dde_kit/pci.cc index 17420cd56..ea1f0b4d3 100644 --- a/repos/os/src/lib/dde_kit/pci.cc +++ b/repos/os/src/lib/dde_kit/pci.cc @@ -29,6 +29,7 @@ extern "C" { } #include "pci_tree.h" +#include "device.h" static const bool verbose = false;