pci: provide io_ports via device interface

Issue #1487
This commit is contained in:
Alexander Boettcher 2015-04-17 13:40:32 +02:00 committed by Christian Helmuth
parent 4e99925c7c
commit 1006571c85
7 changed files with 112 additions and 7 deletions

View File

@ -50,6 +50,9 @@ struct Pci::Device_client : public Genode::Rpc_client<Device>
Genode::Irq_session_capability irq(Genode::uint8_t id) override {
return call<Rpc_irq>(id); }
Genode::Io_port_session_capability io_port(Genode::uint8_t id) override {
return call<Rpc_io_port>(id); }
};
#endif /* _INCLUDE__PCI_DEVICE__CLIENT_H_ */

View File

@ -18,6 +18,7 @@
#include <base/signal.h>
#include <base/exception.h>
#include <io_mem_session/io_mem_session.h>
#include <io_port_session/capability.h>
#include <irq_session/capability.h>
#include <ram_session/ram_session.h>
@ -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_bus_address,
Genode::Meta::Type_tuple<Rpc_vendor_id,
Genode::Meta::Type_tuple<Rpc_device_id,
Genode::Meta::Type_tuple<Rpc_class_code,
Genode::Meta::Type_tuple<Rpc_resource,
Genode::Meta::Type_tuple<Rpc_config_read,
Genode::Meta::Type_tuple<Rpc_config_write,
Genode::Meta::Type_tuple<Rpc_irq,
Genode::Meta::Type_tuple<Rpc_io_port,
Genode::Meta::Empty>
> > > > > > > > Rpc_functions;
};
#endif /* _INCLUDE__PCI_DEVICE__PCI_DEVICE_H_ */

View File

@ -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();
}
};

View File

@ -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();
}

View File

@ -40,6 +40,16 @@ class Pci::Device_component : public Genode::Rpc_object<Pci::Device>,
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<Genode::Io_port_connection, IO_BLOCK_SIZE> _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<Pci::Device>,
_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::Device>,
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<Pci::Device>,
~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<Pci::Device>,
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_ */

View File

@ -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)/..

View File

@ -29,6 +29,7 @@ extern "C" {
}
#include "pci_tree.h"
#include "device.h"
static const bool verbose = false;