dde_zircon: add pc-ps2 driver

Fixes #2926
This commit is contained in:
Johannes Kliemann 2018-07-20 13:51:26 +02:00 committed by Christian Helmuth
parent 21ca7be235
commit 3b3e155c79
29 changed files with 1648 additions and 0 deletions

14
repos/dde_zircon/README Normal file
View File

@ -0,0 +1,14 @@
Device drivers ported from the Zircon kernel
zircon.lib.so
#############
The zircon.lib.so provides the interfacing between Genode and Zircon APIs.
It is meant to be extended if required and is required by any Zircon driver.
PS2
###
The zx_pc_ps2_drv can be used as a drop in replacement of the
ps2_drv. Its RAM resources needs to be increased to at least 2M.

View File

@ -0,0 +1,19 @@
LIB_DIR = $(REP_DIR)/src/lib/zircon
ZIRCON_SYSTEM = $(call select_from_ports,dde_zircon)/zircon/src/system
ZIRCON_KERNEL = $(call select_from_ports,dde_zircon)/zircon/src/kernel
ZIRCON_THIRD_PARTY = $(call select_from_ports,dde_zircon)/zircon/src/third_party
INC_DIR += $(LIB_DIR)/pre_include \
$(ZIRCON_SYSTEM)/ulib/ddk/include \
$(ZIRCON_SYSTEM)/ulib/hid/include \
$(ZIRCON_SYSTEM)/public \
$(ZIRCON_KERNEL)/lib/libc/include \
$(ZIRCON_KERNEL)/lib/io/include \
$(ZIRCON_KERNEL)/lib/heap/include \
$(ZIRCON_KERNEL)/arch/x86/include \
$(ZIRCON_THIRD_PARTY)/ulib/musl/include \
$(LIB_DIR)/include
CC_C_OPT += -D_ALL_SOURCE -Wno-multichar
CC_CXX_OPT += -Wno-multichar

View File

@ -0,0 +1,21 @@
include $(REP_DIR)/lib/import/import-zircon.mk
SHARED_LIB = yes
LIBS += base
SRC_C = stdio.c\
printf.c
SRC_CC = libc.cc \
mutex.cc \
threads.cc \
device.cc \
syscalls.cc \
io_port.cc \
irq.cc \
debug.cc
vpath %.cc $(LIB_DIR)
vpath %.c $(ZIRCON_KERNEL)/lib/libc

View File

@ -0,0 +1 @@
cb1a09b52cc0c47fb67647b48ffb1678b32ec325

View File

@ -0,0 +1,7 @@
LICENSE := MIT
VERSION := git
DOWNLOADS := zircon.git
URL(zircon) := https://github.com/fuchsia-mirror/zircon.git
REV(zircon) := eaed741a38d648f6f2236d3dd171059d4b0c4c7a
DIR(zircon) := zircon/src

View File

@ -0,0 +1,147 @@
#
# Build
#
assert_spec x86
set build_components {
core init
drivers/timer
server/dynamic_rom
test/input
drivers/input/zx_pc_ps2
}
source ${genode_dir}/repos/base/run/platform_drv.inc
append_platform_drv_build_components
build $build_components
create_boot_directory
#
# Generate config
#
append config {
<config>
<parent-provides>
<service name="ROM"/>
<service name="IRQ"/>
<service name="IO_MEM"/>
<service name="IO_PORT"/>
<service name="PD"/>
<service name="RM"/>
<service name="CPU"/>
<service name="LOG"/>
</parent-provides>
<default-route/>
<default caps="100"/>
<start name="timer">
<resource name="RAM" quantum="1M"/>
<provides><service name="Timer"/></provides>
<route>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="IO_MEM"> <parent/> </service>
<service name="IRQ"> <parent/> </service>
<service name="IO_PORT"> <parent/> </service>
</route>
</start>}
append_platform_drv_config
append config {
<start name="ps2_drv">
<binary name="zx_pc_ps2_drv"/>
<resource name="RAM" quantum="2M"/>
<provides><service name="Input"/></provides>
<config verbose_keyboard="no" verbose_mouse="no" verbose_scancodes="no"
capslock_led="rom" numlock_led="rom" scrlock_led="rom"/>
<route>
<service name="ROM" label="capslock"> <child name="dynamic_rom"/> </service>
<service name="ROM" label="numlock"> <child name="dynamic_rom"/> </service>
<service name="ROM" label="scrlock"> <child name="dynamic_rom"/> </service>
<service name="ROM"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="IO_PORT"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="Platform"> <any-child/> </service>
<service name="Timer"> <child name="timer"/> </service>
</route>
</start>
<alias name="input_drv" child="ps2_drv"/>
<start name="dynamic_rom">
<resource name="RAM" quantum="4M"/>
<provides> <service name="ROM"/> </provides>
<config verbose="no">
<rom name="capslock">
<inline> <capslock enabled="no"/> </inline>
<sleep milliseconds="250" />
<inline> <capslock enabled="yes"/> </inline>
<sleep milliseconds="250" />
</rom>
<rom name="numlock">
<inline> <numlock enabled="no"/> </inline>
<sleep milliseconds="500" />
<inline> <numlock enabled="yes"/> </inline>
<sleep milliseconds="500" />
</rom>
<rom name="scrlock">
<inline> <scrlock enabled="no"/> </inline>
<sleep milliseconds="1000" />
<inline> <scrlock enabled="yes"/> </inline>
<sleep milliseconds="1000" />
</rom>
</config>
<route>
<service name="ROM"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="Timer"> <child name="timer"/> </service>
</route>
</start>
<start name="test-input">
<resource name="RAM" quantum="1M"/>
<route>
<service name="ROM"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="Timer"> <child name="timer"/> </service>
<service name="Input"> <child name="input_drv"/> </service>
</route>
</start>}
append config {
</config>}
install_config $config
#
# Boot modules
#
# generic modules
set boot_modules {
core ld.lib.so init
timer dynamic_rom
test-input
zircon.lib.so
zx_pc_ps2_drv
}
# platform-specific modules
append_platform_drv_boot_modules
build_boot_image $boot_modules
run_genode_until forever

