parent
e4d663cf41
commit
8743575dcf
|
@ -16,17 +16,28 @@
|
||||||
|
|
||||||
#include <base/rpc.h>
|
#include <base/rpc.h>
|
||||||
#include <base/signal.h>
|
#include <base/signal.h>
|
||||||
|
#include <base/exception.h>
|
||||||
#include <io_mem_session/io_mem_session.h>
|
#include <io_mem_session/io_mem_session.h>
|
||||||
#include <irq_session/capability.h>
|
#include <irq_session/capability.h>
|
||||||
|
#include <ram_session/ram_session.h>
|
||||||
|
|
||||||
/* os includes */
|
/* os includes */
|
||||||
#include <platform/device.h>
|
#include <platform/device.h>
|
||||||
|
|
||||||
|
|
||||||
namespace Pci { struct Device; }
|
namespace Pci { struct Device; }
|
||||||
|
|
||||||
|
|
||||||
struct Pci::Device : Platform::Device
|
struct Pci::Device : Platform::Device
|
||||||
{
|
{
|
||||||
|
/*********************
|
||||||
|
** Exception types **
|
||||||
|
*********************/
|
||||||
|
|
||||||
|
class Alloc_failed : public Genode::Exception { };
|
||||||
|
class Quota_exceeded : public Alloc_failed { };
|
||||||
|
|
||||||
|
|
||||||
class Resource
|
class Resource
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -14,9 +14,11 @@
|
||||||
#ifndef _INCLUDE__PCI_SESSION__CLIENT_H_
|
#ifndef _INCLUDE__PCI_SESSION__CLIENT_H_
|
||||||
#define _INCLUDE__PCI_SESSION__CLIENT_H_
|
#define _INCLUDE__PCI_SESSION__CLIENT_H_
|
||||||
|
|
||||||
#include <pci_session/capability.h>
|
|
||||||
#include <base/rpc_client.h>
|
#include <base/rpc_client.h>
|
||||||
|
|
||||||
|
#include <pci_device/client.h>
|
||||||
|
#include <pci_session/capability.h>
|
||||||
|
|
||||||
namespace Pci { struct Session_client; }
|
namespace Pci { struct Session_client; }
|
||||||
|
|
||||||
|
|
||||||
|
@ -45,6 +47,9 @@ struct Pci::Session_client : public Genode::Rpc_client<Session>
|
||||||
|
|
||||||
void free_dma_buffer(Genode::Ram_dataspace_capability cap) override {
|
void free_dma_buffer(Genode::Ram_dataspace_capability cap) override {
|
||||||
call<Rpc_free_dma_buffer>(cap); }
|
call<Rpc_free_dma_buffer>(cap); }
|
||||||
|
|
||||||
|
Device_capability device(String const &device) override {
|
||||||
|
return call<Rpc_device>(device); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _INCLUDE__PCI_SESSION__CLIENT_H_ */
|
#endif /* _INCLUDE__PCI_SESSION__CLIENT_H_ */
|
||||||
|
|
|
@ -14,13 +14,16 @@
|
||||||
#ifndef _INCLUDE__PCI_SESSION__PCI_SESSION_H_
|
#ifndef _INCLUDE__PCI_SESSION__PCI_SESSION_H_
|
||||||
#define _INCLUDE__PCI_SESSION__PCI_SESSION_H_
|
#define _INCLUDE__PCI_SESSION__PCI_SESSION_H_
|
||||||
|
|
||||||
#include <pci_device/pci_device.h>
|
/* base */
|
||||||
#include <session/session.h>
|
#include <session/session.h>
|
||||||
#include <ram_session/ram_session.h>
|
#include <ram_session/ram_session.h>
|
||||||
|
|
||||||
|
/* os */
|
||||||
|
#include <pci_device/pci_device.h>
|
||||||
|
|
||||||
namespace Pci {
|
namespace Pci {
|
||||||
|
|
||||||
typedef Genode::Capability<Device> Device_capability;
|
typedef Genode::Capability<Pci::Device> Device_capability;
|
||||||
|
|
||||||
struct Session;
|
struct Session;
|
||||||
}
|
}
|
||||||
|
@ -61,9 +64,16 @@ struct Pci::Session : Genode::Session
|
||||||
*/
|
*/
|
||||||
virtual Genode::Io_mem_dataspace_capability config_extended(Device_capability) = 0;
|
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;
|
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;
|
virtual void free_dma_buffer(Genode::Ram_dataspace_capability) = 0;
|
||||||
|
|
||||||
|
|
||||||
/*********************
|
/*********************
|
||||||
** RPC declaration **
|
** RPC declaration **
|
||||||
*********************/
|
*********************/
|
||||||
|
@ -88,10 +99,14 @@ struct Pci::Session : Genode::Session
|
||||||
Genode::size_t);
|
Genode::size_t);
|
||||||
GENODE_RPC(Rpc_free_dma_buffer, void, free_dma_buffer,
|
GENODE_RPC(Rpc_free_dma_buffer, void, free_dma_buffer,
|
||||||
Genode::Ram_dataspace_capability);
|
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,
|
GENODE_RPC_INTERFACE(Rpc_first_device, Rpc_next_device,
|
||||||
Rpc_release_device, Rpc_config_extended,
|
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_ */
|
#endif /* _INCLUDE__PCI_SESSION__PCI_SESSION_H_ */
|
||||||
|
|
|
@ -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 <irq_session/connection.h>
|
||||||
|
#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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -57,6 +57,16 @@ class Pci::Device_component : public Genode::Rpc_object<Pci::Device>,
|
||||||
_ep->manage(&_irq_session);
|
_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
|
* De-constructor
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -14,65 +14,26 @@
|
||||||
#ifndef _PCI_SESSION_COMPONENT_H_
|
#ifndef _PCI_SESSION_COMPONENT_H_
|
||||||
#define _PCI_SESSION_COMPONENT_H_
|
#define _PCI_SESSION_COMPONENT_H_
|
||||||
|
|
||||||
|
/* base */
|
||||||
#include <base/rpc_server.h>
|
#include <base/rpc_server.h>
|
||||||
#include <pci_session/pci_session.h>
|
#include <ram_session/connection.h>
|
||||||
#include <root/component.h>
|
#include <root/component.h>
|
||||||
|
|
||||||
|
/* os */
|
||||||
#include <io_mem_session/connection.h>
|
#include <io_mem_session/connection.h>
|
||||||
|
|
||||||
#include <os/config.h>
|
#include <os/config.h>
|
||||||
|
#include <pci_session/pci_session.h>
|
||||||
|
|
||||||
|
/* local */
|
||||||
#include "pci_device_component.h"
|
#include "pci_device_component.h"
|
||||||
#include "pci_config_access.h"
|
#include "pci_config_access.h"
|
||||||
#include "pci_device_pd_ipc.h"
|
#include "pci_device_pd_ipc.h"
|
||||||
|
|
||||||
namespace Pci {
|
namespace Pci {
|
||||||
|
bool bus_valid(int bus = 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
namespace Pci {
|
||||||
* 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];
|
|
||||||
}
|
|
||||||
|
|
||||||
class Session_component : public Genode::Rpc_object<Session>
|
class Session_component : public Genode::Rpc_object<Session>
|
||||||
{
|
{
|
||||||
|
@ -335,6 +296,8 @@ namespace Pci {
|
||||||
if (ram.valid())
|
if (ram.valid())
|
||||||
_ram->free(ram);
|
_ram->free(ram);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Device_capability device(String const &name) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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];
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
TARGET = pci_drv
|
TARGET = pci_drv
|
||||||
REQUIRES = x86
|
REQUIRES = x86
|
||||||
SRC_CC = main.cc irq.cc
|
SRC_CC = main.cc irq.cc nonpci_devices.cc session.cc
|
||||||
LIBS = base config
|
LIBS = base config
|
||||||
|
|
||||||
INC_DIR = $(PRG_DIR)/..
|
INC_DIR = $(PRG_DIR)/..
|
||||||
|
|
Loading…
Reference in New Issue