mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-11 13:35:27 +00:00
parent
ed8f71e459
commit
92b5dda2bc
@ -16,7 +16,6 @@
|
|||||||
#include <base/log.h>
|
#include <base/log.h>
|
||||||
#include <base/allocator.h>
|
#include <base/allocator.h>
|
||||||
#include <io_mem_session/connection.h>
|
#include <io_mem_session/connection.h>
|
||||||
#include <legacy/x86/platform_session/connection.h>
|
|
||||||
|
|
||||||
/* local includes */
|
/* local includes */
|
||||||
#include "framebuffer.h"
|
#include "framebuffer.h"
|
||||||
@ -263,16 +262,6 @@ int Framebuffer::set_mode(unsigned &width, unsigned &height, unsigned mode)
|
|||||||
void Framebuffer::init(Genode::Env &env, Genode::Allocator &heap)
|
void Framebuffer::init(Genode::Env &env, Genode::Allocator &heap)
|
||||||
{
|
{
|
||||||
local_init_genode_env(env, heap);
|
local_init_genode_env(env, heap);
|
||||||
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Wait until Acpi/Pci driver initialization is done to avoid
|
|
||||||
* potentially concurrent access by this driver and the Acpi/Pci driver
|
|
||||||
* to the graphics device, i.e., to the PCI config space.
|
|
||||||
*/
|
|
||||||
Platform::Connection sync(env);
|
|
||||||
}
|
|
||||||
|
|
||||||
hw_emul_init(env);
|
hw_emul_init(env);
|
||||||
X86emu::init(env, heap);
|
X86emu::init(env, heap);
|
||||||
}
|
}
|
||||||
|
@ -33,8 +33,7 @@ static const bool verbose = false;
|
|||||||
** PCI virtualization **
|
** PCI virtualization **
|
||||||
************************/
|
************************/
|
||||||
|
|
||||||
#include <legacy/x86/platform_session/connection.h>
|
#include <platform_session/device.h>
|
||||||
#include <legacy/x86/platform_device/client.h>
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
PCI_ADDR_REG = 0xcf8,
|
PCI_ADDR_REG = 0xcf8,
|
||||||
@ -42,89 +41,59 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct Devfn
|
|
||||||
{
|
|
||||||
unsigned char b, d, f;
|
|
||||||
|
|
||||||
Devfn(Platform::Device &device) { device.bus_address(&b, &d, &f); }
|
|
||||||
|
|
||||||
Devfn(unsigned short devfn)
|
|
||||||
: b((devfn >> 8) & 0xff), d((devfn >> 3) & 0x1f), f(devfn & 7) { }
|
|
||||||
|
|
||||||
unsigned short devfn() const { return b << 8 | d << 3 | f; }
|
|
||||||
|
|
||||||
void print(Genode::Output &out) const
|
|
||||||
{
|
|
||||||
Genode::print(out, Hex(b, Hex::OMIT_PREFIX, Hex::PAD), ":",
|
|
||||||
Hex(d, Hex::OMIT_PREFIX, Hex::PAD), ".",
|
|
||||||
Hex(f, Hex::OMIT_PREFIX));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class Pci_card
|
class Pci_card
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
enum { BAR_MAX = 6 };
|
||||||
|
|
||||||
Platform::Connection _pci_drv;
|
Platform::Connection _pci_drv;
|
||||||
Platform::Device_client _device;
|
Platform::Device _device { _pci_drv };
|
||||||
Devfn _devfn;
|
unsigned _vendor_device_id { 0 };
|
||||||
|
unsigned _class_code { 0 };
|
||||||
Platform::Device_capability _first_device()
|
uint32_t _bar[BAR_MAX] { 0xffffffff};
|
||||||
{
|
|
||||||
return _pci_drv.with_upgrade([&] () {
|
|
||||||
return _pci_drv.first_device(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
Platform::Device_capability _next_device(Platform::Device_capability prev)
|
|
||||||
{
|
|
||||||
return _pci_drv.with_upgrade([&] () {
|
|
||||||
return _pci_drv.next_device(prev); });
|
|
||||||
}
|
|
||||||
|
|
||||||
Platform::Device_capability _find_vga_card()
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Iterate through all accessible devices.
|
|
||||||
*/
|
|
||||||
Platform::Device_capability prev_device_cap, device_cap;
|
|
||||||
for (device_cap = _first_device();
|
|
||||||
device_cap.valid();
|
|
||||||
device_cap = _next_device(prev_device_cap)) {
|
|
||||||
|
|
||||||
Platform::Device_client device(device_cap);
|
|
||||||
|
|
||||||
if (prev_device_cap.valid())
|
|
||||||
_pci_drv.release_device(prev_device_cap);
|
|
||||||
/*
|
|
||||||
* If the device is an VGA compatible controller with base
|
|
||||||
* class 0x03 and sub class 0x00 stop iteration. (We shift out
|
|
||||||
* the interface bits.)
|
|
||||||
*/
|
|
||||||
if ((device.class_code() >> 8) == 0x0300)
|
|
||||||
break;
|
|
||||||
|
|
||||||
prev_device_cap = device_cap;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!device_cap.valid()) {
|
|
||||||
Genode::error("PCI VGA card not found.");
|
|
||||||
throw Framebuffer::Fatal();
|
|
||||||
}
|
|
||||||
|
|
||||||
return device_cap;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Pci_card(Genode::Env &env)
|
struct Invalid_bar : Exception {};
|
||||||
: _pci_drv(env), _device(_find_vga_card()), _devfn(_device)
|
|
||||||
|
Pci_card(Genode::Env &env) : _pci_drv(env)
|
||||||
{
|
{
|
||||||
Genode::log("Found PCI VGA at ", _devfn);
|
_pci_drv.update();
|
||||||
|
_pci_drv.with_xml([&] (Xml_node node) {
|
||||||
|
node.with_optional_sub_node("device", [&] (Xml_node node) {
|
||||||
|
node.for_each_sub_node("io_mem", [&] (Xml_node node) {
|
||||||
|
unsigned bar = node.attribute_value("pci_bar", 0U);
|
||||||
|
uint32_t addr = node.attribute_value("phys_addr", 0UL);
|
||||||
|
if (bar >= BAR_MAX) throw Invalid_bar();
|
||||||
|
_bar[bar] = addr;
|
||||||
|
});
|
||||||
|
node.for_each_sub_node("io_port_range", [&] (Xml_node node) {
|
||||||
|
unsigned bar = node.attribute_value("pci_bar", 0U);
|
||||||
|
uint32_t addr = node.attribute_value("phys_addr", 0UL);
|
||||||
|
if (bar >= BAR_MAX) throw Invalid_bar();
|
||||||
|
_bar[bar] = addr | 1;
|
||||||
|
});
|
||||||
|
node.with_optional_sub_node("pci-config", [&] (Xml_node node) {
|
||||||
|
unsigned v = node.attribute_value("vendor_id", 0U);
|
||||||
|
unsigned d = node.attribute_value("device_id", 0U);
|
||||||
|
unsigned c = node.attribute_value("class", 0U);
|
||||||
|
unsigned r = node.attribute_value("revision", 0U);
|
||||||
|
_vendor_device_id = v | d << 16;
|
||||||
|
_class_code = r | c << 8;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Platform::Device &device() { return _device; }
|
unsigned vendor_device_id() { return _vendor_device_id; }
|
||||||
unsigned short devfn() const { return _devfn.devfn(); }
|
unsigned class_code() { return _class_code; }
|
||||||
|
|
||||||
|
uint32_t bar(unsigned bar)
|
||||||
|
{
|
||||||
|
if (bar >= BAR_MAX) throw Invalid_bar();
|
||||||
|
return _bar[bar];
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -154,14 +123,6 @@ static bool handle_pci_port_write(unsigned short port, T val)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned const devfn = (val >> 8) & 0xffff;
|
|
||||||
if (devfn != pci_card->devfn()) {
|
|
||||||
if (verbose)
|
|
||||||
warning("accessing unknown PCI device ", Devfn(devfn));
|
|
||||||
pci_cfg_addr_valid = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* remember the configuration address */
|
/* remember the configuration address */
|
||||||
pci_cfg_addr = val & 0xfc;
|
pci_cfg_addr = val & 0xfc;
|
||||||
pci_cfg_addr_valid = true;
|
pci_cfg_addr_valid = true;
|
||||||
@ -208,14 +169,12 @@ static bool handle_pci_port_read(unsigned short port, T *val)
|
|||||||
switch (pci_cfg_addr) {
|
switch (pci_cfg_addr) {
|
||||||
|
|
||||||
case 0: /* vendor / device ID */
|
case 0: /* vendor / device ID */
|
||||||
raw_val = pci_card->device().vendor_id() |
|
raw_val = pci_card->vendor_device_id();
|
||||||
(pci_card->device().device_id() << 16);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4: /* status and command */
|
case 4: /* status and command */
|
||||||
case 8: /* class code / revision ID */
|
case 8: /* class code / revision ID */
|
||||||
raw_val = pci_card->device().config_read(pci_cfg_addr,
|
raw_val = pci_card->class_code();
|
||||||
Platform::Device::ACCESS_32BIT);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x10: /* base address register 0 */
|
case 0x10: /* base address register 0 */
|
||||||
@ -225,15 +184,7 @@ static bool handle_pci_port_read(unsigned short port, T *val)
|
|||||||
case 0x20: /* base address register 4 */
|
case 0x20: /* base address register 4 */
|
||||||
case 0x24: /* base address register 5 */
|
case 0x24: /* base address register 5 */
|
||||||
{
|
{
|
||||||
unsigned bar = (pci_cfg_addr - 0x10) / 4;
|
raw_val = pci_card->bar((pci_cfg_addr-0x10)/4);
|
||||||
Platform::Device::Resource res = pci_card->device().resource(bar);
|
|
||||||
if (res.type() == Platform::Device::Resource::INVALID) {
|
|
||||||
warning("requested PCI resource ", bar, " invalid");
|
|
||||||
*val = 0;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
raw_val = res.bar();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user