View File

@ -0,0 +1,262 @@
/*
* \brief Mapping of USB to Genode keycodes
* \author Johannes Kliemann
* \date 2018-07-25
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _KEYMAP_H_
#define _KEYMAP_H_
#include <input/keycodes.h>
#include <hid/usages.h>
static Input::Keycode zxg_keymap[] =
{
Input::KEY_RESERVED,
Input::KEY_RESERVED,
Input::KEY_RESERVED,
Input::KEY_RESERVED,
Input::KEY_A,
Input::KEY_B,
Input::KEY_C,
Input::KEY_D,
Input::KEY_E,
Input::KEY_F,
Input::KEY_G,
Input::KEY_H,
Input::KEY_I,
Input::KEY_J,
Input::KEY_K,
Input::KEY_L,
Input::KEY_M,
Input::KEY_N,
Input::KEY_O,
Input::KEY_P,
Input::KEY_Q,
Input::KEY_R,
Input::KEY_S,
Input::KEY_T,
Input::KEY_U,
Input::KEY_V,
Input::KEY_W,
Input::KEY_X,
Input::KEY_Y,
Input::KEY_Z,
Input::KEY_1,
Input::KEY_2,
Input::KEY_3,
Input::KEY_4,
Input::KEY_5,
Input::KEY_6,
Input::KEY_7,
Input::KEY_8,
Input::KEY_9,
Input::KEY_0,
Input::KEY_ENTER,
Input::KEY_ESC,
Input::KEY_BACKSPACE,
Input::KEY_TAB,
Input::KEY_SPACE,
Input::KEY_MINUS,
Input::KEY_EQUAL,
Input::KEY_LEFTBRACE,
Input::KEY_RIGHTBRACE,
Input::KEY_BACKSLASH,
Input::KEY_UNKNOWN,
Input::KEY_SEMICOLON,
Input::KEY_APOSTROPHE,
Input::KEY_GRAVE,
Input::KEY_COMMA,
Input::KEY_DOT,
Input::KEY_SLASH,
Input::KEY_CAPSLOCK,
Input::KEY_F1,
Input::KEY_F2,
Input::KEY_F3,
Input::KEY_F4,
Input::KEY_F5,
Input::KEY_F6,
Input::KEY_F7,
Input::KEY_F8,
Input::KEY_F9,
Input::KEY_F10,
Input::KEY_F11,
Input::KEY_F12,
Input::KEY_PRINT,
Input::KEY_SCROLLLOCK,
Input::KEY_PAUSE,
Input::KEY_INSERT,
Input::KEY_HOME,
Input::KEY_PAGEUP,
Input::KEY_DELETE,
Input::KEY_END,
Input::KEY_PAGEDOWN,
Input::KEY_RIGHT,
Input::KEY_LEFT,
Input::KEY_DOWN,
Input::KEY_UP,
Input::KEY_NUMLOCK,
Input::KEY_KPSLASH,
Input::KEY_KPASTERISK,
Input::KEY_KPMINUS,
Input::KEY_KPPLUS,
Input::KEY_KPENTER,
Input::KEY_KP1,
Input::KEY_KP2,
Input::KEY_KP3,
Input::KEY_KP4,
Input::KEY_KP5,
Input::KEY_KP6,
Input::KEY_KP7,
Input::KEY_KP8,
Input::KEY_KP9,
Input::KEY_KP0,
Input::KEY_KPDOT,
Input::KEY_UNKNOWN,
/* see system/ulib/hid/include/hid/usages.h:115 */
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
Input::KEY_UNKNOWN,
/* */
Input::KEY_LEFTCTRL,
Input::KEY_LEFTSHIFT,
Input::KEY_LEFTALT,
Input::KEY_UNKNOWN,
Input::KEY_RIGHTCTRL,
Input::KEY_RIGHTSHIFT,
Input::KEY_RIGHTALT,
Input::KEY_UNKNOWN,
Input::KEY_VOLUMEDOWN,
Input::KEY_VOLUMEUP
};
#endif /* ifndef _KEYMAP_H_ */

View File

@ -0,0 +1,221 @@
/*
* \brief Zircon pc-ps2 driver
* \author Johannes Kliemann
* \date 2018-07-25
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#include <base/component.h>
#include <base/log.h>
#include <base/heap.h>
#include <io_port_session/connection.h>
#include <timer_session/connection.h>
#include <platform_session/connection.h>
#include <input/component.h>
#include <input/root.h>
#include <ddk/driver.h>
#include <ddk/protocol/hidbus.h>
#include <zircon/device/input.h>
#include <zx/static_resource.h>
#include <zx/device.h>
#include <zx/driver.h>
#include <keymap.h>
struct Main
{
static Genode::uint8_t mouse_btn;
static Genode::uint8_t kbd_button[8];
void mouse_button_event(int old_st, int new_st, int key)
{
int old_state = old_st & key;
int new_state = new_st & key;
int key_code;
if (old_state == new_state){
return;
}
switch (key){
case 1: key_code = Input::BTN_LEFT;
break;
case 2: key_code = Input::BTN_RIGHT;
break;
case 4: key_code = Input::BTN_MIDDLE;
break;
default: Genode::log("unsupported mouse button: ", key);
}
if (new_state){
_ev_queue.add(Input::Press{Input::Keycode(key_code)});
}else{
_ev_queue.add(Input::Release{Input::Keycode(key_code)});
}
}
bool contains(Genode::uint8_t const *buf, Genode::uint8_t const val)
{
for (int i = 2; i < 8; i++){
if (buf[i] == val){
return true;
}
}
return false;
}
void handle_modifier(Genode::uint8_t current, int key)
{
int c_mod = current & key;
int o_mod = kbd_button[0] & key;
int key_code;
if (c_mod == o_mod){
return;
}
switch (key){
case 1:
key_code = Input::KEY_LEFTCTRL;
break;
case 2:
key_code = Input::KEY_LEFTSHIFT;
break;
case 4:
key_code = Input::KEY_LEFTALT;
break;
case 8:
key_code = Input::KEY_LEFTMETA;
break;
case 16:
key_code = Input::KEY_RIGHTCTRL;
break;
case 64:
key_code = Input::KEY_RIGHTALT;
break;
default:
Genode::log("unsupported modifier: ", key, " ", current);
return;
}
if (c_mod){
_ev_queue.add(Input::Press{Input::Keycode(key_code)});
}else{
_ev_queue.add(Input::Release{Input::Keycode(key_code)});
}
}
void handle_keyboard(Genode::uint8_t const *current)
{
const Genode::uint8_t rollover[6] = {1, 1, 1, 1, 1, 1};
if (!Genode::memcmp(&current[2], rollover, 6)){
return;
}
for (int i = 2; i < 8; i++){
if (current[i] != 0){
if (!contains(kbd_button, current[i])){
_ev_queue.add(Input::Press{Input::Keycode(zxg_keymap[current[i]])});
}
}
if (kbd_button[i] != 0){
if (!contains(current, kbd_button[i])){
_ev_queue.add(Input::Release{Input::Keycode(zxg_keymap[kbd_button[i]])});
}
}
}
handle_modifier(current[0], 1);
handle_modifier(current[0], 2);
handle_modifier(current[0], 4);
handle_modifier(current[0], 8);
handle_modifier(current[0], 16);
handle_modifier(current[0], 64);
Genode::memcpy(kbd_button, current, sizeof(kbd_button));
}
void handle_mouse(boot_mouse_report_t const *report)
{
if (report->rel_x || report->rel_y){
_ev_queue.add(Input::Relative_motion{report->rel_x, report->rel_y});
}
mouse_button_event(mouse_btn, report->buttons, 1);
mouse_button_event(mouse_btn, report->buttons, 2);
mouse_button_event(mouse_btn, report->buttons, 4);
mouse_btn = report->buttons;
}
static void io_queue(void *cookie, const uint8_t *data, size_t size)
{
switch (size){
case sizeof(boot_kbd_report_t):
static_cast<Main *>(cookie)->handle_keyboard(data);
break;
case sizeof(boot_mouse_report_t):
static_cast<Main *>(cookie)->handle_mouse(reinterpret_cast<boot_mouse_report_t const *>(data));
break;
default:
Genode::warning("invalid data received");
break;
}
}
Genode::Env &_env;
Genode::Heap _heap;
Timer::Connection _timer;
Platform::Connection _platform;
Platform::Device_client _ps2_dev;
ZX::Platform::Io_port _io_config[2] = { {0x60, 0x0}, {0x64, 0x1} };
ZX::Platform::Irq _irq_config[2] = { {0x1, 0x0}, {0xc, 0x1} };
hidbus_ifc_t _hidbus = { Main::io_queue };
ZX::Device _zx_dev;
Input::Session_component _session;
Input::Root_component _root;
Input::Event_queue &_ev_queue;
Main(Genode::Env &env) :
_env(env),
_heap(env.ram(), env.rm()),
_timer(env),
_platform(env),
_ps2_dev(_platform.with_upgrade([&] () {
return _platform.device("PS2"); })),
_zx_dev(this, true),
_session(_env, _env.ram()),
_root(_env.ep().rpc_ep(), _session),
_ev_queue(_session.event_queue())
{
Genode::log("zircon pc-ps2 driver");
_zx_dev.set_io_port(_io_config, 2);
_zx_dev.set_irq(_irq_config, 2);
_zx_dev.set_hidbus(&_hidbus);
ZX::Resource<Genode::Env>::set_component(_env);
ZX::Resource<Genode::Heap>::set_component(_heap);
ZX::Resource<Timer::Connection>::set_component(_timer);
ZX::Resource<Platform::Device_client>::set_component(_ps2_dev);
ZX::Resource<ZX::Device>::set_component(_zx_dev);
bind_driver(nullptr, nullptr);
_env.parent().announce(_env.ep().manage(_root));
}
};
Genode::uint8_t Main::mouse_btn = 0;
Genode::uint8_t Main::kbd_button[8] = {};
void Component::construct(Genode::Env &env)
{
env.exec_static_constructors();
static Main main(env);
}

View File

@ -0,0 +1,15 @@
REQUIRES = x86
TARGET = zx_pc_ps2_drv
LIBS = base zircon
SRC_CC += main.cc
SRC_C += i8042.c
ZIRCON_SYSTEM = $(call select_from_ports,dde_zircon)/zircon/src/system
INC_DIR += $(PRG_DIR)/include
vpath %.cc $(PRG_DIR)
vpath i8042.c $(ZIRCON_SYSTEM)/dev/input/pc-ps2

View File

@ -0,0 +1,36 @@
/*
* \brief Zircon debug functions
* \author Johannes Kliemann
* \date 2018-07-25
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#include <base/log.h>
#include <util/string.h>
#include <zircon/types.h>
extern "C" {
void platform_dputc(char c)
{
Genode::warning(__func__, " called with ", c);
}
void platform_dputs_thread(const char *str, size_t len)
{
Genode::warning(__func__, " called with (", len, ") ", Genode::Cstring(str));
}
int platform_dgetc(char *, bool)
{
return ZX_ERR_NOT_SUPPORTED;
}
}

View File

@ -0,0 +1,82 @@
/*
* \brief Zircon platform configuration
* \author Johannes Kliemann
* \date 2018-07-25
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#include <platform_session/connection.h>
#include <zx/device.h>
#include <zx/static_resource.h>
ZX::Device::Device(void *component, bool use_platform) :
_use_platform(use_platform),
_io_port(nullptr),
_io_port_count(0),
_irq(nullptr),
_irq_count(0),
_interfaces({false}),
_hidbus(0),
_component(component)
{ }
bool ZX::Device::platform()
{
return _use_platform;
}
void *ZX::Device::component()
{
return _component;
}
void ZX::Device::set_io_port(ZX::Platform::Io_port *io_port, int count)
{
_io_port = io_port;
_io_port_count = count;
}
void ZX::Device::set_irq(ZX::Platform::Irq *irq, int count)
{
_irq = irq;
_irq_count = count;
}
void ZX::Device::set_hidbus(hidbus_ifc_t *bus)
{
_hidbus = bus;
_interfaces.hidbus = bus != nullptr;
}
bool ZX::Device::hidbus(hidbus_ifc_t **bus)
{
*bus = _hidbus;
return _interfaces.hidbus;
}
Genode::Io_port_session_capability ZX::Device::io_port_resource(Genode::uint16_t port)
{
for (int i = 0; _io_port && i < _io_port_count; i++){
if (_io_port[i].port == port){
return ZX::Resource<::Platform::Device_client>::get_component().io_port(_io_port[i].resource);
}
}
return Genode::Io_port_session_capability();
}
Genode::Irq_session_capability ZX::Device::irq_resource(Genode::uint32_t irq)
{
for (int i = 0; _irq && i < _irq_count; i++){
if (_irq[i].irq == irq){
return ZX::Resource<::Platform::Device_client>::get_component().irq(_irq[i].resource);
}
}
return Genode::Irq_session_capability();
}

View File

@ -0,0 +1,2 @@
#include <zircon/listnode.h>

View File

@ -0,0 +1,4 @@
int platform_dgetc(char *c, bool wait);
void platform_dputc(char c);
void platform_dputs_thread(const char* str, size_t len);

View File

@ -0,0 +1,38 @@
/*
* \brief Zircon syscall declarations
* \author Johannes Kliemann
* \date 2018-07-25
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _DDE_ZIRCON_DEFINITIONS_H_
#define _DDE_ZIRCON_DEFINITIONS_H_
zx_status_t zx_ioports_request(
ZX_SYSCALL_PARAM_ATTR(handle_use) zx_handle_t resource,
uint16_t io_addr,
uint32_t len) __LEAF_FN;
zx_status_t zx_interrupt_wait(
ZX_SYSCALL_PARAM_ATTR(handle_use) zx_handle_t handle,
zx_time_t *out_timestamp) __LEAF_FN;
zx_status_t zx_interrupt_destroy(
ZX_SYSCALL_PARAM_ATTR(handle_use) zx_handle_t handle) __LEAF_FN;
zx_status_t zx_handle_close(
ZX_SYSCALL_PARAM_ATTR(handle_release_always) zx_handle_t handle) __LEAF_FN;
zx_status_t zx_interrupt_create(
ZX_SYSCALL_PARAM_ATTR(handle_use) zx_handle_t src_obj,
uint32_t src_num,
uint32_t options,
zx_handle_t *out) __NONNULL((4)) __LEAF_FN;
#endif /* ifndef _DDE_ZIRCON_DEFINITIONS_H_ */

View File

@ -0,0 +1,82 @@
/*
* \brief Zircon platform configuration
* \author Johannes Kliemann
* \date 2018-07-25
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _ZX_DEVICE_H_
#define _ZX_DEVICE_H_
#include <io_port_session/connection.h>
#include <irq_session/connection.h>
#include <ddk/driver.h>
#include <ddk/protocol/hidbus.h>
namespace ZX
{
namespace Platform
{
struct Io_port;
struct Irq;
}
namespace Interface
{
struct Available;
}
class Device;
}
struct ZX::Platform::Io_port
{
Genode::uint16_t port;
Genode::uint8_t resource;
};
struct ZX::Platform::Irq
{
Genode::uint32_t irq;
Genode::uint8_t resource;
};
struct ZX::Interface::Available
{
bool hidbus;
};
class ZX::Device
{
private:
bool _use_platform;
Platform::Io_port *_io_port;
int _io_port_count;
Platform::Irq *_irq;
int _irq_count;
ZX::Interface::Available _interfaces;
hidbus_ifc_t *_hidbus;
void *_component;
public:
Device(void *, bool);
bool platform();
void *component();
void set_io_port(Platform::Io_port *, int);
void set_irq(Platform::Irq *, int);
void set_hidbus(hidbus_ifc_t *);
bool hidbus(hidbus_ifc_t **);
Genode::Io_port_session_capability io_port_resource(Genode::uint16_t);
Genode::Irq_session_capability irq_resource(Genode::uint32_t);
};
#endif /* ifndef _ZX_DEVICE_H_ */

View File

@ -0,0 +1,35 @@
/*
* \brief Helper for Zircon driver start mechanism
* \author Johannes Kliemann
* \date 2018-07-25
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _ZX_DRIVER_H_
#define _ZX_DRIVER_H_
#include <base/log.h>
#include <ddk/driver.h>
extern zx_driver_rec_t __zircon_driver_rec__;
static inline int bind_driver(void *ctx, zx_device_t* parent)
{
int ret = -1;
if (__zircon_driver_rec__.ops->version == DRIVER_OPS_VERSION){
ret = __zircon_driver_rec__.ops->bind(ctx, parent);
}else{
Genode::error("Failed to start driver, invalid DRIVER_OPS_VERSION ",
Genode::Hex(__zircon_driver_rec__.ops->version));
}
return ret;
}
#endif /* ifndef _ZX_DRIVER_H_ */

View File

@ -0,0 +1,66 @@
/*
* \brief Zircon interrupt handler
* \author Johannes Kliemann
* \date 2018-07-25
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _ZX_IRQ_H_
#define _ZX_IRQ_H_
#include <irq_session/connection.h>
#include <irq_session/client.h>
#include <base/signal.h>
#include <base/lock.h>
namespace ZX{
enum {
IRQ_LINES = 256
/* we assume that a single driver will never need more than 256 interrupt lines */
};
template <typename tsession>
class Irq
{
private:
tsession _irq;
Genode::Signal_handler<Irq> _irq_handler;
Genode::Lock _lock;
void _unlock()
{
_lock.unlock();
}
public:
Irq(Genode::Env &env, int irq) :
_irq(env, irq),
_irq_handler(env.ep(), *this, &Irq::_unlock),
_lock()
{
_irq.sigh(_irq_handler);
}
Irq(Genode::Env &env, Genode::Irq_session_capability cap) :
_irq(cap),
_irq_handler(env.ep(), *this, &Irq::_unlock),
_lock()
{
_irq.sigh(_irq_handler);
}
void wait()
{
_irq.ack_irq();
_lock.lock();
}
};
}
#endif /* ifndef_ZX_IRQ_H_ */

View File

@ -0,0 +1,88 @@
/*
* \brief Utility to provide resources via type based static singletons
* \author Johannes Kliemann
* \date 2018-07-25
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _ZX_STATIC_RESOURCE_H_
#define _ZX_STATIC_RESOURCE_H_
#include <base/exception.h>
#include <util/reconstructible.h>
namespace ZX
{
template <typename T>
class Resource_uninitialized : Genode::Exception {};
template <typename T>
class Resource_already_initialized : Genode::Exception {};
template <typename Component>
class Container
{
private:
Component &_component;
public:
Container(Component &component) : _component(component)
{ }
Component &component()
{
return _component;
}
};
template <typename Component>
class Resource
{
private:
static Genode::Constructible<Container<Component>> _container;
Resource() {}
public:
static Component &get_component()
{
if (_container.constructed()){
return _container->component();
}
Genode::error("Uninitialized resource: ", __PRETTY_FUNCTION__);
throw Resource_uninitialized<Component>();
}
static void set_component(Component &component)
{
if (!_container.constructed()){
_container.construct(component);
return;
}
Genode::error("Already initialized resource: ", __PRETTY_FUNCTION__);
throw Resource_already_initialized<Component>();
}
static bool initialized()
{
return _container.constructed();
}
};
}
template <typename Component>
Genode::Constructible<ZX::Container<Component>> ZX::Resource<Component>::_container;
#endif /* ifndef _ZX_STATIC_RESOURCE_H_ */

View File

@ -0,0 +1,42 @@
/*
* \brief Zircon thread wrapper
* \author Johannes Kliemann
* \date 2018-07-25
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _ZX_THREAD_H_
#define _ZX_THREAD_H_
#include <base/thread.h>
#include <threads.h>
namespace ZX
{
class Thread;
}
class ZX::Thread : public Genode::Thread
{
private:
thrd_start_t _thread_worker;
unsigned long _arg;
int _result;
void entry() override;
public:
Thread(Genode::Env &, thrd_start_t, const char *, void *);
int result();
};
#endif /* ifndef _ZX_THREAD_H_ */

View File

@ -0,0 +1,66 @@
/*
* \brief Zircon IO port handling
* \author Johannes Kliemann
* \date 2018-07-25
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#include <io_port_session/connection.h>
#include <platform_session/client.h>
#include <zircon/types.h>
#include <zx/static_resource.h>
#include <zx/device.h>
static Genode::Io_port_session_capability _port_reg[65536] = {};
extern "C" {
Genode::uint8_t inp(Genode::uint16_t port)
{
if (ZX::Resource<ZX::Device>::get_component().platform() && _port_reg[port].valid()){
return Genode::Io_port_session_client(_port_reg[port]).inb(port);
}else{
return ZX::Resource<Genode::Io_port_connection>::get_component().inb(port);
}
}
void outp(Genode::uint16_t port, Genode::uint8_t data)
{
if (ZX::Resource<ZX::Device>::get_component().platform() && _port_reg[port].valid()){
Genode::Io_port_session_client(_port_reg[port]).outb(port, data);
}else{
ZX::Resource<Genode::Io_port_connection>::get_component().outb(port, data);
}
}
zx_status_t zx_ioports_request(zx_handle_t,
Genode::uint16_t io_addr,
Genode::uint32_t len)
{
ZX::Device &dev = ZX::Resource<ZX::Device>::get_component();
if (dev.platform()){
for (Genode::uint32_t i = io_addr; i < io_addr + len && io_addr + len < 65536; i++){
_port_reg[i] = dev.io_port_resource(i);
if (!_port_reg[i].valid()){
Genode::warning("No valid resource available for IO port ", Genode::Hex(i));
return ZX_ERR_NO_RESOURCES;
}
}
}else{
if (!ZX::Resource<Genode::Io_port_connection>::initialized()){
Genode::error("IO_PORT request ", Genode::Hex(io_addr), " x ", len, " not satisfied");
return ZX_ERR_NO_RESOURCES;
}
}
return ZX_OK;
}
}

View File

@ -0,0 +1,89 @@
/*
* \brief Zircon interrupt handling
* \author Johannes Kliemann
* \date 2018-07-25
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#include <util/reconstructible.h>
#include <platform_session/client.h>
#include <zircon/types.h>
#include <zx/irq.h>
#include <zx/static_resource.h>
#include <zx/device.h>
static Genode::Constructible<ZX::Irq<Genode::Irq_connection>> _irq_reg_connection[ZX::IRQ_LINES] = {};
static Genode::Constructible<ZX::Irq<Genode::Irq_session_client>> _irq_reg_client[ZX::IRQ_LINES] = {};
extern "C" {
zx_status_t zx_interrupt_create(zx_handle_t,
Genode::uint32_t irq,
Genode::uint32_t,
zx_handle_t *irq_handle)
{
ZX::Device &dev = ZX::Resource<ZX::Device>::get_component();
if (irq < ZX::IRQ_LINES){
if (dev.platform()){
try{
_irq_reg_client[irq].construct(ZX::Resource<Genode::Env>::get_component(),
dev.irq_resource(irq));
*irq_handle = irq;
return ZX_OK;
}catch (...){
Genode::error("Failed to register for IRQ ", irq);
}
}else{
if (!_irq_reg_connection[irq].constructed()){
_irq_reg_connection[irq].construct(ZX::Resource<Genode::Env>::get_component(), irq);
*irq_handle = irq;
return ZX_OK;
}
}
}
return ZX_ERR_NO_RESOURCES;
}
zx_status_t zx_interrupt_wait(zx_handle_t irq, zx_time_t *)
{
if (irq < ZX::IRQ_LINES){
if (ZX::Resource<ZX::Device>::get_component().platform()){
if (_irq_reg_client[irq].constructed()){
_irq_reg_client[irq]->wait();
return ZX_OK;
}
}else{
if (_irq_reg_connection[irq].constructed()){
_irq_reg_connection[irq]->wait();
return ZX_OK;
}
}
}
return ZX_ERR_BAD_HANDLE;
}
zx_status_t zx_interrupt_destroy(zx_handle_t irq)
{
if (irq < ZX::IRQ_LINES){
if (ZX::Resource<ZX::Device>::get_component().platform()){
if (_irq_reg_client[irq].constructed()){
_irq_reg_client[irq].destruct();
}
}else{
if (_irq_reg_connection[irq].constructed()){
_irq_reg_connection[irq].destruct();
}
}
return ZX_OK;
}
return ZX_ERR_BAD_HANDLE;
}
}

View File

@ -0,0 +1,92 @@
/*
* \brief Zircon libc definitions
* \author Johannes Kliemann
* \date 2018-07-25
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#include <base/heap.h>
#include <timer_session/connection.h>
#include <util/string.h>
#include <zx/static_resource.h>
class Format_String
{
private:
static char _buffer[1024];
public:
Format_String(const char *prefix, const char *str, Genode::size_t len)
{
Genode::size_t last = Genode::strlen(_buffer);
Genode::memcpy(_buffer + last, str, Genode::min(len, 1023 - last));
for (Genode::size_t i = 0; i < Genode::min(len, 1023 - last); i++){
_buffer[i + last] = str[i];
if (_buffer[i + last] == '\n'){
Genode::log(Genode::Cstring(prefix), " ", *this);
Genode::memset(_buffer, '\0', 1024);
last = 0;
}
}
}
void print(Genode::Output &out) const
{
_buffer[Genode::strlen(_buffer) - 1] = '\0';
Genode::print(out, Genode::Cstring(_buffer));
}
};
char Format_String::_buffer[1024] = {};
extern "C" {
int usleep(unsigned usecs)
{
ZX::Resource<Timer::Connection>::get_component().usleep(usecs);
return 0;
}
int __printf_output_func(const char *str, Genode::size_t len, void *)
{
Format_String fmt("ZIRCON:", str, len);
return 0;
}
Genode::size_t strlen(char *str)
{
Genode::size_t len = 0;
while (str[++len] != '\0');
return len;
}
void *malloc(Genode::size_t size)
{
void *mem;
Genode::Heap &heap = ZX::Resource<Genode::Heap>::get_component();
if (!heap.alloc(size, &mem)){
return nullptr;
}
return mem;
}
void free(void *ptr)
{
Genode::Heap &heap = ZX::Resource<Genode::Heap>::get_component();
heap.free(ptr, 0);
}
void *calloc(Genode::size_t elem, Genode::size_t size)
{
return malloc(elem * size);
}
}

View File

@ -0,0 +1,46 @@
/*
* \brief Zircon mutex definitions
* \author Johannes Kliemann
* \date 2018-07-25
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#include <base/heap.h>
#include <base/allocator.h>
#include <base/lock.h>
#include <threads.h>
#include <zx/static_resource.h>
extern "C" {
int mtx_init(mtx_t *mtx, int type)
{
if (type & mtx_recursive){
return thrd_error;
}
Genode::Allocator &alloc = ZX::Resource<Genode::Heap>::get_component();
mtx->lock = static_cast<void *>(new (alloc) Genode::Lock());
return thrd_success;
}
int mtx_lock(mtx_t *mtx)
{
static_cast<Genode::Lock *>(mtx->lock)->lock();
return thrd_success;
}
int mtx_unlock(mtx_t *mtx)
{
static_cast<Genode::Lock *>(mtx->lock)->unlock();
return thrd_success;
}
}

View File

@ -0,0 +1,24 @@
/*
* \brief Overwrite Zircon specific mutex type
* \author Johannes Kliemann
* \date 2018-07-25
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef __DEFINED_mtx_t
#define __DEFINED_mtx_t
typedef struct
{
void *lock;
} mtx_t;
#endif /* __DEFINED_mtx_t */
#include_next <bits/alltypes.h>

