diff --git a/repos/os/run/rtc.run b/repos/os/run/rtc.run
new file mode 100644
index 0000000000..a03bacbcfb
--- /dev/null
+++ b/repos/os/run/rtc.run
@@ -0,0 +1,44 @@
+# RTC test
+
+build { core init drivers/rtc drivers/timer test/rtc }
+
+create_boot_directory
+
+install_config {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+
+build_boot_image { core init timer rtc_drv test-rtc }
+
+append qemu_args " -nographic -m 128 "
+
+run_genode_until ".*--- RTC test finished ---.*\n" 20
+
+puts "Test succeeded"
diff --git a/repos/os/src/drivers/rtc/x86/linux.cc b/repos/os/src/drivers/rtc/x86/linux.cc
new file mode 100644
index 0000000000..512943bc30
--- /dev/null
+++ b/repos/os/src/drivers/rtc/x86/linux.cc
@@ -0,0 +1,27 @@
+/*
+ * \brief Linux RTC pseudo driver
+ * \author Christian Helmuth
+ * \date 2015-01-06
+ */
+
+/*
+ * 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.
+ */
+
+/* Linux includes */
+#include
+
+#include "rtc.h"
+
+
+Genode::uint64_t Rtc::get_time(void)
+{
+ struct timeval now { };
+
+ gettimeofday(&now, nullptr);
+
+ return now.tv_sec * 1000000ULL + now.tv_usec;
+}
diff --git a/repos/os/src/drivers/rtc/x86/main.cc b/repos/os/src/drivers/rtc/x86/main.cc
index 0418c8f61e..c43ff32ab5 100644
--- a/repos/os/src/drivers/rtc/x86/main.cc
+++ b/repos/os/src/drivers/rtc/x86/main.cc
@@ -1,13 +1,11 @@
/*
- * \brief Simple real-time-clock driver
+ * \brief RTC server
* \author Christian Helmuth
- * \author Markus Partheymueller
- * \date 2007-04-18
+ * \date 2015-01-06
*/
/*
- * Copyright (C) 2007-2013 Genode Labs GmbH
- * Copyright (C) 2012 Intel Corporation
+ * 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.
@@ -15,229 +13,73 @@
/* Genode */
#include
-#include
-#include
+#include
#include
-#include
#include
-#include
-#include
-using namespace Genode;
+#include "rtc.h"
-static bool verbose = false;
-
-/**
- * Time helper
- */
-bool is_leap_year(int year)
-{
- if (((year & 3) || !((year % 100) != 0)) && (year % 400 != 0)) return false;
- return true;
-}
-
-/**
- * Return UNIX time from given date and time.
- */
-uint64_t mktime(int day, int mon, int year, int hour, int minutes, int seconds)
-{
- bool jan_mar = mon < 3;
- uint64_t ret = 0;
- ret += (367*(10+mon))/12;
- ret += jan_mar*2;
- ret -= 719866;
- ret += day;
- ret += jan_mar * is_leap_year(year);
- ret += 365*year;
- ret += year/4;
- ret -= year/100;
- ret += year/400;
- ret *= 24;
- ret += hour;
- ret *= 60;
- ret += minutes;
- ret *= 60;
- ret += seconds;
-
- return ret;
-}
-
-static uint64_t get_rtc_time();
namespace Rtc {
+ using namespace Genode;
- class Session_component : public Genode::Rpc_object
- {
- public:
- uint64_t get_current_time()
- {
- uint64_t ret = get_rtc_time();
-
- if (verbose)
- PINF("Time is: %llx\n", ret);
-
- return ret;
- }
-
- };
-
- class Root_component : public Genode::Root_component
- {
- protected:
-
- Session_component *_create_session(const char *args)
- {
- return new (md_alloc()) Session_component();
- }
- public:
- Root_component(Genode::Rpc_entrypoint *ep,
- Genode::Allocator *allocator)
- : Genode::Root_component(ep, allocator)
- {
- }
- };
+ struct Session_component;
+ struct Root;
+ struct Main;
}
-/*
- * Our RTC port session
- */
-Io_port_connection *rtc_ports;
-
-enum RTC
+struct Rtc::Session_component : public Genode::Rpc_object
{
- RTC_SECONDS = 0,
- RTC_SECONDS_ALARM = 1,
- RTC_MINUTES = 2,
- RTC_MINUTES_ALARM = 3,
- RTC_HOURS = 4,
- RTC_HOURS_ALARM = 5,
- RTC_DAY_OF_WEEK = 6,
- RTC_DAY_OF_MONTH = 7,
- RTC_MONTH = 8,
- RTC_YEAR = 9,
+ uint64_t get_current_time() override
+ {
+ uint64_t ret = Rtc::get_time();
- RTC_REG_A = 10,
- RTC_REG_B = 11,
- RTC_REG_C = 12,
- RTC_REG_D = 13,
-
- RTC_FREQ_SELECT = RTC_REG_A,
- RTC_UIP = 0x80,
- RTC_DIV_CTL = 0x70,
- RTC_REF_CLCK_4MHZ = 0x00,
- RTC_REF_CLCK_1MHZ = 0x10,
- RTC_REF_CLCK_32KHZ = 0x20,
- RTC_DIV_RESET1 = 0x60,
- RTC_DIV_RESET2 = 0x70,
- RTC_RATE_SELECT = 0x0F,
-
- RTC_CONTROL = RTC_REG_B,
- RTC_SET = 0x80,
- RTC_PIE = 0x40,
- RTC_AIE = 0x20,
- RTC_UIE = 0x10,
- RTC_SQWE = 0x08,
- RTC_DM_BINARY = 0x04,
- RTC_24H = 0x02,
- RTC_DST_EN = 0x01,
-
- RTC_PORT_BASE = 0x70,
- RTC_PORT_ADDR = RTC_PORT_BASE,
- RTC_PORT_DATA = RTC_PORT_BASE + 1,
- RTC_PORT_SIZE = 2,
+ return ret;
+ }
};
-static inline unsigned cmos_read(unsigned char addr)
+class Rtc::Root : public Genode::Root_component
{
- unsigned char val;
- rtc_ports->outb(RTC_PORT_ADDR, addr);
-// iodelay();
- val = rtc_ports->inb(RTC_PORT_DATA);
-// iodelay();
- return val;
-}
+ protected:
+
+ Session_component *_create_session(const char *args)
+ {
+ return new (md_alloc()) Session_component();
+ }
+
+ public:
+
+ Root(Server::Entrypoint &ep, Allocator &md_alloc)
+ :
+ Genode::Root_component(&ep.rpc_ep(), &md_alloc)
+ {
+ /* trigger initial RTC read */
+ Rtc::get_time();
+ }
+};
-static inline void cmos_write(unsigned char val, unsigned char addr)
+struct Rtc::Main
{
- rtc_ports->outb(RTC_PORT_ADDR, addr);
-// iodelay();
- rtc_ports->outb(RTC_PORT_DATA, val);
-// iodelay();
-}
+ Server::Entrypoint &ep;
+ Sliced_heap sliced_heap { env()->ram_session(), env()->rm_session() };
-#define RTC_ALWAYS_BCD 1 /* RTC operates in binary mode */
-#define BCD_TO_BIN(val) ((val) = ((val) & 15) + ((val) >> 4) * 10)
-#define BIN_TO_BCD(val) ((val) = (((val)/10) << 4) + (val) % 10)
+ Root root { ep, sliced_heap };
-
-/**
- * Get current time from CMOS and initialize values.
- */
-static uint64_t get_rtc_time(void)
-{
- unsigned year, mon, day, hour, min, sec;
- int i;
-
- /* The Linux interpretation of the CMOS clock register contents:
- * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
- * RTC registers show the second which has precisely just started.
- * Let's hope other operating systems interpret the RTC the same way. */
-
- /* read RTC exactly on falling edge of update flag */
- for (i = 0 ; i < 1000000 ; i++)
- if (cmos_read(RTC_FREQ_SELECT) & RTC_UIP) break;
-
- for (i = 0 ; i < 1000000 ; i++)
- if (!(cmos_read(RTC_FREQ_SELECT) & RTC_UIP)) break;
-
- do {
- sec = cmos_read(RTC_SECONDS);
- min = cmos_read(RTC_MINUTES);
- hour = cmos_read(RTC_HOURS);
- day = cmos_read(RTC_DAY_OF_MONTH);
- mon = cmos_read(RTC_MONTH);
- year = cmos_read(RTC_YEAR);
- } while (sec != cmos_read(RTC_SECONDS));
-
- /* convert BCD to binary format if needed */
- if (!(cmos_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
- BCD_TO_BIN(sec);
- BCD_TO_BIN(min);
- BCD_TO_BIN(hour);
- BCD_TO_BIN(day);
- BCD_TO_BIN(mon);
- BCD_TO_BIN(year);
+ Main(Server::Entrypoint &ep) : ep(ep)
+ {
+ env()->parent()->announce(ep.manage(root));
}
-
- if ((year += 1900) < 1970) year += 100;
-
- if (verbose)
- PINF("Date:%02d.%02d.%04d Time:%02d:%02d:%02d\n", day, mon, year,
- hour, min, sec);
-
- /* return microseconds */
- return mktime(day, mon, year, hour, min, sec) * 1000000ULL;
-}
+};
-int main(int argc, char **argv)
-{
- static Io_port_connection ports(RTC_PORT_BASE, RTC_PORT_SIZE);
- rtc_ports = &ports;
+/**********************
+ ** Server framework **
+ **********************/
- Cap_connection cap;
- static Sliced_heap sliced_heap(env()->ram_session(), env()->rm_session());
-
- enum { STACK_SIZE = 1024*sizeof(size_t) };
- static Rpc_entrypoint ep(&cap, STACK_SIZE, "rtc_ep");
- static Rtc::Root_component rtc_root(&ep, &sliced_heap);
- env()->parent()->announce(ep.manage(&rtc_root));
-
- sleep_forever();
-
- return 0;
-}
+char const * Server::name() { return "rtc_ep"; }
+Genode::size_t Server::stack_size() { return 1024 * sizeof(long); }
+void Server::construct(Server::Entrypoint &ep) { static Rtc::Main inst(ep); }
diff --git a/repos/os/src/drivers/rtc/x86/rtc.cc b/repos/os/src/drivers/rtc/x86/rtc.cc
new file mode 100644
index 0000000000..2d3589b17f
--- /dev/null
+++ b/repos/os/src/drivers/rtc/x86/rtc.cc
@@ -0,0 +1,178 @@
+/*
+ * \brief RTC/CMOS clock driver
+ * \author Christian Helmuth
+ * \author Markus Partheymueller
+ * \date 2007-04-18
+ */
+
+/*
+ * Copyright (C) 2007-2015 Genode Labs GmbH
+ * Copyright (C) 2012 Intel Corporation
+ *
+ * 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
+#include
+#include
+#include
+#include
+#include
+
+#include "rtc.h"
+
+using namespace Genode;
+
+
+/**
+ * Time helper
+ */
+static bool is_leap_year(int year)
+{
+ if (((year & 3) || !((year % 100) != 0)) && (year % 400 != 0)) return false;
+ return true;
+}
+
+/**
+ * Return UNIX time from given date and time.
+ */
+static uint64_t mktime(int day, int mon, int year, int hour, int minutes, int seconds)
+{
+ bool jan_mar = mon < 3;
+ uint64_t ret = 0;
+ ret += (367*(10+mon))/12;
+ ret += jan_mar*2;
+ ret -= 719866;
+ ret += day;
+ ret += jan_mar * is_leap_year(year);
+ ret += 365*year;
+ ret += year/4;
+ ret -= year/100;
+ ret += year/400;
+ ret *= 24;
+ ret += hour;
+ ret *= 60;
+ ret += minutes;
+ ret *= 60;
+ ret += seconds;
+
+ return ret;
+}
+
+
+enum RTC
+{
+ RTC_SECONDS = 0,
+ RTC_SECONDS_ALARM = 1,
+ RTC_MINUTES = 2,
+ RTC_MINUTES_ALARM = 3,
+ RTC_HOURS = 4,
+ RTC_HOURS_ALARM = 5,
+ RTC_DAY_OF_WEEK = 6,
+ RTC_DAY_OF_MONTH = 7,
+ RTC_MONTH = 8,
+ RTC_YEAR = 9,
+
+ RTC_REG_A = 10,
+ RTC_REG_B = 11,
+ RTC_REG_C = 12,
+ RTC_REG_D = 13,
+
+ RTC_FREQ_SELECT = RTC_REG_A,
+ RTC_UIP = 0x80,
+ RTC_DIV_CTL = 0x70,
+ RTC_REF_CLCK_4MHZ = 0x00,
+ RTC_REF_CLCK_1MHZ = 0x10,
+ RTC_REF_CLCK_32KHZ = 0x20,
+ RTC_DIV_RESET1 = 0x60,
+ RTC_DIV_RESET2 = 0x70,
+ RTC_RATE_SELECT = 0x0F,
+
+ RTC_CONTROL = RTC_REG_B,
+ RTC_SET = 0x80,
+ RTC_PIE = 0x40,
+ RTC_AIE = 0x20,
+ RTC_UIE = 0x10,
+ RTC_SQWE = 0x08,
+ RTC_DM_BINARY = 0x04,
+ RTC_24H = 0x02,
+ RTC_DST_EN = 0x01,
+
+ RTC_PORT_BASE = 0x70,
+ RTC_PORT_ADDR = RTC_PORT_BASE,
+ RTC_PORT_DATA = RTC_PORT_BASE + 1,
+ RTC_PORT_SIZE = 2,
+};
+
+
+/*
+ * Our RTC port session
+ */
+static Io_port_connection & rtc_ports()
+{
+ static Io_port_connection inst(RTC_PORT_BASE, RTC_PORT_SIZE);
+
+ return inst;
+}
+
+
+static inline unsigned cmos_read(unsigned char addr)
+{
+ unsigned char val;
+ rtc_ports().outb(RTC_PORT_ADDR, addr);
+// iodelay();
+ val = rtc_ports().inb(RTC_PORT_DATA);
+// iodelay();
+ return val;
+}
+
+
+#define RTC_ALWAYS_BCD 1 /* RTC operates in binary mode */
+#define BCD_TO_BIN(val) ((val) = ((val) & 15) + ((val) >> 4) * 10)
+#define BIN_TO_BCD(val) ((val) = (((val)/10) << 4) + (val) % 10)
+
+
+uint64_t Rtc::get_time(void)
+{
+ unsigned year, mon, day, hour, min, sec;
+ int i;
+
+ /* The Linux interpretation of the CMOS clock register contents:
+ * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
+ * RTC registers show the second which has precisely just started.
+ * Let's hope other operating systems interpret the RTC the same way. */
+
+ /* read RTC exactly on falling edge of update flag */
+ for (i = 0 ; i < 1000000 ; i++)
+ if (cmos_read(RTC_FREQ_SELECT) & RTC_UIP) break;
+
+ for (i = 0 ; i < 1000000 ; i++)
+ if (!(cmos_read(RTC_FREQ_SELECT) & RTC_UIP)) break;
+
+ do {
+ sec = cmos_read(RTC_SECONDS);
+ min = cmos_read(RTC_MINUTES);
+ hour = cmos_read(RTC_HOURS);
+ day = cmos_read(RTC_DAY_OF_MONTH);
+ mon = cmos_read(RTC_MONTH);
+ year = cmos_read(RTC_YEAR);
+ } while (sec != cmos_read(RTC_SECONDS));
+
+ /* convert BCD to binary format if needed */
+ if (!(cmos_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+ BCD_TO_BIN(sec);
+ BCD_TO_BIN(min);
+ BCD_TO_BIN(hour);
+ BCD_TO_BIN(day);
+ BCD_TO_BIN(mon);
+ BCD_TO_BIN(year);
+ }
+
+ if ((year += 1900) < 1970) year += 100;
+
+ return mktime(day, mon, year, hour, min, sec) * 1000000ULL;
+}
diff --git a/repos/os/src/drivers/rtc/x86/rtc.h b/repos/os/src/drivers/rtc/x86/rtc.h
new file mode 100644
index 0000000000..ee3c0b06a3
--- /dev/null
+++ b/repos/os/src/drivers/rtc/x86/rtc.h
@@ -0,0 +1,25 @@
+/*
+ * \brief RTC driver interface
+ * \author Christian Helmuth
+ * \date 2015-01-06
+ */
+
+/*
+ * 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.
+ */
+
+#ifndef _RTC_H_
+#define _RTC_H_
+
+#include
+
+namespace Rtc {
+
+ /* Get real time in microseconds since 1970 */
+ Genode::uint64_t get_time();
+}
+
+#endif /* _RTC_H_ */
diff --git a/repos/os/src/drivers/rtc/x86/target.mk b/repos/os/src/drivers/rtc/x86/target.mk
index 69285ed74e..0dffe3c9a2 100644
--- a/repos/os/src/drivers/rtc/x86/target.mk
+++ b/repos/os/src/drivers/rtc/x86/target.mk
@@ -1,4 +1,12 @@
TARGET = rtc_drv
REQUIRES = x86
SRC_CC = main.cc
-LIBS = base
+LIBS = base server
+
+# enforce hybrid prg on Linux
+ifeq ($(filter-out $(SPECS),linux),)
+SRC_CC += linux.cc
+LIBS += lx_hybrid
+else
+SRC_CC += rtc.cc
+endif
diff --git a/repos/os/src/test/rtc/main.cc b/repos/os/src/test/rtc/main.cc
new file mode 100644
index 0000000000..7bd519ea5c
--- /dev/null
+++ b/repos/os/src/test/rtc/main.cc
@@ -0,0 +1,41 @@
+/*
+ * \brief Test for RTC driver
+ * \author Christian Helmuth
+ * \date 2015-01-06
+ */
+
+/*
+ * 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
+#include
+#include
+#include
+
+
+int main(int argc, char **argv)
+{
+ Genode::printf("--- RTC test started ---\n");
+
+ /* open sessions */
+ static Rtc::Connection rtc;
+ static Timer::Connection timer;
+
+ for (unsigned i = 0; i < 4; ++i) {
+ Genode::uint64_t now = rtc.get_current_time();
+
+ Genode::printf("RTC: %llu.%06llu seconds since 1970\n",
+ now / 1000000ULL,
+ now % 1000000ULL);
+
+ timer.msleep(1000);
+ }
+
+ Genode::printf("--- RTC test finished ---\n");
+
+ return 0;
+}
diff --git a/repos/os/src/test/rtc/target.mk b/repos/os/src/test/rtc/target.mk
new file mode 100644
index 0000000000..6eb1c85093
--- /dev/null
+++ b/repos/os/src/test/rtc/target.mk
@@ -0,0 +1,3 @@
+TARGET = test-rtc
+SRC_CC = main.cc
+LIBS = base