From e2a23a0ab3ee89e6f991b5d496971d4b601ec787 Mon Sep 17 00:00:00 2001 From: Christian Helmuth Date: Mon, 2 Jan 2017 14:24:00 +0100 Subject: [PATCH] Adapt VESA framebuffer driver to component API Issue #1987 --- .../drivers/framebuffer/vesa/framebuffer.cc | 49 +- .../src/drivers/framebuffer/vesa/hw_emul.cc | 68 ++- .../src/drivers/framebuffer/vesa/ifx86emu.cc | 309 ++++++------- .../framebuffer/vesa/include/framebuffer.h | 17 +- .../framebuffer/vesa/include/genode_env.h | 48 ++ .../framebuffer/vesa/include/hw_emul.h | 7 +- .../framebuffer/vesa/include/ifx86emu.h | 22 +- .../src/drivers/framebuffer/vesa/main.cc | 437 +++++++++--------- .../src/drivers/framebuffer/vesa/target.mk | 4 +- 9 files changed, 491 insertions(+), 470 deletions(-) create mode 100644 repos/libports/src/drivers/framebuffer/vesa/include/genode_env.h diff --git a/repos/libports/src/drivers/framebuffer/vesa/framebuffer.cc b/repos/libports/src/drivers/framebuffer/vesa/framebuffer.cc index c23a81d9cf..0cc8da5464 100644 --- a/repos/libports/src/drivers/framebuffer/vesa/framebuffer.cc +++ b/repos/libports/src/drivers/framebuffer/vesa/framebuffer.cc @@ -6,23 +6,24 @@ */ /* - * Copyright (C) 2007-2013 Genode Labs GmbH + * Copyright (C) 2007-2017 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 -#include -#include +/* Genode includes */ #include -#include #include +#include +/* local includes */ #include "framebuffer.h" #include "ifx86emu.h" +#include "hw_emul.h" #include "vesa.h" #include "vbe.h" +#include "genode_env.h" using namespace Genode; using namespace Vesa; @@ -47,8 +48,8 @@ static inline uint32_t to_phys(uint32_t addr) static uint16_t get_vesa_mode(mb_vbe_ctrl_t *ctrl_info, mb_vbe_mode_t *mode_info, - unsigned long &width, unsigned long &height, - unsigned long depth, bool verbose) + unsigned &width, unsigned &height, unsigned depth, + bool verbose) { bool choose_highest_resolution_mode = ((width == 0) || (height == 0)); @@ -143,25 +144,25 @@ static uint16_t get_vesa_mode(mb_vbe_ctrl_t *ctrl_info, mb_vbe_mode_t *mode_info ** Driver API ** ****************/ -Dataspace_capability Framebuffer_drv::hw_framebuffer() +Dataspace_capability Framebuffer::hw_framebuffer() { return io_mem_cap; } -int Framebuffer_drv::map_io_mem(addr_t base, size_t size, bool write_combined, - void **out_addr, addr_t addr, - Dataspace_capability *out_io_ds) +int Framebuffer::map_io_mem(addr_t base, size_t size, bool write_combined, + void **out_addr, addr_t addr, + Dataspace_capability *out_io_ds) { - Io_mem_connection &io_mem = *new (env()->heap()) - Io_mem_connection(base, size, write_combined); + Io_mem_connection &io_mem = *new (alloc()) + Io_mem_connection(genode_env(), base, size, write_combined); Io_mem_dataspace_capability io_ds = io_mem.dataspace(); if (!io_ds.valid()) return -2; try { - *out_addr = env()->rm_session()->attach(io_ds, size, 0, addr != 0, addr); + *out_addr = genode_env().rm().attach(io_ds, size, 0, addr != 0, addr); } catch (Rm_session::Attach_failed) { return -3; } @@ -175,8 +176,7 @@ int Framebuffer_drv::map_io_mem(addr_t base, size_t size, bool write_combined, } -int Framebuffer_drv::set_mode(unsigned long &width, unsigned long &height, - unsigned long mode) +int Framebuffer::set_mode(unsigned &width, unsigned &height, unsigned mode) { mb_vbe_ctrl_t *ctrl_info; mb_vbe_mode_t *mode_info; @@ -260,10 +260,19 @@ int Framebuffer_drv::set_mode(unsigned long &width, unsigned long &height, ** Driver startup ** ********************/ -int Framebuffer_drv::init() +void Framebuffer::init(Genode::Env &env, Genode::Allocator &heap) { - if (X86emu::init()) - return -1; + local_init_genode_env(env, heap); - return 0; + { + /* + * 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); } diff --git a/repos/libports/src/drivers/framebuffer/vesa/hw_emul.cc b/repos/libports/src/drivers/framebuffer/vesa/hw_emul.cc index da868cdb72..bdd25becf4 100644 --- a/repos/libports/src/drivers/framebuffer/vesa/hw_emul.cc +++ b/repos/libports/src/drivers/framebuffer/vesa/hw_emul.cc @@ -11,16 +11,18 @@ */ /* - * Copyright (C) 2010-2013 Genode Labs GmbH + * Copyright (C) 2010-2017 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 +/* Genode includes */ #include #include +/* local includes */ +#include "framebuffer.h" #include "hw_emul.h" using namespace Genode; @@ -40,24 +42,22 @@ enum { }; -/** - * Helper for the formatted output of a (bus, device, function) triple - */ struct Devfn { - unsigned short devfn; + unsigned char b, d, f; - explicit Devfn(unsigned short devfn) : devfn(devfn) { } + 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 { - unsigned char const bus = devfn >> 8, - dev = (devfn >> 3) & 0x1f, - fn = devfn & 0x7; - - Genode::print(out, Hex(bus, Hex::OMIT_PREFIX, Hex::PAD), ":", - Hex(dev, Hex::OMIT_PREFIX, Hex::PAD), ".", - Hex(fn, Hex::OMIT_PREFIX)); + Genode::print(out, Hex(b, Hex::OMIT_PREFIX, Hex::PAD), ":", + Hex(d, Hex::OMIT_PREFIX, Hex::PAD), ".", + Hex(f, Hex::OMIT_PREFIX)); } }; @@ -68,7 +68,7 @@ class Pci_card Platform::Connection _pci_drv; Platform::Device_client _device; - unsigned short _devfn; + Devfn _devfn; Platform::Device_capability _first_device() { @@ -110,8 +110,8 @@ class Pci_card } if (!device_cap.valid()) { - Genode::error("PCI VGA card not found. Sleeping..."); - sleep_forever(); + Genode::error("PCI VGA card not found."); + throw Framebuffer::Fatal(); } return device_cap; @@ -119,27 +119,18 @@ class Pci_card public: - Pci_card() : _device(_find_vga_card()) + Pci_card(Genode::Env &env) + : _pci_drv(env), _device(_find_vga_card()), _devfn(_device) { - unsigned char bus = 0, dev = 0, fn = 0; - - _device.bus_address(&bus, &dev, &fn); - _devfn = bus << 8 | dev << 3 | fn; - - if (verbose) - Genode::log("Found PCI VGA at ", Devfn(_devfn)); + Genode::log("Found PCI VGA at ", _devfn); } - Platform::Device_client &device() { return _device; } - unsigned short devfn() const { return _devfn; } + Platform::Device &device() { return _device; } + unsigned short devfn() const { return _devfn.devfn(); } }; -static Pci_card *pci_card() -{ - static Pci_card _pci_card; - return &_pci_card; -} +static Constructible pci_card; /** @@ -166,7 +157,7 @@ static bool handle_pci_port_write(unsigned short port, T val) } unsigned const devfn = (val >> 8) & 0xffff; - if (devfn != pci_card()->devfn()) { + if (devfn != pci_card->devfn()) { if (verbose) warning("accessing unknown PCI device ", Devfn(devfn)); pci_cfg_addr_valid = false; @@ -219,13 +210,13 @@ 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->device().vendor_id() | + (pci_card->device().device_id() << 16); break; case 4: /* status and command */ case 8: /* class code / revision ID */ - raw_val = pci_card()->device().config_read(pci_cfg_addr, + raw_val = pci_card->device().config_read(pci_cfg_addr, Platform::Device::ACCESS_32BIT); break; @@ -237,7 +228,7 @@ static bool handle_pci_port_read(unsigned short port, T *val) case 0x24: /* base address register 5 */ { unsigned bar = (pci_cfg_addr - 0x10) / 4; - Platform::Device::Resource res = pci_card()->device().resource(bar); + Platform::Device::Resource res = pci_card->device().resource(bar); if (res.type() == Platform::Device::Resource::INVALID) { warning("requested PCI resource ", bar, " invalid"); *val = 0; @@ -349,3 +340,6 @@ bool hw_emul_handle_port_write(unsigned short port, T val) return false; } + + +void hw_emul_init(Genode::Env &env) { pci_card.construct(env); } diff --git a/repos/libports/src/drivers/framebuffer/vesa/ifx86emu.cc b/repos/libports/src/drivers/framebuffer/vesa/ifx86emu.cc index 7727d5e37e..1dd6633642 100644 --- a/repos/libports/src/drivers/framebuffer/vesa/ifx86emu.cc +++ b/repos/libports/src/drivers/framebuffer/vesa/ifx86emu.cc @@ -6,28 +6,29 @@ */ /* - * Copyright (C) 2007-2013 Genode Labs GmbH + * Copyright (C) 2007-2017 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. */ +/* Genode includes */ #include -#include -#include -#include +#include +#include #include #include -#include - +#include #include -#include -#include +#include /* XXX for emulating X86emu::printk() */ + +/* local includes */ #include "ifx86emu.h" #include "framebuffer.h" #include "vesa.h" #include "hw_emul.h" +#include "genode_env.h" namespace X86emu { @@ -133,163 +134,134 @@ class Region : public Avl_node template -class Region_database : public Avl_tree +struct Region_database : Avl_tree { - public: + Genode::Env &env; + Genode::Allocator &heap; - TYPE * match(addr_t base, size_t size) - { - if (!first()) return 0; + Region_database(Genode::Env &env, Genode::Allocator &heap) + : env(env), heap(heap) { } - return static_cast(first()->match(base, size)); + TYPE * match(addr_t base, size_t size) + { + if (!first()) return 0; + + return static_cast(first()->match(base, size)); + } + + TYPE * meet(addr_t base, size_t size) + { + if (!first()) return 0; + + return static_cast(first()->meet(base, size)); + } + + TYPE * get_region(addr_t base, size_t size) + { + TYPE *region; + + /* look for match and return if found */ + if ((region = match(base, size))) + return region; + + /* + * We try to create a new port region, but first we look if any overlapping + * resp. meeting regions already exist. These are freed and merged into a + * new super region including the new port region. + */ + + addr_t beg = base, end = base + size; + + while ((region = meet(beg, end - beg))) { + /* merge region into super region */ + beg = min(beg, static_cast(region->base())); + end = max(end, static_cast(region->base() + region->size())); + + /* destroy old region */ + remove(region); + destroy(heap, region); } - TYPE * meet(addr_t base, size_t size) - { - if (!first()) return 0; - - return static_cast(first()->meet(base, size)); + try { + region = new (heap) TYPE(env, beg, end - beg); + insert(region); + return region; + } catch (...) { + Genode::error("access to I/O region ", + Hex_range(beg, end - beg), " denied"); + return 0; } + } - TYPE * get_region(addr_t base, size_t size) - { - TYPE *region; + void print_regions() + { + if (!first()) return; - /* look for match and return if found */ - if ((region = match(base, size))) - return region; - - /* - * We try to create a new port region, but first we look if any overlapping - * resp. meeting regions already exist. These are freed and merged into a - * new super region including the new port region. - */ - - addr_t beg = base, end = base + size; - - while ((region = meet(beg, end - beg))) { - /* merge region into super region */ - beg = min(beg, static_cast(region->base())); - end = max(end, static_cast(region->base() + region->size())); - - /* destroy old region */ - remove(region); - destroy(env()->heap(), region); - } - - try { - region = new (env()->heap()) TYPE(beg, end - beg); - insert(region); - return region; - } catch (...) { - Genode::error("access to I/O region ", - Hex_range(beg, end - beg), " denied"); - return 0; - } - } - - void print_regions() - { - if (!first()) return; - - first()->print_regions(); - } + first()->print_regions(); + } }; /** * I/O port region including corresponding IO_PORT connection */ -class Port_region : public Region, public Io_port_connection +struct Port_region : Region, Io_port_connection { - public: + Port_region(Genode::Env &env, unsigned short port_base, size_t port_size) + : + Region(port_base, port_size), + Io_port_connection(env, port_base, port_size) + { + if (verbose) Genode::log("add port ", *this); + } - void print(Genode::Output &out) const - { - unsigned const beg = base(), end = beg + size(); - Genode::print(out, Hex_range(beg, end - beg)); - } + ~Port_region() + { + if (verbose) Genode::log("del port ", *this); + } - Port_region(unsigned short port_base, size_t port_size) - : Region(port_base, port_size), Io_port_connection(port_base, port_size) - { - if (verbose) - Genode::log("add port ", *this); - } - - ~Port_region() - { - if (verbose) - Genode::log("del port ", *this); - } + void print(Genode::Output &out) const + { + unsigned const beg = base(), end = beg + size(); + Genode::print(out, Hex_range(beg, end - beg)); + } }; /** * I/O memory region including corresponding IO_MEM connection */ -class Mem_region : public Region +struct Mem_region : Region, Attached_io_mem_dataspace { - private: + Mem_region(Genode::Env &env, addr_t mem_base, size_t mem_size) + : + Region(mem_base, mem_size), + Attached_io_mem_dataspace(env, mem_base, mem_size) + { + if (verbose) Genode::log("add mem ", *this, " @ ", local_addr()); + } - class Io_mem_dataspace : public Io_mem_connection - { - private: + ~Mem_region() + { + if (verbose) Genode::log("del mem ", *this); + } - void *_local_addr; + template + T * virt_addr(addr_t addr) + { + return reinterpret_cast(local_addr() + (addr - base())); + } - public: - - Io_mem_dataspace(addr_t base, size_t size) - : Io_mem_connection(base, size) - { - _local_addr = env()->rm_session()->attach(dataspace()); - } - - ~Io_mem_dataspace() - { - env()->rm_session()->detach(_local_addr); - } - - Io_mem_dataspace_capability cap() { return dataspace(); } - - template - T * local_addr() { return static_cast(_local_addr); } - }; - - Io_mem_dataspace _ds; - - public: - - void print(Genode::Output &out) const - { - addr_t const beg = base(), end = beg + size(); - Genode::print(out, Hex_range(beg, end - beg)); - } - - Mem_region(addr_t mem_base, size_t mem_size) - : Region(mem_base, mem_size), _ds(mem_base, mem_size) - { - if (verbose) - Genode::log("add mem ", *this, " @ ", _ds.local_addr()); - } - - ~Mem_region() - { - if (verbose) - Genode::log("del mem ", *this); - } - - template - T * virt_addr(addr_t addr) - { - return reinterpret_cast(_ds.local_addr() + (addr - base())); - } + void print(Genode::Output &out) const + { + addr_t const beg = base(), end = beg + size(); + Genode::print(out, Hex_range(beg, end - beg)); + } }; -static Region_database port_region_db; -static Region_database mem_region_db; +static Genode::Constructible> port_region_db; +static Genode::Constructible> mem_region_db; /** @@ -302,7 +274,7 @@ static int map_code_area(void) void *dummy; /* map page0 */ - if ((err = Framebuffer_drv::map_io_mem(0x0, PAGESIZE, false, &dummy))) { + if ((err = Framebuffer::map_io_mem(0x0, PAGESIZE, false, &dummy))) { Genode::error("could not map page zero"); return err; } @@ -310,7 +282,7 @@ static int map_code_area(void) /* alloc code pages in RAM */ try { - static Attached_ram_dataspace ram_ds(env()->ram_session(), CODESIZE); + static Attached_ram_dataspace ram_ds(genode_env().ram(), genode_env().rm(), CODESIZE); dummy = ram_ds.local_addr(); x86_mem.data_addr(dummy); } catch (...) { @@ -391,7 +363,7 @@ static T X86API inx(X86emu::X86EMU_pioAddr addr) if (hw_emul_handle_port_read(port, &ret)) return ret; - Port_region *region = port_region_db.get_region(port, sizeof(T)); + Port_region *region = port_region_db->get_region(port, sizeof(T)); if (!region) return 0; @@ -423,7 +395,7 @@ static void X86API outx(X86emu::X86EMU_pioAddr addr, T val) if (hw_emul_handle_port_write(port, val)) return; - Port_region *region = port_region_db.get_region(port, sizeof(T)); + Port_region *region = port_region_db->get_region(port, sizeof(T)); if (!region) return; @@ -479,7 +451,7 @@ TYPE * X86emu::virt_addr(ADDR_TYPE addr) local_addr += (x86_mem.data_addr() - PAGESIZE); /* any other I/O memory allocated on demand */ - else if ((region = mem_region_db.get_region(addr & ~(PAGESIZE-1), PAGESIZE))) + else if ((region = mem_region_db->get_region(addr & ~(PAGESIZE-1), PAGESIZE))) return region->virt_addr(local_addr); else { @@ -515,17 +487,35 @@ uint16_t X86emu::x86emu_cmd(uint16_t eax, uint16_t ebx, uint16_t ecx, } -int X86emu::init(void) +void X86emu::print_regions() { - /* - * Wait until Acpi/Pci driver initialization is done to avoid potentially - * concurrently accesses by this driver and the Acpi/Pci driver to the - * graphic device (PCI config space). - */ - Platform::Connection conn; + log("I/O port regions:"); + port_region_db->print_regions(); - if (map_code_area()) - return -1; + log("I/O memory regions:"); + mem_region_db->print_regions(); +} + + +void X86emu::printk(const char *format, ...) +{ + va_list list; + va_start(list, format); + + Genode::vprintf(format, list); + + va_end(list); +} + + +void X86emu::init(Genode::Env &env, Allocator &heap) +{ + local_init_genode_env(env, heap); + + port_region_db.construct(env, heap); + mem_region_db.construct(env, heap); + + if (map_code_area()) throw Framebuffer::Fatal(); if (verbose) { log("--- x86 bios area is ", @@ -537,25 +527,4 @@ int X86emu::init(void) X86emu::M.x86.debug = 0; X86emu::X86EMU_setupPioFuncs(&port_funcs); X86emu::X86EMU_setupMemFuncs(&mem_funcs); - return 0; -} - - -void X86emu::print_regions() -{ - log("I/O port regions:"); - port_region_db.print_regions(); - - log("I/O memory regions:"); - mem_region_db.print_regions(); -} - -void X86emu::printk(const char *format, ...) -{ - va_list list; - va_start(list, format); - - vprintf(format, list); - - va_end(list); } diff --git a/repos/libports/src/drivers/framebuffer/vesa/include/framebuffer.h b/repos/libports/src/drivers/framebuffer/vesa/include/framebuffer.h index 3f60a12bd5..718fe59e1c 100644 --- a/repos/libports/src/drivers/framebuffer/vesa/include/framebuffer.h +++ b/repos/libports/src/drivers/framebuffer/vesa/include/framebuffer.h @@ -6,7 +6,7 @@ */ /* - * Copyright (C) 2006-2013 Genode Labs GmbH + * Copyright (C) 2006-2017 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. @@ -15,12 +15,19 @@ #ifndef _FRAMEBUFFER_H_ #define _FRAMEBUFFER_H_ -#include +#include #include #include "vbe.h" -namespace Framebuffer_drv { +namespace Genode { + struct Env; + struct Allocator; +} + +namespace Framebuffer { + + struct Fatal { }; /* exception */ /** * Return capability for h/w framebuffer dataspace @@ -30,7 +37,7 @@ namespace Framebuffer_drv { /** * Initialize driver, x86emu lib, set up memory */ - int init(); + void init(Genode::Env &, Genode::Allocator &); /** * Set video, initialize framebuffer dataspace @@ -42,7 +49,7 @@ namespace Framebuffer_drv { * \return 0 on success, * non-zero otherwise */ - int set_mode(unsigned long &width, unsigned long &height, unsigned long mode); + int set_mode(unsigned &width, unsigned &height, unsigned mode); /** * Map given device memory, return out_addr (map address) diff --git a/repos/libports/src/drivers/framebuffer/vesa/include/genode_env.h b/repos/libports/src/drivers/framebuffer/vesa/include/genode_env.h new file mode 100644 index 0000000000..46ed0aa4d7 --- /dev/null +++ b/repos/libports/src/drivers/framebuffer/vesa/include/genode_env.h @@ -0,0 +1,48 @@ +/* + * \brief Utilities for accessing the Genode environment + * \author Norman Feske + * \date 2017-01-10 + */ + +/* + * Copyright (C) 2017 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. + */ + +#ifndef _GENODE_ENV_H_ +#define _GENODE_ENV_H_ + +#include +#include + +static Genode::Env *_env_ptr; +static inline Genode::Env &genode_env() +{ + if (_env_ptr) + return *_env_ptr; + + Genode::error("genode env accessed prior initialization"); + throw 1; +} + + +static Genode::Allocator *_alloc_ptr; +static inline Genode::Allocator &alloc() +{ + if (_alloc_ptr) + return *_alloc_ptr; + + Genode::error("allocator accessed prior initialization"); + throw 1; +} + + +static void local_init_genode_env(Genode::Env &env, Genode::Allocator &alloc) +{ + _env_ptr = &env; + _alloc_ptr = &alloc; +} + +#endif /* _GENODE_ENV_H_ */ diff --git a/repos/libports/src/drivers/framebuffer/vesa/include/hw_emul.h b/repos/libports/src/drivers/framebuffer/vesa/include/hw_emul.h index 31a31bc453..bf49afef87 100644 --- a/repos/libports/src/drivers/framebuffer/vesa/include/hw_emul.h +++ b/repos/libports/src/drivers/framebuffer/vesa/include/hw_emul.h @@ -6,7 +6,7 @@ */ /* - * Copyright (C) 2010-2013 Genode Labs GmbH + * Copyright (C) 2010-2017 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. @@ -15,6 +15,11 @@ #ifndef _HW_EMUL_H_ #define _HW_EMUL_H_ + +namespace Genode { struct Env; } + +void hw_emul_init(Genode::Env &); + /** * Handle port-read access * diff --git a/repos/libports/src/drivers/framebuffer/vesa/include/ifx86emu.h b/repos/libports/src/drivers/framebuffer/vesa/include/ifx86emu.h index d19c7b6680..7c70c499e4 100644 --- a/repos/libports/src/drivers/framebuffer/vesa/include/ifx86emu.h +++ b/repos/libports/src/drivers/framebuffer/vesa/include/ifx86emu.h @@ -6,7 +6,7 @@ */ /* - * Copyright (C) 2007-2013 Genode Labs GmbH + * Copyright (C) 2007-2017 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. @@ -17,6 +17,12 @@ #include + +namespace Genode { + struct Env; + struct Allocator; +} + namespace X86emu { using Genode::addr_t; @@ -35,9 +41,6 @@ namespace X86emu { addr_t _bios_addr; addr_t _data_addr; - /** - * Constructur - */ X86emu_mem() : _bios_addr(0), _data_addr(0) { } inline addr_t _addr(addr_t* obj_addr, void* addr = 0) @@ -47,13 +50,8 @@ namespace X86emu { return *obj_addr; } - /** - * set/get functions - */ - inline addr_t bios_addr(void *addr = 0) { - return _addr(&_bios_addr, addr); } - inline addr_t data_addr(void *addr = 0) { - return _addr(&_data_addr, addr); } + inline addr_t bios_addr(void *addr = 0) { return _addr(&_bios_addr, addr); } + inline addr_t data_addr(void *addr = 0) { return _addr(&_data_addr, addr); } }; /** @@ -64,7 +62,7 @@ namespace X86emu { /** * Initialization */ - int init(void); + void init(Genode::Env &, Genode::Allocator &); /** * Execute real mode command diff --git a/repos/libports/src/drivers/framebuffer/vesa/main.cc b/repos/libports/src/drivers/framebuffer/vesa/main.cc index 31690bb6b3..0ef0632b33 100644 --- a/repos/libports/src/drivers/framebuffer/vesa/main.cc +++ b/repos/libports/src/drivers/framebuffer/vesa/main.cc @@ -7,249 +7,240 @@ */ /* - * Copyright (C) 2007-2013 Genode Labs GmbH + * Copyright (C) 2007-2017 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. */ -/* Genode */ -#include -#include -#include +/* Genode includes */ +#include +#include +#include +#include #include -#include -#include -#include -#include -#include +#include +#include #include -#include #include +#include -/* Local */ +/* local includes */ #include "framebuffer.h" -using namespace Genode; - - -/*************** - ** Utilities ** - ***************/ - -/** - * Determine session argument value based on config file and session arguments - * - * \param attr_name attribute name of config node - * \param args session argument string - * \param arg_name argument name - * \param default default session argument value if value is neither - * specified in config node nor in session arguments - */ -unsigned long session_arg(const char *attr_name, const char *args, - const char *arg_name, unsigned long default_value) -{ - unsigned long result = default_value; - - /* try to obtain value from config file */ - try { Genode::config()->xml_node().attribute(attr_name).value(&result); } - catch (...) { } - - /* check session argument to override value from config file */ - result = Arg_string::find_arg(args, arg_name).ulong_value(result); - return result; -} - - -bool config_attribute(const char *attr_name) -{ - return Genode::config()->xml_node().attribute_value(attr_name, false); -} - - -/*********************************************** - ** Implementation of the framebuffer service ** - ***********************************************/ namespace Framebuffer { + struct Session_component; + struct Root; + struct Main; - class Session_component : public Genode::Rpc_object - { - private: - - unsigned _scr_width, _scr_height, _scr_mode; - bool _buffered; - - /* dataspace uses a back buffer (if '_buffered' is true) */ - Genode::Ram_dataspace_capability _bb_ds; - void *_bb_addr; - - /* dataspace of physical frame buffer */ - Genode::Dataspace_capability _fb_ds; - void *_fb_addr; - - Timer::Connection _timer; - - void _refresh_buffered(int x, int y, int w, int h) - { - /* clip specified coordinates against screen boundaries */ - int x2 = min(x + w - 1, (int)_scr_width - 1), - y2 = min(y + h - 1, (int)_scr_height - 1); - int x1 = max(x, 0), - y1 = max(y, 0); - if (x1 > x2 || y1 > y2) return; - - /* determine bytes per pixel */ - int bypp = 0; - if (_scr_mode == 16) bypp = 2; - if (!bypp) return; - - /* copy pixels from back buffer to physical frame buffer */ - char *src = (char *)_bb_addr + bypp*(_scr_width*y1 + x1), - *dst = (char *)_fb_addr + bypp*(_scr_width*y1 + x1); - - blit(src, bypp*_scr_width, dst, bypp*_scr_width, - bypp*(x2 - x1 + 1), y2 - y1 + 1); - } - - public: - - /** - * Constructor - */ - Session_component(unsigned scr_width, unsigned scr_height, unsigned scr_mode, - Genode::Dataspace_capability fb_ds, bool buffered) - : - _scr_width(scr_width), _scr_height(scr_height), _scr_mode(scr_mode), - _buffered(buffered), _fb_ds(fb_ds) - { - if (!_buffered) return; - - if (scr_mode != 16) { - Genode::warning("buffered mode not supported for mode ", (int)scr_mode); - _buffered = false; - } - - size_t buf_size = scr_width*scr_height*scr_mode/8; - try { _bb_ds = Genode::env()->ram_session()->alloc(buf_size); } - catch (...) { - Genode::warning("could not allocate back buffer, disabled buffered output"); - _buffered = false; - } - - if (_buffered && _bb_ds.valid()) { - _bb_addr = Genode::env()->rm_session()->attach(_bb_ds); - _fb_addr = Genode::env()->rm_session()->attach(_fb_ds); - } - - if (_buffered) - Genode::log("using buffered output"); - } - - /** - * Destructor - */ - ~Session_component() - { - if (!_buffered) return; - - Genode::env()->rm_session()->detach(_bb_addr); - Genode::env()->ram_session()->free(_bb_ds); - Genode::env()->rm_session()->detach(_fb_addr); - } - - - /*********************************** - ** Framebuffer session interface ** - ***********************************/ - - Dataspace_capability dataspace() override { - return _buffered ? Dataspace_capability(_bb_ds) - : Dataspace_capability(_fb_ds); } - - Mode mode() const override - { - return Mode(_scr_width, _scr_height, - _scr_mode == 16 ? Mode::RGB565 : Mode::INVALID); - } - - void mode_sigh(Genode::Signal_context_capability) override { } - - void sync_sigh(Genode::Signal_context_capability sigh) override - { - _timer.sigh(sigh); - _timer.trigger_periodic(10*1000); - } - - void refresh(int x, int y, int w, int h) override - { - if (_buffered) - _refresh_buffered(x, y, w, h); - } - }; - - - /** - * Shortcut for single-client root component - */ - typedef Genode::Root_component Root_component; - - class Root : public Root_component - { - protected: - - Session_component *_create_session(const char *args) override - { - unsigned long scr_width = session_arg("width", args, "fb_width", 0), - scr_height = session_arg("height", args, "fb_height", 0), - scr_mode = session_arg("depth", args, "fb_mode", 16); - bool buffered = config_attribute("buffered"); - - if (Framebuffer_drv::set_mode(scr_width, scr_height, scr_mode) != 0) { - Genode::warning("Could not set vesa mode ", - scr_width, "x", scr_height, "@", scr_mode); - throw Root::Invalid_args(); - } - - Genode::log("using video mode: ", scr_width, "x", scr_height, "@", scr_mode); - - return new (md_alloc()) Session_component(scr_width, scr_height, scr_mode, - Framebuffer_drv::hw_framebuffer(), - buffered); - } - - public: - - Root(Rpc_entrypoint *session_ep, Allocator *md_alloc) - : Root_component(session_ep, md_alloc) { } - }; + using Genode::size_t; + using Genode::min; + using Genode::max; + using Genode::Dataspace_capability; + using Genode::Attached_rom_dataspace; + using Genode::Attached_ram_dataspace; } -int main(int argc, char **argv) +class Framebuffer::Session_component : public Genode::Rpc_object { - /* We need to create capabilities for sessions. Therefore, we request the - * CAP service. */ - static Cap_connection cap; + private: - /* initialize server entry point */ - enum { STACK_SIZE = 4*1024*sizeof(long) }; - static Rpc_entrypoint ep(&cap, STACK_SIZE, "vesa_ep"); + Genode::Env &_env; - /* init driver back end */ - if (Framebuffer_drv::init()) { - Genode::error("H/W driver init failed"); - return 3; + unsigned const _scr_width, _scr_height, _scr_depth; + + Timer::Connection _timer { _env }; + + /* dataspace of physical frame buffer */ + Dataspace_capability _fb_cap; + void *_fb_addr; + + /* dataspace uses a back buffer (if '_buffered' is true) */ + Genode::Constructible _bb; + + void _refresh_buffered(int x, int y, int w, int h) + { + /* clip specified coordinates against screen boundaries */ + int x2 = min(x + w - 1, (int)_scr_width - 1), + y2 = min(y + h - 1, (int)_scr_height - 1); + int x1 = max(x, 0), + y1 = max(y, 0); + if (x1 > x2 || y1 > y2) return; + + /* determine bytes per pixel */ + int bypp = 0; + if (_scr_depth == 16) bypp = 2; + if (!bypp) return; + + /* copy pixels from back buffer to physical frame buffer */ + char *src = _bb->local_addr() + bypp*(_scr_width*y1 + x1), + *dst = (char *)_fb_addr + bypp*(_scr_width*y1 + x1); + + blit(src, bypp*_scr_width, dst, bypp*_scr_width, + bypp*(x2 - x1 + 1), y2 - y1 + 1); + } + + bool _buffered() const { return _bb.constructed(); } + + public: + + /** + * Constructor + */ + Session_component(Genode::Env &env, + unsigned scr_width, unsigned scr_height, unsigned scr_depth, + Dataspace_capability fb_cap, bool buffered) + : + _env(env), + _scr_width(scr_width), _scr_height(scr_height), _scr_depth(scr_depth), + _fb_cap(fb_cap) + { + if (!buffered) return; + + if (_scr_depth != 16) { + Genode::warning("buffered mode not supported for depth ", _scr_depth); + return; + } + + size_t const bb_size = _scr_width*_scr_height*_scr_depth/8; + try { _bb.construct(env.ram(), env.rm(), bb_size); } + catch (...) { + Genode::warning("could not allocate back buffer, disabled buffered output"); + return; + } + + _fb_addr = env.rm().attach(_fb_cap); + + Genode::log("using buffered output"); + } + + /** + * Destructor + */ + ~Session_component() + { + if (_buffered()) { + _bb.destruct(); + _env.rm().detach(_fb_addr); + } + } + + + /*********************************** + ** Framebuffer session interface ** + ***********************************/ + + Dataspace_capability dataspace() override + { + return _buffered() ? Dataspace_capability(_bb->cap()) + : Dataspace_capability(_fb_cap); + } + + Mode mode() const override + { + return Mode(_scr_width, _scr_height, + _scr_depth == 16 ? Mode::RGB565 : Mode::INVALID); + } + + void mode_sigh(Genode::Signal_context_capability) override { } + + void sync_sigh(Genode::Signal_context_capability sigh) override + { + _timer.sigh(sigh); + _timer.trigger_periodic(10*1000); + } + + void refresh(int x, int y, int w, int h) override + { + if (_buffered()) + _refresh_buffered(x, y, w, h); + } +}; + + +/** + * Shortcut for single-client root component + */ +typedef Genode::Root_component Root_component; + +class Framebuffer::Root : public Root_component +{ + private: + + Genode::Env &_env; + + Attached_rom_dataspace const &_config; + + unsigned _session_arg(char const *attr_name, char const *args, + char const *arg_name, unsigned default_value) + { + /* try to obtain value from config file */ + unsigned result = _config.xml().attribute_value(attr_name, + default_value); + + /* check session argument to override value from config file */ + return Genode::Arg_string::find_arg(args, arg_name).ulong_value(result); + } + + protected: + + Session_component *_create_session(char const *args) override + { + unsigned scr_width = _session_arg("width", args, "fb_width", 0); + unsigned scr_height = _session_arg("height", args, "fb_height", 0); + unsigned const scr_depth = _session_arg("depth", args, "fb_mode", 16); + + bool const buffered = _config.xml().attribute_value("buffered", false); + + if (Framebuffer::set_mode(scr_width, scr_height, scr_depth) != 0) { + Genode::warning("Could not set vesa mode ", + scr_width, "x", scr_height, "@", scr_depth); + throw Root::Invalid_args(); + } + + Genode::log("using video mode: ", + scr_width, "x", scr_height, "@", scr_depth); + + return new (md_alloc()) Session_component(_env, + scr_width, scr_height, scr_depth, + Framebuffer::hw_framebuffer(), + buffered); + } + + public: + + Root(Genode::Env &env, Genode::Allocator &alloc, + Attached_rom_dataspace const &config) + : + Root_component(&env.ep().rpc_ep(), &alloc), + _env(env), _config(config) + { } +}; + + +struct Framebuffer::Main +{ + Genode::Env &env; + + Genode::Heap heap { env.ram(), env.rm() }; + + Attached_rom_dataspace config { env, "config" }; + + Root root { env, heap, config }; + + Main(Genode::Env &env) : env(env) + { + try { Framebuffer::init(env, heap); } catch (...) { + Genode::error("H/W driver init failed"); + throw; + } + + env.parent().announce(env.ep().manage(root)); } +}; - /* entry point serving framebuffer root interface */ - static Framebuffer::Root fb_root(&ep, env()->heap()); - /* tell parent about the service */ - env()->parent()->announce(ep.manage(&fb_root)); - - /* main's done - go to sleep */ - - sleep_forever(); - return 0; -} +void Component::construct(Genode::Env &env) { static Framebuffer::Main inst(env); } diff --git a/repos/libports/src/drivers/framebuffer/vesa/target.mk b/repos/libports/src/drivers/framebuffer/vesa/target.mk index cb0b71000d..d1b8298ebc 100644 --- a/repos/libports/src/drivers/framebuffer/vesa/target.mk +++ b/repos/libports/src/drivers/framebuffer/vesa/target.mk @@ -1,5 +1,5 @@ TARGET = fb_drv -REQUIRES = vesa +REQUIRES = x86 SRC_CC = main.cc framebuffer.cc ifx86emu.cc hw_emul.cc -LIBS = base blit x86emu config +LIBS = base blit x86emu INC_DIR += $(PRG_DIR)/include $(REP_DIR)/include/x86emu