View File

@ -0,0 +1,20 @@
/*
* \brief Custom define of system/ulib/ddk/include/hw/inout.h
* \author Johannes Kliemann
* \date 2018-07-25
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _INOUT_H_
#define _INOUT_H_
uint8_t inp(uint16_t);
void outp(uint16_t, uint8_t);
#endif

View File

@ -0,0 +1,50 @@
/*
* \brief Definition of Zircon system calls
* \author Johannes Kliemann
* \date 2018-07-25
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#include <base/log.h>
#include <io_port_session/connection.h>
#include <zircon/types.h>
#include <ddk/device.h>
#include <ddk/driver.h>
#include <zx/static_resource.h>
#include <zx/device.h>
extern "C" {
zx_handle_t get_root_resource()
{
return 0;
}
zx_status_t zx_handle_close(zx_handle_t)
{
return ZX_OK;
}
zx_status_t device_add_from_driver(zx_driver_t *,
zx_device_t *,
device_add_args_t *args,
zx_device_t **)
{
ZX::Device &dev = ZX::Resource<ZX::Device>::get_component();
hidbus_ifc_t *hidbus;
if (dev.hidbus(&hidbus)){
static_cast<hidbus_protocol_ops_t *>(args->proto_ops)->start(
args->ctx, hidbus, dev.component());
}
return ZX_OK;
}
}

View File

@ -0,0 +1,74 @@
/*
* \brief Zircon threading implementation
* \author Johannes Kliemann
* \date 2018-07-25
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#include <base/heap.h>
#include <zx/static_resource.h>
#include <zx/thread.h>
ZX::Thread::Thread(Genode::Env &env, thrd_start_t worker, const char *label, void *arg) :
Genode::Thread(env, label, 4096),
_thread_worker(worker),
_arg(reinterpret_cast<unsigned long>(arg)),
_result(-1)
{
if (sizeof(arg) > sizeof(_arg)){
Genode::warning("unsigned long < void *! things can go horribly wrong!");
}
}
void ZX::Thread::entry()
{
_result = _thread_worker(reinterpret_cast<void *>(_arg));
}
int ZX::Thread::result()
{
return _result;
}
extern "C" {
int thrd_create_with_name(thrd_t* thread, thrd_start_t run, void* arg, const char* name)
{
Genode::Allocator &alloc = ZX::Resource<Genode::Heap>::get_component();
Genode::Env &env = ZX::Resource<Genode::Env>::get_component();
ZX::Thread *gthread = new (alloc) ZX::Thread(env, run, name, arg);
*thread = reinterpret_cast<thrd_t>(gthread);
if (sizeof(gthread) != sizeof(*thread)){
Genode::warning("thrd_t * != ZX::Thread *! things can go horribly wrong!");
}
gthread->start();
return thrd_success;
}
int thrd_join(thrd_t thread, int *result)
{
ZX::Thread *gthread = reinterpret_cast<ZX::Thread *>(thread);
if (sizeof(gthread) != sizeof(thread)){
Genode::warning("thrd_t * != ZX::Thread *! things can go horribly wrong!");
}
gthread->join();
if (result){
*result = gthread->result();
}
return thrd_success;
}
}

View File

@ -8,3 +8,8 @@
#
#REPOSITORIES += $(GENODE_DIR)/repos/dde_ipxe
#
# Drivers ported from Zircon
#
#REPOSITORIES += $(GENODE_DIR)/repos/dde_zircon