vesa_fb_drv: use generic platform API

Ref genodelabs/genode#4578
This commit is contained in:
Stefan Kalkowski 2022-08-31 13:51:10 +02:00 committed by Christian Helmuth
parent ed8f71e459
commit 92b5dda2bc
2 changed files with 47 additions and 107 deletions

View File

@ -16,7 +16,6 @@
#include <base/log.h>
#include <base/allocator.h>
#include <io_mem_session/connection.h>
#include <legacy/x86/platform_session/connection.h>
/* local includes */
#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)
{
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);
X86emu::init(env, heap);
}

View File

@ -33,8 +33,7 @@ static const bool verbose = false;
** PCI virtualization **
************************/
#include <legacy/x86/platform_session/connection.h>
#include <legacy/x86/platform_device/client.h>
#include <platform_session/device.h>
enum {
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
{
private:
Platform::Connection _pci_drv;
Platform::Device_client _device;
Devfn _devfn;
enum { BAR_MAX = 6 };
Platform::Device_capability _first_device()
{
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;
}
Platform::Connection _pci_drv;
Platform::Device _device { _pci_drv };
unsigned _vendor_device_id { 0 };
unsigned _class_code { 0 };
uint32_t _bar[BAR_MAX] { 0xffffffff};
public:
Pci_card(Genode::Env &env)
: _pci_drv(env), _device(_find_vga_card()), _devfn(_device)
struct Invalid_bar : Exception {};
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 short devfn() const { return _devfn.devfn(); }
unsigned vendor_device_id() { return _vendor_device_id; }
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;
}
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 */
pci_cfg_addr = val & 0xfc;
pci_cfg_addr_valid = true;
@ -208,14 +169,12 @@ static bool handle_pci_port_read(unsigned short port, T *val)
switch (pci_cfg_addr) {
case 0: /* vendor / device ID */
raw_val = pci_card->device().vendor_id() |
(pci_card->device().device_id() << 16);
raw_val = pci_card->vendor_device_id();
break;
case 4: /* status and command */
case 8: /* class code / revision ID */
raw_val = pci_card->device().config_read(pci_cfg_addr,
Platform::Device::ACCESS_32BIT);
raw_val = pci_card->class_code();
break;
case 0x10: /* base address register 0 */
@ -225,16 +184,8 @@ static bool handle_pci_port_read(unsigned short port, T *val)
case 0x20: /* base address register 4 */
case 0x24: /* base address register 5 */
{
unsigned 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;
raw_val = pci_card->bar((pci_cfg_addr-0x10)/4);
break;
}
default: